@outcomeeng/spx 0.6.12 → 0.6.13
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 +663 -96
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -126,6 +126,7 @@ var AGENT_RESUME_LIMITS = {
|
|
|
126
126
|
RECENT_DAYS: 7,
|
|
127
127
|
PER_AGENT_DISPLAYED_CANDIDATES: 5,
|
|
128
128
|
METADATA_HEAD_BYTES: 131072,
|
|
129
|
+
ACTIVITY_TAIL_BYTES: 131072,
|
|
129
130
|
HOURS_PER_DAY: 24,
|
|
130
131
|
MINUTES_PER_HOUR: 60,
|
|
131
132
|
SECONDS_PER_MINUTE: 60,
|
|
@@ -196,6 +197,10 @@ var FIRST_PICKER_INDEX = 0;
|
|
|
196
197
|
var PICKER_MOVE_UP_DELTA = -1;
|
|
197
198
|
var PICKER_MOVE_DOWN_DELTA = 1;
|
|
198
199
|
var PICKER_QUIT_INPUT = "q";
|
|
200
|
+
var AGENT_RESUME_TIE_ORDER = {
|
|
201
|
+
[AGENT_SESSION_KIND.CODEX]: 0,
|
|
202
|
+
[AGENT_SESSION_KIND.CLAUDE_CODE]: 1
|
|
203
|
+
};
|
|
199
204
|
var AgentResumeModeError = class extends Error {
|
|
200
205
|
constructor(selectedModes) {
|
|
201
206
|
super(`${AGENT_RESUME_TEXT.MODE_CONFLICT}: ${selectedModes.join(", ")}`);
|
|
@@ -314,7 +319,7 @@ function renderAgentResumeList(candidates) {
|
|
|
314
319
|
return AGENT_RESUME_TEXT.NO_MATCHES;
|
|
315
320
|
}
|
|
316
321
|
return candidates.map((candidate) => {
|
|
317
|
-
const updatedAt = candidate.
|
|
322
|
+
const updatedAt = candidate.lastActivityAtMs === null ? "unknown" : new Date(candidate.lastActivityAtMs).toISOString();
|
|
318
323
|
return `${updatedAt} ${AGENT_SESSION_LABEL[candidate.agent]} ${candidate.sessionId} ${candidate.cwd}`;
|
|
319
324
|
}).join("\n");
|
|
320
325
|
}
|
|
@@ -340,32 +345,41 @@ async function claudeTranscriptFiles(root, fs8, dirAccepts) {
|
|
|
340
345
|
return perDir.flat();
|
|
341
346
|
}
|
|
342
347
|
async function collectAgentCandidates(agent, files, fs8, cap, match, parseHead) {
|
|
343
|
-
const
|
|
344
|
-
const candidates = [];
|
|
345
|
-
for (const file of files) {
|
|
346
|
-
if (candidates.length >= cap) {
|
|
347
|
-
break;
|
|
348
|
-
}
|
|
348
|
+
const candidates = await mapWithConcurrency(files, AGENT_RESUME_LIMITS.READ_CONCURRENCY, async (file) => {
|
|
349
349
|
const head = await fs8.readHead(file.path, AGENT_RESUME_LIMITS.METADATA_HEAD_BYTES).catch(() => null);
|
|
350
350
|
if (head === null) {
|
|
351
|
-
|
|
351
|
+
return null;
|
|
352
352
|
}
|
|
353
353
|
const core = parseHead(head);
|
|
354
|
-
if (core === null || !core.interactive || !match(core)
|
|
355
|
-
|
|
354
|
+
if (core === null || !core.interactive || !match(core)) {
|
|
355
|
+
return null;
|
|
356
356
|
}
|
|
357
|
-
|
|
358
|
-
|
|
357
|
+
const tail = await fs8.readTail(file.path, AGENT_RESUME_LIMITS.ACTIVITY_TAIL_BYTES).catch(() => null);
|
|
358
|
+
if (tail === null) {
|
|
359
|
+
return null;
|
|
360
|
+
}
|
|
361
|
+
return {
|
|
359
362
|
agent,
|
|
360
363
|
sessionId: core.sessionId,
|
|
361
364
|
cwd: core.cwd,
|
|
362
365
|
sourcePath: file.path,
|
|
363
366
|
modifiedAtMs: file.modifiedAtMs,
|
|
367
|
+
lastActivityAtMs: latestTranscriptTimestampMs(tail),
|
|
364
368
|
updatedAt: core.updatedAt,
|
|
365
369
|
branch: core.branch
|
|
366
|
-
}
|
|
370
|
+
};
|
|
371
|
+
});
|
|
372
|
+
const bySessionId = /* @__PURE__ */ new Map();
|
|
373
|
+
for (const candidate of candidates) {
|
|
374
|
+
if (candidate === null) {
|
|
375
|
+
continue;
|
|
376
|
+
}
|
|
377
|
+
const existing = bySessionId.get(candidate.sessionId);
|
|
378
|
+
if (existing === void 0 || compareCandidates(candidate, existing) < 0) {
|
|
379
|
+
bySessionId.set(candidate.sessionId, candidate);
|
|
380
|
+
}
|
|
367
381
|
}
|
|
368
|
-
return
|
|
382
|
+
return [...bySessionId.values()].sort(compareCandidates).slice(0, cap);
|
|
369
383
|
}
|
|
370
384
|
async function collectJsonlFiles(root, fs8) {
|
|
371
385
|
const entries = await fs8.readDir(root).catch(() => []);
|
|
@@ -475,6 +489,27 @@ function parseJsonObject(line) {
|
|
|
475
489
|
return null;
|
|
476
490
|
}
|
|
477
491
|
}
|
|
492
|
+
function latestTranscriptTimestampMs(transcriptSlice) {
|
|
493
|
+
let latest = null;
|
|
494
|
+
for (const line of transcriptSlice.split("\n")) {
|
|
495
|
+
const row = parseJsonObject(line);
|
|
496
|
+
if (row === null) {
|
|
497
|
+
continue;
|
|
498
|
+
}
|
|
499
|
+
const timestampMs = parseTimestampMs(firstString(row, [[AGENT_SESSION_JSON_FIELDS.TIMESTAMP]]));
|
|
500
|
+
if (timestampMs !== null && (latest === null || timestampMs > latest)) {
|
|
501
|
+
latest = timestampMs;
|
|
502
|
+
}
|
|
503
|
+
}
|
|
504
|
+
return latest;
|
|
505
|
+
}
|
|
506
|
+
function parseTimestampMs(timestamp) {
|
|
507
|
+
if (timestamp === null) {
|
|
508
|
+
return null;
|
|
509
|
+
}
|
|
510
|
+
const timestampMs = Date.parse(timestamp);
|
|
511
|
+
return Number.isNaN(timestampMs) ? null : timestampMs;
|
|
512
|
+
}
|
|
478
513
|
function firstString(row, paths) {
|
|
479
514
|
for (const path7 of paths) {
|
|
480
515
|
const value = valueAtPath(row, path7);
|
|
@@ -498,11 +533,30 @@ function isRecord(value) {
|
|
|
498
533
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
499
534
|
}
|
|
500
535
|
function compareCandidates(left, right) {
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
536
|
+
if (left.lastActivityAtMs !== null && right.lastActivityAtMs !== null) {
|
|
537
|
+
const activityDiff = right.lastActivityAtMs - left.lastActivityAtMs;
|
|
538
|
+
if (activityDiff !== 0) {
|
|
539
|
+
return activityDiff;
|
|
540
|
+
}
|
|
541
|
+
} else if (left.lastActivityAtMs !== null) {
|
|
542
|
+
return -1;
|
|
543
|
+
} else if (right.lastActivityAtMs !== null) {
|
|
544
|
+
return 1;
|
|
504
545
|
}
|
|
505
|
-
|
|
546
|
+
const agentDiff = AGENT_RESUME_TIE_ORDER[left.agent] - AGENT_RESUME_TIE_ORDER[right.agent];
|
|
547
|
+
if (agentDiff !== 0) {
|
|
548
|
+
return agentDiff;
|
|
549
|
+
}
|
|
550
|
+
return compareCodeUnits(`${left.sessionId}:${left.sourcePath}`, `${right.sessionId}:${right.sourcePath}`);
|
|
551
|
+
}
|
|
552
|
+
function compareCodeUnits(left, right) {
|
|
553
|
+
if (left < right) {
|
|
554
|
+
return -1;
|
|
555
|
+
}
|
|
556
|
+
if (left > right) {
|
|
557
|
+
return 1;
|
|
558
|
+
}
|
|
559
|
+
return 0;
|
|
506
560
|
}
|
|
507
561
|
function isPathInsideOrEqual(parent, child) {
|
|
508
562
|
const rel = relative(resolve3(parent), resolve3(child));
|
|
@@ -1094,6 +1148,19 @@ var nodeAgentSessionFileSystem = {
|
|
|
1094
1148
|
await handle.close();
|
|
1095
1149
|
}
|
|
1096
1150
|
},
|
|
1151
|
+
async readTail(path7, maxBytes) {
|
|
1152
|
+
const fileStat = await stat(path7);
|
|
1153
|
+
const bytesToRead = Math.min(maxBytes, fileStat.size);
|
|
1154
|
+
const start = Math.max(0, fileStat.size - bytesToRead);
|
|
1155
|
+
const handle = await open(path7, "r");
|
|
1156
|
+
try {
|
|
1157
|
+
const buffer = Buffer.alloc(bytesToRead);
|
|
1158
|
+
const { bytesRead } = await handle.read(buffer, 0, bytesToRead, start);
|
|
1159
|
+
return buffer.toString(AGENT_SESSION_STORE.TEXT_ENCODING, 0, bytesRead);
|
|
1160
|
+
} finally {
|
|
1161
|
+
await handle.close();
|
|
1162
|
+
}
|
|
1163
|
+
},
|
|
1097
1164
|
async stat(path7) {
|
|
1098
1165
|
const result = await stat(path7);
|
|
1099
1166
|
return { mtimeMs: result.mtimeMs };
|
|
@@ -3014,6 +3081,7 @@ var AGENT = {
|
|
|
3014
3081
|
CLAUDE_CODE: "claudeCode"
|
|
3015
3082
|
};
|
|
3016
3083
|
var HARNESS_ENVIRONMENT_CONFIG_FIELDS = {
|
|
3084
|
+
METHODOLOGY: "methodology",
|
|
3017
3085
|
INSTRUCTIONS: "instructions",
|
|
3018
3086
|
AGENTS: "agents",
|
|
3019
3087
|
PLUGIN_BOOTSTRAP: "pluginBootstrap",
|
|
@@ -3033,6 +3101,8 @@ var HARNESS_ENVIRONMENT_CONFIG_FIELDS = {
|
|
|
3033
3101
|
VERSION: "version",
|
|
3034
3102
|
MARKETPLACE: "marketplace"
|
|
3035
3103
|
};
|
|
3104
|
+
var DEFAULT_METHODOLOGY_SOURCE = "outcomeeng/spec-tree";
|
|
3105
|
+
var DEFAULT_METHODOLOGY_VERSION = "installed";
|
|
3036
3106
|
var AGENT_SET = new Set(Object.values(AGENT));
|
|
3037
3107
|
var DEFAULT_AGENT_INSTRUCTION_TARGET_AGENTS = [
|
|
3038
3108
|
AGENT.CODEX,
|
|
@@ -3040,6 +3110,10 @@ var DEFAULT_AGENT_INSTRUCTION_TARGET_AGENTS = [
|
|
|
3040
3110
|
];
|
|
3041
3111
|
var DEFAULT_AGENT_INSTRUCTION_FILE_PATH = "AGENTS.md";
|
|
3042
3112
|
var DEFAULT_HARNESS_ENVIRONMENT_CONFIG = {
|
|
3113
|
+
methodology: {
|
|
3114
|
+
source: DEFAULT_METHODOLOGY_SOURCE,
|
|
3115
|
+
version: DEFAULT_METHODOLOGY_VERSION
|
|
3116
|
+
},
|
|
3043
3117
|
instructions: {
|
|
3044
3118
|
files: [
|
|
3045
3119
|
{
|
|
@@ -3073,10 +3147,15 @@ var DEFAULT_HARNESS_ENVIRONMENT_CONFIG = {
|
|
|
3073
3147
|
}
|
|
3074
3148
|
};
|
|
3075
3149
|
var HARNESS_ENVIRONMENT_ALLOWED_FIELDS = /* @__PURE__ */ new Set([
|
|
3150
|
+
HARNESS_ENVIRONMENT_CONFIG_FIELDS.METHODOLOGY,
|
|
3076
3151
|
HARNESS_ENVIRONMENT_CONFIG_FIELDS.INSTRUCTIONS,
|
|
3077
3152
|
HARNESS_ENVIRONMENT_CONFIG_FIELDS.AGENTS,
|
|
3078
3153
|
HARNESS_ENVIRONMENT_CONFIG_FIELDS.PLUGIN_BOOTSTRAP
|
|
3079
3154
|
]);
|
|
3155
|
+
var HARNESS_ENVIRONMENT_METHODOLOGY_ALLOWED_FIELDS = /* @__PURE__ */ new Set([
|
|
3156
|
+
HARNESS_ENVIRONMENT_CONFIG_FIELDS.SOURCE,
|
|
3157
|
+
HARNESS_ENVIRONMENT_CONFIG_FIELDS.VERSION
|
|
3158
|
+
]);
|
|
3080
3159
|
var HARNESS_ENVIRONMENT_INSTRUCTIONS_ALLOWED_FIELDS = /* @__PURE__ */ new Set([
|
|
3081
3160
|
HARNESS_ENVIRONMENT_CONFIG_FIELDS.FILES
|
|
3082
3161
|
]);
|
|
@@ -3141,6 +3220,21 @@ function validateBoolean(path7, value) {
|
|
|
3141
3220
|
}
|
|
3142
3221
|
return { ok: true, value };
|
|
3143
3222
|
}
|
|
3223
|
+
function validateMethodology(raw) {
|
|
3224
|
+
const sectionPath = `${HARNESS_ENVIRONMENT_SECTION}.${HARNESS_ENVIRONMENT_CONFIG_FIELDS.METHODOLOGY}`;
|
|
3225
|
+
if (!isRecord2(raw)) {
|
|
3226
|
+
return { ok: false, error: `${sectionPath} must be an object` };
|
|
3227
|
+
}
|
|
3228
|
+
const unknown = rejectUnknownFields(sectionPath, raw, HARNESS_ENVIRONMENT_METHODOLOGY_ALLOWED_FIELDS);
|
|
3229
|
+
if (!unknown.ok) return unknown;
|
|
3230
|
+
const sourceRaw = raw[HARNESS_ENVIRONMENT_CONFIG_FIELDS.SOURCE];
|
|
3231
|
+
const source = sourceRaw === void 0 ? { ok: true, value: DEFAULT_HARNESS_ENVIRONMENT_CONFIG.methodology.source } : validateNonEmptyString(`${sectionPath}.${HARNESS_ENVIRONMENT_CONFIG_FIELDS.SOURCE}`, sourceRaw);
|
|
3232
|
+
if (!source.ok) return source;
|
|
3233
|
+
const versionRaw = raw[HARNESS_ENVIRONMENT_CONFIG_FIELDS.VERSION];
|
|
3234
|
+
const version2 = versionRaw === void 0 ? { ok: true, value: DEFAULT_HARNESS_ENVIRONMENT_CONFIG.methodology.version } : validateNonEmptyString(`${sectionPath}.${HARNESS_ENVIRONMENT_CONFIG_FIELDS.VERSION}`, versionRaw);
|
|
3235
|
+
if (!version2.ok) return version2;
|
|
3236
|
+
return { ok: true, value: { source: source.value, version: version2.value } };
|
|
3237
|
+
}
|
|
3144
3238
|
function validateAgent(path7, value) {
|
|
3145
3239
|
if (typeof value !== "string" || !isAgent(value)) {
|
|
3146
3240
|
return { ok: false, error: `${path7} must be a registered agent` };
|
|
@@ -3522,6 +3616,9 @@ function validate(value) {
|
|
|
3522
3616
|
HARNESS_ENVIRONMENT_ALLOWED_FIELDS
|
|
3523
3617
|
);
|
|
3524
3618
|
if (!unknown.ok) return unknown;
|
|
3619
|
+
const methodologyRaw = value[HARNESS_ENVIRONMENT_CONFIG_FIELDS.METHODOLOGY];
|
|
3620
|
+
const methodology = methodologyRaw === void 0 ? { ok: true, value: DEFAULT_HARNESS_ENVIRONMENT_CONFIG.methodology } : validateMethodology(methodologyRaw);
|
|
3621
|
+
if (!methodology.ok) return methodology;
|
|
3525
3622
|
const instructionsRaw = value[HARNESS_ENVIRONMENT_CONFIG_FIELDS.INSTRUCTIONS];
|
|
3526
3623
|
const instructions = instructionsRaw === void 0 ? { ok: true, value: DEFAULT_HARNESS_ENVIRONMENT_CONFIG.instructions } : validateInstructions(instructionsRaw);
|
|
3527
3624
|
if (!instructions.ok) return instructions;
|
|
@@ -3534,6 +3631,7 @@ function validate(value) {
|
|
|
3534
3631
|
return {
|
|
3535
3632
|
ok: true,
|
|
3536
3633
|
value: {
|
|
3634
|
+
methodology: methodology.value,
|
|
3537
3635
|
instructions: instructions.value,
|
|
3538
3636
|
agents: agents.value,
|
|
3539
3637
|
pluginBootstrap: pluginBootstrap.value
|
|
@@ -3815,59 +3913,6 @@ var fileInclusionConfigDescriptor = {
|
|
|
3815
3913
|
validate: validate4
|
|
3816
3914
|
};
|
|
3817
3915
|
|
|
3818
|
-
// src/config/source-roots.ts
|
|
3819
|
-
var TEST_RELEVANT_SOURCE_ROOT_PREFIX = {
|
|
3820
|
-
SOURCE: "src/",
|
|
3821
|
-
TESTING: "testing/",
|
|
3822
|
-
SCRIPTS: "scripts/",
|
|
3823
|
-
ESLINT_RULES: "eslint-rules/"
|
|
3824
|
-
};
|
|
3825
|
-
var TEST_RELEVANT_SOURCE_ROOT_PREFIXES = [
|
|
3826
|
-
TEST_RELEVANT_SOURCE_ROOT_PREFIX.SOURCE,
|
|
3827
|
-
TEST_RELEVANT_SOURCE_ROOT_PREFIX.TESTING,
|
|
3828
|
-
TEST_RELEVANT_SOURCE_ROOT_PREFIX.SCRIPTS,
|
|
3829
|
-
TEST_RELEVANT_SOURCE_ROOT_PREFIX.ESLINT_RULES
|
|
3830
|
-
];
|
|
3831
|
-
|
|
3832
|
-
// src/lib/precommit/config.ts
|
|
3833
|
-
var PRECOMMIT_SECTION = "precommit";
|
|
3834
|
-
var PRECOMMIT_DEFAULTS = {
|
|
3835
|
-
sourceDirs: TEST_RELEVANT_SOURCE_ROOT_PREFIXES,
|
|
3836
|
-
testPattern: ".test.ts"
|
|
3837
|
-
};
|
|
3838
|
-
function validate5(value) {
|
|
3839
|
-
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
3840
|
-
return { ok: false, error: `${PRECOMMIT_SECTION} section must be an object` };
|
|
3841
|
-
}
|
|
3842
|
-
const candidate = value;
|
|
3843
|
-
const sourceDirs = candidate["sourceDirs"] ?? PRECOMMIT_DEFAULTS.sourceDirs;
|
|
3844
|
-
if (!Array.isArray(sourceDirs) || !sourceDirs.every((x) => typeof x === "string" && x.length > 0)) {
|
|
3845
|
-
return {
|
|
3846
|
-
ok: false,
|
|
3847
|
-
error: `${PRECOMMIT_SECTION}.sourceDirs must be a non-empty array of non-empty strings`
|
|
3848
|
-
};
|
|
3849
|
-
}
|
|
3850
|
-
const testPattern = candidate["testPattern"] ?? PRECOMMIT_DEFAULTS.testPattern;
|
|
3851
|
-
if (typeof testPattern !== "string" || testPattern.length === 0) {
|
|
3852
|
-
return {
|
|
3853
|
-
ok: false,
|
|
3854
|
-
error: `${PRECOMMIT_SECTION}.testPattern must be a non-empty string`
|
|
3855
|
-
};
|
|
3856
|
-
}
|
|
3857
|
-
return {
|
|
3858
|
-
ok: true,
|
|
3859
|
-
value: {
|
|
3860
|
-
sourceDirs,
|
|
3861
|
-
testPattern
|
|
3862
|
-
}
|
|
3863
|
-
};
|
|
3864
|
-
}
|
|
3865
|
-
var precommitConfigDescriptor = {
|
|
3866
|
-
section: PRECOMMIT_SECTION,
|
|
3867
|
-
defaults: PRECOMMIT_DEFAULTS,
|
|
3868
|
-
validate: validate5
|
|
3869
|
-
};
|
|
3870
|
-
|
|
3871
3916
|
// src/lib/spec-tree/config.ts
|
|
3872
3917
|
var SPEC_TREE_KIND_CATEGORY_VALUES = {
|
|
3873
3918
|
NODE: "node",
|
|
@@ -4056,7 +4101,7 @@ function buildConfigFromKindNames(kindNames) {
|
|
|
4056
4101
|
const entries = kindNames.map((kind) => [kind, KIND_REGISTRY[kind]]);
|
|
4057
4102
|
return { kinds: Object.fromEntries(entries) };
|
|
4058
4103
|
}
|
|
4059
|
-
function
|
|
4104
|
+
function validate5(value) {
|
|
4060
4105
|
if (typeof value !== "object" || value === null) {
|
|
4061
4106
|
return { ok: false, error: `${SPEC_TREE_SECTION} section must be an object` };
|
|
4062
4107
|
}
|
|
@@ -4155,7 +4200,7 @@ function validateKindDefinitionMap(kindEntries) {
|
|
|
4155
4200
|
var specTreeConfigDescriptor = {
|
|
4156
4201
|
section: SPEC_TREE_SECTION,
|
|
4157
4202
|
defaults: buildDefaults(),
|
|
4158
|
-
validate:
|
|
4203
|
+
validate: validate5
|
|
4159
4204
|
};
|
|
4160
4205
|
|
|
4161
4206
|
// src/config/primitives/path-filter.ts
|
|
@@ -4241,7 +4286,7 @@ function resolveDefaultPassingScope() {
|
|
|
4241
4286
|
}
|
|
4242
4287
|
return result.value;
|
|
4243
4288
|
}
|
|
4244
|
-
function
|
|
4289
|
+
function validate6(value) {
|
|
4245
4290
|
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
4246
4291
|
return { ok: false, error: `${TESTING_SECTION} section must be an object` };
|
|
4247
4292
|
}
|
|
@@ -4265,7 +4310,7 @@ function validate7(value) {
|
|
|
4265
4310
|
var testingConfigDescriptor = {
|
|
4266
4311
|
section: TESTING_SECTION,
|
|
4267
4312
|
defaults: defaults4,
|
|
4268
|
-
validate:
|
|
4313
|
+
validate: validate6
|
|
4269
4314
|
};
|
|
4270
4315
|
|
|
4271
4316
|
// src/validation/literal/config.ts
|
|
@@ -4329,7 +4374,7 @@ var LITERAL_DEFAULTS = {
|
|
|
4329
4374
|
function isNonNegativeInteger(value) {
|
|
4330
4375
|
return typeof value === "number" && Number.isInteger(value) && value >= 0;
|
|
4331
4376
|
}
|
|
4332
|
-
function
|
|
4377
|
+
function validate7(value) {
|
|
4333
4378
|
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
4334
4379
|
return { ok: false, error: `${LITERAL_SECTION} section must be an object` };
|
|
4335
4380
|
}
|
|
@@ -4393,7 +4438,7 @@ function isStringArray(value) {
|
|
|
4393
4438
|
var literalConfigDescriptor = {
|
|
4394
4439
|
section: LITERAL_SECTION,
|
|
4395
4440
|
defaults: LITERAL_DEFAULTS,
|
|
4396
|
-
validate:
|
|
4441
|
+
validate: validate7
|
|
4397
4442
|
};
|
|
4398
4443
|
|
|
4399
4444
|
// src/validation/config/descriptor.ts
|
|
@@ -4486,7 +4531,7 @@ function validateKnip(raw) {
|
|
|
4486
4531
|
}
|
|
4487
4532
|
return { ok: true, value: { enabled: enabledRaw } };
|
|
4488
4533
|
}
|
|
4489
|
-
function
|
|
4534
|
+
function validate8(value) {
|
|
4490
4535
|
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
4491
4536
|
return { ok: false, error: `${VALIDATION_SECTION} section must be an object` };
|
|
4492
4537
|
}
|
|
@@ -4505,7 +4550,7 @@ function validate9(value) {
|
|
|
4505
4550
|
var validationConfigDescriptor = {
|
|
4506
4551
|
section: VALIDATION_SECTION,
|
|
4507
4552
|
defaults: defaults5,
|
|
4508
|
-
validate:
|
|
4553
|
+
validate: validate8
|
|
4509
4554
|
};
|
|
4510
4555
|
|
|
4511
4556
|
// src/config/registry.ts
|
|
@@ -4514,7 +4559,6 @@ var productionRegistry = [
|
|
|
4514
4559
|
validationConfigDescriptor,
|
|
4515
4560
|
testingConfigDescriptor,
|
|
4516
4561
|
fileInclusionConfigDescriptor,
|
|
4517
|
-
precommitConfigDescriptor,
|
|
4518
4562
|
harnessEnvironmentConfigDescriptor,
|
|
4519
4563
|
diagnoseConfigDescriptor,
|
|
4520
4564
|
runtimeConfigDescriptor
|
|
@@ -11556,6 +11600,20 @@ function aggregateTestExitCode(invocations, unsupportedSelectionCount = 0) {
|
|
|
11556
11600
|
return SUCCESS_EXIT_CODE;
|
|
11557
11601
|
}
|
|
11558
11602
|
|
|
11603
|
+
// src/config/source-roots.ts
|
|
11604
|
+
var TEST_RELEVANT_SOURCE_ROOT_PREFIX = {
|
|
11605
|
+
SOURCE: "src/",
|
|
11606
|
+
TESTING: "testing/",
|
|
11607
|
+
SCRIPTS: "scripts/",
|
|
11608
|
+
ESLINT_RULES: "eslint-rules/"
|
|
11609
|
+
};
|
|
11610
|
+
var TEST_RELEVANT_SOURCE_ROOT_PREFIXES = [
|
|
11611
|
+
TEST_RELEVANT_SOURCE_ROOT_PREFIX.SOURCE,
|
|
11612
|
+
TEST_RELEVANT_SOURCE_ROOT_PREFIX.TESTING,
|
|
11613
|
+
TEST_RELEVANT_SOURCE_ROOT_PREFIX.SCRIPTS,
|
|
11614
|
+
TEST_RELEVANT_SOURCE_ROOT_PREFIX.ESLINT_RULES
|
|
11615
|
+
];
|
|
11616
|
+
|
|
11559
11617
|
// src/domains/test/changed-set-planning.ts
|
|
11560
11618
|
var PATH_SEPARATOR = "/";
|
|
11561
11619
|
var MARKDOWN_EXTENSION = ".md";
|
|
@@ -19676,6 +19734,7 @@ var UNSEALED_NEXT_ACTIONS = [
|
|
|
19676
19734
|
VERIFY_LIFECYCLE_ACTION.FINISH
|
|
19677
19735
|
];
|
|
19678
19736
|
var VERIFY_VERIFICATION_TYPE = {
|
|
19737
|
+
AUDIT: "audit",
|
|
19679
19738
|
REVIEW: "review"
|
|
19680
19739
|
};
|
|
19681
19740
|
var VERIFY_VERIFICATION_TYPES = new Set(Object.values(VERIFY_VERIFICATION_TYPE));
|
|
@@ -19686,6 +19745,63 @@ var REVIEW_FINDING_DISPOSITION = {
|
|
|
19686
19745
|
BLOCKING: "BLOCKING",
|
|
19687
19746
|
DEBT: "DEBT"
|
|
19688
19747
|
};
|
|
19748
|
+
var REVIEW_SCOPE_COVERAGE_STATE = {
|
|
19749
|
+
CLEAN: "clean",
|
|
19750
|
+
FINDING: "finding"
|
|
19751
|
+
};
|
|
19752
|
+
var REVIEW_ANCHOR_SIDE = {
|
|
19753
|
+
LEFT: "LEFT",
|
|
19754
|
+
RIGHT: "RIGHT"
|
|
19755
|
+
};
|
|
19756
|
+
var REVIEW_TERMINAL_STATE = {
|
|
19757
|
+
APPROVED: "approved",
|
|
19758
|
+
CHANGES_REQUESTED: "changes_requested",
|
|
19759
|
+
COMMENTED: "commented"
|
|
19760
|
+
};
|
|
19761
|
+
var AUDIT_CLASS = {
|
|
19762
|
+
IMPLEMENTATION: "implementation",
|
|
19763
|
+
INSTRUCTIONS: "instructions",
|
|
19764
|
+
SPEC: "spec"
|
|
19765
|
+
};
|
|
19766
|
+
var AUDIT_KIND = {
|
|
19767
|
+
ADR: "adr",
|
|
19768
|
+
ARCHITECTURE: "architecture",
|
|
19769
|
+
CODE: "code",
|
|
19770
|
+
COVERAGE_GAP: "coverage-gap",
|
|
19771
|
+
EVAL_EVIDENCE: "eval-evidence",
|
|
19772
|
+
GUIDE_TEMPLATE: "guide-template",
|
|
19773
|
+
PDR: "pdr",
|
|
19774
|
+
PROMPT: "prompt",
|
|
19775
|
+
SKILL: "skill",
|
|
19776
|
+
SPEC: "spec",
|
|
19777
|
+
SUBAGENT: "subagent",
|
|
19778
|
+
TESTS: "tests"
|
|
19779
|
+
};
|
|
19780
|
+
var AUDIT_COVERAGE_REQUIREMENT = {
|
|
19781
|
+
OPTIONAL: "optional",
|
|
19782
|
+
REQUIRED: "required"
|
|
19783
|
+
};
|
|
19784
|
+
var AUDIT_COVERAGE_STATUS = {
|
|
19785
|
+
AUDITED: "audited",
|
|
19786
|
+
INCOMPLETE: "incomplete",
|
|
19787
|
+
MISSING_SKILL: "missing-skill",
|
|
19788
|
+
NOT_APPLICABLE: "not-applicable",
|
|
19789
|
+
SKIPPED: "skipped",
|
|
19790
|
+
UNSUPPORTED: "unsupported"
|
|
19791
|
+
};
|
|
19792
|
+
var AUDIT_FINDING_SEVERITY = {
|
|
19793
|
+
BLOCKING: "blocking",
|
|
19794
|
+
DEBT: "debt"
|
|
19795
|
+
};
|
|
19796
|
+
var TERMINAL_METADATA_VALIDATION_ERROR = {
|
|
19797
|
+
METADATA_INVALID: "metadata-invalid",
|
|
19798
|
+
STATUS_CONFLICT: "status-conflict"
|
|
19799
|
+
};
|
|
19800
|
+
var VERIFY_EVIDENCE_KIND = {
|
|
19801
|
+
SCOPE: "scope",
|
|
19802
|
+
FINDING: "finding",
|
|
19803
|
+
TERMINAL_METADATA: "terminal-metadata"
|
|
19804
|
+
};
|
|
19689
19805
|
var VERIFY_APPEND_EVENT_TYPE = {
|
|
19690
19806
|
SCOPE: `${RUNTIME_EVENT_NAMESPACE_DEFAULT}.verify.scope`,
|
|
19691
19807
|
FINDING: `${RUNTIME_EVENT_NAMESPACE_DEFAULT}.verify.finding`
|
|
@@ -19768,21 +19884,408 @@ function parseAppendPayload(raw) {
|
|
|
19768
19884
|
function isJsonRecord(value) {
|
|
19769
19885
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
19770
19886
|
}
|
|
19887
|
+
function readRequiredString(record6, field) {
|
|
19888
|
+
const value = record6[field];
|
|
19889
|
+
return typeof value === "string" && value.length > 0 ? value : void 0;
|
|
19890
|
+
}
|
|
19891
|
+
function readRequiredStringValue(record6, field) {
|
|
19892
|
+
const value = record6[field];
|
|
19893
|
+
return typeof value === "string" ? value : void 0;
|
|
19894
|
+
}
|
|
19895
|
+
var OPTIONAL_FIELD_STATE = {
|
|
19896
|
+
ABSENT: "absent",
|
|
19897
|
+
INVALID: "invalid",
|
|
19898
|
+
PRESENT: "present"
|
|
19899
|
+
};
|
|
19900
|
+
function readOptionalString2(record6, field) {
|
|
19901
|
+
if (!(field in record6)) return { state: OPTIONAL_FIELD_STATE.ABSENT };
|
|
19902
|
+
const value = record6[field];
|
|
19903
|
+
return typeof value === "string" && value.length > 0 ? { state: OPTIONAL_FIELD_STATE.PRESENT, value } : { state: OPTIONAL_FIELD_STATE.INVALID };
|
|
19904
|
+
}
|
|
19905
|
+
function readOptionalPositiveInteger(record6, field) {
|
|
19906
|
+
if (!(field in record6)) return { state: OPTIONAL_FIELD_STATE.ABSENT };
|
|
19907
|
+
const value = record6[field];
|
|
19908
|
+
return typeof value === "number" && Number.isInteger(value) && value > 0 ? { state: OPTIONAL_FIELD_STATE.PRESENT, value } : { state: OPTIONAL_FIELD_STATE.INVALID };
|
|
19909
|
+
}
|
|
19910
|
+
function optionalFieldValue(field) {
|
|
19911
|
+
return field.state === OPTIONAL_FIELD_STATE.PRESENT ? field.value : void 0;
|
|
19912
|
+
}
|
|
19913
|
+
function readRequiredRecord(record6, field) {
|
|
19914
|
+
const value = record6[field];
|
|
19915
|
+
return isJsonRecord(value) ? value : void 0;
|
|
19916
|
+
}
|
|
19917
|
+
function readOptionalRecord(record6, field) {
|
|
19918
|
+
if (!(field in record6)) return { state: OPTIONAL_FIELD_STATE.ABSENT };
|
|
19919
|
+
const value = record6[field];
|
|
19920
|
+
return isJsonRecord(value) ? { state: OPTIONAL_FIELD_STATE.PRESENT, value } : { state: OPTIONAL_FIELD_STATE.INVALID };
|
|
19921
|
+
}
|
|
19922
|
+
function hasInvalidOptionalField(...fields) {
|
|
19923
|
+
return fields.some((field) => field.state === OPTIONAL_FIELD_STATE.INVALID);
|
|
19924
|
+
}
|
|
19771
19925
|
function isReviewFindingDisposition(value) {
|
|
19772
19926
|
return Object.values(REVIEW_FINDING_DISPOSITION).includes(value);
|
|
19773
19927
|
}
|
|
19774
|
-
function
|
|
19928
|
+
function isReviewScopeCoverageState(value) {
|
|
19929
|
+
return typeof value === "string" && Object.values(REVIEW_SCOPE_COVERAGE_STATE).includes(value);
|
|
19930
|
+
}
|
|
19931
|
+
function isReviewAnchorSide(value) {
|
|
19932
|
+
return typeof value === "string" && Object.values(REVIEW_ANCHOR_SIDE).includes(value);
|
|
19933
|
+
}
|
|
19934
|
+
function isReviewTerminalState(value) {
|
|
19935
|
+
return typeof value === "string" && Object.values(REVIEW_TERMINAL_STATE).includes(value);
|
|
19936
|
+
}
|
|
19937
|
+
function isAuditClass(value) {
|
|
19938
|
+
return typeof value === "string" && Object.values(AUDIT_CLASS).includes(value);
|
|
19939
|
+
}
|
|
19940
|
+
function isAuditKind(value) {
|
|
19941
|
+
return typeof value === "string" && Object.values(AUDIT_KIND).includes(value);
|
|
19942
|
+
}
|
|
19943
|
+
function isAuditCoverageRequirement(value) {
|
|
19944
|
+
return typeof value === "string" && Object.values(AUDIT_COVERAGE_REQUIREMENT).includes(value);
|
|
19945
|
+
}
|
|
19946
|
+
function isAuditCoverageStatus(value) {
|
|
19947
|
+
return typeof value === "string" && Object.values(AUDIT_COVERAGE_STATUS).includes(value);
|
|
19948
|
+
}
|
|
19949
|
+
function isAuditFindingSeverity(value) {
|
|
19950
|
+
return typeof value === "string" && Object.values(AUDIT_FINDING_SEVERITY).includes(value);
|
|
19951
|
+
}
|
|
19952
|
+
function isCompatibleAuditKind(auditClass, auditKind) {
|
|
19953
|
+
if (auditKind === AUDIT_KIND.COVERAGE_GAP) return true;
|
|
19954
|
+
if (auditClass === AUDIT_CLASS.INSTRUCTIONS) {
|
|
19955
|
+
return auditKind === AUDIT_KIND.SKILL || auditKind === AUDIT_KIND.SUBAGENT || auditKind === AUDIT_KIND.PROMPT || auditKind === AUDIT_KIND.GUIDE_TEMPLATE;
|
|
19956
|
+
}
|
|
19957
|
+
if (auditClass === AUDIT_CLASS.SPEC) {
|
|
19958
|
+
return auditKind === AUDIT_KIND.SPEC || auditKind === AUDIT_KIND.ADR || auditKind === AUDIT_KIND.PDR;
|
|
19959
|
+
}
|
|
19960
|
+
return auditKind === AUDIT_KIND.CODE || auditKind === AUDIT_KIND.TESTS || auditKind === AUDIT_KIND.ARCHITECTURE || auditKind === AUDIT_KIND.EVAL_EVIDENCE;
|
|
19961
|
+
}
|
|
19962
|
+
function evidencePayloadValidator(validator) {
|
|
19963
|
+
return (input) => validator(input.payload);
|
|
19964
|
+
}
|
|
19965
|
+
function readReviewFindingMetadata(payload) {
|
|
19775
19966
|
if (!isJsonRecord(payload)) return void 0;
|
|
19776
19967
|
const { disposition, summary } = payload;
|
|
19777
19968
|
if (!isReviewFindingDisposition(disposition)) return void 0;
|
|
19778
19969
|
if (typeof summary !== "string" || summary.length === 0) return void 0;
|
|
19779
19970
|
return { disposition, summary };
|
|
19780
19971
|
}
|
|
19781
|
-
|
|
19782
|
-
|
|
19972
|
+
function validateReviewFinding(payload) {
|
|
19973
|
+
if (!isJsonRecord(payload)) return void 0;
|
|
19974
|
+
const path7 = readRequiredString(payload, "path");
|
|
19975
|
+
const originalCommit = readRequiredString(payload, "originalCommit");
|
|
19976
|
+
const diffHunk = readRequiredString(payload, "diffHunk");
|
|
19977
|
+
const body = readRequiredString(payload, "body");
|
|
19978
|
+
const { side } = payload;
|
|
19979
|
+
const finding = readReviewFindingMetadata(payload.finding);
|
|
19980
|
+
if (path7 === void 0 || originalCommit === void 0 || diffHunk === void 0 || body === void 0) {
|
|
19981
|
+
return void 0;
|
|
19982
|
+
}
|
|
19983
|
+
if (!isReviewAnchorSide(side)) return void 0;
|
|
19984
|
+
if (finding === void 0) return void 0;
|
|
19985
|
+
const line = readOptionalPositiveInteger(payload, "line");
|
|
19986
|
+
const position = readOptionalPositiveInteger(payload, "position");
|
|
19987
|
+
const providerIdentity = readOptionalString2(payload, "providerIdentity");
|
|
19988
|
+
const url = readOptionalString2(payload, "url");
|
|
19989
|
+
if (hasInvalidOptionalField(line, position, providerIdentity, url)) return void 0;
|
|
19990
|
+
const lineValue = optionalFieldValue(line);
|
|
19991
|
+
const positionValue = optionalFieldValue(position);
|
|
19992
|
+
if (lineValue === void 0 && positionValue === void 0) return void 0;
|
|
19993
|
+
const providerIdentityValue = optionalFieldValue(providerIdentity);
|
|
19994
|
+
const urlValue = optionalFieldValue(url);
|
|
19995
|
+
return {
|
|
19996
|
+
path: path7,
|
|
19997
|
+
side,
|
|
19998
|
+
originalCommit,
|
|
19999
|
+
diffHunk,
|
|
20000
|
+
body,
|
|
20001
|
+
finding,
|
|
20002
|
+
...providerIdentityValue === void 0 ? {} : { providerIdentity: providerIdentityValue },
|
|
20003
|
+
...lineValue === void 0 ? {} : { line: lineValue },
|
|
20004
|
+
...positionValue === void 0 ? {} : { position: positionValue },
|
|
20005
|
+
...urlValue === void 0 ? {} : { url: urlValue }
|
|
20006
|
+
};
|
|
20007
|
+
}
|
|
20008
|
+
function validateReviewScope(payload) {
|
|
20009
|
+
if (!isJsonRecord(payload)) return void 0;
|
|
20010
|
+
const path7 = readRequiredString(payload, "path");
|
|
20011
|
+
const commit = readRequiredString(payload, "commit");
|
|
20012
|
+
const { side, coverageState } = payload;
|
|
20013
|
+
if (path7 === void 0 || commit === void 0) return void 0;
|
|
20014
|
+
if (!isReviewAnchorSide(side)) return void 0;
|
|
20015
|
+
if (!isReviewScopeCoverageState(coverageState)) return void 0;
|
|
20016
|
+
const line = readOptionalPositiveInteger(payload, "line");
|
|
20017
|
+
const position = readOptionalPositiveInteger(payload, "position");
|
|
20018
|
+
const providerIdentity = readOptionalString2(payload, "providerIdentity");
|
|
20019
|
+
const url = readOptionalString2(payload, "url");
|
|
20020
|
+
if (hasInvalidOptionalField(line, position, providerIdentity, url)) return void 0;
|
|
20021
|
+
const lineValue = optionalFieldValue(line);
|
|
20022
|
+
const positionValue = optionalFieldValue(position);
|
|
20023
|
+
const providerIdentityValue = optionalFieldValue(providerIdentity);
|
|
20024
|
+
const urlValue = optionalFieldValue(url);
|
|
20025
|
+
return {
|
|
20026
|
+
path: path7,
|
|
20027
|
+
side,
|
|
20028
|
+
commit,
|
|
20029
|
+
coverageState,
|
|
20030
|
+
...providerIdentityValue === void 0 ? {} : { providerIdentity: providerIdentityValue },
|
|
20031
|
+
...lineValue === void 0 ? {} : { line: lineValue },
|
|
20032
|
+
...positionValue === void 0 ? {} : { position: positionValue },
|
|
20033
|
+
...urlValue === void 0 ? {} : { url: urlValue }
|
|
20034
|
+
};
|
|
20035
|
+
}
|
|
20036
|
+
function validateReviewTerminalMetadata(payload) {
|
|
20037
|
+
if (!isJsonRecord(payload)) return void 0;
|
|
20038
|
+
const actor = readRequiredString(payload, "actor");
|
|
20039
|
+
const body = readRequiredStringValue(payload, "body");
|
|
20040
|
+
const submittedAt = readRequiredString(payload, "submittedAt");
|
|
20041
|
+
const commit = readRequiredString(payload, "commit");
|
|
20042
|
+
const { state } = payload;
|
|
20043
|
+
if (actor === void 0 || body === void 0 || submittedAt === void 0 || commit === void 0) return void 0;
|
|
20044
|
+
if (!isReviewTerminalState(state)) return void 0;
|
|
20045
|
+
const providerIdentity = readOptionalString2(payload, "providerIdentity");
|
|
20046
|
+
const url = readOptionalString2(payload, "url");
|
|
20047
|
+
if (hasInvalidOptionalField(providerIdentity, url)) return void 0;
|
|
20048
|
+
const providerIdentityValue = optionalFieldValue(providerIdentity);
|
|
20049
|
+
const urlValue = optionalFieldValue(url);
|
|
20050
|
+
return {
|
|
20051
|
+
actor,
|
|
20052
|
+
state,
|
|
20053
|
+
body,
|
|
20054
|
+
submittedAt,
|
|
20055
|
+
commit,
|
|
20056
|
+
...providerIdentityValue === void 0 ? {} : { providerIdentity: providerIdentityValue },
|
|
20057
|
+
...urlValue === void 0 ? {} : { url: urlValue }
|
|
20058
|
+
};
|
|
20059
|
+
}
|
|
20060
|
+
function validateReviewTerminal(input) {
|
|
20061
|
+
const validated = input.metadata === void 0 ? void 0 : validateReviewTerminalMetadata(input.metadata);
|
|
20062
|
+
if (input.metadata !== void 0 && validated === void 0) {
|
|
20063
|
+
return { ok: false, error: TERMINAL_METADATA_VALIDATION_ERROR.METADATA_INVALID };
|
|
20064
|
+
}
|
|
20065
|
+
const evidenceStatus = expectedReviewEvidenceTerminalStatus(input.events);
|
|
20066
|
+
const metadataStatus = expectedReviewMetadataTerminalStatus(validated);
|
|
20067
|
+
if (evidenceStatus !== void 0 && metadataStatus !== void 0 && evidenceStatus !== metadataStatus) {
|
|
20068
|
+
return { ok: false, error: TERMINAL_METADATA_VALIDATION_ERROR.STATUS_CONFLICT };
|
|
20069
|
+
}
|
|
20070
|
+
const expectedStatus = evidenceStatus ?? metadataStatus;
|
|
20071
|
+
if (expectedStatus !== void 0 && input.terminalStatus !== expectedStatus) {
|
|
20072
|
+
return { ok: false, error: TERMINAL_METADATA_VALIDATION_ERROR.STATUS_CONFLICT };
|
|
20073
|
+
}
|
|
20074
|
+
if (validated === void 0) return { ok: true, value: void 0 };
|
|
20075
|
+
return {
|
|
20076
|
+
ok: true,
|
|
20077
|
+
value: {
|
|
20078
|
+
actor: validated.actor,
|
|
20079
|
+
state: validated.state,
|
|
20080
|
+
body: validated.body,
|
|
20081
|
+
submittedAt: validated.submittedAt,
|
|
20082
|
+
commit: validated.commit,
|
|
20083
|
+
...validated.providerIdentity === void 0 ? {} : { providerIdentity: validated.providerIdentity },
|
|
20084
|
+
...validated.url === void 0 ? {} : { url: validated.url }
|
|
20085
|
+
}
|
|
20086
|
+
};
|
|
20087
|
+
}
|
|
20088
|
+
function validateAuditProducerIdentity(payload) {
|
|
20089
|
+
if (!isJsonRecord(payload)) return void 0;
|
|
20090
|
+
const producerKind = readRequiredString(payload, "producerKind");
|
|
20091
|
+
const agentName = readRequiredString(payload, "agentName");
|
|
20092
|
+
const agentOwningPluginName = readRequiredString(payload, "agentOwningPluginName");
|
|
20093
|
+
const skillName = readRequiredString(payload, "skillName");
|
|
20094
|
+
const skillOwningPluginName = readRequiredString(payload, "skillOwningPluginName");
|
|
20095
|
+
const invocationRole = readRequiredString(payload, "invocationRole");
|
|
20096
|
+
if (producerKind === void 0 || agentName === void 0 || agentOwningPluginName === void 0 || skillName === void 0 || skillOwningPluginName === void 0 || invocationRole === void 0) {
|
|
20097
|
+
return void 0;
|
|
20098
|
+
}
|
|
20099
|
+
return {
|
|
20100
|
+
producerKind,
|
|
20101
|
+
agentName,
|
|
20102
|
+
agentOwningPluginName,
|
|
20103
|
+
skillName,
|
|
20104
|
+
skillOwningPluginName,
|
|
20105
|
+
invocationRole
|
|
20106
|
+
};
|
|
20107
|
+
}
|
|
20108
|
+
function validateAuditProducerProvenance(payload) {
|
|
20109
|
+
if (!isJsonRecord(payload)) return void 0;
|
|
20110
|
+
const agentOwningPluginVersion = readRequiredString(payload, "agentOwningPluginVersion");
|
|
20111
|
+
const skillOwningPluginVersion = readRequiredString(payload, "skillOwningPluginVersion");
|
|
20112
|
+
if (agentOwningPluginVersion === void 0 || skillOwningPluginVersion === void 0) return void 0;
|
|
20113
|
+
const toolVersion = readOptionalString2(payload, "toolVersion");
|
|
20114
|
+
if (hasInvalidOptionalField(toolVersion)) return void 0;
|
|
20115
|
+
const toolVersionValue = optionalFieldValue(toolVersion);
|
|
20116
|
+
return {
|
|
20117
|
+
agentOwningPluginVersion,
|
|
20118
|
+
skillOwningPluginVersion,
|
|
20119
|
+
...toolVersionValue === void 0 ? {} : { toolVersion: toolVersionValue }
|
|
20120
|
+
};
|
|
20121
|
+
}
|
|
20122
|
+
function validateAuditPriorContextPartitions(payload) {
|
|
20123
|
+
if (!isJsonRecord(payload)) return void 0;
|
|
20124
|
+
const changedFilePartition = readRequiredString(payload, "changedFilePartition");
|
|
20125
|
+
const concernPartition = readRequiredString(payload, "concernPartition");
|
|
20126
|
+
if (changedFilePartition === void 0 || concernPartition === void 0) return void 0;
|
|
20127
|
+
const languagePartition = readOptionalString2(payload, "languagePartition");
|
|
20128
|
+
if (hasInvalidOptionalField(languagePartition)) return void 0;
|
|
20129
|
+
const languagePartitionValue = optionalFieldValue(languagePartition);
|
|
20130
|
+
return {
|
|
20131
|
+
changedFilePartition,
|
|
20132
|
+
concernPartition,
|
|
20133
|
+
...languagePartitionValue === void 0 ? {} : { languagePartition: languagePartitionValue }
|
|
20134
|
+
};
|
|
20135
|
+
}
|
|
20136
|
+
function validateOptionalAuditProducerProvenance(producerProvenance) {
|
|
20137
|
+
if (producerProvenance.state !== OPTIONAL_FIELD_STATE.PRESENT) return producerProvenance;
|
|
20138
|
+
const value = validateAuditProducerProvenance(producerProvenance.value);
|
|
20139
|
+
return value === void 0 ? { state: OPTIONAL_FIELD_STATE.INVALID } : { state: OPTIONAL_FIELD_STATE.PRESENT, value };
|
|
20140
|
+
}
|
|
20141
|
+
function auditKindAllowsProducerProvenance(auditKind, producerProvenance) {
|
|
20142
|
+
return auditKind !== AUDIT_KIND.COVERAGE_GAP || producerProvenance === void 0;
|
|
20143
|
+
}
|
|
20144
|
+
function auditKindAllowsCoverageStatus(auditKind, coverageStatus) {
|
|
20145
|
+
return auditKind !== AUDIT_KIND.COVERAGE_GAP || coverageStatus !== AUDIT_COVERAGE_STATUS.AUDITED && coverageStatus !== AUDIT_COVERAGE_STATUS.NOT_APPLICABLE;
|
|
20146
|
+
}
|
|
20147
|
+
function validateAuditScope(payload) {
|
|
20148
|
+
if (!isJsonRecord(payload)) return void 0;
|
|
20149
|
+
const unitId = readRequiredString(payload, "unitId");
|
|
20150
|
+
const subject = readRequiredString(payload, "subject");
|
|
20151
|
+
const { auditClass, auditKind, coverageRequirement, coverageStatus } = payload;
|
|
20152
|
+
if (unitId === void 0 || subject === void 0) return void 0;
|
|
20153
|
+
if (!isAuditClass(auditClass) || !isAuditKind(auditKind)) return void 0;
|
|
20154
|
+
if (!isCompatibleAuditKind(auditClass, auditKind)) return void 0;
|
|
20155
|
+
if (!isAuditCoverageRequirement(coverageRequirement)) return void 0;
|
|
20156
|
+
if (!isAuditCoverageStatus(coverageStatus)) return void 0;
|
|
20157
|
+
if (!auditKindAllowsCoverageStatus(auditKind, coverageStatus)) return void 0;
|
|
20158
|
+
const priorContext = validateAuditPriorContextPartitions(readRequiredRecord(payload, "priorContext"));
|
|
20159
|
+
const expectedProducer = validateAuditProducerIdentity(readRequiredRecord(payload, "expectedProducer"));
|
|
20160
|
+
const recordedByRunDriver = validateAuditProducerIdentity(readRequiredRecord(payload, "recordedByRunDriver"));
|
|
20161
|
+
if (priorContext === void 0 || expectedProducer === void 0 || recordedByRunDriver === void 0) {
|
|
20162
|
+
return void 0;
|
|
20163
|
+
}
|
|
20164
|
+
const parentUnitId = readOptionalString2(payload, "parentUnitId");
|
|
20165
|
+
const producerProvenance = validateOptionalAuditProducerProvenance(
|
|
20166
|
+
readOptionalRecord(payload, "producerProvenance")
|
|
20167
|
+
);
|
|
20168
|
+
if (hasInvalidOptionalField(parentUnitId, producerProvenance)) return void 0;
|
|
20169
|
+
const parentUnitIdValue = optionalFieldValue(parentUnitId);
|
|
20170
|
+
const producerProvenanceValue = optionalFieldValue(producerProvenance);
|
|
20171
|
+
if (parentUnitIdValue === unitId) return void 0;
|
|
20172
|
+
if (!auditKindAllowsProducerProvenance(auditKind, producerProvenanceValue)) return void 0;
|
|
20173
|
+
return {
|
|
20174
|
+
unitId,
|
|
20175
|
+
auditClass,
|
|
20176
|
+
auditKind,
|
|
20177
|
+
subject,
|
|
20178
|
+
coverageRequirement,
|
|
20179
|
+
coverageStatus,
|
|
20180
|
+
priorContext,
|
|
20181
|
+
expectedProducer,
|
|
20182
|
+
recordedByRunDriver,
|
|
20183
|
+
...parentUnitIdValue === void 0 ? {} : { parentUnitId: parentUnitIdValue },
|
|
20184
|
+
...producerProvenanceValue === void 0 ? {} : { producerProvenance: producerProvenanceValue }
|
|
20185
|
+
};
|
|
20186
|
+
}
|
|
20187
|
+
function validateAuditFindingEvidence(evidence) {
|
|
20188
|
+
if (evidence === void 0) return void 0;
|
|
20189
|
+
const observed = readRequiredString(evidence, "observed");
|
|
20190
|
+
const expected = readRequiredString(evidence, "expected");
|
|
20191
|
+
if (observed === void 0 || expected === void 0) return void 0;
|
|
20192
|
+
return { observed, expected };
|
|
20193
|
+
}
|
|
20194
|
+
function validateAuditFinding(payload) {
|
|
20195
|
+
if (!isJsonRecord(payload)) return void 0;
|
|
20196
|
+
const unitId = readRequiredString(payload, "unitId");
|
|
20197
|
+
const rule = readRequiredString(payload, "rule");
|
|
20198
|
+
const location = readRequiredString(payload, "location");
|
|
20199
|
+
const message = readRequiredString(payload, "message");
|
|
20200
|
+
const { severity } = payload;
|
|
20201
|
+
if (unitId === void 0 || rule === void 0 || location === void 0 || message === void 0) {
|
|
20202
|
+
return void 0;
|
|
20203
|
+
}
|
|
20204
|
+
if (!isAuditFindingSeverity(severity)) return void 0;
|
|
20205
|
+
const producerIdentity = validateAuditProducerIdentity(readRequiredRecord(payload, "producerIdentity"));
|
|
20206
|
+
const producerProvenance = validateAuditProducerProvenance(readRequiredRecord(payload, "producerProvenance"));
|
|
20207
|
+
const evidence = validateAuditFindingEvidence(readRequiredRecord(payload, "evidence"));
|
|
20208
|
+
if (producerIdentity === void 0 || producerProvenance === void 0 || evidence === void 0) {
|
|
20209
|
+
return void 0;
|
|
20210
|
+
}
|
|
20211
|
+
return {
|
|
20212
|
+
unitId,
|
|
20213
|
+
producerIdentity,
|
|
20214
|
+
producerProvenance,
|
|
20215
|
+
rule,
|
|
20216
|
+
severity,
|
|
20217
|
+
location,
|
|
20218
|
+
message,
|
|
20219
|
+
evidence
|
|
20220
|
+
};
|
|
20221
|
+
}
|
|
20222
|
+
function auditFindingReferencesRecordedScope(events, finding) {
|
|
20223
|
+
return events.some((event) => {
|
|
20224
|
+
if (event.type !== VERIFY_APPEND_EVENT_TYPE.SCOPE || !isJsonRecord(event.data)) return false;
|
|
20225
|
+
const scope2 = validateAuditScope(event.data[VERIFY_APPEND_EVENT_FIELD.PAYLOAD]);
|
|
20226
|
+
return scope2?.unitId === finding.unitId;
|
|
20227
|
+
});
|
|
20228
|
+
}
|
|
20229
|
+
function validateAuditFindingForRun(input) {
|
|
20230
|
+
const finding = validateAuditFinding(input.payload);
|
|
20231
|
+
if (finding === void 0) return void 0;
|
|
20232
|
+
return auditFindingReferencesRecordedScope(input.events, finding) ? finding : void 0;
|
|
20233
|
+
}
|
|
20234
|
+
var EVIDENCE_VALIDATORS = {
|
|
20235
|
+
[VERIFY_VERIFICATION_TYPE.AUDIT]: {
|
|
20236
|
+
[VERIFY_EVIDENCE_KIND.SCOPE]: evidencePayloadValidator(validateAuditScope),
|
|
20237
|
+
[VERIFY_EVIDENCE_KIND.FINDING]: validateAuditFindingForRun,
|
|
20238
|
+
[VERIFY_EVIDENCE_KIND.TERMINAL_METADATA]: validateAuditTerminal
|
|
20239
|
+
},
|
|
20240
|
+
[VERIFY_VERIFICATION_TYPE.REVIEW]: {
|
|
20241
|
+
[VERIFY_EVIDENCE_KIND.SCOPE]: evidencePayloadValidator(validateReviewScope),
|
|
20242
|
+
[VERIFY_EVIDENCE_KIND.FINDING]: evidencePayloadValidator(validateReviewFinding),
|
|
20243
|
+
[VERIFY_EVIDENCE_KIND.TERMINAL_METADATA]: validateReviewTerminal
|
|
20244
|
+
}
|
|
19783
20245
|
};
|
|
19784
|
-
function
|
|
19785
|
-
return
|
|
20246
|
+
function evidenceValidatorFor(verificationType, evidenceKind) {
|
|
20247
|
+
return EVIDENCE_VALIDATORS[verificationType]?.[evidenceKind];
|
|
20248
|
+
}
|
|
20249
|
+
function terminalMetadataValidatorFor(verificationType) {
|
|
20250
|
+
return EVIDENCE_VALIDATORS[verificationType]?.[VERIFY_EVIDENCE_KIND.TERMINAL_METADATA];
|
|
20251
|
+
}
|
|
20252
|
+
function expectedReviewEvidenceTerminalStatus(events) {
|
|
20253
|
+
if (countVerifyFindings(events) > 0 || countReviewScopeFindingUnits(events) > 0) {
|
|
20254
|
+
return JOURNAL_RUN_STATE_STATUS.REJECTED;
|
|
20255
|
+
}
|
|
20256
|
+
return void 0;
|
|
20257
|
+
}
|
|
20258
|
+
function auditCoverageRejectsRun(scope2) {
|
|
20259
|
+
if (scope2.coverageRequirement !== AUDIT_COVERAGE_REQUIREMENT.REQUIRED) return false;
|
|
20260
|
+
return scope2.auditKind === AUDIT_KIND.COVERAGE_GAP || scope2.coverageStatus === AUDIT_COVERAGE_STATUS.UNSUPPORTED || scope2.coverageStatus === AUDIT_COVERAGE_STATUS.MISSING_SKILL || scope2.coverageStatus === AUDIT_COVERAGE_STATUS.SKIPPED || scope2.coverageStatus === AUDIT_COVERAGE_STATUS.INCOMPLETE;
|
|
20261
|
+
}
|
|
20262
|
+
function expectedAuditTerminalStatus(events) {
|
|
20263
|
+
const hasFinding = countVerifyFindings(events) > 0;
|
|
20264
|
+
const auditScopeEvents = events.filter((event) => {
|
|
20265
|
+
if (event.type !== VERIFY_APPEND_EVENT_TYPE.SCOPE || !isJsonRecord(event.data)) return false;
|
|
20266
|
+
return validateAuditScope(event.data[VERIFY_APPEND_EVENT_FIELD.PAYLOAD]) !== void 0;
|
|
20267
|
+
});
|
|
20268
|
+
const hasUncoveredRequiredScope = events.some((event) => {
|
|
20269
|
+
if (event.type !== VERIFY_APPEND_EVENT_TYPE.SCOPE || !isJsonRecord(event.data)) return false;
|
|
20270
|
+
const payload = event.data[VERIFY_APPEND_EVENT_FIELD.PAYLOAD];
|
|
20271
|
+
const scope2 = validateAuditScope(payload);
|
|
20272
|
+
return scope2 === void 0 ? false : auditCoverageRejectsRun(scope2);
|
|
20273
|
+
});
|
|
20274
|
+
return hasFinding || auditScopeEvents.length === 0 || hasUncoveredRequiredScope ? JOURNAL_RUN_STATE_STATUS.REJECTED : JOURNAL_RUN_STATE_STATUS.APPROVED;
|
|
20275
|
+
}
|
|
20276
|
+
function validateAuditTerminal(input) {
|
|
20277
|
+
if (input.metadata !== void 0) {
|
|
20278
|
+
return { ok: false, error: TERMINAL_METADATA_VALIDATION_ERROR.METADATA_INVALID };
|
|
20279
|
+
}
|
|
20280
|
+
if (input.terminalStatus !== expectedAuditTerminalStatus(input.events)) {
|
|
20281
|
+
return { ok: false, error: TERMINAL_METADATA_VALIDATION_ERROR.STATUS_CONFLICT };
|
|
20282
|
+
}
|
|
20283
|
+
return { ok: true, value: void 0 };
|
|
20284
|
+
}
|
|
20285
|
+
function expectedReviewMetadataTerminalStatus(metadata) {
|
|
20286
|
+
if (metadata?.state === REVIEW_TERMINAL_STATE.APPROVED) return JOURNAL_RUN_STATE_STATUS.APPROVED;
|
|
20287
|
+
if (metadata?.state === REVIEW_TERMINAL_STATE.CHANGES_REQUESTED) return JOURNAL_RUN_STATE_STATUS.REJECTED;
|
|
20288
|
+
return void 0;
|
|
19786
20289
|
}
|
|
19787
20290
|
function findAppendedSequence(events, idempotencyKey, eventType) {
|
|
19788
20291
|
const match = events.find(
|
|
@@ -19805,6 +20308,7 @@ function buildAppendEvent(args) {
|
|
|
19805
20308
|
}
|
|
19806
20309
|
var VERIFY_TERMINAL_EVENT_TYPE = `${RUNTIME_EVENT_NAMESPACE_DEFAULT}.verify.terminal`;
|
|
19807
20310
|
var VERIFY_TERMINAL_EVENT_FIELD = {
|
|
20311
|
+
TERMINAL_METADATA: "terminalMetadata",
|
|
19808
20312
|
TERMINAL_STATUS: "terminalStatus"
|
|
19809
20313
|
};
|
|
19810
20314
|
var VERIFY_TERMINAL_EVENT_ID_PREFIX = "verify-terminal-";
|
|
@@ -19819,7 +20323,8 @@ function buildTerminalEvent(args) {
|
|
|
19819
20323
|
time: args.at.toISOString(),
|
|
19820
20324
|
attempt: VERIFY_APPEND_ATTEMPT,
|
|
19821
20325
|
data: {
|
|
19822
|
-
[VERIFY_TERMINAL_EVENT_FIELD.TERMINAL_STATUS]: args.terminalStatus
|
|
20326
|
+
[VERIFY_TERMINAL_EVENT_FIELD.TERMINAL_STATUS]: args.terminalStatus,
|
|
20327
|
+
...args.terminalMetadata === void 0 ? {} : { [VERIFY_TERMINAL_EVENT_FIELD.TERMINAL_METADATA]: args.terminalMetadata }
|
|
19823
20328
|
}
|
|
19824
20329
|
};
|
|
19825
20330
|
}
|
|
@@ -19832,11 +20337,23 @@ function terminalStatusOf(event) {
|
|
|
19832
20337
|
const status = event.data[VERIFY_TERMINAL_EVENT_FIELD.TERMINAL_STATUS];
|
|
19833
20338
|
return typeof status === "string" ? status : void 0;
|
|
19834
20339
|
}
|
|
20340
|
+
function terminalMetadataOf(event) {
|
|
20341
|
+
if (event === void 0 || !isJsonRecord(event.data)) return void 0;
|
|
20342
|
+
return event.data[VERIFY_TERMINAL_EVENT_FIELD.TERMINAL_METADATA];
|
|
20343
|
+
}
|
|
19835
20344
|
function countVerifyFindings(events) {
|
|
19836
20345
|
return events.filter(
|
|
19837
20346
|
(event) => event.type === VERIFY_APPEND_EVENT_TYPE.FINDING
|
|
19838
20347
|
).length;
|
|
19839
20348
|
}
|
|
20349
|
+
function countReviewScopeFindingUnits(events) {
|
|
20350
|
+
return events.filter((event) => {
|
|
20351
|
+
if (event.type !== VERIFY_APPEND_EVENT_TYPE.SCOPE || !isJsonRecord(event.data)) return false;
|
|
20352
|
+
const payload = event.data[VERIFY_APPEND_EVENT_FIELD.PAYLOAD];
|
|
20353
|
+
const scope2 = validateReviewScope(payload);
|
|
20354
|
+
return scope2?.coverageState === REVIEW_SCOPE_COVERAGE_STATE.FINDING;
|
|
20355
|
+
}).length;
|
|
20356
|
+
}
|
|
19840
20357
|
function lastSequenceOf(events) {
|
|
19841
20358
|
return events.reduce(
|
|
19842
20359
|
(max, event) => event.seq > max ? event.seq : max,
|
|
@@ -19846,10 +20363,12 @@ function lastSequenceOf(events) {
|
|
|
19846
20363
|
function projectVerifyRun(events) {
|
|
19847
20364
|
const terminal = findTerminalEvent(events);
|
|
19848
20365
|
const terminalStatus = terminalStatusOf(terminal);
|
|
20366
|
+
const terminalMetadata = terminalMetadataOf(terminal);
|
|
19849
20367
|
const sealed = terminal !== void 0;
|
|
19850
20368
|
return {
|
|
19851
20369
|
sealed,
|
|
19852
20370
|
...terminalStatus === void 0 ? {} : { terminalStatus },
|
|
20371
|
+
...terminalMetadata === void 0 ? {} : { terminalMetadata },
|
|
19853
20372
|
findingCount: countVerifyFindings(events),
|
|
19854
20373
|
lastSequence: lastSequenceOf(events),
|
|
19855
20374
|
nextActions: sealed ? [] : UNSEALED_NEXT_ACTIONS
|
|
@@ -19877,11 +20396,14 @@ var VERIFY_CLI_ERROR = {
|
|
|
19877
20396
|
PAYLOAD_READ_FAILED: "spx verification run could not read the evidence payload",
|
|
19878
20397
|
PAYLOAD_INVALID: "spx verification run evidence payload is not valid JSON",
|
|
19879
20398
|
RUN_FINISHED: "spx verification run cannot add evidence to a finished run",
|
|
20399
|
+
SCOPE_INVALID: "spx verification run scope add payload failed verification-type validation",
|
|
19880
20400
|
FINDING_INVALID: "spx verification run finding add payload failed verification-type validation",
|
|
19881
20401
|
UNSUPPORTED_VERIFICATION_TYPE: "spx verification run verification type is not registered",
|
|
19882
20402
|
APPEND_FAILED: "spx verification run could not append the evidence event",
|
|
19883
20403
|
TERMINAL_STATUS_REQUIRED: "spx verification run finish requires --terminal-status <status>",
|
|
19884
20404
|
TERMINAL_STATUS_INVALID: "spx verification run finish requires a terminal status in the journal terminal-status vocabulary",
|
|
20405
|
+
TERMINAL_METADATA_INVALID: "spx verification run terminal metadata failed verification-type validation",
|
|
20406
|
+
TERMINAL_STATUS_CONFLICT: "spx verification run terminal status conflicts with verification-type terminal metadata: status-conflict",
|
|
19885
20407
|
FINISH_FAILED: "spx verification run could not record terminal completion",
|
|
19886
20408
|
SEAL_FAILED: "spx verification run could not seal the run journal",
|
|
19887
20409
|
STATUS_FAILED: "spx verification run could not read the run status",
|
|
@@ -20271,12 +20793,18 @@ function appendRunSelectorMismatchDiagnostic(options, backendIdentity, namespace
|
|
|
20271
20793
|
searchedTarget
|
|
20272
20794
|
});
|
|
20273
20795
|
}
|
|
20274
|
-
function
|
|
20275
|
-
|
|
20276
|
-
const validator =
|
|
20277
|
-
if (validator === void 0) return VERIFY_CLI_ERROR.UNSUPPORTED_VERIFICATION_TYPE;
|
|
20278
|
-
|
|
20279
|
-
|
|
20796
|
+
function validateAppendEvidence(verb, verificationType, payload, events) {
|
|
20797
|
+
const evidenceKind = verb === VERIFY_VERB.APPEND_FINDING ? VERIFY_EVIDENCE_KIND.FINDING : VERIFY_EVIDENCE_KIND.SCOPE;
|
|
20798
|
+
const validator = evidenceValidatorFor(verificationType, evidenceKind);
|
|
20799
|
+
if (validator === void 0) return { ok: false, error: VERIFY_CLI_ERROR.UNSUPPORTED_VERIFICATION_TYPE };
|
|
20800
|
+
const validated = validator({ payload, events });
|
|
20801
|
+
if (validated === void 0) {
|
|
20802
|
+
return {
|
|
20803
|
+
ok: false,
|
|
20804
|
+
error: verb === VERIFY_VERB.APPEND_FINDING ? VERIFY_CLI_ERROR.FINDING_INVALID : VERIFY_CLI_ERROR.SCOPE_INVALID
|
|
20805
|
+
};
|
|
20806
|
+
}
|
|
20807
|
+
return { ok: true, value: JSON.parse(JSON.stringify(validated)) };
|
|
20280
20808
|
}
|
|
20281
20809
|
function appendEventType(verb) {
|
|
20282
20810
|
return verb === VERIFY_VERB.APPEND_FINDING ? VERIFY_APPEND_EVENT_TYPE.FINDING : VERIFY_APPEND_EVENT_TYPE.SCOPE;
|
|
@@ -20299,12 +20827,12 @@ async function verifyAppend(options, deps, verb) {
|
|
|
20299
20827
|
}
|
|
20300
20828
|
const parsed = parseAppendPayload(rawPayload);
|
|
20301
20829
|
if (parsed === void 0) return errorResult3(VERIFY_CLI_ERROR.PAYLOAD_INVALID);
|
|
20302
|
-
const
|
|
20303
|
-
if (
|
|
20830
|
+
const evidence = validateAppendEvidence(verb, options.verificationType, parsed, existingEvents);
|
|
20831
|
+
if (!evidence.ok) return errorResult3(evidence.error);
|
|
20304
20832
|
const event = buildAppendEvent({
|
|
20305
20833
|
eventType,
|
|
20306
20834
|
idempotencyKey: options.idempotencyKey,
|
|
20307
|
-
payload:
|
|
20835
|
+
payload: evidence.value,
|
|
20308
20836
|
at: deps.now?.() ?? /* @__PURE__ */ new Date()
|
|
20309
20837
|
});
|
|
20310
20838
|
const appended = await journalAppendCommand(journalScope, event, binding, forwardDeps(deps));
|
|
@@ -20422,6 +20950,7 @@ function verifyFinishReport(runToken, projection) {
|
|
|
20422
20950
|
return {
|
|
20423
20951
|
runToken,
|
|
20424
20952
|
...projection.terminalStatus === void 0 ? {} : { terminalStatus: projection.terminalStatus },
|
|
20953
|
+
...projection.terminalMetadata === void 0 ? {} : { terminalMetadata: projection.terminalMetadata },
|
|
20425
20954
|
sealed: projection.sealed,
|
|
20426
20955
|
findingCount: projection.findingCount,
|
|
20427
20956
|
lastSequence: projection.lastSequence
|
|
@@ -20446,6 +20975,31 @@ function finishReadFailure(run, options, error) {
|
|
|
20446
20975
|
}
|
|
20447
20976
|
return errorResult3(`${VERIFY_CLI_ERROR.FINISH_FAILED}: ${error}`);
|
|
20448
20977
|
}
|
|
20978
|
+
async function readTerminalMetadata(options, deps) {
|
|
20979
|
+
if (options.terminalMetadata === void 0) return { ok: true, value: void 0 };
|
|
20980
|
+
const readPayload = deps.readPayloadSource;
|
|
20981
|
+
if (readPayload === void 0) return { ok: false, error: VERIFY_CLI_ERROR.TERMINAL_METADATA_INVALID };
|
|
20982
|
+
try {
|
|
20983
|
+
const rawMetadata = await readPayload(options.terminalMetadata);
|
|
20984
|
+
const parsed = parseAppendPayload(rawMetadata);
|
|
20985
|
+
if (parsed === void 0) return { ok: false, error: VERIFY_CLI_ERROR.PAYLOAD_INVALID };
|
|
20986
|
+
return { ok: true, value: parsed };
|
|
20987
|
+
} catch (error) {
|
|
20988
|
+
return { ok: false, error: `${VERIFY_CLI_ERROR.PAYLOAD_READ_FAILED}: ${toMessage2(error)}` };
|
|
20989
|
+
}
|
|
20990
|
+
}
|
|
20991
|
+
function validateTerminalMetadata(verificationType, terminalStatus, metadata, events) {
|
|
20992
|
+
const validator = terminalMetadataValidatorFor(verificationType);
|
|
20993
|
+
if (validator === void 0) {
|
|
20994
|
+
return metadata === void 0 ? { ok: true, value: void 0 } : { ok: false, error: VERIFY_CLI_ERROR.UNSUPPORTED_VERIFICATION_TYPE };
|
|
20995
|
+
}
|
|
20996
|
+
const validated = validator({ terminalStatus, metadata, events });
|
|
20997
|
+
if (validated.ok) return { ok: true, value: validated.value };
|
|
20998
|
+
return {
|
|
20999
|
+
ok: false,
|
|
21000
|
+
error: validated.error === TERMINAL_METADATA_VALIDATION_ERROR.STATUS_CONFLICT ? VERIFY_CLI_ERROR.TERMINAL_STATUS_CONFLICT : VERIFY_CLI_ERROR.TERMINAL_METADATA_INVALID
|
|
21001
|
+
};
|
|
21002
|
+
}
|
|
20449
21003
|
async function finishProjectionResult(run, deps) {
|
|
20450
21004
|
const events = await readRunJournalEvents(run.journalScope, deps);
|
|
20451
21005
|
if (!events.ok) return errorResult3(`${VERIFY_CLI_ERROR.FINISH_FAILED}: ${events.error}`);
|
|
@@ -20475,11 +21029,21 @@ async function verifyFinishCommand(options, deps) {
|
|
|
20475
21029
|
if (inputRecord.value === void 0) {
|
|
20476
21030
|
return errorResult3(existingRunNotFound(run.value, options));
|
|
20477
21031
|
}
|
|
21032
|
+
const rawTerminalMetadata = await readTerminalMetadata(options, deps);
|
|
21033
|
+
if (!rawTerminalMetadata.ok) return errorResult3(rawTerminalMetadata.error);
|
|
21034
|
+
const terminalMetadata = validateTerminalMetadata(
|
|
21035
|
+
options.verificationType,
|
|
21036
|
+
options.terminalStatus,
|
|
21037
|
+
rawTerminalMetadata.value,
|
|
21038
|
+
before.value
|
|
21039
|
+
);
|
|
21040
|
+
if (!terminalMetadata.ok) return errorResult3(terminalMetadata.error);
|
|
20478
21041
|
const binding = deps.journalBinding;
|
|
20479
21042
|
if (binding === void 0) return errorResult3(VERIFY_CLI_ERROR.FINISH_FAILED);
|
|
20480
21043
|
const event = buildTerminalEvent({
|
|
20481
21044
|
runToken: run.value.runToken,
|
|
20482
21045
|
terminalStatus: options.terminalStatus,
|
|
21046
|
+
...terminalMetadata.value === void 0 ? {} : { terminalMetadata: terminalMetadata.value },
|
|
20483
21047
|
at: deps.now?.() ?? /* @__PURE__ */ new Date()
|
|
20484
21048
|
});
|
|
20485
21049
|
const appended = await journalAppendCommand(run.value.journalScope, event, binding, forwardDeps(deps));
|
|
@@ -20513,6 +21077,7 @@ async function verifyStatusCommand(options, deps) {
|
|
|
20513
21077
|
sealed: projection.sealed,
|
|
20514
21078
|
lastSequence: projection.lastSequence,
|
|
20515
21079
|
...projection.terminalStatus === void 0 ? {} : { terminalStatus: projection.terminalStatus },
|
|
21080
|
+
...projection.terminalMetadata === void 0 ? {} : { terminalMetadata: projection.terminalMetadata },
|
|
20516
21081
|
findingCount: projection.findingCount,
|
|
20517
21082
|
nextActions: projection.nextActions
|
|
20518
21083
|
};
|
|
@@ -20539,6 +21104,7 @@ async function verifyRenderCommand(options, deps) {
|
|
|
20539
21104
|
findingCount: projection.findingCount,
|
|
20540
21105
|
sealed: projection.sealed,
|
|
20541
21106
|
...projection.terminalStatus === void 0 ? {} : { terminalStatus: projection.terminalStatus },
|
|
21107
|
+
...projection.terminalMetadata === void 0 ? {} : { terminalMetadata: projection.terminalMetadata },
|
|
20542
21108
|
events: events.value
|
|
20543
21109
|
};
|
|
20544
21110
|
return okResult3(JSON.stringify(report2));
|
|
@@ -20576,6 +21142,7 @@ var VERIFY_CLI = {
|
|
|
20576
21142
|
payloadOptionDescription: "Evidence payload source; stdin or a file path",
|
|
20577
21143
|
idempotencyKeyOption: "--idempotency-key <key>",
|
|
20578
21144
|
idempotencyKeyOptionDescription: "Caller-supplied idempotency key for the evidence add",
|
|
21145
|
+
terminalMetadataOption: "--terminal-metadata <payload-source>",
|
|
20579
21146
|
terminalStatusOption: "--terminal-status <status>"
|
|
20580
21147
|
};
|
|
20581
21148
|
var CLI_SOURCE_ENCODING = "utf8";
|
|
@@ -20629,7 +21196,7 @@ function registerVerifyCommands(program, invocation, handlers = DEFAULT_VERIFY_C
|
|
|
20629
21196
|
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
21197
|
reportCliResult(await handlers.appendFinding(options, deps()), invocation.io);
|
|
20631
21198
|
});
|
|
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) => {
|
|
21199
|
+
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").option(VERIFY_CLI.terminalMetadataOption, "Verification-type terminal metadata source; stdin or a file path").action(async (options) => {
|
|
20633
21200
|
reportCliResult(await handlers.finish(options, deps()), invocation.io);
|
|
20634
21201
|
});
|
|
20635
21202
|
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) => {
|