Skip to content

An epic's attributedCommits silently did not reach the commit that claimed to record it #140

Description

@cfdude

What happened

update-epic <id> --attribute-commit <sha> was run for four commits across two epics. The
engine reported success for each. .conductor/state.json in the working tree held all four.

The commit made immediately afterwards — 0645872, whose message says
chore(conductor): attribute gh-128/gh-134 commits, register #139 — contains
"attributedCommits": [] for both epics. So do the two commits after it. The values sat in the
working tree, uncommitted and unnoticed, across three commits and two branch merges.

$ for c in 0645872 8758026 728dc1e HEAD; do
    git show "$c:.conductor/state.json" | jq -c '[.epics[]|select(.id=="gh-134-…")][0].attributedCommits'
  done
[]
[]
[]
[]           # …while the working tree held ["17f8665","dc62cc9","56c50ab"]

The commit that added --register #139 in the same invocation DID land. So the file was written
and committed; the attribution array specifically was not in what got committed.

Root cause: NOT established

Stating that plainly rather than guessing. Candidates not yet distinguished:

  • A later engine invocation in the same turn re-serialising state.json from a copy read before
    the attribution (the lost-update shape 0.26.0's write-conflict guard exists for). Against this:
    .conductor/write-conflicts.log is empty, so the guard did not fire.
  • git commit -- <pathspec> snapshotting the path at commit time, with a hook rewriting the file
    inside that window. The pre-commit hook runs the full suite, which is a ~75s window.
  • Something specific to git add -A <path> && git commit -- <path> used together.

Why it matters more than one lost array

attributedCommits is the ONLY input to whether a recorded Gate 2 verdict is fresh or stale — the
last entry is the endpoint a verdict's headSha is compared against. An epic whose attributions
silently vanish gets a Gate 2 that reads fresh when it is not, which is the precise failure
0.27.0's gate-evidence work was built to stop. It is also the second time this repository has hit
"the working tree holds the intended edit and the commit does not"; the first produced the
standing task item verify against the commit, not the working tree, and that item is the only
reason this was caught at all.

What would have caught it

Nothing did, and nothing would have. The existing check
delivered-epic-attributed-no-commits fires only on a delivered epic with a passing Gate
2
— these epics were queued at the time. There is no signal for "an epic has commits in
flight and an empty attribution array."

Proposed

Two independent pieces, both cheap:

  1. Make the write verifiable. Have --attribute-commit read back what it wrote and fail loudly
    if the value is not present on disk after the write. A verb that reports success for a write
    that did not persist is the whole defect.
  2. Add the missing detector. An integrity check for an epic in a non-terminal status whose
    attributedCommits is present and empty while its epic has a recorded gate verdict or a
    release assignment — i.e. work is demonstrably underway and nothing is attributed.

Then chase the mechanism with the two candidates above, ideally by reproducing under a hook that
sleeps inside the commit window.

Current state

Not data-lost: the values were re-applied and verified against the commit rather than the tree,
and are correct as of HEAD. Filed rather than chased now, deliberately — the record is right,
the mechanism is not understood, and understanding it is not urgent.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions