@sabaiway/agent-workflow-kit 14.32.0 → 14.34.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 +81 -0
- package/README.md +3 -3
- package/SKILL.md +1 -1
- package/capability.json +1 -1
- package/migrations/1.2.0-agent-attribution.md +10 -8
- package/migrations/3.0.0-hardened-core-loop.md +9 -13
- package/package.json +1 -1
- package/references/contracts.md +2 -2
- package/references/modes/bootstrap.md +5 -3
- package/references/modes/recommendations.md +7 -5
- package/references/modes/upgrade.md +5 -5
- package/references/modes/velocity.md +7 -5
- package/references/modes/worktrees.md +10 -9
- package/references/shared/composition-handoff.md +3 -3
- package/references/shared/deploy-tail.md +2 -2
- package/references/templates/vehicles.json +1 -1
- package/tools/apply-danger-check.mjs +57 -15
- package/tools/attribution.mjs +133 -0
- package/tools/cheap-agents-read.mjs +12 -0
- package/tools/commit-guard.mjs +3 -16
- package/tools/ensure-configs.mjs +6 -6
- package/tools/ensure-executor.mjs +13 -30
- package/tools/ensure-vocabulary.mjs +4 -4
- package/tools/git-hooks.mjs +41 -3
- package/tools/hide-footprint.mjs +87 -61
- package/tools/init-project.mjs +31 -6
- package/tools/recommendations.mjs +112 -65
- package/tools/upgrade-runlist.mjs +1 -1
- package/tools/velocity-profile.mjs +118 -10
- package/tools/worktrees.mjs +28 -10
- package/tools/write-lanes.mjs +23 -2
package/tools/worktrees.mjs
CHANGED
|
@@ -23,11 +23,12 @@ import {
|
|
|
23
23
|
patternToProbe,
|
|
24
24
|
} from './known-footprint.mjs';
|
|
25
25
|
import { isDirectRun } from './direct-run.mjs';
|
|
26
|
-
import { isScratchPlanName, plansInFlight, PLANS_REL
|
|
26
|
+
import { isScratchPlanName, plansInFlight, PLANS_REL } from './plan-files.mjs';
|
|
27
|
+
import { shellQuoteArg } from './repo-lex.mjs';
|
|
27
28
|
import { writeContainedFileAtomic } from './atomic-write.mjs';
|
|
28
29
|
import { assertContainedRealPath } from './fs-safe.mjs';
|
|
29
30
|
import { GIT_MAX_BUFFER } from './git-env.mjs';
|
|
30
|
-
import { isFinalCapableDeclaration } from './
|
|
31
|
+
import { isFinalCapableDeclaration } from './gates-declaration.mjs';
|
|
31
32
|
import {
|
|
32
33
|
WORKTREES_STOP, stop, EXIT, handoffBasename, recordValue, hasControlByte, displayValue,
|
|
33
34
|
composeProvisionRecordSection, composeLandingValue, composeHandoffStub,
|
|
@@ -38,6 +39,8 @@ import {
|
|
|
38
39
|
readSatelliteIdentity,
|
|
39
40
|
} from './satellite-locator.mjs';
|
|
40
41
|
import { composeSatellitePrompt, resolveSeededPlan } from './worktree-prompt.mjs';
|
|
42
|
+
import { applySlot } from './write-lanes.mjs';
|
|
43
|
+
import { dirCovers } from './declared-paths.mjs';
|
|
41
44
|
|
|
42
45
|
// The record format and the satellite locator now live in leaves the dispatch side reads too — but
|
|
43
46
|
// every name they took away is re-exported here, so no import site and no asserted error `code`
|
|
@@ -577,11 +580,25 @@ export const nearestExistingDir = (path, deps = {}) => {
|
|
|
577
580
|
return walk(resolve(path));
|
|
578
581
|
};
|
|
579
582
|
|
|
580
|
-
// The
|
|
581
|
-
//
|
|
583
|
+
// The provision preflight's probe-dir derivation: resolve through the existing-parent realpath, then
|
|
584
|
+
// walk to the nearest existing dir (the advisor walks worktreesGrantDir's answer the same way).
|
|
582
585
|
export const resolveProbeDir = (path, deps = {}) =>
|
|
583
586
|
nearestExistingDir(realpathThroughExistingParent(path, deps), deps);
|
|
584
587
|
|
|
588
|
+
// The worktrees write grant names the parent ITSELF (spec bridges/velocity-profile, part worktrees-grant):
|
|
589
|
+
// the writer, the advisor and the danger check read this one derivation, never resolveProbeDir's ancestor.
|
|
590
|
+
export const worktreesGrantDir = (root, deps = {}) => {
|
|
591
|
+
const realRoot = realpathThroughExistingParent(root, deps);
|
|
592
|
+
const { parentDir } = loadWorktreesConfig(realRoot, deps);
|
|
593
|
+
const dir = realpathThroughExistingParent(parentDir == null ? dirname(realRoot) : resolve(realRoot, parentDir), deps);
|
|
594
|
+
const st = lstatNoFollow(fsOf(deps).lstat, dir);
|
|
595
|
+
if (st !== null && !st.isDirectory()) throw stop(`${CONFIG_REL}: parentDir names an existing non-directory: ${dir}`);
|
|
596
|
+
return dir;
|
|
597
|
+
};
|
|
598
|
+
|
|
599
|
+
export const worktreesGrantHoldsHome = (dir, home, deps = {}) =>
|
|
600
|
+
dirCovers(dir, resolve(home)) || dirCovers(dir, realpathThroughExistingParent(resolve(home), deps));
|
|
601
|
+
|
|
585
602
|
export const probeParentWritable = (parentDir, deps = {}) => {
|
|
586
603
|
const { mkdirPlain, rmdir, rand } = fsOf(deps);
|
|
587
604
|
const probe = join(parentDir, `.aw-write-probe-${rand()}`);
|
|
@@ -620,10 +637,13 @@ const quoteOwnTool = () => `'${WORKTREES_TOOL_ABS.replace(/'/g, `'\\''`)}'`;
|
|
|
620
637
|
const composeOwnToolPrefix = (root) =>
|
|
621
638
|
`cd ${shellQuoteArg(root)} && node ${quoteOwnTool()}`;
|
|
622
639
|
|
|
640
|
+
const composeGrantRoute = (root) => `the kit's worktrees-dir item grants the configured worktrees parent on your yes: the agent runs ${
|
|
641
|
+
applySlot('worktrees-dir', { toolsDir: dirname(WORKTREES_TOOL_ABS), root }).check
|
|
642
|
+
} and, on your yes on its result, its apply line by the consent route, then runs this command again; when that check refuses, prints nothing to change, or grants a dir that does not hold this command's target, use the terminal fallback below`;
|
|
643
|
+
|
|
623
644
|
const landWritabilityStop = ({ parentDir, root, slug }) => stop([
|
|
624
645
|
`the worktrees parent dir is not writable from this session: ${parentDir}`,
|
|
625
|
-
|
|
626
|
-
` .claude/settings.json → sandbox.filesystem.allowWrite += ${JSON.stringify(parentDir)}`,
|
|
646
|
+
composeGrantRoute(root),
|
|
627
647
|
'Or run the full command yourself in a plain terminal:',
|
|
628
648
|
` ${composeOwnToolPrefix(root)} land ${shellQuoteArg(slug)} --prepare`,
|
|
629
649
|
].join('\n'));
|
|
@@ -638,8 +658,7 @@ const writabilityStop = ({ parentDir, root, slug, flags }) => {
|
|
|
638
658
|
return stop(
|
|
639
659
|
[
|
|
640
660
|
`the worktrees parent dir is not writable from this session: ${parentDir}`,
|
|
641
|
-
|
|
642
|
-
` .claude/settings.json → sandbox.filesystem.allowWrite += ${JSON.stringify(parentDir)}`,
|
|
661
|
+
composeGrantRoute(root),
|
|
643
662
|
'Or run the full command yourself in a plain terminal:',
|
|
644
663
|
` ${composeProvisionArgv({ root, slug, flags })}`,
|
|
645
664
|
`(from the target repo root, when that checkout carries the kit at agent-workflow-kit/: node agent-workflow-kit/tools/worktrees.mjs provision ${q(slug)} ${provisionFlagsTail(flags, q).join(' ')})`,
|
|
@@ -3150,8 +3169,7 @@ const destructiveRecovery = ({ slug, branch }) =>
|
|
|
3150
3169
|
|
|
3151
3170
|
const cleanupWritabilityStop = ({ parentDir, root, slug, branch, abandon }) => stop([
|
|
3152
3171
|
`the worktrees parent dir is not writable from this session: ${parentDir}`,
|
|
3153
|
-
|
|
3154
|
-
` .claude/settings.json → sandbox.filesystem.allowWrite += ${JSON.stringify(parentDir)}`,
|
|
3172
|
+
composeGrantRoute(root),
|
|
3155
3173
|
'Or run the full command yourself in a plain terminal:',
|
|
3156
3174
|
` ${composeOwnToolPrefix(root)} ${composeCleanupCommand({ slug, branch, abandon })}`,
|
|
3157
3175
|
].join('\n'));
|
package/tools/write-lanes.mjs
CHANGED
|
@@ -38,11 +38,15 @@ export const VARIANT_LANES = Object.freeze({
|
|
|
38
38
|
'mcp-channel.differing': LANE_HARNESS,
|
|
39
39
|
agents: LANE_HARNESS,
|
|
40
40
|
'executor-vehicle': LANE_HARNESS,
|
|
41
|
+
'executor-vehicle.differing': LANE_HARNESS,
|
|
42
|
+
attribution: LANE_HARNESS,
|
|
43
|
+
'footprint-global': LANE_HARNESS,
|
|
41
44
|
'family-freshness': LANE_USER,
|
|
42
45
|
'adr-store-migration': LANE_CHAT,
|
|
43
46
|
'sandbox-masks': LANE_CHAT,
|
|
44
47
|
'sandbox-masks.unfenced-mount': LANE_CHAT,
|
|
45
|
-
'worktrees-dir':
|
|
48
|
+
'worktrees-dir': LANE_HARNESS,
|
|
49
|
+
'worktrees-dir.home': LANE_USER,
|
|
46
50
|
'spec-adoption': LANE_CHAT,
|
|
47
51
|
'profile-gap': LANE_CHAT,
|
|
48
52
|
'jev-connect': LANE_USER,
|
|
@@ -80,6 +84,7 @@ export const isProtectedPath = (abs, { root, home, hooksDir }) => {
|
|
|
80
84
|
};
|
|
81
85
|
|
|
82
86
|
const SETTINGS_WRITES = [SETTINGS_PATH];
|
|
87
|
+
const LOCAL_SETTINGS_WRITES = [join('.claude', 'settings.local.json')];
|
|
83
88
|
const HOOK_WRITES = [join('.claude', 'hooks', 'agent-workflow-gates.mjs'), ...SETTINGS_WRITES];
|
|
84
89
|
const STOP_HOOK_WRITES = [join('.claude', 'hooks', 'state-block-guard.mjs'), ...SETTINGS_WRITES];
|
|
85
90
|
const MCP_WRITES = ['.mcp.json', ...SETTINGS_WRITES];
|
|
@@ -105,13 +110,15 @@ const getGuardPaths = (facts) => [preCommitOf(facts), join(facts.root, INSTALLER
|
|
|
105
110
|
const formatCommand = (argv) => argv.map(quoteArg).join(' ');
|
|
106
111
|
const TERMINAL_STEP = 'run in a terminal of your own: ';
|
|
107
112
|
|
|
108
|
-
|
|
113
|
+
// rejudged: the written value derives from state init's record does not watch, so init re-runs its check before the apply.
|
|
114
|
+
const createForm = (file, preview, apply, writes, envDependent = false, userStep = null, rejudged = false) => Object.freeze({
|
|
109
115
|
file,
|
|
110
116
|
preview,
|
|
111
117
|
apply,
|
|
112
118
|
writes,
|
|
113
119
|
envDependent,
|
|
114
120
|
userStep,
|
|
121
|
+
rejudged,
|
|
115
122
|
});
|
|
116
123
|
|
|
117
124
|
const CORE_FORM = createForm('velocity-profile.mjs', ['--cwd', '<root>'], ['--apply', '--cwd', '<root>'], SETTINGS_WRITES);
|
|
@@ -138,6 +145,10 @@ const FORMS = Object.freeze({
|
|
|
138
145
|
['--replace', '--cwd', '<root>'], ['--replace', '--apply', '--cwd', '<root>'], MCP_WRITES),
|
|
139
146
|
agents: AGENT_FORM,
|
|
140
147
|
'executor-vehicle': AGENT_FORM,
|
|
148
|
+
'executor-vehicle.differing': AGENT_FORM,
|
|
149
|
+
attribution: createForm('attribution.mjs', ['--cwd', '<root>'], ['--apply', '--cwd', '<root>'], SETTINGS_WRITES),
|
|
150
|
+
'footprint-global': createForm('hide-footprint.mjs',
|
|
151
|
+
['--remove-global', '--dry-run', '--dir', '<root>'], ['--remove-global', '--dir', '<root>'], [], false, null, true),
|
|
141
152
|
'sandbox-provision.installable': createForm('autonomy-doctor.mjs', [], ['--apply', '<tuple>'], [], true,
|
|
142
153
|
(facts, argv) => 'your own step (a sudo install; the doctor prints the --apply line to run next) — '
|
|
143
154
|
+ `${TERMINAL_STEP}cd ${quoteArg(facts.root)} && ${formatCommand(argv.preview)}`),
|
|
@@ -157,6 +168,11 @@ const FORMS = Object.freeze({
|
|
|
157
168
|
['--enforcement', '--cwd', '<root>'], ['--apply', '--enforcement', '--cwd', '<root>'], getEnforcementPaths),
|
|
158
169
|
'commit-guard': createForm('git-hooks.mjs',
|
|
159
170
|
['--commit-guard', '--cwd', '<root>'], ['--apply', '--commit-guard', '--cwd', '<root>'], getGuardPaths),
|
|
171
|
+
'worktrees-dir': createForm('velocity-profile.mjs',
|
|
172
|
+
['--worktrees', '--cwd', '<root>'], ['--apply', '--worktrees', '--cwd', '<root>'], LOCAL_SETTINGS_WRITES, false, null, true),
|
|
173
|
+
'worktrees-dir.home': Object.freeze({
|
|
174
|
+
userStep: () => 'your own step — point docs/ai/worktrees.json parentDir at a dedicated directory, then run /agent-workflow-kit recommendations',
|
|
175
|
+
}),
|
|
160
176
|
});
|
|
161
177
|
|
|
162
178
|
const resolveArgument = (arg, facts) => {
|
|
@@ -190,6 +206,11 @@ export const isEnvDependent = (variant) => {
|
|
|
190
206
|
return FORMS[variant]?.envDependent === true;
|
|
191
207
|
};
|
|
192
208
|
|
|
209
|
+
export const isRejudged = (variant) => {
|
|
210
|
+
laneOf(variant);
|
|
211
|
+
return FORMS[variant]?.rejudged === true;
|
|
212
|
+
};
|
|
213
|
+
|
|
193
214
|
export const applySlot = (variant, facts) => {
|
|
194
215
|
const lane = laneOf(variant);
|
|
195
216
|
const form = FORMS[variant];
|