@outcomeeng/spx 0.6.11 → 0.6.12
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/cli.js +763 -197
- package/dist/cli.js.map +1 -1
- package/package.json +2 -2
package/dist/cli.js
CHANGED
|
@@ -1787,6 +1787,7 @@ import {
|
|
|
1787
1787
|
mkdir as nodeMkdir,
|
|
1788
1788
|
open as nodeOpen,
|
|
1789
1789
|
readdir as nodeReaddir,
|
|
1790
|
+
rename as nodeRename,
|
|
1790
1791
|
rm as nodeRm
|
|
1791
1792
|
} from "fs/promises";
|
|
1792
1793
|
import { dirname as dirname2, join as join2 } from "path";
|
|
@@ -1880,6 +1881,9 @@ var defaultFileSystem = {
|
|
|
1880
1881
|
},
|
|
1881
1882
|
readdir: nodeReaddir,
|
|
1882
1883
|
lstat: nodeLstat,
|
|
1884
|
+
rename: async (from, to) => {
|
|
1885
|
+
await nodeRename(from, to);
|
|
1886
|
+
},
|
|
1883
1887
|
rm: async (path7, options) => {
|
|
1884
1888
|
await nodeRm(path7, options);
|
|
1885
1889
|
}
|
|
@@ -1972,8 +1976,8 @@ function formatRunTimestamp(date) {
|
|
|
1972
1976
|
);
|
|
1973
1977
|
return `${year}-${month}-${day}${RUN_TIMESTAMP_SEPARATOR}${hours}-${minutes}-${seconds}-${milliseconds}`;
|
|
1974
1978
|
}
|
|
1975
|
-
function generateRunId(
|
|
1976
|
-
return
|
|
1979
|
+
function generateRunId(randomBytes3 = nodeRandomBytes) {
|
|
1980
|
+
return randomBytes3(STATE_STORE_RUN_TOKEN.ID_BYTES).toString(HEX_ENCODING);
|
|
1977
1981
|
}
|
|
1978
1982
|
function createStateStoreRunToken(options) {
|
|
1979
1983
|
const startedAt = formatRunTimestamp(options.date);
|
|
@@ -1995,7 +1999,7 @@ async function createJsonlRunFile(scopeDir, domainName, options = {}) {
|
|
|
1995
1999
|
if (!domainRunsDir.ok) return domainRunsDir;
|
|
1996
2000
|
const maxAttempts = options.maxAttempts ?? RUN_FILE_CREATE_ATTEMPTS;
|
|
1997
2001
|
const startedDate = (options.now ?? (() => /* @__PURE__ */ new Date()))();
|
|
1998
|
-
const
|
|
2002
|
+
const randomBytes3 = options.randomBytes ?? nodeRandomBytes;
|
|
1999
2003
|
try {
|
|
2000
2004
|
await fs8.mkdir(domainRunsDir.value, { recursive: true });
|
|
2001
2005
|
} catch (error) {
|
|
@@ -2005,7 +2009,7 @@ async function createJsonlRunFile(scopeDir, domainName, options = {}) {
|
|
|
2005
2009
|
};
|
|
2006
2010
|
}
|
|
2007
2011
|
for (let attempt = 0; attempt < maxAttempts; attempt += 1) {
|
|
2008
|
-
const token = createStateStoreRunToken({ date: startedDate, randomBytes:
|
|
2012
|
+
const token = createStateStoreRunToken({ date: startedDate, randomBytes: randomBytes3 });
|
|
2009
2013
|
const name = runFileName(token.runToken);
|
|
2010
2014
|
const path7 = join2(domainRunsDir.value, name);
|
|
2011
2015
|
try {
|
|
@@ -2528,8 +2532,8 @@ import path2 from "path";
|
|
|
2528
2532
|
// src/lib/atomic-file-write.ts
|
|
2529
2533
|
var TEMP_TOKEN_BYTES = 8;
|
|
2530
2534
|
var TEMP_SUFFIX = ".tmp";
|
|
2531
|
-
function atomicWriteTempPath(targetPath,
|
|
2532
|
-
const token =
|
|
2535
|
+
function atomicWriteTempPath(targetPath, randomBytes3) {
|
|
2536
|
+
const token = randomBytes3(TEMP_TOKEN_BYTES).toString("hex");
|
|
2533
2537
|
return `${targetPath}.${token}${TEMP_SUFFIX}`;
|
|
2534
2538
|
}
|
|
2535
2539
|
async function writeFileAtomic(targetPath, content, options) {
|
|
@@ -3223,37 +3227,37 @@ function validateAgents(raw) {
|
|
|
3223
3227
|
}
|
|
3224
3228
|
return { ok: true, value: agents };
|
|
3225
3229
|
}
|
|
3226
|
-
function validateAgentConfig(path7, raw,
|
|
3230
|
+
function validateAgentConfig(path7, raw, defaults6) {
|
|
3227
3231
|
if (!isRecord2(raw)) return { ok: false, error: `${path7} must be an object` };
|
|
3228
3232
|
const unknown = rejectUnknownFields(path7, raw, HARNESS_ENVIRONMENT_AGENT_CONFIG_ALLOWED_FIELDS);
|
|
3229
3233
|
if (!unknown.ok) return unknown;
|
|
3230
3234
|
const enabledRaw = raw[HARNESS_ENVIRONMENT_CONFIG_FIELDS.ENABLED];
|
|
3231
|
-
const enabled = enabledRaw === void 0 ? { ok: true, value:
|
|
3235
|
+
const enabled = enabledRaw === void 0 ? { ok: true, value: defaults6.enabled } : validateBoolean(`${path7}.${HARNESS_ENVIRONMENT_CONFIG_FIELDS.ENABLED}`, enabledRaw);
|
|
3232
3236
|
if (!enabled.ok) return enabled;
|
|
3233
3237
|
const hooksRaw = raw[HARNESS_ENVIRONMENT_CONFIG_FIELDS.HOOKS];
|
|
3234
|
-
const hooks = hooksRaw === void 0 ? { ok: true, value:
|
|
3238
|
+
const hooks = hooksRaw === void 0 ? { ok: true, value: defaults6.hooks } : validateAgentHooks(`${path7}.${HARNESS_ENVIRONMENT_CONFIG_FIELDS.HOOKS}`, hooksRaw, defaults6.hooks);
|
|
3235
3239
|
if (!hooks.ok) return hooks;
|
|
3236
3240
|
return { ok: true, value: { enabled: enabled.value, hooks: hooks.value } };
|
|
3237
3241
|
}
|
|
3238
|
-
function validateAgentHooks(path7, raw,
|
|
3242
|
+
function validateAgentHooks(path7, raw, defaults6) {
|
|
3239
3243
|
if (!isRecord2(raw)) return { ok: false, error: `${path7} must be an object` };
|
|
3240
3244
|
const unknown = rejectUnknownFields(path7, raw, HARNESS_ENVIRONMENT_AGENT_HOOKS_ALLOWED_FIELDS);
|
|
3241
3245
|
if (!unknown.ok) return unknown;
|
|
3242
3246
|
const sessionStartRaw = raw[HARNESS_ENVIRONMENT_CONFIG_FIELDS.SESSION_START];
|
|
3243
|
-
const sessionStart = sessionStartRaw === void 0 ? { ok: true, value:
|
|
3247
|
+
const sessionStart = sessionStartRaw === void 0 ? { ok: true, value: defaults6.sessionStart } : validateSessionStartHooks(
|
|
3244
3248
|
`${path7}.${HARNESS_ENVIRONMENT_CONFIG_FIELDS.SESSION_START}`,
|
|
3245
3249
|
sessionStartRaw,
|
|
3246
|
-
|
|
3250
|
+
defaults6.sessionStart
|
|
3247
3251
|
);
|
|
3248
3252
|
if (!sessionStart.ok) return sessionStart;
|
|
3249
3253
|
return { ok: true, value: { sessionStart: sessionStart.value } };
|
|
3250
3254
|
}
|
|
3251
|
-
function validateSessionStartHooks(path7, raw,
|
|
3255
|
+
function validateSessionStartHooks(path7, raw, defaults6) {
|
|
3252
3256
|
if (!isRecord2(raw)) return { ok: false, error: `${path7} must be an object` };
|
|
3253
3257
|
const unknown = rejectUnknownFields(path7, raw, HARNESS_ENVIRONMENT_SESSION_START_HOOKS_ALLOWED_FIELDS);
|
|
3254
3258
|
if (!unknown.ok) return unknown;
|
|
3255
3259
|
const compactStdoutRaw = raw[HARNESS_ENVIRONMENT_CONFIG_FIELDS.COMPACT_STDOUT];
|
|
3256
|
-
const compactStdout = compactStdoutRaw === void 0 ? { ok: true, value:
|
|
3260
|
+
const compactStdout = compactStdoutRaw === void 0 ? { ok: true, value: defaults6.compactStdout } : validateBoolean(`${path7}.${HARNESS_ENVIRONMENT_CONFIG_FIELDS.COMPACT_STDOUT}`, compactStdoutRaw);
|
|
3257
3261
|
if (!compactStdout.ok) return compactStdout;
|
|
3258
3262
|
return { ok: true, value: { compactStdout: compactStdout.value } };
|
|
3259
3263
|
}
|
|
@@ -3326,8 +3330,8 @@ function validatePluginBootstrap(raw) {
|
|
|
3326
3330
|
}
|
|
3327
3331
|
};
|
|
3328
3332
|
}
|
|
3329
|
-
function validateEntryArray(path7, raw, validateEntry,
|
|
3330
|
-
if (raw === void 0) return { ok: true, value:
|
|
3333
|
+
function validateEntryArray(path7, raw, validateEntry, defaults6) {
|
|
3334
|
+
if (raw === void 0) return { ok: true, value: defaults6 };
|
|
3331
3335
|
if (!Array.isArray(raw)) return { ok: false, error: `${path7} must be an array` };
|
|
3332
3336
|
const entries = [];
|
|
3333
3337
|
for (const [index, entry] of raw.entries()) {
|
|
@@ -3618,6 +3622,36 @@ var diagnoseConfigDescriptor = {
|
|
|
3618
3622
|
validate: validate2
|
|
3619
3623
|
};
|
|
3620
3624
|
|
|
3625
|
+
// src/lib/agent-run-journal/config.ts
|
|
3626
|
+
var RUNTIME_SECTION = "runtime";
|
|
3627
|
+
var RUNTIME_CONFIG_FIELDS = {
|
|
3628
|
+
EVENT_NAMESPACE: "eventNamespace"
|
|
3629
|
+
};
|
|
3630
|
+
var RUNTIME_EVENT_NAMESPACE_DEFAULT = "sh.spx";
|
|
3631
|
+
var defaults2 = { eventNamespace: RUNTIME_EVENT_NAMESPACE_DEFAULT };
|
|
3632
|
+
function validate3(value) {
|
|
3633
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
3634
|
+
return { ok: false, error: `${RUNTIME_SECTION} section must be an object` };
|
|
3635
|
+
}
|
|
3636
|
+
const candidate = value;
|
|
3637
|
+
const raw = candidate[RUNTIME_CONFIG_FIELDS.EVENT_NAMESPACE];
|
|
3638
|
+
if (raw === void 0) {
|
|
3639
|
+
return { ok: true, value: { eventNamespace: RUNTIME_EVENT_NAMESPACE_DEFAULT } };
|
|
3640
|
+
}
|
|
3641
|
+
if (typeof raw !== "string" || raw.trim().length === 0) {
|
|
3642
|
+
return {
|
|
3643
|
+
ok: false,
|
|
3644
|
+
error: `${RUNTIME_SECTION}.${RUNTIME_CONFIG_FIELDS.EVENT_NAMESPACE} must be a non-empty string`
|
|
3645
|
+
};
|
|
3646
|
+
}
|
|
3647
|
+
return { ok: true, value: { eventNamespace: raw } };
|
|
3648
|
+
}
|
|
3649
|
+
var runtimeConfigDescriptor = {
|
|
3650
|
+
section: RUNTIME_SECTION,
|
|
3651
|
+
defaults: defaults2,
|
|
3652
|
+
validate: validate3
|
|
3653
|
+
};
|
|
3654
|
+
|
|
3621
3655
|
// src/lib/file-inclusion/adapters/eslint.ts
|
|
3622
3656
|
function eslintAdapter(scope2, config) {
|
|
3623
3657
|
return scope2.excluded.flatMap((entry) => [config.ignoreFlag, entry.path]);
|
|
@@ -3678,7 +3712,7 @@ var DEFAULT_SCOPE_CONFIG = {};
|
|
|
3678
3712
|
var DEFAULT_TOOLS_CONFIG = Object.fromEntries(
|
|
3679
3713
|
Object.entries(TOOL_DEFAULT_FLAGS).map(([name, flag]) => [name, { ignoreFlag: flag }])
|
|
3680
3714
|
);
|
|
3681
|
-
var
|
|
3715
|
+
var defaults3 = {
|
|
3682
3716
|
scope: DEFAULT_SCOPE_CONFIG,
|
|
3683
3717
|
tools: DEFAULT_TOOLS_CONFIG
|
|
3684
3718
|
};
|
|
@@ -3750,7 +3784,7 @@ function validateTools(raw) {
|
|
|
3750
3784
|
}
|
|
3751
3785
|
return { ok: true, value: tools };
|
|
3752
3786
|
}
|
|
3753
|
-
function
|
|
3787
|
+
function validate4(value) {
|
|
3754
3788
|
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
3755
3789
|
return { ok: false, error: `${FILE_INCLUSION_SECTION} section must be an object` };
|
|
3756
3790
|
}
|
|
@@ -3777,8 +3811,8 @@ function validate3(value) {
|
|
|
3777
3811
|
}
|
|
3778
3812
|
var fileInclusionConfigDescriptor = {
|
|
3779
3813
|
section: FILE_INCLUSION_SECTION,
|
|
3780
|
-
defaults:
|
|
3781
|
-
validate:
|
|
3814
|
+
defaults: defaults3,
|
|
3815
|
+
validate: validate4
|
|
3782
3816
|
};
|
|
3783
3817
|
|
|
3784
3818
|
// src/config/source-roots.ts
|
|
@@ -3801,7 +3835,7 @@ var PRECOMMIT_DEFAULTS = {
|
|
|
3801
3835
|
sourceDirs: TEST_RELEVANT_SOURCE_ROOT_PREFIXES,
|
|
3802
3836
|
testPattern: ".test.ts"
|
|
3803
3837
|
};
|
|
3804
|
-
function
|
|
3838
|
+
function validate5(value) {
|
|
3805
3839
|
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
3806
3840
|
return { ok: false, error: `${PRECOMMIT_SECTION} section must be an object` };
|
|
3807
3841
|
}
|
|
@@ -3831,7 +3865,7 @@ function validate4(value) {
|
|
|
3831
3865
|
var precommitConfigDescriptor = {
|
|
3832
3866
|
section: PRECOMMIT_SECTION,
|
|
3833
3867
|
defaults: PRECOMMIT_DEFAULTS,
|
|
3834
|
-
validate:
|
|
3868
|
+
validate: validate5
|
|
3835
3869
|
};
|
|
3836
3870
|
|
|
3837
3871
|
// src/lib/spec-tree/config.ts
|
|
@@ -4022,7 +4056,7 @@ function buildConfigFromKindNames(kindNames) {
|
|
|
4022
4056
|
const entries = kindNames.map((kind) => [kind, KIND_REGISTRY[kind]]);
|
|
4023
4057
|
return { kinds: Object.fromEntries(entries) };
|
|
4024
4058
|
}
|
|
4025
|
-
function
|
|
4059
|
+
function validate6(value) {
|
|
4026
4060
|
if (typeof value !== "object" || value === null) {
|
|
4027
4061
|
return { ok: false, error: `${SPEC_TREE_SECTION} section must be an object` };
|
|
4028
4062
|
}
|
|
@@ -4121,7 +4155,7 @@ function validateKindDefinitionMap(kindEntries) {
|
|
|
4121
4155
|
var specTreeConfigDescriptor = {
|
|
4122
4156
|
section: SPEC_TREE_SECTION,
|
|
4123
4157
|
defaults: buildDefaults(),
|
|
4124
|
-
validate:
|
|
4158
|
+
validate: validate6
|
|
4125
4159
|
};
|
|
4126
4160
|
|
|
4127
4161
|
// src/config/primitives/path-filter.ts
|
|
@@ -4194,7 +4228,7 @@ var TESTING_CONFIG_FIELDS = {
|
|
|
4194
4228
|
PASSING_SCOPE: "passingScope"
|
|
4195
4229
|
};
|
|
4196
4230
|
var DEFAULT_PASSING_SCOPE = resolveDefaultPassingScope();
|
|
4197
|
-
var
|
|
4231
|
+
var defaults4 = {
|
|
4198
4232
|
passingScope: DEFAULT_PASSING_SCOPE
|
|
4199
4233
|
};
|
|
4200
4234
|
function resolveDefaultPassingScope() {
|
|
@@ -4207,14 +4241,14 @@ function resolveDefaultPassingScope() {
|
|
|
4207
4241
|
}
|
|
4208
4242
|
return result.value;
|
|
4209
4243
|
}
|
|
4210
|
-
function
|
|
4244
|
+
function validate7(value) {
|
|
4211
4245
|
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
4212
4246
|
return { ok: false, error: `${TESTING_SECTION} section must be an object` };
|
|
4213
4247
|
}
|
|
4214
4248
|
const candidate = value;
|
|
4215
4249
|
const passingScopeRaw = candidate[TESTING_CONFIG_FIELDS.PASSING_SCOPE];
|
|
4216
4250
|
if (passingScopeRaw === void 0) {
|
|
4217
|
-
return { ok: true, value:
|
|
4251
|
+
return { ok: true, value: defaults4 };
|
|
4218
4252
|
}
|
|
4219
4253
|
const passingScopeResult = validatePathFilterConfig(
|
|
4220
4254
|
passingScopeRaw,
|
|
@@ -4230,8 +4264,8 @@ function validate6(value) {
|
|
|
4230
4264
|
}
|
|
4231
4265
|
var testingConfigDescriptor = {
|
|
4232
4266
|
section: TESTING_SECTION,
|
|
4233
|
-
defaults:
|
|
4234
|
-
validate:
|
|
4267
|
+
defaults: defaults4,
|
|
4268
|
+
validate: validate7
|
|
4235
4269
|
};
|
|
4236
4270
|
|
|
4237
4271
|
// src/validation/literal/config.ts
|
|
@@ -4295,7 +4329,7 @@ var LITERAL_DEFAULTS = {
|
|
|
4295
4329
|
function isNonNegativeInteger(value) {
|
|
4296
4330
|
return typeof value === "number" && Number.isInteger(value) && value >= 0;
|
|
4297
4331
|
}
|
|
4298
|
-
function
|
|
4332
|
+
function validate8(value) {
|
|
4299
4333
|
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
4300
4334
|
return { ok: false, error: `${LITERAL_SECTION} section must be an object` };
|
|
4301
4335
|
}
|
|
@@ -4359,7 +4393,7 @@ function isStringArray(value) {
|
|
|
4359
4393
|
var literalConfigDescriptor = {
|
|
4360
4394
|
section: LITERAL_SECTION,
|
|
4361
4395
|
defaults: LITERAL_DEFAULTS,
|
|
4362
|
-
validate:
|
|
4396
|
+
validate: validate8
|
|
4363
4397
|
};
|
|
4364
4398
|
|
|
4365
4399
|
// src/validation/config/descriptor.ts
|
|
@@ -4378,7 +4412,7 @@ var VALIDATION_PATH_TOOL_SUBSECTIONS = {
|
|
|
4378
4412
|
LITERAL: "literal",
|
|
4379
4413
|
FORMATTING: "formatting"
|
|
4380
4414
|
};
|
|
4381
|
-
var
|
|
4415
|
+
var defaults5 = {
|
|
4382
4416
|
paths: {},
|
|
4383
4417
|
literal: {
|
|
4384
4418
|
enabled: true,
|
|
@@ -4418,7 +4452,7 @@ function validateLiteral(raw) {
|
|
|
4418
4452
|
};
|
|
4419
4453
|
}
|
|
4420
4454
|
const candidate = raw;
|
|
4421
|
-
const enabledRaw = candidate[VALIDATION_ENABLED_FIELD] ??
|
|
4455
|
+
const enabledRaw = candidate[VALIDATION_ENABLED_FIELD] ?? defaults5.literal.enabled;
|
|
4422
4456
|
if (typeof enabledRaw !== "boolean") {
|
|
4423
4457
|
return {
|
|
4424
4458
|
ok: false,
|
|
@@ -4443,7 +4477,7 @@ function validateKnip(raw) {
|
|
|
4443
4477
|
};
|
|
4444
4478
|
}
|
|
4445
4479
|
const candidate = raw;
|
|
4446
|
-
const enabledRaw = candidate[VALIDATION_ENABLED_FIELD] ??
|
|
4480
|
+
const enabledRaw = candidate[VALIDATION_ENABLED_FIELD] ?? defaults5.knip.enabled;
|
|
4447
4481
|
if (typeof enabledRaw !== "boolean") {
|
|
4448
4482
|
return {
|
|
4449
4483
|
ok: false,
|
|
@@ -4452,7 +4486,7 @@ function validateKnip(raw) {
|
|
|
4452
4486
|
}
|
|
4453
4487
|
return { ok: true, value: { enabled: enabledRaw } };
|
|
4454
4488
|
}
|
|
4455
|
-
function
|
|
4489
|
+
function validate9(value) {
|
|
4456
4490
|
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
4457
4491
|
return { ok: false, error: `${VALIDATION_SECTION} section must be an object` };
|
|
4458
4492
|
}
|
|
@@ -4470,8 +4504,8 @@ function validate8(value) {
|
|
|
4470
4504
|
}
|
|
4471
4505
|
var validationConfigDescriptor = {
|
|
4472
4506
|
section: VALIDATION_SECTION,
|
|
4473
|
-
defaults:
|
|
4474
|
-
validate:
|
|
4507
|
+
defaults: defaults5,
|
|
4508
|
+
validate: validate9
|
|
4475
4509
|
};
|
|
4476
4510
|
|
|
4477
4511
|
// src/config/registry.ts
|
|
@@ -4482,15 +4516,16 @@ var productionRegistry = [
|
|
|
4482
4516
|
fileInclusionConfigDescriptor,
|
|
4483
4517
|
precommitConfigDescriptor,
|
|
4484
4518
|
harnessEnvironmentConfigDescriptor,
|
|
4485
|
-
diagnoseConfigDescriptor
|
|
4519
|
+
diagnoseConfigDescriptor,
|
|
4520
|
+
runtimeConfigDescriptor
|
|
4486
4521
|
];
|
|
4487
4522
|
|
|
4488
4523
|
// src/config/descriptor-digest.ts
|
|
4489
4524
|
import { createHash as createHash3 } from "crypto";
|
|
4490
4525
|
var DEFAULT_DESCRIPTOR_PATH = "descriptor section";
|
|
4491
|
-
var
|
|
4526
|
+
var DESCRIPTOR_DIGEST_SHA256_ALGORITHM = "sha256";
|
|
4492
4527
|
var UTF8_ENCODING2 = "utf8";
|
|
4493
|
-
var
|
|
4528
|
+
var DESCRIPTOR_DIGEST_HEX_ENCODING = "hex";
|
|
4494
4529
|
function canonicalDescriptorJson(value, path7 = DEFAULT_DESCRIPTOR_PATH) {
|
|
4495
4530
|
const normalized = normalizeDescriptorJsonValue(value, path7, /* @__PURE__ */ new WeakSet());
|
|
4496
4531
|
if (!normalized.ok) return normalized;
|
|
@@ -4499,7 +4534,7 @@ function canonicalDescriptorJson(value, path7 = DEFAULT_DESCRIPTOR_PATH) {
|
|
|
4499
4534
|
function digestDescriptorSection(value, path7 = DEFAULT_DESCRIPTOR_PATH) {
|
|
4500
4535
|
const canonical = canonicalDescriptorJson(value, path7);
|
|
4501
4536
|
if (!canonical.ok) return canonical;
|
|
4502
|
-
const sha256 = createHash3(
|
|
4537
|
+
const sha256 = createHash3(DESCRIPTOR_DIGEST_SHA256_ALGORITHM).update(Buffer.from(canonical.value, UTF8_ENCODING2)).digest(DESCRIPTOR_DIGEST_HEX_ENCODING);
|
|
4503
4538
|
return {
|
|
4504
4539
|
ok: true,
|
|
4505
4540
|
value: {
|
|
@@ -6242,7 +6277,7 @@ import {
|
|
|
6242
6277
|
mkdir as nodeMkdir2,
|
|
6243
6278
|
readFile as nodeReadFile,
|
|
6244
6279
|
readlink as nodeReadlink,
|
|
6245
|
-
rename as
|
|
6280
|
+
rename as nodeRename2,
|
|
6246
6281
|
rm as nodeRm2,
|
|
6247
6282
|
symlink as nodeSymlink,
|
|
6248
6283
|
writeFile as nodeWriteFile
|
|
@@ -6254,7 +6289,7 @@ var defaultOccupancyFileSystem = {
|
|
|
6254
6289
|
writeFile: async (path7, data) => {
|
|
6255
6290
|
await nodeWriteFile(path7, data);
|
|
6256
6291
|
},
|
|
6257
|
-
rename:
|
|
6292
|
+
rename: nodeRename2,
|
|
6258
6293
|
symlink: nodeSymlink,
|
|
6259
6294
|
readlink: nodeReadlink,
|
|
6260
6295
|
readFile: nodeReadFile,
|
|
@@ -7145,9 +7180,9 @@ var JOURNAL_RUN_STATE_INCOMPLETE_REASON = {
|
|
|
7145
7180
|
};
|
|
7146
7181
|
var JOURNAL_RUN_EVENT = {
|
|
7147
7182
|
SOURCE: "/spx/journal",
|
|
7148
|
-
STARTED_TYPE:
|
|
7149
|
-
PROGRESS_TYPE:
|
|
7150
|
-
COMPLETED_TYPE:
|
|
7183
|
+
STARTED_TYPE: `${RUNTIME_EVENT_NAMESPACE_DEFAULT}.journal.run.started`,
|
|
7184
|
+
PROGRESS_TYPE: `${RUNTIME_EVENT_NAMESPACE_DEFAULT}.journal.run.progress`,
|
|
7185
|
+
COMPLETED_TYPE: `${RUNTIME_EVENT_NAMESPACE_DEFAULT}.journal.run.completed`
|
|
7151
7186
|
};
|
|
7152
7187
|
var JOURNAL_RUN_STATE_FIELDS = {
|
|
7153
7188
|
BRANCH_NAME: "branchName",
|
|
@@ -7166,13 +7201,18 @@ var JOURNAL_RUN_STATE_FIELDS = {
|
|
|
7166
7201
|
STATUS: "status"
|
|
7167
7202
|
};
|
|
7168
7203
|
function foldJournalRunState(events, sealed) {
|
|
7169
|
-
if (!sealed)
|
|
7204
|
+
if (!sealed) {
|
|
7205
|
+
return { ok: false, reason: JOURNAL_RUN_STATE_INCOMPLETE_REASON.UNSEALED };
|
|
7206
|
+
}
|
|
7170
7207
|
let completed;
|
|
7171
7208
|
for (const event of events) {
|
|
7172
7209
|
if (event.type === JOURNAL_RUN_EVENT.COMPLETED_TYPE) completed = event;
|
|
7173
7210
|
}
|
|
7174
7211
|
if (completed === void 0) {
|
|
7175
|
-
return {
|
|
7212
|
+
return {
|
|
7213
|
+
ok: false,
|
|
7214
|
+
reason: JOURNAL_RUN_STATE_INCOMPLETE_REASON.MISSING_STATE
|
|
7215
|
+
};
|
|
7176
7216
|
}
|
|
7177
7217
|
const validated = validateJournalRunState(completed.data);
|
|
7178
7218
|
if (!validated.ok) {
|
|
@@ -7185,13 +7225,17 @@ function foldJournalRunState(events, sealed) {
|
|
|
7185
7225
|
return validated;
|
|
7186
7226
|
}
|
|
7187
7227
|
function isJournalRunStateStatus(value) {
|
|
7188
|
-
return typeof value === "string" && Object.values(JOURNAL_RUN_STATE_STATUS).includes(
|
|
7228
|
+
return typeof value === "string" && Object.values(JOURNAL_RUN_STATE_STATUS).includes(
|
|
7229
|
+
value
|
|
7230
|
+
);
|
|
7189
7231
|
}
|
|
7190
7232
|
function isJournalTargetKind(value) {
|
|
7191
7233
|
return typeof value === "string" && Object.values(JOURNAL_TARGET_KIND).includes(value);
|
|
7192
7234
|
}
|
|
7193
7235
|
function validateJournalRunState(value) {
|
|
7194
|
-
if (!isRecord5(value))
|
|
7236
|
+
if (!isRecord5(value)) {
|
|
7237
|
+
return { ok: false, error: "journal run state must be an object" };
|
|
7238
|
+
}
|
|
7195
7239
|
const identity = readRunStateIdentity(value);
|
|
7196
7240
|
if (!identity.ok) return identity;
|
|
7197
7241
|
const body = readRunStateBody(value);
|
|
@@ -7203,9 +7247,15 @@ function readRunStateIdentity(value) {
|
|
|
7203
7247
|
if (!branchName.ok) return branchName;
|
|
7204
7248
|
const branchSlug = readString(value, JOURNAL_RUN_STATE_FIELDS.BRANCH_SLUG);
|
|
7205
7249
|
if (!branchSlug.ok) return branchSlug;
|
|
7206
|
-
const targetKind = readTargetKind(
|
|
7250
|
+
const targetKind = readTargetKind(
|
|
7251
|
+
value,
|
|
7252
|
+
JOURNAL_RUN_STATE_FIELDS.TARGET_KIND
|
|
7253
|
+
);
|
|
7207
7254
|
if (!targetKind.ok) return targetKind;
|
|
7208
|
-
const pullRequestNumber = readOptionalNonNegativeInteger(
|
|
7255
|
+
const pullRequestNumber = readOptionalNonNegativeInteger(
|
|
7256
|
+
value,
|
|
7257
|
+
JOURNAL_RUN_STATE_FIELDS.PULL_REQUEST_NUMBER
|
|
7258
|
+
);
|
|
7209
7259
|
if (!pullRequestNumber.ok) return pullRequestNumber;
|
|
7210
7260
|
const headSha = readString(value, JOURNAL_RUN_STATE_FIELDS.HEAD_SHA);
|
|
7211
7261
|
if (!headSha.ok) return headSha;
|
|
@@ -7227,9 +7277,15 @@ function readRunStateIdentity(value) {
|
|
|
7227
7277
|
};
|
|
7228
7278
|
}
|
|
7229
7279
|
function readRunStateBody(value) {
|
|
7230
|
-
const configDigest = readString(
|
|
7280
|
+
const configDigest = readString(
|
|
7281
|
+
value,
|
|
7282
|
+
JOURNAL_RUN_STATE_FIELDS.CONFIG_DIGEST
|
|
7283
|
+
);
|
|
7231
7284
|
if (!configDigest.ok) return configDigest;
|
|
7232
|
-
const participants = readStringArray(
|
|
7285
|
+
const participants = readStringArray(
|
|
7286
|
+
value,
|
|
7287
|
+
JOURNAL_RUN_STATE_FIELDS.PARTICIPANTS
|
|
7288
|
+
);
|
|
7233
7289
|
if (!participants.ok) return participants;
|
|
7234
7290
|
const scope2 = readPathFilter(value, JOURNAL_RUN_STATE_FIELDS.SCOPE);
|
|
7235
7291
|
if (!scope2.ok) return scope2;
|
|
@@ -7237,7 +7293,10 @@ function readRunStateBody(value) {
|
|
|
7237
7293
|
if (!startedAt.ok) return startedAt;
|
|
7238
7294
|
const completedAt = readString(value, JOURNAL_RUN_STATE_FIELDS.COMPLETED_AT);
|
|
7239
7295
|
if (!completedAt.ok) return completedAt;
|
|
7240
|
-
const outputPaths = readStringArray(
|
|
7296
|
+
const outputPaths = readStringArray(
|
|
7297
|
+
value,
|
|
7298
|
+
JOURNAL_RUN_STATE_FIELDS.OUTPUT_PATHS
|
|
7299
|
+
);
|
|
7241
7300
|
if (!outputPaths.ok) return outputPaths;
|
|
7242
7301
|
const status = readStatus(value, JOURNAL_RUN_STATE_FIELDS.STATUS);
|
|
7243
7302
|
if (!status.ok) return status;
|
|
@@ -7266,7 +7325,10 @@ function readOptionalString(value, field) {
|
|
|
7266
7325
|
function readOptionalNonNegativeInteger(value, field) {
|
|
7267
7326
|
const raw = value[field];
|
|
7268
7327
|
if (raw === void 0) return { ok: true, value: void 0 };
|
|
7269
|
-
return typeof raw === "number" && Number.isInteger(raw) && raw >= 0 ? { ok: true, value: raw } : {
|
|
7328
|
+
return typeof raw === "number" && Number.isInteger(raw) && raw >= 0 ? { ok: true, value: raw } : {
|
|
7329
|
+
ok: false,
|
|
7330
|
+
error: `${field} must be a non-negative integer when present`
|
|
7331
|
+
};
|
|
7270
7332
|
}
|
|
7271
7333
|
function readStringArray(value, field) {
|
|
7272
7334
|
const raw = value[field];
|
|
@@ -7508,6 +7570,7 @@ function createJournal(backend, identity) {
|
|
|
7508
7570
|
|
|
7509
7571
|
// src/lib/appendable-journal-store/index.ts
|
|
7510
7572
|
var SEAL_MARKER_SUFFIX = ".sealed";
|
|
7573
|
+
var APPENDABLE_JOURNAL_SEAL_MARKER_CONTENT = "";
|
|
7511
7574
|
var LINE_SEPARATOR3 = "\n";
|
|
7512
7575
|
function appendableJournalSealMarkerPath(runFilePath) {
|
|
7513
7576
|
return `${runFilePath}${SEAL_MARKER_SUFFIX}`;
|
|
@@ -7547,7 +7610,7 @@ function createAppendableJournalStore(options) {
|
|
|
7547
7610
|
readAll,
|
|
7548
7611
|
async seal() {
|
|
7549
7612
|
await fs8.mkdir(dirname5(sealMarkerPath), { recursive: true });
|
|
7550
|
-
await fs8.writeFile(sealMarkerPath,
|
|
7613
|
+
await fs8.writeFile(sealMarkerPath, APPENDABLE_JOURNAL_SEAL_MARKER_CONTENT);
|
|
7551
7614
|
},
|
|
7552
7615
|
async isSealed() {
|
|
7553
7616
|
return await readFileOrUndefined(fs8, sealMarkerPath) !== void 0;
|
|
@@ -8004,6 +8067,20 @@ async function sealJournalRun(ref, options = {}) {
|
|
|
8004
8067
|
return { ok: false, error: `${JOURNAL_RUNTIME_ERROR.SEAL_FAILED}: ${toMessage(error)}` };
|
|
8005
8068
|
}
|
|
8006
8069
|
}
|
|
8070
|
+
async function isJournalRunSealed(ref, options = {}) {
|
|
8071
|
+
const runFilePath = bindRunFilePath(ref);
|
|
8072
|
+
if (!runFilePath.ok) return runFilePath;
|
|
8073
|
+
const fs8 = options.fs ?? defaultFileSystem;
|
|
8074
|
+
if (!await runFileExists(fs8, runFilePath.value)) {
|
|
8075
|
+
return { ok: false, error: JOURNAL_RUNTIME_ERROR.RUN_NOT_FOUND };
|
|
8076
|
+
}
|
|
8077
|
+
const store = createAppendableJournalStore({ runFilePath: runFilePath.value, fs: fs8 });
|
|
8078
|
+
try {
|
|
8079
|
+
return { ok: true, value: await store.isSealed() };
|
|
8080
|
+
} catch (error) {
|
|
8081
|
+
return { ok: false, error: `${JOURNAL_RUNTIME_ERROR.READ_FAILED}: ${toMessage(error)}` };
|
|
8082
|
+
}
|
|
8083
|
+
}
|
|
8007
8084
|
async function renderJournalRun(ref, projection, options = {}) {
|
|
8008
8085
|
const bound = await bindJournal(ref, options.fs);
|
|
8009
8086
|
if (!bound.ok) return bound;
|
|
@@ -11683,8 +11760,8 @@ var PRODUCT_INPUT_DIGEST_FIELDS = {
|
|
|
11683
11760
|
DESCRIPTOR_ID: "descriptorId",
|
|
11684
11761
|
DIGEST: "digest"
|
|
11685
11762
|
};
|
|
11686
|
-
var
|
|
11687
|
-
var
|
|
11763
|
+
var SHA256_ALGORITHM2 = "sha256";
|
|
11764
|
+
var HEX_ENCODING2 = "hex";
|
|
11688
11765
|
var SEGMENT_SEPARATOR = "-";
|
|
11689
11766
|
var defaultFileSystem2 = defaultFileSystem;
|
|
11690
11767
|
function formatTestRunTimestamp(date) {
|
|
@@ -11960,7 +12037,7 @@ function isRecord6(value) {
|
|
|
11960
12037
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
11961
12038
|
}
|
|
11962
12039
|
function sha256Hex2(value) {
|
|
11963
|
-
return createHash4(
|
|
12040
|
+
return createHash4(SHA256_ALGORITHM2).update(value).digest(HEX_ENCODING2);
|
|
11964
12041
|
}
|
|
11965
12042
|
var UNKNOWN_ERROR_MESSAGE = "unknown error";
|
|
11966
12043
|
function toErrorMessage3(error) {
|
|
@@ -19418,13 +19495,13 @@ async function persistVerificationContext(scope2, document, options = {}) {
|
|
|
19418
19495
|
const existing = await readExistingContext(fs8, contextPath.value);
|
|
19419
19496
|
if (!existing.ok) return existing;
|
|
19420
19497
|
if (existing.value === document.canonicalJson) {
|
|
19421
|
-
return { ok: true, value: { digest: document.digest, contextPath: contextPath.value } };
|
|
19498
|
+
return { ok: true, value: { digest: document.digest, contextPath: contextPath.value, created: false } };
|
|
19422
19499
|
}
|
|
19423
19500
|
return { ok: false, error: VERIFICATION_CONTEXT_RUNTIME_ERROR.CONTENT_MISMATCH };
|
|
19424
19501
|
}
|
|
19425
19502
|
return { ok: false, error: `${VERIFICATION_CONTEXT_RUNTIME_ERROR.WRITE_FAILED}: ${toMessage(error)}` };
|
|
19426
19503
|
}
|
|
19427
|
-
return { ok: true, value: { digest: document.digest, contextPath: contextPath.value } };
|
|
19504
|
+
return { ok: true, value: { digest: document.digest, contextPath: contextPath.value, created: true } };
|
|
19428
19505
|
}
|
|
19429
19506
|
async function readExistingContext(fs8, contextPath) {
|
|
19430
19507
|
try {
|
|
@@ -19570,6 +19647,7 @@ var verificationContextDomain = {
|
|
|
19570
19647
|
import { readFile as readFile13 } from "fs/promises";
|
|
19571
19648
|
|
|
19572
19649
|
// src/commands/verify/cli.ts
|
|
19650
|
+
import { randomBytes as randomBytes2 } from "crypto";
|
|
19573
19651
|
import { dirname as dirname12 } from "path";
|
|
19574
19652
|
|
|
19575
19653
|
// src/domains/verify/verify.ts
|
|
@@ -19582,18 +19660,35 @@ var VERIFY_VERB = {
|
|
|
19582
19660
|
START: "start",
|
|
19583
19661
|
INPUT: "input",
|
|
19584
19662
|
APPEND_SCOPE: "append-scope",
|
|
19585
|
-
APPEND_FINDING: "append-finding"
|
|
19663
|
+
APPEND_FINDING: "append-finding",
|
|
19664
|
+
FINISH: "finish",
|
|
19665
|
+
STATUS: "status",
|
|
19666
|
+
RENDER: "render"
|
|
19667
|
+
};
|
|
19668
|
+
var VERIFY_LIFECYCLE_ACTION = {
|
|
19669
|
+
SCOPE_ADD: "scope add",
|
|
19670
|
+
FINDING_ADD: "finding add",
|
|
19671
|
+
FINISH: VERIFY_VERB.FINISH
|
|
19586
19672
|
};
|
|
19673
|
+
var UNSEALED_NEXT_ACTIONS = [
|
|
19674
|
+
VERIFY_LIFECYCLE_ACTION.SCOPE_ADD,
|
|
19675
|
+
VERIFY_LIFECYCLE_ACTION.FINDING_ADD,
|
|
19676
|
+
VERIFY_LIFECYCLE_ACTION.FINISH
|
|
19677
|
+
];
|
|
19587
19678
|
var VERIFY_VERIFICATION_TYPE = {
|
|
19588
19679
|
REVIEW: "review"
|
|
19589
19680
|
};
|
|
19681
|
+
var VERIFY_VERIFICATION_TYPES = new Set(Object.values(VERIFY_VERIFICATION_TYPE));
|
|
19682
|
+
function isVerifyVerificationType(value) {
|
|
19683
|
+
return VERIFY_VERIFICATION_TYPES.has(value);
|
|
19684
|
+
}
|
|
19590
19685
|
var REVIEW_FINDING_DISPOSITION = {
|
|
19591
19686
|
BLOCKING: "BLOCKING",
|
|
19592
19687
|
DEBT: "DEBT"
|
|
19593
19688
|
};
|
|
19594
19689
|
var VERIFY_APPEND_EVENT_TYPE = {
|
|
19595
|
-
SCOPE:
|
|
19596
|
-
FINDING:
|
|
19690
|
+
SCOPE: `${RUNTIME_EVENT_NAMESPACE_DEFAULT}.verify.scope`,
|
|
19691
|
+
FINDING: `${RUNTIME_EVENT_NAMESPACE_DEFAULT}.verify.finding`
|
|
19597
19692
|
};
|
|
19598
19693
|
var VERIFY_EVENT_SOURCE = "/spx/verify";
|
|
19599
19694
|
var VERIFY_APPEND_EVENT_FIELD = {
|
|
@@ -19611,7 +19706,9 @@ var VERIFY_SCOPE_ERROR = {
|
|
|
19611
19706
|
var VERIFY_INPUT_DIGEST_PATH = "verify run input";
|
|
19612
19707
|
function parseChangesetScope(scope2) {
|
|
19613
19708
|
const separatorIndex = scope2.indexOf(VERIFY_SCOPE_SEPARATOR);
|
|
19614
|
-
if (separatorIndex < 0)
|
|
19709
|
+
if (separatorIndex < 0) {
|
|
19710
|
+
return { ok: false, error: VERIFY_SCOPE_ERROR.MALFORMED_CHANGESET };
|
|
19711
|
+
}
|
|
19615
19712
|
const base = scope2.slice(0, separatorIndex);
|
|
19616
19713
|
const head = scope2.slice(separatorIndex + VERIFY_SCOPE_SEPARATOR.length);
|
|
19617
19714
|
if (base.length === 0 || head.length === 0 || head.includes(VERIFY_SCOPE_SEPARATOR)) {
|
|
@@ -19631,7 +19728,10 @@ function buildRunLocator(parts) {
|
|
|
19631
19728
|
};
|
|
19632
19729
|
}
|
|
19633
19730
|
function digestRunInput(source, content) {
|
|
19634
|
-
const digest = digestDescriptorSection(
|
|
19731
|
+
const digest = digestDescriptorSection(
|
|
19732
|
+
{ source, content },
|
|
19733
|
+
VERIFY_INPUT_DIGEST_PATH
|
|
19734
|
+
);
|
|
19635
19735
|
if (!digest.ok) return digest;
|
|
19636
19736
|
return { ok: true, value: digest.value.sha256 };
|
|
19637
19737
|
}
|
|
@@ -19651,7 +19751,10 @@ function verifyInputRecordPath(scope2) {
|
|
|
19651
19751
|
if (!token.ok) return token;
|
|
19652
19752
|
return {
|
|
19653
19753
|
ok: true,
|
|
19654
|
-
value: join36(
|
|
19754
|
+
value: join36(
|
|
19755
|
+
runs.value,
|
|
19756
|
+
`${VERIFY_INPUT_RECORD.PREFIX}${token.value}${VERIFY_INPUT_RECORD.SUFFIX}`
|
|
19757
|
+
)
|
|
19655
19758
|
};
|
|
19656
19759
|
}
|
|
19657
19760
|
var VERIFY_APPEND_ATTEMPT = 1;
|
|
@@ -19700,6 +19803,58 @@ function buildAppendEvent(args) {
|
|
|
19700
19803
|
}
|
|
19701
19804
|
};
|
|
19702
19805
|
}
|
|
19806
|
+
var VERIFY_TERMINAL_EVENT_TYPE = `${RUNTIME_EVENT_NAMESPACE_DEFAULT}.verify.terminal`;
|
|
19807
|
+
var VERIFY_TERMINAL_EVENT_FIELD = {
|
|
19808
|
+
TERMINAL_STATUS: "terminalStatus"
|
|
19809
|
+
};
|
|
19810
|
+
var VERIFY_TERMINAL_EVENT_ID_PREFIX = "verify-terminal-";
|
|
19811
|
+
function isVerifyTerminalStatus(value) {
|
|
19812
|
+
return isJournalRunStateStatus(value);
|
|
19813
|
+
}
|
|
19814
|
+
function buildTerminalEvent(args) {
|
|
19815
|
+
return {
|
|
19816
|
+
id: `${VERIFY_TERMINAL_EVENT_ID_PREFIX}${args.runToken}`,
|
|
19817
|
+
source: VERIFY_EVENT_SOURCE,
|
|
19818
|
+
type: VERIFY_TERMINAL_EVENT_TYPE,
|
|
19819
|
+
time: args.at.toISOString(),
|
|
19820
|
+
attempt: VERIFY_APPEND_ATTEMPT,
|
|
19821
|
+
data: {
|
|
19822
|
+
[VERIFY_TERMINAL_EVENT_FIELD.TERMINAL_STATUS]: args.terminalStatus
|
|
19823
|
+
}
|
|
19824
|
+
};
|
|
19825
|
+
}
|
|
19826
|
+
var VERIFY_NO_EVENTS_SEQUENCE = 0;
|
|
19827
|
+
function findTerminalEvent(events) {
|
|
19828
|
+
return events.find((event) => event.type === VERIFY_TERMINAL_EVENT_TYPE);
|
|
19829
|
+
}
|
|
19830
|
+
function terminalStatusOf(event) {
|
|
19831
|
+
if (event === void 0 || !isJsonRecord(event.data)) return void 0;
|
|
19832
|
+
const status = event.data[VERIFY_TERMINAL_EVENT_FIELD.TERMINAL_STATUS];
|
|
19833
|
+
return typeof status === "string" ? status : void 0;
|
|
19834
|
+
}
|
|
19835
|
+
function countVerifyFindings(events) {
|
|
19836
|
+
return events.filter(
|
|
19837
|
+
(event) => event.type === VERIFY_APPEND_EVENT_TYPE.FINDING
|
|
19838
|
+
).length;
|
|
19839
|
+
}
|
|
19840
|
+
function lastSequenceOf(events) {
|
|
19841
|
+
return events.reduce(
|
|
19842
|
+
(max, event) => event.seq > max ? event.seq : max,
|
|
19843
|
+
VERIFY_NO_EVENTS_SEQUENCE
|
|
19844
|
+
);
|
|
19845
|
+
}
|
|
19846
|
+
function projectVerifyRun(events) {
|
|
19847
|
+
const terminal = findTerminalEvent(events);
|
|
19848
|
+
const terminalStatus = terminalStatusOf(terminal);
|
|
19849
|
+
const sealed = terminal !== void 0;
|
|
19850
|
+
return {
|
|
19851
|
+
sealed,
|
|
19852
|
+
...terminalStatus === void 0 ? {} : { terminalStatus },
|
|
19853
|
+
findingCount: countVerifyFindings(events),
|
|
19854
|
+
lastSequence: lastSequenceOf(events),
|
|
19855
|
+
nextActions: sealed ? [] : UNSEALED_NEXT_ACTIONS
|
|
19856
|
+
};
|
|
19857
|
+
}
|
|
19703
19858
|
|
|
19704
19859
|
// src/commands/verify/cli.ts
|
|
19705
19860
|
var VERIFY_CLI_EXIT_CODE = {
|
|
@@ -19710,19 +19865,40 @@ var VERIFY_CLI_ENV = {
|
|
|
19710
19865
|
BRANCH: SPX_VERIFY_ENV.BRANCH
|
|
19711
19866
|
};
|
|
19712
19867
|
var VERIFY_CLI_ERROR = {
|
|
19713
|
-
INPUT_REQUIRED: "spx
|
|
19714
|
-
RUN_REQUIRED: "spx
|
|
19715
|
-
RUN_NOT_FOUND: "spx
|
|
19716
|
-
|
|
19717
|
-
|
|
19718
|
-
|
|
19719
|
-
|
|
19720
|
-
|
|
19721
|
-
|
|
19722
|
-
|
|
19723
|
-
|
|
19724
|
-
|
|
19725
|
-
|
|
19868
|
+
INPUT_REQUIRED: "spx verification run start requires --input <input-source>",
|
|
19869
|
+
RUN_REQUIRED: "spx verification run existing-run commands require an explicit --run <run-token>",
|
|
19870
|
+
RUN_NOT_FOUND: "spx verification run could not locate the requested run",
|
|
19871
|
+
RUN_SELECTOR_MISMATCH: "spx verification run selector does not match the recorded run",
|
|
19872
|
+
CHANGED_SCOPE_FAILED: "spx verification run could not derive the changeset changed-file scope",
|
|
19873
|
+
INPUT_PERSIST_FAILED: "spx verification run could not persist the recorded run input",
|
|
19874
|
+
INPUT_READ_FAILED: "spx verification run could not read the recorded run input",
|
|
19875
|
+
PAYLOAD_REQUIRED: "spx verification run evidence-add commands require --payload <payload-source>",
|
|
19876
|
+
IDEMPOTENCY_KEY_REQUIRED: "spx verification run evidence-add commands require --idempotency-key <key>",
|
|
19877
|
+
PAYLOAD_READ_FAILED: "spx verification run could not read the evidence payload",
|
|
19878
|
+
PAYLOAD_INVALID: "spx verification run evidence payload is not valid JSON",
|
|
19879
|
+
RUN_FINISHED: "spx verification run cannot add evidence to a finished run",
|
|
19880
|
+
FINDING_INVALID: "spx verification run finding add payload failed verification-type validation",
|
|
19881
|
+
UNSUPPORTED_VERIFICATION_TYPE: "spx verification run verification type is not registered",
|
|
19882
|
+
APPEND_FAILED: "spx verification run could not append the evidence event",
|
|
19883
|
+
TERMINAL_STATUS_REQUIRED: "spx verification run finish requires --terminal-status <status>",
|
|
19884
|
+
TERMINAL_STATUS_INVALID: "spx verification run finish requires a terminal status in the journal terminal-status vocabulary",
|
|
19885
|
+
FINISH_FAILED: "spx verification run could not record terminal completion",
|
|
19886
|
+
SEAL_FAILED: "spx verification run could not seal the run journal",
|
|
19887
|
+
STATUS_FAILED: "spx verification run could not read the run status",
|
|
19888
|
+
RENDER_FAILED: "spx verification run could not render the run projection"
|
|
19889
|
+
};
|
|
19890
|
+
var VERIFY_RUN_NOT_FOUND_DIAGNOSTIC_FIELD = {
|
|
19891
|
+
RUN: "run=",
|
|
19892
|
+
VERIFICATION_TYPE: "verification-type=",
|
|
19893
|
+
SCOPE_TYPE: "scope-type=",
|
|
19894
|
+
SCOPE: "scope=",
|
|
19895
|
+
BACKEND: "backend=",
|
|
19896
|
+
NAMESPACE: "namespace=",
|
|
19897
|
+
TARGET: "target="
|
|
19898
|
+
};
|
|
19899
|
+
var VERIFY_START_ROLLBACK_ARTIFACT = {
|
|
19900
|
+
CONTEXT_FILE: "verification context file",
|
|
19901
|
+
RUN_FILE: "journal run file"
|
|
19726
19902
|
};
|
|
19727
19903
|
function okResult3(output) {
|
|
19728
19904
|
return { exitCode: VERIFY_CLI_EXIT_CODE.OK, output };
|
|
@@ -19781,73 +19957,131 @@ async function persistInputRecord(runScope2, record6, deps) {
|
|
|
19781
19957
|
const fs8 = deps.fs ?? defaultFileSystem;
|
|
19782
19958
|
try {
|
|
19783
19959
|
await fs8.mkdir(dirname12(path7.value), { recursive: true });
|
|
19784
|
-
await
|
|
19960
|
+
await writeFileAtomic(path7.value, JSON.stringify(record6), { fs: fs8, randomBytes: randomBytes2 });
|
|
19785
19961
|
return { ok: true, value: void 0 };
|
|
19786
19962
|
} catch (error) {
|
|
19787
19963
|
return { ok: false, error: `${VERIFY_CLI_ERROR.INPUT_PERSIST_FAILED}: ${toMessage2(error)}` };
|
|
19788
19964
|
}
|
|
19789
19965
|
}
|
|
19966
|
+
async function readStartInputContent(source, deps) {
|
|
19967
|
+
try {
|
|
19968
|
+
return { ok: true, value: await deps.readInputSource(source) };
|
|
19969
|
+
} catch (error) {
|
|
19970
|
+
return { ok: false, error: `${VERIFY_CLI_ERROR.INPUT_READ_FAILED}: ${toMessage2(error)}` };
|
|
19971
|
+
}
|
|
19972
|
+
}
|
|
19973
|
+
async function removeStartedRunArtifact(path7, label, deps) {
|
|
19974
|
+
const fs8 = deps.fs ?? defaultFileSystem;
|
|
19975
|
+
try {
|
|
19976
|
+
await fs8.rm(path7, { force: true });
|
|
19977
|
+
return { ok: true, value: void 0 };
|
|
19978
|
+
} catch (error) {
|
|
19979
|
+
return {
|
|
19980
|
+
ok: false,
|
|
19981
|
+
error: `${VERIFY_CLI_ERROR.INPUT_PERSIST_FAILED}: rollback failed for ${label}: ${toMessage2(error)}`
|
|
19982
|
+
};
|
|
19983
|
+
}
|
|
19984
|
+
}
|
|
19985
|
+
async function removeStartedRunArtifacts(artifacts, deps) {
|
|
19986
|
+
const rollbackErrors = [];
|
|
19987
|
+
if (artifacts.contextPath !== void 0) {
|
|
19988
|
+
const contextRollback = await removeStartedRunArtifact(
|
|
19989
|
+
artifacts.contextPath,
|
|
19990
|
+
VERIFY_START_ROLLBACK_ARTIFACT.CONTEXT_FILE,
|
|
19991
|
+
deps
|
|
19992
|
+
);
|
|
19993
|
+
if (!contextRollback.ok) rollbackErrors.push(contextRollback.error);
|
|
19994
|
+
}
|
|
19995
|
+
if (artifacts.runFile !== void 0) {
|
|
19996
|
+
const runRollback = await removeStartedRunArtifact(
|
|
19997
|
+
artifacts.runFile,
|
|
19998
|
+
VERIFY_START_ROLLBACK_ARTIFACT.RUN_FILE,
|
|
19999
|
+
deps
|
|
20000
|
+
);
|
|
20001
|
+
if (!runRollback.ok) rollbackErrors.push(runRollback.error);
|
|
20002
|
+
}
|
|
20003
|
+
if (rollbackErrors.length > 0) return { ok: false, error: rollbackErrors.join("; ") };
|
|
20004
|
+
return { ok: true, value: void 0 };
|
|
20005
|
+
}
|
|
20006
|
+
function isStoredRecordedInput(value) {
|
|
20007
|
+
if (typeof value !== "object" || value === null) return false;
|
|
20008
|
+
const record6 = value;
|
|
20009
|
+
return typeof record6.scopeIdentity === "string" && typeof record6.scopeType === "string" && typeof record6.source === "string" && typeof record6.digest === "string" && typeof record6.content === "string";
|
|
20010
|
+
}
|
|
20011
|
+
function parseRecordedInput(content) {
|
|
20012
|
+
try {
|
|
20013
|
+
const parsed = JSON.parse(content);
|
|
20014
|
+
if (!isStoredRecordedInput(parsed)) {
|
|
20015
|
+
return { ok: false, error: `${VERIFY_CLI_ERROR.INPUT_READ_FAILED}: recorded input is missing required fields` };
|
|
20016
|
+
}
|
|
20017
|
+
return { ok: true, value: parsed };
|
|
20018
|
+
} catch (error) {
|
|
20019
|
+
return { ok: false, error: `${VERIFY_CLI_ERROR.INPUT_READ_FAILED}: ${toMessage2(error)}` };
|
|
20020
|
+
}
|
|
20021
|
+
}
|
|
19790
20022
|
async function readInputRecordAt(path7, deps) {
|
|
19791
20023
|
const fs8 = deps.fs ?? defaultFileSystem;
|
|
20024
|
+
let content;
|
|
19792
20025
|
try {
|
|
19793
|
-
|
|
19794
|
-
return { ok: true, value: JSON.parse(content) };
|
|
20026
|
+
content = await fs8.readFile(path7, STATE_STORE_TEXT_ENCODING);
|
|
19795
20027
|
} catch (error) {
|
|
19796
20028
|
if (hasErrorCode(error, ERROR_CODE_NOT_FOUND)) return { ok: true, value: void 0 };
|
|
19797
20029
|
return { ok: false, error: `${VERIFY_CLI_ERROR.INPUT_READ_FAILED}: ${toMessage2(error)}` };
|
|
19798
20030
|
}
|
|
20031
|
+
const parsed = parseRecordedInput(content);
|
|
20032
|
+
if (!parsed.ok) return parsed;
|
|
20033
|
+
return { ok: true, value: parsed.value };
|
|
19799
20034
|
}
|
|
19800
|
-
function
|
|
20035
|
+
function verifyRunLocatorDiagnostic(summary, context) {
|
|
19801
20036
|
return [
|
|
19802
|
-
|
|
19803
|
-
|
|
19804
|
-
|
|
19805
|
-
|
|
19806
|
-
|
|
19807
|
-
|
|
19808
|
-
|
|
19809
|
-
|
|
20037
|
+
summary,
|
|
20038
|
+
`${VERIFY_RUN_NOT_FOUND_DIAGNOSTIC_FIELD.RUN}${context.runToken}`,
|
|
20039
|
+
`${VERIFY_RUN_NOT_FOUND_DIAGNOSTIC_FIELD.VERIFICATION_TYPE}${context.verificationType}`,
|
|
20040
|
+
`${VERIFY_RUN_NOT_FOUND_DIAGNOSTIC_FIELD.SCOPE_TYPE}${context.scopeType}`,
|
|
20041
|
+
`${VERIFY_RUN_NOT_FOUND_DIAGNOSTIC_FIELD.SCOPE}${context.scopeIdentity}`,
|
|
20042
|
+
`${VERIFY_RUN_NOT_FOUND_DIAGNOSTIC_FIELD.BACKEND}${context.backendIdentity}`,
|
|
20043
|
+
`${VERIFY_RUN_NOT_FOUND_DIAGNOSTIC_FIELD.NAMESPACE}${context.storageNamespace}`,
|
|
20044
|
+
`${VERIFY_RUN_NOT_FOUND_DIAGNOSTIC_FIELD.TARGET}${context.searchedTarget}`
|
|
19810
20045
|
].join(" ");
|
|
19811
20046
|
}
|
|
19812
|
-
|
|
19813
|
-
|
|
19814
|
-
|
|
19815
|
-
|
|
19816
|
-
|
|
19817
|
-
const resolved = await resolveVerifyScope(deps);
|
|
19818
|
-
if (!resolved.ok) return errorResult3(resolved.error);
|
|
19819
|
-
const inputContent = await deps.readInputSource(options.input);
|
|
19820
|
-
const inputDigest = digestRunInput(options.input, inputContent);
|
|
19821
|
-
if (!inputDigest.ok) return errorResult3(inputDigest.error);
|
|
19822
|
-
const context = await verificationContextCreateCommand(
|
|
19823
|
-
{
|
|
19824
|
-
subject: VERIFICATION_CONTEXT_SUBJECT_KIND.CHANGESET,
|
|
19825
|
-
base: scope2.value.base,
|
|
19826
|
-
head: scope2.value.head,
|
|
19827
|
-
predicate: options.verificationType,
|
|
19828
|
-
workflow: options.verificationType
|
|
19829
|
-
},
|
|
19830
|
-
forwardDeps(deps)
|
|
19831
|
-
);
|
|
19832
|
-
if (context.exitCode !== VERIFY_CLI_EXIT_CODE.OK) return errorResult3(context.output);
|
|
19833
|
-
const contextDigest = JSON.parse(context.output).digest;
|
|
20047
|
+
function verifyRunNotFoundDiagnostic(context) {
|
|
20048
|
+
return verifyRunLocatorDiagnostic(VERIFY_CLI_ERROR.RUN_NOT_FOUND, context);
|
|
20049
|
+
}
|
|
20050
|
+
async function completeVerifyStartCommand(args) {
|
|
20051
|
+
const { options, deps } = args;
|
|
19834
20052
|
const opened = await journalOpenCommand(
|
|
19835
|
-
{ type: options.verificationType, branchSlug:
|
|
20053
|
+
{ type: options.verificationType, branchSlug: args.branchSlug },
|
|
19836
20054
|
forwardDeps(deps)
|
|
19837
20055
|
);
|
|
19838
|
-
if (opened.exitCode !== VERIFY_CLI_EXIT_CODE.OK)
|
|
20056
|
+
if (opened.exitCode !== VERIFY_CLI_EXIT_CODE.OK) {
|
|
20057
|
+
const rollback = await removeStartedRunArtifacts(
|
|
20058
|
+
{ ...args.contextCreated ? { contextPath: args.contextPath } : {} },
|
|
20059
|
+
deps
|
|
20060
|
+
);
|
|
20061
|
+
return errorResult3(rollback.ok ? opened.output : `${opened.output}; ${rollback.error}`);
|
|
20062
|
+
}
|
|
19839
20063
|
const { runToken, runFile } = JSON.parse(opened.output);
|
|
19840
20064
|
const runScope2 = {
|
|
19841
|
-
productDir:
|
|
19842
|
-
branchSlug:
|
|
20065
|
+
productDir: args.productDir,
|
|
20066
|
+
branchSlug: args.branchSlug,
|
|
19843
20067
|
type: options.verificationType,
|
|
19844
20068
|
runToken
|
|
19845
20069
|
};
|
|
19846
|
-
const recorded = {
|
|
20070
|
+
const recorded = {
|
|
20071
|
+
scopeIdentity: options.scope,
|
|
20072
|
+
scopeType: options.scopeType,
|
|
20073
|
+
source: options.input,
|
|
20074
|
+
digest: args.inputDigest,
|
|
20075
|
+
content: args.inputContent
|
|
20076
|
+
};
|
|
19847
20077
|
const persisted = await persistInputRecord(runScope2, recorded, deps);
|
|
19848
|
-
if (!persisted.ok)
|
|
19849
|
-
|
|
19850
|
-
|
|
20078
|
+
if (!persisted.ok) {
|
|
20079
|
+
const rollback = await removeStartedRunArtifacts(
|
|
20080
|
+
{ ...args.contextCreated ? { contextPath: args.contextPath } : {}, runFile },
|
|
20081
|
+
deps
|
|
20082
|
+
);
|
|
20083
|
+
return errorResult3(rollback.ok ? persisted.error : `${persisted.error}; ${rollback.error}`);
|
|
20084
|
+
}
|
|
19851
20085
|
const namespace = verifyRunsDir(runScope2);
|
|
19852
20086
|
if (!namespace.ok) return errorResult3(namespace.error);
|
|
19853
20087
|
const locator = buildRunLocator({
|
|
@@ -19855,52 +20089,69 @@ async function verifyStartCommand(options, deps) {
|
|
|
19855
20089
|
verificationType: options.verificationType,
|
|
19856
20090
|
scopeType: options.scopeType,
|
|
19857
20091
|
scopeIdentity: options.scope,
|
|
19858
|
-
backendIdentity:
|
|
20092
|
+
backendIdentity: args.backendIdentity,
|
|
19859
20093
|
storageNamespace: namespace.value,
|
|
19860
20094
|
runTarget: runFile
|
|
19861
20095
|
});
|
|
19862
20096
|
const report2 = {
|
|
19863
20097
|
runToken,
|
|
19864
|
-
contextDigest,
|
|
19865
|
-
changedScope: changedScope
|
|
19866
|
-
input: { source: options.input, digest: inputDigest
|
|
20098
|
+
contextDigest: args.contextDigest,
|
|
20099
|
+
changedScope: args.changedScope,
|
|
20100
|
+
input: { source: options.input, digest: args.inputDigest },
|
|
19867
20101
|
locator
|
|
19868
20102
|
};
|
|
19869
20103
|
return okResult3(JSON.stringify(report2));
|
|
19870
20104
|
}
|
|
19871
|
-
async function
|
|
19872
|
-
if (options.
|
|
20105
|
+
async function verifyStartCommand(options, deps) {
|
|
20106
|
+
if (!isVerifyVerificationType(options.verificationType)) {
|
|
20107
|
+
return errorResult3(VERIFY_CLI_ERROR.UNSUPPORTED_VERIFICATION_TYPE);
|
|
20108
|
+
}
|
|
20109
|
+
if (options.scopeType !== VERIFY_SCOPE_TYPE.CHANGESET) return errorResult3(VERIFY_SCOPE_ERROR.UNSUPPORTED_SCOPE_TYPE);
|
|
20110
|
+
if (options.input.trim().length === 0) return errorResult3(VERIFY_CLI_ERROR.INPUT_REQUIRED);
|
|
20111
|
+
const scope2 = parseChangesetScope(options.scope);
|
|
20112
|
+
if (!scope2.ok) return errorResult3(scope2.error);
|
|
19873
20113
|
const resolved = await resolveVerifyScope(deps);
|
|
19874
20114
|
if (!resolved.ok) return errorResult3(resolved.error);
|
|
19875
|
-
const
|
|
20115
|
+
const inputContent = await readStartInputContent(options.input, deps);
|
|
20116
|
+
if (!inputContent.ok) return errorResult3(inputContent.error);
|
|
20117
|
+
const inputDigest = digestRunInput(options.input, inputContent.value);
|
|
20118
|
+
if (!inputDigest.ok) return errorResult3(inputDigest.error);
|
|
20119
|
+
const changedScope = await resolveChangedScope(scope2.value, deps);
|
|
20120
|
+
if (!changedScope.ok) return errorResult3(changedScope.error);
|
|
20121
|
+
const context = await verificationContextCreateCommand(
|
|
20122
|
+
{
|
|
20123
|
+
subject: VERIFICATION_CONTEXT_SUBJECT_KIND.CHANGESET,
|
|
20124
|
+
base: scope2.value.base,
|
|
20125
|
+
head: scope2.value.head,
|
|
20126
|
+
predicate: options.verificationType,
|
|
20127
|
+
workflow: options.verificationType
|
|
20128
|
+
},
|
|
20129
|
+
forwardDeps(deps)
|
|
20130
|
+
);
|
|
20131
|
+
if (context.exitCode !== VERIFY_CLI_EXIT_CODE.OK) return errorResult3(context.output);
|
|
20132
|
+
const { digest: contextDigest, contextPath, created: contextCreated } = JSON.parse(context.output);
|
|
20133
|
+
return completeVerifyStartCommand({
|
|
20134
|
+
options,
|
|
20135
|
+
deps,
|
|
19876
20136
|
productDir: resolved.value.productDir,
|
|
19877
20137
|
branchSlug: resolved.value.branchSlug,
|
|
19878
|
-
|
|
19879
|
-
|
|
19880
|
-
|
|
19881
|
-
|
|
19882
|
-
|
|
19883
|
-
|
|
19884
|
-
|
|
19885
|
-
|
|
19886
|
-
|
|
19887
|
-
|
|
19888
|
-
|
|
19889
|
-
|
|
19890
|
-
|
|
19891
|
-
verificationType: options.verificationType,
|
|
19892
|
-
scopeType: options.scopeType,
|
|
19893
|
-
scopeIdentity: options.scope,
|
|
19894
|
-
backendIdentity: resolved.value.backendIdentity,
|
|
19895
|
-
storageNamespace: namespace.value,
|
|
19896
|
-
searchedTarget: path7.value
|
|
19897
|
-
})
|
|
19898
|
-
);
|
|
19899
|
-
}
|
|
20138
|
+
backendIdentity: resolved.value.backendIdentity,
|
|
20139
|
+
changedScope: changedScope.value,
|
|
20140
|
+
inputDigest: inputDigest.value,
|
|
20141
|
+
inputContent: inputContent.value,
|
|
20142
|
+
contextDigest,
|
|
20143
|
+
contextPath,
|
|
20144
|
+
contextCreated
|
|
20145
|
+
});
|
|
20146
|
+
}
|
|
20147
|
+
async function verifyInputCommand(options, deps) {
|
|
20148
|
+
const run = await resolveExistingRun(options, deps);
|
|
20149
|
+
if (!run.ok) return errorResult3(run.error);
|
|
20150
|
+
const record6 = run.value.recordedInput;
|
|
19900
20151
|
const report2 = {
|
|
19901
|
-
source: record6.
|
|
19902
|
-
digest: record6.
|
|
19903
|
-
content: record6.
|
|
20152
|
+
source: record6.source,
|
|
20153
|
+
digest: record6.digest,
|
|
20154
|
+
content: record6.content
|
|
19904
20155
|
};
|
|
19905
20156
|
return okResult3(JSON.stringify(report2));
|
|
19906
20157
|
}
|
|
@@ -19909,12 +20160,36 @@ async function readRunJournalEvents(scope2, deps) {
|
|
|
19909
20160
|
if (read.exitCode !== VERIFY_CLI_EXIT_CODE.OK) return { ok: false, error: read.output };
|
|
19910
20161
|
return { ok: true, value: JSON.parse(read.output) };
|
|
19911
20162
|
}
|
|
20163
|
+
async function readAppendExistingEvents(options, deps, journalScope, backendIdentity, namespace) {
|
|
20164
|
+
const existingEvents = await readRunJournalEvents(journalScope, deps);
|
|
20165
|
+
if (!existingEvents.ok) {
|
|
20166
|
+
if (existingEvents.error === JOURNAL_RUNTIME_ERROR.RUN_NOT_FOUND) {
|
|
20167
|
+
return {
|
|
20168
|
+
ok: false,
|
|
20169
|
+
error: appendRunNotFoundDiagnostic(options, backendIdentity, namespace)
|
|
20170
|
+
};
|
|
20171
|
+
}
|
|
20172
|
+
return { ok: false, error: `${VERIFY_CLI_ERROR.APPEND_FAILED}: ${existingEvents.error}` };
|
|
20173
|
+
}
|
|
20174
|
+
if (findTerminalEvent(existingEvents.value) !== void 0) {
|
|
20175
|
+
return { ok: false, error: VERIFY_CLI_ERROR.RUN_FINISHED };
|
|
20176
|
+
}
|
|
20177
|
+
return existingEvents;
|
|
20178
|
+
}
|
|
19912
20179
|
async function prepareAppend(options, deps) {
|
|
19913
20180
|
if (options.run.trim().length === 0) return { ok: false, error: VERIFY_CLI_ERROR.RUN_REQUIRED };
|
|
20181
|
+
if (!isVerifyVerificationType(options.verificationType)) {
|
|
20182
|
+
return { ok: false, error: VERIFY_CLI_ERROR.UNSUPPORTED_VERIFICATION_TYPE };
|
|
20183
|
+
}
|
|
19914
20184
|
if (options.payload.trim().length === 0) return { ok: false, error: VERIFY_CLI_ERROR.PAYLOAD_REQUIRED };
|
|
19915
20185
|
if (options.idempotencyKey.trim().length === 0) {
|
|
19916
20186
|
return { ok: false, error: VERIFY_CLI_ERROR.IDEMPOTENCY_KEY_REQUIRED };
|
|
19917
20187
|
}
|
|
20188
|
+
if (options.scopeType !== VERIFY_SCOPE_TYPE.CHANGESET) {
|
|
20189
|
+
return { ok: false, error: VERIFY_SCOPE_ERROR.UNSUPPORTED_SCOPE_TYPE };
|
|
20190
|
+
}
|
|
20191
|
+
const scope2 = parseChangesetScope(options.scope);
|
|
20192
|
+
if (!scope2.ok) return scope2;
|
|
19918
20193
|
const readPayload = deps.readPayloadSource;
|
|
19919
20194
|
const binding = deps.journalBinding;
|
|
19920
20195
|
if (readPayload === void 0 || binding === void 0) return { ok: false, error: VERIFY_CLI_ERROR.APPEND_FAILED };
|
|
@@ -19928,25 +20203,53 @@ async function prepareAppend(options, deps) {
|
|
|
19928
20203
|
};
|
|
19929
20204
|
const namespace = verifyRunsDir(runScope2);
|
|
19930
20205
|
if (!namespace.ok) return namespace;
|
|
20206
|
+
const journalScope = {
|
|
20207
|
+
type: options.verificationType,
|
|
20208
|
+
runToken: options.run,
|
|
20209
|
+
branchSlug: resolved.value.branchSlug
|
|
20210
|
+
};
|
|
20211
|
+
const existingEvents = await readAppendExistingEvents(
|
|
20212
|
+
options,
|
|
20213
|
+
deps,
|
|
20214
|
+
journalScope,
|
|
20215
|
+
resolved.value.backendIdentity,
|
|
20216
|
+
namespace.value
|
|
20217
|
+
);
|
|
20218
|
+
if (!existingEvents.ok) return existingEvents;
|
|
19931
20219
|
const inputPath = verifyInputRecordPath(runScope2);
|
|
19932
20220
|
if (!inputPath.ok) return inputPath;
|
|
19933
20221
|
const inputRecord = await readInputRecordAt(inputPath.value, deps);
|
|
19934
20222
|
if (!inputRecord.ok) return inputRecord;
|
|
19935
20223
|
if (inputRecord.value === void 0) {
|
|
19936
|
-
return {
|
|
20224
|
+
return {
|
|
20225
|
+
ok: false,
|
|
20226
|
+
error: appendRunNotFoundDiagnostic(options, resolved.value.backendIdentity, namespace.value, inputPath.value)
|
|
20227
|
+
};
|
|
20228
|
+
}
|
|
20229
|
+
if (!recordedSelectorMatches(inputRecord.value, options)) {
|
|
20230
|
+
return {
|
|
20231
|
+
ok: false,
|
|
20232
|
+
error: appendRunSelectorMismatchDiagnostic(
|
|
20233
|
+
options,
|
|
20234
|
+
resolved.value.backendIdentity,
|
|
20235
|
+
namespace.value,
|
|
20236
|
+
inputPath.value
|
|
20237
|
+
)
|
|
20238
|
+
};
|
|
19937
20239
|
}
|
|
19938
20240
|
return {
|
|
19939
20241
|
ok: true,
|
|
19940
20242
|
value: {
|
|
19941
20243
|
readPayload,
|
|
19942
20244
|
binding,
|
|
19943
|
-
journalScope
|
|
20245
|
+
journalScope,
|
|
19944
20246
|
namespace: namespace.value,
|
|
19945
|
-
backendIdentity: resolved.value.backendIdentity
|
|
20247
|
+
backendIdentity: resolved.value.backendIdentity,
|
|
20248
|
+
existingEvents: existingEvents.value
|
|
19946
20249
|
}
|
|
19947
20250
|
};
|
|
19948
20251
|
}
|
|
19949
|
-
function appendRunNotFoundDiagnostic(options, backendIdentity, namespace) {
|
|
20252
|
+
function appendRunNotFoundDiagnostic(options, backendIdentity, namespace, searchedTarget = namespace) {
|
|
19950
20253
|
return verifyRunNotFoundDiagnostic({
|
|
19951
20254
|
runToken: options.run,
|
|
19952
20255
|
verificationType: options.verificationType,
|
|
@@ -19954,7 +20257,18 @@ function appendRunNotFoundDiagnostic(options, backendIdentity, namespace) {
|
|
|
19954
20257
|
scopeIdentity: options.scope,
|
|
19955
20258
|
backendIdentity,
|
|
19956
20259
|
storageNamespace: namespace,
|
|
19957
|
-
searchedTarget
|
|
20260
|
+
searchedTarget
|
|
20261
|
+
});
|
|
20262
|
+
}
|
|
20263
|
+
function appendRunSelectorMismatchDiagnostic(options, backendIdentity, namespace, searchedTarget) {
|
|
20264
|
+
return verifyRunLocatorDiagnostic(VERIFY_CLI_ERROR.RUN_SELECTOR_MISMATCH, {
|
|
20265
|
+
runToken: options.run,
|
|
20266
|
+
verificationType: options.verificationType,
|
|
20267
|
+
scopeType: options.scopeType,
|
|
20268
|
+
scopeIdentity: options.scope,
|
|
20269
|
+
backendIdentity,
|
|
20270
|
+
storageNamespace: namespace,
|
|
20271
|
+
searchedTarget
|
|
19958
20272
|
});
|
|
19959
20273
|
}
|
|
19960
20274
|
function validateAppendFinding(verb, verificationType, payload) {
|
|
@@ -19970,16 +20284,9 @@ function appendEventType(verb) {
|
|
|
19970
20284
|
async function verifyAppend(options, deps, verb) {
|
|
19971
20285
|
const prepared = await prepareAppend(options, deps);
|
|
19972
20286
|
if (!prepared.ok) return errorResult3(prepared.error);
|
|
19973
|
-
const { readPayload, binding, journalScope,
|
|
20287
|
+
const { readPayload, binding, journalScope, existingEvents } = prepared.value;
|
|
19974
20288
|
const eventType = appendEventType(verb);
|
|
19975
|
-
const
|
|
19976
|
-
if (!before.ok) {
|
|
19977
|
-
if (before.error === JOURNAL_RUNTIME_ERROR.RUN_NOT_FOUND) {
|
|
19978
|
-
return errorResult3(appendRunNotFoundDiagnostic(options, backendIdentity, namespace));
|
|
19979
|
-
}
|
|
19980
|
-
return errorResult3(`${VERIFY_CLI_ERROR.APPEND_FAILED}: ${before.error}`);
|
|
19981
|
-
}
|
|
19982
|
-
const existing = findAppendedSequence(before.value, options.idempotencyKey, eventType);
|
|
20289
|
+
const existing = findAppendedSequence(existingEvents, options.idempotencyKey, eventType);
|
|
19983
20290
|
if (existing !== void 0) {
|
|
19984
20291
|
const report3 = { sequence: existing, idempotent: true };
|
|
19985
20292
|
return okResult3(JSON.stringify(report3));
|
|
@@ -20017,24 +20324,270 @@ async function verifyAppendScopeCommand(options, deps) {
|
|
|
20017
20324
|
async function verifyAppendFindingCommand(options, deps) {
|
|
20018
20325
|
return verifyAppend(options, deps, VERIFY_VERB.APPEND_FINDING);
|
|
20019
20326
|
}
|
|
20327
|
+
function existingRunNotFound(run, options) {
|
|
20328
|
+
return verifyRunNotFoundDiagnostic({
|
|
20329
|
+
runToken: run.runToken,
|
|
20330
|
+
verificationType: options.verificationType,
|
|
20331
|
+
scopeType: options.scopeType,
|
|
20332
|
+
scopeIdentity: options.scope,
|
|
20333
|
+
backendIdentity: run.backendIdentity,
|
|
20334
|
+
storageNamespace: run.namespace,
|
|
20335
|
+
searchedTarget: run.inputRecordPath
|
|
20336
|
+
});
|
|
20337
|
+
}
|
|
20338
|
+
function existingRunSelectorMismatch(run, options) {
|
|
20339
|
+
return verifyRunLocatorDiagnostic(VERIFY_CLI_ERROR.RUN_SELECTOR_MISMATCH, {
|
|
20340
|
+
runToken: run.runToken,
|
|
20341
|
+
verificationType: options.verificationType,
|
|
20342
|
+
scopeType: options.scopeType,
|
|
20343
|
+
scopeIdentity: options.scope,
|
|
20344
|
+
backendIdentity: run.backendIdentity,
|
|
20345
|
+
storageNamespace: run.namespace,
|
|
20346
|
+
searchedTarget: run.inputRecordPath
|
|
20347
|
+
});
|
|
20348
|
+
}
|
|
20349
|
+
function recordedSelectorMatches(record6, options) {
|
|
20350
|
+
return record6.scopeType === options.scopeType && record6.scopeIdentity === options.scope;
|
|
20351
|
+
}
|
|
20352
|
+
async function readExistingRecordedInput(run, deps) {
|
|
20353
|
+
return readInputRecordAt(run.inputRecordPath, deps);
|
|
20354
|
+
}
|
|
20355
|
+
async function resolveExistingRunAddress(options, deps) {
|
|
20356
|
+
if (!isVerifyVerificationType(options.verificationType)) {
|
|
20357
|
+
return { ok: false, error: VERIFY_CLI_ERROR.UNSUPPORTED_VERIFICATION_TYPE };
|
|
20358
|
+
}
|
|
20359
|
+
if (options.scopeType !== VERIFY_SCOPE_TYPE.CHANGESET) {
|
|
20360
|
+
return { ok: false, error: VERIFY_SCOPE_ERROR.UNSUPPORTED_SCOPE_TYPE };
|
|
20361
|
+
}
|
|
20362
|
+
const scope2 = parseChangesetScope(options.scope);
|
|
20363
|
+
if (!scope2.ok) return scope2;
|
|
20364
|
+
if (options.run.trim().length === 0) return { ok: false, error: VERIFY_CLI_ERROR.RUN_REQUIRED };
|
|
20365
|
+
const resolved = await resolveVerifyScope(deps);
|
|
20366
|
+
if (!resolved.ok) return resolved;
|
|
20367
|
+
const runScope2 = {
|
|
20368
|
+
productDir: resolved.value.productDir,
|
|
20369
|
+
branchSlug: resolved.value.branchSlug,
|
|
20370
|
+
type: options.verificationType,
|
|
20371
|
+
runToken: options.run
|
|
20372
|
+
};
|
|
20373
|
+
const namespace = verifyRunsDir(runScope2);
|
|
20374
|
+
if (!namespace.ok) return namespace;
|
|
20375
|
+
const inputPath = verifyInputRecordPath(runScope2);
|
|
20376
|
+
if (!inputPath.ok) return inputPath;
|
|
20377
|
+
return {
|
|
20378
|
+
ok: true,
|
|
20379
|
+
value: {
|
|
20380
|
+
productDir: resolved.value.productDir,
|
|
20381
|
+
runToken: options.run,
|
|
20382
|
+
journalScope: { type: options.verificationType, runToken: options.run, branchSlug: resolved.value.branchSlug },
|
|
20383
|
+
namespace: namespace.value,
|
|
20384
|
+
backendIdentity: resolved.value.backendIdentity,
|
|
20385
|
+
inputRecordPath: inputPath.value
|
|
20386
|
+
}
|
|
20387
|
+
};
|
|
20388
|
+
}
|
|
20389
|
+
async function resolveExistingRun(options, deps) {
|
|
20390
|
+
const address = await resolveExistingRunAddress(options, deps);
|
|
20391
|
+
if (!address.ok) return address;
|
|
20392
|
+
const inputRecord = await readExistingRecordedInput(address.value, deps);
|
|
20393
|
+
if (!inputRecord.ok) return inputRecord;
|
|
20394
|
+
if (inputRecord.value === void 0) {
|
|
20395
|
+
return { ok: false, error: existingRunNotFound(address.value, options) };
|
|
20396
|
+
}
|
|
20397
|
+
if (!recordedSelectorMatches(inputRecord.value, options)) {
|
|
20398
|
+
return { ok: false, error: existingRunSelectorMismatch(address.value, options) };
|
|
20399
|
+
}
|
|
20400
|
+
const run = { ...address.value, recordedInput: inputRecord.value };
|
|
20401
|
+
return { ok: true, value: run };
|
|
20402
|
+
}
|
|
20403
|
+
function isRecordedInputReadFailure(error) {
|
|
20404
|
+
return error.startsWith(VERIFY_CLI_ERROR.INPUT_READ_FAILED);
|
|
20405
|
+
}
|
|
20406
|
+
async function readRecordedInputForProjection(run, options, events, deps) {
|
|
20407
|
+
const terminal = findTerminalEvent(events);
|
|
20408
|
+
const inputRecord = await readExistingRecordedInput(run, deps);
|
|
20409
|
+
if (!inputRecord.ok) {
|
|
20410
|
+
if (terminal !== void 0 && isRecordedInputReadFailure(inputRecord.error)) {
|
|
20411
|
+
return { ok: true, value: void 0 };
|
|
20412
|
+
}
|
|
20413
|
+
return inputRecord;
|
|
20414
|
+
}
|
|
20415
|
+
if (inputRecord.value === void 0) return { ok: true, value: void 0 };
|
|
20416
|
+
if (!recordedSelectorMatches(inputRecord.value, options)) {
|
|
20417
|
+
return { ok: false, error: existingRunSelectorMismatch(run, options) };
|
|
20418
|
+
}
|
|
20419
|
+
return { ok: true, value: inputRecord.value };
|
|
20420
|
+
}
|
|
20421
|
+
function verifyFinishReport(runToken, projection) {
|
|
20422
|
+
return {
|
|
20423
|
+
runToken,
|
|
20424
|
+
...projection.terminalStatus === void 0 ? {} : { terminalStatus: projection.terminalStatus },
|
|
20425
|
+
sealed: projection.sealed,
|
|
20426
|
+
findingCount: projection.findingCount,
|
|
20427
|
+
lastSequence: projection.lastSequence
|
|
20428
|
+
};
|
|
20429
|
+
}
|
|
20430
|
+
async function isJournalPhysicallySealed(run, deps) {
|
|
20431
|
+
return isJournalRunSealed(
|
|
20432
|
+
{ ...run.journalScope, productDir: run.productDir },
|
|
20433
|
+
{ ...deps.fs === void 0 ? {} : { fs: deps.fs } }
|
|
20434
|
+
);
|
|
20435
|
+
}
|
|
20436
|
+
async function sealExistingRun(run, deps) {
|
|
20437
|
+
const sealed = await journalSealCommand(run.journalScope, forwardDeps(deps));
|
|
20438
|
+
if (sealed.exitCode !== VERIFY_CLI_EXIT_CODE.OK) {
|
|
20439
|
+
return errorResult3(`${VERIFY_CLI_ERROR.SEAL_FAILED}: ${sealed.output}`);
|
|
20440
|
+
}
|
|
20441
|
+
return void 0;
|
|
20442
|
+
}
|
|
20443
|
+
function finishReadFailure(run, options, error) {
|
|
20444
|
+
if (error === JOURNAL_RUNTIME_ERROR.RUN_NOT_FOUND) {
|
|
20445
|
+
return errorResult3(existingRunNotFound(run, options));
|
|
20446
|
+
}
|
|
20447
|
+
return errorResult3(`${VERIFY_CLI_ERROR.FINISH_FAILED}: ${error}`);
|
|
20448
|
+
}
|
|
20449
|
+
async function finishProjectionResult(run, deps) {
|
|
20450
|
+
const events = await readRunJournalEvents(run.journalScope, deps);
|
|
20451
|
+
if (!events.ok) return errorResult3(`${VERIFY_CLI_ERROR.FINISH_FAILED}: ${events.error}`);
|
|
20452
|
+
return okResult3(JSON.stringify(verifyFinishReport(run.runToken, projectVerifyRun(events.value))));
|
|
20453
|
+
}
|
|
20454
|
+
async function retrySealForTerminalRun(run, deps) {
|
|
20455
|
+
const physicallySealed = await isJournalPhysicallySealed(run, deps);
|
|
20456
|
+
if (!physicallySealed.ok) return void 0;
|
|
20457
|
+
if (physicallySealed.value) return void 0;
|
|
20458
|
+
return sealExistingRun(run, deps);
|
|
20459
|
+
}
|
|
20460
|
+
async function verifyFinishCommand(options, deps) {
|
|
20461
|
+
if (options.terminalStatus.trim().length === 0) return errorResult3(VERIFY_CLI_ERROR.TERMINAL_STATUS_REQUIRED);
|
|
20462
|
+
if (!isVerifyTerminalStatus(options.terminalStatus)) return errorResult3(VERIFY_CLI_ERROR.TERMINAL_STATUS_INVALID);
|
|
20463
|
+
const run = await resolveExistingRunAddress(options, deps);
|
|
20464
|
+
if (!run.ok) return errorResult3(run.error);
|
|
20465
|
+
const before = await readRunJournalEvents(run.value.journalScope, deps);
|
|
20466
|
+
if (!before.ok) {
|
|
20467
|
+
return finishReadFailure(run.value, options, before.error);
|
|
20468
|
+
}
|
|
20469
|
+
const inputRecord = await readRecordedInputForProjection(run.value, options, before.value, deps);
|
|
20470
|
+
if (!inputRecord.ok) return errorResult3(inputRecord.error);
|
|
20471
|
+
if (findTerminalEvent(before.value) !== void 0) {
|
|
20472
|
+
const retrySeal = await retrySealForTerminalRun(run.value, deps);
|
|
20473
|
+
return retrySeal ?? finishProjectionResult(run.value, deps);
|
|
20474
|
+
}
|
|
20475
|
+
if (inputRecord.value === void 0) {
|
|
20476
|
+
return errorResult3(existingRunNotFound(run.value, options));
|
|
20477
|
+
}
|
|
20478
|
+
const binding = deps.journalBinding;
|
|
20479
|
+
if (binding === void 0) return errorResult3(VERIFY_CLI_ERROR.FINISH_FAILED);
|
|
20480
|
+
const event = buildTerminalEvent({
|
|
20481
|
+
runToken: run.value.runToken,
|
|
20482
|
+
terminalStatus: options.terminalStatus,
|
|
20483
|
+
at: deps.now?.() ?? /* @__PURE__ */ new Date()
|
|
20484
|
+
});
|
|
20485
|
+
const appended = await journalAppendCommand(run.value.journalScope, event, binding, forwardDeps(deps));
|
|
20486
|
+
if (appended.exitCode !== VERIFY_CLI_EXIT_CODE.OK) {
|
|
20487
|
+
return errorResult3(`${VERIFY_CLI_ERROR.FINISH_FAILED}: ${appended.output}`);
|
|
20488
|
+
}
|
|
20489
|
+
const sealResult = await sealExistingRun(run.value, deps);
|
|
20490
|
+
if (sealResult !== void 0) return sealResult;
|
|
20491
|
+
return finishProjectionResult(run.value, deps);
|
|
20492
|
+
}
|
|
20493
|
+
async function verifyStatusCommand(options, deps) {
|
|
20494
|
+
const run = await resolveExistingRunAddress(options, deps);
|
|
20495
|
+
if (!run.ok) return errorResult3(run.error);
|
|
20496
|
+
const events = await readRunJournalEvents(run.value.journalScope, deps);
|
|
20497
|
+
if (!events.ok) {
|
|
20498
|
+
if (events.error === JOURNAL_RUNTIME_ERROR.RUN_NOT_FOUND) {
|
|
20499
|
+
return errorResult3(existingRunNotFound(run.value, options));
|
|
20500
|
+
}
|
|
20501
|
+
return errorResult3(`${VERIFY_CLI_ERROR.STATUS_FAILED}: ${events.error}`);
|
|
20502
|
+
}
|
|
20503
|
+
const inputRecord = await readRecordedInputForProjection(run.value, options, events.value, deps);
|
|
20504
|
+
if (!inputRecord.ok) return errorResult3(inputRecord.error);
|
|
20505
|
+
if (inputRecord.value === void 0 && findTerminalEvent(events.value) === void 0) {
|
|
20506
|
+
return errorResult3(existingRunNotFound(run.value, options));
|
|
20507
|
+
}
|
|
20508
|
+
const projection = projectVerifyRun(events.value);
|
|
20509
|
+
const report2 = {
|
|
20510
|
+
runToken: run.value.runToken,
|
|
20511
|
+
verificationType: options.verificationType,
|
|
20512
|
+
scopeType: options.scopeType,
|
|
20513
|
+
sealed: projection.sealed,
|
|
20514
|
+
lastSequence: projection.lastSequence,
|
|
20515
|
+
...projection.terminalStatus === void 0 ? {} : { terminalStatus: projection.terminalStatus },
|
|
20516
|
+
findingCount: projection.findingCount,
|
|
20517
|
+
nextActions: projection.nextActions
|
|
20518
|
+
};
|
|
20519
|
+
return okResult3(JSON.stringify(report2));
|
|
20520
|
+
}
|
|
20521
|
+
async function verifyRenderCommand(options, deps) {
|
|
20522
|
+
const run = await resolveExistingRunAddress(options, deps);
|
|
20523
|
+
if (!run.ok) return errorResult3(run.error);
|
|
20524
|
+
const events = await readRunJournalEvents(run.value.journalScope, deps);
|
|
20525
|
+
if (!events.ok) {
|
|
20526
|
+
if (events.error === JOURNAL_RUNTIME_ERROR.RUN_NOT_FOUND) {
|
|
20527
|
+
return errorResult3(existingRunNotFound(run.value, options));
|
|
20528
|
+
}
|
|
20529
|
+
return errorResult3(`${VERIFY_CLI_ERROR.RENDER_FAILED}: ${events.error}`);
|
|
20530
|
+
}
|
|
20531
|
+
const inputRecord = await readRecordedInputForProjection(run.value, options, events.value, deps);
|
|
20532
|
+
if (!inputRecord.ok) return errorResult3(inputRecord.error);
|
|
20533
|
+
if (inputRecord.value === void 0 && findTerminalEvent(events.value) === void 0) {
|
|
20534
|
+
return errorResult3(existingRunNotFound(run.value, options));
|
|
20535
|
+
}
|
|
20536
|
+
const projection = projectVerifyRun(events.value);
|
|
20537
|
+
const report2 = {
|
|
20538
|
+
runToken: run.value.runToken,
|
|
20539
|
+
findingCount: projection.findingCount,
|
|
20540
|
+
sealed: projection.sealed,
|
|
20541
|
+
...projection.terminalStatus === void 0 ? {} : { terminalStatus: projection.terminalStatus },
|
|
20542
|
+
events: events.value
|
|
20543
|
+
};
|
|
20544
|
+
return okResult3(JSON.stringify(report2));
|
|
20545
|
+
}
|
|
20020
20546
|
|
|
20021
20547
|
// src/interfaces/cli/verify.ts
|
|
20548
|
+
var VERIFICATION_RUN_CLI_SURFACE = {
|
|
20549
|
+
addCommandName: "add",
|
|
20550
|
+
findingResourceCommandName: "finding",
|
|
20551
|
+
forbiddenRootCommandName: "verify",
|
|
20552
|
+
forbiddenRunHelpTerms: ["Append", "append"],
|
|
20553
|
+
forbiddenRunCommandNames: ["journal", "event", "append-scope", "append-finding"],
|
|
20554
|
+
rootCommandName: "verification",
|
|
20555
|
+
runCommandName: "run",
|
|
20556
|
+
scopeResourceCommandName: "scope"
|
|
20557
|
+
};
|
|
20022
20558
|
var VERIFY_CLI = {
|
|
20023
|
-
|
|
20559
|
+
addCommandName: VERIFICATION_RUN_CLI_SURFACE.addCommandName,
|
|
20560
|
+
commandName: VERIFICATION_RUN_CLI_SURFACE.rootCommandName,
|
|
20024
20561
|
description: "Record and replay a typed verification run",
|
|
20025
20562
|
startCommandName: VERIFY_VERB.START,
|
|
20026
20563
|
inputCommandName: VERIFY_VERB.INPUT,
|
|
20027
|
-
|
|
20028
|
-
|
|
20564
|
+
findingCommandName: VERIFICATION_RUN_CLI_SURFACE.findingResourceCommandName,
|
|
20565
|
+
runCommandName: VERIFICATION_RUN_CLI_SURFACE.runCommandName,
|
|
20566
|
+
scopeCommandName: VERIFICATION_RUN_CLI_SURFACE.scopeResourceCommandName,
|
|
20567
|
+
finishCommandName: VERIFY_VERB.FINISH,
|
|
20568
|
+
statusCommandName: VERIFY_VERB.STATUS,
|
|
20569
|
+
renderCommandName: VERIFY_VERB.RENDER,
|
|
20029
20570
|
verificationTypeOption: "--verification-type <type>",
|
|
20030
20571
|
scopeTypeOption: "--scope-type <scope-type>",
|
|
20031
20572
|
scopeOption: "--scope <base>..<head>",
|
|
20032
20573
|
inputOption: "--input <input-source>",
|
|
20033
20574
|
runOption: "--run <token>",
|
|
20034
20575
|
payloadOption: "--payload <payload-source>",
|
|
20035
|
-
|
|
20576
|
+
payloadOptionDescription: "Evidence payload source; stdin or a file path",
|
|
20577
|
+
idempotencyKeyOption: "--idempotency-key <key>",
|
|
20578
|
+
idempotencyKeyOptionDescription: "Caller-supplied idempotency key for the evidence add",
|
|
20579
|
+
terminalStatusOption: "--terminal-status <status>"
|
|
20036
20580
|
};
|
|
20037
20581
|
var CLI_SOURCE_ENCODING = "utf8";
|
|
20582
|
+
var DEFAULT_VERIFY_CLI_HANDLERS = {
|
|
20583
|
+
appendFinding: verifyAppendFindingCommand,
|
|
20584
|
+
appendScope: verifyAppendScopeCommand,
|
|
20585
|
+
finish: verifyFinishCommand,
|
|
20586
|
+
input: verifyInputCommand,
|
|
20587
|
+
render: verifyRenderCommand,
|
|
20588
|
+
start: verifyStartCommand,
|
|
20589
|
+
status: verifyStatusCommand
|
|
20590
|
+
};
|
|
20038
20591
|
async function readStdinText() {
|
|
20039
20592
|
const chunks = [];
|
|
20040
20593
|
for await (const chunk of process.stdin) {
|
|
@@ -20049,30 +20602,43 @@ async function readCliSource(source) {
|
|
|
20049
20602
|
var verifyDomain = {
|
|
20050
20603
|
name: VERIFY_CLI.commandName,
|
|
20051
20604
|
description: VERIFY_CLI.description,
|
|
20052
|
-
register: (program, invocation) =>
|
|
20053
|
-
|
|
20054
|
-
|
|
20055
|
-
|
|
20056
|
-
|
|
20057
|
-
|
|
20058
|
-
|
|
20059
|
-
|
|
20060
|
-
|
|
20061
|
-
|
|
20062
|
-
|
|
20063
|
-
|
|
20064
|
-
|
|
20065
|
-
|
|
20066
|
-
|
|
20067
|
-
|
|
20068
|
-
|
|
20069
|
-
|
|
20070
|
-
|
|
20071
|
-
|
|
20072
|
-
|
|
20073
|
-
|
|
20074
|
-
}
|
|
20075
|
-
|
|
20605
|
+
register: (program, invocation) => registerVerifyCommands(program, invocation)
|
|
20606
|
+
};
|
|
20607
|
+
function registerVerifyCommands(program, invocation, handlers = DEFAULT_VERIFY_CLI_HANDLERS) {
|
|
20608
|
+
const deps = () => ({
|
|
20609
|
+
cwd: invocation.resolveEffectiveInvocationDir(),
|
|
20610
|
+
readInputSource: readCliSource,
|
|
20611
|
+
readPayloadSource: readCliSource,
|
|
20612
|
+
// The append verbs write a single structured JSON result to stdout, so the run's event
|
|
20613
|
+
// stream goes to stderr under the local backend rather than sharing the result channel.
|
|
20614
|
+
journalBinding: createJournalStreamBinding(invocation.io, stderrStreamSink(invocation.io))
|
|
20615
|
+
});
|
|
20616
|
+
const command = program.command(VERIFY_CLI.commandName).description(VERIFY_CLI.description);
|
|
20617
|
+
const runCommand = command.command(VERIFY_CLI.runCommandName).description("Manage a typed verification run lifecycle");
|
|
20618
|
+
runCommand.command(VERIFY_CLI.startCommandName).description("Start a changeset-scoped verification run and report its run locator").requiredOption(VERIFY_CLI.verificationTypeOption, "Verification type recorded for the run").requiredOption(VERIFY_CLI.scopeTypeOption, "Scope type; changeset").requiredOption(VERIFY_CLI.scopeOption, "Changeset scope as <base>..<head>").requiredOption(VERIFY_CLI.inputOption, "Verification input source; stdin or a file path").action(async (options) => {
|
|
20619
|
+
reportCliResult(await handlers.start(options, deps()), invocation.io);
|
|
20620
|
+
});
|
|
20621
|
+
runCommand.command(VERIFY_CLI.inputCommandName).description("Replay the verification input recorded at start").requiredOption(VERIFY_CLI.verificationTypeOption, "Verification type recorded for the run").requiredOption(VERIFY_CLI.scopeTypeOption, "Scope type; changeset").requiredOption(VERIFY_CLI.scopeOption, "Changeset scope as <base>..<head>").requiredOption(VERIFY_CLI.runOption, "Run token reported by start").action(async (options) => {
|
|
20622
|
+
reportCliResult(await handlers.input(options, deps()), invocation.io);
|
|
20623
|
+
});
|
|
20624
|
+
const scopeCommand = runCommand.command(VERIFY_CLI.scopeCommandName).description("Manage inspected scope evidence for a started verification run");
|
|
20625
|
+
scopeCommand.command(VERIFY_CLI.addCommandName).description("Record the inspected scope for a started run").requiredOption(VERIFY_CLI.verificationTypeOption, "Verification type recorded for the run").requiredOption(VERIFY_CLI.scopeTypeOption, "Scope type; changeset").requiredOption(VERIFY_CLI.scopeOption, "Changeset scope as <base>..<head>").requiredOption(VERIFY_CLI.runOption, "Run token reported by start").requiredOption(VERIFY_CLI.payloadOption, VERIFY_CLI.payloadOptionDescription).requiredOption(VERIFY_CLI.idempotencyKeyOption, VERIFY_CLI.idempotencyKeyOptionDescription).action(async (options) => {
|
|
20626
|
+
reportCliResult(await handlers.appendScope(options, deps()), invocation.io);
|
|
20627
|
+
});
|
|
20628
|
+
const findingCommand = runCommand.command(VERIFY_CLI.findingCommandName).description("Manage finding evidence for a started verification run");
|
|
20629
|
+
findingCommand.command(VERIFY_CLI.addCommandName).description("Record a validated verification finding for a started run").requiredOption(VERIFY_CLI.verificationTypeOption, "Verification type recorded for the run").requiredOption(VERIFY_CLI.scopeTypeOption, "Scope type; changeset").requiredOption(VERIFY_CLI.scopeOption, "Changeset scope as <base>..<head>").requiredOption(VERIFY_CLI.runOption, "Run token reported by start").requiredOption(VERIFY_CLI.payloadOption, VERIFY_CLI.payloadOptionDescription).requiredOption(VERIFY_CLI.idempotencyKeyOption, VERIFY_CLI.idempotencyKeyOptionDescription).action(async (options) => {
|
|
20630
|
+
reportCliResult(await handlers.appendFinding(options, deps()), invocation.io);
|
|
20631
|
+
});
|
|
20632
|
+
runCommand.command(VERIFY_CLI.finishCommandName).description("Record terminal completion, seal the run journal, and report its terminal projection").requiredOption(VERIFY_CLI.verificationTypeOption, "Verification type recorded for the run").requiredOption(VERIFY_CLI.scopeTypeOption, "Scope type; changeset").requiredOption(VERIFY_CLI.scopeOption, "Changeset scope as <base>..<head>").requiredOption(VERIFY_CLI.runOption, "Run token reported by start").requiredOption(VERIFY_CLI.terminalStatusOption, "Terminal status recorded before sealing").action(async (options) => {
|
|
20633
|
+
reportCliResult(await handlers.finish(options, deps()), invocation.io);
|
|
20634
|
+
});
|
|
20635
|
+
runCommand.command(VERIFY_CLI.statusCommandName).description("Report the run's resumable status projected from its journal history").requiredOption(VERIFY_CLI.verificationTypeOption, "Verification type recorded for the run").requiredOption(VERIFY_CLI.scopeTypeOption, "Scope type; changeset").requiredOption(VERIFY_CLI.scopeOption, "Changeset scope as <base>..<head>").requiredOption(VERIFY_CLI.runOption, "Run token reported by start").action(async (options) => {
|
|
20636
|
+
reportCliResult(await handlers.status(options, deps()), invocation.io);
|
|
20637
|
+
});
|
|
20638
|
+
runCommand.command(VERIFY_CLI.renderCommandName).description("Render the run's journal projection with its authoritative finding count").requiredOption(VERIFY_CLI.verificationTypeOption, "Verification type recorded for the run").requiredOption(VERIFY_CLI.scopeTypeOption, "Scope type; changeset").requiredOption(VERIFY_CLI.scopeOption, "Changeset scope as <base>..<head>").requiredOption(VERIFY_CLI.runOption, "Run token reported by start").action(async (options) => {
|
|
20639
|
+
reportCliResult(await handlers.render(options, deps()), invocation.io);
|
|
20640
|
+
});
|
|
20641
|
+
}
|
|
20076
20642
|
|
|
20077
20643
|
// src/interfaces/cli/worktree.ts
|
|
20078
20644
|
import { randomBytes as nodeRandomBytes4 } from "crypto";
|