ushman-ledger 0.3.0 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (80) hide show
  1. package/AGENTS.md +11 -7
  2. package/CHANGELOG.md +8 -12
  3. package/README.md +28 -57
  4. package/dist/archive-journal.d.ts +29 -18
  5. package/dist/archive-journal.d.ts.map +1 -1
  6. package/dist/archive-journal.js +17 -17
  7. package/dist/blobs.js +3 -3
  8. package/dist/builders.d.ts +79 -358
  9. package/dist/builders.d.ts.map +1 -1
  10. package/dist/builders.js +15 -60
  11. package/dist/cli.d.ts.map +1 -1
  12. package/dist/cli.js +227 -52
  13. package/dist/doctor.d.ts.map +1 -1
  14. package/dist/doctor.js +104 -4
  15. package/dist/handle.d.ts +4 -2
  16. package/dist/handle.d.ts.map +1 -1
  17. package/dist/handle.js +20 -15
  18. package/dist/helpers.d.ts +7 -0
  19. package/dist/helpers.d.ts.map +1 -0
  20. package/dist/helpers.js +38 -0
  21. package/dist/index.d.ts +4 -5
  22. package/dist/index.d.ts.map +1 -1
  23. package/dist/index.js +3 -4
  24. package/dist/lab-min.d.ts +7 -7
  25. package/dist/lab-min.d.ts.map +1 -1
  26. package/dist/lab-min.js +7 -9
  27. package/dist/list.d.ts +104 -303
  28. package/dist/list.d.ts.map +1 -1
  29. package/dist/note.d.ts +20 -0
  30. package/dist/note.d.ts.map +1 -1
  31. package/dist/note.js +5 -0
  32. package/dist/patch-resolver.d.ts +27 -0
  33. package/dist/patch-resolver.d.ts.map +1 -0
  34. package/dist/patch-resolver.js +184 -0
  35. package/dist/read-index.d.ts +45 -57
  36. package/dist/read-index.d.ts.map +1 -1
  37. package/dist/read-index.js +16 -34
  38. package/dist/record.d.ts.map +1 -1
  39. package/dist/record.js +19 -130
  40. package/dist/recovery.d.ts +19 -8
  41. package/dist/recovery.d.ts.map +1 -1
  42. package/dist/recovery.js +13 -13
  43. package/dist/render/migration-log.d.ts +3 -0
  44. package/dist/render/migration-log.d.ts.map +1 -0
  45. package/dist/render/migration-log.js +72 -0
  46. package/dist/render/retro.d.ts.map +1 -1
  47. package/dist/render/retro.js +41 -25
  48. package/dist/render/workspace-narrative.d.ts +6 -0
  49. package/dist/render/workspace-narrative.d.ts.map +1 -0
  50. package/dist/render/workspace-narrative.js +69 -0
  51. package/dist/schema/entry-core.d.ts +110 -0
  52. package/dist/schema/entry-core.d.ts.map +1 -0
  53. package/dist/schema/entry-core.js +143 -0
  54. package/dist/schema/entry-migrations.d.ts +3 -0
  55. package/dist/schema/entry-migrations.d.ts.map +1 -0
  56. package/dist/schema/entry-migrations.js +48 -0
  57. package/dist/schema/entry-read.d.ts +694 -0
  58. package/dist/schema/entry-read.d.ts.map +1 -0
  59. package/dist/schema/entry-read.js +92 -0
  60. package/dist/schema/entry-write.d.ts +865 -0
  61. package/dist/schema/entry-write.d.ts.map +1 -0
  62. package/dist/schema/entry-write.js +105 -0
  63. package/dist/schema/entry.d.ts +6 -3295
  64. package/dist/schema/entry.d.ts.map +1 -1
  65. package/dist/schema/entry.js +10 -619
  66. package/dist/schema/manifest.d.ts +28 -41
  67. package/dist/schema/manifest.d.ts.map +1 -1
  68. package/dist/schema/manifest.js +20 -24
  69. package/dist/schema/note.d.ts +3 -9
  70. package/dist/schema/note.d.ts.map +1 -1
  71. package/dist/schema/note.js +13 -2
  72. package/dist/storage/filesystem.d.ts +2 -1
  73. package/dist/storage/filesystem.d.ts.map +1 -1
  74. package/dist/storage/filesystem.js +6 -4
  75. package/dist/storage/lock-reclaimer.d.ts +2 -0
  76. package/dist/storage/lock-reclaimer.d.ts.map +1 -0
  77. package/dist/storage/lock-reclaimer.js +45 -0
  78. package/dist/version.d.ts +1 -1
  79. package/dist/version.js +1 -1
  80. package/package.json +3 -4
