agentopology 0.9.1 → 0.10.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/README.md +17 -19
- package/dist/__tests__/e2e/action-guard.test.d.ts +13 -0
- package/dist/__tests__/e2e/action-guard.test.d.ts.map +1 -0
- package/dist/__tests__/e2e/action-guard.test.js +299 -0
- package/dist/__tests__/e2e/action-guard.test.js.map +1 -0
- package/dist/__tests__/e2e/compile.test.js +1 -1
- package/dist/__tests__/e2e/compile.test.js.map +1 -1
- package/dist/__tests__/e2e/conformance.test.d.ts +13 -0
- package/dist/__tests__/e2e/conformance.test.d.ts.map +1 -0
- package/dist/__tests__/e2e/conformance.test.js +109 -0
- package/dist/__tests__/e2e/conformance.test.js.map +1 -0
- package/dist/__tests__/e2e/contract-drift.test.d.ts +11 -0
- package/dist/__tests__/e2e/contract-drift.test.d.ts.map +1 -0
- package/dist/__tests__/e2e/contract-drift.test.js +142 -0
- package/dist/__tests__/e2e/contract-drift.test.js.map +1 -0
- package/dist/__tests__/e2e/fail-closed.test.d.ts +11 -0
- package/dist/__tests__/e2e/fail-closed.test.d.ts.map +1 -0
- package/dist/__tests__/e2e/fail-closed.test.js +111 -0
- package/dist/__tests__/e2e/fail-closed.test.js.map +1 -0
- package/dist/__tests__/e2e/guard-check.test.d.ts +9 -0
- package/dist/__tests__/e2e/guard-check.test.d.ts.map +1 -0
- package/dist/__tests__/e2e/guard-check.test.js +316 -0
- package/dist/__tests__/e2e/guard-check.test.js.map +1 -0
- package/dist/__tests__/e2e/guard-target.test.d.ts +11 -0
- package/dist/__tests__/e2e/guard-target.test.d.ts.map +1 -0
- package/dist/__tests__/e2e/guard-target.test.js +198 -0
- package/dist/__tests__/e2e/guard-target.test.js.map +1 -0
- package/dist/__tests__/e2e/inventory.test.d.ts +18 -0
- package/dist/__tests__/e2e/inventory.test.d.ts.map +1 -0
- package/dist/__tests__/e2e/inventory.test.js +187 -0
- package/dist/__tests__/e2e/inventory.test.js.map +1 -0
- package/dist/__tests__/e2e/matcher.test.d.ts +14 -0
- package/dist/__tests__/e2e/matcher.test.d.ts.map +1 -0
- package/dist/__tests__/e2e/matcher.test.js +145 -0
- package/dist/__tests__/e2e/matcher.test.js.map +1 -0
- package/dist/__tests__/e2e/step-check.test.d.ts +9 -0
- package/dist/__tests__/e2e/step-check.test.d.ts.map +1 -0
- package/dist/__tests__/e2e/step-check.test.js +158 -0
- package/dist/__tests__/e2e/step-check.test.js.map +1 -0
- package/dist/__tests__/e2e/strength.test.d.ts +17 -0
- package/dist/__tests__/e2e/strength.test.d.ts.map +1 -0
- package/dist/__tests__/e2e/strength.test.js +130 -0
- package/dist/__tests__/e2e/strength.test.js.map +1 -0
- package/dist/__tests__/e2e/verified-on.test.d.ts +2 -0
- package/dist/__tests__/e2e/verified-on.test.d.ts.map +1 -0
- package/dist/__tests__/e2e/verified-on.test.js +57 -0
- package/dist/__tests__/e2e/verified-on.test.js.map +1 -0
- package/dist/__tests__/open-findings.test.js +1 -0
- package/dist/__tests__/open-findings.test.js.map +1 -1
- package/dist/bindings/__tests__/bindings.test.js +6 -686
- package/dist/bindings/__tests__/bindings.test.js.map +1 -1
- package/dist/bindings/__tests__/defaults-agreement.test.js +0 -12
- package/dist/bindings/__tests__/defaults-agreement.test.js.map +1 -1
- package/dist/bindings/__tests__/hook-command.test.js +2 -2
- package/dist/bindings/__tests__/hook-command.test.js.map +1 -1
- package/dist/bindings/__tests__/mod-plugin.test.js +2 -2
- package/dist/bindings/__tests__/mod-plugin.test.js.map +1 -1
- package/dist/bindings/claude-code.d.ts +45 -1
- package/dist/bindings/claude-code.d.ts.map +1 -1
- package/dist/bindings/claude-code.js +191 -19
- package/dist/bindings/claude-code.js.map +1 -1
- package/dist/bindings/index.d.ts +5 -5
- package/dist/bindings/index.d.ts.map +1 -1
- package/dist/bindings/index.js +9 -16
- package/dist/bindings/index.js.map +1 -1
- package/dist/bindings/lib/stub.d.ts +15 -1
- package/dist/bindings/lib/stub.d.ts.map +1 -1
- package/dist/bindings/lib/stub.js +27 -2
- package/dist/bindings/lib/stub.js.map +1 -1
- package/dist/bindings/types.d.ts +6 -1
- package/dist/bindings/types.d.ts.map +1 -1
- package/dist/cli/__tests__/cli.test.js +25 -0
- package/dist/cli/__tests__/cli.test.js.map +1 -1
- package/dist/cli/index.js +222 -8
- package/dist/cli/index.js.map +1 -1
- package/dist/conformance/claude-code.d.ts +99 -0
- package/dist/conformance/claude-code.d.ts.map +1 -0
- package/dist/conformance/claude-code.js +242 -0
- package/dist/conformance/claude-code.js.map +1 -0
- package/dist/conformance/extract.d.ts +70 -0
- package/dist/conformance/extract.d.ts.map +1 -0
- package/dist/conformance/extract.js +185 -0
- package/dist/conformance/extract.js.map +1 -0
- package/dist/docs/content.d.ts.map +1 -1
- package/dist/docs/content.js +57 -32
- package/dist/docs/content.js.map +1 -1
- package/dist/guard/check.d.ts +53 -0
- package/dist/guard/check.d.ts.map +1 -0
- package/dist/guard/check.js +366 -0
- package/dist/guard/check.js.map +1 -0
- package/dist/guard/target.d.ts +45 -0
- package/dist/guard/target.d.ts.map +1 -0
- package/dist/guard/target.js +168 -0
- package/dist/guard/target.js.map +1 -0
- package/dist/import/__tests__/import.test.js +0 -554
- package/dist/import/__tests__/import.test.js.map +1 -1
- package/dist/import/index.d.ts +0 -1
- package/dist/import/index.d.ts.map +1 -1
- package/dist/import/index.js +1 -7
- package/dist/import/index.js.map +1 -1
- package/dist/import/serializer.d.ts.map +1 -1
- package/dist/import/serializer.js +41 -0
- package/dist/import/serializer.js.map +1 -1
- package/dist/index.d.ts +0 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +0 -4
- package/dist/index.js.map +1 -1
- package/dist/inventory/index.d.ts +65 -0
- package/dist/inventory/index.d.ts.map +1 -0
- package/dist/inventory/index.js +272 -0
- package/dist/inventory/index.js.map +1 -0
- package/dist/parser/ast.d.ts +46 -0
- package/dist/parser/ast.d.ts.map +1 -1
- package/dist/parser/ast.js.map +1 -1
- package/dist/parser/index.d.ts +6 -1
- package/dist/parser/index.d.ts.map +1 -1
- package/dist/parser/index.js +66 -4
- package/dist/parser/index.js.map +1 -1
- package/dist/parser/known-fields.d.ts +3 -0
- package/dist/parser/known-fields.d.ts.map +1 -1
- package/dist/parser/known-fields.js +5 -3
- package/dist/parser/known-fields.js.map +1 -1
- package/dist/parser/ledger.d.ts +36 -0
- package/dist/parser/ledger.d.ts.map +1 -0
- package/dist/parser/ledger.js +72 -0
- package/dist/parser/ledger.js.map +1 -0
- package/dist/parser/run.d.ts +6 -0
- package/dist/parser/run.d.ts.map +1 -1
- package/dist/parser/run.js +10 -0
- package/dist/parser/run.js.map +1 -1
- package/dist/parser/validator.d.ts.map +1 -1
- package/dist/parser/validator.js +255 -1
- package/dist/parser/validator.js.map +1 -1
- package/dist/scaffold/manifest.d.ts.map +1 -1
- package/dist/scaffold/manifest.js +0 -8
- package/dist/scaffold/manifest.js.map +1 -1
- package/dist/scaffold/merge.d.ts.map +1 -1
- package/dist/scaffold/merge.js +1 -3
- package/dist/scaffold/merge.js.map +1 -1
- package/dist/step/check.d.ts +56 -0
- package/dist/step/check.d.ts.map +1 -0
- package/dist/step/check.js +125 -0
- package/dist/step/check.js.map +1 -0
- package/dist/sync/index.d.ts +0 -2
- package/dist/sync/index.d.ts.map +1 -1
- package/dist/sync/index.js +0 -109
- package/dist/sync/index.js.map +1 -1
- package/package.json +3 -1
- package/spec/claude-code/README.md +19 -0
- package/spec/claude-code/hooks-contract.2.1.295.json +143 -0
- package/spec/claude-code/hooks-contract.json +142 -0
- package/spec/grammar.md +45 -7
- package/spec/testing.md +16 -0
- package/spec/validation.md +11 -2
- package/dist/__tests__/live/zz-debug.test.d.ts +0 -2
- package/dist/__tests__/live/zz-debug.test.d.ts.map +0 -1
- package/dist/__tests__/live/zz-debug.test.js +0 -4
- package/dist/__tests__/live/zz-debug.test.js.map +0 -1
- package/dist/bindings/copilot-cli.d.ts +0 -20
- package/dist/bindings/copilot-cli.d.ts.map +0 -1
- package/dist/bindings/copilot-cli.js +0 -1516
- package/dist/bindings/copilot-cli.js.map +0 -1
- package/dist/bindings/gemini-cli.d.ts +0 -18
- package/dist/bindings/gemini-cli.d.ts.map +0 -1
- package/dist/bindings/gemini-cli.js +0 -1318
- package/dist/bindings/gemini-cli.js.map +0 -1
- package/dist/bindings/kiro.d.ts +0 -17
- package/dist/bindings/kiro.d.ts.map +0 -1
- package/dist/bindings/kiro.js +0 -1615
- package/dist/bindings/kiro.js.map +0 -1
- package/dist/bindings/openclaw.d.ts +0 -18
- package/dist/bindings/openclaw.d.ts.map +0 -1
- package/dist/bindings/openclaw.js +0 -1947
- package/dist/bindings/openclaw.js.map +0 -1
- package/dist/import/openclaw.d.ts +0 -70
- package/dist/import/openclaw.d.ts.map +0 -1
- package/dist/import/openclaw.js +0 -1060
- package/dist/import/openclaw.js.map +0 -1
|
@@ -0,0 +1,366 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `agentopology guard <file> --check`: what a project enforces today, read
|
|
3
|
+
* from disk. It writes nothing.
|
|
4
|
+
*
|
|
5
|
+
* For each gate, approval step and permission rule the topology declares, it
|
|
6
|
+
* works out what the claude-code binding compiles it to, then looks in the
|
|
7
|
+
* project for that piece: the settings.json hook entry, the scripts it runs,
|
|
8
|
+
* the permission rule. Each item gets a strength:
|
|
9
|
+
*
|
|
10
|
+
* - `refuse`: a hook or a settings rule stops the step, and it is on disk.
|
|
11
|
+
* - `none`: the binding compiles it to a hook or rule, but the project is
|
|
12
|
+
* missing it (or names it by a relative path, which is skipped once Claude
|
|
13
|
+
* changes directory). Nothing stops the step.
|
|
14
|
+
* - `hope`: the binding has no hook for it (an advisory gate, inline
|
|
15
|
+
* delegation, or a gate with no agent on either side); only the playbook's
|
|
16
|
+
* prose asks for it.
|
|
17
|
+
*
|
|
18
|
+
* @module
|
|
19
|
+
*/
|
|
20
|
+
import * as fs from "node:fs";
|
|
21
|
+
import { join } from "node:path";
|
|
22
|
+
import { gateAnchors } from "../parser/ast.js";
|
|
23
|
+
import { runParts, isProjectPath, scriptNameFromRun } from "../parser/run.js";
|
|
24
|
+
import { approvalTargets, checkableActionGate, claudeEvent, convertMcpToolName, gateWiring, settingsHooksOf } from "../bindings/claude-code.js";
|
|
25
|
+
import { isStubContent } from "../bindings/lib/stub.js";
|
|
26
|
+
import { unanchoredScript, VERIFIED_ON } from "../conformance/claude-code.js";
|
|
27
|
+
function readJson(path) {
|
|
28
|
+
try {
|
|
29
|
+
return JSON.parse(fs.readFileSync(path, "utf8"));
|
|
30
|
+
}
|
|
31
|
+
catch {
|
|
32
|
+
return null;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
function readText(path) {
|
|
36
|
+
try {
|
|
37
|
+
return fs.readFileSync(path, "utf8");
|
|
38
|
+
}
|
|
39
|
+
catch {
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
/** The command hooks on disk for an event whose command names `file`, under a matcher test. */
|
|
44
|
+
function findHooks(settings, event, file, matcher) {
|
|
45
|
+
const entries = (settings?.hooks?.[event] ?? []);
|
|
46
|
+
return entries.filter((e) => matcher(e.matcher)).flatMap((e) => (e.hooks ?? []).filter((h) => h.type === "command" && h.command?.includes(file)));
|
|
47
|
+
}
|
|
48
|
+
/** Notes on the check script a gate's `run:` names: unwritten or missing scripts block every run. */
|
|
49
|
+
function checkScriptNotes(root, scriptsDir, run) {
|
|
50
|
+
const { script } = runParts(run);
|
|
51
|
+
const path = script.startsWith("/") ? script : isProjectPath(script) ? join(root, script.replace(/^\.\//, "")) : join(root, scriptsDir, script.replace(/^.*\//, ""));
|
|
52
|
+
const text = readText(path);
|
|
53
|
+
const shown = path.startsWith(root) ? path.slice(root.length + 1) : path;
|
|
54
|
+
if (text === null)
|
|
55
|
+
return [`its check script ${shown} is missing, so it blocks every run`];
|
|
56
|
+
if (isStubContent(text))
|
|
57
|
+
return [`its check script ${shown} is still a stub, so it blocks every run until it is written`];
|
|
58
|
+
return [];
|
|
59
|
+
}
|
|
60
|
+
/** How many lines either side of a cited line the match text may sit. */
|
|
61
|
+
const MATCH_WINDOW = 5;
|
|
62
|
+
/**
|
|
63
|
+
* Check an `at: "path[:line]"` citation on disk: the file exists, the line is
|
|
64
|
+
* in it, and `match` appears within 5 lines of it (anywhere, with no line).
|
|
65
|
+
* Null when it holds; otherwise why not.
|
|
66
|
+
*/
|
|
67
|
+
function citationProblem(root, at, match) {
|
|
68
|
+
const m = /^(.*?)(?::(\d+))?$/.exec(at);
|
|
69
|
+
const [file, lineText] = [m[1].replace(/^\.\//, ""), m[2]];
|
|
70
|
+
const text = readText(join(root, file));
|
|
71
|
+
if (text === null)
|
|
72
|
+
return `the cited file ${file} is missing`;
|
|
73
|
+
const all = text.split("\n");
|
|
74
|
+
if (text.endsWith("\n"))
|
|
75
|
+
all.pop();
|
|
76
|
+
const line = lineText ? parseInt(lineText, 10) : undefined;
|
|
77
|
+
if (line !== undefined && (line < 1 || line > all.length))
|
|
78
|
+
return `${file} has ${all.length} lines, so line ${line} is not in it`;
|
|
79
|
+
if (match === undefined)
|
|
80
|
+
return null;
|
|
81
|
+
const window = line === undefined ? all : all.slice(Math.max(0, line - 1 - MATCH_WINDOW), line + MATCH_WINDOW);
|
|
82
|
+
if (window.some((l) => l.includes(match)))
|
|
83
|
+
return null;
|
|
84
|
+
return line === undefined
|
|
85
|
+
? `"${match}" is not in ${file}`
|
|
86
|
+
: `"${match}" is not within ${MATCH_WINDOW} lines of line ${line} in ${file}; the check may have moved or gone`;
|
|
87
|
+
}
|
|
88
|
+
/** Whether a declared hook is in settings.json: same event, same matcher, a command naming its script. */
|
|
89
|
+
function hookOnDisk(settings, hook) {
|
|
90
|
+
const script = runParts(hook.run).script.replace(/^\.\//, "");
|
|
91
|
+
if (!script)
|
|
92
|
+
return false;
|
|
93
|
+
return findHooks(settings, claudeEvent(hook.on), script, (m) => !hook.matcher || m === hook.matcher).length > 0;
|
|
94
|
+
}
|
|
95
|
+
/** Notes on a hook's command: a relative path is skipped off the project root. */
|
|
96
|
+
function commandProblem(command = "") {
|
|
97
|
+
const loose = unanchoredScript(command);
|
|
98
|
+
return loose ? `the hook names ${loose} by a relative path, so it is skipped once Claude changes directory` : null;
|
|
99
|
+
}
|
|
100
|
+
export function checkGuards(ast, root) {
|
|
101
|
+
const name = ast.topology.name;
|
|
102
|
+
const scriptsDir = `.claude/skills/${name}/scripts`;
|
|
103
|
+
const settings = readJson(join(root, ".claude/settings.json"));
|
|
104
|
+
const beforeAgent = readText(join(root, scriptsDir, "before-agent.sh"));
|
|
105
|
+
const items = [];
|
|
106
|
+
/** The before-agent PreToolUse entry: present and anchored, with onFailure noted. */
|
|
107
|
+
const guardEntry = () => {
|
|
108
|
+
const hooks = findHooks(settings, "PreToolUse", "before-agent.sh", (m) => !!m && /\b(Agent|Task)\b/.test(m));
|
|
109
|
+
if (hooks.length === 0)
|
|
110
|
+
return { ok: false, notes: ["no PreToolUse entry for before-agent.sh in .claude/settings.json"] };
|
|
111
|
+
const bad = commandProblem(hooks[0].command);
|
|
112
|
+
if (bad)
|
|
113
|
+
return { ok: false, notes: [bad] };
|
|
114
|
+
if (beforeAgent === null)
|
|
115
|
+
return { ok: false, notes: [`${scriptsDir}/before-agent.sh is missing`] };
|
|
116
|
+
const notes = hooks.some((h) => h.onFailure === "block") ? [] : ['the entry has no onFailure: "block", so the step goes through if the hook cannot start'];
|
|
117
|
+
return { ok: true, notes };
|
|
118
|
+
};
|
|
119
|
+
for (const node of ast.nodes) {
|
|
120
|
+
if (node.type !== "gate")
|
|
121
|
+
continue;
|
|
122
|
+
const gate = node;
|
|
123
|
+
const base = { kind: "gate", id: gate.id };
|
|
124
|
+
if (gate.behavior === "advisory") {
|
|
125
|
+
items.push({ ...base, strength: "hope", by: "prose", where: "advisory: it reports and never blocks", notes: [] });
|
|
126
|
+
continue;
|
|
127
|
+
}
|
|
128
|
+
// A gate before a script step: before-action.sh refuses its command. One
|
|
129
|
+
// with nothing to check (V110) compiles to no line, and falls through to
|
|
130
|
+
// the cases below (prose, or a citation).
|
|
131
|
+
if (checkableActionGate(ast, gate)) {
|
|
132
|
+
const where = `PreToolUse on Bash running ${gateAnchors(gate, "before").join(", ")} → before-action.sh`;
|
|
133
|
+
const problems = [];
|
|
134
|
+
const hooks = findHooks(settings, "PreToolUse", "before-action.sh", (m) => !!m && /\bBash\b/.test(m));
|
|
135
|
+
if (hooks.length === 0)
|
|
136
|
+
problems.push("no PreToolUse entry on Bash for before-action.sh in .claude/settings.json");
|
|
137
|
+
else {
|
|
138
|
+
const bad = commandProblem(hooks[0].command);
|
|
139
|
+
if (bad)
|
|
140
|
+
problems.push(bad);
|
|
141
|
+
}
|
|
142
|
+
const script = readText(join(root, scriptsDir, "before-action.sh"));
|
|
143
|
+
if (script === null)
|
|
144
|
+
problems.push(`${scriptsDir}/before-action.sh is missing`);
|
|
145
|
+
else if (!script.includes(`# gate ${gate.id} (`))
|
|
146
|
+
problems.push(`before-action.sh has no line for gate ${gate.id}`);
|
|
147
|
+
if (gate.run && scriptNameFromRun(gate.run) && readText(join(root, scriptsDir, `gate-${gate.id}.sh`)) === null)
|
|
148
|
+
problems.push(`${scriptsDir}/gate-${gate.id}.sh is missing`);
|
|
149
|
+
const scope = "refuses in Claude Code sessions only; a step run outside Claude is covered by step check (by: code)";
|
|
150
|
+
const indirect = "a command that runs the step indirectly (bash -c, eval, a script that calls it) is not seen";
|
|
151
|
+
if (problems.length) {
|
|
152
|
+
items.push({ ...base, strength: "none", by: "hook", where, notes: [...problems, scope, indirect] });
|
|
153
|
+
}
|
|
154
|
+
else {
|
|
155
|
+
const entryNotes = hooks.some((h) => h.onFailure === "block") ? [] : ['the entry has no onFailure: "block", so the step goes through if the hook cannot start'];
|
|
156
|
+
items.push({ ...base, strength: "refuse", by: "hook", where, notes: [...entryNotes, ...(gate.run && scriptNameFromRun(gate.run) ? checkScriptNotes(root, scriptsDir, gate.run) : []), scope, indirect] });
|
|
157
|
+
}
|
|
158
|
+
continue;
|
|
159
|
+
}
|
|
160
|
+
if (!gate.run || !scriptNameFromRun(gate.run)) {
|
|
161
|
+
items.push({ ...base, strength: "hope", by: "prose", where: "its run: names no script", notes: [] });
|
|
162
|
+
continue;
|
|
163
|
+
}
|
|
164
|
+
const wiring = gateWiring(ast, gate);
|
|
165
|
+
if (wiring.kind === "none") {
|
|
166
|
+
const anchors = [...gateAnchors(gate, "after"), ...gateAnchors(gate, "before")].join(", ") || "nothing";
|
|
167
|
+
items.push({ ...base, strength: "hope", by: "prose", where: `no Claude Code event marks its moment (between ${anchors}); the playbook runs it`, notes: [] });
|
|
168
|
+
continue;
|
|
169
|
+
}
|
|
170
|
+
const scriptNotes = checkScriptNotes(root, scriptsDir, gate.run);
|
|
171
|
+
if (wiring.kind === "subagent-stop") {
|
|
172
|
+
const file = `gate-${gate.id}.sh`;
|
|
173
|
+
const problems = [];
|
|
174
|
+
for (const anchor of wiring.anchors) {
|
|
175
|
+
const hooks = findHooks(settings, "SubagentStop", file, (m) => m === anchor);
|
|
176
|
+
if (hooks.length === 0)
|
|
177
|
+
problems.push(`no SubagentStop entry for ${anchor} running ${file} in .claude/settings.json`);
|
|
178
|
+
else {
|
|
179
|
+
const bad = commandProblem(hooks[0].command);
|
|
180
|
+
if (bad)
|
|
181
|
+
problems.push(bad);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
if (readText(join(root, scriptsDir, file)) === null)
|
|
185
|
+
problems.push(`${scriptsDir}/${file} is missing`);
|
|
186
|
+
const where = `SubagentStop on ${wiring.anchors.join(", ")} → ${file}`;
|
|
187
|
+
items.push(problems.length
|
|
188
|
+
? { ...base, strength: "none", by: "hook", where, notes: problems }
|
|
189
|
+
: { ...base, strength: "refuse", by: "hook", where, notes: scriptNotes });
|
|
190
|
+
continue;
|
|
191
|
+
}
|
|
192
|
+
// before-agent
|
|
193
|
+
const where = `PreToolUse on launching ${wiring.agents.join(", ")} → before-agent.sh`;
|
|
194
|
+
const entry = guardEntry();
|
|
195
|
+
const problems = entry.ok ? [] : entry.notes;
|
|
196
|
+
if (entry.ok && !beforeAgent.includes(`gate-${gate.id}.sh`))
|
|
197
|
+
problems.push(`before-agent.sh does not run gate-${gate.id}.sh`);
|
|
198
|
+
if (readText(join(root, scriptsDir, `gate-${gate.id}.sh`)) === null)
|
|
199
|
+
problems.push(`${scriptsDir}/gate-${gate.id}.sh is missing`);
|
|
200
|
+
items.push(problems.length
|
|
201
|
+
? { ...base, strength: "none", by: "hook", where, notes: problems }
|
|
202
|
+
: { ...base, strength: "refuse", by: "hook", where, notes: [...entry.notes, ...scriptNotes] });
|
|
203
|
+
}
|
|
204
|
+
for (const node of ast.nodes) {
|
|
205
|
+
if (node.type !== "human")
|
|
206
|
+
continue;
|
|
207
|
+
const human = node;
|
|
208
|
+
const base = { kind: "human", id: human.id };
|
|
209
|
+
const targets = approvalTargets(ast, human);
|
|
210
|
+
if (targets.length === 0) {
|
|
211
|
+
items.push({ ...base, strength: "hope", by: "prose", where: "no agent follows it, so no launch to ask before; the playbook asks", notes: [] });
|
|
212
|
+
continue;
|
|
213
|
+
}
|
|
214
|
+
const where = `PreToolUse on launching ${targets.join(", ")} → ask`;
|
|
215
|
+
const entry = guardEntry();
|
|
216
|
+
const problems = entry.ok ? [] : entry.notes;
|
|
217
|
+
if (entry.ok && !beforeAgent.includes(`# approval step ${human.id}`))
|
|
218
|
+
problems.push(`before-agent.sh does not ask for ${human.id}`);
|
|
219
|
+
items.push(problems.length
|
|
220
|
+
? { ...base, strength: "none", by: "hook", where, notes: problems }
|
|
221
|
+
: { ...base, strength: "refuse", by: "hook", where, notes: [...entry.notes, "Claude Code asks the person in the session; in claude -p there is no one to ask, so it is denied"] });
|
|
222
|
+
}
|
|
223
|
+
for (const key of ["deny", "ask"]) {
|
|
224
|
+
for (const raw of ast.settings?.[key] ?? []) {
|
|
225
|
+
const rule = convertMcpToolName(raw);
|
|
226
|
+
const onDisk = (settings?.permissions?.[key] ?? []).includes(rule);
|
|
227
|
+
items.push({
|
|
228
|
+
kind: "permission",
|
|
229
|
+
id: `${key} ${rule}`,
|
|
230
|
+
strength: onDisk ? "refuse" : "none",
|
|
231
|
+
by: "settings",
|
|
232
|
+
where: `permissions.${key} in .claude/settings.json`,
|
|
233
|
+
notes: onDisk ? [] : [`.claude/settings.json has no ${key} rule ${rule}`],
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
// A hook is the topology's own when it runs a script from the skill's
|
|
238
|
+
// scripts folder, or when it is one the topology's hooks {} block compiles to.
|
|
239
|
+
const ours = `.claude/skills/${name}/scripts/`;
|
|
240
|
+
const declared = new Set();
|
|
241
|
+
for (const [event, entries] of Object.entries(settingsHooksOf(ast))) {
|
|
242
|
+
for (const e of entries)
|
|
243
|
+
for (const h of (e.hooks ?? []))
|
|
244
|
+
declared.add(`${event}|${h.command ?? h.prompt ?? h.url ?? ""}`);
|
|
245
|
+
}
|
|
246
|
+
const unattributed = [];
|
|
247
|
+
for (const [event, entries] of Object.entries((settings?.hooks ?? {}))) {
|
|
248
|
+
for (const e of entries ?? [])
|
|
249
|
+
for (const h of e.hooks ?? []) {
|
|
250
|
+
const handler = h;
|
|
251
|
+
if (h.command?.includes(ours) || declared.has(`${event}|${handler.command ?? handler.prompt ?? handler.url ?? ""}`))
|
|
252
|
+
continue;
|
|
253
|
+
unattributed.push(`${event}${e.matcher ? ` ${e.matcher}` : ""}: ${h.type === "command" ? h.command : h.type}`);
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
// Citations. A gate that cites the code refusing it (by: code, at:) is
|
|
257
|
+
// checked on disk; a gate the binding gives no hook is credited by a guard
|
|
258
|
+
// its edge cites. A cited hook counts only when it is in settings.json and
|
|
259
|
+
// declares its strength: the file's own claim, cited, not proven.
|
|
260
|
+
const hooksByName = new Map((ast.hooks ?? []).map((h) => [h.name, h]));
|
|
261
|
+
const gateItem = (id) => items.find((i) => i.kind === "gate" && i.id === id);
|
|
262
|
+
for (const node of ast.nodes) {
|
|
263
|
+
if (node.type !== "gate")
|
|
264
|
+
continue;
|
|
265
|
+
const gate = node;
|
|
266
|
+
const item = gateItem(gate.id);
|
|
267
|
+
if (gate.at) {
|
|
268
|
+
const bad = citationProblem(root, gate.at, gate.match);
|
|
269
|
+
const by = (gate.by ?? "code");
|
|
270
|
+
const notes = bad ? [bad] : ["cited, not proven: the code is there, this check cannot run it", ...(gate.bypass ? [`bypass: ${gate.bypass}`] : [])];
|
|
271
|
+
if (item.strength !== "refuse" || bad) {
|
|
272
|
+
Object.assign(item, { strength: bad ? "none" : (gate.strength ?? "refuse"), by, where: `${by} at ${gate.at}`, notes });
|
|
273
|
+
}
|
|
274
|
+
else {
|
|
275
|
+
item.notes.push(...notes.map((n) => `also ${n}`));
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
for (const node of ast.nodes) {
|
|
280
|
+
if (node.type !== "gate")
|
|
281
|
+
continue;
|
|
282
|
+
const gate = node;
|
|
283
|
+
const item = gateItem(gate.id);
|
|
284
|
+
if (item.strength === "refuse" || item.strength === "none")
|
|
285
|
+
continue;
|
|
286
|
+
const afters = gateAnchors(gate, "after");
|
|
287
|
+
const befores = gateAnchors(gate, "before");
|
|
288
|
+
const edges = ast.edges.filter((e) => e.guard?.length && afters.includes(e.from) && befores.includes(e.to));
|
|
289
|
+
const why = [];
|
|
290
|
+
const credited = () => item.strength === "refuse";
|
|
291
|
+
for (const edge of edges) {
|
|
292
|
+
for (const g of edge.guard) {
|
|
293
|
+
const hook = hooksByName.get(g);
|
|
294
|
+
if (hook) {
|
|
295
|
+
if (!hook.strength) {
|
|
296
|
+
why.push(`its edge cites ${g}, but ${g} declares no strength`);
|
|
297
|
+
continue;
|
|
298
|
+
}
|
|
299
|
+
if (!hookOnDisk(settings, hook)) {
|
|
300
|
+
why.push(`its edge cites ${g}, but ${g} is not in .claude/settings.json`);
|
|
301
|
+
continue;
|
|
302
|
+
}
|
|
303
|
+
if (hook.strength === "refuse" || hook.strength === "detect") {
|
|
304
|
+
Object.assign(item, { strength: hook.strength, by: "hook", where: `${hook.on}${hook.matcher ? ` ${hook.matcher}` : ""} hook ${g}, cited on ${edge.from} -> ${edge.to}`, notes: ["cited, not proven", ...(hook.bypass ? [`bypass: ${hook.bypass}`] : [])] });
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
else {
|
|
308
|
+
const other = gateItem(g);
|
|
309
|
+
if (other?.strength === "refuse")
|
|
310
|
+
Object.assign(item, { strength: "refuse", by: "gate", where: `gate ${g}, cited on ${edge.from} -> ${edge.to}`, notes: [`as strong as gate ${g}`] });
|
|
311
|
+
}
|
|
312
|
+
if (credited())
|
|
313
|
+
break;
|
|
314
|
+
}
|
|
315
|
+
if (credited())
|
|
316
|
+
break;
|
|
317
|
+
}
|
|
318
|
+
if (!credited() && why.length)
|
|
319
|
+
item.notes.push(...why);
|
|
320
|
+
}
|
|
321
|
+
for (const edge of ast.edges) {
|
|
322
|
+
if (!edge.strength)
|
|
323
|
+
continue;
|
|
324
|
+
items.push({
|
|
325
|
+
kind: "edge", id: `${edge.from} -> ${edge.to}`, strength: edge.strength, by: "prose", declared: true,
|
|
326
|
+
where: edge.at ? `as written, at ${edge.at}` : "as written in the flow",
|
|
327
|
+
notes: [`declared in the file${edge.strength === "none" ? ": nothing stops this step, and the file says so" : ""}`],
|
|
328
|
+
});
|
|
329
|
+
}
|
|
330
|
+
// A declared hook's settings entry is the topology's own, however its interpreter is spelled.
|
|
331
|
+
for (let i = unattributed.length - 1; i >= 0; i--) {
|
|
332
|
+
const u = unattributed[i];
|
|
333
|
+
if ((ast.hooks ?? []).some((h) => { const sc = runParts(h.run).script.replace(/^\.\//, ""); return !!sc && u.startsWith(claudeEvent(h.on)) && u.includes(sc); }))
|
|
334
|
+
unattributed.splice(i, 1);
|
|
335
|
+
}
|
|
336
|
+
const steps = items.filter((i) => i.kind === "gate" || i.kind === "human");
|
|
337
|
+
return {
|
|
338
|
+
items,
|
|
339
|
+
enforcement: { refuse: steps.filter((i) => i.strength === "refuse").length, of: steps.length },
|
|
340
|
+
missing: items.filter((i) => i.strength === "none" && !i.declared).length,
|
|
341
|
+
unattributed,
|
|
342
|
+
verifiedOn: VERIFIED_ON,
|
|
343
|
+
};
|
|
344
|
+
}
|
|
345
|
+
/** The report as terminal lines. */
|
|
346
|
+
export function renderGuardReport(report) {
|
|
347
|
+
const label = (i) => `${i.kind === "permission" ? "" : i.kind + " "}${i.id}`;
|
|
348
|
+
const width = Math.max(10, ...report.items.map((i) => label(i).length));
|
|
349
|
+
const lines = [];
|
|
350
|
+
for (const i of report.items) {
|
|
351
|
+
lines.push(` ${label(i).padEnd(width)} ${i.strength.padEnd(6)} by: ${i.by.padEnd(8)} ${i.where}`);
|
|
352
|
+
for (const n of i.notes)
|
|
353
|
+
lines.push(` ${"".padEnd(width)} ${i.strength === "none" && !i.declared ? "✗" : "⚠"} ${n}`);
|
|
354
|
+
}
|
|
355
|
+
lines.push("");
|
|
356
|
+
lines.push(`enforcement: ${report.enforcement.refuse} of ${report.enforcement.of} steps refuse · checked against Claude Code ${report.verifiedOn}`);
|
|
357
|
+
if (report.unattributed.length) {
|
|
358
|
+
lines.push(`${report.unattributed.length} hook(s) in .claude/settings.json are not tied to any step here (hand-built guards?). They may refuse steps shown as hope or none. Declare them in hooks { } with a strength and cite them on the edge with [guard: name]:`);
|
|
359
|
+
for (const u of report.unattributed)
|
|
360
|
+
lines.push(` ${u.length > 110 ? u.slice(0, 107) + "..." : u}`);
|
|
361
|
+
}
|
|
362
|
+
if (report.missing)
|
|
363
|
+
lines.push(`${report.missing} item(s) are missing or their citation no longer holds: rerun scaffold, fix the citation, or fix the project by hand`);
|
|
364
|
+
return lines;
|
|
365
|
+
}
|
|
366
|
+
//# sourceMappingURL=check.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"check.js","sourceRoot":"","sources":["../../src/guard/check.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `agentopology guard <file> --target claude-code`: write the guard part of
|
|
3
|
+
* what scaffold writes, and nothing else, into a project that may have been
|
|
4
|
+
* built by hand.
|
|
5
|
+
*
|
|
6
|
+
* Why it exists: scaffold owns a whole project; a hand-built one has its own
|
|
7
|
+
* agents, skills and settings, and only lacks the hooks that refuse. Running
|
|
8
|
+
* scaffold there meant either every generated file next to the user's or none.
|
|
9
|
+
* This writes the enforcement and leaves the rest.
|
|
10
|
+
*
|
|
11
|
+
* The set is discovered, not listed: the scripts settings.json hook commands
|
|
12
|
+
* run, then every generated file those scripts name by `$CLAUDE_PROJECT_DIR/…`
|
|
13
|
+
* (the gate wrappers, then the check scripts the gates run). A hard-coded
|
|
14
|
+
* list went stale the first time the binding added a hook script.
|
|
15
|
+
*
|
|
16
|
+
* @module
|
|
17
|
+
*/
|
|
18
|
+
import type { TopologyAST } from "../parser/ast.js";
|
|
19
|
+
import type { GeneratedFile } from "../bindings/types.js";
|
|
20
|
+
import { type ExecuteResult } from "../scaffold/incremental.js";
|
|
21
|
+
import type { FileAction } from "../scaffold/types.js";
|
|
22
|
+
/** The guard subset of a binding's output: hook scripts, gates, checks, and settings.json cut to hooks and permissions. */
|
|
23
|
+
export declare function guardFiles(files: GeneratedFile[]): GeneratedFile[];
|
|
24
|
+
export interface GuardTargetPlan {
|
|
25
|
+
/** What would be written, per file. */
|
|
26
|
+
actions: FileAction[];
|
|
27
|
+
/** Files left as they are, and why. */
|
|
28
|
+
skipped: Array<{
|
|
29
|
+
path: string;
|
|
30
|
+
why: string;
|
|
31
|
+
}>;
|
|
32
|
+
/** The files this run owns (the subset of scaffold's output). */
|
|
33
|
+
files: GeneratedFile[];
|
|
34
|
+
/** Check scripts, reached through a gate, among `files`. */
|
|
35
|
+
checks: Set<string>;
|
|
36
|
+
}
|
|
37
|
+
/** Plan the guard write for a project. Reads the disk; writes nothing. */
|
|
38
|
+
export declare function planGuardTarget(ast: TopologyAST, root: string, source: string): GuardTargetPlan;
|
|
39
|
+
/**
|
|
40
|
+
* Write a plan and record it in the scaffold manifest. The manifest keeps the
|
|
41
|
+
* entries of files this run did not touch (a full scaffold's agents, say), so
|
|
42
|
+
* a later scaffold still knows what it owns. Nothing is pruned.
|
|
43
|
+
*/
|
|
44
|
+
export declare function applyGuardTarget(plan: GuardTargetPlan, root: string, source: string, sourceText: string): ExecuteResult;
|
|
45
|
+
//# sourceMappingURL=target.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"target.d.ts","sourceRoot":"","sources":["../../src/guard/target.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAIH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAEpD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAG1D,OAAO,EAA6D,KAAK,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAC3H,OAAO,KAAK,EAAE,UAAU,EAAoB,MAAM,sBAAsB,CAAC;AAwCzE,2HAA2H;AAC3H,wBAAgB,UAAU,CAAC,KAAK,EAAE,aAAa,EAAE,GAAG,aAAa,EAAE,CAElE;AAkCD,MAAM,WAAW,eAAe;IAC9B,uCAAuC;IACvC,OAAO,EAAE,UAAU,EAAE,CAAC;IACtB,uCAAuC;IACvC,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC9C,iEAAiE;IACjE,KAAK,EAAE,aAAa,EAAE,CAAC;IACvB,4DAA4D;IAC5D,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;CACrB;AAED,0EAA0E;AAC1E,wBAAgB,eAAe,CAAC,GAAG,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,eAAe,CA2B/F;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,eAAe,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,aAAa,CAcvH"}
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `agentopology guard <file> --target claude-code`: write the guard part of
|
|
3
|
+
* what scaffold writes, and nothing else, into a project that may have been
|
|
4
|
+
* built by hand.
|
|
5
|
+
*
|
|
6
|
+
* Why it exists: scaffold owns a whole project; a hand-built one has its own
|
|
7
|
+
* agents, skills and settings, and only lacks the hooks that refuse. Running
|
|
8
|
+
* scaffold there meant either every generated file next to the user's or none.
|
|
9
|
+
* This writes the enforcement and leaves the rest.
|
|
10
|
+
*
|
|
11
|
+
* The set is discovered, not listed: the scripts settings.json hook commands
|
|
12
|
+
* run, then every generated file those scripts name by `$CLAUDE_PROJECT_DIR/…`
|
|
13
|
+
* (the gate wrappers, then the check scripts the gates run). A hard-coded
|
|
14
|
+
* list went stale the first time the binding added a hook script.
|
|
15
|
+
*
|
|
16
|
+
* @module
|
|
17
|
+
*/
|
|
18
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
19
|
+
import { join } from "node:path";
|
|
20
|
+
import { claudeCodeBinding } from "../bindings/claude-code.js";
|
|
21
|
+
import { isStubContent } from "../bindings/lib/stub.js";
|
|
22
|
+
import { readManifest, writeManifest, hashContent } from "../scaffold/manifest.js";
|
|
23
|
+
import { computeIncrementalPlan, executeActions, nextManifestFiles } from "../scaffold/incremental.js";
|
|
24
|
+
const SETTINGS = ".claude/settings.json";
|
|
25
|
+
const VAR_PATH = /\$\{?([A-Za-z_]\w*)\}?\/([^\s"'`;|&)]+)/g;
|
|
26
|
+
/**
|
|
27
|
+
* The generated paths a piece of text names: `$CLAUDE_PROJECT_DIR/<path>`, or
|
|
28
|
+
* `$VAR/<file>` where the text sets `VAR="<dir>"` itself. before-agent.sh calls
|
|
29
|
+
* its gates as `"$DIR/gate-x.sh"` with `DIR=".claude/skills/…/scripts"`; reading
|
|
30
|
+
* only the project-dir form missed every gate (the first run of N41).
|
|
31
|
+
*/
|
|
32
|
+
function refs(text, known) {
|
|
33
|
+
const vars = new Map([["CLAUDE_PROJECT_DIR", ""]]);
|
|
34
|
+
for (const m of text.matchAll(/^\s*(?:export\s+)?([A-Za-z_]\w*)=["']?([^"'\n]*?)["']?\s*$/gm))
|
|
35
|
+
vars.set(m[1], m[2].replace(/^\.\//, "").replace(/\/$/, ""));
|
|
36
|
+
const out = [];
|
|
37
|
+
for (const m of text.matchAll(VAR_PATH)) {
|
|
38
|
+
const dir = vars.get(m[1]);
|
|
39
|
+
if (dir === undefined)
|
|
40
|
+
continue;
|
|
41
|
+
const p = (dir ? `${dir}/` : "") + m[2].replace(/^\.\//, "");
|
|
42
|
+
if (known.has(p))
|
|
43
|
+
out.push(p);
|
|
44
|
+
}
|
|
45
|
+
return out;
|
|
46
|
+
}
|
|
47
|
+
/** `hooks` keeps only command groups (a prompt or http hook names no script and could not be told apart on a rerun); `permissions` whole. */
|
|
48
|
+
function guardSettings(raw) {
|
|
49
|
+
const s = JSON.parse(raw);
|
|
50
|
+
const hooks = {};
|
|
51
|
+
for (const [event, groups] of Object.entries(s.hooks ?? {})) {
|
|
52
|
+
const kept = groups
|
|
53
|
+
.map((g) => ({ ...g, hooks: (g.hooks ?? []).filter((h) => typeof h.command === "string") }))
|
|
54
|
+
.filter((g) => g.hooks.length > 0);
|
|
55
|
+
if (kept.length > 0)
|
|
56
|
+
hooks[event] = kept;
|
|
57
|
+
}
|
|
58
|
+
const out = {};
|
|
59
|
+
if (Object.keys(hooks).length > 0)
|
|
60
|
+
out.hooks = hooks;
|
|
61
|
+
if (s.permissions !== undefined)
|
|
62
|
+
out.permissions = s.permissions;
|
|
63
|
+
return JSON.stringify(out, null, 2) + "\n";
|
|
64
|
+
}
|
|
65
|
+
/** The guard subset of a binding's output: hook scripts, gates, checks, and settings.json cut to hooks and permissions. */
|
|
66
|
+
export function guardFiles(files) {
|
|
67
|
+
return discover(files).files;
|
|
68
|
+
}
|
|
69
|
+
/** `checks` are the files two calls from a hook (the checks the gates run), for the "no longer a stub" rule. */
|
|
70
|
+
function discover(files) {
|
|
71
|
+
const byPath = new Map(files.map((f) => [f.path, f]));
|
|
72
|
+
const known = new Set(byPath.keys());
|
|
73
|
+
const settings = byPath.get(SETTINGS);
|
|
74
|
+
const picked = new Map();
|
|
75
|
+
const checks = new Set();
|
|
76
|
+
const queue = [];
|
|
77
|
+
if (settings) {
|
|
78
|
+
const hooks = JSON.parse(settings.content).hooks ?? {};
|
|
79
|
+
for (const groups of Object.values(hooks))
|
|
80
|
+
for (const g of groups)
|
|
81
|
+
for (const h of g.hooks ?? [])
|
|
82
|
+
if (h.command)
|
|
83
|
+
queue.push(...refs(h.command, known));
|
|
84
|
+
}
|
|
85
|
+
// depth 0: scripts hooks run; 1: gate wrappers they call; 2+: the checks the gates run
|
|
86
|
+
const depth = new Map(queue.map((p) => [p, 0]));
|
|
87
|
+
while (queue.length > 0) {
|
|
88
|
+
const p = queue.shift();
|
|
89
|
+
if (picked.has(p))
|
|
90
|
+
continue;
|
|
91
|
+
const f = byPath.get(p);
|
|
92
|
+
picked.set(p, f);
|
|
93
|
+
for (const r of refs(f.content, known)) {
|
|
94
|
+
if (r === p)
|
|
95
|
+
continue;
|
|
96
|
+
if (!depth.has(r))
|
|
97
|
+
depth.set(r, depth.get(p) + 1);
|
|
98
|
+
queue.push(r);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
for (const [p, d] of depth)
|
|
102
|
+
if (d >= 2)
|
|
103
|
+
checks.add(p);
|
|
104
|
+
const out = [...picked.values()];
|
|
105
|
+
if (settings)
|
|
106
|
+
out.push({ ...settings, content: guardSettings(settings.content) });
|
|
107
|
+
return { files: out, checks };
|
|
108
|
+
}
|
|
109
|
+
/** Plan the guard write for a project. Reads the disk; writes nothing. */
|
|
110
|
+
export function planGuardTarget(ast, root, source) {
|
|
111
|
+
const { files, checks } = discover(claudeCodeBinding.scaffold(ast));
|
|
112
|
+
const manifest = readManifest(root, "claude-code", source);
|
|
113
|
+
const owned = new Set(files.map((f) => f.path));
|
|
114
|
+
// The planner deletes manifest files the run no longer generates; this run
|
|
115
|
+
// generates a subset on purpose, so only its own paths are planned.
|
|
116
|
+
const actions = computeIncrementalPlan(root, "claude-code", files, manifest).filter((a) => owned.has(a.path));
|
|
117
|
+
const skipped = [];
|
|
118
|
+
const planned = [];
|
|
119
|
+
for (const a of actions) {
|
|
120
|
+
const abs = join(root, a.path);
|
|
121
|
+
const generated = files.find((f) => f.path === a.path);
|
|
122
|
+
// A check someone has implemented is theirs, even when scaffold recorded
|
|
123
|
+
// its stub: the hash then differs from the manifest only by their work.
|
|
124
|
+
if (checks.has(a.path) && existsSync(abs) && a.type !== "unchanged") {
|
|
125
|
+
const onDisk = readFileSync(abs, "utf-8");
|
|
126
|
+
if (onDisk !== generated.content && !isStubContent(onDisk)) {
|
|
127
|
+
skipped.push({ path: a.path, why: "skipped: no longer a stub" });
|
|
128
|
+
continue;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
if (a.type === "conflict") {
|
|
132
|
+
skipped.push({ path: a.path, why: `kept: ${a.detail}` });
|
|
133
|
+
continue;
|
|
134
|
+
}
|
|
135
|
+
if (a.type === "kept") {
|
|
136
|
+
skipped.push({ path: a.path, why: `kept: ${a.detail}` });
|
|
137
|
+
continue;
|
|
138
|
+
}
|
|
139
|
+
if (a.type === "blocked" && !a.unsafe) {
|
|
140
|
+
skipped.push({ path: a.path, why: `blocked: ${a.detail}` });
|
|
141
|
+
continue;
|
|
142
|
+
}
|
|
143
|
+
planned.push(a);
|
|
144
|
+
}
|
|
145
|
+
return { actions: planned, skipped, files, checks };
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Write a plan and record it in the scaffold manifest. The manifest keeps the
|
|
149
|
+
* entries of files this run did not touch (a full scaffold's agents, say), so
|
|
150
|
+
* a later scaffold still knows what it owns. Nothing is pruned.
|
|
151
|
+
*/
|
|
152
|
+
export function applyGuardTarget(plan, root, source, sourceText) {
|
|
153
|
+
const previous = readManifest(root, "claude-code", source);
|
|
154
|
+
const result = executeActions(root, plan.actions, { prune: false, force: false });
|
|
155
|
+
const manifest = {
|
|
156
|
+
source,
|
|
157
|
+
sourceHash: hashContent(sourceText),
|
|
158
|
+
target: "claude-code",
|
|
159
|
+
generatedAt: new Date().toISOString(),
|
|
160
|
+
files: { ...(previous?.files ?? {}), ...nextManifestFiles(root, plan.actions, plan.files, previous, result) },
|
|
161
|
+
};
|
|
162
|
+
// A timestamp alone is not a change: a rerun that did nothing writes nothing.
|
|
163
|
+
const same = previous && previous.sourceHash === manifest.sourceHash && JSON.stringify(previous.files) === JSON.stringify(manifest.files);
|
|
164
|
+
if (!same)
|
|
165
|
+
writeManifest(root, "claude-code", manifest);
|
|
166
|
+
return result;
|
|
167
|
+
}
|
|
168
|
+
//# sourceMappingURL=target.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"target.js","sourceRoot":"","sources":["../../src/guard/target.ts"],"names":[],"mappings":"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"}
|