Conversation
leandrodamascena
left a comment
There was a problem hiding this comment.
The authorization and unit-lifecycle additions have several fail-open paths that defeat the new authority floor or allow the workflow to reach a gate with an active/incomplete unit. The inline findings include direct reproductions for audit receipt forgery, rogue-unit deadlock, completed-unit restart, and same-second attempt reuse.
leandrodamascena
left a comment
There was a problem hiding this comment.
The corrective commit resolves several earlier findings, but lifecycle integrity still has fail-open and upgrade-breaking paths.
-
[P1] Bind
unit startto the engine-routed stage/unit pair
unit startchecks DAG membership but not dependency readiness. Startingunit-bbeforeunit-asucceeds, andnextthen routesunit-b, overriding topological order. -
[P1] Do not order same-second attempt boundaries by shard filename
A newGATE_REJECTEDin another shard can lose the tie to an olderSTAGE_STARTED, allowing the prior attempt’sUNIT_COMPLETEDreceipt to remain settled. -
[P1] Require artifacts to be regular files
existsSync()accepts directories named*.md. I created directories for every required artifact andunit completeemittedUNIT_COMPLETED. -
[P2] Preserve in-flight swarms across upgrades
finalizenow requires the new stampedSWARM_STARTED. Worktrees prepared before upgrading cannot finalize or be re-stamped without being discarded and rebuilt. -
[P2] Preserve legacy safe unit names
The new lowercase-only validator rejects previously accepted names such asapi_v2andWebUI, breaking existing receipt-free workflows despite the compatibility claim.
Focused validation passed: 111 tests, 476 assertions, package parity, and remote CI.
|
Addressed @leandrodamascena's follow-up review in
Verification:
|
leandrodamascena
left a comment
There was a problem hiding this comment.
The corrective commit resolves several earlier findings, but authority and lifecycle integrity still fail open under same-second cross-shard races.
[P1] Fail closed when a resolution competes with human presence across shards
When GATE_APPROVED exists in one shard and GATE_REJECTED plus HUMAN_TURN share its timestamp in another, humanActedSinceGate() returns true. The global order is unknowable, so the human turn may predate the latest resolution.
[P1] Do not order same-second unit lifecycle events by shard filename
With UNIT_STARTED and UNIT_PAUSED in different shards at the same timestamp, activeUnitCheckpoint() can report in-progress based on lexical shard order. This ignores a potentially effective pause and permits operations that should remain blocked.
Focused validation reproduced both issues. git diff --check and remote CI passed; full local guards were not rerun.
|
Addressed the latest cross-shard race findings in
Regression coverage includes both filename orientations, the exact three-event authority repro, same-shard reverse ordering, pause/start and pause/resume ambiguity, completion/non-terminal ambiguity, and strictly later lifecycle events. Verification:
|
leandrodamascena
left a comment
There was a problem hiding this comment.
Latest updates address the blocking authority and lifecycle issues from the previous reviews. Focused lifecycle, authority, swarm, parity, typecheck, lint, and diff checks pass.
Approving. Two non-blocking compatibility edge cases would still be worth fixing before merge:
- Backward jumps to inline Construction stages while autonomy remains enabled cannot emit Unit lifecycle receipts because
unit start/completeare refused. - Safe legacy Unit names beginning with a digit, such as
2fa, were accepted byv2but are now reported as malformed.
Neither warrants another blocking review round, but addressing them would make the upgrade path more robust.
- The public audit CLI (append / append-batch) refuses authority-bearing receipts (HUMAN_TURN, GATE_*, QUESTION_ANSWERED, REVIEW_*, SWARM_UNIT_CONVERGED, AUTONOMY_MODE_SET); append-raw refuses bodies carrying a taxonomy **Event**: line; caller-supplied Event/Timestamp field keys are refused on every emit path. - aidlc-bolt set-autonomy --mode autonomous requires a fresh human turn (the ladder answer), and the autonomous grant consumes the turn like a gate resolution does. - humanActedSinceGate reads shards individually: same-second cross-shard ties on the deciding human-turn/resolution pair now fail closed instead of resolving by shard filename order. - aidlc-log answer, aidlc-state approve/reject refuse cancellation boilerplate (Cancelled / dismissed / timed out) as answers, approval choices, or rejection feedback. Suite runner sets AIDLC_ALLOW_DIRECT_AUDIT_EVENTS=1 so fixtures that simulate owning emitters keep working.
…ms 1, 2, 9) - New audit events UNIT_STARTED / UNIT_PAUSED / UNIT_RESUMED / UNIT_COMPLETED, emitted by the new 'aidlc-state.ts unit start|pause|resume|complete' verb (CLI-protected like other receipts). - unit complete verifies the unit's required artifacts on disk before committing: the receipt is the transition, artifacts are evidence. - Engine coverage (nextUncoveredUnit) now requires a UNIT_COMPLETED receipt per unit once any receipt exists for the stage; receipt-free workflows keep artifact-driven coverage (no upgrade break). - A paused unit routes first and hard-stops the loop: the engine emits an ask naming the unit, its recorded reason, and next action (unit_state: paused) until an explicit unit resume; approval entry is refused while a unit is paused. - unit start refuses a second active unit (single-active-unit invariant); resume/complete validate against the active checkpoint. - State file mirrors the checkpoint (Active Unit / Unit State / Unit Pause Reason / Unit Next Action under Runtime State) for status reads. - Taxonomy pins updated: t28 74 -> 78, registry tables + emitter rows in audit-format.md and 12-state-machine.md, stage-protocol receipt prose.
…fecycle (t259, t260) - t259: CLI forge refusals (append/append-batch/append-raw + Event field key), set-autonomy presence + consume-once, cross-shard same-second fail-closed, cancellation-boilerplate floors (incl. the issue's status=completed answer=Cancelled repro). - t260: receipts-not-artifacts completion, single-active-unit invariant, pause checkpoint mirroring, paused-unit engine ask + approval refusal. - Timestamp removed from the reserved field keys (park/unpark rows carry it legitimately; the emitter's own line is written first so it cannot spoof). - 74 -> 78 event-count pins updated (t28, t81, t239, docs, user guide); coverage registry regenerated; t259/t260 added to the none->cli reclassification ratchet. - Version 2.5.31 + CHANGELOG entry + README badge.
- UNIT_STARTED/PAUSED/RESUMED/COMPLETED added to CLI_PROTECTED_EVENT_TYPES: routing trusts UNIT_COMPLETED as the completion signal, so a CLI-forged receipt would skip the owning verb's artifact verification. - aidlc-state.ts unit refuses under Construction Autonomy Mode: autonomous (the swarm referee owns per-unit bookkeeping via SWARM_UNIT_*; same rule park applies) - keeps the two ledgers from interleaving. - Resume surfaces the unit checkpoint: handleResume returns active_unit/unit_state/unit_pause_reason/unit_next_action, and the session-start hook injects an 'Active Unit: ...' context line so a fresh session lands on the exact stopping point. - Doctor STATE_ALLOWLIST carries the four new runtime fields. - Protected-set doc mentions updated (stage-protocol, audit-format, 12-state-machine); t259 covers the four new refusals.
Closes the verified authorization and lifecycle gaps from #681 (the brownfield Codex evaluation). Seven of the nine reported claims are addressed; the remaining two (decision-ID-bound reusable receipts, decision-ledger locking) describe a receipt subsystem v2 does not have and are deliberately left to a follow-up design discussion rather than bolted on here.
What each claim gets
Claim 8 - the public audit CLI could forge authority rows.
aidlc-audit.ts append/append-batchnow refuse the receipts the engine's guards read as authorization evidence (HUMAN_TURN,GATE_APPROVED,GATE_REJECTED,QUESTION_ANSWERED,REVIEW_REQUESTED,REVIEW_COMPLETED,SWARM_UNIT_CONVERGED,AUTONOMY_MODE_SET, and the four newUNIT_*receipts) with an error naming the owning tool.append-rawrefuses a body carrying a taxonomy**Event**:line, and a caller-suppliedEventfield key is refused on every emit path (a second**Event**:line would spoof the multiline event queries;Timestampstays legal - park/unpark rows carry it and the emitter's own line is written first). Owning tools and hooks emit through the library import, untouched. Test fixtures that simulate owning emitters setAIDLC_ALLOW_DIRECT_AUDIT_EVENTS=1; the suite runner sets it globally.Claim 7 - autonomous execution could weaken mandatory gates.
aidlc-bolt.ts set-autonomy --mode autonomousrequires a fresh human turn (the ladder-prompt answer), and the grant consumes that turn exactly like a gate resolution - one human turn can no longer both grant autonomy and approve something else. De-escalating togatednever needs presence.Claim 4 - same-second cross-shard ordering was unsafe.
humanActedSinceGatenow reads shards individually: buffer position remains the tiebreak only within a shard (where it reflects append order), and when the deciding human-turn/resolution pair shares one second-precision timestamp across different shards - where execution order is unknowable - the gate fails closed and requires a fresh turn instead of trusting shard filename order.Claim 3 - ambiguous/auto-resolved question responses. Cancellation boilerplate ("Cancelled", "dismissed", "timed out", empty text - the exact
status=completed/ answerCancelledrepro from the issue) is refused as an interview answer (aidlc-log.ts answer), an approval choice (approve --user-input), and rejection feedback (reject --feedback). A substantive answer that merely contains a cancellation word ("cancel the standing order via cron") still passes. The presence mint itself stays content-blind by design.Claims 1, 2, 9 - unit lifecycle. New
UNIT_STARTED/UNIT_PAUSED/UNIT_RESUMED/UNIT_COMPLETEDreceipts (taxonomy 74 → 78), emitted by the newaidlc-state.ts unit start|pause|resume|completeverb on inline per-unit Construction stages:unit completeverifies the unit's required artifacts on disk (kind-filtered, same rules as the engine's coverage walk) before committing. Once any receipt exists for a stage, the engine requires a receipt per unit - a scaffolded or partially-written unit can no longer read as done by file existence alone. Receipt-free workflows keep today's artifact-driven coverage, so nothing re-opens on upgrade.unit pauserequires--reasonand--next-action; the state file mirrors them under## Runtime State,resumereturns them as JSON, and the session-start hook injects anActive Unit:context line so a fresh session lands on the exact stopping point.nextemits an ask naming the unit, its reason, and next action (unit_state: paused) until an explicitunit resume;report --result awaiting-approvalis refused while a unit is paused;unit startrefuses while another unit is open (single-active-unit invariant, so resume/restart races cannot create two active units).Construction Autonomy Mode: autonomous(same rule aspark); the referee'sSWARM_UNIT_*ledger remains the sole per-unit authority on the autonomous path.Tests
t261-audit-authority-floor- CLI forge refusals across all three append paths, theEventfield-key floor, set-autonomy presence + consume-once, cross-shard fail-closed vs same-shard append order, and the non-answer floors including the issue's named repro.t260-unit-lifecycle-receipts- receipts-not-artifacts completion, single-active-unit, pause checkpoint mirroring, the paused-unit engine ask, and the approval refusal.Gates run:
package.ts --check, typecheck, lint, smoke + unit (183 files / 4481 assertions) all green on the rebased head. E2E ran sliced across the full 67-file tier: all deterministic journeys green including the construction-worktree scopes, swarm referee, and stop hook; the two reds (t113, t138) fail identically on the pristine base commit (t113's helper predates reviewer enforcement; t138 is the known live-SDK timeout) - both exonerated by baseline runs.Notes for reviewers
aidlc-audit.ts append HUMAN_TURN-style calls needAIDLC_ALLOW_DIRECT_AUDIT_EVENTS=1. The CHANGELOG entry carries the upgrade note.