@uwmd/core 1.7.0 → 1.9.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.
- package/dist/agents/bancroft.js +4 -1
- package/dist/agents/bancroft.js.map +1 -1
- package/dist/asset-class.d.ts +98 -0
- package/dist/asset-class.d.ts.map +1 -0
- package/dist/asset-class.js +226 -0
- package/dist/asset-class.js.map +1 -0
- package/dist/browser.d.ts +26 -8
- package/dist/browser.d.ts.map +1 -1
- package/dist/browser.js +25 -5
- package/dist/browser.js.map +1 -1
- package/dist/calc/errors.d.ts +1 -1
- package/dist/calc/errors.d.ts.map +1 -1
- package/dist/calc/errors.js.map +1 -1
- package/dist/calc/evaluator.js +25 -1
- package/dist/calc/evaluator.js.map +1 -1
- package/dist/calc/prng.d.ts +59 -0
- package/dist/calc/prng.d.ts.map +1 -0
- package/dist/calc/prng.js +181 -0
- package/dist/calc/prng.js.map +1 -0
- package/dist/calc/sensitivity.d.ts +76 -0
- package/dist/calc/sensitivity.d.ts.map +1 -0
- package/dist/calc/sensitivity.js +160 -0
- package/dist/calc/sensitivity.js.map +1 -0
- package/dist/calc/stochastic.d.ts +97 -0
- package/dist/calc/stochastic.d.ts.map +1 -0
- package/dist/calc/stochastic.js +265 -0
- package/dist/calc/stochastic.js.map +1 -0
- package/dist/cascade.d.ts.map +1 -1
- package/dist/cascade.js +8 -4
- package/dist/cascade.js.map +1 -1
- package/dist/cli-args.d.ts +37 -0
- package/dist/cli-args.d.ts.map +1 -0
- package/dist/cli-args.js +93 -0
- package/dist/cli-args.js.map +1 -0
- package/dist/cli.js +155 -75
- package/dist/cli.js.map +1 -1
- package/dist/editor.d.ts +18 -1
- package/dist/editor.d.ts.map +1 -1
- package/dist/editor.js +68 -7
- package/dist/editor.js.map +1 -1
- package/dist/format-rules.d.ts +46 -0
- package/dist/format-rules.d.ts.map +1 -0
- package/dist/format-rules.js +134 -0
- package/dist/format-rules.js.map +1 -0
- package/dist/format.d.ts +4 -0
- package/dist/format.d.ts.map +1 -1
- package/dist/format.js +34 -4
- package/dist/format.js.map +1 -1
- package/dist/index.d.ts +27 -9
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +26 -5
- package/dist/index.js.map +1 -1
- package/dist/init.d.ts.map +1 -1
- package/dist/init.js +16 -4
- package/dist/init.js.map +1 -1
- package/dist/integrity-canonical.d.ts.map +1 -1
- package/dist/integrity-canonical.js +10 -2
- package/dist/integrity-canonical.js.map +1 -1
- package/dist/integrity.d.ts +92 -4
- package/dist/integrity.d.ts.map +1 -1
- package/dist/integrity.js +195 -9
- package/dist/integrity.js.map +1 -1
- package/dist/lease-up.d.ts +134 -0
- package/dist/lease-up.d.ts.map +1 -0
- package/dist/lease-up.js +196 -0
- package/dist/lease-up.js.map +1 -0
- package/dist/migrate-source-tags.d.ts +34 -0
- package/dist/migrate-source-tags.d.ts.map +1 -0
- package/dist/migrate-source-tags.js +179 -0
- package/dist/migrate-source-tags.js.map +1 -0
- package/dist/module-runtime.d.ts +57 -0
- package/dist/module-runtime.d.ts.map +1 -0
- package/dist/module-runtime.js +167 -0
- package/dist/module-runtime.js.map +1 -0
- package/dist/module-signing.d.ts +85 -0
- package/dist/module-signing.d.ts.map +1 -0
- package/dist/module-signing.js +136 -0
- package/dist/module-signing.js.map +1 -0
- package/dist/modules.d.ts +42 -0
- package/dist/modules.d.ts.map +1 -1
- package/dist/modules.js +124 -1
- package/dist/modules.js.map +1 -1
- package/dist/parser.d.ts.map +1 -1
- package/dist/parser.js +28 -1
- package/dist/parser.js.map +1 -1
- package/dist/protocol.d.ts +249 -24
- package/dist/protocol.d.ts.map +1 -1
- package/dist/protocol.js +387 -33
- package/dist/protocol.js.map +1 -1
- package/dist/renderer.d.ts +10 -0
- package/dist/renderer.d.ts.map +1 -1
- package/dist/renderer.js +72 -8
- package/dist/renderer.js.map +1 -1
- package/dist/runner.d.ts.map +1 -1
- package/dist/runner.js +9 -3
- package/dist/runner.js.map +1 -1
- package/dist/types.d.ts +124 -5
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +44 -0
- package/dist/types.js.map +1 -1
- package/dist/validator.d.ts +26 -2
- package/dist/validator.d.ts.map +1 -1
- package/dist/validator.js +336 -19
- package/dist/validator.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +6 -2
package/dist/cli.js
CHANGED
|
@@ -3,10 +3,11 @@
|
|
|
3
3
|
// Commands: parse, validate, compact, diff, init, summary, render
|
|
4
4
|
// Usage: uwmd <command> <file> [options]
|
|
5
5
|
import { readFileSync, writeFileSync, existsSync, readdirSync, mkdirSync } from 'node:fs';
|
|
6
|
-
import { resolve, basename
|
|
6
|
+
import { resolve, basename } from 'node:path';
|
|
7
7
|
import { parseUWFile } from './parser.js';
|
|
8
8
|
import { validateUWFile } from './validator.js';
|
|
9
9
|
import { compact, diff } from './compactor.js';
|
|
10
|
+
import { migrateSourceTags } from './migrate-source-tags.js';
|
|
10
11
|
import { generateBlankUWFile } from './init.js';
|
|
11
12
|
import { render } from './renderer.js';
|
|
12
13
|
import { renderReportHtml } from './report.js';
|
|
@@ -14,8 +15,9 @@ import { stringifyUWEnvelope } from './uwjson.js';
|
|
|
14
15
|
import { stampEnvelopeDigest, toUWEnvelope, } from './envelope.js';
|
|
15
16
|
import { CORE_CODEC_REGISTRY } from './codecs.js';
|
|
16
17
|
import { writeAgentBlock } from './runner.js';
|
|
17
|
-
import { applyEdit } from './editor.js';
|
|
18
|
+
import { applyEdit, applyEditAsync } from './editor.js';
|
|
18
19
|
import { verifyChain, verifyProvenance } from './integrity.js';
|
|
20
|
+
import { REFERENCE_IMPLEMENTATION_MANIFEST } from './protocol.js';
|
|
19
21
|
import { loadModuleManifest, createModuleRegistry, ModuleRegistryError } from './modules.js';
|
|
20
22
|
import { cmdLeaseValidate, cmdLeaseProject, cmdPackageCreate, cmdPackageVerify, cmdPackageList, cmdPackageToContext, cmdPackageContextValidate, cmdPackageEdges, } from './cli-packages.js';
|
|
21
23
|
import { evaluateCalc } from './calc/index.js';
|
|
@@ -34,6 +36,7 @@ import { detectUWSourceRepresentation, UWX_REPRESENTATION_ID, UW_LITE_SOURCE_DES
|
|
|
34
36
|
import { parseUWLite } from './lite.js';
|
|
35
37
|
import { compileUWLite, projectUWEnvelopeToLite, stringifyUWX, } from './lite-bridge.js';
|
|
36
38
|
import { UW_LITE_REPRESENTATION_ID } from './source-representation.js';
|
|
39
|
+
import { parseFlags, extractPositionals, replaceUWExtension, hostTierFlag, defaultPartsDir, readManifestFile, } from './cli-args.js';
|
|
37
40
|
const [, , command, ...args] = process.argv;
|
|
38
41
|
function readFile(path) {
|
|
39
42
|
const resolved = resolve(path);
|
|
@@ -54,30 +57,6 @@ function loadInstitutionConfig(path) {
|
|
|
54
57
|
return undefined;
|
|
55
58
|
}
|
|
56
59
|
}
|
|
57
|
-
function parseFlags(rawArgs) {
|
|
58
|
-
const flags = {};
|
|
59
|
-
for (let i = 0; i < rawArgs.length; i++) {
|
|
60
|
-
const arg = rawArgs[i];
|
|
61
|
-
if (arg.startsWith('--')) {
|
|
62
|
-
const body = arg.slice(2);
|
|
63
|
-
const eqIdx = body.indexOf('=');
|
|
64
|
-
if (eqIdx >= 0) {
|
|
65
|
-
flags[body.slice(0, eqIdx)] = body.slice(eqIdx + 1);
|
|
66
|
-
continue;
|
|
67
|
-
}
|
|
68
|
-
const key = body;
|
|
69
|
-
const next = rawArgs[i + 1];
|
|
70
|
-
if (next && !next.startsWith('--')) {
|
|
71
|
-
flags[key] = next;
|
|
72
|
-
i++;
|
|
73
|
-
}
|
|
74
|
-
else {
|
|
75
|
-
flags[key] = true;
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
return flags;
|
|
80
|
-
}
|
|
81
60
|
// ─── Commands ─────────────────────────────────────────────────────────────────
|
|
82
61
|
function cmdParse(file, flags) {
|
|
83
62
|
const content = readFile(file);
|
|
@@ -96,11 +75,24 @@ function cmdParse(file, flags) {
|
|
|
96
75
|
for (const warning of detection.warnings)
|
|
97
76
|
console.warn(`Warning: ${warning}`);
|
|
98
77
|
const parsed = parseUWFile(content, { strict: flags['strict'] === true });
|
|
78
|
+
// The whole ParsedUWFile minus `raw` (which is just the input echoed back).
|
|
79
|
+
// Four fields — custom_calculations, custom_scenarios, extensions, and the
|
|
80
|
+
// full `superseded` blocks — used to be dropped here, so a caller that
|
|
81
|
+
// trusted `uwmd parse` to be "the parsed file" silently lost every custom
|
|
82
|
+
// calculation and every x_* extension in the document.
|
|
83
|
+
//
|
|
84
|
+
// `superseded_blocks` is kept alongside `superseded` for compatibility: it
|
|
85
|
+
// carries only each prior block's `content`, where `superseded` carries the
|
|
86
|
+
// whole block. New callers should read `superseded`.
|
|
99
87
|
const output = {
|
|
100
88
|
frontmatter: parsed.frontmatter,
|
|
101
89
|
sections: Object.fromEntries(Object.entries(parsed.sections).map(([id, block]) => [id, block])),
|
|
102
90
|
prose: parsed.prose,
|
|
103
91
|
pipeline_log: parsed.pipeline_log.map(b => b.content),
|
|
92
|
+
custom_calculations: parsed.custom_calculations,
|
|
93
|
+
custom_scenarios: parsed.custom_scenarios,
|
|
94
|
+
extensions: parsed.extensions,
|
|
95
|
+
superseded: parsed.superseded,
|
|
104
96
|
superseded_blocks: Object.fromEntries(Object.entries(parsed.superseded).map(([id, blocks]) => [id, blocks.map(b => b.content)])),
|
|
105
97
|
};
|
|
106
98
|
console.log(JSON.stringify(output, null, flags['compact'] ? 0 : 2));
|
|
@@ -171,6 +163,40 @@ function cmdValidate(file, flags) {
|
|
|
171
163
|
console.log('');
|
|
172
164
|
process.exit(result.errors.length > 0 ? 1 : 0);
|
|
173
165
|
}
|
|
166
|
+
/**
|
|
167
|
+
* Build the `verifyChain` options from `--signing --keystore=<path>`.
|
|
168
|
+
*
|
|
169
|
+
* `@uwmd/signing` is reached by dynamic import and declared as an optional peer
|
|
170
|
+
* - the same arrangement `@anthropic-ai/sdk` gets. `@uwmd/core` must not take a
|
|
171
|
+
* crypto dependency to satisfy a flag most invocations never pass, and the
|
|
172
|
+
* layering invariant (core depends on no sibling package) forbids a static
|
|
173
|
+
* import outright.
|
|
174
|
+
*/
|
|
175
|
+
async function signingOptions(flags) {
|
|
176
|
+
if (!flags['signing'])
|
|
177
|
+
return {};
|
|
178
|
+
const keystore = flags['keystore'];
|
|
179
|
+
if (typeof keystore !== 'string' || keystore.length === 0) {
|
|
180
|
+
console.error('--signing requires --keystore=<path> to a JSON key store.');
|
|
181
|
+
process.exit(1);
|
|
182
|
+
}
|
|
183
|
+
let signing;
|
|
184
|
+
try {
|
|
185
|
+
signing = (await import('@uwmd/signing'));
|
|
186
|
+
}
|
|
187
|
+
catch {
|
|
188
|
+
console.error('--signing needs the optional @uwmd/signing package. Install it with `npm i @uwmd/signing`.');
|
|
189
|
+
process.exit(1);
|
|
190
|
+
}
|
|
191
|
+
try {
|
|
192
|
+
const store = await signing.loadKeyStoreFile(resolve(keystore));
|
|
193
|
+
return { signatureVerifier: signing.createBlockSignatureVerifier(store) };
|
|
194
|
+
}
|
|
195
|
+
catch (error) {
|
|
196
|
+
console.error(error.message);
|
|
197
|
+
process.exit(1);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
174
200
|
async function cmdVerify(file, flags) {
|
|
175
201
|
const content = readFile(file);
|
|
176
202
|
// --resolved verifies the assembled record. Without it an externalized
|
|
@@ -191,8 +217,8 @@ async function cmdVerify(file, flags) {
|
|
|
191
217
|
}
|
|
192
218
|
let chain;
|
|
193
219
|
let prov;
|
|
194
|
-
if (runAll || onlyIntegrity) {
|
|
195
|
-
chain = await verifyChain(parsed);
|
|
220
|
+
if (runAll || onlyIntegrity || flags['signing']) {
|
|
221
|
+
chain = await verifyChain(parsed, await signingOptions(flags));
|
|
196
222
|
sections['integrity'] = chain;
|
|
197
223
|
if (!chain.ok)
|
|
198
224
|
hadError = true;
|
|
@@ -219,6 +245,12 @@ async function cmdVerify(file, flags) {
|
|
|
219
245
|
}
|
|
220
246
|
if (chain) {
|
|
221
247
|
console.log(`\nIntegrity: ${chain.ok ? 'ok' : 'FAIL'} — chains_with_hashes=${chain.chains_with_hashes}, chains_verified=${chain.chains_verified}`);
|
|
248
|
+
if (chain.signatures_present > 0) {
|
|
249
|
+
const checked = flags['signing']
|
|
250
|
+
? `${chain.signatures_verified} verified`
|
|
251
|
+
: 'not checked (pass --signing --keystore=<path>)';
|
|
252
|
+
console.log(`Signatures: ${chain.signatures_present} present, ${checked}`);
|
|
253
|
+
}
|
|
222
254
|
for (const issue of chain.issues) {
|
|
223
255
|
console.log(` [${issue.severity.toUpperCase()}] ${issue.code}${issue.section ? ` [${issue.section}]` : ''}: ${issue.message}`);
|
|
224
256
|
}
|
|
@@ -253,6 +285,24 @@ function cmdCompact(file, flags) {
|
|
|
253
285
|
writeFileSync(outPath, compacted, 'utf-8');
|
|
254
286
|
console.log(`Compacted ${totalSuperseded} superseded block(s). Wrote to: ${outPath}`);
|
|
255
287
|
}
|
|
288
|
+
function cmdMigrateSourceTags(file, flags) {
|
|
289
|
+
const content = readFile(file);
|
|
290
|
+
const result = migrateSourceTags(content);
|
|
291
|
+
for (const source of result.unmapped) {
|
|
292
|
+
console.error(`[unmapped] _meta.source '${source}' was left in place — rewrite it by hand.`);
|
|
293
|
+
}
|
|
294
|
+
if (result.changed === 0) {
|
|
295
|
+
console.log(`No legacy _meta.source values found in ${basename(file)} — nothing to migrate.`);
|
|
296
|
+
return;
|
|
297
|
+
}
|
|
298
|
+
if (flags['dry-run']) {
|
|
299
|
+
console.log(`Would migrate ${result.changed} block(s) in ${basename(file)} (RFC 0031 actor/resolution split).`);
|
|
300
|
+
return;
|
|
301
|
+
}
|
|
302
|
+
const outPath = flags['output'] ? resolve(flags['output']) : resolve(file);
|
|
303
|
+
writeFileSync(outPath, result.content, 'utf-8');
|
|
304
|
+
console.log(`Migrated ${result.changed} block(s). Wrote to: ${outPath}`);
|
|
305
|
+
}
|
|
256
306
|
function cmdDiff(fileA, fileB) {
|
|
257
307
|
const contentA = readFile(fileA);
|
|
258
308
|
const contentB = readFile(fileB);
|
|
@@ -402,14 +452,6 @@ async function loadEnvelope(file) {
|
|
|
402
452
|
* rather than `deal.uw.json`. (`.uw.md` does not match a `.uwx.md` filename —
|
|
403
453
|
* the suffixes genuinely differ — so it was silently a no-op, not a mis-match.)
|
|
404
454
|
*/
|
|
405
|
-
function replaceUWExtension(file, extension) {
|
|
406
|
-
const lower = file.toLowerCase();
|
|
407
|
-
for (const suffix of [UWX_EXTENSION, '.uw.csv.zip', '.uw.md', '.uw.json', '.uw.xml']) {
|
|
408
|
-
if (lower.endsWith(suffix))
|
|
409
|
-
return `${file.slice(0, -suffix.length)}${extension}`;
|
|
410
|
-
}
|
|
411
|
-
return `${file}${extension}`;
|
|
412
|
-
}
|
|
413
455
|
async function cmdConvert(file, flags) {
|
|
414
456
|
const requested = flags['to'];
|
|
415
457
|
if (typeof requested !== 'string') {
|
|
@@ -488,18 +530,6 @@ async function cmdReceiptIssue(file, flags) {
|
|
|
488
530
|
console.log('A receipt attests that these outputs follow from this record. It does not attest that the inputs are true.');
|
|
489
531
|
}
|
|
490
532
|
// ─── Modules ──────────────────────────────────────────────────────────────────
|
|
491
|
-
function readManifestFile(path) {
|
|
492
|
-
try {
|
|
493
|
-
return { ok: true, manifest: JSON.parse(readFileSync(resolve(path), 'utf-8')) };
|
|
494
|
-
}
|
|
495
|
-
catch (e) {
|
|
496
|
-
return { ok: false, message: e instanceof Error ? e.message : String(e) };
|
|
497
|
-
}
|
|
498
|
-
}
|
|
499
|
-
function hostTierFlag(flags) {
|
|
500
|
-
const tier = flags['tier'];
|
|
501
|
-
return typeof tier === 'string' ? tier : undefined;
|
|
502
|
-
}
|
|
503
533
|
function cmdModulesValidate(files, flags) {
|
|
504
534
|
const hostTier = hostTierFlag(flags);
|
|
505
535
|
const reports = files.map((file) => {
|
|
@@ -809,16 +839,7 @@ function cmdRefine(file, flags) {
|
|
|
809
839
|
}
|
|
810
840
|
// ─── Router ───────────────────────────────────────────────────────────────────
|
|
811
841
|
const flags = parseFlags(args);
|
|
812
|
-
|
|
813
|
-
const positional = [];
|
|
814
|
-
for (let _i = 0; _i < args.length; _i++) {
|
|
815
|
-
const a = args[_i];
|
|
816
|
-
if (a.startsWith('--')) {
|
|
817
|
-
_i++;
|
|
818
|
-
continue;
|
|
819
|
-
} // skip flag + its value
|
|
820
|
-
positional.push(a);
|
|
821
|
-
}
|
|
842
|
+
const positional = extractPositionals(args);
|
|
822
843
|
// ─── Composition (RFC 0021) ──────────────────────────────────────────────────
|
|
823
844
|
/** Load every `.uwpart.md` in a directory, keyed by `part_id`. */
|
|
824
845
|
function loadPartsDir(dir) {
|
|
@@ -836,10 +857,6 @@ function loadPartsDir(dir) {
|
|
|
836
857
|
}
|
|
837
858
|
return parts;
|
|
838
859
|
}
|
|
839
|
-
/** Where fragments live for a record, unless told otherwise. */
|
|
840
|
-
function defaultPartsDir(file) {
|
|
841
|
-
return resolve(dirname(resolve(file)), 'parts');
|
|
842
|
-
}
|
|
843
860
|
function cmdCompose(file, flags) {
|
|
844
861
|
const section = flags['externalize'];
|
|
845
862
|
if (typeof section !== 'string') {
|
|
@@ -969,7 +986,7 @@ function withResolved(parsed, file, flags) {
|
|
|
969
986
|
break;
|
|
970
987
|
case 'verify':
|
|
971
988
|
if (!positional[0]) {
|
|
972
|
-
console.error('Usage: uwmd verify <file> [--validate] [--integrity] [--policy] [--resolved] [--json]');
|
|
989
|
+
console.error('Usage: uwmd verify <file> [--validate] [--integrity] [--policy] [--signing --keystore=<path>] [--resolved] [--json]');
|
|
973
990
|
process.exit(1);
|
|
974
991
|
}
|
|
975
992
|
await cmdVerify(positional[0], flags);
|
|
@@ -988,6 +1005,13 @@ function withResolved(parsed, file, flags) {
|
|
|
988
1005
|
}
|
|
989
1006
|
cmdDiff(positional[0], positional[1]);
|
|
990
1007
|
break;
|
|
1008
|
+
case 'migrate':
|
|
1009
|
+
if (!positional[0] || !flags['source-tags']) {
|
|
1010
|
+
console.error('Usage: uwmd migrate <file> --source-tags [--output <file>] [--dry-run]');
|
|
1011
|
+
process.exit(1);
|
|
1012
|
+
}
|
|
1013
|
+
cmdMigrateSourceTags(positional[0], flags);
|
|
1014
|
+
break;
|
|
991
1015
|
case 'render': {
|
|
992
1016
|
if (!positional[0]) {
|
|
993
1017
|
console.error('Usage: uwmd render <file> [--format <json|csv|chat|summary>] [--profile <summary|live|compact|full|relevant>] [--sections a,b,c] [--max-tokens 12000] [--no-meta] [--output <file>] [--tier screener|analyst]');
|
|
@@ -1153,7 +1177,7 @@ function withResolved(parsed, file, flags) {
|
|
|
1153
1177
|
break;
|
|
1154
1178
|
case 'edit': {
|
|
1155
1179
|
if (!positional[0] || !positional[1]) {
|
|
1156
|
-
console.error('Usage: uwmd edit <file> <operation.json> [--actor <name>] [--source <pattern>] [--agent-id <id>] [--agent-version <v>] [--confidence high|medium|low] [--output <file>]');
|
|
1180
|
+
console.error('Usage: uwmd edit <file> <operation.json> [--actor <name>] [--source <pattern>] [--agent-id <id>] [--agent-version <v>] [--confidence high|medium|low] [--output <file>] [--capability-token <jwt> --coord-key <keystore.json>]');
|
|
1157
1181
|
process.exit(1);
|
|
1158
1182
|
}
|
|
1159
1183
|
const fileContent = readFile(positional[0]);
|
|
@@ -1174,7 +1198,47 @@ function withResolved(parsed, file, flags) {
|
|
|
1174
1198
|
agentVersion: flags['agent-version'] ?? null,
|
|
1175
1199
|
confidence: flags['confidence'] ?? 'medium',
|
|
1176
1200
|
};
|
|
1177
|
-
|
|
1201
|
+
// Capability enforcement (Protocol §XIV, RFC 0011). Same optional-peer
|
|
1202
|
+
// dynamic-import arrangement as `--signing` above: core takes no crypto
|
|
1203
|
+
// dependency to satisfy a flag most invocations never pass.
|
|
1204
|
+
let result;
|
|
1205
|
+
const capToken = flags['capability-token'];
|
|
1206
|
+
if (typeof capToken === 'string' && capToken.length > 0) {
|
|
1207
|
+
const coordKey = flags['coord-key'];
|
|
1208
|
+
if (typeof coordKey !== 'string' || coordKey.length === 0) {
|
|
1209
|
+
console.error('--capability-token requires --coord-key=<path> to the coordinator\'s JSON key store.');
|
|
1210
|
+
process.exit(1);
|
|
1211
|
+
}
|
|
1212
|
+
let signing;
|
|
1213
|
+
try {
|
|
1214
|
+
signing = (await import('@uwmd/signing'));
|
|
1215
|
+
}
|
|
1216
|
+
catch {
|
|
1217
|
+
console.error('--capability-token needs the optional @uwmd/signing package. Install it with `npm i @uwmd/signing`.');
|
|
1218
|
+
process.exit(1);
|
|
1219
|
+
}
|
|
1220
|
+
try {
|
|
1221
|
+
const store = await signing.loadKeyStoreFile(resolve(coordKey));
|
|
1222
|
+
ctx.capability_token = capToken;
|
|
1223
|
+
result = await applyEditAsync(fileContent, parsedFile, op, ctx, undefined, {
|
|
1224
|
+
capabilityVerifier: signing.createCapabilityVerifier(store),
|
|
1225
|
+
});
|
|
1226
|
+
}
|
|
1227
|
+
catch (error) {
|
|
1228
|
+
console.error(error.message);
|
|
1229
|
+
process.exit(1);
|
|
1230
|
+
}
|
|
1231
|
+
}
|
|
1232
|
+
else {
|
|
1233
|
+
result = applyEdit(fileContent, parsedFile, op, ctx);
|
|
1234
|
+
}
|
|
1235
|
+
// --json reports the edit instead of performing it: the conformance driver
|
|
1236
|
+
// needs the resulting content, and a driver that rewrote fixtures as a side
|
|
1237
|
+
// effect of reading them would corrupt the corpus it is testing.
|
|
1238
|
+
if (flags['json']) {
|
|
1239
|
+
console.log(JSON.stringify(result, null, 2));
|
|
1240
|
+
process.exit(result.ok ? 0 : 1);
|
|
1241
|
+
}
|
|
1178
1242
|
if (!result.ok || !result.content) {
|
|
1179
1243
|
console.error(`Edit rejected: [${result.error?.code}] ${result.error?.message}`);
|
|
1180
1244
|
if (result.error?.pointer)
|
|
@@ -1214,16 +1278,21 @@ function withResolved(parsed, file, flags) {
|
|
|
1214
1278
|
locale: 'en-US',
|
|
1215
1279
|
};
|
|
1216
1280
|
const results = decls.map((d) => evaluateCalc(d, ctx));
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
}
|
|
1221
|
-
else {
|
|
1222
|
-
console.log(`${r.calc_id} ERROR [${r.error?.code}] ${r.error?.message}`);
|
|
1223
|
-
}
|
|
1224
|
-
}
|
|
1281
|
+
// Under --json, stdout is exactly one JSON document — the conformance CLI
|
|
1282
|
+
// protocol (§II.6a) depends on that, and printing the human lines first
|
|
1283
|
+
// would make every calc response unparseable.
|
|
1225
1284
|
if (flags['json']) {
|
|
1226
|
-
console.log(JSON.stringify(results, null, 2));
|
|
1285
|
+
console.log(JSON.stringify(results.length === 1 ? results[0] : results, null, 2));
|
|
1286
|
+
}
|
|
1287
|
+
else {
|
|
1288
|
+
for (const r of results) {
|
|
1289
|
+
if (r.ok) {
|
|
1290
|
+
console.log(`${r.calc_id} = ${r.display ?? String(r.value)}`);
|
|
1291
|
+
}
|
|
1292
|
+
else {
|
|
1293
|
+
console.log(`${r.calc_id} ERROR [${r.error?.code}] ${r.error?.message}`);
|
|
1294
|
+
}
|
|
1295
|
+
}
|
|
1227
1296
|
}
|
|
1228
1297
|
if (results.some((r) => !r.ok))
|
|
1229
1298
|
process.exit(1);
|
|
@@ -1402,6 +1471,11 @@ function withResolved(parsed, file, flags) {
|
|
|
1402
1471
|
}
|
|
1403
1472
|
break;
|
|
1404
1473
|
}
|
|
1474
|
+
case 'manifest':
|
|
1475
|
+
// The conformance CLI protocol's identity call (§II.6a). Emitted with no
|
|
1476
|
+
// surrounding prose so a driver can read it without a parser.
|
|
1477
|
+
console.log(JSON.stringify(REFERENCE_IMPLEMENTATION_MANIFEST, null, 2));
|
|
1478
|
+
break;
|
|
1405
1479
|
case 'receipt': {
|
|
1406
1480
|
const sub = positional[0];
|
|
1407
1481
|
if (sub === 'issue') {
|
|
@@ -1432,11 +1506,14 @@ Commands:
|
|
|
1432
1506
|
parse <file> Parse file and output JSON
|
|
1433
1507
|
validate <file> Run all validation checks
|
|
1434
1508
|
verify <file> Validate + verify integrity (hashes) + provenance (actor/policy)
|
|
1509
|
+
--signing --keystore=<path> also checks block signatures (RFC 0010,
|
|
1510
|
+
via the optional @uwmd/signing package)
|
|
1435
1511
|
render <file> Render to output format (see --format)
|
|
1436
1512
|
run <file> Invoke a Bancroft agent (see --agent)
|
|
1437
1513
|
edit <file> <op.json> Apply an EditOperation (Tier-2)
|
|
1438
1514
|
compact <file> Strip superseded blocks
|
|
1439
1515
|
diff <file-a> <file-b> Compare two files section by section
|
|
1516
|
+
migrate <file> --source-tags Rewrite legacy _meta.source values into the actor/resolution split (RFC 0031)
|
|
1440
1517
|
calc <file> <calc.json> Evaluate a calc declaration or inline formula (Tier-3)
|
|
1441
1518
|
init Generate a blank .uwx.md file
|
|
1442
1519
|
summary <file> Print quick metrics to terminal
|
|
@@ -1452,16 +1529,19 @@ Commands:
|
|
|
1452
1529
|
modules validate|list Validate module manifest files, or list the registry they form
|
|
1453
1530
|
lease validate|project Validate a lease abstract, or project it to a rent-roll row (RFC 0018)
|
|
1454
1531
|
package create|verify|... Build, verify, list, or project a UW Deal Package (RFC 0018)
|
|
1532
|
+
manifest Print this implementation's ImplementationManifest (conformance protocol)
|
|
1455
1533
|
layers List Bancroft agent layers
|
|
1456
1534
|
|
|
1457
1535
|
Options:
|
|
1458
1536
|
--output <path> Output file path (compact, init)
|
|
1459
1537
|
--dry-run Show what would change without writing (compact)
|
|
1460
|
-
--json JSON output (validate)
|
|
1538
|
+
--json JSON output on stdout, nothing else (validate, calc, edit)
|
|
1461
1539
|
--strict Throw on parse errors instead of collecting
|
|
1462
1540
|
--format <f> Render format: json|csv|chat|summary (render, default: summary)
|
|
1463
1541
|
--no-superseded Drop append-only history from the .uw.json export (export)
|
|
1464
1542
|
--resolved Resolve externalized sections first (verify, export)
|
|
1543
|
+
--signing Check _meta.signature on every block (verify; requires --keystore)
|
|
1544
|
+
--keystore <path> JSON key store mapping kid to public key (verify --signing)
|
|
1465
1545
|
--parts <dir> Fragment directory (compose, resolve, --resolved; default: ./parts)
|
|
1466
1546
|
--externalize <s> Section to split into fragments (compose)
|
|
1467
1547
|
--collection-key <k> Row identity field (compose, default: unit_id)
|