@a-company/gnomon 0.0.0-stage → 8.0.2

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 (71) hide show
  1. package/README.md +126 -2
  2. package/dist/agent.d.ts +28 -0
  3. package/dist/agent.js +45708 -0
  4. package/dist/build-id.json +1 -0
  5. package/dist/cli/gnomon.js +53946 -0
  6. package/dist/cli/gnomond.js +47744 -0
  7. package/dist/gnomon-local/cli.js +897 -0
  8. package/dist/index.d.ts +3477 -0
  9. package/dist/index.js +13698 -0
  10. package/dist/loops.d.ts +440 -0
  11. package/dist/loops.js +4706 -0
  12. package/dist/signer-CQ3Bpe7G.d.ts +158 -0
  13. package/dist/transport/gnomon-web.js +688 -0
  14. package/gnomon-mods/.purpose +143 -0
  15. package/gnomon-mods/constellation/README.md +27 -0
  16. package/gnomon-mods/constellation/fixtures/map-the-idea.golden.json +19 -0
  17. package/gnomon-mods/constellation/fixtures/map-the-idea.json +3 -0
  18. package/gnomon-mods/constellation/fixtures/summarize-the-session.golden.json +20 -0
  19. package/gnomon-mods/constellation/fixtures/summarize-the-session.json +3 -0
  20. package/gnomon-mods/constellation/fixtures/two-blocks.golden.json +4 -0
  21. package/gnomon-mods/constellation/fixtures/two-blocks.json +3 -0
  22. package/gnomon-mods/constellation/gnomon-manifest.json +68 -0
  23. package/gnomon-mods/constellation/skills/constellation-desk/SKILL.md +35 -0
  24. package/gnomon-mods/ledger/README.md +10 -0
  25. package/gnomon-mods/ledger/fixtures/breaker.golden.json +28 -0
  26. package/gnomon-mods/ledger/fixtures/breaker.json +80 -0
  27. package/gnomon-mods/ledger/fixtures/compacted.golden.json +42 -0
  28. package/gnomon-mods/ledger/fixtures/compacted.json +103 -0
  29. package/gnomon-mods/ledger/fixtures/over-budget.golden.json +24 -0
  30. package/gnomon-mods/ledger/fixtures/over-budget.json +86 -0
  31. package/gnomon-mods/ledger/fixtures/strip-reduced.golden.json +23 -0
  32. package/gnomon-mods/ledger/fixtures/strip-reduced.json +76 -0
  33. package/gnomon-mods/ledger/fixtures/strip.golden.json +18 -0
  34. package/gnomon-mods/ledger/fixtures/strip.json +68 -0
  35. package/gnomon-mods/ledger/gnomon-manifest.json +16 -0
  36. package/gnomon-mods/ledger/index.mjs +77 -0
  37. package/gnomon-mods/ledger/model.mjs +237 -0
  38. package/gnomon-mods/neurons/README.md +31 -0
  39. package/gnomon-mods/neurons/fixtures/capture-a-decision.golden.json +20 -0
  40. package/gnomon-mods/neurons/fixtures/capture-a-decision.json +3 -0
  41. package/gnomon-mods/neurons/fixtures/capture-a-learning.golden.json +19 -0
  42. package/gnomon-mods/neurons/fixtures/capture-a-learning.json +3 -0
  43. package/gnomon-mods/neurons/fixtures/search-the-brain.golden.json +19 -0
  44. package/gnomon-mods/neurons/fixtures/search-the-brain.json +3 -0
  45. package/gnomon-mods/neurons/fixtures/undeclared-kind.golden.json +9 -0
  46. package/gnomon-mods/neurons/fixtures/undeclared-kind.json +3 -0
  47. package/gnomon-mods/neurons/gnomon-manifest.json +87 -0
  48. package/gnomon-mods/neurons/skills/neurons-desk/SKILL.md +44 -0
  49. package/gnomon-mods/paradigm-context/README.md +9 -0
  50. package/gnomon-mods/paradigm-context/fixtures/empty.golden.json +28 -0
  51. package/gnomon-mods/paradigm-context/fixtures/empty.json +48 -0
  52. package/gnomon-mods/paradigm-context/fixtures/full-dark.golden.json +497 -0
  53. package/gnomon-mods/paradigm-context/fixtures/full-dark.json +134 -0
  54. package/gnomon-mods/paradigm-context/fixtures/full.golden.json +497 -0
  55. package/gnomon-mods/paradigm-context/fixtures/full.json +134 -0
  56. package/gnomon-mods/paradigm-context/fixtures/stale.golden.json +205 -0
  57. package/gnomon-mods/paradigm-context/fixtures/stale.json +69 -0
  58. package/gnomon-mods/paradigm-context/fixtures/unfocused.golden.json +28 -0
  59. package/gnomon-mods/paradigm-context/fixtures/unfocused.json +14 -0
  60. package/gnomon-mods/paradigm-context/gnomon-manifest.json +15 -0
  61. package/gnomon-mods/paradigm-context/index.mjs +64 -0
  62. package/gnomon-mods/paradigm-context/model.mjs +137 -0
  63. package/gnomon-mods/workshop/README.md +12 -0
  64. package/gnomon-mods/workshop/fixtures/strip-reduced.golden.json +56 -0
  65. package/gnomon-mods/workshop/fixtures/strip-reduced.json +16 -0
  66. package/gnomon-mods/workshop/fixtures/strip.golden.json +56 -0
  67. package/gnomon-mods/workshop/fixtures/strip.json +16 -0
  68. package/gnomon-mods/workshop/gnomon-manifest.json +14 -0
  69. package/gnomon-mods/workshop/index.mjs +73 -0
  70. package/gnomon-mods/workshop/model.mjs +152 -0
  71. package/package.json +80 -4
