devflow-kit 3.8.0 → 3.9.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 (94) hide show
  1. package/CHANGELOG.md +120 -0
  2. package/README.md +5 -5
  3. package/dist/agents/code.md +4 -4
  4. package/dist/agents/fix.md +1 -1
  5. package/dist/agents/git.md +2 -2
  6. package/dist/agents/skim.md +1 -1
  7. package/dist/agents/triage.md +7 -0
  8. package/dist/cli/commands/curation.js +67 -16
  9. package/dist/cli/commands/gate-level-prompts.js +8 -6
  10. package/dist/cli/commands/gates.js +5 -4
  11. package/dist/cli/commands/init.js +8 -7
  12. package/dist/cli/commands/memory.js +59 -12
  13. package/dist/cli/commands/uninstall.js +77 -9
  14. package/dist/commands/bug-analysis.md +2 -2
  15. package/dist/commands/code-review.md +11 -11
  16. package/dist/commands/debug.md +2 -2
  17. package/dist/commands/dynamic-build.md +2 -2
  18. package/dist/commands/dynamic-plan.md +2 -2
  19. package/dist/commands/dynamic-profile.md +2 -2
  20. package/dist/commands/dynamic-tickets.md +2 -2
  21. package/dist/commands/explore.md +2 -2
  22. package/dist/commands/implement.md +2 -2
  23. package/dist/commands/plan.md +2 -2
  24. package/dist/commands/release.md +2 -2
  25. package/dist/commands/research.md +2 -2
  26. package/dist/commands/resolve.md +16 -16
  27. package/dist/commands/self-review.md +2 -2
  28. package/dist/core/area-pause-notice.js +44 -0
  29. package/dist/core/curation-move-skip.js +4 -5
  30. package/dist/core/curation-queue-cleanup.js +6 -5
  31. package/dist/core/curation-store.js +1 -0
  32. package/dist/core/evidence-policy.js +10 -8
  33. package/dist/core/plugins.js +4 -4
  34. package/dist/core/tracked-areas.js +138 -14
  35. package/dist/curation-off/agents/code.md +4 -4
  36. package/dist/curation-off/agents/fix.md +1 -1
  37. package/dist/curation-off/agents/triage.md +7 -0
  38. package/dist/curation-off/commands/code-review.md +11 -11
  39. package/dist/curation-off/commands/debug.md +2 -2
  40. package/dist/curation-off/commands/dynamic-build.md +2 -2
  41. package/dist/curation-off/commands/explore.md +2 -2
  42. package/dist/curation-off/commands/implement.md +2 -2
  43. package/dist/curation-off/commands/plan.md +2 -2
  44. package/dist/curation-off/commands/resolve.md +16 -16
  45. package/dist/curation-off/commands/self-review.md +2 -2
  46. package/dist/hud/components/curation-counts.js +27 -0
  47. package/dist/skills/git/references/pr/post-resolution-summary.md +12 -11
  48. package/dist/skills/git/references/pr/post-review-summary.md +12 -11
  49. package/dist/skills/git/references/pr/update-pr-evidence.md +2 -2
  50. package/dist/skills/git/references/publication-gate.md +6 -7
  51. package/dist/skills/git/references/tracker/github/manage-debt.md +6 -2
  52. package/dist/skills/git/references/tracker/jira/manage-debt.md +6 -2
  53. package/dist/skills/git/references/tracker/linear/manage-debt.md +6 -2
  54. package/package.json +1 -1
  55. package/src/assets/agents/code.mds +4 -4
  56. package/src/assets/agents/evaluate.md +6 -12
  57. package/src/assets/agents/fix.mds +1 -1
  58. package/src/assets/agents/git.mds +2 -2
  59. package/src/assets/agents/skim.mds +1 -1
  60. package/src/assets/agents/triage.mds +7 -0
  61. package/src/assets/agents/validate.md +20 -27
  62. package/src/assets/commands/_partials/_decisions.mds +10 -8
  63. package/src/assets/commands/_partials/_settings.mds +2 -2
  64. package/src/assets/commands/code-review.mds +9 -9
  65. package/src/assets/commands/resolve.mds +14 -14
  66. package/src/assets/mds/git/_ops.mds +6 -1
  67. package/src/assets/mds/git/_ops_pr.mds +20 -10
  68. package/src/assets/mds/git/_ops_steps.mds +10 -0
  69. package/src/assets/mds/git/_pr.mds +14 -14
  70. package/src/assets/mds/git/_references.mds +6 -7
  71. package/src/assets/mds/tracker/_github.mds +1 -4
  72. package/src/assets/mds/tracker/_jira.mds +1 -4
  73. package/src/assets/mds/tracker/_linear.mds +1 -4
  74. package/src/assets/scripts/ci-wait.cjs +389 -92
  75. package/src/assets/scripts/hooks/background-memory-update +79 -1
  76. package/src/assets/scripts/hooks/json-helper.cjs +44 -2
  77. package/src/assets/scripts/hooks/lib/curation-store.cjs +82 -20
  78. package/src/assets/scripts/hooks/lib/render-decisions.cjs +9 -1
  79. package/src/assets/scripts/hooks/lib/tracked-areas.cjs +226 -33
  80. package/src/assets/scripts/hooks/memory-permission +10 -2
  81. package/src/assets/scripts/hooks/memory-worker +11 -0
  82. package/src/assets/scripts/hooks/pre-compact-memory +11 -0
  83. package/src/assets/scripts/hooks/queue-append +218 -1
  84. package/src/assets/scripts/hooks/session-start-context +89 -37
  85. package/src/assets/scripts/hooks/session-start-memory +39 -0
  86. package/src/assets/scripts/pr-evidence.cjs +5 -2
  87. package/src/assets/scripts/resolve-settings.cjs +244 -30
  88. package/src/assets/scripts/verify-evidence.cjs +307 -75
  89. package/src/assets/skills/agent-references/SKILL.md +7 -1
  90. package/src/assets/skills/agent-references/references/commands/implement-levels.md +6 -4
  91. package/src/assets/skills/agent-references/references/commands/resolve-levels.md +3 -2
  92. package/src/assets/skills/agent-references/references/synthesize/review.md +4 -4
  93. package/src/assets/skills/agent-references/references/triage/severity-tiers.md +43 -0
  94. package/src/assets/skills/agent-references/references/validate/passed-alone.md +14 -0
