blun-king-cli 9.1.485 → 9.1.488

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 (99) hide show
  1. package/LIESMICH.txt +33 -17
  2. package/README.md +20 -8
  3. package/agent-spine-plugin/.claude-plugin/marketplace.json +20 -0
  4. package/agent-spine-plugin/.claude-plugin/plugin.json +14 -0
  5. package/agent-spine-plugin/.codex-plugin/plugin.json +34 -0
  6. package/agent-spine-plugin/.mcp.json +8 -0
  7. package/agent-spine-plugin/CHANGELOG.md +277 -0
  8. package/agent-spine-plugin/LICENSE +186 -0
  9. package/agent-spine-plugin/README.md +342 -0
  10. package/agent-spine-plugin/assets/agentspine-banner.svg +32 -0
  11. package/agent-spine-plugin/bin/agentspine-mcp.js +4 -0
  12. package/agent-spine-plugin/bin/agentspine.js +7 -0
  13. package/agent-spine-plugin/blun.plugin.json +33 -0
  14. package/agent-spine-plugin/docs/acceptance.md +61 -0
  15. package/agent-spine-plugin/docs/architecture.md +183 -0
  16. package/agent-spine-plugin/docs/attention.md +121 -0
  17. package/agent-spine-plugin/docs/automatic-continuity.md +79 -0
  18. package/agent-spine-plugin/docs/channel-runtime.md +92 -0
  19. package/agent-spine-plugin/docs/coordination.md +138 -0
  20. package/agent-spine-plugin/docs/feed-transport.md +99 -0
  21. package/agent-spine-plugin/docs/gateway-runtime.md +109 -0
  22. package/agent-spine-plugin/docs/harness-reference.md +45 -0
  23. package/agent-spine-plugin/docs/host-integration.md +129 -0
  24. package/agent-spine-plugin/docs/https-transport.md +116 -0
  25. package/agent-spine-plugin/docs/learning.md +98 -0
  26. package/agent-spine-plugin/docs/object-transport.md +93 -0
  27. package/agent-spine-plugin/docs/peer-transport.md +88 -0
  28. package/agent-spine-plugin/docs/preservation-contract.md +53 -0
  29. package/agent-spine-plugin/docs/quality-gates.md +50 -0
  30. package/agent-spine-plugin/docs/relationships.md +67 -0
  31. package/agent-spine-plugin/docs/releasing.md +83 -0
  32. package/agent-spine-plugin/docs/roadmap.md +307 -0
  33. package/agent-spine-plugin/docs/selfstarter.md +88 -0
  34. package/agent-spine-plugin/docs/session-briefing.md +74 -0
  35. package/agent-spine-plugin/docs/shared-memory.md +259 -0
  36. package/agent-spine-plugin/docs/source-roots.md +86 -0
  37. package/agent-spine-plugin/docs/sqlite-transport.md +76 -0
  38. package/agent-spine-plugin/hooks/hooks.json +95 -0
  39. package/agent-spine-plugin/hooks/version.json +5 -0
  40. package/agent-spine-plugin/package.json +69 -0
  41. package/agent-spine-plugin/scripts/check-hosts.js +193 -0
  42. package/agent-spine-plugin/scripts/check-install.js +551 -0
  43. package/agent-spine-plugin/scripts/check-syntax.js +29 -0
  44. package/agent-spine-plugin/scripts/github-actions.js +11 -0
  45. package/agent-spine-plugin/scripts/release-check.js +127 -0
  46. package/agent-spine-plugin/scripts/run-acceptance.js +19 -0
  47. package/agent-spine-plugin/scripts/run-checks.js +46 -0
  48. package/agent-spine-plugin/scripts/run-tests-hermetic.js +73 -0
  49. package/agent-spine-plugin/skill/SKILL.md +76 -0
  50. package/agent-spine-plugin/skills/agent-spine/SKILL.md +84 -0
  51. package/agent-spine-plugin/spine-example/1-identity.md +12 -0
  52. package/agent-spine-plugin/spine-example/2-voice.md +6 -0
  53. package/agent-spine-plugin/spine-example/3-conduct.md +8 -0
  54. package/agent-spine-plugin/spine-example/4-history.md +4 -0
  55. package/agent-spine-plugin/src/cli.js +950 -0
  56. package/agent-spine-plugin/src/hook.js +646 -0
  57. package/agent-spine-plugin/src/index.js +84 -0
  58. package/agent-spine-plugin/src/lib/acceptance.js +294 -0
  59. package/agent-spine-plugin/src/lib/attention.js +755 -0
  60. package/agent-spine-plugin/src/lib/audit.js +308 -0
  61. package/agent-spine-plugin/src/lib/authentication.js +513 -0
  62. package/agent-spine-plugin/src/lib/briefing.js +305 -0
  63. package/agent-spine-plugin/src/lib/catalog.js +142 -0
  64. package/agent-spine-plugin/src/lib/channel-runtime.js +665 -0
  65. package/agent-spine-plugin/src/lib/context.js +154 -0
  66. package/agent-spine-plugin/src/lib/continuity.js +333 -0
  67. package/agent-spine-plugin/src/lib/coordination.js +577 -0
  68. package/agent-spine-plugin/src/lib/documents.js +199 -0
  69. package/agent-spine-plugin/src/lib/feed-transport.js +497 -0
  70. package/agent-spine-plugin/src/lib/filesystem-retry.js +27 -0
  71. package/agent-spine-plugin/src/lib/gateway-runtime.js +760 -0
  72. package/agent-spine-plugin/src/lib/graph.js +284 -0
  73. package/agent-spine-plugin/src/lib/https-transport.js +392 -0
  74. package/agent-spine-plugin/src/lib/indexed-memory-offline.js +40 -0
  75. package/agent-spine-plugin/src/lib/indexed-memory.js +281 -0
  76. package/agent-spine-plugin/src/lib/learning.js +645 -0
  77. package/agent-spine-plugin/src/lib/object-transport.js +206 -0
  78. package/agent-spine-plugin/src/lib/paths.js +60 -0
  79. package/agent-spine-plugin/src/lib/peer-transport.js +283 -0
  80. package/agent-spine-plugin/src/lib/persona-runtime.js +503 -0
  81. package/agent-spine-plugin/src/lib/runtime.js +13 -0
  82. package/agent-spine-plugin/src/lib/selfstarter.js +819 -0
  83. package/agent-spine-plugin/src/lib/sharing.js +969 -0
  84. package/agent-spine-plugin/src/lib/source-roots.js +451 -0
  85. package/agent-spine-plugin/src/lib/sqlite-transport.js +501 -0
  86. package/agent-spine-plugin/src/lib/telegram-adapter.js +119 -0
  87. package/agent-spine-plugin/src/lib/voice-runtime.js +39 -0
  88. package/agent-spine-plugin/src/mcp.js +526 -0
  89. package/agent-spine-plugin/src/version.js +1 -0
  90. package/agent-spine-plugin/src/worker.js +178 -0
  91. package/bin/identity-context-policy.cjs +51 -1
  92. package/bin/launcher-runtime.js +22 -1
  93. package/bin/plugin-bootstrap.js +68 -27
  94. package/bin/startup-preferences.cjs +130 -0
  95. package/bin/turn-thinking-policy.cjs +5 -4
  96. package/bin/turn-tool-performance-policy.cjs +15 -2
  97. package/bin/update-notice.js +104 -43
  98. package/blun.mjs +108 -32
  99. package/package.json +2 -1
