I3995 — A task started before the first commit finishes: an unborn recorded head is an ancestor of every commit
mj_git_label (lib/common.sh) labels a recorded head of NONE, which mj_git_head writes when start runs on an unborn branch, as advanced once the branch has commits, so the state doctrine passes and check and a completed finish are no longer refused for a history that was never rewritten. start's refusal of a second task names the commands that release the first: finish, or handover --close.
BLOCKED wave 0 · p0 · implementation profile · parallel safe
Blocked. This issue cannot start until milestone:a-stranger-adopts-it-unaided is done. The status is derived from that, not declared.
Objective
mj_git_label (lib/common.sh) labels a recorded head of NONE, which mj_git_head writes when start runs on an unborn branch, as advanced once the branch has commits, so the state doctrine passes and check and a completed finish are no longer refused for a history that was never rewritten. start's refusal of a second task names the commands that release the first: finish, or handover --close.
Why
On 2026-10-23 an adopter of a new repository (majordomus-reel, task t-20261023002255-4d5b) ran majordomus start --scope . before the first commit. start recorded head NONE; after the first commits mj_git_label asked git merge-base --is-ancestor NONE HEAD, which fails for a name that is not a revision, and fell through to diverged. mj_validate_state turned that into a refusal, and state is in verification.finish_requires, so every check and every finish was refused for good and the task could not be closed. The refusal of a second start told the user to run majordomus handover, which does not release the task without --close. A supported release for the stuck task already existed, majordomus handover --close (lib/handover.sh), and the first diagnosis (a handover does not release a task, so there is no supported way out) missed that flag; the adopter was released with it, and the state doctrine is fixed so that no adopter needs it.
Current state
lib/common.sh mj_git_label returns diverged for a recorded head of NONE once HEAD exists; lib/start.sh names majordomus handover as a way out of an active task.
Desired state
A task started on an unborn branch reads advanced after its commits, check passes the state doctrine and a completed finish succeeds; the start refusal names finish and handover --close.
Scope
- lib/common.sh
- lib/start.sh
- docs/claims/scoped-task.md
- test/cases/3995_a_task_started_before_the_first_commit_finishes.sh
- .ai/repo/project/issues/I3995.yaml
Out of scope
- mj_git_touched with a base of NONE, which counts only uncommitted paths for the scope doctrine; a separate issue if the scope of such a task must see its commits
- A task whose branch changes between start and finish, which stays different_context
Dependencies
None. This issue is a root of the graph.
Acceptance criteria
- In a fresh repository, start --scope . before the first commit, two commits, then check passes with state advanced and finish --outcome completed succeeds
- With the NONE line of mj_git_label removed, the case fails at check with state diverged
Validation
- bash test/run.sh 3995_a_task_started_before_the_first_commit_finishes
- bin/majordomus plan validate
Evidence required
- a_task_started_before_the_first_commit_finishes
Evidence
None recorded. Every token above needs a command or an artifact behind it before this issue can be completed; narrative is refused.
Timeline
- started
- —
- verified
- —
- completed
- —
Those three fields, the evidence above and the state of the dependencies are all the status is made of. There is no status field to disagree with them.
Canonical record: .ai/repo/project/issues/I3995.yaml. Read it back with majordomus plan show I3995.