dev-loops 0.7.2 → 0.8.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 (71) hide show
  1. package/.claude/.claude-plugin/plugin.json +1 -1
  2. package/.claude/agents/dev-loop.md +1 -1
  3. package/.claude/agents/refiner.md +2 -2
  4. package/.claude/agents/review.md +9 -12
  5. package/.claude/commands/loop-continue.md +2 -1
  6. package/.claude/commands/loop-enqueue.md +8 -1
  7. package/.claude/commands/loop-info.md +1 -1
  8. package/.claude/hooks/_bash-command-classify.mjs +7 -6
  9. package/.claude/hooks/_hook-decisions.mjs +5 -4
  10. package/.claude/skills/copilot-pr-followup/SKILL.md +5 -5
  11. package/.claude/skills/dev-loop/SKILL.md +7 -7
  12. package/.claude/skills/docs/acceptance-criteria-verification.md +12 -4
  13. package/.claude/skills/docs/anti-patterns.md +3 -3
  14. package/.claude/skills/docs/artifact-authority-contract.md +6 -4
  15. package/.claude/skills/docs/confirmation-rules.md +1 -1
  16. package/.claude/skills/docs/copilot-loop-operations.md +4 -2
  17. package/.claude/skills/docs/issue-intake-procedure.md +12 -3
  18. package/.claude/skills/docs/merge-preconditions.md +5 -3
  19. package/.claude/skills/docs/pr-lifecycle-contract.md +1 -1
  20. package/.claude/skills/docs/public-dev-loop-contract.md +2 -1
  21. package/.claude/skills/docs/retrospective-checkpoint-contract.md +9 -6
  22. package/.claude/skills/docs/validation-policy.md +1 -1
  23. package/.claude/skills/local-implementation/SKILL.md +3 -3
  24. package/.claude/skills/loop-grill/SKILL.md +34 -14
  25. package/AGENTS.md +1 -1
  26. package/CHANGELOG.md +30 -0
  27. package/README.md +95 -189
  28. package/agents/refiner.agent.md +2 -2
  29. package/agents/review.agent.md +9 -12
  30. package/extension/README.md +5 -4
  31. package/package.json +5 -4
  32. package/scripts/docs/validate-state-machine-conformance.mjs +78 -1
  33. package/scripts/github/_gate-names.mjs +5 -0
  34. package/scripts/github/capture-review-threads.mjs +2 -2
  35. package/scripts/github/detect-checkpoint-evidence.mjs +7 -7
  36. package/scripts/github/edit-issue.mjs +259 -0
  37. package/scripts/github/probe-ci-status.mjs +18 -0
  38. package/scripts/github/probe-copilot-review.mjs +24 -3
  39. package/scripts/github/reconcile-draft-gate.mjs +13 -13
  40. package/scripts/github/request-copilot-review.mjs +17 -16
  41. package/scripts/github/upsert-checkpoint-verdict.mjs +25 -23
  42. package/scripts/github/verify-briefing-prefixes.mjs +224 -33
  43. package/scripts/github/write-gate-context.mjs +8 -4
  44. package/scripts/loop/_post-convergence-change.mjs +2 -2
  45. package/scripts/loop/_pr-runner-coordination.mjs +112 -13
  46. package/scripts/loop/check-retro-tooling.mjs +14 -9
  47. package/scripts/loop/copilot-pr-handoff.mjs +18 -14
  48. package/scripts/loop/detect-copilot-loop-state.mjs +11 -11
  49. package/scripts/loop/detect-internal-only-pr.mjs +6 -6
  50. package/scripts/loop/detect-pr-gate-coordination-state.mjs +117 -15
  51. package/scripts/loop/detect-refinement-grill-state.mjs +136 -0
  52. package/scripts/loop/run-watch-cycle.mjs +42 -7
  53. package/scripts/loop/sanctioned-commands.mjs +1 -0
  54. package/scripts/pages/build-state-atlas.mjs +15 -0
  55. package/scripts/projects/add-queue-item.mjs +87 -4
  56. package/skills/copilot-pr-followup/SKILL.md +5 -5
  57. package/skills/dev-loop/SKILL.md +2 -2
  58. package/skills/docs/acceptance-criteria-verification.md +12 -4
  59. package/skills/docs/anti-patterns.md +3 -3
  60. package/skills/docs/artifact-authority-contract.md +6 -4
  61. package/skills/docs/confirmation-rules.md +1 -1
  62. package/skills/docs/copilot-loop-operations.md +4 -2
  63. package/skills/docs/issue-intake-procedure.md +12 -3
  64. package/skills/docs/merge-preconditions.md +5 -3
  65. package/skills/docs/pr-lifecycle-contract.md +1 -1
  66. package/skills/docs/public-dev-loop-contract.md +2 -1
  67. package/skills/docs/required-rules.json +17 -1
  68. package/skills/docs/retrospective-checkpoint-contract.md +9 -6
  69. package/skills/docs/validation-policy.md +1 -1
  70. package/skills/local-implementation/SKILL.md +3 -3
  71. package/skills/loop-grill/SKILL.md +38 -17