@@ -1 +1 @@
1
- {"version":3,"file":"note.d.ts","sourceRoot":"","sources":["../src/note.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAGpD,MAAM,MAAM,QAAQ,GAAG;IACnB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC;IAC5B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC5B,CAAC;AAEF,eAAO,MAAM,UAAU,GACnB,eAAe,MAAM,EACrB,SAAS,WAAW,EACpB,UAAU,QAAQ,KACnB,OAAO,CAAC;IAAE,KAAK,EAAE,OAAO,CAAC,UAAU,CAAC,OAAO,YAAY,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,CAYlF,CAAC"}
1
+ {"version":3,"file":"note.d.ts","sourceRoot":"","sources":["../src/note.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAGpD,MAAM,MAAM,QAAQ,GAAG;IACnB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC;IAC5B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC5B,CAAC;AAEF,eAAO,MAAM,UAAU,GACnB,eAAe,MAAM,EACrB,SAAS,WAAW,EACpB,UAAU,QAAQ,KACnB,OAAO,CAAC;IAAE,KAAK,EAAE,OAAO,CAAC,UAAU,CAAC,OAAO,YAAY,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,CAYlF,CAAC;AAEF,eAAO,MAAM,qBAAqB,GAAI,eAAe,MAAM,EAAE,UAAU,QAAQ;WAd3D,OAAO,CAAC,UAAU,CAAC,OAAO,YAAY,CAAC,CAAC,CAAC,OAAO,CAAC;QAAM,MAAM;EAe1B,CAAC;AAExD,eAAO,MAAM,sBAAsB,GAAI,eAAe,MAAM,EAAE,UAAU,QAAQ;WAjB5D,OAAO,CAAC,UAAU,CAAC,OAAO,YAAY,CAAC,CAAC,CAAC,OAAO,CAAC;QAAM,MAAM;EAkBzB,CAAC;AAEzD,eAAO,MAAM,mBAAmB,GAAI,eAAe,MAAM,EAAE,UAAU,QAAQ;WApBzD,OAAO,CAAC,UAAU,CAAC,OAAO,YAAY,CAAC,CAAC,CAAC,OAAO,CAAC;QAAM,MAAM;EAqB5B,CAAC;AAEtD,eAAO,MAAM,2BAA2B,GAAI,eAAe,MAAM,EAAE,UAAU,QAAQ;WAvBjE,OAAO,CAAC,UAAU,CAAC,OAAO,YAAY,CAAC,CAAC,CAAC,OAAO,CAAC;QAAM,MAAM;EAwBpB,CAAC;AAE9D,eAAO,MAAM,gCAAgC,GAAI,eAAe,MAAM,EAAE,UAAU,QAAQ;WA1BtE,OAAO,CAAC,UAAU,CAAC,OAAO,YAAY,CAAC,CAAC,CAAC,OAAO,CAAC;QAAM,MAAM;EA2Bd,CAAC"}
package/dist/note.js CHANGED
@@ -13,3 +13,8 @@ export const appendNote = async (workspaceRoot, subkind, noteBody) => {
13
13
  summary: noteBody.summary,
14
14
  });
15
15
  };