@@ -30,13 +30,13 @@ $ARGUMENTS
30
30
 
31
31
  ### Phase 1: Resolve Settings
32
32
 
33
- **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 when the run has one worktree:
33
+ **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:
34
34
 
35
35
  ```bash
36
36
  node "$HOME/.devflow/scripts/resolve-settings.cjs" "{root}" 2>/dev/null; echo "exit=$?"
37
37
  ```
38
38
 
39
- 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=on CURATION=on KNOWLEDGE=off GATE_LEVEL=full` instead.
39
+ 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.
40
40
 
41
41
  The accepted line is the only source of these values.
42
42
 
@@ -77,13 +77,13 @@ When a ticket requires multiple sequential Code agent phases, each Code agent ap
77
77
 
78
78
  ### Settings line
79
79
 
80
- **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 when the run has one worktree:
80
+ **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:
81
81
 
82
82
  ```bash
83
83
  node "$HOME/.devflow/scripts/resolve-settings.cjs" "{root}" 2>/dev/null; echo "exit=$?"
84
84
  ```
85
85
 
86
- 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=on CURATION=on KNOWLEDGE=off GATE_LEVEL=full` instead.
86
+ 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.
87
87
 
88
88
  The accepted line is the only source of these values.
89
89
 
@@ -30,13 +30,13 @@ $ARGUMENTS
30
30
 
31
31
  ### Phase 1: Resolve Settings
32
32
 
33
- **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 when the run has one worktree:
33
+ **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:
34
34
 
35
35
  ```bash
36
36
  node "$HOME/.devflow/scripts/resolve-settings.cjs" "{root}" 2>/dev/null; echo "exit=$?"
37
37
  ```
38
38
 
39
- 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=on CURATION=on KNOWLEDGE=off GATE_LEVEL=full` instead.
39
+ 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.
40
40
 
41
41
  The accepted line is the only source of these values.
42
42
 
@@ -144,13 +144,13 @@ node "$HOME/.devflow/scripts/verify-evidence.cjs" render --plan "{worktree}/.dev
144
144
 
145
145
  - `EVIDENCE_FILE` — `{worktree}/.devflow/docs/evidence-{branch_slug}.md`, its `## Evidence Exceptions` section now a byte copy of `PR_EXCEPTIONS` (absent when that is `(none)`).
