devflow-kit 3.8.0 → 3.10.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.
- package/CHANGELOG.md +231 -0
- package/README.md +6 -6
- package/dist/agents/code.md +10 -10
- package/dist/agents/fix.md +7 -7
- package/dist/agents/git.md +2 -2
- package/dist/agents/harden.md +7 -6
- package/dist/agents/refactor.md +6 -6
- package/dist/agents/skim.md +1 -1
- package/dist/agents/triage.md +7 -0
- package/dist/cli/commands/ambient.js +10 -2
- package/dist/cli/commands/compliance-prompts.js +9 -4
- package/dist/cli/commands/compliance.js +171 -24
- package/dist/cli/commands/curation.js +79 -23
- package/dist/cli/commands/gate-level-prompts.js +39 -23
- package/dist/cli/commands/gates.js +6 -7
- package/dist/cli/commands/init.js +150 -145
- package/dist/cli/commands/install-report.js +34 -0
- package/dist/cli/commands/legacy-sweep.js +64 -0
- package/dist/cli/commands/memory.js +59 -12
- package/dist/cli/commands/proxy.js +6 -1
- package/dist/cli/commands/rules.js +29 -12
- package/dist/cli/commands/skills.js +42 -9
- package/dist/cli/commands/tracker.js +9 -3
- package/dist/cli/commands/uninstall.js +354 -60
- package/dist/commands/bug-analysis.md +71 -122
- package/dist/commands/code-review.md +11 -11
- package/dist/commands/debug.md +2 -2
- package/dist/commands/dynamic-build.md +25 -25
- package/dist/commands/dynamic-plan.md +2 -2
- package/dist/commands/dynamic-profile.md +2 -2
- package/dist/commands/dynamic-tickets.md +2 -2
- package/dist/commands/explore.md +2 -2
- package/dist/commands/implement.md +48 -34
- package/dist/commands/plan.md +2 -2
- package/dist/commands/release.md +3 -3
- package/dist/commands/research.md +2 -2
- package/dist/commands/resolve.md +50 -46
- package/dist/commands/self-review.md +10 -9
- package/dist/compliance-off/agents/git.md +120 -0
- package/dist/compliance-off/agents/triage.md +180 -0
- package/dist/compliance-off/commands/bug-analysis.md +398 -0
- package/dist/compliance-off/commands/code-review.md +520 -0
- package/dist/compliance-off/commands/dynamic-build.md +1251 -0
- package/dist/compliance-off/commands/dynamic-tickets.md +676 -0
- package/dist/compliance-off/commands/implement.md +736 -0
- package/dist/compliance-off/commands/plan.md +671 -0
- package/dist/compliance-off/commands/release.md +309 -0
- package/dist/compliance-off/commands/resolve.md +742 -0
- package/dist/compliance-off/skills/git/references/decision-markers.md +17 -0
- package/dist/compliance-off/skills/git/references/learn-conventions.md +80 -0
- package/dist/compliance-off/skills/git/references/pr/check-ci-status.md +33 -0
- package/dist/compliance-off/skills/git/references/pr/check-merge-readiness.md +49 -0
- package/dist/compliance-off/skills/git/references/pr/fetch-review-threads.md +52 -0
- package/dist/compliance-off/skills/git/references/pr/validate-branch.md +47 -0
- package/dist/compliance-off/skills/git/references/tracker/_contract.md +33 -0
- package/dist/compliance-off/skills/git/references/tracker/_mcp.md +153 -0
- package/dist/compliance-off/skills/git/references/tracker/github/create-release.md +35 -0
- package/dist/compliance-off/skills/git/references/tracker/github/ensure-pr-ready.md +100 -0
- package/dist/compliance-off/skills/git/references/tracker/github/ensure-traceable-issue.md +74 -0
- package/dist/compliance-off/skills/git/references/tracker/github/fetch-issue.md +69 -0
- package/dist/compliance-off/skills/git/references/tracker/github/fetch-issues-batch.md +65 -0
- package/dist/compliance-off/skills/git/references/tracker/github/gather-release-evidence.md +48 -0
- package/dist/compliance-off/skills/git/references/tracker/github/setup-task.md +77 -0
- package/dist/compliance-off/skills/git/references/tracker/jira/create-release.md +35 -0
- package/dist/compliance-off/skills/git/references/tracker/jira/ensure-pr-ready.md +100 -0
- package/dist/compliance-off/skills/git/references/tracker/jira/ensure-traceable-issue.md +61 -0
- package/dist/compliance-off/skills/git/references/tracker/jira/fetch-issue.md +51 -0
- package/dist/compliance-off/skills/git/references/tracker/jira/fetch-issues-batch.md +63 -0
- package/dist/compliance-off/skills/git/references/tracker/jira/gather-release-evidence.md +47 -0
- package/dist/compliance-off/skills/git/references/tracker/jira/setup-task.md +82 -0
- package/dist/compliance-off/skills/git/references/tracker/linear/create-release.md +35 -0
- package/dist/compliance-off/skills/git/references/tracker/linear/ensure-pr-ready.md +100 -0
- package/dist/compliance-off/skills/git/references/tracker/linear/ensure-traceable-issue.md +61 -0
- package/dist/compliance-off/skills/git/references/tracker/linear/fetch-issue.md +51 -0
- package/dist/compliance-off/skills/git/references/tracker/linear/fetch-issues-batch.md +63 -0
- package/dist/compliance-off/skills/git/references/tracker/linear/gather-release-evidence.md +47 -0
- package/dist/compliance-off/skills/git/references/tracker/linear/setup-task.md +83 -0
- package/dist/compliance-off/skills/git/references/trust-rule.md +7 -0
- package/dist/core/agent-models.js +19 -4
- package/dist/core/area-pause-notice.js +44 -0
- package/dist/core/assets.js +126 -17
- package/dist/core/compliance-off-files.js +27 -0
- package/dist/core/curation-move-skip.js +4 -5
- package/dist/core/curation-queue-cleanup.js +6 -5
- package/dist/core/curation-store.js +1 -0
- package/dist/core/curation-variants.js +460 -112
- package/dist/core/evidence-policy.js +10 -8
- package/dist/core/flags.js +2 -2
- package/dist/core/installed-variants.js +63 -0
- package/dist/core/manifest.js +48 -5
- package/dist/core/mds-variants.js +700 -3
- package/dist/core/orphan-sweep.js +11 -2
- package/dist/core/plugins.js +69 -12
- package/dist/core/tracked-areas.js +138 -14
- package/dist/curation-compliance-off/agents/triage.md +176 -0
- package/dist/curation-compliance-off/commands/bug-analysis.md +349 -0
- package/dist/curation-compliance-off/commands/code-review.md +481 -0
- package/dist/curation-compliance-off/commands/dynamic-build.md +1211 -0
- package/dist/curation-compliance-off/commands/dynamic-tickets.md +634 -0
- package/dist/curation-compliance-off/commands/implement.md +689 -0
- package/dist/curation-compliance-off/commands/plan.md +631 -0
- package/dist/curation-compliance-off/commands/release.md +279 -0
- package/dist/curation-compliance-off/commands/resolve.md +692 -0
- package/dist/curation-off/agents/code.md +10 -10
- package/dist/curation-off/agents/fix.md +7 -7
- package/dist/curation-off/agents/harden.md +7 -6
- package/dist/curation-off/agents/refactor.md +6 -6
- package/dist/curation-off/agents/triage.md +7 -0
- package/dist/curation-off/commands/bug-analysis.md +69 -119
- package/dist/curation-off/commands/code-review.md +11 -11
- package/dist/curation-off/commands/debug.md +2 -2
- package/dist/curation-off/commands/dynamic-build.md +25 -25
- package/dist/curation-off/commands/explore.md +2 -2
- package/dist/curation-off/commands/implement.md +48 -34
- package/dist/curation-off/commands/plan.md +2 -2
- package/dist/curation-off/commands/release.md +1 -1
- package/dist/curation-off/commands/resolve.md +50 -46
- package/dist/curation-off/commands/self-review.md +10 -9
- package/dist/hud/components/curation-counts.js +27 -0
- package/dist/skills/git/references/pr/post-resolution-summary.md +12 -11
- package/dist/skills/git/references/pr/post-review-summary.md +12 -11
- package/dist/skills/git/references/pr/resolve-review-threads.md +1 -1
- package/dist/skills/git/references/pr/update-pr-evidence.md +2 -2
- package/dist/skills/git/references/publication-gate.md +6 -7
- package/dist/skills/git/references/tracker/github/manage-debt.md +6 -2
- package/dist/skills/git/references/tracker/jira/manage-debt.md +6 -2
- package/dist/skills/git/references/tracker/linear/manage-debt.md +6 -2
- package/dist/targets/claude-code/behavior-install.js +23 -9
- package/dist/targets/claude-code/charter-render.js +374 -0
- package/dist/targets/claude-code/compliance-install.js +32 -12
- package/dist/targets/claude-code/compliance-off-files.js +245 -0
- package/dist/targets/claude-code/curation-install.js +570 -100
- package/dist/targets/claude-code/installer.js +467 -62
- package/dist/targets/claude-code/language-stamp.js +6 -0
- package/dist/targets/claude-code/linked-folder.js +182 -0
- package/dist/targets/claude-code/reference-converge.js +118 -0
- package/dist/targets/claude-code/tracker-install.js +21 -8
- package/dist/targets/claude-code/tracker-servers.js +20 -6
- package/dist/targets/claude-code/workflow-folder-install.js +231 -0
- package/dist/variant-axes.json +109 -0
- package/package.json +1 -1
- package/src/assets/agents/_partials/_code.mds +6 -6
- package/src/assets/agents/code.mds +4 -4
- package/src/assets/agents/evaluate.md +7 -13
- package/src/assets/agents/fix.mds +1 -1
- package/src/assets/agents/git.mds +34 -2
- package/src/assets/agents/harden.mds +7 -6
- package/src/assets/agents/skim.mds +1 -1
- package/src/assets/agents/test.md +21 -12
- package/src/assets/agents/triage.mds +9 -0
- package/src/assets/agents/validate.md +27 -34
- package/src/assets/commands/_partials/_compliance.mds +5 -3
- package/src/assets/commands/_partials/_decisions.mds +10 -8
- package/src/assets/commands/_partials/_engine.mds +9 -8
- package/src/assets/commands/_partials/_publication.mds +10 -1
- package/src/assets/commands/_partials/_settings.mds +2 -2
- package/src/assets/commands/bug-analysis.mds +80 -126
- package/src/assets/commands/code-review.mds +52 -9
- package/src/assets/commands/dynamic-build.mds +109 -15
- package/src/assets/commands/dynamic-tickets.mds +13 -0
- package/src/assets/commands/implement.mds +145 -33
- package/src/assets/commands/plan.mds +19 -0
- package/src/assets/commands/release.mds +50 -1
- package/src/assets/commands/resolve.mds +229 -44
- package/src/assets/commands/self-review.mds +8 -7
- package/src/assets/mds/git/_ops.mds +29 -1
- package/src/assets/mds/git/_ops_pr.mds +20 -10
- package/src/assets/mds/git/_ops_steps.mds +27 -0
- package/src/assets/mds/git/_pr.mds +15 -15
- package/src/assets/mds/git/_references.mds +12 -7
- package/src/assets/mds/tracker/_common.mds +4 -0
- package/src/assets/mds/tracker/_github.mds +43 -4
- package/src/assets/mds/tracker/_jira.mds +44 -4
- package/src/assets/mds/tracker/_linear.mds +44 -4
- package/src/assets/rules/quality.md +2 -0
- package/src/assets/scripts/ci-wait.cjs +493 -118
- package/src/assets/scripts/hooks/assets/implement-installed +1 -0
- package/src/assets/scripts/hooks/assets/orchestrator-charter.md +13 -11
- package/src/assets/scripts/hooks/background-memory-update +79 -1
- package/src/assets/scripts/hooks/json-helper.cjs +44 -2
- package/src/assets/scripts/hooks/lib/curation-store.cjs +82 -20
- package/src/assets/scripts/hooks/lib/render-decisions.cjs +9 -1
- package/src/assets/scripts/hooks/lib/tracked-areas.cjs +226 -33
- package/src/assets/scripts/hooks/memory-permission +10 -2
- package/src/assets/scripts/hooks/memory-worker +11 -0
- package/src/assets/scripts/hooks/pre-compact-memory +11 -0
- package/src/assets/scripts/hooks/preamble +18 -8
- package/src/assets/scripts/hooks/queue-append +218 -1
- package/src/assets/scripts/hooks/session-start-context +89 -37
- package/src/assets/scripts/hooks/session-start-memory +39 -0
- package/src/assets/scripts/hooks/session-start-orchestrator +4 -2
- package/src/assets/scripts/pr-evidence.cjs +46 -4
- package/src/assets/scripts/resolve-settings.cjs +244 -30
- package/src/assets/scripts/verify-evidence.cjs +708 -124
- package/src/assets/skills/agent-references/SKILL.md +7 -1
- package/src/assets/skills/agent-references/references/commands/implement-levels.md +6 -4
- package/src/assets/skills/agent-references/references/commands/implement-revalidate.md +3 -3
- package/src/assets/skills/agent-references/references/commands/plan-levels.md +1 -1
- package/src/assets/skills/agent-references/references/commands/resolve-levels.md +3 -2
- package/src/assets/skills/agent-references/references/synthesize/bug-analysis.md +6 -2
- package/src/assets/skills/agent-references/references/synthesize/review.md +4 -4
- package/src/assets/skills/agent-references/references/triage/severity-tiers.md +43 -0
- package/src/assets/skills/agent-references/references/validate/passed-alone.md +14 -0
- package/src/assets/skills/docs-framework/SKILL.md +5 -2
- package/src/assets/skills/git/SKILL.md +3 -3
- package/src/assets/skills/git/references/github-api.md +2 -139
- package/src/assets/skills/git/references/github-posting.md +158 -0
- package/src/assets/skills/review-methodology/SKILL.md +1 -1
- package/src/assets/skills/review-methodology/references/patterns.md +1 -1
- package/src/assets/skills/review-methodology/references/report-template.md +1 -2
- package/src/assets/skills/testing/SKILL.md +2 -4
|
@@ -29,7 +29,7 @@ Process issues from code review reports: triage every issue through the blast-ra
|
|
|
29
29
|
- Additional filter: must have unresolved reviews (latest review directory has no `resolution-summary.md`)
|
|
30
30
|
2. **If `--path` flag provided:** use only that worktree, skip discovery
|
|
31
31
|
**`--path` validation**: Before proceeding, verify the path exists as a directory and appears in `git worktree list` output. If not: report error and stop.
|
|
32
|
-
3. **If only 1 resolvable worktree
|
|
32
|
+
3. **If only 1 resolvable worktree:** proceed as single-worktree flow
|
|
33
33
|
4. **If multiple resolvable worktrees:** report "Found N worktrees with unresolved reviews: {list}" and proceed with multi-worktree flow
|
|
34
34
|
|
|
35
35
|
#### Step 0b: Per-Worktree Pre-Flight (Git Agent)
|
|
@@ -59,7 +59,7 @@ PR_DESCRIPTION=$(gh pr view {pr_number} --json body --jq '.body' 2>/dev/null ||
|
|
|
59
59
|
```
|
|
60
60
|
If `pr_number` is absent or the command fails, set `PR_DESCRIPTION` to `(none)`.
|
|
61
61
|
|
|
62
|
-
**DIFF_FILES** is
|
|
62
|
+
**DIFF_FILES** is the `### Diff Scope` block of the validate-branch output, or `""` when the block is absent.
|
|
63
63
|
|
|
64
64
|
#### Step 0c: Target Review Directory
|
|
65
65
|
|
|
@@ -70,13 +70,13 @@ For each worktree:
|
|
|
70
70
|
|
|
71
71
|
1. List directories in `{worktree}/.devflow/docs/reviews/{branch-slug}/`
|
|
72
72
|
2. **If `--review {timestamp}` provided:** use that specific directory (not supported in multi-worktree mode)
|
|
73
|
-
3. **Otherwise:** sort directories by name descending
|
|
73
|
+
3. **Otherwise:** sort directories by name descending, scan the 10 most recent directories only. Select the first that contains `review-summary.md` (complete review)
|
|
74
74
|
4. **If latest directory already has `resolution-summary.md`:** the review is resolved — check bug-analysis fallback (step 5b).
|
|
75
|
-
5. **Legacy fallback:** if no timestamped subdirectories exist but flat `*.md` files do in `{worktree}/.devflow/docs/reviews/{branch-slug}/`, read them directly
|
|
75
|
+
5. **Legacy fallback:** if no timestamped subdirectories exist but flat `*.md` files do in `{worktree}/.devflow/docs/reviews/{branch-slug}/`, read them directly.
|
|
76
76
|
|
|
77
77
|
**5b. Bug analysis fallback** — if no qualifying review directory found (no reviews exist, or all resolved):
|
|
78
78
|
- List directories in `{worktree}/.devflow/docs/bug-analysis/{branch-slug}/`
|
|
79
|
-
- Sort by name descending
|
|
79
|
+
- Sort by name descending, scan the 10 most recent directories only. Select the latest that:
|
|
80
80
|
- Contains at least one focus report (`security.md`, `functional.md`, `integration.md`, or `usability.md`)
|
|
81
81
|
- Does NOT contain a `resolution-summary.md`
|
|
82
82
|
- If found: set `TARGET_DIR` to that path. Reviews take priority — bug analysis is only used when no qualifying review exists.
|
|
@@ -88,13 +88,13 @@ Set `TARGET_DIR` to the selected review or bug-analysis directory path, and `TAR
|
|
|
88
88
|
|
|
89
89
|
**Produces:** FEATURE_KNOWLEDGE, FEATURE_KNOWLEDGE_RULES, EVIDENCE_POLICY, ISSUE_REQUIRED, APPLY_CONVENTIONS, REQUIRE_NON_AUTHOR_APPROVAL, REVIEW_PUBLICATION, RESOLUTION_TS, GATE_LEVEL
|
|
90
90
|
|
|
91
|
-
**Resolve the settings line** once per worktree root, reusing a line this run already resolved for the same root. `{root}` is the worktree the values are for — the repository root
|
|
91
|
+
**Resolve the settings line** once per worktree root, reusing a line this run already resolved for the same root. `{root}` is the worktree the values are for — the repository root in a one-worktree run:
|
|
92
92
|
|
|
93
93
|
```bash
|
|
94
94
|
node "$HOME/.devflow/scripts/resolve-settings.cjs" "{root}" 2>/dev/null; echo "exit=$?"
|
|
95
95
|
```
|
|
96
96
|
|
|
97
|
-
Accept the output only when it is exactly two lines: `exit=0` last and, before it, one line of the form `TRACKER=<github|jira|linear> TRACKER_SOURCE=<project|personal|machine|default> TRACKER_WARN=<none|mismatch|invalid> SITE=<none|https://<host>> KEY=<none|<key>> REVIEW_PUBLICATION=<off|auto|full> COMPLIANCE=<off|generic|<id>[,<id>…]> MEMORY=<on|off> CURATION=<on|off> KNOWLEDGE=<on|off> GATE_LEVEL=<full|standard|lean>` — these fields, in this order, nothing else, where `<host>` is a lowercase dotted host name alone, `<key>` is 2–10 of `A-Z`, `0-9` and `_` starting with a letter, and each `<id>` is one of `gdpr`, `hipaa`, `pci-dss`, `soc2`, `iso-27001`, `sox`. **Anything else** (a non-zero exit, no line, extra text, or a missing, reordered or unlisted field or value) ⇒ use `TRACKER=github TRACKER_SOURCE=default TRACKER_WARN=invalid SITE=none KEY=none REVIEW_PUBLICATION=off COMPLIANCE=generic MEMORY=
|
|
97
|
+
Accept the output only when it is exactly two lines: `exit=0` last and, before it, one line of the form `TRACKER=<github|jira|linear> TRACKER_SOURCE=<project|personal|machine|default> TRACKER_WARN=<none|mismatch|invalid> SITE=<none|https://<host>> KEY=<none|<key>> REVIEW_PUBLICATION=<off|auto|full> COMPLIANCE=<off|generic|<id>[,<id>…]> MEMORY=<on|off> CURATION=<on|off> KNOWLEDGE=<on|off> GATE_LEVEL=<full|standard|lean>` — these fields, in this order, nothing else, where `<host>` is a lowercase dotted host name alone, `<key>` is 2–10 of `A-Z`, `0-9` and `_` starting with a letter, and each `<id>` is one of `gdpr`, `hipaa`, `pci-dss`, `soc2`, `iso-27001`, `sox`. **Anything else** (a non-zero exit, no line, extra text, or a missing, reordered or unlisted field or value) ⇒ use `TRACKER=github TRACKER_SOURCE=default TRACKER_WARN=invalid SITE=none KEY=none REVIEW_PUBLICATION=off COMPLIANCE=generic MEMORY=off CURATION=off KNOWLEDGE=off GATE_LEVEL=full` instead.
|
|
98
98
|
|
|
99
99
|
The accepted line is the only source of these values.
|
|
100
100
|
|
|
@@ -196,9 +196,9 @@ Read review reports from `{TARGET_DIR}/*.md` and extract:
|
|
|
196
196
|
|
|
197
197
|
**Exclude from issue extraction:**
|
|
198
198
|
- `review-summary.md` (Synthesize agent output, not individual findings)
|
|
199
|
-
- `resolution-summary.md` (
|
|
199
|
+
- `resolution-summary.md` (from a previous partial run)
|
|
200
200
|
- `bug-analysis-summary.md` (Synthesize agent output for bug-analysis runs)
|
|
201
|
-
- `static-findings.md` (raw
|
|
201
|
+
- `static-findings.md` (raw tool output, not individual findings)
|
|
202
202
|
|
|
203
203
|
**Include:** ALL issues from all categories and severities, including Suggestions.
|
|
204
204
|
|
|
@@ -252,15 +252,17 @@ Triage every issue: collapse duplicates first, then apply the blast-radius dispo
|
|
|
252
252
|
Follow devflow:apply-feature-knowledge for FEATURE_KNOWLEDGE."
|
|
253
253
|
```
|
|
254
254
|
|
|
255
|
-
|
|
255
|
+
When the Triage agent completes, parse its verdict ledger:
|
|
256
256
|
- **ESCALATED**: Security issues requiring human escalation
|
|
257
|
-
- **FIX_NOW**: Valid issues assigned to Code agents (with risk tier: Standard | Careful)
|
|
257
|
+
- **FIX_NOW**: Valid issues assigned to Code agents (with risk tier: Standard | Careful | `Standard, prose only: edit text alone; agent instructions count as logic; if this issue needs a logic change, leave it unedited and name it`; any other value counts as Careful). SCOPE gives one `{id}: {tier}` line per issue.
|
|
258
258
|
- **FALSE_POSITIVE**: Issues the Review agent got wrong (with cited evidence)
|
|
259
259
|
- **BY_DESIGN**: Intentional code (with a recorded decision, stated in words, or a code doc citation)
|
|
260
260
|
- **FIX_SEPARATE**: Valid but out of blast-radius scope (must become manage-debt ticket)
|
|
261
261
|
- **TECH_DEBT**: Architectural overhaul only — LAST RESORT
|
|
262
262
|
- **DUPLICATE**: Collapsed duplicate issue — carries `duplicate_of: <primary-id>` referencing the non-DUPLICATE primary; inherits the primary's outcome
|
|
263
263
|
|
|
264
|
+
A ledger `### Summary` line `- Tiers: not applied (…)` is the level note.
|
|
265
|
+
|
|
264
266
|
**Triage agent completeness assertion:** Verify the parsed ledger against ISSUES before proceeding:
|
|
265
267
|
1. Every issue `id` from ISSUES must appear in exactly one verdict bucket — none may vanish, none may appear in multiple buckets. DUPLICATE is a valid bucket; a valid DUPLICATE entry must name its `duplicate_of` primary (the `Duplicate Of` column of the ledger's DUPLICATE table) and that primary must be a non-DUPLICATE issue id. A missing `duplicate_of` or one that chains to another DUPLICATE is a **Triage agent failure** (retry-then-abort as below).
|
|
266
268
|
2. If the Triage agent output is empty, contains a skill re-entrancy guard string (e.g., contains `already running`), or is missing any issue IDs from ISSUES: treat as a **Triage agent failure**:
|
|
@@ -276,7 +278,7 @@ Wait for Triage agent to complete before proceeding. Parse verdict ledger from T
|
|
|
276
278
|
|
|
277
279
|
If FIX_NOW list is empty: skip to Phase 5, then run Phases 9, 9b, 9c and 10.
|
|
278
280
|
|
|
279
|
-
Otherwise, batch FIX_NOW issues
|
|
281
|
+
Otherwise, batch FIX_NOW issues. **DUPLICATE issues are never dispatched** — they inherit the primary's outcome:
|
|
280
282
|
- **Same-file issues** → one batch (one Code agent per file)
|
|
281
283
|
- **Distinct-file issues** → parallel Code agents
|
|
282
284
|
- **Max 5 issues per batch** — chunk large sets
|
|
@@ -308,26 +310,29 @@ Spawn distinct-file batch Code agents **in a single message** (parallel). Sequen
|
|
|
308
310
|
Collect from each Code agent:
|
|
309
311
|
- `{status, commitShas, unresolved}` per batch
|
|
310
312
|
- `## Verification` block (commands run + results)
|
|
313
|
+
- An unresolved prose-only issue that Code names as needing a logic change, and whose type is not `security` → FIX_SEPARATE in TRIAGE_RESULTS, Reason `needs a logic change`; every other unresolved issue stays Blocked
|
|
311
314
|
|
|
312
315
|
### Phase 5: Write resolution-summary.md
|
|
313
316
|
|
|
314
317
|
**Produces:** RESOLUTION_FILE (early write for compaction safety)
|
|
315
318
|
**Requires:** TRIAGE_RESULTS, CODE_AGENT_RESULTS, TARGET_DIR, TARGET_DIR_REL, BRANCH_INFO, RESOLUTION_TS, GATE_LEVEL
|
|
316
319
|
|
|
317
|
-
**Immediately write `resolution-summary.md`** to `{TARGET_DIR}
|
|
320
|
+
**Immediately write `resolution-summary.md`** to `{TARGET_DIR}`.
|
|
318
321
|
|
|
319
322
|
Set `Tracked` for FIX_SEPARATE and TECH_DEBT items to `(pending)` — to be backfilled after Phase 9 manage-debt (or `TRACEABILITY: DEGRADED ({reason})` if manage-debt degrades).
|
|
320
323
|
|
|
321
324
|
DUPLICATE issues are listed **only** in `## Duplicates` — never in `## Fixed Issues`, `## False Positives`, `## By Design`, `## Fix Separately`, `## Deferred to Tech Debt`, `## Escalations`, or `## Blocked`. A duplicate of a FALSE_POSITIVE primary therefore leaves only the primary in the `False Positive` row and the `## False Positives` section; the same holds for every other outcome the duplicate inherits.
|
|
322
325
|
|
|
323
|
-
|
|
326
|
+
Open each Issue cell with its severity in brackets when it has one, as `[HIGH]`.
|
|
327
|
+
|
|
328
|
+
Use the template from the Output Artifact section below. Put text not for public posting in a final `## Private notes` section.
|
|
324
329
|
|
|
325
330
|
### Phase 6: Polish
|
|
326
331
|
|
|
327
332
|
**Produces:** POLISH_RESULT
|
|
328
333
|
**Requires:** CODE_AGENT_RESULTS, GATE_LEVEL
|
|
329
334
|
|
|
330
|
-
If any fixes were made, spawn Polish agent
|
|
335
|
+
If any fixes were made, spawn Polish agent:
|
|
331
336
|
|
|
332
337
|
```
|
|
333
338
|
Agent(subagent_type="Polish", run_in_background=false):
|
|
@@ -340,7 +345,7 @@ Commit any improvements with a conventional-commit message."
|
|
|
340
345
|
|
|
341
346
|
### Phase 7: Verification Gate
|
|
342
347
|
|
|
343
|
-
**Produces:** VERIFICATION_STATUS
|
|
348
|
+
**Produces:** VERIFICATION_STATUS, VERIFICATION_BLOCKER
|
|
344
349
|
**Requires:** CODE_AGENT_RESULTS, BRANCH_INFO
|
|
345
350
|
|
|
346
351
|
If no fixes were made (CODE_AGENT_RESULTS contains 0 commits) → set VERIFICATION_STATUS = SKIPPED, skip: "No fixes applied — skipping Verification Gate."
|
|
@@ -357,10 +362,9 @@ Run build, typecheck, lint, test. Report pass/fail with failure details."
|
|
|
357
362
|
`validation_retry_count = 0`
|
|
358
363
|
|
|
359
364
|
**If FAIL:**
|
|
360
|
-
1.
|
|
361
|
-
2.
|
|
362
|
-
|
|
363
|
-
- Spawn Fix agent with fix context:
|
|
365
|
+
1. Increment `validation_retry_count`
|
|
366
|
+
2. If `validation_retry_count <= 2`:
|
|
367
|
+
- Spawn Fix agent:
|
|
364
368
|
```
|
|
365
369
|
Agent(subagent_type="Fix"):
|
|
366
370
|
"OPERATION: validation-fix
|
|
@@ -372,12 +376,16 @@ Run build, typecheck, lint, test. Report pass/fail with failure details."
|
|
|
372
376
|
{COMPLIANCE_DIRECTIVE}"
|
|
373
377
|
```
|
|
374
378
|
- Loop back to re-validate
|
|
375
|
-
|
|
379
|
+
3. If `validation_retry_count > 2`: set VERIFICATION_STATUS = FAILED, Final gate `FAILED after N attempts`; exit the validation loop.
|
|
380
|
+
|
|
381
|
+
**If BLOCKED:** FAILED, Final gate `FAILED (Validate blocked)`, no Fix agent, exit the loop; VERIFICATION_BLOCKER = its cause and log path, for the Phase 10 report only, never resolution-summary.md.
|
|
382
|
+
|
|
383
|
+
**If PASS:** set VERIFICATION_STATUS = PASS, Final gate `PASS`; exit the validation loop.
|
|
376
384
|
|
|
377
|
-
|
|
385
|
+
Any other or missing Status: FAILED, Final gate `FAILED (no Validate status)`, exit the loop; never PASS.
|
|
378
386
|
|
|
379
387
|
Record `## Verification` outcome in resolution-summary.md (runs unconditionally after the validation loop exits):
|
|
380
|
-
- Rewrite the `## Verification` section with | Command | Result | table + `Final gate:
|
|
388
|
+
- Rewrite the `## Verification` section with | Command | Result | table + `Final gate: {value above}`; a FAILED gate gets a blocking callout (never a silent pass)
|
|
381
389
|
|
|
382
390
|
Push all commits to remote once (Code and Fix agents ran with PUSH: false — runs whether the gate PASSED or FAILED, so the branch is always visible before Phase 9 or CI runs):
|
|
383
391
|
```bash
|
|
@@ -393,9 +401,7 @@ git -C {worktree} push
|
|
|
393
401
|
**Produces:** CI_STATUS
|
|
394
402
|
**Requires:** CODE_AGENT_RESULTS, VERIFICATION_STATUS, BRANCH_INFO
|
|
395
403
|
|
|
396
|
-
If
|
|
397
|
-
|
|
398
|
-
If Verification Gate FAILED → skip CI gate (validation failures already reported).
|
|
404
|
+
If VERIFICATION_STATUS is not PASS → skip CI gate.
|
|
399
405
|
|
|
400
406
|
If `fork_no_push` is set → skip: "Cannot push to fork — skipping CI validation."
|
|
401
407
|
|
|
@@ -409,16 +415,16 @@ Otherwise, for each worktree with fixes:
|
|
|
409
415
|
git -C {worktree} push; echo "exit=$?"
|
|
410
416
|
```
|
|
411
417
|
|
|
412
|
-
|
|
418
|
+
`exit=0` continues to the gate. Any other result records `TRACEABILITY: DEGRADED (ci push failed)`, reports "CI status unknown — verify manually before merging" and skips the wait for this worktree. Pass `WORKTREE_PATH: {worktree_path}` on the fix spawn below.
|
|
413
419
|
|
|
414
420
|
<!-- PATTERN: ci-status-gate -->
|
|
415
|
-
1. Wait: run `cd {worktree} && HEAD_SHA=$(git rev-parse HEAD) && node "$HOME/.devflow/scripts/ci-wait.cjs" --pr {PR_NUMBER} --head "$HEAD_SHA"` through the Bash tool with `timeout: 600000`. Each run
|
|
421
|
+
1. Wait: run `cd {worktree} && HEAD_SHA=$(git rev-parse HEAD) && node "$HOME/.devflow/scripts/ci-wait.cjs" --pr {PR_NUMBER} --head "$HEAD_SHA"` through the Bash tool with `timeout: 600000`. Each run waits at most 570 seconds and prints one line, `CI <STATUS> pr=… head=… failing=… pending=… waited=…` (INDETERMINATE adds `reason=…`). A missing or unparseable line, an unknown status or a non-zero exit is INDETERMINATE.
|
|
416
422
|
2. **If PASSING** → proceed to next phase.
|
|
417
423
|
3. **If NO_PR or NO_CI** → skip: "No PR/CI configured, skipping CI validation." Proceed to next phase.
|
|
418
|
-
4. **If PENDING** and fewer than 3 waits have run → wait again
|
|
419
|
-
5. **If INDETERMINATE** and fewer than 3 waits have run → wait again
|
|
420
|
-
6. **If FAILING** and fewer than 2 fixes have run → report the failing checks from the line. Spawn `Agent(subagent_type="Fix")` whose prompt opens with `OPERATION: ci-fix`, with `COMPLIANCE_DIRECTIVE` (when it is not empty), `CI_FAILURES` and `PUSH: false`; `CI_FAILURES` holds the failing-check names from the line
|
|
421
|
-
7. **Budget**: at most 3 waits and 2 fixes in all, per worktree. When one is spent, report the
|
|
424
|
+
4. **If PENDING** and fewer than 3 waits have run → wait again. Otherwise → report "CI still running — verify manually before merging" and proceed.
|
|
425
|
+
5. **If INDETERMINATE** and fewer than 3 waits have run → wait again, unless `waited=570` with `reason=head-mismatch` or `no-workflow-check`. Otherwise → report "CI status unknown — verify manually before merging" and proceed.
|
|
426
|
+
6. **If FAILING** and fewer than 2 fixes have run → report the failing checks from the line. Spawn `Agent(subagent_type="Fix")` whose prompt opens with `OPERATION: ci-fix`, with `COMPLIANCE_DIRECTIVE` (when it is not empty), `CI_FAILURES` and `PUSH: false`; `CI_FAILURES` holds only the failing-check names from the line: the Fix agent fetches the full names and reads the logs itself. After a fix, push with the command above and, if a wait remains, wait again (step 1); a failed push records `TRACEABILITY: DEGRADED (ci push failed)`, reports "CI status unknown — verify manually before merging" and stops waiting. After the second fix still FAILING → report the failing checks and proceed.
|
|
427
|
+
7. **Budget**: at most 3 waits and 2 fixes in all, per worktree. When one is spent, report the status and proceed.
|
|
422
428
|
<!-- /PATTERN: ci-status-gate -->
|
|
423
429
|
|
|
424
430
|
### Phase 9: Manage Debt (Sequential)
|
|
@@ -477,6 +483,8 @@ Append one claim per `### Test Plan Evidence` row whose TP is in the stale file
|
|
|
477
483
|
|
|
478
484
|
The line ends at `by:test` when the row's Exit is not a number from 0 to 255; append nothing when the report's `HEAD:` is not one 40-hex SHA. Record `Test plan: {n} stale, {m} re-verified` under `## Verification` in resolution-summary.md now, before 9b-2 posts it, and set `STALE_REVERIFICATION` to that line.
|
|
479
485
|
|
|
486
|
+
A Test Status whose first word is not PASS or FAIL still gets its claims, but `Test plan: DEGRADED (Test run blocked)` replaces that line. `{m}` counts PASS rows only.
|
|
487
|
+
|
|
480
488
|
**Step 9b-1: Resolve external threads**
|
|
481
489
|
|
|
482
490
|
Run this step only when `EVIDENCE_POLICY` is `required` and THREAD_MAP is non-empty; otherwise skip it and record `THREAD_RESOLUTION_RESULT` as `SKIPPED ({reason})`.
|
|
@@ -556,7 +564,7 @@ If the script prints a `TRACEABILITY: DEGRADED` line: warn, proceed to Phase 10.
|
|
|
556
564
|
|
|
557
565
|
### Phase 10: Report
|
|
558
566
|
|
|
559
|
-
**Requires:** BRANCH_INFO, TARGET_DIR, PR_COMMENT, THREAD_RESOLUTION_RESULT, GATE_LEVEL
|
|
567
|
+
**Requires:** BRANCH_INFO, TARGET_DIR, PR_COMMENT, THREAD_RESOLUTION_RESULT, GATE_LEVEL, VERIFICATION_BLOCKER
|
|
560
568
|
|
|
561
569
|
The resolution summary was already written to `{TARGET_DIR}/resolution-summary.md` in Phase 5 (updated by Phase 7, Phase 9 and Phase 9b-1). Display results to the user:
|
|
562
570
|
|
|
@@ -580,7 +588,8 @@ The resolution summary was already written to `{TARGET_DIR}/resolution-summary.m
|
|
|
580
588
|
| Duplicates Collapsed | {n} |
|
|
581
589
|
|
|
582
590
|
### Verification
|
|
583
|
-
Final gate: {
|
|
591
|
+
Final gate: {the value Phase 7 recorded}
|
|
592
|
+
{VERIFICATION_BLOCKER, if any}
|
|
584
593
|
|
|
585
594
|
### Commits Created
|
|
586
595
|
- {sha} {message}
|
|
@@ -669,10 +678,7 @@ When the Knowledge agent reports `KB_COMMIT: skipped (detached HEAD)`, the files
|
|
|
669
678
|
├─ Phase 8: CI Status Gate (conditional)
|
|
670
679
|
├─ Phase 9: Git agent (manage-debt) — FIX_SEPARATE + TECH_DEBT → backfill Tracked={ISSUE_REF} (or TRACEABILITY: DEGRADED on failure)
|
|
671
680
|
│
|
|
672
|
-
├─ Phase 9b:
|
|
673
|
-
│ ├─ Step 9b-0: verify-evidence.cjs --stale-out → ≤1 Test agent on the stale TPs (wrapped) — only after this run's push
|
|
674
|
-
│ ├─ Step 9b-1: Git agent (resolve-review-threads) — evidence policy required
|
|
675
|
-
│ ├─ Step 9b-2: Git agent (post-resolution-summary, REVIEW_PUBLICATION) — always-on
|
|
681
|
+
├─ Phase 9b: 9b-0 Test agent (stale TPs), 9b-1/9b-2 Git agent (threads, resolution comment)
|
|
676
682
|
│ └─ Step 9b-3: verify-evidence.cjs publish (inline, no Git spawn) — only when the head moved
|
|
677
683
|
│
|
|
678
684
|
├─ Phase 9c: verify-evidence.cjs readiness (inline, no Git spawn) — non-author approval required, report-only
|
|
@@ -688,26 +694,24 @@ When the Knowledge agent reports `KB_COMMIT: skipped (detached HEAD)`, the files
|
|
|
688
694
|
| Fix attempt fails | Revert changes, mark BLOCKED, continue others |
|
|
689
695
|
| Issue dependencies | Sequential chain, skip dependents if predecessor blocked |
|
|
690
696
|
| No issues parsed | Report "No issues to resolve" |
|
|
691
|
-
| Latest review already resolved | Check bug-analysis fallback (Step 0c-5b); if also absent, skip worktree and suggest `/code-review` or `/bug-analysis` |
|
|
692
697
|
| `--review {timestamp}` in multi-worktree mode | Not supported — use `--path` + `--review` to target specific worktree + review |
|
|
693
698
|
| gh/GitHub absent | manage-debt degrades (`TRACEABILITY: DEGRADED ({reason})`); Tracked stays `(pending — TRACEABILITY: DEGRADED ({reason}))` — recorded, not dropped |
|
|
694
699
|
| `EVIDENCE_POLICY` is `standard` | Phases 1b and 9b-step-1 are skipped; post-resolution-summary (Phase 9b step 2) still runs if a PR is known |
|
|
695
700
|
| `REQUIRE_NON_AUTHOR_APPROVAL` is `false` | Phase 9c is skipped and reported as SKIPPED |
|
|
696
|
-
| Public repo (`auto` mode) | Git agent probes visibility, posts counts-only STUB comment; full resolution report stays local |
|
|
697
701
|
| `reviewPublication: off` | Git agent skips posting the resolution comment (OFF) — except that, only when `EVIDENCE_POLICY` is `required`, Step 0d passes `stub` and a counts-only STUB comment posts |
|
|
698
|
-
| Fork PR this run cannot push to
|
|
702
|
+
| Fork PR this run cannot push to | `TRACEABILITY: DEGRADED (cannot push to fork)` → `fork_no_push`: no push in Phase 7, Phase 8 skipped, 9b-1 records FIXED threads as DEGRADED, 9b-2 still posts; the head did not move, so 9b-0 and 9b-3 are skipped |
|
|
699
703
|
| The PR has no trusted evidence record | 9b-0 finds no vouched-for stale line, so no Test agent runs; 9b-3 still refreshes the block and comment, every TP without a claim reading `UNVERIFIED` |
|
|
700
704
|
| A CI run behind a claim has expired (~90 days) | The TP reads `INDETERMINATE` — never verified, never failed — until a claim at a newer SHA settles it |
|
|
701
705
|
|
|
702
706
|
## Principles
|
|
703
707
|
|
|
704
708
|
1. **Orchestration only** - Command spawns agents, doesn't do git/resolve work itself
|
|
705
|
-
2. **Git agent for git work** - All git operations go through Git agent;
|
|
706
|
-
3. **Traceability-aware** - Policy-gated ops
|
|
709
|
+
2. **Git agent for git work** - All git operations go through Git agent; inline scripts are plumbing
|
|
710
|
+
3. **Traceability-aware** - Policy-gated ops are skipped cleanly when the evidence policy does not ask for them; resolution comment (Phase 9b-2) is always-on; test-plan evidence is re-verified (≤1 Test agent) and refreshed only when this run moved the head (Steps 9b-0, 9b-3)
|
|
707
711
|
|
|
708
712
|
## Output Artifact
|
|
709
713
|
|
|
710
|
-
Written in Phase 5
|
|
714
|
+
Written in Phase 5 to `{TARGET_DIR}/resolution-summary.md`:
|
|
711
715
|
|
|
712
716
|
```markdown
|
|
713
717
|
# Resolution Summary
|
|
@@ -716,7 +720,7 @@ Written in Phase 5 (Collect Results) to `{TARGET_DIR}/resolution-summary.md`:
|
|
|
716
720
|
**Date**: {RESOLUTION_TS}
|
|
717
721
|
**Review**: {TARGET_DIR_REL}
|
|
718
722
|
**Command**: /resolve
|
|
719
|
-
**Gate level**: {GATE_LEVEL}
|
|
723
|
+
**Gate level**: {GATE_LEVEL, with any level note}
|
|
720
724
|
|
|
721
725
|
## Statistics
|
|
722
726
|
| Metric | Value |
|
|
@@ -739,7 +743,7 @@ _(Note: `Deferred` = `## Fix Separately` count + `## Deferred to Tech Debt` coun
|
|
|
739
743
|
|
|
740
744
|
Regression tests added: {n}
|
|
741
745
|
|
|
742
|
-
Final gate:
|
|
746
|
+
Final gate: {the value Phase 7 recorded}
|
|
743
747
|
|
|
744
748
|
## Fixed Issues
|
|
745
749
|
| Issue | File:Line | Commit |
|
|
@@ -24,13 +24,13 @@ Detect changed files and build context:
|
|
|
24
24
|
4. Build TASK_DESCRIPTION from recent commit messages or branch name
|
|
25
25
|
5. Record `HEAD_BEFORE` (`git rev-parse HEAD`) now, before Polish runs — Phase 3 compares against it
|
|
26
26
|
|
|
27
|
-
**Resolve the settings line** once per worktree root, reusing a line this run already resolved for the same root. `{root}` is the worktree the values are for — the repository root
|
|
27
|
+
**Resolve the settings line** once per worktree root, reusing a line this run already resolved for the same root. `{root}` is the worktree the values are for — the repository root in a one-worktree run:
|
|
28
28
|
|
|
29
29
|
```bash
|
|
30
30
|
node "$HOME/.devflow/scripts/resolve-settings.cjs" "{root}" 2>/dev/null; echo "exit=$?"
|
|
31
31
|
```
|
|
32
32
|
|
|
33
|
-
Accept the output only when it is exactly two lines: `exit=0` last and, before it, one line of the form `TRACKER=<github|jira|linear> TRACKER_SOURCE=<project|personal|machine|default> TRACKER_WARN=<none|mismatch|invalid> SITE=<none|https://<host>> KEY=<none|<key>> REVIEW_PUBLICATION=<off|auto|full> COMPLIANCE=<off|generic|<id>[,<id>…]> MEMORY=<on|off> CURATION=<on|off> KNOWLEDGE=<on|off> GATE_LEVEL=<full|standard|lean>` — these fields, in this order, nothing else, where `<host>` is a lowercase dotted host name alone, `<key>` is 2–10 of `A-Z`, `0-9` and `_` starting with a letter, and each `<id>` is one of `gdpr`, `hipaa`, `pci-dss`, `soc2`, `iso-27001`, `sox`. **Anything else** (a non-zero exit, no line, extra text, or a missing, reordered or unlisted field or value) ⇒ use `TRACKER=github TRACKER_SOURCE=default TRACKER_WARN=invalid SITE=none KEY=none REVIEW_PUBLICATION=off COMPLIANCE=generic MEMORY=
|
|
33
|
+
Accept the output only when it is exactly two lines: `exit=0` last and, before it, one line of the form `TRACKER=<github|jira|linear> TRACKER_SOURCE=<project|personal|machine|default> TRACKER_WARN=<none|mismatch|invalid> SITE=<none|https://<host>> KEY=<none|<key>> REVIEW_PUBLICATION=<off|auto|full> COMPLIANCE=<off|generic|<id>[,<id>…]> MEMORY=<on|off> CURATION=<on|off> KNOWLEDGE=<on|off> GATE_LEVEL=<full|standard|lean>` — these fields, in this order, nothing else, where `<host>` is a lowercase dotted host name alone, `<key>` is 2–10 of `A-Z`, `0-9` and `_` starting with a letter, and each `<id>` is one of `gdpr`, `hipaa`, `pci-dss`, `soc2`, `iso-27001`, `sox`. **Anything else** (a non-zero exit, no line, extra text, or a missing, reordered or unlisted field or value) ⇒ use `TRACKER=github TRACKER_SOURCE=default TRACKER_WARN=invalid SITE=none KEY=none REVIEW_PUBLICATION=off COMPLIANCE=generic MEMORY=off CURATION=off KNOWLEDGE=off GATE_LEVEL=full` instead.
|
|
34
34
|
|
|
35
35
|
The accepted line is the only source of these values.
|
|
36
36
|
|
|
@@ -131,7 +131,7 @@ Follow devflow:apply-feature-knowledge for FEATURE_KNOWLEDGE. Skip if (none)."
|
|
|
131
131
|
|
|
132
132
|
If STATUS is BLOCKED, skip this phase: the report (Phase 4) names the blocker.
|
|
133
133
|
|
|
134
|
-
Run this phase only if HEAD moved — `git rev-parse HEAD` differs from `HEAD_BEFORE`, meaning Polish or Harden committed (Polish alone counts, whatever Harden's STATUS is). Otherwise skip it.
|
|
134
|
+
Run this phase only if HEAD moved — `git rev-parse HEAD` differs from `HEAD_BEFORE`, meaning Polish or Harden committed (Polish alone counts, whatever Harden's STATUS is). Otherwise skip it.
|
|
135
135
|
|
|
136
136
|
Agent(subagent_type="Validate", run_in_background=false):
|
|
137
137
|
"FILES_CHANGED: {output of `git diff --name-only HEAD_BEFORE..HEAD`}
|
|
@@ -140,6 +140,7 @@ Run build, typecheck, lint, test on modified files"
|
|
|
140
140
|
|
|
141
141
|
**If FAIL:** Report validation failures to user and halt
|
|
142
142
|
**If PASS:** Continue to report
|
|
143
|
+
**Any other or missing Status** (BLOCKED included): report the status or "none", its cause and log path if any, then halt.
|
|
143
144
|
|
|
144
145
|
### Phase 4: Report
|
|
145
146
|
|
|
@@ -230,7 +231,7 @@ When the Knowledge agent reports `KB_COMMIT: skipped (detached HEAD)`, the files
|
|
|
230
231
|
│ └─ 9-pillar quality gate (may fix and commit)
|
|
231
232
|
│
|
|
232
233
|
├─ Phase 3: Validate agent (conditional)
|
|
233
|
-
│ └─ If HEAD moved
|
|
234
|
+
│ └─ If HEAD moved: changed-only over HEAD_BEFORE..HEAD
|
|
234
235
|
│
|
|
235
236
|
└─ Phase 4: Report
|
|
236
237
|
└─ Display summary with pillar status
|
|
@@ -242,13 +243,13 @@ When the Knowledge agent reports `KB_COMMIT: skipped (detached HEAD)`, the files
|
|
|
242
243
|
| No changes | Report "No changes to review" and exit |
|
|
243
244
|
| Polish agent finds nothing | Normal, continue to Harden agent |
|
|
244
245
|
| Harden agent BLOCKED | Report blocking issue, halt workflow |
|
|
245
|
-
| Validation fails | Report failures, halt
|
|
246
|
+
| Validation fails | Report failures, halt |
|
|
247
|
+
| Validate not PASS or FAIL | Report status and cause, halt |
|
|
246
248
|
| Not in git repo | Report error, suggest running in git repo |
|
|
247
249
|
|
|
248
250
|
## Principles
|
|
249
251
|
|
|
250
252
|
1. **Orchestration only** - Command spawns agents, doesn't do the work
|
|
251
|
-
2. **
|
|
252
|
-
3. **
|
|
253
|
-
4. **
|
|
254
|
-
5. **Fail fast** - Stop on BLOCKED or validation failure
|
|
253
|
+
2. **Validation gate** - If Polish agent or Harden agent committed, the changes must pass validation
|
|
254
|
+
3. **Honest reporting** - Display actual agent outputs
|
|
255
|
+
4. **Fail fast** - Stop on BLOCKED or a Validate status other than PASS
|
|
@@ -6,6 +6,7 @@ import { formatMoveNotice, gatherMoveNotice } from '../../core/curation-move-not
|
|
|
6
6
|
import { isMoveSkipReason } from '../../core/curation-move-skip.js';
|
|
7
7
|
import { getLedgerRoot, LEDGER_ROOT_TIMEOUT_MS } from '../../core/ledger-root.js';
|
|
8
8
|
import { isActiveDecisionsStatus } from '../../core/observations.js';
|
|
9
|
+
import { probeTrackedArea } from '../../core/tracked-areas.js';
|
|
9
10
|
/**
|
|
10
11
|
* The largest ledger the statusline reads: 8 MiB, far above the roughly 0.5 MB
|
|
11
12
|
* real ledgers reach.
|
|
@@ -101,6 +102,16 @@ export function gatherCurationCounts(cwd) {
|
|
|
101
102
|
}
|
|
102
103
|
return parsedAny ? counts : null;
|
|
103
104
|
}
|
|
105
|
+
/** Whether anything stands at `ledgerPath`, a link included: the cheap test that keeps git out of a project with no ledger. */
|
|
106
|
+
async function ledgerPresent(ledgerPath) {
|
|
107
|
+
try {
|
|
108
|
+
await fs.promises.lstat(ledgerPath);
|
|
109
|
+
return true;
|
|
110
|
+
}
|
|
111
|
+
catch {
|
|
112
|
+
return false;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
104
115
|
/**
|
|
105
116
|
* Count the ledger the hooks write for a session started in `cwd`: the ledger
|
|
106
117
|
* root (getLedgerRoot — the main checkout in a linked worktree, the repository
|
|
@@ -109,10 +120,26 @@ export function gatherCurationCounts(cwd) {
|
|
|
109
120
|
* status gather, not after it (D-LEDGER-MAIN-WORKTREE). Where the old ledger folder
|
|
110
121
|
* still stands it adds the move notice (gatherMoveNotice): any notice when both counts
|
|
111
122
|
* are zero, a skip notice only when a count is above zero.
|
|
123
|
+
*
|
|
124
|
+
* The ledger is read only where git tracks nothing in the curation folders: when it
|
|
125
|
+
* stands, the tracked-areas check asks git, and any answer other than `untracked` (git
|
|
126
|
+
* tracks files there, git did not answer, or the budget ran out) gives no counts and no
|
|
127
|
+
* notice. A project with no ledger makes no git call here. The root lookup and the check
|
|
128
|
+
* share one LEDGER_ROOT_TIMEOUT_MS deadline: the check gets what the lookup left, and when
|
|
129
|
+
* nothing is left it does not run and the answer is no counts.
|
|
112
130
|
*/
|
|
113
131
|
export async function gatherLedgerCurationCounts(cwd, options = {}) {
|
|
132
|
+
const deadline = Date.now() + LEDGER_ROOT_TIMEOUT_MS;
|
|
114
133
|
const root = await getLedgerRoot(cwd, { ...options, timeoutMs: LEDGER_ROOT_TIMEOUT_MS });
|
|
115
134
|
const ledgerRoot = root ?? cwd;
|
|
135
|
+
if (await ledgerPresent(getDecisionsLedgerPath(ledgerRoot))) {
|
|
136
|
+
const timeLeftMs = deadline - Date.now();
|
|
137
|
+
if (timeLeftMs <= 0)
|
|
138
|
+
return null;
|
|
139
|
+
const { answer } = await probeTrackedArea(ledgerRoot, 'curation', { timeoutMs: timeLeftMs });
|
|
140
|
+
if (answer !== 'untracked')
|
|
141
|
+
return null;
|
|
142
|
+
}
|
|
116
143
|
const counts = gatherCurationCounts(ledgerRoot);
|
|
117
144
|
const move = gatherMoveNotice(ledgerRoot, options.home ?? os.homedir());
|
|
118
145
|
if (counts !== null && counts.decisions + counts.pitfalls > 0) {
|
|
@@ -1,47 +1,48 @@
|
|
|
1
1
|
## Operation: post-resolution-summary
|
|
2
2
|
|
|
3
|
-
Post the resolution summary as
|
|
3
|
+
Post the resolution summary as one PR comment per workflow run, deduplicated by its marker; never edited after posting (D8).
|
|
4
4
|
|
|
5
5
|
**Input:** `PR_NUMBER`, `RESOLUTION_SUMMARY_PATH`, `RESOLUTION_TS`, `WORKTREE_PATH` (optional), `REVIEW_PUBLICATION` (optional; values: `auto` | `full` | `off` | `stub`; absent/unrecognised → `auto`)
|
|
6
6
|
|
|
7
|
-
**Degradation (D4):** No PR → `TRACEABILITY: DEGRADED (no PR)`, warn, return
|
|
7
|
+
**Degradation (D4):** No PR → `TRACEABILITY: DEGRADED (no PR)`, warn, return; the summary stays on disk.
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
Its publication gate is the `devflow:git` skill's `references/publication-gate.md` (D10).
|
|
10
10
|
|
|
11
11
|
The body the steps below compose MUST NOT reproduce verbatim content from any `<external-thread>` body or `<untrusted-issue-body>` — cite only internal evidence (commit SHAs, file:line from this codebase) and the thread's `ext-{N}` id.
|
|
12
12
|
|
|
13
|
+
**Private sections:** one starts at any line, fenced or not, of 0-3 spaces, 1-6 `#`, a space or tab and the word `Private` (any case) not followed by a letter or digit. It ends before the next unfenced heading (0-3 spaces) with as many `#` as its start or fewer, else at end of file; an unclosed fence in it runs it to end of file. When unsure, strip more. The read strips them before either mode, closing at each cut any fence the cut leaves open; compose, cap and re-cap use only the stripped text; the file stays unedited. A failed read or strip, blank stripped text or, before the scrub, a body line of that start shape → post nothing; report `**Status**: DEGRADED (no postable summary)` and never quote private text.
|
|
14
|
+
|
|
13
15
|
**Output:**
|
|
14
16
|
```markdown
|
|
15
17
|
## Resolution Summary Posted
|
|
16
18
|
**PR**: #{number}
|
|
17
19
|
**Publication**: FULL (private repo) | FULL (config override) | STUB (public repository) | OFF (publication disabled by config) | STUB (visibility undeterminable) | STUB (evidence policy)
|
|
18
|
-
**Status**: POSTED | POSTED+TRUNCATED (body exceeded 60k after redaction
|
|
20
|
+
**Status**: POSTED | POSTED+TRUNCATED (body exceeded 60k after redaction) | SKIPPED (already posted) | DEGRADED ({reason})
|
|
21
|
+
**Stripped**: {n} private sections
|
|
19
22
|
```
|
|
20
23
|
|
|
21
24
|
Load for `post-resolution-summary` under every tracker provider.
|
|
22
25
|
|
|
23
|
-
**PR mechanics held here:** the author-filtered marker dedup, the visibility probe, the FULL/STUB compose templates with the 60000-character cap, and the scrub-then-post call.
|
|
24
|
-
|
|
25
26
|
### Process
|
|
26
27
|
|
|
27
|
-
1. Check for existing marker (author-filtered
|
|
28
|
+
1. Check for an existing marker (author-filtered, so a third party's copy of it cannot suppress devflow's comment):
|
|
28
29
|
- Fetch viewer login: `gh api user --jq '.login'` → store as VIEWER_LOGIN
|
|
29
30
|
- `gh pr view {PR_NUMBER} --json comments --jq '[.comments[] | select(.author.login == "'"$VIEWER_LOGIN"'")] | .[].body'`
|
|
30
31
|
- Search the viewer-authored bodies only for the exact key `<!-- devflow:resolution-summary ts:{RESOLUTION_TS} -->`
|
|
31
32
|
- If found: skip — report `Skipped: already posted for ts:{RESOLUTION_TS}`
|
|
32
33
|
2. Load `references/publication-gate.md` and resolve `REVIEW_PUBLICATION` by its step 2; `off` ends the op without posting.
|
|
33
34
|
3. Probe (if mode not yet determined): `gh repo view --json visibility --jq '.visibility'`, case-insensitive. `PRIVATE`/`INTERNAL` → FULL; `PUBLIC` → `STUB (public repository)`; empty output, an error or any other value → `STUB (visibility undeterminable)`. **Fail-closed: on any error or unrecognised value, treat as PUBLIC (mode STUB).**
|
|
34
|
-
4. Read `RESOLUTION_SUMMARY_PATH`
|
|
35
|
+
4. Read `RESOLUTION_SUMMARY_PATH` (repo-relative) under `WORKTREE_PATH` (else cwd); strip it (above).
|
|
35
36
|
5. Compose body (where `{TS}` = `RESOLUTION_TS`):
|
|
36
37
|
- **FULL mode:**
|
|
37
38
|
```
|
|
38
39
|
<!-- devflow:resolution-summary ts:{TS} -->
|
|
39
|
-
{
|
|
40
|
+
{stripped resolution-summary.md}
|
|
40
41
|
|
|
41
42
|
---
|
|
42
43
|
*Posted by [devflow](https://github.com/dean0x/devflow)*
|
|
43
44
|
```
|
|
44
|
-
- **STUB mode** (excluded:
|
|
45
|
+
- **STUB mode** (stripped text only; excluded: all but the counts table):
|
|
45
46
|
```
|
|
46
47
|
<!-- devflow:resolution-summary ts:{TS} -->
|
|
47
48
|
## Resolution Summary
|
|
@@ -53,6 +54,6 @@ Load for `post-resolution-summary` under every tracker provider.
|
|
|
53
54
|
Full report: {RESOLUTION_SUMMARY_PATH} (not committed; ask the author)
|
|
54
55
|
*Posted by [devflow](https://github.com/dean0x/devflow)*
|
|
55
56
|
```
|
|
56
|
-
Cap body at 60000 characters
|
|
57
|
+
Cap body at 60000 characters; truncate lowest-value sections first (Suggestions, then Pre-existing), keeping the counts table and every Blocking entry; end with `…truncated — full report in the local review artifact {RESOLUTION_SUMMARY_PATH} (not committed; ask the author)`.
|
|
57
58
|
6. Write body to `$DEVFLOW_BODY_RAW`; apply the Comment-sink scrub (D11) — non-zero exit or missing script → DO NOT POST. Re-check the 60000-char cap on the scrubbed body (redaction may grow it; truncate at a line boundary below 59,800 chars, keeping the truncation pointer sentence; if truncation fires here: emit `NOTE: body exceeded 60k after redaction — truncated/stub posted` in op output and prepend that notice to the body). Post: `gh pr comment {PR_NUMBER} --body-file "$DEVFLOW_BODY"`.
|
|
58
59
|
7. On 5xx: retry once. If still 5xx: `TRACEABILITY: DEGRADED (5xx on post-resolution-summary)`, warn, return.
|
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
## Operation: post-review-summary
|
|
2
2
|
|
|
3
|
-
Post a consolidated code review summary as
|
|
3
|
+
Post a consolidated code review summary as one PR comment per review run (D7), deduplicated by its cycle+timestamp marker; never edited after posting.
|
|
4
4
|
|
|
5
5
|
**Input:** `PR_NUMBER`, `REVIEW_SUMMARY_PATH`, `CYCLE_NUMBER`, `REVIEW_TIMESTAMP`, `WORKTREE_PATH` (optional), `REVIEW_PUBLICATION` (optional; values: `auto` | `full` | `off` | `stub`; absent/unrecognised → `auto`)
|
|
6
6
|
|
|
7
|
-
- `REVIEW_TIMESTAMP`: the review directory timestamp slug (e.g., `2026-08-20_1030`)
|
|
7
|
+
- `REVIEW_TIMESTAMP`: the review directory's timestamp slug (e.g., `2026-08-20_1030`), the run half of the dedup key, so a re-review posts its own comment
|
|
8
8
|
|
|
9
|
-
**Degradation (D4):** No PR / `gh` unauthenticated → `TRACEABILITY: DEGRADED (no PR)`, warn
|
|
9
|
+
**Degradation (D4):** No PR / `gh` unauthenticated → `TRACEABILITY: DEGRADED (no PR)`, warn, return; the summary stays on disk.
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
Its publication gate is the `devflow:git` skill's `references/publication-gate.md` (D10).
|
|
12
|
+
|
|
13
|
+
**Private sections:** one starts at any line, fenced or not, of 0-3 spaces, 1-6 `#`, a space or tab and the word `Private` (any case) not followed by a letter or digit. It ends before the next unfenced heading (0-3 spaces) with as many `#` as its start or fewer, else at end of file; an unclosed fence in it runs it to end of file. When unsure, strip more. The read strips them before either mode, closing at each cut any fence the cut leaves open; compose, cap and re-cap use only the stripped text; the file stays unedited. A failed read or strip, blank stripped text or, before the scrub, a body line of that start shape → post nothing; report `**Status**: DEGRADED (no postable summary)` and never quote private text.
|
|
12
14
|
|
|
13
15
|
**Output:**
|
|
14
16
|
```markdown
|
|
@@ -17,35 +19,34 @@ The publication gate this operation applies is the `devflow:git` skill's `refere
|
|
|
17
19
|
**Cycle**: {CYCLE_NUMBER}
|
|
18
20
|
**Review timestamp**: {REVIEW_TIMESTAMP}
|
|
19
21
|
**Publication**: FULL (private repo) | FULL (config override) | STUB (public repository) | OFF (publication disabled by config) | STUB (visibility undeterminable) | STUB (evidence policy)
|
|
20
|
-
**Status**: POSTED | POSTED+TRUNCATED (body exceeded 60k after redaction
|
|
22
|
+
**Status**: POSTED | POSTED+TRUNCATED (body exceeded 60k after redaction) | SKIPPED (already posted for cycle {N} ts:{REVIEW_TIMESTAMP}) | DEGRADED ({reason})
|
|
23
|
+
**Stripped**: {n} private sections
|
|
21
24
|
```
|
|
22
25
|
|
|
23
26
|
Load for `post-review-summary` under every tracker provider.
|
|
24
27
|
|
|
25
|
-
**PR mechanics held here:** the author-filtered marker dedup, the visibility probe, the FULL/STUB compose templates with the 60000-character cap, and the scrub-then-post call.
|
|
26
|
-
|
|
27
28
|
### Process
|
|
28
29
|
|
|
29
|
-
1. Check for existing comment with this run's marker (author-filtered
|
|
30
|
+
1. Check for existing comment with this run's marker (author-filtered, so a third party's copy of the marker cannot suppress it):
|
|
30
31
|
- Fetch viewer login: `gh api user --jq '.login'` → store as VIEWER_LOGIN
|
|
31
32
|
- `gh pr view {PR_NUMBER} --json comments --jq '[.comments[] | select(.author.login == "'"$VIEWER_LOGIN"'")] | .[].body'`
|
|
32
33
|
- Search for `<!-- devflow:review-summary cycle:{CYCLE_NUMBER} ts:{REVIEW_TIMESTAMP}` in the viewer-authored comment bodies only (full pair match)
|
|
33
34
|
- If found: skip — report `Skipped: already posted for cycle {CYCLE_NUMBER} ts:{REVIEW_TIMESTAMP}`
|
|
34
35
|
2. Load `references/publication-gate.md` and resolve `REVIEW_PUBLICATION` by its step 2; `off` ends the op without posting.
|
|
35
36
|
3. Probe (if mode not yet determined): `gh repo view --json visibility --jq '.visibility'`, case-insensitive. `PRIVATE`/`INTERNAL` → FULL; `PUBLIC` → `STUB (public repository)`; empty output, an error or any other value → `STUB (visibility undeterminable)`. **Fail-closed: on any error or unrecognised value, treat as PUBLIC (mode STUB).**
|
|
36
|
-
4. Read `REVIEW_SUMMARY_PATH`
|
|
37
|
+
4. Read `REVIEW_SUMMARY_PATH` (repo-relative) under `WORKTREE_PATH` (else cwd); strip it (above).
|
|
37
38
|
5. Compose body:
|
|
38
39
|
- **FULL mode:**
|
|
39
40
|
```
|
|
40
41
|
<!-- devflow:review-summary cycle:{CYCLE_NUMBER} ts:{REVIEW_TIMESTAMP} -->
|
|
41
42
|
## Code Review — Cycle {CYCLE_NUMBER}
|
|
42
43
|
|
|
43
|
-
{
|
|
44
|
+
{stripped review-summary.md}
|
|
44
45
|
|
|
45
46
|
---
|
|
46
47
|
*Posted by [devflow](https://github.com/dean0x/devflow) · cycle {CYCLE_NUMBER}*
|
|
47
48
|
```
|
|
48
|
-
- **STUB mode** (
|
|
49
|
+
- **STUB mode** (stripped text only; excluded: all but the counts table):
|
|
49
50
|
```
|
|
50
51
|
<!-- devflow:review-summary cycle:{CYCLE_NUMBER} ts:{REVIEW_TIMESTAMP} -->
|
|
51
52
|
## Code Review — Cycle {CYCLE_NUMBER}
|
|
@@ -41,7 +41,7 @@ Each `THREAD_MAP` entry carries one verdict:
|
|
|
41
41
|
|
|
42
42
|
### Process
|
|
43
43
|
|
|
44
|
-
Rate limits: this op fans out, so read the remaining-budget rungs in `references/github-api.md` before the first iteration.
|
|
44
|
+
Rate limits: this op fans out, so read the remaining-budget rungs in `references/github-api.md` before the first iteration. The thread-reply and `resolveReviewThread` recipes are in `references/github-posting.md`.
|
|
45
45
|
|
|
46
46
|
For each `ext-{N}` in THREAD_MAP (sequentially, ≤50, 1s between operations). `fetch-review-threads`
|
|
47
47
|
returns up to 100 threads, so a busy PR can exceed this bound: process the first 50 in THREAD_MAP
|
|
@@ -10,7 +10,7 @@ Update the PR's test-plan block and evidence comment.
|
|
|
10
10
|
```markdown
|
|
11
11
|
## PR Evidence
|
|
12
12
|
{the script's EVIDENCE line}
|
|
13
|
-
**Body**: EDITED | UNCHANGED | SKIPPED | DEGRADED ({reason}) · **Comment**: POSTED | SKIPPED | OFF | DEGRADED ({reason})
|
|
13
|
+
**Body**: EDITED | UNCHANGED | SKIPPED | DEGRADED ({reason}) · **Comment**: POSTED | SKIPPED | OFF | EDITED | DEGRADED ({reason})
|
|
14
14
|
```
|
|
15
15
|
|
|
16
16
|
Load for `update-pr-evidence` under every tracker provider.
|
|
@@ -22,4 +22,4 @@ Load for `update-pr-evidence` under every tracker provider.
|
|
|
22
22
|
1. From `WORKTREE_PATH` (else cwd), run `node "$HOME/.devflow/scripts/verify-evidence.cjs" publish --pr {PR_NUMBER}; echo "exit=$?"`, adding `--publication {REVIEW_PUBLICATION}` only when that is `auto`, `full`, `off` or `stub`, and `--evidence "{EVIDENCE_FILE}"` when given — only a value matching `^[A-Za-z0-9._/-]{1,255}$` reaches the shell; any other is a failed run. Set the Bash `timeout` to 180000.
|
|
23
23
|
2. Print the script's stdout and nothing else. On exit 0 it is the `## PR Evidence` block: the heading, the line `EVIDENCE pr:<n> head:<sha> total:<n> VERIFIED-CI:<n> ATTESTED-LOCAL:<n> UNVERIFIED:<n> STALE:<n> FAILED:<n> INDETERMINATE:<n> stale:<ids|none> exceptions:<kinds|none> approval:<yes|no|unchecked> key:<hex> posted:<yes|no|n/a> body:<same|changed>`, and the `**Body**:` / `**Comment**:` line, then one `TRACEABILITY: DEGRADED ({reason})` line for each part that degraded, such as `DEGRADED (concurrent edit)` (the body edit then reads `SKIPPED`), `DEGRADED (body read-back mismatch)` or `DEGRADED (redaction unavailable)`: a body the script cannot scrub is never posted. On exit 2 it is `TRACEABILITY: DEGRADED (evidence unavailable)`. Any other exit, or empty stdout, is a failed run: emit that same line.
|
|
24
24
|
|
|
25
|
-
Run nothing else: the script makes the one PR read, the compare-and-swap body edit, its read-back and the
|
|
25
|
+
Run nothing else: the script makes the one PR read, the compare-and-swap body edit, its read-back and the evidence comment itself, edited in place when the viewer's own is the newest evidence comment, and posts nothing it could not scrub.
|
|
@@ -2,12 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
Applies to **`post-review-summary` and `post-resolution-summary` only.** No other op probes repo visibility.
|
|
4
4
|
|
|
5
|
-
**Step order
|
|
6
|
-
1. Dedup check (D7/D8 marker
|
|
5
|
+
**Step order:**
|
|
6
|
+
1. Dedup check (D7/D8 marker; stays first).
|
|
7
7
|
2. Resolve `REVIEW_PUBLICATION` input: `off` → report `**Publication**: OFF (publication disabled by config)`, op ends without posting. `full` → mode FULL, skip probe. `auto` or absent/unrecognised → probe.
|
|
8
8
|
- `stub` (never unrecognised) → mode STUB, skip probe; report `STUB (evidence policy)`.
|
|
9
|
-
3. Probe once: `gh repo view --json visibility --jq '.visibility'
|
|
10
|
-
4. Compose body (
|
|
11
|
-
5. Scrub per D11 (both modes
|
|
12
|
-
6.
|
|
13
|
-
7. Post; 5xx retry-once (unchanged).
|
|
9
|
+
3. Probe once: `gh repo view --json visibility --jq '.visibility'`, case-insensitive. `PRIVATE` or `INTERNAL` → mode FULL; anything else → mode STUB. **Fail-closed rule: on any error or unrecognised value, treat as PUBLIC (mode STUB).**
|
|
10
|
+
4. Compose body (defined per op).
|
|
11
|
+
5. Scrub per D11 (both modes), then re-check the 60000-char cap **after** the scrub.
|
|
12
|
+
6. Post; 5xx retry-once.
|