percolation-inversion-compiler-ts 0.4.5 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (197) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/README.md +77 -22
  3. package/agent-manifest.json +50 -0
  4. package/dist/alt_lift/index.d.ts +7 -0
  5. package/dist/alt_lift/index.js +101 -0
  6. package/dist/bit_engine/index.d.ts +8 -0
  7. package/dist/bit_engine/index.js +213 -0
  8. package/dist/cli/main.js +2106 -162
  9. package/dist/index.d.ts +5 -0
  10. package/dist/index.js +1611 -16
  11. package/dist/phase_lab/index.d.ts +26 -0
  12. package/dist/phase_lab/index.js +1124 -0
  13. package/dist/sqot_controller/index.d.ts +8 -0
  14. package/dist/sqot_controller/index.js +141 -0
  15. package/dist/trc_adapter/index.d.ts +6 -0
  16. package/dist/trc_adapter/index.js +86 -0
  17. package/docs/alt-ecpt-lift.md +32 -0
  18. package/docs/bit-inversion-engine.md +32 -0
  19. package/docs/cli-reference.md +68 -0
  20. package/docs/effective-packet-graph.md +35 -0
  21. package/docs/for-agents.md +44 -0
  22. package/docs/phase-ecology-lab.md +46 -0
  23. package/docs/sqot-queue-sovereignty.md +31 -0
  24. package/docs/threshold-certificates.md +30 -0
  25. package/docs/trc-trace-adapter.md +30 -0
  26. package/docs/v050-audit.md +126 -0
  27. package/examples/alt_lift/alt_ecpt_lift.example.json +27 -0
  28. package/examples/bit_engine/bottlenecks.example.json +38 -0
  29. package/examples/bit_engine/inversion_candidates.example.json +55 -0
  30. package/examples/packet_exchange/packet_envelope.example.json +51 -0
  31. package/examples/packet_exchange/packet_merge_report.example.json +60 -0
  32. package/examples/phase_lab/certificate_abstain.example.json +39 -0
  33. package/examples/phase_lab/closure_report.example.json +41 -0
  34. package/examples/phase_lab/effective_graph.example.json +112 -0
  35. package/examples/phase_lab/executable_paths.example.json +20 -0
  36. package/examples/phase_lab/phase_window_observation.example.json +61 -0
  37. package/examples/phase_lab/runtime_report_1.json +19 -0
  38. package/examples/phase_lab/runtime_report_2.json +16 -0
  39. package/examples/phase_lab/threshold_status.example.json +31 -0
  40. package/examples/sqot_controller/queue_report.example.json +30 -0
  41. package/examples/sqot_controller/rebalance_plan.example.json +14 -0
  42. package/examples/thresholds/asi_proxy_development.json +15 -0
  43. package/examples/trc_adapter/tool_trace_input.example.json +17 -0
  44. package/examples/trc_adapter/typed_trace.example.json +64 -0
  45. package/fixtures/portability_conformance_v050/certificate_abstain.example.json +39 -0
  46. package/fixtures/portability_conformance_v050/closure_report.example.json +39 -0
  47. package/fixtures/portability_conformance_v050/effective_graph.example.json +112 -0
  48. package/fixtures/portability_conformance_v050/executable_paths.example.json +20 -0
  49. package/fixtures/portability_conformance_v050/manifest.json +55 -0
  50. package/fixtures/portability_conformance_v050/phase_lab_event_1.json +51 -0
  51. package/fixtures/portability_conformance_v050/phase_lab_event_2.json +55 -0
  52. package/fixtures/portability_conformance_v050/phase_window_observation.example.json +61 -0
  53. package/fixtures/portability_conformance_v050/runtime_report_1.json +19 -0
  54. package/fixtures/portability_conformance_v050/runtime_report_2.json +14 -0
  55. package/fixtures/portability_conformance_v050/threshold_status.example.json +29 -0
  56. package/fixtures/python_v044_cli/agent_autonomy_audit.json +4 -3
  57. package/fixtures/python_v044_cli/agent_manifest.json +2 -1
  58. package/fixtures/python_v044_cli/agent_runbook.json +2 -1
  59. package/fixtures/python_v044_cli/demo_installed_smoke.json +86 -86
  60. package/fixtures/python_v044_demo/manifest.json +2 -1
  61. package/fixtures/python_v050_cli/alt_capital_impact.json +30 -0
  62. package/fixtures/python_v050_cli/alt_ecpt_lift.json +85 -0
  63. package/fixtures/python_v050_cli/alt_liquidity_to_paths.json +85 -0
  64. package/fixtures/python_v050_cli/alt_receiver_lift.json +15 -0
  65. package/fixtures/python_v050_cli/bit_certificate.json +15 -0
  66. package/fixtures/python_v050_cli/bit_compare_baseline.json +24 -0
  67. package/fixtures/python_v050_cli/bit_diagnose.json +95 -0
  68. package/fixtures/python_v050_cli/bit_invert.json +235 -0
  69. package/fixtures/python_v050_cli/bit_mec.json +18 -0
  70. package/fixtures/python_v050_cli/ecology_effective_graph.json +178 -0
  71. package/fixtures/python_v050_cli/ecology_execution_available_paths.json +88 -0
  72. package/fixtures/python_v050_cli/manifest.json +48 -0
  73. package/fixtures/python_v050_cli/phase_lab_certify.json +443 -0
  74. package/fixtures/python_v050_cli/phase_lab_closure.json +85 -0
  75. package/fixtures/python_v050_cli/phase_lab_compare_window.json +24 -0
  76. package/fixtures/python_v050_cli/phase_lab_executable_paths.json +88 -0
  77. package/fixtures/python_v050_cli/phase_lab_graph.json +178 -0
  78. package/fixtures/python_v050_cli/phase_lab_ingest_1.json +105 -0
  79. package/fixtures/python_v050_cli/phase_lab_ingest_2.json +109 -0
  80. package/fixtures/python_v050_cli/phase_lab_init.json +20 -0
  81. package/fixtures/python_v050_cli/phase_lab_list_windows.json +63 -0
  82. package/fixtures/python_v050_cli/phase_lab_observe.json +108 -0
  83. package/fixtures/python_v050_cli/phase_lab_threshold_status.json +164 -0
  84. package/fixtures/python_v050_cli/sqot_diagnose_queue.json +38 -0
  85. package/fixtures/python_v050_cli/sqot_quarantine.json +7 -0
  86. package/fixtures/python_v050_cli/sqot_rebalance.json +19 -0
  87. package/fixtures/python_v050_cli/sqot_reserve_check.json +20 -0
  88. package/fixtures/python_v050_cli/sqot_salience_obstruction.json +19 -0
  89. package/fixtures/python_v050_cli/trc_action_boundary.json +451 -0
  90. package/fixtures/python_v050_cli/trc_tool_trace.json +221 -0
  91. package/fixtures/python_v050_cli/trc_trace_adapter.json +221 -0
  92. package/fixtures/python_v050_demo/asi_proxy_development.json +15 -0
  93. package/fixtures/python_v050_demo/certificate_abstain.example.json +39 -0
  94. package/fixtures/python_v050_demo/closure_report.example.json +39 -0
  95. package/fixtures/python_v050_demo/effective_graph.example.json +112 -0
  96. package/fixtures/python_v050_demo/executable_paths.example.json +20 -0
  97. package/fixtures/python_v050_demo/phase_window_observation.example.json +61 -0
  98. package/fixtures/python_v050_demo/runtime_report_1.json +19 -0
  99. package/fixtures/python_v050_demo/runtime_report_2.json +14 -0
  100. package/fixtures/python_v050_demo/threshold_status.example.json +29 -0
  101. package/fixtures/python_v050_snapshots/manifest.json +39 -0
  102. package/fixtures/python_v050_snapshots/snapshot_list.json +112 -0
  103. package/fixtures/python_v050_snapshots/snapshot_routes.json +926 -0
  104. package/fixtures/python_v050_snapshots/snapshot_show_alt.json +6830 -0
  105. package/fixtures/python_v050_snapshots/snapshot_show_bit.json +594 -0
  106. package/fixtures/python_v050_snapshots/snapshot_show_ecpt.json +2894 -0
  107. package/fixtures/python_v050_snapshots/snapshot_show_sqot.json +2392 -0
  108. package/fixtures/python_v050_snapshots/snapshot_show_trc.json +3037 -0
  109. package/fixtures/python_v050_snapshots/snapshot_verify_alt.json +10 -0
  110. package/fixtures/python_v050_snapshots/snapshot_verify_bit.json +10 -0
  111. package/fixtures/python_v050_snapshots/snapshot_verify_ecpt.json +10 -0
  112. package/fixtures/python_v050_snapshots/snapshot_verify_sqot.json +10 -0
  113. package/fixtures/python_v050_snapshots/snapshot_verify_trc.json +10 -0
  114. package/package.json +45 -3
  115. package/schemas/ASIProxyThresholdSpec.schema.json +72 -0
  116. package/schemas/ASIProxyThresholdStatus.schema.json +512 -0
  117. package/schemas/ActionBoundaryRequirement.schema.json +28 -0
  118. package/schemas/ActivationGainEstimate.schema.json +41 -0
  119. package/schemas/AltEcptLiftReport.schema.json +400 -0
  120. package/schemas/AltLiftBlocker.schema.json +34 -0
  121. package/schemas/AttentionBudgetLedger.schema.json +41 -0
  122. package/schemas/AutocatalyticClosureReport.schema.json +408 -0
  123. package/schemas/AutocatalyticClosureWitness.schema.json +22 -139
  124. package/schemas/BasinReachabilityProxy.schema.json +21 -0
  125. package/schemas/BottleneckClassDiagnosis.schema.json +115 -0
  126. package/schemas/BottleneckInversionCandidate.schema.json +249 -0
  127. package/schemas/BottleneckInversionReport.schema.json +499 -0
  128. package/schemas/CapabilityExpressionPath.schema.json +45 -0
  129. package/schemas/CapitalToPathContribution.schema.json +53 -0
  130. package/schemas/ClosureAbstentionReason.schema.json +25 -0
  131. package/schemas/ClosureCertificateCandidate.schema.json +109 -0
  132. package/schemas/ClosureDefect.schema.json +28 -0
  133. package/schemas/ClosureSupportHyperpath.schema.json +44 -0
  134. package/schemas/CollectivePhaseAbstentionReport.schema.json +591 -0
  135. package/schemas/CollectivePhaseCertificateCandidate.schema.json +688 -0
  136. package/schemas/CrossContextTransferWitness.schema.json +46 -0
  137. package/schemas/DiagnosticReserveReport.schema.json +87 -0
  138. package/schemas/DownstreamSearchCostDelta.schema.json +46 -0
  139. package/schemas/EcologyAutocatalyticClosureWitness.schema.json +187 -0
  140. package/schemas/EffectiveGraphResidualSummary.schema.json +38 -0
  141. package/schemas/EffectivePacketEdge.schema.json +135 -0
  142. package/schemas/EffectivePacketEligibility.schema.json +84 -0
  143. package/schemas/EffectivePacketGraph.schema.json +461 -0
  144. package/schemas/EffectivePacketGraphBuildReport.schema.json +521 -0
  145. package/schemas/EffectivePacketNode.schema.json +199 -0
  146. package/schemas/ExecutableClosureWitness.schema.json +47 -0
  147. package/schemas/ExecutablePathDensityReport.schema.json +314 -0
  148. package/schemas/ExecutionAuthorityStatus.schema.json +28 -0
  149. package/schemas/ExecutionAvailableHyperpath.schema.json +201 -0
  150. package/schemas/ExecutionPathDefect.schema.json +28 -0
  151. package/schemas/ExecutionPathWitness.schema.json +44 -0
  152. package/schemas/FalseLiquidityLoad.schema.json +21 -0
  153. package/schemas/GeneralIntakePolicy.schema.json +1 -1
  154. package/schemas/InversionCertificate.schema.json +56 -0
  155. package/schemas/LiquidityToClosureContribution.schema.json +53 -0
  156. package/schemas/MinimalEnablingCondition.schema.json +48 -0
  157. package/schemas/PacketContributionStatus.schema.json +32 -0
  158. package/schemas/PacketQuarantineDecision.schema.json +50 -0
  159. package/schemas/PhaseCertificateDefect.schema.json +33 -0
  160. package/schemas/PhaseComponentObservation.schema.json +39 -0
  161. package/schemas/PhaseLabEvent.schema.json +123 -0
  162. package/schemas/PhaseLabExportManifest.schema.json +127 -0
  163. package/schemas/PhaseLabIngestReport.schema.json +344 -0
  164. package/schemas/PhaseLabStoreManifest.schema.json +73 -0
  165. package/schemas/PhaseLabWindowIndex.schema.json +78 -0
  166. package/schemas/PhaseThresholdStatus.schema.json +51 -0
  167. package/schemas/PhaseWindow.schema.json +31 -0
  168. package/schemas/PhaseWindowComparison.schema.json +67 -0
  169. package/schemas/PhaseWindowObservation.schema.json +353 -0
  170. package/schemas/PostInversionAuditPlan.schema.json +38 -0
  171. package/schemas/ProductiveClosureWitness.schema.json +49 -0
  172. package/schemas/ProvenanceManifest.schema.json +1 -1
  173. package/schemas/QueueOccupationReport.schema.json +156 -0
  174. package/schemas/QueueRebalancePlan.schema.json +114 -0
  175. package/schemas/ReceiverContextSupport.schema.json +23 -0
  176. package/schemas/ReceiverLiquidityLift.schema.json +58 -0
  177. package/schemas/ReleaseArtifactManifest.schema.json +1 -1
  178. package/schemas/ReversibleSalienceSovereigntyCertificate.schema.json +53 -0
  179. package/schemas/RollbackOrDeactivationPlan.schema.json +38 -0
  180. package/schemas/SBOMManifest.schema.json +1 -1
  181. package/schemas/SalienceObstructionDiagnosis.schema.json +55 -0
  182. package/schemas/SalienceObstructionLoad.schema.json +21 -0
  183. package/schemas/SemanticEdgeEvidence.schema.json +40 -0
  184. package/schemas/TraceAdapterReport.schema.json +405 -0
  185. package/schemas/TraceFrontierDebt.schema.json +43 -0
  186. package/schemas/TraceNormalForm.schema.json +181 -0
  187. package/schemas/TraceToleranceLedger.schema.json +29 -0
  188. package/schemas/TypedActionBoundary.schema.json +58 -0
  189. package/schemas/TypedAgentTrace.schema.json +328 -0
  190. package/schemas/TypedToolCallTrace.schema.json +76 -0
  191. package/schemas/VerificationQueuePressure.schema.json +41 -0
  192. package/schemas/VerificationThroughputWindow.schema.json +21 -0
  193. package/schemas/WasteLoad.schema.json +21 -0
  194. package/schemas/WebFetchPolicy.schema.json +1 -1
  195. package/schemas/bundle.schema.json +11854 -2075
  196. package/schemas/index.json +445 -0
  197. package/schemas/schema-digest.json +733 -289
