dev-loops 0.6.0 → 0.7.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (203) hide show
  1. package/.claude/.claude-plugin/plugin.json +1 -1
  2. package/.claude/agents/dev-loop.md +8 -7
  3. package/.claude/agents/fixer.md +1 -0
  4. package/.claude/agents/refiner.md +2 -2
  5. package/.claude/agents/review.md +4 -3
  6. package/.claude/commands/{auto.md → loop-auto.md} +1 -1
  7. package/.claude/commands/loop-continue.md +15 -0
  8. package/.claude/commands/loop-enqueue.md +22 -0
  9. package/.claude/commands/loop-grill.md +17 -0
  10. package/.claude/commands/{info.md → loop-info.md} +2 -2
  11. package/.claude/commands/loop-queue-status.md +24 -0
  12. package/.claude/commands/{start-spike.md → loop-start-spike.md} +2 -2
  13. package/.claude/commands/{start.md → loop-start.md} +1 -1
  14. package/.claude/commands/{status.md → loop-status.md} +1 -1
  15. package/.claude/hooks/_bash-command-classify.mjs +333 -29
  16. package/.claude/hooks/_hook-decisions.mjs +138 -15
  17. package/.claude/hooks/pre-tool-use-bash-gate.mjs +36 -15
  18. package/.claude/skills/copilot-pr-followup/SKILL.md +60 -34
  19. package/.claude/skills/dev-loop/SKILL.md +16 -12
  20. package/.claude/skills/docs/acceptance-criteria-verification.md +8 -3
  21. package/.claude/skills/docs/anti-patterns.md +5 -3
  22. package/.claude/skills/docs/artifact-authority-contract.md +30 -11
  23. package/.claude/skills/docs/confirmation-rules.md +1 -0
  24. package/.claude/skills/docs/contract-style-guide.md +37 -0
  25. package/.claude/skills/docs/copilot-loop-operations.md +19 -15
  26. package/.claude/skills/docs/cross-harness-regression-contract.md +60 -0
  27. package/.claude/skills/docs/debt-remediation-contract.md +1 -1
  28. package/.claude/skills/docs/epic-tree-refinement-procedure.md +25 -22
  29. package/.claude/skills/docs/issue-intake-procedure.md +26 -19
  30. package/.claude/skills/docs/local-planning-flow.md +1 -1
  31. package/.claude/skills/docs/local-planning-worked-example.md +1 -1
  32. package/.claude/skills/docs/merge-preconditions.md +30 -12
  33. package/.claude/skills/docs/plan-file-contract.md +1 -1
  34. package/.claude/skills/docs/pr-lifecycle-contract.md +44 -35
  35. package/.claude/skills/docs/public-dev-loop-contract.md +60 -44
  36. package/.claude/skills/docs/retrospective-checkpoint-contract.md +106 -79
  37. package/.claude/skills/docs/spike-mode-contract.md +14 -7
  38. package/.claude/skills/docs/stop-conditions.md +30 -15
  39. package/.claude/skills/docs/tracker-first-loop-state.md +13 -8
  40. package/.claude/skills/docs/ui-e2e-scoping-step.md +32 -0
  41. package/.claude/skills/docs/validation-policy.md +4 -5
  42. package/.claude/skills/docs/workflow-handoff-contract.md +39 -0
  43. package/.claude/skills/local-implementation/SKILL.md +62 -145
  44. package/.claude/skills/loop-grill/SKILL.md +163 -0
  45. package/AGENTS.md +1 -0
  46. package/CHANGELOG.md +101 -0
  47. package/README.md +9 -9
  48. package/agents/dev-loop.agent.md +11 -10
  49. package/agents/developer.agent.md +1 -1
  50. package/agents/docs.agent.md +1 -1
  51. package/agents/fixer.agent.md +2 -1
  52. package/agents/quality.agent.md +1 -1
  53. package/agents/refiner.agent.md +3 -3
  54. package/agents/review.agent.md +5 -4
  55. package/cli/index.mjs +35 -42
  56. package/extension/README.md +4 -4
  57. package/extension/checks.ts +1 -5
  58. package/extension/harness-types.ts +1 -0
  59. package/extension/index.ts +6 -0
  60. package/extension/pi-extension-adapter.ts +2 -0
  61. package/extension/presentation.ts +7 -19
  62. package/package.json +12 -12
  63. package/scripts/_core-helpers.mjs +2 -0
  64. package/scripts/claude/headless-dev-loop.mjs +1 -1
  65. package/scripts/docs/validate-rule-ownership.mjs +442 -0
  66. package/scripts/docs/validate-state-machine-conformance.mjs +1092 -0
  67. package/scripts/github/_review-thread-mutations.mjs +5 -2
  68. package/scripts/github/capture-review-threads.mjs +2 -9
  69. package/scripts/github/comment-issue.mjs +2 -9
  70. package/scripts/github/create-label.mjs +133 -0
  71. package/scripts/github/create-pr.mjs +119 -10
  72. package/scripts/github/detect-checkpoint-evidence.mjs +259 -18
  73. package/scripts/github/detect-linked-issue-pr.mjs +22 -6
  74. package/scripts/github/edit-pr.mjs +259 -0
  75. package/scripts/github/fetch-ci-logs.mjs +2 -9
  76. package/scripts/github/list-issues.mjs +2 -9
  77. package/scripts/github/list-review-threads.mjs +277 -0
  78. package/scripts/github/manage-sub-issues.mjs +46 -10
  79. package/scripts/github/offer-human-handoff.mjs +8 -5
  80. package/scripts/github/post-gate-findings.mjs +20 -5
  81. package/scripts/github/probe-ci-status.mjs +8 -2
  82. package/scripts/github/probe-copilot-review.mjs +21 -14
  83. package/scripts/github/ready-for-review.mjs +26 -8
  84. package/scripts/github/reconcile-draft-gate.mjs +7 -3
  85. package/scripts/github/reply-resolve-review-thread.mjs +16 -5
  86. package/scripts/github/reply-resolve-review-threads.mjs +69 -7
  87. package/scripts/github/request-copilot-review.mjs +98 -26
  88. package/scripts/github/resolve-handoff-candidates.mjs +7 -3
  89. package/scripts/github/resolve-tracker-local-spec.mjs +9 -3
  90. package/scripts/github/stage-reviewer-draft.mjs +10 -2
  91. package/scripts/github/tick-verified-checkboxes.mjs +202 -0
  92. package/scripts/github/upsert-checkpoint-verdict.mjs +105 -15
  93. package/scripts/github/verify-briefing-prefixes.mjs +191 -0
  94. package/scripts/github/verify-fresh-review-context.mjs +226 -32
  95. package/scripts/github/view-pr.mjs +150 -0
  96. package/scripts/github/wait-pr-checks.mjs +171 -0
  97. package/scripts/github/write-gate-context.mjs +458 -65
  98. package/scripts/github/write-gate-findings-log.mjs +128 -2
  99. package/scripts/lib/jq-output.mjs +18 -0
  100. package/scripts/loop/_post-convergence-change.mjs +211 -0
  101. package/scripts/loop/_pr-runner-coordination.mjs +70 -0
  102. package/scripts/loop/_repo-root-resolver.mjs +47 -0
  103. package/scripts/loop/build-handoff-envelope.mjs +14 -4
  104. package/scripts/loop/check-retro-tooling.mjs +14 -3
  105. package/scripts/loop/checkpoint-contract.mjs +7 -4
  106. package/scripts/loop/cleanup-worktree.mjs +12 -3
  107. package/scripts/loop/conductor-monitor.mjs +12 -18
  108. package/scripts/loop/copilot-pr-handoff.mjs +162 -14
  109. package/scripts/loop/debt-remediate.mjs +24 -12
  110. package/scripts/loop/detect-change-scope.mjs +38 -9
  111. package/scripts/loop/detect-copilot-loop-state.mjs +34 -8
  112. package/scripts/loop/detect-copilot-session-activity.mjs +7 -3
  113. package/scripts/loop/detect-initial-copilot-pr-state.mjs +7 -3
  114. package/scripts/loop/detect-internal-only-pr.mjs +8 -2
  115. package/scripts/loop/detect-issue-refinement-artifact.mjs +6 -3
  116. package/scripts/loop/detect-pr-gate-coordination-state.mjs +184 -69
  117. package/scripts/loop/detect-reviewer-loop-state.mjs +12 -2
  118. package/scripts/loop/detect-tracker-first-loop-state.mjs +9 -1
  119. package/scripts/loop/detect-tracker-pr-state.mjs +10 -3
  120. package/scripts/loop/ensure-worktree.mjs +8 -3
  121. package/scripts/loop/info.mjs +12 -4
  122. package/scripts/loop/inspect-run-viewer/constants.mjs +4 -18
  123. package/scripts/loop/inspect-run-viewer/vendor/mermaid.min.js +3405 -0
  124. package/scripts/loop/inspect-run-viewer-ci-changes.mjs +18 -6
  125. package/scripts/loop/inspect-run-viewer.mjs +67 -4
  126. package/scripts/loop/inspect-run.mjs +8 -2
  127. package/scripts/loop/outer-loop.mjs +8 -4
  128. package/scripts/loop/pr-runner-coordination.mjs +2 -9
  129. package/scripts/loop/pre-commit-branch-guard.mjs +16 -10
  130. package/scripts/loop/pre-flight-gate.mjs +9 -9
  131. package/scripts/loop/pre-pr-ready-gate.mjs +8 -4
  132. package/scripts/loop/pre-write-remote-freshness-guard.mjs +13 -4
  133. package/scripts/loop/provision-worktree.mjs +74 -3
  134. package/scripts/loop/resolve-dev-loop-startup.mjs +216 -10
  135. package/scripts/loop/resolve-gate-dispatch.mjs +134 -0
  136. package/scripts/loop/resolve-pr-conflicts.mjs +14 -7
  137. package/scripts/loop/run-conductor-cycle.mjs +8 -2
  138. package/scripts/loop/run-queue.mjs +18 -9
  139. package/scripts/loop/run-refinement-audit.mjs +8 -9
  140. package/scripts/loop/run-watch-cycle.mjs +2 -9
  141. package/scripts/loop/sanctioned-commands.mjs +106 -0
  142. package/scripts/loop/steer-loop.mjs +29 -16
  143. package/scripts/loop/validate-pr-body-spec.mjs +223 -0
  144. package/scripts/loop/watch-initial-copilot-pr.mjs +8 -3
  145. package/scripts/pages/build-site.mjs +59 -8
  146. package/scripts/pages/build-state-atlas.mjs +443 -0
  147. package/scripts/projects/_resolve-project.mjs +1 -0
  148. package/scripts/projects/add-queue-item.mjs +60 -54
  149. package/scripts/projects/archive-done-items.mjs +49 -84
  150. package/scripts/projects/ensure-queue-board.mjs +10 -36
  151. package/scripts/projects/list-queue-items.mjs +59 -382
  152. package/scripts/projects/move-queue-item.mjs +21 -449
  153. package/scripts/projects/reconcile-queue.mjs +253 -0
  154. package/scripts/projects/reorder-queue-item.mjs +43 -68
  155. package/scripts/projects/resolve-active-board-item.mjs +108 -46
  156. package/scripts/projects/sync-item-status.mjs +15 -10
  157. package/scripts/refine/_refine-helpers.mjs +21 -5
  158. package/scripts/refine/exit-spike.mjs +18 -8
  159. package/scripts/refine/promote-plan.mjs +22 -16
  160. package/scripts/refine/prose-linkage-detector.mjs +1 -1
  161. package/scripts/refine/refine-plan-file.mjs +13 -4
  162. package/scripts/refine/refinement-completeness-checker.mjs +1 -1
  163. package/scripts/refine/scaffold-spike-file.mjs +4 -8
  164. package/scripts/refine/scope-boundary-cross-checker.mjs +1 -1
  165. package/scripts/refine/tree-integrity-validator.mjs +1 -1
  166. package/scripts/refine/validate-plan-file.mjs +1 -1
  167. package/scripts/refine/validate-spike-file.mjs +1 -1
  168. package/scripts/refine/verify.mjs +11 -6
  169. package/scripts/release/assert-core-dependency-version.mjs +123 -0
  170. package/scripts/release/extract-changelog-section.mjs +16 -2
  171. package/skills/copilot-pr-followup/SKILL.md +60 -34
  172. package/skills/dev-loop/SKILL.md +11 -7
  173. package/skills/docs/acceptance-criteria-verification.md +8 -3
  174. package/skills/docs/anti-patterns.md +5 -3
  175. package/skills/docs/artifact-authority-contract.md +30 -11
  176. package/skills/docs/confirmation-rules.md +1 -0
  177. package/skills/docs/contract-style-guide.md +37 -0
  178. package/skills/docs/copilot-loop-operations.md +19 -15
  179. package/skills/docs/cross-harness-regression-contract.md +60 -0
  180. package/skills/docs/debt-remediation-contract.md +1 -1
  181. package/skills/docs/epic-tree-refinement-procedure.md +25 -22
  182. package/skills/docs/issue-intake-procedure.md +26 -19
  183. package/skills/docs/local-planning-flow.md +1 -1
  184. package/skills/docs/local-planning-worked-example.md +1 -1
  185. package/skills/docs/merge-preconditions.md +30 -12
  186. package/skills/docs/plan-file-contract.md +1 -1
  187. package/skills/docs/pr-lifecycle-contract.md +44 -35
  188. package/skills/docs/public-dev-loop-contract.md +60 -44
  189. package/skills/docs/required-rules.json +149 -0
  190. package/skills/docs/retrospective-checkpoint-contract.md +106 -79
  191. package/skills/docs/spike-mode-contract.md +14 -7
  192. package/skills/docs/stop-conditions.md +30 -15
  193. package/skills/docs/tracker-first-loop-state.md +13 -8
  194. package/skills/docs/ui-e2e-scoping-step.md +32 -0
  195. package/skills/docs/validation-policy.md +4 -5
  196. package/skills/docs/workflow-handoff-contract.md +39 -0
  197. package/skills/local-implementation/SKILL.md +62 -145
  198. package/skills/loop-grill/SKILL.md +165 -0
  199. package/.claude/commands/continue.md +0 -15
  200. package/scripts/docs/validate-no-duplicate-rules.mjs +0 -250
  201. package/scripts/loop/conductor.mjs +0 -233
  202. package/scripts/loop/detect-stale-runner.mjs +0 -265
  203. package/scripts/loop/pre-push-main-guard.mjs +0 -117
