dev-loops 0.1.0

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 (156) hide show
  1. package/.pi/dev-loop/defaults.yaml +477 -0
  2. package/AGENTS.md +25 -0
  3. package/CHANGELOG.md +18 -0
  4. package/LICENSE +21 -0
  5. package/README.md +178 -0
  6. package/agents/dev-loop.agent.md +82 -0
  7. package/agents/developer.agent.md +37 -0
  8. package/agents/docs.agent.md +33 -0
  9. package/agents/fixer.agent.md +53 -0
  10. package/agents/quality.agent.md +28 -0
  11. package/agents/refiner.agent.md +87 -0
  12. package/agents/review.agent.md +64 -0
  13. package/cli/index.mjs +424 -0
  14. package/extension/README.md +233 -0
  15. package/extension/checks.ts +94 -0
  16. package/extension/index.ts +131 -0
  17. package/extension/post-merge-update.ts +512 -0
  18. package/extension/presentation.ts +107 -0
  19. package/lib/dev-loops-core.mjs +284 -0
  20. package/package.json +103 -0
  21. package/scripts/README.md +1007 -0
  22. package/scripts/_cli-primitives.mjs +10 -0
  23. package/scripts/_core-helpers.mjs +30 -0
  24. package/scripts/docs/validate-links.mjs +567 -0
  25. package/scripts/docs/validate-no-duplicate-rules.mjs +250 -0
  26. package/scripts/github/_review-thread-mutations.mjs +214 -0
  27. package/scripts/github/capture-review-threads.mjs +180 -0
  28. package/scripts/github/create-draft-pr.mjs +108 -0
  29. package/scripts/github/detect-checkpoint-evidence.mjs +393 -0
  30. package/scripts/github/detect-linked-issue-pr.mjs +331 -0
  31. package/scripts/github/manage-sub-issues.mjs +394 -0
  32. package/scripts/github/probe-copilot-review.mjs +323 -0
  33. package/scripts/github/ready-for-review.mjs +93 -0
  34. package/scripts/github/reconcile-draft-gate.mjs +328 -0
  35. package/scripts/github/reply-resolve-review-thread.mjs +42 -0
  36. package/scripts/github/reply-resolve-review-threads.mjs +329 -0
  37. package/scripts/github/request-copilot-review.mjs +551 -0
  38. package/scripts/github/resolve-tracker-local-spec.mjs +205 -0
  39. package/scripts/github/stage-reviewer-draft.mjs +191 -0
  40. package/scripts/github/upsert-checkpoint-verdict.mjs +694 -0
  41. package/scripts/github/verify-fresh-review-context.mjs +125 -0
  42. package/scripts/github/write-gate-findings-log.mjs +212 -0
  43. package/scripts/loop/_checkpoint-io.mjs +55 -0
  44. package/scripts/loop/_checkpoint-paths.mjs +28 -0
  45. package/scripts/loop/_handoff-contract.mjs +230 -0
  46. package/scripts/loop/_inspect-run-viewer-adapter.mjs +345 -0
  47. package/scripts/loop/_loop-evidence.mjs +32 -0
  48. package/scripts/loop/_pr-runner-coordination.mjs +611 -0
  49. package/scripts/loop/_stale-runner-detection.mjs +145 -0
  50. package/scripts/loop/_steering-state-file.mjs +134 -0
  51. package/scripts/loop/build-handoff-envelope.mjs +181 -0
  52. package/scripts/loop/checkpoint-contract.mjs +49 -0
  53. package/scripts/loop/conductor-monitor.mjs +1850 -0
  54. package/scripts/loop/conductor.mjs +214 -0
  55. package/scripts/loop/copilot-pr-handoff.mjs +493 -0
  56. package/scripts/loop/debt-remediate.mjs +304 -0
  57. package/scripts/loop/detect-change-scope.mjs +102 -0
  58. package/scripts/loop/detect-copilot-loop-state.mjs +454 -0
  59. package/scripts/loop/detect-copilot-session-activity.mjs +186 -0
  60. package/scripts/loop/detect-initial-copilot-pr-state.mjs +318 -0
  61. package/scripts/loop/detect-internal-only-pr.mjs +270 -0
  62. package/scripts/loop/detect-issue-refinement-artifact.mjs +163 -0
  63. package/scripts/loop/detect-pr-gate-coordination-state.mjs +509 -0
  64. package/scripts/loop/detect-reviewer-loop-state.mjs +231 -0
  65. package/scripts/loop/detect-stale-runner.mjs +250 -0
  66. package/scripts/loop/detect-tracker-first-loop-state.mjs +76 -0
  67. package/scripts/loop/detect-tracker-pr-state.mjs +102 -0
  68. package/scripts/loop/info.mjs +267 -0
  69. package/scripts/loop/inspect-run-viewer/cli.mjs +117 -0
  70. package/scripts/loop/inspect-run-viewer/constants.mjs +80 -0
  71. package/scripts/loop/inspect-run-viewer/graph.mjs +757 -0
  72. package/scripts/loop/inspect-run-viewer/handoff-envelope-renderer.mjs +398 -0
  73. package/scripts/loop/inspect-run-viewer/inbox.mjs +308 -0
  74. package/scripts/loop/inspect-run-viewer/managed-instance.mjs +750 -0
  75. package/scripts/loop/inspect-run-viewer/rendering.mjs +411 -0
  76. package/scripts/loop/inspect-run-viewer/server.mjs +638 -0
  77. package/scripts/loop/inspect-run-viewer/shared.mjs +103 -0
  78. package/scripts/loop/inspect-run-viewer/status.mjs +715 -0
  79. package/scripts/loop/inspect-run-viewer-ci-changes.mjs +77 -0
  80. package/scripts/loop/inspect-run-viewer.mjs +82 -0
  81. package/scripts/loop/inspect-run.mjs +382 -0
  82. package/scripts/loop/outer-loop.mjs +419 -0
  83. package/scripts/loop/pr-runner-coordination.mjs +143 -0
  84. package/scripts/loop/pre-commit-branch-guard.mjs +68 -0
  85. package/scripts/loop/pre-flight-gate.mjs +236 -0
  86. package/scripts/loop/pre-pr-ready-gate.mjs +183 -0
  87. package/scripts/loop/pre-push-main-guard.mjs +103 -0
  88. package/scripts/loop/pre-write-remote-freshness-guard.mjs +32 -0
  89. package/scripts/loop/print-gates.mjs +42 -0
  90. package/scripts/loop/resolve-dev-loop-startup.mjs +533 -0
  91. package/scripts/loop/run-conductor-cycle.mjs +322 -0
  92. package/scripts/loop/run-queue.mjs +124 -0
  93. package/scripts/loop/run-refinement-audit.mjs +513 -0
  94. package/scripts/loop/run-watch-cycle.mjs +358 -0
  95. package/scripts/loop/steer-loop.mjs +841 -0
  96. package/scripts/loop/ui-designer-review-contract.mjs +76 -0
  97. package/scripts/loop/watch-initial-copilot-pr.mjs +253 -0
  98. package/scripts/projects/add-queue-item.mjs +528 -0
  99. package/scripts/projects/ensure-queue-board.mjs +837 -0
  100. package/scripts/projects/list-queue-items.mjs +489 -0
  101. package/scripts/projects/move-queue-item.mjs +549 -0
  102. package/scripts/projects/reorder-queue-item.mjs +518 -0
  103. package/scripts/refine/_refine-helpers.mjs +258 -0
  104. package/scripts/refine/prose-linkage-detector.mjs +92 -0
  105. package/scripts/refine/refinement-completeness-checker.mjs +88 -0
  106. package/scripts/refine/scope-boundary-cross-checker.mjs +163 -0
  107. package/scripts/refine/tree-integrity-validator.mjs +211 -0
  108. package/scripts/refine/verify.mjs +178 -0
  109. package/scripts/repo-wiki-local.mjs +156 -0
  110. package/scripts/repo-wiki.mjs +119 -0
  111. package/skills/copilot-pr-followup/SKILL.md +380 -0
  112. package/skills/dev-loop/SKILL.md +141 -0
  113. package/skills/dev-loop/scripts/dev-mode-context.mjs +152 -0
  114. package/skills/dev-loop/scripts/dev-mode-context.test.mjs +80 -0
  115. package/skills/dev-loop/scripts/init-phase.mjs +71 -0
  116. package/skills/dev-loop/scripts/log-bash-exit-1.mjs +25 -0
  117. package/skills/dev-loop/scripts/phase-files.mjs +29 -0
  118. package/skills/dev-loop/scripts/post-gate-verdict-fallback.mjs +480 -0
  119. package/skills/dev-loop/scripts/post-gate-verdict-fallback.test.mjs +732 -0
  120. package/skills/dev-loop/scripts/render-template.mjs +82 -0
  121. package/skills/dev-loop/scripts/render-template.test.mjs +63 -0
  122. package/skills/dev-loop/templates/bootstrap-agents.md +26 -0
  123. package/skills/dev-loop/templates/bootstrap-implementation-state.md +31 -0
  124. package/skills/dev-loop/templates/bootstrap-implementation-workflow.md +17 -0
  125. package/skills/dev-loop/templates/dev-mode-retrospective.md +15 -0
  126. package/skills/dev-loop/templates/dev-mode-review.md +17 -0
  127. package/skills/dev-loop/templates/dev-mode-skill-changes.md +11 -0
  128. package/skills/dev-loop/templates/merged-phase-plan.md +19 -0
  129. package/skills/dev-loop/templates/phase-doc.md +27 -0
  130. package/skills/dev-loop/templates/phase-summary.md +13 -0
  131. package/skills/dev-loop/templates/phase-variant.md +15 -0
  132. package/skills/dev-loop/templates/retrospective.md +11 -0
  133. package/skills/dev-loop/templates/review.md +32 -0
  134. package/skills/dev-loop/templates/ui-vision-review.md +55 -0
  135. package/skills/docs/acceptance-criteria-verification.md +21 -0
  136. package/skills/docs/anti-patterns.md +21 -0
  137. package/skills/docs/artifact-authority-contract.md +119 -0
  138. package/skills/docs/confirmation-rules.md +28 -0
  139. package/skills/docs/copilot-ci-status-contract.md +52 -0
  140. package/skills/docs/copilot-loop-operations.md +233 -0
  141. package/skills/docs/debt-remediation-contract.md +107 -0
  142. package/skills/docs/entrypoint-strategies.md +115 -0
  143. package/skills/docs/epic-tree-refinement-procedure.md +234 -0
  144. package/skills/docs/issue-intake-procedure.md +235 -0
  145. package/skills/docs/main-agent-contract.md +72 -0
  146. package/skills/docs/merge-preconditions.md +29 -0
  147. package/skills/docs/pr-lifecycle-contract.md +209 -0
  148. package/skills/docs/public-dev-loop-contract.md +497 -0
  149. package/skills/docs/retrospective-checkpoint-contract.md +159 -0
  150. package/skills/docs/stop-conditions.md +29 -0
  151. package/skills/docs/structural-quality.md +42 -0
  152. package/skills/docs/tracker-first-loop-state.md +281 -0
  153. package/skills/docs/validation-policy.md +27 -0
  154. package/skills/docs/workflow-handoff-contract.md +135 -0
  155. package/skills/final-approval/SKILL.md +19 -0
  156. package/skills/local-implementation/SKILL.md +640 -0
