devflow-kit 3.5.0 → 3.7.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 +178 -1
- package/README.md +10 -6
- package/dist/agents/code.md +7 -11
- package/dist/agents/{diagnose.md → debug.md} +4 -4
- package/dist/agents/{code-fix.md → fix.md} +7 -8
- package/dist/agents/{scrutinize.md → harden.md} +6 -6
- package/dist/agents/{code-edit.md → refactor.md} +8 -9
- package/dist/agents/review.md +2 -0
- package/dist/cli/agents-view/render.js +1 -1
- package/dist/cli/commands/gates.js +276 -0
- package/dist/cli/commands/init-seed.js +9 -1
- package/dist/cli/commands/init.js +34 -11
- package/dist/cli/commands/learning.js +12 -12
- package/dist/cli/commands/legacy-hooks.js +1 -1
- package/dist/cli/commands/memory.js +18 -0
- package/dist/cli/commands/uninstall.js +111 -5
- package/dist/cli.js +2 -0
- package/dist/commands/bug-analysis.md +21 -17
- package/dist/commands/code-review.md +65 -66
- package/dist/commands/debug.md +17 -17
- package/dist/commands/dynamic-build.md +104 -116
- package/dist/commands/dynamic-plan.md +13 -11
- package/dist/commands/dynamic-profile.md +9 -7
- package/dist/commands/dynamic-tickets.md +13 -11
- package/dist/commands/explore.md +15 -15
- package/dist/commands/implement.md +80 -154
- package/dist/commands/plan.md +34 -66
- package/dist/commands/release.md +11 -7
- package/dist/commands/research.md +14 -10
- package/dist/commands/resolve.md +44 -88
- package/dist/commands/self-review.md +44 -44
- package/dist/core/agent-models.js +47 -11
- package/dist/core/{learning-tuning-config.js → curate-tuning-config.js} +14 -14
- package/dist/core/echo-value.js +42 -0
- package/dist/core/evidence-policy.js +17 -5
- package/dist/core/gate-level.js +213 -0
- package/dist/core/learning-queue-cleanup.js +1 -1
- package/dist/core/manifest.js +26 -10
- package/dist/core/migrations.js +63 -44
- package/dist/core/model-discovery.js +7 -1
- package/dist/core/plugins.js +14 -12
- package/dist/core/project-paths.js +3 -3
- package/dist/core/tracker.js +5 -33
- package/dist/hud/codex-usage.js +247 -0
- package/dist/hud/components/codex-quota.js +37 -0
- package/dist/hud/components/usage-quota.js +1 -1
- package/dist/hud/config.js +1 -0
- package/dist/hud/index.js +16 -3
- package/dist/hud/render.js +3 -1
- package/dist/learning-off/agents/code.md +7 -11
- package/dist/learning-off/agents/{diagnose.md → debug.md} +4 -4
- package/dist/learning-off/agents/{code-fix.md → fix.md} +7 -8
- package/dist/learning-off/agents/{scrutinize.md → harden.md} +6 -6
- package/dist/learning-off/agents/{code-edit.md → refactor.md} +8 -9
- package/dist/learning-off/agents/review.md +2 -0
- package/dist/learning-off/commands/bug-analysis.md +9 -9
- package/dist/learning-off/commands/code-review.md +54 -59
- package/dist/learning-off/commands/debug.md +6 -10
- package/dist/learning-off/commands/dynamic-build.md +98 -112
- package/dist/learning-off/commands/dynamic-plan.md +5 -5
- package/dist/learning-off/commands/dynamic-profile.md +1 -1
- package/dist/learning-off/commands/dynamic-tickets.md +5 -5
- package/dist/learning-off/commands/explore.md +4 -8
- package/dist/learning-off/commands/implement.md +68 -146
- package/dist/learning-off/commands/plan.md +23 -58
- package/dist/learning-off/commands/release.md +4 -2
- package/dist/learning-off/commands/research.md +2 -2
- package/dist/learning-off/commands/resolve.md +33 -81
- package/dist/learning-off/commands/self-review.md +32 -36
- package/dist/skills/git/references/pr/check-merge-readiness.md +2 -0
- package/dist/skills/git/references/pr/update-pr-evidence.md +4 -6
- package/dist/skills/git/references/tracker/github/ensure-pr-ready.md +7 -9
- package/dist/skills/git/references/tracker/jira/ensure-pr-ready.md +7 -15
- package/dist/skills/git/references/tracker/linear/ensure-pr-ready.md +7 -15
- package/dist/targets/claude-code/installer.js +117 -84
- package/dist/targets/claude-code/learning-install.js +15 -3
- package/dist/targets/claude-code/tracker-servers.js +1 -1
- package/package.json +1 -1
- package/src/assets/agents/_partials/_code.mds +7 -8
- package/src/assets/agents/code.mds +4 -7
- package/src/assets/agents/{learning.md → curate.md} +8 -10
- package/src/assets/agents/{diagnose.mds → debug.mds} +4 -4
- package/src/assets/agents/evaluate.md +4 -4
- package/src/assets/agents/{code-fix.mds → fix.mds} +5 -5
- package/src/assets/agents/{scrutinize.mds → harden.mds} +6 -6
- package/src/assets/agents/{simplify.md → polish.md} +4 -4
- package/src/assets/agents/{code-edit.mds → refactor.mds} +6 -6
- package/src/assets/agents/review.mds +2 -0
- package/src/assets/agents/synthesize.md +2 -2
- package/src/assets/agents/test.md +2 -2
- package/src/assets/commands/_partials/_compliance.mds +1 -1
- package/src/assets/commands/_partials/_decisions.mds +26 -6
- package/src/assets/commands/_partials/_engine.mds +15 -15
- package/src/assets/commands/_partials/_evidence_policy.mds +0 -17
- package/src/assets/commands/_partials/_knowledge.mds +14 -9
- package/src/assets/commands/_partials/_preamble.mds +4 -2
- package/src/assets/commands/_partials/_roster.mds +4 -4
- package/src/assets/commands/_partials/_settings.mds +2 -2
- package/src/assets/commands/_partials/_wave.mds +10 -17
- package/src/assets/commands/bug-analysis.mds +7 -7
- package/src/assets/commands/code-review.mds +51 -56
- package/src/assets/commands/debug.mds +2 -2
- package/src/assets/commands/dynamic-build.mds +67 -74
- package/src/assets/commands/implement.mds +65 -127
- package/src/assets/commands/plan.mds +21 -61
- package/src/assets/commands/release.mds +5 -1
- package/src/assets/commands/resolve.mds +28 -76
- package/src/assets/commands/self-review.mds +27 -27
- package/src/assets/mds/git/_ops_steps.mds +3 -3
- package/src/assets/mds/git/_pr.mds +6 -6
- 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/scripts/ci-wait.cjs +22 -4
- package/src/assets/scripts/claude-md-audit.cjs +66 -51
- package/src/assets/scripts/hooks/assets/orchestrator-charter.md +4 -3
- package/src/assets/scripts/hooks/background-memory-update +404 -95
- package/src/assets/scripts/hooks/capture-prompt +1 -1
- package/src/assets/scripts/hooks/capture-question +1 -1
- package/src/assets/scripts/hooks/capture-turn +1 -1
- package/src/assets/scripts/hooks/json-helper.cjs +13 -2
- package/src/assets/scripts/hooks/json-parse +18 -3
- package/src/assets/scripts/hooks/lib/learning-store.cjs +1 -1
- package/src/assets/scripts/hooks/lib/project-paths.cjs +4 -4
- package/src/assets/scripts/hooks/memory-permission +358 -0
- package/src/assets/scripts/hooks/preamble +1 -1
- package/src/assets/scripts/hooks/session-start-context +60 -47
- package/src/assets/scripts/hooks/session-start-memory +26 -5
- package/src/assets/scripts/lib/project-config.cjs +19 -4
- package/src/assets/scripts/resolve-settings.cjs +200 -32
- package/src/assets/scripts/verify-evidence.cjs +726 -9
- package/src/assets/skills/agent-references/SKILL.md +14 -6
- package/src/assets/skills/agent-references/references/commands/code-review-levels.md +19 -0
- package/src/assets/skills/agent-references/references/commands/implement-evidence-asks.md +35 -0
- package/src/assets/skills/agent-references/references/commands/implement-revalidate.md +15 -0
- package/src/assets/skills/agent-references/references/commands/plan-levels.md +40 -0
- package/src/assets/skills/agent-references/references/synthesize/bug-analysis.md +1 -1
- 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 +6 -4
- package/src/assets/skills/docs-framework/SKILL.md +3 -3
- package/src/assets/skills/qa/SKILL.md +1 -1
- package/src/assets/skills/quality-gates/SKILL.md +7 -7
- package/src/assets/skills/quality-gates/references/report-template.md +7 -7
- /package/src/assets/skills/agent-references/references/{learning → curate}/maintain.md +0 -0
|
@@ -102,11 +102,11 @@ For each issue reference in `SHIPPED_ISSUES` (sequentially, the first ≤50 in l
|
|
|
102
102
|
|
|
103
103
|
This is a sink check, not a provider check: the spawn that resolved the provider rendered the line, this spawn does not re-derive it, and you never decide it. Two bounds sit outside the pattern because an anchor cannot express them, and you apply both: the value is **rejected if it carries a newline** — anchors are read as end-of-LINE by some engines, and everything after the first line would land in the PR body as free text — and rejected if it exceeds **60 characters**, which no valid line approaches.
|
|
104
104
|
|
|
105
|
-
`(none)
|
|
105
|
+
`(none)` is **not a mismatch**: it means no line was captured — never compose one from `ISSUE_NUMBER`. A bare issue number is not a reference at all — the same digits name a different issue under each provider — which is why `TRACEABILITY: DEGRADED (ambiguous issue reference)` exists rather than a `#`-prefixed guess. On a MISMATCH, do not paste it and do not repair it — emit `TRACEABILITY: DEGRADED (issue reference "{ref}" does not match any tracker reference grammar)`.
|
|
106
106
|
|
|
107
|
-
This re-check is the only gate on that value — no operation checks the rendered line's shape before returning it — and it belongs at this paste because a value that was well-formed when it was produced is still attacker-influenceable text by the time it reaches a GitHub-visible sink. Never re-derive `ISSUE_BRANCH_TOKEN
|
|
107
|
+
This re-check is the only gate on that value — no operation checks the rendered line's shape before returning it — and it belongs at this paste because a value that was well-formed when it was produced is still attacker-influenceable text by the time it reaches a GitHub-visible sink. Never re-derive `ISSUE_BRANCH_TOKEN`; if the block is absent, say so.
|
|
108
108
|
|
|
109
|
-
**A given `ISSUE_PR_LINK` is final.** When it is given
|
|
109
|
+
**A given `ISSUE_PR_LINK` is final.** When it is given, `(none)` included, it is the section's whole answer, whether the gate above admitted it or refused it: step 4b does not resolve a number or render a line. An admitted line goes under `## Related Issues` in the body this step creates; on an existing PR whose body has no `## Related Issues` section, step 4b's PR-host half publishes it. Only an absent `ISSUE_PR_LINK` goes to step 4b, and only when no admitted wave block exists. When `ISSUE_NUMBER` is set and no line is admitted, emit the heading with no reference and `TRACEABILITY: DEGRADED (ambiguous issue reference)`; when it is `(none)`, write no heading.
|
|
110
110
|
|
|
111
111
|
**Pasting `PR_EXCEPTIONS`.** When `PR_EXCEPTIONS` is provided (not `(none)`), append it verbatim as the body's last section — it is scrubbed with the body. Re-check its shape first: its first line must be exactly `## Evidence Exceptions`, and every line after it must match this pattern as the WHOLE line:
|
|
112
112
|
|
|
@@ -260,6 +260,8 @@ Load for `check-merge-readiness` under every tracker provider.
|
|
|
260
260
|
|
|
261
261
|
### Process
|
|
262
262
|
|
|
263
|
+
Run the script from `WORKTREE_PATH` (else cwd) and print its stdout, nothing else: `node "$HOME/.devflow/scripts/verify-evidence.cjs" readiness --pr {PR_NUMBER}; echo "exit=$?"`, adding `--require-non-author-approval {REQUIRE_NON_AUTHOR_APPROVAL}` only when that is `true` or `false`, with the Bash `timeout` at 180000. On exit 0 or 2 its stdout is the `## Merge Readiness` block (exit 2: `DEGRADED`, closed by a `TRACEABILITY: DEGRADED ({reason})` line); any other exit, or empty stdout, is `TRACEABILITY: DEGRADED (readiness unavailable)`. The script makes the reads and applies the ladder below, so the steps are its specification: run none of them yourself.
|
|
264
|
+
|
|
263
265
|
1. Fetch unresolved review threads via GraphQL: `reviewThreads(first: 100) { nodes { isResolved } totalCount }`. Count unresolved from nodes (`isResolved == false`). If `totalCount > 100`, report the unresolved count as approximate: prefix with `>` and note `(count approximate — PR has more than 100 threads)`.
|
|
264
266
|
2. Fetch PR review decision: `gh pr view {PR_NUMBER} --json reviewDecision --jq '.reviewDecision'`
|
|
265
267
|
- Values: `APPROVED`, `CHANGES_REQUESTED`, `REVIEW_REQUIRED`, or null
|
|
@@ -289,16 +291,14 @@ Never take action on the PR — report READY or NOT_READY, always with the speci
|
|
|
289
291
|
|
|
290
292
|
Load for `update-pr-evidence` under every tracker provider.
|
|
291
293
|
|
|
292
|
-
**PR mechanics held here:** the
|
|
294
|
+
**PR mechanics held here:** the one script run. `verify-evidence.cjs publish` owns every step, marker, grammar and state rule, and scrubs (D11) each body before it posts one; nothing here restates any of them.
|
|
293
295
|
|
|
294
296
|
### Process
|
|
295
297
|
|
|
296
|
-
|
|
298
|
+
1. From `WORKTREE_PATH` (else cwd), run `node "$HOME/.devflow/scripts/verify-evidence.cjs" publish --pr {PR_NUMBER}; echo "exit=$?"`, adding `--publication {REVIEW_PUBLICATION}` only when that is `auto`, `full`, `off` or `stub`, and `--evidence "{EVIDENCE_FILE}"` when given — only a value matching `^[A-Za-z0-9._/-]{1,255}$` reaches the shell; any other is a failed run. Set the Bash `timeout` to 180000.
|
|
299
|
+
2. Print the script's stdout and nothing else. On exit 0 it is the `## PR Evidence` block: the heading, the line `EVIDENCE pr:<n> head:<sha> total:<n> VERIFIED-CI:<n> ATTESTED-LOCAL:<n> UNVERIFIED:<n> STALE:<n> FAILED:<n> INDETERMINATE:<n> stale:<ids|none> exceptions:<kinds|none> approval:<yes|no|unchecked> key:<hex> posted:<yes|no|n/a> body:<same|changed>`, and the `**Body**:` / `**Comment**:` line, then one `TRACEABILITY: DEGRADED ({reason})` line for each part that degraded, such as `DEGRADED (concurrent edit)` (the body edit then reads `SKIPPED`), `DEGRADED (body read-back mismatch)` or `DEGRADED (redaction unavailable)`: a body the script cannot scrub is never posted. On exit 2 it is `TRACEABILITY: DEGRADED (evidence unavailable)`. Any other exit, or empty stdout, is a failed run: emit that same line.
|
|
297
300
|
|
|
298
|
-
|
|
299
|
-
2. **Body**, only on `body:changed` (else `UNCHANGED`): `node "$V/redact-secrets.cjs" "$DEVFLOW_NOTES_RAW" "$DEVFLOW_NOTES" && node "$V/verify-evidence.cjs" splice --pr {PR_NUMBER} --state "$S" --block "$DEVFLOW_NOTES" --out "$DEVFLOW_BODY" && gh pr edit {PR_NUMBER} --body-file "$DEVFLOW_BODY"`. Only the composed block is scrubbed (D11); every byte outside its markers is the PR's own and stays identical. `splice` re-reads the body: unchanged since step 1 → it writes; changed → it splices once onto the fresh body and re-reads; changed again → `SPLICE conflict`: `SKIPPED` and `TRACEABILITY: DEGRADED (concurrent edit)`. Any other non-zero → `DEGRADED ({reason})`, naming a printed `SPLICE` token. No edit either way; go to step 4.
|
|
300
|
-
3. **Read back** after an edit: `node "$V/verify-evidence.cjs" readback --pr {PR_NUMBER} --expect "$DEVFLOW_BODY"`; anything but `READBACK ok` → `TRACEABILITY: DEGRADED (body read-back mismatch)`, else `EDITED`. GitHub has no conditional body edit: a human edit landing between the last re-read and `gh pr edit` is overwritten (it stays in the PR's edit history), and the read-back proves only that these bytes landed.
|
|
301
|
-
4. **Comment.** `posted:yes` → `SKIPPED`; `posted:n/a` → `OFF`. Otherwise apply the Comment-sink scrub (D11): `node "$V/redact-secrets.cjs" "$DEVFLOW_BODY_RAW" "$DEVFLOW_BODY" && gh pr comment {PR_NUMBER} --body-file "$DEVFLOW_BODY"` → `POSTED`. Never edit or delete an evidence comment. On 5xx retry once; still 5xx → `DEGRADED ({reason})`.
|
|
301
|
+
Run nothing else: the script makes the one PR read, the compare-and-swap body edit, its read-back and the append-only comment itself, and posts nothing it could not scrub.
|
|
302
302
|
@end
|
|
303
303
|
|
|
304
304
|
<!-- op: validate-branch -->
|
|
@@ -20,7 +20,7 @@ what the other holds:
|
|
|
20
20
|
EACH DEFINE STATES ITS OWN AUDIENCE, because this module's are not all the same.
|
|
21
21
|
`state_batch_line`, `traceable_issue_rules`, `wave_report_inputs`,
|
|
22
22
|
`conventions_step`, `branch_detection_step`, `closing_keyword_rule`,
|
|
23
|
-
`last_release_tag_step`, `trace_map_step` and `
|
|
23
|
+
`last_release_tag_step`, `trace_map_step`, `handoff_values` and `pr_link_resolution` are every
|
|
24
24
|
provider's, the CLI one included. `traceable_issue_rules` and `wave_report_inputs` are text moved out of
|
|
25
25
|
the always-loaded agent — the `ensure-traceable-issue` D3 section list and
|
|
26
26
|
untrusted-input rule, and the `post-wave-report` input definitions (its
|
|
@@ -54,19 +54,25 @@ happen before the run (GitHub writes the SHAs step 4 traced; a keyed provider
|
|
|
54
54
|
names its key). `handoff_values` renders the canonical
|
|
55
55
|
`### Handoff Values` forms per provider, which the contract block's Output template
|
|
56
56
|
(`_ops.mds`) leaves as placeholders.
|
|
57
|
-
|
|
58
|
-
|
|
57
|
+
`pr_link_resolution` is `ensure-pr-ready`'s step 4b after its first sentence, written once so the
|
|
58
|
+
three providers take the link line from the same source and refuse it in the same words. The
|
|
59
|
+
first sentence stays in each provider module, because it names that provider's line and because
|
|
60
|
+
the module tests read a provider's steps from its own source. The optional note is the provider's own and
|
|
61
|
+
covers closing effects only: the step renders nothing, because the Handoff Values line reaches it
|
|
62
|
+
already rendered.
|
|
63
|
+
|
|
64
|
+
The four ref pre-flight defines (`bare_number_rule` and the three heads below) are the
|
|
59
65
|
TOOL-CALL providers' only, and they are here rather than in `_mcp.mds` — where
|
|
60
66
|
their subject would put them — for a measured reason recorded at that module:
|
|
61
67
|
compiling `_jira.mds` against `_mcp.mds` doubles in cost per define added there
|
|
62
|
-
and stops finishing at twelve, while the same
|
|
68
|
+
and stops finishing at twelve, while the same defines cost under 1.2 s here. An
|
|
63
69
|
audience is a comment; a build that does not finish is not.
|
|
64
70
|
|
|
65
|
-
THE REF PRE-FLIGHT HEAD IS
|
|
71
|
+
THE REF PRE-FLIGHT HEAD IS THREE DEFINES, NOT ONE TAKING A MODE. The three differ
|
|
66
72
|
by what is being gated — one reference a caller named, a list, the always-loaded
|
|
67
|
-
entry gate
|
|
73
|
+
entry gate — while the grammar, the normalisation
|
|
68
74
|
step and the alternation warning arrive as arguments, so a provider needing none
|
|
69
|
-
of them pays for none of them.
|
|
75
|
+
of them pays for none of them. Three rather than one because `@if` is
|
|
70
76
|
BLOCK-structured: its expansion ends the line, and every one of the fourteen call
|
|
71
77
|
sites is a fragment in the middle of a markdown list item, so a mode parameter
|
|
72
78
|
would break the list the sites live in.
|
|
@@ -98,10 +104,6 @@ A **bare number** ⇒ `TRACEABILITY: DEGRADED (ambiguous issue reference)` — u
|
|
|
98
104
|
{{normalise}}Every entry of `SHIPPED_ISSUES` must satisfy {{grammar}}, anchored at both ends of the STRING (a newline fails it){{forms}} — this provider's grammar is what the entry gate's shape requirement means here, and the anchored form is what keeps a ref out of a query or a command. **Drop** every entry that fails and report it as `TRACEABILITY: DEGRADED (issue reference "{ref}" does not match {{provider}} reference grammar)`.
|
|
99
105
|
@end
|
|
100
106
|
|
|
101
|
-
@define ref_preflight_branch(match_phrase):
|
|
102
|
-
extract the segment {{match_phrase}} and verify it with the *fetch by key* capability. If the call fails, or the issue is not open, **skip silently** — never render a link for an unverified reference. A branch name can carry a token that merely looks like one, and the existence check is the guard.
|
|
103
|
-
@end
|
|
104
|
-
|
|
105
107
|
@define traceable_issue_rules():
|
|
106
108
|
**D3 issue template sections:** `## Initial Request`, `## Product Requirements`, `## Implementation Plan`. `TASK_DESCRIPTION`, `INITIAL_REQUEST`, `REQUIREMENTS` and `LABELS` are caller-supplied and untrusted — never interpolate them into a command string.
|
|
107
109
|
@end
|
|
@@ -132,6 +134,15 @@ extract the segment {{match_phrase}} and verify it with the *fetch by key* capab
|
|
|
132
134
|
**Handoff Values:** `Issue ID` = {{id_form}}; `PR link line` = `{{link_form}}`.
|
|
133
135
|
@end
|
|
134
136
|
|
|
137
|
+
@define pr_link_resolution(note = ""):
|
|
138
|
+
A given `ISSUE_PR_LINK` is already decided in step 4a: skip the resolution below. Resolution: the only source is the `PR link line` of the `### Handoff Values` block that `setup-task` or `fetch-issue` returned for this branch. Publish it only if it passes step 4a's shape check. A line that fails the check is refused as step 4a refuses it, not repaired: emit `TRACEABILITY: DEGRADED (issue reference "{ref}" does not match any tracker reference grammar)` and publish nothing. This step composes no line itself. Never compose a line from a bare issue number or a branch name.{{note}}
|
|
139
|
+
|
|
140
|
+
Publish the section through step 4b's PR-host half.
|
|
141
|
+
|
|
142
|
+
If no such line exists, skip silently.
|
|
143
|
+
A failure while updating the PR body emits `TRACEABILITY: DEGRADED ({reason})` and continues — a failed Related Issues update never blocks the PR.
|
|
144
|
+
@end
|
|
145
|
+
|
|
135
146
|
@define last_release_tag_step():
|
|
136
147
|
1a. **Last release tag.** Step 1's `git describe` can return a non-release marker tag. From `WORKTREE_PATH` (else cwd), run `node "$HOME/.devflow/scripts/release-trace.cjs" last-tag`: `LAST_TAG <tag>` ⇒ that tag is `{last_tag}`; `LAST_TAG none` ⇒ step 1's initial-commit rule; anything else ⇒ keep step 1's tag and report status `INDETERMINATE (last release tag unresolved)`.
|
|
137
148
|
@end
|
|
@@ -145,12 +156,12 @@ extract the segment {{match_phrase}} and verify it with the *fetch by key* capab
|
|
|
145
156
|
@export ref_preflight_single
|
|
146
157
|
@export ref_preflight_list
|
|
147
158
|
@export ref_preflight_entry
|
|
148
|
-
@export ref_preflight_branch
|
|
149
159
|
@export traceable_issue_rules
|
|
150
160
|
@export wave_report_inputs
|
|
151
161
|
@export conventions_step
|
|
152
162
|
@export branch_detection_step
|
|
153
163
|
@export closing_keyword_rule
|
|
154
164
|
@export handoff_values
|
|
165
|
+
@export pr_link_resolution
|
|
155
166
|
@export last_release_tag_step
|
|
156
167
|
@export trace_map_step
|
|
@@ -476,20 +476,13 @@ Load when the resolved tracker provider is `github` and the operation is `post-w
|
|
|
476
476
|
|
|
477
477
|
Load when the resolved tracker provider is `github` and the operation is `ensure-pr-ready`.
|
|
478
478
|
|
|
479
|
-
**Mechanics held here:** the whole operation. Steps 1–4a, the PR-host half of step 4b and steps 4c–6 are PR-host mechanics, the same under every provider (written once in `_ops.mds`); step 4b
|
|
479
|
+
**Mechanics held here:** the whole operation. Steps 1–4a, the PR-host half of step 4b and steps 4c–6 are PR-host mechanics, the same under every provider (written once in `_ops.mds`); step 4b takes its link line and refuses it the same way under every provider; the line itself, `Closes #{n}`, is this provider's.
|
|
480
480
|
|
|
481
481
|
### Process
|
|
482
482
|
|
|
483
483
|
{{opsteps.ensure_pr_ready_steps_to_4a()}}
|
|
484
484
|
|
|
485
|
-
4b. (ALWAYS-ON) Ensure PR body contains a `## Related Issues` section with `Closes #{n}`
|
|
486
|
-
a. Prefer the issue number returned by `setup-task` / `ensure-traceable-issue` for this branch.
|
|
487
|
-
b. If unavailable, fall back to the branch name pattern `{type}/{number}-{slug}`: extract the numeric segment and verify with `gh issue view {n} --json number,state`. If the call fails or `.state` is not `"open"`, skip silently — never add a `Closes` link for an unverified number. Branches like `chore/2026-cleanup` or `fix/2fa-login` may produce false matches; the existence check is the guard.
|
|
488
|
-
|
|
489
|
-
Publish the section through step 4b's PR-host half.
|
|
490
|
-
|
|
491
|
-
If no verified issue number is discoverable, skip silently.
|
|
492
|
-
On any 4xx/5xx from `gh pr edit` when updating the body: emit `TRACEABILITY: DEGRADED ({reason})` and continue — a failed Related Issues update never blocks the PR.
|
|
485
|
+
4b. (ALWAYS-ON) Ensure the PR body contains a `## Related Issues` section with the `Closes #{n}` line of this branch's issue. {{common.pr_link_resolution()}}
|
|
493
486
|
{{opsteps.ensure_pr_ready_steps_from_4c()}}
|
|
494
487
|
|
|
495
488
|
{{opsteps.ensure_pr_ready_pr_edit()}}
|
|
@@ -406,28 +406,15 @@ Load when the resolved tracker provider is `jira` and the operation is `post-wav
|
|
|
406
406
|
|
|
407
407
|
Load when the resolved tracker provider is `jira` and the operation is `ensure-pr-ready`.
|
|
408
408
|
|
|
409
|
-
**Mechanics held here:** the whole operation. Steps 1–4a, the PR-host half of step 4b and steps 4c–6 are PR-host mechanics, the same under every provider (written once in `_ops.mds`): devflow deliberately keeps pull requests on their existing host while the tracker is this one, so nothing about the PR surface is provider-dependent. Step 4b
|
|
409
|
+
**Mechanics held here:** the whole operation. Steps 1–4a, the PR-host half of step 4b and steps 4c–6 are PR-host mechanics, the same under every provider (written once in `_ops.mds`): devflow deliberately keeps pull requests on their existing host while the tracker is this one, so nothing about the PR surface is provider-dependent. Step 4b takes its link line and refuses it the same way under every provider; only its note on closing effects is this provider's.
|
|
410
410
|
|
|
411
411
|
### Process
|
|
412
412
|
|
|
413
413
|
{{opsteps.ensure_pr_ready_steps_to_4a()}}
|
|
414
414
|
|
|
415
|
-
4b. (ALWAYS-ON) Ensure the PR body contains a `## Related Issues` section
|
|
416
|
-
a. Prefer the issue key returned by `setup-task` / `ensure-traceable-issue` for this branch — it was verified at creation time.
|
|
417
|
-
b. Otherwise fall back to the branch name pattern `{type}/{KEY}-{slug}`: {{common.ref_preflight_branch("matching `^[A-Z][A-Z0-9_]{1,9}-[1-9][0-9]{0,8}$`")}}
|
|
418
|
-
c. The *fetch by key* capability absent or denied ⇒ `TRACEABILITY: DEGRADED (no tracker tool for fetch by key)` and skip the section; the PR is never blocked on it.
|
|
419
|
-
|
|
420
|
-
Render the line through `## Reference Rendering`. **This provider has no closing-reference magic** — a reference in a PR body does not transition or close anything here, and claiming otherwise in the rendered text would promise an effect that never happens; closing is a `## Transitions` matter and `gather-release-evidence` reports the absence as `TRACEABILITY: DEGRADED (unsupported by jira)`. `## Reference Rendering` absent, or its token discarded by the gate below ⇒ render the key on its own line under the section heading, and record the discard under `### Substitutions`.
|
|
421
|
-
|
|
422
|
-
Publish the section through step 4b's PR-host half.
|
|
423
|
-
|
|
424
|
-
If no verified issue key is discoverable, skip silently. A failure while updating the PR body emits `TRACEABILITY: DEGRADED ({reason})` and continues — a failed Related Issues update never blocks the PR.
|
|
415
|
+
4b. (ALWAYS-ON) Ensure the PR body contains a `## Related Issues` section with the `{{pr_link_default()}}` line of this branch's issue. {{common.pr_link_resolution(" **This provider has no closing-reference magic** — a reference in a PR body does not transition or close anything here, and claiming otherwise in the rendered text would promise an effect that never happens; closing is a `## Transitions` matter and `gather-release-evidence` reports the absence as `TRACEABILITY: DEGRADED (unsupported by jira)`.")}}
|
|
425
416
|
{{opsteps.ensure_pr_ready_steps_from_4c()}}
|
|
426
417
|
|
|
427
|
-
{{mcp.reference_rendering_gate()}}
|
|
428
|
-
|
|
429
|
-
**This provider's documented default is `{{pr_link_default()}}`.** It is stated here because it is a provider fact, and the gate above is what routes to it: a section that is absent, a file that is absent and a token the gate discarded all render this, and none of them is a degradation.
|
|
430
|
-
|
|
431
418
|
{{opsteps.ensure_pr_ready_pr_edit()}}
|
|
432
419
|
@end
|
|
433
420
|
|
|
@@ -448,28 +448,15 @@ Load when the resolved tracker provider is `linear` and the operation is `post-w
|
|
|
448
448
|
|
|
449
449
|
Load when the resolved tracker provider is `linear` and the operation is `ensure-pr-ready`.
|
|
450
450
|
|
|
451
|
-
**Mechanics held here:** the whole operation. Steps 1–4a, the PR-host half of step 4b and steps 4c–6 are PR-host mechanics, the same under every provider (written once in `_ops.mds`): devflow deliberately keeps pull requests on their existing host while the tracker is this one, so nothing about the PR surface is provider-dependent. Step 4b
|
|
451
|
+
**Mechanics held here:** the whole operation. Steps 1–4a, the PR-host half of step 4b and steps 4c–6 are PR-host mechanics, the same under every provider (written once in `_ops.mds`): devflow deliberately keeps pull requests on their existing host while the tracker is this one, so nothing about the PR surface is provider-dependent. Step 4b takes its link line and refuses it the same way under every provider; only its note on closing effects is this provider's.
|
|
452
452
|
|
|
453
453
|
### Process
|
|
454
454
|
|
|
455
455
|
{{opsteps.ensure_pr_ready_steps_to_4a()}}
|
|
456
456
|
|
|
457
|
-
4b. (ALWAYS-ON) Ensure the PR body contains a `## Related Issues` section
|
|
458
|
-
a. Prefer the issue reference returned by `setup-task` / `ensure-traceable-issue` for this branch — it was verified at creation time.
|
|
459
|
-
b. Otherwise fall back to the branch name pattern `{type}/{REF}-{slug}`: {{common.ref_preflight_branch("that, after ASCII-upper normalisation, satisfies `^[A-Z][A-Z0-9]{0,9}-[1-9][0-9]{0,8}$`")}}
|
|
460
|
-
c. The *fetch by key* capability absent or denied ⇒ `TRACEABILITY: DEGRADED (no tracker tool for fetch by key)` and skip the section; the PR is never blocked on it.
|
|
461
|
-
|
|
462
|
-
Render the line through `## Reference Rendering`. **This provider's magic words are the SERVER's behaviour, not a capability this operation controls.** A reference rendered in a PR body may or may not transition or close the issue depending on how the workspace is configured, and on how the PR host and the tracker are connected — so the rendered text **never claims an effect**: closing is a `## Transitions` matter, and `gather-release-evidence` reports the absence of a closing-reference capability as `TRACEABILITY: DEGRADED (unsupported by linear)`. Promising an effect that may not happen is worse than rendering a plain reference that always does. `## Reference Rendering` absent, or its token discarded by the gate below ⇒ render the reference on its own line under the section heading, and record the discard under `### Substitutions`.
|
|
463
|
-
|
|
464
|
-
Publish the section through step 4b's PR-host half.
|
|
465
|
-
|
|
466
|
-
If no verified issue reference is discoverable, skip silently. A failure while updating the PR body emits `TRACEABILITY: DEGRADED ({reason})` and continues — a failed Related Issues update never blocks the PR.
|
|
457
|
+
4b. (ALWAYS-ON) Ensure the PR body contains a `## Related Issues` section with the `{{pr_link_default()}}` line of this branch's issue. {{common.pr_link_resolution(" **This provider's magic words are the SERVER's behaviour, not a capability this operation controls.** A reference rendered in a PR body may or may not transition or close the issue depending on how the workspace is configured, and on how the PR host and the tracker are connected — so the rendered text **never claims an effect**: closing is a `## Transitions` matter, and `gather-release-evidence` reports the absence of a closing-reference capability as `TRACEABILITY: DEGRADED (unsupported by linear)`. Promising an effect that may not happen is worse than rendering a plain reference that always does.")}}
|
|
467
458
|
{{opsteps.ensure_pr_ready_steps_from_4c()}}
|
|
468
459
|
|
|
469
|
-
{{mcp.reference_rendering_gate()}}
|
|
470
|
-
|
|
471
|
-
**This provider's documented default is `{{pr_link_default()}}`.** It is stated here because it is a provider fact, and the gate above is what routes to it: a section that is absent, a file that is absent and a token the gate discarded all render this, and none of them is a degradation.
|
|
472
|
-
|
|
473
460
|
{{opsteps.ensure_pr_ready_pr_edit()}}
|
|
474
461
|
@end
|
|
475
462
|
|
|
@@ -383,6 +383,22 @@ function parseChecks(stdout) {
|
|
|
383
383
|
// The wait
|
|
384
384
|
// ---------------------------------------------------------------------------
|
|
385
385
|
|
|
386
|
+
/**
|
|
387
|
+
* One settle window, as a pure step. `firstAt` is when the condition was first seen,
|
|
388
|
+
* or null when the poll before did not see it; the window opens at `now` then. It is
|
|
389
|
+
* done once `settleMs` have passed since it opened. The caller keeps one clock per
|
|
390
|
+
* window and stores the returned `firstAt`.
|
|
391
|
+
*
|
|
392
|
+
* @param {number | null} firstAt
|
|
393
|
+
* @param {number} now
|
|
394
|
+
* @param {number} settleMs
|
|
395
|
+
* @returns {{ firstAt: number, done: boolean }}
|
|
396
|
+
*/
|
|
397
|
+
function settle(firstAt, now, settleMs) {
|
|
398
|
+
const opened = firstAt === null ? now : firstAt;
|
|
399
|
+
return { firstAt: opened, done: now - opened >= settleMs };
|
|
400
|
+
}
|
|
401
|
+
|
|
386
402
|
/**
|
|
387
403
|
* D-CI-HEAD-BINDING: wait for the CI verdict of `head`, and of nothing else. `gh pr
|
|
388
404
|
* checks` has no SHA field and reports the PR's current head, so each poll reads
|
|
@@ -471,8 +487,9 @@ async function waitForCi(input) {
|
|
|
471
487
|
const oid = parseHeadRefOid(view.stdout);
|
|
472
488
|
if (oid === null) return finish('INDETERMINATE', 'unparseable', [], []);
|
|
473
489
|
if (oid !== head) {
|
|
474
|
-
|
|
475
|
-
|
|
490
|
+
const mismatch = settle(firstMismatchAt, clock.now(), settleMs);
|
|
491
|
+
firstMismatchAt = mismatch.firstAt;
|
|
492
|
+
step = mismatch.done
|
|
476
493
|
? { state: 'done', result: finish('INDETERMINATE', 'head-mismatch', [], []) }
|
|
477
494
|
: { state: 'pending', pending: [] };
|
|
478
495
|
} else {
|
|
@@ -487,8 +504,9 @@ async function waitForCi(input) {
|
|
|
487
504
|
const rows = isResult ? parseChecks(checks.stdout) : [];
|
|
488
505
|
if (rows === null) return finish('INDETERMINATE', 'unparseable', [], []);
|
|
489
506
|
if (rows.length === 0) {
|
|
490
|
-
|
|
491
|
-
|
|
507
|
+
const empty = settle(firstEmptyAt, clock.now(), settleMs);
|
|
508
|
+
firstEmptyAt = empty.firstAt;
|
|
509
|
+
step = empty.done
|
|
492
510
|
? { state: 'done', result: finish('NO_CI', null, [], []) }
|
|
493
511
|
: { state: 'pending', pending: [] };
|
|
494
512
|
} else {
|
|
@@ -347,21 +347,71 @@ function readStampFile(stampPath) {
|
|
|
347
347
|
|
|
348
348
|
// ── The walk ───────────────────────────────────────────────────────────────────
|
|
349
349
|
|
|
350
|
+
/**
|
|
351
|
+
* Scan the head of the file at `p` for imports. It reads at most SCAN_BYTES and no
|
|
352
|
+
* more than `remaining`, the bytes the run may still read, and it changes nothing
|
|
353
|
+
* outside itself. `cut` is true when the run's byte budget shortens the scan, so
|
|
354
|
+
* imports may be missed.
|
|
355
|
+
*
|
|
356
|
+
* @param {string} p
|
|
357
|
+
* @param {number} size the file's size in bytes
|
|
358
|
+
* @param {number} remaining
|
|
359
|
+
* @returns {{ tokens: string[], bytes: number, cut: boolean }}
|
|
360
|
+
*/
|
|
361
|
+
function scanImports(p, size, remaining) {
|
|
362
|
+
const cut = remaining < Math.min(size, SCAN_BYTES);
|
|
363
|
+
const want = Math.min(size, SCAN_BYTES, remaining);
|
|
364
|
+
if (want <= 0) return { tokens: [], bytes: 0, cut };
|
|
365
|
+
const head = readHead(p, want);
|
|
366
|
+
if (head === null) return { tokens: [], bytes: 0, cut };
|
|
367
|
+
return { tokens: extractImports(head.text), bytes: head.bytes, cut };
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
/**
|
|
371
|
+
* The figures of one root from its `members`, which are in the order the walk reached
|
|
372
|
+
* them, breadth-first: whether the root exists, its size, the chain total, the largest
|
|
373
|
+
* file and the findings. The largest file is the first of the biggest, so a tie goes to
|
|
374
|
+
* the shorter route. It is pure.
|
|
375
|
+
*
|
|
376
|
+
* @param {string} rootPath
|
|
377
|
+
* @param {{ path: string, size: number, mtime: number, hop: number }[]} members
|
|
378
|
+
* @param {boolean} truncated whether the walk was cut short
|
|
379
|
+
*/
|
|
380
|
+
function summarizeMembers(rootPath, members, truncated) {
|
|
381
|
+
let total = 0;
|
|
382
|
+
let largest = null;
|
|
383
|
+
let exists = false;
|
|
384
|
+
let size = 0;
|
|
385
|
+
let mtime = 0;
|
|
386
|
+
const findings = [];
|
|
387
|
+
for (const m of members) {
|
|
388
|
+
total += m.size;
|
|
389
|
+
if (m.hop === 0) {
|
|
390
|
+
exists = true;
|
|
391
|
+
size = m.size;
|
|
392
|
+
mtime = m.mtime;
|
|
393
|
+
}
|
|
394
|
+
if (largest === null || m.size > largest.size) largest = { path: m.path, size: m.size };
|
|
395
|
+
if (m.hop >= 1 && m.size > FILE_THRESHOLD_BYTES) {
|
|
396
|
+
findings.push({ kind: 'file', path: m.path, size: m.size, mtime: m.mtime, hop: m.hop });
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
if (total > CHAIN_THRESHOLD_BYTES && largest !== null) {
|
|
400
|
+
findings.push({ kind: 'chain', path: rootPath, total, mtime, largest, truncated });
|
|
401
|
+
}
|
|
402
|
+
return { exists, size, total, largest, findings };
|
|
403
|
+
}
|
|
404
|
+
|
|
350
405
|
/**
|
|
351
406
|
* Walk one root's import chain breadth-first, so a file reached by two routes is
|
|
352
|
-
* judged at its shortest hop count.
|
|
407
|
+
* judged at its shortest hop count. This is the only function that changes the run's
|
|
408
|
+
* context `ctx`.
|
|
353
409
|
*/
|
|
354
410
|
function walkRoot(rootPath, ctx) {
|
|
355
411
|
const examined = new Map();
|
|
356
412
|
const seenReal = new Set();
|
|
357
413
|
const members = [];
|
|
358
|
-
const fileFindings = [];
|
|
359
|
-
let total = 0;
|
|
360
|
-
let largest = null;
|
|
361
414
|
let truncated = false;
|
|
362
|
-
let exists = false;
|
|
363
|
-
let rootSize = 0;
|
|
364
|
-
let rootMtime = 0;
|
|
365
415
|
const queue = [{ p: rootPath, hop: 0 }];
|
|
366
416
|
const queued = new Set([rootPath]);
|
|
367
417
|
|
|
@@ -389,32 +439,16 @@ function walkRoot(rootPath, ctx) {
|
|
|
389
439
|
seenReal.add(real);
|
|
390
440
|
ctx.counted.add(real);
|
|
391
441
|
|
|
392
|
-
|
|
393
|
-
total += st.size;
|
|
394
|
-
members.push({ path: p, size: st.size, mtime, hop });
|
|
395
|
-
if (hop === 0) {
|
|
396
|
-
exists = true;
|
|
397
|
-
rootSize = st.size;
|
|
398
|
-
rootMtime = mtime;
|
|
399
|
-
}
|
|
400
|
-
if (largest === null || st.size > largest.size) largest = { path: p, size: st.size };
|
|
401
|
-
if (hop >= 1 && st.size > FILE_THRESHOLD_BYTES) {
|
|
402
|
-
fileFindings.push({ kind: 'file', path: p, size: st.size, mtime, hop });
|
|
403
|
-
}
|
|
442
|
+
members.push({ path: p, size: st.size, mtime: Math.floor(st.mtimeMs / 1000), hop });
|
|
404
443
|
if (hop >= MAX_HOPS) continue;
|
|
405
444
|
|
|
406
|
-
const
|
|
407
|
-
|
|
408
|
-
if (remaining < Math.min(st.size, SCAN_BYTES)) {
|
|
409
|
-
// The run's byte budget cuts this scan short: imports may be missed, so the total is a lower bound.
|
|
445
|
+
const scan = scanImports(p, st.size, MAX_BYTES_READ - ctx.bytesRead);
|
|
446
|
+
if (scan.cut) {
|
|
410
447
|
truncated = true;
|
|
411
448
|
ctx.truncated = true;
|
|
412
449
|
}
|
|
413
|
-
|
|
414
|
-
const
|
|
415
|
-
if (head === null) continue;
|
|
416
|
-
ctx.bytesRead += head.bytes;
|
|
417
|
-
for (const token of extractImports(head.text)) {
|
|
450
|
+
ctx.bytesRead += scan.bytes;
|
|
451
|
+
for (const token of scan.tokens) {
|
|
418
452
|
const next = resolveImport(token, p, ctx.home);
|
|
419
453
|
if (examined.has(next) || queued.has(next)) continue;
|
|
420
454
|
queued.add(next);
|
|
@@ -422,28 +456,9 @@ function walkRoot(rootPath, ctx) {
|
|
|
422
456
|
}
|
|
423
457
|
}
|
|
424
458
|
|
|
425
|
-
const findings =
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
kind: 'chain',
|
|
429
|
-
path: rootPath,
|
|
430
|
-
total,
|
|
431
|
-
mtime: rootMtime,
|
|
432
|
-
largest,
|
|
433
|
-
truncated,
|
|
434
|
-
});
|
|
435
|
-
}
|
|
436
|
-
return {
|
|
437
|
-
path: rootPath,
|
|
438
|
-
exists,
|
|
439
|
-
size: rootSize,
|
|
440
|
-
total,
|
|
441
|
-
largest,
|
|
442
|
-
truncated,
|
|
443
|
-
members,
|
|
444
|
-
examined: [...examined.entries()].map(([p, flag]) => ({ path: p, flag })),
|
|
445
|
-
findings,
|
|
446
|
-
};
|
|
459
|
+
const { exists, size, total, largest, findings } = summarizeMembers(rootPath, members, truncated);
|
|
460
|
+
const examinedList = [...examined.entries()].map(([p, flag]) => ({ path: p, flag }));
|
|
461
|
+
return { path: rootPath, exists, size, total, largest, truncated, examined: examinedList, findings };
|
|
447
462
|
}
|
|
448
463
|
|
|
449
464
|
// ── Findings: keys and display ─────────────────────────────────────────────────
|
|
@@ -546,7 +561,7 @@ function audit(input) {
|
|
|
546
561
|
const stamp = renderStamp({ roots: input.roots, examined, keys });
|
|
547
562
|
return {
|
|
548
563
|
ok: true,
|
|
549
|
-
roots: roots.map(({
|
|
564
|
+
roots: roots.map(({ examined: _examined, findings: _findings, ...rest }) => rest),
|
|
550
565
|
findings,
|
|
551
566
|
examined,
|
|
552
567
|
filesExamined: ctx.counted.size,
|
|
@@ -5,16 +5,17 @@ Never do work-product mainline: no file edits, no builds, no multi-file reads, n
|
|
|
5
5
|
|
|
6
6
|
Routing (Agent tool) — pick the roster agent that fits the work:
|
|
7
7
|
- Search and listing: Explore. Codebase orientation: Skim.
|
|
8
|
-
- Execution against a spec: Code (write code to a plan; open the prompt with `OPERATION: <mode>` — `issue-fix` for pre-classified review issues, else `implement`),
|
|
8
|
+
- Execution against a spec: Code (write code to a plan; open the prompt with `OPERATION: <mode>` — `issue-fix` for pre-classified review issues, else `implement`), Refactor (a given mechanical change: "rename X to Y everywhere", moves, boilerplate; `OPERATION: edit`), Polish (judgment pass for clarity that keeps behaviour: "make this code cleaner"), Validate (build, typecheck, lint, test), Git (git/GitHub).
|
|
9
|
+
- Bug fix: Code (`OPERATION: implement`; `issue-fix` only for Triage-classified review issues). Fix: gate failures only (`validation-fix`, `alignment-fix`, `qa-fix`, `ci-fix`).
|
|
9
10
|
- Analysis, design, research: Design, Research, Review, Triage (validate review issues against blast-radius matrix).
|
|
10
|
-
- Real-scale work
|
|
11
|
+
- Real-scale work matching a workflow: invoke the full skill instead — devflow:implement, devflow:plan, devflow:research, devflow:explore, devflow:debug (all debug work, never the Debug agent), devflow:code-review, devflow:resolve.
|
|
11
12
|
- Anything else: the closest roster agent, never general-purpose.
|
|
12
13
|
|
|
13
14
|
Stays mainline (judgment work): conversation, decisions, routing, synthesizing agent reports, answers already in loaded context, one targeted Read to scope a delegation.
|
|
14
15
|
|
|
15
16
|
Operating rules:
|
|
16
17
|
- Decompose mainline. Subagents cannot spawn subagents — you own task breakdown, then delegate leaf tasks.
|
|
17
|
-
- Subagents see none of this conversation. Make every delegation self-contained: goal, constraints, relevant session decisions and facts, exact paths. A deliverable that draws on the conversation (issue, PR, report) needs
|
|
18
|
+
- Subagents see none of this conversation. Make every delegation self-contained: goal, constraints, relevant session decisions and facts, exact paths. A deliverable that draws on the conversation (issue, PR, report) needs its substance in the prompt, not a pointer.
|
|
18
19
|
- Report cap: ask every direct delegation for a final report of at most about 1,500 tokens — findings, paths and verdicts, not file dumps.
|
|
19
20
|
- Parallelize independent delegations in one message. Git operations stay sequential.
|
|
20
21
|
- Feature knowledge (direct delegations only — workflow skills handle their own): before delegating non-trivial code work, match the task area against .devflow/features/index.md and pass each matching KB's one to three most relevant `## Rules` bullets (verbatim, IDs included; a KB without Rules: Anti-Patterns or Gotchas entries, cited by section), its path and its `##` heading index as FEATURE_KNOWLEDGE; after delegated changes to a covered area, spawn Knowledge to refresh that KB.
|