@@ -1,17 +1,20 @@
1
1
  # Issue intake procedure
2
2
 
3
- This document is the canonical owner of the routed `issue_intake` procedure behind the public `dev-loop` façade.
3
+ Canonical owner for the routed `issue_intake` procedure behind the public `dev-loop` façade: preflight, normalization, async refinement, epic decomposition, and Copilot handoff.
4
4
 
5
5
  Use it together with:
6
6
  - [Copilot PR Follow-up Skill](../copilot-pr-followup/SKILL.md)
7
- - [Public Dev Loop Contract](./public-dev-loop-contract.md)
7
+ - [Public Dev Loop Contract](./public-dev-loop-contract.md) — owner of `FACADE-LINKED-PR-SINGLE-ARTIFACT`, `FACADE-BOOTSTRAP-WATCH-ROUTE`, `FACADE-BOOTSTRAP-ISOLATED-WORKTREE-CONTINUATION`
8
8
  - [Retrospective Checkpoint Contract](./retrospective-checkpoint-contract.md) when the current step depends on async start/resume/status or retrospective enforcement
9
+ - [Stop Conditions](./stop-conditions.md) — owner of `STOP-INITIAL-COPILOT-001` and the other strategy-wide stop/wait rules this procedure operationalizes
10
+ - [Merge Preconditions](./merge-preconditions.md) — the merge gate this procedure defers to before `gh pr merge`
9
11
 
