ushman-ledger 1.3.0 → 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.
- package/README.md +10 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +62 -11
- package/dist/helpers.d.ts.map +1 -1
- package/dist/helpers.js +2 -1
- package/dist/lab-min.d.ts +1 -1
- package/dist/lab-min.d.ts.map +1 -1
- package/dist/lab-min.js +2 -1
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -145,14 +145,18 @@ ushman-ledger record --workspace=<ws> --kind=change-log --subkind=semantic-clean
|
|
|
145
145
|
ushman-ledger note regression --workspace=<ws> --phase=cleanup --summary="runtime drift" --body=/tmp/note.md
|
|
146
146
|
ushman-ledger note cleanup-wave --workspace=<ws> --phase=cleanup --summary="wave 1" --body=/tmp/narrative.md
|
|
147
147
|
ushman-ledger list --workspace=<ws> --json
|
|
148
|
+
ushman-ledger list --workspace=<ws> --json --progress
|
|
148
149
|
ushman-ledger render --workspace=<ws> --to=retro
|
|
149
150
|
ushman-ledger render --workspace=<ws> --to=migration-log-md
|
|
150
151
|
ushman-ledger render --workspace=<ws> --to=workspace-narrative-md
|
|
152
|
+
ushman-ledger render --workspace=<ws> --to=retro --out=/tmp/retro.md --quiet
|
|
151
153
|
ushman-ledger render --workspace=<ws> --to=jsonl --out=/tmp/ledger.jsonl
|
|
152
154
|
ushman-ledger render --workspace=<ws> --to=dependency-graph --out=/tmp/ledger.mmd
|
|
153
155
|
ushman-ledger archive --workspace=<ws> --out=/tmp/ledger.tgz
|
|
156
|
+
ushman-ledger archive --workspace=<ws> --out=/tmp/ledger.tgz --progress
|
|
154
157
|
ushman-ledger doctor --workspace=<ws>
|
|
155
158
|
ushman-ledger doctor --workspace=<ws> --json
|
|
159
|
+
ushman-ledger doctor --workspace=<ws> --quiet
|
|
156
160
|
```
|
|
157
161
|
|
|
158
162
|
Valid record kinds: `tool-invocation`, `stage-write`, `agent-patch`, `operator-patch`, `operator-decision`, `validator-result`, `runtime-event`, `note`, `correction`, `strip-decision-reverted`, `change-log`
|
|
@@ -184,6 +188,12 @@ Valid render targets: `retro`, `jsonl`, `timeline-html`, `dependency-graph`, `mi
|
|
|
184
188
|
`render()` still returns a string for in-memory callers. `renderTo()` is the bounded-output alternative for large ledgers and can write to a callback or the canonical render file on disk.
|
|
185
189
|
`renderTo()` writers receive sequential chunks, can return synchronously or asynchronously, and should throw only when the render should abort.
|
|
186
190
|
|
|
191
|
+
## CLI quiet and progress modes
|
|
192
|
+
|
|
193
|
+
- `--progress` writes concise progress lines to stderr for long-running `list`, `render`, `archive`, and `doctor` CLI operations. Stdout remains reserved for the command result, so `list --json --progress` still emits parseable JSON.
|
|
194
|
+
- `--quiet` suppresses verbose human output on those commands. `doctor --quiet` prints `ok` or one finding code per line; `archive --quiet` and `render --quiet` print `ok` on success; `list --quiet` prints one entry id per line for non-JSON output.
|
|
195
|
+
- `--quiet` takes precedence over `--progress`. For render targets without a canonical ledger render file, such as `jsonl` and `dependency-graph`, `render --quiet` requires `--out`.
|
|
196
|
+
|
|
187
197
|
## Workspace prerequisite
|
|
188
198
|
|
|
189
199
|
`openLedger()` and the CLI expect a valid ushman v4 workspace with `.lab/lab.json` already present.
|
package/dist/cli.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAmEA,KAAK,UAAU,GAAG;IACd,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,cAAc,EAAE;QACrB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QACtB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;KAC5B,CAAC;IACF,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC,cAAc,GAAG,aAAa,CAAC,UAAU,GAAG,MAAM,CAAC,CAAC;IAC3E,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,cAAc,CAAC;IACvC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,cAAc,CAAC;CAC1C,CAAC;AAomCF,eAAO,MAAM,YAAY,GAAU,MAAM,SAAS,MAAM,EAAE,EAAE,UAAS,OAAO,CAAC,UAAU,CAAM,KAAG,OAAO,CAAC,MAAM,CAqC7G,CAAC;AAEF,eAAO,MAAM,IAAI,GAAU,OAAM,SAAS,MAAM,EAA0B,KAAG,OAAO,CAAC,MAAM,CAE1F,CAAC"}
|
package/dist/cli.js
CHANGED
|
@@ -15,7 +15,7 @@ import { LEDGER_LIBRARY_VERSION } from "./version.js";
|
|
|
15
15
|
const execFileAsync = promisify(execFile);
|
|
16
16
|
const DEFAULT_GIT_DIFF_MAX_BUFFER_BYTES = 10 * 1024 * 1024;
|
|
17
17
|
const DEFAULT_GIT_DIFF_TIMEOUT_MS = 30_000;
|
|
18
|
-
const BOOLEAN_FLAG_NAMES = new Set(['from-stdin', 'help', 'json']);
|
|
18
|
+
const BOOLEAN_FLAG_NAMES = new Set(['from-stdin', 'help', 'json', 'progress', 'quiet']);
|
|
19
19
|
const GIT_DIFF_FORMAT_ARGS = ['--no-color', '--no-ext-diff', '--src-prefix=a/', '--dst-prefix=b/'];
|
|
20
20
|
const RENDER_TARGETS = [
|
|
21
21
|
'retro',
|
|
@@ -25,6 +25,12 @@ const RENDER_TARGETS = [
|
|
|
25
25
|
'migration-log-md',
|
|
26
26
|
'workspace-narrative-md',
|
|
27
27
|
];
|
|
28
|
+
const CANONICAL_RENDER_TARGETS = new Set([
|
|
29
|
+
'migration-log-md',
|
|
30
|
+
'retro',
|
|
31
|
+
'timeline-html',
|
|
32
|
+
'workspace-narrative-md',
|
|
33
|
+
]);
|
|
28
34
|
const GIT_DIFF_FLAG_NAMES = ['git-diff-max-buffer-bytes', 'git-diff-timeout-ms', 'git-paths'];
|
|
29
35
|
const CHANGE_LOG_RECORD_ONLY_FLAGS = [
|
|
30
36
|
'commands',
|
|
@@ -75,12 +81,12 @@ const renderHelp = (commandName) => `${commandName}
|
|
|
75
81
|
Commands:
|
|
76
82
|
${renderRecordUsage(commandName)}
|
|
77
83
|
${commandName} note <subkind> [--workspace=<ws>] --phase=<phase> --summary="..." [--body=<markdown-file>] [--from-stdin]
|
|
78
|
-
${commandName} list [--workspace=<ws>] [--phase=<phase>] [--kind=<kind>] [--since=<iso>] [--limit=<n>] [--json]
|
|
84
|
+
${commandName} list [--workspace=<ws>] [--phase=<phase>] [--kind=<kind>] [--since=<iso>] [--limit=<n>] [--json] [--quiet] [--progress]
|
|
79
85
|
${commandName} show [--workspace=<ws>] <entry-id>
|
|
80
86
|
${commandName} tail [--workspace=<ws>] [--phase=<phase>] [--limit=<n>]
|
|
81
|
-
${commandName} render [--workspace=<ws>] [--to=retro|jsonl|timeline-html|dependency-graph|migration-log-md|workspace-narrative-md] [--phase=<phase>] [--since=<iso>] [--limit=<n>] [--out=<file>]
|
|
82
|
-
${commandName} archive [--workspace=<ws>] --out=<file.tgz>
|
|
83
|
-
${commandName} doctor [--workspace=<ws>] [--json]
|
|
87
|
+
${commandName} render [--workspace=<ws>] [--to=retro|jsonl|timeline-html|dependency-graph|migration-log-md|workspace-narrative-md] [--phase=<phase>] [--since=<iso>] [--limit=<n>] [--out=<file>] [--quiet] [--progress]
|
|
88
|
+
${commandName} archive [--workspace=<ws>] --out=<file.tgz> [--quiet] [--progress]
|
|
89
|
+
${commandName} doctor [--workspace=<ws>] [--json] [--quiet] [--progress]
|
|
84
90
|
${commandName} --version
|
|
85
91
|
|
|
86
92
|
${renderValidValues()}
|
|
@@ -98,17 +104,17 @@ ${renderRuntimeTuningHelp()}`;
|
|
|
98
104
|
${renderValidValues()}
|
|
99
105
|
${renderRuntimeTuningHelp()}`;
|
|
100
106
|
case 'list':
|
|
101
|
-
return `${commandName} list [--workspace=<ws>] [--phase=<phase>] [--kind=<kind>] [--since=<iso>] [--limit=<n>] [--json]
|
|
107
|
+
return `${commandName} list [--workspace=<ws>] [--phase=<phase>] [--kind=<kind>] [--since=<iso>] [--limit=<n>] [--json] [--quiet] [--progress]
|
|
102
108
|
|
|
103
109
|
${renderValidValues()}
|
|
104
110
|
${renderRuntimeTuningHelp()}`;
|
|
105
111
|
case 'render':
|
|
106
|
-
return `${commandName} render [--workspace=<ws>] [--to=<target>] [--phase=<phase>] [--since=<iso>] [--limit=<n>] [--out=<file>]
|
|
112
|
+
return `${commandName} render [--workspace=<ws>] [--to=<target>] [--phase=<phase>] [--since=<iso>] [--limit=<n>] [--out=<file>] [--quiet] [--progress]
|
|
107
113
|
|
|
108
114
|
${renderValidValues()}
|
|
109
115
|
${renderRuntimeTuningHelp()}`;
|
|
110
116
|
case 'doctor':
|
|
111
|
-
return `${commandName} doctor [--workspace=<ws>] [--json]
|
|
117
|
+
return `${commandName} doctor [--workspace=<ws>] [--json] [--quiet] [--progress]
|
|
112
118
|
|
|
113
119
|
${renderRuntimeTuningHelp()}`;
|
|
114
120
|
default:
|
|
@@ -307,6 +313,14 @@ const print = (context, text) => {
|
|
|
307
313
|
const printJson = (context, value) => {
|
|
308
314
|
print(context, JSON.stringify(value, null, 2));
|
|
309
315
|
};
|
|
316
|
+
const isQuiet = (flags) => hasFlag(flags, 'quiet');
|
|
317
|
+
const isProgressEnabled = (flags) => hasFlag(flags, 'progress') && !isQuiet(flags);
|
|
318
|
+
const printProgress = (context, flags, message) => {
|
|
319
|
+
if (!isProgressEnabled(flags)) {
|
|
320
|
+
return;
|
|
321
|
+
}
|
|
322
|
+
context.stderr.write(`progress ${message}\n`);
|
|
323
|
+
};
|
|
310
324
|
const parseLimit = (flags) => getFlag(flags, 'limit')
|
|
311
325
|
? parsePositiveIntegerFlag({
|
|
312
326
|
defaultValue: 0,
|
|
@@ -791,7 +805,9 @@ const runNoteCli = async (parsed, context) => {
|
|
|
791
805
|
return 0;
|
|
792
806
|
};
|
|
793
807
|
const runListCli = async (parsed, context) => {
|
|
808
|
+
printProgress(context, parsed.flags, 'list start');
|
|
794
809
|
const ledger = await openLedger(getWorkspaceRoot(parsed.flags));
|
|
810
|
+
let entryCount = 0;
|
|
795
811
|
if (hasFlag(parsed.flags, 'json')) {
|
|
796
812
|
let wroteEntry = false;
|
|
797
813
|
context.stdout.write('[\n');
|
|
@@ -807,8 +823,10 @@ const runListCli = async (parsed, context) => {
|
|
|
807
823
|
const renderedEntry = JSON.stringify(entry, null, 2).replaceAll('\n', '\n ');
|
|
808
824
|
context.stdout.write(` ${renderedEntry}`);
|
|
809
825
|
wroteEntry = true;
|
|
826
|
+
entryCount += 1;
|
|
810
827
|
}
|
|
811
828
|
context.stdout.write(wroteEntry ? '\n]\n' : ']\n');
|
|
829
|
+
printProgress(context, parsed.flags, `list done entries=${entryCount}`);
|
|
812
830
|
return 0;
|
|
813
831
|
}
|
|
814
832
|
for await (const entry of ledger.list({
|
|
@@ -817,8 +835,15 @@ const runListCli = async (parsed, context) => {
|
|
|
817
835
|
phase: parseOptionalPhase(parsed.flags),
|
|
818
836
|
since: parseSince(parsed.flags),
|
|
819
837
|
})) {
|
|
820
|
-
|
|
838
|
+
entryCount += 1;
|
|
839
|
+
if (isQuiet(parsed.flags)) {
|
|
840
|
+
print(context, entry.id);
|
|
841
|
+
}
|
|
842
|
+
else {
|
|
843
|
+
print(context, `${entry.id} ${entry.phase} ${entry.kind} ${entry.summary}`);
|
|
844
|
+
}
|
|
821
845
|
}
|
|
846
|
+
printProgress(context, parsed.flags, `list done entries=${entryCount}`);
|
|
822
847
|
return 0;
|
|
823
848
|
};
|
|
824
849
|
const runShowCli = async (parsed, context) => {
|
|
@@ -843,6 +868,7 @@ const runTailCli = async (parsed, context) => runListCli({
|
|
|
843
868
|
}, context);
|
|
844
869
|
const runRenderCli = async (parsed, context) => {
|
|
845
870
|
const target = parseRenderTarget(parsed.flags);
|
|
871
|
+
printProgress(context, parsed.flags, `render start target=${target}`);
|
|
846
872
|
const ledger = await openLedger(getWorkspaceRoot(parsed.flags));
|
|
847
873
|
const renderOptions = {
|
|
848
874
|
limit: parseLimit(parsed.flags),
|
|
@@ -851,19 +877,29 @@ const runRenderCli = async (parsed, context) => {
|
|
|
851
877
|
since: parseSince(parsed.flags),
|
|
852
878
|
to: target,
|
|
853
879
|
};
|
|
854
|
-
if (renderOptions.out) {
|
|
880
|
+
if (isQuiet(parsed.flags) && !renderOptions.out && !CANONICAL_RENDER_TARGETS.has(target)) {
|
|
881
|
+
throw new CliUsageError(`render --quiet requires --out for ${target} output.`);
|
|
882
|
+
}
|
|
883
|
+
if (renderOptions.out || isQuiet(parsed.flags)) {
|
|
855
884
|
await ledger.renderTo(renderOptions);
|
|
885
|
+
if (isQuiet(parsed.flags)) {
|
|
886
|
+
print(context, 'ok');
|
|
887
|
+
}
|
|
888
|
+
printProgress(context, parsed.flags, `render done target=${target}`);
|
|
856
889
|
return 0;
|
|
857
890
|
}
|
|
858
891
|
const content = await ledger.render(renderOptions);
|
|
859
892
|
print(context, content);
|
|
893
|
+
printProgress(context, parsed.flags, `render done target=${target}`);
|
|
860
894
|
return 0;
|
|
861
895
|
};
|
|
862
896
|
const runArchiveCli = async (parsed, context) => {
|
|
863
897
|
const outPath = getRequiredString(parsed.flags, 'out');
|
|
898
|
+
printProgress(context, parsed.flags, 'archive start');
|
|
864
899
|
const ledger = await openLedger(getWorkspaceRoot(parsed.flags));
|
|
865
900
|
const result = await ledger.archive(outPath);
|
|
866
|
-
print(context, result.integrityHash);
|
|
901
|
+
print(context, isQuiet(parsed.flags) ? 'ok' : result.integrityHash);
|
|
902
|
+
printProgress(context, parsed.flags, 'archive done');
|
|
867
903
|
return 0;
|
|
868
904
|
};
|
|
869
905
|
const formatDoctorFinding = (finding) => [`[${finding.code}] ${finding.message}`, `Next step: ${finding.remediation}`].join('\n');
|
|
@@ -878,17 +914,32 @@ const printDoctorFindings = (context, report) => {
|
|
|
878
914
|
context.stderr.write('\n');
|
|
879
915
|
};
|
|
880
916
|
const runDoctorCli = async (parsed, context) => {
|
|
917
|
+
printProgress(context, parsed.flags, 'doctor start');
|
|
881
918
|
const ledger = await openLedger(getWorkspaceRoot(parsed.flags));
|
|
882
919
|
const result = await ledger.doctor();
|
|
883
920
|
if (hasFlag(parsed.flags, 'json')) {
|
|
884
921
|
printJson(context, result);
|
|
922
|
+
printProgress(context, parsed.flags, `doctor done issues=${result.issueCount}`);
|
|
923
|
+
return result.ok ? 0 : 1;
|
|
924
|
+
}
|
|
925
|
+
if (isQuiet(parsed.flags)) {
|
|
926
|
+
if (result.ok) {
|
|
927
|
+
print(context, 'ok');
|
|
928
|
+
}
|
|
929
|
+
else {
|
|
930
|
+
for (const finding of result.findings) {
|
|
931
|
+
print(context, finding.code);
|
|
932
|
+
}
|
|
933
|
+
}
|
|
885
934
|
return result.ok ? 0 : 1;
|
|
886
935
|
}
|
|
887
936
|
if (result.ok) {
|
|
888
937
|
print(context, 'ok');
|
|
938
|
+
printProgress(context, parsed.flags, 'doctor done issues=0');
|
|
889
939
|
return 0;
|
|
890
940
|
}
|
|
891
941
|
printDoctorFindings(context, result);
|
|
942
|
+
printProgress(context, parsed.flags, `doctor done issues=${result.issueCount}`);
|
|
892
943
|
return 1;
|
|
893
944
|
};
|
|
894
945
|
const formatCliError = (error) => {
|
package/dist/helpers.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../src/helpers.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../src/helpers.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,sBAAsB;;;EAuBlC,CAAC;AAEF,eAAO,MAAM,OAAO,GAAU,UAAU,MAAM,EAAE,cAAc,kBAG7D,CAAC;AAEF,eAAO,MAAM,WAAW,GAAU,UAAU,MAAM,EAAE,kBAAiB,kBAcpE,CAAC;AAEF,eAAO,MAAM,gBAAgB,GAAU,KAAK,EACxC,WAAW,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,EAC7C,QAAQ,MAAM,OAAO,CAAC,KAAK,CAAC,mBAuB/B,CAAC"}
|
package/dist/helpers.js
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { mkdir, mkdtemp, rm, stat, utimes, writeFile } from 'node:fs/promises';
|
|
2
2
|
import os from 'node:os';
|
|
3
3
|
import path from 'node:path';
|
|
4
|
+
import { V4_SCHEMA_VERSION } from 'ushman-lab-types';
|
|
4
5
|
export const createWorkspaceFixture = async () => {
|
|
5
6
|
const workspaceRoot = await mkdtemp(path.join(os.tmpdir(), 'ushman-ledger-'));
|
|
6
7
|
await mkdir(path.join(workspaceRoot, '.lab'), { recursive: true });
|
|
7
8
|
await mkdir(path.join(workspaceRoot, 'src'), { recursive: true });
|
|
8
9
|
await writeFile(path.join(workspaceRoot, '.lab', 'lab.json'), `${JSON.stringify({
|
|
9
|
-
schemaVersion:
|
|
10
|
+
schemaVersion: V4_SCHEMA_VERSION,
|
|
10
11
|
workspaceId: '3d71d4fb-dca0-4d63-9ad6-69d59a2395f4',
|
|
11
12
|
}, null, 2)}\n`, 'utf8');
|
|
12
13
|
return {
|
package/dist/lab-min.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as v from 'valibot';
|
|
2
2
|
export declare const LabManifestMin: v.LooseObjectSchema<{
|
|
3
3
|
readonly createdAt: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
|
|
4
|
-
readonly schemaVersion: v.LiteralSchema<"
|
|
4
|
+
readonly schemaVersion: v.LiteralSchema<"shibuk-lab/v4.0", undefined>;
|
|
5
5
|
readonly workspaceId: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.UuidAction<string, undefined>]>;
|
|
6
6
|
}, undefined>;
|
|
7
7
|
export type LabManifestMin = v.InferOutput<typeof LabManifestMin>;
|
package/dist/lab-min.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lab-min.d.ts","sourceRoot":"","sources":["../src/lab-min.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"lab-min.d.ts","sourceRoot":"","sources":["../src/lab-min.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,CAAC,MAAM,SAAS,CAAC;AAE7B,eAAO,MAAM,cAAc;;;;aAIzB,CAAC;AAEH,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,WAAW,CAAC,OAAO,cAAc,CAAC,CAAC;AAElE,eAAO,MAAM,kBAAkB,GAAU,eAAe,MAAM,KAAG,OAAO,CAAC,cAAc,CAWtF,CAAC"}
|
package/dist/lab-min.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { readFile } from 'node:fs/promises';
|
|
2
2
|
import path from 'node:path';
|
|
3
|
+
import { V4_SCHEMA_VERSION } from 'ushman-lab-types';
|
|
3
4
|
import * as v from 'valibot';
|
|
4
5
|
export const LabManifestMin = v.looseObject({
|
|
5
6
|
createdAt: v.optional(v.string()),
|
|
6
|
-
schemaVersion: v.literal(
|
|
7
|
+
schemaVersion: v.literal(V4_SCHEMA_VERSION),
|
|
7
8
|
workspaceId: v.pipe(v.string(), v.uuid()),
|
|
8
9
|
});
|
|
9
10
|
export const readLabManifestMin = async (workspaceRoot) => {
|
package/package.json
CHANGED
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
"dependencies": {
|
|
13
13
|
"safe-stable-stringify": "^2.5.0",
|
|
14
14
|
"tar": "^7.5.15",
|
|
15
|
+
"ushman-lab-types": "^0.2.0",
|
|
15
16
|
"valibot": "^1.4.1"
|
|
16
17
|
},
|
|
17
18
|
"description": "Append-only workspace ledger library and CLI for Ushman v4.",
|
|
@@ -70,5 +71,5 @@
|
|
|
70
71
|
},
|
|
71
72
|
"type": "module",
|
|
72
73
|
"types": "dist/index.d.ts",
|
|
73
|
-
"version": "1.3.
|
|
74
|
+
"version": "1.3.1"
|
|
74
75
|
}
|