@@ -0,0 +1,3477 @@
1
+ import { S as Signer, K as KeyRing, D as DOMAINS_BY_KEY_CLASS, a as KeyClass, b as KeyCustody, c as SIGNATURE_DOMAINS, d as SignatureDomain, e as SignerDomainError, f as SoftwareEd25519Signer, g as answerDigest, h as approveMessage, i as decisionMessage, j as ed25519KeyId, p as p256KeyId, s as signaturePreimage, u as usesDecisionV2 } from './signer-CQ3Bpe7G.js';
2
+ import { ReleaseManifestV1, ReleaseArtifactV1, ReleaseArtifactName, RefusedError, RefusalCode, KindOwner, Audience, Sensitivity, EventLabels, EventV1, EventScopeV1, OfferSpecV1, GrantRowKind, CardV1 } from '@a-company/gnomon-contracts';
3
+ export { VOICE_IO_REQUIREMENT } from '@a-company/gnomon-contracts';
4
+ import * as fs from 'node:fs';
5
+ import 'node:crypto';
6
+
7
+ /**
8
+ * @symbol #identity
9
+ *
10
+ * #identity (spec §3.1 key classes, I5; M1.4 slice) — the `RootAuthority` seam.
11
+ *
12
+ * The root key is non-exportable hardware P-256 (Secure Enclave via the signed
13
+ * helper / Windows Hello in the Passport KSP) with presence per signature, and
14
+ * it is the ONLY signer of registry rows (I5). That custody arrives with M1.3,
15
+ * which is blocked on the founder's provisioning profile. Until then:
16
+ *
17
+ * - `UnprovisionedRootAuthority` (the production default): no trust set. It
18
+ * verifies nothing and signs nothing; `signRow` refuses `UNSUPPORTED`
19
+ * naming M1.3. With it, no registry row ever resolves, so no device can
20
+ * authenticate and no client can verify `serverSig` against a registered
21
+ * kernel key. That is the honest production posture before M1.3 — never a
22
+ * software fallback (§3.1 failure modes).
23
+ * - `HardwareRootAuthority` (identity/hardware.ts, M1.3): the Secure Enclave
24
+ * root behind the signed helper, provisioned by `gnomon identity init`.
25
+ * - `DevTestRootAuthority`: a SOFTWARE P-256 key in memory, constructible
26
+ * only by code that passes the literal acknowledgement `DEV_TEST_ROOT_ACK`.
27
+ * No env var or flag selects it (§15.3: the daemon reads no `GNOMON_*`),
28
+ * and no file does for the daemon: `gnomond` never constructs it and
29
+ * refuses a dev home. The ONE file exception is honoured only by the
30
+ * `gnomon` CLI's `dev up` (#dev-launch): a DEV home's ack-bearing marker
31
+ * plus its 0600 root key file. It exists so tests can drive
32
+ * the full mutual-auth path, and so `gnomon dev up` (#dev-launch, the
33
+ * unsigned dogfood path until M1.3) can run a kernel IN ITS OWN PROCESS on
34
+ * a separate, marked DEV home — never `~/.gnomon`. Everything it touches reports
35
+ * `state: 'dev-test'` (status, daemon.start) so it can never pass silently.
36
+ *
37
+ * Row signatures use the §3.1 `gnomon:row-sig:v1` domain over the canonical
38
+ * JSON of the row, ECDSA P-256 / SHA-256 in IEEE-P1363 encoding — the same
39
+ * bytes `KeyRing.verify(…, 'row', …)` checks, so a hardware root drops in
40
+ * behind this interface without changing a verifier.
41
+ */
42
+
43
+ type RootState = 'unprovisioned' | 'dev-test' | 'hardware';
44
+ interface RootAuthority {
45
+ readonly state: RootState;
46
+ /** `gkey-p256:v1:<sha256(spki DER)>`, or null when no root exists. */
47
+ readonly rootKeyId: string | null;
48
+ /** The trust-set namespace, or null when no root exists. */
49
+ readonly ns: string | null;
50
+ /** Verify a registry row signature: true only for THIS root (the 8.0 trust set, I5). */
51
+ verifyRow(signer: string, row: unknown, sigB64: string): boolean;
52
+ /** Sign a registry row; throws RootUnavailableError when there is no usable root. */
53
+ signRow(row: unknown): {
54
+ signer: string;
55
+ sig: string;
56
+ };
57
+ /** Asynchronous form (M1.3 hardware root: the daemon's helper, so a presence prompt never blocks the event loop). */
58
+ signRowAsync?(row: unknown): Promise<{
59
+ signer: string;
60
+ sig: string;
61
+ }>;
62
+ }
63
+
64
+ /** Anything that verifies rows from the trust set (RootAuthority or a client's RootVerifier). */
65
+ interface RowVerifier {
66
+ readonly rootKeyId: string | null;
67
+ readonly ns: string | null;
68
+ verifyRow(signer: string, row: unknown, sigB64: string): boolean;
69
+ }
70
+
71
+ /**
72
+ * @symbol #release-pins
73
+ *
74
+ * #release-pins (TD-2026-10-21-758 zero-build, G-HLP-01; T-2026-10-21-028) — the exact native bytes THIS kernel
75
+ * build accepts. The pins are COMPILED INTO THE BUNDLE, never read from a file at runtime (Aegis M1 review):
76
+ * `npm run build:release` (scripts/build-release.mjs) writes a release-manifest:v1 (gnomon-contracts) from the signed
77
+ * bin/ outputs, then rebuilds with tsup `define` (tsup.config.ts, env GNOMON_RELEASE_MANIFEST):
78
+ * __GNOMON_RELEASE__ = true and __GNOMON_RELEASE_MANIFEST__ = the manifest JSON.
79
+ *
80
+ * - release: every helper pin (identity/helper.ts pinHelper) and every voice-io install and pre-spawn re-check
81
+ * (voice/voice-install.ts) must match the compiled sha256 for this arch, ON TOP of the code-signing requirement
82
+ * and the version floor. A mismatch, or no entry for this arch, is refused `checksum`. Deleting or editing
83
+ * dist/build-id.json, loading dist/index.js, or copying dist elsewhere changes nothing: the hashes travel with
84
+ * the code (the stamp's `release` copy is informational only, for status and the upgrade card).
85
+ * - broken: compiled as a release but the compiled manifest is missing or invalid: EVERY pin is refused; a
86
+ * release never degrades to dev.
87
+ * - dev: not compiled as a release (a plain `npm run build`, a test run from src): signature plus version floor
88
+ * only. `gnomon daemon status` says `build: dev` and the setup helper row says so.
89
+ * Residual: a dev tree's dist is session-writable, so its code (and so its pins) is only as strong as the tree; the
90
+ * signed app bundle's seal is what makes a release's compiled pins hold.
91
+ */
92
+
93
+ type ReleasePins = {
94
+ readonly mode: 'release';
95
+ readonly manifest: ReleaseManifestV1;
96
+ } | {
97
+ readonly mode: 'dev';
98
+ readonly why: string;
99
+ } | {
100
+ readonly mode: 'broken';
101
+ readonly why: string;
102
+ };
103
+ type ReleaseMode = ReleasePins['mode'];
104
+ declare const DEV_PINS: ReleasePins;
105
+ /** The pins a build carries: not a release ⇒ dev; a release ⇒ its compiled manifest must be present and valid, else broken. */
106
+ declare function releasePinsFromCompiled(release: boolean, manifestJson: string | null | undefined): ReleasePins;
107
+ /** The pins compiled into the bundle this process runs (computed once). */
108
+ declare function loadedReleasePins(): ReleasePins;
109
+ /** What a verifier must enforce for one artifact on this arch. */
110
+ type ArtifactPin = {
111
+ readonly kind: 'dev';
112
+ } | {
113
+ readonly kind: 'pinned';
114
+ readonly artifact: ReleaseArtifactV1;
115
+ } | {
116
+ readonly kind: 'refuse';
117
+ readonly why: string;
118
+ };
119
+ declare function artifactPin(pins: ReleasePins, name: ReleaseArtifactName, arch?: string): ArtifactPin;
120
+ /** One line for status surfaces: `release 8.0.0 (sha256-pinned)`, `dev (…)`, `broken (…)`. */
121
+ declare function describeReleasePins(pins: ReleasePins): string;
122
+
123
+ type releasePins_ArtifactPin = ArtifactPin;
124
+ declare const releasePins_DEV_PINS: typeof DEV_PINS;
125
+ type releasePins_ReleaseMode = ReleaseMode;
126
+ type releasePins_ReleasePins = ReleasePins;
127
+ declare const releasePins_artifactPin: typeof artifactPin;
128
+ declare const releasePins_describeReleasePins: typeof describeReleasePins;
129
+ declare const releasePins_loadedReleasePins: typeof loadedReleasePins;
130
+ declare const releasePins_releasePinsFromCompiled: typeof releasePinsFromCompiled;
131
+ declare namespace releasePins {
132
+ export { releasePins_DEV_PINS as DEV_PINS, releasePins_artifactPin as artifactPin, releasePins_describeReleasePins as describeReleasePins, releasePins_loadedReleasePins as loadedReleasePins, releasePins_releasePinsFromCompiled as releasePinsFromCompiled };
133
+ export type { releasePins_ArtifactPin as ArtifactPin, releasePins_ReleaseMode as ReleaseMode, releasePins_ReleasePins as ReleasePins };
134
+ }
135
+
136
+ /**
137
+ * Aegis H1 (c): identifier + team is not enough (every binary the team signs
138
+ * as gnomon.helper passes it, an old one included). After spawn and before
139
+ * any request the kernel asks `info` and refuses a helper whose protocol is
140
+ * not HELPER_PROTOCOL or whose version is below this floor (the floor moves
141
+ * with every security-relevant helper change). Chosen over a CDHash
142
+ * allowlist: a timestamped signature changes the CDHash-bearing bytes on
143
+ * every founder build, so an allowlist shipped with the kernel would break on
144
+ * each rebuild; the floor stops downgrades to known-weaker helpers.
145
+ */
146
+ declare const MIN_HELPER_VERSION = "1.6.0";
147
+ /** The designated requirement the helper must satisfy (Developer ID, this team, this identifier). */
148
+ declare const HELPER_REQUIREMENT = "anchor apple generic and certificate 1[field.1.2.840.113635.100.6.2.6] exists and certificate leaf[field.1.2.840.113635.100.6.1.13] exists and certificate leaf[subject.OU] = \"SW4BMQ8PNL\" and identifier \"gnomon.helper\"";
149
+ interface HelperVerifier {
150
+ /** Throws HelperUnavailableError when `exe` is not the signed helper. */
151
+ verify(exe: string): void;
152
+ /** After spawn, before the first request: throws when the RUNNING child is not the signed helper (H5). */
153
+ verifyRunning(pid: number): void;
154
+ readonly kind: 'codesign' | 'dev-test' | 'unavailable';
155
+ }
156
+ interface PinnedHelper {
157
+ readonly exe: string;
158
+ readonly sha256: string;
159
+ readonly verifier: HelperVerifier;
160
+ /** Synchronous re-check right before a spawn: same path, inode, size, mtime and sha256. Throws HelperUnavailableError. */
161
+ recheck(): void;
162
+ }
163
+ /**
164
+ * Resolve once; HASH, then VERIFY the signature, then RE-HASH and compare
165
+ * (Aegis H5: a file swapped between the codesign check and the hash would
166
+ * otherwise pin bytes nobody verified); record the facts the pre-spawn
167
+ * re-check compares.
168
+ */
169
+ declare function pinHelper(exePath: string, o?: {
170
+ verifier?: HelperVerifier;
171
+ expectedSha256?: string;
172
+ pins?: ReleasePins;
173
+ }): PinnedHelper;
174
+ /**
175
+ * G-HLP-01 (T-2026-10-21-028): the sha256 a release build pins for the helper on this arch, or undefined in a dev
176
+ * build (signature + version floor only). A release that pins no helper for this arch, pins it under another
177
+ * signing requirement, or pins one below MIN_HELPER_VERSION refuses before anything is verified or run.
178
+ */
179
+ declare function releaseHelperSha256(pins: ReleasePins, arch?: string): string | undefined;
180
+
181
+ declare const FORBIDDEN_FLAGS: readonly string[];
182
+ declare const SETTING_SOURCES: readonly ["user", "project", "local"];
183
+ type SettingSource = (typeof SETTING_SOURCES)[number];
184
+ /**
185
+ * "Your hooks inside sessions" (founder decision OPEN, T-2026-10-18-010 L4;
186
+ * docs/private/gnomon-founder-steps.html): which Claude settings layers a
187
+ * Gnomon-started session loads — and so whose hooks run inside it, with no
188
+ * trust prompt in `-p` mode. A ROOT-SIGNED config switch
189
+ * (`config.sessions.hooks`, budget/config.ts), never env/project/CLI:
190
+ * - `audited` (DEFAULT, founder ruling P8-D94): user only, plus the repo's
191
+ * project/local hooks the KERNEL extracted and the human approved per
192
+ * hook (kernel/supervisor/repo-hooks.ts), written into the session's own
193
+ * policy.json (`--settings`); unapproved, denied or unsafe hooks never run.
194
+ * P8-D97: the repo's CONTEXT still loads — `--add-dir` memory dirs (with
195
+ * REPO_CONTEXT_ENV) and a kernel-staged `--plugin-dir` of its skills,
196
+ * agents and commands with frontmatter hooks stripped
197
+ * (kernel/supervisor/repo-context.ts; probe p10m-repo-context);
198
+ * - `all` (the slice-1 behaviour): user, project, local — your hooks AND
199
+ * any hooks committed in the repo's `.claude/settings.json`, raw;
200
+ * - `user-only`: user — your own hooks, never the repo's;
201
+ * - `none`: no layer — only Gnomon's generated policy.json applies.
202
+ * Managed settings load regardless (p01: outside the switch).
203
+ */
204
+ declare const SESSION_HOOKS_MODES: readonly ["audited", "all", "user-only", "none"];
205
+ type SessionHooksMode = (typeof SESSION_HOOKS_MODES)[number];
206
+ declare const DEFAULT_SESSION_HOOKS: SessionHooksMode;
207
+ /** P8-D97: only `audited` loads the repo's context through the kernel (`all` loads it natively; the others not at all). */
208
+ declare function repoContextFor(mode: SessionHooksMode): boolean;
209
+ declare function settingSourcesFor(mode: SessionHooksMode): readonly SettingSource[];
210
+ /** P8-D96: the only permission-channel values (p01b: `host` needs `--permission-prompt-tool stdio`). */
211
+ declare const PERMISSION_PROMPTS: "host";
212
+ declare const PERMISSION_PROMPT_TOOL: "stdio";
213
+ /** Exactly one `--permission-prompts host` and one `--permission-prompt-tool stdio` (also in `--flag=value` form); anything else throws. */
214
+ declare function assertPermissionChannel(argv: readonly string[]): void;
215
+ declare class ForbiddenFlagError extends Error {
216
+ readonly flag: string;
217
+ constructor(flag: string);
218
+ }
219
+ interface ClaudeArgvInput {
220
+ /** `--session-id` for a new session, `--resume` for a respawn. */
221
+ uuid: string;
222
+ resume?: boolean;
223
+ policyPath: string;
224
+ mcpConfigPath: string;
225
+ /** Explicit subset (p01: user, project, local); empty = none. */
226
+ settingSources: readonly SettingSource[];
227
+ appendSystemPrompt?: string;
228
+ model?: string;
229
+ /** P8-D97: kernel-staged plugin dirs (`--plugin-dir`, each once) — the repo's stripped skills, agents, commands. */
230
+ pluginDirs?: readonly string[];
231
+ /** P8-D97: memory dirs (`--add-dir`, each once) — loaded as CLAUDE.md dirs with REPO_CONTEXT_ENV. */
232
+ addDirs?: readonly string[];
233
+ /** Extra flags (never a forbidden one). */
234
+ extra?: readonly string[];
235
+ }
236
+ /** Throws ForbiddenFlagError for any forbidden flag, also in `--flag=value` form. */
237
+ declare function assertNoForbiddenFlags(argv: readonly string[]): void;
238
+ /** Q6 (Aegis): the ONLY flags a caller may pass in `extra`, with their arity. Every other flag is refused. */
239
+ declare const EXTRA_FLAGS: Readonly<Record<string, 0 | 1>>;
240
+ type FlagSpec = {
241
+ arity: 0 | 1 | '*';
242
+ min: number;
243
+ max: number;
244
+ };
245
+ /**
246
+ * Q6: the whole argv grammar. Every kernel-owned flag appears exactly once (min = max = 1) or at most once; `--agents`
247
+ * and `--tools` are kernel-owned and the kernel never sets them, so they may not appear at all. `--session-id` and
248
+ * `--resume` are exactly one between them. `--add-dir` is ONE variadic flag.
249
+ */
250
+ declare const ARGV_GRAMMAR: Readonly<Record<string, FlagSpec>>;
251
+ /** Q6: walk an argv against a grammar (arity-aware, `--flag=value` included); throws TypeError on any unknown flag, stray value or wrong count. */
252
+ declare function assertArgv(argv: readonly string[], grammar?: Readonly<Record<string, FlagSpec>>, enforceMin?: boolean): Map<string, number>;
253
+ declare function buildClaudeArgv(i: ClaudeArgvInput): string[];
254
+ /**
255
+ * The user message for one turn. `guidance` (#gnomon-voice table talk, TD-2026-10-20-294) rides as a SECOND text
256
+ * block after the human's text; the first block is always the human's text alone (its bytes are the contentHash).
257
+ */
258
+ declare function userMessageLine(text: string, guidance?: string | null): string;
259
+ declare function controlInterruptLine(requestId?: string): string;
260
+ /**
261
+ * The mid-session model switch (probe p-set-model). The model must pass claudeModelProblem (an alias or a strict
262
+ * `claude-…` id); the request id must be a REQUEST_ID (the kernel matches the control_response by it).
263
+ */
264
+ declare function controlSetModelLine(requestId: string, model: string): string;
265
+ /** P8-D96 allow: `updatedInput` is ALWAYS the kernel-held input of the request (never a client's); no updatedPermissions. */
266
+ declare function permissionAllowLine(requestId: string, updatedInput: unknown): string;
267
+ declare function permissionDenyLine(requestId: string, message: string, interrupt?: boolean): string;
268
+ /** The answer to a control_request subtype the kernel does not serve. */
269
+ /** #kernel-mcp: the answer to an `mcp_message` control request (the SDK server shape: response.mcp_response). */
270
+ declare function mcpResponseLine(requestId: string, mcpResponse: unknown): string;
271
+ declare function controlErrorLine(requestId: string, error: string): string;
272
+ interface Usage {
273
+ tokens: number;
274
+ }
275
+ type AdapterEvent = {
276
+ kind: 'init';
277
+ type: string;
278
+ sessionId: string | null;
279
+ model: string | null;
280
+ apiKeySource: string | null;
281
+ }
282
+ /**
283
+ * A stream_event line. parentToolUseId: null on the main chain (a sub-agent's stream sets it). stopReason: the
284
+ * message_delta's stop_reason when this line carries one (the #gnomon-voice busy guard ends a reply at the main-chain
285
+ * message_stop after an end_turn delta, TD-2026-10-20 voice drops fix).
286
+ */
287
+ | {
288
+ kind: 'partial';
289
+ type: string;
290
+ bytes: number;
291
+ usage?: {
292
+ messageId: string | null;
293
+ tokens: number;
294
+ };
295
+ parentToolUseId: string | null;
296
+ stopReason: string | null;
297
+ } | {
298
+ kind: 'message';
299
+ type: string;
300
+ messageId: string | null;
301
+ tokens: number | null;
302
+ toolUses: Array<{
303
+ id: string | null;
304
+ name: string;
305
+ input: unknown;
306
+ }>;
307
+ quota: boolean;
308
+ model: string | null;
309
+ parentToolUseId: string | null;
310
+ stopReason: string | null;
311
+ } | {
312
+ kind: 'user';
313
+ type: string;
314
+ replay: boolean;
315
+ toolResults: ToolResultSeen[];
316
+ } | {
317
+ kind: 'result';
318
+ type: string;
319
+ subtype: string | null;
320
+ isError: boolean;
321
+ tokens: number | null;
322
+ split: UsageSplit | null;
323
+ costUsd: number | null;
324
+ permissionDenials: number;
325
+ quota: boolean;
326
+ } | {
327
+ kind: 'control';
328
+ type: string;
329
+ subtype: string | null;
330
+ requestId: string | null;
331
+ error: string | null;
332
+ errorCode: string | null;
333
+ } | {
334
+ kind: 'permission-request';
335
+ type: 'control_request.can_use_tool';
336
+ requestId: string;
337
+ toolName: string;
338
+ toolUseId: string | null;
339
+ input: Record<string, unknown>;
340
+ } | {
341
+ kind: 'control-cancel';
342
+ type: 'control_cancel_request';
343
+ requestId: string;
344
+ } | {
345
+ kind: 'permission-malformed';
346
+ type: 'control_request.can_use_tool';
347
+ requestId: string;
348
+ } | {
349
+ kind: 'control-request-unknown';
350
+ type: string;
351
+ subtype: string;
352
+ requestId: string | null;
353
+ } | {
354
+ kind: 'mcp-message';
355
+ type: 'control_request.mcp_message';
356
+ requestId: string;
357
+ serverName: string;
358
+ message: unknown;
359
+ } | {
360
+ kind: 'unknown';
361
+ type: string;
362
+ } | {
363
+ kind: 'malformed';
364
+ type: string;
365
+ bytes: number;
366
+ };
367
+ /** One tool_result in a `user` line: its tool_use id, is_error, and Claude's permission decision (`accept` | `reject`) when reported. */
368
+ interface ToolResultSeen {
369
+ toolUseId: string;
370
+ isError: boolean;
371
+ decision: string | null;
372
+ }
373
+ /** A control request id we answer: printable, bounded (p01b: Claude sends UUIDs). */
374
+ declare const REQUEST_ID: RegExp;
375
+ /** The turn's usage by kind (#ledger-mod): numbers only, from result.usage. */
376
+ interface UsageSplit {
377
+ in: number;
378
+ out: number;
379
+ cacheRead: number;
380
+ cacheWrite: number;
381
+ }
382
+ /** input / output / cache read / cache creation; null when no usage object. */
383
+ declare function usageSplit(u: unknown): UsageSplit | null;
384
+ /** input + output + cache creation + cache read; null when no usage object. */
385
+ declare function usageTokens(u: unknown): number | null;
386
+ declare function parseStreamLine(line: string): AdapterEvent;
387
+ /**
388
+ * The kernel's facts about one hook line, read from the FULL line before the line is stored (Aegis M2: a hook that
389
+ * prints past EVENT_LINE_CAP pushes its line to hash-only storage, so a reader of the stored row could not see a block).
390
+ * The supervisor logs them as `turn.event.hook`; readers use them first and parse the line only as a fallback.
391
+ */
392
+ interface HookFacts {
393
+ id: string | null;
394
+ event: string | null;
395
+ name: string | null;
396
+ /** hook_response only: the exit code and Claude's outcome (success | error | cancelled) */
397
+ exit: number | null;
398
+ outcome: string | null;
399
+ /** hook_response only: the hook blocked (exit 2, or exit 0 with stdout JSON `{decision: 'block'}`) */
400
+ blocked: boolean;
401
+ }
402
+ /** Per hook output field (stdout, stderr, output): kept inline up to this many bytes, above it `{bytes, sha256}` (Aegis L2). */
403
+ declare const HOOK_OUTPUT_INLINE_CAP = 4096;
404
+ /** A hook_response that blocked (claude 2.1.309): exit 2, or exit 0 (or none) with stdout a JSON object whose decision is 'block'. */
405
+ declare function stopHookBlocked(o: Record<string, unknown>): boolean;
406
+ /** The facts of a system.hook_started / hook_response line, or null for any other line. */
407
+ declare function hookFactsOf(line: string): HookFacts | null;
408
+ /**
409
+ * Aegis L2: the hook_response line as the log keeps it. stdout, stderr and output stay inline up to
410
+ * HOOK_OUTPUT_INLINE_CAP bytes each (after `redact`), above it `{bytes, sha256}`; `output` is dropped when it is exactly
411
+ * stdout + stderr (Claude writes both). Null for any other line (it is stored as received).
412
+ */
413
+ declare function hookStoredLine(line: string, redact?: (s: string) => {
414
+ text: string;
415
+ count: number;
416
+ }): {
417
+ line: string;
418
+ redacted: number;
419
+ hashed: string[];
420
+ dropped: string[];
421
+ } | null;
422
+ /**
423
+ * Aegis 2026-10-23: Claude's SYNTHETIC user line (`isSynthetic: true`, e.g. "Stop hook feedback:\n[<command>]: <reason>")
424
+ * carries hook output fed back to the model, so it is kept like hook output: each text block's text inline up to
425
+ * HOOK_OUTPUT_INLINE_CAP bytes (after `redact`), above it `{bytes, sha256}`. Null for any other line: a real user line
426
+ * (the human's replay, tool results) is stored as received.
427
+ */
428
+ declare function syntheticStoredLine(line: string, redact?: (s: string) => {
429
+ text: string;
430
+ count: number;
431
+ }): {
432
+ line: string;
433
+ redacted: number;
434
+ hashed: string[];
435
+ dropped: string[];
436
+ } | null;
437
+ /** A control_response error made safe to show: sanitised (§4.5), one line, at most 256 characters. */
438
+ declare function controlErrorText(raw: string, max?: number): string;
439
+ /** The two tool uses that become cards (§3.3): AskUserQuestion ⇒ ask-user, ExitPlanMode ⇒ plan. */
440
+ declare function cardKindOfTool(name: string): 'ask-user' | 'plan' | null;
441
+ /** Per-turn usage deltas (no double count across repeated message usage and the result total). */
442
+ declare class UsageMeter {
443
+ #private;
444
+ /** A message's cumulative usage; returns the tokens not yet charged. */
445
+ message(messageId: string | null, tokens: number): number;
446
+ /** The turn's total from `result.usage`; returns what the messages did not charge, and resets the turn. */
447
+ result(total: number | null): number;
448
+ }
449
+ /**
450
+ * Line splitter with the §3.3 caps: a stdout line over `maxLine` bytes is
451
+ * dropped and reported ONCE (with its total size, at its end), never buffered
452
+ * without bound. Linear: each chunk is measured once (no re-measuring of the
453
+ * accumulated buffer).
454
+ */
455
+ declare class LineSplitter {
456
+ #private;
457
+ constructor(maxLine: number);
458
+ push(chunk: string, onLine: (line: string) => void, onDropped: (bytes: number) => void): void;
459
+ }
460
+
461
+ declare const adapter_ARGV_GRAMMAR: typeof ARGV_GRAMMAR;
462
+ type adapter_AdapterEvent = AdapterEvent;
463
+ type adapter_ClaudeArgvInput = ClaudeArgvInput;
464
+ declare const adapter_DEFAULT_SESSION_HOOKS: typeof DEFAULT_SESSION_HOOKS;
465
+ declare const adapter_EXTRA_FLAGS: typeof EXTRA_FLAGS;
466
+ declare const adapter_FORBIDDEN_FLAGS: typeof FORBIDDEN_FLAGS;
467
+ type adapter_ForbiddenFlagError = ForbiddenFlagError;
468
+ declare const adapter_ForbiddenFlagError: typeof ForbiddenFlagError;
469
+ declare const adapter_HOOK_OUTPUT_INLINE_CAP: typeof HOOK_OUTPUT_INLINE_CAP;
470
+ type adapter_HookFacts = HookFacts;
471
+ type adapter_LineSplitter = LineSplitter;
472
+ declare const adapter_LineSplitter: typeof LineSplitter;
473
+ declare const adapter_PERMISSION_PROMPTS: typeof PERMISSION_PROMPTS;
474
+ declare const adapter_PERMISSION_PROMPT_TOOL: typeof PERMISSION_PROMPT_TOOL;
475
+ declare const adapter_REQUEST_ID: typeof REQUEST_ID;
476
+ declare const adapter_SESSION_HOOKS_MODES: typeof SESSION_HOOKS_MODES;
477
+ declare const adapter_SETTING_SOURCES: typeof SETTING_SOURCES;
478
+ type adapter_SessionHooksMode = SessionHooksMode;
479
+ type adapter_SettingSource = SettingSource;
480
+ type adapter_ToolResultSeen = ToolResultSeen;
481
+ type adapter_Usage = Usage;
482
+ type adapter_UsageMeter = UsageMeter;
483
+ declare const adapter_UsageMeter: typeof UsageMeter;
484
+ type adapter_UsageSplit = UsageSplit;
485
+ declare const adapter_assertArgv: typeof assertArgv;
486
+ declare const adapter_assertNoForbiddenFlags: typeof assertNoForbiddenFlags;
487
+ declare const adapter_assertPermissionChannel: typeof assertPermissionChannel;
488
+ declare const adapter_buildClaudeArgv: typeof buildClaudeArgv;
489
+ declare const adapter_cardKindOfTool: typeof cardKindOfTool;
490
+ declare const adapter_controlErrorLine: typeof controlErrorLine;
491
+ declare const adapter_controlErrorText: typeof controlErrorText;
492
+ declare const adapter_controlInterruptLine: typeof controlInterruptLine;
493
+ declare const adapter_controlSetModelLine: typeof controlSetModelLine;
494
+ declare const adapter_hookFactsOf: typeof hookFactsOf;
495
+ declare const adapter_hookStoredLine: typeof hookStoredLine;
496
+ declare const adapter_mcpResponseLine: typeof mcpResponseLine;
497
+ declare const adapter_parseStreamLine: typeof parseStreamLine;
498
+ declare const adapter_permissionAllowLine: typeof permissionAllowLine;
499
+ declare const adapter_permissionDenyLine: typeof permissionDenyLine;
500
+ declare const adapter_repoContextFor: typeof repoContextFor;
501
+ declare const adapter_settingSourcesFor: typeof settingSourcesFor;
502
+ declare const adapter_stopHookBlocked: typeof stopHookBlocked;
503
+ declare const adapter_syntheticStoredLine: typeof syntheticStoredLine;
504
+ declare const adapter_usageSplit: typeof usageSplit;
505
+ declare const adapter_usageTokens: typeof usageTokens;
506
+ declare const adapter_userMessageLine: typeof userMessageLine;
507
+ declare namespace adapter {
508
+ export { adapter_ARGV_GRAMMAR as ARGV_GRAMMAR, adapter_DEFAULT_SESSION_HOOKS as DEFAULT_SESSION_HOOKS, adapter_EXTRA_FLAGS as EXTRA_FLAGS, adapter_FORBIDDEN_FLAGS as FORBIDDEN_FLAGS, adapter_ForbiddenFlagError as ForbiddenFlagError, adapter_HOOK_OUTPUT_INLINE_CAP as HOOK_OUTPUT_INLINE_CAP, adapter_LineSplitter as LineSplitter, adapter_PERMISSION_PROMPTS as PERMISSION_PROMPTS, adapter_PERMISSION_PROMPT_TOOL as PERMISSION_PROMPT_TOOL, adapter_REQUEST_ID as REQUEST_ID, adapter_SESSION_HOOKS_MODES as SESSION_HOOKS_MODES, adapter_SETTING_SOURCES as SETTING_SOURCES, adapter_UsageMeter as UsageMeter, adapter_assertArgv as assertArgv, adapter_assertNoForbiddenFlags as assertNoForbiddenFlags, adapter_assertPermissionChannel as assertPermissionChannel, adapter_buildClaudeArgv as buildClaudeArgv, adapter_cardKindOfTool as cardKindOfTool, adapter_controlErrorLine as controlErrorLine, adapter_controlErrorText as controlErrorText, adapter_controlInterruptLine as controlInterruptLine, adapter_controlSetModelLine as controlSetModelLine, adapter_hookFactsOf as hookFactsOf, adapter_hookStoredLine as hookStoredLine, adapter_mcpResponseLine as mcpResponseLine, adapter_parseStreamLine as parseStreamLine, adapter_permissionAllowLine as permissionAllowLine, adapter_permissionDenyLine as permissionDenyLine, adapter_repoContextFor as repoContextFor, adapter_settingSourcesFor as settingSourcesFor, adapter_stopHookBlocked as stopHookBlocked, adapter_syntheticStoredLine as syntheticStoredLine, adapter_usageSplit as usageSplit, adapter_usageTokens as usageTokens, adapter_userMessageLine as userMessageLine };
509
+ export type { adapter_AdapterEvent as AdapterEvent, adapter_ClaudeArgvInput as ClaudeArgvInput, adapter_HookFacts as HookFacts, adapter_SessionHooksMode as SessionHooksMode, adapter_SettingSource as SettingSource, adapter_ToolResultSeen as ToolResultSeen, adapter_Usage as Usage, adapter_UsageSplit as UsageSplit };
510
+ }
511
+
512
+ declare const SESSION_POLICY_SCHEMA: "gnomon-session-policy:v1";
513
+ /** §15.5 `session` denies that are not file paths (platform-neutral names). */
514
+ declare const SESSION_DENY_CLASSES: readonly ["unix-socket:tmux", "unix-socket:screen", "ipc:helper-service", "ipc:process-table-service", "automation:apple-events", "service-manager", "media:microphone", "media:camera", "launchers", "process-info:others", "loopback:endpoint-port"];
515
+ type SessionDenyClass = (typeof SESSION_DENY_CLASSES)[number];
516
+ /**
517
+ * `steering` (P8-D97 R1): under `path`, at ANY depth and in ANY letter case, a `CLAUDE*.md` file or anything in a
518
+ * `.claude` dir — the memory and settings Claude Code may load from a subtree. Write-deny only.
519
+ */
520
+ /**
521
+ * `dep-steering` (P8-D97 F2): under `path`, inside ANY `node_modules` at any depth, in any case, a `CLAUDE*.md` file or
522
+ * anything in a `.claude` dir — dependency-shipped memory the subtree audit does not walk. Read-deny only.
523
+ */
524
+ /**
525
+ * `worktree-guard` (#git-verbs, T-2026-10-23-002): `path` is a kernel worktrees dir W (`<root>/.gnomon/worktrees`).
526
+ * Write-deny of each worktree's own entry `W/<name>` (no create, remove or rename: only the kernel adds or removes a
527
+ * worktree), its `.git` pointer file `W/<name>/.git` and its `W/<name>/.mcp.json` (any case).
528
+ * `worktree-gitdir`: `path` is `<commonDir>/worktrees`. Write-deny of each worktree's private git dir entry and its
529
+ * `commondir`, `gitdir` and `config.worktree` (what tells git where the config lives); HEAD, index and logs stay writable.
530
+ */
531
+ /**
532
+ * `dotgit-any` (Aegis round 2 M5): under `path` (a session root), at ANY depth and in any case, an entry named `.git`
533
+ * (a planted nested repo or gitfile the human's git would later read). Only the entry itself: an existing nested repo's
534
+ * contents stay as they were. The kernel worktrees' pointers are below it too (and guarded by worktree-guard).
535
+ */
536
+ type PathMatch = 'subpath' | 'literal' | 'prefix' | 'steering' | 'dep-steering' | 'worktree-guard' | 'worktree-gitdir' | 'dotgit-any';
537
+ /** Where the kernel makes a session's worktrees, relative to a session root (#git-verbs git.worktree.add). */
538
+ declare const KERNEL_WORKTREES_REL = ".gnomon/worktrees";
539
+ interface PolicyPath {
540
+ path: string;
541
+ match: PathMatch;
542
+ /** why the deny exists (the §15.5 class) */
543
+ class: 'keys' | 'kernel-log' | 'warpline-tokens' | 'browser-profile' | 'gnomon-home' | 'settings' | 'linked-folder' | 'git' | 'binary' | 'persistence' | 'transcripts' | 'session-env' | 'worktrees' | 'root' | 'temp' | 'cache';
544
+ }
545
+ interface SessionPolicy {
546
+ schemaVersion: typeof SESSION_POLICY_SCHEMA;
547
+ profile: 'session';
548
+ denyRead: PolicyPath[];
549
+ /**
550
+ * M1.7 slice 2 (T-2026-10-18-010): the ONLY reads carved back out of the
551
+ * read-denied Gnomon home — the session's own dir, the binary the kernel
552
+ * execs from `<home>/bin`, the pinned runner copy. Never under keys/,
553
+ * the kernel log, or another session's dir (buildSessionPolicy refuses).
554
+ */
555
+ allowRead: PolicyPath[];
556
+ /** metadata only (lstat, for realpath) on the literal ancestors of allowRead inside the home; no listing, no data */
557
+ allowReadMetadata: PolicyPath[];
558
+ /** re-denied AFTER allowRead (belt and braces: keys + the kernel log stay unreadable whatever is allowed) */
559
+ denyReadAlways: PolicyPath[];
560
+ denyWrite: PolicyPath[];
561
+ /**
562
+ * TD-2026-10-19-814 item 1 (probe p-resume, darwin): writes carved back out of denyWrite, rendered AFTER it (last
563
+ * match wins). Only ever `<userClaudeDir>/projects` (subpath) — Claude Code's transcripts, so `--resume` works —
564
+ * and `<userClaudeDir>/session-env/<uuid>` (subpath) — THIS session's dir Claude Code creates before any command
565
+ * hook runs (never the whole session-env, Aegis H1) — and only for a Claude session (`claudeTranscripts` / `claudeSessionEnv`). Never an input path: no
566
+ * manifest or caller can name one.
567
+ */
568
+ allowWrite: PolicyPath[];
569
+ /**
570
+ * T-2026-10-23-004 (Aegis, the root fix): session file writes are DENY BY DEFAULT. The profile opens with
571
+ * `(deny file-write*)` and allows ONLY these (rendered before denyWrite, so every deny still wins inside them): the
572
+ * session roots (subpath; the kernel worktrees live under them), the session's temp (its TMPDIR's per-user
573
+ * /private/var/folders/<a>/<b> dir, /private/tmp, /private/var/tmp) and the measured tool caches
574
+ * (WRITE_CACHE_PATHS under the user home). The transcript and session-env carve-backs stay allowWrite. A policy
575
+ * object without the field allows nothing but those carve-backs and the device files (fail closed).
576
+ */
577
+ writeAllow?: PolicyPath[];
578
+ /**
579
+ * re-denied AFTER allowWrite so the carve-back reopens nothing else: each allowWrite root itself (literal — it can
580
+ * be neither removed, renamed nor replaced; Aegis M1), the denyWrite entries inside it, and the steering regexes
581
+ * re-rooted at it (Aegis L3)
582
+ */
583
+ denyWriteAlways: PolicyPath[];
584
+ /** why the transcript carve-back was withheld (fail closed: no allow), when `claudeTranscripts` asked for it */
585
+ allowWriteRefused?: string;
586
+ /** why the session-env carve-back was withheld (fail closed: no allow), when `claudeSessionEnv` asked for it */
587
+ sessionEnvRefused?: string;
588
+ /** outbound loopback connects refused to these ports (the web endpoint) */
589
+ denyLoopbackPorts: number[];
590
+ /** process-info on every process but self (process-info*, sysctl process lists, the sysmond lookup on macOS) */
591
+ processInfo: 'deny-others';
592
+ /** launcher escapes (open/osascript/lsregister on macOS; job limits on Windows) — realised by M1.7 */
593
+ launchers: 'deny';
594
+ /** platform-neutral deny classes (SESSION_DENY_CLASSES); mapped per platform in src/platform/session-denies.ts */
595
+ denyClasses: SessionDenyClass[];
596
+ /** the M1.7 step that turns this data into a platform profile */
597
+ realisedBy: 'M1.7';
598
+ }
599
+ interface SessionPolicyInput {
600
+ home: string;
601
+ cwd: string;
602
+ worktree?: string;
603
+ userClaudeDir: string;
604
+ managedSettingsPaths: readonly string[];
605
+ linkedFolders: readonly string[];
606
+ /** the web endpoint port, or null when the endpoint is not listening */
607
+ endpointPort: number | null;
608
+ /** platform-specific browser profile + wrapper WebView data dirs (S29-K7) */
609
+ browserProfileDirs?: readonly string[];
610
+ /** `~/.claude.json` (default: beside userClaudeDir) */
611
+ userClaudeJson?: string;
612
+ /**
613
+ * M1.7 (Aegis M2): the user's home — its persistence paths are write-denied
614
+ * (PERSISTENCE_PATHS: LaunchAgents, shell rc files, git config, ~/.ssh).
615
+ */
616
+ userHome?: string;
617
+ /**
618
+ * M1.7 (Aegis H1): extra write denies the supervisor computes, ALREADY
619
+ * resolved (a symlink's own path must stay literal: the claude binary's
620
+ * known-location links, its realpath and its versions dir).
621
+ */
622
+ extraDenyWrite?: readonly PolicyPath[];
623
+ /**
624
+ * M1.8 slice 2 round 3 (Aegis H1, node half): the root-signed local runner. EVERY session profile — Claude
625
+ * and local alike — denies writes to its node binary, node's install prefix (bin/ + lib/libnode) and the
626
+ * pinned runner source dir, so no running session can swap what the next local session execs.
627
+ */
628
+ localRunner?: {
629
+ node: string;
630
+ dir: string;
631
+ };
632
+ /**
633
+ * M1.7 slice 2 (T-2026-10-18-010): what the session may READ inside the
634
+ * read-denied Gnomon home. Each entry must sit strictly inside one of
635
+ * HOME_READABLE_ROOTS (`sessions/<short>/…`, `bin/<file>`,
636
+ * `runners/<tree>/…`); anything else refuses the policy (fail closed).
637
+ */
638
+ homeReadable?: ReadonlyArray<{
639
+ path: string;
640
+ match: 'literal' | 'subpath';
641
+ }>;
642
+ /**
643
+ * P8-D97 (Aegis M1): the memory chain (the cwd and its ancestors up to the git top-level). Each dir's `CLAUDE*`
644
+ * (prefix) and `.claude/**` join the settings write denies, so a session cannot plant steering that a later
645
+ * session loads (`--add-dir` memory, or an ancestor's `.claude`).
646
+ */
647
+ memoryDirs?: readonly string[];
648
+ /**
649
+ * P8-D97 (Aegis R1): the memory subtree root (the git top-level, else the cwd). Every `CLAUDE*.md` and `.claude/**`
650
+ * below it, in any case, joins the settings write denies (`steering` match: an SBPL regex), because Claude Code
651
+ * loads a subdirectory's CLAUDE.md lazily.
652
+ */
653
+ memorySubtree?: string;
654
+ /**
655
+ * P8-D97 (Aegis F3): every in-repo `@` import target the memory audit resolved, existing or not. Each is a
656
+ * settings-class write-deny literal, so a session cannot plant or rewrite what an approved memory file imports.
657
+ */
658
+ memoryImports?: readonly string[];
659
+ /**
660
+ * TD-2026-10-19-814 item 1: a Claude Code session — carve `<userClaudeDir>/projects` (its transcripts) back out of
661
+ * the `~/.claude` write deny. A flag, not a path: the carve-back is derived here and nowhere else, so nothing a
662
+ * project supplies can widen it to another `~/.claude` path. Withheld (allowWriteRefused) when its realpath is not
663
+ * exactly `realpath(userClaudeDir)/projects` or another write deny covers it.
664
+ */
665
+ claudeTranscripts?: boolean;
666
+ /**
667
+ * T-2026-10-21 (hooks fix; Aegis H1/M1 rework): the backend session uuid (`--session-id` / `--resume`) of a Claude
668
+ * Code session — carve ONLY `<userClaudeDir>/session-env/<uuid>` back out of the `~/.claude` write deny. Claude Code
669
+ * creates `session-env/<session-id>/` before it runs ANY command hook; with it denied, every hook fails with
670
+ * `EPERM mkdir`. Not a path: a uuid, checked against a strict lowercase RFC 4122 shape, so it can never name
671
+ * `..`, a separator or a sibling. Writing another session's dir would let this session plant that session's
672
+ * CLAUDE_ENV_FILE, which Claude Code sources as shell before its Bash commands (the user's unsandboxed Claude Code
673
+ * included) — so siblings stay denied. `session-env` and `session-env/<uuid>` are both literal re-denied (neither
674
+ * can be removed, renamed or swapped for a link). Withheld (sessionEnvRefused) on a malformed uuid, when the dir's
675
+ * realpath is not exactly `realpath(userClaudeDir)/session-env/<uuid>`, or another write deny covers it.
676
+ */
677
+ claudeSessionEnv?: string;
678
+ /**
679
+ * #git-verbs (T-2026-10-23-002): the session may work in kernel-made worktrees under `<root>/.gnomon/worktrees/<name>`
680
+ * (git.worktree.add runs outside the sandbox). Ordinary files there stay writable (they are under the root); what
681
+ * steers Claude or git there is write-denied: `<root>/.gnomon` and W as literals (never renamed or removed), each
682
+ * worktree's own entry, `.git` pointer and `.mcp.json` (worktree-guard), every CLAUDE*.md and `.claude/**` below W
683
+ * (steering), and each worktree git dir's entry, commondir, gitdir and config.worktree (worktree-gitdir). The common
684
+ * dir's hooks, config and info stay denied as for any root.
685
+ */
686
+ kernelWorktrees?: boolean;
687
+ /** T-2026-10-23-004 / Aegis round 2 M1: the session's TMPDIR — only its own realpath is writable (a Gnomon-made dir for a Claude session) */
688
+ tmpdir?: string;
689
+ /** Aegis round 2 H: the session's Gnomon-made tool cache dir (SESSION_CACHE_ENV); writable */
690
+ sessionCache?: string;
691
+ /**
692
+ * Aegis round 3 M (measured, probe p10m-write-allow): Claude Code writes its task outputs under
693
+ * /private/tmp/claude-<uid>/<encoded cwd>/<session uuid>/, a tree the human's own unsandboxed Claude Code shares. The
694
+ * whole /private/tmp/claude-<uid> is write-denied and only this session's subtree is carved back (literal re-denied,
695
+ * so it is never removed or swapped); the supervisor makes its parents first. Absent ⇒ the whole tree stays denied.
696
+ */
697
+ claudeTmp?: {
698
+ uid: number;
699
+ uuid: string;
700
+ cwds: readonly string[];
701
+ };
702
+ /** TEST RIG ONLY (the supervisor passes it only with allowScripts): the fake claude's own dir, where it writes its trace */
703
+ testWriteAllow?: readonly string[];
704
+ }
705
+ /**
706
+ * T-2026-10-23-004: the tool caches under the user home a session may write (deny-by-default writes). MEASURED, not
707
+ * guessed: what Claude Code and an `npm install` in a root wrote under the profile (test/session-sandbox.test.ts,
708
+ * probes/p10m-write-allow). Anything else under the home stays denied; add one only when measured, narrowly.
709
+ */
710
+ declare const WRITE_CACHE_PATHS: readonly string[];
711
+ /**
712
+ * Aegis round 2 H (T-2026-10-23-004): a session never writes the human's own tool caches (~/.npm/_npx is run unsandboxed
713
+ * by the human's npx). Each session gets a Gnomon-made cache per repo (SESSION_CACHE_ENV points the tools at it,
714
+ * `sessionCache` is its write allow) and a Gnomon-made 0700 TMPDIR (`tmpdir`), both made by the supervisor.
715
+ */
716
+ declare const SESSION_CACHE_ENV: Readonly<Record<string, string>>;
717
+ /** Aegis round 2 M6: credential stores a session can neither read nor write (subpath / literal / prefix, under the user home). */
718
+ declare const CREDENTIAL_READ_DENY: ReadonlyArray<{
719
+ rel: string;
720
+ match: PathMatch;
721
+ }>;
722
+ /** T-2026-10-23-004: the shared temp dirs every session may write. */
723
+ declare const WRITE_TEMP_PATHS: readonly string[];
724
+ /** Aegis round 2 M1: the TMPDIR a session may write is exactly its realpath (never the per-user /private/var/folders parent). */
725
+ declare function userTempRoot(tmpdir: string): string;
726
+ /** The one write carve-back (TD-2026-10-19-814): Claude Code's transcript dir, relative to the user Claude dir. */
727
+ declare const CLAUDE_TRANSCRIPTS_REL = "projects";
728
+ /** The second write carve-back: Claude Code's per-session hook environment dir, relative to the user Claude dir. */
729
+ declare const CLAUDE_SESSION_ENV_REL = "session-env";
730
+ /** The only session id shape the session-env carve-back accepts (lowercase RFC 4122, as `randomUUID()` mints). */
731
+ declare const SESSION_UUID_RE: RegExp;
732
+ /** The only top-level home entries a session may be granted a read under (one level below them, never the root itself). */
733
+ declare const HOME_READABLE_ROOTS: readonly string[];
734
+ /** The kernel log files inside the home (spec §3.2; kernel-log.ts ACTIVE_DB + SEGMENTS_DIR): read-denied by name too. */
735
+ declare const KERNEL_LOG_PATHS: ReadonlyArray<{
736
+ rel: string;
737
+ match: PathMatch;
738
+ }>;
739
+ /** The write denies for the local runner's node install and source dir (realpath'd; a prefix that is /, the user home or above it narrows to node's own dir). */
740
+ declare function localRunnerDenies(r: {
741
+ node: string;
742
+ dir: string;
743
+ }, userHome?: string): PolicyPath[];
744
+ /** Aegis M2: user persistence paths a session may not write (relative to the user's home). */
745
+ declare const PERSISTENCE_PATHS: ReadonlyArray<{
746
+ rel: string;
747
+ match: PathMatch;
748
+ }>;
749
+ /** Realpath the longest existing prefix of `p` and append the rest. */
750
+ declare function realpathLoose(p: string): string;
751
+ /** A path whose symlinks cannot be followed to an answer (a loop, too many hops, a component that cannot be lstat'd). */
752
+ declare class UnresolvablePath extends Error {
753
+ }
754
+ /**
755
+ * Aegis H1 (run modes): the path a WRITE to `p` actually lands on. Unlike realpathLoose, a DANGLING symlink is
756
+ * followed (readlink, textually, as the OS does when it creates the target), so `scripts/x -> ../.git/hooks/pre-commit`
757
+ * resolves to the hook, not to `scripts/x`. Components past the first missing one are appended as text. Throws
758
+ * UnresolvablePath on a loop (more than 40 hops) or on an lstat/readlink failure other than ENOENT/ENOTDIR — the
759
+ * caller treats that as denied/carded, never as a plain name.
760
+ */
761
+ declare function realpathFollow(p: string): string;
762
+ declare function buildSessionPolicy(inp: SessionPolicyInput): SessionPolicy;
763
+ declare function policyHash(p: SessionPolicy): string;
764
+ /**
765
+ * P8-D96 (Aegis C2, probe p01b (h)): every tool that writes, runs or fetches is ALWAYS asked. An `allow` rule in
766
+ * any loaded settings layer would otherwise run it with no can_use_tool request (no card); `ask` wins over `allow`,
767
+ * so the request reaches the kernel and the card stays the gate. `deny` still wins over `ask`.
768
+ */
769
+ declare const ALWAYS_ASK_TOOLS: readonly string[];
770
+ /** The `policy.json` permissions block: the sandbox deny mirror (§6.1 step 6) and the always-ask tools (P8-D96). */
771
+ /**
772
+ * F7 (TD-2026-10-20-086): settings env for every Claude session. CLAUDE_BASH_MAINTAIN_PROJECT_WORKING_DIR=1 makes
773
+ * Claude Code return to the project dir after each Bash command, so its idea of the cwd matches the anchored
774
+ * read-only pass (#shell-readonly K1, which stays the proof: it cds into the root itself).
775
+ */
776
+ declare const CLAUDE_SESSION_ENV: Readonly<Record<string, string>>;
777
+ declare function claudePermissions(p: SessionPolicy, platform?: string): {
778
+ permissions: {
779
+ deny: string[];
780
+ ask: string[];
781
+ };
782
+ env: Record<string, string>;
783
+ };
784
+
785
+ /**
786
+ * @symbol #claude-adapter
787
+ * @symbol #session-runner
788
+ *
789
+ * Platform registry for Claude Code (spec §3.3 Preflight, §3.4 "Law 7 inside
790
+ * the broker", §16 "Claude Code preflight paths"; p01). DATA ONLY: kernel code
791
+ * looks a row up by platform key and never branches on the platform itself
792
+ * (G-WIN-05).
793
+ *
794
+ * knownBinaries — where the `claude` binary is looked for when the
795
+ * root-signed config names none. NEVER a `PATH` lookup (p01: the native
796
+ * installer's ~/.local/bin is not on a non-login PATH, and the daemon's
797
+ * clean env has no shell profile). `~` = the user's home.
798
+ * managedSettings — the managed-policy sources the CLI always loads (not
799
+ * controllable by --setting-sources, p01) and the law-7 scan must read.
800
+ * A source that is not JSON (a managed-preferences plist, a registry key)
801
+ * is scanned fail-closed: present but unreadable as JSON ⇒ a hit (B5).
802
+ * managedUnscannable — sources the kernel cannot read at all on that
803
+ * platform yet (Windows HKLM/HKCU policy keys need the helper, parity
804
+ * phase P8-D78): reported in status, never silently skipped.
805
+ * minVersion — `claudeCli.ts:13` floor (2.1.288).
806
+ */
807
+ type ClaudePlatform = 'darwin' | 'win32' | 'linux';
808
+ interface ClaudeCodePlatformRow {
809
+ knownBinaries: readonly string[];
810
+ /** `~` = the user's home. Globs are not expanded: a `*.json` directory source is listed via managedSettingsDirs. */
811
+ managedSettings: readonly string[];
812
+ /** Directories whose `*.json` files are managed sources. */
813
+ managedSettingsDirs: readonly string[];
814
+ managedUnscannable: readonly string[];
815
+ /** The user's Claude dir relative to home. */
816
+ userClaudeDir: string;
817
+ }
818
+ declare const CLAUDE_CODE_PLATFORMS: Readonly<Record<ClaudePlatform, ClaudeCodePlatformRow>>;
819
+
820
+ interface DarwinSessionExtras {
821
+ uid: number;
822
+ /** the daemon's TMPDIR (screen's socket dir lives under it) */
823
+ tmpdir: string;
824
+ home: string;
825
+ /** cwd + worktree: their git pointer files / config.worktree / modules are denied */
826
+ roots: readonly string[];
827
+ /** Aegis round 3 H: the ssh-agent sockets the daemon's env names (SSH_AUTH_SOCK), denied by path beside the known ones */
828
+ agentSockets?: readonly string[];
829
+ }
830
+
831
+ type MacosProbe = () => number | null;
832
+ /** true = enabled; false = disabled or partially disabled; null = unknown (fail closed) */
833
+ type SipProbe = () => boolean | null;
834
+
835
+ interface SessionLaunchInput {
836
+ policy: SessionPolicy;
837
+ /** realpath of the driver binary (claude) */
838
+ binaryReal: string;
839
+ argv: string[];
840
+ extras: DarwinSessionExtras;
841
+ /** the session's hsid (win32: its own restricting SID, sessionSidFor) */
842
+ hsid?: string;
843
+ }
844
+ interface SessionLaunchPlan {
845
+ command: string;
846
+ args: string[];
847
+ sandbox: 'full' | 'partial';
848
+ profile: string;
849
+ profileHash: string;
850
+ /** what this launch could not deny (Aegis M1, PR #52): logged on the session.sandbox row, never dropped */
851
+ partial?: readonly string[];
852
+ }
853
+ interface FloorResult {
854
+ ok: boolean;
855
+ /** which floor failed: the macOS major, or System Integrity Protection */
856
+ floor?: 'macos' | 'sip';
857
+ have: number | string | null;
858
+ need: number | string;
859
+ }
860
+ /**
861
+ * The darwin floor (platform data): below SESSION_SANDBOX_MIN_MACOS, or with
862
+ * SIP disabled / partially disabled / unknown, the backend refuses — never a
863
+ * weaker profile. macOS is checked first. `probe`/`sip` are test seams.
864
+ */
865
+ declare function darwinFloor(probe?: MacosProbe, sip?: SipProbe): FloorResult;
866
+ /** Aegis round 2 M6: what the darwin session profile does not deny yet (the egress proxy is 8.1, spec §6.6). */
867
+ declare const NETWORK_EGRESS_PARTIAL = "network:egress open (outbound connections are not limited to localhost; only the Gnomon endpoint port is denied; the egress proxy is 8.1)";
868
+ /** Aegis round 3 H: what the profile cannot stop — a gh token stored in the login keychain is readable with `security`. */
869
+ declare const KEYCHAIN_TOKEN_PARTIAL = "credentials:keychain a gh token in the login keychain is readable with security find-generic-password -s gh:github.com (security is not denied); use gh auth login --insecure-storage (its file is read-denied)";
870
+ /** Platform registry of session sandbox backends (G-WIN-05). */
871
+ declare const SESSION_SANDBOX_BACKENDS: Readonly<Partial<Record<string, (i: SessionLaunchInput, probe?: MacosProbe, sip?: SipProbe) => SessionLaunchPlan>>>;
872
+ /** `probe` reads the OS version and `sip` System Integrity Protection (platform code); tests pass fixed ones to exercise the floor refusals. */
873
+ declare function sessionLaunchPlan(i: SessionLaunchInput, platform?: string, probe?: MacosProbe, sip?: SipProbe): SessionLaunchPlan;
874
+ /** status: the session profile's fidelity on `platform` — full only with a backend and every class full (G-WIN-06). */
875
+ declare function sessionSandboxFidelity(platform?: string, probe?: MacosProbe, sip?: SipProbe): {
876
+ fidelity: 'full' | 'partial' | 'none' | 'unavailable';
877
+ classes: Record<string, string>;
878
+ reason?: string;
879
+ have?: number | string | null;
880
+ need?: number | string;
881
+ };
882
+
883
+ type session_FloorResult = FloorResult;
884
+ declare const session_KEYCHAIN_TOKEN_PARTIAL: typeof KEYCHAIN_TOKEN_PARTIAL;
885
+ declare const session_NETWORK_EGRESS_PARTIAL: typeof NETWORK_EGRESS_PARTIAL;
886
+ declare const session_SESSION_SANDBOX_BACKENDS: typeof SESSION_SANDBOX_BACKENDS;
887
+ type session_SessionLaunchInput = SessionLaunchInput;
888
+ type session_SessionLaunchPlan = SessionLaunchPlan;
889
+ declare const session_darwinFloor: typeof darwinFloor;
890
+ declare const session_sessionLaunchPlan: typeof sessionLaunchPlan;
891
+ declare const session_sessionSandboxFidelity: typeof sessionSandboxFidelity;
892
+ declare namespace session {
893
+ export { session_KEYCHAIN_TOKEN_PARTIAL as KEYCHAIN_TOKEN_PARTIAL, session_NETWORK_EGRESS_PARTIAL as NETWORK_EGRESS_PARTIAL, session_SESSION_SANDBOX_BACKENDS as SESSION_SANDBOX_BACKENDS, session_darwinFloor as darwinFloor, session_sessionLaunchPlan as sessionLaunchPlan, session_sessionSandboxFidelity as sessionSandboxFidelity };
894
+ export type { session_FloorResult as FloorResult, session_SessionLaunchInput as SessionLaunchInput, session_SessionLaunchPlan as SessionLaunchPlan };
895
+ }
896
+
897
+ declare const LAYERS_HASH_SCHEMA: "gnomon-layers:v1";
898
+ declare const GIT_HASH_SCHEMA: "gnomon-git-layers:v1";
899
+ interface HashInput {
900
+ /** `<scope>:<path>`; normalised by normalizeLayerKey. */
901
+ key: string;
902
+ /** null = absent. */
903
+ bytes: Uint8Array | null;
904
+ /** The absolute path read (not hashed; lets the policy test prove every layer is write-denied). */
905
+ abs?: string;
906
+ }
907
+ /** CRLF → LF (A23-4). */
908
+ declare function normalizeContent(b: Uint8Array): Uint8Array;
909
+ /** Posix separators, no `./`, NFC, case-folded. */
910
+ declare function normalizeLayerKey(key: string): string;
911
+ declare function digestInputs(schema: string, inputs: readonly HashInput[]): string;
912
+ interface LayersInput {
913
+ /** The session cwd (project layer). */
914
+ cwd: string;
915
+ /** The session worktree, when it differs from cwd. */
916
+ worktree?: string;
917
+ /** The user's `~/.claude` (platform-resolved by the caller). */
918
+ userClaudeDir: string;
919
+ /** Managed settings files (platform-specific paths, from the caller / root-signed config). */
920
+ managedPaths: readonly string[];
921
+ /** `~/.claude.json` (default: beside userClaudeDir). */
922
+ userClaudeJson?: string;
923
+ /** M1.7: leave ~/.claude.json out (the mid-session watch hashes only its law-7 projection). */
924
+ excludeClaudeJson?: boolean;
925
+ }
926
+ declare function defaultClaudeJson(userClaudeDir: string): string;
927
+ /** The inputs of `layersHash` (exposed for tests and for `session.layers.changed{which}`). */
928
+ declare function collectLayerInputs(inp: LayersInput): HashInput[];
929
+ declare function layersHash(inp: LayersInput): string;
930
+ /** Resolve `<repo>/.git` to {gitDir, commonDir}; a `.git` file (`gitdir: …`) is followed. */
931
+ declare function resolveGitDirs(repo: string): {
932
+ gitDir: string;
933
+ commonDir: string;
934
+ } | null;
935
+ declare function collectGitInputs(repo: string): HashInput[];
936
+ declare function gitHash(repo: string): string;
937
+ declare function gateClassPathRule(relPath: string): string | null;
938
+ /** A gate-class file a loop check may read (the loop config closure): never a directory rule, a memory file or an alias. */
939
+ declare function isClosureName(name: string): boolean;
940
+ /** TD-2026-10-23-268 (Aegis L1): a loop env file may not be named like a config tools run (a `.env*` dotenv is fine). */
941
+ declare function isConfigNamedEnvFile(name: string): boolean;
942
+
943
+ declare const BUNDLED_RUNNER_DIR = "gnomon-local";
944
+ declare const BUNDLED_RUNNER_ENTRY = "cli.js";
945
+ /** The tree hash this build compiled for its bundled runner, or null (no bundled runner in this build). */
946
+ declare function compiledLocalRunnerPin(): string | null;
947
+ type DefaultRunner = {
948
+ ok: true;
949
+ dir: string;
950
+ source: 'bundled';
951
+ treeSha256: string;
952
+ } | {
953
+ ok: true;
954
+ dir: string;
955
+ source: 'clone';
956
+ treeSha256: null;
957
+ } | {
958
+ ok: false;
959
+ why: string;
960
+ };
961
+ /**
962
+ * The default runner dir. `from` is the directory of the running kernel module (dist/ or dist/cli/ in a build,
963
+ * src/kernel/local in tests); `pin` defaults to the compiled one.
964
+ */
965
+ declare function defaultLocalRunner(from?: string, pin?: string | null): DefaultRunner;
966
+ /**
967
+ * The gnomon-local version of a runner dir, for the card and status.local: the compiled one when `tree` is this
968
+ * build's bundled pin; else the `@a-company/gnomon-local` package.json one level up (a clone's dist); else null.
969
+ */
970
+ declare function runnerVersionOf(dir: string, tree: string | null): string | null;
971
+ /** The pinned node's version when it is the kernel's own node (the bundled one in the app), else null (never exec'd to ask). */
972
+ declare function nodeVersionOf(node: string): string | null;
973
+
974
+ declare const bundledRunner_BUNDLED_RUNNER_DIR: typeof BUNDLED_RUNNER_DIR;
975
+ declare const bundledRunner_BUNDLED_RUNNER_ENTRY: typeof BUNDLED_RUNNER_ENTRY;
976
+ type bundledRunner_DefaultRunner = DefaultRunner;
977
+ declare const bundledRunner_compiledLocalRunnerPin: typeof compiledLocalRunnerPin;
978
+ declare const bundledRunner_defaultLocalRunner: typeof defaultLocalRunner;
979
+ declare const bundledRunner_nodeVersionOf: typeof nodeVersionOf;
980
+ declare const bundledRunner_runnerVersionOf: typeof runnerVersionOf;
981
+ declare namespace bundledRunner {
982
+ export { bundledRunner_BUNDLED_RUNNER_DIR as BUNDLED_RUNNER_DIR, bundledRunner_BUNDLED_RUNNER_ENTRY as BUNDLED_RUNNER_ENTRY, bundledRunner_compiledLocalRunnerPin as compiledLocalRunnerPin, bundledRunner_defaultLocalRunner as defaultLocalRunner, bundledRunner_nodeVersionOf as nodeVersionOf, bundledRunner_runnerVersionOf as runnerVersionOf };
983
+ export type { bundledRunner_DefaultRunner as DefaultRunner };
984
+ }
985
+
986
+ /** Aegis H1: every path a session could use to swap the binary the kernel runs next — write-denied. */
987
+ declare function binaryDenies(row: ClaudeCodePlatformRow, userHome: string, sourceReal: string, explicit?: string): PolicyPath[];
988
+
989
+ declare const GENESIS_PREFIX: "gnomon-log-genesis:";
990
+ /** `sha256:<hex>` of a UTF-8 string (node:crypto; same digest as contracts' sha256Tagged). */
991
+ declare function sha256TaggedFast(text: string): string;
992
+ /** prev of seq 1. `logId` is the full `log:<ULID>` id, as in `envelope.log`. */
993
+ declare function genesisPrev(logId: string): string;
994
+ /** The text that is hashed (and stored in `chain.envelope`): canonical(envelope minus hash, sig). */
995
+ declare function hashPreimage(envelope: Record<string, unknown>): string;
996
+ /** Namespaces whose events MUST carry a signature (§3.2, verbatim list). */
997
+ declare const SIG_MANDATORY_NAMESPACES: readonly ["approval", "budget", "permit", "key", "manifest", "config", "billing", "verdict"];
998
+ /**
999
+ * Single kinds whose events MUST carry a signature (§3.2), plus the
1000
+ * integrity rows of the log itself (research 33 S34-06, P8-D83): a stripped
1001
+ * signature on a gap / segment / lag / anchor-failure / socket-theft row would
1002
+ * otherwise pass verify as a "diagnostic".
1003
+ */
1004
+ declare const SIG_MANDATORY_KINDS: readonly ["oracle.result", "daemon.log.gap", "daemon.log.quarantined", "daemon.segment", "daemon.anchor.lag", "daemon.anchor.failed", "socket.auth.theft"];
1005
+ /** Diagnostics that MAY be unsigned (§3.2): the ONLY unsigned rows the log accepts. */
1006
+ declare const DIAGNOSTIC_NAMESPACES: readonly ["daemon", "socket", "schedule"];
1007
+ declare function isSigMandatory(kind: string): boolean;
1008
+ declare function isDiagnostic(kind: string): boolean;
1009
+ /**
1010
+ * May this kind be appended unsigned? Only diagnostics. §3.2 also says
1011
+ * "kernel-appended events are signed by the kernel key" and "every event
1012
+ * appended by a keyed principal" is signed, so outside the three diagnostic
1013
+ * namespaces an unsigned row is refused at append and fails verify — a
1014
+ * superset of the mandatory list (G-LOG-08 tests the mandatory list). The
1015
+ * sig-mandatory diagnostic kinds (daemon.log.gap etc., S34-06) are excluded.
1016
+ */
1017
+ declare function mayBeUnsigned(kind: string): boolean;
1018
+ /**
1019
+ * The labels an append gets: the kind's §9.1 default, optionally TIGHTENED by
1020
+ * the appending component. Relaxing (a lower sensitivity, a wider audience)
1021
+ * is refused; an unregistered kind is refused — never guessed (`G-LOG-09`).
1022
+ */
1023
+ declare function resolveLabels(kind: string, requested?: {
1024
+ audience?: Audience;
1025
+ sensitivity?: Sensitivity;
1026
+ }): EventLabels;
1027
+ /** L7: a kernel appender never writes a userland kind, and vice versa. */
1028
+ declare function assertOwner(kind: string, as: KindOwner): void;
1029
+ type LogRefusalReason = 'unregistered-kind' | 'label-relaxed' | 'kind-owner' | 'unsigned-mandatory' | 'unsigned-kind' | 'bad-envelope' | 'bad-payload' | 'missing-db' | 'anchor-missing' | 'anchor-mismatch' | 'anchor-lag' | 'anchor-failed' | 'truncated' | 'tip-moved' | 'segment-broken' | 'reader-unsupported' | 'reserved-kind' | 'closed' | 'no-gap' | 'presence-required' | 'tamper' | 'unauthenticated-lead' | 'anchor-faulted' | 'rotation-failed' | 'kernel-key-required' | 'not-genesis' | 'not-a-home' | 'nothing-to-quarantine' | 'daemon-running' | 'quarantine-pending' | 'home-busy' | 'install-busy' | 'no-space' | 'not-interactive' | 'not-confirmed';
1030
+ /** A refusal:v1 thrown by the log; `reason` is also in `refusal.data.reason`. */
1031
+ declare class LogRefusal extends RefusedError {
1032
+ readonly reason: LogRefusalReason;
1033
+ constructor(code: RefusalCode, reason: LogRefusalReason, message: string, data?: Record<string, unknown>);
1034
+ }
1035
+ declare function logRefusal(code: RefusalCode, reason: LogRefusalReason, message: string, data?: Record<string, unknown>): LogRefusal;
1036
+
1037
+ declare const HEAD_SCHEMA: "gnomonHead:v1";
1038
+ interface HeadAnchor {
1039
+ schemaVersion: typeof HEAD_SCHEMA;
1040
+ log: string;
1041
+ segment: number;
1042
+ /** 0 = genesis, no row yet; `hash` is then the genesis prev. */
1043
+ seq: number;
1044
+ hash: string;
1045
+ at: string;
1046
+ /** Written only by a clean close (S33-07 clean-close marker); cleared durably on the next open. */
1047
+ closed?: true;
1048
+ /** S33-10: boot session the anchor was written in (`kern.bootsessionuuid` / `boot_id` / `unknown`). Absent on pre-D83 anchors. */
1049
+ boot?: string;
1050
+ }
1051
+ type AnchorReadResult = {
1052
+ state: 'present';
1053
+ head: HeadAnchor;
1054
+ } | {
1055
+ state: 'absent';
1056
+ } | {
1057
+ state: 'unavailable';
1058
+ why: string;
1059
+ } | {
1060
+ state: 'malformed';
1061
+ why: string;
1062
+ };
1063
+ interface AnchorStore {
1064
+ readonly name: 'file' | 'keystore';
1065
+ read(): AnchorReadResult;
1066
+ /** `durable` = fsync before returning (genesis, rotation, close). May be async (helper IPC, P04). */
1067
+ write(head: HeadAnchor, durable: boolean): void | Promise<void>;
1068
+ }
1069
+ declare class FileAnchorStore implements AnchorStore {
1070
+ readonly name: "file";
1071
+ readonly path: string;
1072
+ constructor(home: string);
1073
+ read(): AnchorReadResult;
1074
+ write(head: HeadAnchor, durable: boolean): void;
1075
+ }
1076
+ /**
1077
+ * The helper-backed keystore anchor (`gnomon-head`). SEAM ONLY in PR-4: the
1078
+ * signed helper that owns the Keychain / Credential Manager item does not
1079
+ * exist yet, so reads report `unavailable` and writes are no-ops. Never
1080
+ * falls back to a second file — a second file in the same home would add no
1081
+ * protection against a same-user rewrite (§3.2 scope statement).
1082
+ */
1083
+ declare class KeystoreAnchorStore implements AnchorStore {
1084
+ readonly name: "keystore";
1085
+ read(): AnchorReadResult;
1086
+ write(): void;
1087
+ }
1088
+ /** fsync a file by path (Windows: an 'r+' handle, which FlushFileBuffers requires). */
1089
+ declare function fsyncFile(file: string): void;
1090
+ /** True for an error that only says the directory fsync is unsupported (S34-28). */
1091
+ declare function isBenignDirFsyncError(err: unknown): boolean;
1092
+ /**
1093
+ * fsync a directory so a rename inside it is durable. Skipped on win32 (see
1094
+ * the seam note above). On POSIX an unsupported directory fsync is a no-op
1095
+ * (isBenignDirFsyncError); every other error — EIO above all — is rethrown.
1096
+ */
1097
+ declare function fsyncDir(dir: string): void;
1098
+
1099
+ /**
1100
+ * @symbol #kernel-log
1101
+ *
1102
+ * #kernel-log (spec §3.2; research 33 S33-05..S33-07, S33-10; P8-D82, P8-D83) — the head-anchor
1103
+ * WRITE POLICY: when the file anchor and the keystore anchor are written, which
1104
+ * kinds force both anchors before `append` resolves, and the lag bounds that
1105
+ * open() enforces. Pure constants and predicates; kernel-log.ts applies them.
1106
+ *
1107
+ * Measured basis (probes/p-log-fsync, research 33 table): a tmp+rename after
1108
+ * every commit (arm B) leaves dirty APFS metadata that the next WAL fsync must
1109
+ * flush — 0.94 % of appends over 5 ms. Coalescing to 1 rename per 64 rows
1110
+ * (arm D) or per 50 ms (arm E) is indistinguishable from raw SQLite (arm A).
1111
+ *
1112
+ * Off-by-one, stated: the commit and the anchor write are not atomic, so a
1113
+ * crash right after the commit that triggers an anchor leaves lag = trigger.
1114
+ * The spec's open bound is "lag > 63 ⇒ INTEGRITY_BROKEN", so the in-path
1115
+ * trigger fires when the un-anchored row count REACHES 63 (rename rate 1/63,
1116
+ * ≈ arm D's 1/64). Same for the keystore: trigger at 1023, bound 1023.
1117
+ */
1118
+ /** S33-07: open refuses INTEGRITY_BROKEN{anchor-lag} when the file anchor lags by more than this. */
1119
+ declare const FILE_ANCHOR_MAX_LAG = 63;
1120
+ /** S33-05: file anchor written within this many ms of the first un-anchored row (unref'd timer). */
1121
+ declare const FILE_ANCHOR_MAX_MS = 50;
1122
+ /** S33-07: keystore lag above this on open ⇒ a kernel-signed `daemon.anchor.lag{rows, which}`. */
1123
+ declare const KEYSTORE_ANCHOR_MAX_LAG = 1023;
1124
+ /** S33-05: keystore anchor written (async, off the append path) within this many ms. Provisional until P04. */
1125
+ declare const KEYSTORE_ANCHOR_MAX_MS = 1000;
1126
+ /** S33-06 telemetry: forcedAnchorRate is computed over this many most recent rows. */
1127
+ declare const FORCED_ANCHOR_WINDOW = 10000;
1128
+ /** S33-06: above this forced-anchor rate the bulk p99 is outside the measured envelope (arm D). */
1129
+ declare const FORCED_ANCHOR_ENVELOPE: number;
1130
+ /**
1131
+ * S33-06 — the CRITICAL kinds (research 33, "The list"). A critical append
1132
+ * commits (bulk durability — no F_FULLFSYNC since S33-10 / P8-D83), renames
1133
+ * the file anchor in and awaits the keystore anchor, in that order, and only
1134
+ * then resolves; no effect of the event may be released before the promise
1135
+ * resolves. That is an ordering guarantee against a same-user process, not a
1136
+ * power-loss guarantee (an anchor ahead of the db after a power loss is
1137
+ * classified on open, kernel-log.ts).
1138
+ *
1139
+ * Deviations from the spec list, stated:
1140
+ * - `manifest.*` "(decisions)": the whole manifest namespace is treated as
1141
+ * critical (conservative; every manifest kind is a human-speed event).
1142
+ * - `grant.*`: no `grant` namespace is registered in contracts yet
1143
+ * (permit.grant / request.grant are other namespaces); the prefix is kept
1144
+ * so a future `grant.*` kind is critical on registration.
1145
+ * - `link.*` (pair/renew/revoke) maps to the registered kinds
1146
+ * link.pair.offered, link.paired, link.renewed, link.revoked.
1147
+ * - `approval.rule.revoked` (P8-D98, Aegis M1) is added beside
1148
+ * `approval.rule.learned`: a lost revoke silently widens permission
1149
+ * (the rule comes back), so it is anchored like the learn it undoes.
1150
+ * - `approval.rule.disabled` (8.0:rules-view) likewise: a lost "off" silently
1151
+ * turns the rule back on. (`approval.rule.enabled` is not critical: a lost
1152
+ * one leaves the rule off, the narrow side.)
1153
+ */
1154
+ declare const CRITICAL_ANCHOR_KINDS: Readonly<{
1155
+ ref: "research 33 S33-06 (P8-D82)";
1156
+ kinds: readonly ["approval.decide", "approval.suspect", "approval.presence.denied", "approval.rule.learned", "approval.rule.revoked", "approval.rule.disabled", "approval.voice.arm", "approval.voice.disarm", "link.pair.offered", "link.paired", "link.renewed", "link.revoked", "socket.auth.theft"];
1157
+ namespaces: readonly ["key", "grant", "config", "manifest", "billing", "verdict"];
1158
+ /** Kinds critical only for some payloads: session.inject{origin:'peer'} (L2 for peer bytes). */
1159
+ byPayload: Readonly<{
1160
+ 'session.inject': Readonly<{
1161
+ field: "origin";
1162
+ equals: "peer";
1163
+ }>;
1164
+ }>;
1165
+ }>;
1166
+ /** Is this (kind, payload) a S33-06 critical append? */
1167
+ declare function isCriticalKind(kind: string, payload?: unknown): boolean;
1168
+
1169
+ declare const BOOT_UNKNOWN: "unknown";
1170
+ /** Validate a raw boot id: trimmed UUID, else `unknown`. */
1171
+ declare function normalizeBootId(raw: string): string;
1172
+ /**
1173
+ * The current boot session id (`kern.bootsessionuuid` / `boot_id`), or
1174
+ * `unknown`. A real id is cached per process; `unknown` is NOT cached (a
1175
+ * transient sysctl failure is retried on the next open; the log emits an
1176
+ * onDiagnostic `boot.unknown`).
1177
+ */
1178
+ declare function readBootSession(): string;
1179
+
1180
+ type ReaderClass = {
1181
+ class: 'human';
1182
+ } | {
1183
+ class: 'read-token';
1184
+ } | {
1185
+ class: 'community-client';
1186
+ } | {
1187
+ class: 'session';
1188
+ hsid: string;
1189
+ } | {
1190
+ class: 'mod';
1191
+ name: string;
1192
+ grantedKinds?: readonly string[];
1193
+ } | {
1194
+ class: 'peer';
1195
+ } | {
1196
+ class: 'agent';
1197
+ } | {
1198
+ class: 'voice';
1199
+ hsid?: string | null;
1200
+ };
1201
+ /** `{kind, hsid, at, hash}` — what a redacting reader gets for a sensitive-column row (§9.3). */
1202
+ interface LogStub {
1203
+ kind: string;
1204
+ hsid?: string;
1205
+ at: string;
1206
+ /** Present only in a full-class reader's stub (never for limited views). */
1207
+ hash?: string;
1208
+ }
1209
+ /** A projected event: limited views omit hash, sig, prev, idem and refHash. */
1210
+ type ProjectedEvent = Omit<EventV1, 'hash' | 'sig' | 'prev' | 'idem' | 'refHash'> & Partial<Pick<EventV1, 'hash' | 'sig' | 'prev' | 'idem' | 'refHash'>>;
1211
+ type LogView = {
1212
+ seq: number;
1213
+ view: 'full';
1214
+ event: ProjectedEvent;
1215
+ } | {
1216
+ seq: number;
1217
+ view: 'stub';
1218
+ stub: LogStub;
1219
+ };
1220
+ interface RedactedField {
1221
+ redacted: true;
1222
+ }
1223
+ /** Projection counter (tests: per-commit fan-out must not project). */
1224
+ declare const projectionStats: {
1225
+ calls: number;
1226
+ };
1227
+ /** The strictest of the registered default, the envelope label and the stored column label (never widens). */
1228
+ declare function effectiveSensitivity(e: Pick<EventV1, 'kind' | 'sensitivity'>, storedLabel?: string): Sensitivity;
1229
+ declare const SESSION_NEVER_FIELDS: ReadonlyArray<{
1230
+ kind: (k: string) => boolean;
1231
+ field: string;
1232
+ when?: (p: Record<string, unknown>) => boolean;
1233
+ }>;
1234
+ /**
1235
+ * Could `reader` see this row at all? Metadata only (kind, labels, session) —
1236
+ * no projection, no copy, no hash: the subscription fan-out on the commit path
1237
+ * uses it to decide whether to wake a pump. Over-approximates nothing that
1238
+ * projectForReader would show; it may say yes for rows a scope filter drops.
1239
+ */
1240
+ declare function mayBeVisible(e: Pick<EventV1, 'kind' | 'sensitivity' | 'session'>, reader: ReaderClass): boolean;
1241
+ /**
1242
+ * Project one row for one reader. `undefined` = the reader does not see the
1243
+ * row at all. A projected (field-redacted) event no longer hashes to its
1244
+ * `hash`; it is a view, the chain row is untouched.
1245
+ */
1246
+ declare function projectForReader(e: EventV1, reader: ReaderClass, storedLabel?: string): LogView | undefined;
1247
+
1248
+ declare const DEFAULT_SEGMENT_ROWS = 1000000;
1249
+ declare const SEGMENT_SCHEMA: "gnomonLogSegment:v1";
1250
+ declare const ACTIVE_DB = "kernel.db";
1251
+ declare const SEGMENTS_DIR: string;
1252
+ type Durability = 'process-crash' | 'power-loss';
1253
+ interface KernelLogOptions {
1254
+ /** The Gnomon home (`~/.gnomon`), already created 0700 by $daemon-lifecycle. */
1255
+ home: string;
1256
+ /** The kernel principal `p:<ns>/kernel` — appender of daemon.segment rows. */
1257
+ kernelPrincipal: string;
1258
+ /** The kernel key. `null` = no key loaded: only diagnostics can be appended. */
1259
+ signer: Signer | null;
1260
+ /** Public keys for verify; the signer's own key is added automatically. */
1261
+ keyRing?: KeyRing;
1262
+ segmentRows?: number;
1263
+ durability?: Durability;
1264
+ /** Keys exist on this machine (M1.3 supplies it): a missing db is then INTEGRITY_BROKEN, never a fresh genesis. */
1265
+ keysPresent?: boolean;
1266
+ /** S34-23 test seam: file-anchor coalescing window in ms (default FILE_ANCHOR_MAX_MS). */
1267
+ fileAnchorMaxMs?: number;
1268
+ /** S34-11: per-write keystore anchor timeout, measured from DEQUEUE (default KEYSTORE_WRITE_TIMEOUT_MS). */
1269
+ keystoreTimeoutMs?: number;
1270
+ /** Earlier kernel key ids (rotated keys) accepted on kernel-principal rows at verify; the signer's own key is added. */
1271
+ kernelKeyIds?: readonly string[];
1272
+ clock?: () => number;
1273
+ /** PASSIVE WAL checkpoint after this many ms without an append (default 250). */
1274
+ checkpointIdleMs?: number;
1275
+ /** Hard WAL bound: inline PASSIVE checkpoint every N appends (default 20 000). */
1276
+ checkpointEvery?: number;
1277
+ onDiagnostic?: (d: {
1278
+ what: string;
1279
+ detail: Record<string, unknown>;
1280
+ }) => void;
1281
+ }
1282
+ interface AppendInput {
1283
+ kind: string;
1284
+ principal: string;
1285
+ payload?: unknown;
1286
+ session?: string;
1287
+ connId?: string;
1288
+ deviceId?: string;
1289
+ idem?: string;
1290
+ scope?: EventScopeV1;
1291
+ causes?: string[];
1292
+ ref?: string;
1293
+ refHash?: string;
1294
+ /** Tighten only (L6). Omitted = the §9.1 default for the kind. */
1295
+ audience?: Audience;
1296
+ sensitivity?: Sensitivity;
1297
+ /** Which side appends (L7). Default 'kernel'. */
1298
+ as?: KindOwner;
1299
+ /** Override the signer for this row (e.g. a hardware key later); `null` = unsigned (diagnostics only). */
1300
+ signer?: Signer | null;
1301
+ }
1302
+ type AnchorState = 'ok' | 'lagging-repaired' | 'created' | 'unavailable' | 'ahead';
1303
+ /** S34-03: how a critical row was anchored — `file-only` while the keystore anchor is the unavailable stub (until M1.3). */
1304
+ type Anchoring = 'both' | 'file-only';
1305
+ /** Default per-write keystore anchor timeout (S34-11). */
1306
+ declare const KEYSTORE_WRITE_TIMEOUT_MS = 5000;
1307
+ /** S33-10: why an anchor is ahead of the db. Classifies, never downgrades: both are INTEGRITY_BROKEN{truncated}. */
1308
+ type TruncationCause = 'tamper' | 'unclean-reboot';
1309
+ /** An anchor ahead of the db (S33-10), as found on open. */
1310
+ interface TruncationReport {
1311
+ cause: TruncationCause;
1312
+ /** Which anchor was ahead (the keystore anchor wins when both are). */
1313
+ anchor: 'file' | 'keystore';
1314
+ /** First and last lost seq; `lostHash` is the anchor's hash for row `lostTo`. */
1315
+ lostFrom: number;
1316
+ lostTo: number;
1317
+ lostHash: string;
1318
+ /** The authoritative (keystore) anchor's boot session, `unknown` if none/unreadable. */
1319
+ bootPrev: string;
1320
+ bootNow: string;
1321
+ /** The authoritative anchor was written by a clean close. */
1322
+ cleanClose: boolean;
1323
+ /** Which anchors are ahead of the db (S34-04 / report nit). */
1324
+ ahead: {
1325
+ file: boolean;
1326
+ keystore: boolean;
1327
+ };
1328
+ /**
1329
+ * S34-24: rows the FILE anchor lags the db by while the keystore anchor is
1330
+ * ahead (0 when the file anchor is ahead or exact). Not bounded by the > 63
1331
+ * file-anchor bound here: the keystore anchor classifies the truncation.
1332
+ */
1333
+ fileLag: number;
1334
+ /**
1335
+ * S34-04: only the FILE anchor leads while a keystore anchor is present and
1336
+ * not ahead — the lead is unauthenticated (a same-user process can write the
1337
+ * file anchor), so acknowledgeGap refuses FORBIDDEN{unauthenticated-lead}.
1338
+ */
1339
+ unauthenticatedLead: boolean;
1340
+ }
1341
+ /** Live integrity state (S34-14): `report.integrity` is the open-time snapshot, `log.integrity` is now. */
1342
+ type LogIntegrity = {
1343
+ state: 'ok';
1344
+ } | ({
1345
+ state: 'truncated';
1346
+ } & TruncationReport) | {
1347
+ state: 'anchor-faulted';
1348
+ failed: FaultEntry[];
1349
+ };
1350
+ /** A critical row whose anchoring failed after COMMIT; `markerSeq` = its committed daemon.anchor.failed row. */
1351
+ interface FaultEntry {
1352
+ seq: number;
1353
+ kind: string;
1354
+ recorded: boolean;
1355
+ markerSeq?: number;
1356
+ }
1357
+ /** What `close()` resolves to (S34-12): a failed clean-close keystore write is surfaced, never swallowed. */
1358
+ interface CloseReport {
1359
+ keystore: 'ok' | 'failed' | 'skipped-truncated';
1360
+ error?: string;
1361
+ /** S34-17: anchor-fault outcome — `recovered` = markers recorded and anchored by the closing anchors. */
1362
+ fault: 'none' | 'recovered' | 'pending';
1363
+ }
1364
+ interface OpenReport {
1365
+ logId: string;
1366
+ created: boolean;
1367
+ recoveredRotation: boolean;
1368
+ /** Rows the file anchor lagged the db by at open (crash between commit and anchor write; ≤ 63, or > 63 relaxed across a boot change with a daemon.anchor.lag{which: 'file'} row (P8-D85), or refused). */
1369
+ anchorLag: number;
1370
+ /** Rows the keystore anchor lagged by at open (> 1023 ⇒ a daemon.anchor.lag row was appended). */
1371
+ keystoreLag: number;
1372
+ anchors: {
1373
+ file: AnchorState;
1374
+ keystore: AnchorState;
1375
+ };
1376
+ /** The boot session this open recorded into every anchor (S33-10). */
1377
+ boot: string;
1378
+ /** `ok`, or (only via `openForRecovery`) the truncation the log refuses appends for. */
1379
+ integrity: {
1380
+ state: 'ok';
1381
+ } | ({
1382
+ state: 'truncated';
1383
+ } & TruncationReport);
1384
+ }
1385
+ /**
1386
+ * What `append` resolves to. `anchored` (S34-03): `false` for bulk rows; for
1387
+ * critical kinds (S33-06) `'both'` = file + keystore anchors written before
1388
+ * resolving, `'file-only'` = the keystore anchor is the unavailable stub.
1389
+ */
1390
+ interface AppendResult {
1391
+ seq: number;
1392
+ hash: string;
1393
+ anchored: false | Anchoring;
1394
+ event: EventV1;
1395
+ }
1396
+ /** `status.log` anchor telemetry (S33-06). */
1397
+ interface AnchorStatus {
1398
+ /** Forced (critical) anchors per row over the last ≤ 10⁴ rows. */
1399
+ forcedAnchorRate: number;
1400
+ /** false ⇒ forcedAnchorRate > 1/64: bulk p99 is outside the measured envelope; re-probe. */
1401
+ withinEnvelope: boolean;
1402
+ /** Rows committed since the last file anchor write / the last CONFIRMED (resolved) keystore anchor write (S34-15). */
1403
+ fileLag: number;
1404
+ keystoreLag: number;
1405
+ /** S34-03: `file-only` while the keystore anchor is unavailable (stub). */
1406
+ anchoring: Anchoring;
1407
+ /** S34-02: true while critical appends must re-anchor first (see `integrity`). */
1408
+ faulted: boolean;
1409
+ fileAnchors: number;
1410
+ keystoreAnchors: number;
1411
+ forcedAnchors: number;
1412
+ checkpoints: number;
1413
+ }
1414
+ interface SegmentInfo {
1415
+ segment: number;
1416
+ file: string;
1417
+ baseSeq: number;
1418
+ basePrev: string;
1419
+ /** baseSeq - 1 when empty. */
1420
+ lastSeq: number;
1421
+ lastHash: string;
1422
+ lastKind: string | null;
1423
+ sealed: boolean;
1424
+ }
1425
+ type VerifyFailureCode = 'seq-gap' | 'envelope' | 'hash' | 'prev' | 'log' | 'column-mismatch' | 'sig' | 'unknown-key' | 'unsigned' | 'unregistered-kind' | 'label-relaxed' | 'meta' | 'segment-link' | 'segment-unsealed' | 'anchor' | 'kernel-key' | 'reserved-binding';
1426
+ interface VerifyFailure {
1427
+ code: VerifyFailureCode;
1428
+ segment: number;
1429
+ seq?: number;
1430
+ detail: string;
1431
+ }
1432
+ interface VerifyReport {
1433
+ ok: boolean;
1434
+ rows: number;
1435
+ segments: Array<{
1436
+ segment: number;
1437
+ firstSeq: number;
1438
+ lastSeq: number;
1439
+ rows: number;
1440
+ ok: boolean;
1441
+ }>;
1442
+ failures: VerifyFailure[];
1443
+ /**
1444
+ * S34-18: were kernel rows (reserved kinds, kernel principal) bound to the
1445
+ * kernel identity? `not-checked` when verify ran without it (standalone
1446
+ * verifyLog without kernelPrincipal/kernelKeyIds) — `ok` alone then says
1447
+ * nothing about who wrote the log's own rows.
1448
+ */
1449
+ kernelBinding: 'ok' | 'failed' | 'not-checked';
1450
+ anchors: {
1451
+ file: 'ok' | 'lagging' | 'mismatch' | 'missing' | 'not-checked';
1452
+ keystore: 'ok' | 'lagging' | 'unavailable' | 'mismatch' | 'not-checked';
1453
+ };
1454
+ }
1455
+ /** List sealed segment files, ascending. */
1456
+ declare function listSealedSegments(home: string): Array<{
1457
+ segment: number;
1458
+ file: string;
1459
+ }>;
1460
+ declare class KernelLog {
1461
+ #private;
1462
+ readonly home: string;
1463
+ readonly logId: string;
1464
+ readonly report: OpenReport;
1465
+ private constructor();
1466
+ /**
1467
+ * Open (or, on a machine with no log, no anchor and no keys, create) the
1468
+ * kernel log. Production only: the keystore anchor is the store the kernel
1469
+ * builds itself and the boot session is read from the OS.
1470
+ */
1471
+ static open(opts: KernelLogOptions): KernelLog;
1472
+ /**
1473
+ * T-2026-10-17-009(a) — the successor log of a quarantined home. `opts.home`
1474
+ * must hold NO log (no db, no anchor, no segment): the log is created and
1475
+ * its genesis row (seq 1) is the kernel-signed reserved
1476
+ * `daemon.log.quarantined{quarantinedLog, quarantinedHead, evidencePath,
1477
+ * authorizedBy}`, then both anchors are written durably. This is the ONLY
1478
+ * way that kind is appended (append() refuses it as reserved, and verify
1479
+ * flags it anywhere but seq 1), so it can never be appended to, or
1480
+ * downgrade, an existing log. Refused: an existing log
1481
+ * (BAD_REQUEST{not-genesis}); no kernel key (FORBIDDEN{kernel-key-required}).
1482
+ * The caller (quarantine.ts) closes the returned log.
1483
+ */
1484
+ static createQuarantineSuccessor(opts: KernelLogOptions, payload: QuarantinedPayload): Promise<KernelLog>;
1485
+ get activePath(): string;
1486
+ get keyRing(): KeyRing;
1487
+ /** The `at` of the chain's last event (S-L2: the fuse's day windows), `''` on an empty chain. */
1488
+ lastEventAt(): string;
1489
+ /** Is this one of the kernel's signing keys (current or recorded)? */
1490
+ isKernelKey(keyId: string): boolean;
1491
+ /** `{log, segment, seq, hash}` of the chain head. */
1492
+ head(): {
1493
+ log: string;
1494
+ segment: number;
1495
+ seq: number;
1496
+ hash: string;
1497
+ };
1498
+ /** S33-06 telemetry (`status.log.forcedAnchorRate`): forced anchors per row over the last ≤ 10⁴ rows. */
1499
+ get forcedAnchorRate(): number;
1500
+ /** The `status.log` anchor block (S33-06/07). */
1501
+ get anchorStatus(): AnchorStatus;
1502
+ /**
1503
+ * Append one event. The commit is durable per the durability policy before
1504
+ * the promise resolves — so a caller that must log BEFORE acting (L2,
1505
+ * `session.inject` before the child reads, G-LOG-03) sequences on it.
1506
+ *
1507
+ * Critical kinds (CRITICAL_ANCHOR_KINDS, S33-06/S33-10) resolve only after
1508
+ * the commit, the file-anchor rename and the keystore anchor write have
1509
+ * completed, in that order: `{anchored: 'both' | 'file-only'}`. The commit
1510
+ * uses the bulk durability (no F_FULLFSYNC, P8-D83): this orders the anchor
1511
+ * before any effect against a same-user process; it is not a power-loss
1512
+ * guarantee. NO EFFECT of a critical event (tool release, card result,
1513
+ * grant) may be released before this resolves. Any failure after COMMIT
1514
+ * rejects ENGINE{anchor-failed} (the row is committed but must be treated
1515
+ * as not having happened) and faults the log (S34-02, header).
1516
+ *
1517
+ * The first append after open waits for the keystore re-stamp (S34-01).
1518
+ */
1519
+ append(input: AppendInput): Promise<AppendResult>;
1520
+ /** PASSIVE WAL checkpoint (never blocks on readers); also renames in a pending file anchor (S33-05 "on idle checkpoint"). */
1521
+ checkpoint(): void;
1522
+ /** Write both anchors for the current head now and wait for the keystore write (daemon shutdown paths, tests). */
1523
+ flushAnchors(): Promise<void>;
1524
+ /** Every segment, sealed first, then the active one. */
1525
+ segments(): SegmentInfo[];
1526
+ /**
1527
+ * Rows in seq order, projected for `reader` (audience/sensitivity, §9.3).
1528
+ * Rows the reader may not see are skipped; sensitive-column rows reach
1529
+ * redacting readers as `{kind, hsid, at, hash}` stubs.
1530
+ */
1531
+ read(opts: {
1532
+ reader: ReaderClass;
1533
+ fromSeq?: number;
1534
+ toSeq?: number;
1535
+ kinds?: readonly string[];
1536
+ limit?: number;
1537
+ }): Generator<LogView>;
1538
+ /**
1539
+ * RELEASED HEAD (D83 ordering, M1.4 slice 2 round 2): the highest seq with
1540
+ * no unresolved critical row at or below it. A critical row is committed
1541
+ * before its anchors resolve; until they do, neither it nor any later row
1542
+ * is readable or streamed. It advances when the critical append's anchors
1543
+ * resolve (success) or fail — a failed row is then FAILED: withheld from
1544
+ * every read (its daemon.anchor.failed marker row is the visible record).
1545
+ */
1546
+ releasedHead(): number;
1547
+ /**
1548
+ * M1.4 slice 2 read primitive (cursor paging + subscriptions). Scans rows
1549
+ * with `afterSeq < seq <= min(untilSeq, releasedHead())` in seq order, at
1550
+ * most `maxScan` of them. Per row: FAILED seqs (anchoring failed) are
1551
+ * skipped; for a non-human reader the projection runs FIRST (a row the
1552
+ * reader cannot see costs no hash and leaves no integrity signal); then the
1553
+ * envelope is RE-HASHED against its stored hash, its seq/kind/id checked
1554
+ * against the columns, and its `prev` checked against the previous row's
1555
+ * hash (linkage across contiguous rows; the page start is checked against
1556
+ * the stored hash of row afterSeq). A failing row is withheld from every
1557
+ * reader and counted. RESIDUAL: a same-user writer who rewrites a row AND
1558
+ * every later row's prev/hash consistently passes these checks — only
1559
+ * signature verification (kernel key) would catch it; that writer can read
1560
+ * kernel.db directly anyway, so it widens nothing for socket principals.
1561
+ * `visit` returns false to stop AFTER consuming that row; `lastScanned` is
1562
+ * the seq to resume after (stable: seqs are immutable).
1563
+ */
1564
+ readPage(opts: {
1565
+ reader: ReaderClass;
1566
+ afterSeq: number;
1567
+ untilSeq?: number;
1568
+ maxScan: number;
1569
+ kinds?: ReadonlySet<string> | ((kind: string) => boolean);
1570
+ match?: (v: LogView) => boolean;
1571
+ visit: (v: LogView) => boolean;
1572
+ }): {
1573
+ lastScanned: number;
1574
+ scanned: number;
1575
+ withheld: number;
1576
+ head: number;
1577
+ caughtUp: boolean;
1578
+ };
1579
+ /**
1580
+ * `ev:<ULID>` lookup (#ref-resolver, §3.7). `undefined` = no such row, the
1581
+ * reader may not see it, it is above the released head, or its anchoring
1582
+ * failed — one answer, no existence oracle. Visibility is decided BEFORE
1583
+ * the hash check, so `'withheld'` (hash/column mismatch) is only ever
1584
+ * returned for a row the reader could otherwise see.
1585
+ */
1586
+ getById(id: string, reader: ReaderClass): LogView | 'withheld' | undefined;
1587
+ /**
1588
+ * Observe every committed row (read-side tail for #socket subscriptions).
1589
+ * Called synchronously after COMMIT, in seq order, BEFORE the row is
1590
+ * released (a committed critical row may still be unreadable); a listener
1591
+ * must not append re-entrantly (defer) and its exceptions never reach the
1592
+ * appender. Pair with onRelease to learn when rows become readable.
1593
+ */
1594
+ onCommit(listener: (e: EventV1) => void): () => void;
1595
+ /** Called with the new releasedHead() whenever a critical row's anchoring resolves (or fails). */
1596
+ onRelease(listener: (head: number) => void): () => void;
1597
+ /** The truncation this (recovery-mode) log refuses appends for, if any. */
1598
+ get truncation(): TruncationReport | undefined;
1599
+ /** S34-14: the LIVE integrity state (`report.integrity` is the open-time snapshot). */
1600
+ get integrity(): LogIntegrity;
1601
+ /** `gnomon log verify`: the full chain (every segment + both anchors), or one segment. */
1602
+ verify(opts?: {
1603
+ segment?: number;
1604
+ }): VerifyReport;
1605
+ /**
1606
+ * Clean close: both anchors durably, carrying the clean-close marker
1607
+ * (S33-07; the keystore copy is the authoritative one, S34-05), then a
1608
+ * TRUNCATE checkpoint. The db work is synchronous; the returned promise
1609
+ * resolves when the keystore write settles and REPORTS a failed write
1610
+ * (S34-12) — `{keystore: 'failed', error}` — instead of swallowing it. A
1611
+ * truncated (recovery-mode) log writes no anchor: `skipped-truncated`. An
1612
+ * anchor-faulted log first commits any pending daemon.anchor.failed markers;
1613
+ * `fault` reports whether the closing anchors cleared the fault (S34-17).
1614
+ */
1615
+ close(): Promise<CloseReport>;
1616
+ }
1617
+ /** Kinds only the log itself appends (rotation, open, recovery, anchor faults); verify binds them to the kernel identity (S34-18). */
1618
+ declare const RESERVED_KINDS: readonly string[];
1619
+ /** T-2026-10-17-009(a): the reserved kind that may only be a log's GENESIS row (seq 1): the successor of a quarantined home. */
1620
+ declare const QUARANTINE_GENESIS_KIND: "daemon.log.quarantined";
1621
+ /** daemon.log.quarantined payload (contracts RESERVED_KIND_PAYLOADS, P8-D89). `evidencePath` is a sensitive field label. */
1622
+ interface QuarantinedPayload {
1623
+ quarantinedLog: string;
1624
+ quarantinedHead: {
1625
+ seq: number;
1626
+ hash: string;
1627
+ segment: number;
1628
+ };
1629
+ evidencePath: string;
1630
+ /** How the human was proved: `interactive-confirm` (a TTY confirmation) until presence lands (M1.3). */
1631
+ authorizedBy: 'interactive-confirm';
1632
+ }
1633
+ interface VerifyLogOptions {
1634
+ keyRing: KeyRing;
1635
+ segment?: number;
1636
+ kernelPrincipal?: string;
1637
+ kernelKeyIds?: readonly string[];
1638
+ /**
1639
+ * Called once per row, in seq order, with the exact bytes this pass checked
1640
+ * (M1.12 replay folds inside verify's single pass, Aegis C2). A consumer
1641
+ * must discard what it saw unless the report is `ok`.
1642
+ */
1643
+ onRow?: (row: VerifiedRow) => void;
1644
+ }
1645
+ /** A row as verify read it (the bytes its checks ran on). */
1646
+ interface VerifiedRow {
1647
+ seq: number;
1648
+ kind: string;
1649
+ envelope: string;
1650
+ hash: string;
1651
+ }
1652
+ declare function verifyLog(home: string, opts: VerifyLogOptions): VerifyReport;
1653
+
1654
+ declare const QUARANTINE_JOURNAL = "quarantine-journal.json";
1655
+ declare const QUARANTINE_JOURNAL_SCHEMA: "gnomonQuarantineJournal:v1";
1656
+ /** Crash points of the move, in order (the test seam injects a crash after each). */
1657
+ declare const QUARANTINE_STEPS: readonly ["identity-read", "staging-created", "staged", "evidence-renamed", "moved", "installed"];
1658
+ type QuarantineStep = (typeof QUARANTINE_STEPS)[number];
1659
+ interface QuarantineOptions {
1660
+ /** The Gnomon home to quarantine (absolute). */
1661
+ home: string;
1662
+ /** The NEW log's kernel key (the genesis row is signed by it; its public half is recorded in the new home). */
1663
+ signer: Signer | null;
1664
+ /** The kernel principal for the new log (`p:<ns>/kernel`, from the same root authority as the daemon). */
1665
+ kernelPrincipal: string;
1666
+ /** How the human was proved; only `interactive-confirm` (no proof of presence) until M1.3. */
1667
+ authorizedBy: QuarantinedPayload['authorizedBy'];
1668
+ /** The daemon socket path, for the liveness check alongside the pidfile. */
1669
+ socketPath?: string;
1670
+ clock?: () => number;
1671
+ }
1672
+ type HeadSource = 'db' | 'segment' | 'file-anchor' | 'keystore-anchor';
1673
+ interface ObservedHead {
1674
+ source: HeadSource;
1675
+ log: string;
1676
+ seq: number;
1677
+ hash: string;
1678
+ segment: number;
1679
+ }
1680
+ /** The quarantined log as found. `head` is the HIGHEST observed seq; `observed` lists every source. */
1681
+ interface QuarantineIdentity {
1682
+ log: string;
1683
+ head: {
1684
+ seq: number;
1685
+ hash: string;
1686
+ segment: number;
1687
+ };
1688
+ source: HeadSource;
1689
+ observed: ObservedHead[];
1690
+ /** The sources disagree (seq, hash or log id): e.g. a truncated db behind its anchor. */
1691
+ disagree: boolean;
1692
+ /** Sources present but unreadable (copy or open failed) — shown, never silently dropped. */
1693
+ unreadable: Array<{
1694
+ source: 'db' | 'segment';
1695
+ reason: string;
1696
+ }>;
1697
+ }
1698
+ type QuarantineReport = {
1699
+ outcome: 'quarantined';
1700
+ home: string;
1701
+ evidencePath: string;
1702
+ evidenceName: string;
1703
+ quarantined: QuarantineIdentity;
1704
+ newLogId: string;
1705
+ genesis: {
1706
+ seq: number;
1707
+ hash: string;
1708
+ };
1709
+ /** `another-process`: the step-5 rename found staging gone — a daemon start installed it (completePendingQuarantine). */
1710
+ installedBy: 'this' | 'another-process';
1711
+ /** Abandoned (incomplete, unverifiable or pre-move) staging dirs left in place. */
1712
+ abandoned: string[];
1713
+ } | {
1714
+ outcome: 'completed-pending';
1715
+ home: string;
1716
+ evidencePath: string;
1717
+ evidenceName: string;
1718
+ newLogId: string;
1719
+ staging: string;
1720
+ abandoned: string[];
1721
+ };
1722
+ interface PendingQuarantine {
1723
+ /** A staging dir installed as the home by this call (a crash between the two renames). */
1724
+ completed: {
1725
+ staging: string;
1726
+ evidence: string;
1727
+ newLog: string;
1728
+ } | null;
1729
+ /** Staging dirs that never became a home (left in place, never deleted), with why. */
1730
+ abandoned: string[];
1731
+ /** A valid journal names this home while the home AND its evidence both exist. */
1732
+ conflict: string | null;
1733
+ /** Our own lock pidfile left in the evidence by a crash between the step-4 rename and its release (reported, never deleted). */
1734
+ lockResidue: string | null;
1735
+ }
1736
+ /** Test seam (internal test entry only): replace the step-4/5 renames to simulate EPERM etc. */
1737
+ interface QuarantineFsOps {
1738
+ rename(from: string, to: string): void;
1739
+ }
1740
+ /** `<base>.quarantine-<YYYYMMDDTHHMMSSZ>-<8 hex>`: valid on every platform (no Windows-reserved character, no trailing dot/space). */
1741
+ declare function evidenceNameFor(base: string, at: Date, rand?: string): string;
1742
+ /**
1743
+ * Finish a quarantine interrupted between its two renames (evidence present,
1744
+ * home absent, staging complete and verified). Run before anything creates a home.
1745
+ */
1746
+ declare function completePendingQuarantine(home: string): PendingQuarantine;
1747
+ /**
1748
+ * The quarantined log's id and head from every source, without writing
1749
+ * anything in the home. The keystore anchor is per OS USER, not per home
1750
+ * (spec §22 OPEN 19): it is consulted only for the default home (`keystore`
1751
+ * defaults to `home` === resolveGnomonHome()) — never for an evidence dir or
1752
+ * a non-default --home, where it would speak for a different log.
1753
+ */
1754
+ declare function readQuarantineIdentity(home: string, opts?: {
1755
+ keystore?: boolean;
1756
+ }): QuarantineIdentity | undefined;
1757
+ /** `gnomon log quarantine` (see the header). */
1758
+ declare function quarantineLog(opts: QuarantineOptions): Promise<QuarantineReport>;
1759
+
1760
+ /**
1761
+ * @symbol #loop-runner
1762
+ *
1763
+ * The run ledger (docs/specs/gnomon-loops.md §4 "#loop-runner", "Restart"; LL6). A PURE fold of the runner's
1764
+ * kernel-signed rows, so everything the runner knows after a restart comes back from the log:
1765
+ *
1766
+ * loop.run.started{runId, loopId, scope, repoKey, contentHash, trigger, budgets, parentRunId?}
1767
+ * loop.node{runId, loopId, nodeId, type, visit, round, verdict, edge, next, durationMs, evidenceRef, evidence?, …}
1768
+ * loop.round{runId, loopId, round, nodeVisits, escalations}
1769
+ * loop.notified{runId, loopId, nodeId, as, text, cardId?}
1770
+ * loop.run.ended{runId, loopId, scope, repoKey, reason, terminal?, rounds, computeMs} (terminal: the @goal/@stop/@pause
1771
+ * the walk reached, when it did)
1772
+ *
1773
+ * - **Open runs** (a start with no end) are what the boot sweep closes `daemon-restart`; nothing resumes mid-step.
1774
+ * - **Day windows** come from chain time (the row's `at`), as the fuse's do: top-level runs started and compute
1775
+ * spent per loop key and globally, per local calendar day. The counters are their OWN fold, never touched by the
1776
+ * eviction of run records (Aegis step 5 #1), and a callee's compute is charged to the ROOT caller's key (`rootKey`
1777
+ * on loop.run.started, else the parent run's), so the caller's day.computeSec funds its calls (§3.4).
1778
+ * - **Replay (G-LOOP-17).** Every loop.node row names the edge it took (`edge`, the verdict or choice key) and
1779
+ * where it went (`next`); `replayLoopRuns` reproduces each run's walk from the rows alone and reports a
1780
+ * divergence when a row's `next` is not the node the following row ran, or the end does not match the terminal.
1781
+ *
1782
+ * - **Model tokens (step 8).** A loop model step's spawn permit names the paying loop (`permit.grant{permit.scope.loop}`
1783
+ * = the root caller's key); the ledger maps each such permitId to that key and folds the permit's `budget.usage`
1784
+ * tokens into the same per-day counters (the key and '*'), so `day.tokens` and the global day cap survive a restart.
1785
+ *
1786
+ * Only rows from the kernel principal (and, when given, a kernel key) are folded: a forged row changes nothing.
1787
+ */
1788
+
1789
+ interface LoopReplayRun {
1790
+ loopId: string;
1791
+ /** [nodeId, verdict, edge, next] per visit, in log order */
1792
+ edges: Array<[string, string, string | null, string | null]>;
1793
+ ended: string | null;
1794
+ /** #loop-events (step 7): the `loop.trigger.fired` trigger the run started from; present only for event-started runs */
1795
+ why?: Record<string, unknown>;
1796
+ }
1797
+
1798
+ declare const REPLAY_PROJECTION: "gnomon-replay:v1";
1799
+ interface ReplayInput {
1800
+ seq: number;
1801
+ kind: 'session.inject' | 'turn.sent';
1802
+ hash: string;
1803
+ origin?: string;
1804
+ bytes?: number;
1805
+ turn?: string;
1806
+ permitId?: string;
1807
+ }
1808
+ interface ReplayProjection {
1809
+ schema: typeof REPLAY_PROJECTION;
1810
+ log: string | null;
1811
+ head: {
1812
+ seq: number;
1813
+ hash: string;
1814
+ } | null;
1815
+ kinds: Record<string, number>;
1816
+ sessions: Record<string, {
1817
+ inputs: ReplayInput[];
1818
+ host: Array<{
1819
+ seq: number;
1820
+ kind: string;
1821
+ hashes: Record<string, string>;
1822
+ }>;
1823
+ }>;
1824
+ cards: Record<string, {
1825
+ state: string;
1826
+ seq: number;
1827
+ }>;
1828
+ /** #loop-runner (G-LOOP-17): every loop run's walk, each edge taken; present only when the log has loop runs */
1829
+ loops?: Record<string, LoopReplayRun>;
1830
+ }
1831
+ interface ReplayDivergence {
1832
+ seq: number;
1833
+ reason: 'input-mismatch' | 'inject-plaintext' | 'malformed-envelope' | 'loop-edge-mismatch' | DecisionSigDivergence | RootDecisionDivergence;
1834
+ detail: string;
1835
+ }
1836
+ interface ReplayReport {
1837
+ ok: boolean;
1838
+ verify: VerifyReport;
1839
+ /** Absent when verify failed (an unverified log is never folded). */
1840
+ projection?: ReplayProjection;
1841
+ projectionHash?: string;
1842
+ divergences: ReplayDivergence[];
1843
+ /** `verified` when decisionKeys was given (every approval.decide checked), else `unchecked`. */
1844
+ decisionSigs: 'verified' | 'unchecked';
1845
+ /** The seq of the decisionSig v2 cutover marker row, when one was seen (verified mode only). */
1846
+ decisionCutoverSeq?: number;
1847
+ /** Set when `expect` was given. */
1848
+ expected?: {
1849
+ hash: string;
1850
+ matches: boolean;
1851
+ };
1852
+ }
1853
+ type Row = VerifiedRow;
1854
+ /** The fold, pure over the rows (exported so a test can feed it rows directly). */
1855
+ declare function foldReplay(rows: Iterable<Row>): {
1856
+ projection: ReplayProjection;
1857
+ divergences: ReplayDivergence[];
1858
+ };
1859
+ /** Divergences of the decisionSig check (P8-D98). */
1860
+ type DecisionSigDivergence = 'decision-sig-bad' | 'decision-sig-v1-after-cutover' | 'decision-sig-unverifiable';
1861
+ interface DecisionKeys {
1862
+ /** The approvals key ids (in the key ring) of an approver principal; none ⇒ the row cannot verify (fail closed). */
1863
+ keyIdsFor(principal: string): readonly string[];
1864
+ }
1865
+ /**
1866
+ * Verify every approval.decide decisionSig over its layout, with the per-log cutover (see the header).
1867
+ * Pure over the rows, in seq order; exported so a test can feed rows directly.
1868
+ */
1869
+ declare function checkDecisionSigs(rows: Iterable<Row>, keyRing: KeyRing, keys: DecisionKeys): {
1870
+ divergences: ReplayDivergence[];
1871
+ cutoverSeq?: number;
1872
+ };
1873
+ /** Aegis C1f (TD-2026-10-20-514): divergences of the v2 root-decision check. */
1874
+ type RootDecisionDivergence = 'root-rows-missing' | 'root-rows-digest' | 'root-sig-bad';
1875
+ /**
1876
+ * Aegis C1f: every approval.decide carrying a rowsDigest (a v2 root decision) is checked against the card the log
1877
+ * showed. Its approval.request card's root-rows node detail must hash to the card's contentHash, and
1878
+ * sha256(canonicalJson(detail.rootRows)) must be the logged rowsDigest. With `root` (the pinned root key), the
1879
+ * logged rootSig must verify over the gnomon-root-decision:v2 row rebuilt from the logged fields. Pure over the rows.
1880
+ */
1881
+ declare function checkRootDecisions(rows: Iterable<Row>, root?: {
1882
+ readonly rootKeyId: string | null;
1883
+ verifyRow(signer: string, row: unknown, sigB64: string): boolean;
1884
+ }): ReplayDivergence[];
1885
+ declare function replayProjectionHash(p: ReplayProjection): string;
1886
+ /**
1887
+ * verifyLog with the fold (and, given decisionKeys, the decisionSig check) inside its single pass; `expect`
1888
+ * compares the projection hash. ok ⇔ verified ∧ no divergence ∧ (no expect ∨ it matches).
1889
+ */
1890
+ declare function replayLog(home: string, opts: Omit<VerifyLogOptions, 'onRow'> & {
1891
+ expect?: string;
1892
+ decisionKeys?: DecisionKeys;
1893
+ root?: Parameters<typeof checkRootDecisions>[1];
1894
+ }): ReplayReport;
1895
+
1896
+ /**
1897
+ * @symbol #kernel-log
1898
+ *
1899
+ * #kernel-log (spec §3.2, M1.2) — public surface of the kernel log module.
1900
+ */
1901
+
1902
+ declare const index$1_ACTIVE_DB: typeof ACTIVE_DB;
1903
+ type index$1_AnchorReadResult = AnchorReadResult;
1904
+ type index$1_AnchorState = AnchorState;
1905
+ type index$1_AnchorStatus = AnchorStatus;
1906
+ type index$1_AnchorStore = AnchorStore;
1907
+ type index$1_Anchoring = Anchoring;
1908
+ type index$1_AppendInput = AppendInput;
1909
+ type index$1_AppendResult = AppendResult;
1910
+ declare const index$1_BOOT_UNKNOWN: typeof BOOT_UNKNOWN;
1911
+ declare const index$1_CRITICAL_ANCHOR_KINDS: typeof CRITICAL_ANCHOR_KINDS;
1912
+ type index$1_CloseReport = CloseReport;
1913
+ declare const index$1_DEFAULT_SEGMENT_ROWS: typeof DEFAULT_SEGMENT_ROWS;
1914
+ declare const index$1_DIAGNOSTIC_NAMESPACES: typeof DIAGNOSTIC_NAMESPACES;
1915
+ declare const index$1_DOMAINS_BY_KEY_CLASS: typeof DOMAINS_BY_KEY_CLASS;
1916
+ type index$1_DecisionKeys = DecisionKeys;
1917
+ type index$1_DecisionSigDivergence = DecisionSigDivergence;
1918
+ type index$1_Durability = Durability;
1919
+ declare const index$1_FILE_ANCHOR_MAX_LAG: typeof FILE_ANCHOR_MAX_LAG;
1920
+ declare const index$1_FILE_ANCHOR_MAX_MS: typeof FILE_ANCHOR_MAX_MS;
1921
+ declare const index$1_FORCED_ANCHOR_ENVELOPE: typeof FORCED_ANCHOR_ENVELOPE;
1922
+ declare const index$1_FORCED_ANCHOR_WINDOW: typeof FORCED_ANCHOR_WINDOW;
1923
+ type index$1_FaultEntry = FaultEntry;
1924
+ type index$1_FileAnchorStore = FileAnchorStore;
1925
+ declare const index$1_FileAnchorStore: typeof FileAnchorStore;
1926
+ declare const index$1_GENESIS_PREFIX: typeof GENESIS_PREFIX;
1927
+ declare const index$1_HEAD_SCHEMA: typeof HEAD_SCHEMA;
1928
+ type index$1_HeadAnchor = HeadAnchor;
1929
+ type index$1_HeadSource = HeadSource;
1930
+ declare const index$1_KEYSTORE_ANCHOR_MAX_LAG: typeof KEYSTORE_ANCHOR_MAX_LAG;
1931
+ declare const index$1_KEYSTORE_ANCHOR_MAX_MS: typeof KEYSTORE_ANCHOR_MAX_MS;
1932
+ declare const index$1_KEYSTORE_WRITE_TIMEOUT_MS: typeof KEYSTORE_WRITE_TIMEOUT_MS;
1933
+ type index$1_KernelLog = KernelLog;
1934
+ declare const index$1_KernelLog: typeof KernelLog;
1935
+ type index$1_KernelLogOptions = KernelLogOptions;
1936
+ declare const index$1_KeyClass: typeof KeyClass;
1937
+ declare const index$1_KeyCustody: typeof KeyCustody;
1938
+ declare const index$1_KeyRing: typeof KeyRing;
1939
+ type index$1_KeystoreAnchorStore = KeystoreAnchorStore;
1940
+ declare const index$1_KeystoreAnchorStore: typeof KeystoreAnchorStore;
1941
+ type index$1_LogIntegrity = LogIntegrity;
1942
+ type index$1_LogRefusal = LogRefusal;
1943
+ declare const index$1_LogRefusal: typeof LogRefusal;
1944
+ type index$1_LogRefusalReason = LogRefusalReason;
1945
+ type index$1_LogStub = LogStub;
1946
+ type index$1_LogView = LogView;
1947
+ type index$1_ObservedHead = ObservedHead;
1948
+ type index$1_OpenReport = OpenReport;
1949
+ type index$1_PendingQuarantine = PendingQuarantine;
1950
+ type index$1_ProjectedEvent = ProjectedEvent;
1951
+ declare const index$1_QUARANTINE_GENESIS_KIND: typeof QUARANTINE_GENESIS_KIND;
1952
+ declare const index$1_QUARANTINE_JOURNAL: typeof QUARANTINE_JOURNAL;
1953
+ declare const index$1_QUARANTINE_JOURNAL_SCHEMA: typeof QUARANTINE_JOURNAL_SCHEMA;
1954
+ declare const index$1_QUARANTINE_STEPS: typeof QUARANTINE_STEPS;
1955
+ type index$1_QuarantineFsOps = QuarantineFsOps;
1956
+ type index$1_QuarantineIdentity = QuarantineIdentity;
1957
+ type index$1_QuarantineOptions = QuarantineOptions;
1958
+ type index$1_QuarantineReport = QuarantineReport;
1959
+ type index$1_QuarantineStep = QuarantineStep;
1960
+ type index$1_QuarantinedPayload = QuarantinedPayload;
1961
+ declare const index$1_REPLAY_PROJECTION: typeof REPLAY_PROJECTION;
1962
+ declare const index$1_RESERVED_KINDS: typeof RESERVED_KINDS;
1963
+ type index$1_ReaderClass = ReaderClass;
1964
+ type index$1_RedactedField = RedactedField;
1965
+ type index$1_ReplayDivergence = ReplayDivergence;
1966
+ type index$1_ReplayInput = ReplayInput;
1967
+ type index$1_ReplayProjection = ReplayProjection;
1968
+ type index$1_ReplayReport = ReplayReport;
1969
+ type index$1_RootDecisionDivergence = RootDecisionDivergence;
1970
+ declare const index$1_SEGMENTS_DIR: typeof SEGMENTS_DIR;
1971
+ declare const index$1_SEGMENT_SCHEMA: typeof SEGMENT_SCHEMA;
1972
+ declare const index$1_SESSION_NEVER_FIELDS: typeof SESSION_NEVER_FIELDS;
1973
+ declare const index$1_SIGNATURE_DOMAINS: typeof SIGNATURE_DOMAINS;
1974
+ declare const index$1_SIG_MANDATORY_KINDS: typeof SIG_MANDATORY_KINDS;
1975
+ declare const index$1_SIG_MANDATORY_NAMESPACES: typeof SIG_MANDATORY_NAMESPACES;
1976
+ type index$1_SegmentInfo = SegmentInfo;
1977
+ declare const index$1_SignatureDomain: typeof SignatureDomain;
1978
+ declare const index$1_Signer: typeof Signer;
1979
+ declare const index$1_SignerDomainError: typeof SignerDomainError;
1980
+ declare const index$1_SoftwareEd25519Signer: typeof SoftwareEd25519Signer;
1981
+ type index$1_TruncationCause = TruncationCause;
1982
+ type index$1_TruncationReport = TruncationReport;
1983
+ type index$1_VerifiedRow = VerifiedRow;
1984
+ type index$1_VerifyFailure = VerifyFailure;
1985
+ type index$1_VerifyFailureCode = VerifyFailureCode;
1986
+ type index$1_VerifyLogOptions = VerifyLogOptions;
1987
+ type index$1_VerifyReport = VerifyReport;
1988
+ declare const index$1_answerDigest: typeof answerDigest;
1989
+ declare const index$1_approveMessage: typeof approveMessage;
1990
+ declare const index$1_assertOwner: typeof assertOwner;
1991
+ declare const index$1_checkDecisionSigs: typeof checkDecisionSigs;
1992
+ declare const index$1_checkRootDecisions: typeof checkRootDecisions;
1993
+ declare const index$1_completePendingQuarantine: typeof completePendingQuarantine;
1994
+ declare const index$1_decisionMessage: typeof decisionMessage;
1995
+ declare const index$1_ed25519KeyId: typeof ed25519KeyId;
1996
+ declare const index$1_effectiveSensitivity: typeof effectiveSensitivity;
1997
+ declare const index$1_evidenceNameFor: typeof evidenceNameFor;
1998
+ declare const index$1_foldReplay: typeof foldReplay;
1999
+ declare const index$1_fsyncDir: typeof fsyncDir;
2000
+ declare const index$1_fsyncFile: typeof fsyncFile;
2001
+ declare const index$1_genesisPrev: typeof genesisPrev;
2002
+ declare const index$1_hashPreimage: typeof hashPreimage;
2003
+ declare const index$1_isBenignDirFsyncError: typeof isBenignDirFsyncError;
2004
+ declare const index$1_isCriticalKind: typeof isCriticalKind;
2005
+ declare const index$1_isDiagnostic: typeof isDiagnostic;
2006
+ declare const index$1_isSigMandatory: typeof isSigMandatory;
2007
+ declare const index$1_listSealedSegments: typeof listSealedSegments;
2008
+ declare const index$1_logRefusal: typeof logRefusal;
2009
+ declare const index$1_mayBeUnsigned: typeof mayBeUnsigned;
2010
+ declare const index$1_mayBeVisible: typeof mayBeVisible;
2011
+ declare const index$1_normalizeBootId: typeof normalizeBootId;
2012
+ declare const index$1_p256KeyId: typeof p256KeyId;
2013
+ declare const index$1_projectForReader: typeof projectForReader;
2014
+ declare const index$1_projectionStats: typeof projectionStats;
2015
+ declare const index$1_quarantineLog: typeof quarantineLog;
2016
+ declare const index$1_readBootSession: typeof readBootSession;
2017
+ declare const index$1_readQuarantineIdentity: typeof readQuarantineIdentity;
2018
+ declare const index$1_replayLog: typeof replayLog;
2019
+ declare const index$1_replayProjectionHash: typeof replayProjectionHash;
2020
+ declare const index$1_resolveLabels: typeof resolveLabels;
2021
+ declare const index$1_sha256TaggedFast: typeof sha256TaggedFast;
2022
+ declare const index$1_signaturePreimage: typeof signaturePreimage;
2023
+ declare const index$1_usesDecisionV2: typeof usesDecisionV2;
2024
+ declare const index$1_verifyLog: typeof verifyLog;
2025
+ declare namespace index$1 {
2026
+ export { index$1_ACTIVE_DB as ACTIVE_DB, index$1_BOOT_UNKNOWN as BOOT_UNKNOWN, index$1_CRITICAL_ANCHOR_KINDS as CRITICAL_ANCHOR_KINDS, index$1_DEFAULT_SEGMENT_ROWS as DEFAULT_SEGMENT_ROWS, index$1_DIAGNOSTIC_NAMESPACES as DIAGNOSTIC_NAMESPACES, index$1_DOMAINS_BY_KEY_CLASS as DOMAINS_BY_KEY_CLASS, index$1_FILE_ANCHOR_MAX_LAG as FILE_ANCHOR_MAX_LAG, index$1_FILE_ANCHOR_MAX_MS as FILE_ANCHOR_MAX_MS, index$1_FORCED_ANCHOR_ENVELOPE as FORCED_ANCHOR_ENVELOPE, index$1_FORCED_ANCHOR_WINDOW as FORCED_ANCHOR_WINDOW, index$1_FileAnchorStore as FileAnchorStore, index$1_GENESIS_PREFIX as GENESIS_PREFIX, index$1_HEAD_SCHEMA as HEAD_SCHEMA, index$1_KEYSTORE_ANCHOR_MAX_LAG as KEYSTORE_ANCHOR_MAX_LAG, index$1_KEYSTORE_ANCHOR_MAX_MS as KEYSTORE_ANCHOR_MAX_MS, index$1_KEYSTORE_WRITE_TIMEOUT_MS as KEYSTORE_WRITE_TIMEOUT_MS, index$1_KernelLog as KernelLog, index$1_KeyClass as KeyClass, index$1_KeyCustody as KeyCustody, index$1_KeyRing as KeyRing, index$1_KeystoreAnchorStore as KeystoreAnchorStore, index$1_LogRefusal as LogRefusal, index$1_QUARANTINE_GENESIS_KIND as QUARANTINE_GENESIS_KIND, index$1_QUARANTINE_JOURNAL as QUARANTINE_JOURNAL, index$1_QUARANTINE_JOURNAL_SCHEMA as QUARANTINE_JOURNAL_SCHEMA, index$1_QUARANTINE_STEPS as QUARANTINE_STEPS, index$1_REPLAY_PROJECTION as REPLAY_PROJECTION, index$1_RESERVED_KINDS as RESERVED_KINDS, index$1_SEGMENTS_DIR as SEGMENTS_DIR, index$1_SEGMENT_SCHEMA as SEGMENT_SCHEMA, index$1_SESSION_NEVER_FIELDS as SESSION_NEVER_FIELDS, index$1_SIGNATURE_DOMAINS as SIGNATURE_DOMAINS, index$1_SIG_MANDATORY_KINDS as SIG_MANDATORY_KINDS, index$1_SIG_MANDATORY_NAMESPACES as SIG_MANDATORY_NAMESPACES, index$1_SignatureDomain as SignatureDomain, index$1_Signer as Signer, index$1_SignerDomainError as SignerDomainError, index$1_SoftwareEd25519Signer as SoftwareEd25519Signer, index$1_answerDigest as answerDigest, index$1_approveMessage as approveMessage, index$1_assertOwner as assertOwner, index$1_checkDecisionSigs as checkDecisionSigs, index$1_checkRootDecisions as checkRootDecisions, index$1_completePendingQuarantine as completePendingQuarantine, index$1_decisionMessage as decisionMessage, index$1_ed25519KeyId as ed25519KeyId, index$1_effectiveSensitivity as effectiveSensitivity, index$1_evidenceNameFor as evidenceNameFor, index$1_foldReplay as foldReplay, index$1_fsyncDir as fsyncDir, index$1_fsyncFile as fsyncFile, index$1_genesisPrev as genesisPrev, index$1_hashPreimage as hashPreimage, index$1_isBenignDirFsyncError as isBenignDirFsyncError, index$1_isCriticalKind as isCriticalKind, index$1_isDiagnostic as isDiagnostic, index$1_isSigMandatory as isSigMandatory, index$1_listSealedSegments as listSealedSegments, index$1_logRefusal as logRefusal, index$1_mayBeUnsigned as mayBeUnsigned, index$1_mayBeVisible as mayBeVisible, index$1_normalizeBootId as normalizeBootId, index$1_p256KeyId as p256KeyId, index$1_projectForReader as projectForReader, index$1_projectionStats as projectionStats, index$1_quarantineLog as quarantineLog, index$1_readBootSession as readBootSession, index$1_readQuarantineIdentity as readQuarantineIdentity, index$1_replayLog as replayLog, index$1_replayProjectionHash as replayProjectionHash, index$1_resolveLabels as resolveLabels, index$1_sha256TaggedFast as sha256TaggedFast, index$1_signaturePreimage as signaturePreimage, index$1_usesDecisionV2 as usesDecisionV2, index$1_verifyLog as verifyLog };
2027
+ export type { index$1_AnchorReadResult as AnchorReadResult, index$1_AnchorState as AnchorState, index$1_AnchorStatus as AnchorStatus, index$1_AnchorStore as AnchorStore, index$1_Anchoring as Anchoring, index$1_AppendInput as AppendInput, index$1_AppendResult as AppendResult, index$1_CloseReport as CloseReport, index$1_DecisionKeys as DecisionKeys, index$1_DecisionSigDivergence as DecisionSigDivergence, index$1_Durability as Durability, index$1_FaultEntry as FaultEntry, index$1_HeadAnchor as HeadAnchor, index$1_HeadSource as HeadSource, index$1_KernelLogOptions as KernelLogOptions, index$1_LogIntegrity as LogIntegrity, index$1_LogRefusalReason as LogRefusalReason, index$1_LogStub as LogStub, index$1_LogView as LogView, index$1_ObservedHead as ObservedHead, index$1_OpenReport as OpenReport, index$1_PendingQuarantine as PendingQuarantine, index$1_ProjectedEvent as ProjectedEvent, index$1_QuarantineFsOps as QuarantineFsOps, index$1_QuarantineIdentity as QuarantineIdentity, index$1_QuarantineOptions as QuarantineOptions, index$1_QuarantineReport as QuarantineReport, index$1_QuarantineStep as QuarantineStep, index$1_QuarantinedPayload as QuarantinedPayload, index$1_ReaderClass as ReaderClass, index$1_RedactedField as RedactedField, index$1_ReplayDivergence as ReplayDivergence, index$1_ReplayInput as ReplayInput, index$1_ReplayProjection as ReplayProjection, index$1_ReplayReport as ReplayReport, index$1_RootDecisionDivergence as RootDecisionDivergence, index$1_SegmentInfo as SegmentInfo, index$1_TruncationCause as TruncationCause, index$1_TruncationReport as TruncationReport, index$1_VerifiedRow as VerifiedRow, index$1_VerifyFailure as VerifyFailure, index$1_VerifyFailureCode as VerifyFailureCode, index$1_VerifyLogOptions as VerifyLogOptions, index$1_VerifyReport as VerifyReport };
2028
+ }
2029
+
2030
+ /** Kernel version. test/version.test.ts keeps this equal to package.json. */
2031
+ declare const GNOMON_VERSION: "8.0.2";
2032
+
2033
+ /** The thirteen kernel modules of spec §18, in spec order. */
2034
+ declare const KERNEL_MODULES: readonly ["identity", "log", "runner", "supervisor", "broker", "budget", "scheduler", "manifest", "refs", "socket", "web", "sandbox", "modhost"];
2035
+ type KernelModule = (typeof KERNEL_MODULES)[number];
2036
+ /** The single non-`node:` package the kernel may import (G-KRN-02). */
2037
+ declare const KERNEL_ALLOWED_PACKAGE: "@a-company/gnomon-contracts";
2038
+
2039
+ /**
2040
+ * @symbol #manifest-loader
2041
+ *
2042
+ * #manifest-loader refusals (spec §3.6, §4.6, §12.5). Every refusal is a
2043
+ * contracts `refusal:v1` (refuse()) carried by a RefusedError, so the socket
2044
+ * maps it with the §4.9 code map unchanged.
2045
+ *
2046
+ * The manifest-specific code (`SNAPSHOT`, `LOCKFILE`, …) rides in
2047
+ * `refusal.data.manifestCode`, the same token the `manifest.refuse{code}`
2048
+ * event carries (§12.5: `manifest.refuse{code:'SNAPSHOT'}`). It is NOT put in
2049
+ * `data.reason`: `refusal.reason` is an additive enum hashed into
2050
+ * `clientApiId` (contracts rpc.ts ADDITIVE_ENUMS), so naming new reasons there
2051
+ * would move the pinned id. For the same reason no detail key is named
2052
+ * `reason` (strict refusal:v1 validation checks `data.reason` against that enum). Adding these codes to REFUSAL_REASONS is a batch
2053
+ * candidate for the next clientApiId move (reported in the M1.5 hand-off).
2054
+ */
2055
+
2056
+ /** Manifest refusal codes (kernel-internal; `manifest.refuse{code}` and `refusal.data.manifestCode`). */
2057
+ declare const MANIFEST_REFUSAL_CODES: readonly ["SCHEMA", "ABI", "NAME", "TIER", "CAPABILITY", "EGRESS", "KNOWLEDGE", "SNAPSHOT", "LOCKFILE", "POSTINSTALL", "GRANT", "INTEGRITY", "GENERATED", "NOT_INSTALLED", "FORMAT", "ENGINE", "PUBLISHER", "COLLISION"];
2058
+ type ManifestRefusalCode = (typeof MANIFEST_REFUSAL_CODES)[number];
2059
+ declare class ManifestRefusal extends RefusedError {
2060
+ readonly manifestCode: ManifestRefusalCode;
2061
+ readonly detail: Readonly<Record<string, unknown>>;
2062
+ constructor(manifestCode: ManifestRefusalCode, message: string, detail?: Record<string, unknown>);
2063
+ }
2064
+ declare function isManifestRefusal(err: unknown): err is ManifestRefusal;
2065
+ /** The kernel event sink (§9.1 kinds; the caller appends them to #kernel-log). */
2066
+ type ManifestEventSink = (kind: string, payload: Record<string, unknown>) => void;
2067
+ declare const noEvents: ManifestEventSink;
2068
+
2069
+ /**
2070
+ * @symbol #manifest-loader
2071
+ *
2072
+ * #manifest-loader egress policy (spec §3.6, §4.3, §15.4; G-MAN-01). Anthropic
2073
+ * API hosts are refused in a manifest's `requires.egress` and in every
2074
+ * `grant.egress` row: a mod never talks to Anthropic directly (law 7 — the
2075
+ * subscription path is the kernel's, never a mod's).
2076
+ *
2077
+ * Matching is fail-closed: the host is lower-cased, a trailing dot and a
2078
+ * `:port` are stripped, and a WILDCARD that could match an Anthropic host
2079
+ * (`*`, `*.com`, `*.anthropic.com`) is refused as well. Malformed hosts
2080
+ * (empty, whitespace, a scheme, a path, `@`) are refused as not-a-host.
2081
+ *
2082
+ * Also refused (Aegis F8): any port (`host:443` — the egress proxy decides
2083
+ * ports, a grant names hosts only); numeric hosts in any form (an all-numeric
2084
+ * last label covers dotted-quad and decimal, a `0x…`/octal label the hex and
2085
+ * octal forms); single-label names; and local/private names (`localhost`,
2086
+ * `*.localhost`, `.local`, `.internal`, `.lan`, `.home.arpa`, `.localdomain`).
2087
+ * The resolved-IP check against Anthropic and private ranges is the egress
2088
+ * proxy's (M1.7); this is the name-level gate.
2089
+ */
2090
+ /** Registrable domains whose hosts are Anthropic API / product endpoints. */
2091
+ declare const ANTHROPIC_DOMAINS: readonly string[];
2092
+ /** Normalise a host for comparison, or null when it is not a plain host[:port]. */
2093
+ declare function normalizeHost(raw: unknown): string | null;
2094
+ /** True when the (possibly wildcard) host could reach an Anthropic domain. */
2095
+ declare function isAnthropicHost(raw: unknown): boolean;
2096
+ type EgressRefusalWhy = 'anthropic' | 'not-a-host' | 'port' | 'numeric' | 'single-label' | 'private-name';
2097
+ type EgressVerdict = {
2098
+ ok: true;
2099
+ host: string;
2100
+ } | {
2101
+ ok: false;
2102
+ host: string;
2103
+ why: EgressRefusalWhy;
2104
+ };
2105
+ declare const PRIVATE_NAME_SUFFIXES: readonly string[];
2106
+ /** Check one egress host. */
2107
+ declare function checkEgressHost(raw: unknown): EgressVerdict;
2108
+
2109
+ declare const MANIFEST_FILE = "gnomon-manifest.json";
2110
+ declare const MOD_ABI_V1: "mod-abi:v1";
2111
+ declare const KNOWN_ABIS: readonly "mod-abi:v1"[];
2112
+ declare const MANIFEST_KINDS: readonly ["distro", "mod", "provider", "adapter", "skill-pack"];
2113
+ type ManifestKind = (typeof MANIFEST_KINDS)[number];
2114
+ /** Kinds accepted only from the first-party trust tier (A23-2, S25-H4). */
2115
+ declare const FIRST_PARTY_ONLY_KINDS: readonly ManifestKind[];
2116
+ declare const TOOL_EFFECTS: readonly ["read", "write", "network", "spend"];
2117
+ type ToolEffect = (typeof TOOL_EFFECTS)[number];
2118
+ /** §12.2 reserved decision keys (and the digits): never bindable by a mod (`G-MOD-06`). */
2119
+ declare const RESERVED_DECISION_KEYS: readonly string[];
2120
+ /** Trust tiers (§12.4 "Trust"): judged on provenance + hash, never self-description. */
2121
+ type TrustTier = 'first-party' | 'local' | `signed:${string}`;
2122
+ declare const TRUST_TIER_PATTERN: RegExp;
2123
+ /** Capabilities no mod manifest may request whatever its tier (§12.4 "Trust"). */
2124
+ declare const NEVER_REQUESTABLE: readonly string[];
2125
+ /** Keys whose meaning never changes across manifest formats (S0b §3). */
2126
+ declare const FORMAT_INVARIANT_KEYS: readonly string[];
2127
+ declare const MANIFEST_FORMAT_CURRENT: 2;
2128
+ declare const MANIFEST_FORMATS_ACCEPTED: readonly number[];
2129
+ /** The version cap (semver, ≤ 64) and the prerelease bound (≤ 4 identifiers of ≤ 16 characters). */
2130
+ declare const VERSION_MAX = 64;
2131
+ interface ManifestTool {
2132
+ name: string;
2133
+ schema?: Record<string, unknown>;
2134
+ effects: ToolEffect[];
2135
+ }
2136
+ interface ManifestView {
2137
+ id: string;
2138
+ slot: string;
2139
+ placement: 'append' | 'replace';
2140
+ fixtures?: string[];
2141
+ }
2142
+ interface ManifestCommand {
2143
+ id: string;
2144
+ title: string;
2145
+ args?: Record<string, unknown>;
2146
+ }
2147
+ interface ManifestKeybinding {
2148
+ key: string;
2149
+ command: string;
2150
+ }
2151
+ interface ManifestKnowledge {
2152
+ name: string;
2153
+ scheme: string;
2154
+ query: string;
2155
+ maxTier: string;
2156
+ }
2157
+ interface ManifestHook {
2158
+ event: string;
2159
+ command: string;
2160
+ }
2161
+ /** A manifest:2 provides.mcp entry: no `name` (the kernel derives it: mcpServerName(id)). */
2162
+ interface ManifestMcp {
2163
+ command: string;
2164
+ args?: string[];
2165
+ /** what a per-user override may replace (TD-2026-10-20-812): absent = nothing (the manifest's command runs as is) */
2166
+ config?: ManifestMcpConfig;
2167
+ }
2168
+ /** The author-declared override surface of one provides.mcp server (closed). */
2169
+ interface ManifestMcpConfig {
2170
+ command?: true;
2171
+ args?: true;
2172
+ /** env var NAMES the user may set (never a launch-critical name, MCP_ENV_DENY) */
2173
+ env?: string[];
2174
+ /** env names (a subset of env) that hold SECRETS; refused in a per-user override until a secret store exists (Aegis S1 M2) */
2175
+ secret?: string[];
2176
+ }
2177
+ /** A per-user override of a provides.mcp server's launch (validateMcpUserConfig); only what config permits. */
2178
+ interface McpUserConfig {
2179
+ command?: string;
2180
+ args?: string[];
2181
+ env?: Record<string, string>;
2182
+ }
2183
+ /**
2184
+ * A declarable env name: uppercase only. Lowercase names (http_proxy, no_proxy, …, which curl and others honour) are
2185
+ * therefore unreachable by construction, so the denylist below lists only uppercase forms.
2186
+ */
2187
+ declare const MCP_ENV_NAME: RegExp;
2188
+ /**
2189
+ * Env names no override may set (Aegis M1): they change how a process loads code, resolves a binary, trusts TLS,
2190
+ * routes traffic, finds its home/temp/config, or where its keys live.
2191
+ */
2192
+ declare const MCP_ENV_DENY: ReadonlySet<string>;
2193
+ /** Prefix families no override may set (no bare GO prefix: GOOGLE_… stays declarable; the Go names are exact above). */
2194
+ declare const MCP_ENV_DENY_PREFIXES: readonly string[];
2195
+ /**
2196
+ * Below the first-party tier a declared env name must start with the mod's own prefix (S0b: `<PUB>__<NAME>__`, double
2197
+ * underscore, contracts modEnvPrefix) or be a credential (`…_API_KEY`, `…_TOKEN`). The denylist runs after and is never skipped.
2198
+ */
2199
+ declare function mcpEnvOwnPrefix(modId: string): string;
2200
+ declare const MCP_CONFIG_LIMITS: Readonly<{
2201
+ env: 16;
2202
+ args: 64;
2203
+ value: 4096;
2204
+ }>;
2205
+ interface ManifestEgress {
2206
+ host: string;
2207
+ purpose: string;
2208
+ }
2209
+ interface ManifestV2 {
2210
+ manifest: 2;
2211
+ kind: ManifestKind;
2212
+ publisher: string;
2213
+ name: string;
2214
+ version: string;
2215
+ /** compatibility: `engines.gnomon` comparators (S0b §3), refused ENGINE at stage and load */
2216
+ engines?: {
2217
+ gnomon?: string;
2218
+ };
2219
+ abi?: string;
2220
+ description?: string;
2221
+ compat?: {
2222
+ kernel?: string;
2223
+ claudeCode?: string;
2224
+ };
2225
+ provides?: {
2226
+ mcp?: ManifestMcp[];
2227
+ skills?: unknown[];
2228
+ agents?: unknown[];
2229
+ hooks?: ManifestHook[];
2230
+ bands?: unknown[];
2231
+ steps?: unknown[];
2232
+ resolvers?: unknown[];
2233
+ blocks?: unknown[];
2234
+ oracles?: unknown[];
2235
+ tools?: ManifestTool[];
2236
+ views?: ManifestView[];
2237
+ events?: string[];
2238
+ commands?: ManifestCommand[];
2239
+ keybindings?: ManifestKeybinding[];
2240
+ knowledge?: ManifestKnowledge[];
2241
+ /** the Desk (TD-2026-10-20-812): playbook offers, offer-spec:v1, at most OFFERS_PER_MOD_MAX */
2242
+ offers?: OfferSpecV1[];
2243
+ };
2244
+ requires?: {
2245
+ capabilities?: string[];
2246
+ egress?: 'none' | ManifestEgress[];
2247
+ };
2248
+ config_schema?: Record<string, unknown>;
2249
+ }
2250
+ /** Mod names reserved outright (Aegis, Desk reviews): never a mod name at any tier or publisher. */
2251
+ declare const RESERVED_MOD_NAMES: ReadonlySet<string>;
2252
+ /**
2253
+ * Names of the first-party mods (contracts FIRST_PARTY_MOD_NAMES). S0b: the tier rule is the publisher now (gnomon ⇔
2254
+ * first-party); the old name-prefix list is gone, and a NON-gnomon publisher is refused any first-party display name,
2255
+ * as the name, a prefix of it, or a skeleton of either (FIRST_PARTY_DISPLAY_NAMES).
2256
+ */
2257
+ declare const FIRST_PARTY_MOD_NAMES: ReadonlySet<string>;
2258
+ /** Namespace tokens the kernel owns (the §9.1 registry's namespaces + the reserved prefixes). */
2259
+ declare const KERNEL_NAMESPACE_TOKENS: ReadonlySet<string>;
2260
+ /** S0b: `sha256:<hex>` of the manifest file's RAW bytes (what the human approved, byte for byte). */
2261
+ declare function manifestHash(raw: Uint8Array | string): string;
2262
+ /**
2263
+ * `sha256:<hex>` of the canonical JSON of a manifest object: the format-1 manifestHash (the hash every pre-S0b grant
2264
+ * row was signed over), the upgradedHash of an upgraded V2 object, and the distro generator's marker.
2265
+ */
2266
+ declare function canonicalManifestHash(m: unknown): string;
2267
+ declare const ENGINES_MAX = 64;
2268
+ declare const ENGINE_OPS: readonly [">=", "<=", ">", "<", "="];
2269
+ type EngineOp = (typeof ENGINE_OPS)[number];
2270
+ /**
2271
+ * Parse `engines.gnomon`: space-joined comparators (AND), each one of `>= > <= < =` followed by `x.y.z`; at most
2272
+ * ENGINES_MAX characters. Returns the comparators or null when malformed.
2273
+ */
2274
+ declare function parseEngines(range: unknown): Array<{
2275
+ op: EngineOp;
2276
+ v: [number, number, number];
2277
+ }> | null;
2278
+ /** Does `engines.gnomon` admit this kernel version? null when the range is malformed. */
2279
+ declare function enginesAdmit(range: unknown, version?: string): boolean | null;
2280
+ /** Compare two semver strings by their core (prerelease sorts below its release); null if either is not semver. */
2281
+ declare function compareVersions(a: string, b: string): number | null;
2282
+ /** The §15.4 form a capability string instantiates, or undefined. */
2283
+ declare function capabilityForm(cap: string): string | undefined;
2284
+ interface ValidateManifestOptions {
2285
+ /** The trust tier of the install (provenance, recorded on the card and the grant.trust row). */
2286
+ tier: TrustTier;
2287
+ /**
2288
+ * Only for a format-1 manifest upgraded under the frozen alias table (grants.ts LEGACY_ALIASES): the bare legacy
2289
+ * name, whose `modns.<legacyName>.*` the mod may keep writing (S0b §4). Never set for a format-2 manifest.
2290
+ */
2291
+ legacyName?: string;
2292
+ /** The kernel assigned `local` (the format-1 alias mapping); a manifest that declares `local` itself is refused. */
2293
+ kernelAssignedLocal?: boolean;
2294
+ }
2295
+ /**
2296
+ * The PURE format-1 upgrader (S0b §3): reads only the raw object and the kernel-derived publisher (the alias table:
2297
+ * `gnomon` or `local`), never the disk, never mutates its input. provides.mcp entries lose `name`; a `local` mod's
2298
+ * `modns.<N>.` kinds and log.append become `modns.local.<N>.` (only alias-table `gnomon` mods keep their legacy
2299
+ * namespace). The full V2 validator always runs after (readManifest).
2300
+ */
2301
+ declare function upgradeManifestV1(raw: unknown, publisher: 'gnomon' | 'local'): Record<string, unknown>;
2302
+ interface ReadManifestOptions extends Omit<ValidateManifestOptions, 'legacyName' | 'kernelAssignedLocal'> {
2303
+ /**
2304
+ * The alias publisher of a format-1 manifest (grants.ts aliasOf, or `gnomon` for a historical first-party
2305
+ * packageHash at stage). Absent ⇒ format 1 is a FRESH install and is refused FORMAT.
2306
+ */
2307
+ legacyPublisher?: 'gnomon' | 'local';
2308
+ }
2309
+ interface ReadManifestResult {
2310
+ manifest: ManifestV2;
2311
+ /** raw-bytes hash (format 2); the legacy canonical hash its rows were signed over (format 1) */
2312
+ manifestHash: string;
2313
+ format: 1 | 2;
2314
+ /** format 1 only: canonicalManifestHash of the upgraded V2 object (recorded on the install grant) */
2315
+ upgradedHash?: string;
2316
+ }
2317
+ /** THE manifest entry (S0b): raw bytes → a validated V2 manifest and its hashes. Throws ManifestRefusal. */
2318
+ declare function readManifest(raw: Uint8Array | string, opts: ReadManifestOptions): ReadManifestResult;
2319
+ /**
2320
+ * The stricter class for every COMMAND-RUNNING field (mcp.command, mcp.args,
2321
+ * hooks.command, hooks.event; Aegis round 2 C1): C0/C1 plus Zl (U+2028), Zp
2322
+ * (U+2029) and Cf (format characters: bidi controls, zero-widths, tags). The
2323
+ * §4.5 sanitizer turns LS/PS into a newline, so one in a hook command could
2324
+ * draw a fake install-card line; here they are refused SCHEMA instead.
2325
+ */
2326
+ declare const COMMAND_UNSAFE: RegExp;
2327
+ /**
2328
+ * Validate a parsed manifest. Returns the manifest (typed) or throws a
2329
+ * ManifestRefusal naming the manifest code.
2330
+ */
2331
+ declare function validateManifest(value: unknown, opts: ValidateManifestOptions): ManifestV2;
2332
+ /**
2333
+ * Validate a per-user override of one provides.mcp server (TD-2026-10-20-812: first-party servers launch as
2334
+ * `node <absolute path>` from another repo, so the manifest's fixed command cannot name them). Closed: only what the
2335
+ * manifest entry's `config` permits; the same COMMAND_UNSAFE rule as the manifest; env names from the declared list
2336
+ * only. Throws ManifestRefusal SCHEMA.
2337
+ */
2338
+ declare function validateMcpUserConfig(entry: ManifestMcp, value: unknown): McpUserConfig;
2339
+ /** The launch of one provides.mcp server under an optional per-user override (validated here). */
2340
+ declare function resolveMcpLaunch(entry: ManifestMcp, override?: unknown): {
2341
+ command: string;
2342
+ args: string[];
2343
+ env: Record<string, string>;
2344
+ };
2345
+ /** §12.5's list plus `mcp` and `hooks` (Aegis F3): both run commands, so an addition is always a widening; plus
2346
+ * `offers` (TD-2026-10-20-812): a new offer is a new way the model may steer the human to the mod. */
2347
+ declare const WIDENING_FIELDS: readonly ["effects", "egress", "capabilities", "events", "tools", "views", "commands", "keybindings", "knowledge", "mcp", "hooks", "offers"];
2348
+ type WideningField = (typeof WIDENING_FIELDS)[number];
2349
+ interface WideningEntry {
2350
+ field: WideningField;
2351
+ added: string[];
2352
+ }
2353
+ /**
2354
+ * Any ADDITION between two snapshots' manifests, by field (`prev = null`
2355
+ * means a first install: everything is an addition). An empty result means
2356
+ * the new manifest asks for nothing the old one did not.
2357
+ */
2358
+ declare function detectWidening(prev: ManifestV2 | null, next: ManifestV2): WideningEntry[];
2359
+
2360
+ declare const PACKAGE_TREE_SCHEMA: "gnomon-package-tree:v1";
2361
+ declare const NPM_LOCKFILES: readonly string[];
2362
+ declare const OTHER_LOCKFILES: readonly string[];
2363
+ declare const LIFECYCLE_INSTALL_SCRIPTS: readonly string[];
2364
+ type SnapshotRefusalReason = 'symlink' | 'hardlink' | 'native-addon' | 'escape' | 'special-file' | 'case-collision' | 'not-a-folder' | 'changed-during-copy';
2365
+ interface TreeFile {
2366
+ /** posix path relative to the package root */
2367
+ path: string;
2368
+ sha256: string;
2369
+ size: number;
2370
+ }
2371
+ interface PackageTree {
2372
+ files: TreeFile[];
2373
+ packageHash: string;
2374
+ /** `package@version` from the npm lockfile when node_modules is present. */
2375
+ packages: string[];
2376
+ lockfile: string | null;
2377
+ }
2378
+ declare function computePackageHash(files: readonly TreeFile[]): string;
2379
+ /** The hex part of a `sha256:<hex>` hash (the snapshot directory name). */
2380
+ declare function hashHex(h: string): string;
2381
+ interface WalkEntry {
2382
+ rel: string;
2383
+ abs: string;
2384
+ stat: fs.Stats;
2385
+ }
2386
+ /** Walk a source folder applying every copier refusal; returns regular files only. */
2387
+ declare function walkSource(root: string, name: string, emit: ManifestEventSink): WalkEntry[];
2388
+ /** Read one file once, refusing a swap since the walk (dev/ino/nlink/type re-checked by fstat). */
2389
+ declare function readChecked(e: WalkEntry, name: string, emit: ManifestEventSink): Buffer;
2390
+ /** Hash a source folder in place (no copy) under the copier's refusals — the "full rehash". */
2391
+ declare function hashSourceTree(root: string, name: string, emit: ManifestEventSink): PackageTree & {
2392
+ bytes: Map<string, Buffer>;
2393
+ };
2394
+ /** Hash a pinned snapshot directory (no refusals needed beyond a plain walk; integrity = equality). */
2395
+ declare function hashPinnedTree(dir: string): TreeFile[];
2396
+ declare function modDir(home: string, name: string): string;
2397
+ declare function pinnedDir(home: string, name: string, packageHash: string): string;
2398
+ /** Make a read-only tree writable again and remove it (snapshots are 0500/0400). */
2399
+ declare function removeTree(p: string): void;
2400
+ interface SnapshotResult extends PackageTree {
2401
+ dir: string;
2402
+ /** false when an identical snapshot was already pinned (content-addressed reuse). */
2403
+ created: boolean;
2404
+ }
2405
+ /**
2406
+ * Copy `source` into a content-addressed snapshot for mod `name`. The copy is
2407
+ * hashed after it is written (packageHash is over the copy, §12.5), then
2408
+ * renamed into `pinned/<hex>/` and made read-only.
2409
+ */
2410
+ declare function snapshotFolder(home: string, source: string, name: string, emit: ManifestEventSink): SnapshotResult;
2411
+ interface TreeDiff {
2412
+ added: Array<{
2413
+ path: string;
2414
+ sha256: string;
2415
+ }>;
2416
+ changed: Array<{
2417
+ path: string;
2418
+ from: string;
2419
+ to: string;
2420
+ }>;
2421
+ removed: Array<{
2422
+ path: string;
2423
+ sha256: string;
2424
+ }>;
2425
+ }
2426
+ declare function diffTrees(prev: readonly TreeFile[], next: readonly TreeFile[]): TreeDiff;
2427
+
2428
+ /**
2429
+ * @symbol #manifest-loader
2430
+ *
2431
+ * S0b (mod ids): who owns a `modns.*` event kind. Dependency-free on purpose (the log's redaction, the socket's
2432
+ * log.append gate and the mod host all import it; none may pull the grant reader in).
2433
+ */
2434
+ /**
2435
+ * The FROZEN format-1 alias table (S0b §4): the bare names of the bundled first-party mods before S0b. A test fails if
2436
+ * format-1 support is removed while this table remains (the two expire together).
2437
+ */
2438
+ declare const LEGACY_ALIASES: readonly string[];
2439
+ /**
2440
+ * Does a mod own an event kind (S0b §2)? Its own `modns.<publisher>.<name>.` by WHOLE segments (the trailing dot), or,
2441
+ * for an alias-table entry gnomon.<N> only, its legacy `modns.<N>.` (publisher N is reserved, so nobody else can own it).
2442
+ */
2443
+ declare function ownsModKind(id: string, kind: string): boolean;
2444
+
2445
+ declare const GRANTS_FILE = "grants.jsonl";
2446
+ declare const GRANT_ROW_SCHEMA: "grantRow:v1";
2447
+ /** S0b: the row schema of grant.install / grant.uninstall / grant.publisher (full mod ids). */
2448
+ declare const GRANT_ROW_SCHEMA_V2: "grantRow:v2";
2449
+
2450
+ /** packageHashes of the historical (format-1) first-party pins: an alias resolves to gnomon.<N> only from one of these. */
2451
+ declare const HISTORICAL_FIRST_PARTY_PINS: ReadonlySet<string>;
2452
+ /** Is format 1 still loadable (MANIFEST_FORMAT.accepted)? The alias table is only meaningful while it is. */
2453
+ declare const FORMAT_1_SUPPORTED: boolean;
2454
+ /** The alias of a legacy bare name (S0b §4): the full mod id it resolves to. */
2455
+ declare function aliasOf(legacyName: string, tier: TrustTier | undefined, packageHash: string): string;
2456
+ /** The snapshot directory key of a pin row: the legacy bare name for a resolved v1 row, else the mod id. */
2457
+ declare function pinDirKey(row: {
2458
+ name: string;
2459
+ legacyName?: string;
2460
+ }): string;
2461
+ interface GrantInstallRow {
2462
+ schemaVersion: typeof GRANT_ROW_SCHEMA | typeof GRANT_ROW_SCHEMA_V2;
2463
+ kind: 'grant.install';
2464
+ createdAt: string;
2465
+ /** the full mod id (v2 rows; a resolved v1 row carries its alias here) */
2466
+ name: string;
2467
+ /** a resolved v1 row only: the bare legacy name (never written) */
2468
+ legacyName?: string;
2469
+ manifestHash: string;
2470
+ packageHash: string;
2471
+ cardId: string;
2472
+ source: 'package' | `linked:${string}` | `git:${string}`;
2473
+ /** a format-1 manifest: canonicalManifestHash of its upgraded V2 object (a mismatch at load re-cards) */
2474
+ upgradedHash?: string;
2475
+ dev?: {
2476
+ until: string;
2477
+ };
2478
+ }
2479
+ /** S0b: the TOFU binding of a non-GitHub publisher to (host, namespace). */
2480
+ interface GrantPublisherRow {
2481
+ schemaVersion: typeof GRANT_ROW_SCHEMA_V2;
2482
+ kind: 'grant.publisher';
2483
+ createdAt: string;
2484
+ /** TD-2026-10-20-514 (Aegis Q1): the card whose decision wrote it; REQUIRED on rows written through decision.sign */
2485
+ cardId?: string;
2486
+ publisher: string;
2487
+ host: string;
2488
+ namespace: string;
2489
+ }
2490
+ interface GrantCapabilityRow {
2491
+ schemaVersion: typeof GRANT_ROW_SCHEMA;
2492
+ kind: 'grant.capability';
2493
+ createdAt: string;
2494
+ /** TD-2026-10-20-514 (Aegis Q1): the card whose decision wrote it; REQUIRED on rows written through decision.sign */
2495
+ cardId?: string;
2496
+ manifestHash?: string;
2497
+ deviceId?: string;
2498
+ capabilities: string[];
2499
+ read?: string[];
2500
+ }
2501
+ interface GrantTrustRow {
2502
+ schemaVersion: typeof GRANT_ROW_SCHEMA;
2503
+ kind: 'grant.trust';
2504
+ createdAt: string;
2505
+ /** TD-2026-10-20-514 (Aegis Q1): the card whose decision wrote it; REQUIRED on rows written through decision.sign */
2506
+ cardId?: string;
2507
+ manifestHash: string;
2508
+ tier: TrustTier;
2509
+ maxKnowledgeTier?: string;
2510
+ }
2511
+ interface GrantEgressRow {
2512
+ schemaVersion: typeof GRANT_ROW_SCHEMA;
2513
+ kind: 'grant.egress';
2514
+ createdAt: string;
2515
+ /** TD-2026-10-20-514 (Aegis Q1): the card whose decision wrote it; REQUIRED on rows written through decision.sign */
2516
+ cardId?: string;
2517
+ manifestHash: string;
2518
+ hosts: string[];
2519
+ }
2520
+ interface GrantBindRow {
2521
+ schemaVersion: typeof GRANT_ROW_SCHEMA;
2522
+ kind: 'grant.bind';
2523
+ createdAt: string;
2524
+ /** TD-2026-10-20-514 (Aegis Q1): the card whose decision wrote it; REQUIRED on rows written through decision.sign */
2525
+ cardId?: string;
2526
+ principal: string;
2527
+ manifestHash: string;
2528
+ kinds: string[];
2529
+ }
2530
+ /** M1.11 slice 3: a root-signed uninstall (decided on a root-class card); the effective pin is the LAST install/uninstall row naming the mod. */
2531
+ interface GrantUninstallRow {
2532
+ schemaVersion: typeof GRANT_ROW_SCHEMA | typeof GRANT_ROW_SCHEMA_V2;
2533
+ kind: 'grant.uninstall';
2534
+ createdAt: string;
2535
+ name: string;
2536
+ legacyName?: string;
2537
+ /** the pin it removes */
2538
+ packageHash: string;
2539
+ cardId: string;
2540
+ }
2541
+ type GrantRow = GrantInstallRow | GrantCapabilityRow | GrantTrustRow | GrantEgressRow | GrantBindRow | GrantUninstallRow | GrantPublisherRow;
2542
+ /** What a writer passes: a grant row without schemaVersion (createdAt optional). */
2543
+ type GrantRowInput = GrantRow extends infer R ? (R extends GrantRow ? Omit<R, 'schemaVersion' | 'createdAt'> & {
2544
+ createdAt?: string;
2545
+ } : never) : never;
2546
+ interface ResolvedGrants {
2547
+ capabilities: Map<string, {
2548
+ capabilities: Set<string>;
2549
+ read: string[];
2550
+ }>;
2551
+ trust: Map<string, TrustTier>;
2552
+ egress: Map<string, Set<string>>;
2553
+ binds: GrantBindRow[];
2554
+ installs: GrantInstallRow[];
2555
+ /** grant.install and grant.uninstall rows in file order (effectiveInstall reads this) */
2556
+ pins: Array<GrantInstallRow | GrantUninstallRow>;
2557
+ /** S0b: publisher → its TOFU (host, namespace) binding (last row wins) */
2558
+ /** publisher → its newest accepted binding (Aegis S0b M6: per-publisher strictly increasing createdAt) */
2559
+ publishers: Map<string, {
2560
+ host: string;
2561
+ namespace: string;
2562
+ createdAt?: string;
2563
+ }>;
2564
+ other: Array<{
2565
+ line: number;
2566
+ kind: GrantRowKind;
2567
+ }>;
2568
+ rejected: Array<{
2569
+ line: number;
2570
+ reason: string;
2571
+ }>;
2572
+ }
2573
+ declare function grantsPath(home: string): string;
2574
+ /** Row-shape check; null = valid. Never consults other rows. */
2575
+ declare function checkGrantRow(row: unknown): string | null;
2576
+ /** Read and resolve the grant table against the trust set. Never throws on content. */
2577
+ declare function readGrants(home: string, trust: RowVerifier): ResolvedGrants;
2578
+ /**
2579
+ * Append one root-signed grant row. The row is validated first (an Anthropic
2580
+ * egress host or a knowledge+egress pairing is refused before signing), then
2581
+ * signed by the authority — which refuses UNSUPPORTED until M1.3 in production.
2582
+ */
2583
+ /** The newest accepted pin row's createdAt (ms) for a mod, by the reader's own rule (accepted pins are strictly increasing). */
2584
+ declare function newestPinMs(grants: ResolvedGrants, name: string): number | undefined;
2585
+ /**
2586
+ * TD-2026-10-20-514: build ONE grant row (schemaVersion, createdAt, the replay-safe createdAt bumps and the
2587
+ * knowledge+egress clash) against the table AND the rows already pending in the same batch. Pure: no signing, no
2588
+ * write. A row built here, signed, then rebuilt under the lock must come out identical, or the table moved.
2589
+ */
2590
+ declare function buildGrantRow(home: string, authority: RowVerifier, input: GrantRowInput, now?: Date, pending?: readonly GrantRow[], table?: ResolvedGrants): GrantRow;
2591
+ /** Build every row of one batch in order (each sees the ones before it). */
2592
+ declare function buildGrantRows(home: string, authority: RowVerifier, inputs: readonly GrantRowInput[], now?: Date): GrantRow[];
2593
+ /**
2594
+ * TD-2026-10-20-514 / Aegis C5: append rows that are ALREADY root-signed. Every signature is verified; then, under the
2595
+ * cross-process file lock, every row is rebuilt against the table as it is NOW and must come out byte-identical (a
2596
+ * row whose createdAt went stale, a concurrent pin or binding, a new knowledge/egress clash: refused, nothing is
2597
+ * written and nothing is silently re-signed). ONE write + fsync, grant.install LAST, then the pin read-back.
2598
+ */
2599
+ declare function appendSignedGrantRows(home: string, authority: RowVerifier, rows: readonly GrantRow[], sigs: ReadonlyArray<{
2600
+ signer: string;
2601
+ sig: string;
2602
+ }>): void;
2603
+ /**
2604
+ * Append one root-signed grant row (the CLI path; the daemon's card decisions go through buildGrantRows +
2605
+ * decision.sign + appendSignedGrantRows). Built, signed by the authority (RootUnavailableError without a root),
2606
+ * then re-checked and written under the same lock as the batch path.
2607
+ */
2608
+ declare function appendGrantRow(home: string, authority: RootAuthority, input: GrantRowInput, now?: Date): GrantRow;
2609
+ /**
2610
+ * Aegis F4 (TD-2026-10-20-514): the verified rows ONE decision wrote (its cardId), in file order, when that decision's
2611
+ * anchor (grant.install / grant.uninstall naming the cardId) is among them; else []. A commit whose append landed but
2612
+ * whose decision was not recorded (the pin read-back or the staged write threw) is finished from these rows.
2613
+ */
2614
+ declare function rowsOfDecision(home: string, trust: RowVerifier, cardId: string): GrantRow[];
2615
+ interface GrantCheck {
2616
+ ok: boolean;
2617
+ missingCapabilities: string[];
2618
+ missingEgress: string[];
2619
+ tier: TrustTier | undefined;
2620
+ read: string[];
2621
+ }
2622
+ /** Does the grant table hold every capability and egress host the manifest requires? */
2623
+ declare function checkAgainstGrants(manifest: {
2624
+ requires?: {
2625
+ capabilities?: string[];
2626
+ egress?: 'none' | Array<{
2627
+ host: string;
2628
+ }>;
2629
+ };
2630
+ }, mh: string, grants: ResolvedGrants): GrantCheck;
2631
+ /** The effective install of a mod: the LAST grant.install row naming it (re-pins and rollbacks append), unless a later grant.uninstall names it. */
2632
+ declare function effectiveInstall(grants: ResolvedGrants, name: string): GrantInstallRow | undefined;
2633
+
2634
+ declare const GNOMON_REPO_DIR = ".gnomon";
2635
+ declare const RECORD_SCHEMA: "gnomon-generated-record:v1";
2636
+ declare const TEXT_MARKER = "# gnomon:generated";
2637
+ /** The only directories generateRepo may create or remove. */
2638
+ declare const GENERATED_DIRS: readonly string[];
2639
+ declare const GENERATED_FILES: readonly string[];
2640
+ interface GeneratedRecord {
2641
+ schemaVersion: typeof RECORD_SCHEMA;
2642
+ repo: string;
2643
+ manifestHash: string;
2644
+ files: Array<{
2645
+ path: string;
2646
+ sha256: string;
2647
+ }>;
2648
+ createdDirs: string[];
2649
+ }
2650
+ /** Canonical pretty JSON: sorted keys at every level, 2-space indent, final newline. */
2651
+ declare function stableJson(v: unknown): string;
2652
+ /** The generated file set (posix path under the repo → content), a pure function of the manifest. */
2653
+ declare function renderGenerated(m: ManifestV2): Map<string, string>;
2654
+ /** Kernel-held record path for a repo. */
2655
+ declare function recordPath(home: string, repo: string): string;
2656
+ declare function readRecord(home: string, repo: string): GeneratedRecord | null;
2657
+ /**
2658
+ * T-2026-10-18-008 (M1.7): the generated plugin bytes a session may use, verified at SPAWN against the
2659
+ * kernel-held record — never the repo's bytes on trust. No record ⇒ null (the repo has no generated plugin).
2660
+ * Every recorded generated file under `.gnomon/generated/` is read (confined, O_NOFOLLOW) and must hash to
2661
+ * the record AND carry the marker, else refused GENERATED. The returned bytes are what the session gets
2662
+ * (the supervisor copies them into the kernel's own session dir); the repo files are never passed by path.
2663
+ */
2664
+ declare function verifiedGenerated(repo: string, opts: {
2665
+ home: string;
2666
+ emit?: ManifestEventSink;
2667
+ }): Map<string, Buffer> | null;
2668
+ interface GenerateReport {
2669
+ written: string[];
2670
+ unchanged: string[];
2671
+ manifestHash: string;
2672
+ /** record entries outside the fixed generated set (ignored, never touched) */
2673
+ ignored: string[];
2674
+ }
2675
+ /** Generate (or regenerate) the repo's files. Idempotent; refuses to overwrite a file that is not ours. */
2676
+ declare function generateRepo(repo: string, m: ManifestV2, opts: {
2677
+ home: string;
2678
+ writeProjectYaml?: boolean;
2679
+ emit?: ManifestEventSink;
2680
+ }): GenerateReport;
2681
+ interface UninstallReport {
2682
+ removed: string[];
2683
+ /** generated files whose bytes were edited since generation: kept, never deleted */
2684
+ keptEdited: string[];
2685
+ removedDirs: string[];
2686
+ /** record entries outside the fixed generated set: ignored, never touched */
2687
+ ignored: string[];
2688
+ }
2689
+ declare function uninstallRepo(repo: string, opts: {
2690
+ home: string;
2691
+ emit?: ManifestEventSink;
2692
+ }): UninstallReport;
2693
+ declare function uninstallHome(home: string, opts: {
2694
+ mode: 'remove' | 'keep';
2695
+ emit?: ManifestEventSink;
2696
+ }): {
2697
+ removed: boolean;
2698
+ exportPath: string | null;
2699
+ };
2700
+
2701
+ /** The user's MCP server names (sorted, unique) from user, local and (optionally) project scope. */
2702
+ declare function userMcpServerNames(opts: {
2703
+ userHome?: string;
2704
+ repo?: string;
2705
+ }): string[];
2706
+
2707
+ declare const STAGED_RECORD_SCHEMA: "gnomon-staged-install:v1";
2708
+ type InstallSource = 'package' | `linked:${string}` | `git:${string}`;
2709
+ /** S0b §3: how the bytes compare with the approved history of this mod id (the card's index-3 line). */
2710
+ /** What a publisher binding replaces (Aegis S0b M2). */
2711
+ type PublisherFrom = {
2712
+ host: string;
2713
+ namespace: string;
2714
+ } | 'github.com' | null;
2715
+ type VersionClass = 'first' | 'update' | 'downgrade' | 'revert' | 'same-version-new-bytes' | 'format-only';
2716
+ /** What the install card shows (§12.5), and what its contentHash covers. */
2717
+ interface InstallCardDetail {
2718
+ /** the mod id <publisher>.<name> */
2719
+ name: string;
2720
+ publisher: string;
2721
+ /** how the publisher is shown: `acme`, `acme (unverified, local folder)`, `acme @ gitlab.com` */
2722
+ publisherDisplay: string;
2723
+ /** manifest format of the staged bytes (1 only for a historical first-party pin) */
2724
+ format: 1 | 2;
2725
+ upgradedHash?: string;
2726
+ versionClass: VersionClass;
2727
+ /** the version of the pin this replaces (absent on a first install) */
2728
+ prevVersion?: string;
2729
+ /** the source this replaces when it differs in kind, owner, host or namespace (a source change: always the full card) */
2730
+ sourceChangedFrom?: string;
2731
+ /** another installed third-party publisher this one is a skeleton match of */
2732
+ looksLike?: string;
2733
+ /** the derived MCP server name (absent when the mod has no provides.mcp) */
2734
+ serverName?: string;
2735
+ /** a non-GitHub publisher re-bound to a new (host, namespace) by this card */
2736
+ /**
2737
+ * the publisher binding this install writes (Aegis S0b M2): `from` is the binding it replaces as seen at stage
2738
+ * ({host, namespace}, 'github.com' for the implicit owner claim, or null for a first binding); decide refuses
2739
+ * PUBLISHER unless the binding is still `from`
2740
+ */
2741
+ rebind?: {
2742
+ host: string;
2743
+ namespace: string;
2744
+ from?: PublisherFrom;
2745
+ };
2746
+ kind: ManifestV2['kind'];
2747
+ version: string;
2748
+ source: InstallSource;
2749
+ tier: TrustTier;
2750
+ manifestHash: string;
2751
+ packageHash: string;
2752
+ effects: string[];
2753
+ egress: string[];
2754
+ capabilities: string[];
2755
+ events: string[];
2756
+ tools: string[];
2757
+ views: string[];
2758
+ readPaths: string[];
2759
+ packages: string[];
2760
+ commands: string[];
2761
+ keybindings: string[];
2762
+ knowledge: string[];
2763
+ mcp: string[];
2764
+ hooks: string[];
2765
+ /** the Desk (TD-2026-10-20-812): one line per declared offer; absent when the manifest declares none */
2766
+ offers?: string[];
2767
+ /** counts of the opaque provides arrays (skills, agents, bands, steps, resolvers, blocks, oracles) */
2768
+ opaque: Record<string, number>;
2769
+ /** the effective pin this card would replace, or null for a first install */
2770
+ replaces: {
2771
+ packageHash: string;
2772
+ manifestHash: string;
2773
+ } | null;
2774
+ widened: WideningEntry[];
2775
+ files: TreeDiff;
2776
+ stagedBy: string;
2777
+ hsid?: string;
2778
+ }
2779
+ interface StagedRecord {
2780
+ schemaVersion: typeof STAGED_RECORD_SCHEMA;
2781
+ card: CardV1;
2782
+ detail: InstallCardDetail;
2783
+ manifest: ManifestV2;
2784
+ decision?: {
2785
+ decision: 'install' | 'deny';
2786
+ at: string;
2787
+ };
2788
+ }
2789
+ interface StageOptions {
2790
+ home: string;
2791
+ /** the package path or the linked folder */
2792
+ source: string;
2793
+ via: 'package' | 'linked' | 'git';
2794
+ /**
2795
+ * via 'git': the claimed URL and commit of the fetched checkout in `source` (the fetch itself is S4).
2796
+ * TODO(S4, Aegis S0b L4): the fetch seam MUST run git with `-c http.followRedirects=false` (spec
2797
+ * gnomon-mod-naming-versioning.md §3 Git source: repo-jacking) plus the other D4 clone flags; integrity stays the
2798
+ * packageHash verified here and at load, never the sha40 locator.
2799
+ */
2800
+ git?: {
2801
+ url: string;
2802
+ commit: string;
2803
+ };
2804
+ /** the human asked to re-bind a non-GitHub publisher to this source's (host, namespace) (full card) */
2805
+ rebindPublisher?: boolean;
2806
+ /** MCP server names in the user's .mcp.json (COLLISION) */
2807
+ userMcpServers?: readonly string[];
2808
+ /**
2809
+ * kernel-internal (loadMod's upgradedHash re-card, Aegis S0b L2): the alias publisher of the pinned format-1 row,
2810
+ * and a re-card even when the bytes, manifestHash and source equal the current pin. Never set from a client.
2811
+ */
2812
+ recard?: {
2813
+ legacyPublisher?: 'gnomon' | 'local';
2814
+ };
2815
+ /** a signature over the manifestHash claiming the `signed:<gkey>` tier (refused until trusted keys exist) */
2816
+ signature?: {
2817
+ keyId: string;
2818
+ sig: string;
2819
+ };
2820
+ /** the principal that staged it (an agent session principal for agent-written mods) */
2821
+ requestedBy: string;
2822
+ hsid?: string;
2823
+ attended?: boolean;
2824
+ /** extra read paths a knowledge:provide grant asks for (listed on the card) */
2825
+ readPaths?: string[];
2826
+ trust: RowVerifier;
2827
+ emit?: ManifestEventSink;
2828
+ now?: Date;
2829
+ }
2830
+ type StageResult = {
2831
+ state: 'staged';
2832
+ cardId: string;
2833
+ record: StagedRecord;
2834
+ } | {
2835
+ state: 'unchanged';
2836
+ packageHash: string;
2837
+ };
2838
+ declare function readStaged(home: string, name: string, cardId: string): StagedRecord | null;
2839
+ /** Stage an install (package), a link (folder) or a fetched git checkout. Raises a pending card; takes no effect. */
2840
+ declare function stageInstall(opts: StageOptions): StageResult;
2841
+ interface DecideOptions {
2842
+ presenceToken: unknown;
2843
+ /** MCP server names in the user's .mcp.json (COLLISION, re-checked at decide) */
2844
+ userMcpServers?: readonly string[];
2845
+ authority: RootAuthority;
2846
+ emit?: ManifestEventSink;
2847
+ now?: Date;
2848
+ }
2849
+ type LoadResult = {
2850
+ state: 'ready';
2851
+ name: string;
2852
+ snapshotDir: string;
2853
+ manifest: ManifestV2;
2854
+ packageHash: string;
2855
+ manifestHash: string;
2856
+ tier: TrustTier | undefined;
2857
+ readPaths: string[];
2858
+ source: InstallSource;
2859
+ } | {
2860
+ state: 'paused';
2861
+ name: string;
2862
+ reason: 'changed';
2863
+ cardId: string | null;
2864
+ files: TreeDiff;
2865
+ snapshotDir: string;
2866
+ };
2867
+ interface LoadOptions {
2868
+ home: string;
2869
+ name: string;
2870
+ trust: RowVerifier;
2871
+ emit?: ManifestEventSink;
2872
+ /** principal recorded on a re-approve card raised by a linked-folder change (the kernel) */
2873
+ kernelPrincipal?: string;
2874
+ /** MCP server names in the user's .mcp.json (COLLISION, re-checked at load) */
2875
+ userMcpServers?: readonly string[];
2876
+ }
2877
+ /** Resolve what may load for a mod: from the pinned snapshot only, under its grants. */
2878
+ declare function loadMod(opts: LoadOptions): LoadResult;
2879
+ /** Linked folders of every effective install (the session profile's write denies, regenerated per spawn). */
2880
+ declare function linkedFolders(home: string, trust: RowVerifier): string[];
2881
+
2882
+ /**
2883
+ * @symbol #manifest-loader
2884
+ *
2885
+ * #manifest-loader public surface (spec §3.6). The install-card DECISION and
2886
+ * the rollback are deliberately NOT exported: they live behind the internal
2887
+ * seam channel until the M1.6 approval broker (install.ts header).
2888
+ */
2889
+
2890
+ declare const index_ALWAYS_ASK_TOOLS: typeof ALWAYS_ASK_TOOLS;
2891
+ declare const index_ANTHROPIC_DOMAINS: typeof ANTHROPIC_DOMAINS;
2892
+ declare const index_CLAUDE_SESSION_ENV: typeof CLAUDE_SESSION_ENV;
2893
+ declare const index_CLAUDE_SESSION_ENV_REL: typeof CLAUDE_SESSION_ENV_REL;
2894
+ declare const index_CLAUDE_TRANSCRIPTS_REL: typeof CLAUDE_TRANSCRIPTS_REL;
2895
+ declare const index_COMMAND_UNSAFE: typeof COMMAND_UNSAFE;
2896
+ declare const index_CREDENTIAL_READ_DENY: typeof CREDENTIAL_READ_DENY;
2897
+ type index_DecideOptions = DecideOptions;
2898
+ declare const index_ENGINES_MAX: typeof ENGINES_MAX;
2899
+ type index_EgressRefusalWhy = EgressRefusalWhy;
2900
+ type index_EgressVerdict = EgressVerdict;
2901
+ declare const index_FIRST_PARTY_MOD_NAMES: typeof FIRST_PARTY_MOD_NAMES;
2902
+ declare const index_FIRST_PARTY_ONLY_KINDS: typeof FIRST_PARTY_ONLY_KINDS;
2903
+ declare const index_FORMAT_1_SUPPORTED: typeof FORMAT_1_SUPPORTED;
2904
+ declare const index_FORMAT_INVARIANT_KEYS: typeof FORMAT_INVARIANT_KEYS;
2905
+ declare const index_GENERATED_DIRS: typeof GENERATED_DIRS;
2906
+ declare const index_GENERATED_FILES: typeof GENERATED_FILES;
2907
+ declare const index_GIT_HASH_SCHEMA: typeof GIT_HASH_SCHEMA;
2908
+ declare const index_GNOMON_REPO_DIR: typeof GNOMON_REPO_DIR;
2909
+ declare const index_GRANTS_FILE: typeof GRANTS_FILE;
2910
+ declare const index_GRANT_ROW_SCHEMA: typeof GRANT_ROW_SCHEMA;
2911
+ declare const index_GRANT_ROW_SCHEMA_V2: typeof GRANT_ROW_SCHEMA_V2;
2912
+ type index_GenerateReport = GenerateReport;
2913
+ type index_GeneratedRecord = GeneratedRecord;
2914
+ type index_GrantBindRow = GrantBindRow;
2915
+ type index_GrantCapabilityRow = GrantCapabilityRow;
2916
+ type index_GrantCheck = GrantCheck;
2917
+ type index_GrantEgressRow = GrantEgressRow;
2918
+ type index_GrantInstallRow = GrantInstallRow;
2919
+ type index_GrantPublisherRow = GrantPublisherRow;
2920
+ type index_GrantRow = GrantRow;
2921
+ type index_GrantRowInput = GrantRowInput;
2922
+ type index_GrantTrustRow = GrantTrustRow;
2923
+ type index_GrantUninstallRow = GrantUninstallRow;
2924
+ declare const index_HISTORICAL_FIRST_PARTY_PINS: typeof HISTORICAL_FIRST_PARTY_PINS;
2925
+ declare const index_HOME_READABLE_ROOTS: typeof HOME_READABLE_ROOTS;
2926
+ type index_HashInput = HashInput;
2927
+ type index_InstallCardDetail = InstallCardDetail;
2928
+ type index_InstallSource = InstallSource;
2929
+ declare const index_KERNEL_LOG_PATHS: typeof KERNEL_LOG_PATHS;
2930
+ declare const index_KERNEL_NAMESPACE_TOKENS: typeof KERNEL_NAMESPACE_TOKENS;
2931
+ declare const index_KERNEL_WORKTREES_REL: typeof KERNEL_WORKTREES_REL;
2932
+ declare const index_KNOWN_ABIS: typeof KNOWN_ABIS;
2933
+ declare const index_LAYERS_HASH_SCHEMA: typeof LAYERS_HASH_SCHEMA;
2934
+ declare const index_LEGACY_ALIASES: typeof LEGACY_ALIASES;
2935
+ declare const index_LIFECYCLE_INSTALL_SCRIPTS: typeof LIFECYCLE_INSTALL_SCRIPTS;
2936
+ type index_LayersInput = LayersInput;
2937
+ type index_LoadOptions = LoadOptions;
2938
+ type index_LoadResult = LoadResult;
2939
+ declare const index_MANIFEST_FILE: typeof MANIFEST_FILE;
2940
+ declare const index_MANIFEST_FORMATS_ACCEPTED: typeof MANIFEST_FORMATS_ACCEPTED;
2941
+ declare const index_MANIFEST_FORMAT_CURRENT: typeof MANIFEST_FORMAT_CURRENT;
2942
+ declare const index_MANIFEST_KINDS: typeof MANIFEST_KINDS;
2943
+ declare const index_MANIFEST_REFUSAL_CODES: typeof MANIFEST_REFUSAL_CODES;
2944
+ declare const index_MCP_CONFIG_LIMITS: typeof MCP_CONFIG_LIMITS;
2945
+ declare const index_MCP_ENV_DENY: typeof MCP_ENV_DENY;
2946
+ declare const index_MCP_ENV_DENY_PREFIXES: typeof MCP_ENV_DENY_PREFIXES;
2947
+ declare const index_MCP_ENV_NAME: typeof MCP_ENV_NAME;
2948
+ declare const index_MOD_ABI_V1: typeof MOD_ABI_V1;
2949
+ type index_ManifestCommand = ManifestCommand;
2950
+ type index_ManifestEgress = ManifestEgress;
2951
+ type index_ManifestEventSink = ManifestEventSink;
2952
+ type index_ManifestHook = ManifestHook;
2953
+ type index_ManifestKeybinding = ManifestKeybinding;
2954
+ type index_ManifestKind = ManifestKind;
2955
+ type index_ManifestKnowledge = ManifestKnowledge;
2956
+ type index_ManifestMcp = ManifestMcp;
2957
+ type index_ManifestMcpConfig = ManifestMcpConfig;
2958
+ type index_ManifestRefusal = ManifestRefusal;
2959
+ declare const index_ManifestRefusal: typeof ManifestRefusal;
2960
+ type index_ManifestRefusalCode = ManifestRefusalCode;
2961
+ type index_ManifestTool = ManifestTool;
2962
+ type index_ManifestV2 = ManifestV2;
2963
+ type index_ManifestView = ManifestView;
2964
+ type index_McpUserConfig = McpUserConfig;
2965
+ declare const index_NEVER_REQUESTABLE: typeof NEVER_REQUESTABLE;
2966
+ declare const index_NPM_LOCKFILES: typeof NPM_LOCKFILES;
2967
+ declare const index_OTHER_LOCKFILES: typeof OTHER_LOCKFILES;
2968
+ declare const index_PACKAGE_TREE_SCHEMA: typeof PACKAGE_TREE_SCHEMA;
2969
+ declare const index_PERSISTENCE_PATHS: typeof PERSISTENCE_PATHS;
2970
+ declare const index_PRIVATE_NAME_SUFFIXES: typeof PRIVATE_NAME_SUFFIXES;
2971
+ type index_PackageTree = PackageTree;
2972
+ type index_PathMatch = PathMatch;
2973
+ type index_PolicyPath = PolicyPath;
2974
+ declare const index_RECORD_SCHEMA: typeof RECORD_SCHEMA;
2975
+ declare const index_RESERVED_DECISION_KEYS: typeof RESERVED_DECISION_KEYS;
2976
+ declare const index_RESERVED_MOD_NAMES: typeof RESERVED_MOD_NAMES;
2977
+ type index_ReadManifestOptions = ReadManifestOptions;
2978
+ type index_ReadManifestResult = ReadManifestResult;
2979
+ type index_ResolvedGrants = ResolvedGrants;
2980
+ declare const index_SESSION_CACHE_ENV: typeof SESSION_CACHE_ENV;
2981
+ declare const index_SESSION_DENY_CLASSES: typeof SESSION_DENY_CLASSES;
2982
+ declare const index_SESSION_POLICY_SCHEMA: typeof SESSION_POLICY_SCHEMA;
2983
+ declare const index_SESSION_UUID_RE: typeof SESSION_UUID_RE;
2984
+ declare const index_STAGED_RECORD_SCHEMA: typeof STAGED_RECORD_SCHEMA;
2985
+ type index_SessionDenyClass = SessionDenyClass;
2986
+ type index_SessionPolicy = SessionPolicy;
2987
+ type index_SessionPolicyInput = SessionPolicyInput;
2988
+ type index_SnapshotRefusalReason = SnapshotRefusalReason;
2989
+ type index_SnapshotResult = SnapshotResult;
2990
+ type index_StageOptions = StageOptions;
2991
+ type index_StageResult = StageResult;
2992
+ type index_StagedRecord = StagedRecord;
2993
+ declare const index_TEXT_MARKER: typeof TEXT_MARKER;
2994
+ declare const index_TOOL_EFFECTS: typeof TOOL_EFFECTS;
2995
+ declare const index_TRUST_TIER_PATTERN: typeof TRUST_TIER_PATTERN;
2996
+ type index_ToolEffect = ToolEffect;
2997
+ type index_TreeDiff = TreeDiff;
2998
+ type index_TreeFile = TreeFile;
2999
+ type index_TrustTier = TrustTier;
3000
+ type index_UninstallReport = UninstallReport;
3001
+ type index_UnresolvablePath = UnresolvablePath;
3002
+ declare const index_UnresolvablePath: typeof UnresolvablePath;
3003
+ declare const index_VERSION_MAX: typeof VERSION_MAX;
3004
+ type index_ValidateManifestOptions = ValidateManifestOptions;
3005
+ declare const index_WIDENING_FIELDS: typeof WIDENING_FIELDS;
3006
+ declare const index_WRITE_CACHE_PATHS: typeof WRITE_CACHE_PATHS;
3007
+ declare const index_WRITE_TEMP_PATHS: typeof WRITE_TEMP_PATHS;
3008
+ type index_WalkEntry = WalkEntry;
3009
+ type index_WideningEntry = WideningEntry;
3010
+ type index_WideningField = WideningField;
3011
+ declare const index_aliasOf: typeof aliasOf;
3012
+ declare const index_appendGrantRow: typeof appendGrantRow;
3013
+ declare const index_appendSignedGrantRows: typeof appendSignedGrantRows;
3014
+ declare const index_buildGrantRow: typeof buildGrantRow;
3015
+ declare const index_buildGrantRows: typeof buildGrantRows;
3016
+ declare const index_buildSessionPolicy: typeof buildSessionPolicy;
3017
+ declare const index_canonicalManifestHash: typeof canonicalManifestHash;
3018
+ declare const index_capabilityForm: typeof capabilityForm;
3019
+ declare const index_checkAgainstGrants: typeof checkAgainstGrants;
3020
+ declare const index_checkEgressHost: typeof checkEgressHost;
3021
+ declare const index_checkGrantRow: typeof checkGrantRow;
3022
+ declare const index_claudePermissions: typeof claudePermissions;
3023
+ declare const index_collectGitInputs: typeof collectGitInputs;
3024
+ declare const index_collectLayerInputs: typeof collectLayerInputs;
3025
+ declare const index_compareVersions: typeof compareVersions;
3026
+ declare const index_computePackageHash: typeof computePackageHash;
3027
+ declare const index_defaultClaudeJson: typeof defaultClaudeJson;
3028
+ declare const index_detectWidening: typeof detectWidening;
3029
+ declare const index_diffTrees: typeof diffTrees;
3030
+ declare const index_digestInputs: typeof digestInputs;
3031
+ declare const index_effectiveInstall: typeof effectiveInstall;
3032
+ declare const index_enginesAdmit: typeof enginesAdmit;
3033
+ declare const index_gateClassPathRule: typeof gateClassPathRule;
3034
+ declare const index_generateRepo: typeof generateRepo;
3035
+ declare const index_gitHash: typeof gitHash;
3036
+ declare const index_grantsPath: typeof grantsPath;
3037
+ declare const index_hashHex: typeof hashHex;
3038
+ declare const index_hashPinnedTree: typeof hashPinnedTree;
3039
+ declare const index_hashSourceTree: typeof hashSourceTree;
3040
+ declare const index_isAnthropicHost: typeof isAnthropicHost;
3041
+ declare const index_isClosureName: typeof isClosureName;
3042
+ declare const index_isConfigNamedEnvFile: typeof isConfigNamedEnvFile;
3043
+ declare const index_isManifestRefusal: typeof isManifestRefusal;
3044
+ declare const index_layersHash: typeof layersHash;
3045
+ declare const index_linkedFolders: typeof linkedFolders;
3046
+ declare const index_loadMod: typeof loadMod;
3047
+ declare const index_localRunnerDenies: typeof localRunnerDenies;
3048
+ declare const index_manifestHash: typeof manifestHash;
3049
+ declare const index_mcpEnvOwnPrefix: typeof mcpEnvOwnPrefix;
3050
+ declare const index_modDir: typeof modDir;
3051
+ declare const index_newestPinMs: typeof newestPinMs;
3052
+ declare const index_noEvents: typeof noEvents;
3053
+ declare const index_normalizeContent: typeof normalizeContent;
3054
+ declare const index_normalizeHost: typeof normalizeHost;
3055
+ declare const index_normalizeLayerKey: typeof normalizeLayerKey;
3056
+ declare const index_ownsModKind: typeof ownsModKind;
3057
+ declare const index_parseEngines: typeof parseEngines;
3058
+ declare const index_pinDirKey: typeof pinDirKey;
3059
+ declare const index_pinnedDir: typeof pinnedDir;
3060
+ declare const index_policyHash: typeof policyHash;
3061
+ declare const index_readChecked: typeof readChecked;
3062
+ declare const index_readGrants: typeof readGrants;
3063
+ declare const index_readManifest: typeof readManifest;
3064
+ declare const index_readRecord: typeof readRecord;
3065
+ declare const index_readStaged: typeof readStaged;
3066
+ declare const index_realpathFollow: typeof realpathFollow;
3067
+ declare const index_realpathLoose: typeof realpathLoose;
3068
+ declare const index_recordPath: typeof recordPath;
3069
+ declare const index_removeTree: typeof removeTree;
3070
+ declare const index_renderGenerated: typeof renderGenerated;
3071
+ declare const index_resolveGitDirs: typeof resolveGitDirs;
3072
+ declare const index_resolveMcpLaunch: typeof resolveMcpLaunch;
3073
+ declare const index_rowsOfDecision: typeof rowsOfDecision;
3074
+ declare const index_snapshotFolder: typeof snapshotFolder;
3075
+ declare const index_stableJson: typeof stableJson;
3076
+ declare const index_stageInstall: typeof stageInstall;
3077
+ declare const index_uninstallHome: typeof uninstallHome;
3078
+ declare const index_uninstallRepo: typeof uninstallRepo;
3079
+ declare const index_upgradeManifestV1: typeof upgradeManifestV1;
3080
+ declare const index_userMcpServerNames: typeof userMcpServerNames;
3081
+ declare const index_userTempRoot: typeof userTempRoot;
3082
+ declare const index_validateManifest: typeof validateManifest;
3083
+ declare const index_validateMcpUserConfig: typeof validateMcpUserConfig;
3084
+ declare const index_verifiedGenerated: typeof verifiedGenerated;
3085
+ declare const index_walkSource: typeof walkSource;
3086
+ declare namespace index {
3087
+ export { index_ALWAYS_ASK_TOOLS as ALWAYS_ASK_TOOLS, index_ANTHROPIC_DOMAINS as ANTHROPIC_DOMAINS, index_CLAUDE_SESSION_ENV as CLAUDE_SESSION_ENV, index_CLAUDE_SESSION_ENV_REL as CLAUDE_SESSION_ENV_REL, index_CLAUDE_TRANSCRIPTS_REL as CLAUDE_TRANSCRIPTS_REL, index_COMMAND_UNSAFE as COMMAND_UNSAFE, index_CREDENTIAL_READ_DENY as CREDENTIAL_READ_DENY, index_ENGINES_MAX as ENGINES_MAX, index_FIRST_PARTY_MOD_NAMES as FIRST_PARTY_MOD_NAMES, index_FIRST_PARTY_ONLY_KINDS as FIRST_PARTY_ONLY_KINDS, index_FORMAT_1_SUPPORTED as FORMAT_1_SUPPORTED, index_FORMAT_INVARIANT_KEYS as FORMAT_INVARIANT_KEYS, index_GENERATED_DIRS as GENERATED_DIRS, index_GENERATED_FILES as GENERATED_FILES, index_GIT_HASH_SCHEMA as GIT_HASH_SCHEMA, index_GNOMON_REPO_DIR as GNOMON_REPO_DIR, index_GRANTS_FILE as GRANTS_FILE, index_GRANT_ROW_SCHEMA as GRANT_ROW_SCHEMA, index_GRANT_ROW_SCHEMA_V2 as GRANT_ROW_SCHEMA_V2, index_HISTORICAL_FIRST_PARTY_PINS as HISTORICAL_FIRST_PARTY_PINS, index_HOME_READABLE_ROOTS as HOME_READABLE_ROOTS, index_KERNEL_LOG_PATHS as KERNEL_LOG_PATHS, index_KERNEL_NAMESPACE_TOKENS as KERNEL_NAMESPACE_TOKENS, index_KERNEL_WORKTREES_REL as KERNEL_WORKTREES_REL, index_KNOWN_ABIS as KNOWN_ABIS, index_LAYERS_HASH_SCHEMA as LAYERS_HASH_SCHEMA, index_LEGACY_ALIASES as LEGACY_ALIASES, index_LIFECYCLE_INSTALL_SCRIPTS as LIFECYCLE_INSTALL_SCRIPTS, index_MANIFEST_FILE as MANIFEST_FILE, index_MANIFEST_FORMATS_ACCEPTED as MANIFEST_FORMATS_ACCEPTED, index_MANIFEST_FORMAT_CURRENT as MANIFEST_FORMAT_CURRENT, index_MANIFEST_KINDS as MANIFEST_KINDS, index_MANIFEST_REFUSAL_CODES as MANIFEST_REFUSAL_CODES, index_MCP_CONFIG_LIMITS as MCP_CONFIG_LIMITS, index_MCP_ENV_DENY as MCP_ENV_DENY, index_MCP_ENV_DENY_PREFIXES as MCP_ENV_DENY_PREFIXES, index_MCP_ENV_NAME as MCP_ENV_NAME, index_MOD_ABI_V1 as MOD_ABI_V1, index_ManifestRefusal as ManifestRefusal, index_NEVER_REQUESTABLE as NEVER_REQUESTABLE, index_NPM_LOCKFILES as NPM_LOCKFILES, index_OTHER_LOCKFILES as OTHER_LOCKFILES, index_PACKAGE_TREE_SCHEMA as PACKAGE_TREE_SCHEMA, index_PERSISTENCE_PATHS as PERSISTENCE_PATHS, index_PRIVATE_NAME_SUFFIXES as PRIVATE_NAME_SUFFIXES, index_RECORD_SCHEMA as RECORD_SCHEMA, index_RESERVED_DECISION_KEYS as RESERVED_DECISION_KEYS, index_RESERVED_MOD_NAMES as RESERVED_MOD_NAMES, index_SESSION_CACHE_ENV as SESSION_CACHE_ENV, index_SESSION_DENY_CLASSES as SESSION_DENY_CLASSES, index_SESSION_POLICY_SCHEMA as SESSION_POLICY_SCHEMA, index_SESSION_UUID_RE as SESSION_UUID_RE, index_STAGED_RECORD_SCHEMA as STAGED_RECORD_SCHEMA, index_TEXT_MARKER as TEXT_MARKER, index_TOOL_EFFECTS as TOOL_EFFECTS, index_TRUST_TIER_PATTERN as TRUST_TIER_PATTERN, index_UnresolvablePath as UnresolvablePath, index_VERSION_MAX as VERSION_MAX, index_WIDENING_FIELDS as WIDENING_FIELDS, index_WRITE_CACHE_PATHS as WRITE_CACHE_PATHS, index_WRITE_TEMP_PATHS as WRITE_TEMP_PATHS, index_aliasOf as aliasOf, index_appendGrantRow as appendGrantRow, index_appendSignedGrantRows as appendSignedGrantRows, index_buildGrantRow as buildGrantRow, index_buildGrantRows as buildGrantRows, index_buildSessionPolicy as buildSessionPolicy, index_canonicalManifestHash as canonicalManifestHash, index_capabilityForm as capabilityForm, index_checkAgainstGrants as checkAgainstGrants, index_checkEgressHost as checkEgressHost, index_checkGrantRow as checkGrantRow, index_claudePermissions as claudePermissions, index_collectGitInputs as collectGitInputs, index_collectLayerInputs as collectLayerInputs, index_compareVersions as compareVersions, index_computePackageHash as computePackageHash, index_defaultClaudeJson as defaultClaudeJson, index_detectWidening as detectWidening, index_diffTrees as diffTrees, index_digestInputs as digestInputs, index_effectiveInstall as effectiveInstall, index_enginesAdmit as enginesAdmit, index_gateClassPathRule as gateClassPathRule, index_generateRepo as generateRepo, index_gitHash as gitHash, index_grantsPath as grantsPath, index_hashHex as hashHex, index_hashPinnedTree as hashPinnedTree, index_hashSourceTree as hashSourceTree, index_isAnthropicHost as isAnthropicHost, index_isClosureName as isClosureName, index_isConfigNamedEnvFile as isConfigNamedEnvFile, index_isManifestRefusal as isManifestRefusal, index_layersHash as layersHash, index_linkedFolders as linkedFolders, index_loadMod as loadMod, index_localRunnerDenies as localRunnerDenies, index_manifestHash as manifestHash, index_mcpEnvOwnPrefix as mcpEnvOwnPrefix, index_modDir as modDir, index_newestPinMs as newestPinMs, index_noEvents as noEvents, index_normalizeContent as normalizeContent, index_normalizeHost as normalizeHost, index_normalizeLayerKey as normalizeLayerKey, index_ownsModKind as ownsModKind, index_parseEngines as parseEngines, index_pinDirKey as pinDirKey, index_pinnedDir as pinnedDir, index_policyHash as policyHash, index_readChecked as readChecked, index_readGrants as readGrants, index_readManifest as readManifest, index_readRecord as readRecord, index_readStaged as readStaged, index_realpathFollow as realpathFollow, index_realpathLoose as realpathLoose, index_recordPath as recordPath, index_removeTree as removeTree, index_renderGenerated as renderGenerated, index_resolveGitDirs as resolveGitDirs, index_resolveMcpLaunch as resolveMcpLaunch, index_rowsOfDecision as rowsOfDecision, index_snapshotFolder as snapshotFolder, index_stableJson as stableJson, index_stageInstall as stageInstall, index_uninstallHome as uninstallHome, index_uninstallRepo as uninstallRepo, index_upgradeManifestV1 as upgradeManifestV1, index_userMcpServerNames as userMcpServerNames, index_userTempRoot as userTempRoot, index_validateManifest as validateManifest, index_validateMcpUserConfig as validateMcpUserConfig, index_verifiedGenerated as verifiedGenerated, index_walkSource as walkSource };
3088
+ export type { index_DecideOptions as DecideOptions, index_EgressRefusalWhy as EgressRefusalWhy, index_EgressVerdict as EgressVerdict, index_GenerateReport as GenerateReport, index_GeneratedRecord as GeneratedRecord, index_GrantBindRow as GrantBindRow, index_GrantCapabilityRow as GrantCapabilityRow, index_GrantCheck as GrantCheck, index_GrantEgressRow as GrantEgressRow, index_GrantInstallRow as GrantInstallRow, index_GrantPublisherRow as GrantPublisherRow, index_GrantRow as GrantRow, index_GrantRowInput as GrantRowInput, index_GrantTrustRow as GrantTrustRow, index_GrantUninstallRow as GrantUninstallRow, index_HashInput as HashInput, index_InstallCardDetail as InstallCardDetail, index_InstallSource as InstallSource, index_LayersInput as LayersInput, index_LoadOptions as LoadOptions, index_LoadResult as LoadResult, index_ManifestCommand as ManifestCommand, index_ManifestEgress as ManifestEgress, index_ManifestEventSink as ManifestEventSink, index_ManifestHook as ManifestHook, index_ManifestKeybinding as ManifestKeybinding, index_ManifestKind as ManifestKind, index_ManifestKnowledge as ManifestKnowledge, index_ManifestMcp as ManifestMcp, index_ManifestMcpConfig as ManifestMcpConfig, index_ManifestRefusalCode as ManifestRefusalCode, index_ManifestTool as ManifestTool, index_ManifestV2 as ManifestV2, index_ManifestView as ManifestView, index_McpUserConfig as McpUserConfig, index_PackageTree as PackageTree, index_PathMatch as PathMatch, index_PolicyPath as PolicyPath, index_ReadManifestOptions as ReadManifestOptions, index_ReadManifestResult as ReadManifestResult, index_ResolvedGrants as ResolvedGrants, index_SessionDenyClass as SessionDenyClass, index_SessionPolicy as SessionPolicy, index_SessionPolicyInput as SessionPolicyInput, index_SnapshotRefusalReason as SnapshotRefusalReason, index_SnapshotResult as SnapshotResult, index_StageOptions as StageOptions, index_StageResult as StageResult, index_StagedRecord as StagedRecord, index_ToolEffect as ToolEffect, index_TreeDiff as TreeDiff, index_TreeFile as TreeFile, index_TrustTier as TrustTier, index_UninstallReport as UninstallReport, index_ValidateManifestOptions as ValidateManifestOptions, index_WalkEntry as WalkEntry, index_WideningEntry as WideningEntry, index_WideningField as WideningField };
3089
+ }
3090
+
3091
+ /** The generated plugin's name: its items appear as `project:<name>`. */
3092
+ declare const REPO_CONTEXT_PLUGIN = "project";
3093
+ /** The child env that makes Claude load `--add-dir` memory (CLAUDE.md, .claude/CLAUDE.md, .claude/rules). */
3094
+ declare const REPO_CONTEXT_ENV: Readonly<Record<string, string>>;
3095
+ declare const SKILL_KEYS: readonly string[];
3096
+ declare const AGENT_KEYS: readonly string[];
3097
+ declare const COMMAND_KEYS: readonly string[];
3098
+ declare const MAX_CONTEXT_FILES = 1024;
3099
+ declare const MAX_CONTEXT_BYTES: number;
3100
+ declare const MAX_CONTEXT_FILE_BYTES: number;
3101
+ declare const MAX_TREE_DEPTH = 6;
3102
+ /**
3103
+ * H2 (Aegis): Claude Code runs `!`cmd`` and ```! fenced blocks in skills and commands BEFORE the model sees them.
3104
+ * Fail closed: a skill or command that contains either is not loaded, and the session's policy.json also sets
3105
+ * REPO_CONTEXT_SETTINGS.disableSkillShellExecution (2.1.303: "Commands are replaced with a placeholder").
3106
+ */
3107
+ declare function hasShellPreprocessing(text: string): boolean;
3108
+ /** Kernel settings merged into an audited session's policy.json (P8-D97, H2). */
3109
+ declare const REPO_CONTEXT_SETTINGS: Readonly<{
3110
+ disableSkillShellExecution: true;
3111
+ }>;
3112
+ type SanitizeResult = {
3113
+ ok: true;
3114
+ text: string;
3115
+ dropped: string[];
3116
+ hooks: boolean;
3117
+ } | {
3118
+ ok: false;
3119
+ why: string;
3120
+ };
3121
+ /**
3122
+ * Keep only the allowed top-level frontmatter keys (and their indented or `- ` continuation lines). Fail closed:
3123
+ * anything that is not a plain `key:` line, a continuation, a blank or a comment refuses the whole file.
3124
+ */
3125
+ declare function sanitizeFrontmatter(raw: string, allowed: readonly string[]): SanitizeResult;
3126
+ interface RepoContext {
3127
+ /** the generated plugin dir, or null when the repo has no skill, agent or command to load */
3128
+ pluginDir: string | null;
3129
+ /** `--add-dir` targets for memory (outermost first), each passed by auditMemoryDir */
3130
+ memoryDirs: string[];
3131
+ /** F3: every in-repo `@` import target of the added memory dirs (existing or not): write-denied as literals */
3132
+ importTargets: string[];
3133
+ /** H1: memory dirs NOT added (relative to the git top-level), with why: a symlink, or an @ import leaving the repo */
3134
+ memoryRefused: Array<{
3135
+ dir: string;
3136
+ why: string;
3137
+ }>;
3138
+ skills: string[];
3139
+ agents: string[];
3140
+ commands: string[];
3141
+ /** repo-relative paths not loaded, with why */
3142
+ refused: Array<{
3143
+ path: string;
3144
+ why: string;
3145
+ }>;
3146
+ /** repo-relative paths whose frontmatter lost keys (hooks, allowed-tools, permissionMode, unknown) */
3147
+ dropped: Array<{
3148
+ path: string;
3149
+ keys: string[];
3150
+ }>;
3151
+ /** repo-relative paths whose frontmatter declared `hooks` (stripped: never run) */
3152
+ frontmatterHooks: string[];
3153
+ }
3154
+ /**
3155
+ * The memory chain: the cwd and its ancestors up to the git top-level (innermost first), never the user home or
3156
+ * above; without a git top-level, the cwd alone. `top` bounds every `@` import (the git top-level, else the cwd).
3157
+ */
3158
+ declare function memoryChainOf(cwd: string, userHome: string): {
3159
+ chain: string[];
3160
+ top: string;
3161
+ };
3162
+ /** The memory dirs that hold memory, outermost first (unaudited: buildRepoContext audits them). */
3163
+ declare function memoryDirsOf(cwd: string, userHome: string): string[];
3164
+ declare const MAX_IMPORT_DEPTH = 5;
3165
+ /**
3166
+ * The `@` imports of a memory file, resolved the way Claude resolves them (`~/` = the user home). Code spans are NOT
3167
+ * skipped (stricter than Claude). `refuse` is set when the file carries an entity-encoded `@` or an import token
3168
+ * containing `%` (R2: no percent-encoded path tricks).
3169
+ */
3170
+ declare function importAudit(text: string, file: string, userHome: string): {
3171
+ targets: string[];
3172
+ refuse: string | null;
3173
+ };
3174
+ /** The resolved import targets only (see importAudit). */
3175
+ declare function importTargets(text: string, file: string, userHome: string): string[];
3176
+ /** R1: the most directories one memory dir's subtree walk visits; past it the dir is refused (fail closed). */
3177
+ declare const MAX_SUBTREE_DIRS = 200000;
3178
+ /**
3179
+ * R1 (Aegis): EVERY memory file in a memory dir's SUBTREE — Claude Code loads a subdirectory's CLAUDE.md lazily, when
3180
+ * it reads files there. Collected in any letter case (APFS, NTFS): every `claude.md` at any depth (so
3181
+ * `.claude/CLAUDE.md` too), and every `.md` under a `.claude/rules` dir. A symlink named `claude.md` or `.claude`, or
3182
+ * anything symlinked inside `.claude/rules`, refuses; other symlinks are not followed. The VCS dir and `node_modules`
3183
+ * dirs are skipped (dependency trees: 80% of a real repo's dirs; their CLAUDE.md is a residual, writes there stay
3184
+ * denied by the `steering` match). An
3185
+ * unreadable dir, or more than `maxDirs` dirs, refuses (fail closed).
3186
+ */
3187
+ declare function memoryFilesUnder(dir: string, maxDirs?: number, top?: string): {
3188
+ ok: true;
3189
+ files: string[];
3190
+ dirs: number;
3191
+ } | {
3192
+ ok: false;
3193
+ why: string;
3194
+ };
3195
+ /**
3196
+ * H1 (Aegis): audit one memory dir in the KERNEL. Refused (the whole dir is not added) when any memory file is a
3197
+ * symlink, unreadable or oversized, or when any `@` import followed recursively (depth MAX_IMPORT_DEPTH, `~`,
3198
+ * absolute and relative forms) names an existing path outside `top`, or a symlink. A target that does not exist is
3199
+ * nothing Claude can load and is ignored.
3200
+ */
3201
+ /** F3: the most distinct in-repo import targets one memory dir may name (each becomes a write-deny literal). */
3202
+ declare const MAX_IMPORT_TARGETS = 4096;
3203
+ declare function auditMemoryDir(dir: string, top: string, userHome: string, maxDirs?: number, walked?: {
3204
+ ok: true;
3205
+ files: string[];
3206
+ }): {
3207
+ ok: true;
3208
+ imports: string[];
3209
+ } | {
3210
+ ok: false;
3211
+ why: string;
3212
+ };
3213
+ /**
3214
+ * Build the session's repo context: the memory dirs and the generated plugin under `outDir` (wiped first).
3215
+ * Reads only `<cwd>/.claude/{skills,agents,commands}` and the memory files' presence; writes only under outDir.
3216
+ */
3217
+ declare function buildRepoContext(i: {
3218
+ cwd: string;
3219
+ userHome: string;
3220
+ outDir: string;
3221
+ maxSubtreeDirs?: number;
3222
+ }): RepoContext;
3223
+ /** What the repo's settings layers carry besides hooks: NOT loaded (P8-D97), reported only. Never a value. */
3224
+ interface RepoSettingsInfo {
3225
+ files: string[];
3226
+ permissions: {
3227
+ allow: number;
3228
+ ask: number;
3229
+ deny: number;
3230
+ other: string[];
3231
+ };
3232
+ envKeys: string[];
3233
+ otherKeys: string[];
3234
+ unreadable: string[];
3235
+ }
3236
+ declare function repoSettingsInfo(roots: readonly string[]): RepoSettingsInfo;
3237
+ /** The informational card lines (kernel-composed, bounded): empty when the repo sets nothing besides hooks. */
3238
+ declare function repoSettingsLines(info: RepoSettingsInfo): string[];
3239
+ /** The `gate-class.detected{what:'repo-context'}` payload (names and counts only, bounded). */
3240
+ declare function repoContextRow(hsid: string, ctx: RepoContext, info: RepoSettingsInfo): Record<string, unknown>;
3241
+ /** The repo-card lines about the context (kernel-composed): what memory and which items were refused. */
3242
+ declare function repoContextLines(ctx: RepoContext): string[];
3243
+
3244
+ declare const repoContext_AGENT_KEYS: typeof AGENT_KEYS;
3245
+ declare const repoContext_COMMAND_KEYS: typeof COMMAND_KEYS;
3246
+ declare const repoContext_MAX_CONTEXT_BYTES: typeof MAX_CONTEXT_BYTES;
3247
+ declare const repoContext_MAX_CONTEXT_FILES: typeof MAX_CONTEXT_FILES;
3248
+ declare const repoContext_MAX_CONTEXT_FILE_BYTES: typeof MAX_CONTEXT_FILE_BYTES;
3249
+ declare const repoContext_MAX_IMPORT_DEPTH: typeof MAX_IMPORT_DEPTH;
3250
+ declare const repoContext_MAX_IMPORT_TARGETS: typeof MAX_IMPORT_TARGETS;
3251
+ declare const repoContext_MAX_SUBTREE_DIRS: typeof MAX_SUBTREE_DIRS;
3252
+ declare const repoContext_MAX_TREE_DEPTH: typeof MAX_TREE_DEPTH;
3253
+ declare const repoContext_REPO_CONTEXT_ENV: typeof REPO_CONTEXT_ENV;
3254
+ declare const repoContext_REPO_CONTEXT_PLUGIN: typeof REPO_CONTEXT_PLUGIN;
3255
+ declare const repoContext_REPO_CONTEXT_SETTINGS: typeof REPO_CONTEXT_SETTINGS;
3256
+ type repoContext_RepoContext = RepoContext;
3257
+ type repoContext_RepoSettingsInfo = RepoSettingsInfo;
3258
+ declare const repoContext_SKILL_KEYS: typeof SKILL_KEYS;
3259
+ type repoContext_SanitizeResult = SanitizeResult;
3260
+ declare const repoContext_auditMemoryDir: typeof auditMemoryDir;
3261
+ declare const repoContext_buildRepoContext: typeof buildRepoContext;
3262
+ declare const repoContext_hasShellPreprocessing: typeof hasShellPreprocessing;
3263
+ declare const repoContext_importAudit: typeof importAudit;
3264
+ declare const repoContext_importTargets: typeof importTargets;
3265
+ declare const repoContext_memoryChainOf: typeof memoryChainOf;
3266
+ declare const repoContext_memoryDirsOf: typeof memoryDirsOf;
3267
+ declare const repoContext_memoryFilesUnder: typeof memoryFilesUnder;
3268
+ declare const repoContext_repoContextLines: typeof repoContextLines;
3269
+ declare const repoContext_repoContextRow: typeof repoContextRow;
3270
+ declare const repoContext_repoSettingsInfo: typeof repoSettingsInfo;
3271
+ declare const repoContext_repoSettingsLines: typeof repoSettingsLines;
3272
+ declare const repoContext_sanitizeFrontmatter: typeof sanitizeFrontmatter;
3273
+ declare namespace repoContext {
3274
+ export { repoContext_AGENT_KEYS as AGENT_KEYS, repoContext_COMMAND_KEYS as COMMAND_KEYS, repoContext_MAX_CONTEXT_BYTES as MAX_CONTEXT_BYTES, repoContext_MAX_CONTEXT_FILES as MAX_CONTEXT_FILES, repoContext_MAX_CONTEXT_FILE_BYTES as MAX_CONTEXT_FILE_BYTES, repoContext_MAX_IMPORT_DEPTH as MAX_IMPORT_DEPTH, repoContext_MAX_IMPORT_TARGETS as MAX_IMPORT_TARGETS, repoContext_MAX_SUBTREE_DIRS as MAX_SUBTREE_DIRS, repoContext_MAX_TREE_DEPTH as MAX_TREE_DEPTH, repoContext_REPO_CONTEXT_ENV as REPO_CONTEXT_ENV, repoContext_REPO_CONTEXT_PLUGIN as REPO_CONTEXT_PLUGIN, repoContext_REPO_CONTEXT_SETTINGS as REPO_CONTEXT_SETTINGS, repoContext_SKILL_KEYS as SKILL_KEYS, repoContext_auditMemoryDir as auditMemoryDir, repoContext_buildRepoContext as buildRepoContext, repoContext_hasShellPreprocessing as hasShellPreprocessing, repoContext_importAudit as importAudit, repoContext_importTargets as importTargets, repoContext_memoryChainOf as memoryChainOf, repoContext_memoryDirsOf as memoryDirsOf, repoContext_memoryFilesUnder as memoryFilesUnder, repoContext_repoContextLines as repoContextLines, repoContext_repoContextRow as repoContextRow, repoContext_repoSettingsInfo as repoSettingsInfo, repoContext_repoSettingsLines as repoSettingsLines, repoContext_sanitizeFrontmatter as sanitizeFrontmatter };
3275
+ export type { repoContext_RepoContext as RepoContext, repoContext_RepoSettingsInfo as RepoSettingsInfo, repoContext_SanitizeResult as SanitizeResult };
3276
+ }
3277
+
3278
+ declare const REPO_HOOK_FILES: readonly [{
3279
+ readonly source: "project";
3280
+ readonly rel: readonly [".claude", "settings.json"];
3281
+ }, {
3282
+ readonly source: "local";
3283
+ readonly rel: readonly [".claude", "settings.local.json"];
3284
+ }];
3285
+ declare const MAX_SETTINGS_BYTES: number;
3286
+ declare const MAX_REPO_HOOKS = 64;
3287
+ /** pending (raised, undecided) cards remembered per process; the oldest is forgotten past this (re-raised on the next open) */
3288
+ declare const MAX_PENDING_HOOK_CARDS = 256;
3289
+ interface RepoHook {
3290
+ hookId: string;
3291
+ source: 'project' | 'local';
3292
+ event: string;
3293
+ matcher: string | null;
3294
+ command: string;
3295
+ timeout: number | null;
3296
+ }
3297
+ type RepoHookSet = {
3298
+ status: 'none';
3299
+ repoKey: string;
3300
+ setHash: null;
3301
+ hooks: [];
3302
+ refused: [];
3303
+ } | {
3304
+ status: 'ok';
3305
+ repoKey: string;
3306
+ setHash: string;
3307
+ hooks: RepoHook[];
3308
+ refused: string[];
3309
+ } | {
3310
+ status: 'unreadable' | 'too-many';
3311
+ repoKey: string;
3312
+ setHash: null;
3313
+ hooks: [];
3314
+ refused: [];
3315
+ why: string;
3316
+ };
3317
+ /** The session roots realpath'd and deduped (a worktree equal to cwd counts once). */
3318
+ declare function uniqueRoots(roots: readonly string[]): string[];
3319
+ /** One key per repo root (realpath'd, deduped cwd + worktree). */
3320
+ declare function repoKeyOf(roots: readonly string[]): string;
3321
+ /**
3322
+ * The hook events Claude Code supports (Aegis C1): anything else is refused,
3323
+ * so no repo-controlled name ever becomes a key the kernel did not expect.
3324
+ */
3325
+ declare const CLAUDE_HOOK_EVENTS: readonly string[];
3326
+ /** refused hook ids carried on a gate-class.detected row (the set is bounded by MAX_REPO_HOOKS too) */
3327
+ declare const MAX_REFUSED_LOGGED = 64;
3328
+ /** Read one settings layer: O_NOFOLLOW + fstat (no symlink, a regular file, bounded). null = absent. */
3329
+ declare function readLayer(file: string): {
3330
+ ok: true;
3331
+ text: string;
3332
+ } | {
3333
+ ok: false;
3334
+ why: string;
3335
+ } | null;
3336
+ /** Extract the repo hooks of the session roots (strict, fail closed). Pure but for reading the two settings files per root. */
3337
+ declare function extractRepoHooks(roots: readonly string[]): RepoHookSet;
3338
+ /** The approved hooks as a Claude settings `hooks` block (merged into the session's policy.json). */
3339
+ declare function hooksBlock(approved: readonly RepoHook[]): Record<string, Array<{
3340
+ matcher?: string;
3341
+ hooks: Array<{
3342
+ type: 'command';
3343
+ command: string;
3344
+ timeout?: number;
3345
+ }>;
3346
+ }>>;
3347
+ /** Merge two settings `hooks` blocks (generated first, then approved repo hooks). */
3348
+ declare function mergeHooks(a: unknown, b: Record<string, unknown[]>): Record<string, unknown[]>;
3349
+ /** Aegis C2: the kernel's warning line on every repo-hook card. */
3350
+ declare const REPO_HOOK_WARNING = "approving trusts the command and every file it runs; a repo change, a pull, or a session edit can change what runs";
3351
+ /** The card for one hook: the install-card rendering (count line first, one line for the hook, never cut). */
3352
+ /** Hook events whose hook can answer a tool permission itself (p01b (i)), so the card warns about it. */
3353
+ declare const TOOL_APPROVING_EVENTS: readonly string[];
3354
+ declare const TOOL_APPROVAL_WARNING = "This hook can approve tool uses with no card: a PreToolUse or PermissionRequest hook that answers allow runs the tool without asking you (P8-D96).";
3355
+ declare function repoHookCard(set: Extract<RepoHookSet, {
3356
+ status: 'ok';
3357
+ }>, h: RepoHook, root: string, info?: readonly string[]): {
3358
+ detail: Record<string, unknown>;
3359
+ lines: string[];
3360
+ block: Record<string, unknown>;
3361
+ };
3362
+ /** A chain row as the decision reader sees it (a full-view event). */
3363
+ interface DecisionRow {
3364
+ principal: string;
3365
+ keyId?: unknown;
3366
+ payload?: unknown;
3367
+ }
3368
+ /**
3369
+ * P8-D94: the human's per-hook decisions for (repoKey, setHash), read back from the chain. Only KERNEL-signed
3370
+ * rows count (principal === the kernel principal AND keyId a kernel key): a forged `gate-class.decided` from
3371
+ * any other principal or key is ignored. The last decision per hook wins.
3372
+ */
3373
+ declare function repoHookDecisionsFrom(rows: Iterable<DecisionRow>, kernel: {
3374
+ principal: string;
3375
+ isKernelKey: (keyId: string) => boolean;
3376
+ }, repoKey: string, setHash: string): Map<string, 'allow' | 'deny'>;
3377
+
3378
+ declare const repoHooks_CLAUDE_HOOK_EVENTS: typeof CLAUDE_HOOK_EVENTS;
3379
+ type repoHooks_DecisionRow = DecisionRow;
3380
+ declare const repoHooks_MAX_PENDING_HOOK_CARDS: typeof MAX_PENDING_HOOK_CARDS;
3381
+ declare const repoHooks_MAX_REFUSED_LOGGED: typeof MAX_REFUSED_LOGGED;
3382
+ declare const repoHooks_MAX_REPO_HOOKS: typeof MAX_REPO_HOOKS;
3383
+ declare const repoHooks_MAX_SETTINGS_BYTES: typeof MAX_SETTINGS_BYTES;
3384
+ declare const repoHooks_REPO_HOOK_FILES: typeof REPO_HOOK_FILES;
3385
+ declare const repoHooks_REPO_HOOK_WARNING: typeof REPO_HOOK_WARNING;
3386
+ type repoHooks_RepoHook = RepoHook;
3387
+ type repoHooks_RepoHookSet = RepoHookSet;
3388
+ declare const repoHooks_TOOL_APPROVAL_WARNING: typeof TOOL_APPROVAL_WARNING;
3389
+ declare const repoHooks_TOOL_APPROVING_EVENTS: typeof TOOL_APPROVING_EVENTS;
3390
+ declare const repoHooks_extractRepoHooks: typeof extractRepoHooks;
3391
+ declare const repoHooks_hooksBlock: typeof hooksBlock;
3392
+ declare const repoHooks_mergeHooks: typeof mergeHooks;
3393
+ declare const repoHooks_readLayer: typeof readLayer;
3394
+ declare const repoHooks_repoHookCard: typeof repoHookCard;
3395
+ declare const repoHooks_repoHookDecisionsFrom: typeof repoHookDecisionsFrom;
3396
+ declare const repoHooks_repoKeyOf: typeof repoKeyOf;
3397
+ declare const repoHooks_uniqueRoots: typeof uniqueRoots;
3398
+ declare namespace repoHooks {
3399
+ export { repoHooks_CLAUDE_HOOK_EVENTS as CLAUDE_HOOK_EVENTS, repoHooks_MAX_PENDING_HOOK_CARDS as MAX_PENDING_HOOK_CARDS, repoHooks_MAX_REFUSED_LOGGED as MAX_REFUSED_LOGGED, repoHooks_MAX_REPO_HOOKS as MAX_REPO_HOOKS, repoHooks_MAX_SETTINGS_BYTES as MAX_SETTINGS_BYTES, repoHooks_REPO_HOOK_FILES as REPO_HOOK_FILES, repoHooks_REPO_HOOK_WARNING as REPO_HOOK_WARNING, repoHooks_TOOL_APPROVAL_WARNING as TOOL_APPROVAL_WARNING, repoHooks_TOOL_APPROVING_EVENTS as TOOL_APPROVING_EVENTS, repoHooks_extractRepoHooks as extractRepoHooks, repoHooks_hooksBlock as hooksBlock, repoHooks_mergeHooks as mergeHooks, repoHooks_readLayer as readLayer, repoHooks_repoHookCard as repoHookCard, repoHooks_repoHookDecisionsFrom as repoHookDecisionsFrom, repoHooks_repoKeyOf as repoKeyOf, repoHooks_uniqueRoots as uniqueRoots };
3400
+ export type { repoHooks_DecisionRow as DecisionRow, repoHooks_RepoHook as RepoHook, repoHooks_RepoHookSet as RepoHookSet };
3401
+ }
3402
+
3403
+ /**
3404
+ * The voice-io floor (T-2026-10-21-028): the copy must answer `--version` with at least this. Every security-relevant
3405
+ * voice-io fix bumps voiceIOVersion (packages/gnomon-voice/io-darwin/Sources/VoiceIOCore/Frame.swift) and raises this
3406
+ * floor with it, like MIN_HELPER_VERSION (identity/helper.ts): the floor is what refuses an older, validly signed copy.
3407
+ */
3408
+ declare const MIN_VOICE_IO_VERSION = "0.1.0";
3409
+ /**
3410
+ * The sha256 a release build pins for voice-io on this arch; undefined in a dev build (signature + version floor
3411
+ * only). Refuses (`checksum` / `version`) when the release cannot pin it: no entry for this arch, a broken stamp, a
3412
+ * different signing requirement than VOICE_IO_REQUIREMENT, or a pinned version below the floor.
3413
+ */
3414
+ declare function releaseVoiceIoSha256(pins: ReleasePins, arch?: string): string | undefined;
3415
+
3416
+ declare const LOOPS_DISABLED_REASON = "loops-disabled";
3417
+ declare const LOOPS_DISABLED_MESSAGE = "Loops are off in this build. They arrive in Gnomon 8.1.";
3418
+ declare const LOOPS_DISABLED_STATUS_REASON = "not-in-this-build";
3419
+ interface LoopsGateInput {
3420
+ /** the compiled release define is present (default: this bundle's own) */
3421
+ release?: boolean;
3422
+ env?: Readonly<Record<string, string | undefined>>;
3423
+ }
3424
+ /** Are loops enabled in this process? Pure given its inputs; the daemon calls it once at boot. */
3425
+ declare function resolveLoopsEnabled(i?: LoopsGateInput): boolean;
3426
+
3427
+ declare const gate_LOOPS_DISABLED_MESSAGE: typeof LOOPS_DISABLED_MESSAGE;
3428
+ declare const gate_LOOPS_DISABLED_REASON: typeof LOOPS_DISABLED_REASON;
3429
+ declare const gate_LOOPS_DISABLED_STATUS_REASON: typeof LOOPS_DISABLED_STATUS_REASON;
3430
+ type gate_LoopsGateInput = LoopsGateInput;
3431
+ declare const gate_resolveLoopsEnabled: typeof resolveLoopsEnabled;
3432
+ declare namespace gate {
3433
+ export { gate_LOOPS_DISABLED_MESSAGE as LOOPS_DISABLED_MESSAGE, gate_LOOPS_DISABLED_REASON as LOOPS_DISABLED_REASON, gate_LOOPS_DISABLED_STATUS_REASON as LOOPS_DISABLED_STATUS_REASON, gate_resolveLoopsEnabled as resolveLoopsEnabled };
3434
+ export type { gate_LoopsGateInput as LoopsGateInput };
3435
+ }
3436
+
3437
+ type AppZipRefusal = 'dev' | 'broken' | 'unpinned' | 'missing' | 'checksum';
3438
+ declare class AppZipRefused extends Error {
3439
+ readonly reason: AppZipRefusal;
3440
+ constructor(reason: AppZipRefusal, message: string);
3441
+ }
3442
+ /** The sha256 this build accepts for `arch`'s published zip, or the refusal. */
3443
+ declare function appZipPin(pins: ReleasePins, arch: string): {
3444
+ kind: 'pinned';
3445
+ sha256: string;
3446
+ } | {
3447
+ kind: 'refuse';
3448
+ reason: AppZipRefusal;
3449
+ why: string;
3450
+ };
3451
+ /** Streamed sha256 of a file (the zip is tens of MB). */
3452
+ declare function sha256OfFile(file: string): string;
3453
+ /**
3454
+ * The installed @a-company/gnomon-darwin-<arch> zip, resolved from `from` (this module by default). Refused `missing`
3455
+ * when npm skipped the package or the resolved package.json is not that package.
3456
+ */
3457
+ declare function platformPackageZip(arch: string, from?: string): string;
3458
+ /** Refuse unless `zipPath` hashes to the sha256 compiled into this build for `arch`. Returns the digest. */
3459
+ declare function verifyAppZip(zipPath: string, { arch, pins }?: {
3460
+ arch?: string;
3461
+ pins?: ReleasePins;
3462
+ }): string;
3463
+
3464
+ type appZip_AppZipRefusal = AppZipRefusal;
3465
+ type appZip_AppZipRefused = AppZipRefused;
3466
+ declare const appZip_AppZipRefused: typeof AppZipRefused;
3467
+ declare const appZip_appZipPin: typeof appZipPin;
3468
+ declare const appZip_platformPackageZip: typeof platformPackageZip;
3469
+ declare const appZip_sha256OfFile: typeof sha256OfFile;
3470
+ declare const appZip_verifyAppZip: typeof verifyAppZip;
3471
+ declare namespace appZip {
3472
+ export { appZip_AppZipRefused as AppZipRefused, appZip_appZipPin as appZipPin, appZip_platformPackageZip as platformPackageZip, appZip_sha256OfFile as sha256OfFile, appZip_verifyAppZip as verifyAppZip };
3473
+ export type { appZip_AppZipRefusal as AppZipRefusal };
3474
+ }
3475
+
3476
+ export { CLAUDE_CODE_PLATFORMS, GNOMON_VERSION, HELPER_REQUIREMENT, KERNEL_ALLOWED_PACKAGE, KERNEL_MODULES, MIN_HELPER_VERSION, MIN_VOICE_IO_VERSION, appZip, binaryDenies, bundledRunner, adapter as claudeAdapter, index$1 as kernelLog, gate as loopsGate, index as manifestLoader, pinHelper, releaseHelperSha256, releasePins, releaseVoiceIoSha256, repoContext, repoHooks, session as sessionSandbox };
3477
+ export type { KernelModule };