agentopology 0.5.2 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -5
- package/dist/__tests__/e2e/roundtrip.test.d.ts +16 -0
- package/dist/__tests__/e2e/roundtrip.test.d.ts.map +1 -0
- package/dist/__tests__/e2e/roundtrip.test.js +178 -0
- package/dist/__tests__/e2e/roundtrip.test.js.map +1 -0
- package/dist/__tests__/e2e/scaffold-owns.test.d.ts +10 -0
- package/dist/__tests__/e2e/scaffold-owns.test.d.ts.map +1 -0
- package/dist/__tests__/e2e/scaffold-owns.test.js +154 -0
- package/dist/__tests__/e2e/scaffold-owns.test.js.map +1 -0
- package/dist/__tests__/global-setup.d.ts +7 -0
- package/dist/__tests__/global-setup.d.ts.map +1 -0
- package/dist/__tests__/global-setup.js +16 -0
- package/dist/__tests__/global-setup.js.map +1 -0
- package/dist/__tests__/live/claude-code.live.test.d.ts +20 -0
- package/dist/__tests__/live/claude-code.live.test.d.ts.map +1 -0
- package/dist/__tests__/live/claude-code.live.test.js +136 -0
- package/dist/__tests__/live/claude-code.live.test.js.map +1 -0
- package/dist/__tests__/live/zz-debug.test.d.ts +2 -0
- package/dist/__tests__/live/zz-debug.test.d.ts.map +1 -0
- package/dist/__tests__/live/zz-debug.test.js +4 -0
- package/dist/__tests__/live/zz-debug.test.js.map +1 -0
- package/dist/__tests__/open-findings.test.d.ts +10 -0
- package/dist/__tests__/open-findings.test.d.ts.map +1 -0
- package/dist/__tests__/open-findings.test.js +37 -0
- package/dist/__tests__/open-findings.test.js.map +1 -0
- package/dist/__tests__/spec-testing-sync.test.d.ts +10 -0
- package/dist/__tests__/spec-testing-sync.test.d.ts.map +1 -0
- package/dist/__tests__/spec-testing-sync.test.js +57 -0
- package/dist/__tests__/spec-testing-sync.test.js.map +1 -0
- package/dist/bindings/__tests__/hook-command.test.d.ts +9 -0
- package/dist/bindings/__tests__/hook-command.test.d.ts.map +1 -0
- package/dist/bindings/__tests__/hook-command.test.js +88 -0
- package/dist/bindings/__tests__/hook-command.test.js.map +1 -0
- package/dist/bindings/__tests__/mod-plugin.test.d.ts +9 -0
- package/dist/bindings/__tests__/mod-plugin.test.d.ts.map +1 -0
- package/dist/bindings/__tests__/mod-plugin.test.js +164 -0
- package/dist/bindings/__tests__/mod-plugin.test.js.map +1 -0
- package/dist/bindings/claude-code.d.ts +52 -1
- package/dist/bindings/claude-code.d.ts.map +1 -1
- package/dist/bindings/claude-code.js +306 -68
- package/dist/bindings/claude-code.js.map +1 -1
- package/dist/bindings/index.d.ts +7 -0
- package/dist/bindings/index.d.ts.map +1 -1
- package/dist/bindings/index.js +26 -7
- package/dist/bindings/index.js.map +1 -1
- package/dist/bindings/types.d.ts +6 -0
- package/dist/bindings/types.d.ts.map +1 -1
- package/dist/bindings/types.js.map +1 -1
- package/dist/cli/__tests__/cli.test.d.ts +1 -1
- package/dist/cli/__tests__/cli.test.js +1 -1
- package/dist/cli/index.js +118 -78
- package/dist/cli/index.js.map +1 -1
- package/dist/docs/content.d.ts.map +1 -1
- package/dist/docs/content.js +39 -3
- package/dist/docs/content.js.map +1 -1
- package/dist/docs/teach.d.ts.map +1 -1
- package/dist/docs/teach.js +36 -0
- package/dist/docs/teach.js.map +1 -1
- package/dist/import/__tests__/import.test.js +21 -9
- package/dist/import/__tests__/import.test.js.map +1 -1
- package/dist/import/claude-code.d.ts.map +1 -1
- package/dist/import/claude-code.js +128 -44
- package/dist/import/claude-code.js.map +1 -1
- package/dist/import/serializer.d.ts.map +1 -1
- package/dist/import/serializer.js +10 -0
- package/dist/import/serializer.js.map +1 -1
- package/dist/parser/__tests__/mod-hooks.test.d.ts +10 -0
- package/dist/parser/__tests__/mod-hooks.test.d.ts.map +1 -0
- package/dist/parser/__tests__/mod-hooks.test.js +136 -0
- package/dist/parser/__tests__/mod-hooks.test.js.map +1 -0
- package/dist/parser/ast.d.ts +29 -2
- 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 +76 -22
- package/dist/parser/index.js.map +1 -1
- package/dist/parser/paths.d.ts +15 -0
- package/dist/parser/paths.d.ts.map +1 -0
- package/dist/parser/paths.js +34 -0
- package/dist/parser/paths.js.map +1 -0
- package/dist/parser/run.d.ts +24 -0
- package/dist/parser/run.d.ts.map +1 -0
- package/dist/parser/run.js +55 -0
- package/dist/parser/run.js.map +1 -0
- package/dist/parser/validator.d.ts +12 -0
- package/dist/parser/validator.d.ts.map +1 -1
- package/dist/parser/validator.js +218 -2
- package/dist/parser/validator.js.map +1 -1
- package/dist/scaffold/__tests__/safety.test.d.ts +11 -0
- package/dist/scaffold/__tests__/safety.test.d.ts.map +1 -0
- package/dist/scaffold/__tests__/safety.test.js +184 -0
- package/dist/scaffold/__tests__/safety.test.js.map +1 -0
- package/dist/scaffold/__tests__/scaffold.test.js +2 -1
- package/dist/scaffold/__tests__/scaffold.test.js.map +1 -1
- package/dist/scaffold/__tests__/settings-merge.test.js +40 -9
- package/dist/scaffold/__tests__/settings-merge.test.js.map +1 -1
- package/dist/scaffold/incremental.d.ts +49 -13
- package/dist/scaffold/incremental.d.ts.map +1 -1
- package/dist/scaffold/incremental.js +235 -95
- package/dist/scaffold/incremental.js.map +1 -1
- package/dist/scaffold/manifest.d.ts +8 -1
- package/dist/scaffold/manifest.d.ts.map +1 -1
- package/dist/scaffold/manifest.js +32 -8
- package/dist/scaffold/manifest.js.map +1 -1
- package/dist/scaffold/merge.d.ts +15 -4
- package/dist/scaffold/merge.d.ts.map +1 -1
- package/dist/scaffold/merge.js +109 -18
- package/dist/scaffold/merge.js.map +1 -1
- package/dist/scaffold/types.d.ts +17 -0
- package/dist/scaffold/types.d.ts.map +1 -1
- package/package.json +1 -1
- package/spec/grammar.md +20 -4
- package/spec/testing.md +81 -0
- package/spec/validation.md +6 -2
package/dist/scaffold/merge.js
CHANGED
|
@@ -107,24 +107,38 @@ export function deepMergeJson(existingRaw, generatedRaw) {
|
|
|
107
107
|
return existingRaw;
|
|
108
108
|
}
|
|
109
109
|
const merged = mergeObjects(existing, generated);
|
|
110
|
+
// Nothing to add: keep the user's bytes, formatting included.
|
|
111
|
+
if (JSON.stringify(merged) === JSON.stringify(existing))
|
|
112
|
+
return existingRaw;
|
|
110
113
|
return JSON.stringify(merged, null, 2) + "\n";
|
|
111
114
|
}
|
|
112
115
|
/**
|
|
113
116
|
* Merge settings.json files with domain-aware logic for Claude Code settings.
|
|
114
117
|
*
|
|
118
|
+
* The user's file is the base; scaffold only adds or replaces what it owns.
|
|
119
|
+
*
|
|
115
120
|
* Rules:
|
|
116
|
-
* - permissions
|
|
117
|
-
*
|
|
121
|
+
* - permissions: every existing key is kept (ask, defaultMode,
|
|
122
|
+
* additionalDirectories, ...); allow, deny and ask arrays are
|
|
123
|
+
* union-merged; a generated scalar is added only where none exists
|
|
118
124
|
* - env: shallow-merge (generated wins on key conflict)
|
|
119
|
-
* - hooks:
|
|
125
|
+
* - hooks: a hook group is the topology's when one of its commands names a
|
|
126
|
+
* path in `ownedPaths`; those are replaced by the generated hooks, and
|
|
127
|
+
* every other group — the user's — is kept. Without `ownedPaths`, nothing
|
|
128
|
+
* existing is treated as owned, so nothing is removed
|
|
120
129
|
* - All other top-level keys: existing wins (user-only keys preserved)
|
|
121
130
|
*
|
|
131
|
+
* This used to rebuild permissions from allow/deny alone and replace hooks
|
|
132
|
+
* wholesale, so a re-scaffold deleted the user's own hooks, ask rules and
|
|
133
|
+
* defaultMode, and two topologies in one repo deleted each other's hooks.
|
|
134
|
+
*
|
|
122
135
|
* @param existingRaw - Current settings.json content on disk (JSON string, or empty string)
|
|
123
136
|
* @param generatedRaw - Freshly generated settings.json content (JSON string)
|
|
137
|
+
* @param ownedPaths - Paths this topology writes or wrote (generated + manifest)
|
|
124
138
|
* @returns Merged JSON string
|
|
125
139
|
* @throws {Error} if existingRaw is non-empty and is invalid JSON
|
|
126
140
|
*/
|
|
127
|
-
export function deepMergeSettingsJson(existingRaw, generatedRaw) {
|
|
141
|
+
export function deepMergeSettingsJson(existingRaw, generatedRaw, ownedPaths = []) {
|
|
128
142
|
// Empty existing means first scaffold — return generated unchanged
|
|
129
143
|
if (existingRaw.trim() === "") {
|
|
130
144
|
return generatedRaw;
|
|
@@ -145,22 +159,35 @@ export function deepMergeSettingsJson(existingRaw, generatedRaw) {
|
|
|
145
159
|
}
|
|
146
160
|
// Start with existing (preserves all user-only top-level keys)
|
|
147
161
|
const merged = { ...existing };
|
|
148
|
-
// --- permissions: union
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
const mergedPerms = {};
|
|
153
|
-
for (const key of
|
|
154
|
-
const
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
162
|
+
// --- permissions: keep every existing key; union the rule arrays ---
|
|
163
|
+
if (isPlainObject(generated.permissions) || isPlainObject(existing.permissions)) {
|
|
164
|
+
const ex = isPlainObject(existing.permissions) ? existing.permissions : {};
|
|
165
|
+
const gen = isPlainObject(generated.permissions) ? generated.permissions : {};
|
|
166
|
+
const mergedPerms = { ...ex };
|
|
167
|
+
for (const [key, value] of Object.entries(gen)) {
|
|
168
|
+
const current = mergedPerms[key];
|
|
169
|
+
if (Array.isArray(value) || Array.isArray(current)) {
|
|
170
|
+
const union = Array.from(new Set([
|
|
171
|
+
...(Array.isArray(current) ? current : []),
|
|
172
|
+
...(Array.isArray(value) ? value : []),
|
|
173
|
+
]));
|
|
158
174
|
mergedPerms[key] = union;
|
|
159
175
|
}
|
|
176
|
+
else if (current === undefined) {
|
|
177
|
+
mergedPerms[key] = value;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
for (const key of Object.keys(mergedPerms)) {
|
|
181
|
+
if (Array.isArray(mergedPerms[key]) && mergedPerms[key].length === 0) {
|
|
182
|
+
delete mergedPerms[key];
|
|
183
|
+
}
|
|
160
184
|
}
|
|
161
185
|
if (Object.keys(mergedPerms).length > 0) {
|
|
162
186
|
merged.permissions = mergedPerms;
|
|
163
187
|
}
|
|
188
|
+
else {
|
|
189
|
+
delete merged.permissions;
|
|
190
|
+
}
|
|
164
191
|
}
|
|
165
192
|
// --- env: shallow-merge, generated wins on conflict ---
|
|
166
193
|
if (generated.env !== undefined) {
|
|
@@ -168,12 +195,12 @@ export function deepMergeSettingsJson(existingRaw, generatedRaw) {
|
|
|
168
195
|
const generatedEnv = generated.env;
|
|
169
196
|
merged.env = { ...existingEnv, ...generatedEnv };
|
|
170
197
|
}
|
|
171
|
-
// --- hooks:
|
|
172
|
-
|
|
173
|
-
|
|
198
|
+
// --- hooks: replace the topology's own groups, keep the user's ---
|
|
199
|
+
const mergedHooks = mergeHooks(existing.hooks, generated.hooks, ownedPaths);
|
|
200
|
+
if (mergedHooks) {
|
|
201
|
+
merged.hooks = mergedHooks;
|
|
174
202
|
}
|
|
175
203
|
else {
|
|
176
|
-
// No hooks in generated — remove the hooks key (topology no longer declares any)
|
|
177
204
|
delete merged.hooks;
|
|
178
205
|
}
|
|
179
206
|
// --- all other generated keys: add if missing, do NOT overwrite existing ---
|
|
@@ -184,8 +211,72 @@ export function deepMergeSettingsJson(existingRaw, generatedRaw) {
|
|
|
184
211
|
merged[key] = value;
|
|
185
212
|
}
|
|
186
213
|
}
|
|
214
|
+
// Nothing to add: keep the user's bytes, formatting included.
|
|
215
|
+
if (JSON.stringify(merged) === JSON.stringify(existing))
|
|
216
|
+
return existingRaw;
|
|
187
217
|
return JSON.stringify(merged, null, 2) + "\n";
|
|
188
218
|
}
|
|
219
|
+
function isPlainObject(v) {
|
|
220
|
+
return v !== null && typeof v === "object" && !Array.isArray(v);
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* Identity of a hook group for deduplication: matcher plus each command with
|
|
224
|
+
* the project-dir prefix, quotes and "./" removed. An imported hook written
|
|
225
|
+
* as `bash .claude/hooks/x.sh` and the same hook compiled as
|
|
226
|
+
* `bash "$CLAUDE_PROJECT_DIR/.claude/hooks/x.sh"` are one hook, not two that
|
|
227
|
+
* both fire.
|
|
228
|
+
*/
|
|
229
|
+
function hookGroupKey(group) {
|
|
230
|
+
if (!isPlainObject(group) || !Array.isArray(group.hooks))
|
|
231
|
+
return JSON.stringify(group);
|
|
232
|
+
const commands = group.hooks.map((h) => isPlainObject(h) && typeof h.command === "string"
|
|
233
|
+
? h.command.replace(/"?\$CLAUDE_PROJECT_DIR\/?/g, "").replace(/["']/g, "").replace(/(^|\s)\.\//g, "$1").replace(/\s+/g, " ").trim()
|
|
234
|
+
: JSON.stringify(h));
|
|
235
|
+
return JSON.stringify([group.matcher ?? "", commands]);
|
|
236
|
+
}
|
|
237
|
+
/** Whether a hook group runs a script this topology owns. */
|
|
238
|
+
function isOwnedHookGroup(group, scripts) {
|
|
239
|
+
if (!isPlainObject(group) || !Array.isArray(group.hooks))
|
|
240
|
+
return false;
|
|
241
|
+
return group.hooks.some((h) => {
|
|
242
|
+
if (!isPlainObject(h) || typeof h.command !== "string")
|
|
243
|
+
return false;
|
|
244
|
+
const tokens = h.command.split(/\s+/).map((t) => t.replace(/^\.\//, ""));
|
|
245
|
+
return tokens.some((t) => scripts.includes(t));
|
|
246
|
+
});
|
|
247
|
+
}
|
|
248
|
+
/**
|
|
249
|
+
* Per event: the user's groups first, then the generated ones, deduplicated.
|
|
250
|
+
* Returns undefined when no event keeps any group.
|
|
251
|
+
*/
|
|
252
|
+
function mergeHooks(existingHooks, generatedHooks, ownedPaths) {
|
|
253
|
+
// Config files are never hook scripts; matching them would claim a user hook
|
|
254
|
+
// that merely mentions CLAUDE.md.
|
|
255
|
+
const scripts = ownedPaths
|
|
256
|
+
.filter((p) => !/\.(md|json)$/.test(p))
|
|
257
|
+
.map((p) => p.replace(/^\.\//, ""));
|
|
258
|
+
const ex = isPlainObject(existingHooks) ? existingHooks : {};
|
|
259
|
+
const gen = isPlainObject(generatedHooks) ? generatedHooks : {};
|
|
260
|
+
const out = {};
|
|
261
|
+
for (const event of new Set([...Object.keys(ex), ...Object.keys(gen)])) {
|
|
262
|
+
// A group generated again stays where it is, so reruns (and two
|
|
263
|
+
// topologies taking turns) do not reorder the file.
|
|
264
|
+
const regenerated = new Set((Array.isArray(gen[event]) ? gen[event] : []).map(hookGroupKey));
|
|
265
|
+
const kept = (Array.isArray(ex[event]) ? ex[event] : []).filter((g) => regenerated.has(hookGroupKey(g)) || !isOwnedHookGroup(g, scripts));
|
|
266
|
+
const seen = new Set();
|
|
267
|
+
const groups = [];
|
|
268
|
+
for (const g of [...kept, ...(Array.isArray(gen[event]) ? gen[event] : [])]) {
|
|
269
|
+
const key = hookGroupKey(g);
|
|
270
|
+
if (seen.has(key))
|
|
271
|
+
continue;
|
|
272
|
+
seen.add(key);
|
|
273
|
+
groups.push(g);
|
|
274
|
+
}
|
|
275
|
+
if (groups.length > 0)
|
|
276
|
+
out[event] = groups;
|
|
277
|
+
}
|
|
278
|
+
return Object.keys(out).length > 0 ? out : undefined;
|
|
279
|
+
}
|
|
189
280
|
function mergeObjects(existing, generated) {
|
|
190
281
|
// Start with a copy of existing (preserves user-only keys)
|
|
191
282
|
const result = { ...existing };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"merge.js","sourceRoot":"","sources":["../../src/scaffold/merge.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"merge.js","sourceRoot":"","sources":["../../src/scaffold/merge.ts"],"names":[],"mappings":"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"}
|
package/dist/scaffold/types.d.ts
CHANGED
|
@@ -49,5 +49,22 @@ export type FileAction = {
|
|
|
49
49
|
path: string;
|
|
50
50
|
content: string;
|
|
51
51
|
detail: string;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Never written or deleted, even with --force. `unsafe` marks a path that
|
|
55
|
+
* must abort the whole run before anything is written (an empty or
|
|
56
|
+
* malformed file name — the EISDIR class).
|
|
57
|
+
*/
|
|
58
|
+
| {
|
|
59
|
+
type: "blocked";
|
|
60
|
+
path: string;
|
|
61
|
+
detail: string;
|
|
62
|
+
unsafe?: boolean;
|
|
63
|
+
}
|
|
64
|
+
/** A create-only file already there: the user's. Never written or claimed. */
|
|
65
|
+
| {
|
|
66
|
+
type: "kept";
|
|
67
|
+
path: string;
|
|
68
|
+
detail: string;
|
|
52
69
|
};
|
|
53
70
|
//# sourceMappingURL=types.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/scaffold/types.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,+CAA+C;AAC/C,MAAM,WAAW,aAAa;IAC5B,2DAA2D;IAC3D,IAAI,EAAE,MAAM,CAAC;IACb,6EAA6E;IAC7E,QAAQ,EAAE,SAAS,GAAG,OAAO,GAAG,QAAQ,GAAG,eAAe,CAAC;CAC5D;AAED,wDAAwD;AACxD,MAAM,WAAW,gBAAgB;IAC/B,4BAA4B;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,8DAA8D;IAC9D,UAAU,EAAE,MAAM,CAAC;IACnB,gDAAgD;IAChD,MAAM,EAAE,MAAM,CAAC;IACf,6DAA6D;IAC7D,WAAW,EAAE,MAAM,CAAC;IACpB,4DAA4D;IAC5D,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;CACtC;AAED,yEAAyE;AACzE,MAAM,MAAM,UAAU,GAClB;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,OAAO,CAAA;CAAE,GACvE;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,OAAO,CAAA;CAAE,GACvF;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAChC;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GACnC;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC"}
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/scaffold/types.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,+CAA+C;AAC/C,MAAM,WAAW,aAAa;IAC5B,2DAA2D;IAC3D,IAAI,EAAE,MAAM,CAAC;IACb,6EAA6E;IAC7E,QAAQ,EAAE,SAAS,GAAG,OAAO,GAAG,QAAQ,GAAG,eAAe,CAAC;CAC5D;AAED,wDAAwD;AACxD,MAAM,WAAW,gBAAgB;IAC/B,4BAA4B;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,8DAA8D;IAC9D,UAAU,EAAE,MAAM,CAAC;IACnB,gDAAgD;IAChD,MAAM,EAAE,MAAM,CAAC;IACf,6DAA6D;IAC7D,WAAW,EAAE,MAAM,CAAC;IACpB,4DAA4D;IAC5D,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;CACtC;AAED,yEAAyE;AACzE,MAAM,MAAM,UAAU,GAClB;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,OAAO,CAAA;CAAE,GACvE;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,OAAO,CAAA;CAAE,GACvF;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAChC;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GACnC;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE;AACrE;;;;GAIG;GACD;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,OAAO,CAAA;CAAE;AACrE,8EAA8E;GAC5E;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC"}
|
package/package.json
CHANGED
package/spec/grammar.md
CHANGED
|
@@ -368,6 +368,7 @@ scale-field = 'mode' ':' ('auto' | 'fixed' | 'config')
|
|
|
368
368
|
|
|
369
369
|
| Field | Type | Required | Default | Description |
|
|
370
370
|
|-------|------|----------|---------|-------------|
|
|
371
|
+
| `file` | string | no | -- | Project-relative path of the hand-written file holding this node's internals. Bindings reference it and never generate or overwrite it (V97). `import` sets it on every file it did not generate, so a hand-built system comes in without losing anything. |
|
|
371
372
|
| `role` | identifier | no | -- | Maps to a role defined in the `roles` block |
|
|
372
373
|
| `model` | model-id | yes | -- | LLM model identifier (e.g., `opus`, `gpt-4o`, `gemini-pro`) |
|
|
373
374
|
| `permissions` | perm-enum | no | `autonomous` | Permission mode |
|
|
@@ -1088,7 +1089,7 @@ Environment blocks have no fixed schema -- fields are identifier/string key-valu
|
|
|
1088
1089
|
```ebnf
|
|
1089
1090
|
triggers = 'triggers' '{' command-decl* '}'
|
|
1090
1091
|
command-decl = 'command' identifier '{' command-fields '}'
|
|
1091
|
-
command-fields = 'pattern' ':' string ('argument' ':' template-var)?
|
|
1092
|
+
command-fields = 'pattern' ':' string ('argument' ':' template-var)? ('file' ':' string)?
|
|
1092
1093
|
```
|
|
1093
1094
|
|
|
1094
1095
|
```agenttopology
|
|
@@ -1108,6 +1109,7 @@ triggers {
|
|
|
1108
1109
|
|-------|------|----------|---------|
|
|
1109
1110
|
| `pattern` | string | yes | -- |
|
|
1110
1111
|
| `argument` | template-var | no | -- |
|
|
1112
|
+
| `file` | string | no | -- |
|
|
1111
1113
|
|
|
1112
1114
|
---
|
|
1113
1115
|
|
|
@@ -1117,9 +1119,12 @@ triggers {
|
|
|
1117
1119
|
hooks = 'hooks' '{' hook-decl* '}'
|
|
1118
1120
|
hook-decl = 'hook' identifier '{' hook-fields '}'
|
|
1119
1121
|
hook-fields = ('on' ':' hook-event | 'matcher' ':' string | 'run' ':' string
|
|
1120
|
-
| 'type' ':' hook-type | 'timeout' ':' number)*
|
|
1121
|
-
hook-event = <universal-event> | <platform-event>
|
|
1122
|
-
hook-type = 'command' | 'prompt'
|
|
1122
|
+
| 'type' ':' hook-type | 'flag' ':' env-name | 'timeout' ':' number)*
|
|
1123
|
+
hook-event = <universal-event> | <platform-event> | <engine-event>
|
|
1124
|
+
hook-type = 'command' | 'prompt' | 'mod'
|
|
1125
|
+
engine-event = 'tool.call' | 'prompt.submit' | 'prompt.context' | 'session.start'
|
|
1126
|
+
| 'session.end' | 'model.complete' | 'message.received'
|
|
1127
|
+
|
|
1123
1128
|
```
|
|
1124
1129
|
|
|
1125
1130
|
**Universal hook events** -- these are defined by the spec and must be supported by all bindings:
|
|
@@ -1170,8 +1175,14 @@ hooks {
|
|
|
1170
1175
|
| `matcher` | string | no | -- |
|
|
1171
1176
|
| `run` | string | yes | -- |
|
|
1172
1177
|
| `type` | hook-type | no | `command` |
|
|
1178
|
+
| `flag` | env-name | no (mod only) | -- |
|
|
1173
1179
|
| `timeout` | number | no | `600` |
|
|
1174
1180
|
|
|
1181
|
+
A `type: mod` hook is a TypeScript module loaded inside the engine (Claude
|
|
1182
|
+
Code function hooks). Its `on:` is an `engine-event` (V95); a command or
|
|
1183
|
+
prompt hook takes a PascalCase event. `flag:` names the env variable that
|
|
1184
|
+
switches the Mod on. Fields are one per line (V90).
|
|
1185
|
+
|
|
1175
1186
|
---
|
|
1176
1187
|
|
|
1177
1188
|
### 4.17 `settings`
|
|
@@ -1351,6 +1362,10 @@ agent processor {
|
|
|
1351
1362
|
|
|
1352
1363
|
---
|
|
1353
1364
|
|
|
1365
|
+
### 4.20a `file:` — hand-written internals
|
|
1366
|
+
|
|
1367
|
+
Any node (`agent`, `group`, `human`, ...), any `skill` and any trigger `command` may carry `file: "<project-relative path>"`. It says: the structure is described here, the internals live in that file, and they are the author's. A binding never generates or overwrites a file so marked; for a skill it leaves the whole skill folder alone, for a group its skill and runtime folder too. Gates and hooks still wire to the node by name. `agentopology import` sets `file:` on every file it finds that no scaffold manifest lists as generated, which is what makes import followed by scaffold lossless.
|
|
1368
|
+
|
|
1354
1369
|
### 4.21 `skill` (declarations)
|
|
1355
1370
|
|
|
1356
1371
|
Topology-level skill declarations. Each `skill` block declares a self-contained application that bundles executable scripts, domain knowledge, reference docs, and instructions into a coherent capability. Agents load skills via their `skills` field.
|
|
@@ -1394,6 +1409,7 @@ skill classification {
|
|
|
1394
1409
|
|
|
1395
1410
|
| Field | Type | Required | Default |
|
|
1396
1411
|
|-------|------|----------|---------|
|
|
1412
|
+
| `file` | string | no | -- |
|
|
1397
1413
|
| `description` | string | no | -- |
|
|
1398
1414
|
| `scripts` | name-list | no | `[]` |
|
|
1399
1415
|
| `domains` | path-list | no | `[]` |
|
package/spec/testing.md
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
# Testing spec: what the suite proves
|
|
2
|
+
|
|
3
|
+
Every guarantee has an id. A test carries that id in its name (`[G3] ...`), and
|
|
4
|
+
`src/__tests__/spec-testing-sync.test.ts` fails when an id here has no test, or
|
|
5
|
+
a test names an id that isn't here. Open findings are listed as `it.todo` in
|
|
6
|
+
`src/__tests__/open-findings.test.ts`, so the suite shows what is not yet
|
|
7
|
+
guaranteed instead of hiding it.
|
|
8
|
+
|
|
9
|
+
## How to run
|
|
10
|
+
|
|
11
|
+
| Suite | Command | Needs |
|
|
12
|
+
|---|---|---|
|
|
13
|
+
| Everything offline (unit, CLI, e2e) | `npx vitest run` | nothing; the build runs first (vitest globalSetup), so tests never see a stale `dist/` |
|
|
14
|
+
| Live Claude Code | `AT_LIVE=1 npx vitest run src/__tests__/live` | the `claude` CLI; one small haiku call per project; `AT_CLAUDE_BIN` overrides the binary |
|
|
15
|
+
|
|
16
|
+
Run the live suite before every release, and after any change to a binding.
|
|
17
|
+
|
|
18
|
+
## Guarantees
|
|
19
|
+
|
|
20
|
+
| Id | Guarantee | Where |
|
|
21
|
+
|---|---|---|
|
|
22
|
+
| G1 | The first scaffold keeps a file it did not create (conflict, kept unless `--force`) | e2e/scaffold-owns.test.ts |
|
|
23
|
+
| G2 | Scaffold never writes or deletes through a symlink, even with `--force` | e2e/scaffold-owns.test.ts |
|
|
24
|
+
| G3 | Re-scaffolding keeps the user's hooks, `ask`, `defaultMode` and other permission keys | e2e/scaffold-owns.test.ts |
|
|
25
|
+
| G4 | A second scaffold with no changes writes nothing | e2e/scaffold-owns.test.ts |
|
|
26
|
+
| G5 | `--dry-run` writes nothing | e2e/scaffold-owns.test.ts |
|
|
27
|
+
| G6 | Prose in a gate's `run` fails validate (V96) and scaffold, and nothing is written | e2e/scaffold-owns.test.ts |
|
|
28
|
+
| G7 | An edited file that scaffold owns is kept on the next run | e2e/scaffold-owns.test.ts |
|
|
29
|
+
| G8 | `--prune` removes untouched leftovers and keeps edited ones | e2e/scaffold-owns.test.ts |
|
|
30
|
+
| G9 | Two topologies in one project keep separate manifests | e2e/scaffold-owns.test.ts |
|
|
31
|
+
| G10 | No `${…}` reference or `#`-key reaches settings `env` (Claude Code applies env literally) | e2e/scaffold-owns.test.ts |
|
|
32
|
+
| G11 | An unsafe generated path aborts the run before any file is written | scaffold/__tests__/safety.test.ts |
|
|
33
|
+
| G12 | A second scaffold of an imported project changes nothing | e2e/roundtrip.test.ts |
|
|
34
|
+
| G13 | An agent's `extensions` never leak into project-wide settings (only a topology-level `extensions` block is top-level) | e2e/roundtrip.test.ts |
|
|
35
|
+
| G14 | An imported hook and its compiled form (`$CLAUDE_PROJECT_DIR`) merge as one hook, not two | e2e/roundtrip.test.ts |
|
|
36
|
+
| G15 | V97 refuses a `file:` outside the project | e2e/roundtrip.test.ts |
|
|
37
|
+
| G16 | Scaffold names every hand-written `file:` the project lacks | e2e/roundtrip.test.ts |
|
|
38
|
+
| G17 | V11 does not demand a flow path for an on-demand (`invocation: manual`) agent | e2e/roundtrip.test.ts |
|
|
39
|
+
| R1 | Import then scaffold keeps every hand-built file (was: 37 of 72 missing) | e2e/roundtrip.test.ts |
|
|
40
|
+
| R2 | Import then scaffold leaves every hand-built file byte-identical, settings.json included (was: 2,957 lines cut to 1,706) | e2e/roundtrip.test.ts |
|
|
41
|
+
| R3 | The imported .at validates with no errors (was: 22) | e2e/roundtrip.test.ts |
|
|
42
|
+
| R4 | Import keeps frontmatter the language has no field for, comma-string lists, and the real `permissions` block | e2e/roundtrip.test.ts |
|
|
43
|
+
| A4 | Agents, groups, skills and commands found on disk are imported with `file:` and never generated | e2e/roundtrip.test.ts |
|
|
44
|
+
| F3 | `--allow-invalid` compiles despite validation errors; `--force` only overwrites kept files | e2e/roundtrip.test.ts |
|
|
45
|
+
| C5 | A hook's own script is created only when missing: never overwritten (even with `--force`), reported or claimed | e2e/roundtrip.test.ts |
|
|
46
|
+
| L2 | Real Claude Code loads a hand-built project after import then scaffold | live/claude-code.live.test.ts |
|
|
47
|
+
| L1 | Real Claude Code loads every scaffolded example: every agent, skill and command registers, and the session succeeds | live/claude-code.live.test.ts |
|
|
48
|
+
|
|
49
|
+
## Open findings (not yet guaranteed)
|
|
50
|
+
|
|
51
|
+
Each is an `it.todo` with the same id. When one is fixed, its todo becomes a
|
|
52
|
+
real test and the row moves to Guarantees. Source: the compile audit,
|
|
53
|
+
2026-10-28/29 (plan page and `.history/2026-10-28-content-harness-gaps.md`).
|
|
54
|
+
|
|
55
|
+
| Id | Finding | Phase |
|
|
56
|
+
|---|---|---|
|
|
57
|
+
| N11 | sync pulls generated prose back into the .at, so the prompt grows each cycle | 2 |
|
|
58
|
+
| N12 | A skill `prompt: "path"` emits `See: path`; the instructions never reach Claude | 2 |
|
|
59
|
+
| A3 | `kind: external` actions ignore `commands:` and emit a TODO stub | 3 |
|
|
60
|
+
| A3b | Tools with a real `script:` get stub copies | 3 |
|
|
61
|
+
| B4 | Schedule scripts call the wrong action path; `every:` becomes a commented-out cron line | 3 |
|
|
62
|
+
| H1 | Human nodes compile to frontmatter-less AGENT.md files that Claude Code ignores; they should be an approval step | 3 |
|
|
63
|
+
| N4 | `.mcp.json` drops `type`, so a url server is skipped | 3 |
|
|
64
|
+
| N5 | `type: prompt` hooks are emitted as commands | 3 |
|
|
65
|
+
| N6 | Universal events (AgentStop, ToolUse, Error) are emitted unmapped, so the hook never fires | 3 |
|
|
66
|
+
| N7 | MCP tool names: whole-server and dotted names mis-converted; permissions not converted | 3 |
|
|
67
|
+
| N8 | V27 accepts `confirm` and `bypass`, emitted as invalid `permissionMode` | 3 |
|
|
68
|
+
| N9 | A hook matcher with a regex breaks the agent file's YAML | 3 |
|
|
69
|
+
| N10 | `invocation: manual` drops the description, so the agent is not registered | 3 |
|
|
70
|
+
| N14 | `settings.ask` is parsed but never emitted | 3 |
|
|
71
|
+
| N16 | Model ids are not checked per target | 3 |
|
|
72
|
+
| N17 | Unquoted YAML scalars change type (`yes` becomes `true`) | 3 |
|
|
73
|
+
| N18 | No reference checks for `skills:`, `mcp-servers:`, skill `agent:` | 3 |
|
|
74
|
+
| N19 | Hook stubs carry the date, so output is not byte-stable | 3 |
|
|
75
|
+
| C1 | `scaffold --dry-run` says settings.json and .mcp.json would be "config merged" but does not show the diff (content session, 2026-10-29) | 3 |
|
|
76
|
+
| C2 | Scaffold adds `.claude/CLAUDE.md`, which competes with a project's root CLAUDE.md (content session, 2026-10-29) | 3 |
|
|
77
|
+
| C3 | Run-line parsing takes placeholders and file arguments as scripts (`SLUG`, `frames-critic.json`) and plans stubs for them (content session, 2026-10-29) | 3 |
|
|
78
|
+
| C4 | A gate whose `after:` is an action or a human compiles to no enforceable hook (10 gates in content-harness) | 3 |
|
|
79
|
+
| B5 | An agent's permissions read as per-agent grants; Claude Code allow rules are session-wide | 4 |
|
|
80
|
+
| F1 | Missing first-class fields: agent effort, initialPrompt, omitClaudeMd, cache TTL, color; skill when_to_use, arguments, paths, shell | 4 |
|
|
81
|
+
| F2 | Hooks as a typed union (http, mcp_tool, agent; once, async, if) | 4 |
|
package/spec/validation.md
CHANGED
|
@@ -665,7 +665,7 @@ agent researcher {
|
|
|
665
665
|
|
|
666
666
|
## Summary Table
|
|
667
667
|
|
|
668
|
-
All
|
|
668
|
+
All 97 rules, generated from `src/parser/validator.ts` so the spec cannot drift
|
|
669
669
|
from the implementation. Rules V8, V12, V23, V24, V89 and V90 are collected at
|
|
670
670
|
**parse time** — the misuse they catch leaves no trace in the AST — and surfaced
|
|
671
671
|
through the validator like any other rule.
|
|
@@ -684,7 +684,7 @@ through the validator like any other rule.
|
|
|
684
684
|
| V8 | error/warning | Import references should resolve (warning only -- we cannot check the filesystem) |
|
|
685
685
|
| V9 | error/warning | Every action referenced in flow must appear in orchestrator.handles |
|
|
686
686
|
| V10 | error/warning | Prompt content should not be empty if a prompt block is declared |
|
|
687
|
-
| V11 | error | If agent A writes X and agent B reads X, a path A -> B must exist in flow |
|
|
687
|
+
| V11 | error | If agent A writes X and agent B reads X, a path A -> B must exist in flow — unless either is on demand (`invocation: manual`), which has no flow by definition |
|
|
688
688
|
| V12 | error | Edge attribute order must be [when, max, per] |
|
|
689
689
|
| V13 | error | Gate `after` and `before` must reference declared nodes |
|
|
690
690
|
| V14 | error | `tools` and `disallowed-tools` cannot both appear on the same agent |
|
|
@@ -767,6 +767,10 @@ through the validator like any other rule.
|
|
|
767
767
|
| V91 | error | A required field must not be satisfied by a parser-injected placeholder — `meta.version` and `orchestrator.model` are required, and their sentinels (`0.0.0`, `unknown`) satisfied every downstream check |
|
|
768
768
|
| V92 | error | An edge's attributes go in ONE bracket, comma-separated — `[when ...] [max N]` produced a condition string containing brackets, silently |
|
|
769
769
|
| V93 | warning | An edge between two agents that both declare paths should declare a handoff — `writer.writes \| reader.reads` empty means the receiver runs after the sender with none of its output |
|
|
770
|
+
| V94 | error | A hook's `type` is `command`, `prompt` or `mod`; `flag:` belongs only to a mod and is an env variable name — `type: mod` passed silently and was scaffolded as a bash command |
|
|
771
|
+
| V95 | error | A hook's `on:` must fit its type — a mod takes a known engine event (`tool.call`, `prompt.submit`; five more seen in the engine warn as unproven), a command/prompt hook a PascalCase event |
|
|
772
|
+
| V96 | error | A gate or hook `run` must be a command, not prose — a sentence there compiled to junk script files (`E;`, `fail:`) and crashed scaffold with EISDIR; the explanation belongs in `description` |
|
|
773
|
+
| V97 | error | A node, skill or command `file:` must be a project-relative path (no `..`, not absolute, safe names) — it marks hand-written internals scaffold never writes, so it must be a path scaffold can honour |
|
|
770
774
|
|
|
771
775
|
> Sections above document the first 35 rules with worked examples. The rest are
|
|
772
776
|
> single-line entries here plus their doc comment in the source. Adding an
|