blun-king-cli 9.1.563 → 9.1.565

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 (85) hide show
  1. package/agent-spine-plugin/.claude-plugin/marketplace.json +20 -20
  2. package/agent-spine-plugin/.claude-plugin/plugin.json +14 -14
  3. package/agent-spine-plugin/.codex-plugin/plugin.json +34 -34
  4. package/agent-spine-plugin/.mcp.json +8 -8
  5. package/agent-spine-plugin/CONTRIBUTING.md +52 -0
  6. package/agent-spine-plugin/LICENSE +186 -186
  7. package/agent-spine-plugin/README.md +394 -0
  8. package/agent-spine-plugin/SECURITY.md +47 -0
  9. package/agent-spine-plugin/assets/agentspine-banner.svg +32 -32
  10. package/agent-spine-plugin/bin/agentspine-mcp.js +4 -4
  11. package/agent-spine-plugin/bin/agentspine.js +7 -7
  12. package/agent-spine-plugin/blun.plugin.json +33 -33
  13. package/agent-spine-plugin/hooks/codex.json +47 -47
  14. package/agent-spine-plugin/hooks/hooks.json +106 -106
  15. package/agent-spine-plugin/hooks/version.json +5 -5
  16. package/agent-spine-plugin/package.json +69 -69
  17. package/agent-spine-plugin/scripts/check-hosts.js +199 -199
  18. package/agent-spine-plugin/skill/SKILL.md +76 -76
  19. package/agent-spine-plugin/skills/agent-spine/SKILL.md +85 -85
  20. package/agent-spine-plugin/src/cli.js +1488 -1442
  21. package/agent-spine-plugin/src/hook.js +886 -812
  22. package/agent-spine-plugin/src/index.js +93 -93
  23. package/agent-spine-plugin/src/lib/acceptance.js +333 -333
  24. package/agent-spine-plugin/src/lib/attention.js +755 -755
  25. package/agent-spine-plugin/src/lib/audit.js +351 -342
  26. package/agent-spine-plugin/src/lib/authentication.js +515 -515
  27. package/agent-spine-plugin/src/lib/briefing.js +317 -317
  28. package/agent-spine-plugin/src/lib/catalog.js +167 -167
  29. package/agent-spine-plugin/src/lib/channel-runtime.js +665 -665
  30. package/agent-spine-plugin/src/lib/context.js +154 -154
  31. package/agent-spine-plugin/src/lib/continuity.js +338 -338
  32. package/agent-spine-plugin/src/lib/coordination.js +577 -577
  33. package/agent-spine-plugin/src/lib/documents.js +217 -217
  34. package/agent-spine-plugin/src/lib/feed-transport.js +499 -499
  35. package/agent-spine-plugin/src/lib/filesystem-retry.js +32 -32
  36. package/agent-spine-plugin/src/lib/gateway-runtime.js +1119 -760
  37. package/agent-spine-plugin/src/lib/graph.js +337 -337
  38. package/agent-spine-plugin/src/lib/hook-audit.js +29 -0
  39. package/agent-spine-plugin/src/lib/https-transport.js +392 -392
  40. package/agent-spine-plugin/src/lib/indexed-memory-offline.js +40 -40
  41. package/agent-spine-plugin/src/lib/indexed-memory.js +281 -281
  42. package/agent-spine-plugin/src/lib/learning.js +6923 -6466
  43. package/agent-spine-plugin/src/lib/object-transport.js +206 -206
  44. package/agent-spine-plugin/src/lib/owned-file-lock.js +143 -143
  45. package/agent-spine-plugin/src/lib/paths.js +109 -109
  46. package/agent-spine-plugin/src/lib/peer-transport.js +283 -283
  47. package/agent-spine-plugin/src/lib/persona-runtime.js +581 -581
  48. package/agent-spine-plugin/src/lib/preflight.js +702 -702
  49. package/agent-spine-plugin/src/lib/runtime.js +13 -13
  50. package/agent-spine-plugin/src/lib/selfstarter.js +892 -819
  51. package/agent-spine-plugin/src/lib/sharing.js +969 -969
  52. package/agent-spine-plugin/src/lib/source-roots.js +529 -482
  53. package/agent-spine-plugin/src/lib/sqlite-transport.js +501 -501
  54. package/agent-spine-plugin/src/lib/telegram-adapter.js +119 -119
  55. package/agent-spine-plugin/src/lib/voice-runtime.js +39 -39
  56. package/agent-spine-plugin/src/mcp.js +597 -572
  57. package/agent-spine-plugin/src/version.js +1 -1
  58. package/agent-spine-plugin/src/worker.js +202 -195
  59. package/bin/active-steer-priority-policy.cjs +24 -0
  60. package/bin/launcher-runtime.js +8 -1
  61. package/bin/mnemo-tool-agent-policy.cjs +22 -0
  62. package/bin/thinking-activity-status-policy.cjs +132 -0
  63. package/bin/thinking-only-guard.cjs +75 -0
  64. package/bin/tool-call-loop-policy.cjs +53 -0
  65. package/bin/turn-thinking-policy.cjs +25 -1
  66. package/blun.mjs +554 -64
  67. package/package.json +4 -1
  68. package/standard-skills/translate-native/LICENSE +21 -21
  69. package/standard-skills/translate-native/references/evaluation-protocol.md +95 -95
  70. package/standard-skills/translate-native/references/native-orthography.md +79 -79
  71. package/standard-skills/translate-native/references/native-translation-standard.md +94 -94
  72. package/standard-skills/translate-native/references/structured-content.md +72 -72
  73. package/standard-skills/translate-native/references/translationese-review.md +77 -77
  74. package/standard-skills/translate-native/scripts/blun_language_guard.py +697 -697
  75. package/standard-skills/translate-native/scripts/check_diacritics.py +353 -353
  76. package/standard-skills/translate-native/scripts/guard_service_client.py +264 -264
  77. package/standard-skills/translate-native/scripts/language_gateway.py +62 -62
  78. package/standard-skills/translate-native/scripts/language_quality.py +377 -377
  79. package/standard-skills/translate-native/scripts/pre_output_guard.py +64 -64
  80. package/standard-skills/translate-native/scripts/translation_guard.py +916 -916
  81. package/standard-tools/language-guard/blun_language_guard.py +697 -697
  82. package/standard-tools/language-guard/check_diacritics.py +353 -353
  83. package/standard-tools/language-guard/guard_service_client.py +264 -264
  84. package/standard-tools/language-guard/language_quality.py +377 -377
  85. package/standard-tools/language-guard/translation_guard.py +916 -916
