@h-rig/kernel-seed 0.0.6-alpha.135 → 0.0.6-alpha.136

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.
@@ -1,3 +1,4 @@
1
+ export * from "./journalConformance";
1
2
  export * from "./pluginAbi";
2
3
  export * from "./resolveCapability";
3
4
  export * from "./seed";
package/dist/src/index.js CHANGED
@@ -1,4 +1,33 @@
1
1
  // @bun
2
+ // packages/kernel-seed/src/journalConformance.ts
3
+ class JournalConformanceError extends Error {
4
+ name = "JournalConformanceError";
5
+ }
6
+ var CONFORMANCE_RUN_ID = "rig.kernel.__journal-conformance__";
7
+ function sampleResolvedPipeline() {
8
+ return {
9
+ order: ["validate", "merge-gate"],
10
+ record: [
11
+ { stageId: "validate", contributedBy: "default", isProtected: false },
12
+ { stageId: "merge-gate", contributedBy: "default", isProtected: true }
13
+ ],
14
+ cycles: [],
15
+ grantUses: [],
16
+ resolvedAt: "1970-01-01T00:00:00.000Z"
17
+ };
18
+ }
19
+ async function assertJournalConformance(journal, runId = CONFORMANCE_RUN_ID) {
20
+ const pipeline = sampleResolvedPipeline();
21
+ await journal.recordPipeline(runId, pipeline);
22
+ const events = await journal.read(runId);
23
+ if (!Array.isArray(events) || events.length === 0) {
24
+ throw new JournalConformanceError("journal.read returned no records after recordPipeline \u2014 provider does not durably record (append-and-record contract violated)");
25
+ }
26
+ const serialized = JSON.stringify(events);
27
+ if (!serialized.includes("merge-gate") || !serialized.includes("validate")) {
28
+ throw new JournalConformanceError("journal.read did not surface the recorded resolved-pipeline \u2014 provider does not expose the append-and-record contract");
29
+ }
30
+ }
2
31
  // packages/kernel-seed/src/pluginAbi.ts
3
32
  function loadedPluginId(plugin) {
4
33
  return plugin.meta.id;
@@ -151,6 +180,9 @@ async function boot(config) {
151
180
  throw new BootIncoherent("no kernel provider resolved");
152
181
  }
153
182
  assertSatisfiesKernelInterface(resolution.value);
183
+ if (config.verifyJournalConformance === true) {
184
+ await assertJournalConformance(resolution.value.journal);
185
+ }
154
186
  return { kernel: resolution.value, plugins };
155
187
  }