146
146
 
147
- **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 when the run has one worktree:
147
+ **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:
148
148
 
149
149
  ```bash
150
150
  node "$HOME/.devflow/scripts/resolve-settings.cjs" "{root}" 2>/dev/null; echo "exit=$?"
151
151
  ```
152
152
 
153
- 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=on CURATION=on KNOWLEDGE=off GATE_LEVEL=full` instead.
153
+ 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.
154
154
 
155
155
  The accepted line is the only source of these values.
156
156
 
@@ -108,13 +108,13 @@ If the user says "skip" or "just proceed" — skip remaining questions, present
108
108
  **Produces:** SKIM_CONTEXT, FEATURE_KNOWLEDGE, FEATURE_KNOWLEDGE_RULES, GATE_LEVEL
109
109
  **Requires:** CONFIRMED_SCOPE
110
110
 
111
- **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 when the run has one worktree:
111
+ **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:
112
112
 
113
113
  ```bash
114
114
  node "$HOME/.devflow/scripts/resolve-settings.cjs" "{root}" 2>/dev/null; echo "exit=$?"
115
115
  ```
116
116
 
117
- 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=on CURATION=on KNOWLEDGE=off GATE_LEVEL=full` instead.
117
+ 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.
118
118
 
119
119
  The accepted line is the only source of these values.
120
120
 
@@ -72,7 +72,7 @@ For each worktree:
72
72
  2. **If `--review {timestamp}` provided:** use that specific directory (not supported in multi-worktree mode)
73
73
  3. **Otherwise:** sort directories by name descending (timestamps are naturally sortable), 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 (backwards compatible).
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}/`
@@ -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 when the run has one worktree:
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=on CURATION=on KNOWLEDGE=off GATE_LEVEL=full` instead.
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
 
@@ -254,13 +254,15 @@ Follow devflow:apply-feature-knowledge for FEATURE_KNOWLEDGE."
254
254
 
255
255
  Wait for Triage agent to complete before proceeding. Parse verdict ledger from Triage agent output:
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**:
@@ -308,19 +310,22 @@ 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}` using the Write tool. Do this now — not in Phase 9 — while results are fresh in context.
320
+ **Immediately write `resolution-summary.md`** to `{TARGET_DIR}` using the Write tool.
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
- Use the template from the Output Artifact section below.
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
 
@@ -669,10 +674,7 @@ When the Knowledge agent reports `KB_COMMIT: skipped (detached HEAD)`, the files
669
674
  ├─ Phase 8: CI Status Gate (conditional)
670
675
  ├─ Phase 9: Git agent (manage-debt) — FIX_SEPARATE + TECH_DEBT → backfill Tracked={ISSUE_REF} (or TRACEABILITY: DEGRADED on failure)
671
676
  │
672
- ├─ Phase 9b: Thread resolution + resolution comment
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
677
+ ├─ Phase 9b: 9b-0 Test agent (stale TPs), 9b-1/9b-2 Git agent (threads, resolution comment)
676
678
  │ └─ Step 9b-3: verify-evidence.cjs publish (inline, no Git spawn) — only when the head moved
677
679
  │
678
680
  ├─ Phase 9c: verify-evidence.cjs readiness (inline, no Git spawn) — non-author approval required, report-only
@@ -688,22 +690,20 @@ When the Knowledge agent reports `KB_COMMIT: skipped (detached HEAD)`, the files
688
690
  | Fix attempt fails | Revert changes, mark BLOCKED, continue others |
689
691
  | Issue dependencies | Sequential chain, skip dependents if predecessor blocked |
690
692
  | 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
693
  | `--review {timestamp}` in multi-worktree mode | Not supported — use `--path` + `--review` to target specific worktree + review |
693
694
  | gh/GitHub absent | manage-debt degrades (`TRACEABILITY: DEGRADED ({reason})`); Tracked stays `(pending — TRACEABILITY: DEGRADED ({reason}))` — recorded, not dropped |
694
695
  | `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
