@event4u/agent-config 9.10.0 → 9.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.
Files changed (142) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/CHANGELOG.md +111 -0
  3. package/README.md +20 -16
  4. package/agents/templates/.ai-council.yml.example +481 -0
  5. package/agents/templates/.ai-video.xml.example +247 -0
  6. package/dist/agent-src/commands/fix/ci.md +29 -0
  7. package/dist/agent-src/commands/pr/create.md +60 -0
  8. package/dist/agent-src/contexts/authority/kernel-rule-edits.md +18 -2
  9. package/dist/agent-src/rules/design-fidelity.md +2 -2
  10. package/dist/agent-src/skills/ai-code-blindspots/SKILL.md +1 -0
  11. package/dist/agent-src/skills/design-intelligence/SKILL.md +27 -1
  12. package/dist/agent-src/skills/design-intelligence/data/font-pairings-reference.csv +74 -74
  13. package/dist/agent-src/skills/design-intelligence/data/manifest.json +2 -0
  14. package/dist/agent-src/skills/design-tokens/scripts/tokens.ts +0 -7
  15. package/dist/agent-src/skills/existing-ui-audit/SKILL.md +15 -2
  16. package/dist/agent-src/skills/fe-design/SKILL.md +10 -0
  17. package/dist/agent-src/skills/typography-system/SKILL.md +55 -11
  18. package/dist/agent-src/skills/ui-apply-generic/SKILL.md +180 -0
  19. package/dist/agent-src/templates/agents/agent-project-settings.example.yml +1 -1
  20. package/dist/agent-src/templates/scripts/work_engine/directives/ui/apply.ts +34 -30
  21. package/dist/agent-src/templates/scripts/work_engine/directives/ui/design.ts +88 -33
  22. package/dist/agent-src/templates/scripts/work_engine/directives/ui/polish.ts +23 -0
  23. package/dist/agent-src/templates/scripts/work_engine/directives/ui/review.ts +24 -1
  24. package/dist/agent-src/templates/scripts/work_engine/directives/ui/stack_bundles.ts +332 -0
  25. package/dist/agent-src/templates/scripts/work_engine/stack/detect.ts +449 -11
  26. package/dist/agent-src/templates/scripts/work_engine/state.ts +21 -4
  27. package/dist/cli/initRouting.js +74 -11
  28. package/dist/cli/initRouting.js.map +1 -1
  29. package/dist/cli/main.js +14 -3
  30. package/dist/cli/main.js.map +1 -1
  31. package/dist/cli-delegate/chunk-523HCFYO.js +90 -0
  32. package/dist/cli-delegate/chunk-736JCWLM.js +1104 -0
  33. package/dist/cli-delegate/chunk-7HQ52DHU.js +74 -0
  34. package/dist/cli-delegate/chunk-A3HJ6NTI.js +1084 -0
  35. package/dist/cli-delegate/chunk-EJYIGZ3T.js +125 -0
  36. package/dist/cli-delegate/chunk-FTAISGDQ.js +117 -0
  37. package/dist/cli-delegate/chunk-GME3Q44L.js +82 -0
  38. package/dist/cli-delegate/chunk-GRRPEPRN.js +336 -0
  39. package/dist/cli-delegate/chunk-HJ6DAJHR.js +502 -0
  40. package/dist/cli-delegate/chunk-HYWSRNUX.js +179 -0
  41. package/dist/cli-delegate/chunk-J55WI3RR.js +47 -0
  42. package/dist/cli-delegate/chunk-MCJYCQPF.js +35 -0
  43. package/dist/cli-delegate/chunk-NDJLNC6Q.js +169 -0
  44. package/dist/cli-delegate/chunk-OMIVVCG2.js +26 -0
  45. package/dist/cli-delegate/chunk-OY53J6II.js +7336 -0
  46. package/dist/cli-delegate/chunk-QFKQLQ7X.js +10835 -0
  47. package/dist/cli-delegate/chunk-TEGJU2JX.js +6908 -0
  48. package/dist/cli-delegate/chunk-TJIAM5FW.js +133 -0
  49. package/dist/cli-delegate/chunk-XX6TOPD7.js +715 -0
  50. package/dist/cli-delegate/cmd_analyze_session.js +294 -0
  51. package/dist/cli-delegate/cmd_conformance.js +643 -0
  52. package/dist/cli-delegate/cmd_converge.js +326 -0
  53. package/dist/cli-delegate/cmd_doctor.js +142 -0
  54. package/dist/cli-delegate/cmd_explain.js +2576 -0
  55. package/dist/cli-delegate/cmd_export.js +298 -0
  56. package/dist/cli-delegate/cmd_fleet.js +333 -0
  57. package/dist/cli-delegate/cmd_memory_get.js +3878 -0
  58. package/dist/cli-delegate/cmd_migrate.js +11 -0
  59. package/dist/cli-delegate/cmd_preflight.js +153 -0
  60. package/dist/cli-delegate/cmd_prune.js +446 -0
  61. package/dist/cli-delegate/cmd_refresh.js +28 -0
  62. package/dist/cli-delegate/cmd_settings_check.js +574 -0
  63. package/dist/cli-delegate/cmd_settings_migrate.js +225 -0
  64. package/dist/cli-delegate/cmd_sync.js +266 -0
  65. package/dist/cli-delegate/cmd_uninstall.js +657 -0
  66. package/dist/cli-delegate/cmd_update.js +425 -0
  67. package/dist/cli-delegate/cmd_upgrade.js +444 -0
  68. package/dist/cli-delegate/cmd_validate.js +307 -0
  69. package/dist/cli-delegate/cmd_versions.js +370 -0
  70. package/dist/discovery/deprecation-report.md +1 -1
  71. package/dist/discovery/discovery-manifest.json +45 -16
  72. package/dist/discovery/discovery-manifest.json.sha256 +1 -1
  73. package/dist/discovery/discovery-manifest.summary.md +3 -3
  74. package/dist/discovery/orphan-report.md +1 -1
  75. package/dist/discovery/packs.json +13 -7
  76. package/dist/discovery/trust-report.md +2 -2
  77. package/dist/discovery/workspaces.json +6 -4
  78. package/dist/install/emit_host_rules_cli.js +2 -1
  79. package/dist/install/emit_host_rules_cli.js.map +1 -1
  80. package/dist/install/install.mjs +634 -409
  81. package/dist/install/ruleInScope.js +123 -0
  82. package/dist/install/ruleInScope.js.map +1 -0
  83. package/dist/install/rule_scope.js +7 -3
  84. package/dist/install/rule_scope.js.map +1 -1
  85. package/dist/install/toolDetection.js +40 -12
  86. package/dist/install/toolDetection.js.map +1 -1
  87. package/dist/install/wizard-plan.js +12 -3
  88. package/dist/install/wizard-plan.js.map +1 -1
  89. package/dist/mcp/registry-manifest.json +3 -3
  90. package/dist/mcp/server.json +2 -2
  91. package/dist/mcp/server.mjs +1553 -2728
  92. package/dist/router.json +1 -1
  93. package/dist/scripts/condense.js +6 -22
  94. package/dist/scripts/condense.js.map +1 -1
  95. package/docs/guidelines/design-fidelity-mechanics.md +14 -0
  96. package/package.json +4 -2
  97. package/src/agent-src/templates/scripts/work_engine/directives/ui/apply.ts +34 -30
  98. package/src/agent-src/templates/scripts/work_engine/directives/ui/design.ts +88 -33
  99. package/src/agent-src/templates/scripts/work_engine/directives/ui/polish.ts +23 -0
  100. package/src/agent-src/templates/scripts/work_engine/directives/ui/review.ts +24 -1
  101. package/src/agent-src/templates/scripts/work_engine/directives/ui/stack_bundles.ts +332 -0
  102. package/src/agent-src/templates/scripts/work_engine/stack/detect.ts +449 -11
  103. package/src/agent-src/templates/scripts/work_engine/state.ts +21 -4
  104. package/src/config/discovery/packs.yml +7 -0
  105. package/src/config/evaluator-budgets.json +1 -1
  106. package/src/config/pack-size-budget.json +27 -0
  107. package/src/install/emit_host_rules_cli.ts +2 -1
  108. package/src/install/ruleInScope.ts +133 -0
  109. package/src/install/rule_scope.ts +7 -3
  110. package/src/install/toolDetection.ts +39 -8
  111. package/src/install/wizard-plan.ts +13 -3
  112. package/src/scripts/_cli/cmd_conformance.ts +2 -1
  113. package/src/scripts/_cli/cmd_converge.ts +2 -1
  114. package/src/scripts/_cli/cmd_doctor.ts +214 -13
  115. package/src/scripts/_cli/cmd_export.ts +2 -1
  116. package/src/scripts/_cli/cmd_fleet.ts +2 -1
  117. package/src/scripts/_cli/cmd_migrate.ts +2 -1
  118. package/src/scripts/_cli/cmd_preflight.ts +2 -1
  119. package/src/scripts/_cli/cmd_refresh.ts +2 -1
  120. package/src/scripts/_cli/cmd_update.ts +2 -1
  121. package/src/scripts/_cli/cmd_upgrade.ts +2 -1
  122. package/src/scripts/_cli/cmd_versions.ts +2 -1
  123. package/src/scripts/_cli/detection_report.ts +480 -0
  124. package/src/scripts/_dispatch.bash +52 -14
  125. package/src/scripts/_lib/changelog_eras.ts +103 -9
  126. package/src/scripts/_lib/environment_detector.ts +441 -0
  127. package/src/scripts/_lib/global_deploy_inventory.ts +38 -2
  128. package/src/scripts/_lib/package_root.ts +72 -0
  129. package/src/scripts/ai_council/config.ts +15 -7
  130. package/src/scripts/ai_council/modes.ts +68 -2
  131. package/src/scripts/ai_council/transport_resolver.ts +331 -0
  132. package/src/scripts/check_bundle_path_leakage.ts +10 -4
  133. package/src/scripts/check_dependency_floors.ts +153 -0
  134. package/src/scripts/check_installer_import_purity.ts +295 -0
  135. package/src/scripts/check_pack_size.ts +188 -0
  136. package/src/scripts/condense.ts +7 -28
  137. package/src/scripts/council_cli.ts +6 -2
  138. package/src/scripts/evaluator_umbrella.sh +34 -1
  139. package/src/scripts/install-hooks.sh +36 -4
  140. package/src/scripts/install.ts +210 -5
  141. package/src/scripts/lint_eval_fixture_citations.ts +113 -0
  142. package/src/scripts/lint_ui_stack_bundles.ts +201 -0
