v1.29.0 ·
The phase nothing ever measured
AIDLC had never once measured the first phase of any piece of work it ran. Every instance, since the beginning. That is not what the report said.
The report came from running the lifecycle end to end on someone else's codebase for the first time. It had five findings, each with a suggested fix. It said that reopening a phase erased its timing data, because two of four phases reported zero elapsed seconds. The symptom was real. The mechanism was not. Reopening a phase keeps its metrics on purpose, and finishing it again recomputes them. On a scratch instance, a phase that had recorded twenty minutes still read twenty after a reopen and twenty-two after finishing again. No path could write a zero.
The zero came from somewhere worse. A phase gets its entry timestamp from the transition that moves into it. The first phase is not moved into, it is where the instance starts, so nothing ever stamped it. The completion code skipped the elapsed calculation for want of an anchor, and the phase closed at zero. The lead-time report filters for phases with both timestamps, so the first phase has been silently left out of every lead-time figure this project has published about itself. That is 57 instances.
The second finding failed the same way. It said a coverage gate called a criterion untested while a test for it sat in the suite, with no diagnostic. The diagnostic existed, worded almost as the report asked, four lines above the violation. But the run drove the command with the machine-readable flag, and in that mode the warnings were printed under a condition that excluded them and appeared in none of the four payloads. The gate told humans its own fix and hid it from agents, the only audience that flag has.
Why I reproduced first
Two symptoms, two wrong causes. Either would have sent me after something that was not broken. The person who wrote the report had just spent sixty dollars and a hundred and fifty responses on the ground, so trusting it was not foolish. Reproducing cost an afternoon in a scratch project and changed two of the seven fixes completely. A field report is the best source of symptoms and the worst source of diagnoses, and they arrive in the same paragraph.
For the untimed first phase, stamping every phase on creation was rejected, because status derives "last updated" from the newest entry stamp and every instance would look freshly active. Only the first phase is stamped. For instances already on disk I did not migrate. Writing timestamps into recorded history to make it look measured is the same dishonesty as the metric below. Completion falls back to the instance's creation time, a real fact already recorded, so only future completions benefit.
One per-phase metric had been set to zero at creation and written by nothing since. It was zero in every file, read by no code, and shaped like a measurement. I deleted it. A reader can tell an absent number from a zero, but not a zero from a real zero. For the same reason, the elapsed-time helper now returns nothing, not zero, when there is no anchor.
What else shipped
Amendments can now say none, meaning nothing downstream was invalidated. Before, the only accepted answer was to name a finished phase that needed nothing, which reopened it and every phase after it and wrote rework into the log that never happened. Elapsed time for a reopened phase is now measured from the reopen, so the time it sat finished is no longer billed as work. Gate warnings and the context reading now appear in every JSON payload.
The transition command now reports how much context the session carries against the budget and recommends a fresh start when over. A gate was tempting. This very release ran at a hundred and seventy percent of budget and said so. I rejected it on this project's record: five of its six traceable bugfixes came from features that watch the lifecycle, each adding a gate every future piece of work must pass. It is a warning, wrapped so an unreadable transcript or malformed config cannot refuse a transition. That collided with an old guard that searched the source for the reading. I replaced it with the property it approximated, that the reading reaches no violation, exit code or verdict, and recorded it as an amendment, using the none form this release adds.
The last finding was that creating a piece of work by hand told the agent to write out each phase's required artifacts, while the only copy of that list sat inside an installed dependency. On the first real run, guessing produced three artifacts the chosen template does not require. A new templates command prints each template's phases and what each requires. I rejected copying resolved templates into each project, because a copy drifts and drift needs a health check, which is another gate. A command that reads the package cannot go stale.