@aionis/substrate 0.1.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 (61) hide show
  1. package/CHANGELOG.md +29 -0
  2. package/LICENSE +201 -0
  3. package/README.md +222 -0
  4. package/dist/backup.d.ts +38 -0
  5. package/dist/backup.d.ts.map +1 -0
  6. package/dist/backup.js +203 -0
  7. package/dist/backup.js.map +1 -0
  8. package/dist/event-log.d.ts +18 -0
  9. package/dist/event-log.d.ts.map +1 -0
  10. package/dist/event-log.js +157 -0
  11. package/dist/event-log.js.map +1 -0
  12. package/dist/file-substrate.d.ts +7 -0
  13. package/dist/file-substrate.d.ts.map +1 -0
  14. package/dist/file-substrate.js +409 -0
  15. package/dist/file-substrate.js.map +1 -0
  16. package/dist/index.d.ts +9 -0
  17. package/dist/index.d.ts.map +1 -0
  18. package/dist/index.js +9 -0
  19. package/dist/index.js.map +1 -0
  20. package/dist/runtime-reference-corpus.d.ts +76 -0
  21. package/dist/runtime-reference-corpus.d.ts.map +1 -0
  22. package/dist/runtime-reference-corpus.js +308 -0
  23. package/dist/runtime-reference-corpus.js.map +1 -0
  24. package/dist/runtime-snapshot-corpus.d.ts +53 -0
  25. package/dist/runtime-snapshot-corpus.d.ts.map +1 -0
  26. package/dist/runtime-snapshot-corpus.js +176 -0
  27. package/dist/runtime-snapshot-corpus.js.map +1 -0
  28. package/dist/runtime-snapshot-importer.d.ts +27 -0
  29. package/dist/runtime-snapshot-importer.d.ts.map +1 -0
  30. package/dist/runtime-snapshot-importer.js +571 -0
  31. package/dist/runtime-snapshot-importer.js.map +1 -0
  32. package/dist/runtime-snapshot-parity.d.ts +40 -0
  33. package/dist/runtime-snapshot-parity.d.ts.map +1 -0
  34. package/dist/runtime-snapshot-parity.js +217 -0
  35. package/dist/runtime-snapshot-parity.js.map +1 -0
  36. package/dist/search.d.ts +3 -0
  37. package/dist/search.d.ts.map +1 -0
  38. package/dist/search.js +157 -0
  39. package/dist/search.js.map +1 -0
  40. package/dist/sqlite-substrate.d.ts +7 -0
  41. package/dist/sqlite-substrate.d.ts.map +1 -0
  42. package/dist/sqlite-substrate.js +666 -0
  43. package/dist/sqlite-substrate.js.map +1 -0
  44. package/dist/types.d.ts +253 -0
  45. package/dist/types.d.ts.map +1 -0
  46. package/dist/types.js +2 -0
  47. package/dist/types.js.map +1 -0
  48. package/docs/ADAPTER_CONTRACT.md +155 -0
  49. package/docs/API_USAGE.md +225 -0
  50. package/docs/BACKUP_RESTORE.md +108 -0
  51. package/docs/CHECKPOINT_COMPACTION.md +75 -0
  52. package/docs/EXTERNAL_ADMISSION_PARITY.md +98 -0
  53. package/docs/RUNTIME_DUAL_WRITE_EXPERIMENT.md +132 -0
  54. package/docs/RUNTIME_MAPPING.md +69 -0
  55. package/docs/RUNTIME_REFERENCE_CORPUS.md +129 -0
  56. package/docs/RUNTIME_SNAPSHOT_CORPUS.md +81 -0
  57. package/docs/RUNTIME_SNAPSHOT_IMPORT.md +120 -0
  58. package/docs/STORE_CONTRACT.md +181 -0
  59. package/examples/basic/README.md +19 -0
  60. package/examples/basic/index.mjs +112 -0
  61. package/package.json +65 -0
