iterate-kernel 0.1.0-draft.1

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 (49) hide show
  1. package/README.md +56 -0
  2. package/dist/canonical-json.d.ts +21 -0
  3. package/dist/canonical-json.d.ts.map +1 -0
  4. package/dist/canonical-json.js +31 -0
  5. package/dist/canonical-json.js.map +1 -0
  6. package/dist/decision-log-entry.d.ts +34 -0
  7. package/dist/decision-log-entry.d.ts.map +1 -0
  8. package/dist/decision-log-entry.js +17 -0
  9. package/dist/decision-log-entry.js.map +1 -0
  10. package/dist/decision-log.d.ts +142 -0
  11. package/dist/decision-log.d.ts.map +1 -0
  12. package/dist/decision-log.js +288 -0
  13. package/dist/decision-log.js.map +1 -0
  14. package/dist/dimension-context.d.ts +402 -0
  15. package/dist/dimension-context.d.ts.map +1 -0
  16. package/dist/dimension-context.js +226 -0
  17. package/dist/dimension-context.js.map +1 -0
  18. package/dist/errors.d.ts +15 -0
  19. package/dist/errors.d.ts.map +1 -0
  20. package/dist/errors.js +18 -0
  21. package/dist/errors.js.map +1 -0
  22. package/dist/evidence-decision.d.ts +44 -0
  23. package/dist/evidence-decision.d.ts.map +1 -0
  24. package/dist/evidence-decision.js +88 -0
  25. package/dist/evidence-decision.js.map +1 -0
  26. package/dist/evidence-pack.d.ts +1884 -0
  27. package/dist/evidence-pack.d.ts.map +1 -0
  28. package/dist/evidence-pack.js +243 -0
  29. package/dist/evidence-pack.js.map +1 -0
  30. package/dist/index.d.ts +19 -0
  31. package/dist/index.d.ts.map +1 -0
  32. package/dist/index.js +19 -0
  33. package/dist/index.js.map +1 -0
  34. package/dist/parse.d.ts +22 -0
  35. package/dist/parse.d.ts.map +1 -0
  36. package/dist/parse.js +53 -0
  37. package/dist/parse.js.map +1 -0
  38. package/dist/recipe-config.d.ts +48 -0
  39. package/dist/recipe-config.d.ts.map +1 -0
  40. package/dist/recipe-config.js +20 -0
  41. package/dist/recipe-config.js.map +1 -0
  42. package/dist/schemas.d.ts +11 -0
  43. package/dist/schemas.d.ts.map +1 -0
  44. package/dist/schemas.js +19 -0
  45. package/dist/schemas.js.map +1 -0
  46. package/package.json +84 -0
  47. package/schemas/decision-log-entry.schema.json +45 -0
  48. package/schemas/evidence-pack.schema.json +359 -0
  49. package/schemas/recipe-config.schema.json +36 -0
