devflow-kit 3.4.0 → 3.6.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 +127 -0
- package/README.md +12 -8
- package/dist/agents/code.md +39 -182
- package/dist/agents/{diagnose.md → debug.md} +4 -4
- package/dist/agents/design.md +0 -1
- package/dist/agents/fix.md +165 -0
- package/dist/agents/git.md +31 -693
- package/dist/agents/{scrutinize.md → harden.md} +9 -6
- package/dist/agents/knowledge.md +8 -2
- package/dist/agents/refactor.md +133 -0
- package/dist/agents/research.md +6 -0
- package/dist/agents/review.md +0 -4
- package/dist/agents/skim.md +4 -0
- package/dist/agents/triage.md +8 -1
- package/dist/cli/agents-view/render.js +1 -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 +75 -8
- package/dist/cli/commands/learning.js +12 -12
- package/dist/cli/commands/legacy-hooks.js +1 -1
- package/dist/cli/commands/rules.js +16 -0
- package/dist/cli/commands/tracker.js +112 -15
- package/dist/cli/commands/uninstall.js +111 -5
- package/dist/cli.js +2 -0
- package/dist/commands/bug-analysis.md +22 -18
- package/dist/commands/code-review.md +25 -29
- package/dist/commands/debug.md +36 -15
- package/dist/commands/dynamic-build.md +64 -78
- package/dist/commands/dynamic-plan.md +18 -14
- package/dist/commands/dynamic-profile.md +8 -6
- package/dist/commands/dynamic-tickets.md +19 -15
- package/dist/commands/explore.md +14 -14
- package/dist/commands/implement.md +122 -225
- package/dist/commands/plan.md +32 -47
- package/dist/commands/release.md +12 -7
- package/dist/commands/research.md +26 -15
- package/dist/commands/resolve.md +53 -92
- package/dist/commands/self-review.md +42 -42
- package/dist/core/agent-frontmatter.js +101 -0
- package/dist/core/agent-models.js +47 -11
- package/dist/core/compliance-compose.js +6 -4
- package/dist/core/{learning-tuning-config.js → curate-tuning-config.js} +14 -14
- package/dist/core/feature-switch.js +23 -2
- package/dist/core/flags.js +111 -0
- package/dist/core/learning-queue-cleanup.js +1 -1
- package/dist/core/manifest.js +11 -3
- package/dist/core/mds-variants.js +68 -26
- package/dist/core/migrations.js +63 -44
- package/dist/core/plugins.js +49 -70
- package/dist/core/project-paths.js +3 -7
- 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/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 +37 -180
- package/dist/learning-off/agents/{diagnose.md → debug.md} +4 -4
- package/dist/learning-off/agents/design.md +0 -1
- package/dist/learning-off/agents/fix.md +161 -0
- package/dist/learning-off/agents/{scrutinize.md → harden.md} +9 -6
- package/dist/learning-off/agents/knowledge.md +8 -2
- package/dist/learning-off/agents/refactor.md +129 -0
- package/dist/learning-off/agents/research.md +6 -0
- package/dist/learning-off/agents/review.md +0 -4
- 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 +12 -12
- package/dist/learning-off/commands/code-review.md +14 -22
- package/dist/learning-off/commands/debug.md +24 -8
- package/dist/learning-off/commands/dynamic-build.md +58 -74
- package/dist/learning-off/commands/dynamic-plan.md +12 -10
- package/dist/learning-off/commands/dynamic-profile.md +2 -2
- package/dist/learning-off/commands/dynamic-tickets.md +13 -11
- package/dist/learning-off/commands/explore.md +3 -7
- package/dist/learning-off/commands/implement.md +110 -217
- package/dist/learning-off/commands/plan.md +21 -39
- package/dist/learning-off/commands/release.md +7 -4
- package/dist/learning-off/commands/research.md +16 -9
- package/dist/learning-off/commands/resolve.md +42 -85
- package/dist/learning-off/commands/self-review.md +30 -34
- 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 +21 -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 +17 -6
- 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 +177 -77
- 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.mds +18 -222
- package/src/assets/agents/{learning.md → curate.md} +22 -72
- package/src/assets/agents/{diagnose.mds → debug.mds} +4 -4
- package/src/assets/agents/design.mds +0 -1
- package/src/assets/agents/evaluate.md +11 -5
- package/src/assets/agents/explore.md +58 -0
- package/src/assets/agents/fix.mds +113 -0
- package/src/assets/agents/git.mds +31 -693
- package/src/assets/agents/{scrutinize.mds → harden.mds} +9 -6
- package/src/assets/agents/knowledge.mds +8 -2
- package/src/assets/agents/{simplify.md → polish.md} +7 -4
- package/src/assets/agents/refactor.mds +81 -0
- package/src/assets/agents/research.mds +6 -0
- package/src/assets/agents/review.mds +0 -4
- package/src/assets/agents/skim.mds +4 -0
- package/src/assets/agents/synthesize.md +26 -352
- package/src/assets/agents/test.md +10 -2
- 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 +26 -6
- package/src/assets/commands/_partials/_engine.mds +17 -17
- 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 +5 -3
- package/src/assets/commands/_partials/_roster.mds +6 -5
- package/src/assets/commands/_partials/_wave.mds +2 -2
- package/src/assets/commands/bug-analysis.mds +10 -10
- package/src/assets/commands/code-review.mds +12 -22
- package/src/assets/commands/debug.mds +24 -2
- package/src/assets/commands/dynamic-build.mds +34 -51
- 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 +108 -201
- package/src/assets/commands/plan.mds +19 -44
- package/src/assets/commands/release.mds +8 -3
- package/src/assets/commands/research.mds +14 -7
- package/src/assets/commands/resolve.mds +37 -82
- package/src/assets/commands/self-review.mds +27 -27
- 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 +45 -50
- 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 +5 -3
- 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 +2 -2
- package/src/assets/scripts/hooks/lib/learning-store.cjs +1 -1
- package/src/assets/scripts/hooks/lib/project-paths.cjs +4 -10
- package/src/assets/scripts/hooks/preamble +1 -1
- package/src/assets/scripts/hooks/session-start-context +58 -45
- package/src/assets/scripts/verify-evidence.cjs +726 -9
- package/src/assets/skills/agent-references/SKILL.md +37 -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/curate/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/apply-decisions/SKILL.md +6 -4
- package/src/assets/skills/compliance/SKILL.md +1 -1
- package/src/assets/skills/docs-framework/SKILL.md +81 -84
- 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/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/dist/skills/git/references/pr/ensure-pr-ready.md +0 -24
|
@@ -7,7 +7,7 @@ import color from 'picocolors';
|
|
|
7
7
|
import { getInstallationPaths, getClaudeDirectory, getHomeDirectory, getManagedSettingsPath } from '../../targets/claude-code/claude-paths.js';
|
|
8
8
|
import { getGitRoot } from '../../core/git.js';
|
|
9
9
|
import { isSameLocation } from '../../core/same-location.js';
|
|
10
|
-
import { DEVFLOW_PLUGINS, SKILL_NAMESPACE, getAllSkillNames, getAllAgentNames, getAllCommandNames, parsePluginSelection, resolveFeatureRedirect, prefixSkillName, unprefixSkillName, skillsOf, FEATURE_OWNED_SKILLS } from '../../core/plugins.js';
|
|
10
|
+
import { DEVFLOW_PLUGINS, SKILL_NAMESPACE, buildAssetMaps, getAllSkillNames, getAllAgentNames, getAllCommandNames, parsePluginSelection, resolveFeatureRedirect, prefixSkillName, unprefixSkillName, skillsOf, FEATURE_OWNED_SKILLS } from '../../core/plugins.js';
|
|
11
11
|
import { readManifest, removeManifestPlugins } from '../../core/manifest.js';
|
|
12
12
|
import { sweepOrphanedAssets, mdFileName, mdEntryName } from '../../core/orphan-sweep.js';
|
|
13
13
|
import { LEGACY_SKILL_NAMES } from '../../targets/claude-code/legacy.js';
|
|
@@ -20,7 +20,7 @@ import { removeContextHook } from './context.js';
|
|
|
20
20
|
import { applyProxyTeardownToSettings } from './proxy.js';
|
|
21
21
|
import { readProxyState, proxyJsonExists } from '../../core/proxy-state.js';
|
|
22
22
|
import { hudCacheDir } from '../../core/cache.js';
|
|
23
|
-
import { TRACKER_ATTEMPTS_NAMES, TRACKER_CLAIM_FILE, TRACKER_CONVENTIONS_DIR, TRACKER_ENABLED_FILE, TRACKER_LEGACY_ATTEMPTS_FILE, TRACKER_LEGACY_CONVENTIONS_FILE, TRACKER_PROVIDER_IDS, TRACKER_STAGED_PREFIX, } from '../../core/tracker.js';
|
|
23
|
+
import { effectiveTrackerServers, TRACKER_ATTEMPTS_NAMES, TRACKER_CLAIM_FILE, TRACKER_CONVENTIONS_DIR, TRACKER_ENABLED_FILE, TRACKER_LEGACY_ATTEMPTS_FILE, TRACKER_LEGACY_CONVENTIONS_FILE, TRACKER_PROVIDER_IDS, TRACKER_STAGED_PREFIX, } from '../../core/tracker.js';
|
|
24
24
|
import { CLAUDE_MD_AUDIT_STAMP_FILE, CLAUDE_MD_AUDIT_STAMP_TMP_PREFIX } from '../../core/claude-md-audit.js';
|
|
25
25
|
import { revertExternalAgents } from '../../core/agent-models.js';
|
|
26
26
|
import { detectShell, getProfilePath } from '../../core/safe-delete.js';
|
|
@@ -32,6 +32,7 @@ import { stripDevflowTeammateModeFromJson } from '../../core/teammate-mode-clean
|
|
|
32
32
|
import { getPackageRoot, isContainedIn } from '../../core/paths.js';
|
|
33
33
|
import { firstSymbolicLink } from '../../core/linked-path.js';
|
|
34
34
|
import { restampInstalledCommands } from '../../targets/claude-code/language-stamp.js';
|
|
35
|
+
import { installCommandsAndAgents } from '../../targets/claude-code/installer.js';
|
|
35
36
|
/**
|
|
36
37
|
* Where a retired repo-local install lives: `<gitRoot>/.claude` and `<gitRoot>/.devflow`.
|
|
37
38
|
*
|
|
@@ -488,7 +489,7 @@ export function userContentPaths(devflowDir) {
|
|
|
488
489
|
const name = `${TRACKER_LEGACY_CONVENTIONS_FILE}.${id}.bak`;
|
|
489
490
|
return { relPath: name, label: `${name} (previous issue tracker conventions)` };
|
|
490
491
|
}),
|
|
491
|
-
// learning.json — global
|
|
492
|
+
// learning.json — global curate agent tuning config
|
|
492
493
|
{ relPath: 'learning.json', label: 'learning.json' },
|
|
493
494
|
// hud.json — user HUD enable/disable preference and display config
|
|
494
495
|
{ relPath: 'hud.json', label: 'hud.json (HUD configuration)' },
|
|
@@ -885,6 +886,89 @@ export async function runDryRunPhase(opts) {
|
|
|
885
886
|
}
|
|
886
887
|
}
|
|
887
888
|
}
|
|
889
|
+
/**
|
|
890
|
+
* After a selective uninstall removed a retired agent file, write the current commands
|
|
891
|
+
* and agents of the plugins that stay installed.
|
|
892
|
+
*
|
|
893
|
+
* A retired agent file only exists on a machine that ran an older release. That
|
|
894
|
+
* release's commands, for the plugins that stay, still spawn the retired name, and the
|
|
895
|
+
* agents that replaced it are not installed. Removing the file without this step would
|
|
896
|
+
* leave those plugins unable to spawn their agents until the next full `devflow init`.
|
|
897
|
+
*
|
|
898
|
+
* Writes only commands and agents, through the same copy path `devflow init` uses
|
|
899
|
+
* ({@link installCommandsAndAgents}). It does not touch the hooks, the scripts or
|
|
900
|
+
* settings.json, so the notice tells the user to run `devflow init` for those.
|
|
901
|
+
*
|
|
902
|
+
* Never runs in a legacy local scope (D-CLI-NO-SYMLINK): a repository can commit a command
|
|
903
|
+
* file as a symbolic link, and the copy writes through it. The folder guard below does not
|
|
904
|
+
* check files. `devflow init` can not update a legacy local install either, so the warning
|
|
905
|
+
* tells the user to remove it in full.
|
|
906
|
+
*
|
|
907
|
+
* Skipped, with a warning, when there is no readable manifest or it lists no known plugin (the
|
|
908
|
+
* retained set would be a guess), or when a folder is behind a link the caller's guard
|
|
909
|
+
* refuses. Those warnings name `devflow init` as the remedy. When the copy fails, it stops
|
|
910
|
+
* at the first failure: files it wrote before then stay, and the warning names the same
|
|
911
|
+
* remedy. Never throws: an uninstall must finish.
|
|
912
|
+
* Agent model lines are reverted again after the copy, as the selective phase does before
|
|
913
|
+
* its removal, so a freshly written agent carries no external-model line. Like the
|
|
914
|
+
* selective phase, it prints the warnings of that revert only with `verbose`.
|
|
915
|
+
*/
|
|
916
|
+
export async function refreshRetainedCommandsAndAgents(opts) {
|
|
917
|
+
const { claudeDir, devflowDir, retained, retiredAgents } = opts;
|
|
918
|
+
const scope = opts.scope ?? 'user';
|
|
919
|
+
const verbose = opts.verbose ?? false;
|
|
920
|
+
const mayChange = opts.mayChange ?? changeAnything;
|
|
921
|
+
const agentsDir = path.join(claudeDir, 'agents', 'devflow');
|
|
922
|
+
const commandsDir = path.join(claudeDir, 'commands', 'devflow');
|
|
923
|
+
const retired = `Removed the agent file(s) of an older Devflow release: ${retiredAgents.join(', ')}.`;
|
|
924
|
+
const remedy = 'Run `devflow init` to update the commands, agents, hooks and scripts of the plugins that stay installed.';
|
|
925
|
+
if (retained.length === 0)
|
|
926
|
+
return;
|
|
927
|
+
if (scope === 'local') {
|
|
928
|
+
p.log.warn(`${retired} Devflow does not rewrite files in a legacy local install, so the remaining commands can still name the removed agents. Remove the legacy local install in full with \`devflow uninstall --scope local\`.`);
|
|
929
|
+
return;
|
|
930
|
+
}
|
|
931
|
+
// readManifest returns null for a missing file and for one it can not parse or validate.
|
|
932
|
+
const manifest = await readManifest(devflowDir).catch(() => null);
|
|
933
|
+
if (manifest === null) {
|
|
934
|
+
p.log.warn(`${retired} There is no readable manifest, so Devflow did not rewrite the remaining files. ${remedy}`);
|
|
935
|
+
return;
|
|
936
|
+
}
|
|
937
|
+
if (manifest.plugins.length === 0) {
|
|
938
|
+
p.log.warn(`${retired} The manifest lists no plugins, so Devflow did not rewrite the remaining files. ${remedy}`);
|
|
939
|
+
return;
|
|
940
|
+
}
|
|
941
|
+
// resolveInstalledPlugins falls back to the whole registry when no manifest name resolves, so
|
|
942
|
+
// the retained set would hold plugins that were never installed.
|
|
943
|
+
if (!manifest.plugins.some(name => DEVFLOW_PLUGINS.some(plugin => plugin.name === name))) {
|
|
944
|
+
p.log.warn(`${retired} The manifest lists no known plugin, so Devflow did not rewrite the remaining files. ${remedy}`);
|
|
945
|
+
return;
|
|
946
|
+
}
|
|
947
|
+
if (!(await mayChange(agentsDir)) || !(await mayChange(commandsDir))) {
|
|
948
|
+
p.log.warn(`${retired} A linked folder blocks the rewrite. ${remedy}`);
|
|
949
|
+
return;
|
|
950
|
+
}
|
|
951
|
+
try {
|
|
952
|
+
await installCommandsAndAgents({
|
|
953
|
+
plugins: retained,
|
|
954
|
+
agentsMap: buildAssetMaps(retained).agentsMap,
|
|
955
|
+
claudeDir,
|
|
956
|
+
learning: manifest.features.learning,
|
|
957
|
+
trackerServers: effectiveTrackerServers(manifest.features.tracker),
|
|
958
|
+
warn: (msg) => p.log.warn(msg),
|
|
959
|
+
});
|
|
960
|
+
}
|
|
961
|
+
catch (err) {
|
|
962
|
+
p.log.warn(`${retired} Devflow could not write the current commands and agents (${err instanceof Error ? err.message : String(err)}). ${remedy}`);
|
|
963
|
+
return;
|
|
964
|
+
}
|
|
965
|
+
try {
|
|
966
|
+
await revertExternalAgents({ installDir: agentsDir, devflowDir, onWarning: (msg) => { if (verbose)
|
|
967
|
+
p.log.warn(msg); } });
|
|
968
|
+
}
|
|
969
|
+
catch { /* the revert is best effort, as in the selective phase */ }
|
|
970
|
+
p.log.info(`${retired} Devflow wrote the current commands and agents of the plugins that stay installed. Run \`devflow init\` to update the hooks and scripts.`);
|
|
971
|
+
}
|
|
888
972
|
/**
|
|
889
973
|
* SELECTIVE PHASE (per scope): revert agent model overrides, remove the
|
|
890
974
|
* selected plugins' assets, and clean up the ambient hook if the ambient
|
|
@@ -919,7 +1003,23 @@ export async function runSelectivePhaseForScope(opts) {
|
|
|
919
1003
|
}
|
|
920
1004
|
catch { /* agents dir absent or revert failed — non-fatal */ }
|
|
921
1005
|
}
|
|
922
|
-
await removeSelectedPlugins(claudeDir, selectedPlugins, verbose, installedPlugins, mayChange);
|
|
1006
|
+
const sweeps = await removeSelectedPlugins(claudeDir, selectedPlugins, verbose, installedPlugins, mayChange);
|
|
1007
|
+
// A retired agent file means the install is from an older release, and the commands of the
|
|
1008
|
+
// plugins that stay installed still spawn the name that was just removed. Write their
|
|
1009
|
+
// current commands and agents so the install stays whole. Runs before the language stamp
|
|
1010
|
+
// below, which then restamps the command this wrote.
|
|
1011
|
+
if (sweeps.agents.removed.length > 0) {
|
|
1012
|
+
const removed = new Set(selectedPlugins.map(sp => sp.name));
|
|
1013
|
+
await refreshRetainedCommandsAndAgents({
|
|
1014
|
+
claudeDir,
|
|
1015
|
+
devflowDir,
|
|
1016
|
+
retained: installedPlugins.filter(plugin => !removed.has(plugin.name)),
|
|
1017
|
+
retiredAgents: sweeps.agents.removed,
|
|
1018
|
+
scope,
|
|
1019
|
+
verbose,
|
|
1020
|
+
mayChange,
|
|
1021
|
+
});
|
|
1022
|
+
}
|
|
923
1023
|
// D-LANGUAGE-FOCUS-STAMP: re-stamp the installed /code-review from the selection that REMAINS.
|
|
924
1024
|
// A language plugin owns a skill and no command, so removing it deletes the skill while its
|
|
925
1025
|
// name would stay on the stamped line, and /code-review would spawn a focus whose skill is gone.
|
|
@@ -1627,6 +1727,9 @@ export async function removeAllDevFlow(claudeDir, devflowScriptsDir, verbose, ma
|
|
|
1627
1727
|
* A folder `mayChange` refuses is not swept at all (D-CLI-NO-SYMLINK,
|
|
1628
1728
|
* legacyLocalChangeGuard). An entry in a swept folder that is itself a link is
|
|
1629
1729
|
* only unlinked: `fs.rm` never follows the link it is given.
|
|
1730
|
+
*
|
|
1731
|
+
* Returns what each sweep removed and failed to remove, so a caller can tell that
|
|
1732
|
+
* a retired agent was removed (see {@link refreshRetainedCommandsAndAgents}).
|
|
1630
1733
|
*/
|
|
1631
1734
|
export async function sweepDevflowNamespaces(claudeDir, verbose, mayChange = changeAnything) {
|
|
1632
1735
|
const agentsDir = path.join(claudeDir, 'agents', 'devflow');
|
|
@@ -1656,6 +1759,7 @@ export async function sweepDevflowNamespaces(claudeDir, verbose, mayChange = cha
|
|
|
1656
1759
|
p.log.warn(`Could not remove orphaned ${kind} "${failure.name}" (${reason}) — remove it manually`);
|
|
1657
1760
|
}
|
|
1658
1761
|
}
|
|
1762
|
+
return { agents: agentsSweep, commands: commandsSweep, skills: skillsSweep };
|
|
1659
1763
|
}
|
|
1660
1764
|
/**
|
|
1661
1765
|
* Remove only specific plugin assets (selective uninstall).
|
|
@@ -1665,6 +1769,8 @@ export async function sweepDevflowNamespaces(claudeDir, verbose, mayChange = cha
|
|
|
1665
1769
|
* For skills: only remove skills that are NOT used by any remaining plugin.
|
|
1666
1770
|
* Each removal passes `mayChange` first, which skips one a symbolic link would
|
|
1667
1771
|
* redirect in a legacy local install (D-CLI-NO-SYMLINK, legacyLocalChangeGuard).
|
|
1772
|
+
*
|
|
1773
|
+
* Returns what the closing registry-diff sweep removed.
|
|
1668
1774
|
*/
|
|
1669
1775
|
export async function removeSelectedPlugins(claudeDir, plugins, verbose, installedPlugins = DEVFLOW_PLUGINS, mayChange = changeAnything) {
|
|
1670
1776
|
const { skills, agents, commands, rules } = computeAssetsToRemove(plugins, installedPlugins);
|
|
@@ -1734,6 +1840,6 @@ export async function removeSelectedPlugins(claudeDir, plugins, verbose, install
|
|
|
1734
1840
|
// Removes any orphaned files whose names left the registry (retired, renamed,
|
|
1735
1841
|
// or deleted from all plugins). Spans ALL plugins so assets belonging to
|
|
1736
1842
|
// non-selected plugins are never swept.
|
|
1737
|
-
|
|
1843
|
+
return sweepDevflowNamespaces(claudeDir, verbose, mayChange);
|
|
1738
1844
|
}
|
|
1739
1845
|
//# sourceMappingURL=uninstall.js.map
|
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
|
|
@@ -195,19 +195,19 @@ The accepted line is the only source of these values: the script alone folds the
|
|
|
195
195
|
|
|
196
196
|
When the settings line says `LEARNING=off`, set `DECISIONS_CONTEXT` to `(none)` and skip this step, locating no ledger and reading no index.
|
|
197
197
|
|
|
198
|
-
The decisions ledger belongs to the repository, not to one checkout:
|
|
198
|
+
The decisions ledger belongs to the repository, not to one checkout: a linked worktree reads the main worktree's copy, a subdirectory session the repository root's. Locate it with ONE git call, run from the start directory — `WORKTREE_PATH` if provided, otherwise cwd (`devflow:worktree-support`):
|
|
199
199
|
|
|
200
200
|
```bash
|
|
201
201
|
git -C "{start}" rev-parse --path-format=absolute --show-toplevel --git-common-dir
|
|
202
202
|
```
|
|
203
203
|
|
|
204
|
-
Line 1 is the checkout's toplevel, line 2 the
|
|
204
|
+
Line 1 is the checkout's toplevel, line 2 the common git directory. A git older than 2.31 echoes `--path-format=absolute` back as a line of its own first. `{ledger}` is the first that applies:
|
|
205
205
|
|
|
206
206
|
1. **The main worktree** — line 2 without its trailing `/.git`, when the output is exactly two lines each beginning with `/`, line 2 ends in `/.git`, and the directory left once it is removed is not your home directory and contains a `.devflow/` directory.
|
|
207
207
|
2. **The toplevel** — line 1, or on an older git the line after the echoed flag.
|
|
208
208
|
3. **The start directory itself** — when the command failed or printed no absolute toplevel (outside a git repository).
|
|
209
209
|
|
|
210
|
-
This is the rule the learning hooks apply
|
|
210
|
+
This is the rule the learning hooks apply, so you read the index the Curate agent writes.
|
|
211
211
|
|
|
212
212
|
**Step 1 — Read the pre-rendered index:**
|
|
213
213
|
|
|
@@ -216,11 +216,15 @@ Attempt to read `{ledger}/.devflow/learning/index.md`.
|
|
|
216
216
|
- If the file exists and contains non-empty content: use that content as `DECISIONS_CONTEXT`.
|
|
217
217
|
- If the file is absent or empty: set `DECISIONS_CONTEXT` to `(none)`.
|
|
218
218
|
|
|
219
|
-
The index is one direct file read, written at render time by `render-decisions.cjs`
|
|
219
|
+
The index is one direct file read, written at render time by `render-decisions.cjs` — no `.cjs` script runs here.
|
|
220
220
|
|
|
221
|
-
**Step 2 —
|
|
221
|
+
**Step 2 — Slice the index, then hand it on:**
|
|
222
222
|
|
|
223
|
-
When `DECISIONS_CONTEXT` is not `(none)`,
|
|
223
|
+
When `DECISIONS_CONTEXT` is not `(none)`, hand it only to the agents whose contract declares it.
|
|
224
|
+
|
|
225
|
+
Hand each agent that takes `DECISIONS_CONTEXT` a slice, not the whole index: the index lines whose title, scope or area touch the files and task it works on, verbatim, led by `(slice: N of M entries — full index: <absolute index path>)` and closed by the index footer. When unsure, include the line. Siblings over one diff share ONE slice.
|
|
226
|
+
|
|
227
|
+
Those agents follow `devflow:apply-decisions`. A host that uses the index in its own thread says so in its own step.
|
|
224
228
|
|
|
225
229
|
#### Feature Knowledge
|
|
226
230
|
|
|
@@ -246,7 +250,7 @@ If `index.md` exists and contains at least one entry line, use it for relevance
|
|
|
246
250
|
|
|
247
251
|
**Step 2 — Fallback: glob frontmatter (if `index.md` is absent or empty):**
|
|
248
252
|
|
|
249
|
-
Glob `{worktree}/.devflow/features/*/KNOWLEDGE.md`. For each file found, read only its YAML frontmatter block (between the opening and closing `---` delimiters).
|
|
253
|
+
Glob `{worktree}/.devflow/features/*/KNOWLEDGE.md`. For each file found, read only its YAML frontmatter block (between the opening and closing `---` delimiters).
|
|
250
254
|
|
|
251
255
|
**Step 3 — Pick relevant KBs:**
|
|
252
256
|
|
|
@@ -277,12 +281,12 @@ Headings: L5 Rules · L40 Overview · L62 Anti-Patterns · L118 Key Files
|
|
|
277
281
|
|
|
278
282
|
A KB with no Rules section labels its entries `Rules ({section name}):` and gives them no ID. `FEATURE_KNOWLEDGE` is these blocks; `FEATURE_KNOWLEDGE_RULES` is the same blocks without the `Headings:` line. Both come from this one selection, and each spawn names the variable its recipient takes. If no KBs exist, no KBs are relevant, or `.devflow/features/` is absent, set both to `(none)`.
|
|
279
283
|
|
|
280
|
-
**One git call, then direct reads — no `.cjs` script.**
|
|
284
|
+
**One git call, then direct reads — no `.cjs` script.**
|
|
281
285
|
|
|
282
286
|
#### Plan Artifact
|
|
283
287
|
|
|
284
|
-
1. List `{worktree}/.devflow/docs/design/*.md`
|
|
285
|
-
2. Read the most recent file
|
|
288
|
+
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
|
|
289
|
+
2. Read the most recent file that carries an `## Acceptance Criteria` section
|
|
286
290
|
3. Extract `## Acceptance Criteria` section → parse into table: `| ID | Criterion | Type | Testable Condition |`
|
|
287
291
|
4. Set `PLAN_CONTEXT` to plan summary; `ACCEPTANCE_RULES` to the table
|
|
288
292
|
5. If no plan files exist or section not found: `PLAN_CONTEXT=(none)`, `ACCEPTANCE_RULES=(none)`
|
|
@@ -306,11 +310,11 @@ Determine which focus analyzers to run using `CHANGED_FILES` (already computed i
|
|
|
306
310
|
**Produces:** ANALYZER_OUTPUTS
|
|
307
311
|
**Requires:** DIFF_RANGE, ANALYSIS_DIR, ACTIVE_FOCUSES, STATIC_FINDINGS, ACCEPTANCE_RULES, PLAN_CONTEXT, DECISIONS_CONTEXT, FEATURE_KNOWLEDGE
|
|
308
312
|
|
|
309
|
-
Spawn ALL active
|
|
313
|
+
Spawn ALL active Debug agents **in a single message** (parallel, NOT background):
|
|
310
314
|
|
|
311
315
|
For each active focus, spawn:
|
|
312
316
|
```
|
|
313
|
-
Agent(subagent_type="
|
|
317
|
+
Agent(subagent_type="Debug", run_in_background=false):
|
|
314
318
|
"Analyze focusing on {focus}.
|
|
315
319
|
FOCUS: {focus}
|
|
316
320
|
DIFF_COMMAND: git diff {DIFF_RANGE}
|
|
@@ -408,10 +412,10 @@ Run `/resolve` to process and fix these findings.
|
|
|
408
412
|
│ └─ Detect active focuses (security + functional always; integration + usability conditional)
|
|
409
413
|
│
|
|
410
414
|
├─ Phase 5: Bug Analysis (PARALLEL)
|
|
411
|
-
│ ├─
|
|
412
|
-
│ ├─
|
|
413
|
-
│ ├─
|
|
414
|
-
│ └─
|
|
415
|
+
│ ├─ Debug agent: security (+ STATIC_FINDINGS)
|
|
416
|
+
│ ├─ Debug agent: functional
|
|
417
|
+
│ ├─ Debug agent: integration (conditional)
|
|
418
|
+
│ └─ Debug agent: usability (conditional)
|
|
415
419
|
│
|
|
416
420
|
├─ Phase 6: Synthesis
|
|
417
421
|
│ └─ Synthesize agent (mode: bug-analysis)
|
|
@@ -448,7 +452,7 @@ Run `/resolve` after `/bug-analysis` to fix identified bugs. `/resolve` automati
|
|
|
448
452
|
2. **Parallel, not background** — Analyzers spawn in one message with `run_in_background=false`
|
|
449
453
|
3. **Static + semantic** — Two complementary tracks, each validates the other
|
|
450
454
|
4. **Incremental by default** — Only analyze new changes unless `--full` specified
|
|
451
|
-
5. **Verify before reporting** —
|
|
455
|
+
5. **Verify before reporting** — Debug agents self-verify every finding
|
|
452
456
|
6. **Honest reporting** — Display risk level and counts directly from synthesis
|
|
453
457
|
|
|
454
458
|
## Phase Completion Checklist
|
|
@@ -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:
|
|
@@ -287,19 +288,19 @@ The core, database, dependencies, documentation and compliance focuses, and ever
|
|
|
287
288
|
|
|
288
289
|
When the settings line says `LEARNING=off`, set `DECISIONS_CONTEXT` to `(none)` and skip this step, locating no ledger and reading no index.
|
|
289
290
|
|
|
290
|
-
The decisions ledger belongs to the repository, not to one checkout:
|
|
291
|
+
The decisions ledger belongs to the repository, not to one checkout: a linked worktree reads the main worktree's copy, a subdirectory session the repository root's. Locate it with ONE git call, run from the start directory — `WORKTREE_PATH` if provided, otherwise cwd (`devflow:worktree-support`):
|
|
291
292
|
|
|
292
293
|
```bash
|
|
293
294
|
git -C "{start}" rev-parse --path-format=absolute --show-toplevel --git-common-dir
|
|
294
295
|
```
|
|
295
296
|
|
|
296
|
-
Line 1 is the checkout's toplevel, line 2 the
|
|
297
|
+
Line 1 is the checkout's toplevel, line 2 the common git directory. A git older than 2.31 echoes `--path-format=absolute` back as a line of its own first. `{ledger}` is the first that applies:
|
|
297
298
|
|
|
298
299
|
1. **The main worktree** — line 2 without its trailing `/.git`, when the output is exactly two lines each beginning with `/`, line 2 ends in `/.git`, and the directory left once it is removed is not your home directory and contains a `.devflow/` directory.
|
|
299
300
|
2. **The toplevel** — line 1, or on an older git the line after the echoed flag.
|
|
300
301
|
3. **The start directory itself** — when the command failed or printed no absolute toplevel (outside a git repository).
|
|
301
302
|
|
|
302
|
-
This is the rule the learning hooks apply
|
|
303
|
+
This is the rule the learning hooks apply, so you read the index the Curate agent writes.
|
|
303
304
|
|
|
304
305
|
**Step 1 — Read the pre-rendered index:**
|
|
305
306
|
|
|
@@ -308,13 +309,17 @@ Attempt to read `{ledger}/.devflow/learning/index.md`.
|
|
|
308
309
|
- If the file exists and contains non-empty content: use that content as `DECISIONS_CONTEXT`.
|
|
309
310
|
- If the file is absent or empty: set `DECISIONS_CONTEXT` to `(none)`.
|
|
310
311
|
|
|
311
|
-
The index is one direct file read, written at render time by `render-decisions.cjs`
|
|
312
|
+
The index is one direct file read, written at render time by `render-decisions.cjs` — no `.cjs` script runs here.
|
|
312
313
|
|
|
313
|
-
**Step 2 —
|
|
314
|
+
**Step 2 — Slice the index, then hand it on:**
|
|
314
315
|
|
|
315
|
-
When `DECISIONS_CONTEXT` is not `(none)`,
|
|
316
|
+
When `DECISIONS_CONTEXT` is not `(none)`, hand it only to the agents whose contract declares it.
|
|
316
317
|
|
|
317
|
-
|
|
318
|
+
Hand each agent that takes `DECISIONS_CONTEXT` a slice, not the whole index: the index lines whose title, scope or area touch the files and task it works on, verbatim, led by `(slice: N of M entries — full index: <absolute index path>)` and closed by the index footer. When unsure, include the line. Siblings over one diff share ONE slice.
|
|
319
|
+
|
|
320
|
+
Those agents follow `devflow:apply-decisions`. A host that uses the index in its own thread says so in its own step.
|
|
321
|
+
|
|
322
|
+
This produces a compact index of active ADR/PF entries. Pass `DECISIONS_CONTEXT` to all Review agents as one shared slice, cut over the diff's files. Review agents use `devflow:apply-decisions` to Read full entry bodies on demand.
|
|
318
323
|
|
|
319
324
|
### Load Feature Knowledge
|
|
320
325
|
|
|
@@ -338,7 +343,7 @@ If `index.md` exists and contains at least one entry line, use it for relevance
|
|
|
338
343
|
|
|
339
344
|
**Step 2 — Fallback: glob frontmatter (if `index.md` is absent or empty):**
|
|
340
345
|
|
|
341
|
-
Glob `{worktree}/.devflow/features/*/KNOWLEDGE.md`. For each file found, read only its YAML frontmatter block (between the opening and closing `---` delimiters).
|
|
346
|
+
Glob `{worktree}/.devflow/features/*/KNOWLEDGE.md`. For each file found, read only its YAML frontmatter block (between the opening and closing `---` delimiters).
|
|
342
347
|
|
|
343
348
|
**Step 3 — Pick relevant KBs:**
|
|
344
349
|
|
|
@@ -369,7 +374,7 @@ Headings: L5 Rules · L40 Overview · L62 Anti-Patterns · L118 Key Files
|
|
|
369
374
|
|
|
370
375
|
A KB with no Rules section labels its entries `Rules ({section name}):` and gives them no ID. `FEATURE_KNOWLEDGE` is these blocks; `FEATURE_KNOWLEDGE_RULES` is the same blocks without the `Headings:` line. Both come from this one selection, and each spawn names the variable its recipient takes. If no KBs exist, no KBs are relevant, or `.devflow/features/` is absent, set both to `(none)`.
|
|
371
376
|
|
|
372
|
-
**One git call, then direct reads — no `.cjs` script.**
|
|
377
|
+
**One git call, then direct reads — no `.cjs` script.**
|
|
373
378
|
|
|
374
379
|
Pass `FEATURE_KNOWLEDGE` to all Review agents alongside `DECISIONS_CONTEXT`.
|
|
375
380
|
|
|
@@ -408,6 +413,10 @@ Spawn Review agents **in a single message**, for the focus set `DIFF_CLASS` sele
|
|
|
408
413
|
|
|
409
414
|
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
415
|
|
|
416
|
+
**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:
|
|
417
|
+
|
|
418
|
+
> 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.
|
|
419
|
+
|
|
411
420
|
Each Review agent invocation (all in one message, **NOT background**):
|
|
412
421
|
```
|
|
413
422
|
Agent(subagent_type="Review", run_in_background=false):
|
|
@@ -421,7 +430,7 @@ DECISIONS_CONTEXT: {decisions_context}
|
|
|
421
430
|
FEATURE_KNOWLEDGE: {feature_knowledge}
|
|
422
431
|
PR_DESCRIPTION: <pr-description>{pr_description}</pr-description>
|
|
423
432
|
PRIOR_RESOLUTIONS: <prior-resolution-summary>{prior_resolutions}</prior-resolution-summary>
|
|
424
|
-
|
|
433
|
+
{COMPLIANCE_FOCUS_DIRECTIVE} (compliance focus only)
|
|
425
434
|
If PRIOR_RESOLUTIONS is not (none), follow Cross-Cycle Awareness in review.md.
|
|
426
435
|
Follow devflow:apply-decisions to scan the index and Read full ADR/PF bodies on demand.
|
|
427
436
|
Follow devflow:apply-feature-knowledge for FEATURE_KNOWLEDGE — feature-specific patterns and anti-patterns inform findings.
|
|
@@ -517,21 +526,8 @@ In multi-worktree mode, report results per worktree.
|
|
|
517
526
|
|
|
518
527
|
| Case | Handling |
|
|
519
528
|
|------|----------|
|
|
520
|
-
| No new commits since last review | Skip review, report: "No new commits since last review. Use --full for a full re-review." |
|
|
521
|
-
| Rebase invalidates `.last-review-head` SHA | `git cat-file -t` check fails → fallback to full diff |
|
|
522
|
-
| Same-minute review collision | `mkdir` fails → retry with seconds appended (`YYYY-MM-DD_HHMMSS`) |
|
|
523
|
-
| Worktree in detached HEAD | Filtered out (no branch name → not reviewable) |
|
|
524
|
-
| Worktree mid-rebase or mid-merge | Filtered out by status check |
|
|
525
|
-
| Two worktrees on same branch | Deduplicate by branch — review once, use first worktree's path |
|
|
526
|
-
| Worktree on protected branch | Filtered out (not reviewable) |
|
|
527
|
-
| Worktree pre-flight fails | Report failure, continue with other worktrees |
|
|
528
529
|
| `--full` in multi-worktree mode | Applies to all worktrees (global modifier) |
|
|
529
|
-
| Many worktrees (5+) | Report count and proceed — user manages their worktree count |
|
|
530
530
|
| Review comment already posted | Git agent matches its own marker on the `{cycle, timestamp}` pair → skip silently (D7); a re-review in the same cycle (different timestamp) posts its own comment. The marker's format belongs to the operation; this caller passes the pair and never restates the literal |
|
|
531
|
-
| First review (no prior resolution) | PRIOR_RESOLUTIONS=(none), no convergence check |
|
|
532
|
-
| fp_ratio denominator = 0 | fp_ratio = 0, no warning |
|
|
533
|
-
| `--full` flag | Bypass incremental detection (Step 0d), still load PRIOR_RESOLUTIONS for cross-cycle awareness |
|
|
534
|
-
| Parsing failure on resolution-summary.md | fp_ratio = 0, convergence tracking degraded (see Step 0e-ii) |
|
|
535
531
|
| Concurrent sessions | Advisory only, each session computes independently |
|
|
536
532
|
| Docs-only diff | `docs-only`: documentation, consistency, security on `diff.patch`; no language or conditional focus |
|
|
537
533
|
| Tests-only diff | `tests-only`: testing, reliability, consistency, security on `diff.patch`; no language or conditional focus |
|
package/dist/commands/debug.md
CHANGED
|
@@ -42,23 +42,31 @@ 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.
|
|
48
56
|
|
|
49
|
-
The decisions ledger belongs to the repository, not to one checkout:
|
|
57
|
+
The decisions ledger belongs to the repository, not to one checkout: a linked worktree reads the main worktree's copy, a subdirectory session the repository root's. Locate it with ONE git call, run from the start directory — `WORKTREE_PATH` if provided, otherwise cwd (`devflow:worktree-support`):
|
|
50
58
|
|
|
51
59
|
```bash
|
|
52
60
|
git -C "{start}" rev-parse --path-format=absolute --show-toplevel --git-common-dir
|
|
53
61
|
```
|
|
54
62
|
|
|
55
|
-
Line 1 is the checkout's toplevel, line 2 the
|
|
63
|
+
Line 1 is the checkout's toplevel, line 2 the common git directory. A git older than 2.31 echoes `--path-format=absolute` back as a line of its own first. `{ledger}` is the first that applies:
|
|
56
64
|
|
|
57
65
|
1. **The main worktree** — line 2 without its trailing `/.git`, when the output is exactly two lines each beginning with `/`, line 2 ends in `/.git`, and the directory left once it is removed is not your home directory and contains a `.devflow/` directory.
|
|
58
66
|
2. **The toplevel** — line 1, or on an older git the line after the echoed flag.
|
|
59
67
|
3. **The start directory itself** — when the command failed or printed no absolute toplevel (outside a git repository).
|
|
60
68
|
|
|
61
|
-
This is the rule the learning hooks apply
|
|
69
|
+
This is the rule the learning hooks apply, so you read the index the Curate agent writes.
|
|
62
70
|
|
|
63
71
|
**Step 1 — Read the pre-rendered index:**
|
|
64
72
|
|
|
@@ -67,11 +75,15 @@ Attempt to read `{ledger}/.devflow/learning/index.md`.
|
|
|
67
75
|
- If the file exists and contains non-empty content: use that content as `DECISIONS_CONTEXT`.
|
|
68
76
|
- If the file is absent or empty: set `DECISIONS_CONTEXT` to `(none)`.
|
|
69
77
|
|
|
70
|
-
The index is one direct file read, written at render time by `render-decisions.cjs`
|
|
78
|
+
The index is one direct file read, written at render time by `render-decisions.cjs` — no `.cjs` script runs here.
|
|
79
|
+
|
|
80
|
+
**Step 2 — Slice the index, then hand it on:**
|
|
71
81
|
|
|
72
|
-
|
|
82
|
+
When `DECISIONS_CONTEXT` is not `(none)`, hand it only to the agents whose contract declares it.
|
|
73
83
|
|
|
74
|
-
|
|
84
|
+
Hand each agent that takes `DECISIONS_CONTEXT` a slice, not the whole index: the index lines whose title, scope or area touch the files and task it works on, verbatim, led by `(slice: N of M entries — full index: <absolute index path>)` and closed by the index footer. When unsure, include the line. Siblings over one diff share ONE slice.
|
|
85
|
+
|
|
86
|
+
Those agents follow `devflow:apply-decisions`. A host that uses the index in its own thread says so in its own step.
|
|
75
87
|
|
|
76
88
|
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
89
|
|
|
@@ -226,7 +238,20 @@ Produce the final report:
|
|
|
226
238
|
|
|
227
239
|
Ask user via AskUserQuestion: "Want me to implement this fix?"
|
|
228
240
|
|
|
229
|
-
- **YES** →
|
|
241
|
+
- **YES** → implement the fix through the Code agent, never in this thread, then spawn `Agent(subagent_type="Polish")` on the changed files. /debug loads no feature knowledge, so the fix gets none:
|
|
242
|
+
|
|
243
|
+
```
|
|
244
|
+
Agent(subagent_type="Code"):
|
|
245
|
+
"OPERATION: implement
|
|
246
|
+
TASK_ID: debug-{YYYY-MM-DD_HHMM}
|
|
247
|
+
TASK_DESCRIPTION: Implement the fix for this root cause: {bug description}
|
|
248
|
+
EXECUTION_PLAN: {Root Cause, Key Findings and Recommended Fix from Phase 6, with their file:line references}
|
|
249
|
+
PUSH: false
|
|
250
|
+
DECISIONS_CONTEXT: {decisions_context}
|
|
251
|
+
FEATURE_KNOWLEDGE: (none)
|
|
252
|
+
{COMPLIANCE_DIRECTIVE}"
|
|
253
|
+
```
|
|
254
|
+
|
|
230
255
|
- **NO** → Done. Report stands as documentation.
|
|
231
256
|
|
|
232
257
|
### Feature Knowledge Write-Back (Conditional)
|
|
@@ -261,21 +286,17 @@ FEATURE_SLUG: {slug derived from primary changed directory, kebab-case}
|
|
|
261
286
|
FEATURE_NAME: {human-readable name}
|
|
262
287
|
DIRECTORIES: {list of primary directories touched by this workflow}
|
|
263
288
|
FILES_CHANGED: {list of files changed}
|
|
264
|
-
DECISIONS_CONTEXT: {
|
|
289
|
+
DECISIONS_CONTEXT: {the slice for these directories, else (none)}
|
|
265
290
|
|
|
266
291
|
Write the knowledge base to:
|
|
267
292
|
{worktree}/.devflow/features/{slug}/KNOWLEDGE.md
|
|
268
293
|
|
|
269
|
-
Then update the index cache
|
|
294
|
+
Then update the index cache:
|
|
270
295
|
{worktree}/.devflow/features/index.md
|
|
271
296
|
|
|
272
297
|
Index line format: `- **{slug}** — {areas} — {Use-when description}` — at most 300 characters, the description at most 220; reword a longer one, never cut it.
|
|
273
298
|
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
The frontmatter in KNOWLEDGE.md is the source of truth — index.md is only a cache. Write the two files directly — no intermediate result JSON files, no external scripts.
|
|
277
|
-
|
|
278
|
-
After writing, commit the two files to the current worktree branch yourself by running git via your Bash tool (do not use a script). Stage ONLY .devflow/features/index.md and .devflow/features/{slug}/KNOWLEDGE.md, then commit just those paths with a docs(knowledge): message. Do NOT push, do NOT force, do NOT stage anything else. Follow your Commit Protocol — it is non-blocking, so if any git step fails, report KB_COMMIT and finish normally."
|
|
299
|
+
Then commit the two files as your Commit Protocol directs."
|
|
279
300
|
```
|
|
280
301
|
|
|
281
302
|
**Step 4 — Surface an uncommitted knowledge base:**
|
|
@@ -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) + Polish agent, or done
|
|
311
332
|
│
|
|
312
333
|
└─ Feature Knowledge Write-Back (Conditional)
|
|
313
334
|
└─ Knowledge agent (if investigation surfaced durable cross-cutting knowledge)
|