devflow-kit 3.6.0 → 3.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +438 -1
- package/README.md +15 -11
- package/dist/agents/code.md +9 -15
- package/dist/agents/design.md +1 -1
- package/dist/agents/fix.md +11 -13
- package/dist/agents/git.md +1 -1
- package/dist/agents/harden.md +1 -1
- package/dist/agents/refactor.md +7 -10
- package/dist/agents/review.md +6 -4
- package/dist/agents/skim.md +2 -2
- package/dist/agents/triage.md +2 -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/{learning.js → curation.js} +302 -99
- package/dist/cli/commands/gate-level-prompts.js +426 -0
- package/dist/cli/commands/gates.js +299 -0
- package/dist/cli/commands/init-seed.js +16 -5
- package/dist/cli/commands/init.js +263 -54
- package/dist/cli/commands/memory.js +20 -2
- package/dist/cli/commands/prompt-io.js +37 -0
- package/dist/cli/commands/uninstall.js +81 -9
- package/dist/cli.js +4 -2
- package/dist/commands/bug-analysis.md +25 -36
- package/dist/commands/code-review.md +77 -73
- package/dist/commands/debug.md +5 -5
- package/dist/commands/dynamic-build.md +76 -83
- 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 +68 -102
- package/dist/commands/plan.md +19 -29
- package/dist/commands/release.md +5 -5
- package/dist/commands/research.md +6 -6
- package/dist/commands/resolve.md +29 -31
- package/dist/commands/self-review.md +5 -13
- 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 +36 -0
- package/dist/core/curation-move.js +35 -0
- package/dist/core/curation-queue-cleanup.js +134 -0
- package/dist/core/curation-store.js +98 -0
- package/dist/core/{learning-variants.js → curation-variants.js} +65 -41
- package/dist/core/echo-value.js +48 -0
- package/dist/core/evidence-policy.js +18 -6
- package/dist/core/feature-switch.js +95 -19
- package/dist/core/fs-atomic.js +1 -1
- package/dist/core/gate-level.js +221 -0
- 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 +84 -24
- package/dist/core/migrations.js +1 -13
- package/dist/core/model-discovery.js +7 -1
- package/dist/core/observations.js +2 -2
- package/dist/core/plugins.js +15 -15
- 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 +35 -0
- package/dist/core/tracker.js +6 -34
- package/dist/{learning-off → curation-off}/agents/code.md +9 -15
- package/dist/{learning-off → curation-off}/agents/fix.md +11 -13
- package/dist/{learning-off → curation-off}/agents/refactor.md +7 -10
- package/dist/{learning-off → curation-off}/agents/review.md +5 -3
- package/dist/{learning-off → curation-off}/agents/triage.md +1 -1
- package/dist/{learning-off → curation-off}/commands/bug-analysis.md +20 -31
- package/dist/{learning-off → curation-off}/commands/code-review.md +74 -70
- package/dist/{learning-off → curation-off}/commands/debug.md +2 -2
- package/dist/{learning-off → curation-off}/commands/dynamic-build.md +73 -80
- package/dist/{learning-off → curation-off}/commands/explore.md +2 -2
- package/dist/{learning-off → curation-off}/commands/implement.md +65 -99
- package/dist/{learning-off → curation-off}/commands/plan.md +15 -25
- package/dist/{learning-off → curation-off}/commands/resolve.md +26 -28
- package/dist/{learning-off → curation-off}/commands/self-review.md +2 -10
- package/dist/hud/components/{learning-counts.js → curation-counts.js} +36 -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/validate-branch.md +8 -5
- package/dist/skills/git/references/tracker/github/ensure-pr-ready.md +20 -14
- package/dist/skills/git/references/tracker/jira/ensure-pr-ready.md +20 -20
- package/dist/skills/git/references/tracker/linear/ensure-pr-ready.md +20 -20
- package/dist/targets/claude-code/{learning-install.js → curation-install.js} +99 -67
- 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 +16 -17
- package/src/assets/agents/code.mds +4 -7
- package/src/assets/agents/curate.md +12 -14
- package/src/assets/agents/debug.mds +6 -6
- package/src/assets/agents/design.mds +18 -18
- package/src/assets/agents/fix.mds +6 -5
- package/src/assets/agents/git.mds +1 -1
- 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 +45 -43
- package/src/assets/agents/skim.mds +11 -11
- package/src/assets/agents/synthesize.md +2 -2
- package/src/assets/agents/triage.mds +22 -22
- package/src/assets/agents/validate.md +13 -26
- package/src/assets/commands/_partials/_decisions.mds +13 -13
- 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 +17 -24
- package/src/assets/commands/bug-analysis.mds +37 -48
- package/src/assets/commands/code-review.mds +90 -86
- package/src/assets/commands/debug.mds +14 -14
- package/src/assets/commands/dynamic-build.mds +78 -78
- 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 +92 -118
- package/src/assets/commands/plan.mds +41 -51
- package/src/assets/commands/release.mds +12 -12
- package/src/assets/commands/research.mds +19 -19
- package/src/assets/commands/resolve.mds +56 -50
- package/src/assets/commands/self-review.mds +20 -20
- package/src/assets/mds/git/_ops.mds +3 -1
- package/src/assets/mds/git/_ops_pr.mds +1 -1
- package/src/assets/mds/git/_ops_steps.mds +13 -7
- package/src/assets/mds/git/_pr.mds +7 -4
- package/src/assets/mds/tracker/_common.mds +23 -12
- package/src/assets/mds/tracker/_github.mds +2 -9
- package/src/assets/mds/tracker/_jira.mds +2 -15
- package/src/assets/mds/tracker/_linear.mds +2 -15
- package/src/assets/rules/quality.md +1 -0
- package/src/assets/scripts/ci-wait.cjs +22 -4
- package/src/assets/scripts/claude-md-audit.cjs +66 -51
- package/src/assets/scripts/hooks/background-memory-update +406 -97
- 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 +145 -51
- package/src/assets/scripts/hooks/json-parse +19 -4
- package/src/assets/scripts/hooks/lib/curation-move.cjs +1582 -0
- package/src/assets/scripts/hooks/lib/{learning-store.cjs → curation-store.cjs} +242 -118
- 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 +34 -22
- package/src/assets/scripts/hooks/lib/tracked-areas.cjs +259 -0
- package/src/assets/scripts/hooks/memory-permission +358 -0
- package/src/assets/scripts/hooks/memory-worker +1 -1
- package/src/assets/scripts/hooks/pre-compact-memory +6 -16
- package/src/assets/scripts/hooks/queue-append +228 -103
- package/src/assets/scripts/hooks/resolve-project-root +2 -2
- package/src/assets/scripts/hooks/session-start-context +145 -71
- package/src/assets/scripts/hooks/session-start-memory +27 -46
- package/src/assets/scripts/lib/project-config.cjs +31 -9
- package/src/assets/scripts/resolve-base.cjs +1043 -0
- package/src/assets/scripts/resolve-settings.cjs +238 -46
- package/src/assets/skills/agent-references/SKILL.md +9 -2
- package/src/assets/skills/agent-references/references/commands/code-review-levels.md +19 -0
- package/src/assets/skills/agent-references/references/commands/implement-levels.md +27 -0
- package/src/assets/skills/agent-references/references/commands/implement-revalidate.md +6 -4
- package/src/assets/skills/agent-references/references/commands/plan-levels.md +40 -0
- package/src/assets/skills/agent-references/references/commands/resolve-levels.md +24 -0
- package/src/assets/skills/agent-references/references/synthesize/planning.md +9 -22
- package/src/assets/skills/agent-references/references/synthesize/review.md +11 -11
- 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/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
|
@@ -47,13 +47,13 @@ and using its one-line output. If the command fails (outside a git repository),
|
|
|
47
47
|
node "$HOME/.devflow/scripts/resolve-settings.cjs" "{root}" 2>/dev/null; echo "exit=$?"
|
|
48
48
|
```
|
|
49
49
|
|
|
50
|
-
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>
|
|
50
|
+
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.
|
|
51
51
|
|
|
52
|
-
The accepted line is the only source of these values
|
|
52
|
+
The accepted line is the only source of these values.
|
|
53
53
|
|
|
54
54
|
### Load DECISIONS_CONTEXT
|
|
55
55
|
|
|
56
|
-
When the settings line says `
|
|
56
|
+
When the settings line says `CURATION=off`, set `DECISIONS_CONTEXT` to `(none)` and skip this step, locating no ledger and reading no index.
|
|
57
57
|
|
|
58
58
|
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`):
|
|
59
59
|
|
|
@@ -67,11 +67,11 @@ Line 1 is the checkout's toplevel, line 2 the common git directory. A git older
|
|
|
67
67
|
2. **The toplevel** — line 1, or on an older git the line after the echoed flag.
|
|
68
68
|
3. **The start directory itself** — when the command failed or printed no absolute toplevel (outside a git repository).
|
|
69
69
|
|
|
70
|
-
This is the rule the
|
|
70
|
+
This is the rule the curation hooks apply, so you read the index the Curate agent writes.
|
|
71
71
|
|
|
72
72
|
**Step 1 — Read the pre-rendered index:**
|
|
73
73
|
|
|
74
|
-
Attempt to read `{ledger}/.devflow/
|
|
74
|
+
Attempt to read `{ledger}/.devflow/curation/index.md`.
|
|
75
75
|
|
|
76
76
|
- If the file exists and contains non-empty content: use that content as `DECISIONS_CONTEXT`.
|
|
77
77
|
- If the file is absent or empty: set `DECISIONS_CONTEXT` to `(none)`.
|
|
@@ -166,7 +166,7 @@ Analyze the research question to infer research types needed (min 2, max 5). For
|
|
|
166
166
|
|
|
167
167
|
Only if `codebase` type is in RESEARCH_PLAN.
|
|
168
168
|
|
|
169
|
-
Spawn `Agent(subagent_type="Skim")` with `
|
|
169
|
+
Spawn `Agent(subagent_type="Skim")` with `CURATION` from the settings line, targeting codebase areas relevant to the research question.
|
|
170
170
|
|
|
171
171
|
Skip and set ORIENT_OUTPUT = "(none)" if `codebase` type is not in RESEARCH_PLAN.
|
|
172
172
|
|
package/dist/commands/resolve.md
CHANGED
|
@@ -86,7 +86,7 @@ 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
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:
|
|
92
92
|
|
|
@@ -94,13 +94,13 @@ Set `TARGET_DIR` to the selected review or bug-analysis directory path, and `TAR
|
|
|
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=on CURATION=on KNOWLEDGE=off GATE_LEVEL=full` instead.
|
|
98
98
|
|
|
99
|
-
The accepted line is the only source of these values
|
|
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
|
|
@@ -309,10 +315,10 @@ Collect every decision and pitfall the Triage agent's Reasoning columns state, i
|
|
|
309
315
|
**Produces:** BATCHES
|
|
310
316
|
**Requires:** TRIAGE_RESULTS
|
|
311
317
|
|
|
312
|
-
If FIX_NOW list is empty: skip to Phase 5
|
|
318
|
+
If FIX_NOW list is empty: skip to Phase 5, then run Phases 9, 9b, 9c and 10.
|
|
313
319
|
|
|
314
320
|
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
|
|
321
|
+
- **Same-file issues** → one batch (one Code agent per file)
|
|
316
322
|
- **Distinct-file issues** → parallel Code agents
|
|
317
323
|
- **Max 5 issues per batch** — chunk large sets
|
|
318
324
|
|
|
@@ -348,9 +354,9 @@ Collect from each Code agent:
|
|
|
348
354
|
### Phase 5: Write resolution-summary.md
|
|
349
355
|
|
|
350
356
|
**Produces:** RESOLUTION_FILE (early write for compaction safety)
|
|
351
|
-
**Requires:** TRIAGE_RESULTS, CODE_AGENT_RESULTS, TARGET_DIR, TARGET_DIR_REL, BRANCH_INFO, RESOLUTION_TS
|
|
357
|
+
**Requires:** TRIAGE_RESULTS, CODE_AGENT_RESULTS, TARGET_DIR, TARGET_DIR_REL, BRANCH_INFO, RESOLUTION_TS, GATE_LEVEL
|
|
352
358
|
|
|
353
|
-
**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.
|
|
359
|
+
**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.
|
|
354
360
|
|
|
355
361
|
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
362
|
|
|
@@ -361,7 +367,7 @@ Use the template from the Output Artifact section below.
|
|
|
361
367
|
### Phase 6: Polish
|
|
362
368
|
|
|
363
369
|
**Produces:** POLISH_RESULT
|
|
364
|
-
**Requires:** CODE_AGENT_RESULTS
|
|
370
|
+
**Requires:** CODE_AGENT_RESULTS, GATE_LEVEL
|
|
365
371
|
|
|
366
372
|
If any fixes were made, spawn Polish agent to refine the changed code:
|
|
367
373
|
|
|
@@ -423,7 +429,7 @@ git -C {worktree} push
|
|
|
423
429
|
|
|
424
430
|
**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
431
|
|
|
426
|
-
**Route after push:** VERIFICATION_STATUS = PASS → continue to Phase 8 (CI gate).
|
|
432
|
+
**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
433
|
|
|
428
434
|
### Phase 8: CI Status Gate (Conditional)
|
|
429
435
|
|
|
@@ -593,7 +599,7 @@ If the script prints a `TRACEABILITY: DEGRADED` line: warn, proceed to Phase 10.
|
|
|
593
599
|
|
|
594
600
|
### Phase 10: Report
|
|
595
601
|
|
|
596
|
-
**Requires:** BRANCH_INFO, TARGET_DIR, PR_COMMENT, THREAD_RESOLUTION_RESULT
|
|
602
|
+
**Requires:** BRANCH_INFO, TARGET_DIR, PR_COMMENT, THREAD_RESOLUTION_RESULT, GATE_LEVEL
|
|
597
603
|
|
|
598
604
|
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
605
|
|
|
@@ -603,6 +609,7 @@ The resolution summary was already written to `{TARGET_DIR}/resolution-summary.m
|
|
|
603
609
|
**Branch**: {branch}
|
|
604
610
|
**Reviews Processed**: {n} reports from {TARGET_DIR}
|
|
605
611
|
**Total Issues**: {n}
|
|
612
|
+
**Gate level**: {GATE_LEVEL, with any level note}
|
|
606
613
|
|
|
607
614
|
### Results
|
|
608
615
|
| Outcome | Count |
|
|
@@ -648,14 +655,6 @@ In multi-worktree mode, report results per worktree with aggregate summary.
|
|
|
648
655
|
|
|
649
656
|
### Feature Knowledge Write-Back (Conditional)
|
|
650
657
|
|
|
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
658
|
**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
659
|
|
|
661
660
|
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,15 +702,15 @@ When the Knowledge agent reports `KB_COMMIT: skipped (detached HEAD)`, the files
|
|
|
703
702
|
/resolve (orchestrator - spawns agents only)
|
|
704
703
|
│
|
|
705
704
|
├─ Phase 0: Worktree Discovery & Pre-flight
|
|
706
|
-
├─ Phase 1: Parse issues from TARGET_DIR
|
|
705
|
+
├─ Phase 1: Parse issues from TARGET_DIR
|
|
707
706
|
├─ Phase 1b: Fetch external threads (evidence policy required)
|
|
708
707
|
├─ Phase 2: Global Triage [Triage agent, opus, single agent]
|
|
709
|
-
├─ Phase 3: Batch FIX_NOW issues
|
|
710
|
-
├─ Phase 4: Fix [Code agent × N
|
|
708
|
+
├─ Phase 3: Batch FIX_NOW issues
|
|
709
|
+
├─ Phase 4: Fix [Code agent × N]
|
|
711
710
|
├─ Phase 5: Write resolution-summary.md (compaction safety; Tracked = "(pending)" or "(pending — TRACEABILITY: DEGRADED)" if manage-debt degrades)
|
|
712
|
-
├─ Phase 6: Polish
|
|
711
|
+
├─ Phase 6: Polish
|
|
713
712
|
├─ Phase 7: Verification Gate [Validate agent, haiku] + push + Fix agent validation-fix loop ≤2
|
|
714
|
-
├─ Phase 8: CI Status Gate (conditional
|
|
713
|
+
├─ Phase 8: CI Status Gate (conditional)
|
|
715
714
|
├─ Phase 9: Git agent (manage-debt) — FIX_SEPARATE + TECH_DEBT → backfill Tracked={ISSUE_REF} (or TRACEABILITY: DEGRADED on failure)
|
|
716
715
|
│
|
|
717
716
|
├─ Phase 9b: Thread resolution + resolution comment
|
|
@@ -730,10 +729,9 @@ When the Knowledge agent reports `KB_COMMIT: skipped (detached HEAD)`, the files
|
|
|
730
729
|
| Case | Handling |
|
|
731
730
|
|------|----------|
|
|
732
731
|
| 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
732
|
| Fix attempt fails | Revert changes, mark BLOCKED, continue others |
|
|
735
733
|
| Issue dependencies | Sequential chain, skip dependents if predecessor blocked |
|
|
736
|
-
| No
|
|
734
|
+
| No issues parsed | Report "No issues to resolve" |
|
|
737
735
|
| Latest review already resolved | Check bug-analysis fallback (Step 0c-5b); if also absent, skip worktree and suggest `/code-review` or `/bug-analysis` |
|
|
738
736
|
| `--review {timestamp}` in multi-worktree mode | Not supported — use `--path` + `--review` to target specific worktree + review |
|
|
739
737
|
| gh/GitHub absent | manage-debt degrades (`TRACEABILITY: DEGRADED ({reason})`); Tracked stays `(pending — TRACEABILITY: DEGRADED ({reason}))` — recorded, not dropped |
|
|
@@ -748,9 +746,8 @@ When the Knowledge agent reports `KB_COMMIT: skipped (detached HEAD)`, the files
|
|
|
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; the CI wait, the evidence refresh and the merge-readiness check are inline scripts (plumbing, no model work)
|
|
750
|
+
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)
|
|
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}
|
|
766
764
|
|
|
767
765
|
## Decisions Citations
|
|
768
766
|
|
|
@@ -30,13 +30,13 @@ Detect changed files and build context:
|
|
|
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=on CURATION=on KNOWLEDGE=off GATE_LEVEL=full` instead.
|
|
34
34
|
|
|
35
|
-
The accepted line is the only source of these values
|
|
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.
|
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,36 @@
|
|
|
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 session start hook
|
|
11
|
+
* (src/assets/scripts/hooks/session-start-context) holds the same words;
|
|
12
|
+
* tests/shell-hooks.test.ts requires the two to agree. The two commands the notice
|
|
13
|
+
* tells the user to run are listed in NOTICE_COMMAND_PHRASES in
|
|
14
|
+
* tests/guards/no-fsmonitor-index-read.test.ts, which holds both copies to them.
|
|
15
|
+
*/
|
|
16
|
+
import { CURATION_DIR_NAME, LEGACY_NAMES } from './project-paths.js';
|
|
17
|
+
const MOVE_DESCRIPTION = `devflow did not move the curation data of this project from .devflow/${LEGACY_NAMES.folder}/ to .devflow/${CURATION_DIR_NAME}/, `;
|
|
18
|
+
/** The notice of each skip reason, as one paragraph of short sentences. */
|
|
19
|
+
export const MOVE_SKIP_NOTICE = {
|
|
20
|
+
tracked: `${MOVE_DESCRIPTION}because git tracks files in a curation data folder. `
|
|
21
|
+
+ 'To find them, run `git ls-files .devflow`. '
|
|
22
|
+
+ 'Untrack them with `git rm --cached <file>`, and delete them if you did not make them. '
|
|
23
|
+
+ 'Run these commands in the checkout that holds these folders.',
|
|
24
|
+
unknown: `${MOVE_DESCRIPTION}because git did not answer. `
|
|
25
|
+
+ 'The move runs again at the next session start or the next init. '
|
|
26
|
+
+ 'If this notice stays, check that git runs in this project.',
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* Whether `value` is a {@link MoveSkipReason}: a reason that has a notice. The members
|
|
30
|
+
* come from the keys of {@link MOVE_SKIP_NOTICE}, which the compiler requires to list
|
|
31
|
+
* every reason, so this module needs no runtime import of the move seam.
|
|
32
|
+
*/
|
|
33
|
+
export function isMoveSkipReason(value) {
|
|
34
|
+
return typeof value === 'string' && Object.hasOwn(MOVE_SKIP_NOTICE, value);
|
|
35
|
+
}
|
|
36
|
+
//# 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
|