16
+ export const appendCleanupWaveNote = (workspaceRoot, noteBody) => appendNote(workspaceRoot, 'cleanup-wave', noteBody);
17
+ export const appendVerifiedFlowNote = (workspaceRoot, noteBody) => appendNote(workspaceRoot, 'verified-flow', noteBody);
18
+ export const appendOpenIssueNote = (workspaceRoot, noteBody) => appendNote(workspaceRoot, 'open-issue', noteBody);
19
+ export const appendDecompositionWaveNote = (workspaceRoot, noteBody) => appendNote(workspaceRoot, 'decomposition-wave', noteBody);
20
+ export const appendSemanticCleanupSummaryNote = (workspaceRoot, noteBody) => appendNote(workspaceRoot, 'semantic-cleanup-summary', noteBody);
@@ -0,0 +1,27 @@
1
+ import { type AgentPatchDiff, type ChangeLogFileChange, type LedgerLinks, type LedgerRecord } from './schema/entry.ts';
2
+ type AgentPatchRecord = Extract<LedgerRecord, {
3
+ kind: 'agent-patch';
4
+ }>;
5
+ type OperatorPatchRecord = Extract<LedgerRecord, {
6
+ kind: 'operator-patch';
7
+ }>;
8
+ type ResolvedAgentPatchRecord = Omit<AgentPatchRecord, 'diffPath' | 'diffText' | 'links'> & {
9
+ readonly diff: AgentPatchDiff;
10
+ readonly links: LedgerLinks;
11
+ };
12
+ type ResolvedOperatorPatchRecord = Omit<OperatorPatchRecord, 'diffPath' | 'diffText' | 'links'> & {
13
+ readonly diff: AgentPatchDiff;
14
+ readonly links: LedgerLinks;
15
+ };
16
+ export type ResolvedPatchRecord = ResolvedAgentPatchRecord | ResolvedOperatorPatchRecord;
17
+ export declare const deriveFilesChangedFromPatch: (patchText: string) => ChangeLogFileChange[];
18
+ export declare function resolvePatchRecord(args: {
19
+ readonly record: AgentPatchRecord;
20
+ readonly workspaceRoot: string;
21
+ }): Promise<ResolvedAgentPatchRecord>;
22
+ export declare function resolvePatchRecord(args: {
23
+ readonly record: OperatorPatchRecord;
24
+ readonly workspaceRoot: string;
25
+ }): Promise<ResolvedOperatorPatchRecord>;
26
+ export {};
27
+ //# sourceMappingURL=patch-resolver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"patch-resolver.d.ts","sourceRoot":"","sources":["../src/patch-resolver.ts"],"names":[],"mappings":"AAIA,OAAO,EACH,KAAK,cAAc,EACnB,KAAK,mBAAmB,EACxB,KAAK,WAAW,EAChB,KAAK,YAAY,EAEpB,MAAM,mBAAmB,CAAC;AAI3B,KAAK,gBAAgB,GAAG,OAAO,CAAC,YAAY,EAAE;IAAE,IAAI,EAAE,aAAa,CAAA;CAAE,CAAC,CAAC;AACvE,KAAK,mBAAmB,GAAG,OAAO,CAAC,YAAY,EAAE;IAAE,IAAI,EAAE,gBAAgB,CAAA;CAAE,CAAC,CAAC;AAQ7E,KAAK,wBAAwB,GAAG,IAAI,CAAC,gBAAgB,EAAE,UAAU,GAAG,UAAU,GAAG,OAAO,CAAC,GAAG;IACxF,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC;IAC9B,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC;CAC/B,CAAC;AACF,KAAK,2BAA2B,GAAG,IAAI,CAAC,mBAAmB,EAAE,UAAU,GAAG,UAAU,GAAG,OAAO,CAAC,GAAG;IAC9F,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC;IAC9B,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC;CAC/B,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG,wBAAwB,GAAG,2BAA2B,CAAC;AAqKzF,eAAO,MAAM,2BAA2B,GAAI,WAAW,MAAM,KAAG,mBAAmB,EAuClF,CAAC;AAmBF,wBAAgB,kBAAkB,CAAC,IAAI,EAAE;IACrC,QAAQ,CAAC,MAAM,EAAE,gBAAgB,CAAC;IAClC,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;CAClC,GAAG,OAAO,CAAC,wBAAwB,CAAC,CAAC;AACtC,wBAAgB,kBAAkB,CAAC,IAAI,EAAE;IACrC,QAAQ,CAAC,MAAM,EAAE,mBAAmB,CAAC;IACrC,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;CAClC,GAAG,OAAO,CAAC,2BAA2B,CAAC,CAAC"}
@@ -0,0 +1,184 @@
1
+ import { readFile } from 'node:fs/promises';
2
+ import path from 'node:path';
3
+ import * as v from 'valibot';
4
+ import { resolveBlobPath, storePatchBlob } from "./blobs.js";
5
+ import { WorkspaceRelativePathSchema, } from "./schema/entry.js";
6
+ const readBlobText = async (workspaceRoot, blobSha256) => readFile(resolveBlobPath(workspaceRoot, blobSha256), 'utf8');
7
+ const formatRecordContext = (record) => `${record.kind} "${record.summary}" [${record.phase}]`;
8
+ const normalizeWorkspaceRelativePath = (value) => v.parse(WorkspaceRelativePathSchema, value.replaceAll('\\', '/'));
9
+ const stripGitPathPrefix = (value) => {
10
+ const normalized = value.trim().replace(/^"([^"]*)"$/u, '$1');
11
+ if (normalized === '/dev/null') {
12
+ return null;
13
+ }
14
+ if (normalized.startsWith('a/') || normalized.startsWith('b/')) {
15
+ return normalized.slice(2);
16
+ }
17
+ return normalized;
18
+ };
19
+ const inferHeaderPath = (line) => {
20
+ const match = /^diff --git (?:"a\/([^"]+)"|a\/(\S+)) (?:"b\/([^"]+)"|b\/(\S+))$/u.exec(line.trim());
21
+ if (!match) {
22
+ return null;
23
+ }
24
+ const rightPath = match[3] ?? match[4];
25
+ return rightPath ? stripGitPathPrefix(`b/${rightPath}`) : null;
26
+ };
27
+ const finalizeFileChange = (current, filesChanged) => {
28
+ if (!current) {
29
+ return;
30
+ }
31
+ const resolvedPath = current.plusPath ?? current.minusPath ?? current.headerPath;
32
+ if (!resolvedPath) {
33
+ throw new Error('Unable to derive a workspace-relative path from a diff block.');
34
+ }
35
+ filesChanged.push({
36
+ added: current.added > 0 ? current.added : undefined,
37
+ path: normalizeWorkspaceRelativePath(resolvedPath),
38
+ removed: current.removed > 0 ? current.removed : undefined,
39
+ });
40
+ };
41
+ const createDiffFileAccumulator = (line) => ({
42
+ added: 0,
43
+ headerPath: inferHeaderPath(line),
44
+ minusPath: null,
45
+ plusPath: null,
46
+ removed: 0,
47
+ });
48
+ const applyPatchMetadataLine = (current, line) => {
49
+ if (line.startsWith('+++ ')) {
50
+ return {
51
+ next: {
52
+ ...current,
53
+ plusPath: stripGitPathPrefix(line.slice(4)),
54
+ },
55
+ };
56
+ }
57
+ if (line.startsWith('--- ')) {
58
+ return {
59
+ next: {
60
+ ...current,
61
+ minusPath: stripGitPathPrefix(line.slice(4)),
62
+ },
63
+ };
64
+ }
65
+ if (line.startsWith('@@')) {
66
+ return {
67
+ next: current,
68
+ startHunk: true,
69
+ };
70
+ }
71
+ return {
72
+ next: current,
73
+ };
74
+ };
75
+ const applyPatchHunkLine = (current, line) => {
76
+ if (line.startsWith('+')) {
77
+ return {
78
+ ...current,
79
+ added: current.added + 1,
80
+ };
81
+ }
82
+ if (line.startsWith('-')) {
83
+ return {
84
+ ...current,
85
+ removed: current.removed + 1,
86
+ };
87
+ }
88
+ return current;
89
+ };
90
+ const mergeBlobLink = (links, blobSha256) => ({
91
+ ...links,
92
+ blobs: [...new Set([...(links?.blobs ?? []), blobSha256])],
93
+ });
94
+ const resolvePatchSource = async ({ record, workspaceRoot, }) => {
95
+ if (record.diffPath) {
96
+ const resolvedPath = path.resolve(workspaceRoot, record.diffPath);
97
+ return {
98
+ patchText: await readFile(resolvedPath, 'utf8'),
99
+ source: 'file',
100
+ sourceLabel: resolvedPath,
101
+ };
102
+ }
103
+ if (record.diffText) {
104
+ return {
105
+ patchText: record.diffText,
106
+ source: 'inline',
107
+ sourceLabel: 'inline diff text',
108
+ };
109
+ }
110
+ if (record.diff) {
111
+ try {
112
+ return {
113
+ patchText: await readBlobText(workspaceRoot, record.diff.blobSha256),
114
+ source: 'blob',
115
+ sourceLabel: `blob ${record.diff.blobSha256}`,
116
+ };
117
+ }
118
+ catch (error) {
119
+ if (error.code === 'ENOENT') {
120
+ throw new Error(`Patch blob ${record.diff.blobSha256} was not found for ${formatRecordContext(record)}. Store it first or use diffPath.`);
121
+ }
122
+ throw error;
123
+ }
124
+ }
125
+ throw new Error(`${record.kind} records require diff, diffPath, or diffText.`);
126
+ };
127
+ export const deriveFilesChangedFromPatch = (patchText) => {
128
+ const filesChanged = [];
129
+ let current;
130
+ let insideHunk = false;
131
+ for (const line of patchText.split(/\r?\n/u)) {
132
+ if (line.startsWith('diff --git ')) {
133
+ finalizeFileChange(current, filesChanged);
134
+ current = createDiffFileAccumulator(line);
135
+ insideHunk = false;
136
+ continue;
137
+ }
138
+ if (!current) {
139
+ continue;
140
+ }
141
+ if (insideHunk) {
142
+ if (line.startsWith('@@')) {
143
+ continue;
144
+ }
145
+ current = applyPatchHunkLine(current, line);
146
+ continue;
147
+ }
148
+ const metadataUpdate = applyPatchMetadataLine(current, line);
149
+ current = metadataUpdate.next;
150
+ if (metadataUpdate.startHunk) {
151
+ insideHunk = true;
152
+ continue;
153
+ }
154
+ if (!insideHunk) {
155
+ continue;
156
+ }
157
+ current = applyPatchHunkLine(current, line);
158
+ }
159
+ finalizeFileChange(current, filesChanged);
160
+ return filesChanged;
161
+ };
162
+ const buildResolvedPatchRecord = ({ links, record, storedDiff, }) => {
163
+ const { diffPath: _diffPath, diffText: _diffText, ...rest } = record;
164
+ return {
165
+ ...rest,
166
+ diff: storedDiff,
167
+ links,
168
+ };
169
+ };
170
+ export async function resolvePatchRecord({ record, workspaceRoot, }) {
171
+ const { patchText, sourceLabel } = await resolvePatchSource({
172
+ record,
173
+ workspaceRoot,
174
+ });
175
+ const storedDiff = await storePatchBlob(workspaceRoot, patchText);
176
+ if (record.diff && record.diff.blobSha256 !== storedDiff.blobSha256) {
177
+ throw new Error(`Provided diff blob ${record.diff.blobSha256} from ${sourceLabel} does not match patch text hash ${storedDiff.blobSha256} for ${formatRecordContext(record)}.`);
178
+ }
179
+ return buildResolvedPatchRecord({
180
+ links: mergeBlobLink(record.links, storedDiff.blobSha256),
181
+ record,
182
+ storedDiff,
183
+ });
184
+ }
@@ -1,59 +1,47 @@
1
- import { z } from 'zod';
1
+ import * as v from 'valibot';
2
2
  import { type LedgerEntry, type LedgerKind, type LedgerPhase } from './schema/entry.ts';