@@ -0,0 +1,380 @@
1
+ ---
2
+ name: copilot-pr-followup
3
+ description: >-
4
+ Internal routed strategy behind `dev-loop` for GitHub-first Copilot-owned PR
5
+ follow-up: inspect the canonical PR state, request or re-request Copilot when
6
+ appropriate, wait deterministically for new review activity, run narrow Pi
7
+ fix/reply/resolve passes, verify gate evidence, and stop for explicit human
8
+ approval before merge.
9
+ compatibility: Internal routed strategy for Copilot PR follow-up. Needs gh auth for PR-followup automation.
10
+ allowed-tools: read bash edit write subagent review_loop
11
+ user-invocable: false
12
+ ---
13
+
14
+ # Copilot PR Follow-up
15
+
16
+ This skill is the canonical internal `copilot_pr_followup` route behind the public `dev-loop` façade.
17
+
18
+ It is also the canonical internal owner of the shared post-PR mechanics used by this repo:
19
+ PR discovery and interpretation, async watch behavior, fix / reply-resolve / re-request flow,
20
+ gate sequencing, final approval, and merge-ready preconditions.
21
+
22
+ ## Route ownership
23
+
24
+ Use this skill whenever the public router lands on any PR-follow-up path that shares the same
25
+ post-PR mechanics:
26
+ - `copilot_pr_followup`
27
+ - `external_pr_followup`
28
+ - `reviewer_fixer`
29
+ - `wait_watch`
30
+
31
+ Route-specific companion docs:
32
+ - routed `issue_intake` work is implemented through this skill plus [Copilot Loop Operations](../docs/copilot-loop-operations.md) and [Issue Intake Procedure](../docs/issue-intake-procedure.md)
33
+ - routed `final_approval` work is implemented through this skill's **Human approval checkpoint** section; [Final Approval](../final-approval/SKILL.md) is now a thin redirect to that canonical section
34
+ - the deterministic state-machine/operator guide lives in [Copilot Loop Operations](../docs/copilot-loop-operations.md)
35
+
36
+ ## Operational cookbook
37
+
38
+ All commands use the resolved skill scripts directory (see [Skill asset path resolution](#skill-asset-path-resolution) below).
39
+
40
+ **1. Detect current loop state**
41
+ ```sh
42
+ node <resolved-skill-scripts>/loop/detect-copilot-loop-state.mjs --repo <owner/name> --pr <number>
43
+ ```
44
+ Emits JSON including `{ ok: true, state, allowedTransitions, nextAction, snapshot }`. Follow `nextAction`.
45
+
46
+ **2. One-step detect → request → emit watch params (preferred handoff contract)**
47
+ ```sh
48
+ node <resolved-skill-scripts>/loop/copilot-pr-handoff.mjs --repo <owner/name> --pr <number>
49
+ ```
50
+ Use this helper output as source of truth for the normal routing seam. Interpret:
51
+ - `requestWatchContract.routingState` for request-vs-watch posture
52
+ - `requestWatchContract.requestStatus` and top-level `action` / `nextAction`
53
+ - `watchArgs` only when `action: "watch"` and `requestWatchContract.watchEntryConfirmed=true`
54
+ - `requestWatchContract.stopState` for explicit blocked/stop handling
55
+
56
+ **3. Preferred async wait-boundary helper**
57
+ ```sh
58
+ node <resolved-skill-scripts>/loop/run-watch-cycle.mjs --repo <owner/name> --pr <number>
59
+ ```
60
+ Persistent async watch/fix loop, not handoff-only behavior: `watch → detect → if threads found, fix + reply + resolve → re-request → watch again → … → pre_approval_gate → merge`. **PERSISTENCE MODEL: Subagents do bounded implementation tasks and exit on external wait. The main session drives the loop and re-dispatches when continuation is feasible.** A single returned watch cycle is never completion by itself. If `cycleDisposition` is `pending` and `terminal` is `false`, the subagent exits on the wait boundary; the main session re-dispatches another watch boundary. Max watch timeout: **30 minutes** (from `policy-constants.mjs` COPILOT_REVIEW_WAIT_TIMEOUT_MS); expired budget + still `waiting_for_copilot_review` = hard stop. If the user explicitly asks for async handoff-only behavior, say that out loud and stop after the handoff boundary.
61
+
62
+ **4. Low-level helpers**
63
+ ```sh
64
+ node <resolved-skill-scripts>/github/request-copilot-review.mjs --help
65
+ node <resolved-skill-scripts>/github/probe-copilot-review.mjs --help
66
+ node <resolved-skill-scripts>/loop/detect-copilot-loop-state.mjs --help
67
+ ```
68
+
69
+ For detailed machine guarantees, judgment calls, pre-follow-up planning rules, PR description rules, and timeout defaults, use [Copilot Loop Operations](../docs/copilot-loop-operations.md).
70
+
71
+ ## Required startup reads
72
+
73
+ Read the canonical entrypoint briefing first: [Entrypoint Strategies](../docs/entrypoint-strategies.md#copilot-pr-follow-up). Then read only the contract docs needed for the current step:
74
+
75
+ - [Agent Instructions](../../AGENTS.md) (repo constitution)
76
+ - [Public Dev Loop Contract](../docs/public-dev-loop-contract.md) (always)
77
+ - [Retrospective Checkpoint Contract](../docs/retrospective-checkpoint-contract.md) (when async state/resume applies)
78
+ - Active GitHub issue/PR
79
+ - Task-relevant source, tests, config, and CI
80
+
81
+ Route-dependent: see [Copilot Loop Operations](../docs/copilot-loop-operations.md) and [Issue Intake Procedure](../docs/issue-intake-procedure.md) when relevant.
82
+ Verify all material claims against source, tests, configuration, and CI.
83
+
84
+ ## Skill asset path resolution
85
+
86
+ When this skill refers to helper paths such as `scripts/...` or `docs/...`, resolve them from the actual skill installation layout you are running, not from the active target repository checkout.
87
+
88
+ Use this rule:
89
+ - if the skill is installed as a normalized standalone copy, the required bundled contract docs live under the shared `../docs/` directory next to the installed skill directories; do not assume helper scripts are bundled unless that installed layout actually contains them
90
+ - if you are working in the `dev-loops` source repository, this skill file lives under `skills/copilot-pr-followup/`, so source-repo helper scripts live two levels up at `../../scripts/`, while required bundled contract docs live one level up at `../docs/`
91
+ - when in doubt, resolve helper paths relative to this [skill file](./SKILL.md) first, then verify the target file exists before running it
92
+
93
+ Required bundled runtime contract docs for installed copies of this skill:
94
+ - [Public Dev Loop Contract](../docs/public-dev-loop-contract.md)
95
+ - [Retrospective Checkpoint Contract](../docs/retrospective-checkpoint-contract.md)
96
+ - [Issue Intake Procedure](../docs/issue-intake-procedure.md)
97
+ - [Copilot Loop Operations](../docs/copilot-loop-operations.md)
98
+
99
+ Read those bundled `../docs/` files from the installed skill layout instead of assuming the source repository checkout is present. If any required bundled contract doc is missing from the installed skill layout, treat that as a packaging/installer bug.
100
+ Do not assume `scripts/...` is repo-local to the target codebase you are operating on.
101
+
102
+ ## Authority and safety rules
103
+
104
+ Source code, tests, CI, and config are authoritative. Generated wiki is navigation aid only. See [Confirmation Rules](../docs/confirmation-rules.md), [Stop Conditions](../docs/stop-conditions.md), and [Merge Preconditions](../docs/merge-preconditions.md) for authorization boundaries.
105
+
106
+ ## Structural quality
107
+
108
+ Apply [Structural Quality](../docs/structural-quality.md) standards from the `deep` review angle during implementation and follow-up fixes.
109
+
110
+ ## Step 5: PR discovery and interpretation
111
+
112
+ Treat the PR as the main working artifact once it exists.
113
+
114
+ Inspect: PR body/title (must satisfy [PR description contract](../docs/copilot-loop-operations.md)), closing reference (operator-controlled; subagents must NOT modify), author, review summaries, unresolved comments, latest commits, CI results.
115
+
116
+ At the issue-assignment seam, use `detect-initial-copilot-pr-state.mjs` and keep waiting when `waiting_for_initial_copilot_implementation`.
117
+
118
+ When confirming whether Copilot is requested as a reviewer, do not rely solely on `gh pr view --json reviewRequests`. Use `request-copilot-review.mjs` (see [Operational cookbook](#operational-cookbook)). Do **not** request Copilot by posting literal `/copilot` or `/copilot re-review` PR comments. After draft→ready or fix push, explicitly decide whether another pass is desired; if yes, ensure green/credibly green posture first.
119
+
120
+ Branch on the `request-copilot-review.mjs` machine-readable result:
121
+ - `requested`: if another Copilot pass is actually desired, immediately re-baseline with `detect-copilot-loop-state.mjs` and follow its `nextAction` (enter persistent wait only through `dev-loops loop watch-cycle` or `gh run watch`)
122
+ - `already-requested`: apply the same detector-first rebasing and wait branching as `requested`
123
+ - `suppressed_same_head_clean`: report clean-converged state and stop unless `--force-rerequest-review` bypass is intentionally authorized
124
+ - `unavailable`: report the limitation and stop
125
+ - non-zero / unexpected failure: stop and report error
126
+
127
+ Do not treat an attempted request as equivalent to a confirmed request.
128
+
129
+ ### Re-attachment guard (check for existing loop state first)
130
+
131
+ Before entering issue-intake normalization or asking "what should we do" for a PR that
132
+ already has an outer-loop checkpoint, check whether the checkpoint implies an auto-resume:
133
+
134
+ 1. Read the existing outer-loop checkpoint from
135
+ `tmp/copilot-loop/<owner>/<repo>/pr-<n>/outer-loop-state.json`.
136
+ Do **not** run `outer-loop.mjs` for this guard — it always rewrites the checkpoint
137
+ (including `timestamp` and potentially incrementing `waitCycles`).
138
+ Read the on-disk artifact without mutating it.
139
+ 2. If `outerAction` is `continue_wait`:
140
+ - The loop was waiting. The subagent exits; the main session re-dispatches a fresh
141
+ `dev-loop` async subagent that resumes from the checkpoint.
142
+ 3. If `outerAction` is `reenter_copilot_loop`:
143
+ - The copilot inner loop needs action. Run `copilot-pr-handoff.mjs` to determine the
144
+ exact next step and proceed.
145
+ 4. If `outerAction` is `reenter_reviewer_loop`:
146
+ - The reviewer inner loop needs action. Enter the reviewer-loop path.
147
+ 5. If `outerAction` is `stop`:
148
+ - Report the `reason` field and ask for direction.
149
+ 6. If no checkpoint exists or `outerAction` is `done`:
150
+ - Continue with normal step sequencing.
151
+
152
+ Do not skip this guard when transitioning between async subagent runs on the same PR.
153
+ The outer-loop checkpoint is the canonical re-attachment artifact for the subagent.
154
+
155
+ ## Step 6: Async watch behavior
156
+
157
+ Start every wait seam with a detector refresh: `detect-copilot-loop-state.mjs --repo <owner/name> --pr <number>`.
158
+
159
+ Allowed wait tools: `detect-copilot-loop-state.mjs` (one-shot), `dev-loops loop watch-cycle` (persistent), `copilot-pr-handoff.mjs --watch-status` (refresh after timeout/idle), `gh run watch <run-id> --repo <owner/name>` (CI with known run id). Otherwise exit and resume later from fresh detector call.
160
+
161
+ Practical rules: do not poll manually. `waiting_for_copilot_review` → `run-watch-cycle.mjs` or report-and-resume. `waiting_for_ci` with pending/none CI → `gh run watch <run-id> --repo <owner/name>` (known run id) or report-and-resume. Bounded CI exception: zero current-head suites + previous-head green + local `npm run verify` passed → rerun detector with `--local-validation-head-sha` for `crediblyGreen` promotion. `ciStatus=failure` → stop/fix, never wait.
162
+
163
+ Preferred approach:
164
+ - route decisions through `copilot-pr-handoff.mjs` output; enter watcher only on `action: "watch"` with `watchEntryConfirmed=true`; prefer `dev-loops loop watch-cycle` for deterministic handoff → watch
165
+ - `changed` → re-enter Step 7 fix/reply-resolve/validate immediately; do not stop after one watch cycle
166
+ - `timeout`/`idle` → re-run `copilot-pr-handoff.mjs --watch-status <status>` once to refresh state; if still `waiting_for_copilot_review` after 30-minute watch budget exhausted, hard stop with `watch timeout — PR #<number> needs manual attention`
167
+ - zero-timeout `idle` probes are for explicit one-shot status/reattach checks only; they are not the normal async wait mechanism
168
+ - after a successful fix / reply-resolve / re-request cycle, returning to `waiting_for_copilot_review` is a persistence boundary: resume the watcher instead of reporting completion
169
+ - if a child async run exits and the refreshed state remains non-terminal (for example `waiting_for_copilot_review`) before merge and without a hard stop, treat that as early exit and the main session re-dispatches the same-PR follow-up path when feasible (the subagent exits on external wait)
170
+ - dispatch fix findings to `fixer` subagent; do not run inline fix passes in-watcher
171
+ - do not report completion while unresolved Copilot feedback remains
172
+
173
+ ### Canonical async dispatch wording
174
+
175
+ Every async dev-loop dispatch task body must include this clause verbatim so fresh-context subagents inherit the gate requirement:
176
+
177
+ > Before reporting merge-ready or stopping at the human approval checkpoint, you must complete the pre_approval_gate procedure and verify that a visible clean checkpoint verdict comment exists on the PR for the current head SHA. Do not stop or report completion without this evidence.
178
+
179
+ Key rules:
180
+ - helper-owned sleep inside `dev-loops loop watch-cycle`, `dev-loops gate probe-copilot`, or `dev-loops loop watch-initial` is allowed
181
+ - agent-authored shell polling is forbidden: do not use `nohup`, detached shell jobs, `tmux`, `screen`, or ad hoc `for i in $(seq ...)`, `while true`, `until ...; do sleep ...; done`, or `sleep`-retry bash loops
182
+ - do not wrap repeated `gh pr view`, `gh pr checks`, `gh api`, or `detect-copilot-loop-state.mjs` calls inside shell polling loops
183
+ - do not bypass session-based async notifications with detached shell automation
184
+ - if Pi async subagents or the designated async follow-up skill are not appropriate or available, stop and report rather than improvising a shell watcher
185
+ - the async-start contract is enforced in code: `outer-loop.mjs` fails closed without a visible Pi-managed async run id when `workflow.asyncStartMode: required`
186
+
187
+ ### Async delegation guard rules (#524)
188
+
189
+ See [Async delegation guard rules](../dev-loop/SKILL.md#async-delegation-guard-rules-524) in the public `dev-loop` skill. Those rules are authoritative and apply to all async subagent dispatch in the PR-followup pipeline. The dev-loop skill is the single source of truth; this section exists only to ensure the rules are visible when this skill is loaded standalone.
190
+
191
+ ## Step 7: Pi review/fix follow-up loop
192
+
193
+ This step covers four responsibilities: the draft gate right before `gh pr ready`, the narrower post-review follow-up loop once unresolved feedback exists, the pre-approval gate before calling the PR merge-ready, and the final approval / merge boundary.
194
+
195
+ ### Follow-up loop when unresolved feedback exists
196
+
197
+ When unresolved feedback exists, use a narrow follow-up loop:
198
+
199
+ 1. inspect unresolved comments/threads and failing checks
200
+ 2. before the first local file write in each fixer pass on a Copilot-assigned PR, run `node <resolved-skill-scripts>/loop/pre-write-remote-freshness-guard.mjs --branch <headRefName>` as a required fail-closed guard
201
+ - source `<headRefName>` from authoritative PR state (`headRefName`), not from a local branch guess
202
+ - if the guard exits non-zero (`remote_ahead`), stop writing locally, reconcile to the refreshed remote head, then restart the fixer pass
203
+ 3. classify findings:
204
+ - must-fix: blocks gate; always fixed
205
+ - worth-fixing-now: blocks gate when `blockCleanOnFindingSeverities` includes it; fixed when blocking
206
+ - defer / non-blocking / disagree
207
+ 4. apply only the accepted narrow fixes
208
+ 5. run the smallest validation that honestly proves the fix
209
+ 6. if files changed, run `node <resolved-skill-scripts>/loop/pre-commit-branch-guard.mjs --expected-branch <headRefName>` immediately before every `git add && git commit` sequence as a required fail-closed guard
210
+ - source `<headRefName>` from authoritative PR state (`headRefName`), not from a local branch guess
211
+ - if the guard exits non-zero (`branch_mismatch`), stop and realign to the expected branch before staging or committing
212
+ 7. if files changed, push the resolving commit before any thread reply claims the fix is present
213
+ 8. when a comment or thread is actually addressed, reply on GitHub with a short resolution note that references the resolving commit SHA or commit URL when applicable
214
+ - for one thread, must use the deterministic helper `reply-resolve-review-thread.mjs` from the resolved skill scripts directory
215
+ - when the same bounded resolution note applies to multiple matching unresolved threads, use `reply-resolve-review-threads.mjs` instead of ad hoc inline `gh api` / `gh api graphql` mutations
216
+ - when using the single-thread helper, pair `--comment-id` and `--thread-id` from the same fresh PR thread snapshot rather than mixing ids across review rounds
217
+ - use a body file under `tmp/` rather than inline shell text for the single-thread reply body; for the batch helper, prefer stdin from that same `tmp/` body file rather than inline shell text
218
+ - when the intent is GitHub linkability, keep commit SHAs and issue/PR refs as plain text (for example 3ee82fc and owner/repo#70) and do not wrap them in backticks
219
+ - keep backticks for actual code/path/CLI literals only
220
+ - if either helper was newly added or recently changed, smoke-check it against one real thread before assuming the rest of the loop can rely on it
221
+ 9. before resolving an addressed review thread, run a post-fix verification checkpoint
222
+ - confirm the GitHub reply actually exists on the intended thread/comment, not only in local notes or helper stdout
223
+ - confirm the pushed current-head diff genuinely addresses the reviewer concern on the flagged lines or pattern; if the concern is only partially addressed, leave the thread open and explain what remains
224
+ - refresh the API-backed thread snapshot via `dev-loops gate capture-threads` and use that refreshed data — including the unresolved thread count — for follow-up decisions rather than prose assumptions
225
+ - if any verification check fails, do **not** resolve the thread; leave it open, add a short explanation when needed, and re-enter the fix/reply loop
226
+ 10. resolve the addressed review thread only after the reply is attached successfully, the verification checkpoint passes, and the concern is genuinely addressed
227
+ - do not stop at a local fix if GitHub-side reply/resolve is authorized
228
+ 11. after completing reply/resolve for a pass, verify zero unresolved threads remain via `dev-loops gate capture-threads` before proceeding
229
+ - if the refreshed snapshot reports unresolved threads, re-enter the reply/resolve loop for the missed threads
230
+ 12. only after GitHub-side reply/resolve work is done for the addressed threads and the refreshed thread snapshot proves zero unresolved threads remain, decide whether another Copilot pass is desired
231
+ - resolve the review-round cap from config via `resolveRefinementConfig(config, "maxCopilotRounds")` from `@dev-loops/core/config`; default config ships `maxCopilotRounds: 5`
232
+ - use the completed Copilot review-round count from `detect-copilot-loop-state.mjs` / `copilot-pr-handoff.mjs` as the current PR's review-round count
233
+ - if completed review rounds have reached the maximum (default: 5), do **not** re-request Copilot review
234
+ - when the round limit is reached **and** the refreshed thread snapshot proves zero unresolved threads **and** current-head CI is green or credibly green, treat that clean state as eligible for `pre_approval_gate` fallback instead of deadlocking on another Copilot rerequest
235
+ - when using that fallback, add a short round-exhaustion note to the visible `pre_approval_gate` gate evidence so the PR records why no further Copilot rerequest occurred
236
+ - if the round cap is reached before the PR is thread-clean or before CI is green/credibly green, reply-resolve any remaining intentionally deferred threads with a short `deferred to follow-up` note, then stop and report that the Copilot round limit was reached
237
+ - **Signal-gated re-request suppression:** the `detect-copilot-loop-state.mjs` state machine classifies review-thread comments by signal level (High/Mid/Low). High-signal (bugs, security, contract violations) always re-requests; Low-signal (cosmetic nits) never re-requests. When low-signal detection is enabled and thresholds are met, the machine returns a low-signal-converged terminal state routing to `pre_approval_gate` without further re-requests. See [Copilot Loop Operations](../docs/copilot-loop-operations.md) for full signal-level semantics.
238
+ - if that local validation is still known red, continue remediation instead of re-requesting Copilot
239
+ - after a fix push advances the PR head SHA, re-run `detect-copilot-loop-state.mjs` for the new head and apply the [Copilot CI Status Contract](../docs/copilot-ci-status-contract.md). Previous-head CI is stale; only current-head results unblock CI-dependent steps. if GitHub CI/checks for the updated head are known red for a fixable issue, continue remediation instead of re-requesting Copilot. only once the updated head is green or credibly green, explicitly re-request Copilot review for the new head. Always use `request-copilot-review.mjs` — never `gh api POST repos/.../requested_reviewers` directly.
240
+ - only enter a wait/watch loop if the request result is confirmed as `requested` or `already-requested`
241
+ - for `requested` / `already-requested`, immediately re-baseline with `detect-copilot-loop-state.mjs`; if the returned state is `waiting_for_copilot_review`, use `dev-loops loop watch-cycle` or stop/resume later, and if the returned state is `waiting_for_ci`, use `gh run watch` for a known run id or stop/resume later after that single detector refresh
242
+ - if the request result is `unavailable`, report that limitation and stop unless the user explicitly wants passive waiting anyway
243
+ - if the request command fails unexpectedly, stop and report the error rather than sleeping and hoping for a new review
244
+ 13. after a confirmed re-requested Copilot pass, refresh PR thread state again before reporting completion; if fresh Copilot threads exist, return to this follow-up loop rather than stopping at `review requested`
245
+ 14. after a confirmed re-request returns the PR to `waiting_for_copilot_review`, jump back to Step 6 and keep the same session alive; do not exit on `review requested` alone
246
+ 15. if scope has broadened, stop and ask before continuing
247
+
248
+ Do not treat `fix applied locally` as the end of the loop when the workflow also requires GitHub-side reviewer follow-up. If comment/reply authorization is withheld, report explicitly that the code may be fixed while the PR conversation state remains unresolved.
249
+
250
+ ### Mandatory gate-comment command contract
251
+
252
+ For every `draft_gate` or `pre_approval_gate` comment, you MUST run:
253
+
254
+ ```sh
255
+ node <resolved-skill-scripts>/github/upsert-checkpoint-verdict.mjs \
256
+ --repo <owner/name> \
257
+ --pr <number> \
258
+ --gate <draft_gate|pre_approval_gate> \
259
+ --head-sha <current_head_sha> \
260
+ --verdict <clean|findings_present|blocked> \
261
+ --findings-summary "<summary>" \
262
+ --next-action "<next action>" --findings-severity-counts '{"must-fix":0,"worth-fixing-now":0,"defer":0}'
263
+ ```
264
+
265
+ Do NOT use `gh pr comment`, `gh api`, or `gh pr review` for gate comments.
266
+
267
+ `--force --force-reason` on `upsert-checkpoint-verdict.mjs` is a narrow operator-authorized CI override for the helper itself, not the default gate path. Use it only when the helper refuses gate entry solely because the current head is `blocked_needs_user_decision` with `ciStatus="failure"`, and only after the user explicitly authorizes ignoring that current-head CI failure for this one gate-comment upsert. It does **not** bypass stale-head checks, unresolved-thread / unsettled-review refusal, non-draft `draft_gate` refusal, merge conflicts, or other legality checks.
268
+
269
+ ### Draft gate contract (before marking PR ready for review)
270
+
271
+ The canonical checkpoint verdict comment contract is [Gate Review Comment Contract](../../docs/gate-review-comment-contract.md). This section summarizes the procedural integration only.
272
+
273
+ - **Gate name:** Draft gate
274
+ - **Trigger / boundary:** right before running `gh pr ready` (draft → ready for review)
275
+ - **Skip rule:** before entering the draft gate, run `detect-pr-gate-coordination-state.mjs` and check `draftGateAlreadySatisfied`. If `true`, skip the draft gate entirely — the draft→ready transition was already recorded. `draft_gate` is a one-time gate; do not re-post on new heads once clean draft-gate evidence exists for the transition record. (While the PR is still draft, advancing the head SHA does require a new draft-gate comment for the new head.) This skip rule applies only to the draft boundary.
276
+ - **Execution directive:** run the checkpoint review chain defined in [Gate Review Sub-Loop Contract](../../docs/gate-review-sub-loop-contract.md) with the draft gate inspection angles resolved from config.
277
+ - **Review angles:** resolved at runtime from config via `resolveGateAngles(config, "draft")` from `@dev-loops/core/config`. Default config enables all configured draft gate angle families; consumer repos may opt out individual angles via `excludeAngles`. Do **not** apply angles from the other gate; each gate owns its own angle list from config.
278
+ - **CI prerequisite:** resolve the draft gate config first (`resolveGateConfig(config, "draft")`). When `requireCi=true` (default), wait for green current-head CI before entering `draft_gate`. When `requireCi=false`, the draft gate may proceed without green CI. This draft-only override does **not** relax `pre_approval_gate`; final approval and merge readiness still require green current-head CI.
279
+ - **Pass criteria:** all configured draft gate angles pass; all findings at severities in `blockCleanOnFindingSeverities` are addressed; validation passes; no unrelated files are included.
280
+ - **Next step after passing:** mark the PR ready for review.
281
+ - **Non-substitution rule:** a clean `draft_gate` comment only authorizes the draft → ready-for-review transition for that head SHA. It does **not** satisfy `pre_approval_gate`, final-approval readiness, or merge-ready requirements.
282
+ - **Required PR comment:** post a visible checkpoint verdict comment using the mandatory [Gate comment command](#mandatory-gate-comment-command-contract). Keep validation reporting concise: include command names with pass/fail status. Do **not** paste raw passing test output into the visible gate comment. If you include a failing validation excerpt, keep it focused and truncate it to a deterministic retained-prefix length before posting the comment. See [Gate Review Comment Contract](../../docs/gate-review-comment-contract.md). Do not run `gh pr ready` unless a visible `clean` `draft_gate` checkpoint verdict comment exists for the current head SHA. A checkpoint verdict comment for an older head SHA does not satisfy this requirement for the current head. If findings exist, the PR stays draft and needs fixes before retry. If fixes advance the head SHA while still draft, post a new checkpoint verdict comment for the new head. If the checkpoint verdict comment cannot be posted, fail closed and do not run `gh pr ready`.
283
+
284
+ ### Pre-approval gate contract
285
+
286
+ This is the default pre-approval gate for this workflow boundary. The canonical checkpoint verdict comment contract is [Gate Review Comment Contract](../../docs/gate-review-comment-contract.md). This section summarizes the procedural integration only.
287
+
288
+ - **Gate name:** Pre-approval gate
289
+ - **Trigger / boundary:** right before calling a PR/branch review-complete, approval-ready, merge-ready, or ready for final handoff
290
+ - **Execution directive:** run the checkpoint review chain defined in [Gate Review Sub-Loop Contract](../../docs/gate-review-sub-loop-contract.md) with the pre-approval gate inspection angles resolved from config. Retry rule: in subsequent cycles, only re-run reviewers that produced `findings_present` in the previous pass.
291
+ - **Review angles:** resolved at runtime from config via `resolveGateAngles(config, "preApproval")` from `@dev-loops/core/config`. Default config enables all configured pre-approval gate angle families; consumer repos may opt out individual angles via `excludeAngles`.
292
+ - **Persona mapping:** each angle resolves to a reviewer persona via `resolveReviewerRole(config, angle)` from `@dev-loops/core/config`. Include this prompt in each reviewer's briefing so the reviewer knows exactly what to look for.
293
+ - **Pass criteria:** the sub-loop completes with verdict `clean`; all configured angles pass; if parallel execution is impractical, still run all configured lenses and explicitly record the limitation.
294
+ - **Acceptance criteria verification:** follow the canonical procedure in [Acceptance Criteria Verification](../docs/acceptance-criteria-verification.md) before posting the `pre_approval_gate` comment.
295
+ - **Next step after passing:** continue the Step 7 flow and then proceed to the human approval checkpoint below.
296
+ - **Non-substitution rule:** a clean `pre_approval_gate` comment is separate from `draft_gate` evidence. It governs final-approval readiness for that head SHA; it does **not** replace the required `draft_gate` evidence for leaving draft.
297
+ - **Required PR comment:** post a visible checkpoint verdict comment using the mandatory [Gate comment command](#mandatory-gate-comment-command-contract). Keep validation reporting concise: include command names with pass/fail status. Do **not** paste raw passing test output into the visible gate comment. If you include a failing validation excerpt, keep it focused and truncate it to a deterministic retained-prefix length before posting the comment. Do not declare final-approval readiness unless a visible `clean` `pre_approval_gate` checkpoint verdict comment exists for the current head SHA. Final-approval readiness must not rely only on local or hidden artifacts; the visible PR comment is the required auditable evidence. If the checkpoint verdict comment cannot be posted, fail closed and do not declare final-approval readiness. A checkpoint verdict comment for an older head SHA does not satisfy this requirement for the current head. If findings exist, follow-up fixes are required before final approval. The `pre_approval_gate` procedure must be entered and completed (visible comment posted) before any merge-ready or approval-ready declaration. Skipping the gate is not recoverable by asserting convergence. If fixes advance the head SHA, post a new checkpoint verdict comment for the new head.
298
+
299
+ ### Conflict-resolution gate
300
+
301
+ Before any merge-ready or final-approval claim, run `detect-pr-gate-coordination-state.mjs` for the current PR. If it reports `gateBoundary=conflict_resolution` or `mergeStateStatus` is conflicted, stop the normal gate path immediately and use this recovery flow:
302
+
303
+ 1. fetch fresh `origin/main`, confirm the current PR head SHA, and summarize the conflict scope from `mergeStateStatus` plus any reported `conflictFiles`
304
+ 2. ask for explicit authorization before any rebase or other branch-state-changing reconciliation command
305
+ 3. after authorization, reconcile locally on the PR branch; default to rebase onto latest `origin/main`, unless the operator explicitly chooses another conflict-resolution command
306
+ 4. auto-resolve simple conflicts when the correct fix is mechanical and clearly in scope; report complex conflicts explicitly and fix them manually only for in-scope files
307
+ 5. rerun the smallest honest local validation for the touched conflict slice
308
+ 6. rerun `detect-pr-gate-coordination-state.mjs` for the new head
309
+ 7. because the head changed, rerun `pre_approval_gate` for the new head before any approval-ready or merge-ready claim
310
+ 8. wait for current-head CI again before retrying merge evaluation
311
+ 9. if the chosen reconciliation rewrote branch history (for example rebase), ask for explicit authorization before `git push --force-with-lease`, then continue the loop on the updated head
312
+
313
+ `mergeStateStatus: CLEAN` alone is not enough to resume approval or merge claims. The existing merge-ready preconditions still apply: zero unresolved review threads, a clean current-head `pre_approval_gate`, and green current-head CI.
314
+
315
+ ### Merge-ready preconditions
316
+
317
+ See [Merge Preconditions](../docs/merge-preconditions.md). Verify: zero unresolved threads (via `dev-loops gate capture-threads`), visible clean `draft_gate` + current-head `pre_approval_gate`, green CI. Fresh-context review follows [Gate Review Sub-Loop Contract](../../docs/gate-review-sub-loop-contract.md).
318
+
319
+ ### Human approval checkpoint
320
+
321
+ After merge-ready preconditions pass, verify [Merge Preconditions](../docs/merge-preconditions.md) authoritatively before reporting merge-ready. Stop at the human approval checkpoint by default. Cross-check via `dev-loops gate capture-threads` (not prose assertion).
322
+ Follow [Merge Preconditions](../docs/merge-preconditions.md): stop at `waiting_for_merge_authorization` after approval unless merge explicitly authorized. Run pre-merge gate evidence check before any `gh pr merge`.
323
+
324
+ ### Mechanical pre-merge gate evidence check
325
+
326
+ Immediately before any `gh pr merge`, run:
327
+
328
+ ```sh
329
+ node <resolved-skill-scripts>/github/detect-checkpoint-evidence.mjs \
330
+ --repo <owner/name> \
331
+ --pr <number>
332
+ ```
333
+
334
+ This helper is always-on: it uses `gh api` to fetch visible PR issue comments and fails closed unless both required gate comments exist: a clean `draft_gate` comment for the one-time draft boundary and a clean current-head `pre_approval_gate` comment. Do not run `gh pr merge` if this command exits non-zero. There is no opt-out flag. Resolved threads, green CI, clean Copilot rereview, or local notes do not substitute for this successful helper output. If a final approval or merge boundary sees `gh pr merge` without a same-boundary successful check, treat that as a workflow violation and stop.
335
+
336
+ ### Mandatory post-merge retrospective checkpoint write
337
+
338
+ After a merge succeeds (or an explicit retrospective skip is authorized), write the durable retrospective checkpoint before exiting the subagent session:
339
+
340
+ ```sh
341
+ node <resolved-skill-scripts>/loop/checkpoint-contract.mjs --state complete --notes "<one-line retrospective summary>"
342
+ ```
343
+
344
+ For an explicit skip:
345
+
346
+ ```sh
347
+ node <resolved-skill-scripts>/loop/checkpoint-contract.mjs --state skipped --reason "<why retrospective is skipped>"
348
+ ```
349
+
350
+ Do not report completion or advance to the next PR queue item until `.pi/dev-loop-retrospective-checkpoint.json` is updated to `complete` or `skipped`.
351
+
352
+ ## Validation policy
353
+
354
+ Follow [Validation Policy](../docs/validation-policy.md). Default: `npm run verify` before PR creation, gate entry, and merge. For repo-local examples: `npm run test:dev-loop` for skill scripts, contract tests for templates, `git diff --check` for docs. When CI runs exist, use `gh run watch` or `detect-copilot-loop-state.mjs` instead of `sleep`-based polling. Distinguish: locally validated, full PR-equivalent checks, awaiting CI.
355
+
356
+ ## Confirmation checkpoints
357
+
358
+ See [Confirmation Rules](../docs/confirmation-rules.md). Stop and ask before GitHub mutations (edits, assignments, labels, comments, reviews, thread resolution, commits, pushes, merges, workflows) unless explicitly authorized.
359
+
360
+ ## Stop conditions
361
+
362
+ Follow [Stop Conditions](../docs/stop-conditions.md). Genuine stops: `blocked` state, `done`, `approval_ready` without merge auth, ambiguous state, scope drift. Non-stops: `waiting` watcher states, quiet observations.
363
+
364
+ ## Anti-patterns
365
+
366
+ See [Anti-patterns](../docs/anti-patterns.md). Key repo-specific additions:
367
+ - Use `reply-resolve-review-thread.mjs` / `reply-resolve-review-threads.mjs` helpers instead of ad hoc `gh api`/`gh api graphql` thread-mutation commands. Do NOT use `gh pr comment`, `gh api`, or `gh pr review` for gate comments (use `upsert-checkpoint-verdict.mjs`).
368
+ - Do not declare merge-ready without visible `pre_approval_gate` comment on current head SHA. Do not declare merge-ready based solely on `mergeable_state: clean` + CI green without gate evidence. CI green + resolved threads alone is insufficient.
369
+ - Do not blind-run `gh pr merge`/`gh pr update-branch`/unapproved rebase when conflicted. Do not dispatch async dev-loop tasks that omit the pre-approval gate requirement.
370
+ - Do not assume generated wiki is authoritative over code or CI.
371
+
372
+ ## Output expectations
373
+
374
+ When using this skill, keep user-facing summaries concise and operational.
375
+
376
+ A good status update should say:
377
+ - what issue or PR you inspected
378
+ - current state
379
+ - what the next recommended action is
380
+ - whether authorization is needed before taking it
@@ -0,0 +1,141 @@
1
+ ---
2
+ name: dev-loop
3
+ description: >-
4
+ Single public dev-loop entrypoint. Resolve canonical current state first,
5
+ then load only route-specific internal skills.
6
+ user-invocable: true
7
+ compatibility: Pi skill for git+GitHub repositories. Requires gh auth; async follow-up works best in Pi/TelePi sessions.
8
+ allowed-tools: read bash edit write subagent review_loop
9
+ ---
10
+
11
+ **No-implicit-start rule:** Never start implementation without explicit instruction.
12
+
13
+ **Work-origin rule:** All work must originate from a tracked artifact: a GitHub issue (tracker-first) or a persisted markdown plan file (local-planning). See [Artifact Authority Contract](../docs/artifact-authority-contract.md) for canonical mode definitions and settings. No work may originate from a PR or direct local change unless explicitly requested.
14
+
15
+ # Unified Dev Loop
16
+
17
+ This is the public `dev-loop` façade — a summary of the authoritative routing contract. The authoritative contract is [Public Dev Loop Contract](../docs/public-dev-loop-contract.md). Runtime evaluator: `@dev-loops/core/loop/public-dev-loop-routing`. For status/progress/readiness/merge-state/next-step queries, resolve authoritative artifact identity first; for issue targets, identity resolution is handled by the startup resolver. Fail closed to reconcile/unknown when unresolved. When an open linked PR exists, treat it as the single canonical artifact for the issue and reuse it instead of opening another PR.
18
+
19
+ ## Installed skill layout
20
+
21
+ Required installed runtime contract docs are shared bundled copies under `../docs/` from this skill directory. Read those bundled `../docs/` files from the installed skill layout — do not assume a source checkout. If a required bundled contract doc is missing, treat it as a packaging/installer bug.
22
+
23
+ ## Startup procedure
24
+
25
+ ### Main agent (read-only)
26
+
27
+ The main agent must **always** dispatch the `dev-loop` async subagent for any dev-loop work.
28
+ Do not run `dev-loops loop startup` or any startup resolver in the main agent.
29
+ The resolver requires `PI_SUBAGENT_RUN_ID` for async-required routes (the default `required` mode); the startup resolver can also run without it for non-async routes. Regardless, only the `dev-loop` async subagent runs it — never the main agent.
30
+
31
+ ### Dev-loop subagent (post-dispatch)
32
+
33
+ The subagent resolves authoritative state via the startup resolver (`npx dev-loops loop startup --issue <n>` for issues, `npx dev-loops loop startup --pr <n>` for PRs), then immediately builds the handoff envelope via `npx dev-loops loop build-envelope --input <resolver-output.json>`. The envelope determines `requiredReads`, `nextAction`, `stopRules`, and `acceptance` — load only those files, execute only that bounded task. It is the first handoff artifact consumed before loading any route pack. See [Workflow Handoff Contract](../docs/workflow-handoff-contract.md) for the derivation contract.
34
+
35
+ **Retrospective checkpoint gate:** the resolver reads `.pi/dev-loop-retrospective-checkpoint.json` and injects the state. When the checkpoint is `missing` and the repo config `workflow.requireRetrospective` (set via `.devloops` at repo root) is `true`, the resolver returns `needs_reconcile`. Complete or explicitly skip the retrospective before starting.
36
+
37
+ **Pre-delegation gate (mandatory — subagent only):** Before delegating async work targeting an existing PR, the dev-loop subagent must run `node scripts/loop/copilot-pr-handoff.mjs --repo <owner/name> --pr <number>` and abort if `action: "stop"`. When `terminal: true`, proceed inline. When `terminal: false`, resolve the blocking condition first.
38
+
39
+ **Worktree cwd (mandatory — subagent only):** Always use a worktree checkout for git operations, file reads/writes, and validation commands — never use the `main` checkout.
40
+
41
+ **Worktree fetch (mandatory — subagent only):** Always run `git fetch origin` before creating or reusing any worktree.
42
+
43
+ ### Resume from existing loop state
44
+
45
+ When the startup resolver returns a fresh-start routing but an existing outer-loop checkpoint
46
+ (`tmp/copilot-loop/<owner>/<repo>/pr-<n>/outer-loop-state.json`) is present on disk, the
47
+ subagent must check the checkpoint before treating the start as a fresh intake or follow-up:
48
+
49
+ 1. Read the outer-loop checkpoint (authored by `outer-loop.mjs`).
50
+ 2. If `outerAction` is `continue_wait`, `reenter_copilot_loop`, or `reenter_reviewer_loop`:
51
+ - Skip issue-intake normalization or fresh-intake routing.
52
+ - Route directly to the existing PR's follow-up path (the PR number is in the
53
+ checkpoint's `pr` field). For `reenter_copilot_loop`, enter the copilot-pr-followup
54
+ path. For `reenter_reviewer_loop`, enter the reviewer-loop path.
55
+ - Use the checkpoint's `copilotState` and `reviewerState` as last-known context for
56
+ re-attachment, then re-baseline with fresh detectors (`copilot-pr-handoff.mjs`
57
+ or `detect-copilot-loop-state.mjs`) before acting on the state.
58
+ 3. If `outerAction` is `stop`:
59
+ - Report the `reason` field and the authoritative state from the checkpoint.
60
+ - `stop` means the loop is blocked or needs a human decision; ask for direction
61
+ rather than guessing or starting fresh.
62
+ 4. If no checkpoint exists, or `outerAction` is `done`:
63
+ - Treat as normal fresh startup (the existing startup resolver path).
64
+
65
+ This eliminates the manual "report-and-resume" or "exit and resume later" pattern when the
66
+ deterministic state already knows the next action.
67
+
68
+ The outer-loop checkpoint is the canonical re-attachment artifact. Do not rely on chat
69
+ context, local notes, or prose recollection of "where we left off."
70
+
71
+ ## Route table
72
+
73
+ Load only the route-specific internal skill required by `selectedStrategy`:
74
+
75
+ | Strategy | Route pack to load |
76
+ | --- | --- |
77
+ | `local_implementation` | [Local Implementation Skill](../local-implementation/SKILL.md) |
78
+ | `issue_intake` | [Copilot PR Follow-up Skill](../copilot-pr-followup/SKILL.md) + [Copilot Loop Operations](../docs/copilot-loop-operations.md) + [Issue Intake Procedure](../docs/issue-intake-procedure.md) |
79
+ | `copilot_pr_followup` | [Copilot PR Follow-up Skill](../copilot-pr-followup/SKILL.md) + [Copilot Loop Operations](../docs/copilot-loop-operations.md) |
80
+ | `external_pr_followup` | same as `copilot_pr_followup` |
81
+ | `reviewer_fixer` | same as `copilot_pr_followup` |
82
+ | `wait_watch` | same as `copilot_pr_followup` |
83
+ | `final_approval` | same as `copilot_pr_followup` + [Final Approval Skill](../final-approval/SKILL.md) |
84
+
85
+ Do not preload route packs before the resolver selects the strategy.
86
+
87
+ ## Async dispatch
88
+
89
+ **Async dispatch rule (enforced):** the resolver enforces fail-closed for GitHub-first strategies when `canonicalStateSummary.requiresAsyncDispatch` is `true` (default `required` mode). Inline invocation without `PI_SUBAGENT_RUN_ID` is rejected only for those routes. See [Startup procedure](#startup-procedure).
90
+
91
+
92
+ ## Fallback gate-comment poster
93
+
94
+ When the `@dev-loops/core` package is not installed in the consumer repo, the full `scripts/github/upsert-checkpoint-verdict.mjs` helper (referenced from the copilot-pr-followup skill procedure) is unavailable. To keep the PR audit trail intact in that mode, the dev-loop skill ships a small gh-only fallback poster at `scripts/post-gate-verdict-fallback.mjs` (relative to the dev-loop skill root) that renders the same visible comment format and fails closed if posting cannot succeed.
95
+
96
+ Use the fallback poster only when the full helper cannot be reached:
97
+
98
+ 1. Detect the missing helper: try `node scripts/github/upsert-checkpoint-verdict.mjs --help` from the consumer repo. If the script is absent or imports fail, switch to the fallback path.
99
+ 2. Invoke the fallback from the installed dev-loop skill directory: `node <resolved-skill-scripts>/post-gate-verdict-fallback.mjs --repo <owner/name> --pr <number> --head-sha <sha> --verdict <clean|findings_present|blocked> (--findings-summary <text> | --findings-file <path>) --next-action <text> [--gate <draft_gate|pre_approval_gate>]`.
100
+ 3. Treat every successful fallback-posted gate comment as a one-shot create with no idempotent same-head update: if the agent reruns the gate on the same head, a duplicate comment will be created. Detect duplicates manually and update manually if needed.
101
+ 4. Treat every fallback-posted gate comment as a degraded audit-trail artifact: the visible body uses the same parser-stable shape as the full helper (gate name, head SHA, verdict, blocking severities when applicable, findings summary, next action), but the helper skips stale-head detection, gate-coordination validation, blocking-severity count enforcement, and the internal-only PR short-circuit.
102
+ 5. If the fallback helper exits non-zero, stop the gate and report the posting failure: do not mark the PR ready for review and do not proceed to merge readiness until the comment is posted.
103
+
104
+ When `@dev-loops/core` is available again, switch back to the full helper. The fallback poster is a degraded path, not a permanent replacement.
105
+
106
+ ## Read-only info shortcut
107
+
108
+ The main agent may handle info/handoff requests directly via `npx dev-loops loop info` without dispatching the async `dev-loop` subagent:
109
+ - `npx dev-loops loop info --issue <n>` — human-readable issue state summary (strategy, route, linked PR, next action)
110
+ - `npx dev-loops loop info --pr <n>` — human-readable PR state summary (branch, CI, threads, rounds, action)
111
+ - `npx dev-loops loop info --issue <n> --json` — machine-readable JSON output
112
+
113
+ ## Guard rules (subagent reference)
114
+
115
+ **Handoff envelope precedence:** The subagent builds the envelope immediately after authoritative-state resolution and treats it as the first handoff artifact. Read it first, load only `requiredReads`, execute `nextAction`. See [Dev-loop subagent](#dev-loop-subagent-post-dispatch). Derivation contract: [Workflow Handoff Contract](../docs/workflow-handoff-contract.md).
116
+
117
+ **Handoff contract rule:** When no envelope is present, use the `workflow-handoff-contract.md` contract. Never delegate with abbreviated task summaries. Include deterministic routing inputs, explicit `cwd`, bounded task scope, exit conditions.
118
+
119
+ **Inline-first rule:** Prefer inline commands over nested async delegation when managing a single PR. Use nested delegation only for parallel fan-out or when the parent needs to continue other work.
120
+
121
+ **Bounded async task contract:** Break work into discrete tasks with clear inputs, explicit outputs, bounded scope. No shell polling — use `run-watch-cycle.mjs` or `gh run watch`.
122
+
123
+ **Round-cap budget check (enforced):** After every watch cycle, fix pass, or reply-resolve, check whether completed Copilot review rounds have reached the maximum (default: 5). Stop re-requesting Copilot review when the limit is reached — never re-request after the cap.
124
+
125
+ ## Shorthand issue-based auto trigger contract
126
+
127
+ - `auto dev loop on issue <n>` → public `dev-loop` intent `auto_continue_current` after authoritative current-state resolution
128
+ - Continue through GitHub/Copilot loop until stop condition or human approval checkpoint
129
+ - Stop at the human approval checkpoint by default unless merge explicitly authorized
130
+
131
+ ## No gate exemptions
132
+
133
+ All PRs must pass the full gate pipeline before merge. No scope is exempt: docs-only, tooling, meta, configuration, internal-process — all require `draft_gate`, current-head `pre_approval_gate` evidence, and Copilot review (except internal-only PRs detected by path pattern, which skip the Copilot convergence requirement).
134
+
135
+ ## Authority boundary
136
+
137
+ - Source code, tests, config, CI, and shared contract docs are authoritative.
138
+ - Main-agent delegation contract: [Main Agent Contract](../docs/main-agent-contract.md) — absolute read-only boundary; all mutations flow through `dev-loop` async subagent.
139
+ - Before any state-changing action, get explicit confirmation unless already authorized.
140
+ - A question requires an answer, not an action.
141
+ - Stop and ask rather than guessing when facts don't agree.