@event4u/agent-config 17.3.0 → 17.4.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 (137) hide show
  1. package/.augment-plugin/marketplace.json +3 -3
  2. package/.augment-plugin/plugin.json +1 -1
  3. package/.claude-plugin/marketplace.json +1 -1
  4. package/CHANGELOG.md +164 -342
  5. package/CREDITS.md +2 -2
  6. package/README.md +1 -1
  7. package/dist/agent-src/skills/code-intelligence/SKILL.md +3 -0
  8. package/dist/agent-src/templates/agents/agent-project-settings.example.yml +1 -1
  9. package/dist/cli/registry.js +2 -2
  10. package/dist/cli-delegate/{chunk-DHSSP7V3.js → chunk-5AYJGUA3.js} +0 -2
  11. package/dist/cli-delegate/chunk-DIFZBP4G.js +1336 -0
  12. package/dist/cli-delegate/{chunk-MT2WOOCY.js → chunk-WY5ZZPGL.js} +2 -2
  13. package/dist/cli-delegate/{chunk-ORJPBER2.js → chunk-X6LZ7W5A.js} +73 -10
  14. package/dist/cli-delegate/cmd_conformance.js +175 -183
  15. package/dist/cli-delegate/cmd_doctor.js +5 -5
  16. package/dist/cli-delegate/cmd_doctor_neighbours.js +3 -3
  17. package/dist/cli-delegate/cmd_explain.js +1 -1
  18. package/dist/cli-delegate/cmd_handoff.js +2 -2
  19. package/dist/cli-delegate/cmd_memory_get.js +1 -1
  20. package/dist/cli-delegate/cmd_route_audit.js +1 -1
  21. package/dist/cli-delegate/cmd_session_recycle.js +2 -2
  22. package/dist/cli-delegate/cmd_update.js +24 -13
  23. package/dist/cli-delegate/cmd_upgrade.js +2 -2
  24. package/dist/cli-delegate/dist-25AZAHOP.js +3240 -0
  25. package/dist/cli-delegate/dist-P7MFPMF3.js +411 -0
  26. package/dist/cli-delegate/dist-XAS5ZLQB.js +6 -0
  27. package/dist/cli-delegate/{upgrade_unattended-VVL6JLSX.js → upgrade_unattended-QCWOKTUN.js} +178 -163
  28. package/dist/discovery/deprecation-report.md +1 -1
  29. package/dist/discovery/discovery-manifest.json +3 -3
  30. package/dist/discovery/discovery-manifest.json.sha256 +1 -1
  31. package/dist/discovery/discovery-manifest.summary.md +1 -1
  32. package/dist/discovery/dormancy-report.md +1 -1
  33. package/dist/discovery/orphan-report.md +1 -1
  34. package/dist/discovery/packs.json +2 -2
  35. package/dist/discovery/trust-report.md +1 -1
  36. package/dist/discovery/workspaces.json +2 -2
  37. package/dist/hooks/code_graph_refresh.chunk.cjs +56 -27
  38. package/dist/hooks/code_graph_refresh.chunk.cjs.sha256 +1 -1
  39. package/dist/hooks/dispatch.js +982 -929
  40. package/dist/hooks/dispatch.sha256 +1 -1
  41. package/dist/hooks/egress_engine.chunk.cjs +56 -6
  42. package/dist/hooks/egress_engine.chunk.cjs.sha256 +1 -1
  43. package/dist/hooks/update_notice.chunk.cjs +914 -0
  44. package/dist/hooks/update_notice.chunk.cjs.sha256 +1 -0
  45. package/dist/mcp/registry-manifest.json +1 -1
  46. package/dist/mcp/server.json +2 -2
  47. package/dist/mcp/server.mjs +71259 -66437
  48. package/dist/scripts/condense.js +9 -6
  49. package/package.json +4 -1
  50. package/src/config/evaluator-budgets.json +9 -8
  51. package/src/config/gate-violation-baselines.json +2 -2
  52. package/src/config/hook-bundle-budget.json +31 -6
  53. package/src/config/packed-binary-manifest.json +9 -0
  54. package/src/config/sigstore/npm_keys.json +50 -0
  55. package/src/config/sigstore/trust-material.json +9 -0
  56. package/src/config/sigstore/trusted_root.json +126 -0
  57. package/src/config/skill-body-budget.json +7 -1
  58. package/src/scripts/_cli/cmd_update.ts +48 -20
  59. package/src/scripts/_cli/cmd_upgrade.ts +7 -1
  60. package/src/scripts/_cli/upgrade_unattended.ts +90 -76
  61. package/src/scripts/_dispatch.bash +3 -2
  62. package/src/scripts/_lib/confusables.ts +0 -19
  63. package/src/scripts/_lib/egress_normalize.ts +53 -23
  64. package/src/scripts/_lib/egress_text.ts +5 -3
  65. package/src/scripts/_lib/egress_token.ts +7 -5
  66. package/src/scripts/_lib/gate_collector_experimental.ts +633 -0
  67. package/src/scripts/_lib/git_common_dir.ts +10 -0
  68. package/src/scripts/_lib/graph_feeder_record.ts +3 -2
  69. package/src/scripts/_lib/install_reach_checks.ts +32 -2
  70. package/src/scripts/_lib/lineage_backfill.ts +136 -0
  71. package/src/scripts/_lib/lineage_ledger.ts +211 -0
  72. package/src/scripts/_lib/lineage_map.ts +55 -0
  73. package/src/scripts/_lib/lineage_query.ts +140 -0
  74. package/src/scripts/_lib/lineage_seed.ts +116 -0
  75. package/src/scripts/_lib/lineage_watch.ts +249 -0
  76. package/src/scripts/_lib/link_crypto.ts +8 -4
  77. package/src/scripts/_lib/production_reach.ts +3 -3
  78. package/src/scripts/_lib/project_registry.ts +227 -0
  79. package/src/scripts/_lib/provenance_verify.ts +14 -242
  80. package/src/scripts/_lib/sigstore_provenance.ts +177 -0
  81. package/src/scripts/_lib/source_id.ts +48 -0
  82. package/src/scripts/_lib/source_shape.ts +4 -0
  83. package/src/scripts/_lib/unattended_gates.ts +6 -1
  84. package/src/scripts/advisories.ts +26 -10
  85. package/src/scripts/ai_council/council_egress.ts +5 -6
  86. package/src/scripts/bench_graph_feeder_latency.ts +10 -3
  87. package/src/scripts/check_dependency_floors.ts +7 -0
  88. package/src/scripts/check_egress_mutations.ts +1 -0
  89. package/src/scripts/code_graph/build.ts +67 -3
  90. package/src/scripts/code_graph/cli.ts +131 -28
  91. package/src/scripts/code_graph/conventions_default.ts +20 -1
  92. package/src/scripts/code_graph/detect.ts +5 -5
  93. package/src/scripts/code_graph/estate_cli.ts +135 -0
  94. package/src/scripts/code_graph/estate_index.ts +394 -0
  95. package/src/scripts/code_graph/estate_manifests.ts +223 -0
  96. package/src/scripts/code_graph/estate_map.ts +141 -0
  97. package/src/scripts/code_graph/extract.ts +4 -1
  98. package/src/scripts/code_graph/extract_more.ts +137 -2
  99. package/src/scripts/code_graph/graph_budget.ts +158 -0
  100. package/src/scripts/code_graph/graph_home.ts +80 -0
  101. package/src/scripts/code_graph/lineage_cli.ts +315 -0
  102. package/src/scripts/code_graph/map.ts +22 -13
  103. package/src/scripts/code_graph/map_model.ts +67 -12
  104. package/src/scripts/code_graph/map_verify.ts +68 -5
  105. package/src/scripts/code_graph/map_viewer/viewer.css +12 -0
  106. package/src/scripts/code_graph/map_viewer/viewer.js +45 -15
  107. package/src/scripts/code_graph/project_ref.ts +25 -0
  108. package/src/scripts/code_graph/projects_cli.ts +254 -0
  109. package/src/scripts/code_graph/providers/catalog.ts +14 -5
  110. package/src/scripts/code_graph/providers/django.ts +52 -9
  111. package/src/scripts/code_graph/providers/index.ts +2 -0
  112. package/src/scripts/code_graph/providers/rails.ts +204 -0
  113. package/src/scripts/code_graph/providers/spring.ts +38 -1
  114. package/src/scripts/code_graph/query.ts +9 -9
  115. package/src/scripts/code_graph/refresh_lock.ts +12 -8
  116. package/src/scripts/code_graph/repo_identity.ts +169 -0
  117. package/src/scripts/code_graph/sqlite_store.ts +22 -25
  118. package/src/scripts/code_graph/types.ts +6 -2
  119. package/src/scripts/condense.ts +6 -6
  120. package/src/scripts/hook_chunks.mjs +7 -0
  121. package/src/scripts/hook_manifest.json +1 -1
  122. package/src/scripts/hook_manifest.yaml +20 -17
  123. package/src/scripts/hooks/code_graph_refresh_hook.ts +10 -7
  124. package/src/scripts/hooks/dispatch_hook.ts +6 -7
  125. package/src/scripts/hooks/host_semantics.ts +72 -0
  126. package/src/scripts/hooks/lazy_concern.ts +4 -0
  127. package/src/scripts/hooks/user_notice.ts +105 -0
  128. package/src/scripts/lint_harvest_provenance.ts +137 -11
  129. package/src/scripts/mcp_server/consumer_tool_catalog.json +69 -15
  130. package/src/scripts/mcp_server/graph_tools.ts +161 -41
  131. package/src/scripts/network_sources.ts +24 -6
  132. package/src/scripts/schemas/provenance-mechanism.schema.json +46 -0
  133. package/src/scripts/update_notice_hook.ts +75 -7
  134. package/src/vendor/grammars/README.md +7 -6
  135. package/src/vendor/grammars/tree-sitter-ruby.wasm +0 -0
  136. /package/dist/cli-delegate/{chunk-FKYZOWVD.js → chunk-QBAFP67O.js} +0 -0
  137. /package/dist/cli-delegate/{chunk-BMGUGSY6.js → chunk-TQG6UMPC.js} +0 -0