10
12
  When routed work is issue-first rather than already in active PR follow-up, use the procedure below before entering the shared post-PR loop. Treat this document as the issue-refinement specialist procedure for the routed `issue_intake` seam.
11
13
 
12
14
  ## New-idea safety layer (default contract in this repo)
13
15
 
14
- For **all new ideas** that are not already anchored to an existing issue (including abstract ideas such as plain-language requests without an issue number or plan-doc path), apply this procedure-owned intake contract before any GitHub mutation:
16
+ <!-- rule: INTAKE-NEW-IDEA-SAFETY -->
17
+ For **all new ideas** that are not already anchored to an existing issue (including abstract ideas such as plain-language requests without an issue number or plan-doc path), the procedure MUST apply this intake contract before any GitHub mutation:
15
18
 
16
19
  - procedure owns classification; human operator gates all mutations
17
20
  - run classification in fresh context by default
@@ -50,9 +53,11 @@ Proposal artifact contract:
50
53
  - machine-readable JSON snapshot
51
54
  - write temporary artifacts under `Proposal` (`tmp/new-idea-intake/<run-id>/proposal.md`) and `tmp/new-idea-intake/<run-id>/proposal.json`
52
55
 
53
- If the Phase 1 preflight verdict is `pause_for_clarification`, stop and ask.
54
- If the intake state machine stops at `stopped_overlap_needs_decision` or `stopped_low_confidence`, stop and ask.
55
- If the intake state machine stops at `stopped_explicit_reject`, stop and record that the proposal was rejected; do not mutate GitHub.
56
+ <!-- rule: INTAKE-STOP-STATES -->
57
+ If the Phase 1 preflight verdict is `pause_for_clarification`, the procedure MUST stop and ask.
58
+ If the intake state machine stops at `stopped_overlap_needs_decision` or `stopped_low_confidence`, the procedure MUST stop and ask.
59
+ If the intake state machine stops at `stopped_explicit_reject`, the procedure MUST stop and record that the proposal was rejected; it MUST NOT mutate GitHub.
60
+
56
61
  After approval, start a separate async mutation pass (dispatched via the procedure) that consumes the approved proposal and emits a post-mutation verification artifact. Emit a concise post-mutation verification artifact and record what the mutation pass actually changed and verify the resulting issue/artifact state.