@@ -1,6 +1,7 @@
1
1
  {
2
2
  "requiredRules": [
3
3
  "ACCEPT-CRITERIA-VERIFY-AND-REFLECT",
4
+ "ANTIPATTERN-FANIN-WAIT",
4
5
  "ARTIFACT-LIGHTWEIGHT-BODY-INVARIANTS",
5
6
  "ARTIFACT-LIGHTWEIGHT-PLAN-FILE-EXCLUSIVE",
6
7
  "ARTIFACT-STRATEGY-ENUM-FAIL-CLOSED",
@@ -56,6 +57,10 @@
56
57
  "GATE-EXEC-REGATE-MANDATORY",
57
58
  "GATE-EXEC-SEPARATE-CHAINS",
58
59
  "GATE-SKIP-NOT-RECOVERABLE-BY-CONVERGENCE",
60
+ "GRILL-SUBLOOP-HONEST-HANDOFF",
61
+ "GRILL-SUBLOOP-ITERATE-TO-CLEAN",
62
+ "GRILL-SUBLOOP-NO-EMBED-SYNTHESIS",
63
+ "GRILL-SUBLOOP-STATE-MACHINE",
59
64
  "INTAKE-LINKED-PR-HELPER-DELEGATION",
60
65
  "INTAKE-NEW-IDEA-SAFETY",
61
66
  "INTAKE-STOP-STATES",
@@ -79,9 +84,11 @@
79
84
  "OPS-NO-INLINE-INTERPRETER",
80
85
  "QUEUE-BOARD-LINKED",
81
86
  "QUEUE-BOARD-QUERY-FAIL-CLOSED",
87
+ "QUEUE-BOARD-SYNC-CONTINUOUS",
82
88
  "QUEUE-BOOTSTRAP-ONLY-MUTATOR",
83
89
  "QUEUE-COLUMN-CANONICAL",
84
90
  "QUEUE-COLUMN-NO-REMOVE",
91
+ "QUEUE-ENQUEUE-REFINEMENT-GATE",
85
92
  "QUEUE-LIVE-PICKUP-SOURCE",
86
93
  "QUEUE-NEXTUP-EMPTY-FAIL-CLOSED",
87
94
  "QUEUE-NEXTUP-SOURCE",
@@ -144,6 +151,15 @@
144
151
  "WORKTREE-DEDUPE",
145
152
  "WORKTREE-DEFAULT-USE",
146
153
  "WORKTREE-DEPS-ISOLATED",
147
- "WORKTREE-FALLBACK"
154
+ "WORKTREE-FALLBACK",
155
+ "COPILOT-FOLLOWUP-VERIFY-BEFORE-RESOLVE",
156
+ "INTAKE-TIMEOUT-ROUTE-ON-SEAM-EXIT",
157
+ "INTAKE-TIMEOUT-SURFACE-BUDGET-EXHAUSTED",
158
+ "INTAKE-REPO-SLUG-RESOLVE-FIRST",
159
+ "FACADE-COPILOT-INTERNAL-ONLY",
160
+ "REFINER-DOD-PROPOSED-SUBSECTION",
161
+ "REFINER-NO-INVENT-AUDIT-FINDINGS",
162
+ "COPILOT-FOLLOWUP-REREQUEST-GREEN-GATE",
163
+ "COPILOT-FOLLOWUP-RESOLVE-AFTER-REPLY"
148
164
  ]
149
165
  }
