devflow-kit 2.5.0 → 3.0.1
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 +82 -0
- package/README.md +44 -19
- package/dist/agents/git.md +13 -15
- package/dist/cli/commands/ambient.js +160 -145
- package/dist/cli/commands/capture.js +29 -55
- package/dist/cli/commands/compliance.js +32 -61
- package/dist/cli/commands/context.js +17 -32
- package/dist/cli/commands/debug.js +65 -26
- package/dist/cli/commands/flags.js +3 -3
- package/dist/cli/commands/hud.js +34 -10
- package/dist/cli/commands/init-seed.js +40 -4
- package/dist/cli/commands/init.js +249 -271
- package/dist/cli/commands/install-report.js +10 -15
- package/dist/cli/commands/knowledge/index.js +1 -1
- package/dist/cli/commands/knowledge/toggle.js +11 -3
- package/dist/cli/commands/learning.js +52 -37
- package/dist/cli/commands/legacy-hooks.js +11 -14
- package/dist/cli/commands/memory.js +67 -78
- package/dist/cli/commands/proxy.js +23 -41
- package/dist/cli/commands/security.js +5 -13
- package/dist/cli/commands/skills.js +21 -3
- package/dist/cli/commands/tracker.js +100 -228
- package/dist/cli/commands/uninstall.js +343 -138
- package/dist/commands/bug-analysis.md +38 -12
- package/dist/commands/code-review.md +70 -21
- package/dist/commands/debug.md +37 -7
- package/dist/commands/dynamic-build.md +66 -17
- package/dist/commands/dynamic-plan.md +19 -8
- package/dist/commands/dynamic-profile.md +24 -10
- package/dist/commands/dynamic-tickets.md +22 -11
- package/dist/commands/explore.md +37 -7
- package/dist/commands/implement.md +96 -32
- package/dist/commands/plan.md +62 -19
- package/dist/commands/release.md +2 -2
- package/dist/commands/research.md +34 -8
- package/dist/commands/resolve.md +65 -17
- package/dist/commands/self-review.md +45 -9
- package/dist/core/compliance-compose.js +27 -27
- package/dist/core/evidence-policy.js +240 -24
- package/dist/core/feature-config.js +94 -25
- package/dist/core/feature-switch.js +1 -1
- package/dist/core/flags.js +30 -2
- package/dist/core/fs-atomic.js +27 -0
- package/dist/core/hook-log-dirs.js +104 -0
- package/dist/core/learning-tuning-config.js +5 -3
- package/dist/core/ledger-root.js +102 -0
- package/dist/core/manifest.js +6 -4
- package/dist/core/mds-variants.js +34 -97
- package/dist/core/migrations.js +49 -23
- package/dist/core/plugins.js +5 -4
- package/dist/core/project-paths.js +0 -17
- package/dist/core/same-location.js +25 -0
- package/dist/core/tracker.js +226 -139
- package/dist/hud/components/config-counts.js +15 -4
- package/dist/hud/components/learning-counts.js +14 -0
- package/dist/hud/config.js +2 -1
- package/dist/hud/cost-history.js +2 -4
- package/dist/hud/git.js +52 -7
- package/dist/hud/index.js +7 -9
- package/dist/skills/git/references/pr/check-merge-readiness.md +1 -1
- package/dist/skills/git/references/pr/ensure-pr-ready.md +1 -1
- package/dist/skills/git/references/pr/update-pr-evidence.md +1 -1
- package/dist/skills/git/references/tracker/_mcp.md +1 -1
- package/dist/skills/git/references/tracker/github/backlink-shipped-issues.md +1 -1
- package/dist/skills/git/references/tracker/github/ensure-traceable-issue.md +1 -1
- package/dist/skills/git/references/tracker/github/gather-release-evidence.md +2 -2
- package/dist/skills/git/references/tracker/github/manage-debt.md +3 -3
- package/dist/skills/git/references/tracker/jira/backlink-shipped-issues.md +1 -1
- package/dist/skills/git/references/tracker/jira/ensure-traceable-issue.md +1 -1
- package/dist/skills/git/references/tracker/jira/gather-release-evidence.md +2 -2
- package/dist/skills/git/references/tracker/jira/manage-debt.md +1 -1
- package/dist/skills/git/references/tracker/jira/post-wave-report.md +1 -1
- package/dist/skills/git/references/tracker/jira/setup-task.md +1 -1
- package/dist/skills/git/references/tracker/linear/backlink-shipped-issues.md +1 -1
- package/dist/skills/git/references/tracker/linear/ensure-traceable-issue.md +1 -1
- package/dist/skills/git/references/tracker/linear/gather-release-evidence.md +2 -2
- package/dist/skills/git/references/tracker/linear/manage-debt.md +1 -1
- package/dist/skills/git/references/tracker/linear/post-wave-report.md +1 -1
- package/dist/skills/git/references/tracker/linear/setup-task.md +1 -1
- package/dist/targets/claude-code/claude-paths.js +59 -57
- package/dist/targets/claude-code/compliance-install.js +49 -65
- package/dist/targets/claude-code/hooks.js +108 -3
- package/dist/targets/claude-code/installer.js +30 -57
- package/dist/targets/claude-code/post-install.js +246 -139
- package/dist/targets/claude-code/tracker-install.js +38 -65
- package/package.json +5 -4
- package/src/assets/agents/code.md +4 -3
- package/src/assets/agents/design.md +1 -0
- package/src/assets/agents/git.mds +55 -57
- package/src/assets/agents/knowledge.md +2 -2
- package/src/assets/agents/review.md +3 -1
- package/src/assets/agents/tracker.md +37 -30
- package/src/assets/commands/_partials/_compliance.mds +19 -1
- package/src/assets/commands/_partials/_decisions.mds +15 -3
- package/src/assets/commands/_partials/_docs_root.mds +35 -0
- package/src/assets/commands/_partials/_engine.mds +2 -2
- package/src/assets/commands/_partials/_evidence_policy.mds +3 -3
- package/src/assets/commands/_partials/_factory.mds +1 -1
- package/src/assets/commands/_partials/_knowledge.mds +27 -9
- package/src/assets/commands/_partials/_plan_contract.mds +2 -2
- package/src/assets/commands/_partials/_preamble.mds +1 -1
- package/src/assets/commands/_partials/_publication.mds +6 -2
- package/src/assets/commands/_partials/_settings.mds +28 -0
- package/src/assets/commands/_partials/_ticket_template.mds +3 -3
- package/src/assets/commands/_partials/_tracker.mds +4 -4
- package/src/assets/commands/_partials/_wave.mds +4 -4
- package/src/assets/commands/bug-analysis.mds +19 -17
- package/src/assets/commands/code-review.mds +39 -33
- package/src/assets/commands/debug.mds +4 -5
- package/src/assets/commands/dynamic-build.mds +75 -53
- package/src/assets/commands/dynamic-plan.mds +20 -15
- package/src/assets/commands/dynamic-profile.mds +24 -11
- package/src/assets/commands/dynamic-tickets.mds +25 -20
- package/src/assets/commands/explore.mds +4 -5
- package/src/assets/commands/implement.mds +58 -45
- package/src/assets/commands/plan.mds +34 -29
- package/src/assets/commands/release.md +2 -2
- package/src/assets/commands/research.mds +11 -9
- package/src/assets/commands/resolve.mds +41 -39
- package/src/assets/commands/self-review.mds +24 -25
- package/src/assets/mds/git/_pr.mds +61 -61
- package/src/assets/mds/git/_references.mds +19 -19
- package/src/assets/mds/tracker/_common.mds +8 -8
- package/src/assets/mds/tracker/_github.mds +71 -71
- package/src/assets/mds/tracker/_jira.mds +74 -74
- package/src/assets/mds/tracker/_linear.mds +75 -75
- package/src/assets/mds/tracker/_mcp.mds +23 -17
- package/src/assets/scripts/hooks/background-memory-update +35 -19
- package/src/assets/scripts/hooks/capture-prompt +18 -12
- package/src/assets/scripts/hooks/capture-question +18 -12
- package/src/assets/scripts/hooks/capture-turn +27 -17
- package/src/assets/scripts/hooks/debug-trace +11 -6
- package/src/assets/scripts/hooks/ensure-devflow-init +33 -6
- package/src/assets/scripts/hooks/ensure-proxy +9 -8
- package/src/assets/scripts/hooks/ensure-root-gitignore +111 -36
- package/src/assets/scripts/hooks/git-marker +48 -0
- package/src/assets/scripts/hooks/json-helper.cjs +6 -1
- package/src/assets/scripts/hooks/lib/project-paths.cjs +0 -19
- package/src/assets/scripts/hooks/log-paths +80 -0
- package/src/assets/scripts/hooks/memory-worker +17 -15
- package/src/assets/scripts/hooks/pre-compact-memory +41 -16
- package/src/assets/scripts/hooks/queue-append +104 -30
- package/src/assets/scripts/hooks/resolve-project-root +101 -7
- package/src/assets/scripts/hooks/session-start-context +289 -122
- package/src/assets/scripts/hooks/session-start-memory +35 -16
- package/src/assets/scripts/lib/project-config.cjs +633 -0
- package/src/assets/scripts/resolve-evidence-policy.cjs +300 -220
- package/src/assets/scripts/resolve-settings.cjs +1054 -0
- package/src/assets/scripts/verify-evidence.cjs +1 -1
- package/src/assets/skills/compliance/SKILL.md +2 -2
- package/src/assets/skills/docs-framework/SKILL.md +6 -7
- package/src/assets/skills/docs-framework/references/patterns.md +10 -17
- package/src/assets/skills/gap-analysis/SKILL.md +2 -2
- package/src/assets/skills/git/references/github-api.md +9 -9
- package/src/assets/skills/git/references/patterns.md +1 -1
- package/src/assets/skills/worktree-support/SKILL.md +1 -1
- package/src/assets/skills/worktree-support/references/roots.md +29 -0
- package/src/targets/claude-code/templates/managed-settings.json +25 -9
|
@@ -27,18 +27,38 @@ Research a topic by spawning parallel Research agents across multiple research t
|
|
|
27
27
|
|
|
28
28
|
**Produces:** DECISIONS_CONTEXT, FEATURE_KNOWLEDGE
|
|
29
29
|
|
|
30
|
+
**Docs root (D-DOCS-ROOT).** Every `.devflow/docs/` path this command reads or writes lives at the checkout's toplevel, never under the directory the session started in. Resolve `{worktree}` from the start directory — `WORKTREE_PATH` if provided, otherwise cwd (`devflow:worktree-support`) — by running
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
git -C "{start}" rev-parse --show-toplevel
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
and using its one-line output. If the command fails (outside a git repository), `{worktree}` is the start directory itself. Every docs path below is written `{worktree}/.devflow/docs/…`; a repo-relative docs path handed to an agent always travels with a `WORKTREE_PATH` naming the checkout it is relative to.
|
|
37
|
+
|
|
30
38
|
### Load DECISIONS_CONTEXT
|
|
31
39
|
|
|
32
|
-
|
|
40
|
+
The decisions ledger belongs to the repository, not to one checkout: in a linked worktree it lives in the main worktree, and a session started in a subdirectory reads the copy at the repository root. Locate it with ONE git call, run from the start directory — `WORKTREE_PATH` if provided, otherwise cwd (`devflow:worktree-support`):
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
git -C "{start}" rev-parse --path-format=absolute --show-toplevel --git-common-dir
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Line 1 is the checkout's toplevel, line 2 the repository's common git directory. A git older than 2.31 echoes `--path-format=absolute` back as a line of its own first. `{ledger}` is the first of these that applies:
|
|
47
|
+
|
|
48
|
+
1. **The main worktree** — line 2 without its trailing `/.git`, when the output is exactly two lines each beginning with `/`, line 2 ends in `/.git`, and the directory left once it is removed is not your home directory and contains a `.devflow/` directory.
|
|
49
|
+
2. **The toplevel** — line 1, or on an older git the line after the echoed flag.
|
|
50
|
+
3. **The start directory itself** — when the command failed or printed no absolute toplevel (outside a git repository).
|
|
51
|
+
|
|
52
|
+
This is the rule the learning hooks apply (D-LEDGER-MAIN-WORKTREE, D-PROMPT-ROOT), so you read the index the Learning agent writes.
|
|
33
53
|
|
|
34
54
|
**Step 1 — Read the pre-rendered index:**
|
|
35
55
|
|
|
36
|
-
Attempt to read `{
|
|
56
|
+
Attempt to read `{ledger}/.devflow/learning/index.md`.
|
|
37
57
|
|
|
38
58
|
- If the file exists and contains non-empty content: use that content as `DECISIONS_CONTEXT`.
|
|
39
59
|
- If the file is absent or empty: set `DECISIONS_CONTEXT` to `(none)`.
|
|
40
60
|
|
|
41
|
-
|
|
61
|
+
The index is one direct file read, written at render time by `render-decisions.cjs` alongside `decisions.md`/`pitfalls.md` — no `.cjs` script runs here, and the index's own footer names the files that hold each entry's full body.
|
|
42
62
|
|
|
43
63
|
**Step 2 — Apply decisions using `devflow:apply-decisions`:**
|
|
44
64
|
|
|
@@ -48,7 +68,13 @@ Use `DECISIONS_CONTEXT` locally when framing research — prior decisions and pi
|
|
|
48
68
|
|
|
49
69
|
### Load Feature Knowledge
|
|
50
70
|
|
|
51
|
-
Resolve the
|
|
71
|
+
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
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
git -C "{start}" rev-parse --show-toplevel
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
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}`.
|
|
52
78
|
|
|
53
79
|
**Step 1 — Read the index cache:**
|
|
54
80
|
|
|
@@ -83,7 +109,7 @@ Concatenate the selected KNOWLEDGE.md files under slug headers:
|
|
|
83
109
|
|
|
84
110
|
If no KBs exist, no KBs are relevant, or `.devflow/features/` is absent, set `FEATURE_KNOWLEDGE` to `(none)`.
|
|
85
111
|
|
|
86
|
-
**
|
|
112
|
+
**One git call, then direct file reads — no `.cjs` script.** After resolving `{worktree}`, this step is 1 index read (or N frontmatter reads on fallback), bounded by KB count.
|
|
87
113
|
|
|
88
114
|
Use `FEATURE_KNOWLEDGE` **locally** for research framing. Pass to each Research agent in Phase 4.
|
|
89
115
|
|
|
@@ -94,7 +120,7 @@ Use `FEATURE_KNOWLEDGE` **locally** for research framing. Pass to each Research
|
|
|
94
120
|
Analyze the research question to infer research types needed (min 2, max 5). For each type:
|
|
95
121
|
- `RESEARCH_TYPE`: `codebase | external | market | competitor | technology`
|
|
96
122
|
- `RESEARCH_QUESTION`: Focused sub-question for this type
|
|
97
|
-
- `OUTPUT_PATH`:
|
|
123
|
+
- `OUTPUT_PATH`: `{worktree}/.devflow/docs/research/{topic-slug}/{YYYY-MM-DD_HHMM}/{type}.md`
|
|
98
124
|
|
|
99
125
|
**Tool availability check**: If WebSearch/WebFetch are unavailable, restrict to `codebase` type only.
|
|
100
126
|
|
|
@@ -136,7 +162,7 @@ Spawn `Agent(subagent_type="Synthesize")` in `research` mode:
|
|
|
136
162
|
- Merges findings with trust-aware aggregation
|
|
137
163
|
- Writes `research-summary.md` to the same timestamped directory
|
|
138
164
|
|
|
139
|
-
Output path:
|
|
165
|
+
Output path: `{worktree}/.devflow/docs/research/{topic-slug}/{timestamp}/research-summary.md`
|
|
140
166
|
|
|
141
167
|
### Phase 6: Present
|
|
142
168
|
|
|
@@ -168,7 +194,7 @@ If the orchestrator receives a `WORKTREE_PATH` context (e.g., from multi-worktre
|
|
|
168
194
|
|
|
169
195
|
## Output
|
|
170
196
|
|
|
171
|
-
Research findings saved to
|
|
197
|
+
Research findings saved to `{worktree}/.devflow/docs/research/{topic-slug}/{YYYY-MM-DD_HHMM}/`:
|
|
172
198
|
- `{type}.md` per research type (codebase.md, external.md, etc.)
|
|
173
199
|
- `research-summary.md` — synthesized findings with trust annotations
|
|
174
200
|
|
package/dist/commands/resolve.md
CHANGED
|
@@ -24,7 +24,7 @@ Process issues from code review reports: triage every issue through the blast-ra
|
|
|
24
24
|
|
|
25
25
|
1. **Discover resolvable worktrees** using the `devflow:worktree-support` skill discovery algorithm:
|
|
26
26
|
- Run `git worktree list --porcelain` → parse, filter (skip protected/detached/mid-rebase), dedup by branch, sort by recent commit
|
|
27
|
-
- See
|
|
27
|
+
- See the `devflow:worktree-support` skill for the full 7-step algorithm and canonical protected branch list
|
|
28
28
|
- Additional filter: must have unresolved reviews (latest review directory has no `resolution-summary.md`)
|
|
29
29
|
2. **If `--path` flag provided:** use only that worktree, skip discovery
|
|
30
30
|
**`--path` validation**: Before proceeding, verify the path exists as a directory and appears in `git worktree list` output. If not: report error and stop.
|
|
@@ -89,16 +89,28 @@ Set `TARGET_DIR` to the selected review or bug-analysis directory path, and `TAR
|
|
|
89
89
|
|
|
90
90
|
### Load DECISIONS_CONTEXT
|
|
91
91
|
|
|
92
|
-
|
|
92
|
+
The decisions ledger belongs to the repository, not to one checkout: in a linked worktree it lives in the main worktree, and a session started in a subdirectory reads the copy at the repository root. Locate it with ONE git call, run from the start directory — `WORKTREE_PATH` if provided, otherwise cwd (`devflow:worktree-support`):
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
git -C "{start}" rev-parse --path-format=absolute --show-toplevel --git-common-dir
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
Line 1 is the checkout's toplevel, line 2 the repository's common git directory. A git older than 2.31 echoes `--path-format=absolute` back as a line of its own first. `{ledger}` is the first of these that applies:
|
|
99
|
+
|
|
100
|
+
1. **The main worktree** — line 2 without its trailing `/.git`, when the output is exactly two lines each beginning with `/`, line 2 ends in `/.git`, and the directory left once it is removed is not your home directory and contains a `.devflow/` directory.
|
|
101
|
+
2. **The toplevel** — line 1, or on an older git the line after the echoed flag.
|
|
102
|
+
3. **The start directory itself** — when the command failed or printed no absolute toplevel (outside a git repository).
|
|
103
|
+
|
|
104
|
+
This is the rule the learning hooks apply (D-LEDGER-MAIN-WORKTREE, D-PROMPT-ROOT), so you read the index the Learning agent writes.
|
|
93
105
|
|
|
94
106
|
**Step 1 — Read the pre-rendered index:**
|
|
95
107
|
|
|
96
|
-
Attempt to read `{
|
|
108
|
+
Attempt to read `{ledger}/.devflow/learning/index.md`.
|
|
97
109
|
|
|
98
110
|
- If the file exists and contains non-empty content: use that content as `DECISIONS_CONTEXT`.
|
|
99
111
|
- If the file is absent or empty: set `DECISIONS_CONTEXT` to `(none)`.
|
|
100
112
|
|
|
101
|
-
|
|
113
|
+
The index is one direct file read, written at render time by `render-decisions.cjs` alongside `decisions.md`/`pitfalls.md` — no `.cjs` script runs here, and the index's own footer names the files that hold each entry's full body.
|
|
102
114
|
|
|
103
115
|
**Step 2 — Apply decisions using `devflow:apply-decisions`:**
|
|
104
116
|
|
|
@@ -108,7 +120,13 @@ This produces a compact index of active ADR/PF entries written at render time
|
|
|
108
120
|
|
|
109
121
|
### Load Feature Knowledge
|
|
110
122
|
|
|
111
|
-
Resolve the
|
|
123
|
+
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
|
|
124
|
+
|
|
125
|
+
```bash
|
|
126
|
+
git -C "{start}" rev-parse --show-toplevel
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
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}`.
|
|
112
130
|
|
|
113
131
|
**Step 1 — Read the index cache:**
|
|
114
132
|
|
|
@@ -143,14 +161,14 @@ Concatenate the selected KNOWLEDGE.md files under slug headers:
|
|
|
143
161
|
|
|
144
162
|
If no KBs exist, no KBs are relevant, or `.devflow/features/` is absent, set `FEATURE_KNOWLEDGE` to `(none)`.
|
|
145
163
|
|
|
146
|
-
**
|
|
164
|
+
**One git call, then direct file reads — no `.cjs` script.** After resolving `{worktree}`, this step is 1 index read (or N frontmatter reads on fallback), bounded by KB count.
|
|
147
165
|
|
|
148
166
|
Pass `FEATURE_KNOWLEDGE` to the Triage agent in Phase 2.
|
|
149
167
|
|
|
150
168
|
**Resolve the evidence policy once per run**, from the repository root, before any step reads the values:
|
|
151
169
|
|
|
152
170
|
```bash
|
|
153
|
-
node "$
|
|
171
|
+
node "$HOME/.devflow/scripts/resolve-evidence-policy.cjs" 2>/dev/null; echo "exit=$?"
|
|
154
172
|
```
|
|
155
173
|
|
|
156
174
|
Accept the output only when it is exactly two lines: `exit=0` last and, before it, one line of the form `EVIDENCE_POLICY=<required|standard> SOURCE=<file|worktree|default|invalid|error> REF=<branch|none>[ WARN=<remote-unavailable|invalid-file|raised-by-compliance|pr-changes-policy>[,…]] ISSUE_REQUIRED=<true|false> APPLY_CONVENTIONS=<true|false> REQUIRE_NON_AUTHOR_APPROVAL=<true|false>` — these fields, in this order, nothing else, where `<branch>` is a branch name such as `main`. **Anything else** (a non-zero exit, no line, extra text, or a missing, reordered or unlisted field or value) ⇒ use `EVIDENCE_POLICY=required SOURCE=error REF=none ISSUE_REQUIRED=true APPLY_CONVENTIONS=true REQUIRE_NON_AUTHOR_APPROVAL=true` instead.
|
|
@@ -158,12 +176,22 @@ Accept the output only when it is exactly two lines: `exit=0` last and, before i
|
|
|
158
176
|
Set `EVIDENCE_POLICY`, `ISSUE_REQUIRED`, `APPLY_CONVENTIONS` and `REQUIRE_NON_AUTHOR_APPROVAL` from the accepted line. Pass agents only the three mechanism inputs, never `EVIDENCE_POLICY`. Report `Evidence policy: {EVIDENCE_POLICY} (source: {SOURCE})`, plus any `WARN` tokens as advisory, once in the final report.
|
|
159
177
|
Reuse this result for every worktree.
|
|
160
178
|
|
|
161
|
-
**Resolve
|
|
179
|
+
**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:
|
|
180
|
+
|
|
181
|
+
```bash
|
|
182
|
+
node "$HOME/.devflow/scripts/resolve-settings.cjs" "{root}" 2>/dev/null; echo "exit=$?"
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
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> LEARNING=<on|off> KNOWLEDGE=<on|off>` — 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 LEARNING=on KNOWLEDGE=off` instead.
|
|
162
186
|
|
|
163
|
-
|
|
187
|
+
The accepted line is the only source of these values: the script alone folds the committed `.devflow/project.json`, the personal `.devflow/config.json` and the machine manifest.
|
|
188
|
+
|
|
189
|
+
**Resolve `REVIEW_PUBLICATION` per worktree:** take `REVIEW_PUBLICATION` from that worktree's settings line, with `{root}` the worktree's root — multi-worktree repos may resolve different values per worktree. The line already caps the personal choice at the team's (D-PUBLICATION-CEILING), so it is `off`, `auto` or `full`, and `off` when the line was unresolvable.
|
|
190
|
+
|
|
191
|
+
**Evidence stub:** only when `EVIDENCE_POLICY` is `required`, a resolved `off` becomes `stub`, so a counts-only record still reaches the PR. `stub` is never a config value: the settings line never carries it.
|
|
164
192
|
|
|
165
193
|
Note: `auto` is NOT fail-open — under `auto`, the Git agent probes the repository visibility and treats any error or unrecognised value as PUBLIC (mode STUB). What each value does is decided by the Git agent's publication gate (`references/publication-gate.md` step 2); this partial only resolves the value.
|
|
166
|
-
Resolve this per worktree — unlike the evidence policy above, the
|
|
194
|
+
Resolve this per worktree — unlike the evidence policy above, the settings line is per worktree root. From the same line: `COMPLIANCE_FRAMEWORKS` is the settings line's `COMPLIANCE` with `generic` written `none`: `off`, `none`, or the framework ids the machine and this repository declare.
|
|
167
195
|
|
|
168
196
|
**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.
|
|
169
197
|
|
|
@@ -283,6 +311,7 @@ CREATE_PR: false
|
|
|
283
311
|
WORKTREE_PATH: {worktree_path} (omit if cwd)
|
|
284
312
|
DECISIONS_CONTEXT: {decisions_context}
|
|
285
313
|
FEATURE_KNOWLEDGE: {feature_knowledge}
|
|
314
|
+
COMPLIANCE_FRAMEWORKS: {COMPLIANCE_FRAMEWORKS}
|
|
286
315
|
Fix only the listed pre-classified FIX_NOW issues. Do not re-litigate dispositions.
|
|
287
316
|
Same-file issues → one commit. Include ## Verification block in report.
|
|
288
317
|
Regression fix without failing-then-passing regression test → BLOCKED."
|
|
@@ -353,7 +382,8 @@ Run build, typecheck, lint, test. Report pass/fail with failure details."
|
|
|
353
382
|
SCOPE: Fix only the listed failures, no other changes
|
|
354
383
|
PUSH: false
|
|
355
384
|
CREATE_PR: false
|
|
356
|
-
WORKTREE_PATH: {worktree_path} (omit if cwd)
|
|
385
|
+
WORKTREE_PATH: {worktree_path} (omit if cwd)
|
|
386
|
+
COMPLIANCE_FRAMEWORKS: {COMPLIANCE_FRAMEWORKS}"
|
|
357
387
|
```
|
|
358
388
|
- Loop back to re-validate
|
|
359
389
|
4. If `validation_retry_count > 2`: set VERIFICATION_STATUS = FAILED and exit the validation loop — record a blocking callout in the `## Verification` section (never a silent pass).
|
|
@@ -391,7 +421,7 @@ Otherwise, for each worktree with fixes:
|
|
|
391
421
|
3. **If NO_PR or NO_CI** → skip: "No PR/CI configured, skipping CI validation." Proceed to next phase.
|
|
392
422
|
4. **If PENDING** → poll every 60 seconds (global budget, see step 7). Re-spawn Git agent each poll. If PASSING → proceed. If still PENDING after budget exhausted → report "CI still running — verify manually before merging" and proceed.
|
|
393
423
|
5. **If INDETERMINATE** → poll as PENDING within the same budget. If still INDETERMINATE after budget exhausted → report "CI status unknown — verify manually before merging" and proceed.
|
|
394
|
-
6. **If FAILING** → report failing checks. Spawn `Agent(subagent_type="Code")` to fix CI failures based on check names and failure context. After fix, push and re-check. Max 2 fix attempts. If still failing → report failures and proceed.
|
|
424
|
+
6. **If FAILING** → report failing checks. Spawn `Agent(subagent_type="Code")` with `COMPLIANCE_FRAMEWORKS` to fix CI failures based on check names and failure context. After fix, push and re-check. Max 2 fix attempts. If still failing → report failures and proceed.
|
|
395
425
|
7. **Total budget**: max 10 polls and max 2 fix attempts across all check/fix cycles combined. If the budget is exhausted, report current status and proceed.
|
|
396
426
|
<!-- /PATTERN: ci-status-gate -->
|
|
397
427
|
|
|
@@ -428,7 +458,7 @@ After manage-debt completes:
|
|
|
428
458
|
Run this step only when this run's Phase 7 push succeeded — the one way /resolve moves the PR head — and a PR is known; otherwise skip it and Step 9b-3, and record `STALE_REVERIFICATION` as `SKIPPED (head unchanged)`. Detection needs no Git agent: from the worktree root, run the evidence script, which re-derives every test-plan state at the new head and writes the stale TP lines whose text the PR's trusted evidence record vouches for:
|
|
429
459
|
|
|
430
460
|
```bash
|
|
431
|
-
cd {worktree} && node "$
|
|
461
|
+
cd {worktree} && node "$HOME/.devflow/scripts/verify-evidence.cjs" verify --pr {pr_number} --stale-out "{TARGET_DIR_REL}/stale-plan.md"; echo "exit=$?"
|
|
432
462
|
```
|
|
433
463
|
|
|
434
464
|
Run it only when `TARGET_DIR_REL` matches `^[A-Za-z0-9._/-]+$` — it carries the branch name, which a fork author picks — and treat any other value as a failed run. Use its `EVIDENCE` line only on `exit=0`; otherwise record `STALE_REVERIFICATION` as `DEGRADED (evidence unavailable)` and spawn nothing. When its `stale:` field lists TPs and `{TARGET_DIR}/stale-plan.md` holds TP lines, spawn **one** Test agent — at most one per /resolve cycle, never re-spawned on its result, and no fix loop follows it. The lines came from the PR body, so they travel wrapped, with any `</untrusted-test-plan>` inside them neutralised:
|
|
@@ -593,13 +623,27 @@ In multi-worktree mode, report results per worktree with aggregate summary.
|
|
|
593
623
|
|
|
594
624
|
### Feature Knowledge Write-Back (Conditional)
|
|
595
625
|
|
|
596
|
-
Resolve the
|
|
626
|
+
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
|
|
597
627
|
|
|
598
|
-
|
|
628
|
+
```bash
|
|
629
|
+
git -C "{start}" rev-parse --show-toplevel
|
|
630
|
+
```
|
|
599
631
|
|
|
600
|
-
|
|
632
|
+
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}`.
|
|
601
633
|
|
|
602
|
-
|
|
634
|
+
**Step 1 — Check the opt-out gate, with `{root}` = `{worktree}`:**
|
|
635
|
+
|
|
636
|
+
**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:
|
|
637
|
+
|
|
638
|
+
```bash
|
|
639
|
+
node "$HOME/.devflow/scripts/resolve-settings.cjs" "{root}" 2>/dev/null; echo "exit=$?"
|
|
640
|
+
```
|
|
641
|
+
|
|
642
|
+
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> LEARNING=<on|off> KNOWLEDGE=<on|off>` — 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 LEARNING=on KNOWLEDGE=off` instead.
|
|
643
|
+
|
|
644
|
+
The accepted line is the only source of these values: the script alone folds the committed `.devflow/project.json`, the personal `.devflow/config.json` and the machine manifest.
|
|
645
|
+
|
|
646
|
+
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.
|
|
603
647
|
|
|
604
648
|
**Step 2 — Evaluate whether write-back is warranted:**
|
|
605
649
|
|
|
@@ -638,6 +682,10 @@ The frontmatter in KNOWLEDGE.md is the source of truth — index.md is only a ca
|
|
|
638
682
|
After writing, commit the two files to the current worktree branch yourself by running git via your Bash tool (do not use a script). Stage ONLY .devflow/features/index.md and .devflow/features/{slug}/KNOWLEDGE.md, then commit just those paths with a docs(knowledge): message. Do NOT push, do NOT force, do NOT stage anything else. Follow your Commit Protocol — it is non-blocking, so if any git step fails, report KB_COMMIT and finish normally."
|
|
639
683
|
```
|
|
640
684
|
|
|
685
|
+
**Step 4 — Surface an uncommitted knowledge base:**
|
|
686
|
+
|
|
687
|
+
When the Knowledge agent reports `KB_COMMIT: skipped (detached HEAD)`, the files were written but deliberately not committed — a commit on a detached HEAD becomes unreachable once HEAD moves. Tell the user in the workflow's final report, in one line, that the knowledge base was written but not committed, and name the uncommitted paths the agent listed, so they can commit them on a branch before the worktree is removed. Never commit them yourself.
|
|
688
|
+
|
|
641
689
|
**Failure handling**: Non-blocking. If the Knowledge agent fails, log the failure and continue — the workflow outcome is not affected by write-back success.
|
|
642
690
|
|
|
643
691
|
## Architecture
|
|
@@ -24,16 +24,28 @@ Detect changed files and build context:
|
|
|
24
24
|
4. Build TASK_DESCRIPTION from recent commit messages or branch name
|
|
25
25
|
### Load DECISIONS_CONTEXT
|
|
26
26
|
|
|
27
|
-
|
|
27
|
+
The decisions ledger belongs to the repository, not to one checkout: in a linked worktree it lives in the main worktree, and a session started in a subdirectory reads the copy at the repository root. Locate it with ONE git call, run from the start directory — `WORKTREE_PATH` if provided, otherwise cwd (`devflow:worktree-support`):
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
git -C "{start}" rev-parse --path-format=absolute --show-toplevel --git-common-dir
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Line 1 is the checkout's toplevel, line 2 the repository's common git directory. A git older than 2.31 echoes `--path-format=absolute` back as a line of its own first. `{ledger}` is the first of these that applies:
|
|
34
|
+
|
|
35
|
+
1. **The main worktree** — line 2 without its trailing `/.git`, when the output is exactly two lines each beginning with `/`, line 2 ends in `/.git`, and the directory left once it is removed is not your home directory and contains a `.devflow/` directory.
|
|
36
|
+
2. **The toplevel** — line 1, or on an older git the line after the echoed flag.
|
|
37
|
+
3. **The start directory itself** — when the command failed or printed no absolute toplevel (outside a git repository).
|
|
38
|
+
|
|
39
|
+
This is the rule the learning hooks apply (D-LEDGER-MAIN-WORKTREE, D-PROMPT-ROOT), so you read the index the Learning agent writes.
|
|
28
40
|
|
|
29
41
|
**Step 1 — Read the pre-rendered index:**
|
|
30
42
|
|
|
31
|
-
Attempt to read `{
|
|
43
|
+
Attempt to read `{ledger}/.devflow/learning/index.md`.
|
|
32
44
|
|
|
33
45
|
- If the file exists and contains non-empty content: use that content as `DECISIONS_CONTEXT`.
|
|
34
46
|
- If the file is absent or empty: set `DECISIONS_CONTEXT` to `(none)`.
|
|
35
47
|
|
|
36
|
-
|
|
48
|
+
The index is one direct file read, written at render time by `render-decisions.cjs` alongside `decisions.md`/`pitfalls.md` — no `.cjs` script runs here, and the index's own footer names the files that hold each entry's full body.
|
|
37
49
|
|
|
38
50
|
**Step 2 — Apply decisions using `devflow:apply-decisions`:**
|
|
39
51
|
|
|
@@ -43,7 +55,13 @@ Pass `DECISIONS_CONTEXT` to Scrutinize agent — the compact index lists active
|
|
|
43
55
|
|
|
44
56
|
### Load Feature Knowledge
|
|
45
57
|
|
|
46
|
-
Resolve the
|
|
58
|
+
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
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
git -C "{start}" rev-parse --show-toplevel
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
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}`.
|
|
47
65
|
|
|
48
66
|
**Step 1 — Read the index cache:**
|
|
49
67
|
|
|
@@ -78,7 +96,7 @@ Concatenate the selected KNOWLEDGE.md files under slug headers:
|
|
|
78
96
|
|
|
79
97
|
If no KBs exist, no KBs are relevant, or `.devflow/features/` is absent, set `FEATURE_KNOWLEDGE` to `(none)`.
|
|
80
98
|
|
|
81
|
-
**
|
|
99
|
+
**One git call, then direct file reads — no `.cjs` script.** After resolving `{worktree}`, this step is 1 index read (or N frontmatter reads on fallback), bounded by KB count.
|
|
82
100
|
|
|
83
101
|
Pass `FEATURE_KNOWLEDGE` to Scrutinize agent.
|
|
84
102
|
|
|
@@ -165,13 +183,27 @@ Display summary:
|
|
|
165
183
|
|
|
166
184
|
### Feature Knowledge Write-Back (Conditional)
|
|
167
185
|
|
|
168
|
-
Resolve the
|
|
186
|
+
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
|
|
169
187
|
|
|
170
|
-
|
|
188
|
+
```bash
|
|
189
|
+
git -C "{start}" rev-parse --show-toplevel
|
|
190
|
+
```
|
|
171
191
|
|
|
172
|
-
|
|
192
|
+
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}`.
|
|
173
193
|
|
|
174
|
-
|
|
194
|
+
**Step 1 — Check the opt-out gate, with `{root}` = `{worktree}`:**
|
|
195
|
+
|
|
196
|
+
**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:
|
|
197
|
+
|
|
198
|
+
```bash
|
|
199
|
+
node "$HOME/.devflow/scripts/resolve-settings.cjs" "{root}" 2>/dev/null; echo "exit=$?"
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
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> LEARNING=<on|off> KNOWLEDGE=<on|off>` — 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 LEARNING=on KNOWLEDGE=off` instead.
|
|
203
|
+
|
|
204
|
+
The accepted line is the only source of these values: the script alone folds the committed `.devflow/project.json`, the personal `.devflow/config.json` and the machine manifest.
|
|
205
|
+
|
|
206
|
+
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.
|
|
175
207
|
|
|
176
208
|
**Step 2 — Evaluate whether write-back is warranted:**
|
|
177
209
|
|
|
@@ -210,6 +242,10 @@ The frontmatter in KNOWLEDGE.md is the source of truth — index.md is only a ca
|
|
|
210
242
|
After writing, commit the two files to the current worktree branch yourself by running git via your Bash tool (do not use a script). Stage ONLY .devflow/features/index.md and .devflow/features/{slug}/KNOWLEDGE.md, then commit just those paths with a docs(knowledge): message. Do NOT push, do NOT force, do NOT stage anything else. Follow your Commit Protocol — it is non-blocking, so if any git step fails, report KB_COMMIT and finish normally."
|
|
211
243
|
```
|
|
212
244
|
|
|
245
|
+
**Step 4 — Surface an uncommitted knowledge base:**
|
|
246
|
+
|
|
247
|
+
When the Knowledge agent reports `KB_COMMIT: skipped (detached HEAD)`, the files were written but deliberately not committed — a commit on a detached HEAD becomes unreachable once HEAD moves. Tell the user in the workflow's final report, in one line, that the knowledge base was written but not committed, and name the uncommitted paths the agent listed, so they can commit them on a branch before the worktree is removed. Never commit them yourself.
|
|
248
|
+
|
|
213
249
|
**Failure handling**: Non-blocking. If the Knowledge agent fails, log the failure and continue — the workflow outcome is not affected by write-back success.
|
|
214
250
|
|
|
215
251
|
## Architecture
|
|
@@ -167,44 +167,44 @@ function collectMissingFragmentWarnings(fnName, activeFrameworks, fragments, omi
|
|
|
167
167
|
}
|
|
168
168
|
return warnings;
|
|
169
169
|
}
|
|
170
|
+
/**
|
|
171
|
+
* How a consumer picks framework references at run time (D-COMPLIANCE-REPO-LENS).
|
|
172
|
+
*
|
|
173
|
+
* Every framework reference is installed on every machine
|
|
174
|
+
* (D-COMPLIANCE-INSTALL-ALWAYS), so file presence no longer says which
|
|
175
|
+
* frameworks apply. The caller hands the agent `COMPLIANCE_FRAMEWORKS` — the
|
|
176
|
+
* `COMPLIANCE` field of the settings line, which folds this machine's selection
|
|
177
|
+
* with the repository's `.devflow/project.json` — and those ids alone are in force.
|
|
178
|
+
*/
|
|
179
|
+
const RUNTIME_SELECTION_LINES = [
|
|
180
|
+
'Every `references/{id}.md` is installed, so presence decides nothing: the ids you were given',
|
|
181
|
+
"(`COMPLIANCE_FRAMEWORKS`, this machine's plus the repository's) are the frameworks in force.",
|
|
182
|
+
'Load `references/{id}.md` for each given id and no other; `none` means generic controls only.',
|
|
183
|
+
'Apply generic controls always.',
|
|
184
|
+
'',
|
|
185
|
+
'NEVER fabricate framework-specific guidance for a framework you were not given.',
|
|
186
|
+
];
|
|
170
187
|
/**
|
|
171
188
|
* Build the ${DEVFLOW_COMPLIANCE_ACTIVE} substitution — the body of the
|
|
172
189
|
* Active Frameworks section.
|
|
173
190
|
*
|
|
174
|
-
*
|
|
175
|
-
*
|
|
176
|
-
*
|
|
177
|
-
*
|
|
191
|
+
* The stamp names the machine's own selection; zero frameworks is the neutral
|
|
192
|
+
* stamp a compliance-off machine's skill carries. Either way the section ends in
|
|
193
|
+
* RUNTIME_SELECTION_LINES, because the frameworks a run applies are the ids its
|
|
194
|
+
* caller passes, not the stamp.
|
|
178
195
|
*
|
|
179
196
|
* C5: a framework with no fragment still appears here — only its mapping row,
|
|
180
197
|
* checklist item and reference row are omitted.
|
|
181
198
|
*
|
|
182
|
-
* Frameworks the registry cannot label are dropped entirely:
|
|
183
|
-
*
|
|
199
|
+
* Frameworks the registry cannot label are dropped entirely: no label is emitted
|
|
200
|
+
* (see resolveRegistryFrameworks).
|
|
184
201
|
*/
|
|
185
202
|
function buildActiveSection(activeFrameworks) {
|
|
186
203
|
const resolved = resolveRegistryFrameworks(activeFrameworks);
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
'NEVER fabricate framework-specific guidance for absent `references/{id}.md` files.',
|
|
192
|
-
'If no reference file is present for a framework, apply generic controls only.',
|
|
193
|
-
].join('\n');
|
|
194
|
-
}
|
|
195
|
-
const labels = resolved.map(fw => fw.label);
|
|
196
|
-
const refList = resolved.map(fw => `\`references/${fw.id}.md\``).join(' and ');
|
|
197
|
-
return [
|
|
198
|
-
`**Active: ${labels.join(', ')}.**`,
|
|
199
|
-
'',
|
|
200
|
-
`Load ${refList} for framework-specific controls. Apply generic controls always.`,
|
|
201
|
-
'',
|
|
202
|
-
'File presence in the installed skill directory is the authoritative signal: if a',
|
|
203
|
-
'`references/{id}.md` file is absent, treat that framework as inactive regardless of',
|
|
204
|
-
'this list.',
|
|
205
|
-
'',
|
|
206
|
-
'NEVER fabricate framework-specific guidance for absent `references/{id}.md` files.',
|
|
207
|
-
].join('\n');
|
|
204
|
+
const stamp = resolved.length === 0
|
|
205
|
+
? 'The machine declares no framework.'
|
|
206
|
+
: `**Machine frameworks: ${resolved.map(fw => fw.label).join(', ')}.**`;
|
|
207
|
+
return [stamp, '', ...RUNTIME_SELECTION_LINES].join('\n');
|
|
208
208
|
}
|
|
209
209
|
/**
|
|
210
210
|
* Build the ${DEVFLOW_COMPLIANCE_MAPPING} substitution — the ENTIRE Framework
|