@@ -24,46 +24,24 @@ import {
24
24
  import "./chunk-J55WI3RR.js";
25
25
 
26
26
  // src/scripts/_cli/upgrade_unattended.ts
27
- import * as fs from "node:fs";
28
- import * as path from "node:path";
27
+ import * as crypto from "node:crypto";
28
+ import * as fs2 from "node:fs";
29
+ import * as os from "node:os";
30
+ import * as path2 from "node:path";
29
31
  import { spawnSync } from "node:child_process";
30
32
  import process from "node:process";
31
33
 
34
+ // src/scripts/_lib/sigstore_provenance.ts
35
+ import { createHash } from "node:crypto";
36
+ import * as fs from "node:fs";
37
+ import * as path from "node:path";
38
+
32
39
  // src/scripts/_lib/provenance_verify.ts
33
40
  var EXPECTED_WORKFLOW_REF = ".github/workflows/publish-npm.yml";
34
41
  var EXPECTED_REPOSITORY = "https://github.com/event4u-app/agent-config";
35
42
  function asRecord(v) {
36
43
  return v !== null && typeof v === "object" && !Array.isArray(v) ? v : null;
37
44
  }
38
- function decode_payload(doc) {
39
- const list = asRecord(doc)?.["attestations"];
40
- if (!Array.isArray(list) || list.length === 0) return null;
41
- for (const entry of list) {
42
- const payload = asRecord(asRecord(asRecord(entry)?.["bundle"])?.["dsseEnvelope"])?.["payload"];
43
- if (typeof payload !== "string" || payload === "") continue;
44
- try {
45
- const parsed = JSON.parse(Buffer.from(payload, "base64").toString("utf8"));
46
- const rec = asRecord(parsed);
47
- if (rec !== null) return rec;
48
- } catch {
49
- }
50
- }
51
- return null;
52
- }
53
- function external_workflow(doc) {
54
- const payload = decode_payload(doc);
55
- if (payload === null) return null;
56
- const predicate = asRecord(payload["predicate"]);
57
- const external = asRecord(asRecord(predicate?.["buildDefinition"])?.["externalParameters"]);
58
- return asRecord(external?.["workflow"]);
59
- }
60
- function attestation_workflow_ref(doc) {
61
- const path_value = external_workflow(doc)?.["path"];
62
- return typeof path_value === "string" && path_value !== "" ? path_value : null;
63
- }
64
- function provenance_matches_publish(doc) {
65
- return payload_names_publish(decode_payload(doc));
66
- }
67
45
  function payload_names_publish(payload) {
68
46
  const predicate = asRecord(payload?.["predicate"]);
69
47
  const workflow = asRecord(asRecord(asRecord(predicate?.["buildDefinition"])?.["externalParameters"])?.["workflow"]);
@@ -72,109 +50,124 @@ function payload_names_publish(payload) {
72
50
  if (typeof repo !== "string" || repo === "") return false;
73
51
  return repo.replace(/\.git$/, "").replace(/\/$/, "") === EXPECTED_REPOSITORY;
74
52
  }
75
- function san_names_workflow(san) {
76
- return san.split(/,\s*/).some((e) => e.startsWith(`URI:${SAN_WORKFLOW_MARKER}@`));
77
- }
78
- var SAN_WORKFLOW_MARKER = `${EXPECTED_REPOSITORY}/${EXPECTED_WORKFLOW_REF}`;
79
- function dssePae(payloadType, payload) {
80
- const type = Buffer.from(payloadType, "utf8");
81
- return Buffer.concat([
82
- Buffer.from(`DSSEv1 ${String(type.length)} `, "utf8"),
83
- type,
84
- Buffer.from(` ${String(payload.length)} `, "utf8"),
85
- payload
86
- ]);
87
- }
88
- function readEnvelope(entry) {
89
- const bundle = asRecord(asRecord(entry)?.["bundle"]);
90
- const dsse = asRecord(bundle?.["dsseEnvelope"]);
91
- if (dsse === null) return null;
92
- const payloadB64 = dsse["payload"];
93
- const payloadType = dsse["payloadType"];
94
- const sigs = dsse["signatures"];
95
- if (typeof payloadB64 !== "string" || typeof payloadType !== "string" || !Array.isArray(sigs) || sigs.length === 0) return null;
96
- const sigB64 = asRecord(sigs[0])?.["sig"];
97
- if (typeof sigB64 !== "string" || sigB64 === "") return null;
98
- const material = asRecord(bundle?.["verificationMaterial"]);
99
- const single = asRecord(material?.["certificate"])?.["rawBytes"];
100
- const chain = asRecord(material?.["x509CertificateChain"])?.["certificates"];
101
- const first = Array.isArray(chain) ? asRecord(chain[0])?.["rawBytes"] : void 0;
102
- const certB64 = typeof single === "string" ? single : typeof first === "string" ? first : null;
103
- if (certB64 === null || certB64 === "") return null;
104
- return {
105
- payloadType,
106
- payload: Buffer.from(payloadB64, "base64"),
107
- sig: Buffer.from(sigB64, "base64"),
108
- certDer: Buffer.from(certB64, "base64")
109
- };
53
+
54
+ // src/scripts/_lib/sigstore_provenance.ts
55
+ var SLSA_PROVENANCE_V1 = "https://slsa.dev/provenance/v1";
56
+ var NPM_PUBLISH_V01 = "https://github.com/npm/attestation/tree/main/specs/publish/v0.1";
57
+ var GITHUB_OIDC_ISSUER = "https://token.actions.githubusercontent.com";
58
+ var PACKAGE_PURL_BASE = "pkg:npm/%40event4u/agent-config";
59
+ function asRecord2(v) {
60
+ return v !== null && typeof v === "object" && !Array.isArray(v) ? v : null;
61
+ }
62
+ function escapeRegExp(s) {
63
+ return s.replace(/[.*+?^${}()|[\]\\/]/g, "\\$&");
64
+ }
65
+ function expectedSan(version) {
66
+ return new RegExp(`^${escapeRegExp(`${EXPECTED_REPOSITORY}/${EXPECTED_WORKFLOW_REF}@refs/tags/${version}`)}$`);
67
+ }
68
+ function readTrustFiles(packageRoot = resolvePackageRoot(import.meta.url)) {
69
+ const dir = path.join(packageRoot, "src", "config", "sigstore");
70
+ try {
71
+ const manifest = JSON.parse(fs.readFileSync(path.join(dir, "trust-material.json"), "utf-8"));
72
+ const read = (name) => {
73
+ const bytes = fs.readFileSync(path.join(dir, name));
74
+ const want = manifest.files?.[name];
75
+ const got = createHash("sha256").update(bytes).digest("hex");
76
+ if (want !== got) throw new Error(`${name} has sha256 ${got}, the recorded one is ${String(want)}`);
77
+ return JSON.parse(bytes.toString("utf-8"));
78
+ };
79
+ return { trustedRoot: read("trusted_root.json"), npmKeys: read("npm_keys.json") };
80
+ } catch (err) {
81
+ return `the pinned sigstore trust material is unusable: ${err instanceof Error ? err.message : String(err)}`;
82
+ }
83
+ }
84
+ function subjectMatches(payload, version, sha512Hex) {
85
+ const subjects = payload?.["subject"];
86
+ if (!Array.isArray(subjects) || subjects.length !== 1) return "it does not name exactly one subject";
87
+ const subject = asRecord2(subjects[0]);
88
+ if (subject?.["name"] !== `${PACKAGE_PURL_BASE}@${version}`) return `its subject is ${String(subject?.["name"])}, not ${version}`;
89
+ const digest = asRecord2(subject["digest"])?.["sha512"];
90
+ if (typeof digest !== "string" || digest.toLowerCase() !== sha512Hex.toLowerCase()) {
91
+ return "its subject digest does not match the tarball about to be installed";
92
+ }
93
+ return null;
110
94
  }
111
- async function verify_attestation_signature(doc) {
112
- const list = asRecord(doc)?.["attestations"];
113
- if (!Array.isArray(list) || list.length === 0) return "the attestation bundle carries no attestations";
114
- const crypto = await import("node:crypto");
115
- let lastReason = "no attestation carried a readable DSSE envelope";
95
+ async function verify_release_provenance(release, trust = readTrustFiles()) {
96
+ if (typeof trust === "string") return trust;
97
+ const list = asRecord2(release.attestations)?.["attestations"];
98
+ if (!Array.isArray(list)) return "the attestation document carries no attestations";
99
+ const byType = /* @__PURE__ */ new Map();
116
100
  for (const entry of list) {
117
- const env = readEnvelope(entry);
118
- if (env === null) continue;
119
- let cert;
120
- try {
121
- cert = new crypto.X509Certificate(env.certDer);
122
- } catch {
123
- lastReason = "the signing certificate could not be parsed";
124
- continue;
125
- }
126
- const san = cert.subjectAltName ?? "";
127
- if (!san_names_workflow(san)) {
128
- lastReason = `the signing certificate names ${san === "" ? "no identity" : san}, not ${SAN_WORKFLOW_MARKER}`;
129
- continue;
130
- }
131
- let ok = false;
132
- try {
133
- ok = crypto.verify(null, dssePae(env.payloadType, env.payload), cert.publicKey, env.sig);
134
- } catch {
135
- ok = false;
136
- }
137
- if (!ok) {
138
- lastReason = "the DSSE signature does not verify against the certificate in the bundle";
139
- continue;
101
+ const type = asRecord2(entry)?.["predicateType"];
102
+ if (typeof type === "string" && !byType.has(type)) byType.set(type, asRecord2(entry)?.["bundle"]);
103
+ }
104
+ for (const type of [SLSA_PROVENANCE_V1, NPM_PUBLISH_V01]) {
105
+ if (!byType.has(type)) return `the release carries no ${type} attestation`;
106
+ }
107
+ const { Verifier, toSignedEntity, toTrustMaterial } = await import("./dist-25AZAHOP.js");
108
+ const { bundleFromJSON } = await import("./dist-P7MFPMF3.js");
109
+ const { PublicKey, TrustedRoot } = await import("./dist-XAS5ZLQB.js");
110
+ let material;
111
+ try {
112
+ const keys = {};
113
+ const listed = asRecord2(trust.npmKeys)?.["keys"];
114
+ for (const k of Array.isArray(listed) ? listed : []) {
115
+ const key = asRecord2(k);
116
+ if (key?.["keyUsage"] === "npm:attestations" && typeof key["keyId"] === "string") {
117
+ keys[key["keyId"]] = PublicKey.fromJSON(key["publicKey"]);
118
+ }
140
119
  }
141
- let verified = null;
120
+ material = toTrustMaterial(TrustedRoot.fromJSON(trust.trustedRoot), keys);
121
+ } catch (err) {
122
+ return `the pinned sigstore trust material could not be loaded: ${err instanceof Error ? err.message : String(err)}`;
123
+ }
124
+ for (const type of [SLSA_PROVENANCE_V1, NPM_PUBLISH_V01]) {
125
+ let payload;
142
126
  try {
143
- verified = asRecord(JSON.parse(env.payload.toString("utf8")));
144
- } catch {
145
- verified = null;
127
+ const bundle = bundleFromJSON(byType.get(type));
128
+ const verifier = new Verifier(material, { tlogThreshold: 1, ctlogThreshold: 1, timestampThreshold: 1 });
129
+ const policy = type === SLSA_PROVENANCE_V1 ? { subjectAlternativeName: expectedSan(release.version), extensions: { issuer: GITHUB_OIDC_ISSUER } } : void 0;
130
+ verifier.verify(toSignedEntity(bundle), policy);
131
+ if (bundle.content.$case !== "dsseEnvelope") return `the ${type} attestation is not a DSSE envelope`;
132
+ payload = asRecord2(JSON.parse(bundle.content.dsseEnvelope.payload.toString("utf-8")));
133
+ } catch (err) {
134
+ const code = asRecord2(err)?.["code"];
135
+ return `the ${type} attestation does not verify${typeof code === "string" ? ` (${code})` : ""}: ${err instanceof Error ? err.message : String(err)}`;
146
136
  }
147
- if (!payload_names_publish(verified)) {
148
- lastReason = "the signed payload does not name this package's publish workflow";
149
- continue;
137
+ if (payload?.["predicateType"] !== type) return `the ${type} attestation's statement names another predicate type`;
138
+ const subject = subjectMatches(payload, release.version, release.tarballSha512Hex);
139
+ if (subject !== null) return `the ${type} attestation is not for this tarball: ${subject}`;
140
+ if (type === SLSA_PROVENANCE_V1 && !payload_names_publish(payload)) {
141
+ return `the signed provenance does not name ${EXPECTED_WORKFLOW_REF} in ${EXPECTED_REPOSITORY}`;
150
142
  }
151
- return null;
152
143
  }
153
- return lastReason;
144
+ return null;
154
145
  }
155
146
 
156
147
  // src/scripts/_lib/unattended_gates.ts
157
148
  var UNATTENDED_MIN_RELEASE_AGE_HOURS = 72;
158
- function asRecord2(v) {
149
+ function asRecord3(v) {
159
150
  return v !== null && typeof v === "object" && !Array.isArray(v) ? v : null;
160
151
  }
161
152
  function read_candidate(packument) {
162
- const doc = asRecord2(packument);
163
- const version = asRecord2(doc?.["dist-tags"])?.["latest"];
153
+ const doc = asRecord3(packument);
154
+ const version = asRecord3(doc?.["dist-tags"])?.["latest"];
164
155
  if (typeof version !== "string" || version === "") return null;
165
- const manifest = asRecord2(asRecord2(doc?.["versions"])?.[version]);
156
+ const manifest = asRecord3(asRecord3(doc?.["versions"])?.[version]);
166
157
  if (manifest === null) return null;
167
- const published = asRecord2(doc?.["time"])?.[version];
168
- const attestations = asRecord2(asRecord2(manifest["dist"])?.["attestations"]);
169
- const predicate = asRecord2(attestations?.["provenance"])?.["predicateType"];
158
+ const published = asRecord3(doc?.["time"])?.[version];
159
+ const attestations = asRecord3(asRecord3(manifest["dist"])?.["attestations"]);
160
+ const predicate = asRecord3(attestations?.["provenance"])?.["predicateType"];
170
161
  return {
171
162
  version,
172
163
  publishedAt: typeof published === "string" ? published : null,
173
164
  deprecated: manifest["deprecated"],
174
165
  engines: manifest["engines"],
175
166
  provenance: typeof predicate === "string" && predicate.startsWith("https://slsa.dev/provenance/"),
176
- impactMap: asRecord2(manifest["agentConfig"])?.["impact"] ?? null,
177
- attestationsUrl: typeof attestations?.["url"] === "string" ? attestations["url"] : null
167
+ impactMap: asRecord3(manifest["agentConfig"])?.["impact"] ?? null,
168
+ attestationsUrl: typeof attestations?.["url"] === "string" ? attestations["url"] : null,
169
+ tarballUrl: typeof asRecord3(manifest["dist"])?.["tarball"] === "string" ? asRecord3(manifest["dist"])?.["tarball"] : null,
170
+ integrity: typeof asRecord3(manifest["dist"])?.["integrity"] === "string" ? asRecord3(manifest["dist"])?.["integrity"] : null
178
171
  };
179
172
  }
180
173
  function unattended_decision(input) {
@@ -214,7 +207,7 @@ function say(sink, line) {
214
207
  }
215
208
  function read_skips(skipPath) {
216
209
  try {
217
- const data = JSON.parse(fs.readFileSync(skipPath, "utf-8"));
210
+ const data = JSON.parse(fs2.readFileSync(skipPath, "utf-8"));
218
211
  const list = data?.skip;
219
212
  return Array.isArray(list) ? list.filter((v) => typeof v === "string") : [];
220
213
  } catch {
@@ -224,12 +217,12 @@ function read_skips(skipPath) {
224
217
  function record_skip(skipPath, version) {
225
218
  const skips = read_skips(skipPath);
226
219
  if (!skips.includes(version)) skips.push(version);
227
- fs.mkdirSync(path.dirname(skipPath), { recursive: true });
228
- fs.writeFileSync(skipPath, JSON.stringify({ skip: skips.sort() }, null, 2) + "\n", "utf-8");
220
+ fs2.mkdirSync(path2.dirname(skipPath), { recursive: true });
221
+ fs2.writeFileSync(skipPath, JSON.stringify({ skip: skips.sort() }, null, 2) + "\n", "utf-8");
229
222
  }
230
223
  function read_text(p) {
231
224
  try {
232
- return fs.readFileSync(p, "utf-8");
225
+ return fs2.readFileSync(p, "utf-8");
233
226
  } catch {
234
227
  return null;
235
228
  }
@@ -238,15 +231,15 @@ function acquire_lock(deps) {
238
231
  const record = { pid: deps.pid, started_at: deps.now().toISOString(), ttl_ms: LOCK_TTL_MS };
239
232
  const mine = `${deps.lockPath}.${deps.pid}.${process.hrtime.bigint()}`;
240
233
  try {
241
- fs.mkdirSync(path.dirname(deps.lockPath), { recursive: true });
242
- fs.writeFileSync(mine, JSON.stringify(record) + "\n", { flag: "wx" });
234
+ fs2.mkdirSync(path2.dirname(deps.lockPath), { recursive: true });
235
+ fs2.writeFileSync(mine, JSON.stringify(record) + "\n", { flag: "wx" });
243
236
  } catch (exc) {
244
237
  return `cannot write the lock: ${String(exc)}`;
245
238
  }
246
239
  try {
247
240
  for (let attempt = 0; attempt < 2; attempt += 1) {
248
241
  try {
249
- fs.linkSync(mine, deps.lockPath);
242
+ fs2.linkSync(mine, deps.lockPath);
250
243
  return null;
251
244
  } catch (exc) {
252
245
  if (exc.code !== "EEXIST") return `cannot write the lock: ${String(exc)}`;
@@ -264,35 +257,35 @@ function acquire_lock(deps) {
264
257
  }
265
258
  const tomb = `${mine}.stale`;
266
259
  try {
267
- fs.renameSync(deps.lockPath, tomb);
260
+ fs2.renameSync(deps.lockPath, tomb);
268
261
  } catch {
269
262
  continue;
270
263
  }
271
264
  if (read_text(tomb) !== judged) {
272
265
  try {
273
- fs.linkSync(tomb, deps.lockPath);
266
+ fs2.linkSync(tomb, deps.lockPath);
274
267
  } catch {
275
268
  }
276
- fs.rmSync(tomb, { force: true });
269
+ fs2.rmSync(tomb, { force: true });
277
270
  return "another unattended upgrade took the lock over first";
278
271
  }
279
- fs.rmSync(tomb, { force: true });
272
+ fs2.rmSync(tomb, { force: true });
280
273
  }
281
274
  return "the lock could not be taken";
282
275
  } finally {
283
- fs.rmSync(mine, { force: true });
276
+ fs2.rmSync(mine, { force: true });
284
277
  }
285
278
  }
286
279
  function release_lock(deps) {
287
280
  try {
288
- const held = JSON.parse(fs.readFileSync(deps.lockPath, "utf-8"));
289
- if (held.pid === deps.pid) fs.unlinkSync(deps.lockPath);
281
+ const held = JSON.parse(fs2.readFileSync(deps.lockPath, "utf-8"));
282
+ if (held.pid === deps.pid) fs2.unlinkSync(deps.lockPath);
290
283
  } catch {
291
284
  }
292
285
  }
293
- function install_steps(version, deps) {
286
+ function install_steps(spec, deps) {
294
287
  return [
295
- ["npm", "install", "-g", `${PACKAGE_NAME}@${version}`],
288
+ ["npm", "install", "-g", spec],
296
289
  [deps.agentConfigBin, "global", "--no-ui"],
297
290
  ...deps.globalSettings.map((target) => [deps.agentConfigBin, "settings:sync", "--path", target])
298
291
  ];
@@ -307,7 +300,7 @@ function run_steps(steps, deps, honourSignal = true) {
307
300
  return { ok: true };
308
301
  }
309
302
  function restore(previous, deps) {
310
- const back = run_steps(install_steps(previous, deps).slice(0, 2), deps, false);
303
+ const back = run_steps(install_steps(`${PACKAGE_NAME}@${previous}`, deps).slice(0, 2), deps, false);
311
304
  const lock = deps.readInstalled();
312
305
  const binary = deps.readBinary();
313
306
  if (back.ok && lock === previous && binary === previous) {
@@ -334,41 +327,58 @@ async function decide(installed, deps) {
334
327
  });
335
328
  if (!decision.install) return { refused: [...decision.reasons] };
336
329
  const provenance = await deps.verifyProvenance(candidate);
337
- if (provenance !== null) return { refused: [provenance] };
338
- return { candidate };
339
- }
340
- async function verify_provenance_default(candidate, fetch_impl = fetch, timeoutMs = 1e4) {
341
- if (candidate.attestationsUrl === null) {
342
- return `${candidate.version} carries no attestation bundle to verify`;
330
+ if (!provenance.ok) return { refused: [provenance.reason] };
331
+ return { candidate, tarball: provenance.tarball };
332
+ }
333
+ var MAX_TARBALL_BYTES = 64 * 1024 * 1024;
334
+ async function verify_provenance_default(candidate, fetch_impl = fetch, timeoutMs = 6e4, verify = (r) => verify_release_provenance(r)) {
335
+ const v = candidate.version;
336
+ const registry = new URL(PACKUMENT_URL).origin;
337
+ const refuse = (reason2) => ({ ok: false, reason: `${v}: ${reason2}` });
338
+ for (const [what, url] of [
339
+ ["attestation bundle", candidate.attestationsUrl],
340
+ ["tarball", candidate.tarballUrl]
341
+ ]) {
342
+ if (url === null) return refuse(`the registry names no ${what} to verify`);
343
+ let origin = "";
344
+ try {
345
+ origin = new URL(url).origin;
346
+ } catch {
347
+ }
348
+ if (origin !== registry) return refuse(`the ${what} url is not on ${registry}`);
343
349
  }
344
- let origin;
350
+ const integrity = /^sha512-([A-Za-z0-9+/=]+)$/.exec(candidate.integrity ?? "");
351
+ if (integrity === null) return refuse("the registry records no sha512 integrity for the tarball");
352
+ const get = async (url) => {
353
+ const resp = await fetch_impl(url, { signal: AbortSignal.timeout(timeoutMs), redirect: "error" });
354
+ if (!resp.ok) throw new Error(`HTTP ${resp.status}`);
355
+ return resp;
356
+ };
357
+ let attestations;
358
+ let bytes;
345
359
  try {
346
- origin = new URL(candidate.attestationsUrl).origin;
347
- } catch {
348
- origin = "";
360
+ attestations = await (await get(candidate.attestationsUrl)).json();
361
+ const resp = await get(candidate.tarballUrl);
362
+ if (Number(resp.headers.get("content-length") ?? 0) > MAX_TARBALL_BYTES) return refuse("the tarball is larger than allowed");
363
+ bytes = Buffer.from(await resp.arrayBuffer());
364
+ } catch (err) {
365
+ return refuse(`download failed: ${err instanceof Error ? err.message : String(err)}`);
349
366
  }
350
- if (origin !== new URL(PACKUMENT_URL).origin) {
351
- return `${candidate.version}: attestation url is not on ${new URL(PACKUMENT_URL).origin}`;
367
+ if (bytes.length > MAX_TARBALL_BYTES) return refuse("the tarball is larger than allowed");
368
+ const digest = crypto.createHash("sha512").update(bytes).digest();
369
+ if (!digest.equals(Buffer.from(integrity[1], "base64"))) {
370
+ return refuse("the downloaded tarball does not match the integrity the registry records");
352
371
  }
353
- let doc;
372
+ const reason = await verify({ version: v, tarballSha512Hex: digest.toString("hex"), attestations });
373
+ if (reason !== null) return refuse(reason);
354
374
  try {
355
- const resp = await fetch_impl(candidate.attestationsUrl, {
356
- signal: AbortSignal.timeout(timeoutMs),
357
- headers: { accept: "application/json" },
358
- redirect: "error"
359
- });
360
- if (!resp.ok) return `attestation fetch failed: HTTP ${resp.status}`;
361
- doc = await resp.json();
375
+ const dir = fs2.mkdtempSync(path2.join(os.tmpdir(), "agent-config-upgrade-"));
376
+ const tarball = path2.join(dir, `agent-config-${v}.tgz`);
377
+ fs2.writeFileSync(tarball, bytes, { mode: 384, flag: "wx" });
378
+ return { ok: true, tarball };
362
379
  } catch (err) {
363
- return `attestation fetch failed: ${err instanceof Error ? err.message : String(err)}`;
364
- }
365
- if (!provenance_matches_publish(doc)) {
366
- const named = attestation_workflow_ref(doc);
367
- return named === null ? `${candidate.version} has no readable provenance workflow in its attestation` : `${candidate.version} was built by ${named}, not ${EXPECTED_WORKFLOW_REF}`;
380
+ return refuse(`cannot write the verified tarball: ${err instanceof Error ? err.message : String(err)}`);
368
381
  }
369
- const signature = await verify_attestation_signature(doc);
370
- if (signature !== null) return `${candidate.version}: ${signature}`;
371
- return null;
372
382
  }
373
383
  function quiet_context(deps) {
374
384
  if (deps.env.ci) return "suppressed: CI";
@@ -392,14 +402,16 @@ async function run_unattended(deps) {
392
402
  say(deps.err, `${PREFIX}: not installing \u2014 ${locked}.`);
393
403
  return EXIT_REFUSED;
394
404
  }
405
+ let verified = null;
395
406
  try {
396
407
  const verdict = await decide(previous, deps);
397
408
  if ("refused" in verdict) {
398
409
  say(deps.out, `\u2139\uFE0F ${PREFIX}: not installing (installed: ${previous}) \u2014 ${verdict.refused.join("; ")}.`);
399
410
  return EXIT_REFUSED;
400
411
  }
412
+ verified = verdict.tarball;
401
413
  const target = verdict.candidate.version;
402
- const steps = install_steps(target, deps);
414
+ const steps = install_steps(verified, deps);
403
415
  if (deps.activationBlocked !== null) {
404
416
  const how = deps.dryRun ? "dry run: a real run would not install" : "not installing";
405
417
  say(deps.out, `\u2139\uFE0F ${PREFIX}: every gate passed for ${target}, but ${how} \u2014 ${deps.activationBlocked}.`);
@@ -417,9 +429,10 @@ async function run_unattended(deps) {
417
429
  }
418
430
  const what = `${ran.cmd.join(" ")} (exit ${ran.result.rc})`;
419
431
  if (/\bEACCES\b/.test(ran.result.stderr)) {
432
+ const manual = ran.cmd === steps[0] ? ["npm", "install", "-g", `${PACKAGE_NAME}@${target}`] : ran.cmd;
420
433
  say(
421
434
  deps.err,
422
- `\u274C ${PREFIX}: permission denied on ${what}. agent-config never runs sudo; run this yourself with the right permissions: ${ran.cmd.join(" ")}`
435
+ `\u274C ${PREFIX}: permission denied on ${what}. agent-config never runs sudo; run this yourself with the right permissions: ${manual.join(" ")}`
423
436
  );
424
437
  const untouched = ran.cmd === steps[0] && deps.readInstalled() === previous && deps.readBinary() === previous;
425
438
  if (untouched) return 1;
@@ -428,6 +441,7 @@ async function run_unattended(deps) {
428
441
  say(deps.err, `\u274C ${PREFIX}: step failed: ${what} \u2014 restoring ${previous}.`);
429
442
  return restore(previous, deps);
430
443
  } finally {
444
+ if (verified !== null) fs2.rmSync(path2.dirname(verified), { recursive: true, force: true });
431
445
  release_lock(deps);
432
446
  }
433
447
  }
@@ -467,8 +481,8 @@ function skip_version(version, out) {
467
481
  return 0;
468
482
  }
469
483
  async function run_unattended_default(options) {
470
- const globalSettings = path.join(event4u_root(), "settings", ".agent-settings.yml");
471
- const packageJson = path.join(resolvePackageRoot(import.meta.url), "package.json");
484
+ const globalSettings = path2.join(event4u_root(), "settings", ".agent-settings.yml");
485
+ const packageJson = path2.join(resolvePackageRoot(import.meta.url), "package.json");
472
486
  let terminated = false;
473
487
  const onTerm = () => {
474
488
  terminated = true;
@@ -484,7 +498,7 @@ function run_unattended_wired(options, globalSettings, packageJson, interrupted)
484
498
  return run_unattended({
485
499
  readBinary: () => {
486
500
  try {
487
- const v = JSON.parse(fs.readFileSync(packageJson, "utf-8")).version;
501
+ const v = JSON.parse(fs2.readFileSync(packageJson, "utf-8")).version;
488
502
  return typeof v === "string" ? v : "";
489
503
  } catch {
490
504
  return "";
@@ -500,7 +514,7 @@ function run_unattended_wired(options, globalSettings, packageJson, interrupted)
500
514
  },
501
515
  origin: running_origin(),
502
516
  agentConfigBin: options.agentConfigBin,
503
- globalSettings: fs.existsSync(globalSettings) ? [globalSettings] : [],
517
+ globalSettings: fs2.existsSync(globalSettings) ? [globalSettings] : [],
504
518
  lockPath: write_target(LOCK_FILE),
505
519
  skipPath: write_target(SKIP_FILE),
506
520
  env: {
@@ -523,6 +537,7 @@ export {
523
537
  EXIT_RESTORE_FAILED,
524
538
  LOCK_FILE,
525
539
  LOCK_TTL_MS,
540
+ MAX_TARBALL_BYTES,
526
541
  PACKAGE_NAME,
527
542
  PACKUMENT_URL,
528
543
  SKIP_FILE,
@@ -1,6 +1,6 @@
1
1
  # Discovery — Deprecation Report
2
2
 
3
- - Generated: `2026-10-24T05:31:43Z`
3
+ - Generated: `2026-10-24T10:59:12Z`
4
4
  - Deprecated artefacts: **0**
5
5
 
6
6
  _None. Tree is clean._
@@ -9206,7 +9206,7 @@
9206
9206
  },
9207
9207
  {
9208
9208
  "category": "skill",
9209
- "checksum": "sha256:8453a22d61bc6a6d3f1edf4b1fe8691a1964a7c0fccc64db508cfdf5a96da27a",
9209
+ "checksum": "sha256:f5dc56a475d0180931625a4c590af8b45dc365593fdd44ec992284d4d7b0d6c8",
9210
9210
  "install": {
9211
9211
  "default": true,
9212
9212
  "removable": false
@@ -15120,7 +15120,7 @@
15120
15120
  "workspaces": []
15121
15121
  }
15122
15122
  ],
15123
- "checksum": "sha256:55b3f948c10233f9fa0ddc32b6ff8b6701ea822011e0448a32228a574541cf3e",
15123
+ "checksum": "sha256:03d3bf776b1cd4eb516f50f873eb435611b9d8ab590337913eb19e786224d144",
15124
15124
  "deprecations": [
15125
15125
  {
15126
15126
  "key": "tier",
@@ -15269,7 +15269,7 @@
15269
15269
  "reason": "scaffold template for ticket-bundle tickets (ADR-101); carries no runtime frontmatter — emit-tickets fills it in per ticket"
15270
15270
  }
15271
15271
  ],
15272
- "generated_at": "2026-10-24T05:31:43Z",
15272
+ "generated_at": "2026-10-24T10:59:12Z",
15273
15273
  "packs": [
15274
15274
  {
15275
15275
  "artefact_count": 130,
@@ -1 +1 @@
1
- 9aa654312e6184bbe25cd1777fff6eaedfb4f3c85d543e5cffb780fca2553bae discovery-manifest.json
1
+ 1388c41a068bccdb4c8ad314e25db5de1c2ba4e5bd68ba9ffa5a0f1cf5755318 discovery-manifest.json
@@ -1,6 +1,6 @@
1
1
  # Discovery Manifest — Summary
2
2
 
3
- - Generated: `2026-10-24T05:31:43Z`
3
+ - Generated: `2026-10-24T10:59:12Z`
4
4
  - Scanner: `de0a22b4ac4c`
5
5
  - Artefacts: **637**
6
6
  - Unassigned: **0**
@@ -1,6 +1,6 @@
1
1
  # Discovery — Dormancy Report
2
2
 
3
- - Generated: `2026-10-24T05:31:43Z`
3
+ - Generated: `2026-10-24T10:59:12Z`
4
4
  - Window: **6 months** without a commit
5
5
 
6
6
  > Dormancy triggers **review, never auto-deprecation**
@@ -1,6 +1,6 @@
1
1
  # Discovery — Orphan Report
2
2
 
3
- - Generated: `2026-10-24T05:31:43Z`
3
+ - Generated: `2026-10-24T10:59:12Z`
4
4
  - Orphan artefacts: **0**
5
5
 
6
6
  > An orphan is an artefact whose declared pack has no other members.
@@ -1,6 +1,6 @@
1
1
  {
2
- "checksum": "sha256:55b3f948c10233f9fa0ddc32b6ff8b6701ea822011e0448a32228a574541cf3e",
3
- "generated_at": "2026-10-24T05:31:43Z",
2
+ "checksum": "sha256:03d3bf776b1cd4eb516f50f873eb435611b9d8ab590337913eb19e786224d144",
3
+ "generated_at": "2026-10-24T10:59:12Z",
4
4
  "packs": [
5
5
  {
6
6
  "always_on": false,
@@ -1,6 +1,6 @@
1
1
  # Discovery — Trust Report
2
2
 
3
- - Generated: `2026-10-24T05:31:43Z`
3
+ - Generated: `2026-10-24T10:59:12Z`
4
4
  - Workspaces tracked: **10**
5
5
  - Human-review-required artefacts: **3**
6
6
 
@@ -1,6 +1,6 @@
1
1
  {
2
- "checksum": "sha256:55b3f948c10233f9fa0ddc32b6ff8b6701ea822011e0448a32228a574541cf3e",
3
- "generated_at": "2026-10-24T05:31:43Z",
2
+ "checksum": "sha256:03d3bf776b1cd4eb516f50f873eb435611b9d8ab590337913eb19e786224d144",
3
+ "generated_at": "2026-10-24T10:59:12Z",
4
4
  "scanner_version": "de0a22b4ac4c",
5
5
  "workspaces": [
6
6
  {