156
188
  export {
@@ -159,6 +191,8 @@ export {
159
191
  declaresReplacement,
160
192
  boot,
161
193
  assertSatisfiesKernelInterface,
194
+ assertJournalConformance,
195
+ JournalConformanceError,
162
196
  CapabilityProviderMissingError,
163
197
  BootIncoherent,
164
198
  AmbiguousCapabilityError
@@ -0,0 +1,22 @@
1
+ import type { JournalCapability } from "@rig/contracts";
2
+ /**
3
+ * Raised when a `journal` capability provider passes the *structural* check
4
+ * (append/recordPipeline/read present) but does not actually durably record —
5
+ * e.g. a no-op stub that would silently erase the audit trail / safety backstop.
6
+ */
7
+ export declare class JournalConformanceError extends Error {
8
+ readonly name = "JournalConformanceError";
9
+ }
10
+ /**
11
+ * Behavioral journal-append conformance — the fixed contract every `journal`
12
+ * provider must satisfy (see the Journal-Append Invariant). The storage backend
13
+ * is swappable; the guarantee that the resolved-pipeline record is durably
14
+ * appended and exposed for projection is NOT. A structurally-complete no-op
15
+ * stub (all three methods present, recording nothing) fails this, which is the
16
+ * whole point: observability is the safety backstop, so a journal that does not
17
+ * record must be rejected — not merely accepted because it has the right shape.
18
+ *
19
+ * Uses a clearly-namespaced probe runId so the record is identifiable and
20
+ * harmless to real-run projections (which filter by the actual runId).
21
+ */
22
+ export declare function assertJournalConformance(journal: JournalCapability, runId?: string): Promise<void>;
@@ -0,0 +1,34 @@
1
+ // @bun
2
+ // packages/kernel-seed/src/journalConformance.ts
3
+ class JournalConformanceError extends Error {
4
+ name = "JournalConformanceError";
5
+ }
6
+ var CONFORMANCE_RUN_ID = "rig.kernel.__journal-conformance__";
7
+ function sampleResolvedPipeline() {
8
+ return {
9
+ order: ["validate", "merge-gate"],
10
+ record: [
11
+ { stageId: "validate", contributedBy: "default", isProtected: false },
12
+ { stageId: "merge-gate", contributedBy: "default", isProtected: true }
13
+ ],
14
+ cycles: [],
15
+ grantUses: [],
16
+ resolvedAt: "1970-01-01T00:00:00.000Z"
17
+ };
18
+ }
19
+ async function assertJournalConformance(journal, runId = CONFORMANCE_RUN_ID) {
20
+ const pipeline = sampleResolvedPipeline();
21
+ await journal.recordPipeline(runId, pipeline);
22
+ const events = await journal.read(runId);
23
+ if (!Array.isArray(events) || events.length === 0) {
24
+ throw new JournalConformanceError("journal.read returned no records after recordPipeline \u2014 provider does not durably record (append-and-record contract violated)");
25
+ }
26
+ const serialized = JSON.stringify(events);
27
+ if (!serialized.includes("merge-gate") || !serialized.includes("validate")) {
28
+ throw new JournalConformanceError("journal.read did not surface the recorded resolved-pipeline \u2014 provider does not expose the append-and-record contract");
29
+ }
30
+ }
31
+ export {
32
+ assertJournalConformance,
33
+ JournalConformanceError
34
+ };
@@ -23,6 +23,14 @@ export type ResolvedBootConfig = {
23
23
  readonly plugins?: readonly LoadedPlugin[];
24
24
  readonly loadPlugins?: () => Promise<readonly LoadedPlugin[]> | readonly LoadedPlugin[];
25
25
  readonly capabilityPrecedence?: CapabilityPrecedence;
26
+ /**
27
+ * When true, boot runs the behavioral journal-append conformance probe
28
+ * against the resolved kernel's journal (rejecting a structurally-complete
29
+ * no-op provider). Off by default to avoid writing a probe record into a live
30
+ * run journal on every boot; opt-in for managed/multi-tenant postures and
31
+ * exercised directly by the conformance test.
32
+ */
33
+ readonly verifyJournalConformance?: boolean;
26
34
  };
27
35
  export type BootResult = {
28
36
  readonly kernel: KernelCapability;
package/dist/src/seed.js CHANGED
@@ -1,4 +1,34 @@
1
1
  // @bun
2
+ // packages/kernel-seed/src/journalConformance.ts
3
+ class JournalConformanceError extends Error {
4
+ name = "JournalConformanceError";
5
+ }
6
+ var CONFORMANCE_RUN_ID = "rig.kernel.__journal-conformance__";
7
+ function sampleResolvedPipeline() {
8
+ return {
9
+ order: ["validate", "merge-gate"],
10
+ record: [
11
+ { stageId: "validate", contributedBy: "default", isProtected: false },
12
+ { stageId: "merge-gate", contributedBy: "default", isProtected: true }
13
+ ],
14
+ cycles: [],
15
+ grantUses: [],
16
+ resolvedAt: "1970-01-01T00:00:00.000Z"
17
+ };
18
+ }
19
+ async function assertJournalConformance(journal, runId = CONFORMANCE_RUN_ID) {
20
+ const pipeline = sampleResolvedPipeline();
21
+ await journal.recordPipeline(runId, pipeline);
22
+ const events = await journal.read(runId);
23
+ if (!Array.isArray(events) || events.length === 0) {
24
+ throw new JournalConformanceError("journal.read returned no records after recordPipeline \u2014 provider does not durably record (append-and-record contract violated)");
25
+ }
26
+ const serialized = JSON.stringify(events);
27
+ if (!serialized.includes("merge-gate") || !serialized.includes("validate")) {
28
+ throw new JournalConformanceError("journal.read did not surface the recorded resolved-pipeline \u2014 provider does not expose the append-and-record contract");
29
+ }
30
+ }
31
+
2
32
  // packages/kernel-seed/src/pluginAbi.ts
3
33
  function loadedPluginId(plugin) {
4
34
  return plugin.meta.id;
@@ -147,6 +177,9 @@ async function boot(config) {
147
177
  throw new BootIncoherent("no kernel provider resolved");
148
178
  }
149
179
  assertSatisfiesKernelInterface(resolution.value);
180
+ if (config.verifyJournalConformance === true) {
181
+ await assertJournalConformance(resolution.value.journal);
182
+ }
150
183
  return { kernel: resolution.value, plugins };
151
184
  }
152
185
  export {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@h-rig/kernel-seed",
3
- "version": "0.0.6-alpha.135",
3
+ "version": "0.0.6-alpha.136",
4
4
  "type": "module",
5
5
  "description": "Irreducible Rig bootstrap seed, plugin ABI, and capability resolver.",
6
6
  "license": "UNLICENSED",
@@ -33,6 +33,6 @@
33
33
  "module": "./dist/src/index.js",
34
34
  "types": "./dist/src/index.d.ts",
35
35
  "dependencies": {
36
- "@rig/contracts": "npm:@h-rig/contracts@0.0.6-alpha.135"
36
+ "@rig/contracts": "npm:@h-rig/contracts@0.0.6-alpha.136"
37
37
  }
38
38
  }