devflow-kit 3.7.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.
- package/CHANGELOG.md +479 -1
- package/README.md +15 -15
- package/dist/agents/code.md +6 -8
- package/dist/agents/design.md +1 -1
- package/dist/agents/fix.md +7 -8
- package/dist/agents/git.md +3 -3
- package/dist/agents/harden.md +1 -1
- package/dist/agents/refactor.md +2 -4
- package/dist/agents/review.md +4 -4
- package/dist/agents/skim.md +2 -2
- package/dist/agents/triage.md +9 -2
- package/dist/cli/commands/capture.js +1 -1
- package/dist/cli/commands/curation-move-io.js +102 -0
- package/dist/cli/commands/curation-move-step.js +374 -0
- package/dist/cli/commands/curation.js +808 -0
- package/dist/cli/commands/gate-level-prompts.js +428 -0
- package/dist/cli/commands/gates.js +35 -11
- package/dist/cli/commands/init-seed.js +11 -8
- package/dist/cli/commands/init.js +244 -57
- package/dist/cli/commands/memory.js +60 -13
- package/dist/cli/commands/prompt-io.js +37 -0
- package/dist/cli/commands/uninstall.js +157 -17
- package/dist/cli.js +2 -2
- package/dist/commands/bug-analysis.md +25 -36
- package/dist/commands/code-review.md +40 -44
- package/dist/commands/debug.md +5 -5
- package/dist/commands/dynamic-build.md +26 -25
- package/dist/commands/dynamic-plan.md +5 -5
- package/dist/commands/dynamic-profile.md +5 -5
- package/dist/commands/dynamic-tickets.md +5 -5
- package/dist/commands/explore.md +6 -6
- package/dist/commands/implement.md +53 -82
- package/dist/commands/plan.md +6 -6
- package/dist/commands/release.md +5 -5
- package/dist/commands/research.md +6 -6
- package/dist/commands/resolve.md +39 -41
- package/dist/commands/self-review.md +5 -13
- package/dist/core/area-pause-notice.js +44 -0
- package/dist/core/assets.js +20 -20
- package/dist/core/curate-tuning-config.js +5 -6
- package/dist/core/curation-move-notice.js +84 -0
- package/dist/core/curation-move-skip.js +35 -0
- package/dist/core/curation-move.js +35 -0
- package/dist/core/curation-queue-cleanup.js +135 -0
- package/dist/core/curation-store.js +99 -0
- package/dist/core/{learning-variants.js → curation-variants.js} +65 -41
- package/dist/core/echo-value.js +11 -5
- package/dist/core/evidence-policy.js +11 -9
- package/dist/core/feature-switch.js +95 -19
- package/dist/core/fs-atomic.js +1 -1
- package/dist/core/gate-level.js +10 -2
- package/dist/core/git.js +16 -14
- package/dist/core/ledger-root.js +82 -22
- package/dist/core/linked-path.js +4 -4
- package/dist/core/manifest-lock.js +238 -0
- package/dist/core/manifest.js +58 -14
- package/dist/core/migrations.js +1 -13
- package/dist/core/observations.js +2 -2
- package/dist/core/plugins.js +19 -19
- package/dist/core/pool.js +26 -0
- package/dist/core/project-paths.js +103 -34
- package/dist/core/queue-drain.js +2 -2
- package/dist/core/tracked-areas.js +159 -0
- package/dist/core/tracker.js +1 -1
- package/dist/{learning-off → curation-off}/agents/code.md +6 -8
- package/dist/{learning-off → curation-off}/agents/fix.md +7 -8
- package/dist/{learning-off → curation-off}/agents/refactor.md +2 -4
- package/dist/{learning-off → curation-off}/agents/review.md +3 -3
- package/dist/{learning-off → curation-off}/agents/triage.md +8 -1
- package/dist/{learning-off → curation-off}/commands/bug-analysis.md +20 -31
- package/dist/{learning-off → curation-off}/commands/code-review.md +37 -41
- package/dist/{learning-off → curation-off}/commands/debug.md +2 -2
- package/dist/{learning-off → curation-off}/commands/dynamic-build.md +23 -22
- package/dist/{learning-off → curation-off}/commands/explore.md +2 -2
- package/dist/{learning-off → curation-off}/commands/implement.md +50 -79
- package/dist/{learning-off → curation-off}/commands/plan.md +2 -2
- package/dist/{learning-off → curation-off}/commands/resolve.md +36 -38
- package/dist/{learning-off → curation-off}/commands/self-review.md +2 -10
- package/dist/hud/components/{learning-counts.js → curation-counts.js} +63 -17
- package/dist/hud/config.js +1 -1
- package/dist/hud/index.js +6 -6
- package/dist/hud/render.js +3 -3
- 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/update-pr-evidence.md +2 -2
- package/dist/skills/git/references/pr/validate-branch.md +8 -5
- package/dist/skills/git/references/publication-gate.md +6 -7
- package/dist/skills/git/references/tracker/github/ensure-pr-ready.md +13 -5
- package/dist/skills/git/references/tracker/github/manage-debt.md +6 -2
- package/dist/skills/git/references/tracker/jira/ensure-pr-ready.md +13 -5
- package/dist/skills/git/references/tracker/jira/manage-debt.md +6 -2
- package/dist/skills/git/references/tracker/linear/ensure-pr-ready.md +13 -5
- package/dist/skills/git/references/tracker/linear/manage-debt.md +6 -2
- package/dist/targets/claude-code/{learning-install.js → curation-install.js} +85 -65
- package/dist/targets/claude-code/installer.js +15 -15
- package/dist/targets/claude-code/language-stamp.js +5 -5
- package/dist/targets/claude-code/post-install.js +2 -2
- package/dist/targets/claude-code/tracker-servers.js +1 -1
- package/package.json +3 -2
- package/src/assets/agents/_partials/_code.mds +11 -11
- package/src/assets/agents/code.mds +6 -6
- package/src/assets/agents/curate.md +8 -8
- package/src/assets/agents/debug.mds +6 -6
- package/src/assets/agents/design.mds +18 -18
- package/src/assets/agents/evaluate.md +6 -12
- package/src/assets/agents/fix.mds +7 -6
- package/src/assets/agents/git.mds +3 -3
- package/src/assets/agents/harden.mds +7 -7
- package/src/assets/agents/knowledge.mds +23 -23
- package/src/assets/agents/refactor.mds +2 -2
- package/src/assets/agents/research.mds +15 -15
- package/src/assets/agents/review.mds +43 -43
- package/src/assets/agents/skim.mds +11 -11
- package/src/assets/agents/triage.mds +29 -22
- package/src/assets/agents/validate.md +30 -50
- package/src/assets/commands/_partials/_decisions.mds +22 -20
- package/src/assets/commands/_partials/_engine.mds +8 -8
- package/src/assets/commands/_partials/_knowledge.mds +29 -15
- package/src/assets/commands/_partials/_preamble.mds +4 -4
- package/src/assets/commands/_partials/_settings.mds +3 -3
- package/src/assets/commands/_partials/_wave.mds +7 -7
- package/src/assets/commands/bug-analysis.mds +37 -48
- package/src/assets/commands/code-review.mds +53 -57
- package/src/assets/commands/debug.mds +14 -14
- package/src/assets/commands/dynamic-build.mds +38 -37
- package/src/assets/commands/dynamic-plan.mds +22 -22
- package/src/assets/commands/dynamic-profile.mds +2 -2
- package/src/assets/commands/dynamic-tickets.mds +8 -8
- package/src/assets/commands/explore.mds +20 -20
- package/src/assets/commands/implement.mds +77 -98
- package/src/assets/commands/plan.mds +27 -27
- package/src/assets/commands/release.mds +12 -12
- package/src/assets/commands/research.mds +19 -19
- package/src/assets/commands/resolve.mds +66 -60
- package/src/assets/commands/self-review.mds +20 -20
- package/src/assets/mds/git/_ops.mds +9 -2
- package/src/assets/mds/git/_ops_pr.mds +21 -11
- package/src/assets/mds/git/_ops_steps.mds +20 -4
- package/src/assets/mds/git/_pr.mds +21 -18
- package/src/assets/mds/git/_references.mds +6 -7
- package/src/assets/mds/tracker/_github.mds +1 -4
- package/src/assets/mds/tracker/_jira.mds +1 -4
- package/src/assets/mds/tracker/_linear.mds +1 -4
- package/src/assets/rules/quality.md +1 -0
- package/src/assets/scripts/ci-wait.cjs +389 -92
- package/src/assets/scripts/hooks/background-memory-update +81 -3
- package/src/assets/scripts/hooks/capture-prompt +12 -12
- package/src/assets/scripts/hooks/capture-question +11 -11
- package/src/assets/scripts/hooks/capture-turn +12 -12
- package/src/assets/scripts/hooks/{learning-lock → curation-lock} +2 -2
- package/src/assets/scripts/hooks/curation-move +293 -0
- package/src/assets/scripts/hooks/ensure-devflow-init +45 -13
- package/src/assets/scripts/hooks/ensure-proxy +4 -4
- package/src/assets/scripts/hooks/ensure-root-gitignore +4 -4
- package/src/assets/scripts/hooks/git-marker +81 -0
- package/src/assets/scripts/hooks/json-helper.cjs +176 -51
- package/src/assets/scripts/hooks/json-parse +1 -1
- package/src/assets/scripts/hooks/lib/curation-move.cjs +1582 -0
- package/src/assets/scripts/hooks/lib/{learning-store.cjs → curation-store.cjs} +308 -122
- package/src/assets/scripts/hooks/lib/decisions-format.cjs +3 -3
- package/src/assets/scripts/hooks/lib/mkdir-lock.cjs +24 -7
- package/src/assets/scripts/hooks/lib/project-paths.cjs +132 -39
- package/src/assets/scripts/hooks/lib/render-decisions.cjs +42 -22
- package/src/assets/scripts/hooks/lib/tracked-areas.cjs +452 -0
- package/src/assets/scripts/hooks/memory-permission +10 -2
- package/src/assets/scripts/hooks/memory-worker +12 -1
- package/src/assets/scripts/hooks/pre-compact-memory +17 -16
- package/src/assets/scripts/hooks/queue-append +444 -102
- package/src/assets/scripts/hooks/resolve-project-root +2 -2
- package/src/assets/scripts/hooks/session-start-context +198 -72
- package/src/assets/scripts/hooks/session-start-memory +42 -43
- package/src/assets/scripts/lib/project-config.cjs +12 -5
- package/src/assets/scripts/pr-evidence.cjs +5 -2
- package/src/assets/scripts/resolve-base.cjs +1043 -0
- package/src/assets/scripts/resolve-settings.cjs +283 -45
- package/src/assets/scripts/verify-evidence.cjs +307 -75
- package/src/assets/skills/agent-references/SKILL.md +11 -2
- package/src/assets/skills/agent-references/references/commands/implement-levels.md +29 -0
- package/src/assets/skills/agent-references/references/commands/implement-revalidate.md +6 -4
- package/src/assets/skills/agent-references/references/commands/resolve-levels.md +25 -0
- 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/apply-decisions/SKILL.md +1 -1
- package/src/assets/skills/docs-framework/SKILL.md +7 -7
- package/src/assets/skills/docs-framework/references/patterns.md +3 -4
- package/src/assets/skills/quality-gates/SKILL.md +1 -1
- package/src/assets/skills/worktree-support/references/roots.md +2 -2
- package/templates/lint-pack/.lint-pack.conf +86 -0
- package/templates/lint-pack/README.md +190 -0
- package/templates/lint-pack/lint-pack.sh +905 -0
- package/dist/cli/commands/learning.js +0 -554
- package/dist/core/learning-queue-cleanup.js +0 -27
- package/dist/core/learning-store.js +0 -61
- /package/dist/{learning-off → curation-off}/agents/debug.md +0 -0
- /package/dist/{learning-off → curation-off}/agents/design.md +0 -0
- /package/dist/{learning-off → curation-off}/agents/harden.md +0 -0
- /package/dist/{learning-off → curation-off}/agents/knowledge.md +0 -0
- /package/dist/{learning-off → curation-off}/agents/research.md +0 -0
- /package/dist/{learning-off → curation-off}/agents/skim.md +0 -0
- /package/dist/{learning-off → curation-off}/commands/dynamic-plan.md +0 -0
- /package/dist/{learning-off → curation-off}/commands/dynamic-profile.md +0 -0
- /package/dist/{learning-off → curation-off}/commands/dynamic-tickets.md +0 -0
- /package/dist/{learning-off → curation-off}/commands/release.md +0 -0
- /package/dist/{learning-off → curation-off}/commands/research.md +0 -0
package/dist/commands/resolve.md
CHANGED
|
@@ -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
|
|
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}/`
|
|
@@ -86,21 +86,21 @@ Set `TARGET_DIR` to the selected review or bug-analysis directory path, and `TAR
|
|
|
86
86
|
|
|
87
87
|
#### Step 0d: Load Project Decisions
|
|
88
88
|
|
|
89
|
-
**Produces:** DECISIONS_CONTEXT, FEATURE_KNOWLEDGE, FEATURE_KNOWLEDGE_RULES, EVIDENCE_POLICY, ISSUE_REQUIRED, APPLY_CONVENTIONS, REQUIRE_NON_AUTHOR_APPROVAL, REVIEW_PUBLICATION, RESOLUTION_TS
|
|
89
|
+
**Produces:** DECISIONS_CONTEXT, 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>
|
|
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
|
|
|
101
101
|
### Load DECISIONS_CONTEXT
|
|
102
102
|
|
|
103
|
-
When the settings line says `
|
|
103
|
+
When the settings line says `CURATION=off`, set `DECISIONS_CONTEXT` to `(none)` and skip this step, locating no ledger and reading no index.
|
|
104
104
|
|
|
105
105
|
The decisions ledger belongs to the repository, not to one checkout: a linked worktree reads the main worktree's copy, a subdirectory session the repository root's. Locate it with ONE git call, run from the start directory — `WORKTREE_PATH` if provided, otherwise cwd (`devflow:worktree-support`):
|
|
106
106
|
|
|
@@ -114,11 +114,11 @@ Line 1 is the checkout's toplevel, line 2 the common git directory. A git older
|
|
|
114
114
|
2. **The toplevel** — line 1, or on an older git the line after the echoed flag.
|
|
115
115
|
3. **The start directory itself** — when the command failed or printed no absolute toplevel (outside a git repository).
|
|
116
116
|
|
|
117
|
-
This is the rule the
|
|
117
|
+
This is the rule the curation hooks apply, so you read the index the Curate agent writes.
|
|
118
118
|
|
|
119
119
|
**Step 1 — Read the pre-rendered index:**
|
|
120
120
|
|
|
121
|
-
Attempt to read `{ledger}/.devflow/
|
|
121
|
+
Attempt to read `{ledger}/.devflow/curation/index.md`.
|
|
122
122
|
|
|
123
123
|
- If the file exists and contains non-empty content: use that content as `DECISIONS_CONTEXT`.
|
|
124
124
|
- If the file is absent or empty: set `DECISIONS_CONTEXT` to `(none)`.
|
|
@@ -216,6 +216,12 @@ Resolve this per worktree — unlike the evidence policy above, the settings lin
|
|
|
216
216
|
|
|
217
217
|
Set it per worktree, from that worktree's lens, and pass that worktree's `COMPLIANCE_DIRECTIVE` to each of its Code and Fix spawns, on a line of its own.
|
|
218
218
|
|
|
219
|
+
**Gate level.** Each worktree keeps its own `GATE_LEVEL`. When any is `standard` or `lean`, once per run, run `d="${CLAUDE_CONFIG_DIR:-}"; case "$d" in /*) ;; *) d="$HOME/.claude" ;; esac; printf '%s\n' "$d"` in Bash and Read `<that directory>/skills/devflow:agent-references/references/commands/resolve-levels.md` with the Read tool, and apply each row to the phase it names, as the reference says.
|
|
220
|
+
|
|
221
|
+
- No row or rule overrides the next two lines.
|
|
222
|
+
- If the Read fails, or the file has no `## Phases` heading with the `| Phase | standard | lean |` header, or a row breaks its grammar, apply no row in any worktree, keep every `GATE_LEVEL` and say `level reference unreadable: no level rows applied`.
|
|
223
|
+
- No level changes the Triage security gate or the ESCALATED route. The Verification Gate, the CI gate and the compliance directive run at every level.
|
|
224
|
+
|
|
219
225
|
**Mint `RESOLUTION_TS` once per run:** `date -u +%Y-%m-%dT%H:%M:%SZ`. Every worktree reuses it — the resolution comment's dedup marker is searched per PR, so one run key keeps a retry of this run deduplicated while the next /resolve on the same PR posts. Phase 5 writes it as the summary's `**Date**:` and Phase 9b-2 passes it, so the local file and the posted marker agree.
|
|
220
226
|
|
|
221
227
|
### Phase 1: Parse Issues
|
|
@@ -287,13 +293,15 @@ Follow devflow:apply-feature-knowledge for FEATURE_KNOWLEDGE."
|
|
|
287
293
|
|
|
288
294
|
Wait for Triage agent to complete before proceeding. Parse verdict ledger from Triage agent output:
|
|
289
295
|
- **ESCALATED**: Security issues requiring human escalation
|
|
290
|
-
- **FIX_NOW**: Valid issues assigned to Code agents (with risk tier: Standard | Careful)
|
|
296
|
+
- **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.
|
|
291
297
|
- **FALSE_POSITIVE**: Issues the Review agent got wrong (with cited evidence)
|
|
292
298
|
- **BY_DESIGN**: Intentional code (with a recorded decision, stated in words, or a code doc citation)
|
|
293
299
|
- **FIX_SEPARATE**: Valid but out of blast-radius scope (must become manage-debt ticket)
|
|
294
300
|
- **TECH_DEBT**: Architectural overhaul only — LAST RESORT
|
|
295
301
|
- **DUPLICATE**: Collapsed duplicate issue — carries `duplicate_of: <primary-id>` referencing the non-DUPLICATE primary; inherits the primary's outcome
|
|
296
302
|
|
|
303
|
+
A ledger `### Summary` line `- Tiers: not applied (…)` is the level note.
|
|
304
|
+
|
|
297
305
|
Collect every decision and pitfall the Triage agent's Reasoning columns state, in its words — the resolution summary is posted, so it never carries an ADR/PF ID.
|
|
298
306
|
|
|
299
307
|
**Triage agent completeness assertion:** Verify the parsed ledger against ISSUES before proceeding:
|
|
@@ -309,10 +317,10 @@ Collect every decision and pitfall the Triage agent's Reasoning columns state, i
|
|
|
309
317
|
**Produces:** BATCHES
|
|
310
318
|
**Requires:** TRIAGE_RESULTS
|
|
311
319
|
|
|
312
|
-
If FIX_NOW list is empty: skip to Phase 5
|
|
320
|
+
If FIX_NOW list is empty: skip to Phase 5, then run Phases 9, 9b, 9c and 10.
|
|
313
321
|
|
|
314
322
|
Otherwise, batch FIX_NOW issues for Code agent execution. **DUPLICATE issues are never dispatched** — they inherit the primary's outcome:
|
|
315
|
-
- **Same-file issues** → one batch (one Code agent per file
|
|
323
|
+
- **Same-file issues** → one batch (one Code agent per file)
|
|
316
324
|
- **Distinct-file issues** → parallel Code agents
|
|
317
325
|
- **Max 5 issues per batch** — chunk large sets
|
|
318
326
|
|
|
@@ -344,24 +352,27 @@ Spawn distinct-file batch Code agents **in a single message** (parallel). Sequen
|
|
|
344
352
|
Collect from each Code agent:
|
|
345
353
|
- `{status, commitShas, unresolved}` per batch
|
|
346
354
|
- `## Verification` block (commands run + results)
|
|
355
|
+
- 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
|
|
347
356
|
|
|
348
357
|
### Phase 5: Write resolution-summary.md
|
|
349
358
|
|
|
350
359
|
**Produces:** RESOLUTION_FILE (early write for compaction safety)
|
|
351
|
-
**Requires:** TRIAGE_RESULTS, CODE_AGENT_RESULTS, TARGET_DIR, TARGET_DIR_REL, BRANCH_INFO, RESOLUTION_TS
|
|
360
|
+
**Requires:** TRIAGE_RESULTS, CODE_AGENT_RESULTS, TARGET_DIR, TARGET_DIR_REL, BRANCH_INFO, RESOLUTION_TS, GATE_LEVEL
|
|
352
361
|
|
|
353
|
-
**Immediately write `resolution-summary.md`** to `{TARGET_DIR}` using the Write tool.
|
|
362
|
+
**Immediately write `resolution-summary.md`** to `{TARGET_DIR}` using the Write tool.
|
|
354
363
|
|
|
355
364
|
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).
|
|
356
365
|
|
|
357
366
|
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.
|
|
358
367
|
|
|
359
|
-
|
|
368
|
+
Open each Issue cell with its severity in brackets when it has one, as `[HIGH]`.
|
|
369
|
+
|
|
370
|
+
Use the template from the Output Artifact section below. Put text not for public posting in a final `## Private notes` section.
|
|
360
371
|
|
|
361
372
|
### Phase 6: Polish
|
|
362
373
|
|
|
363
374
|
**Produces:** POLISH_RESULT
|
|
364
|
-
**Requires:** CODE_AGENT_RESULTS
|
|
375
|
+
**Requires:** CODE_AGENT_RESULTS, GATE_LEVEL
|
|
365
376
|
|
|
366
377
|
If any fixes were made, spawn Polish agent to refine the changed code:
|
|
367
378
|
|
|
@@ -423,7 +434,7 @@ git -C {worktree} push
|
|
|
423
434
|
|
|
424
435
|
**If `fork_no_push` is set:** do not push. Record `Push: skipped — cannot push to fork` under `## Verification`, and skip Phase 8 — no pushed commit exists for CI to check.
|
|
425
436
|
|
|
426
|
-
**Route after push:** VERIFICATION_STATUS = PASS → continue to Phase 8 (CI gate).
|
|
437
|
+
**Route after push:** VERIFICATION_STATUS = PASS → continue to Phase 8 (CI gate). FAILED or SKIPPED → skip Phase 8 and continue with Phase 9 and the later phases in order.
|
|
427
438
|
|
|
428
439
|
### Phase 8: CI Status Gate (Conditional)
|
|
429
440
|
|
|
@@ -593,7 +604,7 @@ If the script prints a `TRACEABILITY: DEGRADED` line: warn, proceed to Phase 10.
|
|
|
593
604
|
|
|
594
605
|
### Phase 10: Report
|
|
595
606
|
|
|
596
|
-
**Requires:** BRANCH_INFO, TARGET_DIR, PR_COMMENT, THREAD_RESOLUTION_RESULT
|
|
607
|
+
**Requires:** BRANCH_INFO, TARGET_DIR, PR_COMMENT, THREAD_RESOLUTION_RESULT, GATE_LEVEL
|
|
597
608
|
|
|
598
609
|
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:
|
|
599
610
|
|
|
@@ -603,6 +614,7 @@ The resolution summary was already written to `{TARGET_DIR}/resolution-summary.m
|
|
|
603
614
|
**Branch**: {branch}
|
|
604
615
|
**Reviews Processed**: {n} reports from {TARGET_DIR}
|
|
605
616
|
**Total Issues**: {n}
|
|
617
|
+
**Gate level**: {GATE_LEVEL, with any level note}
|
|
606
618
|
|
|
607
619
|
### Results
|
|
608
620
|
| Outcome | Count |
|
|
@@ -648,14 +660,6 @@ In multi-worktree mode, report results per worktree with aggregate summary.
|
|
|
648
660
|
|
|
649
661
|
### Feature Knowledge Write-Back (Conditional)
|
|
650
662
|
|
|
651
|
-
Resolve `{worktree}` as the checkout's toplevel, because feature knowledge bases are committed with the branch (D-PROMPT-ROOT): from the start directory — `WORKTREE_PATH` if provided, otherwise cwd (`devflow:worktree-support`) — run
|
|
652
|
-
|
|
653
|
-
```bash
|
|
654
|
-
git -C "{start}" rev-parse --show-toplevel
|
|
655
|
-
```
|
|
656
|
-
|
|
657
|
-
and use its one-line output. If the command fails (outside a git repository), `{worktree}` is the start directory itself. All paths below are relative to `{worktree}`.
|
|
658
|
-
|
|
659
663
|
**Step 1 — Check the opt-out gate, with `{root}` = `{worktree}`:** take the settings line resolved above for that root, resolving it with the settings block when this run has not yet.
|
|
660
664
|
|
|
661
665
|
If the settings line says `KNOWLEDGE=off`, skip write-back entirely. The machine switch (`devflow knowledge --disable`), the repository and the personal settings can each turn knowledge off, and none can turn it back on (D-FEATURES-NARROW-ONLY). The fail-closed line says `KNOWLEDGE=off` too, so an unresolvable line skips write-back.
|
|
@@ -703,21 +707,18 @@ When the Knowledge agent reports `KB_COMMIT: skipped (detached HEAD)`, the files
|
|
|
703
707
|
/resolve (orchestrator - spawns agents only)
|
|
704
708
|
│
|
|
705
709
|
├─ Phase 0: Worktree Discovery & Pre-flight
|
|
706
|
-
├─ Phase 1: Parse issues from TARGET_DIR
|
|
710
|
+
├─ Phase 1: Parse issues from TARGET_DIR
|
|
707
711
|
├─ Phase 1b: Fetch external threads (evidence policy required)
|
|
708
712
|
├─ Phase 2: Global Triage [Triage agent, opus, single agent]
|
|
709
|
-
├─ Phase 3: Batch FIX_NOW issues
|
|
710
|
-
├─ Phase 4: Fix [Code agent × N
|
|
713
|
+
├─ Phase 3: Batch FIX_NOW issues
|
|
714
|
+
├─ Phase 4: Fix [Code agent × N]
|
|
711
715
|
├─ Phase 5: Write resolution-summary.md (compaction safety; Tracked = "(pending)" or "(pending — TRACEABILITY: DEGRADED)" if manage-debt degrades)
|
|
712
|
-
├─ Phase 6: Polish
|
|
716
|
+
├─ Phase 6: Polish
|
|
713
717
|
├─ Phase 7: Verification Gate [Validate agent, haiku] + push + Fix agent validation-fix loop ≤2
|
|
714
|
-
├─ Phase 8: CI Status Gate (conditional
|
|
718
|
+
├─ Phase 8: CI Status Gate (conditional)
|
|
715
719
|
├─ Phase 9: Git agent (manage-debt) — FIX_SEPARATE + TECH_DEBT → backfill Tracked={ISSUE_REF} (or TRACEABILITY: DEGRADED on failure)
|
|
716
720
|
│
|
|
717
|
-
├─ Phase 9b:
|
|
718
|
-
│ ├─ Step 9b-0: verify-evidence.cjs --stale-out → ≤1 Test agent on the stale TPs (wrapped) — only after this run's push
|
|
719
|
-
│ ├─ Step 9b-1: Git agent (resolve-review-threads) — evidence policy required
|
|
720
|
-
│ ├─ Step 9b-2: Git agent (post-resolution-summary, REVIEW_PUBLICATION) — always-on
|
|
721
|
+
├─ Phase 9b: 9b-0 Test agent (stale TPs), 9b-1/9b-2 Git agent (threads, resolution comment)
|
|
721
722
|
│ └─ Step 9b-3: verify-evidence.cjs publish (inline, no Git spawn) — only when the head moved
|
|
722
723
|
│
|
|
723
724
|
├─ Phase 9c: verify-evidence.cjs readiness (inline, no Git spawn) — non-author approval required, report-only
|
|
@@ -730,27 +731,23 @@ When the Knowledge agent reports `KB_COMMIT: skipped (detached HEAD)`, the files
|
|
|
730
731
|
| Case | Handling |
|
|
731
732
|
|------|----------|
|
|
732
733
|
| No reviews exist | Check bug-analysis fallback (Step 0c-5b); if also absent, error and suggest `/code-review` or `/bug-analysis` |
|
|
733
|
-
| All false positives | Normal completion, report shows 0 fixes |
|
|
734
734
|
| Fix attempt fails | Revert changes, mark BLOCKED, continue others |
|
|
735
735
|
| Issue dependencies | Sequential chain, skip dependents if predecessor blocked |
|
|
736
|
-
| No
|
|
737
|
-
| Latest review already resolved | Check bug-analysis fallback (Step 0c-5b); if also absent, skip worktree and suggest `/code-review` or `/bug-analysis` |
|
|
736
|
+
| No issues parsed | Report "No issues to resolve" |
|
|
738
737
|
| `--review {timestamp}` in multi-worktree mode | Not supported — use `--path` + `--review` to target specific worktree + review |
|
|
739
738
|
| gh/GitHub absent | manage-debt degrades (`TRACEABILITY: DEGRADED ({reason})`); Tracked stays `(pending — TRACEABILITY: DEGRADED ({reason}))` — recorded, not dropped |
|
|
740
739
|
| `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 |
|
|
741
740
|
| `REQUIRE_NON_AUTHOR_APPROVAL` is `false` | Phase 9c is skipped and reported as SKIPPED |
|
|
742
|
-
| Public repo (`auto` mode) | Git agent probes visibility, posts counts-only STUB comment; full resolution report stays local |
|
|
743
741
|
| `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 |
|
|
744
|
-
| Fork PR this run cannot push to
|
|
742
|
+
| 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 |
|
|
745
743
|
| 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` |
|
|
746
744
|
| 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 |
|
|
747
745
|
|
|
748
746
|
## Principles
|
|
749
747
|
|
|
750
748
|
1. **Orchestration only** - Command spawns agents, doesn't do git/resolve work itself
|
|
751
|
-
2. **
|
|
752
|
-
3. **
|
|
753
|
-
4. **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)
|
|
749
|
+
2. **Git agent for git work** - All git operations go through Git agent; inline scripts are plumbing
|
|
750
|
+
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)
|
|
754
751
|
|
|
755
752
|
## Output Artifact
|
|
756
753
|
|
|
@@ -763,6 +760,7 @@ Written in Phase 5 (Collect Results) to `{TARGET_DIR}/resolution-summary.md`:
|
|
|
763
760
|
**Date**: {RESOLUTION_TS}
|
|
764
761
|
**Review**: {TARGET_DIR_REL}
|
|
765
762
|
**Command**: /resolve
|
|
763
|
+
**Gate level**: {GATE_LEVEL, with any level note}
|
|
766
764
|
|
|
767
765
|
## Decisions Citations
|
|
768
766
|
|
|
@@ -24,19 +24,19 @@ 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>
|
|
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
|
|
|
37
37
|
### Load DECISIONS_CONTEXT
|
|
38
38
|
|
|
39
|
-
When the settings line says `
|
|
39
|
+
When the settings line says `CURATION=off`, set `DECISIONS_CONTEXT` to `(none)` and skip this step, locating no ledger and reading no index.
|
|
40
40
|
|
|
41
41
|
The decisions ledger belongs to the repository, not to one checkout: a linked worktree reads the main worktree's copy, a subdirectory session the repository root's. Locate it with ONE git call, run from the start directory — `WORKTREE_PATH` if provided, otherwise cwd (`devflow:worktree-support`):
|
|
42
42
|
|
|
@@ -50,11 +50,11 @@ Line 1 is the checkout's toplevel, line 2 the common git directory. A git older
|
|
|
50
50
|
2. **The toplevel** — line 1, or on an older git the line after the echoed flag.
|
|
51
51
|
3. **The start directory itself** — when the command failed or printed no absolute toplevel (outside a git repository).
|
|
52
52
|
|
|
53
|
-
This is the rule the
|
|
53
|
+
This is the rule the curation hooks apply, so you read the index the Curate agent writes.
|
|
54
54
|
|
|
55
55
|
**Step 1 — Read the pre-rendered index:**
|
|
56
56
|
|
|
57
|
-
Attempt to read `{ledger}/.devflow/
|
|
57
|
+
Attempt to read `{ledger}/.devflow/curation/index.md`.
|
|
58
58
|
|
|
59
59
|
- If the file exists and contains non-empty content: use that content as `DECISIONS_CONTEXT`.
|
|
60
60
|
- If the file is absent or empty: set `DECISIONS_CONTEXT` to `(none)`.
|
|
@@ -214,14 +214,6 @@ Display summary:
|
|
|
214
214
|
|
|
215
215
|
### Feature Knowledge Write-Back (Conditional)
|
|
216
216
|
|
|
217
|
-
Resolve `{worktree}` as the checkout's toplevel, because feature knowledge bases are committed with the branch (D-PROMPT-ROOT): from the start directory — `WORKTREE_PATH` if provided, otherwise cwd (`devflow:worktree-support`) — run
|
|
218
|
-
|
|
219
|
-
```bash
|
|
220
|
-
git -C "{start}" rev-parse --show-toplevel
|
|
221
|
-
```
|
|
222
|
-
|
|
223
|
-
and use its one-line output. If the command fails (outside a git repository), `{worktree}` is the start directory itself. All paths below are relative to `{worktree}`.
|
|
224
|
-
|
|
225
217
|
**Step 1 — Check the opt-out gate, with `{root}` = `{worktree}`:** take the settings line resolved above for that root, resolving it with the settings block when this run has not yet.
|
|
226
218
|
|
|
227
219
|
If the settings line says `KNOWLEDGE=off`, skip write-back entirely. The machine switch (`devflow knowledge --disable`), the repository and the personal settings can each turn knowledge off, and none can turn it back on (D-FEATURES-NARROW-ONLY). The fail-closed line says `KNOWLEDGE=off` too, so an unresolvable line skips write-back.
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file area-pause-notice.ts
|
|
3
|
+
*
|
|
4
|
+
* The fixed notice of a paused area. When git tracks files in the folders of an area, or
|
|
5
|
+
* a `.git` entry stands and git did not answer, the area's feature reads and writes
|
|
6
|
+
* nothing there, and says so once at session start. The curation area covers the curation
|
|
7
|
+
* folder, the old ledger folder and the backup folders with one notice; the memory
|
|
8
|
+
* area covers the memory folder. Pure: no fs, no os, no process state.
|
|
9
|
+
*
|
|
10
|
+
* The words hold nothing from the repository: the area is a fixed enum, and no path,
|
|
11
|
+
* count or git output goes into them. The session start hook
|
|
12
|
+
* (src/assets/scripts/hooks/session-start-context) holds the curation words, and the
|
|
13
|
+
* memory session start hook (src/assets/scripts/hooks/session-start-memory) holds the
|
|
14
|
+
* memory words; tests/shell-hooks.test.ts requires each copy to agree with this module.
|
|
15
|
+
* The two commands a notice tells the user to run are listed in NOTICE_COMMAND_PHRASES in
|
|
16
|
+
* tests/guards/no-fsmonitor-index-read.test.ts, which holds every copy to them.
|
|
17
|
+
*/
|
|
18
|
+
const UNTRACK_STEPS = 'To find the files, run `git ls-files .devflow`. '
|
|
19
|
+
+ 'Untrack them with `git rm --cached <file>`, then delete them if you did not make them. ';
|
|
20
|
+
const RETRY_STEPS = 'The check runs again at the next session start. ';
|
|
21
|
+
/** The notice of each paused area and reason, as one paragraph of short sentences. */
|
|
22
|
+
export const AREA_PAUSE_NOTICE = {
|
|
23
|
+
curation: {
|
|
24
|
+
tracked: 'Devflow curation is paused for this project, because git tracks files in a curation data folder. '
|
|
25
|
+
+ 'Devflow reads and writes nothing in these folders while git tracks files there. '
|
|
26
|
+
+ UNTRACK_STEPS
|
|
27
|
+
+ 'Run these commands in the main checkout.',
|
|
28
|
+
unknown: 'Devflow curation is paused for this project, because git did not answer whether it tracks files in a curation data folder. '
|
|
29
|
+
+ 'Devflow reads and writes nothing in these folders until git answers. '
|
|
30
|
+
+ RETRY_STEPS
|
|
31
|
+
+ 'If this notice stays, check that git runs in this project.',
|
|
32
|
+
},
|
|
33
|
+
memory: {
|
|
34
|
+
tracked: 'Devflow memory is paused for this checkout, because git tracks files in the memory folder. '
|
|
35
|
+
+ 'Devflow reads and writes nothing there while git tracks files there. '
|
|
36
|
+
+ UNTRACK_STEPS
|
|
37
|
+
+ 'Run these commands in this checkout.',
|
|
38
|
+
unknown: 'Devflow memory is paused for this checkout, because git did not answer whether it tracks files in the memory folder. '
|
|
39
|
+
+ 'Devflow reads and writes nothing there until git answers. '
|
|
40
|
+
+ RETRY_STEPS
|
|
41
|
+
+ 'If this notice stays, check that git runs in this checkout.',
|
|
42
|
+
},
|
|
43
|
+
};
|
|
44
|
+
//# sourceMappingURL=area-pause-notice.js.map
|
package/dist/core/assets.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { join } from 'path';
|
|
2
2
|
import { getPackageRoot } from './paths.js';
|
|
3
3
|
import { SKILL_REFS_OUTPUT_DIR } from './mds-variants.js';
|
|
4
|
-
import {
|
|
4
|
+
import { CURATION_OFF_OUTPUT_DIR } from './curation-variants.js';
|
|
5
5
|
/**
|
|
6
6
|
* Flat skills source directory: src/assets/skills/{name}/
|
|
7
7
|
* All plugins' skills live here directly (no per-plugin subdirectory).
|
|
8
8
|
*
|
|
9
9
|
* @param root - Package root to resolve against. Injectable so a caller working
|
|
10
|
-
* on a temp tree (the
|
|
10
|
+
* on a temp tree (the curation converge) reads the skill source from the same
|
|
11
11
|
* root as the rest of its sources.
|
|
12
12
|
*/
|
|
13
13
|
export function skillsDir(root = getPackageRoot()) {
|
|
@@ -41,42 +41,42 @@ export function scriptsDir() {
|
|
|
41
41
|
/**
|
|
42
42
|
* Compiled commands directory: dist/commands/
|
|
43
43
|
* Single lookup directory for installed commands: one compiled file per `.mds`
|
|
44
|
-
* command host in src/assets/commands/. A host that carries a
|
|
45
|
-
* has a
|
|
44
|
+
* command host in src/assets/commands/. A host that carries a curation arm also
|
|
45
|
+
* has a curation-off variant (see curationOffDir).
|
|
46
46
|
*/
|
|
47
47
|
export function commandsDir() {
|
|
48
48
|
return join(getPackageRoot(), 'dist', 'commands');
|
|
49
49
|
}
|
|
50
50
|
/**
|
|
51
|
-
*
|
|
51
|
+
* Curation-off variant directory: dist/curation-off/{commands,agents}/
|
|
52
52
|
*
|
|
53
|
-
* Holds the
|
|
53
|
+
* Holds the curation-off variant of each prompt that carries a curation arm
|
|
54
54
|
* (D-LEARNING-VARIANTS), and only those. Absent until the build has run, so every
|
|
55
55
|
* reader tolerates its absence.
|
|
56
56
|
*
|
|
57
|
-
* The spelling comes from
|
|
57
|
+
* The spelling comes from CURATION_OFF_OUTPUT_DIR in curation-variants.ts, the
|
|
58
58
|
* build's own destination, rather than being retyped here.
|
|
59
59
|
*
|
|
60
60
|
* @param kind - Which prompt kind's variants.
|
|
61
61
|
* @param root - Package root to resolve against (see agentsDir).
|
|
62
62
|
*/
|
|
63
|
-
export function
|
|
64
|
-
return join(root, ...
|
|
63
|
+
export function curationOffDir(kind, root = getPackageRoot()) {
|
|
64
|
+
return join(root, ...CURATION_OFF_OUTPUT_DIR.split('/'), kind);
|
|
65
65
|
}
|
|
66
66
|
/**
|
|
67
67
|
* Command source directories, MOST-PREFERRED FIRST.
|
|
68
68
|
*
|
|
69
|
-
* D-LEARNING-VARIANT-INSTALL: with
|
|
69
|
+
* D-LEARNING-VARIANT-INSTALL: with curation off the curation-off variant comes
|
|
70
70
|
* first, so a host with an arm installs its off variant and a host with none falls
|
|
71
|
-
* through to the one compiled file; with
|
|
71
|
+
* through to the one compiled file; with curation on the order is the normal
|
|
72
72
|
* single-directory lookup.
|
|
73
73
|
*
|
|
74
|
-
* @param
|
|
74
|
+
* @param curation - The machine's settled curation switch.
|
|
75
75
|
* @param root - Package root to resolve against (see agentsDir).
|
|
76
76
|
*/
|
|
77
|
-
export function commandSourceDirs(
|
|
77
|
+
export function commandSourceDirs(curation, root = getPackageRoot()) {
|
|
78
78
|
const normal = join(root, 'dist', 'commands');
|
|
79
|
-
return
|
|
79
|
+
return curation ? [normal] : [curationOffDir('commands', root), normal];
|
|
80
80
|
}
|
|
81
81
|
/**
|
|
82
82
|
* Compiled agents directory: dist/agents/{name}.md
|
|
@@ -124,17 +124,17 @@ export function compiledSkillRefsDir(root = getPackageRoot()) {
|
|
|
124
124
|
* The non-empty tuple makes an empty list a compile error at every call site:
|
|
125
125
|
* an empty list would survive a `??` default and resolve to nothing.
|
|
126
126
|
*
|
|
127
|
-
* D-LEARNING-VARIANT-INSTALL: `
|
|
128
|
-
* for the installer and the converge only. The default (
|
|
127
|
+
* D-LEARNING-VARIANT-INSTALL: `curation: false` puts dist/curation-off/agents first,
|
|
128
|
+
* for the installer and the converge only. The default (curation on) is the order
|
|
129
129
|
* every other reader wants: the shipped defaults (model, effort) are the same in
|
|
130
130
|
* both variants, so loadShippedAgentDefaults and the test harness keep reading the
|
|
131
|
-
*
|
|
131
|
+
* curation-on tree.
|
|
132
132
|
*
|
|
133
133
|
* @param root - Package root to resolve against (see agentsDir).
|
|
134
|
-
* @param
|
|
134
|
+
* @param curation - The machine's settled curation switch; on by default.
|
|
135
135
|
*/
|
|
136
|
-
export function agentSourceDirs(root = getPackageRoot(),
|
|
136
|
+
export function agentSourceDirs(root = getPackageRoot(), curation = true) {
|
|
137
137
|
const normal = [compiledAgentsDir(root), agentsDir(root)];
|
|
138
|
-
return
|
|
138
|
+
return curation ? normal : [curationOffDir('agents', root), ...normal];
|
|
139
139
|
}
|
|
140
140
|
//# sourceMappingURL=assets.js.map
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import * as fs from 'fs';
|
|
2
|
-
import * as path from 'path';
|
|
3
2
|
import { getDevFlowDirectory } from '../targets/claude-code/claude-paths.js';
|
|
4
|
-
import { getCurateTuningConfigPath } from './project-paths.js';
|
|
3
|
+
import { getCurateTuningConfigPath, getGlobalCurateTuningConfigPath } from './project-paths.js';
|
|
5
4
|
const VALID_MODELS = new Set(['opus', 'sonnet', 'haiku']);
|
|
6
5
|
function isValidModel(value) {
|
|
7
6
|
return typeof value === 'string' && VALID_MODELS.has(value);
|
|
@@ -64,15 +63,15 @@ function readConfigFile(filePath) {
|
|
|
64
63
|
*
|
|
65
64
|
* Priority (highest wins): project config → global config → defaults.
|
|
66
65
|
*
|
|
67
|
-
* - Global: `~/.devflow/
|
|
68
|
-
* - Project: `<ledgerRoot>/.devflow/
|
|
69
|
-
* (getLedgerRoot), where session-start-context reads it and `devflow
|
|
66
|
+
* - Global: `~/.devflow/curation.json`
|
|
67
|
+
* - Project: `<ledgerRoot>/.devflow/curation/curation.json` — pass the ledger root
|
|
68
|
+
* (getLedgerRoot), where session-start-context reads it and `devflow curation
|
|
70
69
|
* --configure` writes it (D-LEDGER-MAIN-WORKTREE).
|
|
71
70
|
*
|
|
72
71
|
* Invalid JSON in either file is silently ignored and treated as absent.
|
|
73
72
|
*/
|
|
74
73
|
export function loadCurateTuningConfig(ledgerRoot) {
|
|
75
|
-
const globalConfigPath =
|
|
74
|
+
const globalConfigPath = getGlobalCurateTuningConfigPath(getDevFlowDirectory());
|
|
76
75
|
const projectConfigPath = getCurateTuningConfigPath(ledgerRoot);
|
|
77
76
|
let config = { ...DEFAULTS };
|
|
78
77
|
const globalJson = readConfigFile(globalConfigPath);
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file curation-move-notice.ts
|
|
3
|
+
*
|
|
4
|
+
* The notice for a project whose ledger still sits in the old folder: which line to
|
|
5
|
+
* show, the words of each, the fixed notice of a skipped move, and where the shell
|
|
6
|
+
* shim's markers for the project stand. The statusline (src/hud/components/curation-counts.ts)
|
|
7
|
+
* and `devflow curation` (src/cli/commands/curation.ts) both import it from here, so they
|
|
8
|
+
* say the same words and read the same markers, and neither imports the other.
|
|
9
|
+
*
|
|
10
|
+
* Reads the disk with one lstat per path, never follows a link and never opens the old
|
|
11
|
+
* ledger. The HUD runs it on every prompt, so it forks nothing and holds no state.
|
|
12
|
+
*/
|
|
13
|
+
import * as fs from 'node:fs';
|
|
14
|
+
import * as path from 'node:path';
|
|
15
|
+
import { LEGACY_NAMES, curationMoveMarkerKey } from './project-paths.js';
|
|
16
|
+
import { MOVE_SKIP_NOTICE, isMoveSkipReason } from './curation-move-skip.js';
|
|
17
|
+
/** The file suffix of each marker kind, as the shim writes it. */
|
|
18
|
+
const MARKER_SUFFIX = {
|
|
19
|
+
refused: 'skip',
|
|
20
|
+
tracked: 'tracked',
|
|
21
|
+
unknown: 'unknown',
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* The marker the `curation-move` shim writes for the ledger root `root`:
|
|
25
|
+
* `<home>/.devflow/logs/curation-move.<key>.<suffix>`, the key being the root's
|
|
26
|
+
* {@link curationMoveMarkerKey}. Without `kind` it is the refusal marker (`refused`, the
|
|
27
|
+
* suffix `skip`). The shim builds the same paths in `_df_cm_markers`
|
|
28
|
+
* (src/assets/scripts/hooks/curation-move); tests/shell-hooks.test.ts runs that function
|
|
29
|
+
* and requires the two to agree for short, long and non-ASCII roots. Every marker stands
|
|
30
|
+
* outside the project, so a skipped move writes nothing into it.
|
|
31
|
+
*/
|
|
32
|
+
export function getCurationMoveMarkerPath(home, root, kind = 'refused') {
|
|
33
|
+
return path.join(home, '.devflow', 'logs', `curation-move.${curationMoveMarkerKey(root)}.${MARKER_SUFFIX[kind]}`);
|
|
34
|
+
}
|
|
35
|
+
/** Whether anything, a link included, sits at `target`. One lstat, never followed. */
|
|
36
|
+
function exists(target) {
|
|
37
|
+
try {
|
|
38
|
+
fs.lstatSync(target);
|
|
39
|
+
return true;
|
|
40
|
+
}
|
|
41
|
+
catch {
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
/** The markers {@link gatherMoveNotice} looks for, in the order it prefers them, and the notice each one means. */
|
|
46
|
+
const MARKER_NOTICES = [
|
|
47
|
+
['tracked', 'tracked'],
|
|
48
|
+
['unknown', 'unknown'],
|
|
49
|
+
['refused', 'refused'],
|
|
50
|
+
];
|
|
51
|
+
/**
|
|
52
|
+
* The one extra question of a project with no counts to show: does it still have the old
|
|
53
|
+
* ledger folder? One existence test. If it does, one more for each of the shim's markers
|
|
54
|
+
* under the key of this same root ({@link getCurationMoveMarkerPath}) says which notice
|
|
55
|
+
* applies. Null when the old folder is gone. The old ledger itself is never opened or counted.
|
|
56
|
+
*/
|
|
57
|
+
export function gatherMoveNotice(ledgerRoot, home) {
|
|
58
|
+
if (!exists(path.join(ledgerRoot, '.devflow', LEGACY_NAMES.folder)))
|
|
59
|
+
return null;
|
|
60
|
+
const found = MARKER_NOTICES.find(([kind]) => exists(getCurationMoveMarkerPath(home, ledgerRoot, kind)));
|
|
61
|
+
return found === undefined ? 'pointer' : found[1];
|
|
62
|
+
}
|
|
63
|
+
const MOVE_NOTICE_TEXT = {
|
|
64
|
+
pointer: 'run devflow init, or open Claude Code in this project after it',
|
|
65
|
+
refused: 'move refused, see the hook log',
|
|
66
|
+
tracked: 'move skipped, git tracks files in the .devflow data folders',
|
|
67
|
+
unknown: 'move skipped, git did not answer',
|
|
68
|
+
};
|
|
69
|
+
/**
|
|
70
|
+
* The one line the HUD prints for a notice. With `counts` (the entry counts, such as
|
|
71
|
+
* `2 decisions, 1 pitfall`) the notice follows them on the same line.
|
|
72
|
+
*/
|
|
73
|
+
export function formatMoveNotice(notice, counts) {
|
|
74
|
+
return counts === undefined ? `Curation: ${MOVE_NOTICE_TEXT[notice]}` : `Curation: ${counts}; ${MOVE_NOTICE_TEXT[notice]}`;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* The text `devflow curation --status`, `--list` and `--show` print for a notice: the HUD's
|
|
78
|
+
* line, except that a skipped move gets its whole fixed notice (MOVE_SKIP_NOTICE),
|
|
79
|
+
* because these commands have room to say what to do.
|
|
80
|
+
*/
|
|
81
|
+
export function describeMoveNotice(notice) {
|
|
82
|
+
return isMoveSkipReason(notice) ? `Curation: ${MOVE_SKIP_NOTICE[notice]}` : formatMoveNotice(notice);
|
|
83
|
+
}
|
|
84
|
+
//# sourceMappingURL=curation-move-notice.js.map
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file curation-move-skip.ts
|
|
3
|
+
*
|
|
4
|
+
* The fixed notice of a skipped move. The move leaves a project alone, and changes
|
|
5
|
+
* nothing, when git tracks files in a curation data folder (`tracked`) or when a
|
|
6
|
+
* `.git` entry stands and git did not answer (`unknown`). Pure: no fs, no os, no
|
|
7
|
+
* process state, so the init step (src/cli/commands/curation-move-step.ts) and the
|
|
8
|
+
* notice module (src/core/curation-move-notice.ts) can both import it.
|
|
9
|
+
*
|
|
10
|
+
* The words hold nothing from the repository. The two commands the notice tells the
|
|
11
|
+
* user to run are listed in NOTICE_COMMAND_PHRASES in
|
|
12
|
+
* tests/guards/no-fsmonitor-index-read.test.ts, which holds this file to them. The
|
|
13
|
+
* notice of a paused area is in src/core/area-pause-notice.ts.
|
|
14
|
+
*/
|
|
15
|
+
import { CURATION_DIR_NAME, LEGACY_NAMES } from './project-paths.js';
|
|
16
|
+
const MOVE_DESCRIPTION = `devflow did not move the curation data of this project from .devflow/${LEGACY_NAMES.folder}/ to .devflow/${CURATION_DIR_NAME}/, `;
|
|
17
|
+
/** The notice of each skip reason, as one paragraph of short sentences. */
|
|
18
|
+
export const MOVE_SKIP_NOTICE = {
|
|
19
|
+
tracked: `${MOVE_DESCRIPTION}because git tracks files in a curation data folder. `
|
|
20
|
+
+ 'To find them, run `git ls-files .devflow`. '
|
|
21
|
+
+ 'Untrack them with `git rm --cached <file>`, and delete them if you did not make them. '
|
|
22
|
+
+ 'Run these commands in the checkout that holds these folders.',
|
|
23
|
+
unknown: `${MOVE_DESCRIPTION}because git did not answer. `
|
|
24
|
+
+ 'The move runs again at the next session start or the next init. '
|
|
25
|
+
+ 'If this notice stays, check that git runs in this project.',
|
|
26
|
+
};
|
|
27
|
+
/**
|
|
28
|
+
* Whether `value` is a {@link MoveSkipReason}: a reason that has a notice. The members
|
|
29
|
+
* come from the keys of {@link MOVE_SKIP_NOTICE}, which the compiler requires to list
|
|
30
|
+
* every reason, so this module needs no runtime import of the move seam.
|
|
31
|
+
*/
|
|
32
|
+
export function isMoveSkipReason(value) {
|
|
33
|
+
return typeof value === 'string' && Object.hasOwn(MOVE_SKIP_NOTICE, value);
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=curation-move-skip.js.map
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The CLI's view of the curation move — a typed seam onto the package's own
|
|
3
|
+
* `hooks/lib/curation-move.cjs`, never a second implementation of it.
|
|
4
|
+
*
|
|
5
|
+
* The one-time move of the old ledger folder to its new name lives in its own module,
|
|
6
|
+
* beside the store it builds on. `devflow init` and `devflow curation` reach it only
|
|
7
|
+
* through this seam: the module is loaded with the evidence-policy seam's `loadScript`
|
|
8
|
+
* from the package's own scripts directory and shape-checked against
|
|
9
|
+
* CURATION_MOVE_SURFACE; the interfaces below are TRANSCRIBED from the module's JSDoc
|
|
10
|
+
* and are this side's only shape authority (as for the store, see curation-store.ts).
|
|
11
|
+
*/
|
|
12
|
+
import { join } from 'path';
|
|
13
|
+
import { scriptsDir } from './assets.js';
|
|
14
|
+
import { loadScript } from './evidence-policy.js';
|
|
15
|
+
/** The move module, relative to src/assets/scripts/ (and ~/.devflow/scripts/). */
|
|
16
|
+
export const CURATION_MOVE_SCRIPT_NAME = join('hooks', 'lib', 'curation-move.cjs');
|
|
17
|
+
/**
|
|
18
|
+
* Every key of CurationMoveModule and the runtime kind the loader requires of it.
|
|
19
|
+
* `satisfies` makes the compiler reject an interface key missing here.
|
|
20
|
+
*/
|
|
21
|
+
export const CURATION_MOVE_SURFACE = Object.freeze({
|
|
22
|
+
moveLedger: 'function',
|
|
23
|
+
sweepLedgerBackups: 'function',
|
|
24
|
+
backupPendingRows: 'function',
|
|
25
|
+
backupQueueFiles: 'function',
|
|
26
|
+
});
|
|
27
|
+
/**
|
|
28
|
+
* Load the curation move module from `dir` (default: the package's own scripts
|
|
29
|
+
* directory) and shape-check its surface. Never throws: a missing file is
|
|
30
|
+
* `not-found`; a module that throws on load or lacks a surface key is `unusable`.
|
|
31
|
+
*/
|
|
32
|
+
export function loadCurationMove(dir = scriptsDir()) {
|
|
33
|
+
return loadScript(join(dir, CURATION_MOVE_SCRIPT_NAME), CURATION_MOVE_SURFACE);
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=curation-move.js.map
|