@@ -1,342 +1,351 @@
1
- import { canonicalPath, statePathIsScanExcluded } 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
- import { preflightStatus } from "./preflight.js";
25
-
26
- function gate(id, name, ok, detail, severity = "error") {
27
- return { id, name, ok, severity, detail };
28
- }
29
-
30
- function authorityViolations(graph, attention, learning, continuity, coordination, sharing, trust, registry, feedState) {
31
- const records = [
32
- ...graph.edges,
33
- ...graph.annotations,
34
- ...graph.entities,
35
- ...graph.entityEdges,
36
- ...graph.history,
37
- ...graph.history.map((entry) => entry.value).filter(Boolean),
38
- ...attention.signals,
39
- ...attention.activities,
40
- ...attention.events,
41
- ...attention.receipts,
42
- ...attention.history,
43
- ...attention.history.map((entry) => entry.value).filter(Boolean),
44
- ...learning.candidates,
45
- ...learning.candidates.flatMap((candidate) => [
46
- ...(candidate.evidence || []), candidate.review, candidate.rollback
47
- ]).filter(Boolean),
48
- ...(learning.outcomes || []),
49
- ...(learning.outcomes || []).map((outcome) => outcome.measurement).filter(Boolean),
50
- ...(learning.measurements || []),
51
- ...(learning.measurements || []).map((measurement) => measurement.measurement).filter(Boolean),
52
- ...(learning.measurementLineage || []),
53
- ...(learning.applications || []),
54
- ...(learning.evaluations || []),
55
- ...(learning.evaluatorRegistry || []),
56
- ...(learning.evaluationBindings || []),
57
- ...(learning.validationLeases || []),
58
- ...(learning.trialFailures || []),
59
- ...(learning.trialFailureRevocations || []),
60
- ...(learning.trialRetryExhaustions || []),
61
- ...(learning.evaluationRevocations || []),
62
- ...(learning.validationRevocations || []),
63
- ...(learning.evidenceRevocations || []),
64
- ...(learning.measurementRevocations || []),
65
- ...(learning.applicationRevocations || []),
66
- ...(learning.deliveryRevocations || []),
67
- ...(learning.outcomeRevocations || []),
68
- ...learning.history,
69
- ...learning.history.map((entry) => entry.value).filter(Boolean),
70
- ...continuity.signals,
71
- ...continuity.history,
72
- ...coordination.tasks,
73
- ...coordination.history,
74
- ...coordination.history.map((entry) => entry.value).filter(Boolean),
75
- ...sharing.records.flatMap((record) => [record, record.event, record.review, record.rollback]).filter(Boolean),
76
- ...sharing.history,
77
- ...sharing.history.flatMap((entry) => [entry.value, entry.value?.event, entry.value?.review, entry.value?.rollback]).filter(Boolean),
78
- ...trust.records.flatMap((record) => [record, record.publicIdentity]).filter(Boolean),
79
- ...trust.history.flatMap((entry) => [entry, entry.value, entry.value?.publicIdentity]).filter(Boolean),
80
- ...registry.signers.flatMap((record) => [record, record.publicIdentity]).filter(Boolean),
81
- ...registry.history.flatMap((entry) => [entry, entry.value]).filter(Boolean),
82
- ...feedState.feeds,
83
- ...feedState.history
84
- ];
85
- return records.filter((record) => record.authority !== "context-only");
86
- }
87
-
88
- function forbiddenEntityKeys(graph) {
89
- const forbidden = /"(?:permissions?|rights?|authorization|credentials?|secrets?|tokens?|api[-_]?keys?)"\s*:/i;
90
- const historicalEntities = graph.history
91
- .filter((entry) => entry.kind === "entity")
92
- .map((entry) => entry.value);
93
- return [...graph.entities, ...historicalEntities].filter((entity) => forbidden.test(JSON.stringify(entity?.attributes || {})));
94
- }
95
-
96
- export async function runAudit(root = process.cwd(), { host = null } = {}) {
97
- let preflight = null;
98
- let preflightError = null;
99
- try { preflight = await preflightStatus(); } catch (error) { preflightError = error.message; }
100
- let sourceResolution = null;
101
- let sourceResolutionError = null;
102
- let resolvedHostSources = null;
103
- if (["claude", "codex"].includes(host)) {
104
- try {
105
- resolvedHostSources = await resolveHostSourceCatalog({ host, cwd: root });
106
- sourceResolution = resolvedHostSources.diagnostics;
107
- }
108
- catch (error) { sourceResolutionError = error.message; }
109
- }
110
- let hostIntegration = null;
111
- let hostIntegrationError = null;
112
- try {
113
- hostIntegration = await checkHosts(fileURLToPath(new URL("../..", import.meta.url)));
114
- } catch (error) {
115
- hostIntegrationError = error.message;
116
- }
117
- const before = resolvedHostSources?.catalog || (sourceResolutionError
118
- ? {
119
- schema: "agentspine.catalog/v1", generatedAt: new Date().toISOString(), root: await canonicalPath(root),
120
- preservation: "source-files-are-read-only", documents: [], conflicts: [],
121
- summary: { total: 0, protected: 0, conflicts: 0, byLayer: {} }
122
- }
123
- : await buildCatalog(root));
124
- const catalog = before;
125
- const catalogPath = await saveCatalog(catalog);
126
- const { graph, graphPath } = await loadGraph(before.root, catalog);
127
- const { attention, attentionPath, error: attentionLoadError } = await inspectAttention(before.root, catalog);
128
- const { learning, learningPath, error: learningLoadError } = await inspectLearning(before.root, catalog);
129
- const { continuity, continuityPath, error: continuityLoadError } = await inspectContinuity(before.root, catalog);
130
- const {
131
- policy, coordination, policyPath, coordinationPath, errors: coordinationLoadErrors
132
- } = await inspectCoordination(before.root, catalog);
133
- const {
134
- policy: executionPolicy, state: selfstarter, executionPolicyPath, selfstarterPath,
135
- errors: selfstarterLoadErrors
136
- } = await inspectSelfstarter(before.root, catalog);
137
- const {
138
- policy: channelPolicy, runtime: channelRuntime, channelPolicyPath, channelRuntimePath,
139
- errors: channelLoadErrors
140
- } = await inspectChannelRuntime(before.root, catalog);
141
- const {
142
- policy: personaPolicy, runtime: personaRuntime, personaPolicyPath, personaRuntimePath,
143
- errors: personaLoadErrors
144
- } = await inspectPersonaRuntime(before.root, catalog);
145
- const {
146
- policy: gatewayPolicy, runtime: gatewayRuntime, gatewayPolicyPath, gatewayRuntimePath,
147
- errors: gatewayLoadErrors
148
- } = await inspectGatewayRuntime(before.root, catalog);
149
- const { sharing, sharingPath, error: sharingLoadError } = await inspectSharing(before.root, catalog);
150
- const { trust, trustPath, error: trustLoadError } = await inspectTrust(before.root, catalog);
151
- const { registry, registryPath, signerDirectory, errors: signerErrors } = await inspectSignerRegistry(before.root, catalog);
152
- const { state: feedState, statePath: feedStatePath, error: feedStateError } = await inspectHttpsFeedState(before.root);
153
- const context = await resolveContext({ root: before.root, cwd: before.root, host: "generic", maxBytes: 16384, includeContent: true, catalog });
154
- let briefing = null;
155
- let briefingError = null;
156
- try {
157
- briefing = await sessionBriefing({
158
- root: before.root, cwd: before.root, host: host || "generic", maxBytes: 16384,
159
- includePrivate: false, focusActive: true, includeSourceContent: true,
160
- catalog: resolvedHostSources?.catalog || null, sourceDiagnostics: sourceResolution
161
- });
162
- } catch (error) {
163
- briefingError = error.message;
164
- }
165
- const verification = ["claude", "codex"].includes(host)
166
- ? { ok: !sourceResolutionError, reason: sourceResolutionError ? "host-native-resolution-failed" : "host-native-rescan" }
167
- : await verifyCatalog(before.root);
168
- const after = resolvedHostSources
169
- ? (await resolveHostSourceCatalog({ host, cwd: root })).catalog
170
- : sourceResolutionError ? before : await buildCatalog(before.root);
171
- const beforeHashes = new Map(before.documents.map((document) => [document.relativePath, document.sha256]));
172
- const byteStable = after.documents.length === before.documents.length && after.documents.every((document) => beforeHashes.get(document.relativePath) === document.sha256);
173
- const brokenLinks = catalog.conflicts.filter((conflict) => conflict.type === "broken-link");
174
- const reviewConflicts = catalog.conflicts.filter((conflict) => conflict.type !== "broken-link");
175
- const authority = authorityViolations(graph, attention, learning, continuity, coordination, sharing, trust, registry, feedState);
176
- const forbidden = forbiddenEntityKeys(graph);
177
- const privacyValues = new Set(["private", "shared", "group"]);
178
- const privateRecords = [
179
- ...graph.entities,
180
- ...graph.entityEdges,
181
- ...graph.history,
182
- ...graph.history.map((entry) => entry.value).filter((value) => value && "privacy" in value),
183
- ...attention.signals,
184
- ...attention.activities,
185
- ...attention.events,
186
- ...attention.history,
187
- ...attention.history.map((entry) => entry.value).filter((value) => value && "privacy" in value),
188
- ...learning.candidates,
189
- ...learning.history,
190
- ...learning.history.map((entry) => entry.value).filter((value) => value && "privacy" in value),
191
- ...coordination.tasks,
192
- ...coordination.history,
193
- ...coordination.history.map((entry) => entry.value).filter((value) => value && "privacy" in value),
194
- ...sharing.records.map((record) => ({ ...record, privacy: record.event?.privacy })),
195
- ...sharing.history,
196
- ...sharing.history.map((entry) => entry.value).filter(Boolean).map((record) => ({ ...record, privacy: record.event?.privacy }))
197
- ];
198
- const privacyInvalid = privateRecords.filter((record) => !privacyValues.has(record.privacy));
199
- const knownGroups = new Set(graph.entities.filter((entity) => entity.kind === "group").map((entity) => entity.id));
200
- const isKnownGroupMember = (record) => !record.entityId || record.entityId === record.groupId || graph.entityEdges.some((edge) => (
201
- edge.relation === "member-of" && edge.privacy !== "private" && (
202
- (edge.from === record.entityId && edge.to === record.groupId)
203
- || (edge.to === record.entityId && edge.from === record.groupId)
204
- )
205
- ));
206
- const attentionGroupInvalid = [
207
- ...attention.signals,
208
- ...attention.activities,
209
- ...attention.events,
210
- ...attention.history.map((entry) => entry.value).filter(Boolean)
211
- ].filter((record) => record.privacy === "group" && (!knownGroups.has(record.groupId) || !isKnownGroupMember(record)));
212
- const attentionConfigValid = typeof attention.config.enabled === "boolean"
213
- && Number.isFinite(attention.config.minIntervalHours) && attention.config.minIntervalHours >= 1 && attention.config.minIntervalHours <= 720
214
- && Number.isFinite(attention.config.entitySilenceDays) && attention.config.entitySilenceDays >= 1 && attention.config.entitySilenceDays <= 3650
215
- && Number.isInteger(attention.config.heartbeatStaleMinutes) && attention.config.heartbeatStaleMinutes >= 1 && attention.config.heartbeatStaleMinutes <= 10080
216
- && Number.isInteger(attention.config.maxItems) && attention.config.maxItems >= 1 && attention.config.maxItems <= 20
217
- && (attention.config.quietHours === null || (
218
- Number.isInteger(attention.config.quietHours?.start) && attention.config.quietHours.start >= 0 && attention.config.quietHours.start <= 23
219
- && Number.isInteger(attention.config.quietHours?.end) && attention.config.quietHours.end >= 0 && attention.config.quietHours.end <= 23
220
- && Number.isFinite(attention.config.quietHours?.utcOffsetMinutes)
221
- && attention.config.quietHours.utcOffsetMinutes >= -720 && attention.config.quietHours.utcOffsetMinutes <= 840
222
- ));
223
- const learningIssues = learningFindings(learning, graph);
224
- const attentionIssues = attentionFindings(attention);
225
- if (attentionLoadError) attentionIssues.push(`unreadable-state:${attentionLoadError}`);
226
- if (learningLoadError) learningIssues.push(`unreadable-state:${learningLoadError}`);
227
- const continuityIssues = continuityFindings(continuity);
228
- if (continuityLoadError) continuityIssues.push(`unreadable-state:${continuityLoadError}`);
229
- const policyIssues = delegationPolicyFindings(policy, graph);
230
- const coordinationIssues = coordinationFindings(coordination, policy, graph);
231
- for (const error of coordinationLoadErrors) {
232
- if (error.startsWith("policy:")) policyIssues.push(`unreadable-state:${error}`);
233
- else coordinationIssues.push(`unreadable-state:${error}`);
234
- }
235
- const coordinationAuthorityIssues = coordinationIssues.filter((issue) => /assignment|policy-snapshot/.test(issue));
236
- const coordinationContextIssues = coordinationIssues.filter((issue) => !coordinationAuthorityIssues.includes(issue));
237
- const executionPolicyIssues = executionPolicyFindings(executionPolicy, graph, coordination);
238
- const selfstarterIssues = selfstarterFindings(selfstarter, executionPolicy, graph, coordination);
239
- for (const error of selfstarterLoadErrors) {
240
- if (error.startsWith("policy:")) executionPolicyIssues.push(`unreadable-state:${error}`);
241
- else selfstarterIssues.push(`unreadable-state:${error}`);
242
- }
243
- const selfstarterAuthorityIssues = selfstarterIssues.filter((issue) => /grant|policy|task-mismatch/.test(issue));
244
- const selfstarterStateIssues = selfstarterIssues.filter((issue) => !selfstarterAuthorityIssues.includes(issue));
245
- const channelPolicyIssues = channelPolicyFindings(channelPolicy, graph);
246
- const channelRuntimeIssues = channelRuntimeFindings(channelRuntime, channelPolicy, graph)
247
- .filter((issue) => !channelPolicyIssues.includes(issue));
248
- for (const error of channelLoadErrors) {
249
- if (error.startsWith("policy:")) channelPolicyIssues.push(`unreadable-state:${error}`);
250
- else channelRuntimeIssues.push(`unreadable-state:${error}`);
251
- }
252
- const personaIssues = personaRuntimeFindings(personaPolicy, personaRuntime, graph);
253
- const personaPolicyIssues = personaIssues.filter((issue) => /binding/.test(issue));
254
- const personaStateIssues = personaIssues.filter((issue) => !personaPolicyIssues.includes(issue));
255
- for (const error of personaLoadErrors) {
256
- if (error.startsWith("policy:")) personaPolicyIssues.push(`unreadable-state:${error}`);
257
- else personaStateIssues.push(`unreadable-state:${error}`);
258
- }
259
- const gatewayIssues = [...gatewayRuntimeFindings(gatewayPolicy, gatewayRuntime),
260
- ...gatewayHealthFindings(gatewayPolicy, gatewayRuntime)];
261
- const gatewayPolicyIssues = gatewayIssues.filter((issue) => /goal/.test(issue));
262
- const gatewayStateIssues = gatewayIssues.filter((issue) => !gatewayPolicyIssues.includes(issue));
263
- for (const error of gatewayLoadErrors) {
264
- if (error.startsWith("policy:")) gatewayPolicyIssues.push(`unreadable-state:${error}`);
265
- else gatewayStateIssues.push(`unreadable-state:${error}`);
266
- }
267
- const sharingIssues = sharingFindings(sharing, graph);
268
- if (sharingLoadError) sharingIssues.push(`unreadable-state:${sharingLoadError}`);
269
- const authenticationIssues = [
270
- ...trustFindings(trust),
271
- ...sharingAuthenticationFindings(sharing, trust)
272
- ];
273
- if (trustLoadError) authenticationIssues.push(`unreadable-trust:${trustLoadError}`);
274
- authenticationIssues.push(...signerErrors);
275
- if (feedStateError) authenticationIssues.push(`unreadable-feed-state:${feedStateError}`);
276
- const sharingAuthorityIssues = sharingIssues.filter((issue) => /authority|unsafe/.test(issue));
277
- const sharingContextIssues = sharingIssues.filter((issue) => !sharingAuthorityIssues.includes(issue));
278
- const nativeMapped = catalog.documents.filter((document) => document.hosts.some((host) => host !== "generic"));
279
- const loadedBytes = context.documents.filter((document) => document.loaded).reduce((sum, document) => sum + document.bytes, 0);
280
- const briefingBytes = briefing ? Buffer.byteLength(JSON.stringify(briefing)) : null;
281
- const briefingBudgetValid = briefing !== null && briefingBytes === briefing.budget.usedBytes
282
- && briefingBytes <= briefing.budget.maxBytes;
283
-
284
- const gates = [
285
- gate(1, "Runtime", Number(process.versions.node.split(".")[0]) >= 20 && hostIntegration?.ok === true, hostIntegrationError
286
- ? `Node ${process.versions.node}; host integration failed closed: ${hostIntegrationError}`
287
- : `Node ${process.versions.node}; one versioned MCP server and lifecycle hook set per host`),
288
- gate(2, "Discovery", catalog.schema === "agentspine.catalog/v1"
289
- && (!host || (sourceResolution?.status === "loaded" && !sourceResolutionError)), sourceResolutionError
290
- ? `${catalog.documents.length} project documents; host-native source resolution failed closed: ${sourceResolutionError}`
291
- : sourceResolution ? `${sourceResolution.scopes.user} user, ${sourceResolution.scopes.project} project, and ${sourceResolution.scopes["project-memory"]} memory sources; broad home scan disabled`
292
- : `${catalog.documents.length} Markdown documents indexed`),
293
- gate(3, "State isolation", [catalogPath, graphPath, attentionPath, learningPath, continuityPath,
294
- policyPath, coordinationPath, executionPolicyPath, selfstarterPath, channelPolicyPath,
295
- channelRuntimePath, personaPolicyPath, personaRuntimePath, gatewayPolicyPath, gatewayRuntimePath,
296
- sharingPath, trustPath, registryPath, signerDirectory, feedStatePath]
297
- .every((path) => statePathIsScanExcluded(catalog, path)),
298
- catalog.scanPolicy?.stateRoot === "excluded"
299
- ? `Authenticated state is excluded from the home-root source scan for ${catalog.root}`
300
- : `State remains outside ${catalog.root}`),
301
- gate(4, "Native hierarchy", nativeMapped.every((document) => document.hosts.length > 0), `${nativeMapped.length} host-native documents mapped`),
302
- gate(5, "Link integrity", brokenLinks.length === 0, brokenLinks.length ? `${brokenLinks.length} broken Markdown links` : "All indexed Markdown links resolve"),
303
- gate(6, "Conflict visibility", Array.isArray(catalog.conflicts), `${reviewConflicts.length} precedence or classification findings exposed`, "warning"),
304
- 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 && !preflightError, preflightError
305
- ? `preflight policy or receipt state failed closed: ${preflightError}`
306
- : `${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; preflight ${preflight.status}`),
307
- 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, ${(learning.evaluations || []).length} immutable evaluation contracts, ${(learning.evaluations || []).filter((item) => ["agentspine.learning-evaluation/v9", "agentspine.learning-evaluation/v10", "agentspine.learning-evaluation/v11", "agentspine.learning-evaluation/v12", "agentspine.learning-evaluation/v13", "agentspine.learning-evaluation/v14", "agentspine.learning-evaluation/v15", "agentspine.learning-evaluation/v16", "agentspine.learning-evaluation/v17", "agentspine.learning-evaluation/v18", "agentspine.learning-evaluation/v19", "agentspine.learning-evaluation/v20", "agentspine.learning-evaluation/v21", "agentspine.learning-evaluation/v22", "agentspine.learning-evaluation/v23", "agentspine.learning-evaluation/v24", "agentspine.learning-evaluation/v25"].includes(item.schema)).length} exact-target contracts, ${(learning.evaluations || []).filter((item) => ["agentspine.learning-evaluation/v8", "agentspine.learning-evaluation/v9", "agentspine.learning-evaluation/v10", "agentspine.learning-evaluation/v11", "agentspine.learning-evaluation/v12", "agentspine.learning-evaluation/v13", "agentspine.learning-evaluation/v14", "agentspine.learning-evaluation/v15", "agentspine.learning-evaluation/v16", "agentspine.learning-evaluation/v17", "agentspine.learning-evaluation/v18", "agentspine.learning-evaluation/v19", "agentspine.learning-evaluation/v20", "agentspine.learning-evaluation/v21", "agentspine.learning-evaluation/v22", "agentspine.learning-evaluation/v23", "agentspine.learning-evaluation/v24", "agentspine.learning-evaluation/v25"].includes(item.schema)).length} precommitted initial-trial contracts, ${(learning.evaluations || []).filter((item) => ["agentspine.learning-evaluation/v10", "agentspine.learning-evaluation/v11", "agentspine.learning-evaluation/v12", "agentspine.learning-evaluation/v13", "agentspine.learning-evaluation/v14", "agentspine.learning-evaluation/v15", "agentspine.learning-evaluation/v16", "agentspine.learning-evaluation/v17", "agentspine.learning-evaluation/v18", "agentspine.learning-evaluation/v19", "agentspine.learning-evaluation/v20", "agentspine.learning-evaluation/v21", "agentspine.learning-evaluation/v22", "agentspine.learning-evaluation/v23", "agentspine.learning-evaluation/v24", "agentspine.learning-evaluation/v25"].includes(item.schema)).length} deadline-bound contracts, ${(learning.evaluations || []).filter((item) => ["agentspine.learning-evaluation/v14", "agentspine.learning-evaluation/v15", "agentspine.learning-evaluation/v16", "agentspine.learning-evaluation/v17", "agentspine.learning-evaluation/v18", "agentspine.learning-evaluation/v19", "agentspine.learning-evaluation/v20", "agentspine.learning-evaluation/v21", "agentspine.learning-evaluation/v22", "agentspine.learning-evaluation/v23", "agentspine.learning-evaluation/v24", "agentspine.learning-evaluation/v25"].includes(item.schema)).length} staleness-bound contracts, ${(learning.evaluations || []).filter((item) => ["agentspine.learning-evaluation/v16", "agentspine.learning-evaluation/v17", "agentspine.learning-evaluation/v18", "agentspine.learning-evaluation/v19", "agentspine.learning-evaluation/v20", "agentspine.learning-evaluation/v21", "agentspine.learning-evaluation/v22", "agentspine.learning-evaluation/v23", "agentspine.learning-evaluation/v24", "agentspine.learning-evaluation/v25"].includes(item.schema)).length} promotion-bound contracts, ${(learning.evaluations || []).filter((item) => ["agentspine.learning-evaluation/v18", "agentspine.learning-evaluation/v19", "agentspine.learning-evaluation/v20", "agentspine.learning-evaluation/v21", "agentspine.learning-evaluation/v22", "agentspine.learning-evaluation/v23", "agentspine.learning-evaluation/v24", "agentspine.learning-evaluation/v25"].includes(item.schema)).length} candidate-admission contracts, ${(learning.evaluations || []).filter((item) => ["agentspine.learning-evaluation/v20", "agentspine.learning-evaluation/v21", "agentspine.learning-evaluation/v22", "agentspine.learning-evaluation/v23", "agentspine.learning-evaluation/v24", "agentspine.learning-evaluation/v25"].includes(item.schema)).length} candidate-evidence-cohort contracts, ${(learning.evaluations || []).filter((item) => ["agentspine.learning-evaluation/v22", "agentspine.learning-evaluation/v23", "agentspine.learning-evaluation/v24", "agentspine.learning-evaluation/v25"].includes(item.schema)).length} blocking-defect-bound contracts, ${(learning.evaluations || []).filter((item) => ["agentspine.learning-evaluation/v24", "agentspine.learning-evaluation/v25"].includes(item.schema)).length} evidence-source-bound contracts, ${(learning.evaluations || []).filter((item) => ["agentspine.learning-evaluation/v13", "agentspine.learning-evaluation/v15", "agentspine.learning-evaluation/v17", "agentspine.learning-evaluation/v19", "agentspine.learning-evaluation/v21", "agentspine.learning-evaluation/v23", "agentspine.learning-evaluation/v25"].includes(item.schema)).length} bounded retry contracts, ${(learning.trialRetryExhaustions || []).length} terminal retry-exhaustion receipts, ${(learning.applications || []).filter((item) => ["agentspine.learning-application/v5", "agentspine.learning-application/v6", "agentspine.learning-application/v7"].includes(item.schema)).length} immutable initial-trial admissions, ${(learning.applications || []).filter((item) => ["agentspine.learning-application/v6", "agentspine.learning-application/v7"].includes(item.schema)).length} exact-target admissions, ${(learning.applications || []).filter((item) => item.schema === "agentspine.learning-application/v7").length} deadline-bound admissions, ${(learning.trialFailures || []).length} blocking trial-failure receipts, ${(learning.evaluatorRegistry || []).length} locally confirmed evaluator roots, ${(learning.evaluationBindings || []).length} evaluator-registry bindings, ${(learning.validationLeases || []).length} immutable validation leases, ${(learning.measurements || []).length} immutable measurement runs, ${(learning.applications || []).length} turn-bound projections, ${(learning.deliveries || []).length} completed model-turn deliveries, ${(learning.evaluationRevocations || []).length} evaluation revocations, ${(learning.evidenceRevocations || []).length} evidence revocations, ${(learning.measurementRevocations || []).length} measurement revocations, ${(learning.applicationRevocations || []).length} application revocations, ${(learning.deliveryRevocations || []).length} delivery revocations, ${(learning.outcomeRevocations || []).length} outcome revocations, ${(learning.outcomes || []).length} outcome receipts, ${(learning.outcomes || []).filter((item) => ["agentspine.learning-outcome/v5", "agentspine.learning-outcome/v6", "agentspine.learning-outcome/v7", "agentspine.learning-outcome/v8", "agentspine.learning-outcome/v9"].includes(item.schema)).length} case-coverage receipts, ${(learning.outcomes || []).filter((item) => ["agentspine.learning-outcome/v6", "agentspine.learning-outcome/v7", "agentspine.learning-outcome/v8", "agentspine.learning-outcome/v9"].includes(item.schema)).length} provenance-bound receipts, ${(learning.outcomes || []).filter((item) => ["agentspine.learning-outcome/v7", "agentspine.learning-outcome/v8", "agentspine.learning-outcome/v9"].includes(item.schema)).length} lineage-bound receipts, ${(learning.outcomes || []).filter((item) => ["agentspine.learning-outcome/v8", "agentspine.learning-outcome/v9"].includes(item.schema)).length} paired-evaluator receipts and ${(learning.outcomes || []).filter((item) => item.schema === "agentspine.learning-outcome/v9").length} evaluator-root-bound receipts, ${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`),
308
- gate(9, "Context budget", loadedBytes <= context.budget.maxBytes && briefingBudgetValid, briefingError
309
- ? `${loadedBytes}/${context.budget.maxBytes} source bytes; briefing failed closed: ${briefingError}`
310
- : `${loadedBytes}/${context.budget.maxBytes} source bytes; ${briefingBytes}/${briefing.budget.maxBytes} briefing bytes`),
311
- gate(10, "Byte preservation", byteStable && verification.ok, verification.ok ? "Sources remained byte-for-byte unchanged" : "Source drift detected")
312
- ];
313
- return {
314
- schema: "agentspine.audit/v1",
315
- root: catalog.root,
316
- ok: gates.every((item) => item.ok || item.severity === "warning"),
317
- passed: gates.filter((item) => item.ok).length,
318
- total: gates.length,
319
- gates,
320
- catalogPath,
321
- graphPath,
322
- attentionPath,
323
- learningPath,
324
- continuityPath,
325
- policyPath,
326
- coordinationPath,
327
- executionPolicyPath,
328
- selfstarterPath,
329
- channelPolicyPath,
330
- channelRuntimePath,
331
- personaPolicyPath,
332
- personaRuntimePath,
333
- gatewayPolicyPath,
334
- gatewayRuntimePath,
335
- sharingPath,
336
- trustPath,
337
- registryPath,
338
- feedStatePath,
339
- sourceResolution,
340
- preflight
341
- };
342
- }
1
+ import { canonicalPath, statePathIsScanExcluded } 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
+ import { preflightStatus } from "./preflight.js";
25
+
26
+ function gate(id, name, ok, detail, severity = "error") {
27
+ return { id, name, ok, severity, detail };
28
+ }
29
+
30
+ function authorityViolations(graph, attention, learning, continuity, coordination, sharing, trust, registry, feedState) {
31
+ const records = [
32
+ ...graph.edges,
33
+ ...graph.annotations,
34
+ ...graph.entities,
35
+ ...graph.entityEdges,
36
+ ...graph.history,
37
+ ...graph.history.map((entry) => entry.value).filter(Boolean),
38
+ ...attention.signals,
39
+ ...attention.activities,
40
+ ...attention.events,
41
+ ...attention.receipts,
42
+ ...attention.history,
43
+ ...attention.history.map((entry) => entry.value).filter(Boolean),
44
+ ...learning.candidates,
45
+ ...learning.candidates.flatMap((candidate) => [
46
+ ...(candidate.evidence || []), candidate.review, candidate.rollback
47
+ ]).filter(Boolean),
48
+ ...(learning.outcomes || []),
49
+ ...(learning.outcomes || []).map((outcome) => outcome.measurement).filter(Boolean),
50
+ ...(learning.measurements || []),
51
+ ...(learning.measurements || []).map((measurement) => measurement.measurement).filter(Boolean),
52
+ ...(learning.measurementLineage || []),
53
+ ...(learning.candidateEvidenceLineage || []),
54
+ ...(learning.applications || []),
55
+ ...(learning.evaluations || []),
56
+ ...(learning.evaluatorRegistry || []),
57
+ ...(learning.evaluationBindings || []),
58
+ ...(learning.validationLeases || []),
59
+ ...(learning.trialFailures || []),
60
+ ...(learning.trialFailureRevocations || []),
61
+ ...(learning.trialRetryExhaustions || []),
62
+ ...(learning.evaluationRevocations || []),
63
+ ...(learning.evidenceSourceAttestationRevocations || []),
64
+ ...(learning.validationRevocations || []),
65
+ ...(learning.evidenceRevocations || []),
66
+ ...(learning.measurementRevocations || []),
67
+ ...(learning.applicationRevocations || []),
68
+ ...(learning.deliveryRevocations || []),
69
+ ...(learning.outcomeRevocations || []),
70
+ ...learning.history,
71
+ ...learning.history.map((entry) => entry.value).filter(Boolean),
72
+ ...continuity.signals,
73
+ ...continuity.history,
74
+ ...coordination.tasks,
75
+ ...coordination.history,
76
+ ...coordination.history.map((entry) => entry.value).filter(Boolean),
77
+ ...sharing.records.flatMap((record) => [record, record.event, record.review, record.rollback]).filter(Boolean),
78
+ ...sharing.history,
79
+ ...sharing.history.flatMap((entry) => [entry.value, entry.value?.event, entry.value?.review, entry.value?.rollback]).filter(Boolean),
80
+ ...trust.records.flatMap((record) => [record, record.publicIdentity]).filter(Boolean),
81
+ ...trust.history.flatMap((entry) => [entry, entry.value, entry.value?.publicIdentity]).filter(Boolean),
82
+ ...registry.signers.flatMap((record) => [record, record.publicIdentity]).filter(Boolean),
83
+ ...registry.history.flatMap((entry) => [entry, entry.value]).filter(Boolean),
84
+ ...feedState.feeds,
85
+ ...feedState.history
86
+ ];
87
+ return records.filter((record) => record.authority !== "context-only");
88
+ }
89
+
90
+ function forbiddenEntityKeys(graph) {
91
+ const forbidden = /"(?:permissions?|rights?|authorization|credentials?|secrets?|tokens?|api[-_]?keys?)"\s*:/i;
92
+ const historicalEntities = graph.history
93
+ .filter((entry) => entry.kind === "entity")
94
+ .map((entry) => entry.value);
95
+ return [...graph.entities, ...historicalEntities].filter((entity) => forbidden.test(JSON.stringify(entity?.attributes || {})));
96
+ }
97
+
98
+ export async function runAudit(root = process.cwd(), { host = null } = {}) {
99
+ let preflight = null;
100
+ let preflightError = null;
101
+ try { preflight = await preflightStatus(); } catch (error) { preflightError = error.message; }
102
+ let sourceResolution = null;
103
+ let sourceResolutionError = null;
104
+ let resolvedHostSources = null;
105
+ if (["claude", "codex"].includes(host)) {
106
+ try {
107
+ resolvedHostSources = await resolveHostSourceCatalog({ host, cwd: root });
108
+ sourceResolution = resolvedHostSources.diagnostics;
109
+ }
110
+ catch (error) { sourceResolutionError = error.message; }
111
+ }
112
+ let hostIntegration = null;
113
+ let hostIntegrationError = null;
114
+ try {
115
+ hostIntegration = await checkHosts(fileURLToPath(new URL("../..", import.meta.url)));
116
+ } catch (error) {
117
+ hostIntegrationError = error.message;
118
+ }
119
+ const before = resolvedHostSources?.catalog || (sourceResolutionError
120
+ ? {
121
+ schema: "agentspine.catalog/v1", generatedAt: new Date().toISOString(), root: await canonicalPath(root),
122
+ preservation: "source-files-are-read-only", documents: [], conflicts: [],
123
+ summary: { total: 0, protected: 0, conflicts: 0, byLayer: {} }
124
+ }
125
+ : await buildCatalog(root));
126
+ const catalog = before;
127
+ const catalogPath = await saveCatalog(catalog);
128
+ const { graph, graphPath } = await loadGraph(before.root, catalog);
129
+ const { attention, attentionPath, error: attentionLoadError } = await inspectAttention(before.root, catalog);
130
+ const { learning, learningPath, error: learningLoadError } = await inspectLearning(before.root, catalog);
131
+ const { continuity, continuityPath, error: continuityLoadError } = await inspectContinuity(before.root, catalog);
132
+ const {
133
+ policy, coordination, policyPath, coordinationPath, errors: coordinationLoadErrors
134
+ } = await inspectCoordination(before.root, catalog);
135
+ const {
136
+ policy: executionPolicy, state: selfstarter, executionPolicyPath, selfstarterPath,
137
+ errors: selfstarterLoadErrors
138
+ } = await inspectSelfstarter(before.root, catalog);
139
+ const {
140
+ policy: channelPolicy, runtime: channelRuntime, channelPolicyPath, channelRuntimePath,
141
+ errors: channelLoadErrors
142
+ } = await inspectChannelRuntime(before.root, catalog);
143
+ const {
144
+ policy: personaPolicy, runtime: personaRuntime, personaPolicyPath, personaRuntimePath,
145
+ errors: personaLoadErrors
146
+ } = await inspectPersonaRuntime(before.root, catalog);
147
+ const {
148
+ policy: gatewayPolicy, runtime: gatewayRuntime, gatewayPolicyPath, gatewayRuntimePath,
149
+ errors: gatewayLoadErrors
150
+ } = await inspectGatewayRuntime(before.root, catalog);
151
+ const { sharing, sharingPath, error: sharingLoadError } = await inspectSharing(before.root, catalog);
152
+ const { trust, trustPath, error: trustLoadError } = await inspectTrust(before.root, catalog);
153
+ const { registry, registryPath, signerDirectory, errors: signerErrors } = await inspectSignerRegistry(before.root, catalog);
154
+ const { state: feedState, statePath: feedStatePath, error: feedStateError } = await inspectHttpsFeedState(before.root);
155
+ const context = await resolveContext({ root: before.root, cwd: before.root, host: "generic", maxBytes: 16384, includeContent: true, catalog });
156
+ let briefing = null;
157
+ let briefingError = null;
158
+ try {
159
+ briefing = await sessionBriefing({
160
+ root: before.root, cwd: before.root, host: host || "generic", maxBytes: 16384,
161
+ includePrivate: false, focusActive: true, includeSourceContent: true,
162
+ catalog: resolvedHostSources?.catalog || null, sourceDiagnostics: sourceResolution
163
+ });
164
+ } catch (error) {
165
+ briefingError = error.message;
166
+ }
167
+ const verification = ["claude", "codex"].includes(host)
168
+ ? { ok: !sourceResolutionError, reason: sourceResolutionError ? "host-native-resolution-failed" : "host-native-rescan" }
169
+ : await verifyCatalog(before.root);
170
+ const after = resolvedHostSources
171
+ ? (await resolveHostSourceCatalog({ host, cwd: root })).catalog
172
+ : sourceResolutionError ? before : await buildCatalog(before.root);
173
+ const beforeHashes = new Map(before.documents.map((document) => [document.relativePath, document.sha256]));
174
+ const byteStable = after.documents.length === before.documents.length && after.documents.every((document) => beforeHashes.get(document.relativePath) === document.sha256);
175
+ const brokenLinks = catalog.conflicts.filter((conflict) => conflict.type === "broken-link");
176
+ const reviewConflicts = catalog.conflicts.filter((conflict) => conflict.type !== "broken-link");
177
+ const authority = authorityViolations(graph, attention, learning, continuity, coordination, sharing, trust, registry, feedState);
178
+ const forbidden = forbiddenEntityKeys(graph);
179
+ const privacyValues = new Set(["private", "shared", "group"]);
180
+ const privateRecords = [
181
+ ...graph.entities,
182
+ ...graph.entityEdges,
183
+ ...graph.history,
184
+ ...graph.history.map((entry) => entry.value).filter((value) => value && "privacy" in value),
185
+ ...attention.signals,
186
+ ...attention.activities,
187
+ ...attention.events,
188
+ ...attention.history,
189
+ ...attention.history.map((entry) => entry.value).filter((value) => value && "privacy" in value),
190
+ ...learning.candidates,
191
+ ...learning.history,
192
+ ...learning.history.map((entry) => entry.value).filter((value) => value && "privacy" in value),
193
+ ...coordination.tasks,
194
+ ...coordination.history,
195
+ ...coordination.history.map((entry) => entry.value).filter((value) => value && "privacy" in value),
196
+ ...sharing.records.map((record) => ({ ...record, privacy: record.event?.privacy })),
197
+ ...sharing.history,
198
+ ...sharing.history.map((entry) => entry.value).filter(Boolean).map((record) => ({ ...record, privacy: record.event?.privacy }))
199
+ ];
200
+ const privacyInvalid = privateRecords.filter((record) => !privacyValues.has(record.privacy));
201
+ const knownGroups = new Set(graph.entities.filter((entity) => entity.kind === "group").map((entity) => entity.id));
202
+ const isKnownGroupMember = (record) => !record.entityId || record.entityId === record.groupId || graph.entityEdges.some((edge) => (
203
+ edge.relation === "member-of" && edge.privacy !== "private" && (
204
+ (edge.from === record.entityId && edge.to === record.groupId)
205
+ || (edge.to === record.entityId && edge.from === record.groupId)
206
+ )
207
+ ));
208
+ const attentionGroupInvalid = [
209
+ ...attention.signals,
210
+ ...attention.activities,
211
+ ...attention.events,
212
+ ...attention.history.map((entry) => entry.value).filter(Boolean)
213
+ ].filter((record) => record.privacy === "group" && (!knownGroups.has(record.groupId) || !isKnownGroupMember(record)));
214
+ const attentionConfigValid = typeof attention.config.enabled === "boolean"
215
+ && Number.isFinite(attention.config.minIntervalHours) && attention.config.minIntervalHours >= 1 && attention.config.minIntervalHours <= 720
216
+ && Number.isFinite(attention.config.entitySilenceDays) && attention.config.entitySilenceDays >= 1 && attention.config.entitySilenceDays <= 3650
217
+ && Number.isInteger(attention.config.heartbeatStaleMinutes) && attention.config.heartbeatStaleMinutes >= 1 && attention.config.heartbeatStaleMinutes <= 10080
218
+ && Number.isInteger(attention.config.maxItems) && attention.config.maxItems >= 1 && attention.config.maxItems <= 20
219
+ && (attention.config.quietHours === null || (
220
+ Number.isInteger(attention.config.quietHours?.start) && attention.config.quietHours.start >= 0 && attention.config.quietHours.start <= 23
221
+ && Number.isInteger(attention.config.quietHours?.end) && attention.config.quietHours.end >= 0 && attention.config.quietHours.end <= 23
222
+ && Number.isFinite(attention.config.quietHours?.utcOffsetMinutes)
223
+ && attention.config.quietHours.utcOffsetMinutes >= -720 && attention.config.quietHours.utcOffsetMinutes <= 840
224
+ ));
225
+ const learningIssues = learningFindings(learning, graph);
226
+ const attentionIssues = attentionFindings(attention);
227
+ if (attentionLoadError) attentionIssues.push(`unreadable-state:${attentionLoadError}`);
228
+ if (learningLoadError) learningIssues.push(`unreadable-state:${learningLoadError}`);
229
+ const continuityIssues = continuityFindings(continuity);
230
+ if (continuityLoadError) continuityIssues.push(`unreadable-state:${continuityLoadError}`);
231
+ const policyIssues = delegationPolicyFindings(policy, graph);
232
+ const coordinationIssues = coordinationFindings(coordination, policy, graph);
233
+ for (const error of coordinationLoadErrors) {
234
+ if (error.startsWith("policy:")) policyIssues.push(`unreadable-state:${error}`);
235
+ else coordinationIssues.push(`unreadable-state:${error}`);
236
+ }
237
+ const coordinationAuthorityIssues = coordinationIssues.filter((issue) => /assignment|policy-snapshot/.test(issue));
238
+ const coordinationContextIssues = coordinationIssues.filter((issue) => !coordinationAuthorityIssues.includes(issue));
239
+ const executionPolicyIssues = executionPolicyFindings(executionPolicy, graph, coordination);
240
+ const selfstarterIssues = selfstarterFindings(selfstarter, executionPolicy, graph, coordination);
241
+ for (const error of selfstarterLoadErrors) {
242
+ if (error.startsWith("policy:")) executionPolicyIssues.push(`unreadable-state:${error}`);
243
+ else selfstarterIssues.push(`unreadable-state:${error}`);
244
+ }
245
+ const selfstarterAuthorityIssues = selfstarterIssues.filter((issue) => /grant|policy|task-mismatch/.test(issue));
246
+ const selfstarterStateIssues = selfstarterIssues.filter((issue) => !selfstarterAuthorityIssues.includes(issue));
247
+ const channelPolicyIssues = channelPolicyFindings(channelPolicy, graph);
248
+ const channelRuntimeIssues = channelRuntimeFindings(channelRuntime, channelPolicy, graph)
249
+ .filter((issue) => !channelPolicyIssues.includes(issue));
250
+ for (const error of channelLoadErrors) {
251
+ if (error.startsWith("policy:")) channelPolicyIssues.push(`unreadable-state:${error}`);
252
+ else channelRuntimeIssues.push(`unreadable-state:${error}`);
253
+ }
254
+ const personaIssues = personaRuntimeFindings(personaPolicy, personaRuntime, graph);
255
+ const personaPolicyIssues = personaIssues.filter((issue) => /binding/.test(issue));
256
+ const personaStateIssues = personaIssues.filter((issue) => !personaPolicyIssues.includes(issue));
257
+ for (const error of personaLoadErrors) {
258
+ if (error.startsWith("policy:")) personaPolicyIssues.push(`unreadable-state:${error}`);
259
+ else personaStateIssues.push(`unreadable-state:${error}`);
260
+ }
261
+ const gatewayIssues = [...gatewayRuntimeFindings(gatewayPolicy, gatewayRuntime),
262
+ ...gatewayHealthFindings(gatewayPolicy, gatewayRuntime)];
263
+ const gatewayPolicyIssues = gatewayIssues.filter((issue) => /goal/.test(issue));
264
+ const gatewayStateIssues = gatewayIssues.filter((issue) => !gatewayPolicyIssues.includes(issue));
265
+ for (const error of gatewayLoadErrors) {
266
+ if (error.startsWith("policy:")) gatewayPolicyIssues.push(`unreadable-state:${error}`);
267
+ else gatewayStateIssues.push(`unreadable-state:${error}`);
268
+ }
269
+ const sharingIssues = sharingFindings(sharing, graph);
270
+ if (sharingLoadError) sharingIssues.push(`unreadable-state:${sharingLoadError}`);
271
+ const authenticationIssues = [
272
+ ...trustFindings(trust),
273
+ ...sharingAuthenticationFindings(sharing, trust)
274
+ ];
275
+ if (trustLoadError) authenticationIssues.push(`unreadable-trust:${trustLoadError}`);
276
+ authenticationIssues.push(...signerErrors);
277
+ if (feedStateError) authenticationIssues.push(`unreadable-feed-state:${feedStateError}`);
278
+ const sharingAuthorityIssues = sharingIssues.filter((issue) => /authority|unsafe/.test(issue));
279
+ const sharingContextIssues = sharingIssues.filter((issue) => !sharingAuthorityIssues.includes(issue));
280
+ const nativeMapped = catalog.documents.filter((document) => document.hosts.some((host) => host !== "generic"));
281
+ const loadedBytes = context.documents.filter((document) => document.loaded).reduce((sum, document) => sum + document.bytes, 0);
282
+ const briefingBytes = briefing ? Buffer.byteLength(JSON.stringify(briefing)) : null;
283
+ const briefingBudgetValid = briefing !== null && briefingBytes === briefing.budget.usedBytes
284
+ && briefingBytes <= briefing.budget.maxBytes;
285
+
286
+ const gates = [
287
+ gate(1, "Runtime", Number(process.versions.node.split(".")[0]) >= 20 && hostIntegration?.ok === true, hostIntegrationError
288
+ ? `Node ${process.versions.node}; host integration failed closed: ${hostIntegrationError}`
289
+ : `Node ${process.versions.node}; one versioned MCP server and lifecycle hook set per host`),
290
+ gate(2, "Discovery", catalog.schema === "agentspine.catalog/v1"
291
+ && (!host || (sourceResolution?.status === "loaded" && !sourceResolutionError)), sourceResolutionError
292
+ ? `${catalog.documents.length} project documents; host-native source resolution failed closed: ${sourceResolutionError}`
293
+ : sourceResolution ? `${sourceResolution.scopes.user} user, ${sourceResolution.scopes.project} project, and ${sourceResolution.scopes["project-memory"]} memory sources; broad home scan disabled`
294
+ : `${catalog.documents.length} Markdown documents indexed`),
295
+ gate(3, "State isolation", [catalogPath, graphPath, attentionPath, learningPath, continuityPath,
296
+ policyPath, coordinationPath, executionPolicyPath, selfstarterPath, channelPolicyPath,
297
+ channelRuntimePath, personaPolicyPath, personaRuntimePath, gatewayPolicyPath, gatewayRuntimePath,
298
+ sharingPath, trustPath, registryPath, signerDirectory, feedStatePath]
299
+ .every((path) => statePathIsScanExcluded(catalog, path)),
300
+ catalog.scanPolicy?.stateRoot === "excluded"
301
+ ? `Authenticated state is excluded from the home-root source scan for ${catalog.root}`
302
+ : `State remains outside ${catalog.root}`),
303
+ gate(4, "Native hierarchy", nativeMapped.every((document) => document.hosts.length > 0), `${nativeMapped.length} host-native documents mapped`),
304
+ gate(5, "Link integrity", brokenLinks.length === 0, brokenLinks.length ? `${brokenLinks.length} broken Markdown links` : "All indexed Markdown links resolve"),
305
+ gate(6, "Conflict visibility", Array.isArray(catalog.conflicts), `${reviewConflicts.length} precedence or classification findings exposed`, "warning"),
306
+ 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 && !preflightError, preflightError
307
+ ? `preflight policy or receipt state failed closed: ${preflightError}`
308
+ : `${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; preflight ${preflight.status}`),
309
+ 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, ${(learning.candidateEvidenceLineage || []).length} candidate-evidence lineage receipts, ${(learning.evaluations || []).length} immutable evaluation contracts, ${(learning.evaluations || []).filter((item) => ["agentspine.learning-evaluation/v9", "agentspine.learning-evaluation/v10", "agentspine.learning-evaluation/v11", "agentspine.learning-evaluation/v12", "agentspine.learning-evaluation/v13", "agentspine.learning-evaluation/v14", "agentspine.learning-evaluation/v15", "agentspine.learning-evaluation/v16", "agentspine.learning-evaluation/v17", "agentspine.learning-evaluation/v18", "agentspine.learning-evaluation/v19", "agentspine.learning-evaluation/v20", "agentspine.learning-evaluation/v21", "agentspine.learning-evaluation/v22", "agentspine.learning-evaluation/v23", "agentspine.learning-evaluation/v24", "agentspine.learning-evaluation/v25", "agentspine.learning-evaluation/v26", "agentspine.learning-evaluation/v27", "agentspine.learning-evaluation/v28", "agentspine.learning-evaluation/v29"].includes(item.schema)).length} exact-target contracts, ${(learning.evaluations || []).filter((item) => ["agentspine.learning-evaluation/v8", "agentspine.learning-evaluation/v9", "agentspine.learning-evaluation/v10", "agentspine.learning-evaluation/v11", "agentspine.learning-evaluation/v12", "agentspine.learning-evaluation/v13", "agentspine.learning-evaluation/v14", "agentspine.learning-evaluation/v15", "agentspine.learning-evaluation/v16", "agentspine.learning-evaluation/v17", "agentspine.learning-evaluation/v18", "agentspine.learning-evaluation/v19", "agentspine.learning-evaluation/v20", "agentspine.learning-evaluation/v21", "agentspine.learning-evaluation/v22", "agentspine.learning-evaluation/v23", "agentspine.learning-evaluation/v24", "agentspine.learning-evaluation/v25", "agentspine.learning-evaluation/v26", "agentspine.learning-evaluation/v27", "agentspine.learning-evaluation/v28", "agentspine.learning-evaluation/v29"].includes(item.schema)).length} precommitted initial-trial contracts, ${(learning.evaluations || []).filter((item) => ["agentspine.learning-evaluation/v10", "agentspine.learning-evaluation/v11", "agentspine.learning-evaluation/v12", "agentspine.learning-evaluation/v13", "agentspine.learning-evaluation/v14", "agentspine.learning-evaluation/v15", "agentspine.learning-evaluation/v16", "agentspine.learning-evaluation/v17", "agentspine.learning-evaluation/v18", "agentspine.learning-evaluation/v19", "agentspine.learning-evaluation/v20", "agentspine.learning-evaluation/v21", "agentspine.learning-evaluation/v22", "agentspine.learning-evaluation/v23", "agentspine.learning-evaluation/v24", "agentspine.learning-evaluation/v25", "agentspine.learning-evaluation/v26", "agentspine.learning-evaluation/v27", "agentspine.learning-evaluation/v28", "agentspine.learning-evaluation/v29"].includes(item.schema)).length} deadline-bound contracts, ${(learning.evaluations || []).filter((item) => ["agentspine.learning-evaluation/v14", "agentspine.learning-evaluation/v15", "agentspine.learning-evaluation/v16", "agentspine.learning-evaluation/v17", "agentspine.learning-evaluation/v18", "agentspine.learning-evaluation/v19", "agentspine.learning-evaluation/v20", "agentspine.learning-evaluation/v21", "agentspine.learning-evaluation/v22", "agentspine.learning-evaluation/v23", "agentspine.learning-evaluation/v24", "agentspine.learning-evaluation/v25", "agentspine.learning-evaluation/v26", "agentspine.learning-evaluation/v27", "agentspine.learning-evaluation/v28", "agentspine.learning-evaluation/v29"].includes(item.schema)).length} staleness-bound contracts, ${(learning.evaluations || []).filter((item) => ["agentspine.learning-evaluation/v16", "agentspine.learning-evaluation/v17", "agentspine.learning-evaluation/v18", "agentspine.learning-evaluation/v19", "agentspine.learning-evaluation/v20", "agentspine.learning-evaluation/v21", "agentspine.learning-evaluation/v22", "agentspine.learning-evaluation/v23", "agentspine.learning-evaluation/v24", "agentspine.learning-evaluation/v25", "agentspine.learning-evaluation/v26", "agentspine.learning-evaluation/v27", "agentspine.learning-evaluation/v28", "agentspine.learning-evaluation/v29"].includes(item.schema)).length} promotion-bound contracts, ${(learning.evaluations || []).filter((item) => ["agentspine.learning-evaluation/v18", "agentspine.learning-evaluation/v19", "agentspine.learning-evaluation/v20", "agentspine.learning-evaluation/v21", "agentspine.learning-evaluation/v22", "agentspine.learning-evaluation/v23", "agentspine.learning-evaluation/v24", "agentspine.learning-evaluation/v25", "agentspine.learning-evaluation/v26", "agentspine.learning-evaluation/v27", "agentspine.learning-evaluation/v28", "agentspine.learning-evaluation/v29"].includes(item.schema)).length} candidate-admission contracts, ${(learning.evaluations || []).filter((item) => ["agentspine.learning-evaluation/v20", "agentspine.learning-evaluation/v21", "agentspine.learning-evaluation/v22", "agentspine.learning-evaluation/v23", "agentspine.learning-evaluation/v24", "agentspine.learning-evaluation/v25", "agentspine.learning-evaluation/v26", "agentspine.learning-evaluation/v27", "agentspine.learning-evaluation/v28", "agentspine.learning-evaluation/v29"].includes(item.schema)).length} candidate-evidence-cohort contracts, ${(learning.evaluations || []).filter((item) => ["agentspine.learning-evaluation/v22", "agentspine.learning-evaluation/v23", "agentspine.learning-evaluation/v24", "agentspine.learning-evaluation/v25", "agentspine.learning-evaluation/v26", "agentspine.learning-evaluation/v27", "agentspine.learning-evaluation/v28", "agentspine.learning-evaluation/v29"].includes(item.schema)).length} blocking-defect-bound contracts, ${(learning.evaluations || []).filter((item) => ["agentspine.learning-evaluation/v24", "agentspine.learning-evaluation/v25", "agentspine.learning-evaluation/v26", "agentspine.learning-evaluation/v27", "agentspine.learning-evaluation/v28", "agentspine.learning-evaluation/v29"].includes(item.schema)).length} evidence-source-bound contracts, ${(learning.evaluations || []).filter((item) => ["agentspine.learning-evaluation/v26", "agentspine.learning-evaluation/v27", "agentspine.learning-evaluation/v28", "agentspine.learning-evaluation/v29"].includes(item.schema)).length} evidence-source-attested contracts, ${(learning.evaluations || []).filter((item) => ["agentspine.learning-evaluation/v13", "agentspine.learning-evaluation/v15", "agentspine.learning-evaluation/v17", "agentspine.learning-evaluation/v19", "agentspine.learning-evaluation/v21", "agentspine.learning-evaluation/v23", "agentspine.learning-evaluation/v25", "agentspine.learning-evaluation/v27", "agentspine.learning-evaluation/v29"].includes(item.schema)).length} bounded retry contracts, ${(learning.trialRetryExhaustions || []).length} terminal retry-exhaustion receipts, ${(learning.applications || []).filter((item) => ["agentspine.learning-application/v5", "agentspine.learning-application/v6", "agentspine.learning-application/v7"].includes(item.schema)).length} immutable initial-trial admissions, ${(learning.applications || []).filter((item) => ["agentspine.learning-application/v6", "agentspine.learning-application/v7"].includes(item.schema)).length} exact-target admissions, ${(learning.applications || []).filter((item) => item.schema === "agentspine.learning-application/v7").length} deadline-bound admissions, ${(learning.trialFailures || []).length} blocking trial-failure receipts, ${(learning.evaluatorRegistry || []).length} locally confirmed evaluator roots, ${(learning.evaluationBindings || []).length} evaluator-registry bindings, ${(learning.validationLeases || []).length} immutable validation leases, ${(learning.measurements || []).length} immutable measurement runs, ${(learning.applications || []).length} turn-bound projections, ${(learning.deliveries || []).length} completed model-turn deliveries, ${(learning.evaluationRevocations || []).length} evaluation revocations, ${(learning.evidenceRevocations || []).length} evidence revocations, ${(learning.measurementRevocations || []).length} measurement revocations, ${(learning.applicationRevocations || []).length} application revocations, ${(learning.deliveryRevocations || []).length} delivery revocations, ${(learning.outcomeRevocations || []).length} outcome revocations, ${(learning.outcomes || []).length} outcome receipts, ${(learning.outcomes || []).filter((item) => ["agentspine.learning-outcome/v5", "agentspine.learning-outcome/v6", "agentspine.learning-outcome/v7", "agentspine.learning-outcome/v8", "agentspine.learning-outcome/v9"].includes(item.schema)).length} case-coverage receipts, ${(learning.outcomes || []).filter((item) => ["agentspine.learning-outcome/v6", "agentspine.learning-outcome/v7", "agentspine.learning-outcome/v8", "agentspine.learning-outcome/v9"].includes(item.schema)).length} provenance-bound receipts, ${(learning.outcomes || []).filter((item) => ["agentspine.learning-outcome/v7", "agentspine.learning-outcome/v8", "agentspine.learning-outcome/v9"].includes(item.schema)).length} lineage-bound receipts, ${(learning.outcomes || []).filter((item) => ["agentspine.learning-outcome/v8", "agentspine.learning-outcome/v9"].includes(item.schema)).length} paired-evaluator receipts and ${(learning.outcomes || []).filter((item) => item.schema === "agentspine.learning-outcome/v9").length} evaluator-root-bound receipts, ${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`),
310
+ gate(9, "Context budget", loadedBytes <= context.budget.maxBytes && briefingBudgetValid, briefingError
311
+ ? `${loadedBytes}/${context.budget.maxBytes} source bytes; briefing failed closed: ${briefingError}`
312
+ : `${loadedBytes}/${context.budget.maxBytes} source bytes; ${briefingBytes}/${briefing.budget.maxBytes} briefing bytes`),
313
+ gate(10, "Byte preservation", byteStable && verification.ok, verification.ok ? "Sources remained byte-for-byte unchanged" : "Source drift detected")
314
+ ];
315
+ return {
316
+ schema: "agentspine.audit/v1",
317
+ root: catalog.root,
318
+ ok: gates.every((item) => item.ok || item.severity === "warning"),
319
+ passed: gates.filter((item) => item.ok).length,
320
+ total: gates.length,
321
+ gates,
322
+ catalogPath,
323
+ graphPath,
324
+ attentionPath,
325
+ learningPath,
326
+ continuityPath,
327
+ policyPath,
328
+ coordinationPath,
329
+ executionPolicyPath,
330
+ selfstarterPath,
331
+ channelPolicyPath,
332
+ channelRuntimePath,
333
+ personaPolicyPath,
334
+ personaRuntimePath,
335
+ gatewayPolicyPath,
336
+ gatewayRuntimePath,
337
+ sharingPath,
338
+ trustPath,
339
+ registryPath,
340
+ feedStatePath,
341
+ learningDiagnostics: {
342
+ candidateEvidenceLineageReceipts:
343
+ (learning.candidateEvidenceLineage || []).length,
344
+ evidenceSourceAttestationRevocations:
345
+ (learning.evidenceSourceAttestationRevocations || []).length,
346
+ authority: "context-only"
347
+ },
348
+ sourceResolution,
349
+ preflight
350
+ };
351
+ }