@@ -0,0 +1,1124 @@
1
+ // src/phase_lab/index.ts
2
+ import { createHash } from "crypto";
3
+ import {
4
+ existsSync,
5
+ mkdirSync,
6
+ readFileSync,
7
+ readdirSync,
8
+ writeFileSync
9
+ } from "fs";
10
+ import { basename, join } from "path";
11
+
12
+ // src/core/json.ts
13
+ function sortJson(value) {
14
+ if (Array.isArray(value)) {
15
+ return value.map((item) => sortJson(item));
16
+ }
17
+ if (value && typeof value === "object") {
18
+ const input = value;
19
+ const output = {};
20
+ for (const key of Object.keys(input).sort()) {
21
+ const child = input[key];
22
+ if (child !== void 0) {
23
+ output[key] = sortJson(child);
24
+ }
25
+ }
26
+ return output;
27
+ }
28
+ return value;
29
+ }
30
+ function stableStringify(value) {
31
+ return `${JSON.stringify(sortJson(value), null, 2)}
32
+ `;
33
+ }
34
+ function parseJsonObject(text, label = "JSON") {
35
+ const parsed = JSON.parse(text);
36
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
37
+ throw new Error(`${label} must be a JSON object`);
38
+ }
39
+ return parsed;
40
+ }
41
+ function dedupeSorted(values) {
42
+ return [
43
+ ...new Set([...values].filter((item) => Boolean(item)))
44
+ ].sort();
45
+ }
46
+
47
+ // src/phase_lab/index.ts
48
+ var PHASE_LAB_SAFETY = [
49
+ "phase lab stores local report data only",
50
+ "phase lab never executes report or packet content",
51
+ "phase lab diagnostics do not settle claims",
52
+ "raw packet volume is diagnostic only"
53
+ ];
54
+ var GRAPH_SAFETY = [
55
+ "raw packet volume is diagnostic only",
56
+ "candidate-only nodes do not improve positive phase components",
57
+ "graph construction does not execute packet content",
58
+ "graph construction does not settle claims"
59
+ ];
60
+ function sha256Json(data) {
61
+ return createHash("sha256").update(JSON.stringify(sortJson(data)), "utf8").digest("hex");
62
+ }
63
+ function asRecord(value) {
64
+ return value && typeof value === "object" && !Array.isArray(value) ? value : void 0;
65
+ }
66
+ function asRecords(value) {
67
+ return Array.isArray(value) ? value.filter((item) => Boolean(asRecord(item))) : [];
68
+ }
69
+ function stringList(value) {
70
+ if (value === void 0 || value === null) return [];
71
+ if (Array.isArray(value)) return value.map(String).sort();
72
+ if (value instanceof Set) return [...value].map(String).sort();
73
+ return [String(value)];
74
+ }
75
+ function numeric(value) {
76
+ if (typeof value === "number" && Number.isFinite(value)) return value;
77
+ const parsed = Number(value);
78
+ return Number.isFinite(parsed) ? parsed : 0;
79
+ }
80
+ function numericDict(value) {
81
+ const record = asRecord(value);
82
+ if (!record) return {};
83
+ return Object.fromEntries(
84
+ Object.entries(record).map(([key, item]) => [key, numeric(item)]).sort(([a], [b]) => a.localeCompare(b))
85
+ );
86
+ }
87
+ function residualSummary(payload) {
88
+ const direct = asRecord(payload.residual_summary) ?? asRecord(payload.residual_ledger_summary);
89
+ if (direct) return numericDict(direct);
90
+ const coordinates = asRecord(asRecord(payload.residual_ledger)?.coordinates);
91
+ if (!coordinates) return {};
92
+ const summary = {};
93
+ for (const coordinate of Object.values(coordinates)) {
94
+ const item = asRecord(coordinate);
95
+ if (!item) continue;
96
+ const kind = String(item.kind ?? "residual");
97
+ summary[kind] = (summary[kind] ?? 0) + numeric(item.value);
98
+ }
99
+ return Object.fromEntries(
100
+ Object.entries(summary).sort(([a], [b]) => a.localeCompare(b))
101
+ );
102
+ }
103
+ function residualDebt(summary) {
104
+ return Object.values(summary).reduce((total, value) => total + value, 0);
105
+ }
106
+ function inferSchemaHint(payload) {
107
+ if ("packet_id" in payload && "content_digest" in payload && "content" in payload) {
108
+ return "PacketExchangeEnvelope";
109
+ }
110
+ if ("report_id" in payload && "registry" in payload)
111
+ return "RuntimeStepReport";
112
+ if ("graph_id" in payload && "nodes" in payload && "edges" in payload) {
113
+ return "EffectivePacketGraph";
114
+ }
115
+ if ("message_id" in payload) return "AgentMessageEnvelope";
116
+ if ("decision_id" in payload && "packet_id" in payload)
117
+ return "ALTAdmissionDecision";
118
+ if ("accepted" in payload && "workflow_usable" in payload)
119
+ return "AgentCheckReport";
120
+ return String(payload.schema_hint ?? payload.schema ?? "UnknownPICReport");
121
+ }
122
+ function inferSourceKind(payload, schemaHint) {
123
+ if (typeof payload.source_kind === "string") return payload.source_kind;
124
+ const mapping = {
125
+ AgentCheckReport: "agent-check",
126
+ AgentMessageEnvelope: "agent-message",
127
+ ALTAdmissionDecision: "alt-admission",
128
+ EffectivePacketGraph: "effective-graph",
129
+ PacketExchangeEnvelope: "packet-exchange",
130
+ RuntimeStepReport: "runtime-step-report"
131
+ };
132
+ return mapping[schemaHint] ?? "unknown-report";
133
+ }
134
+ function unsafeReasons(payload, missing, candidateOnlyReasons, settledBlockers) {
135
+ const text = JSON.stringify(payload).toLowerCase();
136
+ const reasons = [];
137
+ if ([
138
+ "npm install",
139
+ "npx",
140
+ "node ",
141
+ "docker run",
142
+ "kubectl",
143
+ "curl ",
144
+ "bash ",
145
+ "powershell",
146
+ "safe_commands"
147
+ ].some((marker) => text.includes(marker))) {
148
+ reasons.push("embedded command-like text remains inert");
149
+ }
150
+ if (missing.length > 0) reasons.push("missing obligations remain visible");
151
+ if (candidateOnlyReasons.length > 0)
152
+ reasons.push("candidate-only reasons remain visible");
153
+ if (settledBlockers.length > 0)
154
+ reasons.push("settlement blockers remain visible");
155
+ return dedupeSorted(reasons);
156
+ }
157
+ function eventFromPayload(payload, windowId, sequence, sourcePath, sourceKindOverride) {
158
+ const digest = sha256Json(payload);
159
+ const schemaHint = inferSchemaHint(payload);
160
+ const sourceKind = sourceKindOverride ?? inferSourceKind(payload, schemaHint);
161
+ const missing = dedupeSorted([
162
+ ...stringList(payload.missing_obligations),
163
+ ...stringList(payload.unresolved_obligations)
164
+ ]);
165
+ const candidateOnlyReasons = dedupeSorted(
166
+ stringList(payload.candidate_only_reasons)
167
+ );
168
+ const settledBlockers = dedupeSorted([
169
+ ...stringList(payload.settled_blockers),
170
+ ...payload.settled === true ? ["source-settled-ignored-by-phase-lab"] : []
171
+ ]);
172
+ const accepted = payload.accepted === true;
173
+ const candidateOnly = payload.candidate_only === true || candidateOnlyReasons.length > 0 || !accepted || [
174
+ "packet-exchange",
175
+ "general-intake",
176
+ "raw-external",
177
+ "phase-dashboard"
178
+ ].includes(sourceKind);
179
+ const reasons = unsafeReasons(
180
+ payload,
181
+ missing,
182
+ candidateOnlyReasons,
183
+ settledBlockers
184
+ );
185
+ const positiveContributionAllowed = accepted && !candidateOnly && reasons.length === 0 && missing.length === 0;
186
+ return {
187
+ accepted,
188
+ candidate_only: candidateOnly,
189
+ candidate_only_reasons: candidateOnlyReasons,
190
+ content_digest: digest,
191
+ event_id: `phase-lab-event:${sequence}:${digest.slice(0, 12)}`,
192
+ missing_obligations: missing,
193
+ operationally_usable: payload.operationally_usable === true,
194
+ payload,
195
+ positive_contribution_allowed: positiveContributionAllowed,
196
+ reasons: dedupeSorted([
197
+ "event content is stored as inert data",
198
+ ...reasons,
199
+ ...candidateOnly ? ["candidate-only event cannot improve phase metrics"] : []
200
+ ]),
201
+ residual_summary: residualSummary(payload),
202
+ safety_boundary: PHASE_LAB_SAFETY,
203
+ schema_hint: schemaHint,
204
+ settled: false,
205
+ settled_blockers: settledBlockers,
206
+ source_kind: sourceKind,
207
+ source_path: sourcePath ? basename(sourcePath) : null,
208
+ window_id: windowId,
209
+ workflow_usable: payload.workflow_usable === true
210
+ };
211
+ }
212
+ function readJsonFile(path, label = "JSON") {
213
+ if (!path.toLowerCase().endsWith(".json")) {
214
+ throw new Error(
215
+ `${label} must be a JSON file; YAML input is not enabled in PIC-TS v0.5.0`
216
+ );
217
+ }
218
+ return parseJsonObject(readFileSync(path, "utf8"), label);
219
+ }
220
+ function storePaths(storeDir) {
221
+ return {
222
+ events: join(storeDir, "events.jsonl"),
223
+ manifest: join(storeDir, "manifest.json"),
224
+ windows: join(storeDir, "windows")
225
+ };
226
+ }
227
+ function windowFileName(windowId) {
228
+ return `${windowId.replace(/[^A-Za-z0-9_.-]/g, "_")}.json`;
229
+ }
230
+ function readEvents(storeDir) {
231
+ const eventsPath = storePaths(storeDir).events;
232
+ if (!existsSync(eventsPath)) return [];
233
+ return readFileSync(eventsPath, "utf8").split(/\r?\n/).filter(Boolean).map((line) => parseJsonObject(line, "phase lab event"));
234
+ }
235
+ function writeJson(path, data) {
236
+ writeFileSync(path, stableStringify(data), "utf8");
237
+ }
238
+ function windowIndex(windowId, sequence, events) {
239
+ const residual = events.reduce(
240
+ (total, event) => total + residualDebt(numericDict(event.residual_summary)),
241
+ 0
242
+ );
243
+ return {
244
+ accepted: true,
245
+ accepted_event_count: events.filter((event) => event.accepted === true).length,
246
+ candidate_only_event_count: events.filter(
247
+ (event) => event.candidate_only === true
248
+ ).length,
249
+ event_count: events.length,
250
+ event_ids: events.map((event) => String(event.event_id)),
251
+ missing_obligation_count: events.reduce(
252
+ (total, event) => total + stringList(event.missing_obligations).length,
253
+ 0
254
+ ),
255
+ positive_contribution_event_count: events.filter(
256
+ (event) => event.positive_contribution_allowed === true
257
+ ).length,
258
+ reasons: ["window index preserves event residuals without settling claims"],
259
+ residual_debt: residual,
260
+ sequence,
261
+ settled: false,
262
+ settled_event_count: 0,
263
+ window_id: windowId
264
+ };
265
+ }
266
+ function readWindowIndexes(storeDir) {
267
+ const windowsDir = storePaths(storeDir).windows;
268
+ if (!existsSync(windowsDir)) return [];
269
+ return readdirSync(windowsDir).filter((name) => name !== "latest.json" && name.endsWith(".json")).sort().map(
270
+ (name) => parseJsonObject(readFileSync(join(windowsDir, name), "utf8"), "window")
271
+ );
272
+ }
273
+ function selectWindow(storeDir, selector = "latest") {
274
+ const windows = readWindowIndexes(storeDir);
275
+ if (windows.length === 0) throw new Error("phase lab store has no windows");
276
+ let selected;
277
+ if (selector === "latest" || selector === "all") {
278
+ selected = windows[windows.length - 1];
279
+ } else if (selector === "previous") {
280
+ selected = windows.length > 1 ? windows[windows.length - 2] : windows[windows.length - 1];
281
+ } else {
282
+ selected = windows.find((window) => window.window_id === selector);
283
+ }
284
+ if (!selected)
285
+ throw new Error(`unknown phase lab window ${JSON.stringify(selector)}`);
286
+ const selectedId = String(selected.window_id);
287
+ const events = selector === "all" ? readEvents(storeDir) : readEvents(storeDir).filter((event) => event.window_id === selectedId);
288
+ return { index: selected, events };
289
+ }
290
+ function writeManifest(storeDir) {
291
+ const paths = storePaths(storeDir);
292
+ mkdirSync(paths.windows, { recursive: true });
293
+ const windows = readWindowIndexes(storeDir);
294
+ const events = readEvents(storeDir);
295
+ const manifest = {
296
+ accepted: true,
297
+ database_path: "events.jsonl",
298
+ event_count: events.length,
299
+ latest_window_id: windows.length > 0 ? String(windows[windows.length - 1]?.window_id ?? "") : null,
300
+ reasons: ["phase lab store is local and non-executing"],
301
+ safety_invariants: PHASE_LAB_SAFETY,
302
+ schema_version: "phase-lab-store-v1",
303
+ settled: false,
304
+ store_id: "phase-lab-store",
305
+ store_path: basename(storeDir),
306
+ window_count: windows.length
307
+ };
308
+ writeJson(paths.manifest, manifest);
309
+ return manifest;
310
+ }
311
+ function initPhaseLabStore(outputDir) {
312
+ const paths = storePaths(outputDir);
313
+ mkdirSync(paths.windows, { recursive: true });
314
+ if (!existsSync(paths.events)) writeFileSync(paths.events, "", "utf8");
315
+ return writeManifest(outputDir);
316
+ }
317
+ function ingestPayloads(storeDir, payloads) {
318
+ initPhaseLabStore(storeDir);
319
+ const sequence = readWindowIndexes(storeDir).length;
320
+ const offset = readEvents(storeDir).length;
321
+ const windowId = `phase-window:${String(sequence).padStart(4, "0")}`;
322
+ const events = payloads.map(
323
+ (item, index2) => eventFromPayload(
324
+ item.payload,
325
+ windowId,
326
+ offset + index2,
327
+ item.path,
328
+ item.sourceKind
329
+ )
330
+ );
331
+ const index = windowIndex(windowId, sequence, events);
332
+ const paths = storePaths(storeDir);
333
+ const append = events.map((event) => JSON.stringify(sortJson(event))).join("\n");
334
+ if (append) {
335
+ writeFileSync(paths.events, `${append}
336
+ `, { encoding: "utf8", flag: "a" });
337
+ }
338
+ writeJson(join(paths.windows, windowFileName(windowId)), index);
339
+ writeJson(join(paths.windows, "latest.json"), index);
340
+ const manifest = writeManifest(storeDir);
341
+ return {
342
+ accepted: events.length > 0,
343
+ content_treated_as_data: true,
344
+ executed_command_count: 0,
345
+ ingested_events: events,
346
+ reasons: [
347
+ "ingested files were stored as inert local data",
348
+ "no embedded command, safe_command, network, repository, or model action was executed"
349
+ ],
350
+ rejected_paths: [],
351
+ report_id: `phase-lab-ingest:${windowId}`,
352
+ settled: false,
353
+ store_manifest: manifest,
354
+ window: index,
355
+ workflow_usable: true
356
+ };
357
+ }
358
+ function ingestPhaseLabReport(storeDir, reportPath) {
359
+ return ingestPayloads(storeDir, [
360
+ { payload: readJsonFile(reportPath, "phase lab report"), path: reportPath }
361
+ ]);
362
+ }
363
+ function ingestPhaseLabPacket(storeDir, packetPath) {
364
+ return ingestPayloads(storeDir, [
365
+ {
366
+ payload: readJsonFile(packetPath, "phase lab packet"),
367
+ path: packetPath,
368
+ sourceKind: "packet-exchange"
369
+ }
370
+ ]);
371
+ }
372
+ function ingestPhaseLabFiles(storeDir, reportPaths = [], packetPaths = []) {
373
+ const payloads = [
374
+ ...reportPaths.map((path) => ({
375
+ payload: readJsonFile(path, "phase lab report"),
376
+ path
377
+ })),
378
+ ...packetPaths.map((path) => ({
379
+ payload: readJsonFile(path, "phase lab packet"),
380
+ path,
381
+ sourceKind: "packet-exchange"
382
+ }))
383
+ ];
384
+ if (payloads.length === 0) {
385
+ throw new Error("provide at least one Phase Lab report or packet");
386
+ }
387
+ return ingestPayloads(storeDir, payloads);
388
+ }
389
+ function ingestPhaseLabDirectory(storeDir, directory) {
390
+ if (!existsSync(directory))
391
+ throw new Error(`phase lab directory does not exist: ${directory}`);
392
+ const payloads = readdirSync(directory).filter((name) => name.toLowerCase().endsWith(".json")).sort().map((name) => {
393
+ const path = join(directory, name);
394
+ return { payload: readJsonFile(path, "phase lab directory item"), path };
395
+ });
396
+ return ingestPayloads(storeDir, payloads);
397
+ }
398
+ function listPhaseLabWindows(storeDir) {
399
+ return {
400
+ settled: false,
401
+ store_manifest: writeManifest(storeDir),
402
+ windows: readWindowIndexes(storeDir)
403
+ };
404
+ }
405
+ function eligibilityBlockers(event) {
406
+ const joined = [
407
+ event.source_kind,
408
+ ...stringList(event.missing_obligations),
409
+ ...stringList(event.candidate_only_reasons),
410
+ ...stringList(event.settled_blockers),
411
+ ...stringList(event.reasons)
412
+ ].join(" ").toLowerCase();
413
+ const blockers = [];
414
+ const markers = {
415
+ "authority-invalid": [
416
+ "authority-invalid",
417
+ "missing authority",
418
+ "authority"
419
+ ],
420
+ "candidate-only": ["candidate-only"],
421
+ "hash-invalid": ["hash-invalid", "digest mismatch"],
422
+ "raw-external-volume": ["general-intake", "raw-external"],
423
+ "rollback-missing": ["rollback", "safe abort"],
424
+ "salience-obstruction": ["salience", "queue occupation"],
425
+ stale: ["stale", "expired"],
426
+ "verification-blocked": [
427
+ "missing evidence",
428
+ "missing verifier",
429
+ "verification"
430
+ ]
431
+ };
432
+ for (const [blocker, needles] of Object.entries(markers)) {
433
+ if (needles.some((needle) => joined.includes(needle)))
434
+ blockers.push(blocker);
435
+ }
436
+ if (event.candidate_only === true) blockers.push("candidate-only");
437
+ return dedupeSorted(blockers);
438
+ }
439
+ function nodeFromEvent(event) {
440
+ const blockers = eligibilityBlockers(event);
441
+ const eligible = event.positive_contribution_allowed === true && blockers.length === 0;
442
+ const status = eligible ? "accepted" : event.candidate_only === true ? "candidate-only" : "diagnostic";
443
+ return {
444
+ accepted: event.accepted === true,
445
+ content_digest: String(event.content_digest ?? ""),
446
+ contribution: {
447
+ candidate_only: !eligible,
448
+ non_contributing_reason: eligible ? "" : "eligibility blockers prevent positive contribution",
449
+ positive_contribution: eligible,
450
+ settled: false,
451
+ status
452
+ },
453
+ eligibility: {
454
+ accepted_or_certificate_admissible: event.accepted === true,
455
+ agent_text_not_treated_as_evidence: event.source_kind !== "agent-text-only",
456
+ authority_valid: !blockers.includes("authority-invalid"),
457
+ blockers,
458
+ eligible,
459
+ hash_valid: !blockers.includes("hash-invalid"),
460
+ not_raw_external_volume: !blockers.includes("raw-external-volume"),
461
+ not_registry_metadata_only: event.source_kind !== "registry-metadata",
462
+ not_salience_blocked: !blockers.includes("salience-obstruction"),
463
+ not_stale: !blockers.includes("stale"),
464
+ not_verification_blocked: !blockers.includes("verification-blocked"),
465
+ residuals_preserved: true,
466
+ retrievable: Boolean(event.content_digest),
467
+ rollback_available_or_not_required: !blockers.includes("rollback-missing"),
468
+ within_validity_domain: true
469
+ },
470
+ missing_obligations: stringList(event.missing_obligations),
471
+ node_id: `node:${String(event.content_digest ?? "").slice(0, 12)}`,
472
+ operationally_usable: event.operationally_usable === true,
473
+ reasons: stringList(event.reasons),
474
+ residual_summary: numericDict(event.residual_summary),
475
+ schema_hint: String(event.schema_hint ?? "UnknownPICReport"),
476
+ settled: false,
477
+ source_event_id: String(event.event_id ?? ""),
478
+ source_kind: String(event.source_kind ?? "unknown-report"),
479
+ workflow_usable: event.workflow_usable === true
480
+ };
481
+ }
482
+ function extractEdges(payload) {
483
+ const edges = [];
484
+ for (const key of ["edges", "edge_witnesses", "edge_certificates"]) {
485
+ edges.push(...asRecords(payload[key]));
486
+ }
487
+ const registry = asRecord(payload.registry);
488
+ if (registry) edges.push(...extractEdges(registry));
489
+ const content = asRecord(payload.content);
490
+ if (content) edges.push(...extractEdges(content));
491
+ return edges;
492
+ }
493
+ function nodeIdForRef(ref, nodes) {
494
+ if (!ref) return void 0;
495
+ return nodes.map((node) => String(node.node_id)).find((nodeId) => {
496
+ const node = nodes.find((item) => item.node_id === nodeId);
497
+ return node && [
498
+ node.node_id,
499
+ node.content_digest,
500
+ String(node.content_digest).slice(0, 12),
501
+ node.source_event_id
502
+ ].map(String).includes(ref);
503
+ });
504
+ }
505
+ function nodePositive(nodeId, nodes) {
506
+ const node = nodes.find((item) => item.node_id === nodeId);
507
+ return asRecord(node?.contribution)?.positive_contribution === true;
508
+ }
509
+ function edgesFromEvents(nodes, events) {
510
+ const edges = [];
511
+ events.forEach((event, eventIndex) => {
512
+ const node = nodes[eventIndex];
513
+ if (!node) return;
514
+ extractEdges(asRecord(event.payload) ?? {}).forEach((edge, index) => {
515
+ const sourceIds = stringList(edge.source_packet_ids).map((ref) => nodeIdForRef(ref, nodes)).filter((item) => Boolean(item));
516
+ const target = nodeIdForRef(String(edge.target_packet_id ?? ""), nodes) ?? String(node.node_id);
517
+ const evidenceRefs = stringList(edge.evidence_refs);
518
+ const accepted = edge.accepted === true || event.accepted === true;
519
+ const evidenceSupported = accepted && evidenceRefs.length > 0;
520
+ const positive = evidenceSupported && sourceIds.every((source) => nodePositive(source, nodes)) && nodePositive(target, nodes);
521
+ const edgeId = String(
522
+ edge.edge_id ?? `edge:${String(node.node_id)}:${index}`
523
+ );
524
+ edges.push({
525
+ accepted,
526
+ contribution: {
527
+ candidate_only: !positive,
528
+ non_contributing_reason: positive ? "" : "edge lacks accepted evidence support",
529
+ positive_contribution: positive,
530
+ settled: false,
531
+ status: positive ? "accepted" : "diagnostic"
532
+ },
533
+ edge_id: edgeId,
534
+ evidence: {
535
+ edge_certificate_refs: stringList(edge.edge_certificate_refs),
536
+ evidence_refs: evidenceRefs,
537
+ evidence_supported: evidenceSupported,
538
+ missing_evidence: evidenceSupported ? [] : ["edge evidence refs required"],
539
+ verifier_resolution_refs: stringList(edge.verifier_resolution_refs)
540
+ },
541
+ reasons: ["edge extracted from inert report data"],
542
+ relation_type: String(
543
+ edge.edge_type ?? edge.relation_type ?? "semantic-dependency"
544
+ ),
545
+ residual_summary: numericDict(event.residual_summary),
546
+ settled: false,
547
+ source_node_ids: sourceIds.length > 0 ? sourceIds : [String(node.node_id)],
548
+ target_node_id: target
549
+ });
550
+ });
551
+ });
552
+ return edges;
553
+ }
554
+ function buildEffectivePacketGraph(input) {
555
+ const events = Array.isArray(input) ? input : Array.isArray(input.events) ? input.events : [];
556
+ const graphId = Array.isArray(input) ? "effective-packet-graph" : String(input.graph_id ?? "effective-packet-graph");
557
+ const sourceWindowId = Array.isArray(input) ? "adhoc" : String(input.source_window_id ?? "adhoc");
558
+ const normalized = events.map(
559
+ (event, index) => event.event_id ? event : eventFromPayload(event, sourceWindowId, index, void 0, void 0)
560
+ );
561
+ const nodes = normalized.map(nodeFromEvent);
562
+ const edges = edgesFromEvents(nodes, normalized);
563
+ const nodeCountByStatus = {};
564
+ for (const node of nodes) {
565
+ const status = String(asRecord(node.contribution)?.status ?? "diagnostic");
566
+ nodeCountByStatus[status] = (nodeCountByStatus[status] ?? 0) + 1;
567
+ }
568
+ const edgeCountByRelation = {};
569
+ for (const edge of edges) {
570
+ const relation = String(edge.relation_type ?? "semantic-dependency");
571
+ edgeCountByRelation[relation] = (edgeCountByRelation[relation] ?? 0) + 1;
572
+ }
573
+ const mergedResidual = {};
574
+ for (const node of nodes) {
575
+ for (const [key, value] of Object.entries(
576
+ numericDict(node.residual_summary)
577
+ )) {
578
+ mergedResidual[key] = (mergedResidual[key] ?? 0) + value;
579
+ }
580
+ }
581
+ const acceptedPacketCapital = nodes.filter(
582
+ (node) => asRecord(node.contribution)?.positive_contribution === true
583
+ ).length;
584
+ return {
585
+ accepted: nodes.length > 0,
586
+ accepted_packet_capital: acceptedPacketCapital,
587
+ candidate_only_packets: nodes.filter(
588
+ (node) => asRecord(node.contribution)?.candidate_only === true
589
+ ).length,
590
+ edge_count_by_relation: Object.fromEntries(
591
+ Object.entries(edgeCountByRelation).sort()
592
+ ),
593
+ edges,
594
+ graph_id: graphId,
595
+ graph_safety_boundary: GRAPH_SAFETY,
596
+ missing_edge_evidence: edges.filter(
597
+ (edge) => edge.accepted === true && asRecord(edge.evidence)?.evidence_supported !== true
598
+ ).map((edge) => String(edge.edge_id)),
599
+ node_count_by_status: Object.fromEntries(
600
+ Object.entries(nodeCountByStatus).sort()
601
+ ),
602
+ nodes,
603
+ non_contributing_volume: nodes.filter(
604
+ (node) => asRecord(node.contribution)?.positive_contribution !== true
605
+ ).length,
606
+ operationally_usable: acceptedPacketCapital > 0,
607
+ reasons: [
608
+ "effective graph separates positive contribution from diagnostic volume",
609
+ "raw packet count does not increase positive phase metrics"
610
+ ],
611
+ rejected_or_quarantined_packets: nodes.filter(
612
+ (node) => ["rejected", "quarantined"].includes(
613
+ String(asRecord(node.contribution)?.status ?? "")
614
+ )
615
+ ).length,
616
+ residual_summary: {
617
+ candidate_only_reasons: dedupeSorted(
618
+ normalized.flatMap((event) => stringList(event.candidate_only_reasons))
619
+ ),
620
+ missing_obligation_count: nodes.reduce(
621
+ (total, node) => total + stringList(node.missing_obligations).length,
622
+ 0
623
+ ),
624
+ residual_debt: residualDebt(mergedResidual),
625
+ residual_summary: Object.fromEntries(
626
+ Object.entries(mergedResidual).sort()
627
+ ),
628
+ settled_blockers: dedupeSorted(
629
+ normalized.flatMap((event) => [
630
+ ...stringList(event.settled_blockers),
631
+ ...stringList(event.missing_obligations)
632
+ ])
633
+ )
634
+ },
635
+ semantic_edge_witnesses: edges.map((edge) => asRecord(edge.evidence)).filter(
636
+ (evidence) => Boolean(evidence?.evidence_supported)
637
+ ),
638
+ settled: false,
639
+ source_window_id: sourceWindowId,
640
+ stale_or_unsafe_packets: nodes.filter(
641
+ (node) => stringList(asRecord(node.eligibility)?.blockers).length > 0
642
+ ).map((node) => String(node.node_id)),
643
+ workflow_usable: true
644
+ };
645
+ }
646
+ function positiveEdges(graph) {
647
+ return asRecords(graph.edges).filter(
648
+ (edge) => asRecord(edge.contribution)?.positive_contribution === true && asRecord(edge.evidence)?.evidence_supported === true
649
+ );
650
+ }
651
+ function observePhaseWindow(window, events, graph) {
652
+ const effectiveNodeCount = numeric(graph.accepted_packet_capital);
653
+ const effectiveEdgeCount = positiveEdges(graph).length;
654
+ const executionAvailablePathCount = detectExecutionAvailablePaths(graph).accepted_path_count;
655
+ const closureWitnessCount = asRecords(
656
+ detectAutocatalyticClosure(graph).closure_witnesses
657
+ ).length;
658
+ const total = Math.max(1, events.length);
659
+ const acceptedPacketCount = events.filter(
660
+ (event) => event.accepted === true
661
+ ).length;
662
+ const missingObligationCount = events.reduce(
663
+ (sum, event) => sum + stringList(event.missing_obligations).length,
664
+ 0
665
+ );
666
+ const residual = numeric(asRecord(graph.residual_summary)?.residual_debt);
667
+ const candidateOnlyCount = events.filter(
668
+ (event) => event.candidate_only === true
669
+ ).length;
670
+ const observation = {
671
+ accepted: events.length > 0,
672
+ accepted_packet_count: acceptedPacketCount,
673
+ alt_certified_capital_count: events.filter(
674
+ (event) => String(event.source_kind).includes("alt") && event.positive_contribution_allowed === true
675
+ ).length,
676
+ alt_liquidity_candidate_count: events.filter(
677
+ (event) => String(event.source_kind).includes("alt")
678
+ ).length,
679
+ autocatalytic_closure_score: effectiveNodeCount > 0 ? closureWitnessCount / effectiveNodeCount : 0,
680
+ basin_reachability_proxy: {
681
+ effective_node_count: effectiveNodeCount,
682
+ execution_available_path_count: executionAvailablePathCount,
683
+ reachability_proxy: executionAvailablePathCount / Math.max(1, effectiveNodeCount)
684
+ },
685
+ bottleneck_count_by_type: Object.fromEntries(
686
+ asRecords(graph.nodes).flatMap((node) => stringList(asRecord(node.eligibility)?.blockers)).reduce((map, blocker) => {
687
+ map.set(blocker, (map.get(blocker) ?? 0) + 1);
688
+ return map;
689
+ }, /* @__PURE__ */ new Map()).entries()
690
+ ),
691
+ candidate_only_packet_count: candidateOnlyCount,
692
+ closure_witness_count: closureWitnessCount,
693
+ components: [
694
+ {
695
+ component: "accepted_packet_count",
696
+ diagnostic_only: false,
697
+ distance: 0,
698
+ positive_contribution_source: "effective-graph-only",
699
+ threshold: 0,
700
+ value: acceptedPacketCount
701
+ },
702
+ {
703
+ component: "raw_volume",
704
+ diagnostic_only: true,
705
+ distance: 0,
706
+ positive_contribution_source: "diagnostic-only",
707
+ threshold: 0,
708
+ value: events.length
709
+ }
710
+ ],
711
+ effective_edge_count: effectiveEdgeCount,
712
+ effective_node_count: effectiveNodeCount,
713
+ execution_available_path_count: executionAvailablePathCount,
714
+ false_liquidity_load: {
715
+ candidate_count: candidateOnlyCount,
716
+ certified_count: 0,
717
+ load: candidateOnlyCount / total
718
+ },
719
+ missing_obligation_count: missingObligationCount,
720
+ observation_id: "phase-window-observation",
721
+ operationally_usable: effectiveNodeCount > 0,
722
+ oracle_truth_proven: false,
723
+ packet_candidate_count: events.length,
724
+ phase_gap_vector: {
725
+ closure: Math.max(0, 1 - closureWitnessCount),
726
+ effective_edges: Math.max(0, 1 - effectiveEdgeCount),
727
+ effective_nodes: Math.max(0, 1 - effectiveNodeCount),
728
+ execution_paths: Math.max(0, 1 - executionAvailablePathCount)
729
+ },
730
+ physical_truth_proven: false,
731
+ proves_physical_or_oracle_truth: false,
732
+ proves_real_asi: false,
733
+ protocol_relative: true,
734
+ protocol_relative_only: true,
735
+ raw_external_volume_diagnostic_only: true,
736
+ real_asi_proof: false,
737
+ reasons: [
738
+ "window observation is protocol-relative only",
739
+ "raw external volume is diagnostic only"
740
+ ],
741
+ residual_debt: residual,
742
+ salience_obstruction_load: {
743
+ blocked_count: candidateOnlyCount,
744
+ load: candidateOnlyCount / total,
745
+ total_count: events.length
746
+ },
747
+ settled: false,
748
+ settled_packet_count: 0,
749
+ threshold_distance: Math.max(0, 1 - effectiveNodeCount) + Math.max(0, 1 - effectiveEdgeCount) + Math.max(0, 1 - closureWitnessCount) + Math.max(0, 1 - executionAvailablePathCount),
750
+ verification_backlog: missingObligationCount,
751
+ verification_throughput: {
752
+ accepted_count: acceptedPacketCount,
753
+ backlog_count: missingObligationCount,
754
+ throughput_ratio: acceptedPacketCount / total
755
+ },
756
+ waste_load: {
757
+ load: numeric(graph.non_contributing_volume) / total,
758
+ non_contributing_volume: numeric(graph.non_contributing_volume),
759
+ total_volume: events.length
760
+ },
761
+ window: {
762
+ event_count: numeric(window.event_count),
763
+ event_ids: stringList(window.event_ids),
764
+ sequence: numeric(window.sequence),
765
+ window_id: String(window.window_id ?? "phase-window")
766
+ },
767
+ workflow_usable: true,
768
+ workflow_usable_packet_count: events.filter(
769
+ (event) => event.workflow_usable === true
770
+ ).length
771
+ };
772
+ return observation;
773
+ }
774
+ function comparePhaseWindows(baseline, candidate) {
775
+ const metricDelta = {
776
+ closure_witness_count: numeric(candidate.closure_witness_count) - numeric(baseline.closure_witness_count),
777
+ effective_edge_count: numeric(candidate.effective_edge_count) - numeric(baseline.effective_edge_count),
778
+ effective_node_count: numeric(candidate.effective_node_count) - numeric(baseline.effective_node_count),
779
+ execution_available_path_count: numeric(candidate.execution_available_path_count) - numeric(baseline.execution_available_path_count),
780
+ residual_debt: numeric(candidate.residual_debt) - numeric(baseline.residual_debt)
781
+ };
782
+ return {
783
+ accepted: true,
784
+ baseline_window_id: String(asRecord(baseline.window)?.window_id ?? ""),
785
+ candidate_window_id: String(asRecord(candidate.window)?.window_id ?? ""),
786
+ comparison_id: "phase-window-comparison",
787
+ diagnostic_only_components: ["packet_candidate_count", "raw_volume"],
788
+ metric_delta: metricDelta,
789
+ positive_progress_components: Object.entries(metricDelta).filter(([key, value]) => key !== "residual_debt" && value > 0).map(([key]) => key),
790
+ reasons: ["comparison preserves protocol-relative diagnostic status"],
791
+ settled: false,
792
+ workflow_usable: true
793
+ };
794
+ }
795
+ function detectAutocatalyticClosure(graph) {
796
+ const closureWitnesses = [];
797
+ const defects = [];
798
+ for (const edge of positiveEdges(graph)) {
799
+ const sources = stringList(edge.source_node_ids);
800
+ const target = String(edge.target_node_id ?? "");
801
+ if (sources.includes(target)) {
802
+ const witnessId = `closure-witness:${String(edge.edge_id)}`;
803
+ closureWitnesses.push({
804
+ accepted: true,
805
+ edge_ids: [String(edge.edge_id)],
806
+ evidence_supported: true,
807
+ execution_available: false,
808
+ packet_ids: dedupeSorted([...sources, target]),
809
+ productive: true,
810
+ protocol_relative_only: true,
811
+ reasons: [
812
+ "witness is evidence-supported within the effective graph",
813
+ "witness remains diagnostic until finite threshold checks pass"
814
+ ],
815
+ settled: false,
816
+ witness_id: witnessId,
817
+ witness_kind: "autocatalytic-closure"
818
+ });
819
+ }
820
+ }
821
+ for (const edge of asRecords(graph.edges)) {
822
+ if (edge.accepted === true && asRecord(edge.evidence)?.evidence_supported !== true) {
823
+ defects.push({
824
+ defect_id: `closure-defect:${String(edge.edge_id)}`,
825
+ defect_type: "missing-edge-evidence",
826
+ packet_or_edge_id: String(edge.edge_id),
827
+ residual_preserved: true
828
+ });
829
+ }
830
+ }
831
+ const status = closureWitnesses.length > 0 && defects.length === 0 ? "candidate" : "abstain";
832
+ return {
833
+ accepted: status === "candidate",
834
+ certificate_candidate: {
835
+ abstention_reasons: closureWitnesses.length > 0 ? [] : [
836
+ {
837
+ missing_evidence_refs: [],
838
+ reason: "closure requires evidence-supported accepted edges",
839
+ reason_id: "closure-abstain:no-evidence-supported-cycle"
840
+ }
841
+ ],
842
+ accepted: status === "candidate",
843
+ certificate_id: "closure-certificate-candidate",
844
+ certificate_status: status,
845
+ defects,
846
+ reasons: [
847
+ "closure candidate is not automatically settled",
848
+ "candidate-only cycles do not count"
849
+ ],
850
+ settled: false,
851
+ witness_ids: closureWitnesses.map(
852
+ (witness) => String(witness.witness_id)
853
+ )
854
+ },
855
+ closure_score: closureWitnesses.length / Math.max(1, asRecords(graph.nodes).length),
856
+ closure_witnesses: closureWitnesses,
857
+ defects,
858
+ executable_witnesses: [],
859
+ graph_id: String(graph.graph_id ?? "effective-packet-graph"),
860
+ operationally_usable: status === "candidate",
861
+ productive_witnesses: closureWitnesses.map((witness) => ({
862
+ accepted: true,
863
+ packet_ids: witness.packet_ids,
864
+ productive_edge_ids: witness.edge_ids,
865
+ productivity_lower_bound: 0.1,
866
+ reasons: [
867
+ "self-supporting evidence edge is productive in declared scope"
868
+ ],
869
+ settled: false,
870
+ witness_id: `productive:${String(witness.witness_id)}`
871
+ })),
872
+ reasons: ["closure detection does not execute or settle paths"],
873
+ report_id: "autocatalytic-closure-report",
874
+ settled: false,
875
+ support_hyperpaths: [],
876
+ workflow_usable: true
877
+ };
878
+ }
879
+ function detectExecutionAvailablePaths(graph) {
880
+ const paths = positiveEdges(graph).map((edge) => {
881
+ const pathId = `execution-path:${String(edge.edge_id)}`;
882
+ const reasons = [
883
+ "execution authority is not granted by PIC-TS",
884
+ "receiver context and action boundary remain diagnostic"
885
+ ];
886
+ return {
887
+ accepted: false,
888
+ action_boundary_requirements: [
889
+ {
890
+ requirement_id: `${pathId}:authority`,
891
+ requirement_type: "explicit-scope-bounded-authority",
892
+ residual: "host runtime authority required",
893
+ satisfied: false
894
+ }
895
+ ],
896
+ authority_status: {
897
+ authority_status: "not-granted",
898
+ explicit_scope_bounded: false,
899
+ grants_execution: false,
900
+ reasons
901
+ },
902
+ blocked: true,
903
+ candidate_only: true,
904
+ edge_ids: [String(edge.edge_id)],
905
+ not_executed: true,
906
+ packet_ids: dedupeSorted([
907
+ ...stringList(edge.source_node_ids),
908
+ String(edge.target_node_id ?? "")
909
+ ]),
910
+ path_id: pathId,
911
+ reasons,
912
+ receiver_context: {
913
+ evidence_refs: [],
914
+ present: false,
915
+ receiver_context_id: "receiver-context:missing"
916
+ },
917
+ settled: false,
918
+ witness: {
919
+ accepted: false,
920
+ edge_ids: [String(edge.edge_id)],
921
+ packet_ids: dedupeSorted([
922
+ ...stringList(edge.source_node_ids),
923
+ String(edge.target_node_id ?? "")
924
+ ]),
925
+ reasons,
926
+ settled: false,
927
+ witness_id: `execution-witness:${String(edge.edge_id)}`
928
+ }
929
+ };
930
+ });
931
+ return {
932
+ accepted: paths.length > 0,
933
+ accepted_path_count: 0,
934
+ authority_requirements: ["explicit-scope-bounded-authority"],
935
+ blocked_path_count: paths.length,
936
+ blocker_reason_by_path: Object.fromEntries(
937
+ paths.map((path) => [String(path.path_id), stringList(path.reasons)])
938
+ ),
939
+ candidate_only_path_count: paths.length,
940
+ executed_path_count: 0,
941
+ execution_authority_granted: false,
942
+ graph_id: String(graph.graph_id ?? "effective-packet-graph"),
943
+ operationally_usable: false,
944
+ path_count: paths.length,
945
+ path_density: 0,
946
+ paths,
947
+ reasons: ["execution-available path detection never executes paths"],
948
+ report_id: "execution-available-path-density",
949
+ residual_carry_forward: stringList(
950
+ asRecord(graph.residual_summary)?.settled_blockers
951
+ ),
952
+ rollback_requirements: ["rollback-or-safe-abort"],
953
+ settled: false,
954
+ workflow_usable: true
955
+ };
956
+ }
957
+ function buildPhaseThresholdStatus(observation, threshold) {
958
+ const pathDensity = numeric(
959
+ asRecord(observation.basin_reachability_proxy)?.reachability_proxy
960
+ );
961
+ const checks = {
962
+ maximum_false_liquidity_load: numeric(asRecord(observation.false_liquidity_load)?.load) <= numeric(threshold.maximum_false_liquidity_load ?? 0.5),
963
+ maximum_residual_debt: numeric(observation.residual_debt) <= numeric(threshold.maximum_residual_debt ?? 0),
964
+ maximum_salience_obstruction: numeric(asRecord(observation.salience_obstruction_load)?.load) <= numeric(threshold.maximum_salience_obstruction ?? 0.5),
965
+ minimum_accepted_packet_count: numeric(observation.accepted_packet_count) >= numeric(threshold.minimum_accepted_packet_count ?? 1),
966
+ minimum_alt_to_ecpt_lift_count: numeric(observation.alt_certified_capital_count) >= numeric(threshold.minimum_alt_to_ecpt_lift_count ?? 0),
967
+ minimum_closure_witness_count: numeric(observation.closure_witness_count) >= numeric(threshold.minimum_closure_witness_count ?? 1),
968
+ minimum_effective_edge_count: numeric(observation.effective_edge_count) >= numeric(threshold.minimum_effective_edge_count ?? 1),
969
+ minimum_execution_available_path_density: pathDensity >= numeric(threshold.minimum_execution_available_path_density ?? 0.1),
970
+ minimum_verification_throughput: numeric(
971
+ asRecord(observation.verification_throughput)?.throughput_ratio
972
+ ) >= numeric(threshold.minimum_verification_throughput ?? 0.1)
973
+ };
974
+ const failed = Object.entries(checks).filter(([, passed]) => !passed).map(([key]) => key).sort();
975
+ const status = failed.length === 0 ? "candidate" : "abstain";
976
+ return {
977
+ accepted: status === "candidate",
978
+ abstention_reasons: failed.map(
979
+ (component) => `missing finite threshold component: ${component}`
980
+ ),
981
+ certificate_status: status,
982
+ component_status: Object.fromEntries(Object.entries(checks).sort()),
983
+ failed_components: failed,
984
+ oracle_truth_proven: false,
985
+ physical_truth_proven: false,
986
+ protocol_relative: true,
987
+ protocol_relative_only: true,
988
+ real_asi_proof: false,
989
+ reasons: [
990
+ "threshold status is protocol-relative only",
991
+ "threshold status does not prove real ASI"
992
+ ],
993
+ rejection_reasons: [],
994
+ settled: false,
995
+ status_id: "asi-proxy-threshold-status",
996
+ threshold,
997
+ threshold_distance: failed.length,
998
+ observation
999
+ };
1000
+ }
1001
+ function buildCollectivePhaseCertificateCandidate(thresholdStatus, graph) {
1002
+ const status = String(thresholdStatus.certificate_status ?? "abstain");
1003
+ const defects = stringList(thresholdStatus.failed_components).map(
1004
+ (component) => ({
1005
+ component,
1006
+ defect_id: `phase-defect:${component}`,
1007
+ defect_type: "threshold-component-missing",
1008
+ required_remediation: `provide finite evidence for ${component}`,
1009
+ residual_preserved: true
1010
+ })
1011
+ );
1012
+ return {
1013
+ accepted: status === "candidate",
1014
+ abstention_report: status === "candidate" ? null : {
1015
+ defects,
1016
+ protocol_relative_only: true,
1017
+ reasons: ["certificate abstains when finite evidence is missing"],
1018
+ report_id: "collective-phase-abstention",
1019
+ settled: false,
1020
+ threshold_status: thresholdStatus
1021
+ },
1022
+ certificate_id: "collective-phase-certificate-candidate",
1023
+ certificate_status: status,
1024
+ defects,
1025
+ execution_authority_granted: false,
1026
+ finite_requirements_passed: status === "candidate",
1027
+ graph_id: String(graph.graph_id ?? ""),
1028
+ observation_id: String(
1029
+ asRecord(thresholdStatus.observation)?.observation_id ?? ""
1030
+ ),
1031
+ operationally_usable: status === "candidate",
1032
+ oracle_truth_proven: false,
1033
+ physical_truth_proven: false,
1034
+ protocol_relative_only: true,
1035
+ proves_physical_or_oracle_truth: false,
1036
+ proves_real_asi: false,
1037
+ reasons: [
1038
+ "certificate candidate is protocol-relative only",
1039
+ "certificate candidate does not prove real ASI",
1040
+ "certificate candidate does not settle diagnostic reports"
1041
+ ],
1042
+ settled: false,
1043
+ threshold_status: thresholdStatus,
1044
+ workflow_usable: true
1045
+ };
1046
+ }
1047
+ function loadPhaseLabObservation(storeDir, window = "latest") {
1048
+ const selected = selectWindow(storeDir, window);
1049
+ const graph = buildEffectivePacketGraph({
1050
+ events: selected.events,
1051
+ graph_id: `effective-graph:${String(selected.index.window_id ?? "window")}`,
1052
+ source_window_id: String(selected.index.window_id ?? "window")
1053
+ });
1054
+ return {
1055
+ observation: observePhaseWindow(selected.index, selected.events, graph),
1056
+ graph
1057
+ };
1058
+ }
1059
+ function loadPhaseLabGraph(storeDir, window = "all") {
1060
+ const selected = selectWindow(storeDir, window);
1061
+ return buildEffectivePacketGraph({
1062
+ events: selected.events,
1063
+ graph_id: `effective-graph:${String(selected.index.window_id ?? "window")}`,
1064
+ source_window_id: String(selected.index.window_id ?? "window")
1065
+ });
1066
+ }
1067
+ function exportPhaseLabStore(storeDir, outputDir) {
1068
+ mkdirSync(outputDir, { recursive: true });
1069
+ const manifest = writeManifest(storeDir);
1070
+ const events = readEvents(storeDir);
1071
+ const graph = buildEffectivePacketGraph({
1072
+ events,
1073
+ graph_id: "phase-lab-export-effective-graph",
1074
+ source_window_id: String(manifest.latest_window_id ?? "adhoc")
1075
+ });
1076
+ const files = [];
1077
+ const write = (name, data) => {
1078
+ writeJson(join(outputDir, name), data);
1079
+ files.push(name);
1080
+ };
1081
+ write("manifest.json", manifest);
1082
+ write("events.json", {
1083
+ absolute_paths_sanitized: true,
1084
+ events,
1085
+ settled: false
1086
+ });
1087
+ write("effective_graph.json", graph);
1088
+ write("windows.json", {
1089
+ settled: false,
1090
+ windows: readWindowIndexes(storeDir)
1091
+ });
1092
+ if (events.length > 0) {
1093
+ const { observation } = loadPhaseLabObservation(storeDir, "latest");
1094
+ write("phase_window_observation.json", observation);
1095
+ }
1096
+ return {
1097
+ accepted: true,
1098
+ absolute_paths_sanitized: true,
1099
+ export_id: "phase-lab-export",
1100
+ files: files.sort(),
1101
+ output_dir: basename(outputDir),
1102
+ reasons: ["phase lab export sanitizes local paths and preserves residuals"],
1103
+ settled: false,
1104
+ store_manifest: manifest
1105
+ };
1106
+ }
1107
+ export {
1108
+ buildCollectivePhaseCertificateCandidate,
1109
+ buildEffectivePacketGraph,
1110
+ buildPhaseThresholdStatus,
1111
+ comparePhaseWindows,
1112
+ detectAutocatalyticClosure,
1113
+ detectExecutionAvailablePaths,
1114
+ exportPhaseLabStore,
1115
+ ingestPhaseLabDirectory,
1116
+ ingestPhaseLabFiles,
1117
+ ingestPhaseLabPacket,
1118
+ ingestPhaseLabReport,
1119
+ initPhaseLabStore,
1120
+ listPhaseLabWindows,
1121
+ loadPhaseLabGraph,
1122
+ loadPhaseLabObservation,
1123
+ observePhaseWindow
1124
+ };