@@ -0,0 +1,1084 @@
1
+ import { createRequire as __acCreateRequire } from 'node:module'; const require = globalThis.require ?? __acCreateRequire(import.meta.url);
2
+ import {
3
+ write_target
4
+ } from "./chunk-NDJLNC6Q.js";
5
+ import {
6
+ require_dist
7
+ } from "./chunk-OY53J6II.js";
8
+ import {
9
+ __export,
10
+ __toESM
11
+ } from "./chunk-J55WI3RR.js";
12
+
13
+ // src/scripts/_lib/fs_atomic.ts
14
+ import fs from "node:fs";
15
+ import path from "node:path";
16
+ import { randomBytes } from "node:crypto";
17
+ function _normalize_encoding(encoding) {
18
+ const compact = encoding.toLowerCase().replace(/[-_\s]/g, "");
19
+ const candidates = [encoding, compact];
20
+ if (compact === "latin1" || compact === "iso88591") candidates.push("latin1");
21
+ if (compact === "utf8") candidates.push("utf8");
22
+ if (compact === "utf16le" || compact === "utf16") candidates.push("utf16le");
23
+ if (compact === "usascii") candidates.push("ascii");
24
+ for (const c of candidates) {
25
+ if (Buffer.isEncoding(c)) return c;
26
+ }
27
+ throw new Error(`unknown encoding: ${encoding}`);
28
+ }
29
+ function write_atomic(p, data, options = {}) {
30
+ const encoding = options.encoding ?? "utf-8";
31
+ const target = path.normalize(p);
32
+ const parent = path.dirname(target);
33
+ fs.mkdirSync(parent, { recursive: true });
34
+ let payload;
35
+ if (typeof data === "string") {
36
+ payload = Buffer.from(data, _normalize_encoding(encoding));
37
+ } else if (data instanceof Uint8Array) {
38
+ payload = Buffer.from(data);
39
+ } else {
40
+ throw new TypeError(
41
+ `write_atomic: data must be str or bytes, got ${typeof data}`
42
+ );
43
+ }
44
+ let fd = null;
45
+ let tmp_path = "";
46
+ for (let attempt = 0; attempt < 32; attempt += 1) {
47
+ tmp_path = path.join(
48
+ parent,
49
+ `.${path.basename(target)}.tmp.${randomBytes(6).toString("hex")}`
50
+ );
51
+ try {
52
+ fd = fs.openSync(tmp_path, "wx", 384);
53
+ break;
54
+ } catch (err) {
55
+ if (err.code === "EEXIST") continue;
56
+ throw err;
57
+ }
58
+ }
59
+ if (fd === null) {
60
+ throw new Error("write_atomic: could not create a unique temp file");
61
+ }
62
+ let closed = false;
63
+ try {
64
+ let offset = 0;
65
+ while (offset < payload.length) {
66
+ offset += fs.writeSync(fd, payload, offset, payload.length - offset);
67
+ }
68
+ try {
69
+ fs.fsyncSync(fd);
70
+ } catch {
71
+ }
72
+ fs.closeSync(fd);
73
+ closed = true;
74
+ fs.renameSync(tmp_path, target);
75
+ } catch (err) {
76
+ if (!closed) {
77
+ try {
78
+ fs.closeSync(fd);
79
+ } catch {
80
+ }
81
+ }
82
+ try {
83
+ fs.unlinkSync(tmp_path);
84
+ } catch {
85
+ }
86
+ throw err;
87
+ }
88
+ _fsync_dir(parent);
89
+ return target;
90
+ }
91
+ function _fsync_dir(directory) {
92
+ let dir_fd;
93
+ try {
94
+ dir_fd = fs.openSync(directory, fs.constants.O_RDONLY);
95
+ } catch {
96
+ return;
97
+ }
98
+ try {
99
+ try {
100
+ fs.fsyncSync(dir_fd);
101
+ } catch {
102
+ }
103
+ } finally {
104
+ fs.closeSync(dir_fd);
105
+ }
106
+ }
107
+
108
+ // src/scripts/_lib/installed_tools.ts
109
+ import * as fs2 from "node:fs";
110
+ import * as os from "node:os";
111
+ import * as fsPath from "node:path";
112
+ var MANIFEST_ENV = "AGENT_CONFIG_INSTALLED_TOOLS";
113
+ var DEFAULT_MANIFEST_RELATIVE = fsPath.join("agents", "installed-tools.lock");
114
+ var SCHEMA_VERSION = 2;
115
+ var SCHEMA_VERSIONS_SUPPORTED = [1, 2];
116
+ var _VALID_SCOPES = ["global", "project"];
117
+ var DEFAULT_DEPLOY_ROOTS = [
118
+ ".augment/rules",
119
+ ".augment/skills",
120
+ ".augment/commands",
121
+ ".cursor/rules",
122
+ ".claude/skills",
123
+ ".claude/commands",
124
+ ".clinerules",
125
+ ".windsurf/rules"
126
+ ];
127
+ function expanduser(p) {
128
+ if (p === "~") {
129
+ return os.homedir();
130
+ }
131
+ if (p.startsWith("~/") || process.platform === "win32" && p.startsWith("~\\")) {
132
+ return fsPath.join(os.homedir(), p.slice(2));
133
+ }
134
+ return p;
135
+ }
136
+ function manifest_path(project_root, env) {
137
+ const env_map = env ?? process.env;
138
+ const override = env_map[MANIFEST_ENV];
139
+ if (override) {
140
+ return expanduser(override);
141
+ }
142
+ return fsPath.join(project_root, DEFAULT_MANIFEST_RELATIVE);
143
+ }
144
+ var _TOP_KEY_RE = /^([A-Za-z_][A-Za-z0-9_]*)\s*:\s*"?([^"\n]*?)"?\s*$/;
145
+ var _LIST_DASH_RE = /^\s*-\s*(.+?)\s*$/;
146
+ var _INDENT_KEY_RE = /^\s+([A-Za-z_][A-Za-z0-9_]*)\s*:\s*"?([^"\n]*?)"?\s*$/;
147
+ function read_manifest(path4) {
148
+ let text;
149
+ try {
150
+ text = require_read_text(path4);
151
+ } catch {
152
+ return null;
153
+ }
154
+ const data = _parse_manual(text);
155
+ return _normalise_v2_shape(data);
156
+ }
157
+ function require_read_text(path4) {
158
+ return fs2.readFileSync(path4, { encoding: "utf-8" });
159
+ }
160
+ function _normalise_v2_shape(data) {
161
+ if (data["tools"] === void 0 || data["tools"] === null) {
162
+ data["tools"] = [];
163
+ }
164
+ if (data["deploy_roots"] === void 0 || data["deploy_roots"] === null) {
165
+ data["deploy_roots"] = [];
166
+ }
167
+ const tools = data["tools"];
168
+ for (const tool of tools) {
169
+ if (typeof tool !== "object" || tool === null) {
170
+ continue;
171
+ }
172
+ const t = tool;
173
+ if (t["files"] === void 0 || t["files"] === null) {
174
+ t["files"] = [];
175
+ }
176
+ if (t["merged_keys"] === void 0 || t["merged_keys"] === null) {
177
+ t["merged_keys"] = [];
178
+ }
179
+ }
180
+ return data;
181
+ }
182
+ function _parse_manual(text) {
183
+ const data = { tools: [] };
184
+ const tools = data["tools"];
185
+ let in_tools = false;
186
+ let current = null;
187
+ let skip_until_outdent = false;
188
+ for (const raw of splitlines(text)) {
189
+ const stripped = raw.trim();
190
+ if (!stripped || stripped.startsWith("#")) {
191
+ continue;
192
+ }
193
+ if (stripped === "tools:") {
194
+ in_tools = true;
195
+ current = null;
196
+ skip_until_outdent = false;
197
+ continue;
198
+ }
199
+ if (in_tools) {
200
+ const indent = raw.length - lstrip_spaces(raw).length;
201
+ if (skip_until_outdent && indent > 4) {
202
+ continue;
203
+ }
204
+ skip_until_outdent = false;
205
+ const m = _LIST_DASH_RE.exec(raw);
206
+ if (m && indent === 2) {
207
+ const first = m[1];
208
+ current = {};
209
+ tools.push(current);
210
+ const inline = _TOP_KEY_RE.exec(first);
211
+ if (inline) {
212
+ current[inline[1]] = inline[2];
213
+ }
214
+ continue;
215
+ }
216
+ const mk = _INDENT_KEY_RE.exec(raw);
217
+ if (mk && current !== null && indent === 4) {
218
+ const key = mk[1];
219
+ const val = mk[2];
220
+ if ((key === "files" || key === "merged_keys") && !val) {
221
+ skip_until_outdent = true;
222
+ continue;
223
+ }
224
+ current[key] = val;
225
+ continue;
226
+ }
227
+ }
228
+ const m_top = _TOP_KEY_RE.exec(raw);
229
+ if (m_top) {
230
+ const key = m_top[1];
231
+ const value = m_top[2];
232
+ if (key === "deploy_roots" && !value) {
233
+ in_tools = false;
234
+ current = null;
235
+ skip_until_outdent = true;
236
+ continue;
237
+ }
238
+ if (key === "schema_version") {
239
+ const parsed = parse_int_strict(value);
240
+ data[key] = parsed === null ? value : parsed;
241
+ } else {
242
+ data[key] = value;
243
+ }
244
+ in_tools = false;
245
+ current = null;
246
+ skip_until_outdent = false;
247
+ }
248
+ }
249
+ return data;
250
+ }
251
+ function splitlines(text) {
252
+ const parts = text.split("\n");
253
+ if (parts.length > 0 && parts[parts.length - 1] === "") {
254
+ parts.pop();
255
+ }
256
+ return parts;
257
+ }
258
+ function lstrip_spaces(s) {
259
+ let i = 0;
260
+ while (i < s.length && s[i] === " ") {
261
+ i += 1;
262
+ }
263
+ return s.slice(i);
264
+ }
265
+ function parse_int_strict(value) {
266
+ if (!/^[+-]?\d+$/.test(value.trim())) {
267
+ return null;
268
+ }
269
+ return Number.parseInt(value, 10);
270
+ }
271
+ function _render(version, tools, options = {}) {
272
+ const deploy_roots = options.deploy_roots ?? null;
273
+ const lines = [
274
+ `schema_version: ${SCHEMA_VERSION}`,
275
+ `agent_config_version: "${version}"`
276
+ ];
277
+ if (deploy_roots && deploy_roots.length > 0) {
278
+ lines.push("deploy_roots:");
279
+ for (const root of deploy_roots) {
280
+ lines.push(` - ${root}`);
281
+ }
282
+ }
283
+ lines.push("tools:");
284
+ for (const tool of tools) {
285
+ lines.push(` - name: ${String(tool["name"])}`);
286
+ lines.push(` scope: ${String(tool["scope"])}`);
287
+ lines.push(` bridge_marker: ${String(tool["bridge_marker"])}`);
288
+ lines.push(` installed_at: "${String(tool["installed_at"])}"`);
289
+ const status = tool["status"];
290
+ if (status) {
291
+ lines.push(` status: ${String(status)}`);
292
+ }
293
+ let files = tool["files"] ?? [];
294
+ if (files.length > 0) {
295
+ files = stable_sort(files, (f) => [String(f["path"])]);
296
+ lines.push(" files:");
297
+ for (const entry of files) {
298
+ lines.push(` - path: ${String(entry["path"])}`);
299
+ lines.push(` kind: ${String(entry["kind"])}`);
300
+ const sha = entry["sha256"];
301
+ if (sha === null || sha === void 0) {
302
+ lines.push(" sha256: null");
303
+ } else {
304
+ lines.push(` sha256: "${String(sha)}"`);
305
+ }
306
+ }
307
+ }
308
+ let merged = tool["merged_keys"] ?? [];
309
+ if (merged.length > 0) {
310
+ merged = stable_sort(merged, (e) => [
311
+ String(e["file"]),
312
+ String(e["json_pointer"])
313
+ ]);
314
+ lines.push(" merged_keys:");
315
+ for (const entry of merged) {
316
+ lines.push(` - file: ${String(entry["file"])}`);
317
+ lines.push(` json_pointer: "${String(entry["json_pointer"])}"`);
318
+ const vh = entry["value_hash"];
319
+ if (vh !== null && vh !== void 0) {
320
+ lines.push(` value_hash: "${String(vh)}"`);
321
+ }
322
+ }
323
+ }
324
+ }
325
+ return lines.join("\n") + "\n";
326
+ }
327
+ function stable_sort(items, key) {
328
+ return items.map((item, index) => ({ item, index, k: key(item) })).sort((a, b) => {
329
+ const len = Math.max(a.k.length, b.k.length);
330
+ for (let i = 0; i < len; i += 1) {
331
+ const av = a.k[i] ?? "";
332
+ const bv = b.k[i] ?? "";
333
+ if (av < bv) return -1;
334
+ if (av > bv) return 1;
335
+ }
336
+ return a.index - b.index;
337
+ }).map((entry) => entry.item);
338
+ }
339
+ function write_manifest(path4, version, tools, options = {}) {
340
+ const rendered = _render(version, tools, { deploy_roots: options.deploy_roots ?? null });
341
+ return write_atomic(path4, rendered);
342
+ }
343
+ var ScopeMismatchError = class extends Error {
344
+ name_;
345
+ recorded_scope;
346
+ new_scope;
347
+ constructor(name, recorded_scope, new_scope) {
348
+ super(
349
+ `tool '${name}' is committed as scope=${recorded_scope}; refusing to change it to scope=${new_scope} without --force`
350
+ );
351
+ this.name = "ScopeMismatchError";
352
+ this.name_ = name;
353
+ this.recorded_scope = recorded_scope;
354
+ this.new_scope = new_scope;
355
+ }
356
+ };
357
+ function upsert_tool(existing, options) {
358
+ const {
359
+ name,
360
+ scope,
361
+ bridge_marker,
362
+ installed_at = null,
363
+ force = false,
364
+ files = null,
365
+ merged_keys = null
366
+ } = options;
367
+ if (!_VALID_SCOPES.includes(scope)) {
368
+ throw new ValueError(`scope must be one of ${_VALID_SCOPES.join(",")}: '${scope}'`);
369
+ }
370
+ const stamp = installed_at || _today();
371
+ const _build = (prior = null) => {
372
+ const entry = {
373
+ name,
374
+ scope,
375
+ bridge_marker,
376
+ installed_at: stamp
377
+ };
378
+ if (files !== null) {
379
+ entry["files"] = [...files];
380
+ } else if (prior !== null && Array.isArray(prior["files"]) && prior["files"].length > 0) {
381
+ entry["files"] = [...prior["files"]];
382
+ }
383
+ if (merged_keys !== null) {
384
+ entry["merged_keys"] = [...merged_keys];
385
+ } else if (prior !== null && Array.isArray(prior["merged_keys"]) && prior["merged_keys"].length > 0) {
386
+ entry["merged_keys"] = [...prior["merged_keys"]];
387
+ }
388
+ return entry;
389
+ };
390
+ const result = [];
391
+ let found = false;
392
+ for (const entry of existing) {
393
+ if (entry["name"] === name) {
394
+ found = true;
395
+ const recorded = String(entry["scope"] ?? "");
396
+ if (recorded === scope) {
397
+ if (files === null && merged_keys === null) {
398
+ result.push(entry);
399
+ } else {
400
+ const refreshed = _build(entry);
401
+ refreshed["installed_at"] = entry["installed_at"] ?? stamp;
402
+ result.push(refreshed);
403
+ }
404
+ continue;
405
+ }
406
+ if (!force) {
407
+ throw new ScopeMismatchError(name, recorded, scope);
408
+ }
409
+ result.push(_build(entry));
410
+ continue;
411
+ }
412
+ result.push(entry);
413
+ }
414
+ if (!found) {
415
+ result.push(_build());
416
+ }
417
+ return result;
418
+ }
419
+ var ValueError = class extends Error {
420
+ constructor(message) {
421
+ super(message);
422
+ this.name = "ValueError";
423
+ }
424
+ };
425
+ function _today() {
426
+ return (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
427
+ }
428
+
429
+ // src/install/atomic.ts
430
+ import {
431
+ closeSync,
432
+ fsyncSync,
433
+ mkdirSync,
434
+ openSync,
435
+ readFileSync as readFileSync2,
436
+ renameSync,
437
+ unlinkSync,
438
+ writeSync
439
+ } from "node:fs";
440
+ import { dirname, join as join2 } from "node:path";
441
+ function atomicWriteFile(target, data, options = {}) {
442
+ const mode = options.mode ?? 420;
443
+ const parent = dirname(target);
444
+ mkdirSync(parent, { recursive: true });
445
+ const tmp = join2(parent, `.tmp.${process.pid}.${randSuffix()}`);
446
+ let fd = null;
447
+ try {
448
+ fd = openSync(tmp, "w", mode);
449
+ const buf = typeof data === "string" ? Buffer.from(data, "utf8") : data;
450
+ writeSync(fd, buf, 0, buf.length, 0);
451
+ fsyncSync(fd);
452
+ closeSync(fd);
453
+ fd = null;
454
+ renameSync(tmp, target);
455
+ } catch (err) {
456
+ if (fd !== null) {
457
+ try {
458
+ closeSync(fd);
459
+ } catch {
460
+ }
461
+ }
462
+ try {
463
+ unlinkSync(tmp);
464
+ } catch {
465
+ }
466
+ throw err;
467
+ }
468
+ }
469
+ function atomicAppendLine(target, line) {
470
+ let existing = "";
471
+ try {
472
+ existing = readFileSync2(target, "utf8");
473
+ } catch {
474
+ existing = "";
475
+ }
476
+ const sep2 = existing.length > 0 && !existing.endsWith("\n") ? "\n" : "";
477
+ atomicWriteFile(target, `${existing}${sep2}${line}
478
+ `);
479
+ }
480
+ function randSuffix() {
481
+ return Math.floor(Math.random() * 281474976710655).toString(16).padStart(12, "0");
482
+ }
483
+
484
+ // src/scripts/_lib/claude_settings_hooks.ts
485
+ var YAML = __toESM(require_dist(), 1);
486
+ import * as fs3 from "node:fs";
487
+ import * as path2 from "node:path";
488
+ function _yaml_parse(text) {
489
+ return YAML.parse(text);
490
+ }
491
+ var MANAGED_SIGNATURE = "dispatch:hook --platform claude";
492
+ var CorruptSettingsError = class extends Error {
493
+ constructor(file, cause) {
494
+ super(
495
+ `${file} exists but is not valid JSON (${cause}). Refusing to overwrite a user-owned settings file \u2014 fix or remove it, then re-run.`
496
+ );
497
+ this.name = "CorruptSettingsError";
498
+ }
499
+ };
500
+ var SettingsLockError = class extends Error {
501
+ constructor(lockPath) {
502
+ super(
503
+ `settings lock ${lockPath} is held by another process. Re-run when the concurrent install finishes (stale lock: delete the file).`
504
+ );
505
+ this.name = "SettingsLockError";
506
+ }
507
+ };
508
+ function build_claude_hook_matrix(manifest_path2) {
509
+ const raw = fs3.readFileSync(manifest_path2, "utf8");
510
+ const manifest = _yaml_parse(raw) ?? {};
511
+ const hook_spec = manifest["schema_version"] ?? 1;
512
+ const platforms = manifest["platforms"] ?? {};
513
+ const claude_events = (platforms["claude"] ?? {}) || {};
514
+ const aliasesAll = manifest["native_event_aliases"] ?? {};
515
+ const aliases = (aliasesAll["claude"] ?? {}) || {};
516
+ const ac_to_native = {};
517
+ for (const [native, ac] of Object.entries(aliases)) {
518
+ ac_to_native[String(ac)] = native;
519
+ }
520
+ const matrix = {};
521
+ for (const [ac_event, concerns] of Object.entries(claude_events)) {
522
+ if (!concerns || Array.isArray(concerns) && concerns.length === 0) continue;
523
+ const native = ac_to_native[ac_event];
524
+ if (native === void 0) continue;
525
+ matrix[native] = `BIN="$CLAUDE_PROJECT_DIR/agent-config"; [ -x "$BIN" ] || BIN=agent-config; command -v "$BIN" >/dev/null 2>&1 || exit 0; "$BIN" dispatch:hook --platform claude --event ${ac_event} --native-event ${native} --project-dir "$CLAUDE_PROJECT_DIR" --min-version ${String(hook_spec)}`;
526
+ }
527
+ return matrix;
528
+ }
529
+ function _is_managed_group(group) {
530
+ if (typeof group !== "object" || group === null || Array.isArray(group)) return false;
531
+ const hooks = group.hooks;
532
+ if (!Array.isArray(hooks)) return false;
533
+ return hooks.some(
534
+ (h) => typeof h === "object" && h !== null && typeof h.command === "string" && h.command.includes(MANAGED_SIGNATURE)
535
+ );
536
+ }
537
+ function _read_settings(settings_path) {
538
+ if (!fs3.existsSync(settings_path)) return {};
539
+ const raw = fs3.readFileSync(settings_path, "utf8");
540
+ if (raw.trim() === "") return {};
541
+ let parsed;
542
+ try {
543
+ parsed = JSON.parse(raw);
544
+ } catch (e) {
545
+ throw new CorruptSettingsError(settings_path, e.message);
546
+ }
547
+ if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
548
+ throw new CorruptSettingsError(settings_path, "top level is not an object");
549
+ }
550
+ return parsed;
551
+ }
552
+ function _with_lock(settings_path, fn) {
553
+ const lockPath = settings_path + ".agent-config.lock";
554
+ fs3.mkdirSync(path2.dirname(lockPath), { recursive: true });
555
+ let fd;
556
+ try {
557
+ fd = fs3.openSync(lockPath, "wx");
558
+ } catch {
559
+ throw new SettingsLockError(lockPath);
560
+ }
561
+ try {
562
+ return fn();
563
+ } finally {
564
+ fs3.closeSync(fd);
565
+ fs3.rmSync(lockPath, { force: true });
566
+ }
567
+ }
568
+ function ensure_managed_hooks(settings_path, matrix) {
569
+ return _with_lock(settings_path, () => {
570
+ const settings = _read_settings(settings_path);
571
+ const before = JSON.stringify(settings);
572
+ const hooks = (settings["hooks"] ?? {}) || {};
573
+ const touched = [];
574
+ for (const [native, command] of Object.entries(matrix)) {
575
+ const existing = Array.isArray(hooks[native]) ? hooks[native] : [];
576
+ const user_groups = existing.filter((g) => !_is_managed_group(g));
577
+ const managed_group = {
578
+ hooks: [{ type: "command", command }]
579
+ };
580
+ const next = [...user_groups, managed_group];
581
+ if (JSON.stringify(next) !== JSON.stringify(existing)) touched.push(native);
582
+ hooks[native] = next;
583
+ }
584
+ settings["hooks"] = hooks;
585
+ const after = JSON.stringify(settings);
586
+ if (after === before) {
587
+ return { changed: false, events: [] };
588
+ }
589
+ atomicWriteFile(settings_path, JSON.stringify(settings, null, 2) + "\n");
590
+ return { changed: true, events: touched };
591
+ });
592
+ }
593
+ function remove_managed_hooks(settings_path) {
594
+ if (!fs3.existsSync(settings_path)) return { changed: false, events: [] };
595
+ return _with_lock(settings_path, () => {
596
+ const settings = _read_settings(settings_path);
597
+ const hooks = settings["hooks"];
598
+ if (typeof hooks !== "object" || hooks === null || Array.isArray(hooks)) {
599
+ return { changed: false, events: [] };
600
+ }
601
+ const hooksRec = hooks;
602
+ const touched = [];
603
+ for (const [native, groups] of Object.entries(hooksRec)) {
604
+ if (!Array.isArray(groups)) continue;
605
+ const kept = groups.filter((g) => !_is_managed_group(g));
606
+ if (kept.length !== groups.length) {
607
+ touched.push(native);
608
+ if (kept.length === 0) {
609
+ delete hooksRec[native];
610
+ } else {
611
+ hooksRec[native] = kept;
612
+ }
613
+ }
614
+ }
615
+ if (touched.length === 0) return { changed: false, events: [] };
616
+ if (Object.keys(hooksRec).length === 0) {
617
+ delete settings["hooks"];
618
+ }
619
+ atomicWriteFile(settings_path, JSON.stringify(settings, null, 2) + "\n");
620
+ return { changed: true, events: touched };
621
+ });
622
+ }
623
+
624
+ // src/scripts/_lib/global_deploy_inventory.ts
625
+ var global_deploy_inventory_exports = {};
626
+ __export(global_deploy_inventory_exports, {
627
+ INVENTORY_BASENAME: () => INVENTORY_BASENAME,
628
+ INVENTORY_ENV: () => INVENTORY_ENV,
629
+ SCHEMA_VERSION: () => SCHEMA_VERSION2,
630
+ expected_deploy_files: () => expected_deploy_files,
631
+ inventory_path: () => inventory_path,
632
+ is_ancestor: () => is_ancestor,
633
+ load_inventory: () => load_inventory,
634
+ reap_stale: () => reap_stale,
635
+ reap_tagged_orphans: () => reap_tagged_orphans,
636
+ record_deploy: () => record_deploy,
637
+ save_inventory: () => save_inventory
638
+ });
639
+ import { randomBytes as randomBytes2 } from "node:crypto";
640
+ import * as fs4 from "node:fs";
641
+ import * as os2 from "node:os";
642
+ import * as path3 from "node:path";
643
+ var SCHEMA_VERSION2 = 1;
644
+ var INVENTORY_BASENAME = "deployed-files.json";
645
+ var INVENTORY_ENV = "AGENT_CONFIG_DEPLOY_INVENTORY";
646
+ function expanduser2(p) {
647
+ if (p === "~") {
648
+ return os2.homedir();
649
+ }
650
+ if (p.startsWith("~/") || process.platform === "win32" && p.startsWith("~\\")) {
651
+ return path3.join(os2.homedir(), p.slice(2));
652
+ }
653
+ return p;
654
+ }
655
+ function resolve_path(p) {
656
+ try {
657
+ return fs4.realpathSync(p);
658
+ } catch {
659
+ const abs = path3.resolve(p);
660
+ const parts = abs.split(path3.sep);
661
+ for (let i = parts.length; i > 0; i -= 1) {
662
+ const prefix = parts.slice(0, i).join(path3.sep) || path3.sep;
663
+ try {
664
+ const real = fs4.realpathSync(prefix);
665
+ const rest = parts.slice(i);
666
+ return rest.length > 0 ? path3.join(real, ...rest) : real;
667
+ } catch {
668
+ continue;
669
+ }
670
+ }
671
+ return abs;
672
+ }
673
+ }
674
+ function path_exists(p) {
675
+ try {
676
+ fs4.statSync(p);
677
+ return true;
678
+ } catch {
679
+ return false;
680
+ }
681
+ }
682
+ function inventory_path(env) {
683
+ const env_map = env ?? process.env;
684
+ const override = env_map[INVENTORY_ENV];
685
+ if (override) {
686
+ return expanduser2(override);
687
+ }
688
+ return write_target(INVENTORY_BASENAME, { env: env ?? null });
689
+ }
690
+ function load_inventory(p) {
691
+ const target = p ?? inventory_path();
692
+ let data;
693
+ try {
694
+ data = JSON.parse(fs4.readFileSync(target, { encoding: "utf-8" }));
695
+ } catch {
696
+ return { schema_version: SCHEMA_VERSION2, tools: {} };
697
+ }
698
+ if (typeof data !== "object" || data === null || Array.isArray(data) || typeof data["tools"] !== "object" || data["tools"] === null || Array.isArray(data["tools"])) {
699
+ return { schema_version: SCHEMA_VERSION2, tools: {} };
700
+ }
701
+ return data;
702
+ }
703
+ function save_inventory(data, p) {
704
+ const target = p ?? inventory_path();
705
+ fs4.mkdirSync(path3.dirname(target), { recursive: true });
706
+ const payload = json_dumps_sorted(data, 2) + "\n";
707
+ const parent = path3.dirname(target);
708
+ let fd = null;
709
+ let tmp_name = "";
710
+ for (let attempt = 0; attempt < 32; attempt += 1) {
711
+ tmp_name = path3.join(parent, `${path3.basename(target)}.${randomBytes2(6).toString("hex")}`);
712
+ try {
713
+ fd = fs4.openSync(tmp_name, "wx", 384);
714
+ break;
715
+ } catch (err) {
716
+ if (err.code === "EEXIST") {
717
+ continue;
718
+ }
719
+ throw err;
720
+ }
721
+ }
722
+ if (fd === null) {
723
+ throw new Error("save_inventory: could not create a unique temp file");
724
+ }
725
+ try {
726
+ fs4.writeFileSync(fd, payload, { encoding: "utf-8" });
727
+ fs4.closeSync(fd);
728
+ fs4.renameSync(tmp_name, target);
729
+ } catch (err) {
730
+ try {
731
+ fs4.closeSync(fd);
732
+ } catch {
733
+ }
734
+ try {
735
+ fs4.unlinkSync(tmp_name);
736
+ } catch {
737
+ }
738
+ throw err;
739
+ }
740
+ return target;
741
+ }
742
+ function json_dumps_sorted(value, indent) {
743
+ return render_json(value, indent, 0);
744
+ }
745
+ function render_json(value, indent, depth) {
746
+ if (value === null) {
747
+ return "null";
748
+ }
749
+ if (typeof value === "boolean" || typeof value === "number") {
750
+ return JSON.stringify(value);
751
+ }
752
+ if (typeof value === "string") {
753
+ return json_string_ascii(value);
754
+ }
755
+ const pad = " ".repeat(indent * (depth + 1));
756
+ const close_pad = " ".repeat(indent * depth);
757
+ if (Array.isArray(value)) {
758
+ if (value.length === 0) {
759
+ return "[]";
760
+ }
761
+ const items = value.map((v) => pad + render_json(v, indent, depth + 1));
762
+ return "[\n" + items.join(",\n") + "\n" + close_pad + "]";
763
+ }
764
+ if (typeof value === "object") {
765
+ const obj = value;
766
+ const keys = Object.keys(obj).sort((a, b) => a < b ? -1 : a > b ? 1 : 0);
767
+ if (keys.length === 0) {
768
+ return "{}";
769
+ }
770
+ const items = keys.map(
771
+ (k) => pad + json_string_ascii(k) + ": " + render_json(obj[k], indent, depth + 1)
772
+ );
773
+ return "{\n" + items.join(",\n") + "\n" + close_pad + "}";
774
+ }
775
+ return "null";
776
+ }
777
+ function json_string_ascii(s) {
778
+ const base = JSON.stringify(s);
779
+ let out = "";
780
+ for (let i = 0; i < base.length; i += 1) {
781
+ const code = base.charCodeAt(i);
782
+ if (code > 126) {
783
+ out += "\\u" + code.toString(16).padStart(4, "0");
784
+ } else {
785
+ out += base[i];
786
+ }
787
+ }
788
+ return out;
789
+ }
790
+ function expected_deploy_files(src, dest_rel, file_filter = null) {
791
+ const out = /* @__PURE__ */ new Set();
792
+ let src_stat;
793
+ try {
794
+ src_stat = fs4.statSync(src);
795
+ } catch {
796
+ return out;
797
+ }
798
+ if (!src_stat.isDirectory()) {
799
+ if (file_filter !== null && !file_filter(src)) {
800
+ return out;
801
+ }
802
+ out.add(as_posix(dest_rel));
803
+ return out;
804
+ }
805
+ const _walk = (node, prefix) => {
806
+ const entries = fs4.readdirSync(node).sort((a, b) => a < b ? -1 : a > b ? 1 : 0);
807
+ for (const name of entries) {
808
+ const entry = path3.join(node, name);
809
+ const rel = join_rel(prefix, name);
810
+ const lst = fs4.lstatSync(entry);
811
+ if (lst.isDirectory() && !lst.isSymbolicLink()) {
812
+ _walk(entry, rel);
813
+ continue;
814
+ }
815
+ let resolved_is_dir = false;
816
+ try {
817
+ resolved_is_dir = fs4.statSync(entry).isDirectory();
818
+ } catch {
819
+ resolved_is_dir = false;
820
+ }
821
+ if (resolved_is_dir) {
822
+ _walk(fs4.realpathSync(entry), rel);
823
+ continue;
824
+ }
825
+ if (file_filter !== null && !file_filter(entry)) {
826
+ continue;
827
+ }
828
+ out.add(as_posix(rel));
829
+ }
830
+ };
831
+ _walk(src, dest_rel);
832
+ return out;
833
+ }
834
+ function join_rel(prefix, name) {
835
+ return prefix ? path3.join(prefix, name) : name;
836
+ }
837
+ function as_posix(p) {
838
+ if (p === "") {
839
+ return ".";
840
+ }
841
+ return p.split(path3.sep).join("/");
842
+ }
843
+ function reap_stale(tool_id, anchor, current_files, inventory, dry_run = false) {
844
+ const tools = inventory["tools"] ?? {};
845
+ const entry = tools[tool_id];
846
+ if (typeof entry !== "object" || entry === null || Array.isArray(entry)) {
847
+ return [];
848
+ }
849
+ const e = entry;
850
+ const recorded_anchor = e["anchor"];
851
+ const prev_files = e["files"];
852
+ if (typeof recorded_anchor !== "string" || !Array.isArray(prev_files)) {
853
+ return [];
854
+ }
855
+ const anchor_resolved = resolve_path(expanduser2(anchor));
856
+ if (resolve_path(expanduser2(recorded_anchor)) !== anchor_resolved) {
857
+ return [];
858
+ }
859
+ const deleted = [];
860
+ const prune_candidates = /* @__PURE__ */ new Set();
861
+ const orphans = difference(prev_files, current_files);
862
+ for (const rel of sorted_strings(orphans)) {
863
+ if (typeof rel !== "string" || !rel || rel.startsWith("/") || rel.startsWith("..")) {
864
+ continue;
865
+ }
866
+ const target = path3.join(anchor_resolved, rel);
867
+ try {
868
+ relative_to(resolve_path(path3.dirname(target)), anchor_resolved);
869
+ } catch {
870
+ continue;
871
+ }
872
+ let lst = null;
873
+ try {
874
+ lst = fs4.lstatSync(target);
875
+ } catch {
876
+ lst = null;
877
+ }
878
+ if (lst && lst.isDirectory() && !lst.isSymbolicLink()) {
879
+ continue;
880
+ }
881
+ if (dry_run) {
882
+ if (path_exists(target) || lst !== null && lst.isSymbolicLink()) {
883
+ deleted.push(target);
884
+ }
885
+ continue;
886
+ }
887
+ try {
888
+ fs4.unlinkSync(target);
889
+ } catch {
890
+ continue;
891
+ }
892
+ deleted.push(target);
893
+ prune_candidates.add(path3.dirname(target));
894
+ }
895
+ prune_empty_dirs(prune_candidates, anchor_resolved);
896
+ return deleted;
897
+ }
898
+ function reap_tagged_orphans(anchor, dest_subs, current_files, package_tag, dry_run = false) {
899
+ const anchor_resolved = resolve_path(expanduser2(anchor));
900
+ const deleted = [];
901
+ const prune_candidates = /* @__PURE__ */ new Set();
902
+ const needle = `package: ${package_tag}`;
903
+ for (const dest_sub of dest_subs) {
904
+ const root = dest_sub ? path3.join(anchor_resolved, dest_sub) : anchor_resolved;
905
+ let root_stat;
906
+ try {
907
+ root_stat = fs4.statSync(root);
908
+ } catch {
909
+ continue;
910
+ }
911
+ if (!root_stat.isDirectory()) {
912
+ continue;
913
+ }
914
+ for (const md of rglob_md(root)) {
915
+ let md_lst;
916
+ try {
917
+ md_lst = fs4.lstatSync(md);
918
+ } catch {
919
+ continue;
920
+ }
921
+ if (md_lst.isDirectory()) {
922
+ continue;
923
+ }
924
+ const rel = relative_to_posix(md, anchor_resolved);
925
+ if (current_files.has(rel)) {
926
+ continue;
927
+ }
928
+ try {
929
+ relative_to(resolve_path(path3.dirname(md)), anchor_resolved);
930
+ } catch {
931
+ continue;
932
+ }
933
+ let head;
934
+ try {
935
+ head = fs4.readFileSync(md, { encoding: "utf-8" });
936
+ } catch {
937
+ continue;
938
+ }
939
+ if (!head.startsWith("---")) {
940
+ continue;
941
+ }
942
+ const end = head.indexOf("\n---", 3);
943
+ const block = head.slice(0, end !== -1 ? end : head.length);
944
+ const hit = splitlines2(block).some((line) => line.trim() === needle);
945
+ if (!hit) {
946
+ continue;
947
+ }
948
+ if (dry_run) {
949
+ deleted.push(md);
950
+ continue;
951
+ }
952
+ try {
953
+ fs4.unlinkSync(md);
954
+ } catch {
955
+ continue;
956
+ }
957
+ deleted.push(md);
958
+ prune_candidates.add(path3.dirname(md));
959
+ }
960
+ }
961
+ prune_empty_dirs(prune_candidates, anchor_resolved);
962
+ return deleted;
963
+ }
964
+ function record_deploy(tool_id, anchor, current_files, inventory) {
965
+ if (typeof inventory["tools"] !== "object" || inventory["tools"] === null || Array.isArray(inventory["tools"])) {
966
+ inventory["tools"] = {};
967
+ }
968
+ const tools = inventory["tools"];
969
+ tools[tool_id] = {
970
+ anchor: String(anchor),
971
+ files: sorted_strings([...current_files])
972
+ };
973
+ inventory["schema_version"] = SCHEMA_VERSION2;
974
+ return inventory;
975
+ }
976
+ function prune_empty_dirs(prune_candidates, anchor_resolved) {
977
+ const ordered = [...prune_candidates].sort(
978
+ (a, b) => b.split(path3.sep).length - a.split(path3.sep).length
979
+ );
980
+ for (const start of ordered) {
981
+ let node = start;
982
+ while (node !== anchor_resolved && is_ancestor(anchor_resolved, node)) {
983
+ try {
984
+ fs4.rmdirSync(node);
985
+ } catch {
986
+ break;
987
+ }
988
+ node = path3.dirname(node);
989
+ }
990
+ }
991
+ }
992
+ function is_ancestor(anchor, node) {
993
+ const rel = path3.relative(anchor, node);
994
+ return rel !== "" && !rel.startsWith("..") && !path3.isAbsolute(rel);
995
+ }
996
+ function relative_to(child, parent) {
997
+ if (child === parent) {
998
+ return "";
999
+ }
1000
+ const rel = path3.relative(parent, child);
1001
+ if (rel.startsWith("..") || path3.isAbsolute(rel)) {
1002
+ throw new Error(`'${child}' is not in the subpath of '${parent}'`);
1003
+ }
1004
+ return rel;
1005
+ }
1006
+ function relative_to_posix(child, parent) {
1007
+ return path3.relative(parent, child).split(path3.sep).join("/");
1008
+ }
1009
+ function rglob_md(root) {
1010
+ const out = [];
1011
+ const walk = (dir) => {
1012
+ let names;
1013
+ try {
1014
+ names = fs4.readdirSync(dir).sort((a, b) => a < b ? -1 : a > b ? 1 : 0);
1015
+ } catch {
1016
+ return;
1017
+ }
1018
+ for (const name of names) {
1019
+ const full = path3.join(dir, name);
1020
+ let lst;
1021
+ try {
1022
+ lst = fs4.lstatSync(full);
1023
+ } catch {
1024
+ continue;
1025
+ }
1026
+ if (lst.isDirectory() && !lst.isSymbolicLink()) {
1027
+ walk(full);
1028
+ } else if (name.endsWith(".md")) {
1029
+ out.push(full);
1030
+ }
1031
+ }
1032
+ };
1033
+ walk(root);
1034
+ return out;
1035
+ }
1036
+ function difference(prev, current) {
1037
+ const seen = /* @__PURE__ */ new Set();
1038
+ const out = [];
1039
+ for (const item of prev) {
1040
+ if (typeof item === "string" && current.has(item)) {
1041
+ continue;
1042
+ }
1043
+ if (seen.has(item)) {
1044
+ continue;
1045
+ }
1046
+ seen.add(item);
1047
+ out.push(item);
1048
+ }
1049
+ return out;
1050
+ }
1051
+ function sorted_strings(items) {
1052
+ return items.filter((i) => typeof i === "string").sort((a, b) => a < b ? -1 : a > b ? 1 : 0);
1053
+ }
1054
+ function splitlines2(text) {
1055
+ const parts = text.split("\n");
1056
+ if (parts.length > 0 && parts[parts.length - 1] === "") {
1057
+ parts.pop();
1058
+ }
1059
+ return parts;
1060
+ }
1061
+
1062
+ export {
1063
+ write_atomic,
1064
+ SCHEMA_VERSIONS_SUPPORTED,
1065
+ DEFAULT_DEPLOY_ROOTS,
1066
+ manifest_path,
1067
+ read_manifest,
1068
+ write_manifest,
1069
+ ScopeMismatchError,
1070
+ upsert_tool,
1071
+ atomicAppendLine,
1072
+ MANAGED_SIGNATURE,
1073
+ build_claude_hook_matrix,
1074
+ ensure_managed_hooks,
1075
+ remove_managed_hooks,
1076
+ load_inventory,
1077
+ save_inventory,
1078
+ expected_deploy_files,
1079
+ reap_stale,
1080
+ reap_tagged_orphans,
1081
+ record_deploy,
1082
+ is_ancestor,
1083
+ global_deploy_inventory_exports
1084
+ };