@@ -96,8 +96,8 @@ If the gate result is `needs_reconcile`, the caller MUST NOT proceed with the pr
96
96
  <!-- rule: RETRO-ADVISORY-NEVER-GATE -->
97
97
  The retrospective is **advisory**: it runs, records flagged raw-call / discipline
98
98
  observations honestly, and passes them back to the conductor (main agent) to
99
- **decide** what to do with them — but it MUST NOT block a merge or any lifecycle
100
- transition. The pre-merge retrospective gate (`evaluateRetrospectiveMergeApproval`
99
+ **decide** what to do with them — but it MUST NOT block a merge or any PR-lifecycle
100
+ transition of the current run. The pre-merge retrospective gate (`evaluateRetrospectiveMergeApproval`
101
101
  and the `requireRetrospectiveGate` / `requireRetrospectiveInternalTooling` config
102
102
  keys) has been **removed**. There is no `retrospective_gate_pending` / `blocked`
103
103
  disposition on account of the internal-tooling raw-call record.
@@ -135,10 +135,13 @@ scripts legitimately call `gh`/GraphQL internally; that is the tooling. The rule
135
135
  targets the agent's own top-level shell calls, not a script's internals.
136
136
 
137
137
  **Write-op allowlist (verifier only):** `gh pr merge`, `gh pr ready`,
138
- `gh issue create`, `gh issue edit` have no internal wrapper today. The deterministic
139
- verifier records these as `allowedWriteOps` rather than violations so they are
140
- surfaced distinctly, not as breaches. Close the gap with a wrapper to remove an
141
- entry. None of these block anything.
138
+ `gh issue create` have no internal wrapper today. `gh issue edit` now has one
139
+ (`scripts/github/edit-issue.mjs`) and stays as a belt-and-suspenders entry like
140
+ `gh label create` (`scripts/github/create-label.mjs`) so a bare invocation
141
+ surfaced from the wrapper's own subprocess is not miscounted as a breach. The
142
+ deterministic verifier records all of these as `allowedWriteOps` rather than
143
+ violations so they are surfaced distinctly, not as breaches. Close the gap with a
144
+ wrapper to remove or reframe a no-wrapper entry. None of these block anything.
142
145
 
143
146
  **Inline-interpreter check item:** the raw-call scan below mechanically catches
144
147
  `node -e`/`python3 -c`/heredoc calls as a `rawCallViolations` entry — the same
@@ -17,7 +17,7 @@ Canonical owner for validation requirements across all workflow families.
17
17
  ## Coverage requirements
18
18
 
19
19
  <!-- rule: VALIDATE-COVERAGE-THRESHOLD -->
20
- `VALIDATE-COVERAGE-THRESHOLD`: Changed files MUST have ≥90% coverage for lines, statements, functions, and branches, and non-trivial logic MUST be test-first.
20
+ `VALIDATE-COVERAGE-THRESHOLD`: Changed files SHOULD maintain ≥90% coverage for lines, statements, functions, and branches (not enforced by the shipped verify config; treat it as the working target), and non-trivial logic MUST be test-first.
21
21
 
22
22
  ## Cross-references
23
23
 
@@ -13,7 +13,7 @@ user-invocable: false
13
13
 
14
14
  # Local Implementation
15
15
 
16
- This skill is the canonical internal `local_implementation` route behind the public `dev-loop` façade.
16
+ Canonical owner for the internal `local_implementation` route behind the public `dev-loop` façade.
17
17
 
18
18
  Use it only after the public dispatcher has already resolved `selectedStrategy: local_implementation`. This skill owns the local phase procedure and artifact discipline for that route; it does not redefine the shipped runtime semantics of helper CLIs, shared loop logic, or extension commands.
19
19
 
@@ -65,7 +65,7 @@ When the local spec already lives in a tracker issue:
65
65
  - sync durable scope / acceptance / status changes back to the tracker issue rather than maintaining a duplicate local phase doc
66
66
  - keep `tmp/` as temporary local execution state only; it does not become a second durable spec surface
67
67
  - for tracker-backed sessions, the handoff path is always: push the working branch → open a PR → merge via GitHub
68
- - <!-- rule: LOCAL-PR-CREATE-CANONICAL --> for tracker-backed sessions, you MUST open PRs through the canonical `dev-loops pr create` path — always draft and always assigned — self-assigned by default (`--assignee @me` when none is given; honors an explicit `--assignee <login>` / `-a <login>`) — and MUST NOT open them via raw `gh pr create`. The PR body MUST contain `Closes #N` (or `Fixes #N`) for the linked issue so GitHub auto-closes it on merge. When `.devloops` sets `workflow.requireDraftFirst` to true, use `dev-loops pr create --assignee @me ...`; the draft-first requirement itself is owned by [`OPS-DRAFT-FIRST-PR`](../docs/copilot-loop-operations.md).
68
+ - <!-- rule: LOCAL-PR-CREATE-CANONICAL --> for tracker-backed sessions, you MUST open PRs through the canonical `dev-loops pr create` path — always draft and always assigned — self-assigned by default (`--assignee @me` when none is given; honors an explicit `--assignee <login>` / `-a <login>`) — and MUST NOT open them via raw `gh pr create`. The PR body MUST contain `Closes #N` (or `Fixes #N`) for the linked issue so GitHub auto-closes it on merge. When `.devloops` sets `workflow.requireDraftFirst` to true, use `dev-loops pr create --assignee @me ...`; the always-draft creation mechanism is owned by [`OPS-DRAFT-FIRST-PR`](../docs/copilot-loop-operations.md) — `create-pr.mjs` is unconditionally draft-only regardless of the toggle, which separately governs whether the draft-gate boundary is enforced before ready.
69
69
  - <!-- rule: LOCAL-TRACKER-NO-DIRECT-MERGE --> `LOCAL-TRACKER-NO-DIRECT-MERGE`: for tracker-backed sessions, agents MUST NOT suggest a direct local-main merge and MUST NOT merge the working branch into local `main` at phase completion
70
70
 
71
71
  ## Primary execution rules
@@ -108,7 +108,7 @@ Follow [Anti-patterns](../docs/anti-patterns.md) for the general tooling-interna
108
108
 
109
109
  - <!-- rule: LOCAL-PHASE-ONE-AT-A-TIME --> You MUST implement **one phase at a time** and MUST NOT refine later phases in detail before the current phase is complete.
110
110
  - Use the `refiner` agent for phase-refinement work when subagents are available; escalate RFC-worthy technical decisions to the parent session / human operator.
111
- - <!-- rule: LOCAL-TEST-FIRST-COVERAGE --> You MUST work **test-first** for all non-trivial logic and SHOULD maintain **90% coverage** thresholds (coverage is not enforced by the shipped verify config; treat it as the working target).
111
+ - <!-- rule: LOCAL-TEST-FIRST-COVERAGE --> You MUST work **test-first** for all non-trivial logic; coverage thresholds are owned by [VALIDATE-COVERAGE-THRESHOLD](../docs/validation-policy.md).
112
112
  - Log detailed iteration artifacts under `tmp/` using the required structure below.
113
113
  - Spec-of-record split (phase-doc-backed vs. tracker-backed vs. lightweight): see [Tracker-backed local implementation](#tracker-backed-local-implementation) above.
114
114
  - When a phase changes durable product truth in ways `PLAN.md` should express (for example command surface, accepted product decisions, resolved open questions, or scope changes), update [Project Plan](../../PLAN.md) before closing the phase.
@@ -1,10 +1,11 @@
1
1
  ---
2
2
  name: loop-grill
3
3
  description: >-
4
- Standalone pre-loop Socratic Q&A grill for issues (tracker-first) or local
5
- plan files (local-planning). Detects spec gaps, asks clarifying questions
6
- (interactive) or self-answers them from codebase context (--auto), then
7
- writes a ## Grill findings section back to the source artifact.
4
+ Standalone pre-loop Socratic Q&A grill for issues (tracker-first), PR bodies,
5
+ or local plan files (local-planning). Detects spec gaps, asks clarifying
6
+ questions (interactive) or self-answers them from codebase context (--auto),
7
+ then synthesizes Acceptance criteria / Definition of done / Non-goals into the
8
+ body while keeping the raw Q&A only in an ephemeral tmp artifact.
8
9
  allowed-tools: read bash edit write
9
10
  user-invocable: false
10
11
  ---
@@ -14,15 +15,23 @@ A standalone, on-demand pre-loop grilling skill. Run it against an issue or a lo
14
15
 
15
16
  It is entirely separate from the in-loop docs-grill (`docs/docs-grill-step.md`), which audits code/doc drift while the loop runs. This skill operates on the *spec* before any implementation begins.
16
17
 
18
+ ## State machine
19
+
20
+ This grill is the bounded, closed sub-loop modeled by `packages/core/src/loop/refinement-grill-state.mjs` (detector `scripts/loop/detect-refinement-grill-state.mjs`), rendered on the State atlas; see `docs/refinement-grill-state-graph.md`. It obeys `GRILL-SUBLOOP-STATE-MACHINE`, `GRILL-SUBLOOP-ITERATE-TO-CLEAN`, `GRILL-SUBLOOP-NO-EMBED-SYNTHESIS`, and `GRILL-SUBLOOP-HONEST-HANDOFF`. Iteration lives in the transition graph; the answer/synthesis is the bounded input consumed at the `await_answers` state.
21
+
17
22
  ## Interface
18
23
 
19
24
  ```
20
25
  /loop-grill <issue-number> # tracker-first, interactive
21
26
  /loop-grill <issue-number> --auto # tracker-first, auto-answer
27
+ /loop-grill <pr-url-or-number> # PR body, interactive
28
+ /loop-grill <pr-url-or-number> --auto # PR body, auto-answer
22
29
  /loop-grill <path/to/plan.md> # local-planning, interactive
23
30
  /loop-grill <path/to/plan.md> --auto # local-planning, auto-answer
24
31
  ```
25
32
 
33
+ PR bodies are supported the same way as issues: fetch/edit the PR body via the existing PR wrappers (`scripts/github/view-pr.mjs` / `scripts/github/edit-pr.mjs`), never raw `gh`.
34
+
26
35
  ## Argument validation (fail-closed)
27
36
 
28
37
  Before doing anything else:
@@ -35,9 +44,12 @@ Before doing anything else:
35
44
 
36
45
  ## Step 1 — Load the target
37
46
 
38
- - **Tracker-first:** fetch the issue body (title + description + any existing `## Grill findings` section).
47
+ - **Tracker-first:** fetch the issue body (title + description).
48
+ - **PR body:** fetch the PR body via `scripts/github/view-pr.mjs` (never raw `gh`).
39
49
  - **Local-planning:** read the plan file from disk.
40
50
 
51
+ "Is it refined" is decided by `detectIssueRefinementArtifact` (`packages/core/src/loop/issue-refinement-artifact.mjs`) — the single source of truth, same as the enqueue gate; do not add a divergent check. An already-refined artifact (AC/DoD present) is a zero-iteration `grill_clean`: do not rewrite the body.
52
+
41
53
  ## Step 1b — Surface external resources
42
54
 
43
55
  Before detecting gaps, scan the loaded content for external resource references: links, other repo URLs, API endpoints, doc URLs, screenshots, or Playwright navigation descriptors.
@@ -91,15 +103,20 @@ Record the evidence source for every answer. Flag a question as **`unresolved`**
91
103
 
92
104
  Do not silently guess an `inferred` answer when no evidence can be cited — flag it `unresolved` instead.
93
105
 
94
- ## Step 4 — Write back (replace-section semantics)
106
+ ## Step 4 — Write back (synthesize sections; raw Q&A to tmp only)
95
107
 
96
- Write a `## Grill findings` section back to the source artifact using **replace-section** semantics:
108
+ Synthesize the answers into the body as sharpened `## Acceptance criteria`, `## Definition of done`, and `## Non-goals` sections. Per canonical heading, use **replace-section** semantics:
97
109
 
98
- - **Find** the existing `## Grill findings` section: the range from the `## Grill findings` heading through the next `##`-level heading (exclusive) or end of file.
99
- - **Replace** that range in place with the new section content.
100
- - If no `## Grill findings` section exists, **append** it.
110
+ - **Find** the existing section: the range from that `##`-level heading through the next `##`-level heading (exclusive) or end of file.
111
+ - **Replace** that range in place with the synthesized content; if the section is absent, **append** it.
101
112
  - This makes re-runs idempotent — no accumulated noise, no duplicate sections.
102
- - If parsing the section boundary fails, **abort with an error** rather than silently truncating.
113
+ - If parsing a section boundary fails, **abort with an error** rather than silently truncating.
114
+
115
+ The body carries ONLY the synthesized sharpened sections. Do NOT write a `## Grill findings` section and do NOT embed the raw Q&A table in the body (`GRILL-SUBLOOP-NO-EMBED-SYNTHESIS`).
116
+
117
+ If a body migrated from older embed behavior still carries a `## Grill findings` section, **remove** it as part of write-back — strip from that heading through the next `##`-level heading (exclusive) or end of file, using the same replace-section boundary logic. This is a removal-only migration, never a re-introduction of the embed.
118
+
119
+ Write the raw Q&A transcript ONLY to the gitignored, ephemeral, session-scoped artifact `tmp/issues/issue-<n>/grill/<timestamp>.md` (`tmp/` is already gitignored; never committed). For PR-body and plan-file surfaces, use the same tmp path shape scoped by surface (issues: `tmp/issues/issue-<n>/grill/`; a parallel `tmp/...` path for PR/plan).
103
120
 
104
121
  **Tracker-first write-back:** update the GitHub issue body using:
105
122
 
@@ -107,19 +124,23 @@ Write a `## Grill findings` section back to the source artifact using **replace-
107
124
  gh issue edit <n> --repo <owner/repo> --body-file <tmp-path>
108
125
  ```
109
126
 
110
- The `## Grill findings` section lives in the issue body, not as a comment. Do not use `comment-issue.mjs` here — that creates a comment, not a body update.
127
+ The synthesized sections live in the issue body, not as a comment. Do not use `comment-issue.mjs` here — that creates a comment, not a body update.
128
+
129
+ **PR-body write-back:** update the PR body via `scripts/github/edit-pr.mjs` (never raw `gh`), same replace-section semantics.
111
130
 
112
- **GitHub body size guard:** issue bodies are capped at 65,536 characters. Before writing back, check whether the updated body would exceed this limit. If so, warn: `Warning: updated body would exceed GitHub's 65,536-character limit — write-back skipped. Truncate the findings or the issue body manually.` Do not silently truncate.
131
+ **GitHub body size guard:** issue/PR bodies are capped at 65,536 characters. Before writing back, check whether the updated body would exceed this limit. If so, warn: `Warning: updated body would exceed GitHub's 65,536-character limit — write-back skipped. Sharpen the sections or the body manually.` Do not silently truncate.
113
132
 
114
133
  **Local-planning write-back:** update the plan file in place using the edit tool.
115
134
 
116
135
  ## Output artifact format
117
136
 
118
- The `## Grill findings` section written to the artifact:
137
+ Two distinct artifacts:
119
138
 
120
- ```markdown
121
- ## Grill findings
139
+ 1. **Synthesized body sections** (issue/PR/plan body): only `## Acceptance criteria`, `## Definition of done`, and `## Non-goals`, sharpened from the answers. No raw Q&A.
122
140
 
141
+ 2. **Raw Q&A transcript** (ephemeral `tmp/issues/issue-<n>/grill/<timestamp>.md` only — never the body):
142
+
143
+ ```markdown
123
144
  <!-- loop-grill: <timestamp> mode:<interactive|auto> -->
124
145
 
125
146
  ### Resolved gaps
@@ -154,7 +175,7 @@ When `CONTEXT.md` is absent from the repo root, skip the context-source check si
154
175
 
155
176
  ## Idempotency guarantee
156
177
 
157
- Running `/loop-grill` twice on the same target must produce a single `## Grill findings` section, not two. The replace-section logic handles the already-present-section case. On the second run, if the gap set is identical to the first run, the section content is replaced with an equivalent section (same questions, same answers, updated timestamp).
178
+ Running `/loop-grill` twice on the same target must not accumulate duplicate sections: the per-heading replace-section logic replaces the synthesized `## Acceptance criteria` / `## Definition of done` / `## Non-goals` sections in place. An already-refined target is a zero-iteration `grill_clean` and its body is left unchanged. The raw Q&A transcript is written to a fresh timestamped tmp file per run; the body never carries it.
158
179
 
159
180
  ## Non-goals
160
181