package/README.md ADDED
@@ -0,0 +1,56 @@
1
+ # iterate-kernel
2
+
3
+ The iterate ecosystem's shared semantic kernel: schemas, the evidence → decision
4
+ transcription, the decision-log audit chain, and public validators.
5
+
6
+ **What it is not.** It carries no verification reasoning. Judging whether a claim is true
7
+ belongs to the engine that produced the evidence; this package transcribes what that engine
8
+ already decided, so that every shell in the ecosystem speaks the same language instead of
9
+ each inventing its own.
10
+
11
+ ## Install
12
+
13
+ ```bash
14
+ npm install iterate-kernel
15
+ ```
16
+
17
+ ## Import per module, not through the barrel
18
+
19
+ ```ts
20
+ import { decisionOutcomeFromEvidence } from "iterate-kernel/evidence-decision"
21
+ import { appendDecisionEntry } from "iterate-kernel/decision-log"
22
+ import { parseEvidencePack } from "iterate-kernel/parse"
23
+ ```
24
+
25
+ Each module is its own subpath export. Importing the barrel (`iterate-kernel`) also pulls
26
+ in `schemas`, which reads the JSON Schema files next to the package at load time — fine in a
27
+ repository, but a runtime file read is a trap for anyone bundling to a single file. The
28
+ subpaths avoid it, and they keep a consumer's dependency on this package as narrow as the
29
+ APIs it actually uses.
30
+
31
+ ## The pieces
32
+
33
+ | Module | What it is for |
34
+ | --- | --- |
35
+ | `evidence-pack` / `parse` | the evidence pack shape, and parsing/validating one |
36
+ | `evidence-decision` | the **transcription**: evidence (attribution level, circuit-breaker level, pass/fail/inconclusive) → a decision outcome and a human summary. It reads fields the engine already decided; it never infers. |
37
+ | `decision-log-entry` / `decision-log` | the append-only decision-log entry and the `opID ↔ entry` hash chain that makes it auditable |
38
+ | `errors` / `schemas` / `canonical-json` / `recipe-config` | `KernelSchemaError`, the JSON Schemas, canonical serialisation, recipe validation |
39
+
40
+ ## Versioning
41
+
42
+ `0.1.x` is pre-stable. The schemas and the transcription rules are the contract every
43
+ consumer depends on, so a change to either is a minor-version change at minimum, and the
44
+ fixtures in `fixtures/` are the executable statement of what the contract means.
45
+
46
+ ## Consumers
47
+
48
+ Vendored or installed, a consumer's kernel is one of two things, and the difference is a
49
+ distribution decision rather than a semantic one:
50
+
51
+ - **vendored source**, hash-pinned per file, with a probe that asks whether the canonical
52
+ branch has moved (what the GlassPane Harness fork does), or
53
+ - **this package**, pinned by semver.
54
+
55
+ Either way, run the fixtures: they are how you find out that the kernel you have is not the
56
+ kernel you think you have.
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Canonical JSON serialization — the cross-language form used by the C35
3
+ * dual-binding gate.
4
+ *
5
+ * Rules (identical to `engine/Sources/GlassPaneEngine/CanonicalJSON.swift`,
6
+ * which is the independent Swift implementation; divergence between the two
7
+ * shows up as a fixture mismatch, not as a silently different digest):
8
+ * - object keys sorted by UTF-16 code unit order;
9
+ * - no insignificant whitespace;
10
+ * - numbers in the host's shortest roundtrip form (integral values print
11
+ * without a fraction on both sides);
12
+ * - scalars quoted exactly as `JSON.stringify` does (control chars as
13
+ * `\u00xx`, `/` and non-ASCII left raw).
14
+ *
15
+ * The decision log hashes this form (see `decision-log.ts`), so the digest of
16
+ * an entry is reproducible from TypeScript, Swift, or `printf … | sha256sum`
17
+ * given the same bytes. That property is the point: an audit chain nobody else
18
+ * can recompute is a claim, not evidence.
19
+ */
20
+ export declare function canonicalJson(value: unknown): string;
21
+ //# sourceMappingURL=canonical-json.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"canonical-json.d.ts","sourceRoot":"","sources":["../src/canonical-json.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAUpD"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Canonical JSON serialization — the cross-language form used by the C35
3
+ * dual-binding gate.
4
+ *
5
+ * Rules (identical to `engine/Sources/GlassPaneEngine/CanonicalJSON.swift`,
6
+ * which is the independent Swift implementation; divergence between the two
7
+ * shows up as a fixture mismatch, not as a silently different digest):
8
+ * - object keys sorted by UTF-16 code unit order;
9
+ * - no insignificant whitespace;
10
+ * - numbers in the host's shortest roundtrip form (integral values print
11
+ * without a fraction on both sides);
12
+ * - scalars quoted exactly as `JSON.stringify` does (control chars as
13
+ * `\u00xx`, `/` and non-ASCII left raw).
14
+ *
15
+ * The decision log hashes this form (see `decision-log.ts`), so the digest of
16
+ * an entry is reproducible from TypeScript, Swift, or `printf … | sha256sum`
17
+ * given the same bytes. That property is the point: an audit chain nobody else
18
+ * can recompute is a claim, not evidence.
19
+ */
20
+ export function canonicalJson(value) {
21
+ if (value === null || typeof value !== "object") {
22
+ return JSON.stringify(value);
23
+ }
24
+ if (Array.isArray(value)) {
25
+ return "[" + value.map((item) => canonicalJson(item)).join(",") + "]";
26
+ }
27
+ const record = value;
28
+ const keys = Object.keys(record).sort();
29
+ return "{" + keys.map((key) => JSON.stringify(key) + ":" + canonicalJson(record[key])).join(",") + "}";
30
+ }
31
+ //# sourceMappingURL=canonical-json.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"canonical-json.js","sourceRoot":"","sources":["../src/canonical-json.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,UAAU,aAAa,CAAC,KAAc;IAC1C,IAAI,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAChD,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;IAC/B,CAAC;IACD,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,GAAG,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC;IACxE,CAAC;IACD,MAAM,MAAM,GAAG,KAAgC,CAAC;IAChD,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC;IACxC,OAAO,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,GAAG,GAAG,aAAa,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC;AACzG,CAAC"}
@@ -0,0 +1,34 @@
1
+ import { z } from "zod";
2
+ export declare const DECISION_ENTRY_ID_PATTERN: RegExp;
3
+ /** SHA-256 full hex (64 lowercase chars), or the empty string for the genesis entry. */
4
+ export declare const PREV_ENTRY_HASH_PATTERN: RegExp;
5
+ export declare const SUMMARY_MAX_LENGTH = 2048;
6
+ export declare const DecisionOutcomeSchema: z.ZodEnum<["pass", "fail", "blocked", "inconclusive"]>;
7
+ export type DecisionOutcome = z.infer<typeof DecisionOutcomeSchema>;
8
+ export declare const DecisionLogEntrySchema: z.ZodObject<{
9
+ entryId: z.ZodString;
10
+ sequence: z.ZodNumber;
11
+ prevEntryHash: z.ZodString;
12
+ operationId: z.ZodOptional<z.ZodString>;
13
+ summary: z.ZodString;
14
+ outcome: z.ZodEnum<["pass", "fail", "blocked", "inconclusive"]>;
15
+ createdAt: z.ZodString;
16
+ }, "strict", z.ZodTypeAny, {
17
+ createdAt: string;
18
+ entryId: string;
19
+ sequence: number;
20
+ prevEntryHash: string;
21
+ summary: string;
22
+ outcome: "pass" | "fail" | "blocked" | "inconclusive";
23
+ operationId?: string | undefined;
24
+ }, {
25
+ createdAt: string;
26
+ entryId: string;
27
+ sequence: number;
28
+ prevEntryHash: string;
29
+ summary: string;
30
+ outcome: "pass" | "fail" | "blocked" | "inconclusive";
31
+ operationId?: string | undefined;
32
+ }>;
33
+ export type DecisionLogEntry = z.infer<typeof DecisionLogEntrySchema>;
34
+ //# sourceMappingURL=decision-log-entry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"decision-log-entry.d.ts","sourceRoot":"","sources":["../src/decision-log-entry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,eAAO,MAAM,yBAAyB,QAAgC,CAAC;AAEvE,wFAAwF;AACxF,eAAO,MAAM,uBAAuB,QAAsB,CAAC;AAE3D,eAAO,MAAM,kBAAkB,OAAO,CAAC;AAEvC,eAAO,MAAM,qBAAqB,wDAAsD,CAAC;AACzF,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAEpE,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;;;;;EAQjC,CAAC;AACH,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAC"}
@@ -0,0 +1,17 @@
1
+ import { z } from "zod";
2
+ import { ISO_MILLIS_PATTERN, OPERATION_ID_PATTERN } from "./evidence-pack.js";
3
+ export const DECISION_ENTRY_ID_PATTERN = /^dl_[0-9A-HJKMNP-TV-Z]{26}$/;
4
+ /** SHA-256 full hex (64 lowercase chars), or the empty string for the genesis entry. */
5
+ export const PREV_ENTRY_HASH_PATTERN = /^([0-9a-f]{64})?$/;
6
+ export const SUMMARY_MAX_LENGTH = 2048;
7
+ export const DecisionOutcomeSchema = z.enum(["pass", "fail", "blocked", "inconclusive"]);
8
+ export const DecisionLogEntrySchema = z.strictObject({
9
+ entryId: z.string().regex(DECISION_ENTRY_ID_PATTERN),
10
+ sequence: z.number().int().min(0),
11
+ prevEntryHash: z.string().regex(PREV_ENTRY_HASH_PATTERN),
12
+ operationId: z.string().regex(OPERATION_ID_PATTERN).optional(),
13
+ summary: z.string().max(SUMMARY_MAX_LENGTH),
14
+ outcome: DecisionOutcomeSchema,
15
+ createdAt: z.string().regex(ISO_MILLIS_PATTERN)
16
+ });
17
+ //# sourceMappingURL=decision-log-entry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"decision-log-entry.js","sourceRoot":"","sources":["../src/decision-log-entry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAE9E,MAAM,CAAC,MAAM,yBAAyB,GAAG,6BAA6B,CAAC;AAEvE,wFAAwF;AACxF,MAAM,CAAC,MAAM,uBAAuB,GAAG,mBAAmB,CAAC;AAE3D,MAAM,CAAC,MAAM,kBAAkB,GAAG,IAAI,CAAC;AAEvC,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,cAAc,CAAC,CAAC,CAAC;AAGzF,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,CAAC,YAAY,CAAC;IACnD,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,yBAAyB,CAAC;IACpD,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACjC,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,uBAAuB,CAAC;IACxD,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,oBAAoB,CAAC,CAAC,QAAQ,EAAE;IAC9D,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,kBAAkB,CAAC;IAC3C,OAAO,EAAE,qBAAqB;IAC9B,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,kBAAkB,CAAC;CAChD,CAAC,CAAC"}
@@ -0,0 +1,142 @@
1
+ import { type DecisionLogEntry, type DecisionOutcome } from "./decision-log-entry.js";
2
+ /**
3
+ * The decision log: an append-only JSONL ledger whose entries are linked by
4
+ * `prevEntryHash` — the opID↔decision one-way audit chain that
5
+ * `kernel/schemas/decision-log-entry.schema.json` describes at the entry level.
6
+ *
7
+ * Chain rule, stated so an auditor can recompute it without reading TypeScript:
8
+ *
9
+ * line i = canonical JSON of entry i (keys sorted, no whitespace)
10
+ * sequence = i (genesis is 0, strictly +1 — no gaps, no reuse)
11
+ * prevEntryHash = "" for i = 0, otherwise sha256_hex(canonical JSON of entry i-1)
12
+ *
13
+ * Because a line's bytes *are* the canonical form,
14
+ * `printf '%s' "$(sed -n '2p' ledger.jsonl)" | sha256sum` reproduces the
15
+ * `prevEntryHash` that entry 3 must carry. A chain only one language can
16
+ * recompute is a claim, not evidence.
17
+ *
18
+ * The write discipline copies the ledgers this ecosystem already runs
19
+ * (`ApprovalGate.swift`, `mcp-shell/src/project-registry.ts`) instead of
20
+ * inventing a third: validate before touching disk, refuse on a corrupt tail
21
+ * rather than "repairing" it, keep the file 0600 in a directory that is not
22
+ * group/other-writable, fsync, then read back and verify — and never truncate,
23
+ * because the ledger's job is to record what happened, including a failed write.
24
+ */
25
+ export declare const DECISION_LOG_CODES: {
26
+ readonly path: "KERNEL_E_DECISION_LOG_PATH";
27
+ readonly corrupt: "KERNEL_E_DECISION_LOG_CORRUPT";
28
+ readonly chain: "KERNEL_E_DECISION_LOG_CHAIN";
29
+ readonly location: "KERNEL_E_DECISION_LOG_LOCATION";
30
+ readonly write: "KERNEL_E_DECISION_LOG_WRITE";
31
+ readonly draft: "KERNEL_E_DECISION_LOG_DRAFT";
32
+ };
33
+ export type KernelDecisionLogCode = (typeof DECISION_LOG_CODES)[keyof typeof DECISION_LOG_CODES];
34
+ /**
35
+ * Every failure carries `code` + `message` + `remedy`, the same three-field shape
36
+ * the engine's error frames use: whoever catches this must be able to act on it
37
+ * without reading this file.
38
+ */
39
+ export declare class KernelDecisionLogError extends Error {
40
+ readonly code: KernelDecisionLogCode;
41
+ readonly path: string;
42
+ readonly line?: number;
43
+ readonly remedy: string;
44
+ constructor(code: KernelDecisionLogCode, path: string, message: string, remedy: string, line?: number);
45
+ }
46
+ /** What a producer supplies; the chain fields are derived from the ledger itself. */
47
+ export interface DecisionLogDraft {
48
+ readonly entryId: string;
49
+ readonly summary: string;
50
+ readonly outcome: DecisionOutcome;
51
+ readonly createdAt: string;
52
+ readonly operationId?: string;
53
+ }
54
+ /**
55
+ * The draft contract, strict. An unknown key is refused rather than dropped:
56
+ * a producer that spells a field wrong (`operation_id`) would otherwise lose
57
+ * that information silently into a ledger whose whole purpose is to say what
58
+ * was decided and why. `sequence`/`prevEntryHash` are deliberately *not*
59
+ * accepted here — the ledger owns them (see `appendDecisionLogEntry`).
60
+ */
61
+ export declare const DecisionLogDraftSchema: import("zod").ZodObject<Omit<{
62
+ entryId: import("zod").ZodString;
63
+ sequence: import("zod").ZodNumber;
64
+ prevEntryHash: import("zod").ZodString;
65
+ operationId: import("zod").ZodOptional<import("zod").ZodString>;
66
+ summary: import("zod").ZodString;
67
+ outcome: import("zod").ZodEnum<["pass", "fail", "blocked", "inconclusive"]>;
68
+ createdAt: import("zod").ZodString;
69
+ }, "sequence" | "prevEntryHash">, "strict", import("zod").ZodTypeAny, {
70
+ createdAt: string;
71
+ entryId: string;
72
+ summary: string;
73
+ outcome: "pass" | "fail" | "blocked" | "inconclusive";
74
+ operationId?: string | undefined;
75
+ }, {
76
+ createdAt: string;
77
+ entryId: string;
78
+ summary: string;
79
+ outcome: "pass" | "fail" | "blocked" | "inconclusive";
80
+ operationId?: string | undefined;
81
+ }>;
82
+ export interface AppendedDecisionLogEntry {
83
+ readonly entry: DecisionLogEntry;
84
+ /** sha256 of the entry's canonical JSON — what the *next* entry must carry as `prevEntryHash`. */
85
+ readonly hash: string;
86
+ /** 1-based line the entry now occupies. */
87
+ readonly line: number;
88
+ readonly bytesWritten: number;
89
+ }
90
+ export interface DecisionLogVerification {
91
+ readonly ok: boolean;
92
+ readonly entries: readonly DecisionLogEntry[];
93
+ /** 1-based line of the first problem, when there is one. */
94
+ readonly firstBrokenLine?: number;
95
+ /** `corrupt` = bytes that are not a valid entry; `chain` = a valid entry that does not link. */
96
+ readonly brokenKind?: "corrupt" | "chain";
97
+ readonly reason?: string;
98
+ }
99
+ /** Canonical JSON of an entry — the exact bytes that are hashed and stored. */
100
+ export declare function serializeDecisionLogEntry(entry: DecisionLogEntry): string;
101
+ /** sha256 over `serializeDecisionLogEntry`, lowercase full hex. */
102
+ export declare function decisionLogEntryHash(entry: DecisionLogEntry): string;
103
+ /**
104
+ * Crockford-base32 ULID (26 chars; alphabet excludes I/L/O/U) with the `dl_`
105
+ * prefix the schema requires: 48-bit ms timestamp + 80-bit randomness. Same
106
+ * shape as the engine's `op_` ids so a reader can sort and compare them.
107
+ */
108
+ export declare function newDecisionEntryId(timestampMs?: number): string;
109
+ /**
110
+ * Parse and verify ledger *text* — the pure half, so a reader can verify a string
111
+ * obtained anywhere (a CI artifact, a pasted excerpt, a Swift-written file).
112
+ * Never throws: a broken chain is a result, because the auditor's job is to say
113
+ * where it broke.
114
+ */
115
+ export declare function verifyDecisionLogText(text: string): DecisionLogVerification;
116
+ /** Read + verify a ledger file. A missing file is an empty chain, not an error. */
117
+ export declare function readDecisionLog(logPath: string): DecisionLogVerification;
118
+ /** The chain fields the next entry must carry, taken from the ledger itself. */
119
+ export declare function decisionLogHead(logPath: string): {
120
+ sequence: number;
121
+ prevEntryHash: string;
122
+ };
123
+ /**
124
+ * Validate a draft plus its chain fields into a strict `DecisionLogEntry`, before
125
+ * any disk access. `operationId` is omitted rather than written as null, matching
126
+ * the schema and the engine's Codable binding.
127
+ */
128
+ export declare function buildDecisionLogEntry(draft: DecisionLogDraft, chain: {
129
+ sequence: number;
130
+ prevEntryHash: string;
131
+ }): DecisionLogEntry;
132
+ /**
133
+ * Append one entry and return what was written. The chain fields come from the
134
+ * ledger, so a caller cannot choose them.
135
+ *
136
+ * Single-writer assumption, stated plainly: concurrent appends from two
137
+ * processes can interleave. This function does not pretend to solve that — it
138
+ * detects it (read-back + verify) and reports it, and the next writer refuses to
139
+ * build on the damaged tail.
140
+ */
141
+ export declare function appendDecisionLogEntry(logPath: string, draft: DecisionLogDraft): AppendedDecisionLogEntry;
142
+ //# sourceMappingURL=decision-log.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"decision-log.d.ts","sourceRoot":"","sources":["../src/decision-log.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,288 @@
1
+ import { createHash, randomBytes } from "node:crypto";
2
+ import { closeSync, fchmodSync, fsyncSync, openSync, readFileSync, statSync, writeSync } from "node:fs";
3
+ import { dirname } from "node:path";
4
+ import { canonicalJson } from "./canonical-json.js";
5
+ import { DecisionLogEntrySchema } from "./decision-log-entry.js";
6
+ import { parseDecisionLogEntry } from "./parse.js";
7
+ /**
8
+ * The decision log: an append-only JSONL ledger whose entries are linked by
9
+ * `prevEntryHash` — the opID↔decision one-way audit chain that
10
+ * `kernel/schemas/decision-log-entry.schema.json` describes at the entry level.
11
+ *
12
+ * Chain rule, stated so an auditor can recompute it without reading TypeScript:
13
+ *
14
+ * line i = canonical JSON of entry i (keys sorted, no whitespace)
15
+ * sequence = i (genesis is 0, strictly +1 — no gaps, no reuse)
16
+ * prevEntryHash = "" for i = 0, otherwise sha256_hex(canonical JSON of entry i-1)
17
+ *
18
+ * Because a line's bytes *are* the canonical form,
19
+ * `printf '%s' "$(sed -n '2p' ledger.jsonl)" | sha256sum` reproduces the
20
+ * `prevEntryHash` that entry 3 must carry. A chain only one language can
21
+ * recompute is a claim, not evidence.
22
+ *
23
+ * The write discipline copies the ledgers this ecosystem already runs
24
+ * (`ApprovalGate.swift`, `mcp-shell/src/project-registry.ts`) instead of
25
+ * inventing a third: validate before touching disk, refuse on a corrupt tail
26
+ * rather than "repairing" it, keep the file 0600 in a directory that is not
27
+ * group/other-writable, fsync, then read back and verify — and never truncate,
28
+ * because the ledger's job is to record what happened, including a failed write.
29
+ */
30
+ export const DECISION_LOG_CODES = {
31
+ path: "KERNEL_E_DECISION_LOG_PATH",
32
+ corrupt: "KERNEL_E_DECISION_LOG_CORRUPT",
33
+ chain: "KERNEL_E_DECISION_LOG_CHAIN",
34
+ location: "KERNEL_E_DECISION_LOG_LOCATION",
35
+ write: "KERNEL_E_DECISION_LOG_WRITE",
36
+ draft: "KERNEL_E_DECISION_LOG_DRAFT",
37
+ };
38
+ /**
39
+ * Every failure carries `code` + `message` + `remedy`, the same three-field shape
40
+ * the engine's error frames use: whoever catches this must be able to act on it
41
+ * without reading this file.
42
+ */
43
+ export class KernelDecisionLogError extends Error {
44
+ code;
45
+ path;
46
+ line;
47
+ remedy;
48
+ constructor(code, path, message, remedy, line) {
49
+ super(`${code}: ${message}`);
50
+ this.name = "KernelDecisionLogError";
51
+ this.code = code;
52
+ this.path = path;
53
+ this.remedy = remedy;
54
+ if (line !== undefined)
55
+ this.line = line;
56
+ }
57
+ }
58
+ /**
59
+ * The draft contract, strict. An unknown key is refused rather than dropped:
60
+ * a producer that spells a field wrong (`operation_id`) would otherwise lose
61
+ * that information silently into a ledger whose whole purpose is to say what
62
+ * was decided and why. `sequence`/`prevEntryHash` are deliberately *not*
63
+ * accepted here — the ledger owns them (see `appendDecisionLogEntry`).
64
+ */
65
+ export const DecisionLogDraftSchema = DecisionLogEntrySchema.omit({
66
+ sequence: true,
67
+ prevEntryHash: true,
68
+ });
69
+ /** Canonical JSON of an entry — the exact bytes that are hashed and stored. */
70
+ export function serializeDecisionLogEntry(entry) {
71
+ return canonicalJson(entry);
72
+ }
73
+ /** sha256 over `serializeDecisionLogEntry`, lowercase full hex. */
74
+ export function decisionLogEntryHash(entry) {
75
+ return createHash("sha256").update(serializeDecisionLogEntry(entry), "utf8").digest("hex");
76
+ }
77
+ const CROCKFORD = "0123456789ABCDEFGHJKMNPQRSTVWXYZ";
78
+ /**
79
+ * Crockford-base32 ULID (26 chars; alphabet excludes I/L/O/U) with the `dl_`
80
+ * prefix the schema requires: 48-bit ms timestamp + 80-bit randomness. Same
81
+ * shape as the engine's `op_` ids so a reader can sort and compare them.
82
+ */
83
+ export function newDecisionEntryId(timestampMs = Date.now()) {
84
+ if (!Number.isInteger(timestampMs) || timestampMs < 0 || timestampMs > 0xffffffffffff) {
85
+ throw new RangeError(`entryId timestamp must be an integer in [0, 2^48): got ${timestampMs}`);
86
+ }
87
+ let out = "";
88
+ let value = timestampMs;
89
+ for (let i = 0; i < 10; i++) {
90
+ out = CROCKFORD.charAt(value & 0x1f) + out;
91
+ value = Math.floor(value / 32);
92
+ }
93
+ for (const byte of randomBytes(10)) {
94
+ out += CROCKFORD.charAt((byte & 0xe0) >> 5) + CROCKFORD.charAt(byte & 0x1f);
95
+ }
96
+ return `dl_${out.slice(0, 26)}`;
97
+ }
98
+ function broken(entries, kind, line, reason) {
99
+ return { ok: false, entries, firstBrokenLine: line, brokenKind: kind, reason };
100
+ }
101
+ /**
102
+ * Parse and verify ledger *text* — the pure half, so a reader can verify a string
103
+ * obtained anywhere (a CI artifact, a pasted excerpt, a Swift-written file).
104
+ * Never throws: a broken chain is a result, because the auditor's job is to say
105
+ * where it broke.
106
+ */
107
+ export function verifyDecisionLogText(text) {
108
+ const body = text.endsWith("\n") ? text.slice(0, -1) : text;
109
+ if (body.length === 0) {
110
+ return { ok: true, entries: [] };
111
+ }
112
+ const lines = body.split("\n");
113
+ const entries = [];
114
+ for (let i = 0; i < lines.length; i++) {
115
+ const lineNumber = i + 1;
116
+ const raw = lines[i] ?? "";
117
+ let parsed;
118
+ try {
119
+ parsed = JSON.parse(raw);
120
+ }
121
+ catch (error) {
122
+ return broken(entries, "corrupt", lineNumber, `line ${lineNumber} is not valid JSON (${error.message})`);
123
+ }
124
+ let entry;
125
+ try {
126
+ entry = parseDecisionLogEntry(parsed);
127
+ }
128
+ catch (error) {
129
+ return broken(entries, "corrupt", lineNumber, `line ${lineNumber} is not a valid DecisionLogEntry: ${error.message}`);
130
+ }
131
+ if (entry.sequence !== i) {
132
+ return broken(entries, "chain", lineNumber, `line ${lineNumber} declares sequence ${entry.sequence}, expected ${i} (sequences start at 0 and rise by one)`);
133
+ }
134
+ if (canonicalJson(entry) !== raw) {
135
+ return broken(entries, "corrupt", lineNumber, `line ${lineNumber} is not stored in canonical JSON form, so its hash cannot be recomputed from the bytes on disk`);
136
+ }
137
+ const previous = i === 0 ? undefined : entries[i - 1];
138
+ const expectedPrev = previous === undefined ? "" : decisionLogEntryHash(previous);
139
+ if (entry.prevEntryHash !== expectedPrev) {
140
+ return broken(entries, "chain", lineNumber, i === 0
141
+ ? `line 1 is the genesis entry and must carry an empty prevEntryHash, found "${entry.prevEntryHash}"`
142
+ : `line ${lineNumber} links to ${entry.prevEntryHash}, but the entry on line ${lineNumber - 1} hashes to ${expectedPrev}`);
143
+ }
144
+ entries.push(entry);
145
+ }
146
+ return { ok: true, entries };
147
+ }
148
+ /** Read + verify a ledger file. A missing file is an empty chain, not an error. */
149
+ export function readDecisionLog(logPath) {
150
+ requireAbsolutePath(logPath);
151
+ let text;
152
+ try {
153
+ text = readFileSync(logPath, "utf8");
154
+ }
155
+ catch (error) {
156
+ if (error.code === "ENOENT") {
157
+ return { ok: true, entries: [] };
158
+ }
159
+ throw new KernelDecisionLogError(DECISION_LOG_CODES.location, logPath, `cannot read the ledger (${error.message})`, `fix the permissions or ownership on ${logPath} — this is evidence, so repair access rather than deleting the file`);
160
+ }
161
+ return verifyDecisionLogText(text);
162
+ }
163
+ /** The chain fields the next entry must carry, taken from the ledger itself. */
164
+ export function decisionLogHead(logPath) {
165
+ const verified = readDecisionLog(logPath);
166
+ if (!verified.ok) {
167
+ throw new KernelDecisionLogError(verified.brokenKind === "chain" ? DECISION_LOG_CODES.chain : DECISION_LOG_CODES.corrupt, logPath, verified.reason ?? "the ledger is not verifiable", `the ledger stops being trustworthy at line ${verified.firstBrokenLine}; preserve the file and investigate — appending on top of a broken link would forge its continuity`, verified.firstBrokenLine);
168
+ }
169
+ const tail = verified.entries[verified.entries.length - 1];
170
+ return {
171
+ sequence: verified.entries.length,
172
+ prevEntryHash: tail === undefined ? "" : decisionLogEntryHash(tail),
173
+ };
174
+ }
175
+ function requireAbsolutePath(logPath) {
176
+ if (typeof logPath !== "string" || logPath.length === 0) {
177
+ throw new KernelDecisionLogError(DECISION_LOG_CODES.path, String(logPath), "the ledger path must be an explicit non-empty string", "pass the resolved absolute path the caller was configured with; this API deliberately has no default location");
178
+ }
179
+ if (!logPath.startsWith("/")) {
180
+ throw new KernelDecisionLogError(DECISION_LOG_CODES.path, logPath, "the ledger path must be absolute", `resolve '${logPath}' against a configured data directory first — a CWD-relative ledger silently lands inside whatever repository the agent happened to run from`);
181
+ }
182
+ }
183
+ /**
184
+ * Validate a draft plus its chain fields into a strict `DecisionLogEntry`, before
185
+ * any disk access. `operationId` is omitted rather than written as null, matching
186
+ * the schema and the engine's Codable binding.
187
+ */
188
+ export function buildDecisionLogEntry(draft, chain) {
189
+ const checked = DecisionLogDraftSchema.safeParse(draft);
190
+ if (!checked.success) {
191
+ const detail = checked.error.issues
192
+ .map((issue) => `${issue.path.length > 0 ? issue.path.join(".") : "<root>"}: ${issue.message}`)
193
+ .join("; ");
194
+ throw new KernelDecisionLogError(DECISION_LOG_CODES.draft, "", `refusing to log a decision whose draft is not schema-valid: ${detail}`, "fix the producer — `sequence` and `prevEntryHash` are derived from the ledger and must not be sent, and an unrecognised key means the field name is wrong, not that it is optional");
195
+ }
196
+ const candidate = {
197
+ entryId: checked.data.entryId,
198
+ sequence: chain.sequence,
199
+ prevEntryHash: chain.prevEntryHash,
200
+ summary: checked.data.summary,
201
+ outcome: checked.data.outcome,
202
+ createdAt: checked.data.createdAt,
203
+ };
204
+ if (checked.data.operationId !== undefined)
205
+ candidate.operationId = checked.data.operationId;
206
+ const parsed = DecisionLogEntrySchema.safeParse(candidate);
207
+ if (!parsed.success) {
208
+ const detail = parsed.error.issues
209
+ .map((issue) => `${issue.path.length > 0 ? issue.path.join(".") : "<root>"}: ${issue.message}`)
210
+ .join("; ");
211
+ throw new KernelDecisionLogError(DECISION_LOG_CODES.draft, "", `refusing to log a decision that is not schema-valid: ${detail}`, "fix the entry at the producer — a ledger line that fails the schema can never be verified again");
212
+ }
213
+ return parsed.data;
214
+ }
215
+ /**
216
+ * Append one entry and return what was written. The chain fields come from the
217
+ * ledger, so a caller cannot choose them.
218
+ *
219
+ * Single-writer assumption, stated plainly: concurrent appends from two
220
+ * processes can interleave. This function does not pretend to solve that — it
221
+ * detects it (read-back + verify) and reports it, and the next writer refuses to
222
+ * build on the damaged tail.
223
+ */
224
+ export function appendDecisionLogEntry(logPath, draft) {
225
+ requireAbsolutePath(logPath);
226
+ // 1. Read and verify first: refuse to append onto a tail we cannot re-hash.
227
+ const head = decisionLogHead(logPath);
228
+ // 2. Validate in memory. Nothing touches the disk if the entry is not valid.
229
+ const entry = buildDecisionLogEntry(draft, head);
230
+ // 3. Location hygiene. The ledger is audit data, so it must not be
231
+ // group/other-readable, and a group/other-writable *directory* would let
232
+ // anyone swap the file out from under the chain.
233
+ const parent = dirname(logPath);
234
+ let dirMode;
235
+ try {
236
+ dirMode = statSync(parent).mode;
237
+ }
238
+ catch {
239
+ throw new KernelDecisionLogError(DECISION_LOG_CODES.location, logPath, `the ledger's directory ${parent} does not exist`, "create it (0700) or point the ledger at a directory you control; this API will not create state directories behind the caller's back");
240
+ }
241
+ if ((dirMode & 0o022) !== 0) {
242
+ throw new KernelDecisionLogError(DECISION_LOG_CODES.location, logPath, `${parent} is writable by group or other (mode ${(dirMode & 0o777).toString(8)})`, "an audit ledger in a group/other-writable directory can be replaced wholesale; move it, or chmod 0700 the directory");
243
+ }
244
+ const line = serializeDecisionLogEntry(entry);
245
+ const payload = `${line}\n`;
246
+ const expectedBytes = Buffer.byteLength(payload, "utf8");
247
+ let fd;
248
+ try {
249
+ fd = openSync(logPath, "a", 0o600);
250
+ fchmodSync(fd, 0o600);
251
+ const written = writeSync(fd, payload, null, "utf8");
252
+ fsyncSync(fd);
253
+ if (written !== expectedBytes) {
254
+ throw new KernelDecisionLogError(DECISION_LOG_CODES.write, logPath, `short write: ${written} of ${expectedBytes} bytes reached the fd`, `the tail may be torn — do not delete ${logPath}; call readDecisionLog() to see where verification stops, then investigate before producing more decisions`);
255
+ }
256
+ }
257
+ catch (error) {
258
+ if (error instanceof KernelDecisionLogError)
259
+ throw error;
260
+ throw new KernelDecisionLogError(DECISION_LOG_CODES.write, logPath, `append failed: ${error.message}`, `nothing was recorded for ${draft.entryId}; report this as a failed write instead of continuing as if the decision had been logged`);
261
+ }
262
+ finally {
263
+ if (fd !== undefined)
264
+ closeSync(fd);
265
+ }
266
+ // 4. Read back and verify. A ledger that lies about having been written is
267
+ // worse than one that refuses; so on mismatch we keep the bytes and shout.
268
+ const after = (readFileSync(logPath, "utf8").match(/^.*$/gm) ?? []).filter((value, index, all) => !(index === all.length - 1 && value === ""));
269
+ const lineNumber = after.length;
270
+ const tailLine = after[lineNumber - 1] ?? "";
271
+ if (tailLine !== line) {
272
+ throw new KernelDecisionLogError(DECISION_LOG_CODES.write, logPath, `read-back mismatch at line ${lineNumber}: the bytes on disk are not what this call wrote`, `another writer may have interleaved — preserve ${logPath} and re-verify the chain from line ${lineNumber}`, lineNumber);
273
+ }
274
+ const verified = verifyDecisionLogText(after.join("\n") + "\n");
275
+ if (!verified.ok) {
276
+ throw new KernelDecisionLogError(DECISION_LOG_CODES.write, logPath, `the ledger fails its own verification immediately after a successful append (line ${verified.firstBrokenLine}): ${verified.reason}`, `preserve the file; check the file mode (${modeOf(logPath).toString(8)}) and the raw tail before anything else`, verified.firstBrokenLine);
277
+ }
278
+ return { entry, hash: decisionLogEntryHash(entry), line: lineNumber, bytesWritten: expectedBytes };
279
+ }
280
+ function modeOf(path) {
281
+ try {
282
+ return statSync(path).mode & 0o777;
283
+ }
284
+ catch {
285
+ return 0;
286
+ }
287
+ }
288
+ //# sourceMappingURL=decision-log.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"decision-log.js","sourceRoot":"","sources":["../src/decision-log.ts"],"names":[],"mappings":"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"}