ushman-ledger 1.2.2 → 1.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. package/AGENTS.md +7 -5
  2. package/ARCHITECTURE.md +8 -2
  3. package/CHANGELOG.md +11 -0
  4. package/README.md +37 -5
  5. package/TROUBLESHOOTING.md +17 -3
  6. package/dist/blobs.d.ts.map +1 -1
  7. package/dist/blobs.js +1 -1
  8. package/dist/builders.d.ts +33 -0
  9. package/dist/builders.d.ts.map +1 -1
  10. package/dist/builders.js +10 -1
  11. package/dist/cli.d.ts.map +1 -1
  12. package/dist/cli.js +153 -43
  13. package/dist/doctor.d.ts +1 -1
  14. package/dist/doctor.d.ts.map +1 -1
  15. package/dist/doctor.js +45 -11
  16. package/dist/handle.d.ts.map +1 -1
  17. package/dist/handle.js +67 -30
  18. package/dist/helpers.d.ts.map +1 -1
  19. package/dist/helpers.js +2 -1
  20. package/dist/index.d.ts +3 -3
  21. package/dist/index.d.ts.map +1 -1
  22. package/dist/index.js +3 -3
  23. package/dist/lab-min.d.ts +1 -1
  24. package/dist/lab-min.d.ts.map +1 -1
  25. package/dist/lab-min.js +2 -1
  26. package/dist/list.d.ts +32 -0
  27. package/dist/list.d.ts.map +1 -1
  28. package/dist/list.js +1 -1
  29. package/dist/patch-resolver.d.ts.map +1 -1
  30. package/dist/patch-resolver.js +1 -1
  31. package/dist/process.d.ts +2 -0
  32. package/dist/process.d.ts.map +1 -0
  33. package/dist/process.js +16 -0
  34. package/dist/read-index.d.ts +7 -7
  35. package/dist/read-index.d.ts.map +1 -1
  36. package/dist/read-index.js +13 -9
  37. package/dist/record.d.ts.map +1 -1
  38. package/dist/record.js +1 -2
  39. package/dist/recovery.d.ts +8 -0
  40. package/dist/recovery.d.ts.map +1 -1
  41. package/dist/recovery.js +142 -30
  42. package/dist/render/retro.d.ts.map +1 -1
  43. package/dist/render/retro.js +4 -1
  44. package/dist/runtime-config.d.ts +2 -0
  45. package/dist/runtime-config.d.ts.map +1 -1
  46. package/dist/runtime-config.js +14 -0
  47. package/dist/schema/entry-core.d.ts +5 -2
  48. package/dist/schema/entry-core.d.ts.map +1 -1
  49. package/dist/schema/entry-core.js +3 -0
  50. package/dist/schema/entry-read.d.ts +57 -0
  51. package/dist/schema/entry-read.d.ts.map +1 -1
  52. package/dist/schema/entry-read.js +9 -1
  53. package/dist/schema/entry-write.d.ts +51 -0
  54. package/dist/schema/entry-write.d.ts.map +1 -1
  55. package/dist/schema/entry-write.js +9 -1
  56. package/dist/storage/filesystem.d.ts +14 -2
  57. package/dist/storage/filesystem.d.ts.map +1 -1
  58. package/dist/storage/filesystem.js +206 -39
  59. package/dist/storage/lock.d.ts.map +1 -1
  60. package/dist/storage/lock.js +38 -16
  61. package/package.json +2 -1
package/dist/recovery.js CHANGED
@@ -1,13 +1,17 @@
1
- import { readdir, readFile, rm, stat } from 'node:fs/promises';
1
+ import { randomUUID } from 'node:crypto';
2
+ import { readdir, readFile, rename, rm, stat } from 'node:fs/promises';
2
3
  import path from 'node:path';
3
4
  import * as v from 'valibot';
5
+ import { mapWithConcurrencyLimit } from "./async.js";
4
6
  import { reconcilePendingArchivesUnderLock } from "./archive-journal.js";
5
7
  import { getNextManifestSequence, updateManifestForEntry } from "./manifest-update.js";
6
8
  import { ensureReadIndexUnderLock } from "./read-index.js";
9
+ import { getLedgerRuntimeConfig } from "./runtime-config.js";
7
10
  import { LedgerEntrySchema } from "./schema/entry.js";
8
11
  import { cleanupStaleTempFiles, ensureLedgerDirectories, readManifest, resolveLedgerPaths, saveManifest, writeAtomicJsonFile, writeEntryFile, } from "./storage/filesystem.js";
9
12
  import { acquireLock } from "./storage/lock.js";
10
13
  const PendingCommitSchemaVersion = 'ushman-ledger-pending-commit/v1';
14
+ const PendingCommitQuarantineSchemaVersion = 'ushman-ledger-pending-commit-quarantine/v1';
11
15
  // Pending commits capture the intended sequence and logical hash before the
12
16
  // entry file and manifest update diverge, so recovery can replay safely.