696
  | `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
697
  | `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 (no maintainer edits, no push access of its own) | validate-branch emits `TRACEABILITY: DEGRADED (cannot push to fork)` → `fork_no_push`: Phase 7 skips the push, Phase 8 is skipped, 9b-1 records FIXED threads as DEGRADED instead of citing unpushed commits; 9b-2 still posts the resolution comment; the head did not move, so 9b-0 and 9b-3 are skipped |
698
+ | 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
699
  | 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
700
  | 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
701
 
702
702
  ## Principles
703
703
 
704
704
  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; the CI wait, the evidence refresh and the merge-readiness check are inline scripts (plumbing, no model work)
706
- 3. **Traceability-aware** - Policy-gated ops (thread fetch/resolve, merge readiness) 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)
705
+ 2. **Git agent for git work** - All git operations go through Git agent; inline scripts are plumbing
706
+ 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
707
 
708
708
  ## Output Artifact
709
709
 
@@ -716,7 +716,7 @@ Written in Phase 5 (Collect Results) to `{TARGET_DIR}/resolution-summary.md`:
716
716
  **Date**: {RESOLUTION_TS}
717
717
  **Review**: {TARGET_DIR_REL}
718
718
  **Command**: /resolve
719
- **Gate level**: {GATE_LEVEL}
719
+ **Gate level**: {GATE_LEVEL, with any level note}
720
720
 
721
721
  ## Statistics
722
722
  | Metric | Value |
@@ -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 when the run has one worktree:
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=on CURATION=on KNOWLEDGE=off GATE_LEVEL=full` instead.
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
 
@@ -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 a single PR comment. Marker-based deduplication — only one comment per workflow run, never edited after posting (D8).
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. Resolution summary is already written to disk.
7
+ **Degradation (D4):** No PR → `TRACEABILITY: DEGRADED (no PR)`, warn, return; the summary stays on disk.
8
8
 
9
- The publication gate this operation applies is the `devflow:git` skill's `references/publication-gate.md` (D10) — the step order below instantiates it.
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 — `NOTE` prepended to body) | SKIPPED (already posted) | DEGRADED ({reason})
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 — a third party posting the marker string must not suppress devflow's comment):
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` — repo-relative; read it under `WORKTREE_PATH` (else cwd).
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
- {full content of resolution-summary.md}
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: finding titles, file:line references, Blocking/Escalations/Third-Party/Verification sections):
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 (GitHub rejects over 65536 with a 422, which the 4xx rule would silently skip); 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
+ 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 a single PR comment per review run (D7). Marker-based deduplication — if the marker for this cycle+timestamp pair already exists, skip; never edit after posting.
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`); identifies the specific review run within a cycle so a re-review in the same cycle posts its own comment while a true re-run of the same review deduplicates
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 in output, return. Summary is written to disk only.
9
+ **Degradation (D4):** No PR / `gh` unauthenticated → `TRACEABILITY: DEGRADED (no PR)`, warn, return; the summary stays on disk.
10
10
 
11
- The publication gate this operation applies is the `devflow:git` skill's `references/publication-gate.md` (D10) — the step order below instantiates it.
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 — `NOTE` prepended to body) | SKIPPED (already posted for cycle {N} ts:{REVIEW_TIMESTAMP}) | DEGRADED ({reason})
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 — a third party posting the marker string must not suppress devflow's comment):
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` — repo-relative; read it under `WORKTREE_PATH` (else cwd).
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
- {full content of review-summary.md}
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** (excluded: finding titles, file:line references, Blocking/Escalations/Third-Party/Verification sections, merge recommendation):
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}
@@ -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 append-only comment itself, and posts nothing it could not scrub.
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 inside each summary op:**
6
- 1. Dedup check (D7/D8 marker — unchanged, stays first).
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'` — compare case-insensitively. `PRIVATE` or `INTERNAL` → mode FULL. Anything else (including `PUBLIC`, empty output, command error, unauthenticated) → mode STUB. **Fail-closed rule: on any error or unrecognised value, treat as PUBLIC (mode STUB).**
10
- 4. Compose body (full content in FULL mode; stub template in STUB mode — defined per op).
11
- 5. Scrub per D11 (both modes — the stub is also scrubbed).
12
- 6. Re-check 60000-char cap **after** the scrub (redaction tokens may grow the body; truncate at a line boundary below 59,800 chars, keeping the truncation pointer sentence).
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.
@@ -1,6 +1,11 @@
1
1
  ## Operation: manage-debt
