@event4u/agent-config 9.11.0 → 9.13.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/.claude-plugin/marketplace.json +1 -1
- package/CHANGELOG.md +80 -204
- package/README.md +8 -1
- package/dist/agent-src/commands/fix/ci.md +29 -0
- package/dist/agent-src/commands/pr/create.md +60 -0
- package/dist/agent-src/contexts/authority/kernel-rule-edits.md +18 -2
- package/dist/agent-src/rules/active-remediation.md +0 -2
- package/dist/agent-src/rules/architecture.md +0 -1
- package/dist/agent-src/rules/artifact-drafting-protocol.md +0 -4
- package/dist/agent-src/rules/autonomous-execution.md +1 -2
- package/dist/agent-src/rules/broken-access-control.md +0 -2
- package/dist/agent-src/rules/code-comment-discipline.md +0 -3
- package/dist/agent-src/rules/code-provenance.md +0 -3
- package/dist/agent-src/rules/communication-through-line.md +2 -3
- package/dist/agent-src/rules/content-quoting-floor.md +0 -2
- package/dist/agent-src/rules/context-hygiene.md +1 -3
- package/dist/agent-src/rules/decision-revisit-gate.md +0 -2
- package/dist/agent-src/rules/design-fidelity.md +30 -1
- package/dist/agent-src/rules/domain-adoption-policy.md +0 -3
- package/dist/agent-src/rules/downstream-changes.md +10 -1
- package/dist/agent-src/rules/external-reference-deep-dive.md +0 -7
- package/dist/agent-src/rules/fast-path-marker-visibility.md +0 -1
- package/dist/agent-src/rules/git-history-discipline.md +0 -7
- package/dist/agent-src/rules/guidelines.md +0 -2
- package/dist/agent-src/rules/improve-before-implement.md +4 -2
- package/dist/agent-src/rules/invite-challenge.md +0 -4
- package/dist/agent-src/rules/linked-projects-onboarding-gate.md +0 -2
- package/dist/agent-src/rules/markdown-safe-codeblocks.md +0 -1
- package/dist/agent-src/rules/minimal-safe-diff.md +2 -2
- package/dist/agent-src/rules/missing-tool-handling.md +0 -1
- package/dist/agent-src/rules/no-attribution-footers.md +0 -3
- package/dist/agent-src/rules/no-decorative-emojis-in-git-surfaces.md +8 -5
- package/dist/agent-src/rules/no-pr-progress-comments.md +1 -3
- package/dist/agent-src/rules/no-roadmap-references.md +0 -2
- package/dist/agent-src/rules/output-discipline.md +0 -1
- package/dist/agent-src/rules/prefer-enums-over-literals.md +0 -2
- package/dist/agent-src/rules/preservation-guard.md +0 -3
- package/dist/agent-src/rules/role-mode-adherence.md +0 -1
- package/dist/agent-src/rules/secret-vcs-guard.md +0 -2
- package/dist/agent-src/rules/senior-engineering-discipline.md +0 -2
- package/dist/agent-src/rules/session-canary.md +0 -2
- package/dist/agent-src/rules/size-enforcement.md +0 -5
- package/dist/agent-src/rules/source-confidentiality.md +0 -3
- package/dist/agent-src/rules/source-discovery-gate.md +0 -2
- package/dist/agent-src/rules/think-before-action.md +3 -3
- package/dist/agent-src/rules/token-budget-discipline.md +0 -1
- package/dist/agent-src/rules/token-efficiency.md +1 -2
- package/dist/agent-src/rules/tool-safety.md +0 -1
- package/dist/agent-src/rules/user-interaction.md +0 -3
- package/dist/agent-src/rules/user-interrupt-priority.md +0 -1
- package/dist/agent-src/skills/agent-docs-writing/SKILL.md +8 -0
- package/dist/agent-src/skills/ai-code-blindspots/SKILL.md +1 -0
- package/dist/agent-src/skills/analysis-skill-router/SKILL.md +55 -86
- package/dist/agent-src/skills/character-consistency/SKILL.md +7 -4
- package/dist/agent-src/skills/decision-record/SKILL.md +8 -0
- package/dist/agent-src/skills/design-intelligence/SKILL.md +27 -1
- package/dist/agent-src/skills/design-intelligence/data/font-pairings-reference.csv +74 -74
- package/dist/agent-src/skills/design-intelligence/data/manifest.json +2 -0
- package/dist/agent-src/skills/design-review/SKILL.md +11 -0
- package/dist/agent-src/skills/design-system-capture/reference/design-system-json.md +8 -0
- package/dist/agent-src/skills/design-tokens/scripts/tokens.ts +0 -7
- package/dist/agent-src/skills/existing-ui-audit/SKILL.md +34 -3
- package/dist/agent-src/skills/fe-design/SKILL.md +10 -0
- package/dist/agent-src/skills/motion-choreographer/SKILL.md +7 -4
- package/dist/agent-src/skills/overbuild-review-lens/SKILL.md +201 -0
- package/dist/agent-src/skills/performance/SKILL.md +14 -0
- package/dist/agent-src/skills/pixar-storyteller/SKILL.md +8 -5
- package/dist/agent-src/skills/scene-expander/SKILL.md +9 -6
- package/dist/agent-src/skills/supply-chain-intake/SKILL.md +10 -0
- package/dist/agent-src/skills/typography-system/SKILL.md +55 -11
- package/dist/agent-src/skills/ui-apply-generic/SKILL.md +180 -0
- package/dist/agent-src/skills/universal-project-analysis/SKILL.md +14 -37
- package/dist/agent-src/skills/video-director/SKILL.md +9 -6
- package/dist/agent-src/templates/agents/agent-project-settings.example.yml +1 -1
- package/dist/agent-src/templates/scripts/work_engine/directives/ui/apply.ts +162 -17
- package/dist/agent-src/templates/scripts/work_engine/directives/ui/design.ts +118 -0
- package/dist/agent-src/templates/scripts/work_engine/directives/ui/polish.ts +49 -6
- package/dist/agent-src/templates/scripts/work_engine/directives/ui/review.ts +9 -5
- package/dist/agent-src/templates/scripts/work_engine/directives/ui/stack_bundles.ts +182 -29
- package/dist/agent-src/templates/scripts/work_engine/stack/detect.ts +311 -24
- package/dist/agent-src/templates/scripts/work_engine/state.ts +55 -0
- package/dist/cli-delegate/chunk-523HCFYO.js +90 -0
- package/dist/cli-delegate/{chunk-IR7P7JWA.js → chunk-A3HJ6NTI.js} +271 -59
- package/dist/cli-delegate/chunk-EJYIGZ3T.js +125 -0
- package/dist/cli-delegate/{chunk-RDGRHAAB.js → chunk-HYWSRNUX.js} +6 -86
- package/dist/cli-delegate/{chunk-YMFO6FDN.js → chunk-QFKQLQ7X.js} +313 -81
- package/dist/cli-delegate/{chunk-4SV3XGFA.js → chunk-TEGJU2JX.js} +7 -9
- package/dist/cli-delegate/chunk-TJIAM5FW.js +133 -0
- package/dist/cli-delegate/cmd_conformance.js +4 -7
- package/dist/cli-delegate/cmd_doctor.js +3 -5
- package/dist/cli-delegate/cmd_explain.js +153 -85
- package/dist/cli-delegate/cmd_export.js +5 -3
- package/dist/cli-delegate/cmd_fleet.js +2 -1
- package/dist/cli-delegate/cmd_preflight.js +6 -123
- package/dist/cli-delegate/cmd_prune.js +5 -3
- package/dist/cli-delegate/cmd_settings_migrate.js +5 -3
- package/dist/cli-delegate/cmd_sync.js +5 -3
- package/dist/cli-delegate/cmd_uninstall.js +6 -5
- package/dist/cli-delegate/cmd_validate.js +5 -3
- package/dist/discovery/deprecation-report.md +1 -1
- package/dist/discovery/discovery-manifest.json +116 -72
- package/dist/discovery/discovery-manifest.json.sha256 +1 -1
- package/dist/discovery/discovery-manifest.summary.md +3 -3
- package/dist/discovery/orphan-report.md +1 -1
- package/dist/discovery/packs.json +7 -5
- package/dist/discovery/trust-report.md +2 -2
- package/dist/discovery/workspaces.json +6 -4
- package/dist/hooks/dispatch.js +174 -13
- package/dist/install/install.mjs +605 -412
- package/dist/install/ruleInScope.js +123 -0
- package/dist/install/ruleInScope.js.map +1 -0
- package/dist/install/rule_scope.js +2 -2
- package/dist/install/rule_scope.js.map +1 -1
- package/dist/install/wizard-plan.js +10 -1
- package/dist/install/wizard-plan.js.map +1 -1
- package/dist/mcp/registry-manifest.json +3 -3
- package/dist/mcp/server.json +2 -2
- package/dist/mcp/server.mjs +710 -2491
- package/dist/router.json +1 -1
- package/dist/scripts/condense.js +8 -24
- package/dist/scripts/condense.js.map +1 -1
- package/docs/MIGRATION.md +1 -1
- package/docs/guidelines/agent-infra/agent-interaction-and-decision-quality.md +71 -0
- package/docs/guidelines/agent-infra/minimal-safe-diff-mechanics.md +24 -1
- package/docs/guidelines/code-clarity.md +9 -2
- package/docs/guidelines/design-fidelity-mechanics.md +58 -0
- package/llms.txt +63 -27
- package/package.json +4 -4
- package/src/agent-src/templates/scripts/work_engine/directives/ui/apply.ts +162 -17
- package/src/agent-src/templates/scripts/work_engine/directives/ui/design.ts +118 -0
- package/src/agent-src/templates/scripts/work_engine/directives/ui/polish.ts +49 -6
- package/src/agent-src/templates/scripts/work_engine/directives/ui/review.ts +9 -5
- package/src/agent-src/templates/scripts/work_engine/directives/ui/stack_bundles.ts +182 -29
- package/src/agent-src/templates/scripts/work_engine/stack/detect.ts +311 -24
- package/src/agent-src/templates/scripts/work_engine/state.ts +55 -0
- package/src/config/agent-settings.template.yml +8 -0
- package/src/install/ruleInScope.ts +133 -0
- package/src/install/rule_scope.ts +2 -2
- package/src/install/wizard-plan.ts +11 -1
- package/src/scripts/_lib/counted_probe.ts +142 -0
- package/src/scripts/_lib/global_deploy_inventory.ts +38 -2
- package/src/scripts/_lib/overbuild_lens_contract.ts +196 -0
- package/src/scripts/_lib/release_scope.ts +207 -0
- package/src/scripts/ai_council/stance_tally.ts +37 -2
- package/src/scripts/audit_auto_rules.ts +9 -9
- package/src/scripts/audit_likelihood.ts +3 -3
- package/src/scripts/audit_overlap.ts +2 -2
- package/src/scripts/audit_skill_overlap.ts +233 -95
- package/src/scripts/audit_skill_overlap_allowlist.json +4 -0
- package/src/scripts/build_proof.ts +15 -1
- package/src/scripts/check_dependency_floors.ts +16 -6
- package/src/scripts/check_gate_coverage.ts +6 -6
- package/src/scripts/check_installer_import_purity.ts +295 -0
- package/src/scripts/check_kernel_rule_bundle.ts +5 -4
- package/src/scripts/check_token_quality_golden.ts +0 -18
- package/src/scripts/code_graph/loader.ts +35 -6
- package/src/scripts/compile_router.ts +3 -8
- package/src/scripts/condense.ts +9 -30
- package/src/scripts/explain_run.ts +0 -1
- package/src/scripts/generate_pack_manifests.ts +3 -20
- package/src/scripts/hooks/block_kernel_rule_writes.ts +145 -10
- package/src/scripts/hooks/block_no_verify.ts +101 -0
- package/src/scripts/install-hooks.sh +36 -4
- package/src/scripts/install.ts +210 -5
- package/src/scripts/lint_agent_security.ts +5 -4
- package/src/scripts/lint_framework_leakage_allowlist.json +2 -2
- package/src/scripts/lint_regression.ts +92 -1
- package/src/scripts/lint_skill_descriptions.ts +93 -5
- package/src/scripts/lint_ui_stack_bundles.ts +31 -0
- package/src/scripts/project_thin_rules.ts +2 -2
- package/src/scripts/release.ts +107 -3
- package/src/scripts/resolve_lint_scope.ts +53 -0
- package/src/scripts/router_telemetry.ts +0 -5
- package/src/scripts/runtime_dispatcher.ts +40 -0
- package/src/scripts/schemas/pack.schema.json +1 -5
- package/src/scripts/schemas/rule.schema.json +1 -2
- package/src/scripts/self_review_gate.ts +15 -73
- package/src/scripts/skill_linter.ts +93 -11
- package/src/scripts/sweep_dead_scan_roots.ts +550 -0
- package/src/scripts/trigger_coverage.ts +11 -37
- package/dist/cli-delegate/chunk-7DSAMZFU.js +0 -356
- package/dist/cli-delegate/chunk-BJGXZNPM.js +0 -266
- package/dist/cli-delegate/chunk-TFG57JJM.js +0 -1969
|
@@ -3,7 +3,11 @@ import {
|
|
|
3
3
|
write_target
|
|
4
4
|
} from "./chunk-NDJLNC6Q.js";
|
|
5
5
|
import {
|
|
6
|
-
|
|
6
|
+
require_dist
|
|
7
|
+
} from "./chunk-OY53J6II.js";
|
|
8
|
+
import {
|
|
9
|
+
__export,
|
|
10
|
+
__toESM
|
|
7
11
|
} from "./chunk-J55WI3RR.js";
|
|
8
12
|
|
|
9
13
|
// src/scripts/_lib/fs_atomic.ts
|
|
@@ -140,18 +144,18 @@ function manifest_path(project_root, env) {
|
|
|
140
144
|
var _TOP_KEY_RE = /^([A-Za-z_][A-Za-z0-9_]*)\s*:\s*"?([^"\n]*?)"?\s*$/;
|
|
141
145
|
var _LIST_DASH_RE = /^\s*-\s*(.+?)\s*$/;
|
|
142
146
|
var _INDENT_KEY_RE = /^\s+([A-Za-z_][A-Za-z0-9_]*)\s*:\s*"?([^"\n]*?)"?\s*$/;
|
|
143
|
-
function read_manifest(
|
|
147
|
+
function read_manifest(path4) {
|
|
144
148
|
let text;
|
|
145
149
|
try {
|
|
146
|
-
text = require_read_text(
|
|
150
|
+
text = require_read_text(path4);
|
|
147
151
|
} catch {
|
|
148
152
|
return null;
|
|
149
153
|
}
|
|
150
154
|
const data = _parse_manual(text);
|
|
151
155
|
return _normalise_v2_shape(data);
|
|
152
156
|
}
|
|
153
|
-
function require_read_text(
|
|
154
|
-
return fs2.readFileSync(
|
|
157
|
+
function require_read_text(path4) {
|
|
158
|
+
return fs2.readFileSync(path4, { encoding: "utf-8" });
|
|
155
159
|
}
|
|
156
160
|
function _normalise_v2_shape(data) {
|
|
157
161
|
if (data["tools"] === void 0 || data["tools"] === null) {
|
|
@@ -332,9 +336,9 @@ function stable_sort(items, key) {
|
|
|
332
336
|
return a.index - b.index;
|
|
333
337
|
}).map((entry) => entry.item);
|
|
334
338
|
}
|
|
335
|
-
function write_manifest(
|
|
339
|
+
function write_manifest(path4, version, tools, options = {}) {
|
|
336
340
|
const rendered = _render(version, tools, { deploy_roots: options.deploy_roots ?? null });
|
|
337
|
-
return write_atomic(
|
|
341
|
+
return write_atomic(path4, rendered);
|
|
338
342
|
}
|
|
339
343
|
var ScopeMismatchError = class extends Error {
|
|
340
344
|
name_;
|
|
@@ -422,6 +426,201 @@ function _today() {
|
|
|
422
426
|
return (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
423
427
|
}
|
|
424
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
|
+
|
|
425
624
|
// src/scripts/_lib/global_deploy_inventory.ts
|
|
426
625
|
var global_deploy_inventory_exports = {};
|
|
427
626
|
__export(global_deploy_inventory_exports, {
|
|
@@ -430,6 +629,7 @@ __export(global_deploy_inventory_exports, {
|
|
|
430
629
|
SCHEMA_VERSION: () => SCHEMA_VERSION2,
|
|
431
630
|
expected_deploy_files: () => expected_deploy_files,
|
|
432
631
|
inventory_path: () => inventory_path,
|
|
632
|
+
is_ancestor: () => is_ancestor,
|
|
433
633
|
load_inventory: () => load_inventory,
|
|
434
634
|
reap_stale: () => reap_stale,
|
|
435
635
|
reap_tagged_orphans: () => reap_tagged_orphans,
|
|
@@ -437,9 +637,9 @@ __export(global_deploy_inventory_exports, {
|
|
|
437
637
|
save_inventory: () => save_inventory
|
|
438
638
|
});
|
|
439
639
|
import { randomBytes as randomBytes2 } from "node:crypto";
|
|
440
|
-
import * as
|
|
640
|
+
import * as fs4 from "node:fs";
|
|
441
641
|
import * as os2 from "node:os";
|
|
442
|
-
import * as
|
|
642
|
+
import * as path3 from "node:path";
|
|
443
643
|
var SCHEMA_VERSION2 = 1;
|
|
444
644
|
var INVENTORY_BASENAME = "deployed-files.json";
|
|
445
645
|
var INVENTORY_ENV = "AGENT_CONFIG_DEPLOY_INVENTORY";
|
|
@@ -448,22 +648,22 @@ function expanduser2(p) {
|
|
|
448
648
|
return os2.homedir();
|
|
449
649
|
}
|
|
450
650
|
if (p.startsWith("~/") || process.platform === "win32" && p.startsWith("~\\")) {
|
|
451
|
-
return
|
|
651
|
+
return path3.join(os2.homedir(), p.slice(2));
|
|
452
652
|
}
|
|
453
653
|
return p;
|
|
454
654
|
}
|
|
455
655
|
function resolve_path(p) {
|
|
456
656
|
try {
|
|
457
|
-
return
|
|
657
|
+
return fs4.realpathSync(p);
|
|
458
658
|
} catch {
|
|
459
|
-
const abs =
|
|
460
|
-
const parts = abs.split(
|
|
659
|
+
const abs = path3.resolve(p);
|
|
660
|
+
const parts = abs.split(path3.sep);
|
|
461
661
|
for (let i = parts.length; i > 0; i -= 1) {
|
|
462
|
-
const prefix = parts.slice(0, i).join(
|
|
662
|
+
const prefix = parts.slice(0, i).join(path3.sep) || path3.sep;
|
|
463
663
|
try {
|
|
464
|
-
const real =
|
|
664
|
+
const real = fs4.realpathSync(prefix);
|
|
465
665
|
const rest = parts.slice(i);
|
|
466
|
-
return rest.length > 0 ?
|
|
666
|
+
return rest.length > 0 ? path3.join(real, ...rest) : real;
|
|
467
667
|
} catch {
|
|
468
668
|
continue;
|
|
469
669
|
}
|
|
@@ -473,7 +673,7 @@ function resolve_path(p) {
|
|
|
473
673
|
}
|
|
474
674
|
function path_exists(p) {
|
|
475
675
|
try {
|
|
476
|
-
|
|
676
|
+
fs4.statSync(p);
|
|
477
677
|
return true;
|
|
478
678
|
} catch {
|
|
479
679
|
return false;
|
|
@@ -491,7 +691,7 @@ function load_inventory(p) {
|
|
|
491
691
|
const target = p ?? inventory_path();
|
|
492
692
|
let data;
|
|
493
693
|
try {
|
|
494
|
-
data = JSON.parse(
|
|
694
|
+
data = JSON.parse(fs4.readFileSync(target, { encoding: "utf-8" }));
|
|
495
695
|
} catch {
|
|
496
696
|
return { schema_version: SCHEMA_VERSION2, tools: {} };
|
|
497
697
|
}
|
|
@@ -502,15 +702,15 @@ function load_inventory(p) {
|
|
|
502
702
|
}
|
|
503
703
|
function save_inventory(data, p) {
|
|
504
704
|
const target = p ?? inventory_path();
|
|
505
|
-
|
|
705
|
+
fs4.mkdirSync(path3.dirname(target), { recursive: true });
|
|
506
706
|
const payload = json_dumps_sorted(data, 2) + "\n";
|
|
507
|
-
const parent =
|
|
707
|
+
const parent = path3.dirname(target);
|
|
508
708
|
let fd = null;
|
|
509
709
|
let tmp_name = "";
|
|
510
710
|
for (let attempt = 0; attempt < 32; attempt += 1) {
|
|
511
|
-
tmp_name =
|
|
711
|
+
tmp_name = path3.join(parent, `${path3.basename(target)}.${randomBytes2(6).toString("hex")}`);
|
|
512
712
|
try {
|
|
513
|
-
fd =
|
|
713
|
+
fd = fs4.openSync(tmp_name, "wx", 384);
|
|
514
714
|
break;
|
|
515
715
|
} catch (err) {
|
|
516
716
|
if (err.code === "EEXIST") {
|
|
@@ -523,16 +723,16 @@ function save_inventory(data, p) {
|
|
|
523
723
|
throw new Error("save_inventory: could not create a unique temp file");
|
|
524
724
|
}
|
|
525
725
|
try {
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
726
|
+
fs4.writeFileSync(fd, payload, { encoding: "utf-8" });
|
|
727
|
+
fs4.closeSync(fd);
|
|
728
|
+
fs4.renameSync(tmp_name, target);
|
|
529
729
|
} catch (err) {
|
|
530
730
|
try {
|
|
531
|
-
|
|
731
|
+
fs4.closeSync(fd);
|
|
532
732
|
} catch {
|
|
533
733
|
}
|
|
534
734
|
try {
|
|
535
|
-
|
|
735
|
+
fs4.unlinkSync(tmp_name);
|
|
536
736
|
} catch {
|
|
537
737
|
}
|
|
538
738
|
throw err;
|
|
@@ -587,36 +787,42 @@ function json_string_ascii(s) {
|
|
|
587
787
|
}
|
|
588
788
|
return out;
|
|
589
789
|
}
|
|
590
|
-
function expected_deploy_files(src, dest_rel) {
|
|
790
|
+
function expected_deploy_files(src, dest_rel, file_filter = null) {
|
|
591
791
|
const out = /* @__PURE__ */ new Set();
|
|
592
792
|
let src_stat;
|
|
593
793
|
try {
|
|
594
|
-
src_stat =
|
|
794
|
+
src_stat = fs4.statSync(src);
|
|
595
795
|
} catch {
|
|
596
796
|
return out;
|
|
597
797
|
}
|
|
598
798
|
if (!src_stat.isDirectory()) {
|
|
799
|
+
if (file_filter !== null && !file_filter(src)) {
|
|
800
|
+
return out;
|
|
801
|
+
}
|
|
599
802
|
out.add(as_posix(dest_rel));
|
|
600
803
|
return out;
|
|
601
804
|
}
|
|
602
805
|
const _walk = (node, prefix) => {
|
|
603
|
-
const entries =
|
|
806
|
+
const entries = fs4.readdirSync(node).sort((a, b) => a < b ? -1 : a > b ? 1 : 0);
|
|
604
807
|
for (const name of entries) {
|
|
605
|
-
const entry =
|
|
808
|
+
const entry = path3.join(node, name);
|
|
606
809
|
const rel = join_rel(prefix, name);
|
|
607
|
-
const lst =
|
|
810
|
+
const lst = fs4.lstatSync(entry);
|
|
608
811
|
if (lst.isDirectory() && !lst.isSymbolicLink()) {
|
|
609
812
|
_walk(entry, rel);
|
|
610
813
|
continue;
|
|
611
814
|
}
|
|
612
815
|
let resolved_is_dir = false;
|
|
613
816
|
try {
|
|
614
|
-
resolved_is_dir =
|
|
817
|
+
resolved_is_dir = fs4.statSync(entry).isDirectory();
|
|
615
818
|
} catch {
|
|
616
819
|
resolved_is_dir = false;
|
|
617
820
|
}
|
|
618
821
|
if (resolved_is_dir) {
|
|
619
|
-
_walk(
|
|
822
|
+
_walk(fs4.realpathSync(entry), rel);
|
|
823
|
+
continue;
|
|
824
|
+
}
|
|
825
|
+
if (file_filter !== null && !file_filter(entry)) {
|
|
620
826
|
continue;
|
|
621
827
|
}
|
|
622
828
|
out.add(as_posix(rel));
|
|
@@ -626,13 +832,13 @@ function expected_deploy_files(src, dest_rel) {
|
|
|
626
832
|
return out;
|
|
627
833
|
}
|
|
628
834
|
function join_rel(prefix, name) {
|
|
629
|
-
return prefix ?
|
|
835
|
+
return prefix ? path3.join(prefix, name) : name;
|
|
630
836
|
}
|
|
631
837
|
function as_posix(p) {
|
|
632
838
|
if (p === "") {
|
|
633
839
|
return ".";
|
|
634
840
|
}
|
|
635
|
-
return p.split(
|
|
841
|
+
return p.split(path3.sep).join("/");
|
|
636
842
|
}
|
|
637
843
|
function reap_stale(tool_id, anchor, current_files, inventory, dry_run = false) {
|
|
638
844
|
const tools = inventory["tools"] ?? {};
|
|
@@ -657,15 +863,15 @@ function reap_stale(tool_id, anchor, current_files, inventory, dry_run = false)
|
|
|
657
863
|
if (typeof rel !== "string" || !rel || rel.startsWith("/") || rel.startsWith("..")) {
|
|
658
864
|
continue;
|
|
659
865
|
}
|
|
660
|
-
const target =
|
|
866
|
+
const target = path3.join(anchor_resolved, rel);
|
|
661
867
|
try {
|
|
662
|
-
relative_to(resolve_path(
|
|
868
|
+
relative_to(resolve_path(path3.dirname(target)), anchor_resolved);
|
|
663
869
|
} catch {
|
|
664
870
|
continue;
|
|
665
871
|
}
|
|
666
872
|
let lst = null;
|
|
667
873
|
try {
|
|
668
|
-
lst =
|
|
874
|
+
lst = fs4.lstatSync(target);
|
|
669
875
|
} catch {
|
|
670
876
|
lst = null;
|
|
671
877
|
}
|
|
@@ -679,12 +885,12 @@ function reap_stale(tool_id, anchor, current_files, inventory, dry_run = false)
|
|
|
679
885
|
continue;
|
|
680
886
|
}
|
|
681
887
|
try {
|
|
682
|
-
|
|
888
|
+
fs4.unlinkSync(target);
|
|
683
889
|
} catch {
|
|
684
890
|
continue;
|
|
685
891
|
}
|
|
686
892
|
deleted.push(target);
|
|
687
|
-
prune_candidates.add(
|
|
893
|
+
prune_candidates.add(path3.dirname(target));
|
|
688
894
|
}
|
|
689
895
|
prune_empty_dirs(prune_candidates, anchor_resolved);
|
|
690
896
|
return deleted;
|
|
@@ -695,10 +901,10 @@ function reap_tagged_orphans(anchor, dest_subs, current_files, package_tag, dry_
|
|
|
695
901
|
const prune_candidates = /* @__PURE__ */ new Set();
|
|
696
902
|
const needle = `package: ${package_tag}`;
|
|
697
903
|
for (const dest_sub of dest_subs) {
|
|
698
|
-
const root = dest_sub ?
|
|
904
|
+
const root = dest_sub ? path3.join(anchor_resolved, dest_sub) : anchor_resolved;
|
|
699
905
|
let root_stat;
|
|
700
906
|
try {
|
|
701
|
-
root_stat =
|
|
907
|
+
root_stat = fs4.statSync(root);
|
|
702
908
|
} catch {
|
|
703
909
|
continue;
|
|
704
910
|
}
|
|
@@ -708,7 +914,7 @@ function reap_tagged_orphans(anchor, dest_subs, current_files, package_tag, dry_
|
|
|
708
914
|
for (const md of rglob_md(root)) {
|
|
709
915
|
let md_lst;
|
|
710
916
|
try {
|
|
711
|
-
md_lst =
|
|
917
|
+
md_lst = fs4.lstatSync(md);
|
|
712
918
|
} catch {
|
|
713
919
|
continue;
|
|
714
920
|
}
|
|
@@ -720,13 +926,13 @@ function reap_tagged_orphans(anchor, dest_subs, current_files, package_tag, dry_
|
|
|
720
926
|
continue;
|
|
721
927
|
}
|
|
722
928
|
try {
|
|
723
|
-
relative_to(resolve_path(
|
|
929
|
+
relative_to(resolve_path(path3.dirname(md)), anchor_resolved);
|
|
724
930
|
} catch {
|
|
725
931
|
continue;
|
|
726
932
|
}
|
|
727
933
|
let head;
|
|
728
934
|
try {
|
|
729
|
-
head =
|
|
935
|
+
head = fs4.readFileSync(md, { encoding: "utf-8" });
|
|
730
936
|
} catch {
|
|
731
937
|
continue;
|
|
732
938
|
}
|
|
@@ -744,12 +950,12 @@ function reap_tagged_orphans(anchor, dest_subs, current_files, package_tag, dry_
|
|
|
744
950
|
continue;
|
|
745
951
|
}
|
|
746
952
|
try {
|
|
747
|
-
|
|
953
|
+
fs4.unlinkSync(md);
|
|
748
954
|
} catch {
|
|
749
955
|
continue;
|
|
750
956
|
}
|
|
751
957
|
deleted.push(md);
|
|
752
|
-
prune_candidates.add(
|
|
958
|
+
prune_candidates.add(path3.dirname(md));
|
|
753
959
|
}
|
|
754
960
|
}
|
|
755
961
|
prune_empty_dirs(prune_candidates, anchor_resolved);
|
|
@@ -769,51 +975,51 @@ function record_deploy(tool_id, anchor, current_files, inventory) {
|
|
|
769
975
|
}
|
|
770
976
|
function prune_empty_dirs(prune_candidates, anchor_resolved) {
|
|
771
977
|
const ordered = [...prune_candidates].sort(
|
|
772
|
-
(a, b) => b.split(
|
|
978
|
+
(a, b) => b.split(path3.sep).length - a.split(path3.sep).length
|
|
773
979
|
);
|
|
774
980
|
for (const start of ordered) {
|
|
775
981
|
let node = start;
|
|
776
982
|
while (node !== anchor_resolved && is_ancestor(anchor_resolved, node)) {
|
|
777
983
|
try {
|
|
778
|
-
|
|
984
|
+
fs4.rmdirSync(node);
|
|
779
985
|
} catch {
|
|
780
986
|
break;
|
|
781
987
|
}
|
|
782
|
-
node =
|
|
988
|
+
node = path3.dirname(node);
|
|
783
989
|
}
|
|
784
990
|
}
|
|
785
991
|
}
|
|
786
992
|
function is_ancestor(anchor, node) {
|
|
787
|
-
const rel =
|
|
788
|
-
return rel !== "" && !rel.startsWith("..") && !
|
|
993
|
+
const rel = path3.relative(anchor, node);
|
|
994
|
+
return rel !== "" && !rel.startsWith("..") && !path3.isAbsolute(rel);
|
|
789
995
|
}
|
|
790
996
|
function relative_to(child, parent) {
|
|
791
997
|
if (child === parent) {
|
|
792
998
|
return "";
|
|
793
999
|
}
|
|
794
|
-
const rel =
|
|
795
|
-
if (rel.startsWith("..") ||
|
|
1000
|
+
const rel = path3.relative(parent, child);
|
|
1001
|
+
if (rel.startsWith("..") || path3.isAbsolute(rel)) {
|
|
796
1002
|
throw new Error(`'${child}' is not in the subpath of '${parent}'`);
|
|
797
1003
|
}
|
|
798
1004
|
return rel;
|
|
799
1005
|
}
|
|
800
1006
|
function relative_to_posix(child, parent) {
|
|
801
|
-
return
|
|
1007
|
+
return path3.relative(parent, child).split(path3.sep).join("/");
|
|
802
1008
|
}
|
|
803
1009
|
function rglob_md(root) {
|
|
804
1010
|
const out = [];
|
|
805
1011
|
const walk = (dir) => {
|
|
806
1012
|
let names;
|
|
807
1013
|
try {
|
|
808
|
-
names =
|
|
1014
|
+
names = fs4.readdirSync(dir).sort((a, b) => a < b ? -1 : a > b ? 1 : 0);
|
|
809
1015
|
} catch {
|
|
810
1016
|
return;
|
|
811
1017
|
}
|
|
812
1018
|
for (const name of names) {
|
|
813
|
-
const full =
|
|
1019
|
+
const full = path3.join(dir, name);
|
|
814
1020
|
let lst;
|
|
815
1021
|
try {
|
|
816
|
-
lst =
|
|
1022
|
+
lst = fs4.lstatSync(full);
|
|
817
1023
|
} catch {
|
|
818
1024
|
continue;
|
|
819
1025
|
}
|
|
@@ -862,11 +1068,17 @@ export {
|
|
|
862
1068
|
write_manifest,
|
|
863
1069
|
ScopeMismatchError,
|
|
864
1070
|
upsert_tool,
|
|
1071
|
+
atomicAppendLine,
|
|
1072
|
+
MANAGED_SIGNATURE,
|
|
1073
|
+
build_claude_hook_matrix,
|
|
1074
|
+
ensure_managed_hooks,
|
|
1075
|
+
remove_managed_hooks,
|
|
865
1076
|
load_inventory,
|
|
866
1077
|
save_inventory,
|
|
867
1078
|
expected_deploy_files,
|
|
868
1079
|
reap_stale,
|
|
869
1080
|
reap_tagged_orphans,
|
|
870
1081
|
record_deploy,
|
|
1082
|
+
is_ancestor,
|
|
871
1083
|
global_deploy_inventory_exports
|
|
872
1084
|
};
|