3
3
  import type { LedgerManifest } from './schema/manifest.ts';
4
- declare const ReadIndexEntrySchema: z.ZodObject<{
5
- id: z.ZodString;
6
- kind: z.ZodEnum<{
7
- "tool-invocation": "tool-invocation";
8
- "agent-patch": "agent-patch";
9
- "operator-patch": "operator-patch";
10
- "stage-transition": "stage-transition";
11
- "operator-decision": "operator-decision";
12
- "validator-result": "validator-result";
13
- "runtime-event": "runtime-event";
14
- note: "note";
15
- correction: "correction";
16
- "strip-decision-reverted": "strip-decision-reverted";
17
- "descope-brief": "descope-brief";
18
- "merge-return": "merge-return";
19
- "merge-return-rejected": "merge-return-rejected";
20
- revert: "revert";
21
- rollback: "rollback";
22
- "rework.test_retired": "rework.test_retired";
23
- }>;
24
- ts: z.ZodString;
25
- }, z.core.$strip>;
26
- declare const LedgerReadIndexSchema: z.ZodObject<{
27
- coveredFiles: z.ZodDefault<z.ZodArray<z.ZodString>>;
28
- entries: z.ZodDefault<z.ZodArray<z.ZodObject<{
29
- id: z.ZodString;
30
- kind: z.ZodEnum<{
31
- "tool-invocation": "tool-invocation";
32
- "agent-patch": "agent-patch";
33
- "operator-patch": "operator-patch";
34
- "stage-transition": "stage-transition";
35
- "operator-decision": "operator-decision";
36
- "validator-result": "validator-result";
37
- "runtime-event": "runtime-event";
38
- note: "note";
39
- correction: "correction";
40
- "strip-decision-reverted": "strip-decision-reverted";
41
- "descope-brief": "descope-brief";
42
- "merge-return": "merge-return";
43
- "merge-return-rejected": "merge-return-rejected";
44
- revert: "revert";
45
- rollback: "rollback";
46
- "rework.test_retired": "rework.test_retired";
47
- }>;
48
- ts: z.ZodString;
49
- }, z.core.$strip>>>;
50
- entryCount: z.ZodNumber;
51
- lastEntryId: z.ZodNullable<z.ZodString>;
52
- lastSequence: z.ZodNumber;
53
- schemaVersion: z.ZodLiteral<"ushman-ledger-read-index/v1">;
54
- }, z.core.$strip>;
55
- export type LedgerReadIndex = z.infer<typeof LedgerReadIndexSchema>;
56
- export type ReadIndexEntry = z.infer<typeof ReadIndexEntrySchema>;
4
+ declare const ReadIndexEntrySchema: v.ObjectSchema<{
5
+ readonly id: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>]>;
6
+ readonly kind: v.PicklistSchema<readonly ["tool-invocation", "agent-patch", "operator-patch", "operator-decision", "validator-result", "runtime-event", "note", "correction", "strip-decision-reverted", "change-log"], undefined>;
7
+ readonly ts: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, undefined>]>;
8
+ }, undefined>;
9
+ declare const LedgerReadIndexSchema: v.SchemaWithPipe<readonly [v.ObjectSchema<{
10
+ readonly coveredFiles: v.OptionalSchema<v.ArraySchema<v.StringSchema<undefined>, undefined>, readonly []>;
11
+ readonly entries: v.OptionalSchema<v.ArraySchema<v.ObjectSchema<{
12
+ readonly id: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>]>;
13
+ readonly kind: v.PicklistSchema<readonly ["tool-invocation", "agent-patch", "operator-patch", "operator-decision", "validator-result", "runtime-event", "note", "correction", "strip-decision-reverted", "change-log"], undefined>;
14
+ readonly ts: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, undefined>]>;
15
+ }, undefined>, undefined>, readonly []>;
16
+ readonly entryCount: v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.IntegerAction<number, undefined>, v.MinValueAction<number, 0, undefined>]>;
17
+ readonly lastEntryId: v.NullableSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>]>, undefined>;
18
+ readonly lastSequence: v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.IntegerAction<number, undefined>, v.MinValueAction<number, 0, undefined>]>;
19
+ readonly schemaVersion: v.LiteralSchema<"ushman-ledger-read-index/v1", undefined>;
20
+ }, undefined>, v.CheckAction<{
21
+ coveredFiles: string[];
22
+ entries: {
23
+ id: string;
24
+ kind: "operator-decision" | "validator-result" | "change-log" | "tool-invocation" | "agent-patch" | "operator-patch" | "runtime-event" | "note" | "correction" | "strip-decision-reverted";
25
+ ts: string;
26
+ }[];
27
+ entryCount: number;
28
+ lastEntryId: string | null;
29
+ lastSequence: number;
30
+ schemaVersion: "ushman-ledger-read-index/v1";
31
+ }, "entryCount must match entries.length">, v.CheckAction<{
32
+ coveredFiles: string[];
33
+ entries: {
34
+ id: string;
35
+ kind: "operator-decision" | "validator-result" | "change-log" | "tool-invocation" | "agent-patch" | "operator-patch" | "runtime-event" | "note" | "correction" | "strip-decision-reverted";
36
+ ts: string;
37
+ }[];
38
+ entryCount: number;
39
+ lastEntryId: string | null;
40
+ lastSequence: number;
41
+ schemaVersion: "ushman-ledger-read-index/v1";
42
+ }, "lastEntryId must match the final indexed entry">]>;
43
+ export type LedgerReadIndex = v.InferOutput<typeof LedgerReadIndexSchema>;
44
+ export type ReadIndexEntry = v.InferOutput<typeof ReadIndexEntrySchema>;
57
45
  export type ManifestEntryLocation = readonly [string, {
58
46
  phase: LedgerPhase;
59
47
  sequence: number;
@@ -62,7 +50,7 @@ export declare const buildReadIndexFromManifest: (workspaceRoot: string, manifes
62
50
  coveredFiles: string[];
63
51
  entries: {
64
52
  id: string;
65
- kind: "tool-invocation" | "agent-patch" | "operator-patch" | "stage-transition" | "operator-decision" | "validator-result" | "runtime-event" | "note" | "correction" | "strip-decision-reverted" | "descope-brief" | "merge-return" | "merge-return-rejected" | "revert" | "rollback" | "rework.test_retired";
53
+ kind: "operator-decision" | "validator-result" | "change-log" | "tool-invocation" | "agent-patch" | "operator-patch" | "runtime-event" | "note" | "correction" | "strip-decision-reverted";
66
54
  ts: string;
67
55
  }[];
68
56
  entryCount: number;
@@ -77,7 +65,7 @@ export declare const ensureReadIndexUnderLock: (workspaceRoot: string, manifest:
77
65
  coveredFiles: string[];
78
66
  entries: {
79
67
  id: string;
80
- kind: "tool-invocation" | "agent-patch" | "operator-patch" | "stage-transition" | "operator-decision" | "validator-result" | "runtime-event" | "note" | "correction" | "strip-decision-reverted" | "descope-brief" | "merge-return" | "merge-return-rejected" | "revert" | "rollback" | "rework.test_retired";
68
+ kind: "operator-decision" | "validator-result" | "change-log" | "tool-invocation" | "agent-patch" | "operator-patch" | "runtime-event" | "note" | "correction" | "strip-decision-reverted";
81
69
  ts: string;
82
70
  }[];
83
71
  entryCount: number;
@@ -93,7 +81,7 @@ export declare const appendEntryToReadIndex: ({ entry, readIndex, sequence, }: {
93
81
  coveredFiles: string[];
94
82
  entries: {
95
83
  id: string;
96
- kind: "tool-invocation" | "agent-patch" | "operator-patch" | "stage-transition" | "operator-decision" | "validator-result" | "runtime-event" | "note" | "correction" | "strip-decision-reverted" | "descope-brief" | "merge-return" | "merge-return-rejected" | "revert" | "rollback" | "rework.test_retired";
84
+ kind: "operator-decision" | "validator-result" | "change-log" | "tool-invocation" | "agent-patch" | "operator-patch" | "runtime-event" | "note" | "correction" | "strip-decision-reverted";
97
85
  ts: string;
98
86
  }[];
99
87
  entryCount: number;
@@ -1 +1 @@
1
- {"version":3,"file":"read-index.d.ts","sourceRoot":"","sources":["../src/read-index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,OAAO,EAAgB,KAAK,WAAW,EAAE,KAAK,UAAU,EAAE,KAAK,WAAW,EAAoB,MAAM,mBAAmB,CAAC;AACxH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAO3D,QAAA,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;iBAIxB,CAAC;AAEH,QAAA,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAyBrB,CAAC;AAEP,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AACpE,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAClE,MAAM,MAAM,qBAAqB,GAAG,SAAS,CAAC,MAAM,EAAE;IAAE,KAAK,EAAE,WAAW,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC;AA0HhG,eAAO,MAAM,0BAA0B,GAAU,eAAe,MAAM,EAAE,UAAU,cAAc;;;;;;;;;;;EAuB/F,CAAC;AAYF,eAAO,MAAM,kBAAkB,GAAI,OAAO,eAAe,EAAE,UAAU,cAAc,YAG1C,CAAC;AAE1C,eAAO,MAAM,aAAa,GAAU,eAAe,MAAM,KAAG,OAAO,CAAC,eAAe,GAAG,IAAI,CAWzF,CAAC;AAEF,eAAO,MAAM,aAAa,GAAU,eAAe,MAAM,EAAE,WAAW,eAAe,kBAGpF,CAAC;AAEF,eAAO,MAAM,wBAAwB,GAAU,eAAe,MAAM,EAAE,UAAU,cAAc;;;;;;;;;;;EAiB7F,CAAC;AAEF,eAAO,MAAM,sBAAsB,GAAI,iCAIpC;IACC,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC;IAC5B,QAAQ,CAAC,SAAS,EAAE,eAAe,CAAC;IACpC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC7B;;;;;;;;;;;CAYA,CAAC;AAEF,eAAO,MAAM,sBAAsB,GAAI,uCAIpC;IACC,QAAQ,CAAC,MAAM,EAAE;QACb,QAAQ,CAAC,IAAI,CAAC,EAAE,UAAU,CAAC;QAC3B,QAAQ,CAAC,KAAK,CAAC,EAAE,WAAW,CAAC;QAC7B,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;KAC3B,CAAC;IACF,QAAQ,CAAC,QAAQ,EAAE,cAAc,CAAC;IAClC,QAAQ,CAAC,cAAc,EAAE,cAAc,CAAC;CAC3C,YAeA,CAAC"}
1
+ {"version":3,"file":"read-index.d.ts","sourceRoot":"","sources":["../src/read-index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,CAAC,MAAM,SAAS,CAAC;AAG7B,OAAO,EAAgB,KAAK,WAAW,EAAE,KAAK,UAAU,EAAE,KAAK,WAAW,EAAoB,MAAM,mBAAmB,CAAC;AACxH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAO3D,QAAA,MAAM,oBAAoB;;;;aAIxB,CAAC;AAEH,QAAA,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;sDAiB1B,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,WAAW,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAC1E,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,WAAW,CAAC,OAAO,oBAAoB,CAAC,CAAC;AACxE,MAAM,MAAM,qBAAqB,GAAG,SAAS,CAAC,MAAM,EAAE;IAAE,KAAK,EAAE,WAAW,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC;AA0HhG,eAAO,MAAM,0BAA0B,GAAU,eAAe,MAAM,EAAE,UAAU,cAAc;;;;;;;;;;;EAuB/F,CAAC;AAYF,eAAO,MAAM,kBAAkB,GAAI,OAAO,eAAe,EAAE,UAAU,cAAc,YAG1C,CAAC;AAE1C,eAAO,MAAM,aAAa,GAAU,eAAe,MAAM,KAAG,OAAO,CAAC,eAAe,GAAG,IAAI,CAWzF,CAAC;AAEF,eAAO,MAAM,aAAa,GAAU,eAAe,MAAM,EAAE,WAAW,eAAe,kBAGpF,CAAC;AAEF,eAAO,MAAM,wBAAwB,GAAU,eAAe,MAAM,EAAE,UAAU,cAAc;;;;;;;;;;;EAiB7F,CAAC;AAEF,eAAO,MAAM,sBAAsB,GAAI,iCAIpC;IACC,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC;IAC5B,QAAQ,CAAC,SAAS,EAAE,eAAe,CAAC;IACpC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC7B;;;;;;;;;;;CAYA,CAAC;AAEF,eAAO,MAAM,sBAAsB,GAAI,uCAIpC;IACC,QAAQ,CAAC,MAAM,EAAE;QACb,QAAQ,CAAC,IAAI,CAAC,EAAE,UAAU,CAAC;QAC3B,QAAQ,CAAC,KAAK,CAAC,EAAE,WAAW,CAAC;QAC7B,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;KAC3B,CAAC;IACF,QAAQ,CAAC,QAAQ,EAAE,cAAc,CAAC;IAClC,QAAQ,CAAC,cAAc,EAAE,cAAc,CAAC;CAC3C,YAeA,CAAC"}
@@ -1,5 +1,5 @@
1
1
  import { readFile } from 'node:fs/promises';
2
- import { z } from 'zod';
2
+ import * as v from 'valibot';
3
3
  import { mapWithConcurrencyLimit } from "./async.js";
4
4
  import { stableStringify } from "./json.js";
5
5
  import { LEDGER_KINDS, parseLedgerEntry } from "./schema/entry.js";
@@ -7,40 +7,22 @@ import { readPhaseEntryText, resolveLedgerPaths, writeAtomicTextFile } from "./s
7
7
  const READ_INDEX_SCHEMA_VERSION = 'ushman-ledger-read-index/v1';
8
8
  const ENTRY_READ_BATCH_SIZE = 32;
9
9
  const ENTRY_READ_CONCURRENCY = 16;
10
- const ReadIndexEntrySchema = z.object({
11
- id: z.string().min(1),
12
- kind: z.enum(LEDGER_KINDS),
13
- ts: z.string().datetime({ offset: true }),
14
- });
15
- const LedgerReadIndexSchema = z
16
- .object({
17
- coveredFiles: z.array(z.string()).default([]),
18
- entries: z.array(ReadIndexEntrySchema).default([]),
19
- entryCount: z.number().int().nonnegative(),
20
- lastEntryId: z.string().min(1).nullable(),
21
- lastSequence: z.number().int().nonnegative(),
22
- schemaVersion: z.literal(READ_INDEX_SCHEMA_VERSION),
23
- })
24
- .superRefine((value, ctx) => {
25
- if (value.entryCount !== value.entries.length) {
26
- ctx.addIssue({
27
- code: 'custom',
28
- message: 'entryCount must match entries.length',
29
- path: ['entryCount'],
30
- });
31
- }
32
- const expectedLastEntryId = value.entries.at(-1)?.id ?? null;
33
- if (value.lastEntryId !== expectedLastEntryId) {
34
- ctx.addIssue({
35
- code: 'custom',
36
- message: 'lastEntryId must match the final indexed entry',
37
- path: ['lastEntryId'],
38
- });
39
- }
10
+ const ReadIndexEntrySchema = v.object({
11
+ id: v.pipe(v.string(), v.minLength(1)),
12
+ kind: v.picklist(LEDGER_KINDS),
13
+ ts: v.pipe(v.string(), v.isoTimestamp()),
40
14
  });
15
+ const LedgerReadIndexSchema = v.pipe(v.object({
16
+ coveredFiles: v.optional(v.array(v.string()), []),
17
+ entries: v.optional(v.array(ReadIndexEntrySchema), []),
18
+ entryCount: v.pipe(v.number(), v.integer(), v.minValue(0)),
19
+ lastEntryId: v.nullable(v.pipe(v.string(), v.minLength(1))),
20
+ lastSequence: v.pipe(v.number(), v.integer(), v.minValue(0)),
21
+ schemaVersion: v.literal(READ_INDEX_SCHEMA_VERSION),
22
+ }), v.check((value) => value.entryCount === value.entries.length, 'entryCount must match entries.length'), v.check((value) => value.lastEntryId === (value.entries.at(-1)?.id ?? null), 'lastEntryId must match the final indexed entry'));
41
23
  const parseReadIndexText = (filePath, text) => {
42
24
  try {
43
- return LedgerReadIndexSchema.parse(JSON.parse(text));
25
+ return v.parse(LedgerReadIndexSchema, JSON.parse(text));
44
26
  }
45
27
  catch (error) {
46
28
  throw new Error(`Invalid ledger read index at ${filePath}: ${error instanceof Error ? error.message : String(error)}`);
@@ -89,7 +71,7 @@ const mergeSortedUniquePaths = (existingPaths, additionalPaths) => {
89
71
  }
90
72
  return mergedPaths;
91
73
  };
92
- const buildReadIndex = ({ coveredFiles, entries, lastSequence, }) => LedgerReadIndexSchema.parse({
74
+ const buildReadIndex = ({ coveredFiles, entries, lastSequence, }) => v.parse(LedgerReadIndexSchema, {
93
75
  coveredFiles,
94
76
  entries,
95
77
  entryCount: entries.length,
@@ -162,7 +144,7 @@ export const readReadIndex = async (workspaceRoot) => {
162
144
  };
163
145
  export const saveReadIndex = async (workspaceRoot, readIndex) => {
164
146
  const filePath = resolveLedgerPaths(workspaceRoot).readIndexFile;
165
- await writeAtomicTextFile(filePath, `${stableStringify(LedgerReadIndexSchema.parse(readIndex), true)}\n`);
147
+ await writeAtomicTextFile(filePath, `${stableStringify(v.parse(LedgerReadIndexSchema, readIndex), true)}\n`);
166
148
  };
167
149
  export const ensureReadIndexUnderLock = async (workspaceRoot, manifest) => {
168
150
  let currentReadIndex = null;
@@ -1 +1 @@
1
- {"version":3,"file":"record.d.ts","sourceRoot":"","sources":["../src/record.ts"],"names":[],"mappings":"AAQA,OAAO,EAEH,KAAK,WAAW,EAQnB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAW3D,KAAK,qBAAqB,GAAG;IACzB,QAAQ,CAAC,eAAe,CAAC,EAAE,CAAC,OAAO,EAAE;QAAE,KAAK,EAAE,WAAW,CAAA;KAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9E,QAAQ,CAAC,iBAAiB,CAAC,EAAE,CAAC,OAAO,EAAE;QAAE,KAAK,EAAE,WAAW,CAAA;KAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAChF,QAAQ,CAAC,uBAAuB,CAAC,EAAE,CAAC,OAAO,EAAE;QAAE,KAAK,EAAE,WAAW,CAAC;QAAC,iBAAiB,EAAE,MAAM,CAAA;KAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACjH,QAAQ,CAAC,kBAAkB,CAAC,EAAE,CAAC,OAAO,EAAE;QAAE,KAAK,EAAE,WAAW,CAAA;KAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACpF,CAAC;AAuBF,eAAO,MAAM,wBAAwB,GAAI,eAAe,MAAM,EAAE,OAAO,qBAAqB,GAAG,IAAI,SAOlG,CAAC;AAgNF,eAAO,MAAM,YAAY,GACrB,eAAe,MAAM,EACrB,OAAO,OAAO,KACf,OAAO,CAAC;IAAE,KAAK,EAAE,WAAW,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,CAqF5C,CAAC;AAEF,eAAO,MAAM,aAAa,GACtB,eAAe,MAAM,EACrB,UAAU,cAAc,EACxB,SAAS,MAAM,KAChB,OAAO,CAAC,WAAW,CAUrB,CAAC"}
1
+ {"version":3,"file":"record.d.ts","sourceRoot":"","sources":["../src/record.ts"],"names":[],"mappings":"AASA,OAAO,EACH,KAAK,WAAW,EAKnB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAU3D,KAAK,qBAAqB,GAAG;IACzB,QAAQ,CAAC,eAAe,CAAC,EAAE,CAAC,OAAO,EAAE;QAAE,KAAK,EAAE,WAAW,CAAA;KAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9E,QAAQ,CAAC,iBAAiB,CAAC,EAAE,CAAC,OAAO,EAAE;QAAE,KAAK,EAAE,WAAW,CAAA;KAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAChF,QAAQ,CAAC,uBAAuB,CAAC,EAAE,CAAC,OAAO,EAAE;QAAE,KAAK,EAAE,WAAW,CAAC;QAAC,iBAAiB,EAAE,MAAM,CAAA;KAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACjH,QAAQ,CAAC,kBAAkB,CAAC,EAAE,CAAC,OAAO,EAAE;QAAE,KAAK,EAAE,WAAW,CAAA;KAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACpF,CAAC;AAOF,eAAO,MAAM,wBAAwB,GAAI,eAAe,MAAM,EAAE,OAAO,qBAAqB,GAAG,IAAI,SAOlG,CAAC;AA0EF,eAAO,MAAM,YAAY,GACrB,eAAe,MAAM,EACrB,OAAO,OAAO,KACf,OAAO,CAAC;IAAE,KAAK,EAAE,WAAW,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,CAsF5C,CAAC;AAEF,eAAO,MAAM,aAAa,GACtB,eAAe,MAAM,EACrB,UAAU,cAAc,EACxB,SAAS,MAAM,KAChB,OAAO,CAAC,WAAW,CAMrB,CAAC"}