@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/cli.js
CHANGED
|
@@ -31,137 +31,158 @@ import { formatContinuityResult, runContinuity } from "./commands/continuity.js"
|
|
|
31
31
|
import { formatRecordContinuityResult, runRecordContinuity } from "./commands/record-continuity.js";
|
|
32
32
|
import { formatReconcileContinuityResult, runReconcileContinuity } from "./commands/reconcile-continuity.js";
|
|
33
33
|
import { formatClearContinuityResult, runClearContinuity } from "./commands/clear-continuity.js";
|
|
34
|
-
import {
|
|
34
|
+
import { formatTaskCreateResult, runTaskCreate } from "./commands/task-create.js";
|
|
35
|
+
import { formatTaskListResult, runTaskList } from "./commands/task-list.js";
|
|
36
|
+
import { formatTaskShowResult, runTaskShow } from "./commands/task-show.js";
|
|
37
|
+
import { formatTaskScopeResult, runTaskScope } from "./commands/task-scope.js";
|
|
38
|
+
import { formatTaskMigrateResult, runTaskMigrate } from "./commands/task-migrate.js";
|
|
39
|
+
import { formatTaskUnlockResult, runTaskUnlock } from "./commands/task-unlock.js";
|
|
40
|
+
import { continuityOptionDefaults, validateContinuityOptions } from "./core/continuity-cli-options.js";
|
|
35
41
|
import { resolveTarget } from "./core/filesystem.js";
|
|
36
42
|
import { getPackageRoot } from "./core/templates.js";
|
|
37
|
-
import {
|
|
38
|
-
|
|
39
|
-
export const COMMANDS = Object.freeze(
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
"preflight",
|
|
46
|
-
"advance",
|
|
47
|
-
"next",
|
|
48
|
-
"continuity",
|
|
49
|
-
"record-continuity",
|
|
50
|
-
"reconcile-continuity",
|
|
51
|
-
"clear-continuity",
|
|
52
|
-
"prepare-completion",
|
|
53
|
-
"run-check",
|
|
54
|
-
"record-check",
|
|
55
|
-
"record-terminal-result",
|
|
56
|
-
"complete",
|
|
57
|
-
"audit",
|
|
58
|
-
"report",
|
|
59
|
-
"policy",
|
|
60
|
-
"bundle",
|
|
61
|
-
"inspect",
|
|
62
|
-
"status",
|
|
63
|
-
"validate-state",
|
|
64
|
-
"clear-state",
|
|
65
|
-
"validate-receipt",
|
|
66
|
-
"validate-protocol",
|
|
67
|
-
]);
|
|
68
|
-
|
|
69
|
-
// Commands whose usage blocks already describe --json (doctor, route) or that
|
|
70
|
-
// accept no --json at all (init, update).
|
|
71
|
-
const GENERIC_JSON_EXCLUDED_COMMANDS = new Set(["init", "doctor", "update", "route"]);
|
|
72
|
-
|
|
73
|
-
function usage(command = null) {
|
|
74
|
-
const commands = COMMANDS.join("|");
|
|
75
|
-
const options = [" --path <directory> target project directory (default: current directory)"];
|
|
76
|
-
if (!command || command === "init" || command === "update") {
|
|
77
|
-
options.push(" --dry-run show planned writes without changing files");
|
|
78
|
-
}
|
|
79
|
-
if (!command || command === "doctor") {
|
|
80
|
-
options.push(" --json emit doctor findings as JSON");
|
|
81
|
-
options.push(" --strict treat warnings as unhealthy");
|
|
82
|
-
options.push(" --fix restore missing managed template files");
|
|
83
|
-
options.push(" --adopt <path> preserve an existing adapter in the manifest");
|
|
84
|
-
}
|
|
85
|
-
if (!command || command === "route") {
|
|
86
|
-
options.push(" --work <type> declared work type");
|
|
87
|
-
options.push(" --surface <value> affected surface (repeatable)");
|
|
88
|
-
options.push(" --risk <value> task risk (repeatable)");
|
|
89
|
-
options.push(" --platform <value> affected platform (repeatable)");
|
|
90
|
-
options.push(" --behavior-change declare behavior change");
|
|
91
|
-
options.push(" --executable-change declare executable/configuration change");
|
|
92
|
-
options.push(" --json emit route result as JSON");
|
|
93
|
-
}
|
|
94
|
-
if (!command || command === "advance") {
|
|
95
|
-
options.push(" --to <phase> destination workflow phase");
|
|
96
|
-
}
|
|
97
|
-
if (!command || command === "record-continuity") {
|
|
98
|
-
options.push(" --focus-id <id> current implementation focus ID");
|
|
99
|
-
options.push(" --focus-summary <text> current implementation focus summary");
|
|
100
|
-
options.push(" --remaining <id:summary> remaining implementation item (repeatable)");
|
|
101
|
-
options.push(" --known-issue <id:summary> known implementation issue (repeatable)");
|
|
102
|
-
options.push(" --changed-area <path> changed project area (repeatable)");
|
|
103
|
-
options.push(" --inspect-first <path> suggested inspection path (repeatable)");
|
|
104
|
-
options.push(" --resume-note <text> bounded operational resume note");
|
|
105
|
-
}
|
|
106
|
-
if (!command || !GENERIC_JSON_EXCLUDED_COMMANDS.has(command)) {
|
|
107
|
-
options.push(" --json emit structured output as JSON");
|
|
108
|
-
}
|
|
109
|
-
if (!command || ["preflight", "complete", "audit", "report"].includes(command)) {
|
|
110
|
-
options.push(" --strict require strict protocol compliance");
|
|
111
|
-
}
|
|
112
|
-
if (!command || command === "policy") {
|
|
113
|
-
options.push(" <name> policy pack name");
|
|
114
|
-
}
|
|
115
|
-
if (!command || command === "bundle") {
|
|
116
|
-
options.push(" --task <id> task ID to export as a portable bundle");
|
|
43
|
+
import { CLI_COMMAND_DEFINITIONS, buildOptionLookup, getPositionalDefinitions } from "./core/cli-command-definitions.js";
|
|
44
|
+
|
|
45
|
+
export const COMMANDS = Object.freeze(Object.keys(CLI_COMMAND_DEFINITIONS));
|
|
46
|
+
|
|
47
|
+
function formatOptionUsage(optKey, optDef) {
|
|
48
|
+
let label = optKey;
|
|
49
|
+
if (optDef.valueName) {
|
|
50
|
+
label = optKey === "--" ? `-- <${optDef.valueName}>` : `${optKey} <${optDef.valueName}>`;
|
|
117
51
|
}
|
|
118
|
-
|
|
119
|
-
|
|
52
|
+
return ` ${label.padEnd(20)} ${optDef.description}`;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export function usage(command = null) {
|
|
56
|
+
if (command && CLI_COMMAND_DEFINITIONS[command]) {
|
|
57
|
+
const def = CLI_COMMAND_DEFINITIONS[command];
|
|
58
|
+
const lines = Object.entries(def.options).map(([optKey, optDef]) => formatOptionUsage(optKey, optDef));
|
|
59
|
+
return `Usage: forgeloop <${command}> [options]\n\nOptions:\n${lines.join("\n")}\n`;
|
|
120
60
|
}
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
61
|
+
|
|
62
|
+
const allOptions = new Map();
|
|
63
|
+
for (const def of Object.values(CLI_COMMAND_DEFINITIONS)) {
|
|
64
|
+
for (const [optKey, optDef] of Object.entries(def.options)) {
|
|
65
|
+
if (!allOptions.has(optKey)) {
|
|
66
|
+
allOptions.set(optKey, optDef);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
128
69
|
}
|
|
129
|
-
|
|
130
|
-
|
|
70
|
+
|
|
71
|
+
const lines = [...allOptions.entries()].map(([optKey, optDef]) => formatOptionUsage(optKey, optDef));
|
|
72
|
+
const commands = COMMANDS.join("|");
|
|
73
|
+
return `Usage: forgeloop <${commands}> [options]\n\nOptions:\n${lines.join("\n")}\n`;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export function splitLongOption(argument) {
|
|
77
|
+
if (!argument.startsWith("--")) {
|
|
78
|
+
return { name: argument, inlineValue: undefined };
|
|
131
79
|
}
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
options.push(" --details <json> additional structured check details");
|
|
80
|
+
const index = argument.indexOf("=");
|
|
81
|
+
if (index === -1) {
|
|
82
|
+
return { name: argument, inlineValue: undefined };
|
|
136
83
|
}
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
84
|
+
return {
|
|
85
|
+
name: argument.slice(0, index),
|
|
86
|
+
inlineValue: argument.slice(index + 1),
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function applyOption({ canonicalName, optionDef, inlineValue, argv, index, options, suppliedFlags }) {
|
|
91
|
+
const key = optionDef.targetKey;
|
|
92
|
+
suppliedFlags.add(canonicalName);
|
|
93
|
+
|
|
94
|
+
if (inlineValue !== undefined && !optionDef.takesValue) {
|
|
95
|
+
throw new Error(`${canonicalName} does not accept a value`);
|
|
146
96
|
}
|
|
147
|
-
|
|
148
|
-
|
|
97
|
+
|
|
98
|
+
switch (optionDef.parseType) {
|
|
99
|
+
case "boolean": {
|
|
100
|
+
options[key] = true;
|
|
101
|
+
return { index };
|
|
102
|
+
}
|
|
103
|
+
case "string": {
|
|
104
|
+
const value = inlineValue ?? argv[index + 1];
|
|
105
|
+
if (
|
|
106
|
+
value === undefined ||
|
|
107
|
+
(value.length === 0 && !optionDef.allowEmpty) ||
|
|
108
|
+
(value.startsWith("-") && inlineValue === undefined && !optionDef.allowLeadingHyphen)
|
|
109
|
+
) {
|
|
110
|
+
throw new Error(optionDef.missingValueMessage ?? `${canonicalName} requires a value`);
|
|
111
|
+
}
|
|
112
|
+
if (optionDef.repeatable) {
|
|
113
|
+
if (!Array.isArray(options[key])) options[key] = [];
|
|
114
|
+
options[key].push(value);
|
|
115
|
+
} else {
|
|
116
|
+
options[key] = value;
|
|
117
|
+
}
|
|
118
|
+
return { index: inlineValue === undefined ? index + 1 : index };
|
|
119
|
+
}
|
|
120
|
+
case "non-negative-integer": {
|
|
121
|
+
const value = inlineValue ?? argv[index + 1];
|
|
122
|
+
if (value === undefined || !/^\d+$/.test(value)) {
|
|
123
|
+
throw new Error(optionDef.missingValueMessage ?? `${canonicalName} requires a non-negative integer`);
|
|
124
|
+
}
|
|
125
|
+
options[key] = Number(value);
|
|
126
|
+
return { index: inlineValue === undefined ? index + 1 : index };
|
|
127
|
+
}
|
|
128
|
+
case "json-object": {
|
|
129
|
+
const raw = inlineValue ?? argv[index + 1];
|
|
130
|
+
if (!raw || (raw.startsWith("-") && inlineValue === undefined)) {
|
|
131
|
+
throw new Error(optionDef.missingValueMessage ?? `${canonicalName} requires a JSON object`);
|
|
132
|
+
}
|
|
133
|
+
let parsed;
|
|
134
|
+
try {
|
|
135
|
+
parsed = JSON.parse(raw);
|
|
136
|
+
} catch {
|
|
137
|
+
throw new Error(`${canonicalName} must be valid JSON`);
|
|
138
|
+
}
|
|
139
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
140
|
+
throw new Error(`${canonicalName} must be a JSON object`);
|
|
141
|
+
}
|
|
142
|
+
options[key] = parsed;
|
|
143
|
+
return { index: inlineValue === undefined ? index + 1 : index };
|
|
144
|
+
}
|
|
145
|
+
case "argv": {
|
|
146
|
+
const remaining = argv.slice(index + 1);
|
|
147
|
+
options[key] = remaining;
|
|
148
|
+
return { index: argv.length, stop: true };
|
|
149
|
+
}
|
|
150
|
+
default:
|
|
151
|
+
throw new Error(`Unsupported option type: ${optionDef.parseType}`);
|
|
149
152
|
}
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
const ALL_VALUE_TAKING_FLAGS = new Set();
|
|
156
|
+
for (const def of Object.values(CLI_COMMAND_DEFINITIONS)) {
|
|
157
|
+
for (const [optName, optDef] of Object.entries(def.options)) {
|
|
158
|
+
if (optDef.takesValue && optName.startsWith("-")) {
|
|
159
|
+
ALL_VALUE_TAKING_FLAGS.add(optName);
|
|
160
|
+
}
|
|
157
161
|
}
|
|
158
|
-
|
|
159
|
-
options.push(" --help show this help");
|
|
162
|
+
}
|
|
160
163
|
|
|
161
|
-
|
|
164
|
+
export function discoverCommand(argv) {
|
|
165
|
+
for (let i = 0; i < argv.length; i += 1) {
|
|
166
|
+
const arg = argv[i];
|
|
167
|
+
if (arg === "--") break;
|
|
168
|
+
|
|
169
|
+
if (arg.startsWith("-")) {
|
|
170
|
+
const eqIdx = arg.indexOf("=");
|
|
171
|
+
const optName = eqIdx === -1 ? arg : arg.slice(0, eqIdx);
|
|
172
|
+
if (eqIdx === -1 && ALL_VALUE_TAKING_FLAGS.has(optName)) {
|
|
173
|
+
i += 1; // Skip the option's value so it is never scanned as a candidate command
|
|
174
|
+
}
|
|
175
|
+
continue;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
if (COMMANDS.includes(arg)) {
|
|
179
|
+
return arg;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
return null;
|
|
162
183
|
}
|
|
163
184
|
|
|
164
|
-
export function
|
|
185
|
+
export function parseCliSyntax(argv) {
|
|
165
186
|
const options = {
|
|
166
187
|
path: ".",
|
|
167
188
|
dryRun: false,
|
|
@@ -204,242 +225,84 @@ export function parseArgs(argv) {
|
|
|
204
225
|
help: false,
|
|
205
226
|
version: false,
|
|
206
227
|
};
|
|
207
|
-
|
|
228
|
+
|
|
229
|
+
const command = discoverCommand(argv);
|
|
230
|
+
const bootstrapLookup = buildOptionLookup(null);
|
|
231
|
+
const commandLookup = buildOptionLookup(command);
|
|
232
|
+
const positionalDefs = getPositionalDefinitions(command);
|
|
233
|
+
let positionalCursor = 0;
|
|
234
|
+
const suppliedFlags = new Set();
|
|
235
|
+
let commandSeen = false;
|
|
208
236
|
|
|
209
237
|
for (let index = 0; index < argv.length; index += 1) {
|
|
210
238
|
const argument = argv[index];
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
} else if (argument === "--strict") {
|
|
221
|
-
options.strict = true;
|
|
222
|
-
} else if (argument === "--fix") {
|
|
223
|
-
options.fix = true;
|
|
224
|
-
} else if (argument === "--adopt") {
|
|
225
|
-
const relativePath = argv[index + 1];
|
|
226
|
-
if (!relativePath || relativePath.startsWith("-")) throw new Error("--adopt requires a path");
|
|
227
|
-
options.adopt.push(relativePath);
|
|
228
|
-
index += 1;
|
|
229
|
-
} else if (argument === "--work") {
|
|
230
|
-
const workType = argv[index + 1];
|
|
231
|
-
if (!workType || workType.startsWith("-")) throw new Error("--work requires a type");
|
|
232
|
-
options.work = workType;
|
|
233
|
-
index += 1;
|
|
234
|
-
} else if (argument === "--surface") {
|
|
235
|
-
const surface = argv[index + 1];
|
|
236
|
-
if (!surface || surface.startsWith("-")) throw new Error("--surface requires a value");
|
|
237
|
-
options.surfaces.push(surface);
|
|
238
|
-
index += 1;
|
|
239
|
-
} else if (argument === "--risk") {
|
|
240
|
-
const risk = argv[index + 1];
|
|
241
|
-
if (!risk || risk.startsWith("-")) throw new Error("--risk requires a value");
|
|
242
|
-
options.risks.push(risk);
|
|
243
|
-
index += 1;
|
|
244
|
-
} else if (argument === "--platform") {
|
|
245
|
-
const platform = argv[index + 1];
|
|
246
|
-
if (!platform || platform.startsWith("-")) throw new Error("--platform requires a value");
|
|
247
|
-
options.platforms.push(platform);
|
|
248
|
-
index += 1;
|
|
249
|
-
} else if (argument === "--behavior-change") {
|
|
250
|
-
options.behaviorChange = true;
|
|
251
|
-
} else if (argument === "--executable-change") {
|
|
252
|
-
options.executableChange = true;
|
|
253
|
-
} else if (argument === "--to") {
|
|
254
|
-
const phase = argv[index + 1];
|
|
255
|
-
if (!phase || phase.startsWith("-")) throw new Error("--to requires a phase");
|
|
256
|
-
options.to = phase;
|
|
257
|
-
index += 1;
|
|
258
|
-
} else if (argument === "--task") {
|
|
259
|
-
const task = argv[index + 1];
|
|
260
|
-
if (!task || task.startsWith("-")) throw new Error("--task requires an ID");
|
|
261
|
-
options.task = task;
|
|
262
|
-
index += 1;
|
|
263
|
-
} else if (argument === "--file") {
|
|
264
|
-
const file = argv[index + 1];
|
|
265
|
-
if (!file || file.startsWith("-")) throw new Error("--file requires a path");
|
|
266
|
-
options.file = file;
|
|
267
|
-
index += 1;
|
|
268
|
-
} else if (argument === "--contract-file") {
|
|
269
|
-
const contractFile = argv[index + 1];
|
|
270
|
-
if (!contractFile || contractFile.startsWith("-")) throw new Error("--contract-file requires a path");
|
|
271
|
-
options.contractFile = contractFile;
|
|
272
|
-
index += 1;
|
|
273
|
-
} else if (["--route-file", "--state-file", "--receipt-file", "--continuity-file"].includes(argument)) {
|
|
274
|
-
const file = argv[index + 1];
|
|
275
|
-
if (!file || file.startsWith("-")) throw new Error(`${argument} requires a path`);
|
|
276
|
-
if (argument === "--route-file") options.routeFile = file;
|
|
277
|
-
if (argument === "--state-file") options.stateFile = file;
|
|
278
|
-
if (argument === "--receipt-file") options.receiptFile = file;
|
|
279
|
-
if (argument === "--continuity-file") options.continuityFile = file;
|
|
280
|
-
index += 1;
|
|
281
|
-
} else if (argument === "--task-brief-file") {
|
|
282
|
-
const file = argv[index + 1];
|
|
283
|
-
if (!file || file.startsWith("-")) throw new Error("--task-brief-file requires a path");
|
|
284
|
-
options.taskBriefFiles.push(file);
|
|
285
|
-
index += 1;
|
|
286
|
-
} else if (argument === "--delegated-result-file") {
|
|
287
|
-
const file = argv[index + 1];
|
|
288
|
-
if (!file || file.startsWith("-")) throw new Error("--delegated-result-file requires a path");
|
|
289
|
-
options.delegatedResultFiles.push(file);
|
|
290
|
-
index += 1;
|
|
291
|
-
} else if (argument === "--id") {
|
|
292
|
-
const id = argv[index + 1];
|
|
293
|
-
if (!id || id.startsWith("-")) throw new Error("--id requires a check ID");
|
|
294
|
-
options.checkId = id;
|
|
295
|
-
index += 1;
|
|
296
|
-
} else if (argument.startsWith("--id=")) {
|
|
297
|
-
const id = argument.slice("--id=".length);
|
|
298
|
-
if (!id || id.startsWith("-")) throw new Error("--id requires a check ID");
|
|
299
|
-
options.checkId = id;
|
|
300
|
-
} else if (argument === "--kind") {
|
|
301
|
-
const kind = argv[index + 1];
|
|
302
|
-
if (!kind || kind.startsWith("-")) throw new Error("--kind requires a check kind");
|
|
303
|
-
options.checkKind = kind;
|
|
304
|
-
index += 1;
|
|
305
|
-
} else if (argument === "--requirement") {
|
|
306
|
-
const requirement = argv[index + 1];
|
|
307
|
-
if (!requirement || requirement.startsWith("-")) throw new Error("--requirement requires an evidence target");
|
|
308
|
-
options.checkRequirement = requirement;
|
|
309
|
-
index += 1;
|
|
310
|
-
} else if (argument.startsWith("--requirement=")) {
|
|
311
|
-
const requirement = argument.slice("--requirement=".length);
|
|
312
|
-
if (!requirement) throw new Error("--requirement requires an evidence target");
|
|
313
|
-
options.checkRequirement = requirement;
|
|
314
|
-
} else if (argument === "--status") {
|
|
315
|
-
const status = argv[index + 1];
|
|
316
|
-
if (!status || status.startsWith("-")) throw new Error("--status requires a check status");
|
|
317
|
-
options.checkStatus = status;
|
|
318
|
-
index += 1;
|
|
319
|
-
} else if (argument === "--evidence-kind") {
|
|
320
|
-
const evidenceKind = argv[index + 1];
|
|
321
|
-
if (!evidenceKind || evidenceKind.startsWith("-")) throw new Error("--evidence-kind requires an evidence kind");
|
|
322
|
-
options.checkEvidenceKind = evidenceKind;
|
|
323
|
-
index += 1;
|
|
324
|
-
} else if (argument === "--command") {
|
|
325
|
-
const commandText = argv[index + 1];
|
|
326
|
-
if (!commandText || commandText.startsWith("-")) throw new Error("--command requires recorded text");
|
|
327
|
-
options.checkCommand = commandText;
|
|
328
|
-
index += 1;
|
|
329
|
-
} else if (argument === "--source") {
|
|
330
|
-
const sourceText = argv[index + 1];
|
|
331
|
-
if (!sourceText || sourceText.startsWith("-")) throw new Error("--source requires recorded text");
|
|
332
|
-
options.checkSource = sourceText;
|
|
333
|
-
index += 1;
|
|
334
|
-
} else if (argument.startsWith("--source=")) {
|
|
335
|
-
const sourceText = argument.slice("--source=".length);
|
|
336
|
-
if (!sourceText) throw new Error("--source requires recorded text");
|
|
337
|
-
options.checkSource = sourceText;
|
|
338
|
-
} else if (argument === "--type") {
|
|
339
|
-
const typeValue = argv[index + 1];
|
|
340
|
-
if (!typeValue || typeValue.startsWith("-")) throw new Error("--type requires a terminal type");
|
|
341
|
-
options.checkType = typeValue;
|
|
342
|
-
index += 1;
|
|
343
|
-
} else if (argument.startsWith("--type=")) {
|
|
344
|
-
const typeValue = argument.slice("--type=".length);
|
|
345
|
-
if (!typeValue) throw new Error("--type requires a terminal type");
|
|
346
|
-
options.checkType = typeValue;
|
|
347
|
-
} else if (argument === "--result") {
|
|
348
|
-
const resultText = argv[index + 1];
|
|
349
|
-
if (!resultText || resultText.startsWith("-")) throw new Error("--result requires recorded text");
|
|
350
|
-
options.checkResult = resultText;
|
|
351
|
-
index += 1;
|
|
352
|
-
} else if (argument.startsWith("--result=")) {
|
|
353
|
-
const resultText = argument.slice("--result=".length);
|
|
354
|
-
if (!resultText) throw new Error("--result requires recorded text");
|
|
355
|
-
options.checkResult = resultText;
|
|
356
|
-
} else if (argument === "--exit-code") {
|
|
357
|
-
const exitCode = argv[index + 1];
|
|
358
|
-
if (!exitCode || exitCode.startsWith("-")) throw new Error("--exit-code requires a non-negative integer");
|
|
359
|
-
if (!/^\d+$/.test(exitCode)) throw new Error("--exit-code requires a non-negative integer");
|
|
360
|
-
options.checkExitCode = Number(exitCode);
|
|
361
|
-
index += 1;
|
|
362
|
-
} else if (argument === "--details") {
|
|
363
|
-
const details = argv[index + 1];
|
|
364
|
-
if (!details || details.startsWith("-")) throw new Error("--details requires a JSON object");
|
|
365
|
-
try {
|
|
366
|
-
options.checkDetails = JSON.parse(details);
|
|
367
|
-
} catch {
|
|
368
|
-
throw new Error("--details must be valid JSON");
|
|
239
|
+
|
|
240
|
+
if (argument === command && !commandSeen) {
|
|
241
|
+
commandSeen = true;
|
|
242
|
+
continue;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
if (argument === "--") {
|
|
246
|
+
if (!commandSeen) {
|
|
247
|
+
throw new Error("-- is not valid before a command");
|
|
369
248
|
}
|
|
370
|
-
|
|
371
|
-
|
|
249
|
+
const passthrough = commandLookup.get("--");
|
|
250
|
+
if (!passthrough) {
|
|
251
|
+
throw new Error(`Unknown option: --`);
|
|
372
252
|
}
|
|
373
|
-
index
|
|
374
|
-
|
|
375
|
-
const executionRef = argv[index + 1];
|
|
376
|
-
if (!executionRef || executionRef.startsWith("-")) throw new Error("--execution-ref requires an execution ID");
|
|
377
|
-
options.checkExecutionRef = executionRef;
|
|
378
|
-
index += 1;
|
|
379
|
-
} else if (argument === "--provenance") {
|
|
380
|
-
const provenance = argv[index + 1];
|
|
381
|
-
if (!provenance || provenance.startsWith("-")) throw new Error("--provenance requires a provenance value");
|
|
382
|
-
options.checkProvenance = provenance;
|
|
383
|
-
index += 1;
|
|
384
|
-
} else if (argument === "--" && command === "run-check") {
|
|
385
|
-
options.commandArgv = argv.slice(index + 1);
|
|
253
|
+
options[passthrough.optionDef.targetKey] = argv.slice(index + 1);
|
|
254
|
+
suppliedFlags.add("--");
|
|
386
255
|
break;
|
|
387
|
-
}
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
if (
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
const { name: optName, inlineValue } = splitLongOption(argument);
|
|
259
|
+
const activeLookup = commandSeen ? commandLookup : bootstrapLookup;
|
|
260
|
+
const matched = activeLookup.get(optName);
|
|
261
|
+
|
|
262
|
+
if (matched) {
|
|
263
|
+
const res = applyOption({
|
|
264
|
+
canonicalName: matched.canonicalName,
|
|
265
|
+
optionDef: matched.optionDef,
|
|
266
|
+
inlineValue,
|
|
267
|
+
argv,
|
|
268
|
+
index,
|
|
269
|
+
options,
|
|
270
|
+
suppliedFlags,
|
|
271
|
+
});
|
|
272
|
+
index = res.index;
|
|
273
|
+
if (res.stop) break;
|
|
274
|
+
continue;
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
if (commandSeen && command && !argument.startsWith("-")) {
|
|
278
|
+
const positional = positionalDefs[positionalCursor];
|
|
279
|
+
if (positional) {
|
|
280
|
+
options[positional.targetKey] = argument;
|
|
281
|
+
positionalCursor += 1;
|
|
282
|
+
continue;
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
if (!commandSeen) {
|
|
287
|
+
if (!command) {
|
|
288
|
+
throw new Error(`Unknown option: ${argument}`);
|
|
289
|
+
}
|
|
290
|
+
throw new Error(`Option ${argument} is not valid before a command`);
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
if (command) {
|
|
294
|
+
throw new Error(`Option ${argument} is not valid for ${command}`);
|
|
411
295
|
} else {
|
|
412
296
|
throw new Error(`Unknown option: ${argument}`);
|
|
413
297
|
}
|
|
414
298
|
}
|
|
415
299
|
|
|
416
|
-
|
|
300
|
+
return { command, options };
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
export function validateCliSemantics({ command, options } = {}) {
|
|
304
|
+
if (!command) return;
|
|
417
305
|
|
|
418
|
-
const jsonCommands = ["doctor", "route", "activate", "advance", "next", "continuity", "record-continuity", "reconcile-continuity", "clear-continuity", "prepare-completion", "run-check", "record-check", "record-terminal-result", "preflight", "complete", "audit", "report", "policy", "bundle", "inspect", "status", "validate-state", "clear-state", "validate-receipt", "validate-protocol"];
|
|
419
|
-
if (!jsonCommands.includes(command) && options.json) {
|
|
420
|
-
throw new Error(`Option --json is not valid for ${command}`);
|
|
421
|
-
}
|
|
422
|
-
if (![
|
|
423
|
-
"init",
|
|
424
|
-
"update",
|
|
425
|
-
].includes(command) && options.dryRun) {
|
|
426
|
-
throw new Error(`Option --dry-run is not valid for ${command}`);
|
|
427
|
-
}
|
|
428
|
-
if (!["doctor", "preflight", "complete", "audit", "report"].includes(command) && options.strict) {
|
|
429
|
-
throw new Error(`Option --strict is not valid for ${command}`);
|
|
430
|
-
}
|
|
431
|
-
if (command !== "doctor" && options.adopt.length > 0) {
|
|
432
|
-
throw new Error(`Option --adopt is not valid for ${command}`);
|
|
433
|
-
}
|
|
434
|
-
if (command !== "doctor" && options.fix) {
|
|
435
|
-
throw new Error(`Option --fix is not valid for ${command}`);
|
|
436
|
-
}
|
|
437
|
-
if (command !== "route" && (options.work || options.surfaces.length || options.risks.length || options.platforms.length || options.behaviorChange || options.executableChange)) {
|
|
438
|
-
throw new Error(`Route options are not valid for ${command}`);
|
|
439
|
-
}
|
|
440
|
-
if (command !== "advance" && options.to) {
|
|
441
|
-
throw new Error(`Option --to is not valid for ${command}`);
|
|
442
|
-
}
|
|
443
306
|
if (command === "policy" && !options.policy) {
|
|
444
307
|
throw new Error("policy requires a name");
|
|
445
308
|
}
|
|
@@ -449,35 +312,12 @@ export function parseArgs(argv) {
|
|
|
449
312
|
if (command === "bundle" && !options.task) {
|
|
450
313
|
throw new Error("bundle requires --task");
|
|
451
314
|
}
|
|
452
|
-
if (command
|
|
453
|
-
throw new Error(
|
|
454
|
-
}
|
|
455
|
-
if (command !== "validate-receipt" && options.file) {
|
|
456
|
-
throw new Error(`Option --file is not valid for ${command}`);
|
|
457
|
-
}
|
|
458
|
-
if (!["status", "inspect", "validate-protocol"].includes(command) && options.contractFile) {
|
|
459
|
-
throw new Error(`Option --contract-file is not valid for ${command}`);
|
|
460
|
-
}
|
|
461
|
-
if (command !== "validate-protocol" && (options.routeFile || options.stateFile || options.receiptFile || options.continuityFile || options.taskBriefFiles.length > 0 || options.delegatedResultFiles.length > 0)) {
|
|
462
|
-
throw new Error(`Protocol artifact options are not valid for ${command}`);
|
|
463
|
-
}
|
|
464
|
-
const checkOptions = [
|
|
465
|
-
options.checkId,
|
|
466
|
-
options.checkKind,
|
|
467
|
-
options.checkRequirement,
|
|
468
|
-
options.checkStatus,
|
|
469
|
-
options.checkEvidenceKind,
|
|
470
|
-
options.checkCommand,
|
|
471
|
-
options.checkResult,
|
|
472
|
-
options.checkExitCode,
|
|
473
|
-
options.checkDetails,
|
|
474
|
-
options.checkExecutionRef,
|
|
475
|
-
options.checkProvenance,
|
|
476
|
-
];
|
|
477
|
-
if (!["record-check", "run-check"].includes(command) && checkOptions.some((value) => value !== null)) {
|
|
478
|
-
throw new Error(`Check recording options are not valid for ${command}`);
|
|
315
|
+
if (command === "task-create" && !options.task) {
|
|
316
|
+
throw new Error("task-create requires --task");
|
|
479
317
|
}
|
|
318
|
+
|
|
480
319
|
validateContinuityOptions(command, options);
|
|
320
|
+
|
|
481
321
|
if (command === "record-check" && !options.help) {
|
|
482
322
|
if (!options.checkId) throw new Error("record-check requires --id");
|
|
483
323
|
if (!options.checkRequirement) throw new Error("record-check requires --requirement");
|
|
@@ -496,7 +336,12 @@ export function parseArgs(argv) {
|
|
|
496
336
|
throw new Error("run-check requires -- followed by an exact command argv");
|
|
497
337
|
}
|
|
498
338
|
}
|
|
499
|
-
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
export function parseArgs(argv) {
|
|
342
|
+
const parsed = parseCliSyntax(argv);
|
|
343
|
+
validateCliSemantics(parsed);
|
|
344
|
+
return parsed;
|
|
500
345
|
}
|
|
501
346
|
|
|
502
347
|
async function packageVersion(packageRoot) {
|
|
@@ -547,6 +392,7 @@ export const COMMAND_HANDLERS = Object.freeze({
|
|
|
547
392
|
platforms: options.platforms,
|
|
548
393
|
behaviorChange: options.behaviorChange,
|
|
549
394
|
executableChange: options.executableChange,
|
|
395
|
+
taskId: options.task,
|
|
550
396
|
});
|
|
551
397
|
console.log(options.json ? JSON.stringify(result, null, 2) : formatRouteResult(result));
|
|
552
398
|
return 0;
|
|
@@ -557,22 +403,22 @@ export const COMMAND_HANDLERS = Object.freeze({
|
|
|
557
403
|
return 0;
|
|
558
404
|
},
|
|
559
405
|
preflight: async ({ target, packageRoot, options }) => {
|
|
560
|
-
const result = await runPreflight({ target, packageRoot, strict: options.strict });
|
|
406
|
+
const result = await runPreflight({ target, packageRoot, strict: options.strict, taskId: options.task });
|
|
561
407
|
console.log(options.json ? JSON.stringify(result, null, 2) : formatPreflightResult(result));
|
|
562
408
|
return result.status === "READY" ? 0 : 1;
|
|
563
409
|
},
|
|
564
410
|
advance: async ({ target, packageRoot, options }) => {
|
|
565
|
-
const result = await runAdvance({ target, packageRoot, to: options.to });
|
|
411
|
+
const result = await runAdvance({ target, packageRoot, to: options.to, taskId: options.task });
|
|
566
412
|
console.log(options.json ? JSON.stringify(result, null, 2) : formatAdvanceResult(result));
|
|
567
413
|
return 0;
|
|
568
414
|
},
|
|
569
415
|
next: async ({ target, packageRoot, options }) => {
|
|
570
|
-
const result = await runNext({ target, packageRoot });
|
|
416
|
+
const result = await runNext({ target, packageRoot, taskId: options.task });
|
|
571
417
|
console.log(options.json ? JSON.stringify(result, null, 2) : formatNextActionResult(result));
|
|
572
418
|
return 0;
|
|
573
419
|
},
|
|
574
420
|
continuity: async ({ target, packageRoot, options }) => {
|
|
575
|
-
const result = await runContinuity({ target, packageRoot });
|
|
421
|
+
const result = await runContinuity({ target, packageRoot, taskId: options.task });
|
|
576
422
|
console.log(options.json ? JSON.stringify(result, null, 2) : formatContinuityResult(result));
|
|
577
423
|
return 0;
|
|
578
424
|
},
|
|
@@ -586,22 +432,23 @@ export const COMMAND_HANDLERS = Object.freeze({
|
|
|
586
432
|
changedAreas: options.continuityChangedAreas,
|
|
587
433
|
inspectFirst: options.continuityInspectFirst,
|
|
588
434
|
resumeNote: options.continuityResumeNote,
|
|
435
|
+
taskId: options.task,
|
|
589
436
|
});
|
|
590
437
|
console.log(options.json ? JSON.stringify(result, null, 2) : formatRecordContinuityResult(result));
|
|
591
438
|
return 0;
|
|
592
439
|
},
|
|
593
440
|
"reconcile-continuity": async ({ target, packageRoot, options }) => {
|
|
594
|
-
const result = await runReconcileContinuity({ target, packageRoot });
|
|
441
|
+
const result = await runReconcileContinuity({ target, packageRoot, taskId: options.task });
|
|
595
442
|
console.log(options.json ? JSON.stringify(result, null, 2) : formatReconcileContinuityResult(result));
|
|
596
443
|
return 0;
|
|
597
444
|
},
|
|
598
445
|
"clear-continuity": async ({ target, options }) => {
|
|
599
|
-
const result = await runClearContinuity({ target });
|
|
446
|
+
const result = await runClearContinuity({ target, taskId: options.task });
|
|
600
447
|
console.log(options.json ? JSON.stringify(result, null, 2) : formatClearContinuityResult(result));
|
|
601
448
|
return 0;
|
|
602
449
|
},
|
|
603
450
|
"prepare-completion": async ({ target, packageRoot, options }) => {
|
|
604
|
-
const result = await runPrepareCompletion({ target, packageRoot });
|
|
451
|
+
const result = await runPrepareCompletion({ target, packageRoot, taskId: options.task });
|
|
605
452
|
console.log(options.json ? JSON.stringify(result, null, 2) : formatPrepareCompletionResult(result));
|
|
606
453
|
return 0;
|
|
607
454
|
},
|
|
@@ -613,6 +460,7 @@ export const COMMAND_HANDLERS = Object.freeze({
|
|
|
613
460
|
requirement: options.checkRequirement,
|
|
614
461
|
argv: options.commandArgv,
|
|
615
462
|
details: options.checkDetails ?? undefined,
|
|
463
|
+
taskId: options.task,
|
|
616
464
|
});
|
|
617
465
|
console.log(options.json ? JSON.stringify(result, null, 2) : formatRunCheckResult(result));
|
|
618
466
|
return result.check.status === "passed" ? 0 : 1;
|
|
@@ -632,6 +480,7 @@ export const COMMAND_HANDLERS = Object.freeze({
|
|
|
632
480
|
details: options.checkDetails ?? undefined,
|
|
633
481
|
executionRef: options.checkExecutionRef ?? undefined,
|
|
634
482
|
provenance: options.checkProvenance ?? undefined,
|
|
483
|
+
taskId: options.task,
|
|
635
484
|
});
|
|
636
485
|
console.log(options.json ? JSON.stringify(result, null, 2) : formatRecordCheckResult(result));
|
|
637
486
|
return 0;
|
|
@@ -646,27 +495,28 @@ export const COMMAND_HANDLERS = Object.freeze({
|
|
|
646
495
|
source: options.checkSource ?? options.checkCommand,
|
|
647
496
|
result: options.checkResult,
|
|
648
497
|
details: options.checkDetails ?? undefined,
|
|
498
|
+
taskId: options.task,
|
|
649
499
|
});
|
|
650
500
|
console.log(options.json ? JSON.stringify(result, null, 2) : formatRecordTerminalResult(result));
|
|
651
501
|
return 0;
|
|
652
502
|
},
|
|
653
503
|
complete: async ({ target, packageRoot, options }) => {
|
|
654
|
-
const result = await runComplete({ target, packageRoot, strict: options.strict });
|
|
504
|
+
const result = await runComplete({ target, packageRoot, strict: options.strict, taskId: options.task });
|
|
655
505
|
console.log(options.json ? JSON.stringify(result, null, 2) : formatCompleteResult(result));
|
|
656
506
|
return result.status === "VALID" ? 0 : 1;
|
|
657
507
|
},
|
|
658
508
|
audit: async ({ target, packageRoot, options }) => {
|
|
659
|
-
const result = await runAudit({ target, packageRoot, strict: options.strict });
|
|
509
|
+
const result = await runAudit({ target, packageRoot, strict: options.strict, taskId: options.task });
|
|
660
510
|
console.log(options.json ? JSON.stringify(result, null, 2) : formatAuditResult(result));
|
|
661
511
|
return result.status === "VALID" ? 0 : 1;
|
|
662
512
|
},
|
|
663
513
|
report: async ({ target, packageRoot, options }) => {
|
|
664
|
-
const result = await runReport({ target, packageRoot, strict: options.strict });
|
|
514
|
+
const result = await runReport({ target, packageRoot, strict: options.strict, taskId: options.task });
|
|
665
515
|
console.log(options.json ? JSON.stringify(result, null, 2) : formatReportResult(result));
|
|
666
516
|
return result.verdict === "VALID" ? 0 : 1;
|
|
667
517
|
},
|
|
668
518
|
policy: async ({ target, packageRoot, options }) => {
|
|
669
|
-
const result = await runPolicy({ target, packageRoot, name: options.policy });
|
|
519
|
+
const result = await runPolicy({ target, packageRoot, name: options.policy, taskId: options.task });
|
|
670
520
|
console.log(options.json ? JSON.stringify(result, null, 2) : formatPolicyResult(result));
|
|
671
521
|
return 0;
|
|
672
522
|
},
|
|
@@ -676,7 +526,7 @@ export const COMMAND_HANDLERS = Object.freeze({
|
|
|
676
526
|
return 0;
|
|
677
527
|
},
|
|
678
528
|
inspect: async ({ target, packageRoot, options }) => {
|
|
679
|
-
const result = await inspectTarget({ target, packageRoot, contractFile: options.contractFile });
|
|
529
|
+
const result = await inspectTarget({ target, packageRoot, contractFile: options.contractFile, taskId: options.task });
|
|
680
530
|
console.log(options.json ? JSON.stringify(result, null, 2) : formatInspectResult(result));
|
|
681
531
|
return result.ok ? 0 : 1;
|
|
682
532
|
},
|
|
@@ -689,32 +539,74 @@ export const COMMAND_HANDLERS = Object.freeze({
|
|
|
689
539
|
const result = await runValidateProtocol({
|
|
690
540
|
target,
|
|
691
541
|
packageRoot,
|
|
692
|
-
stateFile: options.stateFile
|
|
693
|
-
receiptFile: options.receiptFile
|
|
694
|
-
routeFile: options.routeFile
|
|
542
|
+
stateFile: options.stateFile,
|
|
543
|
+
receiptFile: options.receiptFile,
|
|
544
|
+
routeFile: options.routeFile,
|
|
695
545
|
contractFile: options.contractFile,
|
|
696
546
|
continuityFile: options.continuityFile,
|
|
697
547
|
taskBriefFiles: options.taskBriefFiles,
|
|
698
548
|
delegatedResultFiles: options.delegatedResultFiles,
|
|
549
|
+
taskId: options.task,
|
|
699
550
|
});
|
|
700
551
|
console.log(options.json ? JSON.stringify(result, null, 2) : formatValidateProtocolResult(result));
|
|
701
552
|
return result.status === "VALID" ? 0 : 1;
|
|
702
553
|
},
|
|
703
554
|
status: async ({ target, packageRoot, options }) => {
|
|
704
|
-
const result = await runStatus({ target, packageRoot, contractFile: options.contractFile });
|
|
555
|
+
const result = await runStatus({ target, packageRoot, contractFile: options.contractFile, taskId: options.task });
|
|
705
556
|
console.log(options.json ? JSON.stringify(result, null, 2) : formatStatusResult(result));
|
|
706
557
|
return 0;
|
|
707
558
|
},
|
|
708
559
|
"validate-state": async ({ target, packageRoot, options }) => {
|
|
709
|
-
const result = await runValidateState({ target, packageRoot });
|
|
560
|
+
const result = await runValidateState({ target, packageRoot, taskId: options.task });
|
|
710
561
|
console.log(options.json ? JSON.stringify(result, null, 2) : formatValidateStateResult(result));
|
|
711
562
|
return result.ok ? 0 : 1;
|
|
712
563
|
},
|
|
713
564
|
"clear-state": async ({ target, options }) => {
|
|
714
|
-
const result = await runClearState({ target });
|
|
565
|
+
const result = await runClearState({ target, taskId: options.task });
|
|
715
566
|
console.log(options.json ? JSON.stringify(result, null, 2) : formatClearStateResult(result));
|
|
716
567
|
return 0;
|
|
717
568
|
},
|
|
569
|
+
"task-create": async ({ target, packageRoot, options }) => {
|
|
570
|
+
const result = await runTaskCreate({
|
|
571
|
+
target,
|
|
572
|
+
packageRoot,
|
|
573
|
+
taskId: options.task,
|
|
574
|
+
claims: options.claims,
|
|
575
|
+
contractFile: options.contractFile,
|
|
576
|
+
});
|
|
577
|
+
console.log(options.json ? JSON.stringify(result, null, 2) : formatTaskCreateResult(result));
|
|
578
|
+
return 0;
|
|
579
|
+
},
|
|
580
|
+
"task-list": async ({ target, packageRoot, options }) => {
|
|
581
|
+
const result = await runTaskList({ target, packageRoot });
|
|
582
|
+
console.log(options.json ? JSON.stringify(result, null, 2) : formatTaskListResult(result));
|
|
583
|
+
return 0;
|
|
584
|
+
},
|
|
585
|
+
"task-show": async ({ target, packageRoot, options }) => {
|
|
586
|
+
const result = await runTaskShow({ target, packageRoot, taskId: options.task });
|
|
587
|
+
console.log(options.json ? JSON.stringify(result, null, 2) : formatTaskShowResult(result));
|
|
588
|
+
return 0;
|
|
589
|
+
},
|
|
590
|
+
"task-scope": async ({ target, packageRoot, options }) => {
|
|
591
|
+
const result = await runTaskScope({
|
|
592
|
+
target,
|
|
593
|
+
packageRoot,
|
|
594
|
+
taskId: options.task,
|
|
595
|
+
claims: options.claims,
|
|
596
|
+
});
|
|
597
|
+
console.log(options.json ? JSON.stringify(result, null, 2) : formatTaskScopeResult(result));
|
|
598
|
+
return 0;
|
|
599
|
+
},
|
|
600
|
+
"task-migrate": async ({ target, packageRoot, options }) => {
|
|
601
|
+
const result = await runTaskMigrate({ target, packageRoot, dryRun: options.dryRun });
|
|
602
|
+
console.log(options.json ? JSON.stringify(result, null, 2) : formatTaskMigrateResult(result));
|
|
603
|
+
return 0;
|
|
604
|
+
},
|
|
605
|
+
"task-unlock": async ({ target, packageRoot, options }) => {
|
|
606
|
+
const result = await runTaskUnlock({ target, packageRoot, taskId: options.task, force: options.force });
|
|
607
|
+
console.log(options.json ? JSON.stringify(result, null, 2) : formatTaskUnlockResult(result));
|
|
608
|
+
return 0;
|
|
609
|
+
},
|
|
718
610
|
update: async ({ target, packageRoot, packageVersion, options }) => {
|
|
719
611
|
const result = await runUpdate({ target, dryRun: options.dryRun, packageRoot, packageVersion });
|
|
720
612
|
printActions(result.actions);
|