2
2
 
3
- Update tech debt backlog with deferred issues from resolution and pre-existing issues from code review.
3
+ Update tech debt backlog from `{REVIEW_DIR}/resolution-summary.md`:
4
+ - Add only entries of `## Fix Separately` (FIX_SEPARATE) and `## Deferred to Tech Debt` (TECH_DEBT). A section ends at the next heading.
5
+ - An empty section adds none.
6
+ - If `resolution-summary.md` is missing, return `TRACEABILITY: DEGRADED (resolution summary missing)` and do not update the backlog.
7
+ - Never add an item that also has an entry in `## Escalations`, `## Blocked` or `## Fixed Issues`.
8
+ - Read no review report: in `{REVIEW_DIR}`, read only `resolution-summary.md`.
4
9
 
5
10
  **Input:** `REVIEW_DIR`, `TIMESTAMP`, `WORKTREE_PATH` (optional)
6
11
 
@@ -31,7 +36,6 @@ Load when the resolved tracker provider is `github` and the operation is `manage
31
36
  3. Extract items to add:
32
37
  - `## Fix Separately` entries from `{REVIEW_DIR}/resolution-summary.md` (FIX_SEPARATE from Triage agent)
33
38
  - `## Deferred to Tech Debt` entries from `{REVIEW_DIR}/resolution-summary.md` (TECH_DEBT from Triage agent)
34
- - Pre-existing issues (Category 3) from review reports
35
39
  4. Deduplicate against existing items using semantic matching
36
40
  5. Remove items that have been fixed (verify in codebase)
37
41
  6. Compose updated issue body to `$DEVFLOW_BODY_RAW`; apply the Comment-sink scrub (D11) and post via `gh issue edit {number} --body-file "$DEVFLOW_BODY"`
@@ -1,6 +1,11 @@
1
1
  ## Operation: manage-debt
2
2
 
3
- Update tech debt backlog with deferred issues from resolution and pre-existing issues from code review.
3
+ Update tech debt backlog from `{REVIEW_DIR}/resolution-summary.md`:
4
+ - Add only entries of `## Fix Separately` (FIX_SEPARATE) and `## Deferred to Tech Debt` (TECH_DEBT). A section ends at the next heading.
5
+ - An empty section adds none.
6
+ - If `resolution-summary.md` is missing, return `TRACEABILITY: DEGRADED (resolution summary missing)` and do not update the backlog.
7
+ - Never add an item that also has an entry in `## Escalations`, `## Blocked` or `## Fixed Issues`.
8
+ - Read no review report: in `{REVIEW_DIR}`, read only `resolution-summary.md`.
4
9
 
5
10
  **Input:** `REVIEW_DIR`, `TIMESTAMP`, `WORKTREE_PATH` (optional)
6
11
 
@@ -31,7 +36,6 @@ Load when the resolved tracker provider is `jira` and the operation is `manage-d
31
36
  3. Extract items to add:
32
37
  - `## Fix Separately` entries from `{REVIEW_DIR}/resolution-summary.md` (FIX_SEPARATE from Triage agent)
33
38
  - `## Deferred to Tech Debt` entries from `{REVIEW_DIR}/resolution-summary.md` (TECH_DEBT from Triage agent)
34
- - Pre-existing issues (Category 3) from review reports
35
39
  4. Deduplicate against existing items using semantic matching.
36
40
  5. Remove items that have been fixed (verify in codebase).
37
41
  6. Compose the updated description and post it through the gate in `### Posting gate` below, using the *update description* capability.
@@ -1,6 +1,11 @@
1
1
  ## Operation: manage-debt
2
2
 