@@ -0,0 +1,308 @@
1
+ import { canonicalPath, isInside } from "./paths.js";
2
+ import { buildCatalog, saveCatalog, verifyCatalog } from "./catalog.js";
3
+ import { loadGraph } from "./graph.js";
4
+ import { attentionFindings, inspectAttention } from "./attention.js";
5
+ import { inspectLearning, learningFindings } from "./learning.js";
6
+ import { coordinationFindings, delegationPolicyFindings, inspectCoordination } from "./coordination.js";
7
+ import { inspectSharing, sharingAuthenticationFindings, sharingFindings } from "./sharing.js";
8
+ import { inspectSignerRegistry, inspectTrust, trustFindings } from "./authentication.js";
9
+ import { resolveContext } from "./context.js";
10
+ import { sessionBriefing } from "./briefing.js";
11
+ import { inspectHttpsFeedState } from "./feed-transport.js";
12
+ import { continuityFindings, inspectContinuity } from "./continuity.js";
13
+ import {
14
+ executionPolicyFindings, inspectSelfstarter, selfstarterFindings
15
+ } from "./selfstarter.js";
16
+ import {
17
+ channelPolicyFindings, channelRuntimeFindings, inspectChannelRuntime
18
+ } from "./channel-runtime.js";
19
+ import { inspectPersonaRuntime, personaRuntimeFindings } from "./persona-runtime.js";
20
+ import { gatewayHealthFindings, gatewayRuntimeFindings, inspectGatewayRuntime } from "./gateway-runtime.js";
21
+ import { fileURLToPath } from "node:url";
22
+ import { checkHosts } from "../../scripts/check-hosts.js";
23
+ import { resolveHostSourceCatalog } from "./source-roots.js";
24
+
25
+ function gate(id, name, ok, detail, severity = "error") {
26
+ return { id, name, ok, severity, detail };
27
+ }
28
+
29
+ function authorityViolations(graph, attention, learning, continuity, coordination, sharing, trust, registry, feedState) {
30
+ const records = [
31
+ ...graph.edges,
32
+ ...graph.annotations,
33
+ ...graph.entities,
34
+ ...graph.entityEdges,
35
+ ...graph.history,
36
+ ...graph.history.map((entry) => entry.value).filter(Boolean),
37
+ ...attention.signals,
38
+ ...attention.activities,
39
+ ...attention.events,
40
+ ...attention.receipts,
41
+ ...attention.history,
42
+ ...attention.history.map((entry) => entry.value).filter(Boolean),
43
+ ...learning.candidates,
44
+ ...learning.candidates.flatMap((candidate) => [
45
+ ...(candidate.evidence || []), candidate.review, candidate.rollback
46
+ ]).filter(Boolean),
47
+ ...learning.history,
48
+ ...learning.history.map((entry) => entry.value).filter(Boolean),
49
+ ...continuity.signals,
50
+ ...continuity.history,
51
+ ...coordination.tasks,
52
+ ...coordination.history,
53
+ ...coordination.history.map((entry) => entry.value).filter(Boolean),
54
+ ...sharing.records.flatMap((record) => [record, record.event, record.review, record.rollback]).filter(Boolean),
55
+ ...sharing.history,
56
+ ...sharing.history.flatMap((entry) => [entry.value, entry.value?.event, entry.value?.review, entry.value?.rollback]).filter(Boolean),
57
+ ...trust.records.flatMap((record) => [record, record.publicIdentity]).filter(Boolean),
58
+ ...trust.history.flatMap((entry) => [entry, entry.value, entry.value?.publicIdentity]).filter(Boolean),
59
+ ...registry.signers.flatMap((record) => [record, record.publicIdentity]).filter(Boolean),
60
+ ...registry.history.flatMap((entry) => [entry, entry.value]).filter(Boolean),
61
+ ...feedState.feeds,
62
+ ...feedState.history
63
+ ];
64
+ return records.filter((record) => record.authority !== "context-only");
65
+ }
66
+
67
+ function forbiddenEntityKeys(graph) {
68
+ const forbidden = /"(?:permissions?|rights?|authorization|credentials?|secrets?|tokens?|api[-_]?keys?)"\s*:/i;
69
+ const historicalEntities = graph.history
70
+ .filter((entry) => entry.kind === "entity")
71
+ .map((entry) => entry.value);
72
+ return [...graph.entities, ...historicalEntities].filter((entity) => forbidden.test(JSON.stringify(entity?.attributes || {})));
73
+ }
74
+
75
+ export async function runAudit(root = process.cwd(), { host = null } = {}) {
76
+ let sourceResolution = null;
77
+ let sourceResolutionError = null;
78
+ let resolvedHostSources = null;
79
+ if (["claude", "codex"].includes(host)) {
80
+ try {
81
+ resolvedHostSources = await resolveHostSourceCatalog({ host, cwd: root });
82
+ sourceResolution = resolvedHostSources.diagnostics;
83
+ }
84
+ catch (error) { sourceResolutionError = error.message; }
85
+ }
86
+ let hostIntegration = null;
87
+ let hostIntegrationError = null;
88
+ try {
89
+ hostIntegration = await checkHosts(fileURLToPath(new URL("../..", import.meta.url)));
90
+ } catch (error) {
91
+ hostIntegrationError = error.message;
92
+ }
93
+ const before = resolvedHostSources?.catalog || (sourceResolutionError
94
+ ? {
95
+ schema: "agentspine.catalog/v1", generatedAt: new Date().toISOString(), root: await canonicalPath(root),
96
+ preservation: "source-files-are-read-only", documents: [], conflicts: [],
97
+ summary: { total: 0, protected: 0, conflicts: 0, byLayer: {} }
98
+ }
99
+ : await buildCatalog(root));
100
+ const catalog = before;
101
+ const catalogPath = await saveCatalog(catalog);
102
+ const { graph, graphPath } = await loadGraph(before.root, catalog);
103
+ const { attention, attentionPath, error: attentionLoadError } = await inspectAttention(before.root, catalog);
104
+ const { learning, learningPath, error: learningLoadError } = await inspectLearning(before.root, catalog);
105
+ const { continuity, continuityPath, error: continuityLoadError } = await inspectContinuity(before.root, catalog);
106
+ const {
107
+ policy, coordination, policyPath, coordinationPath, errors: coordinationLoadErrors
108
+ } = await inspectCoordination(before.root, catalog);
109
+ const {
110
+ policy: executionPolicy, state: selfstarter, executionPolicyPath, selfstarterPath,
111
+ errors: selfstarterLoadErrors
112
+ } = await inspectSelfstarter(before.root, catalog);
113
+ const {
114
+ policy: channelPolicy, runtime: channelRuntime, channelPolicyPath, channelRuntimePath,
115
+ errors: channelLoadErrors
116
+ } = await inspectChannelRuntime(before.root, catalog);
117
+ const {
118
+ policy: personaPolicy, runtime: personaRuntime, personaPolicyPath, personaRuntimePath,
119
+ errors: personaLoadErrors
120
+ } = await inspectPersonaRuntime(before.root, catalog);
121
+ const {
122
+ policy: gatewayPolicy, runtime: gatewayRuntime, gatewayPolicyPath, gatewayRuntimePath,
123
+ errors: gatewayLoadErrors
124
+ } = await inspectGatewayRuntime(before.root, catalog);
125
+ const { sharing, sharingPath, error: sharingLoadError } = await inspectSharing(before.root, catalog);
126
+ const { trust, trustPath, error: trustLoadError } = await inspectTrust(before.root, catalog);
127
+ const { registry, registryPath, signerDirectory, errors: signerErrors } = await inspectSignerRegistry(before.root, catalog);
128
+ const { state: feedState, statePath: feedStatePath, error: feedStateError } = await inspectHttpsFeedState(before.root);
129
+ const context = await resolveContext({ root: before.root, cwd: before.root, host: "generic", maxBytes: 16384, includeContent: true, catalog });
130
+ let briefing = null;
131
+ let briefingError = null;
132
+ try {
133
+ briefing = await sessionBriefing({
134
+ root: before.root, cwd: before.root, host: host || "generic", maxBytes: 16384,
135
+ includePrivate: false, focusActive: true, includeSourceContent: true,
136
+ catalog: resolvedHostSources?.catalog || null, sourceDiagnostics: sourceResolution
137
+ });
138
+ } catch (error) {
139
+ briefingError = error.message;
140
+ }
141
+ const verification = ["claude", "codex"].includes(host)
142
+ ? { ok: !sourceResolutionError, reason: sourceResolutionError ? "host-native-resolution-failed" : "host-native-rescan" }
143
+ : await verifyCatalog(before.root);
144
+ const after = resolvedHostSources
145
+ ? (await resolveHostSourceCatalog({ host, cwd: root })).catalog
146
+ : sourceResolutionError ? before : await buildCatalog(before.root);
147
+ const beforeHashes = new Map(before.documents.map((document) => [document.relativePath, document.sha256]));
148
+ const byteStable = after.documents.length === before.documents.length && after.documents.every((document) => beforeHashes.get(document.relativePath) === document.sha256);
149
+ const brokenLinks = catalog.conflicts.filter((conflict) => conflict.type === "broken-link");
150
+ const reviewConflicts = catalog.conflicts.filter((conflict) => conflict.type !== "broken-link");
151
+ const authority = authorityViolations(graph, attention, learning, continuity, coordination, sharing, trust, registry, feedState);
152
+ const forbidden = forbiddenEntityKeys(graph);
153
+ const privacyValues = new Set(["private", "shared", "group"]);
154
+ const privateRecords = [
155
+ ...graph.entities,
156
+ ...graph.entityEdges,
157
+ ...graph.history,
158
+ ...graph.history.map((entry) => entry.value).filter((value) => value && "privacy" in value),
159
+ ...attention.signals,
160
+ ...attention.activities,
161
+ ...attention.events,
162
+ ...attention.history,
163
+ ...attention.history.map((entry) => entry.value).filter((value) => value && "privacy" in value),
164
+ ...learning.candidates,
165
+ ...learning.history,
166
+ ...learning.history.map((entry) => entry.value).filter((value) => value && "privacy" in value),
167
+ ...coordination.tasks,
168
+ ...coordination.history,
169
+ ...coordination.history.map((entry) => entry.value).filter((value) => value && "privacy" in value),
170
+ ...sharing.records.map((record) => ({ ...record, privacy: record.event?.privacy })),
171
+ ...sharing.history,
172
+ ...sharing.history.map((entry) => entry.value).filter(Boolean).map((record) => ({ ...record, privacy: record.event?.privacy }))
173
+ ];
174
+ const privacyInvalid = privateRecords.filter((record) => !privacyValues.has(record.privacy));
175
+ const knownGroups = new Set(graph.entities.filter((entity) => entity.kind === "group").map((entity) => entity.id));
176
+ const isKnownGroupMember = (record) => !record.entityId || record.entityId === record.groupId || graph.entityEdges.some((edge) => (
177
+ edge.relation === "member-of" && edge.privacy !== "private" && (
178
+ (edge.from === record.entityId && edge.to === record.groupId)
179
+ || (edge.to === record.entityId && edge.from === record.groupId)
180
+ )
181
+ ));
182
+ const attentionGroupInvalid = [
183
+ ...attention.signals,
184
+ ...attention.activities,
185
+ ...attention.events,
186
+ ...attention.history.map((entry) => entry.value).filter(Boolean)
187
+ ].filter((record) => record.privacy === "group" && (!knownGroups.has(record.groupId) || !isKnownGroupMember(record)));
188
+ const attentionConfigValid = typeof attention.config.enabled === "boolean"
189
+ && Number.isFinite(attention.config.minIntervalHours) && attention.config.minIntervalHours >= 1 && attention.config.minIntervalHours <= 720
190
+ && Number.isFinite(attention.config.entitySilenceDays) && attention.config.entitySilenceDays >= 1 && attention.config.entitySilenceDays <= 3650
191
+ && Number.isInteger(attention.config.heartbeatStaleMinutes) && attention.config.heartbeatStaleMinutes >= 1 && attention.config.heartbeatStaleMinutes <= 10080
192
+ && Number.isInteger(attention.config.maxItems) && attention.config.maxItems >= 1 && attention.config.maxItems <= 20
193
+ && (attention.config.quietHours === null || (
194
+ Number.isInteger(attention.config.quietHours?.start) && attention.config.quietHours.start >= 0 && attention.config.quietHours.start <= 23
195
+ && Number.isInteger(attention.config.quietHours?.end) && attention.config.quietHours.end >= 0 && attention.config.quietHours.end <= 23
196
+ && Number.isFinite(attention.config.quietHours?.utcOffsetMinutes)
197
+ && attention.config.quietHours.utcOffsetMinutes >= -720 && attention.config.quietHours.utcOffsetMinutes <= 840
198
+ ));
199
+ const learningIssues = learningFindings(learning, graph);
200
+ const attentionIssues = attentionFindings(attention);
201
+ if (attentionLoadError) attentionIssues.push(`unreadable-state:${attentionLoadError}`);
202
+ if (learningLoadError) learningIssues.push(`unreadable-state:${learningLoadError}`);
203
+ const continuityIssues = continuityFindings(continuity);
204
+ if (continuityLoadError) continuityIssues.push(`unreadable-state:${continuityLoadError}`);
205
+ const policyIssues = delegationPolicyFindings(policy, graph);
206
+ const coordinationIssues = coordinationFindings(coordination, policy, graph);
207
+ for (const error of coordinationLoadErrors) {
208
+ if (error.startsWith("policy:")) policyIssues.push(`unreadable-state:${error}`);
209
+ else coordinationIssues.push(`unreadable-state:${error}`);
210
+ }
211
+ const coordinationAuthorityIssues = coordinationIssues.filter((issue) => /assignment|policy-snapshot/.test(issue));
212
+ const coordinationContextIssues = coordinationIssues.filter((issue) => !coordinationAuthorityIssues.includes(issue));
213
+ const executionPolicyIssues = executionPolicyFindings(executionPolicy, graph, coordination);
214
+ const selfstarterIssues = selfstarterFindings(selfstarter, executionPolicy, graph, coordination);
215
+ for (const error of selfstarterLoadErrors) {
216
+ if (error.startsWith("policy:")) executionPolicyIssues.push(`unreadable-state:${error}`);
217
+ else selfstarterIssues.push(`unreadable-state:${error}`);
218
+ }
219
+ const selfstarterAuthorityIssues = selfstarterIssues.filter((issue) => /grant|policy|task-mismatch/.test(issue));
220
+ const selfstarterStateIssues = selfstarterIssues.filter((issue) => !selfstarterAuthorityIssues.includes(issue));
221
+ const channelPolicyIssues = channelPolicyFindings(channelPolicy, graph);
222
+ const channelRuntimeIssues = channelRuntimeFindings(channelRuntime, channelPolicy, graph)
223
+ .filter((issue) => !channelPolicyIssues.includes(issue));
224
+ for (const error of channelLoadErrors) {
225
+ if (error.startsWith("policy:")) channelPolicyIssues.push(`unreadable-state:${error}`);
226
+ else channelRuntimeIssues.push(`unreadable-state:${error}`);
227
+ }
228
+ const personaIssues = personaRuntimeFindings(personaPolicy, personaRuntime, graph);
229
+ const personaPolicyIssues = personaIssues.filter((issue) => /binding/.test(issue));
230
+ const personaStateIssues = personaIssues.filter((issue) => !personaPolicyIssues.includes(issue));
231
+ for (const error of personaLoadErrors) {
232
+ if (error.startsWith("policy:")) personaPolicyIssues.push(`unreadable-state:${error}`);
233
+ else personaStateIssues.push(`unreadable-state:${error}`);
234
+ }
235
+ const gatewayIssues = [...gatewayRuntimeFindings(gatewayPolicy, gatewayRuntime),
236
+ ...gatewayHealthFindings(gatewayPolicy, gatewayRuntime)];
237
+ const gatewayPolicyIssues = gatewayIssues.filter((issue) => /goal/.test(issue));
238
+ const gatewayStateIssues = gatewayIssues.filter((issue) => !gatewayPolicyIssues.includes(issue));
239
+ for (const error of gatewayLoadErrors) {
240
+ if (error.startsWith("policy:")) gatewayPolicyIssues.push(`unreadable-state:${error}`);
241
+ else gatewayStateIssues.push(`unreadable-state:${error}`);
242
+ }
243
+ const sharingIssues = sharingFindings(sharing, graph);
244
+ if (sharingLoadError) sharingIssues.push(`unreadable-state:${sharingLoadError}`);
245
+ const authenticationIssues = [
246
+ ...trustFindings(trust),
247
+ ...sharingAuthenticationFindings(sharing, trust)
248
+ ];
249
+ if (trustLoadError) authenticationIssues.push(`unreadable-trust:${trustLoadError}`);
250
+ authenticationIssues.push(...signerErrors);
251
+ if (feedStateError) authenticationIssues.push(`unreadable-feed-state:${feedStateError}`);
252
+ const sharingAuthorityIssues = sharingIssues.filter((issue) => /authority|unsafe/.test(issue));
253
+ const sharingContextIssues = sharingIssues.filter((issue) => !sharingAuthorityIssues.includes(issue));
254
+ const nativeMapped = catalog.documents.filter((document) => document.hosts.some((host) => host !== "generic"));
255
+ const loadedBytes = context.documents.filter((document) => document.loaded).reduce((sum, document) => sum + document.bytes, 0);
256
+ const briefingBytes = briefing ? Buffer.byteLength(JSON.stringify(briefing)) : null;
257
+ const briefingBudgetValid = briefing !== null && briefingBytes === briefing.budget.usedBytes
258
+ && briefingBytes <= briefing.budget.maxBytes;
259
+
260
+ const gates = [
261
+ gate(1, "Runtime", Number(process.versions.node.split(".")[0]) >= 20 && hostIntegration?.ok === true, hostIntegrationError
262
+ ? `Node ${process.versions.node}; host integration failed closed: ${hostIntegrationError}`
263
+ : `Node ${process.versions.node}; one versioned MCP server and lifecycle hook set per host`),
264
+ gate(2, "Discovery", catalog.schema === "agentspine.catalog/v1"
265
+ && (!host || (sourceResolution?.status === "loaded" && !sourceResolutionError)), sourceResolutionError
266
+ ? `${catalog.documents.length} project documents; host-native source resolution failed closed: ${sourceResolutionError}`
267
+ : sourceResolution ? `${sourceResolution.scopes.user} user, ${sourceResolution.scopes.project} project, and ${sourceResolution.scopes["project-memory"]} memory sources; broad home scan disabled`
268
+ : `${catalog.documents.length} Markdown documents indexed`),
269
+ gate(3, "External state", !isInside(catalog.root, catalogPath) && !isInside(catalog.root, graphPath) && !isInside(catalog.root, attentionPath) && !isInside(catalog.root, learningPath) && !isInside(catalog.root, continuityPath) && !isInside(catalog.root, policyPath) && !isInside(catalog.root, coordinationPath) && !isInside(catalog.root, executionPolicyPath) && !isInside(catalog.root, selfstarterPath) && !isInside(catalog.root, channelPolicyPath) && !isInside(catalog.root, channelRuntimePath) && !isInside(catalog.root, personaPolicyPath) && !isInside(catalog.root, personaRuntimePath) && !isInside(catalog.root, gatewayPolicyPath) && !isInside(catalog.root, gatewayRuntimePath) && !isInside(catalog.root, sharingPath) && !isInside(catalog.root, trustPath) && !isInside(catalog.root, registryPath) && !isInside(catalog.root, signerDirectory) && !isInside(catalog.root, feedStatePath), `State remains outside ${catalog.root}`),
270
+ gate(4, "Native hierarchy", nativeMapped.every((document) => document.hosts.length > 0), `${nativeMapped.length} host-native documents mapped`),
271
+ gate(5, "Link integrity", brokenLinks.length === 0, brokenLinks.length ? `${brokenLinks.length} broken Markdown links` : "All indexed Markdown links resolve"),
272
+ gate(6, "Conflict visibility", Array.isArray(catalog.conflicts), `${reviewConflicts.length} precedence or classification findings exposed`, "warning"),
273
+ gate(7, "Authority boundary", authority.length === 0 && forbidden.length === 0 && policyIssues.length === 0 && coordinationAuthorityIssues.length === 0 && executionPolicyIssues.length === 0 && selfstarterAuthorityIssues.length === 0 && channelPolicyIssues.length === 0 && personaPolicyIssues.length === 0 && gatewayPolicyIssues.length === 0 && sharingAuthorityIssues.length === 0, `${authority.length} context authority violations; ${forbidden.length} forbidden entity records; ${policyIssues.length} delegation policy findings; ${coordinationAuthorityIssues.length} assignment findings; ${executionPolicyIssues.length} execution policy findings; ${selfstarterAuthorityIssues.length} self-starter authority findings; ${channelPolicyIssues.length} channel policy findings; ${personaPolicyIssues.length} persona policy findings; ${gatewayPolicyIssues.length} gateway policy findings; ${sharingAuthorityIssues.length} shared authority findings`),
274
+ gate(8, "Context privacy", privacyInvalid.length === 0 && attentionGroupInvalid.length === 0 && attentionConfigValid && attentionIssues.length === 0 && learningIssues.length === 0 && continuityIssues.length === 0 && coordinationContextIssues.length === 0 && selfstarterStateIssues.length === 0 && channelRuntimeIssues.length === 0 && personaStateIssues.length === 0 && gatewayStateIssues.length === 0 && sharingContextIssues.length === 0 && authenticationIssues.length === 0, `${graph.entities.length} entities, ${graph.entityEdges.length} relationships, ${attention.signals.length} attention cues, ${attention.events.length} lifecycle events, ${learning.candidates.length} learning records, ${continuity.signals.length} continuity signals, ${coordination.tasks.length} coordination items, ${selfstarter.jobs.length} self-starter jobs, ${channelRuntime.events.length} channel events, ${personaRuntime.personas.length} authenticated personas, ${gatewayRuntime.queue.length} gateway queue items, ${gatewayRuntime.outbox.length} delivery records, ${sharing.records.length} shared records, ${trust.records.length} trusted keys, ${registry.signers.length} local signers, and ${feedState.feeds.length} feed receipts checked`),
275
+ gate(9, "Context budget", loadedBytes <= context.budget.maxBytes && briefingBudgetValid, briefingError
276
+ ? `${loadedBytes}/${context.budget.maxBytes} source bytes; briefing failed closed: ${briefingError}`
277
+ : `${loadedBytes}/${context.budget.maxBytes} source bytes; ${briefingBytes}/${briefing.budget.maxBytes} briefing bytes`),
278
+ gate(10, "Byte preservation", byteStable && verification.ok, verification.ok ? "Sources remained byte-for-byte unchanged" : "Source drift detected")
279
+ ];
280
+ return {
281
+ schema: "agentspine.audit/v1",
282
+ root: catalog.root,
283
+ ok: gates.every((item) => item.ok || item.severity === "warning"),
284
+ passed: gates.filter((item) => item.ok).length,
285
+ total: gates.length,
286
+ gates,
287
+ catalogPath,
288
+ graphPath,
289
+ attentionPath,
290
+ learningPath,
291
+ continuityPath,
292
+ policyPath,
293
+ coordinationPath,
294
+ executionPolicyPath,
295
+ selfstarterPath,
296
+ channelPolicyPath,
297
+ channelRuntimePath,
298
+ personaPolicyPath,
299
+ personaRuntimePath,
300
+ gatewayPolicyPath,
301
+ gatewayRuntimePath,
302
+ sharingPath,
303
+ trustPath,
304
+ registryPath,
305
+ feedStatePath,
306
+ sourceResolution
307
+ };
308
+ }