Recreated from Strycher/Field_Compass-archive#236 — originally opened by @Strycher on 2026-09-06. Credentials redacted where present.
Parent epic: #213
Feature: #211
Folded in per owner instruction after the #221 / PR #235 merge, where post-push work (merge, ancestry verification, worktree cleanup) ran under two --task NEW checkpoints because the only Citadel task on the issue had already been closed to satisfy the push gate.
Correction first — the gate is not what I reported
I told the owner the pre-push gate's ordering was wrong and that it contradicted /pushpr step 8. Reading the gate shows that is false. Verified in .claude/hooks/pre-push:55-122:
- It checks Citadel only. GitHub issue state is not consulted by this check.
- It matches issue numbers in commit subjects, not bodies.
- It is lenient:
done_tasks = [t for t in tasks if t.get('status') in ('done','closed')] — if any task on that issue is done, the push passes. Only zero-done blocks (standards#19).
not_found and error also pass, so it never blocks on a Citadel outage.
The hook already documents the intended pattern, at pre-push:113-114:
Not an obstacle to route around: operate under an epic and close the testing/predecessor or PR task so a closed task satisfies this gate (the Unfocused pattern).
So the gate never required closing the task that was doing the work. It required a done task on the issue. There is no contradiction with /pushpr step 8, and nothing to file upstream.
The actual defect: our task structure
Field Compass has been creating one Citadel task per issue and closing that task at push time. That satisfies the gate by spending the working task, leaving everything after the push — merge, CI watching, review response, cleanup — with no open task to attach to.
Observed on #221: task 9ws (authoring) closed to push, 8im created for the CI fixes, 8im closed at merge time, then merge/verify/cleanup ran as --task NEW. Three tasks and two orphaned checkpoints for one issue, purely from structure.
Same root cause #213 already names: shipping without a parent to hold the thread.
Proposed convention
Under an Epic, each issue that will be pushed carries at least two Citadel tasks:
| task |
closed when |
satisfies |
| work task |
the change is written and locally verified |
the push gate, leniently |
| PR/verification task |
after CI is green and the PR is merged |
/pushpr step 8 |
The work task closes before push. The PR/verification task stays open across the push, so merge, CI watching, review response and cleanup all have a home, and closes last.
Secondary finding, recorded not fixed
Epics and Features do have Citadel twins (Field_Compass-0uf for #213, Field_Compass-1zo for #211) but they sit in backlog and are not claimed while their children are worked. If the convention above is adopted, decide explicitly whether the Epic task should move to in_progress for the duration — otherwise dw list -s in_progress keeps under-reporting what is actually being worked, which matters for FC's mandatory parallel-agent check.
Acceptance
Out of scope
No hook code changes. The gate behaves correctly; only our use of it was wrong.
Recreated from
Strycher/Field_Compass-archive#236 — originally opened by @Strycher on 2026-09-06. Credentials redacted where present.Parent epic: #213
Feature: #211
Folded in per owner instruction after the #221 / PR #235 merge, where post-push work (merge, ancestry verification, worktree cleanup) ran under two
--task NEWcheckpoints because the only Citadel task on the issue had already been closed to satisfy the push gate.Correction first — the gate is not what I reported
I told the owner the pre-push gate's ordering was wrong and that it contradicted
/pushprstep 8. Reading the gate shows that is false. Verified in.claude/hooks/pre-push:55-122:done_tasks = [t for t in tasks if t.get('status') in ('done','closed')]— if any task on that issue is done, the push passes. Only zero-done blocks (standards#19).not_foundanderroralso pass, so it never blocks on a Citadel outage.The hook already documents the intended pattern, at
pre-push:113-114:So the gate never required closing the task that was doing the work. It required a done task on the issue. There is no contradiction with
/pushprstep 8, and nothing to file upstream.The actual defect: our task structure
Field Compass has been creating one Citadel task per issue and closing that task at push time. That satisfies the gate by spending the working task, leaving everything after the push — merge, CI watching, review response, cleanup — with no open task to attach to.
Observed on #221: task
9ws(authoring) closed to push,8imcreated for the CI fixes,8imclosed at merge time, then merge/verify/cleanup ran as--task NEW. Three tasks and two orphaned checkpoints for one issue, purely from structure.Same root cause #213 already names: shipping without a parent to hold the thread.
Proposed convention
Under an Epic, each issue that will be pushed carries at least two Citadel tasks:
/pushprstep 8The work task closes before push. The PR/verification task stays open across the push, so merge, CI watching, review response and cleanup all have a home, and closes last.
Secondary finding, recorded not fixed
Epics and Features do have Citadel twins (
Field_Compass-0uffor #213,Field_Compass-1zofor #211) but they sit inbacklogand are not claimed while their children are worked. If the convention above is adopted, decide explicitly whether the Epic task should move toin_progressfor the duration — otherwisedw list -s in_progresskeeps under-reporting what is actually being worked, which matters for FC's mandatory parallel-agent check.Acceptance
CLAUDE.mdFC-specific overrides, next to the branch-strategy tablepre-push:113-114, so the next agent does not re-derive the wrong conclusion--task NEWOut of scope
No hook code changes. The gate behaves correctly; only our use of it was wrong.