blun-king-cli 9.1.564 → 9.1.566

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 (88) hide show
  1. package/LIESMICH.txt +2 -2
  2. package/README.md +1 -1
  3. package/agent-spine-plugin/.claude-plugin/marketplace.json +20 -20
  4. package/agent-spine-plugin/.claude-plugin/plugin.json +14 -14
  5. package/agent-spine-plugin/.codex-plugin/plugin.json +34 -34
  6. package/agent-spine-plugin/.mcp.json +8 -8
  7. package/agent-spine-plugin/CONTRIBUTING.md +52 -0
  8. package/agent-spine-plugin/LICENSE +186 -186
  9. package/agent-spine-plugin/README.md +406 -0
  10. package/agent-spine-plugin/SECURITY.md +47 -0
  11. package/agent-spine-plugin/assets/agentspine-banner.svg +32 -32
  12. package/agent-spine-plugin/bin/agentspine-mcp.js +4 -4
  13. package/agent-spine-plugin/bin/agentspine.js +7 -7
  14. package/agent-spine-plugin/blun.plugin.json +33 -33
  15. package/agent-spine-plugin/hooks/codex.json +47 -47
  16. package/agent-spine-plugin/hooks/hooks.json +106 -106
  17. package/agent-spine-plugin/hooks/version.json +5 -5
  18. package/agent-spine-plugin/package.json +69 -69
  19. package/agent-spine-plugin/scripts/check-hosts.js +199 -199
  20. package/agent-spine-plugin/skill/SKILL.md +76 -76
  21. package/agent-spine-plugin/skills/agent-spine/SKILL.md +85 -85
  22. package/agent-spine-plugin/src/cli.js +1488 -1442
  23. package/agent-spine-plugin/src/hook.js +882 -861
  24. package/agent-spine-plugin/src/index.js +94 -93
  25. package/agent-spine-plugin/src/lib/acceptance.js +333 -333
  26. package/agent-spine-plugin/src/lib/attention.js +755 -755
  27. package/agent-spine-plugin/src/lib/audit.js +351 -342
  28. package/agent-spine-plugin/src/lib/authentication.js +515 -515
  29. package/agent-spine-plugin/src/lib/briefing.js +317 -317
  30. package/agent-spine-plugin/src/lib/catalog.js +167 -167
  31. package/agent-spine-plugin/src/lib/channel-runtime.js +665 -665
  32. package/agent-spine-plugin/src/lib/context.js +154 -154
  33. package/agent-spine-plugin/src/lib/continuity.js +338 -338
  34. package/agent-spine-plugin/src/lib/coordination.js +577 -577
  35. package/agent-spine-plugin/src/lib/documents.js +217 -217
  36. package/agent-spine-plugin/src/lib/feed-transport.js +499 -499
  37. package/agent-spine-plugin/src/lib/filesystem-retry.js +32 -32
  38. package/agent-spine-plugin/src/lib/gateway-runtime.js +1623 -760
  39. package/agent-spine-plugin/src/lib/graph.js +337 -337
  40. package/agent-spine-plugin/src/lib/hook-audit.js +29 -29
  41. package/agent-spine-plugin/src/lib/https-transport.js +392 -392
  42. package/agent-spine-plugin/src/lib/indexed-memory-offline.js +40 -40
  43. package/agent-spine-plugin/src/lib/indexed-memory.js +281 -281
  44. package/agent-spine-plugin/src/lib/learning.js +6923 -6466
  45. package/agent-spine-plugin/src/lib/object-transport.js +206 -206
  46. package/agent-spine-plugin/src/lib/owned-file-lock.js +143 -143
  47. package/agent-spine-plugin/src/lib/paths.js +109 -109
  48. package/agent-spine-plugin/src/lib/peer-transport.js +283 -283
  49. package/agent-spine-plugin/src/lib/persona-runtime.js +581 -581
  50. package/agent-spine-plugin/src/lib/preflight.js +702 -702
  51. package/agent-spine-plugin/src/lib/runtime.js +13 -13
  52. package/agent-spine-plugin/src/lib/selfstarter.js +911 -866
  53. package/agent-spine-plugin/src/lib/sharing.js +969 -969
  54. package/agent-spine-plugin/src/lib/source-roots.js +530 -498
  55. package/agent-spine-plugin/src/lib/sqlite-transport.js +501 -501
  56. package/agent-spine-plugin/src/lib/telegram-adapter.js +119 -119
  57. package/agent-spine-plugin/src/lib/voice-runtime.js +39 -39
  58. package/agent-spine-plugin/src/mcp.js +597 -572
  59. package/agent-spine-plugin/src/version.js +1 -1
  60. package/agent-spine-plugin/src/worker.js +210 -195
  61. package/bin/active-steer-priority-policy.cjs +24 -0
  62. package/bin/launcher-runtime.js +8 -1
  63. package/bin/mnemo-tool-agent-policy.cjs +22 -0
  64. package/bin/native-runtime-cache.cjs +76 -0
  65. package/bin/thinking-activity-status-policy.cjs +132 -0
  66. package/bin/thinking-only-guard.cjs +75 -0
  67. package/bin/tool-call-loop-policy.cjs +53 -0
  68. package/bin/turn-thinking-policy.cjs +25 -1
  69. package/blun.mjs +556 -63
  70. package/package.json +4 -1
  71. package/standard-skills/translate-native/LICENSE +21 -21
  72. package/standard-skills/translate-native/references/evaluation-protocol.md +95 -95
  73. package/standard-skills/translate-native/references/native-orthography.md +79 -79
  74. package/standard-skills/translate-native/references/native-translation-standard.md +94 -94
  75. package/standard-skills/translate-native/references/structured-content.md +72 -72
  76. package/standard-skills/translate-native/references/translationese-review.md +77 -77
  77. package/standard-skills/translate-native/scripts/blun_language_guard.py +697 -697
  78. package/standard-skills/translate-native/scripts/check_diacritics.py +353 -353
  79. package/standard-skills/translate-native/scripts/guard_service_client.py +264 -264
  80. package/standard-skills/translate-native/scripts/language_gateway.py +62 -62
  81. package/standard-skills/translate-native/scripts/language_quality.py +377 -377
  82. package/standard-skills/translate-native/scripts/pre_output_guard.py +64 -64
  83. package/standard-skills/translate-native/scripts/translation_guard.py +916 -916
  84. package/standard-tools/language-guard/blun_language_guard.py +697 -697
  85. package/standard-tools/language-guard/check_diacritics.py +353 -353
  86. package/standard-tools/language-guard/guard_service_client.py +264 -264
  87. package/standard-tools/language-guard/language_quality.py +377 -377
  88. 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; ${(sourceResolution.skippedInaccessibleDirectories || []).length} inaccessible directories skipped`
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
+ }