devflow-kit 3.4.0 → 3.5.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 +29 -0
- package/README.md +8 -4
- package/dist/agents/code-edit.md +133 -0
- package/dist/agents/code-fix.md +165 -0
- package/dist/agents/code.md +39 -182
- package/dist/agents/design.md +0 -1
- package/dist/agents/git.md +31 -693
- package/dist/agents/knowledge.md +8 -2
- package/dist/agents/research.md +6 -0
- package/dist/agents/review.md +0 -4
- package/dist/agents/scrutinize.md +3 -0
- package/dist/agents/skim.md +4 -0
- package/dist/agents/triage.md +8 -1
- package/dist/cli/commands/behavior-prompts.js +77 -0
- package/dist/cli/commands/behavior.js +123 -0
- package/dist/cli/commands/flags.js +8 -2
- package/dist/cli/commands/init-seed.js +7 -3
- package/dist/cli/commands/init.js +72 -5
- package/dist/cli/commands/rules.js +16 -0
- package/dist/cli/commands/tracker.js +112 -15
- package/dist/cli.js +2 -0
- package/dist/commands/bug-analysis.md +5 -5
- package/dist/commands/code-review.md +14 -9
- package/dist/commands/debug.md +25 -4
- package/dist/commands/dynamic-build.md +28 -38
- package/dist/commands/dynamic-plan.md +11 -9
- package/dist/commands/dynamic-profile.md +3 -3
- package/dist/commands/dynamic-tickets.md +12 -10
- package/dist/commands/explore.md +3 -3
- package/dist/commands/implement.md +91 -125
- package/dist/commands/plan.md +15 -8
- package/dist/commands/release.md +3 -2
- package/dist/commands/research.md +16 -9
- package/dist/commands/resolve.md +20 -15
- package/dist/commands/self-review.md +2 -2
- package/dist/core/agent-frontmatter.js +101 -0
- package/dist/core/compliance-compose.js +6 -4
- package/dist/core/feature-switch.js +23 -2
- package/dist/core/flags.js +111 -0
- package/dist/core/manifest.js +11 -3
- package/dist/core/mds-variants.js +68 -26
- package/dist/core/plugins.js +42 -65
- package/dist/core/project-paths.js +0 -4
- package/dist/core/proxy-log.js +1 -1
- package/dist/core/proxy-state.js +1 -1
- package/dist/core/tracker.js +120 -2
- package/dist/learning-off/agents/code-edit.md +129 -0
- package/dist/learning-off/agents/code-fix.md +161 -0
- package/dist/learning-off/agents/code.md +37 -180
- package/dist/learning-off/agents/design.md +0 -1
- package/dist/learning-off/agents/knowledge.md +8 -2
- package/dist/learning-off/agents/research.md +6 -0
- package/dist/learning-off/agents/review.md +0 -4
- package/dist/learning-off/agents/scrutinize.md +3 -0
- package/dist/learning-off/agents/skim.md +4 -0
- package/dist/learning-off/agents/triage.md +8 -1
- package/dist/learning-off/commands/bug-analysis.md +3 -3
- package/dist/learning-off/commands/code-review.md +12 -7
- package/dist/learning-off/commands/debug.md +22 -2
- package/dist/learning-off/commands/dynamic-build.md +27 -37
- package/dist/learning-off/commands/dynamic-plan.md +10 -8
- package/dist/learning-off/commands/dynamic-profile.md +2 -2
- package/dist/learning-off/commands/dynamic-tickets.md +11 -9
- package/dist/learning-off/commands/explore.md +1 -1
- package/dist/learning-off/commands/implement.md +89 -123
- package/dist/learning-off/commands/plan.md +13 -6
- package/dist/learning-off/commands/release.md +3 -2
- package/dist/learning-off/commands/research.md +14 -7
- package/dist/learning-off/commands/resolve.md +18 -13
- package/dist/skills/git/references/learn-conventions.md +27 -3
- package/dist/skills/git/references/pr/check-ci-status.md +19 -0
- package/dist/skills/git/references/pr/check-merge-readiness.md +19 -0
- package/dist/skills/git/references/pr/fetch-review-threads.md +30 -0
- package/dist/skills/git/references/pr/post-resolution-summary.md +18 -0
- package/dist/skills/git/references/pr/post-review-summary.md +20 -0
- package/dist/skills/git/references/pr/resolve-review-threads.md +28 -4
- package/dist/skills/git/references/pr/update-pr-evidence.md +13 -0
- package/dist/skills/git/references/pr/validate-branch.md +26 -0
- package/dist/skills/git/references/tracker/github/associate-release.md +24 -0
- package/dist/skills/git/references/tracker/github/backlink-shipped-issues.md +31 -1
- package/dist/skills/git/references/tracker/github/create-release.md +30 -1
- package/dist/skills/git/references/tracker/github/ensure-pr-ready.md +89 -2
- package/dist/skills/git/references/tracker/github/ensure-traceable-issue.md +16 -1
- package/dist/skills/git/references/tracker/github/fetch-issue.md +36 -1
- package/dist/skills/git/references/tracker/github/fetch-issues-batch.md +47 -1
- package/dist/skills/git/references/tracker/github/gather-release-evidence.md +25 -0
- package/dist/skills/git/references/tracker/github/manage-debt.md +21 -1
- package/dist/skills/git/references/tracker/github/post-wave-report.md +15 -1
- package/dist/skills/git/references/tracker/github/setup-task.md +41 -1
- package/dist/skills/git/references/tracker/jira/associate-release.md +24 -0
- package/dist/skills/git/references/tracker/jira/backlink-shipped-issues.md +31 -1
- package/dist/skills/git/references/tracker/jira/create-release.md +30 -1
- package/dist/skills/git/references/tracker/jira/ensure-pr-ready.md +89 -2
- package/dist/skills/git/references/tracker/jira/ensure-traceable-issue.md +16 -1
- package/dist/skills/git/references/tracker/jira/fetch-issue.md +36 -1
- package/dist/skills/git/references/tracker/jira/fetch-issues-batch.md +47 -1
- package/dist/skills/git/references/tracker/jira/gather-release-evidence.md +25 -0
- package/dist/skills/git/references/tracker/jira/manage-debt.md +21 -1
- package/dist/skills/git/references/tracker/jira/post-wave-report.md +15 -1
- package/dist/skills/git/references/tracker/jira/setup-task.md +41 -1
- package/dist/skills/git/references/tracker/linear/associate-release.md +24 -0
- package/dist/skills/git/references/tracker/linear/backlink-shipped-issues.md +31 -1
- package/dist/skills/git/references/tracker/linear/create-release.md +30 -1
- package/dist/skills/git/references/tracker/linear/ensure-pr-ready.md +89 -2
- package/dist/skills/git/references/tracker/linear/ensure-traceable-issue.md +16 -1
- package/dist/skills/git/references/tracker/linear/fetch-issue.md +36 -1
- package/dist/skills/git/references/tracker/linear/fetch-issues-batch.md +47 -1
- package/dist/skills/git/references/tracker/linear/gather-release-evidence.md +25 -0
- package/dist/skills/git/references/tracker/linear/manage-debt.md +21 -1
- package/dist/skills/git/references/tracker/linear/post-wave-report.md +15 -1
- package/dist/skills/git/references/tracker/linear/setup-task.md +41 -1
- package/dist/targets/claude-code/agent-type-owner.js +164 -0
- package/dist/targets/claude-code/behavior-install.js +111 -0
- package/dist/targets/claude-code/installer.js +69 -2
- package/dist/targets/claude-code/learning-install.js +9 -1
- package/dist/targets/claude-code/tracker-install.js +33 -16
- package/dist/targets/claude-code/tracker-servers.js +107 -0
- package/package.json +4 -3
- package/src/assets/agents/_partials/_code.mds +109 -0
- package/src/assets/agents/code-edit.mds +81 -0
- package/src/assets/agents/code-fix.mds +113 -0
- package/src/assets/agents/code.mds +18 -222
- package/src/assets/agents/design.mds +0 -1
- package/src/assets/agents/evaluate.md +7 -1
- package/src/assets/agents/explore.md +58 -0
- package/src/assets/agents/git.mds +31 -693
- package/src/assets/agents/knowledge.mds +8 -2
- package/src/assets/agents/learning.md +19 -69
- package/src/assets/agents/research.mds +6 -0
- package/src/assets/agents/review.mds +0 -4
- package/src/assets/agents/scrutinize.mds +3 -0
- package/src/assets/agents/simplify.md +3 -0
- package/src/assets/agents/skim.mds +4 -0
- package/src/assets/agents/synthesize.md +26 -352
- package/src/assets/agents/test.md +8 -0
- package/src/assets/agents/tracker.md +20 -7
- package/src/assets/agents/triage.mds +8 -1
- package/src/assets/agents/validate.md +5 -0
- package/src/assets/commands/_partials/_compliance.mds +36 -0
- package/src/assets/commands/_partials/_decisions.mds +2 -2
- package/src/assets/commands/_partials/_engine.mds +8 -8
- package/src/assets/commands/_partials/_preamble.mds +3 -3
- package/src/assets/commands/_partials/_roster.mds +4 -3
- package/src/assets/commands/_partials/_wave.mds +2 -2
- package/src/assets/commands/bug-analysis.mds +3 -3
- package/src/assets/commands/code-review.mds +11 -8
- package/src/assets/commands/debug.mds +24 -2
- package/src/assets/commands/dynamic-build.mds +14 -25
- package/src/assets/commands/dynamic-plan.mds +4 -3
- package/src/assets/commands/dynamic-tickets.mds +5 -4
- package/src/assets/commands/explore.mds +1 -1
- package/src/assets/commands/implement.mds +89 -125
- package/src/assets/commands/plan.mds +12 -7
- package/src/assets/commands/release.mds +3 -2
- package/src/assets/commands/research.mds +14 -7
- package/src/assets/commands/resolve.mds +17 -14
- package/src/assets/mds/.mdsroot +4 -0
- package/src/assets/mds/git/_ops.mds +383 -0
- package/src/assets/mds/git/_ops_pr.mds +201 -0
- package/src/assets/mds/git/_ops_steps.mds +147 -0
- package/src/assets/mds/git/_pr.mds +39 -44
- package/src/assets/mds/git/_references.mds +6 -3
- package/src/assets/mds/tracker/_common.mds +5 -5
- package/src/assets/mds/tracker/_contract.mds +4 -3
- package/src/assets/mds/tracker/_github.mds +60 -14
- package/src/assets/mds/tracker/_jira.mds +60 -14
- package/src/assets/mds/tracker/_linear.mds +60 -14
- package/src/assets/mds/tracker/_steps.mds +10 -9
- package/src/assets/rules/behavior.md +6 -0
- package/src/assets/scripts/hooks/assets/orchestrator-charter.md +2 -1
- package/src/assets/scripts/hooks/lib/project-paths.cjs +0 -6
- package/src/assets/skills/agent-references/SKILL.md +33 -0
- package/src/assets/skills/agent-references/references/learning/maintain.md +71 -0
- package/src/assets/skills/agent-references/references/synthesize/bug-analysis.md +71 -0
- package/src/assets/skills/agent-references/references/synthesize/design.md +36 -0
- package/src/assets/skills/agent-references/references/synthesize/exploration.md +38 -0
- package/src/assets/skills/agent-references/references/synthesize/planning.md +60 -0
- package/src/assets/skills/agent-references/references/synthesize/research.md +61 -0
- package/src/assets/skills/agent-references/references/synthesize/review.md +76 -0
- package/src/assets/skills/compliance/SKILL.md +1 -1
- package/src/assets/skills/docs-framework/SKILL.md +80 -83
- package/src/assets/skills/docs-framework/references/patterns.md +14 -25
- package/src/assets/skills/docs-framework/references/violations.md +7 -7
- package/src/assets/skills/gap-analysis/SKILL.md +0 -16
- package/src/assets/skills/gap-analysis/references/compliance.md +19 -0
- package/dist/skills/git/references/pr/ensure-pr-ready.md +0 -24
|
@@ -16,18 +16,22 @@
|
|
|
16
16
|
* --set converges the sentinel in BOTH directions, so flipping
|
|
17
17
|
* back to github removes what flipping away wrote.
|
|
18
18
|
* A failed re-arm or sentinel step warns, it never aborts.
|
|
19
|
+
* --servers sets the machine's tracker tool servers (D-TRACKER-SERVER-ALLOWLIST) and
|
|
20
|
+
* re-stamps the installed Git and Tracker agents at once; it is orthogonal to --set and
|
|
21
|
+
* neither flag touches the other's manifest field.
|
|
19
22
|
*/
|
|
20
23
|
import { Command } from 'commander';
|
|
21
24
|
import { promises as fs } from 'fs';
|
|
22
25
|
import * as path from 'path';
|
|
23
26
|
import * as p from '@clack/prompts';
|
|
24
27
|
import color from 'picocolors';
|
|
25
|
-
import { DEFAULT_TRACKER_PROVIDER, TRACKER_ATTEMPTS_MAX, TRACKER_CONVENTIONS_READ_BYTES, TRACKER_PROVIDERS, applyTrackerSentinel, describeTrackerValue, parseTrackerFrontmatter, parseTrackerId, readBoundedHead, rearmTrackerInference, trackerConventionsPath, } from '../../core/tracker.js';
|
|
28
|
+
import { DEFAULT_TRACKER_PROVIDER, TRACKER_ATTEMPTS_MAX, TRACKER_CONVENTIONS_READ_BYTES, TRACKER_PROVIDERS, applyTrackerSentinel, describeTrackerValue, effectiveTrackerServers, parseTrackerFrontmatter, parseTrackerId, parseTrackerServers, readBoundedHead, rearmTrackerInference, trackerConventionsPath, } from '../../core/tracker.js';
|
|
26
29
|
import { readManifest, syncManifestFeature } from '../../core/manifest.js';
|
|
27
30
|
import { loadSettingsModule, personalConfigTrackedWarning, repoTrackerSelection } from '../../core/evidence-policy.js';
|
|
28
31
|
import { getClaudeDirectory, getDevFlowDirectory } from '../../targets/claude-code/claude-paths.js';
|
|
29
32
|
import { SKILL_REFS_SKILL_NAME, installedReferenceManifest } from '../../core/mds-variants.js';
|
|
30
33
|
import { prefixSkillName } from '../../core/plugins.js';
|
|
34
|
+
import { TRACKER_STAMPED_AGENTS, restampTrackerAgents, } from '../../targets/claude-code/tracker-servers.js';
|
|
31
35
|
/**
|
|
32
36
|
* Read the provenance header of `~/.devflow/tracker/{provider}.md`.
|
|
33
37
|
*
|
|
@@ -112,6 +116,10 @@ export async function readTrackerStatusConventions(devflowDir, provider) {
|
|
|
112
116
|
provenance: await readTrackerProvenance(devflowDir, provider),
|
|
113
117
|
};
|
|
114
118
|
}
|
|
119
|
+
/** Render the tracker servers for the `--status` note. Pure; every name was validated at its boundary. */
|
|
120
|
+
export function formatTrackerServers(list, isDefault) {
|
|
121
|
+
return `${list.join(', ')}${isDefault ? ` ${color.dim('(default)')}` : ''}`;
|
|
122
|
+
}
|
|
115
123
|
/**
|
|
116
124
|
* The `--status` note's lines. Pure.
|
|
117
125
|
*
|
|
@@ -131,7 +139,7 @@ export function formatTrackerStatus(input) {
|
|
|
131
139
|
}
|
|
132
140
|
lines.push(...(input.conventions.kind === 'none'
|
|
133
141
|
? ['Conventions: none (GitHub needs no learned conventions)', 'File: none']
|
|
134
|
-
: [`Conventions: ${formatTrackerProvenance(input.conventions.provenance)}`, `File: ${input.conventions.file}`]), `Mechanics: ${formatTrackerMechanics(input.mechanics)}`, `Inference: ${input.inference}`);
|
|
142
|
+
: [`Conventions: ${formatTrackerProvenance(input.conventions.provenance)}`, `File: ${input.conventions.file}`]), `Mechanics: ${formatTrackerMechanics(input.mechanics)}`, `Servers: ${formatTrackerServers(input.servers.list, input.servers.isDefault)}`, `Inference: ${input.inference}`);
|
|
135
143
|
return lines.join('\n');
|
|
136
144
|
}
|
|
137
145
|
/** The real adapter — the ONE binding of each operation into the `--set` path. */
|
|
@@ -164,7 +172,8 @@ export function buildTrackerSetIO() {
|
|
|
164
172
|
export async function runTrackerSet(opts) {
|
|
165
173
|
const { devflowDir, current, requested, io } = opts;
|
|
166
174
|
const messages = [];
|
|
167
|
-
|
|
175
|
+
// The provider changes; the tracker servers are a different setting and ride along.
|
|
176
|
+
await io.syncManifest(devflowDir, { ...current, provider: requested });
|
|
168
177
|
// [DR-22] a selection change re-arms the attempt counters; [DR-10] the
|
|
169
178
|
// sentinel converges in both directions.
|
|
170
179
|
const rearm = await io.rearmInference(devflowDir);
|
|
@@ -180,18 +189,72 @@ export async function runTrackerSet(opts) {
|
|
|
180
189
|
});
|
|
181
190
|
return { provider: requested, messages };
|
|
182
191
|
}
|
|
192
|
+
/** The real adapter — the ONE binding of each operation into the `--servers` path. */
|
|
193
|
+
export function buildTrackerServersIO() {
|
|
194
|
+
return {
|
|
195
|
+
syncManifest: (devflowDir, state) => syncManifestFeature(devflowDir, 'tracker', state),
|
|
196
|
+
restamp: (claudeDir, servers, warn) => restampTrackerAgents({ claudeDir, servers, warn }),
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* Set the machine's tracker tool servers.
|
|
201
|
+
*
|
|
202
|
+
* Follows `--set`'s convergence order (D-TRACKER-CONVERGE-SET): the manifest first, then
|
|
203
|
+
* the installed agents, which are re-stamped ONLY when the manifest write landed, so an
|
|
204
|
+
* installed agent never names a list the manifest does not record. Unlike `--set`, a failed
|
|
205
|
+
* manifest write is the whole command failing (there is nothing else for it to do), so it is
|
|
206
|
+
* returned as `ok: false` for the caller to exit on; a failed re-stamp warns, it never aborts.
|
|
207
|
+
*
|
|
208
|
+
* `default` removes the key, so an absent `servers` stays the one spelling of the default.
|
|
209
|
+
* Never throws.
|
|
210
|
+
*/
|
|
211
|
+
export async function runTrackerServers(opts) {
|
|
212
|
+
const { devflowDir, claudeDir, current, requested, io } = opts;
|
|
213
|
+
const messages = [];
|
|
214
|
+
const next = requested.kind === 'default'
|
|
215
|
+
? { provider: current.provider }
|
|
216
|
+
: { provider: current.provider, servers: requested.servers };
|
|
217
|
+
try {
|
|
218
|
+
await io.syncManifest(devflowDir, next);
|
|
219
|
+
}
|
|
220
|
+
catch (err) {
|
|
221
|
+
messages.push({
|
|
222
|
+
level: 'error',
|
|
223
|
+
text: `Could not write the manifest — the tracker servers were not changed (${err instanceof Error ? err.message : String(err)})`,
|
|
224
|
+
});
|
|
225
|
+
return { ok: false, state: current, messages };
|
|
226
|
+
}
|
|
227
|
+
const servers = effectiveTrackerServers(next);
|
|
228
|
+
const unchanged = servers.join('\n') === effectiveTrackerServers(current).join('\n');
|
|
229
|
+
const label = `${servers.join(', ')}${requested.kind === 'default' ? ' (default)' : ''}`;
|
|
230
|
+
messages.push({ level: unchanged ? 'info' : 'success', text: `Tracker servers: ${label}${unchanged ? ' (unchanged)' : ''}` });
|
|
231
|
+
const restamp = await io.restamp(claudeDir, servers, (message) => messages.push({ level: 'warn', text: message }));
|
|
232
|
+
const done = restamp.rewritten.length + restamp.unchanged.length;
|
|
233
|
+
if (restamp.absent.length === TRACKER_STAMPED_AGENTS.length && restamp.failed.length === 0) {
|
|
234
|
+
messages.push({ level: 'info', text: 'No installed Git or Tracker agent to update — run devflow init' });
|
|
235
|
+
}
|
|
236
|
+
else if (restamp.rewritten.length > 0) {
|
|
237
|
+
messages.push({ level: 'info', text: `Updated the installed ${restamp.rewritten.join(' and ')} agent${restamp.rewritten.length > 1 ? 's' : ''}` });
|
|
238
|
+
}
|
|
239
|
+
else if (done > 0 && restamp.failed.length === 0) {
|
|
240
|
+
messages.push({ level: 'info', text: 'The installed agents already carry this list' });
|
|
241
|
+
}
|
|
242
|
+
return { ok: true, state: next, messages };
|
|
243
|
+
}
|
|
183
244
|
export const trackerCommand = new Command('tracker')
|
|
184
|
-
.description('Show or set the machine\'s issue tracker provider')
|
|
245
|
+
.description('Show or set the machine\'s issue tracker provider and tracker servers')
|
|
185
246
|
.option('--status', 'Show the provider in effect and its learned conventions file, and re-arm background inference')
|
|
186
247
|
.option('--set <id>', 'Set the machine\'s default issue tracker provider: github, jira, or linear')
|
|
248
|
+
.option('--servers <names>', 'Set the tracker servers the Git and Tracker agents may call: comma-separated names, or "default"')
|
|
187
249
|
.action(async (options) => {
|
|
188
250
|
const devflowDir = getDevFlowDirectory();
|
|
189
|
-
const hasFlag = options.status || options.set !== undefined;
|
|
251
|
+
const hasFlag = options.status || options.set !== undefined || options.servers !== undefined;
|
|
190
252
|
if (!hasFlag) {
|
|
191
253
|
p.intro(color.bgCyan(color.white(' Tracker ')));
|
|
192
254
|
const validIds = TRACKER_PROVIDERS.map(t => `${t.id} — ${t.hint}`).join('\n ');
|
|
193
255
|
p.note(`${color.cyan('devflow tracker --status')} Show the provider and learned conventions\n` +
|
|
194
|
-
`${color.cyan('devflow tracker --set <id>')} Set the machine's default provider\n
|
|
256
|
+
`${color.cyan('devflow tracker --set <id>')} Set the machine's default provider\n` +
|
|
257
|
+
`${color.cyan('devflow tracker --servers <names>')} Set the tracker servers the agents may call\n\n` +
|
|
195
258
|
`Valid provider IDs:\n ${validIds}`, 'Usage');
|
|
196
259
|
p.outro(color.dim('github is the default — devflow tracker --set github returns to it'));
|
|
197
260
|
return;
|
|
@@ -206,7 +269,17 @@ export const trackerCommand = new Command('tracker')
|
|
|
206
269
|
}
|
|
207
270
|
setProvider = parsed.value;
|
|
208
271
|
}
|
|
209
|
-
|
|
272
|
+
// Validate --servers the same way: a bad name exits before any I/O, never repaired.
|
|
273
|
+
let setServers;
|
|
274
|
+
if (options.servers !== undefined) {
|
|
275
|
+
const parsed = parseTrackerServers(options.servers);
|
|
276
|
+
if (!parsed.ok) {
|
|
277
|
+
p.log.error(parsed.error);
|
|
278
|
+
process.exit(1);
|
|
279
|
+
}
|
|
280
|
+
setServers = parsed.value;
|
|
281
|
+
}
|
|
282
|
+
const manifest = await readManifest(devflowDir, { onWarning: (message) => p.log.warn(message) });
|
|
210
283
|
if (!manifest) {
|
|
211
284
|
p.log.error('No manifest found. Run devflow init first.');
|
|
212
285
|
process.exit(1);
|
|
@@ -238,6 +311,7 @@ export const trackerCommand = new Command('tracker')
|
|
|
238
311
|
selection,
|
|
239
312
|
conventions,
|
|
240
313
|
mechanics,
|
|
314
|
+
servers: { list: effectiveTrackerServers(current), isDefault: current.servers === undefined },
|
|
241
315
|
inference,
|
|
242
316
|
}), 'Tracker Status');
|
|
243
317
|
if (!statusRearm.ok)
|
|
@@ -248,13 +322,34 @@ export const trackerCommand = new Command('tracker')
|
|
|
248
322
|
return;
|
|
249
323
|
}
|
|
250
324
|
// ── Set ────────────────────────────────────────────────────────────────────
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
325
|
+
// `--set` and `--servers` are independent settings and may be given together: the provider
|
|
326
|
+
// first, then the servers against the state it left.
|
|
327
|
+
const messages = [];
|
|
328
|
+
let state = current;
|
|
329
|
+
if (setProvider !== undefined) {
|
|
330
|
+
const outcome = await runTrackerSet({
|
|
331
|
+
devflowDir,
|
|
332
|
+
current,
|
|
333
|
+
requested: setProvider,
|
|
334
|
+
io: buildTrackerSetIO(),
|
|
335
|
+
});
|
|
336
|
+
messages.push(...outcome.messages);
|
|
337
|
+
state = { ...current, provider: outcome.provider };
|
|
338
|
+
}
|
|
339
|
+
let failed = false;
|
|
340
|
+
if (setServers !== undefined) {
|
|
341
|
+
const outcome = await runTrackerServers({
|
|
342
|
+
devflowDir,
|
|
343
|
+
claudeDir: getClaudeDirectory(),
|
|
344
|
+
current: state,
|
|
345
|
+
requested: setServers,
|
|
346
|
+
io: buildTrackerServersIO(),
|
|
347
|
+
});
|
|
348
|
+
messages.push(...outcome.messages);
|
|
349
|
+
state = outcome.state;
|
|
350
|
+
failed = !outcome.ok;
|
|
351
|
+
}
|
|
352
|
+
for (const msg of messages) {
|
|
258
353
|
switch (msg.level) {
|
|
259
354
|
case 'success':
|
|
260
355
|
p.log.success(msg.text);
|
|
@@ -270,7 +365,9 @@ export const trackerCommand = new Command('tracker')
|
|
|
270
365
|
break;
|
|
271
366
|
}
|
|
272
367
|
}
|
|
273
|
-
if (
|
|
368
|
+
if (failed)
|
|
369
|
+
process.exit(1);
|
|
370
|
+
if (setProvider !== undefined && state.provider !== DEFAULT_TRACKER_PROVIDER) {
|
|
274
371
|
p.log.info(color.dim('Your issue conventions are learned in the background at the next session start'));
|
|
275
372
|
}
|
|
276
373
|
});
|
package/dist/cli.js
CHANGED
|
@@ -19,6 +19,7 @@ import { safeDeleteCommand } from './cli/commands/safe-delete.js';
|
|
|
19
19
|
import { proxyCommand } from './cli/commands/proxy.js';
|
|
20
20
|
import { agentsCommand } from './cli/commands/agents.js';
|
|
21
21
|
import { complianceCommand } from './cli/commands/compliance.js';
|
|
22
|
+
import { behaviorCommand } from './cli/commands/behavior.js';
|
|
22
23
|
import { trackerCommand } from './cli/commands/tracker.js';
|
|
23
24
|
const __filename = fileURLToPath(import.meta.url);
|
|
24
25
|
const __dirname = dirname(__filename);
|
|
@@ -48,6 +49,7 @@ program.addCommand(safeDeleteCommand);
|
|
|
48
49
|
program.addCommand(proxyCommand);
|
|
49
50
|
program.addCommand(agentsCommand);
|
|
50
51
|
program.addCommand(complianceCommand);
|
|
52
|
+
program.addCommand(behaviorCommand);
|
|
51
53
|
program.addCommand(trackerCommand);
|
|
52
54
|
// Handle no command (bare `devflow`) or unknown subcommand.
|
|
53
55
|
// When Commander sees an unrecognised first argument it does not route to any
|
|
@@ -38,7 +38,7 @@ git -C "{start}" rev-parse --show-toplevel
|
|
|
38
38
|
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.
|
|
39
39
|
|
|
40
40
|
Render the test-plan block from `/implement`'s evidence file, and from nothing else:
|
|
41
|
-
1. `branch_slug` is `git branch --show-current` with every `/` replaced by `-`.
|
|
41
|
+
1. `branch_slug` is `git -C "{worktree}" branch --show-current` with every `/` replaced by `-`.
|
|
42
42
|
2. Only when `branch_slug` matches `^[A-Za-z0-9._-]{1,200}$` and the file exists, run (the path double-quoted):
|
|
43
43
|
|
|
44
44
|
```bash
|
|
@@ -218,9 +218,9 @@ Attempt to read `{ledger}/.devflow/learning/index.md`.
|
|
|
218
218
|
|
|
219
219
|
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.
|
|
220
220
|
|
|
221
|
-
**Step 2 —
|
|
221
|
+
**Step 2 — Agents apply the decisions:**
|
|
222
222
|
|
|
223
|
-
When `DECISIONS_CONTEXT` is not `(none)`, follow `devflow:apply-decisions
|
|
223
|
+
When `DECISIONS_CONTEXT` is not `(none)`, hand it only to the agents whose contract declares it. They follow `devflow:apply-decisions`: scan the index, identify plausibly-relevant entries, Read full entry bodies on demand, and cite verbatim IDs in their reasoning. A host that uses the index in its own thread says so in its own step.
|
|
224
224
|
|
|
225
225
|
#### Feature Knowledge
|
|
226
226
|
|
|
@@ -281,8 +281,8 @@ A KB with no Rules section labels its entries `Rules ({section name}):` and give
|
|
|
281
281
|
|
|
282
282
|
#### Plan Artifact
|
|
283
283
|
|
|
284
|
-
1. List `{worktree}/.devflow/docs/design/*.md`
|
|
285
|
-
2. Read the most recent file
|
|
284
|
+
1. List the design plans: `{worktree}/.devflow/docs/design/*.md` (a `/plan` artifact) and `{worktree}/.devflow/docs/design/*/*/*-plan.md` (a `/dynamic-plan` per-ticket plan). Sort by timestamp, newest first, and scan the 10 most recent. A `/plan` artifact's timestamp is the `YYYY-MM-DD_HHMM` before its `.md`; a per-ticket plan's is the name of its parent directory. Never sort by file name, which starts with an issue ID or a ticket slug. A per-ticket plan counts only when its `{ticket-slug}` (its file name without `-plan.md`) appears in the worktree's branch name
|
|
285
|
+
2. Read the most recent file that carries an `## Acceptance Criteria` section
|
|
286
286
|
3. Extract `## Acceptance Criteria` section → parse into table: `| ID | Criterion | Type | Testable Condition |`
|
|
287
287
|
4. Set `PLAN_CONTEXT` to plan summary; `ACCEPTANCE_RULES` to the table
|
|
288
288
|
5. If no plan files exist or section not found: `PLAN_CONTEXT=(none)`, `ACCEPTANCE_RULES=(none)`
|
|
@@ -22,9 +22,10 @@ Run a comprehensive code review of the current branch by spawning parallel revie
|
|
|
22
22
|
|
|
23
23
|
**Produces:** WORKTREES
|
|
24
24
|
|
|
25
|
-
1. **Discover reviewable worktrees
|
|
26
|
-
- Run `git worktree list --porcelain`
|
|
27
|
-
- Invoke the `devflow:worktree-support` skill, then Read its `references/discovery.md` from the skill's base directory for the full 7-step algorithm; the canonical protected branch list stays in the skill
|
|
25
|
+
1. **Discover reviewable worktrees**:
|
|
26
|
+
- Run `git worktree list --porcelain` and count the worktrees it lists
|
|
27
|
+
- **More than one listed:** Invoke the `devflow:worktree-support` skill, then Read its `references/discovery.md` from the skill's base directory for the full 7-step algorithm; the canonical protected branch list stays in the skill. Parse the list, filter (skip protected/detached/mid-rebase), dedup by branch, sort by recent commit
|
|
28
|
+
- **Exactly one listed:** load neither the skill nor the reference — that worktree is the only candidate, and Step 0c's Git agent validates its branch
|
|
28
29
|
2. **If `--path` flag provided:** use only that worktree, skip discovery
|
|
29
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.
|
|
30
31
|
3. **If only 1 reviewable worktree** (the common case): proceed as single-worktree flow — zero behavior change
|
|
@@ -71,9 +72,9 @@ Set `EVIDENCE_POLICY`, `ISSUE_REQUIRED`, `APPLY_CONVENTIONS` and `REQUIRE_NON_AU
|
|
|
71
72
|
**Requires:** WORKTREES
|
|
72
73
|
|
|
73
74
|
Discover PR description guidance from plan artifact (per worktree):
|
|
74
|
-
1. List `{worktree}/.devflow/docs/design/*.md`
|
|
75
|
-
2. Sort by timestamp
|
|
76
|
-
3. Read the most recent file, extract `## PR Description Guidance` section
|
|
75
|
+
1. List the design plans: `{worktree}/.devflow/docs/design/*.md` (a `/plan` artifact) and `{worktree}/.devflow/docs/design/*/*/*-plan.md` (a `/dynamic-plan` per-ticket plan)
|
|
76
|
+
2. Sort by timestamp, newest first, and scan the 10 most recent. A `/plan` artifact's timestamp is the `YYYY-MM-DD_HHMM` before its `.md`; a per-ticket plan's is the name of its parent directory. Never sort by file name, which starts with an issue ID or a ticket slug. A per-ticket plan counts only when its `{ticket-slug}` (its file name without `-plan.md`) appears in the worktree's branch name
|
|
77
|
+
3. Read the most recent file that carries the section, extract `## PR Description Guidance` section
|
|
77
78
|
4. If no plan files exist or section not found, set `PR_DESCRIPTION_GUIDANCE` to `(none)`
|
|
78
79
|
|
|
79
80
|
Render the test-plan block (per worktree) from `/implement`'s evidence file, and from nothing else:
|
|
@@ -310,9 +311,9 @@ Attempt to read `{ledger}/.devflow/learning/index.md`.
|
|
|
310
311
|
|
|
311
312
|
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.
|
|
312
313
|
|
|
313
|
-
**Step 2 —
|
|
314
|
+
**Step 2 — Agents apply the decisions:**
|
|
314
315
|
|
|
315
|
-
When `DECISIONS_CONTEXT` is not `(none)`, follow `devflow:apply-decisions
|
|
316
|
+
When `DECISIONS_CONTEXT` is not `(none)`, hand it only to the agents whose contract declares it. They follow `devflow:apply-decisions`: scan the index, identify plausibly-relevant entries, Read full entry bodies on demand, and cite verbatim IDs in their reasoning. A host that uses the index in its own thread says so in its own step.
|
|
316
317
|
|
|
317
318
|
This produces a compact index of active ADR/PF entries. Pass `DECISIONS_CONTEXT` to all Review agents. Review agents use `devflow:apply-decisions` to Read full entry bodies on demand.
|
|
318
319
|
|
|
@@ -408,6 +409,10 @@ Spawn Review agents **in a single message**, for the focus set `DIFF_CLASS` sele
|
|
|
408
409
|
|
|
409
410
|
Review agent count: `code` runs 8 core, +1-12 added by Phase 1 (max 20 total per worktree); a reduced class or a mix runs 2-6.
|
|
410
411
|
|
|
412
|
+
**Set the compliance focus directive** from `COMPLIANCE_FRAMEWORKS`. `COMPLIANCE_FOCUS_DIRECTIVE` is this one line, with `<ids>` replaced by the value of `COMPLIANCE_FRAMEWORKS`; only the compliance focus's spawn carries it:
|
|
413
|
+
|
|
414
|
+
> For this compliance focus, invoke Skill(skill="devflow:compliance") and load references/{id}.md only for the ids in <ids> (none: generic controls only); never fabricate guidance for a framework you were not given.
|
|
415
|
+
|
|
411
416
|
Each Review agent invocation (all in one message, **NOT background**):
|
|
412
417
|
```
|
|
413
418
|
Agent(subagent_type="Review", run_in_background=false):
|
|
@@ -421,7 +426,7 @@ DECISIONS_CONTEXT: {decisions_context}
|
|
|
421
426
|
FEATURE_KNOWLEDGE: {feature_knowledge}
|
|
422
427
|
PR_DESCRIPTION: <pr-description>{pr_description}</pr-description>
|
|
423
428
|
PRIOR_RESOLUTIONS: <prior-resolution-summary>{prior_resolutions}</prior-resolution-summary>
|
|
424
|
-
|
|
429
|
+
{COMPLIANCE_FOCUS_DIRECTIVE} (compliance focus only)
|
|
425
430
|
If PRIOR_RESOLUTIONS is not (none), follow Cross-Cycle Awareness in review.md.
|
|
426
431
|
Follow devflow:apply-decisions to scan the index and Read full ADR/PF bodies on demand.
|
|
427
432
|
Follow devflow:apply-feature-knowledge for FEATURE_KNOWLEDGE — feature-specific patterns and anti-patterns inform findings.
|
package/dist/commands/debug.md
CHANGED
|
@@ -42,6 +42,14 @@ Accept the output only when it is exactly two lines: `exit=0` last and, before i
|
|
|
42
42
|
|
|
43
43
|
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.
|
|
44
44
|
|
|
45
|
+
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.
|
|
46
|
+
|
|
47
|
+
**Set the compliance directive** from `COMPLIANCE_FRAMEWORKS`. `COMPLIANCE_DIRECTIVE` is empty when `COMPLIANCE_FRAMEWORKS` is `off`: a spawn line that holds only `{COMPLIANCE_DIRECTIVE}` is then left out, so a lens-off spawn carries nothing about compliance. Otherwise `COMPLIANCE_DIRECTIVE` is this one line, with `<ids>` replaced by the value of `COMPLIANCE_FRAMEWORKS`:
|
|
48
|
+
|
|
49
|
+
> When the task touches regulated surface (data models, auth flows, logging/observability, payments, IaC, retention), invoke Skill(skill="devflow:compliance") and load references/{id}.md only for the ids in <ids> (none: generic controls only); never fabricate guidance for a framework you were not given.
|
|
50
|
+
|
|
51
|
+
Phase 7 passes `COMPLIANCE_DIRECTIVE` to the Code agent that implements the fix, on a line of its own.
|
|
52
|
+
|
|
45
53
|
### Load DECISIONS_CONTEXT
|
|
46
54
|
|
|
47
55
|
When the settings line says `LEARNING=off`, set `DECISIONS_CONTEXT` to `(none)` and skip this step, locating no ledger and reading no index.
|
|
@@ -69,9 +77,9 @@ Attempt to read `{ledger}/.devflow/learning/index.md`.
|
|
|
69
77
|
|
|
70
78
|
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.
|
|
71
79
|
|
|
72
|
-
**Step 2 —
|
|
80
|
+
**Step 2 — Agents apply the decisions:**
|
|
73
81
|
|
|
74
|
-
When `DECISIONS_CONTEXT` is not `(none)`, follow `devflow:apply-decisions
|
|
82
|
+
When `DECISIONS_CONTEXT` is not `(none)`, hand it only to the agents whose contract declares it. They follow `devflow:apply-decisions`: scan the index, identify plausibly-relevant entries, Read full entry bodies on demand, and cite verbatim IDs in their reasoning. A host that uses the index in its own thread says so in its own step.
|
|
75
83
|
|
|
76
84
|
The orchestrator uses `DECISIONS_CONTEXT` locally when generating hypotheses (Phase 2) — prior pitfalls and decisions can suggest specific root causes to investigate. Follow `devflow:apply-decisions` to Read full entry bodies on demand. **Do NOT pass `DECISIONS_CONTEXT` to Explore investigators** — decisions context stays in the orchestrator; investigators examine code directly.
|
|
77
85
|
|
|
@@ -226,7 +234,20 @@ Produce the final report:
|
|
|
226
234
|
|
|
227
235
|
Ask user via AskUserQuestion: "Want me to implement this fix?"
|
|
228
236
|
|
|
229
|
-
- **YES** →
|
|
237
|
+
- **YES** → implement the fix through the Code agent, never in this thread, then spawn `Agent(subagent_type="Simplify")` on the changed files. /debug loads no feature knowledge, so the fix gets none:
|
|
238
|
+
|
|
239
|
+
```
|
|
240
|
+
Agent(subagent_type="Code"):
|
|
241
|
+
"OPERATION: implement
|
|
242
|
+
TASK_ID: debug-{YYYY-MM-DD_HHMM}
|
|
243
|
+
TASK_DESCRIPTION: Implement the fix for this root cause: {bug description}
|
|
244
|
+
EXECUTION_PLAN: {Root Cause, Key Findings and Recommended Fix from Phase 6, with their file:line references}
|
|
245
|
+
PUSH: false
|
|
246
|
+
DECISIONS_CONTEXT: {decisions_context}
|
|
247
|
+
FEATURE_KNOWLEDGE: (none)
|
|
248
|
+
{COMPLIANCE_DIRECTIVE}"
|
|
249
|
+
```
|
|
250
|
+
|
|
230
251
|
- **NO** → Done. Report stands as documentation.
|
|
231
252
|
|
|
232
253
|
### Feature Knowledge Write-Back (Conditional)
|
|
@@ -307,7 +328,7 @@ When the Knowledge agent reports `KB_COMMIT: skipped (detached HEAD)`, the files
|
|
|
307
328
|
├─ Phase 6: Root cause report with confidence level
|
|
308
329
|
│
|
|
309
330
|
├─ Phase 7: Offer Fix
|
|
310
|
-
│ └─ AskUserQuestion →
|
|
331
|
+
│ └─ AskUserQuestion → Code agent (fix) + Simplify agent, or done
|
|
311
332
|
│
|
|
312
333
|
└─ Feature Knowledge Write-Back (Conditional)
|
|
313
334
|
└─ Knowledge agent (if investigation surfaced durable cross-cutting knowledge)
|
|
@@ -41,7 +41,7 @@ Spawn devflow agents with:
|
|
|
41
41
|
agent("your prompt here", { agentType: "Code" })
|
|
42
42
|
```
|
|
43
43
|
|
|
44
|
-
Valid `agentType` values: Code, Validate, Simplify, Scrutinize, Evaluate, Test, Review, Git, Synthesize, Knowledge, Design.
|
|
44
|
+
Valid `agentType` values: Code, Code-fix, Validate, Simplify, Scrutinize, Evaluate, Test, Review, Git, Synthesize, Knowledge, Design.
|
|
45
45
|
|
|
46
46
|
**OMIT `opts.model` whenever `agentType` is set.** The agent frontmatter carries its own model tier (Code→sonnet, Validate→haiku, Review→opus, etc.) and that tier is honored automatically. Passing `opts.model` overrides it — always a mistake.
|
|
47
47
|
|
|
@@ -65,7 +65,7 @@ The `budget` global governs depth. Scale Review agent roster and verification vo
|
|
|
65
65
|
|
|
66
66
|
### Handoff convention for sequential Code agents within a ticket
|
|
67
67
|
|
|
68
|
-
When a ticket requires multiple sequential Code agent phases, each Code agent appends its own `## Phase {N} Implementation Summary` section, at most 8,192 bytes, to `{toplevel}/.devflow/docs/handoff-{branch_slug}.md` (branch-scoped to prevent concurrent session clobber), `{toplevel}` being `git rev-parse --show-toplevel` in the checkout the ticket's branch is in — never a subdirectory. It never rewrites an earlier section. The next Code agent reads, via HANDOFF_FILE input, only the section of the phase immediately before its own, not the whole file. PRIOR_PHASE_SUMMARY is the compact in-context form; the handoff file is the durable form that survives context compaction. Code is authoritative, summaries are supplementary.
|
|
68
|
+
When a ticket requires multiple sequential Code agent phases, each Code agent appends its own `## Phase {N} Implementation Summary` section, at most 8,192 bytes, to `{toplevel}/.devflow/docs/handoff-{branch_slug}.md` (branch-scoped to prevent concurrent session clobber), `{branch_slug}` being the ticket's branch name with every `/` replaced by `-`, and `{toplevel}` being `git rev-parse --show-toplevel` in the checkout the ticket's branch is in — never a subdirectory. It never rewrites an earlier section. The next Code agent reads, via HANDOFF_FILE input, only the section of the phase immediately before its own, not the whole file. PRIOR_PHASE_SUMMARY is the compact in-context form; the handoff file is the durable form that survives context compaction. Code is authoritative, summaries are supplementary.
|
|
69
69
|
|
|
70
70
|
### IRON RULE (LLM-vs-plumbing)
|
|
71
71
|
|
|
@@ -107,7 +107,7 @@ This is the rule the learning hooks apply (D-LEDGER-MAIN-WORKTREE, D-PROMPT-ROOT
|
|
|
107
107
|
|
|
108
108
|
Before you author the workflow script, read `{ledger}/.devflow/learning/index.md`. If the file is absent or empty, set `DECISIONS_CONTEXT` to `(none)`; otherwise use the file content as `DECISIONS_CONTEXT`.
|
|
109
109
|
|
|
110
|
-
The script body cannot perform this read — you (the main model) do it before authoring. Then inject the relevant DECISIONS_CONTEXT into the prompts of the Code, Design, Knowledge, Review and Scrutinize agents, using the `devflow:apply-decisions` consumption algorithm (scan index → Read relevant entries → cite verbatim IDs in agent prompts). Those are the agent types above whose contract declares it; every other agent type gets no decisions context.
|
|
110
|
+
The script body cannot perform this read — you (the main model) do it before authoring. Then inject the relevant DECISIONS_CONTEXT into the prompts of the Code, Code-fix, Design, Knowledge, Review and Scrutinize agents, using the `devflow:apply-decisions` consumption algorithm (scan index → Read relevant entries → cite verbatim IDs in agent prompts). Those are the agent types above whose contract declares it; every other agent type gets no decisions context.
|
|
111
111
|
|
|
112
112
|
---
|
|
113
113
|
|
|
@@ -121,11 +121,12 @@ The following agentType values are valid. Model tiers are shown for reference
|
|
|
121
121
|
|
|
122
122
|
| agentType | Model tier | Role |
|
|
123
123
|
|-----------|-----------|------|
|
|
124
|
-
| Code | sonnet |
|
|
124
|
+
| Code | sonnet | Implements the plan and fixes review findings — the Code family is the ONLY one that writes code |
|
|
125
|
+
| Code-fix | sonnet | Fixes the listed validation, alignment and QA failures — part of the Code family |
|
|
125
126
|
| Validate | haiku | Build / typecheck / lint / test — fast correctness gate |
|
|
126
127
|
| Simplify | sonnet | Reduces complexity, removes duplication, improves readability |
|
|
127
128
|
| Scrutinize | opus | 9-pillar self-review — deep structural analysis |
|
|
128
|
-
| Evaluate |
|
|
129
|
+
| Evaluate | sonnet | Plan-fidelity / alignment — "was the plan implemented correctly?" |
|
|
129
130
|
| Test | sonnet | Scenario-based acceptance tests against acceptance criteria |
|
|
130
131
|
| Review | opus | Focus-parameterized code review — spawn ONE agent() per focus area |
|
|
131
132
|
| Git | haiku | Git operations — branches, commits, merges, worktree management |
|
|
@@ -135,7 +136,7 @@ The following agentType values are valid. Model tiers are shown for reference
|
|
|
135
136
|
|
|
136
137
|
### Agent caveats
|
|
137
138
|
|
|
138
|
-
- **
|
|
139
|
+
- **The Code family writes every fix** — Code for review findings, Code-fix for gate failures; no other agent type writes code. Finding-verification uses adversarial Review agent-style passes (§6.3 of design doc). Risk-assessment and tech-debt routing live in the post-code pipeline + escalation doctrine.
|
|
139
140
|
- **Always omit `opts.model` with `agentType`.** Each agent honors its own frontmatter model tier; overriding it defeats the per-agent specialization.
|
|
140
141
|
- **Review agents are focus-parameterized.** Each focus is a SEPARATE `agent()` call with `agentType: "Review"` and the focus baked into the prompt. Do NOT batch multiple focuses into one Review agent call — that defeats parallel specialization.
|
|
141
142
|
- **Do not depend on agents enumerating their own skills.** Skills are loaded (spike F5 confirmed) but self-reporting is imperfect. Write agent prompts that give the agent full context directly.
|
|
@@ -186,7 +187,7 @@ Author the resolved `ISSUE_REQUIRED` and `APPLY_CONVENTIONS` into the workflow s
|
|
|
186
187
|
|
|
187
188
|
**Set the compliance lens** from that 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.
|
|
188
189
|
|
|
189
|
-
Pass it as `complianceFrameworks` when invoking the workflow; the engine
|
|
190
|
+
Pass it as `complianceFrameworks` when invoking the workflow; the engine builds `COMPLIANCE_DIRECTIVE` from it and hands that to every Code and Code-fix agent.
|
|
190
191
|
|
|
191
192
|
**0c. Resolve the docs root**
|
|
192
193
|
|
|
@@ -268,7 +269,7 @@ If a number is found, record it as the command-level `ISSUE_NUMBER`:
|
|
|
268
269
|
- **SINGLE mode:** it is the ticket's own reference. Pass it as `issueNumber: <number>` when invoking the workflow; the engine hands it to setup-task as `ISSUE_INPUT`. If none is found, pass nothing.
|
|
269
270
|
- **WAVE mode:** it is the tracking issue. Only steps 2 and 3 after the workflow use it: step 2 for the wave report, step 3 for the wave block's tracking line. It never reaches a ticket: each ticket's engine gets that ticket's own reference as `issueInput`.
|
|
270
271
|
|
|
271
|
-
Never pass `ISSUE_PR_LINK` into the workflow. The engine binds each ticket's `ISSUE_NUMBER` and `ISSUE_PR_LINK` from that ticket's own setup-task Output (`### Handoff Values`), never from the token it passed in, and
|
|
272
|
+
Never pass `ISSUE_PR_LINK` into the workflow. The engine binds each ticket's `ISSUE_NUMBER` and `ISSUE_PR_LINK` from that ticket's own setup-task Output (`### Handoff Values`), never from the token it passed in, and returns that ticket's `issuePrLink` for the wave PR's related line. No `- **PR link line**:` captured ⇒ `ISSUE_PR_LINK` is `"(none)"` and the ticket's related line carries no closing reference.
|
|
272
273
|
|
|
273
274
|
---
|
|
274
275
|
|
|
@@ -294,6 +295,7 @@ const ISSUE_INPUT = args.issueInput || args.issueNumber || "(none)"; // this ti
|
|
|
294
295
|
const ISSUE_REQUIRED = String(args.issueRequired) === "false" ? "false" : "true"; // Pre-authoring step 0; only an explicit false turns it off — absent or unrecognised fails closed, like the resolver
|
|
295
296
|
const APPLY_CONVENTIONS = String(args.applyConventions) === "false" ? "false" : "true";
|
|
296
297
|
const COMPLIANCE_FRAMEWORKS = /^(?:off|none|[a-z][a-z0-9-]{0,15}(?:,[a-z][a-z0-9-]{0,15}){0,7})$/.test(String(args.complianceFrameworks)) ? String(args.complianceFrameworks) : "off"; // Pre-authoring step 0b; any other shape is no lens
|
|
298
|
+
const COMPLIANCE_DIRECTIVE = COMPLIANCE_FRAMEWORKS === "off" ? "" : `When the task touches regulated surface (data models, auth flows, logging/observability, payments, IaC, retention), invoke Skill(skill="devflow:compliance") and load references/{id}.md only for the ids in ${COMPLIANCE_FRAMEWORKS} (none: generic controls only); never fabricate guidance for a framework you were not given.`; // D-COMPLIANCE-INJECT: empty when the lens is off, so a Code or Code-fix spawn then carries nothing about compliance; otherwise the one line _compliance.mds renders as compliance_directive(), with the validated ids in place of <ids>
|
|
297
299
|
|
|
298
300
|
// Phase 1: Git setup — declare the operation; the agent owns the process, the branch name included
|
|
299
301
|
const setup = await phase("setup", () =>
|
|
@@ -310,7 +312,7 @@ Return: {"branch": "<the - **Branch name**: value under your ### Branch, or (non
|
|
|
310
312
|
// An Issue ID is a bare number or a KEY-number, per the provider; any other value — "none", blank, prose — is no capture, so the stop fails closed.
|
|
311
313
|
const ISSUE_ID_SHAPE = /^(?:[1-9][0-9]{0,8}|[A-Z][A-Z0-9_]{0,9}-[1-9][0-9]{0,8})$/;
|
|
312
314
|
const ISSUE_NUMBER = ISSUE_ID_SHAPE.test(String(setup?.issueId ?? "")) ? setup.issueId : "(none)"; // the captured Issue ID; "(none)" ⇒ none was captured
|
|
313
|
-
const ISSUE_PR_LINK = setup?.prLinkLine || "(none)"; // "(none)" ⇒
|
|
315
|
+
const ISSUE_PR_LINK = setup?.prLinkLine || "(none)"; // "(none)" ⇒ the wave PR carries no closing reference for this ticket
|
|
314
316
|
// The branch setup-task created, as it reported it: every later phase and the merge use it. The engine never names one.
|
|
315
317
|
const BRANCH = typeof setup?.branch === "string" && setup.branch.trim() !== "" && setup.branch.trim() !== "(none)" ? setup.branch : "(none)";
|
|
316
318
|
|
|
@@ -336,9 +338,7 @@ ${PLAN ? `Implementation plan:\n${PLAN}` : "No plan provided — use best judgme
|
|
|
336
338
|
Relevant architectural decisions (apply devflow:apply-decisions algorithm):
|
|
337
339
|
${DECISIONS_CONTEXT}
|
|
338
340
|
|
|
339
|
-
|
|
340
|
-
ISSUE_PR_LINK: ${ISSUE_PR_LINK}
|
|
341
|
-
COMPLIANCE_FRAMEWORKS: ${COMPLIANCE_FRAMEWORKS}
|
|
341
|
+
${COMPLIANCE_DIRECTIVE}
|
|
342
342
|
|
|
343
343
|
When you build or run tests to verify your work, follow your Running commands block.
|
|
344
344
|
|
|
@@ -373,10 +373,8 @@ Return: {"verdict": "PASS" | "FAIL", "details": "..."}`, { agentType: "Validate"
|
|
|
373
373
|
Fix the validation failures on branch ${BRANCH}:
|
|
374
374
|
${failureDetails}
|
|
375
375
|
DECISIONS_CONTEXT: ${DECISIONS_CONTEXT}
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
COMPLIANCE_FRAMEWORKS: ${COMPLIANCE_FRAMEWORKS}
|
|
379
|
-
Commit fixes with conventional-commit message.`, { agentType: "Code" });
|
|
376
|
+
${COMPLIANCE_DIRECTIVE}
|
|
377
|
+
Commit fixes with conventional-commit message.`, { agentType: "Code-fix" });
|
|
380
378
|
const recheck = await agent(`Re-run build, typecheck, lint, tests on branch ${BRANCH} after fix attempt ${attempt} (follow your Running commands block).
|
|
381
379
|
Return: {"verdict": "PASS" | "FAIL", "details": "..."}`, { agentType: "Validate" });
|
|
382
380
|
if (recheck?.verdict === "PASS") break;
|
|
@@ -416,10 +414,8 @@ Return: {"verdict": "PASS" | "FAIL", "rationale": "..."} — FAIL if either answ
|
|
|
416
414
|
Fix the alignment issues identified by the Evaluate agent on branch ${BRANCH}:
|
|
417
415
|
${evaluation?.rationale || "see the Evaluate agent's report"}
|
|
418
416
|
DECISIONS_CONTEXT: ${DECISIONS_CONTEXT}
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
COMPLIANCE_FRAMEWORKS: ${COMPLIANCE_FRAMEWORKS}
|
|
422
|
-
Self-verify your fix compiles, following your Running commands block. Commit fixes.`, { agentType: "Code" });
|
|
417
|
+
${COMPLIANCE_DIRECTIVE}
|
|
418
|
+
Self-verify your fix compiles, following your Running commands block. Commit fixes.`, { agentType: "Code-fix" });
|
|
423
419
|
evalVerdict = "FAIL-FIXED"; // issues found, fixes applied, not re-evaluated by design
|
|
424
420
|
}
|
|
425
421
|
}
|
|
@@ -438,10 +434,8 @@ Cover: functionality, API contracts, performance, and cover every TEST_PLAN scen
|
|
|
438
434
|
Fix the failing acceptance test scenarios on branch ${BRANCH}:
|
|
439
435
|
${testResult.failures}
|
|
440
436
|
DECISIONS_CONTEXT: ${DECISIONS_CONTEXT}
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
COMPLIANCE_FRAMEWORKS: ${COMPLIANCE_FRAMEWORKS}
|
|
444
|
-
Self-verify your fix compiles and the scenarios pass, following your Running commands block. Commit fixes.`, { agentType: "Code" });
|
|
437
|
+
${COMPLIANCE_DIRECTIVE}
|
|
438
|
+
Self-verify your fix compiles and the scenarios pass, following your Running commands block. Commit fixes.`, { agentType: "Code-fix" });
|
|
445
439
|
testVerdict = "FAIL-FIXED"; // issues found, fixes applied, not re-evaluated by design
|
|
446
440
|
}
|
|
447
441
|
}
|
|
@@ -558,9 +552,7 @@ ${chunk.map((f, n) => `${n + 1}. ${f.file ? `${f.file}${f.line ? `:${f.line}` :
|
|
|
558
552
|
SCOPE: ${chunk.map((f, n) => `${n + 1}=${CAREFUL_SEVERITIES.has(String(f.severity).toLowerCase()) ? "Careful" : "Standard"}`).join(", ")}
|
|
559
553
|
PUSH: false
|
|
560
554
|
DECISIONS_CONTEXT: ${DECISIONS_CONTEXT}
|
|
561
|
-
|
|
562
|
-
ISSUE_PR_LINK: ${ISSUE_PR_LINK}
|
|
563
|
-
COMPLIANCE_FRAMEWORKS: ${COMPLIANCE_FRAMEWORKS}
|
|
555
|
+
${COMPLIANCE_DIRECTIVE}
|
|
564
556
|
Fix all findings in this batch. Self-verify your fix compiles, following your Running commands block. Commit with conventional-commit message.
|
|
565
557
|
Return: {"status": "fixed"|"blocked", "commitShas": ["<sha>"], "unresolved": ["<description of any finding that could not be fixed>"]}`, { agentType: "Code" });
|
|
566
558
|
chunkResults.push({ chunk, result: r });
|
|
@@ -619,10 +611,8 @@ Return: {"verdict": "PASS" | "FAIL", "details": "..."}`, { agentType: "Validate"
|
|
|
619
611
|
Fix the final validation failures on branch ${BRANCH}:
|
|
620
612
|
${failureDetails}
|
|
621
613
|
DECISIONS_CONTEXT: ${DECISIONS_CONTEXT}
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
COMPLIANCE_FRAMEWORKS: ${COMPLIANCE_FRAMEWORKS}
|
|
625
|
-
Self-verify your fix compiles. Commit fixes with conventional-commit message.`, { agentType: "Code" });
|
|
614
|
+
${COMPLIANCE_DIRECTIVE}
|
|
615
|
+
Self-verify your fix compiles. Commit fixes with conventional-commit message.`, { agentType: "Code-fix" });
|
|
626
616
|
const recheck = await agent(`Re-run build, typecheck, lint, tests on branch ${BRANCH} (final gate, after fix attempt ${attempt}; follow your Running commands block).
|
|
627
617
|
Return: {"verdict": "PASS" | "FAIL", "details": "..."}`, { agentType: "Validate" });
|
|
628
618
|
if (recheck?.verdict === "PASS") break;
|
|
@@ -707,12 +697,12 @@ Run builds, typechecks, lints and tests in the foreground, each with an explicit
|
|
|
707
697
|
The standard implementation unit for one ticket. Run in order:
|
|
708
698
|
|
|
709
699
|
```
|
|
710
|
-
Code(agentType:"Code", prompt: "OPERATION: implement" first line, then full task + plan + DECISIONS_CONTEXT +
|
|
700
|
+
Code(agentType:"Code", prompt: "OPERATION: implement" first line, then full task + plan + DECISIONS_CONTEXT + COMPLIANCE_DIRECTIVE + handoff if sequential)
|
|
711
701
|
→ gate1_postcode()
|
|
712
702
|
→ gate2_acceptance() ← Gate 2 runs HERE — before the review pass, not after
|
|
713
703
|
```
|
|
714
704
|
|
|
715
|
-
Every Code agent prompt opens with `OPERATION: <mode>` as its first line
|
|
705
|
+
Every Code-family agent prompt opens with `OPERATION: <mode>` as its first line: `implement` and `issue-fix` go to `agentType:"Code"`, `validation-fix`, `alignment-fix` and `qa-fix` go to `agentType:"Code-fix"`. It must include: task description, implementation plan (if one exists), relevant DECISIONS_CONTEXT (the index you loaded before authoring), the compliance directive (`COMPLIANCE_DIRECTIVE` — every Code prompt carries it when it is not empty, fix prompts included), and any PRIOR_PHASE_SUMMARY / HANDOFF_FILE for sequential multi-phase tickets.
|
|
716
706
|
|
|
717
707
|
Gate 2 runs at implementation acceptance — this matches devflow's deliberate placement: "evaluation is part of implementation acceptance, not post-review" (§6.1).
|
|
718
708
|
|
|
@@ -725,7 +715,7 @@ ORDER IS LOAD-BEARING. Run exactly in this sequence:
|
|
|
725
715
|
- BLOCKED (a P0 issue cannot be fixed in scope), or a missing or unrecognised status, which counts as BLOCKED → stop the pass and escalate as `scrutiny-blocked`; Validate does not run on code Scrutinize could not accept
|
|
726
716
|
3. **Validate agent** — build / typecheck / lint / test; returns `{"verdict": "PASS" | "FAIL", "details": "..."}`. It runs LAST and UNCONDITIONALLY: one full run over the HEAD that Simplify and Scrutinize left, so it covers their commits whether or not Scrutinize changed code
|
|
727
717
|
- Build/test commands follow `build_execution_doctrine()`: the Validate agent's Running commands block, foreground under an explicit Bash timeout.
|
|
728
|
-
- FAIL → Code agent fix (max 2 retries), each followed by a Validate agent re-run
|
|
718
|
+
- FAIL → Code-fix agent fix (max 2 retries), each followed by a Validate agent re-run
|
|
729
719
|
- If still FAIL after 2 retries → escalate as `validation-exhausted` (do not loop endlessly)
|
|
730
720
|
|
|
731
721
|
**Gate 1 contains NO Evaluate agent and NO Test agent.** Those are Gate 2 only.
|
|
@@ -746,11 +736,11 @@ Gate 2 inputs are produced by `/devflow:dynamic-plan`'s plan-challenge step —
|
|
|
746
736
|
|
|
747
737
|
**Evaluate agent** (only if a plan exists):
|
|
748
738
|
- Run `evaluator_panel()` — see that block for the one spawn and the two lenses it names
|
|
749
|
-
- If the Evaluate agent returns FAIL (either lens failed): fix-and-continue — the demanded fixes are applied by a Code agent that self-verifies its own build (batched per the review-pass batching doctrine if numerous). The recorded verdict becomes `FAIL-FIXED` (issues found, fixes applied, not re-evaluated by design); Gate 2 then proceeds. In SINGLE mode the run reports it as `UNVERIFIED`, never PASS.
|
|
739
|
+
- If the Evaluate agent returns FAIL (either lens failed): fix-and-continue — the demanded fixes are applied by a Code-fix agent that self-verifies its own build (batched per the review-pass batching doctrine if numerous). The recorded verdict becomes `FAIL-FIXED` (issues found, fixes applied, not re-evaluated by design); Gate 2 then proceeds. In SINGLE mode the run reports it as `UNVERIFIED`, never PASS.
|
|
750
740
|
|
|
751
741
|
**Test agent** (only if acceptance criteria or a test plan exist):
|
|
752
742
|
- Scenario-based acceptance tests covering functionality, API contracts, performance
|
|
753
|
-
- FAIL → fix-and-continue — a Code agent applies the demanded fixes and self-verifies its own build. The recorded verdict becomes `FAIL-FIXED`; Gate 2 then proceeds. In SINGLE mode the run reports it as `UNVERIFIED`, never PASS.
|
|
743
|
+
- FAIL → fix-and-continue — a Code-fix agent applies the demanded fixes and self-verifies its own build. The recorded verdict becomes `FAIL-FIXED`; Gate 2 then proceeds. In SINGLE mode the run reports it as `UNVERIFIED`, never PASS.
|
|
754
744
|
|
|
755
745
|
**When Gate 2 inputs are absent:**
|
|
756
746
|
- No plan → skip the Evaluate agent silently (note in output: "Gate 2 Evaluate agent skipped — no plan available")
|
|
@@ -869,7 +859,7 @@ If survivors remain: batch the confirmed findings for fixing: group findings by
|
|
|
869
859
|
|
|
870
860
|
### Engine invariants (non-negotiable)
|
|
871
861
|
|
|
872
|
-
1. **Code is written ONLY by Code
|
|
862
|
+
1. **Code is written ONLY by the Code family (Code, Code-fix).** No other agent type writes code — not Review agent, not Evaluate agent.
|
|
873
863
|
2. **Findings are verified before any fix is written.** The adversarial verification step is not optional; unverified findings are not passed to the Code agent.
|
|
874
864
|
3. **All written code passes Gate 1.** No code merge, commit, or handoff before Simplify agent + Scrutinize agent + Validate agent (in that order — Validate last, so its one run covers the commits of the two before it).
|
|
875
865
|
4. **Gate 2 runs once, at implementation acceptance.** It does not re-run after review-fixes.
|
|
@@ -1013,7 +1003,7 @@ Two parallel sibling tickets can produce real git conflicts. The resolution is *
|
|
|
1013
1003
|
**Resolution procedure:**
|
|
1014
1004
|
|
|
1015
1005
|
1. Git agent detects the conflict and reports the conflicting files + sections
|
|
1016
|
-
2. Spawn a Code agent whose prompt opens with `OPERATION: implement` and carries `
|
|
1006
|
+
2. Spawn a Code agent whose prompt opens with `OPERATION: implement` and carries `COMPLIANCE_DIRECTIVE` (when it is not empty) and `DECISIONS_CONTEXT`, with FULL intent context:
|
|
1017
1007
|
- Both ticket descriptions and plans
|
|
1018
1008
|
- The conflicting diff sections (both sides)
|
|
1019
1009
|
- Relevant ADRs from DECISIONS_CONTEXT (loaded by main model before authoring)
|