Skip to content

M001 — A blocking question survives a handover

An unresolved question keeps refusing a completed finish after the work moves to a new task, or the alternative is chosen deliberately and the reason is recorded where the next worker will read it.

DONE 4 of 4 issues done

ready
0
blocked
0
active
0
verify
0
done
4
cancelled
0

Problem

An open question is the mechanism for stopping acceptance when work depends on a person. It is attached to the task that opened it, and the gate only reads questions belonging to the active task. Handing over and starting a new task therefore leaves the question unresolved and no longer blocking anything, so the one thing that was supposed to refuse a completed finish refuses nothing. The gap was found by running the documented end-to-end sequence, not by review, and it is published as a planned claim with no implementation and no test.

Outcome

An unresolved question keeps refusing a completed finish after the work moves to a new task, or the alternative is chosen deliberately and the reason is recorded where the next worker will read it.

Current state

docs/CLAIMS.yaml carries blocker-survives-handover as planned, with implementation and test both '-'. lib/question.sh matches unresolved lines by the active task id; lib/check.sh reads only those. Nothing detects that a handover has orphaned a blocker.

Desired state

The behaviour is decided between two named alternatives, implemented, proved by a behavioural case, and the claim moves from planned to guaranteed with its implementation and test filled in.

Scope

  • lib/question.sh
  • lib/check.sh
  • share/skeleton/templates/open-questions.md
  • docs/CLAIMS.yaml
  • docs/claims
  • docs/CONTINUITY.md
  • test/cases

Out of scope

  • A question that blocks across repositories or worktrees
  • Assigning a question to a person, or notifying anybody
  • Any change to the finish contract's other lines

Acceptance criteria

  • A behavioural case demonstrates the current escape, so the gap is executable rather than asserted
  • The choice between transferring the question and widening the gate is recorded as a decision with what was rejected and why
  • The chosen behaviour is implemented and a case fails when it is removed
  • The claim in docs/CLAIMS.yaml moves to guaranteed with a real implementation path and a real test path
  • The claim detail page states what the behaviour does not cover

Validation

  • bash test/run.sh
  • bin/majordomus doctor
  • scripts/generate-site-data --check

Evidence required

  • gap_reproduced
  • decision_recorded
  • behaviour_tested

Risks

  • Transferring a question with a handover makes it a property of the work rather than of the task, which is right in the common case and wrong when the handover is to a different piece of work. Widening the gate to every unresolved question blocks tasks that never opened one. The decision has to name the case it is choosing to be wrong in.

Evidence

A milestone is never done because its issues are; the last step is its own acceptance, and it is gated on the rows below.

coverstypecommandresult
gap_reproducedtestbash test/run.sh 50_blocker_across_handoverthe case runs the documented sequence and the mutation section reproduces the escape from a probe that narrows the gate back to the active task, so the gap is executable rather than described
decision_recordedmanualbin/majordomus decision listthe choice, both rejected alternatives with the case each gets wrong, and the two conditions the choice imposed on the implementation
behaviour_testedtestbash test/run.sh 50_blocker_across_handover && bash test/run.sh 25_continuity_lifecycle && bin/majordomus doctorexit 0, 85s — recorded as this task's verification; an inherited blocker refuses a completed finish, any task can clear it, and the shipped template is not an entry

Issues

Each one is an execution contract with its own acceptance criteria, validation command and required evidence. The wave column is the layer of the dependency graph it sits in.

issuestatuswavedepends ontitle
I0101 DONE 0 Reproduce the escaped blocker as an executable case
I0102 DONE 1 I0101 Decide whether a question transfers or the gate widens
I0103 DONE 2 I0102 Implement the decision and prove it holds
I0104 DONE 3 I0103 Move the claim from planned to guaranteed

The graph

M001 dependency graphfrom .ai/repo/project
flowchart LR
    I0101["I0101<br/>Reproduce the escaped blocker as an executable case"]:::done
    I0102["I0102<br/>Decide whether a question transfers or the gate widens"]:::done
    I0103["I0103<br/>Implement the decision and prove it holds"]:::done
    I0104["I0104<br/>Move the claim from planned to guaranteed"]:::done
    I0101 --> I0102
    I0102 --> I0103
    I0103 --> I0104
    classDef done stroke:#16a34a,fill:#052e16,stroke-width:2px
    classDef active stroke:#2563eb,fill:#eff6ff,stroke-width:2px
    classDef verify stroke:#7c3aed,fill:#f5f3ff,stroke-width:2px
    classDef ready stroke:#0891b2,fill:#ecfeff,stroke-width:2px
    classDef blocked stroke:#b45309,fill:#fffbeb,stroke-width:2px
    classDef cancelled stroke:#6b7280,fill:#f9fafb,stroke-width:2px

Canonical record: .ai/repo/project/milestones/M001.yaml. Read it back with majordomus plan show M001.