57
62
 
58
63
  ## Unattended issue-first execution and automatic re-entry
@@ -67,7 +72,7 @@ Under that unattended execution contract:
67
72
  - If a PR already exists, classify the post-assignment seam before follow-up
68
73
  - `waiting_for_initial_copilot_implementation`: keep waiting
69
74
  - `linked_pr_ready_for_followup`: route to the existing PR follow-up path immediately; resume from that PR
70
- - when routing leaves bootstrap wait for `linked_pr_ready_for_followup`, do not stop only because local isolation is required; re-enter the same PR follow-up from a safe isolated checkout/worktree
75
+ - when routing leaves bootstrap wait for `linked_pr_ready_for_followup`, follow [FACADE-BOOTSTRAP-ISOLATED-WORKTREE-CONTINUATION](public-dev-loop-contract.md): re-enter the same PR follow-up from a safe isolated checkout/worktree instead of stopping solely because local isolation is required
71
76
  - When the draft PR appears, classify whether it is still the bootstrap-only Copilot draft before entering normal follow-up
72
77
  - if a child async run exits while the deterministic state is still non-terminal (for example `waiting_for_copilot_review`), automatically resume/restart follow-up when continuation is feasible instead of requiring manual operator restart
73
78
  - continue unattended until the human approval checkpoint unless a genuine stop condition is reached
@@ -107,23 +112,23 @@ Preflight verdicts:
107
112
  - detect an existing linked PR with the deterministic linked-PR helper:
108
113
  `node <resolved-skill-scripts>/github/detect-linked-issue-pr.mjs --repo <resolved-repo> --issue <number>`
109
114
  - treat the helper output as authoritative for linked-PR detection/selection
110
- - do not re-implement linked-event query behavior, pagination, repo filtering, or tie-break logic
111
- - do not rely only on PR title/body containing a literal issue number
115
+ - <!-- rule: INTAKE-LINKED-PR-HELPER-DELEGATION --> `INTAKE-LINKED-PR-HELPER-DELEGATION`: Agents MUST NOT re-implement linked-event query behavior, pagination, repo filtering, or tie-break logic, and MUST NOT rely only on PR title/body containing a literal issue number.
112
116
  - treat an open linked PR as the active implementation for this issue
113
- - once an open linked PR exists, that PR is the only canonical follow-up artifact for the issue; attach follow-up work to it and do not open another PR unless the prior PR was explicitly superseded and reconciled first
117
+ - once an open linked PR exists, attach follow-up work to it per `FACADE-LINKED-PR-SINGLE-ARTIFACT` (owned in [Public Dev Loop Contract](public-dev-loop-contract.md)) for the `issue_intake` strategy
118
+ - **follow-up-capture rule:** when a follow-up is discovered while working a PR/loop, note it on the originating issue (or the PR body); file a standalone issue only if the follow-up is genuinely independent of the PR **and** outlives it (a real separate bug/feature that would be lost as a note on a soon-closed issue). Prefer noting PR-scoped follow-ups on the originating artifact over spinning up standalone tracker items for work that is part of the same effort or will be resolved imminently. See [Sub-Issue Tree Contract](../../docs/sub-issue-tree-contract.md).
114
119
  - if a PR already exists, classify bootstrap-wait versus follow-up:
115
120
  `node <resolved-skill-scripts>/loop/detect-initial-copilot-pr-state.mjs --repo <resolved-repo> --issue <number>`
116
121
  - `waiting_for_initial_copilot_implementation`: keep waiting; in durable-auto mode use:
117
122
  ```sh
118
123
  node <resolved-skill-scripts>/loop/watch-initial-copilot-pr.mjs --repo <resolved-repo> --issue <number>
119
124
  ```
120
- - must use the dedicated `watch-initial-copilot-pr.mjs` watcher and its default 1-hour watch budget
125
+ - durable-auto ownership of this seam (the dedicated watcher + its default 1-hour watch budget) is owned by [FACADE-BOOTSTRAP-WATCH-ROUTE](public-dev-loop-contract.md); this procedure does not restate that rule
121
126
  - quiet/no-activity watch observations alone are non-terminal
122
127
  - `ready_for_followup`: linked PR has become substantive; resume from that PR
123
128
  - `timed_out`: observational first; refresh authoritative state
124
129
  - if refreshed state is still `waiting_for_initial_copilot_implementation`, remain attached to the same durable wait seam and continue waiting
125
130
  - if the refreshed state exits this seam, route based on that refreshed state instead of surfacing timeout attention
126
- - when the refreshed state is `linked_pr_ready_for_followup`, re-enter normal PR follow-up; if the follow-up handoff carries `conductorRouting.handoffEnvelope.requiresLocalIsolation=true`, perform the expected isolated-checkout/worktree handoff and continue
131
+ - when the refreshed state is `linked_pr_ready_for_followup`, re-enter normal PR follow-up per [FACADE-BOOTSTRAP-ISOLATED-WORKTREE-CONTINUATION](public-dev-loop-contract.md): if the follow-up handoff carries `conductorRouting.handoffEnvelope.requiresLocalIsolation=true`, perform the expected isolated-checkout/worktree handoff and continue
127
132
  - only surface timeout attention when the seam's durable watch budget is actually exhausted
128
133
  - for explicit inspect/status requests, report the still-waiting state and exit normally
129
134
  - carry that resolved repo slug through every later GitHub issue/PR command
@@ -198,8 +203,10 @@ node <resolved-skill-scripts>/github/manage-sub-issues.mjs list \
198
203
  --repo <resolved-repo> --issue <parent-number>