13
17
  const PendingCommitSchema = v.object({
@@ -18,6 +22,12 @@ const PendingCommitSchema = v.object({
18
22
  schemaVersion: v.literal(PendingCommitSchemaVersion),
19
23
  sequence: v.pipe(v.number(), v.integer(), v.minValue(1)),
20
24
  });
25
+ const PendingCommitQuarantineMetadataSchema = v.object({
26
+ originalFileName: v.pipe(v.string(), v.minLength(1)),
27
+ quarantinedAt: v.pipe(v.string(), v.isoTimestamp()),
28
+ reason: v.pipe(v.string(), v.minLength(1)),
29
+ schemaVersion: v.literal(PendingCommitQuarantineSchemaVersion),
30
+ });
21
31
  const formatSequence = (sequence) => sequence.toString().padStart(8, '0');
22
32
  const PendingCommitFileNameSchema = v.object({
23
33
  entryId: v.pipe(v.string(), v.minLength(1)),
@@ -29,10 +39,15 @@ const parsePendingCommitFileName = (name) => {
29
39
  if (!match) {
30
40
  return null;
31
41
  }
32
- return v.parse(PendingCommitFileNameSchema, {
33
- entryId: match[2],
34
- sequence: Number.parseInt(match[1], 10),
35
- });
42
+ try {
43
+ return v.parse(PendingCommitFileNameSchema, {
44
+ entryId: match[2],
45
+ sequence: Number.parseInt(match[1], 10),
46
+ });
47
+ }
48
+ catch {
49
+ return null;
50
+ }
36
51
  };
37
52
  const readPendingCommit = async (filePath) => {
38
53
  try {
@@ -43,32 +58,68 @@ const readPendingCommit = async (filePath) => {
43
58
  throw new Error(`Invalid pending commit at ${filePath}: ${error instanceof Error ? error.message : String(error)}`);
44
59
  }
45
60
  };
46
- const readPendingCommits = async (workspaceRoot) => {
61
+ const listPendingCommitFiles = async (workspaceRoot) => {
47
62
  const paths = await ensureLedgerDirectories(workspaceRoot);
48
63
  const entries = await readdir(paths.pendingCommitsDir, { withFileTypes: true });
49
- const pendingFiles = entries
50
- .filter((entry) => entry.isFile())
51
- .map((entry) => {
52
- if (!entry.name.endsWith('.json')) {
53
- return null;
64
+ const listing = {
65
+ invalidFiles: [],
66
+ pendingFiles: [],
67
+ };
68
+ for (const entry of entries) {
69
+ if (!entry.isFile() || !entry.name.endsWith('.json')) {
70
+ continue;
54
71
  }
72
+ const filePath = path.join(paths.pendingCommitsDir, entry.name);
55
73
  const parsed = parsePendingCommitFileName(entry.name);
56
74
  if (!parsed) {
57
- return null;
75
+ listing.invalidFiles.push({
76
+ filePath,
77
+ reason: `Invalid pending commit file name: ${entry.name}`,
78
+ });
79
+ continue;
58
80
  }
59
- return {
81
+ listing.pendingFiles.push({
60
82
  ...parsed,
61
- filePath: path.join(paths.pendingCommitsDir, entry.name),
62
- };
63
- })
64
- .filter((pendingFile) => pendingFile !== null)
65
- .sort((left, right) => left.sequence === right.sequence
66
- ? left.entryId.localeCompare(right.entryId)
67
- : left.sequence - right.sequence);
68
- return Promise.all(pendingFiles.map(async (pendingFile) => ({
69
- filePath: pendingFile.filePath,
70
- pending: await readPendingCommit(pendingFile.filePath),
71
- })));
83
+ filePath,
84
+ });
85
+ }
86
+ listing.pendingFiles.sort((left, right) => left.sequence === right.sequence ? left.entryId.localeCompare(right.entryId) : left.sequence - right.sequence);
87
+ return listing;
88
+ };
89
+ const formatRecoveryError = (error) => (error instanceof Error ? error.message : String(error));
90
+ const writeQuarantineMetadata = async ({ metadataPath, originalFileName, reason, }) => {
91
+ try {
92
+ await writeAtomicJsonFile(metadataPath, v.parse(PendingCommitQuarantineMetadataSchema, {
93
+ originalFileName,
94
+ quarantinedAt: new Date().toISOString(),
95
+ reason,
96
+ schemaVersion: PendingCommitQuarantineSchemaVersion,
97
+ }));
98
+ }
99
+ catch {
100
+ // The journal is already quarantined; metadata loss should not block recovery.
101
+ }
102
+ };
103
+ const quarantinePendingCommit = async ({ filePath, reason, workspaceRoot, }) => {
104
+ const paths = await ensureLedgerDirectories(workspaceRoot);
105
+ const originalFileName = path.basename(filePath);
106
+ const quarantineBaseName = `${path.basename(filePath, '.json')}.quarantined.${Date.now()}.${randomUUID()}`;
107
+ const quarantinePath = path.join(paths.pendingCommitQuarantineDir, `${quarantineBaseName}.json`);
108
+ const metadataPath = path.join(paths.pendingCommitQuarantineDir, `${quarantineBaseName}.meta.json`);
109
+ try {
110
+ await rename(filePath, quarantinePath);
111
+ }
112
+ catch (error) {
113
+ if (error.code === 'ENOENT') {
114
+ return;
115
+ }
116
+ throw error;
117
+ }
118
+ await writeQuarantineMetadata({
119
+ metadataPath,
120
+ originalFileName,
121
+ reason,
122
+ });
72
123
  };
73
124
  const ensurePendingCommitEntryFile = async (workspaceRoot, pending) => {
74
125
  const entryPath = path.join(resolveLedgerPaths(workspaceRoot).phaseDir(pending.entry.phase), `${pending.entry.id}.json`);
@@ -141,21 +192,82 @@ export const writePendingCommit = async ({ entry, logicalHash, manifest, workspa
141
192
  export const removePendingCommit = async (filePath) => {
142
193
  await rm(filePath, { force: true });
143
194
  };
195
+ const readQuarantineMetadata = async (metadataPath) => {
196
+ try {
197
+ const text = await readFile(metadataPath, 'utf8');
198
+ return v.parse(PendingCommitQuarantineMetadataSchema, JSON.parse(text));
199
+ }
200
+ catch {
201
+ return null;
202
+ }
203
+ };
204
+ export const listPendingCommitQuarantines = async (workspaceRoot) => {
205
+ const paths = await ensureLedgerDirectories(workspaceRoot);
206
+ const { scanConcurrency } = getLedgerRuntimeConfig();
207
+ const entries = await readdir(paths.pendingCommitQuarantineDir, { withFileTypes: true });
208
+ const quarantinedCommitFiles = entries
209
+ .filter((entry) => entry.isFile() && entry.name.endsWith('.json') && !entry.name.endsWith('.meta.json'))
210
+ .map((entry) => entry.name)
211
+ .sort((left, right) => left.localeCompare(right));
212
+ return mapWithConcurrencyLimit(quarantinedCommitFiles, scanConcurrency, async (fileName) => {
213
+ const baseName = fileName.slice(0, -'.json'.length);
214
+ const commitPath = path.join(paths.pendingCommitQuarantineDir, fileName);
215
+ const metadataPath = path.join(paths.pendingCommitQuarantineDir, `${baseName}.meta.json`);
216
+ const metadata = await readQuarantineMetadata(metadataPath);
217
+ return {
218
+ commitPath,
219
+ metadataPath: metadata ? metadataPath : null,
220
+ originalFileName: metadata?.originalFileName ?? fileName,
221
+ quarantinedAt: metadata?.quarantinedAt ?? null,
222
+ reason: metadata?.reason ?? 'Missing or invalid pending commit quarantine metadata.',
223
+ };
224
+ });
225
+ };
144
226
  export const reconcilePendingCommitsUnderLock = async (workspaceRoot) => {
145
227
  await cleanupStaleTempFiles(workspaceRoot);
146
228
  let manifest = await readManifest(workspaceRoot);
147
- const pendingCommits = await readPendingCommits(workspaceRoot);
229
+ const { invalidFiles, pendingFiles } = await listPendingCommitFiles(workspaceRoot);
148
230
  const processedPendingFiles = [];
149
231
  let manifestChanged = false;
150
- for (const pendingCommit of pendingCommits) {
151
- const replayed = await applyPendingCommit({
152
- manifest,
153
- pending: pendingCommit.pending,
232
+ for (const invalidFile of invalidFiles) {
233
+ await quarantinePendingCommit({
234
+ filePath: invalidFile.filePath,
235
+ reason: invalidFile.reason,
154
236
  workspaceRoot,
155
237
  });
238
+ }
239
+ for (const pendingCommitFile of pendingFiles) {
240
+ let pending;
241
+ try {
242
+ pending = await readPendingCommit(pendingCommitFile.filePath);
243
+ }
244
+ catch (error) {
245
+ await quarantinePendingCommit({
246
+ filePath: pendingCommitFile.filePath,
247
+ reason: formatRecoveryError(error),
248
+ workspaceRoot,
249
+ });
250
+ continue;
251
+ }
252
+ let replayed;
253
+ try {
254
+ replayed = await applyPendingCommit({
255
+ manifest,
256
+ pending,
257
+ workspaceRoot,
258
+ });
259
+ }
260
+ catch (error) {
261
+ await quarantinePendingCommit({
262
+ filePath: pendingCommitFile.filePath,
263
+ reason: formatRecoveryError(error),
264
+ workspaceRoot,
265
+ });
266
+ continue;
267
+ }
156
268
  manifest = replayed.manifest;
157
269
  manifestChanged = manifestChanged || replayed.didChangeManifest;
158
- processedPendingFiles.push(pendingCommit.filePath);
270
+ processedPendingFiles.push(pendingCommitFile.filePath);
159
271
  }
160
272
  if (manifestChanged) {
161
273
  await saveManifest(workspaceRoot, manifest);
@@ -1 +1 @@
1
- {"version":3,"file":"retro.d.ts","sourceRoot":"","sources":["../../src/render/retro.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AA4HtD,eAAO,MAAM,mBAAmB,GAAU,wBAGvC;IACC,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAC,WAAW,CAAC,CAAC;IAC7C,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;CAC9B,KAAG,OAAO,CAAC,MAAM,CAgDjB,CAAC"}
1
+ {"version":3,"file":"retro.d.ts","sourceRoot":"","sources":["../../src/render/retro.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AA+HtD,eAAO,MAAM,mBAAmB,GAAU,wBAGvC;IACC,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAC,WAAW,CAAC,CAAC;IAC7C,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;CAC9B,KAAG,OAAO,CAAC,MAAM,CAgDjB,CAAC"}
@@ -14,7 +14,10 @@ const createRetroBuckets = () => ({
14
14
  });
15
15
  const isProblemEntry = (entry) => (entry.kind === 'note' && entry.subkind === 'regression') ||
16
16
  (entry.kind === 'runtime-event' && entry.level === 'error');
17
- const isToolEntry = (entry) => entry.kind === 'tool-invocation' || entry.kind === 'agent-patch' || entry.kind === 'operator-patch';
17
+ const isToolEntry = (entry) => entry.kind === 'tool-invocation' ||
18
+ entry.kind === 'stage-write' ||
19
+ entry.kind === 'agent-patch' ||
20
+ entry.kind === 'operator-patch';
18
21
  const isToolingEntry = (entry) => (entry.kind === 'note' && entry.subkind === 'automation') ||
19
22
  (entry.kind === 'note' && entry.subkind === 'tooling-gap');
20
23
  const isRetroNote = (entry) => entry.kind === 'note' && entry.subkind === 'retro';
@@ -1,6 +1,8 @@
1
1
  export type LedgerRuntimeConfig = {
2
2
  readonly blobHashConcurrency: number;
3
3
  readonly coverageFileStatConcurrency: number;
4
+ readonly doctorCheckpointMaxAgeMs: number;
5
+ readonly doctorOpenIssueMaxAgeMs: number;
4
6
  readonly maxPatchBytes: number;
5
7
  readonly readIndexRebuildBatchSize: number;
6
8
  readonly readIndexRebuildConcurrency: number;
@@ -1 +1 @@
1
- {"version":3,"file":"runtime-config.d.ts","sourceRoot":"","sources":["../src/runtime-config.ts"],"names":[],"mappings":"AAgCA,MAAM,MAAM,mBAAmB,GAAG;IAC9B,QAAQ,CAAC,mBAAmB,EAAE,MAAM,CAAC;IACrC,QAAQ,CAAC,2BAA2B,EAAE,MAAM,CAAC;IAC7C,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,yBAAyB,EAAE,MAAM,CAAC;IAC3C,QAAQ,CAAC,2BAA2B,EAAE,MAAM,CAAC;IAC7C,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;CACpC,CAAC;AAuDF,eAAO,MAAM,2BAA2B,GAAI,MAAK,MAAM,CAAC,UAAwB,SAE/E,CAAC;AAEF,eAAO,MAAM,sBAAsB,GAAI,MAAK,MAAM,CAAC,UAAwB,KAAG,mBAgB7E,CAAC"}
1
+ {"version":3,"file":"runtime-config.d.ts","sourceRoot":"","sources":["../src/runtime-config.ts"],"names":[],"mappings":"AAoCA,MAAM,MAAM,mBAAmB,GAAG;IAC9B,QAAQ,CAAC,mBAAmB,EAAE,MAAM,CAAC;IACrC,QAAQ,CAAC,2BAA2B,EAAE,MAAM,CAAC;IAC7C,QAAQ,CAAC,wBAAwB,EAAE,MAAM,CAAC;IAC1C,QAAQ,CAAC,uBAAuB,EAAE,MAAM,CAAC;IACzC,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,yBAAyB,EAAE,MAAM,CAAC;IAC3C,QAAQ,CAAC,2BAA2B,EAAE,MAAM,CAAC;IAC7C,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;CACpC,CAAC;AAiEF,eAAO,MAAM,2BAA2B,GAAI,MAAK,MAAM,CAAC,UAAwB,SAE/E,CAAC;AAEF,eAAO,MAAM,sBAAsB,GAAI,MAAK,MAAM,CAAC,UAAwB,KAAG,mBAgB7E,CAAC"}
@@ -1,9 +1,13 @@
1
1
  const DEFAULT_SCAN_BATCH_SIZE = 32;
2
2
  const DEFAULT_SCAN_CONCURRENCY = 16;
3
3
  const DEFAULT_MAX_PATCH_BYTES = 10 * 1024 * 1024;
4
+ const DEFAULT_DOCTOR_CHECKPOINT_MAX_AGE_MS = 24 * 60 * 60 * 1_000;
5
+ const DEFAULT_DOCTOR_OPEN_ISSUE_MAX_AGE_MS = 30 * 24 * 60 * 60 * 1_000;
4
6
  const RUNTIME_CONFIG_ENV_VARS = [
5
7
  'USHMAN_LEDGER_BLOB_HASH_CONCURRENCY',
6
8
  'USHMAN_LEDGER_COVERAGE_FILE_STAT_CONCURRENCY',
9
+ 'USHMAN_LEDGER_DOCTOR_CHECKPOINT_MAX_AGE_MS',
10
+ 'USHMAN_LEDGER_DOCTOR_OPEN_ISSUE_MAX_AGE_MS',
7
11
  'USHMAN_LEDGER_MAX_PATCH_BYTES',
8
12
  'USHMAN_LEDGER_READ_INDEX_REBUILD_BATCH_SIZE',
9
13
  'USHMAN_LEDGER_READ_INDEX_REBUILD_CONCURRENCY',
@@ -44,6 +48,16 @@ const buildLedgerRuntimeConfig = (env) => {
44
48
  env,
45
49
  envVar: 'USHMAN_LEDGER_COVERAGE_FILE_STAT_CONCURRENCY',
46
50
  }),
51
+ doctorCheckpointMaxAgeMs: parsePositiveIntegerEnv({
52
+ defaultValue: DEFAULT_DOCTOR_CHECKPOINT_MAX_AGE_MS,
53
+ env,
54
+ envVar: 'USHMAN_LEDGER_DOCTOR_CHECKPOINT_MAX_AGE_MS',
55
+ }),
56
+ doctorOpenIssueMaxAgeMs: parsePositiveIntegerEnv({
57
+ defaultValue: DEFAULT_DOCTOR_OPEN_ISSUE_MAX_AGE_MS,
58
+ env,
59
+ envVar: 'USHMAN_LEDGER_DOCTOR_OPEN_ISSUE_MAX_AGE_MS',
60
+ }),
47
61
  maxPatchBytes: parsePositiveIntegerEnv({
48
62
  defaultValue: DEFAULT_MAX_PATCH_BYTES,
49
63
  env,
@@ -1,12 +1,14 @@
1
1
  import * as v from 'valibot';
2
2
  export declare const LedgerSchemaVersion: "ushman-ledger-entry/v1";
3
3
  export declare const LEDGER_PHASES: readonly ["capture", "intake", "seed", "vendor-extract", "cleanup", "parity", "characterize", "equiv", "analyze", "recover", "ship", "migration"];
4
- export declare const LEDGER_KINDS: readonly ["tool-invocation", "agent-patch", "operator-patch", "operator-decision", "validator-result", "runtime-event", "note", "correction", "strip-decision-reverted", "change-log"];
4
+ export declare const LEDGER_KINDS: readonly ["tool-invocation", "stage-write", "agent-patch", "operator-patch", "operator-decision", "validator-result", "runtime-event", "note", "correction", "strip-decision-reverted", "change-log"];
5
+ export declare const STAGE_WRITE_STAGES: readonly ["intake", "seed", "vendor-extract", "cleanup", "candidate-promotion"];
5
6
  export declare const OPERATOR_DECISION_ACTIONS: readonly ["bypass-doctor", "skip-check", "override-strip-decision", "override-ship-state", "manual-parity-assertion", "ledger-hand-edit", "escalation"];
6
7
  export declare const NonEmptyTrimmedStringSchema: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>]>;
7
8
  export declare const WorkspaceRelativePathSchema: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>, v.CheckAction<string, "Expected a normalized workspace-relative path.">]>;
8
9
  export declare const LedgerPhaseSchema: v.PicklistSchema<readonly ["capture", "intake", "seed", "vendor-extract", "cleanup", "parity", "characterize", "equiv", "analyze", "recover", "ship", "migration"], undefined>;
9
- export declare const LedgerKindSchema: v.PicklistSchema<readonly ["tool-invocation", "agent-patch", "operator-patch", "operator-decision", "validator-result", "runtime-event", "note", "correction", "strip-decision-reverted", "change-log"], undefined>;
10
+ export declare const LedgerKindSchema: v.PicklistSchema<readonly ["tool-invocation", "stage-write", "agent-patch", "operator-patch", "operator-decision", "validator-result", "runtime-event", "note", "correction", "strip-decision-reverted", "change-log"], undefined>;
11
+ export declare const StageWriteStageSchema: v.PicklistSchema<readonly ["intake", "seed", "vendor-extract", "cleanup", "candidate-promotion"], undefined>;
10
12
  export declare const OperatorDecisionActionSchema: v.PicklistSchema<readonly ["bypass-doctor", "skip-check", "override-strip-decision", "override-ship-state", "manual-parity-assertion", "ledger-hand-edit", "escalation"], undefined>;
11
13
  export declare const ChangeLogSubkindSchema: v.PicklistSchema<readonly ["pre-change-checkpoint", "semantic-cleanup", "vendor-extract", "decomposition", "rollback", "hotfix", "smoke"], undefined>;
12
14
  export declare const ChangeLogSmokeResultSchema: v.PicklistSchema<readonly ["pass", "fail", "partial", "not-run"], undefined>;
@@ -105,6 +107,7 @@ export type LedgerLinks = v.InferOutput<typeof LedgerLinksSchema>;
105
107
  export type LedgerPhase = v.InferOutput<typeof LedgerPhaseSchema>;
106
108
  export type OperatorDecisionAction = v.InferOutput<typeof OperatorDecisionActionSchema>;
107
109
  export type OperatorDecisionPayload = v.InferOutput<typeof OperatorDecisionPayloadSchema>;
110
+ export type StageWriteStage = v.InferOutput<typeof StageWriteStageSchema>;
108
111
  export type StripDecisionRevertedPayload = v.InferOutput<typeof StripDecisionRevertedPayloadSchema>;
109
112
  export type WorkspaceRelativePath = v.InferOutput<typeof WorkspaceRelativePathSchema>;
110
113
  //# sourceMappingURL=entry-core.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"entry-core.d.ts","sourceRoot":"","sources":["../../src/schema/entry-core.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,CAAC,MAAM,SAAS,CAAC;AAE7B,eAAO,MAAM,mBAAmB,EAAG,wBAAiC,CAAC;AAErE,eAAO,MAAM,aAAa,mJAahB,CAAC;AAEX,eAAO,MAAM,YAAY,wLAWf,CAAC;AAEX,eAAO,MAAM,yBAAyB,yJAQ5B,CAAC;AAiDX,eAAO,MAAM,2BAA2B,+GAA+C,CAAC;AAExF,eAAO,MAAM,2BAA2B,0KAIvC,CAAC;AAIF,eAAO,MAAM,iBAAiB,gLAA4B,CAAC;AAC3D,eAAO,MAAM,gBAAgB,qNAA2B,CAAC;AACzD,eAAO,MAAM,4BAA4B,sLAAwC,CAAC;AAElF,eAAO,MAAM,sBAAsB,uJAAkC,CAAC;AACtE,eAAO,MAAM,0BAA0B,8EAAuC,CAAC;AAC/E,eAAO,MAAM,2BAA2B,6EAAyC,CAAC;AAElF,eAAO,MAAM,aAAa;;;;aAIxB,CAAC;AAEH,eAAO,MAAM,iBAAiB;;;;;;;;;;8BAa7B,CAAC;AAEF,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;;;;;CAUlC,CAAC;AAEF,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;;CAOlC,CAAC;AAEF,eAAO,MAAM,oBAAoB;;;;;aAK/B,CAAC;AAEH,eAAO,MAAM,6BAA6B;;;;aAIxC,CAAC;AAEH,eAAO,MAAM,kCAAkC;;;;aAI7C,CAAC;AAEH,eAAO,MAAM,yBAAyB;;;;aAIpC,CAAC;AAEH,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,WAAW,CAAC,OAAO,oBAAoB,CAAC,CAAC;AACxE,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,WAAW,CAAC,OAAO,yBAAyB,CAAC,CAAC;AAClF,MAAM,MAAM,qBAAqB,GAAG,CAAC,CAAC,WAAW,CAAC,OAAO,2BAA2B,CAAC,CAAC;AACtF,MAAM,MAAM,oBAAoB,GAAG,CAAC,CAAC,WAAW,CAAC,OAAO,0BAA0B,CAAC,CAAC;AACpF,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,WAAW,CAAC,OAAO,sBAAsB,CAAC,CAAC;AAC5E,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,WAAW,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAChE,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,WAAW,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAClE,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,WAAW,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAClE,MAAM,MAAM,sBAAsB,GAAG,CAAC,CAAC,WAAW,CAAC,OAAO,4BAA4B,CAAC,CAAC;AACxF,MAAM,MAAM,uBAAuB,GAAG,CAAC,CAAC,WAAW,CAAC,OAAO,6BAA6B,CAAC,CAAC;AAC1F,MAAM,MAAM,4BAA4B,GAAG,CAAC,CAAC,WAAW,CAAC,OAAO,kCAAkC,CAAC,CAAC;AACpG,MAAM,MAAM,qBAAqB,GAAG,CAAC,CAAC,WAAW,CAAC,OAAO,2BAA2B,CAAC,CAAC"}
1
+ {"version":3,"file":"entry-core.d.ts","sourceRoot":"","sources":["../../src/schema/entry-core.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,CAAC,MAAM,SAAS,CAAC;AAE7B,eAAO,MAAM,mBAAmB,EAAG,wBAAiC,CAAC;AAErE,eAAO,MAAM,aAAa,mJAahB,CAAC;AAEX,eAAO,MAAM,YAAY,uMAYf,CAAC;AAEX,eAAO,MAAM,kBAAkB,iFAAkF,CAAC;AAElH,eAAO,MAAM,yBAAyB,yJAQ5B,CAAC;AAiDX,eAAO,MAAM,2BAA2B,+GAA+C,CAAC;AAExF,eAAO,MAAM,2BAA2B,0KAIvC,CAAC;AAIF,eAAO,MAAM,iBAAiB,gLAA4B,CAAC;AAC3D,eAAO,MAAM,gBAAgB,oOAA2B,CAAC;AACzD,eAAO,MAAM,qBAAqB,8GAAiC,CAAC;AACpE,eAAO,MAAM,4BAA4B,sLAAwC,CAAC;AAElF,eAAO,MAAM,sBAAsB,uJAAkC,CAAC;AACtE,eAAO,MAAM,0BAA0B,8EAAuC,CAAC;AAC/E,eAAO,MAAM,2BAA2B,6EAAyC,CAAC;AAElF,eAAO,MAAM,aAAa;;;;aAIxB,CAAC;AAEH,eAAO,MAAM,iBAAiB;;;;;;;;;;8BAa7B,CAAC;AAEF,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;;;;;CAUlC,CAAC;AAEF,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;;CAOlC,CAAC;AAEF,eAAO,MAAM,oBAAoB;;;;;aAK/B,CAAC;AAEH,eAAO,MAAM,6BAA6B;;;;aAIxC,CAAC;AAEH,eAAO,MAAM,kCAAkC;;;;aAI7C,CAAC;AAEH,eAAO,MAAM,yBAAyB;;;;aAIpC,CAAC;AAEH,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,WAAW,CAAC,OAAO,oBAAoB,CAAC,CAAC;AACxE,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,WAAW,CAAC,OAAO,yBAAyB,CAAC,CAAC;AAClF,MAAM,MAAM,qBAAqB,GAAG,CAAC,CAAC,WAAW,CAAC,OAAO,2BAA2B,CAAC,CAAC;AACtF,MAAM,MAAM,oBAAoB,GAAG,CAAC,CAAC,WAAW,CAAC,OAAO,0BAA0B,CAAC,CAAC;AACpF,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,WAAW,CAAC,OAAO,sBAAsB,CAAC,CAAC;AAC5E,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,WAAW,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAChE,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,WAAW,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAClE,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,WAAW,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAClE,MAAM,MAAM,sBAAsB,GAAG,CAAC,CAAC,WAAW,CAAC,OAAO,4BAA4B,CAAC,CAAC;AACxF,MAAM,MAAM,uBAAuB,GAAG,CAAC,CAAC,WAAW,CAAC,OAAO,6BAA6B,CAAC,CAAC;AAC1F,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,WAAW,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAC1E,MAAM,MAAM,4BAA4B,GAAG,CAAC,CAAC,WAAW,CAAC,OAAO,kCAAkC,CAAC,CAAC;AACpG,MAAM,MAAM,qBAAqB,GAAG,CAAC,CAAC,WAAW,CAAC,OAAO,2BAA2B,CAAC,CAAC"}
@@ -17,6 +17,7 @@ export const LEDGER_PHASES = [
17
17
  ];
18
18
  export const LEDGER_KINDS = [
19
19
  'tool-invocation',
20
+ 'stage-write',
20
21
  'agent-patch',
21
22
  'operator-patch',
22
23
  'operator-decision',
@@ -27,6 +28,7 @@ export const LEDGER_KINDS = [
27
28
  'strip-decision-reverted',
28
29
  'change-log',
29
30
  ];
31
+ export const STAGE_WRITE_STAGES = ['intake', 'seed', 'vendor-extract', 'cleanup', 'candidate-promotion'];
30
32
  export const OPERATOR_DECISION_ACTIONS = [
31
33
  'bypass-doctor',
32
34
  'skip-check',
@@ -80,6 +82,7 @@ export const WorkspaceRelativePathSchema = v.pipe(v.string(), v.minLength(1), v.
80
82
  const SHA256HexSchema = v.pipe(v.string(), v.regex(SHA256_HEX_PATTERN, 'Expected a lowercase SHA-256 hex digest.'));
81
83
  export const LedgerPhaseSchema = v.picklist(LEDGER_PHASES);
82
84
  export const LedgerKindSchema = v.picklist(LEDGER_KINDS);
85
+ export const StageWriteStageSchema = v.picklist(STAGE_WRITE_STAGES);
83
86
  export const OperatorDecisionActionSchema = v.picklist(OPERATOR_DECISION_ACTIONS);
84
87
  const StripDecisionInvalidatedStageSchema = v.picklist(STRIP_DECISION_INVALIDATED_STAGES);
85
88
  export const ChangeLogSubkindSchema = v.picklist(CHANGE_LOG_SUBKINDS);
@@ -28,6 +28,35 @@ export declare const ToolInvocationEntrySchema: v.ObjectSchema<{
28
28
  readonly summary: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>]>;
29
29
  readonly ts: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, undefined>]>;
30
30
  }, undefined>;
31
+ export declare const StageWriteEntrySchema: v.ObjectSchema<{
32
+ readonly filePath: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>, v.CheckAction<string, "Expected a normalized workspace-relative path.">]>;
33
+ readonly kind: v.LiteralSchema<"stage-write", undefined>;
34
+ readonly rationale: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>]>;
35
+ readonly stage: v.PicklistSchema<readonly ["intake", "seed", "vendor-extract", "cleanup", "candidate-promotion"], undefined>;
36
+ readonly details: v.OptionalSchema<v.RecordSchema<v.StringSchema<undefined>, v.UnknownSchema, undefined>, undefined>;
37
+ readonly emitter: v.ObjectSchema<{
38
+ readonly tool: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>]>;
39
+ readonly user: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>]>, undefined>;
40
+ readonly version: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>]>;
41
+ }, undefined>;
42
+ readonly id: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>]>;
43
+ readonly links: v.OptionalSchema<v.ObjectWithRestSchema<{
44
+ readonly affectedFiles: v.OptionalSchema<v.ArraySchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>, v.CheckAction<string, "Expected a normalized workspace-relative path.">]>, undefined>, undefined>;
45
+ readonly blobs: v.OptionalSchema<v.ArraySchema<v.StringSchema<undefined>, undefined>, undefined>;
46
+ readonly briefId: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
47
+ readonly correctsLedgerId: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
48
+ readonly gitRef: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
49
+ readonly idempotencyKey: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
50
+ readonly stripDecisionId: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
51
+ readonly supersedesLedgerId: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
52
+ readonly validatorVerdictId: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
53
+ }, v.UnknownSchema, undefined>, {}>;
54
+ readonly phase: v.PicklistSchema<readonly ["capture", "intake", "seed", "vendor-extract", "cleanup", "parity", "characterize", "equiv", "analyze", "recover", "ship", "migration"], undefined>;
55
+ readonly prevEntryId: v.NullableSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>]>, undefined>;
56
+ readonly schemaVersion: v.LiteralSchema<"ushman-ledger-entry/v1", undefined>;
57
+ readonly summary: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>]>;
58
+ readonly ts: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, undefined>]>;
59
+ }, undefined>;
31
60
  export declare const AgentPatchEntrySchema: v.ObjectSchema<{
32
61
  readonly agent: v.ObjectSchema<{
33
62
  readonly name: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>]>;
@@ -375,6 +404,34 @@ export declare const LedgerEntrySchema: v.VariantSchema<"kind", [v.ObjectSchema<
375
404
  readonly schemaVersion: v.LiteralSchema<"ushman-ledger-entry/v1", undefined>;
376
405
  readonly summary: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>]>;
377
406
  readonly ts: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, undefined>]>;
407
+ }, undefined>, v.ObjectSchema<{
408
+ readonly filePath: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>, v.CheckAction<string, "Expected a normalized workspace-relative path.">]>;
409
+ readonly kind: v.LiteralSchema<"stage-write", undefined>;
410
+ readonly rationale: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>]>;
411
+ readonly stage: v.PicklistSchema<readonly ["intake", "seed", "vendor-extract", "cleanup", "candidate-promotion"], undefined>;
412
+ readonly details: v.OptionalSchema<v.RecordSchema<v.StringSchema<undefined>, v.UnknownSchema, undefined>, undefined>;
413
+ readonly emitter: v.ObjectSchema<{
414
+ readonly tool: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>]>;
415
+ readonly user: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>]>, undefined>;
416
+ readonly version: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>]>;
417
+ }, undefined>;
418
+ readonly id: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>]>;
419
+ readonly links: v.OptionalSchema<v.ObjectWithRestSchema<{
420
+ readonly affectedFiles: v.OptionalSchema<v.ArraySchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>, v.CheckAction<string, "Expected a normalized workspace-relative path.">]>, undefined>, undefined>;
421
+ readonly blobs: v.OptionalSchema<v.ArraySchema<v.StringSchema<undefined>, undefined>, undefined>;
422
+ readonly briefId: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
423
+ readonly correctsLedgerId: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
424
+ readonly gitRef: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
425
+ readonly idempotencyKey: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
426
+ readonly stripDecisionId: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
427
+ readonly supersedesLedgerId: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
428
+ readonly validatorVerdictId: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
429
+ }, v.UnknownSchema, undefined>, {}>;
430
+ readonly phase: v.PicklistSchema<readonly ["capture", "intake", "seed", "vendor-extract", "cleanup", "parity", "characterize", "equiv", "analyze", "recover", "ship", "migration"], undefined>;
431
+ readonly prevEntryId: v.NullableSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>]>, undefined>;
432
+ readonly schemaVersion: v.LiteralSchema<"ushman-ledger-entry/v1", undefined>;
433
+ readonly summary: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>]>;
434
+ readonly ts: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, undefined>]>;
378
435
  }, undefined>, v.ObjectSchema<{
379
436
  readonly agent: v.ObjectSchema<{
380
437
  readonly name: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>]>;
@@ -1 +1 @@
1
- {"version":3,"file":"entry-read.d.ts","sourceRoot":"","sources":["../../src/schema/entry-read.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,SAAS,CAAC;AAc7B,eAAO,MAAM,yBAAyB;;;;;;;;;;;;;;;;;;;;;;;;;;;;aAMpC,CAAC;AAQH,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;aAOhC,CAAC;AAEH,eAAO,MAAM,wBAAwB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;aAMnC,CAAC;AAEH,eAAO,MAAM,2BAA2B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;aAItC,CAAC;AAEH,eAAO,MAAM,0BAA0B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;aAOrC,CAAC;AAEH,eAAO,MAAM,uBAAuB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;aAOlC,CAAC;AAEH,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;aAK1B,CAAC;AAEH,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;yDAOjC,CAAC;AAEF,eAAO,MAAM,gCAAgC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;aAI3C,CAAC;AAEH,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;aAY/B,CAAC;AAEH,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;0BAW5B,CAAC;AAEH,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,WAAW,CAAC,OAAO,oBAAoB,CAAC,CAAC;AACxE,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,WAAW,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAClE,MAAM,MAAM,SAAS,GAAG,OAAO,CAAC,WAAW,EAAE;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC"}
1
+ {"version":3,"file":"entry-read.d.ts","sourceRoot":"","sources":["../../src/schema/entry-read.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,SAAS,CAAC;AAgB7B,eAAO,MAAM,yBAAyB;;;;;;;;;;;;;;;;;;;;;;;;;;;;aAMpC,CAAC;AAEH,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;;aAMhC,CAAC;AAQH,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;aAOhC,CAAC;AAEH,eAAO,MAAM,wBAAwB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;aAMnC,CAAC;AAEH,eAAO,MAAM,2BAA2B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;aAItC,CAAC;AAEH,eAAO,MAAM,0BAA0B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;aAOrC,CAAC;AAEH,eAAO,MAAM,uBAAuB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;aAOlC,CAAC;AAEH,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;aAK1B,CAAC;AAEH,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;yDAOjC,CAAC;AAEF,eAAO,MAAM,gCAAgC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;aAI3C,CAAC;AAEH,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;aAY/B,CAAC;AAEH,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;0BAY5B,CAAC;AAEH,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,WAAW,CAAC,OAAO,oBAAoB,CAAC,CAAC;AACxE,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,WAAW,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAClE,MAAM,MAAM,SAAS,GAAG,OAAO,CAAC,WAAW,EAAE;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC"}
@@ -1,5 +1,5 @@
1
1
  import * as v from 'valibot';
2
- import { AgentPatchDiffSchema, ChangeLogFileChangeSchema, ChangeLogParityStatusSchema, ChangeLogSmokeResultSchema, ChangeLogSubkindSchema, ledgerEntryBaseEntries, NonEmptyTrimmedStringSchema, OperatorDecisionPayloadSchema, StripDecisionRevertedPayloadSchema, } from "./entry-core.js";
2
+ import { AgentPatchDiffSchema, ChangeLogFileChangeSchema, ChangeLogParityStatusSchema, ChangeLogSmokeResultSchema, ChangeLogSubkindSchema, ledgerEntryBaseEntries, NonEmptyTrimmedStringSchema, OperatorDecisionPayloadSchema, StageWriteStageSchema, StripDecisionRevertedPayloadSchema, WorkspaceRelativePathSchema, } from "./entry-core.js";
3
3
  import { NoteSubkindSchema } from "./note.js";
4
4
  export const ToolInvocationEntrySchema = v.object({
5
5
  ...ledgerEntryBaseEntries,
@@ -8,6 +8,13 @@ export const ToolInvocationEntrySchema = v.object({
8
8
  exitCode: v.optional(v.pipe(v.number(), v.integer())),
9
9
  kind: v.literal('tool-invocation'),
10
10
  });
11
+ export const StageWriteEntrySchema = v.object({
12
+ ...ledgerEntryBaseEntries,
13
+ filePath: WorkspaceRelativePathSchema,
14
+ kind: v.literal('stage-write'),
15
+ rationale: NonEmptyTrimmedStringSchema,
16
+ stage: StageWriteStageSchema,
17
+ });
11
18
  const patchEntryEntries = {
12
19
  ...ledgerEntryBaseEntries,
13
20
  diff: AgentPatchDiffSchema,
@@ -80,6 +87,7 @@ export const ChangeLogEntrySchema = v.object({
80
87
  });
81
88
  export const LedgerEntrySchema = v.variant('kind', [
82
89
  ToolInvocationEntrySchema,
90
+ StageWriteEntrySchema,
83
91
  AgentPatchEntrySchema,
84
92
  OperatorPatchEntrySchema,
85
93
  OperatorDecisionEntrySchema,
@@ -25,6 +25,32 @@ export declare const ToolInvocationRecordSchema: v.ObjectSchema<{
25
25
  readonly phase: v.PicklistSchema<readonly ["capture", "intake", "seed", "vendor-extract", "cleanup", "parity", "characterize", "equiv", "analyze", "recover", "ship", "migration"], undefined>;
26
26
  readonly summary: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>]>;
27
27
  }, undefined>;
28
+ export declare const StageWriteRecordSchema: v.ObjectSchema<{
29
+ readonly filePath: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>, v.CheckAction<string, "Expected a normalized workspace-relative path.">]>;
30
+ readonly kind: v.LiteralSchema<"stage-write", undefined>;
31
+ readonly rationale: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>]>;
32
+ readonly stage: v.PicklistSchema<readonly ["intake", "seed", "vendor-extract", "cleanup", "candidate-promotion"], undefined>;
33
+ readonly details: v.OptionalSchema<v.RecordSchema<v.StringSchema<undefined>, v.UnknownSchema, undefined>, undefined>;
34
+ readonly emitter: v.ObjectSchema<{
35
+ readonly tool: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>]>;
36
+ readonly user: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>]>, undefined>;
37
+ readonly version: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>]>;
38
+ }, undefined>;
39
+ readonly idempotencyKey: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>]>, undefined>;
40
+ readonly links: v.OptionalSchema<v.ObjectWithRestSchema<{
41
+ readonly affectedFiles: v.OptionalSchema<v.ArraySchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>, v.CheckAction<string, "Expected a normalized workspace-relative path.">]>, undefined>, undefined>;
42
+ readonly blobs: v.OptionalSchema<v.ArraySchema<v.StringSchema<undefined>, undefined>, undefined>;
43
+ readonly briefId: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
44
+ readonly correctsLedgerId: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
45
+ readonly gitRef: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
46
+ readonly idempotencyKey: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
47
+ readonly stripDecisionId: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
48
+ readonly supersedesLedgerId: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
49
+ readonly validatorVerdictId: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
50
+ }, v.UnknownSchema, undefined>, undefined>;
51
+ readonly phase: v.PicklistSchema<readonly ["capture", "intake", "seed", "vendor-extract", "cleanup", "parity", "characterize", "equiv", "analyze", "recover", "ship", "migration"], undefined>;
52
+ readonly summary: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>]>;
53
+ }, undefined>;
28
54
  export declare const AgentPatchRecordSchema: v.SchemaWithPipe<readonly [v.ObjectSchema<{
29
55
  readonly agent: v.ObjectSchema<{
30
56
  readonly name: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>]>;
@@ -459,6 +485,31 @@ export declare const LedgerRecordSchema: v.VariantSchema<"kind", [v.ObjectSchema
459
485
  }, v.UnknownSchema, undefined>, undefined>;
460
486
  readonly phase: v.PicklistSchema<readonly ["capture", "intake", "seed", "vendor-extract", "cleanup", "parity", "characterize", "equiv", "analyze", "recover", "ship", "migration"], undefined>;
461
487
  readonly summary: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>]>;
488
+ }, undefined>, v.ObjectSchema<{
489
+ readonly filePath: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>, v.CheckAction<string, "Expected a normalized workspace-relative path.">]>;
490
+ readonly kind: v.LiteralSchema<"stage-write", undefined>;
491
+ readonly rationale: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>]>;
492
+ readonly stage: v.PicklistSchema<readonly ["intake", "seed", "vendor-extract", "cleanup", "candidate-promotion"], undefined>;
493
+ readonly details: v.OptionalSchema<v.RecordSchema<v.StringSchema<undefined>, v.UnknownSchema, undefined>, undefined>;
494
+ readonly emitter: v.ObjectSchema<{
495
+ readonly tool: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>]>;
496
+ readonly user: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>]>, undefined>;
497
+ readonly version: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>]>;
498
+ }, undefined>;
499
+ readonly idempotencyKey: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>]>, undefined>;
500
+ readonly links: v.OptionalSchema<v.ObjectWithRestSchema<{
501
+ readonly affectedFiles: v.OptionalSchema<v.ArraySchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>, v.CheckAction<string, "Expected a normalized workspace-relative path.">]>, undefined>, undefined>;
502
+ readonly blobs: v.OptionalSchema<v.ArraySchema<v.StringSchema<undefined>, undefined>, undefined>;
503
+ readonly briefId: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
504
+ readonly correctsLedgerId: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
505
+ readonly gitRef: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
506
+ readonly idempotencyKey: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
507
+ readonly stripDecisionId: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
508
+ readonly supersedesLedgerId: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
509
+ readonly validatorVerdictId: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
510
+ }, v.UnknownSchema, undefined>, undefined>;
511
+ readonly phase: v.PicklistSchema<readonly ["capture", "intake", "seed", "vendor-extract", "cleanup", "parity", "characterize", "equiv", "analyze", "recover", "ship", "migration"], undefined>;
512
+ readonly summary: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>]>;
462
513
  }, undefined>, v.SchemaWithPipe<readonly [v.ObjectSchema<{
463
514
  readonly agent: v.ObjectSchema<{
464
515
  readonly name: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>]>;
@@ -1 +1 @@
1
- {"version":3,"file":"entry-write.d.ts","sourceRoot":"","sources":["../../src/schema/entry-write.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,SAAS,CAAC;AAoC7B,eAAO,MAAM,0BAA0B;;;;;;;;;;;;;;;;;;;;;;;;;aAMrC,CAAC;AAUH,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8HAUlC,CAAC;AAEF,eAAO,MAAM,yBAAyB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8HASrC,CAAC;AAEF,eAAO,MAAM,4BAA4B;;;;;;;;;;;;;;;;;;;;;;;;;;;aAIvC,CAAC;AAEH,eAAO,MAAM,2BAA2B;;;;;;;;;;;;;;;;;;;;;;;;;;aAOtC,CAAC;AAEH,eAAO,MAAM,wBAAwB;;;;;;;;;;;;;;;;;;;;;;;;;;aAOnC,CAAC;AAEH,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;aAK3B,CAAC;AAEH,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;yDAOlC,CAAC;AAEF,eAAO,MAAM,iCAAiC;;;;;;;;;;;;;;;;;;;;;;;;;;;aAI5C,CAAC;AAEH,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;qDAkBjC,CAAC;AAEF,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kEAW7B,CAAC;AAEH,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,WAAW,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAC1E,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,WAAW,CAAC,OAAO,kBAAkB,CAAC,CAAC"}
1
+ {"version":3,"file":"entry-write.d.ts","sourceRoot":"","sources":["../../src/schema/entry-write.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,SAAS,CAAC;AAsC7B,eAAO,MAAM,0BAA0B;;;;;;;;;;;;;;;;;;;;;;;;;aAMrC,CAAC;AAEH,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;;;;;;aAMjC,CAAC;AAUH,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8HAUlC,CAAC;AAEF,eAAO,MAAM,yBAAyB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8HASrC,CAAC;AAEF,eAAO,MAAM,4BAA4B;;;;;;;;;;;;;;;;;;;;;;;;;;;aAIvC,CAAC;AAEH,eAAO,MAAM,2BAA2B;;;;;;;;;;;;;;;;;;;;;;;;;;aAOtC,CAAC;AAEH,eAAO,MAAM,wBAAwB;;;;;;;;;;;;;;;;;;;;;;;;;;aAOnC,CAAC;AAEH,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;aAK3B,CAAC;AAEH,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;yDAOlC,CAAC;AAEF,eAAO,MAAM,iCAAiC;;;;;;;;;;;;;;;;;;;;;;;;;;;aAI5C,CAAC;AAEH,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;qDAkBjC,CAAC;AAEF,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kEAY7B,CAAC;AAEH,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,WAAW,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAC1E,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,WAAW,CAAC,OAAO,kBAAkB,CAAC,CAAC"}
@@ -1,5 +1,5 @@
1
1
  import * as v from 'valibot';
2
- import { AgentPatchDiffSchema, ChangeLogFileChangeSchema, ChangeLogParityStatusSchema, ChangeLogSmokeResultSchema, ChangeLogSubkindSchema, NonEmptyTrimmedStringSchema, OperatorDecisionPayloadSchema, recordEntryBaseEntries, StripDecisionRevertedPayloadSchema, } from "./entry-core.js";
2
+ import { AgentPatchDiffSchema, ChangeLogFileChangeSchema, ChangeLogParityStatusSchema, ChangeLogSmokeResultSchema, ChangeLogSubkindSchema, NonEmptyTrimmedStringSchema, OperatorDecisionPayloadSchema, recordEntryBaseEntries, StageWriteStageSchema, StripDecisionRevertedPayloadSchema, WorkspaceRelativePathSchema, } from "./entry-core.js";
3
3
  import { NoteSubkindSchema } from "./note.js";
4
4
  const validatePatchRecord = (value) => {
5
5
  const provided = [value.diff, value.diffPath, value.diffText].filter((entry) => Boolean(entry));
@@ -19,6 +19,13 @@ export const ToolInvocationRecordSchema = v.object({
19
19
  exitCode: v.optional(v.pipe(v.number(), v.integer())),
20
20
  kind: v.literal('tool-invocation'),
21
21
  });
22
+ export const StageWriteRecordSchema = v.object({
23
+ ...recordEntryBaseEntries,
24
+ filePath: WorkspaceRelativePathSchema,
25
+ kind: v.literal('stage-write'),
26
+ rationale: NonEmptyTrimmedStringSchema,
27
+ stage: StageWriteStageSchema,
28
+ });
22
29
  const patchRecordEntries = {
23
30
  ...recordEntryBaseEntries,
24
31
  diff: v.optional(AgentPatchDiffSchema),
@@ -93,6 +100,7 @@ export const ChangeLogRecordSchema = v.pipe(v.object({
93
100
  }), v.check((value) => value.subkind !== 'rollback' || Boolean(value.rollsBack), 'change-log rollback records require rollsBack'));
94
101
  export const LedgerRecordSchema = v.variant('kind', [
95
102
  ToolInvocationRecordSchema,
103
+ StageWriteRecordSchema,
96
104
  AgentPatchRecordSchema,
97
105
  OperatorPatchRecordSchema,
98
106
  OperatorDecisionRecordSchema,
@@ -8,11 +8,22 @@ type AtomicWriteTestHook = {
8
8
  readonly beforeWrite?: () => Promise<void>;
9
9
  readonly retainOnThrow?: boolean;
10
10
  };
11
+ type AtomicTempFileRegistration = {
12
+ readonly remove: () => Promise<void>;
13
+ };
14
+ type AtomicWriteOptions = {
15
+ readonly registerTempFile?: (context: {
16
+ readonly finalPath: string;
17
+ readonly tempPath: string;
18
+ }) => Promise<AtomicTempFileRegistration>;
19
+ };
11
20
  export type LedgerPaths = {
12
21
  readonly blobsDir: string;
22
+ readonly externalTempFilesDir: string;
13
23
  readonly lockFile: (phase: LedgerPhase) => string;
14
24
  readonly manifestLockFile: string;
15
25
  readonly manifestFile: string;
26
+ readonly pendingCommitQuarantineDir: string;
16
27
  readonly pendingCommitsDir: string;
17
28
  readonly pendingArchivesDir: string;
18
29
  readonly phaseDir: (phase: LedgerPhase) => string;
@@ -32,9 +43,10 @@ export type AtomicTextFileWriter = {
32
43
  export declare const resolveLedgerPaths: (workspaceRoot: string) => LedgerPaths;
33
44
  export declare const ensureLedgerDirectories: (workspaceRoot: string) => Promise<LedgerPaths>;
34
45
  export declare const setAtomicWriteTestHook: (filePath: string, hook: AtomicWriteTestHook | null) => void;
35
- export declare const writeAtomicTextFile: (filePath: string, text: string) => Promise<void>;
36
- export declare const createAtomicTextFileWriter: (filePath: string) => Promise<AtomicTextFileWriter>;
46
+ export declare const writeAtomicTextFile: (filePath: string, text: string, options?: AtomicWriteOptions) => Promise<void>;
47
+ export declare const createAtomicTextFileWriter: (filePath: string, options?: AtomicWriteOptions) => Promise<AtomicTextFileWriter>;
37
48
  export declare const writeAtomicJsonFile: (filePath: string, value: unknown) => Promise<void>;
49
+ export declare const createExternalTempFileRegistrar: (workspaceRoot: string) => NonNullable<AtomicWriteOptions["registerTempFile"]>;
38
50
  export declare const readManifest: (workspaceRoot: string) => Promise<LedgerManifest>;
39
51
  export declare const saveManifest: (workspaceRoot: string, manifest: LedgerManifest) => Promise<void>;
40
52
  export declare const cleanupStaleTempFiles: (workspaceRoot: string) => Promise<void>;