ushman-ledger 1.2.0 → 1.2.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.
- package/README.md +57 -5
- package/dist/builders.d.ts +1 -2
- package/dist/builders.d.ts.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +156 -53
- package/dist/doctor.d.ts.map +1 -1
- package/dist/doctor.js +1 -1
- package/dist/handle.d.ts +27 -7
- package/dist/handle.d.ts.map +1 -1
- package/dist/handle.js +96 -20
- package/dist/index.d.ts +4 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/list.d.ts +1 -1
- package/dist/list.d.ts.map +1 -1
- package/dist/list.js +7 -5
- package/dist/note.d.ts +7 -0
- package/dist/note.d.ts.map +1 -1
- package/dist/note.js +6 -0
- package/dist/patch-resolver.d.ts +12 -0
- package/dist/patch-resolver.d.ts.map +1 -1
- package/dist/patch-resolver.js +12 -0
- package/dist/read-index.d.ts.map +1 -1
- package/dist/record.d.ts.map +1 -1
- package/dist/record.js +1 -2
- package/dist/render/migration-log.d.ts +8 -1
- package/dist/render/migration-log.d.ts.map +1 -1
- package/dist/render/migration-log.js +40 -33
- package/dist/render/retro.d.ts.map +1 -1
- package/dist/render/retro.js +1 -7
- package/dist/render/workspace-narrative.d.ts +7 -1
- package/dist/render/workspace-narrative.d.ts.map +1 -1
- package/dist/render/workspace-narrative.js +114 -46
- package/dist/schema/entry-read.d.ts.map +1 -1
- package/dist/schema/entry-read.js +1 -1
- package/dist/schema/entry-write.d.ts.map +1 -1
- package/dist/schema/entry-write.js +1 -1
- package/dist/schema/entry.d.ts.map +1 -1
- package/dist/storage/filesystem.d.ts +7 -0
- package/dist/storage/filesystem.d.ts.map +1 -1
- package/dist/storage/filesystem.js +80 -5
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +2 -2
|
@@ -14,56 +14,124 @@ const NARRATIVE_SUBKINDS = [
|
|
|
14
14
|
'semantic-cleanup-summary',
|
|
15
15
|
];
|
|
16
16
|
const isNarrativeNote = (entry) => entry.kind === 'note' && NARRATIVE_SUBKINDS.some((subkind) => subkind === entry.subkind);
|
|
17
|
-
const
|
|
18
|
-
const
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
const
|
|
22
|
-
const
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
}
|
|
26
|
-
return [`### ${latest.ts} — ${latest.summary}`, '', latest.body || 'No narrative body recorded.'].join('\n');
|
|
27
|
-
};
|
|
28
|
-
export const renderWorkspaceNarrativeMarkdown = async ({ entries, workspaceName, }) => {
|
|
29
|
-
const entriesBySubkind = new Map(NARRATIVE_SUBKINDS.map((subkind) => [subkind, []]));
|
|
17
|
+
const renderSummaryBullet = (entry) => `- ${entry.ts} — ${entry.summary}`;
|
|
18
|
+
const collectNarrativeSections = async (entries) => {
|
|
19
|
+
let latestSummary = null;
|
|
20
|
+
const cleanupWaveEntries = [];
|
|
21
|
+
const decompositionWaveEntries = [];
|
|
22
|
+
const openIssueEntries = [];
|
|
23
|
+
const summaryArchiveEntries = [];
|
|
24
|
+
const verifiedFlowEntries = [];
|
|
30
25
|
for await (const entry of entries) {
|
|
31
26
|
if (!isNarrativeNote(entry)) {
|
|
32
27
|
continue;
|
|
33
28
|
}
|
|
34
|
-
|
|
29
|
+
switch (entry.subkind) {
|
|
30
|
+
case 'cleanup-wave':
|
|
31
|
+
cleanupWaveEntries.push(entry);
|
|
32
|
+
break;
|
|
33
|
+
case 'decomposition-wave':
|
|
34
|
+
decompositionWaveEntries.push(entry);
|
|
35
|
+
break;
|
|
36
|
+
case 'open-issue':
|
|
37
|
+
openIssueEntries.push(entry);
|
|
38
|
+
break;
|
|
39
|
+
case 'semantic-cleanup-summary':
|
|
40
|
+
if (!latestSummary) {
|
|
41
|
+
latestSummary = entry;
|
|
42
|
+
break;
|
|
43
|
+
}
|
|
44
|
+
summaryArchiveEntries.push(entry);
|
|
45
|
+
break;
|
|
46
|
+
case 'verified-flow':
|
|
47
|
+
verifiedFlowEntries.push(entry);
|
|
48
|
+
break;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return {
|
|
52
|
+
cleanupWaveEntries,
|
|
53
|
+
decompositionWaveEntries,
|
|
54
|
+
latestSummary,
|
|
55
|
+
openIssueEntries,
|
|
56
|
+
summaryArchiveEntries,
|
|
57
|
+
verifiedFlowEntries,
|
|
58
|
+
};
|
|
59
|
+
};
|
|
60
|
+
const writeBulletSection = async ({ entries, title, write, }) => {
|
|
61
|
+
await write(`${title}\n\n`);
|
|
62
|
+
if (entries.length === 0) {
|
|
63
|
+
await write('- None recorded.\n');
|
|
64
|
+
await write('\n');
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
for (const entry of entries) {
|
|
68
|
+
await write(`${renderSummaryBullet(entry)}\n`);
|
|
35
69
|
}
|
|
36
|
-
|
|
37
|
-
|
|
70
|
+
await write('\n');
|
|
71
|
+
};
|
|
72
|
+
const writeLatestSummarySection = async ({ latestSummary, write, }) => {
|
|
73
|
+
await write(`${SECTION_TITLES.semanticCleanupSummary}\n\n`);
|
|
74
|
+
if (latestSummary) {
|
|
75
|
+
await write(`### ${latestSummary.ts} — ${latestSummary.summary}\n\n`);
|
|
76
|
+
await write(`${latestSummary.body || 'No narrative body recorded.'}\n\n`);
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
await write('No entries recorded.\n\n');
|
|
80
|
+
};
|
|
81
|
+
const writeSummaryArchiveSection = async ({ entries, write, }) => {
|
|
82
|
+
await write(`${SECTION_TITLES.semanticCleanupSummaryArchive}\n\n`);
|
|
83
|
+
if (entries.length === 0) {
|
|
84
|
+
await write('- None recorded.\n');
|
|
85
|
+
await write('\n');
|
|
86
|
+
return;
|
|
38
87
|
}
|
|
39
|
-
const
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
88
|
+
for (const entry of entries) {
|
|
89
|
+
await write(`${renderSummaryBullet(entry)}\n`);
|
|
90
|
+
}
|
|
91
|
+
await write('\n');
|
|
92
|
+
};
|
|
93
|
+
export const writeWorkspaceNarrativeMarkdown = async ({ entries, workspaceName, write, }) => {
|
|
94
|
+
const sections = await collectNarrativeSections(entries);
|
|
95
|
+
await write(`# Workspace narrative — ${workspaceName}\n\n`);
|
|
96
|
+
await writeLatestSummarySection({
|
|
97
|
+
latestSummary: sections.latestSummary,
|
|
98
|
+
write,
|
|
99
|
+
});
|
|
100
|
+
await writeBulletSection({
|
|
101
|
+
entries: sections.cleanupWaveEntries,
|
|
102
|
+
title: SECTION_TITLES.cleanupWave,
|
|
103
|
+
write,
|
|
104
|
+
});
|
|
105
|
+
await writeBulletSection({
|
|
106
|
+
entries: sections.verifiedFlowEntries,
|
|
107
|
+
title: SECTION_TITLES.verifiedFlow,
|
|
108
|
+
write,
|
|
109
|
+
});
|
|
110
|
+
await writeBulletSection({
|
|
111
|
+
entries: sections.openIssueEntries,
|
|
112
|
+
title: SECTION_TITLES.openIssue,
|
|
113
|
+
write,
|
|
114
|
+
});
|
|
115
|
+
await writeBulletSection({
|
|
116
|
+
entries: sections.decompositionWaveEntries,
|
|
117
|
+
title: SECTION_TITLES.decompositionWave,
|
|
118
|
+
write,
|
|
119
|
+
});
|
|
120
|
+
await writeSummaryArchiveSection({
|
|
121
|
+
entries: sections.summaryArchiveEntries,
|
|
122
|
+
write,
|
|
123
|
+
});
|
|
124
|
+
};
|
|
125
|
+
export const renderWorkspaceNarrativeMarkdown = async ({ entries, workspaceName, write, }) => {
|
|
126
|
+
const chunks = [];
|
|
127
|
+
const resolvedWriter = write ??
|
|
128
|
+
((chunk) => {
|
|
129
|
+
chunks.push(chunk);
|
|
130
|
+
});
|
|
131
|
+
await writeWorkspaceNarrativeMarkdown({
|
|
132
|
+
entries,
|
|
133
|
+
workspaceName,
|
|
134
|
+
write: resolvedWriter,
|
|
135
|
+
});
|
|
136
|
+
return chunks.join('');
|
|
69
137
|
};
|
|
@@ -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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
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,6 +1,6 @@
|
|
|
1
1
|
import * as v from 'valibot';
|
|
2
|
-
import { NoteSubkindSchema } from "./note.js";
|
|
3
2
|
import { AgentPatchDiffSchema, ChangeLogFileChangeSchema, ChangeLogParityStatusSchema, ChangeLogSmokeResultSchema, ChangeLogSubkindSchema, ledgerEntryBaseEntries, NonEmptyTrimmedStringSchema, OperatorDecisionPayloadSchema, StripDecisionRevertedPayloadSchema, } from "./entry-core.js";
|
|
3
|
+
import { NoteSubkindSchema } from "./note.js";
|
|
4
4
|
export const ToolInvocationEntrySchema = v.object({
|
|
5
5
|
...ledgerEntryBaseEntries,
|
|
6
6
|
args: v.optional(v.array(v.string())),
|
|
@@ -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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
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,6 +1,6 @@
|
|
|
1
1
|
import * as v from 'valibot';
|
|
2
|
-
import { NoteSubkindSchema } from "./note.js";
|
|
3
2
|
import { AgentPatchDiffSchema, ChangeLogFileChangeSchema, ChangeLogParityStatusSchema, ChangeLogSmokeResultSchema, ChangeLogSubkindSchema, NonEmptyTrimmedStringSchema, OperatorDecisionPayloadSchema, recordEntryBaseEntries, StripDecisionRevertedPayloadSchema, } from "./entry-core.js";
|
|
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));
|
|
6
6
|
if (provided.length === 0) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"entry.d.ts","sourceRoot":"","sources":["../../src/schema/entry.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,WAAW,EAAqB,MAAM,iBAAiB,CAAC;AACtE,OAAO,EAAE,KAAK,YAAY,EAAsB,MAAM,kBAAkB,CAAC;AAEzE,cAAc,iBAAiB,CAAC;AAChC,cAAc,uBAAuB,CAAC;AACtC,cAAc,iBAAiB,CAAC;AAChC,cAAc,kBAAkB,CAAC;AAEjC,eAAO,MAAM,gBAAgB,GAAI,OAAO,OAAO,KAAG,
|
|
1
|
+
{"version":3,"file":"entry.d.ts","sourceRoot":"","sources":["../../src/schema/entry.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,WAAW,EAAqB,MAAM,iBAAiB,CAAC;AACtE,OAAO,EAAE,KAAK,YAAY,EAAsB,MAAM,kBAAkB,CAAC;AAEzE,cAAc,iBAAiB,CAAC;AAChC,cAAc,uBAAuB,CAAC;AACtC,cAAc,iBAAiB,CAAC;AAChC,cAAc,kBAAkB,CAAC;AAEjC,eAAO,MAAM,gBAAgB,GAAI,OAAO,OAAO,KAAG,WACY,CAAC;AAE/D,eAAO,MAAM,iBAAiB,GAAI,OAAO,OAAO,KAAG,YACa,CAAC"}
|
|
@@ -5,6 +5,7 @@ export declare const LEDGER_ROOT_SEGMENTS: readonly [".lab", "ledger"];
|
|
|
5
5
|
export declare const LEDGER_STALE_TEMP_MS = 60000;
|
|
6
6
|
type AtomicWriteTestHook = {
|
|
7
7
|
readonly beforeRename?: () => Promise<void>;
|
|
8
|
+
readonly retainOnThrow?: boolean;
|
|
8
9
|
};
|
|
9
10
|
export type LedgerPaths = {
|
|
10
11
|
readonly blobsDir: string;
|
|
@@ -22,10 +23,16 @@ export type LedgerPaths = {
|
|
|
22
23
|
readonly root: string;
|
|
23
24
|
readonly workspaceRoot: string;
|
|
24
25
|
};
|
|
26
|
+
export type AtomicTextFileWriter = {
|
|
27
|
+
readonly abort: () => Promise<void>;
|
|
28
|
+
readonly close: () => Promise<void>;
|
|
29
|
+
readonly write: (chunk: string) => Promise<void>;
|
|
30
|
+
};
|
|
25
31
|
export declare const resolveLedgerPaths: (workspaceRoot: string) => LedgerPaths;
|
|
26
32
|
export declare const ensureLedgerDirectories: (workspaceRoot: string) => Promise<LedgerPaths>;
|
|
27
33
|
export declare const setAtomicWriteTestHook: (filePath: string, hook: AtomicWriteTestHook | null) => void;
|
|
28
34
|
export declare const writeAtomicTextFile: (filePath: string, text: string) => Promise<void>;
|
|
35
|
+
export declare const createAtomicTextFileWriter: (filePath: string) => Promise<AtomicTextFileWriter>;
|
|
29
36
|
export declare const writeAtomicJsonFile: (filePath: string, value: unknown) => Promise<void>;
|
|
30
37
|
export declare const readManifest: (workspaceRoot: string) => Promise<LedgerManifest>;
|
|
31
38
|
export declare const saveManifest: (workspaceRoot: string, manifest: LedgerManifest) => Promise<void>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"filesystem.d.ts","sourceRoot":"","sources":["../../src/storage/filesystem.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,aAAa,EAAE,KAAK,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACrE,OAAO,EAAE,KAAK,cAAc,EAAwB,MAAM,uBAAuB,CAAC;AAElF,OAAO,EAAE,aAAa,EAAE,CAAC;AACzB,eAAO,MAAM,oBAAoB,6BAA8B,CAAC;AAChE,eAAO,MAAM,oBAAoB,QAAS,CAAC;AAC3C,KAAK,mBAAmB,GAAG;IACvB,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"filesystem.d.ts","sourceRoot":"","sources":["../../src/storage/filesystem.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,aAAa,EAAE,KAAK,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACrE,OAAO,EAAE,KAAK,cAAc,EAAwB,MAAM,uBAAuB,CAAC;AAElF,OAAO,EAAE,aAAa,EAAE,CAAC;AACzB,eAAO,MAAM,oBAAoB,6BAA8B,CAAC;AAChE,eAAO,MAAM,oBAAoB,QAAS,CAAC;AAC3C,KAAK,mBAAmB,GAAG;IACvB,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5C,QAAQ,CAAC,aAAa,CAAC,EAAE,OAAO,CAAC;CACpC,CAAC;AA+BF,MAAM,MAAM,WAAW,GAAG;IACtB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,MAAM,CAAC;IAClD,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAClC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAC;IACnC,QAAQ,CAAC,kBAAkB,EAAE,MAAM,CAAC;IACpC,QAAQ,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,MAAM,CAAC;IAClD,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,sBAAsB,EAAE,MAAM,CAAC;IACxC,QAAQ,CAAC,kBAAkB,EAAE,MAAM,CAAC;IACpC,QAAQ,CAAC,4BAA4B,EAAE,MAAM,CAAC;IAC9C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;CAClC,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG;IAC/B,QAAQ,CAAC,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IACpC,QAAQ,CAAC,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IACpC,QAAQ,CAAC,KAAK,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACpD,CAAC;AAEF,eAAO,MAAM,kBAAkB,GAAI,eAAe,MAAM,KAAG,WAkB1D,CAAC;AAEF,eAAO,MAAM,uBAAuB,GAAU,eAAe,MAAM,KAAG,OAAO,CAAC,WAAW,CAYxF,CAAC;AAEF,eAAO,MAAM,sBAAsB,GAAI,UAAU,MAAM,EAAE,MAAM,mBAAmB,GAAG,IAAI,SAOxF,CAAC;AAoBF,eAAO,MAAM,mBAAmB,GAAU,UAAU,MAAM,EAAE,MAAM,MAAM,kBAiBvE,CAAC;AAEF,eAAO,MAAM,0BAA0B,GAAU,UAAU,MAAM,KAAG,OAAO,CAAC,oBAAoB,CA4D/F,CAAC;AAEF,eAAO,MAAM,mBAAmB,GAAU,UAAU,MAAM,EAAE,OAAO,OAAO,kBAEzE,CAAC;AAoCF,eAAO,MAAM,YAAY,GAAU,eAAe,MAAM,KAAG,OAAO,CAAC,cAAc,CAmBhF,CAAC;AAEF,eAAO,MAAM,YAAY,GAAU,eAAe,MAAM,EAAE,UAAU,cAAc,kBASjF,CAAC;AAoFF,eAAO,MAAM,qBAAqB,GAAU,eAAe,MAAM,kBAIhE,CAAC;AAEF,eAAO,MAAM,uBAAuB,GAAU,eAAe,MAAM,EAAE,OAAO,WAAW,KAAG,OAAO,CAAC,MAAM,EAAE,CAOzG,CAAC;AAEF,eAAO,MAAM,kBAAkB,GAAU,eAAe,MAAM,EAAE,OAAO,WAAW,EAAE,UAAU,MAAM,oBAGnG,CAAC;AAEF,eAAO,MAAM,cAAc,GAAU,eAAe,MAAM,EAAE,OAAO,WAAW,EAAE,UAAU,MAAM,EAAE,OAAO,OAAO,oBAK/G,CAAC"}
|
|
@@ -11,11 +11,29 @@ export const LEDGER_ROOT_SEGMENTS = ['.lab', 'ledger'];
|
|
|
11
11
|
export const LEDGER_STALE_TEMP_MS = 60_000;
|
|
12
12
|
const atomicWriteTestHooks = new Map();
|
|
13
13
|
const resolveAtomicWriteKey = (filePath) => path.resolve(filePath);
|
|
14
|
-
const
|
|
14
|
+
const getAtomicWriteTestHook = (filePath) => {
|
|
15
15
|
const key = resolveAtomicWriteKey(filePath);
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
16
|
+
return {
|
|
17
|
+
hook: atomicWriteTestHooks.get(key),
|
|
18
|
+
key,
|
|
19
|
+
};
|
|
20
|
+
};
|
|
21
|
+
const runAtomicWriteTestHook = async (filePath) => {
|
|
22
|
+
const { hook, key } = getAtomicWriteTestHook(filePath);
|
|
23
|
+
if (!hook?.beforeRename) {
|
|
24
|
+
atomicWriteTestHooks.delete(key);
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
try {
|
|
28
|
+
await hook.beforeRename();
|
|
29
|
+
atomicWriteTestHooks.delete(key);
|
|
30
|
+
}
|
|
31
|
+
catch (error) {
|
|
32
|
+
if (!hook.retainOnThrow) {
|
|
33
|
+
atomicWriteTestHooks.delete(key);
|
|
34
|
+
}
|
|
35
|
+
throw error;
|
|
36
|
+
}
|
|
19
37
|
};
|
|
20
38
|
export const resolveLedgerPaths = (workspaceRoot) => {
|
|
21
39
|
const root = path.join(workspaceRoot, ...LEDGER_ROOT_SEGMENTS);
|
|
@@ -83,7 +101,7 @@ export const writeAtomicTextFile = async (filePath, text) => {
|
|
|
83
101
|
finally {
|
|
84
102
|
await handle.close();
|
|
85
103
|
}
|
|
86
|
-
await
|
|
104
|
+
await runAtomicWriteTestHook(filePath);
|
|
87
105
|
try {
|
|
88
106
|
await rename(tempPath, filePath);
|
|
89
107
|
}
|
|
@@ -92,6 +110,63 @@ export const writeAtomicTextFile = async (filePath, text) => {
|
|
|
92
110
|
throw error;
|
|
93
111
|
}
|
|
94
112
|
};
|
|
113
|
+
export const createAtomicTextFileWriter = async (filePath) => {
|
|
114
|
+
await mkdir(path.dirname(filePath), { recursive: true });
|
|
115
|
+
const tempPath = `${filePath}.tmp.${process.pid}.${Date.now()}.${randomUUID()}`;
|
|
116
|
+
const handle = await open(tempPath, 'w');
|
|
117
|
+
let completed = false;
|
|
118
|
+
let writeChain = Promise.resolve();
|
|
119
|
+
const finalizeHandle = async () => {
|
|
120
|
+
if (completed) {
|
|
121
|
+
return false;
|
|
122
|
+
}
|
|
123
|
+
completed = true;
|
|
124
|
+
return true;
|
|
125
|
+
};
|
|
126
|
+
const waitForWrites = async () => {
|
|
127
|
+
await writeChain;
|
|
128
|
+
};
|
|
129
|
+
return {
|
|
130
|
+
abort: async () => {
|
|
131
|
+
if (!(await finalizeHandle())) {
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
await waitForWrites();
|
|
135
|
+
await handle.close();
|
|
136
|
+
await rm(tempPath, { force: true });
|
|
137
|
+
},
|
|
138
|
+
close: async () => {
|
|
139
|
+
if (!(await finalizeHandle())) {
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
await waitForWrites();
|
|
143
|
+
try {
|
|
144
|
+
await handle.sync();
|
|
145
|
+
}
|
|
146
|
+
finally {
|
|
147
|
+
await handle.close();
|
|
148
|
+
}
|
|
149
|
+
await runAtomicWriteTestHook(filePath);
|
|
150
|
+
try {
|
|
151
|
+
await rename(tempPath, filePath);
|
|
152
|
+
}
|
|
153
|
+
catch (error) {
|
|
154
|
+
await rm(tempPath, { force: true });
|
|
155
|
+
throw error;
|
|
156
|
+
}
|
|
157
|
+
},
|
|
158
|
+
write: async (chunk) => {
|
|
159
|
+
const nextWrite = writeChain.then(async () => {
|
|
160
|
+
if (completed || chunk.length === 0) {
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
await handle.writeFile(chunk, 'utf8');
|
|
164
|
+
});
|
|
165
|
+
writeChain = nextWrite.then(() => undefined, () => undefined);
|
|
166
|
+
await nextWrite;
|
|
167
|
+
},
|
|
168
|
+
};
|
|
169
|
+
};
|
|
95
170
|
export const writeAtomicJsonFile = async (filePath, value) => {
|
|
96
171
|
await writeAtomicTextFile(filePath, `${stableStringify(value, true)}\n`);
|
|
97
172
|
};
|
package/dist/version.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const LEDGER_LIBRARY_VERSION = "1.
|
|
1
|
+
export declare const LEDGER_LIBRARY_VERSION = "1.2.0";
|
|
2
2
|
//# sourceMappingURL=version.d.ts.map
|
package/dist/version.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const LEDGER_LIBRARY_VERSION = '1.
|
|
1
|
+
export const LEDGER_LIBRARY_VERSION = '1.2.0';
|
package/package.json
CHANGED
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
"dependencies": {
|
|
13
13
|
"safe-stable-stringify": "^2.5.0",
|
|
14
14
|
"tar": "^7.5.15",
|
|
15
|
-
"valibot": "^1.4.
|
|
15
|
+
"valibot": "^1.4.1"
|
|
16
16
|
},
|
|
17
17
|
"description": "Append-only workspace ledger library and CLI for Ushman v4.",
|
|
18
18
|
"devDependencies": {
|
|
@@ -68,5 +68,5 @@
|
|
|
68
68
|
},
|
|
69
69
|
"type": "module",
|
|
70
70
|
"types": "dist/index.d.ts",
|
|
71
|
-
"version": "1.2.
|
|
71
|
+
"version": "1.2.1"
|
|
72
72
|
}
|