199
204
  ```
200
205
 
201
- Do **not** re-implement sub-issue management ad hoc or bypass `manage-sub-issues.mjs`.
202
- Do **not** maintain a body checklist that duplicates the sub-issue tree.
206
+ Ad-hoc bypass of `manage-sub-issues.mjs` and duplicating the tree in the parent body are owned
207
+ by `SUBISSUE-NO-ADHOC-BYPASS` and `SUBISSUE-LEAN-BODY-NO-DUPLICATE` in
208
+ [Sub-Issue Tree Contract](../../docs/sub-issue-tree-contract.md); this procedure does not
209
+ restate those rules.
203
210
 
204
211
  For the full `manage-sub-issues.mjs` contract, use [Sub-Issue Tree Contract](../../docs/sub-issue-tree-contract.md) when working in the `dev-loops` source repository. That contract is a source-repo reference, not part of the bundled installed skill-doc surface. For installed or normalized skill copies, inspect the target repository docs/source directly instead of assuming a bundled shared-doc copy exists.
205
212
 
@@ -231,9 +238,9 @@ The merge itself is gated, not implied by the lines above. Before any `gh pr mer
231
238
  gh pr merge <pr-number> --repo <resolved-repo> --squash --delete-branch
232
239
  ```
233
240
 
234
- Bootstrap-wait interpretation remains fail-closed and observational-first:
235
- - `ready_for_followup`: linked PR has become substantive; resume from that PR
236
- - `timed_out`: observational first; refresh authoritative state
237
- - if refreshed state is still `waiting_for_initial_copilot_implementation`, remain attached to the same durable wait seam and continue waiting
238
- - if refreshed state exits that seam, route based on refreshed state instead of surfacing timeout attention
241
+ Bootstrap-wait interpretation remains fail-closed and observational-first — same seam as Phase 2's `waiting_for_initial_copilot_implementation` handling above: `ready_for_followup` resumes from the now-substantive linked PR; `timed_out` is observational first; refresh authoritative state and re-apply the Phase 2 branching (still-waiting vs. seam-exit) rather than re-deriving it here.
242
+
243
+ ## Cross-references
244
+
245
+ See the "Use it together with" list at the top; additionally, [Epic Tree Refinement Procedure](./epic-tree-refinement-procedure.md) refines an existing sub-issue tree, while this procedure creates it (Phase 3b).
239
246
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  The operator sequence for the local-first plan-file flow. The [Artifact Authority Contract](artifact-authority-contract.md) owns the model and the per-phase contract details; this doc names the shipped helper scripts in the order they run for one plan file. The [Local-Planning Worked Example](local-planning-worked-example.md) shows a single plan file evolving through these steps.
4
4
 
5
- The flow applies under local-planning mode (`strategy.default: local-first`, the shipped default — see the contract's [Shipped default posture](artifact-authority-contract.md#shipped-default-posture)). The plan file lives under `localPlanning.plansDir`, which defaults to `docs/phases/`.
5
+ The flow applies under local-planning mode (`strategy.default: local-first`, the shipped default — see the contract's [Shipped default posture](artifact-authority-contract.md#shipped-default-posture)). The plan file lives under `docs/phases/`.
6
6
 
7
7
  ## Stages
8
8
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  One plan file, `docs/phases/phase-42.md`, carried through every stage of the [Local-Planning Flow](local-planning-flow.md): authored, validated, refined in place, held at the local human-review checkpoint, then promoted to a draft PR. Each stage below shows the same file's content as it evolves. The contract details live in the [Artifact Authority Contract](artifact-authority-contract.md); this is a concrete trace of one file.
4
4
 
5
- The repo runs local-planning by default (`strategy.default: local-first`), and the plan lives under `localPlanning.plansDir` (`docs/phases/`).
5
+ The repo runs local-planning by default (`strategy.default: local-first`), and the plan lives under `docs/phases/`.
6
6
 
7
7
  ## Stage 1 — Authored
8
8
 
@@ -38,14 +38,31 @@ doing manually; it is not a general conflict-resolution engine.
38
38
 
39
39
  ## Required before merge
40
40
 
41
+ <!-- rule: MERGE-PRECOND-REQUIRED -->
41
42
  1. ✅ Conflict-free with base (`mergeable: MERGEABLE`; not `CONFLICTING`/`DIRTY`/`BEHIND`/`UNKNOWN`)
42
- 1. ✅ CI green on current head (or crediblyGreen via `--local-validation-head-sha`)
43
- 2. ✅ Draft gate satisfied (clean verdict)
44
- 3. ✅ Pre-approval gate satisfied (clean verdict, current head)
45
- 4. ✅ All review threads resolved
46
- 5. ✅ Explicit merge authorization from operator
47
- 6. ✅ PR body contains `Closes #N` or `Fixes #N`
48
- 7. ✅ PR **title** free of merge-blocking markers — `WIP`, `[WIP]`, `DRAFT`, `DO NOT MERGE`, `🚧` (case-insensitive)
43
+ 2. ✅ CI green on current head (or crediblyGreen via `--local-validation-head-sha`)
44
+ 3. ✅ Draft gate satisfied clean `draft_gate` verdict per `GATE-COMMENT-VERDICT-VALUES` ([Checkpoint Verdict Comment Contract](../../docs/gate-review-comment-contract.md))
45
+ 4. ✅ Pre-approval gate satisfied clean `pre_approval_gate` verdict on the current head, same rule
46
+ 5. ✅ All review threads resolved
47
+ 6. ✅ Explicit merge authorization from operator
48
+ 7. ✅ Issue-backed work: PR body contains `Closes #N` or `Fixes #N`; for an issue-less lightweight PR the closing reference is instead absent by design (owned by `ARTIFACT-LIGHTWEIGHT-BODY-INVARIANTS` in [Artifact Authority Contract](artifact-authority-contract.md))
49
+ 8. ✅ PR **title** free of merge-blocking markers — `WIP`, `[WIP]`, `DRAFT`, `DO NOT MERGE`, `🚧` (case-insensitive)
50
+
51
+ > Runner-coordination lock: the pre-merge evidence check fails closed on a stale/foreign runner claim for the PR. A completing run releases its claim best-effort at every terminal stop (including the human approval checkpoint), so a merge re-dispatch normally proceeds. If a lock held by a completed/dead run still blocks the merge, take it over explicitly with `node <resolved-skill-scripts>/loop/pr-runner-coordination.mjs takeover --repo <owner/name> --pr <number>`. Never take over a genuinely active (non-stale) run — that fail-closed block is intentional.
52
+
53
+ ### Evidence writes and `gh pr merge` MUST be separate tool calls (#1172)
54
+
55
+ The PreToolUse Bash gate evaluates `gh pr merge` **before** the Bash tool call executes. A compound
56
+ command that both writes gate evidence (the findings-log ledger, `upsert-checkpoint-verdict`) and
57
+ merges in the same call is blocked at hook-evaluation time — the write never runs. This can look
58
+ like the ledger "vanished" between writing and merging; it was never written. The block message
59
+ names this when it detects an evidence-writing invocation in the same command string.
60
+
61
+ Documented pattern — **write, verify, then merge alone**:
62
+
63
+ 1. Write the gate evidence (findings-log ledger / checkpoint verdict) in its own Bash call.
64
+ 2. Verify it landed (e.g. `ls tmp/gate-findings/<slug>/pr-<n>/`) in a separate call.
65
+ 3. Run `gh pr merge` alone, with no other command chained via `&&`/`;`/newline.
49
66
 