@@ -0,0 +1,225 @@
1
+ # API Usage
2
+
3
+ This document shows the first public contract for using Aionis Substrate directly.
4
+
5
+ The API is intentionally small:
6
+
7
+ - write memory nodes;
8
+ - write relations between memory nodes;
9
+ - record outcome feedback;
10
+ - search memory nodes with scoped filters;
11
+ - preview governed context without writing a receipt;
12
+ - compile governed context;
13
+ - inspect decision traces.
14
+
15
+ ## Open a Store
16
+
17
+ SQLite adapter:
18
+
19
+ ```ts
20
+ import { openSqliteAionisSubstrate } from "@aionis/substrate";
21
+
22
+ const store = await openSqliteAionisSubstrate({
23
+ path: "/tmp/aionis-substrate.sqlite",
24
+ });
25
+ ```
26
+
27
+ File adapter:
28
+
29
+ ```ts
30
+ import { openFileAionisSubstrate } from "@aionis/substrate";
31
+
32
+ const store = await openFileAionisSubstrate({
33
+ dir: "/tmp/aionis-substrate-file-store",
34
+ });
35
+ ```
36
+
37
+ Both adapters expose the same contract.
38
+
39
+ ## Inspect Store Metadata
40
+
41
+ ```ts
42
+ const info = await store.getStoreInfo();
43
+
44
+ console.log(info.adapter);
45
+ console.log(info.schemaVersion);
46
+ console.log(info.lastSequence);
47
+ console.log(info.eventCount);
48
+ ```
49
+
50
+ The schema version is part of the substrate contract. A newer unsupported SQLite schema is rejected on open instead of being read best-effort.
51
+
52
+ ## Write Execution Memory
53
+
54
+ ```ts
55
+ await store.putNode({
56
+ id: "route-current",
57
+ scope: "repo-a",
58
+ kind: "procedure",
59
+ title: "Current route",
60
+ summary: "Use src/runtime.ts as the validated current route.",
61
+ lifecycle: "active",
62
+ authority: "trusted",
63
+ confidence: 0.92,
64
+ targetFiles: ["src/runtime.ts", "tests/runtime.test.ts"],
65
+ metadata: {
66
+ source: "agent_observe",
67
+ verifier: "npm test passed",
68
+ },
69
+ });
70
+ ```
71
+
72
+ ## Keep Old Evidence Without Trusting It
73
+
74
+ ```ts
75
+ await store.putNode({
76
+ id: "route-old",
77
+ scope: "repo-a",
78
+ kind: "procedure",
79
+ title: "Old route",
80
+ summary: "Use src/legacy.ts as the previous route.",
81
+ lifecycle: "active",
82
+ authority: "trusted",
83
+ confidence: 0.8,
84
+ targetFiles: ["src/legacy.ts"],
85
+ });
86
+
87
+ await store.putRelation({
88
+ scope: "repo-a",
89
+ kind: "supersedes",
90
+ sourceId: "route-current",
91
+ targetId: "route-old",
92
+ confidence: 0.88,
93
+ metadata: {
94
+ reason: "newer verifier evidence replaced the old route",
95
+ },
96
+ });
97
+ ```
98
+
99
+ The old route remains in the evidence log. It is not silently deleted. The relation prevents it from becoming direct-use context.
100
+
101
+ ## Record Feedback
102
+
103
+ ```ts
104
+ await store.recordFeedback({
105
+ scope: "repo-a",
106
+ memoryId: "route-current",
107
+ outcome: "positive",
108
+ strength: "strong",
109
+ evidenceRef: "trace://run-2026-06-25/verifier",
110
+ runId: "run-2026-06-25",
111
+ });
112
+ ```
113
+
114
+ Feedback is evidence. It does not bypass lifecycle, relation, or authority checks.
115
+
116
+ ## Search Memory Nodes
117
+
118
+ ```ts
119
+ const results = await store.searchNodes({
120
+ scope: "repo-a",
121
+ query: "runtime verifier",
122
+ lifecycle: ["active"],
123
+ authority: ["trusted"],
124
+ targetFiles: ["src/runtime.ts"],
125
+ minConfidence: 0.8,
126
+ limit: 10,
127
+ });
128
+
129
+ for (const result of results) {
130
+ console.log(result.node.id, result.score, result.reasons);
131
+ }
132
+ ```
133
+
134
+ Search is a scoped, read-only substrate query.
135
+
136
+ It supports structured filters for kind, lifecycle, authority, target files, owner identity, confidence, and update time. The optional `query` is deterministic lexical scoring over node id, title, summary, target files, payload pointer, owner ids, and primitive metadata.
137
+
138
+ It is not vector search, semantic adjudication, or admission policy. Use `compileContext` when the Agent needs governed prompt surfaces.
139
+
140
+ ## Preview Context
141
+
142
+ ```ts
143
+ const preview = await store.previewContext({
144
+ scope: "repo-a",
145
+ query: "continue the runtime implementation",
146
+ });
147
+
148
+ console.log(preview.use_now.map((node) => node.id));
149
+ console.log(preview.inspect_before_use.map((node) => node.id));
150
+ console.log(preview.do_not_use.map((node) => node.id));
151
+ console.log(preview.rehydrate.map((node) => node.id));
152
+ ```
153
+
154
+ `previewContext` uses the same admission buckets and reason codes as `compileContext`, but it does not append `memory.decision.recorded` or insert a decision row. Use it for UI previews, dry runs, and adapter parity checks where no exported context receipt should be created.
155
+
156
+ ## Compile Context
157
+
158
+ ```ts
159
+ const context = await store.compileContext({
160
+ scope: "repo-a",
161
+ query: "continue the runtime implementation",
162
+ });
163
+
164
+ console.log(context.use_now.map((node) => node.id));
165
+ console.log(context.inspect_before_use.map((node) => node.id));
166
+ console.log(context.do_not_use.map((node) => node.id));
167
+ console.log(context.rehydrate.map((node) => node.id));
168
+ console.log(context.decision_trace);
169
+ ```
170
+
171
+ The compiled context has four surfaces:
172
+
173
+ - `use_now`: directly usable context;
174
+ - `inspect_before_use`: relevant but not authoritative;
175
+ - `do_not_use`: blocked, superseded, invalidated, or unsafe;
176
+ - `rehydrate`: payload is available but should not flood the prompt unless requested.
177
+
178
+ `compileContext` records a `memory.decision.recorded` event. It is intentionally auditable, not a pure read.
179
+
180
+ ## Compact the Event Log
181
+
182
+ ```ts
183
+ const report = await store.compact();
184
+
185
+ console.log(report.compacted);
186
+ console.log(report.before.eventCount);
187
+ console.log(report.after.eventCount);
188
+ ```
189
+
190
+ Compaction is physical log maintenance. It writes a `substrate.checkpoint.created` event that preserves the current nodes, relations, feedback, decision traces, and checksum metadata for the covered history.
191
+
192
+ It does not change lifecycle state, admission buckets, or Runtime policy.
193
+
194
+ ## Export, Verify, and Restore
195
+
196
+ ```ts
197
+ import {
198
+ exportAionisSubstrateBackup,
199
+ restoreAionisSubstrateBackupToSqlite,
200
+ verifyAionisSubstrateBackup,
201
+ writeAionisSubstrateBackupFile,
202
+ } from "@aionis/substrate";
203
+
204
+ const backup = await exportAionisSubstrateBackup(store);
205
+ const report = verifyAionisSubstrateBackup(backup);
206
+
207
+ if (!report.ok) throw new Error(report.errors.join("; "));
208
+
209
+ await writeAionisSubstrateBackupFile("/backups/aionis-substrate.json", backup);
210
+ await restoreAionisSubstrateBackupToSqlite(backup, "/tmp/restored-aionis-substrate.sqlite");
211
+ ```
212
+
213
+ Backup is event-log based. Restore preserves original event ids and sequence numbers, then rebuilds the read model.
214
+
215
+ ## Close the Store
216
+
217
+ ```ts
218
+ await store.close();
219
+ ```
220
+
221
+ ## Boundary
222
+
223
+ This API is a substrate contract, not the complete Aionis Runtime product facade.
224
+
225
+ Runtime-level features such as product `observe`, `guide`, `forget`, `measure`, lifecycle candidate inference, memory decision trace presentation, and context compiler UX belong above this substrate layer.
@@ -0,0 +1,108 @@
1
+ # Backup and Restore
2
+
3
+ Aionis Substrate backup is event-log based.
4
+
5
+ It exports the append-only evidence events plus a checksum. Restore rebuilds the read model from those events. It does not copy only the derived snapshot.
6
+
7
+ ## Backup Format
8
+
9
+ The backup object contains:
10
+
11
+ - backup format and version;
12
+ - substrate schema version;
13
+ - source adapter metadata from `getStoreInfo`;
14
+ - event count and last sequence;
15
+ - SHA-256 checksum over the canonical event list;
16
+ - every append-only event in sequence order.
17
+
18
+ The checksum covers the event list. If an event payload is changed after export, verification fails and restore is rejected.
19
+
20
+ A compacted store may export a `substrate.checkpoint.created` event instead of the original full event history. The checkpoint includes covered event count, covered last sequence, and the SHA-256 checksum of the covered event list.
21
+
22
+ ## Export
23
+
24
+ ```ts
25
+ import {
26
+ exportAionisSubstrateBackup,
27
+ openSqliteAionisSubstrate,
28
+ writeAionisSubstrateBackupFile,
29
+ } from "@aionis/substrate";
30
+
31
+ const store = await openSqliteAionisSubstrate({
32
+ path: "/data/aionis-substrate.sqlite",
33
+ });
34
+
35
+ const backup = await exportAionisSubstrateBackup(store);
36
+ await writeAionisSubstrateBackupFile("/backups/aionis-substrate-backup.json", backup);
37
+
38
+ await store.close();
39
+ ```
40
+
41
+ ## Verify
42
+
43
+ ```ts
44
+ import {
45
+ readAionisSubstrateBackupFile,
46
+ verifyAionisSubstrateBackup,
47
+ } from "@aionis/substrate";
48
+
49
+ const backup = await readAionisSubstrateBackupFile("/backups/aionis-substrate-backup.json");
50
+ const report = verifyAionisSubstrateBackup(backup);
51
+
52
+ if (!report.ok) {
53
+ throw new Error(report.errors.join("; "));
54
+ }
55
+ ```
56
+
57
+ Verification checks:
58
+
59
+ - backup format and version;
60
+ - supported schema version;
61
+ - event sequence continuity;
62
+ - duplicate event ids;
63
+ - relation / feedback / lifecycle references;
64
+ - event count and last sequence headers;
65
+ - SHA-256 checksum.
66
+
67
+ For checkpoint events, verification also replays the checkpoint payload and checks relation / feedback references inside the checkpoint state.
68
+
69
+ ## Restore to File Store
70
+
71
+ ```ts
72
+ import {
73
+ readAionisSubstrateBackupFile,
74
+ restoreAionisSubstrateBackupToFile,
75
+ } from "@aionis/substrate";
76
+
77
+ const backup = await readAionisSubstrateBackupFile("/backups/aionis-substrate-backup.json");
78
+ await restoreAionisSubstrateBackupToFile(backup, "/data/aionis-substrate-file-store");
79
+ ```
80
+
81
+ Restore writes:
82
+
83
+ - `events.jsonl`
84
+ - `snapshot.json`
85
+
86
+ The target must be empty unless `overwrite: true` is passed.
87
+
88
+ ## Restore to SQLite
89
+
90
+ ```ts
91
+ import {
92
+ readAionisSubstrateBackupFile,
93
+ restoreAionisSubstrateBackupToSqlite,
94
+ } from "@aionis/substrate";
95
+
96
+ const backup = await readAionisSubstrateBackupFile("/backups/aionis-substrate-backup.json");
97
+ await restoreAionisSubstrateBackupToSqlite(backup, "/data/aionis-substrate-restored.sqlite");
98
+ ```
99
+
100
+ Restore writes the original event ids and sequence numbers, rebuilds structured read-model tables, and preserves the next event sequence for future writes.
101
+
102
+ The SQLite target must not exist unless `overwrite: true` is passed.
103
+
104
+ ## Boundary
105
+
106
+ Backup and restore operate on the Substrate store only.
107
+
108
+ They do not back up an Aionis Runtime database, an external vector index, or payload files referenced by `payloadRef`. Payload files remain external artifacts and need their own storage policy.
@@ -0,0 +1,75 @@
1
+ # Checkpoint Compaction
2
+
3
+ Aionis Substrate stores durable memory changes as events. Over time, a long-running store can compact its physical event log into a checkpoint event.
4
+
5
+ Compaction is storage maintenance. It is not forgetting, admission policy, or evidence deletion.
6
+
7
+ ## Checkpoint Event
8
+
9
+ `compact()` rewrites the event log to one event:
10
+
11
+ - `substrate.checkpoint.created`
12
+
13
+ The checkpoint payload contains:
14
+
15
+ - substrate schema version;
16
+ - number of covered events;
17
+ - last covered event sequence;
18
+ - SHA-256 checksum of the covered canonical event list;
19
+ - current memory nodes;
20
+ - current relations;
21
+ - current feedback records;
22
+ - current decision traces.
23
+
24
+ After compaction, the event log starts from the checkpoint at sequence `1`. Future writes continue from sequence `2`.
25
+
26
+ ## Adapter Behavior
27
+
28
+ The file adapter:
29
+
30
+ - validates the checkpoint with the same replay state machine used by backup verification;
31
+ - atomically replaces `events.jsonl`;
32
+ - rewrites `snapshot.json`.
33
+
34
+ The SQLite adapter:
35
+
36
+ - builds the checkpoint from the structured read model;
37
+ - validates the checkpoint with the same replay state machine;
38
+ - replaces the event table inside a transaction;
39
+ - resets the event AUTOINCREMENT sequence.
40
+
41
+ Both adapters preserve the same observable governed state after reopen.
42
+
43
+ ## Backup Boundary
44
+
45
+ Backups can export compacted stores. A compacted backup may contain a checkpoint event instead of the original full event history.
46
+
47
+ The checkpoint keeps audit metadata for the covered history through:
48
+
49
+ - `coveredEventCount`
50
+ - `coveredLastSequence`
51
+ - `coveredEventsSha256`
52
+
53
+ Payload files referenced by `payloadRef` are still external artifacts. Compaction does not embed them.
54
+
55
+ ## Usage
56
+
57
+ ```ts
58
+ const report = await store.compact();
59
+
60
+ console.log(report.before.eventCount);
61
+ console.log(report.after.eventCount);
62
+ console.log(report.after.checkpointEventId);
63
+ ```
64
+
65
+ If the store has no events, `compact()` returns `compacted: false`.
66
+
67
+ ## Non-Goals
68
+
69
+ Checkpoint compaction does not:
70
+
71
+ - remove stale memories;
72
+ - suppress memories;
73
+ - archive payload files;
74
+ - change `use_now`, `inspect_before_use`, `do_not_use`, or `rehydrate`;
75
+ - replace Aionis Runtime policy.
@@ -0,0 +1,98 @@
1
+ # External Admission Parity
2
+
3
+ `scripts/external-admission-parity.ts` validates Aionis Substrate against the real focused Runtime external memory governance path.
4
+
5
+ It starts `AionisRuntime-focused` in local Lite mode, calls the product SDK method that backs `/v1/memory/govern`, projects the same external candidate memories into Aionis Substrate, and compares the four admission buckets:
6
+
7
+ - `use_now`
8
+ - `inspect_before_use`
9
+ - `do_not_use`
10
+ - `rehydrate`
11
+
12
+ ## Run
13
+
14
+ ```bash
15
+ npm run check:external-admission-parity -- \
16
+ --runtime-root /Volumes/ziel/AionisRuntime-focused
17
+ ```
18
+
19
+ By default this runs 6 fixed contract scenarios plus 24 deterministic generated variants:
20
+
21
+ ```bash
22
+ npm run check:external-admission-parity -- \
23
+ --runtime-root /Volumes/ziel/AionisRuntime-focused \
24
+ --generated-count 100 \
25
+ --seed external-admission-parity-v2
26
+ ```
27
+
28
+ The runner writes a report under:
29
+
30
+ ```text
31
+ reports/external-admission-parity-*/summary.json
32
+ ```
33
+
34
+ ## What This Proves
35
+
36
+ This validates that Substrate's minimum admission contract can express the same four-bucket result as focused Runtime's external candidate governance route.
37
+
38
+ The runner covers:
39
+
40
+ - trusted current execution state admitted to `use_now`;
41
+ - unverified candidate memory routed to `inspect_before_use`;
42
+ - failed, stale, suppressed, or blocked memory kept out of direct use;
43
+ - raw trace or payload-only memory routed to `rehydrate`.
44
+ - trusted ordinary preference/fact memory outside code execution traces;
45
+ - known-source memory that remains inspect-only under focused Runtime firewall behavior;
46
+ - explicit authority requirements that override otherwise current lifecycle hints.
47
+
48
+ Generated variants expand these surfaces across execution routes, procedures, handoff state, ordinary preference memory, failed/stale/contested/suppressed negative history, and payload-only evidence. They are deterministic contract variants, not a public benchmark leaderboard.
49
+
50
+ The focused Runtime route may apply stricter product firewall behavior before bucket emission. For example, an inspect-like external candidate outside the active target cluster can be blocked as `do_not_use`. This runner intentionally keeps fixtures inside the shared external admission contract so the comparison validates Substrate bucket expressiveness instead of forcing full Runtime product policy into the substrate layer.
51
+
52
+ ## What This Does Not Prove
53
+
54
+ This is not full Aionis Runtime policy parity.
55
+
56
+ It does not replace focused Runtime's guide policy, lifecycle candidate inference, relation adjudication, feedback attribution, or product context compiler. It is deliberately narrower: external candidate admission into the four bucket contract.
57
+
58
+ It also does not mutate Runtime source code or Runtime product databases. The focused Runtime service is started with isolated temporary SQLite paths under the report directory.
59
+
60
+ ## Current Focused Runtime Check
61
+
62
+ The expanded focused Runtime parity run currently produces:
63
+
64
+ ```text
65
+ scenario_count: 30
66
+ base_scenario_count: 6
67
+ generated_scenario_count: 24
68
+ exact_scenario_count: 30
69
+ failed_scenario_count: 0
70
+ seed: external-admission-parity-v2
71
+ ```
72
+
73
+ Report:
74
+
75
+ ```text
76
+ reports/external-admission-parity-2026-06-25T14-01-55-065Z/summary.json
77
+ ```
78
+
79
+ Reports are generated artifacts and are not committed by default.
80
+
81
+ A larger smoke run also passed:
82
+
83
+ ```text
84
+ scenario_count: 106
85
+ base_scenario_count: 6
86
+ generated_scenario_count: 100
87
+ exact_scenario_count: 106
88
+ failed_scenario_count: 0
89
+ seed: external-admission-parity-v2-large
90
+ ```
91
+
92
+ ## Why This Exists
93
+
94
+ Runtime snapshot parity validates read-only import from existing Runtime SQLite databases.
95
+
96
+ Runtime product reference parity validates same-source execution continuity produced by real `observe` / `guide` / `measure` loops.
97
+
98
+ External admission parity validates the missing product boundary: external memory candidates already carrying candidate governance signals can be routed into the same four bucket contract without relying on Runtime's internal storage.
@@ -0,0 +1,132 @@
1
+ # Runtime Dual-Write Experiment
2
+
3
+ This experiment validates Aionis Substrate as an external sidecar for real focused Runtime execution state.
4
+
5
+ It does not replace Runtime storage. It does not mutate `AionisRuntime-focused`. It starts a real focused Runtime process with isolated Lite SQLite paths, calls the public SDK loop, mirrors the observed memory ids and outcomes into a separate Substrate SQLite store, and compares the resulting admission buckets.
6
+
7
+ ## Why This Exists
8
+
9
+ Snapshot import proves Substrate can read existing Runtime databases.
10
+
11
+ External admission parity proves Substrate can project candidate memories into the same admission buckets as focused Runtime's external memory route.
12
+
13
+ Dual-write is the next integration step. It checks whether an external host can write the same execution-state facts into Runtime and Substrate during one real run, then get equivalent governed context from both systems.
14
+
15
+ ## What It Runs
16
+
17
+ The runner executes this loop for each scenario:
18
+
19
+ 1. Start focused Runtime with isolated Lite SQLite paths.
20
+ 2. Call `execution.guideForRole` before any memory exists.
21
+ 3. Call `execution.observeStep` for an accepted active route.
22
+ 4. Call `execution.observeStep` for a rejected failed branch.
23
+ 5. Write the same returned Runtime memory ids into Substrate.
24
+ 6. Add a Substrate relation from the active route to the failed branch.
25
+ 7. Call `execution.guideForRole` again and extract Runtime guide surfaces.
26
+ 8. Call `store.compileContext` for the same scope and compare Substrate surfaces.
27
+ 9. Call `execution.feedbackFromOutcome` and `execution.measureRun`.
28
+ 10. Write matching Substrate feedback.
29
+ 11. Probe invalid Substrate relation/feedback writes and verify no partial events are appended.
30
+ 12. Optionally run independent Substrate lifecycle/relation chain probes.
31
+ 13. Close and reopen Substrate, then compare persisted surfaces again.
32
+
33
+ The compared surfaces are:
34
+
35
+ - `use_now`
36
+ - `inspect_before_use`
37
+ - `do_not_use`
38
+ - `rehydrate`
39
+
40
+ ## Command
41
+
42
+ ```bash
43
+ npm run check:runtime-dual-write -- \
44
+ --runtime-root /Volumes/ziel/AionisRuntime-focused \
45
+ --generated-count 8 \
46
+ --chain-probe-count 4 \
47
+ --concurrency 4
48
+ ```
49
+
50
+ Optional flags:
51
+
52
+ ```bash
53
+ --scenario-count 4
54
+ --generated-count 24
55
+ --chain-probe-count 4
56
+ --concurrency 4
57
+ --seed runtime-dual-write-v2
58
+ --max-per-bucket 8
59
+ --output-dir reports/runtime-dual-write-manual
60
+ ```
61
+
62
+ Sustained soak example:
63
+
64
+ ```bash
65
+ npm run check:runtime-dual-write -- \
66
+ --runtime-root /Volumes/ziel/AionisRuntime-focused \
67
+ --generated-count 96 \
68
+ --chain-probe-count 16 \
69
+ --concurrency 8
70
+ ```
71
+
72
+ ## Report
73
+
74
+ The runner writes:
75
+
76
+ ```text
77
+ reports/runtime-dual-write-*/summary.json
78
+ ```
79
+
80
+ The report includes:
81
+
82
+ - focused Runtime base URL and isolated Lite SQLite paths
83
+ - Substrate SQLite path
84
+ - Runtime memory ids returned by `observeStep`
85
+ - Runtime guide surfaces
86
+ - Substrate compiled surfaces
87
+ - per-bucket parity details
88
+ - Substrate event counts
89
+ - generated/fixed scenario counts
90
+ - invalid write rollback probes
91
+ - chain probe counts for lifecycle transitions, supersession, invalidation, support, and payload relations
92
+ - persisted parity after close/reopen
93
+ - scenario, chain-probe, and reopen latency summaries
94
+ - append-only event sequence continuity
95
+ - Substrate and focused Runtime SQLite file sizes
96
+
97
+ ## Chain Probes
98
+
99
+ Chain probes run in independent Substrate scopes after the real Runtime sidecar scenarios.
100
+
101
+ Each probe writes:
102
+
103
+ - one verified active memory expected in `use_now`
104
+ - one candidate procedure expected in `inspect_before_use`
105
+ - one prior memory superseded by the active memory
106
+ - one failed branch invalidated by the active memory and transitioned to `blocked`
107
+ - one raw payload pointer that requires rehydration
108
+
109
+ The probe then compiles context, compares the four admission buckets, closes and reopens the SQLite store, and compares again. This validates the substrate relation and lifecycle contract without adding benchmark-specific policy to focused Runtime.
110
+
111
+ ## Soak Metrics
112
+
113
+ The report `soak` object is for sustained sidecar checks:
114
+
115
+ - `scenario_latency`: p50/p95/max latency for real Runtime sidecar scenarios.
116
+ - `chain_probe_latency`: p50/p95/max latency for Substrate-only lifecycle/relation probes.
117
+ - `reopen_latency`: p50/p95/max latency for persisted scenario checks after closing and reopening SQLite.
118
+ - `chain_probe_reopen_latency`: persisted chain probe reopen latency.
119
+ - `event_sequence`: verifies append-only event sequence continuity, duplicate count, and gap count.
120
+ - `db_sizes`: records Substrate SQLite/WAL/SHM file sizes and focused Runtime Lite SQLite file sizes.
121
+
122
+ ## Boundary
123
+
124
+ This experiment is intentionally sidecar-only:
125
+
126
+ - no Runtime source mutation
127
+ - no Runtime storage replacement
128
+ - no production dual-write API
129
+ - no Agent framework logic
130
+ - no benchmark-specific Runtime policy
131
+
132
+ Passing this experiment means Substrate can mirror a small real Runtime execution loop and preserve the same admission surface after reopen. It does not mean Substrate is ready to become the focused Runtime storage engine.