3
- Update tech debt backlog with deferred issues from resolution and pre-existing issues from code review.
3
+ Update tech debt backlog from `{REVIEW_DIR}/resolution-summary.md`:
4
+ - Add only entries of `## Fix Separately` (FIX_SEPARATE) and `## Deferred to Tech Debt` (TECH_DEBT). A section ends at the next heading.
5
+ - An empty section adds none.
6
+ - If `resolution-summary.md` is missing, return `TRACEABILITY: DEGRADED (resolution summary missing)` and do not update the backlog.
7
+ - Never add an item that also has an entry in `## Escalations`, `## Blocked` or `## Fixed Issues`.
8
+ - Read no review report: in `{REVIEW_DIR}`, read only `resolution-summary.md`.
4
9
 
5
10
  **Input:** `REVIEW_DIR`, `TIMESTAMP`, `WORKTREE_PATH` (optional)
6
11
 
@@ -31,7 +36,6 @@ Load when the resolved tracker provider is `linear` and the operation is `manage
31
36
  3. Extract items to add:
32
37
  - `## Fix Separately` entries from `{REVIEW_DIR}/resolution-summary.md` (FIX_SEPARATE from Triage agent)
33
38
  - `## Deferred to Tech Debt` entries from `{REVIEW_DIR}/resolution-summary.md` (TECH_DEBT from Triage agent)
34
- - Pre-existing issues (Category 3) from review reports
35
39
  4. Deduplicate against existing items using semantic matching.
36
40
  5. Remove items that have been fixed (verify in codebase).
37
41
  6. Compose the updated description and post it through the gate in `### Posting gate` below, using the *update description* capability.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "devflow-kit",
3
- "version": "3.8.0",
3
+ "version": "3.9.0",
4
4
  "description": "A meta-harness for Claude Code — turns a single coding agent into an engineering team: orchestration, parallel review, persistent memory, curated decisions, and graph workflows",
5
5
  "type": "module",
6
6
  "bin": {
@@ -53,9 +53,9 @@ You receive from orchestrator:
53
53
  - **BASE_BRANCH**: Branch this feature branch was created from
54
54
  - **EXECUTION_PLAN**: Synthesized plan with steps, files, tests
55
55
  - **PATTERNS**: Codebase patterns to follow
56
- - **OPERATION** (optional): `implement` (default when absent) | `issue-fix` — selects operating mode (see below); every spawn passes it as the first prompt line. Any other value returns BLOCKED, naming it, and changes nothing.
57
- - **ISSUES** (when OPERATION: issue-fix): Pre-classified issues from Triage agent with disposition FIX_NOW; do not re-litigate
58
- - **SCOPE** (when OPERATION: issue-fix): Blast-radius scope hint (Standard | Careful) per issue from Triage agent
56
+ - **OPERATION** (optional): `implement` (default when absent) | `issue-fix` — selects operating mode; every spawn passes it as the first prompt line. Any other value returns BLOCKED, naming it, and changes nothing.
57
+ - **ISSUES** (when OPERATION: issue-fix): Pre-classified issues from Triage agent with disposition FIX_NOW
58
+ - **SCOPE** (when OPERATION: issue-fix): Blast-radius scope hint (Standard | Careful | `Standard, prose only`) per issue
59
59
  - **FEATURE_KNOWLEDGE** (optional): Per KB, the Rules bullets most relevant to the task (anti-patterns, gotchas, invariants), the KB path and a heading index; sections are read on demand
60
60
 
61
61
  **Worktree Support**: If `WORKTREE_PATH` is provided, follow the `devflow:worktree-support` skill for path resolution. If omitted, use cwd.
@@ -92,7 +92,7 @@ You receive from orchestrator:
92
92
 
93
93
  When `OPERATION: issue-fix`, you are fixing pre-classified issues assigned FIX_NOW by the Triage agent. Do not re-litigate dispositions.
94
94
 
95
- **Inputs:** `ISSUES` (pre-classified FIX_NOW issues), `SCOPE` (Standard | Careful per issue; absent means Standard), `PUSH: false` (always for issue-fix; the orchestrator pushes after its final validation gate)
95
+ **Inputs:** `ISSUES` (pre-classified FIX_NOW issues), `SCOPE` (Standard | Careful | `Standard, prose only` per issue; absent means Standard), `PUSH: false` (always for issue-fix; the orchestrator pushes after its final validation gate)
96
96
 
97
97
  **Protocol:**
98
98
  1. Same-file issues → one commit (never two Code agents editing the same file concurrently)