50
67
  ## Title markers
51
68
 
@@ -89,7 +106,7 @@ explicit instruction can unlock.
89
106
  When a repo sets `approval.humanHandoff.enabled: true` in `.devloops`, the loop
90
107
  does not just park silently at the human-merge stop — at the
91
108
  `pre_approval_gate` / `waiting_for_merge_authorization` boundary it **offers**
92
- to route the PR to a named human (pairs with `autonomy.humanMergeOnly`: when
109
+ to route the PR to a contributor (pairs with `autonomy.humanMergeOnly`: when
93
110
  human-merge is enforced, the handoff names who should take it). Disabled by
94
111
  default; no candidate sourcing when disabled.
95
112
 
@@ -124,10 +141,8 @@ human(s).
124
141
 
125
142
  ## Post-merge
126
143
 
127
- - Remove merged worktree (canonical): `node scripts/loop/cleanup-worktree.mjs --repo-root <main> (--issue <n> | --pr <n>)`.
128
- It resolves the namespaced path, runs `git worktree remove --force <path> && git worktree prune` (the underlying
129
- mechanism) from the main checkout, and refuses any path not under `tmp/worktrees/dev-loops/`. See
130
- [worktree guidance](../../docs/worktree-guidance.md).
144
+ - Remove merged worktree (canonical, `WORKTREE-CLEANUP`): `node scripts/loop/cleanup-worktree.mjs --repo-root <main> (--issue <n> | --pr <n>)`.
145
+ See [Worktree usage guidance](../../docs/worktree-guidance.md#post-merge-cleanup).
131
146
  - Archive long-done queue items (operator-induced, NOT a cron): `node scripts/projects/archive-done-items.mjs --repo <owner/name> || true`.
132
147
  Runs as part of this post-merge hook. It applies the configured `queue.archiveOlderThanDays` (default `7d`) and archives
133
148
  board items whose issue/PR has been closed at least that long. Best-effort: run it as a standard post-merge step but ignore
@@ -141,3 +156,6 @@ human(s).
141
156
  - [Confirmation rules](confirmation-rules.md)
142
157
  - [Validation policy](validation-policy.md)
143
158
  - [Stop conditions](stop-conditions.md)
159
+ - [PR Lifecycle Contract](pr-lifecycle-contract.md)
160
+ - [Checkpoint Verdict Comment Contract](../../docs/gate-review-comment-contract.md) — `GATE-COMMENT-VERDICT-VALUES`
161
+ - [Contract style guide](contract-style-guide.md)
@@ -4,7 +4,7 @@ A plan file is the persisted markdown artifact that drives work in local-plannin
4
4
 
5
5
  ## Format
6
6
 
7
- A plan file is a markdown document whose sections are level-2 (`##`) headings. It follows the same shape as the phase docs already committed under `docs/phases/`. The directory that holds plan files is `localPlanning.plansDir`, which defaults to `docs/phases/`.
7
+ A plan file is a markdown document whose sections are level-2 (`##`) headings. It follows the same shape as the phase docs already committed under `docs/phases/`, which is also the directory that holds plan files.
8
8
 
9
9
  ## Base authoring sections
10
10
 
@@ -1,6 +1,7 @@
1
1
  # PR lifecycle contract
2
2
 
3
- This document defines the deterministic **family-local PR lifecycle contract** for the GitHub/Copilot workflow family in `dev-loops`.
3
+ Canonical owner for **PR state vocabulary** rules for the GitHub/Copilot workflow family
4
+ in `dev-loops` — the deterministic family-local PR lifecycle contract.
4
5
 
5
6
  The canonical contract lives in the shipped `skills/docs/` surface because installed skill/runtime consumers reliably own the skills subtree.
6
7
 
@@ -38,23 +39,27 @@ It does not redefine helper transport mechanics, reviewer-loop internals, conduc
38
39
 
39
40
  ## Core rules
40
41
 
41
- - Exactly **one current lifecycle state** must apply at a time.
42
- - The lifecycle must fail closed when required evidence is missing, stale, ambiguous, or unparsable.
42
+ <!-- rule: LIFECYCLE-ONE-STATE -->
43
+ `LIFECYCLE-ONE-STATE`: Exactly **one current lifecycle state** MUST apply at a time.
44
+
45
+ - The lifecycle MUST fail closed when required evidence is missing, stale, ambiguous, or unparsable (see [Fail-closed rules](#fail-closed-rules), `LIFECYCLE-FAIL-CLOSED`).
43
46
  - Every gate-crossing decision is for the **current PR head SHA**.
44
47
  - Draft existence alone is **not** draft-gate readiness.
45
- - A PR must clear the draft-stage gate for the current head before Copilot review may be requested.
48
+ - A PR MUST clear the draft-stage gate for the current head before Copilot review may be requested.
46
49
  - Ready -> draft resets the lifecycle back into draft-stage gating.
47
50
  - A merge-blocking marker in the PR **title** (`WIP`/`[WIP]`/`DRAFT`/`DO NOT MERGE`/`🚧`, case-insensitive) blocks the draft -> ready transition and, for non-draft PRs, blocks entry to the pre-approval gate and final approval (`title_marker_blocked`). Markers are permitted only while the PR remains draft. See [Merge preconditions](merge-preconditions.md#title-markers).
48
51
  - Human approval / merge are explicit external waits, not hidden remediation states.
49
52
 
50
53
  ## Two required local gates
51
54
 
52
- Each gate runs an independent review chain with its own disposition ledger, review angles,
53
- and exit conditions. The chains are not interchangeable; see [Checkpoint Review Chain Contract](../../docs/gate-review-sub-loop-contract.md).
55
+ Each gate runs an independent review chain (`GATE-EXEC-SEPARATE-CHAINS`); see
56
+ [Checkpoint Review Chain Contract](../../docs/gate-review-sub-loop-contract.md). Every gate
57
+ pass writes a durable disposition ledger (`GATE-EXEC-DISPOSITION-LEDGER`) before the
58
+ visible comment defined by [Gate Review Comment Contract](../../docs/gate-review-comment-contract.md).
54
59
 
55
60
  ### 1. `draft_gate`
56
61
 
57
- Applies while the PR is draft.
62
+ <!-- term: gate:draft_gate --> Applies while the PR is draft.
58
63
 
59
64
  Purpose:
60
65
  - decide whether the current draft head is materially reviewable
@@ -64,8 +69,6 @@ Purpose:
64
69
  Boundary note:
65
70
  - `draft_gate` governs only the draft -> ready-for-review boundary for the reviewed head
66
71
  - a clean verdict requires no findings at any severity in the gate's `blockCleanOnFindingSeverities` (resolved from config via `resolveGateConfig(config, "draft").blockCleanOnFindingSeverities`)
67
- - every gate pass writes a durable disposition ledger via `write-gate-findings-log.mjs` under `tmp/gate-findings/`
68
- - visible comment schema/evidence rules stay in [Gate Review Comment Contract](../../docs/gate-review-comment-contract.md)
69
72
  - `gates.draft.requireCi=false` does **not** relax `pre_approval_gate`; final approval and merge readiness still require green current-head CI
70
73
 
71
74
  ### 2. `pre_approval_gate`
@@ -77,33 +80,31 @@ This gate uses review angles resolved from config (`resolveGateAngles(config, "p
77
80
  Boundary note:
78
81
  - `pre_approval_gate` governs only final approval readiness for the reviewed head
79
82
  - a clean verdict requires no findings at any severity in the gate's `blockCleanOnFindingSeverities` (resolved from config via `resolveGateConfig(config, "preApproval").blockCleanOnFindingSeverities`)
80
- - every gate pass writes a durable disposition ledger via `write-gate-findings-log.mjs` under `tmp/gate-findings/`
81
83
  - non-draft PRs do not need visible `draft_gate` evidence to enter the post-draft review / `pre_approval_gate` lifecycle; only the draft -> ready transition depends on `draft_gate`
82
- - visible comment schema/evidence rules stay in [Gate Review Comment Contract](../../docs/gate-review-comment-contract.md)
83
84
 
84
85
  ## Lifecycle states
85
86
 
86
- The family-local lifecycle should be modeled in this vocabulary. These state identifiers are part of the stable contract surface for this lifecycle, even if adjacent helper implementations evolve around them:
87
+ The family-local lifecycle SHOULD be modeled in this vocabulary. These state identifiers are part of the stable contract surface for this lifecycle, even if adjacent helper implementations evolve around them:
87
88
 
88
89
  | State | Meaning |
89
90
  |---|---|
90
- | `draft_local_review_gate` | draft PR is at the local draft-stage gate boundary |
91
- | `draft_local_remediation` | draft-stage findings require more local remediation while the PR remains draft |
92
- | `ready_state_needs_copilot_request` | draft gate is clear for the current head; Copilot request is the next legal step |
91
+ | <!-- term: state:draft_local_review_gate --> `draft_local_review_gate` | draft PR is at the local draft-stage gate boundary |
92
+ | <!-- term: state:draft_local_remediation --> `draft_local_remediation` | draft-stage findings require more local remediation while the PR remains draft |
93
+ | <!-- term: state:ready_state_needs_copilot_request --> `ready_state_needs_copilot_request` | draft gate is clear for the current head; Copilot request is the next legal step |
93
94
  | `waiting_for_copilot_review` | Copilot request/re-review is observably in progress for the current head |
94
- | `copilot_feedback_remediation` | unresolved Copilot feedback exists; fixes are the next active step |
95
- | `copilot_reply_resolve_pending` | fixes were applied, but GitHub thread reply/resolve work still remains |
96
- | `merge_conflict_resolution` | current PR head conflicts with base or local reconcile is in progress; resolve conflicts before any further gate progression |
97
- | `final_local_preapproval_gate` | current-head post-Copilot convergence is ready for the final local gate |
98
- | `final_gate_remediation` | Pre-approval gate findings require more remediation after the final gate |
99
- | `waiting_for_human_pr_approval` | local gates are satisfied; waiting for explicit human approval |
100
- | `waiting_for_merge` | approval exists; waiting for merge / merge-triggering external action |
101
- | `terminal_slice_complete` | merged/closed and no further owned step remains |
102
- | `stopped_needs_user_decision` | blocked/ambiguous state requiring explicit human decision |
95
+ | <!-- term: state:copilot_feedback_remediation --> `copilot_feedback_remediation` | unresolved Copilot feedback exists; fixes are the next active step |
96
+ | <!-- term: state:copilot_reply_resolve_pending --> `copilot_reply_resolve_pending` | fixes were applied, but GitHub thread reply/resolve work still remains |
97
+ | <!-- term: state:merge_conflict_resolution --> `merge_conflict_resolution` | current PR head conflicts with base or local reconcile is in progress; resolve conflicts before any further gate progression |
98
+ | <!-- term: state:final_local_preapproval_gate --> `final_local_preapproval_gate` | current-head post-Copilot convergence is ready for the final local gate |
99
+ | <!-- term: state:final_gate_remediation --> `final_gate_remediation` | Pre-approval gate findings require more remediation after the final gate |
100
+ | <!-- term: state:waiting_for_human_pr_approval --> `waiting_for_human_pr_approval` | local gates are satisfied; waiting for explicit human approval |
101
+ | <!-- term: state:waiting_for_merge --> `waiting_for_merge` | approval exists; waiting for merge / merge-triggering external action |
102
+ | <!-- term: state:terminal_slice_complete --> `terminal_slice_complete` | merged/closed and no further owned step remains |
103
+ | <!-- term: state:stopped_needs_user_decision --> `stopped_needs_user_decision` | blocked/ambiguous state requiring explicit human decision |
103
104
 
104
105
  ## Required transitions
105
106
 
106
- At minimum, the lifecycle must enforce these transitions:
107
+ At minimum, the lifecycle MUST enforce these transitions:
107
108
 
108
109
  - `draft_local_review_gate` -> `draft_local_remediation`
109
110
  - blocking `draft_gate` findings
@@ -133,6 +134,8 @@ At minimum, the lifecycle must enforce these transitions:
133
134
  - pre-approval gate findings require changes
134
135
  - `final_local_preapproval_gate` -> `waiting_for_human_pr_approval`
135
136
  - clean current-head `pre_approval_gate` evidence exists
137
+ - `final_gate_remediation` -> `final_local_preapproval_gate`
138
+ - fixes pushed after pre-approval gate findings
136
139
  - `waiting_for_human_pr_approval` -> `waiting_for_merge`
137
140
  - approval arrives
138
141
  - `waiting_for_human_pr_approval` -> `draft_local_review_gate`
@@ -145,17 +148,17 @@ At minimum, the lifecycle must enforce these transitions:
145
148
  - no Copilot request before clean current-head `draft_gate` evidence
146
149
  - no direct skip from fix-applied to Copilot re-request while reply/resolve remains incomplete
147
150
  - no reuse of ready-side or gate evidence after ready -> draft
148
- - a conflicted PR must not be treated as `waiting_for_human_pr_approval`, `waiting_for_merge`, or merge-ready, even if older gate comments and CI were previously green
151
+ - <!-- rule: LIFECYCLE-CONFLICT-BLOCKS-PROGRESS --> `LIFECYCLE-CONFLICT-BLOCKS-PROGRESS`: a conflicted PR MUST NOT be treated as `waiting_for_human_pr_approval`, `waiting_for_merge`, or merge-ready, even if older gate comments and CI were previously green
149
152
  - no implicit fallthrough from approval/merge waits into remediation without a triggering event
150
153
 
151
154
  ## Remediation ownership boundary
152
155
 
153
- The lifecycle must keep the next action class explicit:
156
+ The lifecycle MUST keep the next action class explicit:
154
157
  - draft-stage local findings route to `draft_local_remediation`
155
158
  - unresolved Copilot feedback routes to `copilot_feedback_remediation`
156
159
  - fixes applied but unresolved GitHub reply/resolve work remains route to `copilot_reply_resolve_pending`
157
160
  - pre-approval gate findings route to `final_gate_remediation`
158
- - merge conflicts route to `merge_conflict_resolution` and must be reconciled locally on the PR branch before lifecycle re-entry
161
+ - merge conflicts route to `merge_conflict_resolution` and MUST be reconciled locally on the PR branch before lifecycle re-entry
159
162
  - human approval / merge remain explicit external waits
160
163
 
161
164
  Reviewer-loop reminder:
@@ -164,7 +167,7 @@ Reviewer-loop reminder:
164
167
 
165
168
  ## Required evidence classes
166
169
 
167
- The lifecycle distinguishes two evidence classes:
170
+ The lifecycle distinguishes three evidence classes:
168
171
 
169
172
  1. **observable GitHub state**
170
173
  - PR draft/non-draft/merged/closed state
@@ -176,10 +179,8 @@ The lifecycle distinguishes two evidence classes:
176
179
  - current-head `draft_gate` evidence when draft-gate clearance is required
177
180
  - current-head `pre_approval_gate` evidence when final approval readiness is required
178
181
 
179
- 3. **durable disposition ledger**
180
- - every gate pass logs findings and dispositions under `tmp/gate-findings/<repo-slug>/pr-<N>/`
181
- - the ledger is the durable record of what each gate found and what was decided
182
- - the visible PR comment is a summary; the disposition ledger is the complete record
182
+ 3. **durable disposition ledger** — owned by `GATE-EXEC-DISPOSITION-LEDGER`
183
+ (see [Checkpoint Review Chain Contract](../../docs/gate-review-sub-loop-contract.md#disposition-ledger-and-durable-logging))
183
184
 
184
185
  ### Precedence rules
185
186
 
@@ -189,7 +190,8 @@ The lifecycle distinguishes two evidence classes:
189
190
 
190
191
  ## Fail-closed rules
191
192
 
192
- The lifecycle must stop or reconcile rather than advance when:
193
+ <!-- rule: LIFECYCLE-FAIL-CLOSED -->
194
+ `LIFECYCLE-FAIL-CLOSED`: The lifecycle MUST stop or reconcile rather than advance when:
193
195
  - current head SHA cannot be determined
194
196
  - required current-head `draft_gate` evidence is missing
195
197
  - required current-head `pre_approval_gate` evidence is missing
@@ -202,9 +204,16 @@ The lifecycle must stop or reconcile rather than advance when:
202
204
  - a boundary that is already CI/validation-dependent cannot confirm current-head freshness because the relevant status is pending, none, unknown, or stale
203
205
  - a required visible gate comment could not be confirmed posted
204
206
 
205
- In those cases the workflow must not:
207
+ In those cases the workflow MUST NOT:
206
208
  - leave draft
207
209
  - request or re-request Copilot review
208
210
  - declare final approval readiness
209
211
  - silently fall through to a more permissive state
210
212
 
213
+ ## Cross-references
214
+
215
+ - [Checkpoint Review Chain Contract](../../docs/gate-review-sub-loop-contract.md) — `GATE-EXEC-*` execution-shape rules
216
+ - [Gate Review Comment Contract](../../docs/gate-review-comment-contract.md) — `GATE-COMMENT-*` PR-comment field rules
217
+ - [Merge preconditions](merge-preconditions.md)
218
+ - [Contract style guide](contract-style-guide.md)
219
+