devflow-kit 3.10.0 → 3.12.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 +74 -0
- package/dist/agents/architect.md +87 -0
- package/dist/agents/code.md +21 -25
- package/dist/agents/debug.md +21 -49
- package/dist/agents/design.md +9 -43
- package/dist/agents/fix.md +15 -29
- package/dist/agents/git.md +19 -22
- package/dist/agents/harden.md +14 -19
- package/dist/agents/knowledge.md +11 -19
- package/dist/agents/refactor.md +9 -14
- package/dist/agents/research.md +11 -34
- package/dist/agents/review.md +22 -52
- package/dist/agents/skim.md +7 -17
- package/dist/agents/triage.md +7 -14
- package/dist/cli/commands/backup-session.js +131 -0
- package/dist/cli/commands/compliance.js +16 -3
- package/dist/cli/commands/curation.js +12 -4
- package/dist/cli/commands/init.js +36 -55
- package/dist/cli/commands/install-report.js +95 -0
- package/dist/cli/commands/legacy-sweep.js +140 -45
- package/dist/cli/commands/rules.js +50 -13
- package/dist/cli/commands/uninstall.js +62 -24
- package/dist/commands/bug-analysis.md +31 -62
- package/dist/commands/code-review.md +38 -87
- package/dist/commands/debug.md +32 -82
- package/dist/commands/dynamic-build.md +155 -211
- package/dist/commands/dynamic-plan.md +71 -93
- package/dist/commands/dynamic-profile.md +7 -155
- package/dist/commands/dynamic-tickets.md +65 -186
- package/dist/commands/explore.md +27 -70
- package/dist/commands/implement.md +98 -186
- package/dist/commands/plan.md +60 -107
- package/dist/commands/release.md +25 -91
- package/dist/commands/research.md +34 -103
- package/dist/commands/resolve.md +64 -128
- package/dist/commands/self-review.md +35 -99
- package/dist/compliance-off/agents/git.md +15 -18
- package/dist/compliance-off/agents/triage.md +7 -14
- package/dist/compliance-off/commands/bug-analysis.md +31 -62
- package/dist/compliance-off/commands/code-review.md +34 -82
- package/dist/compliance-off/commands/dynamic-build.md +149 -205
- package/dist/compliance-off/commands/dynamic-tickets.md +65 -186
- package/dist/compliance-off/commands/implement.md +94 -180
- package/dist/compliance-off/commands/plan.md +60 -107
- package/dist/compliance-off/commands/release.md +25 -90
- package/dist/compliance-off/commands/resolve.md +54 -128
- package/dist/compliance-off/skills/git/references/tracker/github/ensure-pr-ready.md +3 -3
- package/dist/compliance-off/skills/git/references/tracker/jira/ensure-pr-ready.md +3 -3
- package/dist/compliance-off/skills/git/references/tracker/linear/ensure-pr-ready.md +3 -3
- package/dist/core/compliance.js +14 -0
- package/dist/core/fs-atomic.js +5 -1
- package/dist/core/orphan-sweep.js +20 -2
- package/dist/core/path-set.js +15 -0
- package/dist/core/plugins.js +6 -5
- package/dist/core/reference-sweep.js +42 -25
- package/dist/core/retired-shipped-names.js +278 -0
- package/dist/curation-compliance-off/agents/triage.md +7 -13
- package/dist/curation-compliance-off/commands/bug-analysis.md +21 -41
- package/dist/curation-compliance-off/commands/code-review.md +25 -62
- package/dist/curation-compliance-off/commands/dynamic-build.md +142 -194
- package/dist/curation-compliance-off/commands/dynamic-tickets.md +54 -173
- package/dist/curation-compliance-off/commands/implement.md +86 -161
- package/dist/curation-compliance-off/commands/plan.md +51 -86
- package/dist/curation-compliance-off/commands/release.md +17 -78
- package/dist/curation-compliance-off/commands/resolve.md +45 -108
- package/dist/curation-off/agents/architect.md +81 -0
- package/dist/curation-off/agents/code.md +20 -23
- package/dist/curation-off/agents/debug.md +19 -47
- package/dist/curation-off/agents/design.md +8 -41
- package/dist/curation-off/agents/fix.md +14 -27
- package/dist/curation-off/agents/harden.md +13 -18
- package/dist/curation-off/agents/knowledge.md +9 -17
- package/dist/curation-off/agents/refactor.md +8 -12
- package/dist/curation-off/agents/research.md +9 -32
- package/dist/curation-off/agents/review.md +11 -40
- package/dist/curation-off/agents/skim.md +7 -17
- package/dist/curation-off/agents/triage.md +7 -13
- package/dist/curation-off/commands/bug-analysis.md +21 -41
- package/dist/curation-off/commands/code-review.md +29 -67
- package/dist/curation-off/commands/debug.md +24 -63
- package/dist/curation-off/commands/dynamic-build.md +148 -200
- package/dist/curation-off/commands/dynamic-plan.md +60 -80
- package/dist/curation-off/commands/dynamic-tickets.md +54 -173
- package/dist/curation-off/commands/explore.md +18 -50
- package/dist/curation-off/commands/implement.md +90 -167
- package/dist/curation-off/commands/plan.md +51 -86
- package/dist/curation-off/commands/release.md +17 -79
- package/dist/curation-off/commands/research.md +23 -81
- package/dist/curation-off/commands/resolve.md +55 -108
- package/dist/curation-off/commands/self-review.md +26 -78
- package/dist/skills/git/references/pr/update-pr-evidence.md +2 -1
- package/dist/skills/git/references/tracker/github/ensure-pr-ready.md +3 -3
- package/dist/skills/git/references/tracker/jira/ensure-pr-ready.md +3 -3
- package/dist/skills/git/references/tracker/linear/ensure-pr-ready.md +3 -3
- package/dist/targets/claude-code/compliance-install.js +38 -13
- package/dist/targets/claude-code/compliance-off-files.js +5 -1
- package/dist/targets/claude-code/curation-install.js +77 -32
- package/dist/targets/claude-code/folder-swap.js +142 -0
- package/dist/targets/claude-code/install-backup.js +780 -0
- package/dist/targets/claude-code/installer.js +383 -192
- package/dist/targets/claude-code/legacy-skill-hashes.js +170 -0
- package/dist/targets/claude-code/linked-folder.js +5 -11
- package/dist/targets/claude-code/reference-converge.js +15 -2
- package/dist/targets/claude-code/rules-folder.js +34 -0
- package/dist/targets/claude-code/shipped-set.js +160 -0
- package/dist/targets/claude-code/workflow-folder-install.js +32 -12
- package/dist/variant-axes.json +5 -1
- package/package.json +1 -1
- package/src/assets/agents/_partials/_code.mds +3 -5
- package/src/assets/agents/_partials/_design.mds +86 -0
- package/src/assets/agents/architect.mds +41 -0
- package/src/assets/agents/code.mds +18 -20
- package/src/assets/agents/curate.md +26 -35
- package/src/assets/agents/debug.mds +21 -49
- package/src/assets/agents/design.mds +11 -114
- package/src/assets/agents/evaluate.md +6 -16
- package/src/assets/agents/explore.md +1 -2
- package/src/assets/agents/fix.mds +12 -24
- package/src/assets/agents/git.mds +20 -23
- package/src/assets/agents/harden.mds +14 -19
- package/src/assets/agents/knowledge.mds +10 -38
- package/src/assets/agents/polish.md +13 -39
- package/src/assets/agents/refactor.mds +6 -9
- package/src/assets/agents/research.mds +11 -34
- package/src/assets/agents/review.mds +12 -84
- package/src/assets/agents/skim.mds +7 -17
- package/src/assets/agents/synthesize.md +3 -21
- package/src/assets/agents/test.md +31 -32
- package/src/assets/agents/tracker.md +116 -229
- package/src/assets/agents/triage.mds +7 -26
- package/src/assets/agents/validate.md +1 -3
- package/src/assets/commands/_partials/_compliance.mds +2 -2
- package/src/assets/commands/_partials/_decisions.mds +17 -24
- package/src/assets/commands/_partials/_docs_root.mds +31 -10
- package/src/assets/commands/_partials/_engine.mds +34 -56
- package/src/assets/commands/_partials/_evidence_policy.mds +1 -1
- package/src/assets/commands/_partials/_factory.mds +10 -104
- package/src/assets/commands/_partials/_knowledge.mds +47 -51
- package/src/assets/commands/_partials/_plan_contract.mds +2 -2
- package/src/assets/commands/_partials/_preamble.mds +21 -21
- package/src/assets/commands/_partials/_publication.mds +3 -3
- package/src/assets/commands/_partials/_roster.mds +12 -13
- package/src/assets/commands/_partials/_settings.mds +6 -3
- package/src/assets/commands/_partials/_ticket_template.mds +3 -7
- package/src/assets/commands/_partials/_tracker.mds +10 -5
- package/src/assets/commands/_partials/_wave.mds +23 -32
- package/src/assets/commands/bug-analysis.mds +3 -7
- package/src/assets/commands/code-review.mds +12 -33
- package/src/assets/commands/debug.mds +5 -47
- package/src/assets/commands/dynamic-build.mds +48 -70
- package/src/assets/commands/dynamic-plan.mds +23 -42
- package/src/assets/commands/dynamic-profile.mds +7 -57
- package/src/assets/commands/dynamic-tickets.mds +9 -29
- package/src/assets/commands/explore.mds +5 -44
- package/src/assets/commands/implement.mds +75 -117
- package/src/assets/commands/plan.mds +27 -57
- package/src/assets/commands/release.mds +4 -62
- package/src/assets/commands/research.mds +7 -53
- package/src/assets/commands/resolve.mds +40 -87
- package/src/assets/commands/self-review.mds +5 -45
- package/src/assets/mds/git/_ops_pr.mds +1 -0
- package/src/assets/mds/git/_ops_steps.mds +4 -4
- package/src/assets/mds/git/_pr.mds +1 -1
- package/src/assets/rules/engineering.md +1 -1
- package/src/assets/rules/quality.md +2 -2
- package/src/assets/scripts/ci-wait.cjs +150 -18
- package/src/assets/scripts/hooks/assets/orchestrator-charter.md +3 -3
- package/src/assets/scripts/hooks/preamble +2 -3
- package/src/assets/scripts/pr-evidence.cjs +1 -0
- package/src/assets/scripts/resolve-evidence-policy.cjs +14 -13
- package/src/assets/scripts/resolve-root.cjs +186 -0
- package/src/assets/scripts/resolve-settings.cjs +14 -9
- package/src/assets/scripts/verify-evidence.cjs +355 -22
- package/src/assets/skills/accessibility/SKILL.md +28 -95
- package/src/assets/skills/agent-references/SKILL.md +2 -4
- package/src/assets/skills/agent-references/references/commands/implement-evidence-asks.md +1 -1
- package/src/assets/skills/agent-references/references/commands/implement-levels.md +4 -7
- package/src/assets/skills/agent-references/references/commands/implement-revalidate.md +1 -1
- package/src/assets/skills/agent-references/references/commands/plan-levels.md +2 -2
- package/src/assets/skills/apply-decisions/SKILL.md +5 -6
- package/src/assets/skills/apply-feature-knowledge/SKILL.md +3 -13
- package/src/assets/skills/architecture/SKILL.md +29 -105
- package/src/assets/skills/boundary-validation/SKILL.md +27 -78
- package/src/assets/skills/complexity/SKILL.md +8 -104
- package/src/assets/skills/compliance/SKILL.md +9 -67
- package/src/assets/skills/consistency/SKILL.md +7 -107
- package/src/assets/skills/database/SKILL.md +7 -72
- package/src/assets/skills/dependencies/SKILL.md +9 -109
- package/src/assets/skills/dependencies/references/detection.md +10 -0
- package/src/assets/skills/dependency-research/SKILL.md +9 -63
- package/src/assets/skills/design-review/SKILL.md +1 -35
- package/src/assets/skills/docs-framework/SKILL.md +4 -47
- package/src/assets/skills/documentation/SKILL.md +7 -71
- package/src/assets/skills/documentation/references/patterns.md +1 -1
- package/src/assets/skills/documentation/references/violations.md +1 -1
- package/src/assets/skills/feature-knowledge/SKILL.md +19 -222
- package/src/assets/skills/feature-knowledge/references/new-kb.md +128 -0
- package/src/assets/skills/gap-analysis/SKILL.md +1 -31
- package/src/assets/skills/git/SKILL.md +2 -22
- package/src/assets/skills/go/SKILL.md +24 -113
- package/src/assets/skills/java/SKILL.md +12 -98
- package/src/assets/skills/patterns/SKILL.md +8 -93
- package/src/assets/skills/performance/SKILL.md +29 -88
- package/src/assets/skills/python/SKILL.md +22 -120
- package/src/assets/skills/qa/SKILL.md +16 -54
- package/src/assets/skills/qa/references/browser-testing.md +0 -24
- package/src/assets/skills/qa/references/sources.md +2 -2
- package/src/assets/skills/quality-gates/SKILL.md +13 -100
- package/src/assets/skills/react/SKILL.md +33 -95
- package/src/assets/skills/regression/SKILL.md +8 -73
- package/src/assets/skills/reliability/SKILL.md +11 -120
- package/src/assets/skills/research-codebase/SKILL.md +7 -49
- package/src/assets/skills/research-competitor/SKILL.md +4 -39
- package/src/assets/skills/research-external/SKILL.md +5 -43
- package/src/assets/skills/research-market/SKILL.md +5 -43
- package/src/assets/skills/research-technology/SKILL.md +8 -68
- package/src/assets/skills/review-methodology/SKILL.md +10 -56
- package/src/assets/skills/rust/SKILL.md +19 -109
- package/src/assets/skills/security/SKILL.md +39 -66
- package/src/assets/skills/software-design/SKILL.md +20 -105
- package/src/assets/skills/software-design/references/patterns.md +84 -2
- package/src/assets/skills/software-design/references/violations.md +1 -1
- package/src/assets/skills/test-driven-development/SKILL.md +32 -107
- package/src/assets/skills/test-driven-development/references/rationalization-prevention.md +33 -1
- package/src/assets/skills/testing/SKILL.md +35 -53
- package/src/assets/skills/typescript/SKILL.md +23 -102
- package/src/assets/skills/ui-design/SKILL.md +26 -74
- package/src/assets/skills/worktree-support/SKILL.md +4 -10
- package/dist/curation-off/commands/dynamic-profile.md +0 -214
|
@@ -37,8 +37,10 @@ import { probeTrackedArea } from '../../core/tracked-areas.js';
|
|
|
37
37
|
import { restampInstalledCommands } from '../../targets/claude-code/language-stamp.js';
|
|
38
38
|
import { installRenderedCharter, removeHandoffSentinel } from '../../targets/claude-code/charter-render.js';
|
|
39
39
|
import { installCommandsAndAgents } from '../../targets/claude-code/installer.js';
|
|
40
|
+
import { BACKUP_ROOT_NAME, escapeName } from '../../targets/claude-code/install-backup.js';
|
|
40
41
|
import { isUnrealFolder, newLinkReport, refuseUnrealFolder, refusedFolderStatement } from '../../targets/claude-code/linked-folder.js';
|
|
41
42
|
import { formatReplacedLinksSummary } from './install-report.js';
|
|
43
|
+
import { judgeBareLegacySkill } from './legacy-sweep.js';
|
|
42
44
|
/**
|
|
43
45
|
* Where a retired repo-local install lives: `<gitRoot>/.claude` and `<gitRoot>/.devflow`.
|
|
44
46
|
*
|
|
@@ -654,6 +656,9 @@ export function userContentPaths(devflowDir) {
|
|
|
654
656
|
{ relPath: 'skills', isDir: true, label: `skill shadows (${path.join(devflowDir, 'skills')})` },
|
|
655
657
|
// Rule shadow overrides (~/.devflow/rules/{name}.md)
|
|
656
658
|
{ relPath: 'rules', isDir: true, label: `rule shadows (${path.join(devflowDir, 'rules')})` },
|
|
659
|
+
// The files an install moved out of the devflow folders because devflow did not ship them.
|
|
660
|
+
// They are the user's own files, so only a confirmed full wipe removes them.
|
|
661
|
+
{ relPath: BACKUP_ROOT_NAME, isDir: true, label: `install backups (${path.join(devflowDir, BACKUP_ROOT_NAME)})` },
|
|
657
662
|
// preference-profile.md — user-curated decision-preference profile
|
|
658
663
|
{ relPath: 'preference-profile.md', label: 'preference-profile.md' },
|
|
659
664
|
// tracker/ — the inferred, hand-editable issue-tracker conventions, one file
|
|
@@ -921,7 +926,7 @@ export function installArtifactPaths(devflowDir) {
|
|
|
921
926
|
* This function runs on the decline, cancel, non-interactive AND --keep-docs paths,
|
|
922
927
|
* so an entry here is deleted even when the user answers "no" to the full wipe.
|
|
923
928
|
* User-authored state (everything in `userContentPaths`: skill/rule shadows,
|
|
924
|
-
* preference-profile.md, the tracker conventions with the legacy tracker.md and
|
|
929
|
+
* the install backups, preference-profile.md, the tracker conventions with the legacy tracker.md and
|
|
925
930
|
* its backups, the global tuning file under both names, hud.json) is removed only by
|
|
926
931
|
* the confirmed full-dir rm.
|
|
927
932
|
* agent-models.json is an INSTALL ARTIFACT (stale per-agent overrides silently
|
|
@@ -1012,6 +1017,35 @@ export async function isDevFlowInstalled(claudeDir) {
|
|
|
1012
1017
|
catch { /* skills dir absent or unreadable */ }
|
|
1013
1018
|
return false;
|
|
1014
1019
|
}
|
|
1020
|
+
/** Why a bare legacy skill folder stays: its `SKILL.md` is a file that no release of devflow installed. */
|
|
1021
|
+
const KEPT_NOT_MADE = 'devflow did not make this folder';
|
|
1022
|
+
/** Why a bare legacy skill folder stays: there is no regular `SKILL.md`, the folder or file is a link, or a read failed. */
|
|
1023
|
+
const KEPT_UNDECIDED = 'devflow could not tell if it made this folder';
|
|
1024
|
+
/**
|
|
1025
|
+
* Sort the bare legacy skill folders that exist in `skillsDir` into those a full uninstall removes
|
|
1026
|
+
* and those it keeps. The skills folder is shared with Claude Code and other tools, so a bare name
|
|
1027
|
+
* (`python`, `plan`) does not prove that devflow made the folder. It is removed only when the check
|
|
1028
|
+
* `devflow init` uses finds a `SKILL.md` that a release installed (`judgeBareLegacySkill`). The dry
|
|
1029
|
+
* run and the removal both take this one list. A `devflow:` name is in the namespace of devflow, and
|
|
1030
|
+
* the prefixed pass removes it. Reads one file per folder at most. Never throws.
|
|
1031
|
+
*/
|
|
1032
|
+
async function planBareLegacySkills(skillsDir) {
|
|
1033
|
+
const remove = [];
|
|
1034
|
+
const keep = [];
|
|
1035
|
+
for (const name of new Set(LEGACY_SKILL_NAMES)) {
|
|
1036
|
+
if (name.startsWith(SKILL_NAMESPACE))
|
|
1037
|
+
continue;
|
|
1038
|
+
const folder = path.join(skillsDir, name);
|
|
1039
|
+
const verdict = await judgeBareLegacySkill(folder, name);
|
|
1040
|
+
if (verdict === 'devflow')
|
|
1041
|
+
remove.push(folder);
|
|
1042
|
+
else if (verdict === 'other')
|
|
1043
|
+
keep.push({ folder, reason: KEPT_NOT_MADE });
|
|
1044
|
+
else if (verdict === 'unknown')
|
|
1045
|
+
keep.push({ folder, reason: KEPT_UNDECIDED });
|
|
1046
|
+
}
|
|
1047
|
+
return { remove, keep };
|
|
1048
|
+
}
|
|
1015
1049
|
// ---------------------------------------------------------------------------
|
|
1016
1050
|
// Phase runners — extracted from the action function for readability and
|
|
1017
1051
|
// independent testability. Each covers one logical stage of the uninstall.
|
|
@@ -1029,9 +1063,10 @@ export async function isDevFlowInstalled(claudeDir) {
|
|
|
1029
1063
|
* and the scripts directory inside devflowDir.
|
|
1030
1064
|
* 2. ALL skill removal candidates (existence-filtered):
|
|
1031
1065
|
* - Prefixed (devflow:name): live registry ∪ LEGACY_SKILL_NAMES.
|
|
1032
|
-
* - Bare (name or devflow-name legacy): LEGACY_SKILL_NAMES ONLY
|
|
1033
|
-
* ~/.claude/skills/ is
|
|
1034
|
-
* are by construction
|
|
1066
|
+
* - Bare (name or devflow-name legacy): LEGACY_SKILL_NAMES ONLY, and only a
|
|
1067
|
+
* folder that devflow made (planBareLegacySkills). ~/.claude/skills/ is
|
|
1068
|
+
* shared; bare dirs for live-registry skill names are by construction
|
|
1069
|
+
* foreign to Devflow. A bare folder that stays is listed as `(kept: <reason>)`.
|
|
1035
1070
|
* 3. manifest.json (removed separately in removeDevFlowInstallArtifacts).
|
|
1036
1071
|
* 4. Every artifact path from installArtifactPaths(devflowDir) — the single
|
|
1037
1072
|
* source of truth shared with the real removal loop.
|
|
@@ -1057,8 +1092,8 @@ export async function enumerateDryRunExtras(claudeDir, devflowDir, folderWorkflo
|
|
|
1057
1092
|
// 2. Skills: enumerate ALL removal candidates that exist on disk.
|
|
1058
1093
|
// Mirrors removeAllDevFlow's split-pass approach:
|
|
1059
1094
|
// Prefixed: live registry ∪ LEGACY_SKILL_NAMES ∪ FEATURE_OWNED_SKILLS
|
|
1060
|
-
// Bare: LEGACY_SKILL_NAMES only
|
|
1061
|
-
// dirs are by construction foreign to Devflow.
|
|
1095
|
+
// Bare: LEGACY_SKILL_NAMES only, and only a folder that devflow made — shared
|
|
1096
|
+
// skills/ dir; live-registry bare dirs are by construction foreign to Devflow.
|
|
1062
1097
|
// FEATURE_OWNED_SKILLS (compliance) is included so full uninstall removes
|
|
1063
1098
|
// devflow:compliance even though it left the plugin registry (step 1.5).
|
|
1064
1099
|
// The workflow skill folders (D-WORKFLOW-FOLDER-INSTALL) join through getAllSkillNames.
|
|
@@ -1072,14 +1107,10 @@ export async function enumerateDryRunExtras(claudeDir, devflowDir, folderWorkflo
|
|
|
1072
1107
|
}
|
|
1073
1108
|
catch { /* absent */ }
|
|
1074
1109
|
}
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
extras.push(barePath);
|
|
1080
|
-
}
|
|
1081
|
-
catch { /* absent */ }
|
|
1082
|
-
}
|
|
1110
|
+
const bareSkills = await planBareLegacySkills(skillsDir);
|
|
1111
|
+
extras.push(...bareSkills.remove);
|
|
1112
|
+
for (const { folder, reason } of bareSkills.keep)
|
|
1113
|
+
extras.push(`${escapeName(folder)} (kept: ${reason})`);
|
|
1083
1114
|
// 3. manifest.json — removed separately by removeDevFlowInstallArtifacts
|
|
1084
1115
|
// (NOT in installArtifactPaths). List it here so the preview is complete.
|
|
1085
1116
|
const manifestPath = path.join(devflowDir, 'manifest.json');
|
|
@@ -1422,9 +1453,11 @@ export async function runSelectivePhaseForScope(opts) {
|
|
|
1422
1453
|
* @param opts.isTTY - Whether the session is interactive. Injected rather than
|
|
1423
1454
|
* read from process.stdin so the prompt gate is an explicit input (matching
|
|
1424
1455
|
* resolveDevflowDirCleanup) instead of an ambient global a test cannot control.
|
|
1456
|
+
* @param opts.confirm - The prompt for the full-dir wipe (default `p.confirm`).
|
|
1425
1457
|
*/
|
|
1426
1458
|
export async function runFullPhaseForScope(opts) {
|
|
1427
1459
|
const { scope, claudeDir, devflowDir, devflowScriptsDir, verbose, keepDocs, isTTY } = opts;
|
|
1460
|
+
const confirm = opts.confirm ?? p.confirm;
|
|
1428
1461
|
// D-CLI-NO-SYMLINK: a legacy local install's removals and rewrites pass this first.
|
|
1429
1462
|
const mayChange = scopeChangeGuard(scope, { claudeDir, devflowDir });
|
|
1430
1463
|
// Revert GPT agent frontmatter before removing agents — ensures no orphaned
|
|
@@ -1482,7 +1515,7 @@ export async function runFullPhaseForScope(opts) {
|
|
|
1482
1515
|
for (const item of userContent) {
|
|
1483
1516
|
p.log.info(` ${item}`);
|
|
1484
1517
|
}
|
|
1485
|
-
const confirmFullCleanup = await
|
|
1518
|
+
const confirmFullCleanup = await confirm({
|
|
1486
1519
|
message: `Remove entire ${devflowDir}? (includes the items listed above, plus logs and install metadata)`,
|
|
1487
1520
|
initialValue: false,
|
|
1488
1521
|
});
|
|
@@ -2005,10 +2038,11 @@ export async function removeAllDevFlow(claudeDir, devflowScriptsDir, verbose, ma
|
|
|
2005
2038
|
// prefixSkillName() is idempotent for already-prefixed legacy entries.
|
|
2006
2039
|
// FEATURE_OWNED_SKILLS (compliance) is included so full uninstall removes
|
|
2007
2040
|
// devflow:compliance even though it left the plugin registry (step 1.5).
|
|
2008
|
-
// Bare pass (name or devflow-name legacy): LEGACY_SKILL_NAMES ONLY
|
|
2009
|
-
//
|
|
2010
|
-
//
|
|
2011
|
-
//
|
|
2041
|
+
// Bare pass (name or devflow-name legacy): LEGACY_SKILL_NAMES ONLY, and only a folder
|
|
2042
|
+
// whose SKILL.md is a copy that a release of devflow installed (planBareLegacySkills).
|
|
2043
|
+
// Any other bare folder stays and is named. A bare dir whose name matches a
|
|
2044
|
+
// live-registry skill is by construction foreign to Devflow (the devflow: namespace
|
|
2045
|
+
// shipped in dcecda3, 2026-03-30). A bare 'compliance/' dir is also foreign (not in LEGACY_SKILL_NAMES).
|
|
2012
2046
|
// The workflow skill folders (D-WORKFLOW-FOLDER-INSTALL) are in getAllSkillNames, so the folder is removed.
|
|
2013
2047
|
const prefixedSkillNames = new Set([...getAllSkillNames(folderWorkflows), ...LEGACY_SKILL_NAMES, ...FEATURE_OWNED_SKILLS]);
|
|
2014
2048
|
const skillsDir = path.join(claudeDir, 'skills');
|
|
@@ -2025,17 +2059,21 @@ export async function removeAllDevFlow(claudeDir, devflowScriptsDir, verbose, ma
|
|
|
2025
2059
|
}
|
|
2026
2060
|
catch { /* Skill doesn't exist */ }
|
|
2027
2061
|
}
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
|
|
2062
|
+
// Bare variant: frozen legacy list only, never the live registry, and only a folder that devflow made.
|
|
2063
|
+
const bareSkills = await planBareLegacySkills(skillsDir);
|
|
2064
|
+
for (const barePath of bareSkills.remove) {
|
|
2031
2065
|
try {
|
|
2032
|
-
await fs.stat(barePath);
|
|
2033
2066
|
if (!(await mayChange(barePath)))
|
|
2034
2067
|
continue;
|
|
2035
2068
|
await fs.rm(barePath, { recursive: true, force: true });
|
|
2036
2069
|
skillsRemoved++;
|
|
2037
2070
|
}
|
|
2038
|
-
catch {
|
|
2071
|
+
catch (error) {
|
|
2072
|
+
p.log.warn(`Could not remove ${escapeName(barePath)}: ${error}`);
|
|
2073
|
+
}
|
|
2074
|
+
}
|
|
2075
|
+
for (const { folder, reason } of bareSkills.keep) {
|
|
2076
|
+
p.log.info(`Kept ${escapeName(folder)}: ${reason}`);
|
|
2039
2077
|
}
|
|
2040
2078
|
if (skillsRemoved > 0 && verbose) {
|
|
2041
2079
|
p.log.success(`Removed ${skillsRemoved} Devflow skill directories`);
|
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
---
|
|
2
|
-
description: Proactive bug finding with static and semantic analysis
|
|
2
|
+
description: Proactive bug finding in changed code before merge, with static and semantic analysis
|
|
3
3
|
---
|
|
4
4
|
# Bug Analysis Command
|
|
5
5
|
|
|
6
|
-
Run a proactive bug analysis on the current branch: static analysis tools and parallel semantic analyzers, synthesized into one bug report.
|
|
7
|
-
|
|
8
6
|
## Usage
|
|
9
7
|
|
|
10
8
|
`/bug-analysis [--full] [--no-static]`: `--full` ignores incremental state; `--no-static` skips static analysis.
|
|
@@ -21,17 +19,19 @@ Run a proactive bug analysis on the current branch: static analysis tools and pa
|
|
|
21
19
|
node "$HOME/.devflow/scripts/resolve-evidence-policy.cjs" 2>/dev/null; echo "exit=$?"
|
|
22
20
|
```
|
|
23
21
|
|
|
24
|
-
Accept the output only when it is exactly two lines: `exit=0` last and, before it, one line of the form `EVIDENCE_POLICY=<required|standard> SOURCE=<file|worktree|default|invalid|error> REF=<branch|none>[ WARN=<remote-unavailable|invalid-file|raised-by-compliance|pr-changes-policy>[,…]] ISSUE_REQUIRED=<true|false> APPLY_CONVENTIONS=<true|false> REQUIRE_NON_AUTHOR_APPROVAL=<true|false>` — these fields, in this order, nothing else, where `<branch>` is a branch name
|
|
22
|
+
Accept the output only when it is exactly two lines: `exit=0` last and, before it, one line of the form `EVIDENCE_POLICY=<required|standard> SOURCE=<file|worktree|default|invalid|error> REF=<branch|none>[ WARN=<remote-unavailable|invalid-file|raised-by-compliance|pr-changes-policy>[,…]] ISSUE_REQUIRED=<true|false> APPLY_CONVENTIONS=<true|false> REQUIRE_NON_AUTHOR_APPROVAL=<true|false>` — these fields, in this order, nothing else, where `<branch>` is a branch name. **Anything else** (including a script that cannot run) ⇒ use `EVIDENCE_POLICY=required SOURCE=error REF=none ISSUE_REQUIRED=true APPLY_CONVENTIONS=true REQUIRE_NON_AUTHOR_APPROVAL=true` instead.
|
|
25
23
|
|
|
26
24
|
Set `EVIDENCE_POLICY`, `ISSUE_REQUIRED`, `APPLY_CONVENTIONS` and `REQUIRE_NON_AUTHOR_APPROVAL` from the accepted line. Pass agents only the three mechanism inputs, never `EVIDENCE_POLICY`. Report `Evidence policy: {EVIDENCE_POLICY} (source: {SOURCE})`, plus any `WARN` tokens as advisory, once in the final report.
|
|
27
25
|
|
|
28
|
-
**Docs root (D-DOCS-ROOT).** Every `.devflow/docs/` path
|
|
26
|
+
**Docs root (D-DOCS-ROOT).** Every `.devflow/docs/` path is `{worktree}/.devflow/docs/…`. A repo-relative docs path handed to an agent travels with a `WORKTREE_PATH` naming its checkout.
|
|
27
|
+
|
|
28
|
+
Once per start directory (`WORKTREE_PATH` if provided, otherwise cwd), run from it:
|
|
29
29
|
|
|
30
30
|
```bash
|
|
31
|
-
|
|
31
|
+
node "$HOME/.devflow/scripts/resolve-root.cjs" "{start}"; echo "exit=$?"
|
|
32
32
|
```
|
|
33
33
|
|
|
34
|
-
|
|
34
|
+
Accept only the three lines `WORKTREE=<absolute path>`, `LEDGER=<absolute path>` and `exit=0`, which set `{worktree}` and `{ledger}`. Otherwise both are the start directory.
|
|
35
35
|
|
|
36
36
|
Render the test-plan block from `/implement`'s evidence file, and from nothing else:
|
|
37
37
|
1. `branch_slug` is `git -C "{worktree}" branch --show-current` with every `/` replaced by `-`.
|
|
@@ -182,42 +182,33 @@ Set `STATIC_STATUS` to one `{tool}: {value}` per tool: `completed`, `not install
|
|
|
182
182
|
|
|
183
183
|
#### Decisions Index
|
|
184
184
|
|
|
185
|
-
**Resolve the settings line** once per worktree root, reusing a line this run already resolved for the same root. `{root}` is the worktree the values are for
|
|
185
|
+
**Resolve the settings line** once per worktree root, reusing a line this run already resolved for the same root. `{root}` is the worktree the values are for:
|
|
186
186
|
|
|
187
187
|
```bash
|
|
188
188
|
node "$HOME/.devflow/scripts/resolve-settings.cjs" "{root}" 2>/dev/null; echo "exit=$?"
|
|
189
189
|
```
|
|
190
190
|
|
|
191
|
-
Accept the output only when it is exactly two lines: `exit=0` last and, before it, one line of the form `TRACKER=<github|jira|linear> TRACKER_SOURCE=<project|personal|machine|default> TRACKER_WARN=<none|mismatch|invalid> SITE=<none|https://<host>> KEY=<none|<key>> REVIEW_PUBLICATION=<off|auto|full> COMPLIANCE=<off|generic|<id>[,<id>…]> MEMORY=<on|off> CURATION=<on|off> KNOWLEDGE=<on|off> GATE_LEVEL=<full|standard|lean>` — these fields, in this order, nothing else, where `<host>` is a lowercase dotted host name alone, `<key>` is 2–10 of `A-Z`, `0-9` and `_` starting with a letter, and each `<id>` is one of `gdpr`, `hipaa`, `pci-dss`, `soc2`, `iso-27001`, `sox`. **Anything else** (
|
|
191
|
+
Accept the output only when it is exactly two lines: `exit=0` last and, before it, one line of the form `TRACKER=<github|jira|linear> TRACKER_SOURCE=<project|personal|machine|default> TRACKER_WARN=<none|mismatch|invalid> SITE=<none|https://<host>> KEY=<none|<key>> REVIEW_PUBLICATION=<off|auto|full> COMPLIANCE=<off|generic|<id>[,<id>…]> MEMORY=<on|off> CURATION=<on|off> KNOWLEDGE=<on|off> GATE_LEVEL=<full|standard|lean>` — these fields, in this order, nothing else, where `<host>` is a lowercase dotted host name alone, `<key>` is 2–10 of `A-Z`, `0-9` and `_` starting with a letter, and each `<id>` is one of `gdpr`, `hipaa`, `pci-dss`, `soc2`, `iso-27001`, `sox`. **Anything else** (including a script that cannot run) ⇒ use `TRACKER=github TRACKER_SOURCE=default TRACKER_WARN=invalid SITE=none KEY=none REVIEW_PUBLICATION=off COMPLIANCE=generic MEMORY=off CURATION=off KNOWLEDGE=off GATE_LEVEL=full` instead.
|
|
192
192
|
|
|
193
193
|
The accepted line is the only source of these values.
|
|
194
194
|
|
|
195
195
|
### Load DECISIONS_CONTEXT
|
|
196
196
|
|
|
197
|
-
When the settings line says `CURATION=off`, set `DECISIONS_CONTEXT` to `(none)` and skip this step,
|
|
197
|
+
When the settings line says `CURATION=off`, set `DECISIONS_CONTEXT` to `(none)` and skip this step, reading no index.
|
|
198
|
+
|
|
199
|
+
The decisions ledger belongs to the repository, not to one checkout: a linked worktree reads the main worktree's copy.
|
|
198
200
|
|
|
199
|
-
|
|
201
|
+
Once per start directory (`WORKTREE_PATH` if provided, otherwise cwd), run from it:
|
|
200
202
|
|
|
201
203
|
```bash
|
|
202
|
-
|
|
204
|
+
node "$HOME/.devflow/scripts/resolve-root.cjs" "{start}"; echo "exit=$?"
|
|
203
205
|
```
|
|
204
206
|
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
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.
|
|
208
|
-
2. **The toplevel** — line 1, or on an older git the line after the echoed flag.
|
|
209
|
-
3. **The start directory itself** — when the command failed or printed no absolute toplevel (outside a git repository).
|
|
210
|
-
|
|
211
|
-
This is the rule the curation hooks apply, so you read the index the Curate agent writes.
|
|
207
|
+
Accept only the three lines `WORKTREE=<absolute path>`, `LEDGER=<absolute path>` and `exit=0`, which set `{worktree}` and `{ledger}`. Otherwise both are the start directory.
|
|
212
208
|
|
|
213
|
-
**Step 1 — Read the pre-rendered index
|
|
209
|
+
**Step 1 — Read the pre-rendered index** `{ledger}/.devflow/curation/index.md`. Its content is `DECISIONS_CONTEXT`; if it is absent or empty, `DECISIONS_CONTEXT` is `(none)`.
|
|
214
210
|
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
- If the file exists and contains non-empty content: use that content as `DECISIONS_CONTEXT`.
|
|
218
|
-
- If the file is absent or empty: set `DECISIONS_CONTEXT` to `(none)`.
|
|
219
|
-
|
|
220
|
-
The index is one direct file read, written at render time by `render-decisions.cjs` — no `.cjs` script runs here.
|
|
211
|
+
The index is one direct file read.
|
|
221
212
|
|
|
222
213
|
**Step 2 — Slice the index, then hand it on:**
|
|
223
214
|
|
|
@@ -225,51 +216,33 @@ When `DECISIONS_CONTEXT` is not `(none)`, hand it only to the agents whose contr
|
|
|
225
216
|
|
|
226
217
|
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.
|
|
227
218
|
|
|
228
|
-
Those agents follow `devflow:apply-decisions`. A host that uses the index in its own thread says so in its own step.
|
|
229
|
-
|
|
230
219
|
#### Feature Knowledge
|
|
231
220
|
|
|
232
221
|
### Load Feature Knowledge
|
|
233
222
|
|
|
234
|
-
|
|
223
|
+
Once per start directory (`WORKTREE_PATH` if provided, otherwise cwd), run from it:
|
|
235
224
|
|
|
236
225
|
```bash
|
|
237
|
-
|
|
226
|
+
node "$HOME/.devflow/scripts/resolve-root.cjs" "{start}"; echo "exit=$?"
|
|
238
227
|
```
|
|
239
228
|
|
|
240
|
-
|
|
229
|
+
Accept only the three lines `WORKTREE=<absolute path>`, `LEDGER=<absolute path>` and `exit=0`, which set `{worktree}` and `{ledger}`. Otherwise both are the start directory.
|
|
241
230
|
|
|
242
|
-
|
|
231
|
+
All paths below are relative to `{worktree}`.
|
|
243
232
|
|
|
244
|
-
|
|
233
|
+
**Step 1 — Read the index cache** `{worktree}/.devflow/features/index.md`. Each line has the form `- **{slug}** — {areas} — {Use-when description}`. If `index.md` is absent or has no entry line, glob `{worktree}/.devflow/features/*/KNOWLEDGE.md` and read only the YAML frontmatter of each file, in one turn.
|
|
245
234
|
|
|
246
|
-
|
|
247
|
-
- **{slug}** — {areas} — {Use-when description}
|
|
248
|
-
```
|
|
235
|
+
**Step 2 — Pick relevant KBs:** select the entries whose documented area overlaps the current task (index line, or frontmatter `description` and `directories` on fallback).
|
|
249
236
|
|
|
250
|
-
|
|
237
|
+
**Step 3 — Read each selected KB's Rules.** `{kb}` is `{worktree}/.devflow/features/{slug}/KNOWLEDGE.md`:
|
|
251
238
|
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
Glob `{worktree}/.devflow/features/*/KNOWLEDGE.md`. For each file found, read only its YAML frontmatter block (between the opening and closing `---` delimiters).
|
|
255
|
-
|
|
256
|
-
**Step 3 — Pick relevant KBs:**
|
|
257
|
-
|
|
258
|
-
Match the current task area and description against each index line (or frontmatter `description` + `directories` on fallback). Select entries whose documented area overlaps the current task. This is a relevance judgment — prefer specificity over breadth.
|
|
259
|
-
|
|
260
|
-
**Step 4 — Read each selected KB's Rules:**
|
|
261
|
-
|
|
262
|
-
For each selected entry, `{kb}` is `{worktree}/.devflow/features/{slug}/KNOWLEDGE.md`:
|
|
263
|
-
|
|
264
|
-
1. List its `##` headings with line numbers through Bash: `command grep -n '^## ' "{kb}"`. This only locates sections; the text of a KB comes from the Read view alone.
|
|
265
|
-
2. Read the `## Rules` range (its line to the next heading) with the Read tool, using `offset` and `limit`, and choose the one to three bullets most relevant to the current task. The choice is yours, made per KB.
|
|
239
|
+
1. List the `##` headings with line numbers of all selected KBs in one Bash call: `command grep -n '^## ' "{kb}" …`. With two or more paths, each line starts with its `{kb}:` path. This only locates sections; the text of a KB comes from the Read view alone.
|
|
240
|
+
2. Read the `## Rules` range (its line to the next heading) with the Read tool, using `offset` and `limit`, all selected KBs in one turn, and choose the one to three bullets most relevant to the task.
|
|
266
241
|
3. If the KB has no `## Rules` section, choose one to three entries from its `## Anti-Patterns` or `## Gotchas` range the same way, and label them by that section's name instead of an ID.
|
|
267
242
|
|
|
268
|
-
When a KB contradicts the code you observe, **trust the code
|
|
269
|
-
|
|
270
|
-
**Step 5 — Set FEATURE_KNOWLEDGE and FEATURE_KNOWLEDGE_RULES:**
|
|
243
|
+
When a KB contradicts the code you observe, **trust the code**.
|
|
271
244
|
|
|
272
|
-
Write one block per selected KB. Paste each bullet verbatim from the Read view, never from a shell view. The path is relative to the checkout root; an agent resolves it under `WORKTREE_PATH` when one is provided.
|
|
245
|
+
**Step 4 — Set FEATURE_KNOWLEDGE and FEATURE_KNOWLEDGE_RULES.** Write one block per selected KB. Paste each bullet verbatim from the Read view, never from a shell view. The path is relative to the checkout root; an agent resolves it under `WORKTREE_PATH` when one is provided.
|
|
273
246
|
|
|
274
247
|
```
|
|
275
248
|
--- Feature knowledge: {slug} ---
|
|
@@ -280,9 +253,7 @@ Rules:
|
|
|
280
253
|
Headings: L5 Rules · L40 Overview · L62 Anti-Patterns · L118 Key Files
|
|
281
254
|
```
|
|
282
255
|
|
|
283
|
-
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.
|
|
284
|
-
|
|
285
|
-
**One git call, then direct reads — no `.cjs` script.**
|
|
256
|
+
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. 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)`.
|
|
286
257
|
|
|
287
258
|
#### Plan Artifact
|
|
288
259
|
|
|
@@ -310,9 +281,7 @@ Pick the focus analyzers from `CHANGED_FILES` (Step 2b; do not re-run `git diff`
|
|
|
310
281
|
**Produces:** ANALYZER_OUTPUTS
|
|
311
282
|
**Requires:** DIFF_RANGE, ANALYSIS_DIR, ACTIVE_FOCUSES, STATIC_FINDINGS, ACCEPTANCE_RULES, PLAN_CONTEXT, DECISIONS_CONTEXT, FEATURE_KNOWLEDGE
|
|
312
283
|
|
|
313
|
-
Spawn
|
|
314
|
-
|
|
315
|
-
For each active focus, spawn:
|
|
284
|
+
Spawn one Debug agent for each active focus, all in a single message (parallel, not background):
|
|
316
285
|
```
|
|
317
286
|
Agent(subagent_type="Debug", run_in_background=false):
|
|
318
287
|
"Analyze focusing on {focus}.
|
|
@@ -391,7 +360,7 @@ Seven phases: Phase 1 to Phase 7.
|
|
|
391
360
|
|------|----------|
|
|
392
361
|
| Rebase invalidates `.last-analysis-head` SHA | `git cat-file -t` check fails → fallback to full diff |
|
|
393
362
|
| Zero changed files in DIFF_RANGE with exit 0 | Stop: "No changes to analyze." |
|
|
394
|
-
| `--full` flag |
|
|
363
|
+
| `--full` flag | Step 2a takes the full-range path |
|
|
395
364
|
| A scanner did not run or did not complete | Name the tool and why in `STATIC_FINDINGS`, not `(none)`; a tool that did not complete keeps the marker |
|
|
396
365
|
|
|
397
366
|
## Resolve Compatibility
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
description:
|
|
2
|
+
description: Branch review by specialized agents for PR readiness
|
|
3
3
|
---
|
|
4
4
|
# Code Review Command
|
|
5
5
|
|
|
@@ -7,12 +7,7 @@ Run a comprehensive code review of the current branch by spawning parallel revie
|
|
|
7
7
|
|
|
8
8
|
## Usage
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
/code-review (review current branch — or all worktrees if multiple found)
|
|
12
|
-
/code-review #42 (review specific PR)
|
|
13
|
-
/code-review --full (force full-branch review, ignore previous review state)
|
|
14
|
-
/code-review --path /path/to/worktree (review a specific worktree only)
|
|
15
|
-
```
|
|
10
|
+
`/code-review` (the current branch, or every reviewable worktree), `/code-review #42` (one PR), `--full` (ignore the previous review state), `--path <worktree>` (one worktree only).
|
|
16
11
|
|
|
17
12
|
## Phases
|
|
18
13
|
|
|
@@ -35,17 +30,17 @@ Run a comprehensive code review of the current branch by spawning parallel revie
|
|
|
35
30
|
|
|
36
31
|
**Produces:** COMPLIANCE_ACTIVE, COMPLIANCE_FRAMEWORKS, GATE_LEVEL
|
|
37
32
|
|
|
38
|
-
**Resolve the settings line** once per worktree root, reusing a line this run already resolved for the same root. `{root}` is the worktree the values are for
|
|
33
|
+
**Resolve the settings line** once per worktree root, reusing a line this run already resolved for the same root. `{root}` is the worktree the values are for:
|
|
39
34
|
|
|
40
35
|
```bash
|
|
41
36
|
node "$HOME/.devflow/scripts/resolve-settings.cjs" "{root}" 2>/dev/null; echo "exit=$?"
|
|
42
37
|
```
|
|
43
38
|
|
|
44
|
-
Accept the output only when it is exactly two lines: `exit=0` last and, before it, one line of the form `TRACKER=<github|jira|linear> TRACKER_SOURCE=<project|personal|machine|default> TRACKER_WARN=<none|mismatch|invalid> SITE=<none|https://<host>> KEY=<none|<key>> REVIEW_PUBLICATION=<off|auto|full> COMPLIANCE=<off|generic|<id>[,<id>…]> MEMORY=<on|off> CURATION=<on|off> KNOWLEDGE=<on|off> GATE_LEVEL=<full|standard|lean>` — these fields, in this order, nothing else, where `<host>` is a lowercase dotted host name alone, `<key>` is 2–10 of `A-Z`, `0-9` and `_` starting with a letter, and each `<id>` is one of `gdpr`, `hipaa`, `pci-dss`, `soc2`, `iso-27001`, `sox`. **Anything else** (
|
|
39
|
+
Accept the output only when it is exactly two lines: `exit=0` last and, before it, one line of the form `TRACKER=<github|jira|linear> TRACKER_SOURCE=<project|personal|machine|default> TRACKER_WARN=<none|mismatch|invalid> SITE=<none|https://<host>> KEY=<none|<key>> REVIEW_PUBLICATION=<off|auto|full> COMPLIANCE=<off|generic|<id>[,<id>…]> MEMORY=<on|off> CURATION=<on|off> KNOWLEDGE=<on|off> GATE_LEVEL=<full|standard|lean>` — these fields, in this order, nothing else, where `<host>` is a lowercase dotted host name alone, `<key>` is 2–10 of `A-Z`, `0-9` and `_` starting with a letter, and each `<id>` is one of `gdpr`, `hipaa`, `pci-dss`, `soc2`, `iso-27001`, `sox`. **Anything else** (including a script that cannot run) ⇒ use `TRACKER=github TRACKER_SOURCE=default TRACKER_WARN=invalid SITE=none KEY=none REVIEW_PUBLICATION=off COMPLIANCE=generic MEMORY=off CURATION=off KNOWLEDGE=off GATE_LEVEL=full` instead.
|
|
45
40
|
|
|
46
41
|
The accepted line is the only source of these values.
|
|
47
42
|
|
|
48
|
-
**Resolve the compliance lens** for each worktree root, from its settings line — the line resolved above for that root, by the settings block when this run has not yet resolved it (
|
|
43
|
+
**Resolve the compliance lens** for each worktree root, from its settings line — the line resolved above for that root, by the settings block when this run has not yet resolved it (no file check decides it).
|
|
49
44
|
|
|
50
45
|
**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.
|
|
51
46
|
|
|
@@ -62,7 +57,7 @@ Keep each worktree's values for every downstream phase.
|
|
|
62
57
|
node "$HOME/.devflow/scripts/resolve-evidence-policy.cjs" 2>/dev/null; echo "exit=$?"
|
|
63
58
|
```
|
|
64
59
|
|
|
65
|
-
Accept the output only when it is exactly two lines: `exit=0` last and, before it, one line of the form `EVIDENCE_POLICY=<required|standard> SOURCE=<file|worktree|default|invalid|error> REF=<branch|none>[ WARN=<remote-unavailable|invalid-file|raised-by-compliance|pr-changes-policy>[,…]] ISSUE_REQUIRED=<true|false> APPLY_CONVENTIONS=<true|false> REQUIRE_NON_AUTHOR_APPROVAL=<true|false>` — these fields, in this order, nothing else, where `<branch>` is a branch name
|
|
60
|
+
Accept the output only when it is exactly two lines: `exit=0` last and, before it, one line of the form `EVIDENCE_POLICY=<required|standard> SOURCE=<file|worktree|default|invalid|error> REF=<branch|none>[ WARN=<remote-unavailable|invalid-file|raised-by-compliance|pr-changes-policy>[,…]] ISSUE_REQUIRED=<true|false> APPLY_CONVENTIONS=<true|false> REQUIRE_NON_AUTHOR_APPROVAL=<true|false>` — these fields, in this order, nothing else, where `<branch>` is a branch name. **Anything else** (including a script that cannot run) ⇒ use `EVIDENCE_POLICY=required SOURCE=error REF=none ISSUE_REQUIRED=true APPLY_CONVENTIONS=true REQUIRE_NON_AUTHOR_APPROVAL=true` instead.
|
|
66
61
|
|
|
67
62
|
Set `EVIDENCE_POLICY`, `ISSUE_REQUIRED`, `APPLY_CONVENTIONS` and `REQUIRE_NON_AUTHOR_APPROVAL` from the accepted line. Pass agents only the three mechanism inputs, never `EVIDENCE_POLICY`. Report `Evidence policy: {EVIDENCE_POLICY} (source: {SOURCE})`, plus any `WARN` tokens as advisory, once in the final report.
|
|
68
63
|
|
|
@@ -178,11 +173,11 @@ MAX_REVIEW_CYCLES = 10
|
|
|
178
173
|
|
|
179
174
|
For each reviewable worktree, call:
|
|
180
175
|
|
|
181
|
-
**Resolve `REVIEW_PUBLICATION` per worktree:** take `REVIEW_PUBLICATION` from that worktree's settings line — the line resolved above for `{root}`, the worktree's root, by the settings block when this run has not yet resolved that root
|
|
176
|
+
**Resolve `REVIEW_PUBLICATION` per worktree:** take `REVIEW_PUBLICATION` from that worktree's settings line — the line resolved above for `{root}`, the worktree's root, by the settings block when this run has not yet resolved that root. The line already caps the personal choice at the team's, so it is `off`, `auto` or `full`, and `off` when the line was unresolvable.
|
|
182
177
|
|
|
183
|
-
**Evidence stub:** only when `EVIDENCE_POLICY` is `required`, a resolved `off` becomes `stub`, so a counts-only record still reaches the PR. `stub` is never a config value
|
|
178
|
+
**Evidence stub:** only when `EVIDENCE_POLICY` is `required`, a resolved `off` becomes `stub`, so a counts-only record still reaches the PR. `stub` is never a config value.
|
|
184
179
|
|
|
185
|
-
Note: `auto`
|
|
180
|
+
Note: `auto` does not fail open: the Git agent probes the repository visibility and treats any error or unrecognised value as PUBLIC (mode STUB). What each value does is decided by the Git agent's publication gate (`references/publication-gate.md` step 2); this partial only resolves the value.
|
|
186
181
|
|
|
187
182
|
### Phase 1: Analyze Changed Files
|
|
188
183
|
|
|
@@ -302,30 +297,21 @@ The core, database, dependencies, documentation and compliance focuses, and ever
|
|
|
302
297
|
|
|
303
298
|
### Load DECISIONS_CONTEXT
|
|
304
299
|
|
|
305
|
-
When the settings line says `CURATION=off`, set `DECISIONS_CONTEXT` to `(none)` and skip this step,
|
|
300
|
+
When the settings line says `CURATION=off`, set `DECISIONS_CONTEXT` to `(none)` and skip this step, reading no index.
|
|
301
|
+
|
|
302
|
+
The decisions ledger belongs to the repository, not to one checkout: a linked worktree reads the main worktree's copy.
|
|
306
303
|
|
|
307
|
-
|
|
304
|
+
Once per start directory (`WORKTREE_PATH` if provided, otherwise cwd), run from it:
|
|
308
305
|
|
|
309
306
|
```bash
|
|
310
|
-
|
|
307
|
+
node "$HOME/.devflow/scripts/resolve-root.cjs" "{start}"; echo "exit=$?"
|
|
311
308
|
```
|
|
312
309
|
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
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.
|
|
316
|
-
2. **The toplevel** — line 1, or on an older git the line after the echoed flag.
|
|
317
|
-
3. **The start directory itself** — when the command failed or printed no absolute toplevel (outside a git repository).
|
|
318
|
-
|
|
319
|
-
This is the rule the curation hooks apply, so you read the index the Curate agent writes.
|
|
310
|
+
Accept only the three lines `WORKTREE=<absolute path>`, `LEDGER=<absolute path>` and `exit=0`, which set `{worktree}` and `{ledger}`. Otherwise both are the start directory.
|
|
320
311
|
|
|
321
|
-
**Step 1 — Read the pre-rendered index
|
|
312
|
+
**Step 1 — Read the pre-rendered index** `{ledger}/.devflow/curation/index.md`. Its content is `DECISIONS_CONTEXT`; if it is absent or empty, `DECISIONS_CONTEXT` is `(none)`.
|
|
322
313
|
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
- If the file exists and contains non-empty content: use that content as `DECISIONS_CONTEXT`.
|
|
326
|
-
- If the file is absent or empty: set `DECISIONS_CONTEXT` to `(none)`.
|
|
327
|
-
|
|
328
|
-
The index is one direct file read, written at render time by `render-decisions.cjs` — no `.cjs` script runs here.
|
|
314
|
+
The index is one direct file read.
|
|
329
315
|
|
|
330
316
|
**Step 2 — Slice the index, then hand it on:**
|
|
331
317
|
|
|
@@ -333,51 +319,33 @@ When `DECISIONS_CONTEXT` is not `(none)`, hand it only to the agents whose contr
|
|
|
333
319
|
|
|
334
320
|
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.
|
|
335
321
|
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
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.
|
|
322
|
+
Pass `DECISIONS_CONTEXT` to all Review agents as one shared slice, cut over the diff's files.
|
|
339
323
|
|
|
340
324
|
### Load Feature Knowledge
|
|
341
325
|
|
|
342
|
-
|
|
326
|
+
Once per start directory (`WORKTREE_PATH` if provided, otherwise cwd), run from it:
|
|
343
327
|
|
|
344
328
|
```bash
|
|
345
|
-
|
|
329
|
+
node "$HOME/.devflow/scripts/resolve-root.cjs" "{start}"; echo "exit=$?"
|
|
346
330
|
```
|
|
347
331
|
|
|
348
|
-
|
|
332
|
+
Accept only the three lines `WORKTREE=<absolute path>`, `LEDGER=<absolute path>` and `exit=0`, which set `{worktree}` and `{ledger}`. Otherwise both are the start directory.
|
|
349
333
|
|
|
350
|
-
|
|
334
|
+
All paths below are relative to `{worktree}`.
|
|
351
335
|
|
|
352
|
-
|
|
336
|
+
**Step 1 — Read the index cache** `{worktree}/.devflow/features/index.md`. Each line has the form `- **{slug}** — {areas} — {Use-when description}`. If `index.md` is absent or has no entry line, glob `{worktree}/.devflow/features/*/KNOWLEDGE.md` and read only the YAML frontmatter of each file, in one turn.
|
|
353
337
|
|
|
354
|
-
|
|
355
|
-
- **{slug}** — {areas} — {Use-when description}
|
|
356
|
-
```
|
|
338
|
+
**Step 2 — Pick relevant KBs:** select the entries whose documented area overlaps the current task (index line, or frontmatter `description` and `directories` on fallback).
|
|
357
339
|
|
|
358
|
-
|
|
340
|
+
**Step 3 — Read each selected KB's Rules.** `{kb}` is `{worktree}/.devflow/features/{slug}/KNOWLEDGE.md`:
|
|
359
341
|
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
Glob `{worktree}/.devflow/features/*/KNOWLEDGE.md`. For each file found, read only its YAML frontmatter block (between the opening and closing `---` delimiters).
|
|
363
|
-
|
|
364
|
-
**Step 3 — Pick relevant KBs:**
|
|
365
|
-
|
|
366
|
-
Match the current task area and description against each index line (or frontmatter `description` + `directories` on fallback). Select entries whose documented area overlaps the current task. This is a relevance judgment — prefer specificity over breadth.
|
|
367
|
-
|
|
368
|
-
**Step 4 — Read each selected KB's Rules:**
|
|
369
|
-
|
|
370
|
-
For each selected entry, `{kb}` is `{worktree}/.devflow/features/{slug}/KNOWLEDGE.md`:
|
|
371
|
-
|
|
372
|
-
1. List its `##` headings with line numbers through Bash: `command grep -n '^## ' "{kb}"`. This only locates sections; the text of a KB comes from the Read view alone.
|
|
373
|
-
2. Read the `## Rules` range (its line to the next heading) with the Read tool, using `offset` and `limit`, and choose the one to three bullets most relevant to the current task. The choice is yours, made per KB.
|
|
342
|
+
1. List the `##` headings with line numbers of all selected KBs in one Bash call: `command grep -n '^## ' "{kb}" …`. With two or more paths, each line starts with its `{kb}:` path. This only locates sections; the text of a KB comes from the Read view alone.
|
|
343
|
+
2. Read the `## Rules` range (its line to the next heading) with the Read tool, using `offset` and `limit`, all selected KBs in one turn, and choose the one to three bullets most relevant to the task.
|
|
374
344
|
3. If the KB has no `## Rules` section, choose one to three entries from its `## Anti-Patterns` or `## Gotchas` range the same way, and label them by that section's name instead of an ID.
|
|
375
345
|
|
|
376
|
-
When a KB contradicts the code you observe, **trust the code
|
|
377
|
-
|
|
378
|
-
**Step 5 — Set FEATURE_KNOWLEDGE and FEATURE_KNOWLEDGE_RULES:**
|
|
346
|
+
When a KB contradicts the code you observe, **trust the code**.
|
|
379
347
|
|
|
380
|
-
Write one block per selected KB. Paste each bullet verbatim from the Read view, never from a shell view. The path is relative to the checkout root; an agent resolves it under `WORKTREE_PATH` when one is provided.
|
|
348
|
+
**Step 4 — Set FEATURE_KNOWLEDGE and FEATURE_KNOWLEDGE_RULES.** Write one block per selected KB. Paste each bullet verbatim from the Read view, never from a shell view. The path is relative to the checkout root; an agent resolves it under `WORKTREE_PATH` when one is provided.
|
|
381
349
|
|
|
382
350
|
```
|
|
383
351
|
--- Feature knowledge: {slug} ---
|
|
@@ -388,9 +356,7 @@ Rules:
|
|
|
388
356
|
Headings: L5 Rules · L40 Overview · L62 Anti-Patterns · L118 Key Files
|
|
389
357
|
```
|
|
390
358
|
|
|
391
|
-
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.
|
|
392
|
-
|
|
393
|
-
**One git call, then direct reads — no `.cjs` script.**
|
|
359
|
+
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. 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)`.
|
|
394
360
|
|
|
395
361
|
Pass `FEATURE_KNOWLEDGE` to all Review agents alongside `DECISIONS_CONTEXT`.
|
|
396
362
|
|
|
@@ -427,13 +393,11 @@ Spawn Review agents **in a single message**, one per focus in REVIEW_FOCUS_LIST
|
|
|
427
393
|
| documentation | conditional | devflow:documentation | diff.patch |
|
|
428
394
|
| compliance | diff-driven | devflow:compliance | diff.patch |
|
|
429
395
|
|
|
430
|
-
Review agent count: `code` runs 8 core +1-12 at `full`, up to 2 fewer at `standard`, 3-4 at lean; a reduced class or a mix runs 2-6.
|
|
431
|
-
|
|
432
396
|
**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:
|
|
433
397
|
|
|
434
398
|
> 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.
|
|
435
399
|
|
|
436
|
-
Each Review agent invocation
|
|
400
|
+
Each Review agent invocation:
|
|
437
401
|
```
|
|
438
402
|
Agent(subagent_type="Review", run_in_background=false):
|
|
439
403
|
"Review focusing on {focus}. Load the pattern skill via the Skill tool: Skill(skill="devflow:{focus}").
|
|
@@ -509,26 +473,13 @@ Per worktree, after successful completion:
|
|
|
509
473
|
|
|
510
474
|
```
|
|
511
475
|
/code-review
|
|
512
|
-
│
|
|
513
476
|
├─ Phase 0: Worktree Discovery & Pre-flight, Steps 0a-0f (Git agent per worktree, parallel)
|
|
514
477
|
│ ├─ Step 0b: Resolve the compliance lens and gate level
|
|
515
|
-
|
|
516
|
-
├─
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
│ │ ├─ Choose the focuses
|
|
521
|
-
│ │ └─ Write diff.patch and diff-{focus}.patch
|
|
522
|
-
│ │
|
|
523
|
-
│ ├─ Phase 2: Reviews (PARALLEL within worktree), one per REVIEW_FOCUS_LIST focus
|
|
524
|
-
│ │ ├─ code: core (diff.patch), language (diff-{focus}.patch), conditional
|
|
525
|
-
│ │ └─ docs-only / tests-only / lockfile-only: the reduced set (diff.patch)
|
|
526
|
-
│ │
|
|
527
|
-
│ ├─ Phase 3: Synthesis → Review Comment (SEQUENTIAL within worktree)
|
|
528
|
-
│ │ ├─ Step 3a: Synthesize agent (mode: review, writes review-summary.md)
|
|
529
|
-
│ │ └─ Step 3b: Git agent (post-review-summary)
|
|
530
|
-
│ │
|
|
531
|
-
│ └─ Phase 4: Write .last-review-head + display results
|
|
478
|
+
└─ Per worktree (SEQUENTIAL):
|
|
479
|
+
├─ Phase 1: Classify the diff, choose the focuses, write diff.patch and diff-{focus}.patch
|
|
480
|
+
├─ Phase 2: Reviews (PARALLEL): code, or docs-only / tests-only / lockfile-only (the reduced set)
|
|
481
|
+
├─ Phase 3: Synthesize agent, then Git agent (post-review-summary)
|
|
482
|
+
└─ Phase 4: Write .last-review-head + display results
|
|
532
483
|
```
|
|
533
484
|
|
|
534
485
|
## Edge Cases
|
|
@@ -536,7 +487,7 @@ Per worktree, after successful completion:
|
|
|
536
487
|
| Case | Handling |
|
|
537
488
|
|------|----------|
|
|
538
489
|
| `--full` in multi-worktree mode | Applies to all worktrees (global modifier). It sets the diff range, never the gate level |
|
|
539
|
-
| Review comment already posted | Git agent
|
|
490
|
+
| Review comment already posted | Git agent skips it (D7) |
|
|
540
491
|
| Docs-only diff | Its Step 1.1 set, narrowed by level |
|
|
541
492
|
| Tests-only diff | Its Step 1.1 set, narrowed by level |
|
|
542
493
|
| Lockfile-only diff | Its Step 1.1 set, narrowed by level |
|
|
@@ -557,4 +508,4 @@ Per worktree, after successful completion:
|
|
|
557
508
|
2. **Parallel, not background** - Multiple agents in one message, but `run_in_background=false` so phases complete before proceeding
|
|
558
509
|
3. **Git agent for git work** - All git operations go through Git agent, except the exceptions named in Principle 1; its writes print nothing
|
|
559
510
|
4. **Honest reporting** - Display agent outputs directly
|
|
560
|
-
5. **
|
|
511
|
+
5. **Fewest turns** - Send calls that need no output of each other in one message: the Step 0a listing with the Step 0b-ii script; at `standard` or `lean`, the Step 1.2b directory print with the Step 1.1 listing, and its Read with the `paths.txt` Read; the Phase 1b git calls, each under its own condition, with the Step 1.3 writes
|