@cassiomc1/forgeloop 1.0.0 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.cursor/rules/project-loop.mdc +3 -2
- package/.github/copilot-instructions.md +1 -0
- package/AGENTS.md +2 -1
- package/CLAUDE.md +1 -0
- package/DOCS_INDEX.md +36 -0
- package/ENG/design-code-eng.md +31 -0
- package/ENG/documentation-quality-eng.md +400 -0
- package/EXECUTION_STATE.md +23 -13
- package/GUIDE_ROUTER.md +23 -8
- package/LOOP_ENGINEERING.md +77 -12
- package/PROTOCOL_INTEGRATION.md +9 -6
- package/README.md +82 -39
- package/docs/ARTIFACT_REFERENCE.md +442 -0
- package/docs/CLI_REFERENCE.md +892 -0
- package/docs/CROSS_HARNESS_CONTINUITY.md +198 -0
- package/docs/DOCUMENTATION_GUIDE.md +161 -0
- package/docs/GETTING_STARTED.md +348 -0
- package/docs/RECIPES.md +250 -0
- package/docs/TROUBLESHOOTING.md +345 -0
- package/docs/assets/forgeloop-flow.svg +1 -1
- package/docs/forgeloop-flow.mmd +1 -1
- package/package.json +13 -2
- package/schemas/task-descriptor.schema.json +56 -0
- package/schemas/work-state.schema.json +18 -1
- package/scripts/CI_VALIDATORS.md +7 -0
- package/src/cli.js +280 -388
- package/src/commands/advance.js +5 -2
- package/src/commands/audit.js +11 -1
- package/src/commands/clear-continuity.js +5 -2
- package/src/commands/clear-state.js +5 -2
- package/src/commands/complete.js +9 -1
- package/src/commands/continuity.js +5 -2
- package/src/commands/inspect.js +10 -2
- package/src/commands/next.js +5 -2
- package/src/commands/preflight.js +9 -1
- package/src/commands/prepare-completion.js +5 -2
- package/src/commands/reconcile-continuity.js +5 -2
- package/src/commands/record-check.js +7 -1
- package/src/commands/record-continuity.js +21 -14
- package/src/commands/record-terminal-result.js +7 -1
- package/src/commands/route.js +22 -18
- package/src/commands/run-check.js +52 -44
- package/src/commands/status.js +18 -12
- package/src/commands/task-create.js +94 -0
- package/src/commands/task-list.js +48 -0
- package/src/commands/task-migrate.js +34 -0
- package/src/commands/task-scope.js +75 -0
- package/src/commands/task-show.js +81 -0
- package/src/commands/task-unlock.js +35 -0
- package/src/commands/validate-protocol.js +37 -20
- package/src/commands/validate-state.js +24 -18
- package/src/config/guides.json +42 -0
- package/src/core/activation.js +8 -4
- package/src/core/artifact-registry.js +166 -0
- package/src/core/audit.js +65 -12
- package/src/core/bundles.js +76 -50
- package/src/core/cli-command-definitions.js +611 -0
- package/src/core/cli-metadata.js +23 -0
- package/src/core/completion-artifacts.js +161 -74
- package/src/core/completion.js +134 -76
- package/src/core/continuity.js +20 -13
- package/src/core/contract.js +6 -3
- package/src/core/error-codes.js +197 -0
- package/src/core/events.js +19 -14
- package/src/core/execution.js +38 -6
- package/src/core/gate-artifact.js +12 -9
- package/src/core/gates.js +4 -2
- package/src/core/guide-metadata.js +7 -11
- package/src/core/guide-registry.js +29 -0
- package/src/core/inspect.js +7 -4
- package/src/core/native-adapters.js +6 -0
- package/src/core/phase.js +85 -33
- package/src/core/preflight-consistency.js +24 -14
- package/src/core/preflight-loaders.js +16 -11
- package/src/core/preflight.js +44 -25
- package/src/core/protocol.js +2 -11
- package/src/core/receipt.js +1 -1
- package/src/core/report.js +2 -2
- package/src/core/repository.js +46 -12
- package/src/core/resumability.js +6 -4
- package/src/core/route-artifact.js +9 -5
- package/src/core/router.js +11 -7
- package/src/core/schema-validation.js +1 -0
- package/src/core/task-command.js +41 -0
- package/src/core/task-context.js +126 -0
- package/src/core/task-descriptor.js +81 -0
- package/src/core/task-discovery.js +116 -0
- package/src/core/task-identity.js +76 -0
- package/src/core/task-lock.js +209 -0
- package/src/core/task-migration-validation.js +140 -0
- package/src/core/task-migration.js +361 -0
- package/src/core/task-paths.js +96 -0
- package/src/core/task-scope.js +179 -0
- package/src/core/templates.js +3 -9
- package/src/core/work-state.js +24 -13
package/src/core/audit.js
CHANGED
|
@@ -5,20 +5,40 @@ import { PROTOCOL_VERSION } from "./protocol.js";
|
|
|
5
5
|
import { readJsonArtifact } from "./artifacts.js";
|
|
6
6
|
import { currentChangedPaths } from "./repository.js";
|
|
7
7
|
import { validateReadyProtocolConsistency } from "./preflight.js";
|
|
8
|
+
import { taskArtifactPath } from "./task-paths.js";
|
|
9
|
+
import { readTaskDescriptor } from "./task-descriptor.js";
|
|
8
10
|
|
|
9
11
|
function sortErrors(errors) {
|
|
10
12
|
return [...errors].sort((left, right) => left.code.localeCompare(right.code)
|
|
11
13
|
|| left.message.localeCompare(right.message));
|
|
12
14
|
}
|
|
13
15
|
|
|
14
|
-
async function compareChangedPaths(target, packageRoot) {
|
|
16
|
+
async function compareChangedPaths(target, packageRoot, options = {}) {
|
|
17
|
+
const receiptRel = options.receiptPath ?? (options.taskId ? taskArtifactPath(options.taskId, "receipt") : ARTIFACT_PATHS.receipt);
|
|
15
18
|
let receipt;
|
|
16
19
|
try {
|
|
17
|
-
receipt = (await readJsonArtifact(target,
|
|
20
|
+
receipt = (await readJsonArtifact(target, receiptRel, "execution-receipt", packageRoot)).value;
|
|
18
21
|
} catch {
|
|
19
22
|
return { status: "NOT_VERIFIED", expected: [], observed: [], missing: [], unexpected: [] };
|
|
20
23
|
}
|
|
21
|
-
|
|
24
|
+
|
|
25
|
+
let writeClaims = [];
|
|
26
|
+
if (options.taskId) {
|
|
27
|
+
try {
|
|
28
|
+
const desc = await readTaskDescriptor(target, options.taskId, packageRoot);
|
|
29
|
+
writeClaims = desc.value.writeClaims ?? [];
|
|
30
|
+
} catch {
|
|
31
|
+
// ignore
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
let observed;
|
|
36
|
+
if (writeClaims.length > 0) {
|
|
37
|
+
observed = await currentChangedPaths(target, { paths: writeClaims });
|
|
38
|
+
} else {
|
|
39
|
+
observed = await currentChangedPaths(target);
|
|
40
|
+
}
|
|
41
|
+
|
|
22
42
|
if (observed === null) {
|
|
23
43
|
return { status: "NOT_VERIFIED", expected: receipt.changedPaths ?? [], observed: [], missing: [], unexpected: [] };
|
|
24
44
|
}
|
|
@@ -34,8 +54,40 @@ async function compareChangedPaths(target, packageRoot) {
|
|
|
34
54
|
};
|
|
35
55
|
}
|
|
36
56
|
|
|
37
|
-
export async function evaluateAudit({
|
|
38
|
-
|
|
57
|
+
export async function evaluateAudit({
|
|
58
|
+
target,
|
|
59
|
+
packageRoot,
|
|
60
|
+
strict = false,
|
|
61
|
+
authorityContext,
|
|
62
|
+
runtimeContext,
|
|
63
|
+
taskId = null,
|
|
64
|
+
contractPath = null,
|
|
65
|
+
routePath = null,
|
|
66
|
+
statePath = null,
|
|
67
|
+
receiptPath = null,
|
|
68
|
+
eventsPath = null,
|
|
69
|
+
preflightPath = null,
|
|
70
|
+
} = {}) {
|
|
71
|
+
const completion = await evaluateCompletion({
|
|
72
|
+
target,
|
|
73
|
+
packageRoot,
|
|
74
|
+
strict,
|
|
75
|
+
authorityContext,
|
|
76
|
+
runtimeContext,
|
|
77
|
+
taskId,
|
|
78
|
+
contractPath,
|
|
79
|
+
routePath,
|
|
80
|
+
statePath,
|
|
81
|
+
receiptPath,
|
|
82
|
+
eventsPath,
|
|
83
|
+
preflightPath,
|
|
84
|
+
});
|
|
85
|
+
const preflightRel = preflightPath ?? (taskId ? taskArtifactPath(taskId, "preflight") : ARTIFACT_PATHS.preflight);
|
|
86
|
+
const receiptRel = receiptPath ?? (taskId ? taskArtifactPath(taskId, "receipt") : ARTIFACT_PATHS.receipt);
|
|
87
|
+
const stateRel = statePath ?? (taskId ? taskArtifactPath(taskId, "state") : ARTIFACT_PATHS.state);
|
|
88
|
+
const contractRel = contractPath ?? (taskId ? taskArtifactPath(taskId, "contract") : ARTIFACT_PATHS.contract);
|
|
89
|
+
const routeRel = routePath ?? (taskId ? taskArtifactPath(taskId, "route") : ARTIFACT_PATHS.route);
|
|
90
|
+
|
|
39
91
|
let manifest = null;
|
|
40
92
|
let manifestError = null;
|
|
41
93
|
try {
|
|
@@ -45,25 +97,26 @@ export async function evaluateAudit({ target, packageRoot, strict = false, autho
|
|
|
45
97
|
}
|
|
46
98
|
let readyConsistencyErrors = [];
|
|
47
99
|
try {
|
|
48
|
-
const persistedPreflight = await readJsonArtifact(target,
|
|
100
|
+
const persistedPreflight = await readJsonArtifact(target, preflightRel, "preflight", packageRoot);
|
|
49
101
|
if (persistedPreflight.value.status === "READY") {
|
|
50
102
|
readyConsistencyErrors = await validateReadyProtocolConsistency({
|
|
51
103
|
target,
|
|
52
104
|
packageRoot,
|
|
53
105
|
persisted: persistedPreflight.value,
|
|
54
106
|
current: completion.preflight,
|
|
107
|
+
taskId,
|
|
55
108
|
});
|
|
56
109
|
}
|
|
57
110
|
} catch {
|
|
58
111
|
// Completion already reports missing or invalid preflight artifacts.
|
|
59
112
|
}
|
|
60
113
|
const errors = sortErrors([...completion.errors, ...readyConsistencyErrors]);
|
|
61
|
-
const changedPaths = await compareChangedPaths(target, packageRoot);
|
|
114
|
+
const changedPaths = await compareChangedPaths(target, packageRoot, { taskId, receiptPath });
|
|
62
115
|
if (changedPaths.status === "MISMATCH") {
|
|
63
116
|
errors.push({
|
|
64
117
|
code: "E_RECEIPT_PATH_MISMATCH",
|
|
65
118
|
message: "Receipt changedPaths do not match observed repository paths",
|
|
66
|
-
artifacts: [
|
|
119
|
+
artifacts: [receiptRel],
|
|
67
120
|
missing: changedPaths.missing,
|
|
68
121
|
unexpected: changedPaths.unexpected,
|
|
69
122
|
next: "Run forgeloop prepare-completion to refresh changed paths, then rerun audit.",
|
|
@@ -94,10 +147,10 @@ export async function evaluateAudit({ target, packageRoot, strict = false, autho
|
|
|
94
147
|
publicationStatus: completion.publicationStatus,
|
|
95
148
|
productionReadiness: completion.productionReadiness,
|
|
96
149
|
artifacts: {
|
|
97
|
-
contract:
|
|
98
|
-
route:
|
|
99
|
-
state:
|
|
100
|
-
receipt:
|
|
150
|
+
contract: contractRel,
|
|
151
|
+
route: routeRel,
|
|
152
|
+
state: stateRel,
|
|
153
|
+
receipt: receiptRel,
|
|
101
154
|
},
|
|
102
155
|
};
|
|
103
156
|
}
|
package/src/core/bundles.js
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { readdir } from "node:fs/promises";
|
|
2
2
|
|
|
3
3
|
import { ARTIFACT_PATHS, readJsonArtifact, writeJsonArtifact } from "./artifacts.js";
|
|
4
|
-
import {
|
|
4
|
+
import { validateContract } from "./contract.js";
|
|
5
5
|
import { assertSafePath, ensureWithin, fileExists, readBytes, writeFileAtomic } from "./filesystem.js";
|
|
6
6
|
import { PROTOCOL_VERSION } from "./protocol.js";
|
|
7
7
|
import { validateChecksExecutionProvenance } from "./completion-artifacts.js";
|
|
8
8
|
import { readExecutionArtifact } from "./execution.js";
|
|
9
9
|
import { assertContinuitySemantics } from "./continuity.js";
|
|
10
|
+
import { taskArtifactPath, taskDirectory } from "./task-paths.js";
|
|
10
11
|
|
|
11
12
|
export const BUNDLE_SCHEMA_VERSION = 1;
|
|
12
13
|
const BUNDLE_ROOT = ".forgeloop/tasks";
|
|
@@ -36,88 +37,116 @@ async function copyJson(target, sourcePath, destinationPath, schemaName, package
|
|
|
36
37
|
}
|
|
37
38
|
}
|
|
38
39
|
|
|
40
|
+
async function tryReadJson(target, taskPath, legacyPath, schemaName, packageRoot) {
|
|
41
|
+
try {
|
|
42
|
+
return await readJsonArtifact(target, taskPath, schemaName, packageRoot);
|
|
43
|
+
} catch (error) {
|
|
44
|
+
if (error.code === "ARTIFACT_MISSING" && legacyPath) {
|
|
45
|
+
return await readJsonArtifact(target, legacyPath, schemaName, packageRoot);
|
|
46
|
+
}
|
|
47
|
+
throw error;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
39
51
|
export async function exportTaskBundle(target, taskId, packageRoot) {
|
|
40
52
|
safeTaskId(taskId);
|
|
41
53
|
const directory = bundleDirectory(taskId);
|
|
42
54
|
const artifacts = [];
|
|
43
|
-
|
|
55
|
+
|
|
56
|
+
const stateSource = await tryReadJson(target, taskArtifactPath(taskId, "state"), ARTIFACT_PATHS.state, "work-state", packageRoot);
|
|
44
57
|
let receiptSource = null;
|
|
45
58
|
try {
|
|
46
|
-
receiptSource = await
|
|
59
|
+
receiptSource = await tryReadJson(target, taskArtifactPath(taskId, "receipt"), ARTIFACT_PATHS.receipt, "execution-receipt", packageRoot);
|
|
47
60
|
} catch (error) {
|
|
48
61
|
if (error.code !== "ARTIFACT_MISSING") throw error;
|
|
49
62
|
}
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
63
|
+
|
|
64
|
+
await validateChecksExecutionProvenance(stateSource.value.checks, {
|
|
65
|
+
target,
|
|
66
|
+
packageRoot,
|
|
67
|
+
taskId,
|
|
68
|
+
artifactPath: ARTIFACT_PATHS.state,
|
|
69
|
+
});
|
|
70
|
+
if (receiptSource?.value?.checks) {
|
|
71
|
+
await validateChecksExecutionProvenance(receiptSource.value.checks, {
|
|
58
72
|
target,
|
|
59
73
|
packageRoot,
|
|
60
74
|
taskId,
|
|
61
75
|
artifactPath: ARTIFACT_PATHS.receipt,
|
|
62
|
-
})
|
|
63
|
-
];
|
|
64
|
-
if (provenanceErrors.length > 0) {
|
|
65
|
-
const first = provenanceErrors[0];
|
|
66
|
-
const error = new Error(first.message);
|
|
67
|
-
error.code = first.code;
|
|
68
|
-
error.artifacts = first.artifacts;
|
|
69
|
-
throw error;
|
|
76
|
+
});
|
|
70
77
|
}
|
|
78
|
+
|
|
71
79
|
const required = [
|
|
72
|
-
[ARTIFACT_PATHS.contract, "contract.json", "current-contract"],
|
|
73
|
-
[ARTIFACT_PATHS.route, "route.json", "routing-result"],
|
|
74
|
-
[ARTIFACT_PATHS.state, "state.json", "work-state"],
|
|
80
|
+
[taskArtifactPath(taskId, "contract"), ARTIFACT_PATHS.contract, "contract.json", "current-contract"],
|
|
81
|
+
[taskArtifactPath(taskId, "route"), ARTIFACT_PATHS.route, "route.json", "routing-result"],
|
|
82
|
+
[taskArtifactPath(taskId, "state"), ARTIFACT_PATHS.state, "state.json", "work-state"],
|
|
75
83
|
];
|
|
76
|
-
for (const [
|
|
77
|
-
const source = schemaName
|
|
78
|
-
|
|
79
|
-
|
|
84
|
+
for (const [taskRel, legacyRel, destinationName, schemaName] of required) {
|
|
85
|
+
const source = await tryReadJson(target, taskRel, legacyRel, schemaName, packageRoot);
|
|
86
|
+
if (schemaName === "current-contract") {
|
|
87
|
+
await validateContract(source.value, packageRoot);
|
|
88
|
+
}
|
|
80
89
|
if (source.value.taskId !== undefined && source.value.taskId !== taskId) {
|
|
81
|
-
const error = new Error(`${
|
|
90
|
+
const error = new Error(`${taskRel} belongs to ${source.value.taskId}, not ${taskId}`);
|
|
82
91
|
error.code = "E_BUNDLE_TASK_MISMATCH";
|
|
83
92
|
throw error;
|
|
84
93
|
}
|
|
85
94
|
await writeJsonArtifact(target, `${directory}/${destinationName}`, source.value, schemaName, packageRoot);
|
|
86
95
|
artifacts.push(destinationName);
|
|
87
96
|
}
|
|
97
|
+
|
|
88
98
|
const optional = [
|
|
89
|
-
[ARTIFACT_PATHS.preflight, "preflight.json", "preflight"],
|
|
90
|
-
[ARTIFACT_PATHS.receipt, "receipt.json", "execution-receipt"],
|
|
91
|
-
[
|
|
92
|
-
[ARTIFACT_PATHS.
|
|
93
|
-
[ARTIFACT_PATHS.
|
|
99
|
+
[taskArtifactPath(taskId, "preflight"), ARTIFACT_PATHS.preflight, "preflight.json", "preflight"],
|
|
100
|
+
[taskArtifactPath(taskId, "receipt"), ARTIFACT_PATHS.receipt, "receipt.json", "execution-receipt"],
|
|
101
|
+
[taskArtifactPath(taskId, "descriptor"), null, "task.json", "task-descriptor"],
|
|
102
|
+
[ARTIFACT_PATHS.sources, null, "sources.json", "source-registry"],
|
|
103
|
+
[ARTIFACT_PATHS.config, null, "config.json", "config"],
|
|
104
|
+
[taskArtifactPath(taskId, "continuity"), ARTIFACT_PATHS.continuity, "continuity.json", "continuity"],
|
|
94
105
|
];
|
|
95
|
-
for (const [
|
|
96
|
-
|
|
106
|
+
for (const [taskRel, legacyRel, destinationName, schemaName] of optional) {
|
|
107
|
+
let copied = null;
|
|
108
|
+
try {
|
|
109
|
+
copied = await copyJson(target, taskRel, `${directory}/${destinationName}`, schemaName, packageRoot, artifacts, destinationName);
|
|
110
|
+
} catch {
|
|
111
|
+
if (legacyRel) {
|
|
112
|
+
copied = await copyJson(target, legacyRel, `${directory}/${destinationName}`, schemaName, packageRoot, artifacts, destinationName);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
97
115
|
if (copied && !artifacts.includes(destinationName)) artifacts.push(destinationName);
|
|
98
116
|
}
|
|
117
|
+
|
|
99
118
|
const executionRefs = [...new Set([
|
|
100
119
|
...(stateSource.value.checks ?? []),
|
|
101
120
|
...(receiptSource?.value?.checks ?? []),
|
|
102
121
|
].map((check) => check?.executionRef).filter(Boolean))].sort();
|
|
103
122
|
for (const executionRef of executionRefs) {
|
|
104
|
-
const execution = await readExecutionArtifact({ target, executionRef, packageRoot });
|
|
123
|
+
const execution = await readExecutionArtifact({ target, executionRef, packageRoot, taskId });
|
|
105
124
|
const destination = `${directory}/executions/${execution.value.executionId}.json`;
|
|
106
125
|
await writeJsonArtifact(target, destination, execution.value, "execution", packageRoot);
|
|
107
126
|
artifacts.push(`executions/${execution.value.executionId}.json`);
|
|
108
127
|
}
|
|
109
|
-
|
|
128
|
+
|
|
129
|
+
// Events
|
|
130
|
+
let eventsPath = ensureWithin(target, taskArtifactPath(taskId, "events"));
|
|
131
|
+
if (!(await fileExists(eventsPath))) {
|
|
132
|
+
eventsPath = ensureWithin(target, ARTIFACT_PATHS.events);
|
|
133
|
+
}
|
|
110
134
|
if (await fileExists(eventsPath)) {
|
|
111
135
|
await assertSafePath(target, `${directory}/events.ndjson`);
|
|
112
136
|
await writeFileAtomic(ensureWithin(target, `${directory}/events.ndjson`), await readBytes(eventsPath));
|
|
113
137
|
artifacts.push("events.ndjson");
|
|
114
138
|
}
|
|
115
|
-
|
|
139
|
+
|
|
140
|
+
// Gates
|
|
141
|
+
let gateDirectory = ensureWithin(target, `${taskDirectory(taskId)}/gates`);
|
|
142
|
+
if (!(await fileExists(gateDirectory))) {
|
|
143
|
+
gateDirectory = ensureWithin(target, ARTIFACT_PATHS.gates);
|
|
144
|
+
}
|
|
116
145
|
if (await fileExists(gateDirectory)) {
|
|
117
146
|
const entries = await readdir(gateDirectory, { withFileTypes: true });
|
|
118
147
|
for (const entry of entries.filter((item) => item.isFile() && item.name.endsWith(".json")).sort((left, right) => left.name.localeCompare(right.name))) {
|
|
119
148
|
const gateName = entry.name.slice(0, -5);
|
|
120
|
-
const sourcePath = `${
|
|
149
|
+
const sourcePath = `${gateDirectory.replace(target + "/", "")}/${entry.name}`;
|
|
121
150
|
const destinationPath = `${directory}/gates/${entry.name}`;
|
|
122
151
|
const gate = await readJsonArtifact(target, sourcePath, "gate", packageRoot);
|
|
123
152
|
if (gate.value.taskId !== taskId) continue;
|
|
@@ -125,6 +154,7 @@ export async function exportTaskBundle(target, taskId, packageRoot) {
|
|
|
125
154
|
artifacts.push(`gates/${gateName}.json`);
|
|
126
155
|
}
|
|
127
156
|
}
|
|
157
|
+
|
|
128
158
|
artifacts.sort();
|
|
129
159
|
const manifest = {
|
|
130
160
|
schemaVersion: BUNDLE_SCHEMA_VERSION,
|
|
@@ -149,6 +179,7 @@ export async function readTaskBundle(target, taskId, packageRoot) {
|
|
|
149
179
|
"sources.json": ["sources", "source-registry"],
|
|
150
180
|
"config.json": ["config", "config"],
|
|
151
181
|
"continuity.json": ["continuity", "continuity"],
|
|
182
|
+
"task.json": ["descriptor", "task-descriptor"],
|
|
152
183
|
};
|
|
153
184
|
const executions = {};
|
|
154
185
|
for (const artifact of manifest.value.artifacts) {
|
|
@@ -169,30 +200,25 @@ export async function readTaskBundle(target, taskId, packageRoot) {
|
|
|
169
200
|
loaded[mapping[0]] = loadedArtifact.value;
|
|
170
201
|
}
|
|
171
202
|
if (Object.keys(executions).length > 0) loaded.executions = executions;
|
|
172
|
-
|
|
173
|
-
|
|
203
|
+
if (loaded.state?.checks) {
|
|
204
|
+
await validateChecksExecutionProvenance(loaded.state.checks, {
|
|
174
205
|
target,
|
|
175
206
|
packageRoot,
|
|
176
207
|
taskId,
|
|
177
208
|
executionArtifacts: executions,
|
|
178
209
|
allowForeignCwd: true,
|
|
179
210
|
artifactPath: "state.json",
|
|
180
|
-
})
|
|
181
|
-
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
if (loaded.receipt?.checks) {
|
|
214
|
+
await validateChecksExecutionProvenance(loaded.receipt.checks, {
|
|
182
215
|
target,
|
|
183
216
|
packageRoot,
|
|
184
217
|
taskId,
|
|
185
218
|
executionArtifacts: executions,
|
|
186
219
|
allowForeignCwd: true,
|
|
187
220
|
artifactPath: "receipt.json",
|
|
188
|
-
})
|
|
189
|
-
];
|
|
190
|
-
if (provenanceErrors.length > 0) {
|
|
191
|
-
const first = provenanceErrors[0];
|
|
192
|
-
const error = new Error(first.message);
|
|
193
|
-
error.code = first.code;
|
|
194
|
-
error.artifacts = first.artifacts;
|
|
195
|
-
throw error;
|
|
221
|
+
});
|
|
196
222
|
}
|
|
197
223
|
return { manifest: manifest.value, artifacts: loaded };
|
|
198
224
|
}
|