@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
|
@@ -0,0 +1,611 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Canonical, declarative definition of all 33 ForgeLoop CLI commands.
|
|
3
|
+
* This is the machine source of truth for CLI option parsing, help text,
|
|
4
|
+
* metadata, documentation generation, and conformance validation.
|
|
5
|
+
*
|
|
6
|
+
* All value-taking long options accept both:
|
|
7
|
+
* --option value
|
|
8
|
+
* --option=value
|
|
9
|
+
*
|
|
10
|
+
* Boolean options reject =value syntax.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Canonical common options present on every ForgeLoop command.
|
|
15
|
+
*/
|
|
16
|
+
export const CLI_COMMON_OPTIONS = Object.freeze({
|
|
17
|
+
"--path": Object.freeze({
|
|
18
|
+
targetKey: "path",
|
|
19
|
+
parseType: "string",
|
|
20
|
+
takesValue: true,
|
|
21
|
+
valueName: "directory",
|
|
22
|
+
missingValueMessage: "--path requires a directory",
|
|
23
|
+
description: "target project directory (default: current directory)",
|
|
24
|
+
}),
|
|
25
|
+
"--help": Object.freeze({
|
|
26
|
+
targetKey: "help",
|
|
27
|
+
parseType: "boolean",
|
|
28
|
+
takesValue: false,
|
|
29
|
+
aliases: ["-h"],
|
|
30
|
+
description: "show this help",
|
|
31
|
+
}),
|
|
32
|
+
"--version": Object.freeze({
|
|
33
|
+
targetKey: "version",
|
|
34
|
+
parseType: "boolean",
|
|
35
|
+
takesValue: false,
|
|
36
|
+
aliases: ["-v"],
|
|
37
|
+
description: "show the installed package version",
|
|
38
|
+
}),
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Canonical task selector option present on all task-aware commands.
|
|
43
|
+
*/
|
|
44
|
+
export const CLI_TASK_OPTION = Object.freeze({
|
|
45
|
+
"--task": Object.freeze({
|
|
46
|
+
targetKey: "task",
|
|
47
|
+
parseType: "string",
|
|
48
|
+
takesValue: true,
|
|
49
|
+
valueName: "id",
|
|
50
|
+
missingValueMessage: "--task requires an ID",
|
|
51
|
+
description: "task ID to operate on (when omitted, resolved from context or single active task)",
|
|
52
|
+
}),
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Bootstrap options accepted before a command is discovered.
|
|
57
|
+
*/
|
|
58
|
+
export const CLI_BOOTSTRAP_OPTIONS = CLI_COMMON_OPTIONS;
|
|
59
|
+
|
|
60
|
+
export const CLI_COMMAND_DEFINITIONS = Object.freeze({
|
|
61
|
+
init: Object.freeze({
|
|
62
|
+
name: "init",
|
|
63
|
+
category: "project-maintenance",
|
|
64
|
+
mutation: "MUTATING",
|
|
65
|
+
options: Object.freeze({
|
|
66
|
+
...CLI_COMMON_OPTIONS,
|
|
67
|
+
"--dry-run": Object.freeze({ targetKey: "dryRun", parseType: "boolean", takesValue: false, description: "show planned writes without changing files" }),
|
|
68
|
+
}),
|
|
69
|
+
writes: [".forgeloop/*", "AGENTS.md", "CLAUDE.md", ".cursor/rules/project-loop.mdc", ".github/copilot-instructions.md"],
|
|
70
|
+
removes: [],
|
|
71
|
+
mayExecuteExternalProcess: false,
|
|
72
|
+
description: "Initializes a target project directory with ForgeLoop discovery adapters, schemas, and templates.",
|
|
73
|
+
}),
|
|
74
|
+
doctor: Object.freeze({
|
|
75
|
+
name: "doctor",
|
|
76
|
+
category: "diagnostics",
|
|
77
|
+
mutation: "MUTATING",
|
|
78
|
+
options: Object.freeze({
|
|
79
|
+
...CLI_COMMON_OPTIONS,
|
|
80
|
+
"--json": Object.freeze({ targetKey: "json", parseType: "boolean", takesValue: false, description: "emit doctor findings as JSON" }),
|
|
81
|
+
"--strict": Object.freeze({ targetKey: "strict", parseType: "boolean", takesValue: false, description: "treat warnings as unhealthy" }),
|
|
82
|
+
"--fix": Object.freeze({ targetKey: "fix", parseType: "boolean", takesValue: false, description: "restore missing managed template files" }),
|
|
83
|
+
"--adopt": Object.freeze({ targetKey: "adopt", parseType: "string", takesValue: true, repeatable: true, valueName: "path", missingValueMessage: "--adopt requires a path", description: "preserve an existing adapter in the manifest" }),
|
|
84
|
+
}),
|
|
85
|
+
writes: [".forgeloop/.manifest.json"],
|
|
86
|
+
removes: [],
|
|
87
|
+
mayExecuteExternalProcess: false,
|
|
88
|
+
description: "Diagnoses project health, discovers adapters, and optionally repairs missing template files.",
|
|
89
|
+
}),
|
|
90
|
+
update: Object.freeze({
|
|
91
|
+
name: "update",
|
|
92
|
+
category: "project-maintenance",
|
|
93
|
+
mutation: "MUTATING",
|
|
94
|
+
options: Object.freeze({
|
|
95
|
+
...CLI_COMMON_OPTIONS,
|
|
96
|
+
"--dry-run": Object.freeze({ targetKey: "dryRun", parseType: "boolean", takesValue: false, description: "show planned writes without changing files" }),
|
|
97
|
+
}),
|
|
98
|
+
writes: [".forgeloop/*", "AGENTS.md", "CLAUDE.md", ".cursor/rules/project-loop.mdc", ".github/copilot-instructions.md"],
|
|
99
|
+
removes: [],
|
|
100
|
+
mayExecuteExternalProcess: false,
|
|
101
|
+
description: "Updates installed templates, discovery adapters, and canonical engineering guides to the latest version.",
|
|
102
|
+
}),
|
|
103
|
+
activate: Object.freeze({
|
|
104
|
+
name: "activate",
|
|
105
|
+
category: "lifecycle",
|
|
106
|
+
mutation: "MUTATING",
|
|
107
|
+
options: Object.freeze({
|
|
108
|
+
...CLI_COMMON_OPTIONS,
|
|
109
|
+
"--json": Object.freeze({ targetKey: "json", parseType: "boolean", takesValue: false, description: "emit structured output as JSON" }),
|
|
110
|
+
}),
|
|
111
|
+
writes: [".forgeloop/sessions/<sessionId>.json"],
|
|
112
|
+
removes: [],
|
|
113
|
+
mayExecuteExternalProcess: false,
|
|
114
|
+
description: "Emits an active session marker recording sessionId and activationMarker.",
|
|
115
|
+
}),
|
|
116
|
+
route: Object.freeze({
|
|
117
|
+
name: "route",
|
|
118
|
+
category: "lifecycle",
|
|
119
|
+
mutation: "MUTATING",
|
|
120
|
+
options: Object.freeze({
|
|
121
|
+
...CLI_COMMON_OPTIONS,
|
|
122
|
+
...CLI_TASK_OPTION,
|
|
123
|
+
"--work": Object.freeze({ targetKey: "work", parseType: "string", takesValue: true, valueName: "type", missingValueMessage: "--work requires a type", description: "declared work type" }),
|
|
124
|
+
"--surface": Object.freeze({ targetKey: "surfaces", parseType: "string", takesValue: true, valueName: "value", repeatable: true, missingValueMessage: "--surface requires a value", description: "affected surface" }),
|
|
125
|
+
"--risk": Object.freeze({ targetKey: "risks", parseType: "string", takesValue: true, valueName: "value", repeatable: true, missingValueMessage: "--risk requires a value", description: "task risk" }),
|
|
126
|
+
"--platform": Object.freeze({ targetKey: "platforms", parseType: "string", takesValue: true, valueName: "value", repeatable: true, missingValueMessage: "--platform requires a value", description: "affected platform" }),
|
|
127
|
+
"--behavior-change": Object.freeze({ targetKey: "behaviorChange", parseType: "boolean", takesValue: false, description: "declare behavior change" }),
|
|
128
|
+
"--executable-change": Object.freeze({ targetKey: "executableChange", parseType: "boolean", takesValue: false, description: "declare executable/configuration change" }),
|
|
129
|
+
"--json": Object.freeze({ targetKey: "json", parseType: "boolean", takesValue: false, description: "emit route result as JSON" }),
|
|
130
|
+
}),
|
|
131
|
+
writes: [".forgeloop/task-state/<taskKey>/routing-result.json"],
|
|
132
|
+
removes: [],
|
|
133
|
+
mayExecuteExternalProcess: false,
|
|
134
|
+
description: "Evaluates task characteristics and deterministically routes required engineering guides.",
|
|
135
|
+
}),
|
|
136
|
+
preflight: Object.freeze({
|
|
137
|
+
name: "preflight",
|
|
138
|
+
category: "lifecycle",
|
|
139
|
+
mutation: "MUTATING",
|
|
140
|
+
options: Object.freeze({
|
|
141
|
+
...CLI_COMMON_OPTIONS,
|
|
142
|
+
...CLI_TASK_OPTION,
|
|
143
|
+
"--strict": Object.freeze({ targetKey: "strict", parseType: "boolean", takesValue: false, description: "require strict protocol compliance" }),
|
|
144
|
+
"--json": Object.freeze({ targetKey: "json", parseType: "boolean", takesValue: false, description: "emit structured output as JSON" }),
|
|
145
|
+
}),
|
|
146
|
+
writes: [".forgeloop/task-state/<taskKey>/preflight.json", ".forgeloop/task-state/<taskKey>/work-state.json", ".forgeloop/task-state/<taskKey>/events.ndjson"],
|
|
147
|
+
removes: [],
|
|
148
|
+
mayExecuteExternalProcess: false,
|
|
149
|
+
description: "Evaluates pre-implementation contract, routing, and gates; synchronizes work state when READY.",
|
|
150
|
+
}),
|
|
151
|
+
advance: Object.freeze({
|
|
152
|
+
name: "advance",
|
|
153
|
+
category: "lifecycle",
|
|
154
|
+
mutation: "MUTATING",
|
|
155
|
+
options: Object.freeze({
|
|
156
|
+
...CLI_COMMON_OPTIONS,
|
|
157
|
+
...CLI_TASK_OPTION,
|
|
158
|
+
"--to": Object.freeze({ targetKey: "to", parseType: "string", takesValue: true, valueName: "phase", missingValueMessage: "--to requires a phase", description: "destination workflow phase" }),
|
|
159
|
+
"--json": Object.freeze({ targetKey: "json", parseType: "boolean", takesValue: false, description: "emit structured output as JSON" }),
|
|
160
|
+
}),
|
|
161
|
+
writes: [".forgeloop/task-state/<taskKey>/work-state.json", ".forgeloop/task-state/<taskKey>/events.ndjson"],
|
|
162
|
+
removes: [],
|
|
163
|
+
mayExecuteExternalProcess: false,
|
|
164
|
+
description: "Transitions the canonical lifecycle work state to an allowed target phase.",
|
|
165
|
+
}),
|
|
166
|
+
next: Object.freeze({
|
|
167
|
+
name: "next",
|
|
168
|
+
category: "lifecycle",
|
|
169
|
+
mutation: "READ_ONLY",
|
|
170
|
+
options: Object.freeze({
|
|
171
|
+
...CLI_COMMON_OPTIONS,
|
|
172
|
+
...CLI_TASK_OPTION,
|
|
173
|
+
"--json": Object.freeze({ targetKey: "json", parseType: "boolean", takesValue: false, description: "emit structured output as JSON" }),
|
|
174
|
+
}),
|
|
175
|
+
writes: [],
|
|
176
|
+
removes: [],
|
|
177
|
+
mayExecuteExternalProcess: false,
|
|
178
|
+
description: "Returns deterministic next-action guidance and command recommendations based on active state.",
|
|
179
|
+
}),
|
|
180
|
+
continuity: Object.freeze({
|
|
181
|
+
name: "continuity",
|
|
182
|
+
category: "continuity",
|
|
183
|
+
mutation: "READ_ONLY",
|
|
184
|
+
options: Object.freeze({
|
|
185
|
+
...CLI_COMMON_OPTIONS,
|
|
186
|
+
...CLI_TASK_OPTION,
|
|
187
|
+
"--json": Object.freeze({ targetKey: "json", parseType: "boolean", takesValue: false, description: "emit structured output as JSON" }),
|
|
188
|
+
}),
|
|
189
|
+
writes: [],
|
|
190
|
+
removes: [],
|
|
191
|
+
mayExecuteExternalProcess: false,
|
|
192
|
+
description: "Reads and displays current cross-harness continuity handoff notes.",
|
|
193
|
+
}),
|
|
194
|
+
"record-continuity": Object.freeze({
|
|
195
|
+
name: "record-continuity",
|
|
196
|
+
category: "continuity",
|
|
197
|
+
mutation: "MUTATING",
|
|
198
|
+
options: Object.freeze({
|
|
199
|
+
...CLI_COMMON_OPTIONS,
|
|
200
|
+
...CLI_TASK_OPTION,
|
|
201
|
+
"--focus-id": Object.freeze({ targetKey: "continuityFocusId", parseType: "string", takesValue: true, valueName: "id", missingValueMessage: "--focus-id requires a value", description: "current implementation focus ID" }),
|
|
202
|
+
"--focus-summary": Object.freeze({ targetKey: "continuityFocusSummary", parseType: "string", takesValue: true, valueName: "text", missingValueMessage: "--focus-summary requires a value", description: "current implementation focus summary" }),
|
|
203
|
+
"--remaining": Object.freeze({ targetKey: "continuityRemaining", parseType: "string", takesValue: true, valueName: "id:summary", repeatable: true, missingValueMessage: "--remaining requires a value", description: "remaining implementation item" }),
|
|
204
|
+
"--known-issue": Object.freeze({ targetKey: "continuityKnownIssues", parseType: "string", takesValue: true, valueName: "id:summary", repeatable: true, missingValueMessage: "--known-issue requires a value", description: "known implementation issue" }),
|
|
205
|
+
"--changed-area": Object.freeze({ targetKey: "continuityChangedAreas", parseType: "string", takesValue: true, valueName: "path", repeatable: true, missingValueMessage: "--changed-area requires a value", description: "changed project area" }),
|
|
206
|
+
"--inspect-first": Object.freeze({ targetKey: "continuityInspectFirst", parseType: "string", takesValue: true, valueName: "path", repeatable: true, missingValueMessage: "--inspect-first requires a value", description: "suggested inspection path" }),
|
|
207
|
+
"--resume-note": Object.freeze({ targetKey: "continuityResumeNote", parseType: "string", takesValue: true, valueName: "text", missingValueMessage: "--resume-note requires a value", description: "bounded operational resume note" }),
|
|
208
|
+
"--json": Object.freeze({ targetKey: "json", parseType: "boolean", takesValue: false, description: "emit structured output as JSON" }),
|
|
209
|
+
}),
|
|
210
|
+
writes: [".forgeloop/task-state/<taskKey>/continuity.json"],
|
|
211
|
+
removes: [],
|
|
212
|
+
mayExecuteExternalProcess: false,
|
|
213
|
+
description: "Persists cross-harness operational continuity handoff notes bound to current state fingerprints.",
|
|
214
|
+
}),
|
|
215
|
+
"reconcile-continuity": Object.freeze({
|
|
216
|
+
name: "reconcile-continuity",
|
|
217
|
+
category: "continuity",
|
|
218
|
+
mutation: "READ_ONLY",
|
|
219
|
+
options: Object.freeze({
|
|
220
|
+
...CLI_COMMON_OPTIONS,
|
|
221
|
+
...CLI_TASK_OPTION,
|
|
222
|
+
"--json": Object.freeze({ targetKey: "json", parseType: "boolean", takesValue: false, description: "emit structured output as JSON" }),
|
|
223
|
+
}),
|
|
224
|
+
writes: [],
|
|
225
|
+
removes: [],
|
|
226
|
+
mayExecuteExternalProcess: false,
|
|
227
|
+
description: "Reconciles continuity handoff notes with active work state and checkout state.",
|
|
228
|
+
}),
|
|
229
|
+
"clear-continuity": Object.freeze({
|
|
230
|
+
name: "clear-continuity",
|
|
231
|
+
category: "continuity",
|
|
232
|
+
mutation: "MUTATING",
|
|
233
|
+
options: Object.freeze({
|
|
234
|
+
...CLI_COMMON_OPTIONS,
|
|
235
|
+
...CLI_TASK_OPTION,
|
|
236
|
+
"--json": Object.freeze({ targetKey: "json", parseType: "boolean", takesValue: false, description: "emit structured output as JSON" }),
|
|
237
|
+
}),
|
|
238
|
+
writes: [],
|
|
239
|
+
removes: [".forgeloop/task-state/<taskKey>/continuity.json"],
|
|
240
|
+
mayExecuteExternalProcess: false,
|
|
241
|
+
description: "Removes continuity.json for the active task without affecting lifecycle work state.",
|
|
242
|
+
}),
|
|
243
|
+
"prepare-completion": Object.freeze({
|
|
244
|
+
name: "prepare-completion",
|
|
245
|
+
category: "verification",
|
|
246
|
+
mutation: "MUTATING",
|
|
247
|
+
options: Object.freeze({
|
|
248
|
+
...CLI_COMMON_OPTIONS,
|
|
249
|
+
...CLI_TASK_OPTION,
|
|
250
|
+
"--json": Object.freeze({ targetKey: "json", parseType: "boolean", takesValue: false, description: "emit structured output as JSON" }),
|
|
251
|
+
}),
|
|
252
|
+
writes: [".forgeloop/task-state/<taskKey>/execution-receipt.json"],
|
|
253
|
+
removes: [],
|
|
254
|
+
mayExecuteExternalProcess: false,
|
|
255
|
+
description: "Initializes execution-receipt.json with empty requirement evidence slots for the active cycle.",
|
|
256
|
+
}),
|
|
257
|
+
"run-check": Object.freeze({
|
|
258
|
+
name: "run-check",
|
|
259
|
+
category: "verification",
|
|
260
|
+
mutation: "EXTERNAL_EXECUTION",
|
|
261
|
+
options: Object.freeze({
|
|
262
|
+
...CLI_COMMON_OPTIONS,
|
|
263
|
+
...CLI_TASK_OPTION,
|
|
264
|
+
"--id": Object.freeze({ targetKey: "checkId", parseType: "string", takesValue: true, valueName: "id", missingValueMessage: "--id requires a check ID", description: "stable check identifier" }),
|
|
265
|
+
"--requirement": Object.freeze({ targetKey: "checkRequirement", parseType: "string", takesValue: true, valueName: "id", missingValueMessage: "--requirement requires an evidence target", description: "completion requirement covered by the check" }),
|
|
266
|
+
"--details": Object.freeze({ targetKey: "checkDetails", parseType: "json-object", takesValue: true, valueName: "json", missingValueMessage: "--details requires a JSON object", description: "additional structured check details" }),
|
|
267
|
+
"--": Object.freeze({ targetKey: "commandArgv", parseType: "argv", takesValue: true, valueName: "argv...", description: "exact command argv to classify, execute, and attest" }),
|
|
268
|
+
"--json": Object.freeze({ targetKey: "json", parseType: "boolean", takesValue: false, description: "emit structured output as JSON" }),
|
|
269
|
+
}),
|
|
270
|
+
writes: [".forgeloop/task-state/<taskKey>/executions/exec-<id>.json", ".forgeloop/task-state/<taskKey>/work-state.json", ".forgeloop/task-state/<taskKey>/execution-receipt.json", ".forgeloop/task-state/<taskKey>/events.ndjson"],
|
|
271
|
+
removes: [],
|
|
272
|
+
mayExecuteExternalProcess: true,
|
|
273
|
+
description: "Runs an exact command, records the execution provenance artifact, and binds observed check evidence.",
|
|
274
|
+
}),
|
|
275
|
+
"record-check": Object.freeze({
|
|
276
|
+
name: "record-check",
|
|
277
|
+
category: "verification",
|
|
278
|
+
mutation: "MUTATING",
|
|
279
|
+
options: Object.freeze({
|
|
280
|
+
...CLI_COMMON_OPTIONS,
|
|
281
|
+
...CLI_TASK_OPTION,
|
|
282
|
+
"--id": Object.freeze({ targetKey: "checkId", parseType: "string", takesValue: true, valueName: "id", missingValueMessage: "--id requires a check ID", description: "stable check identifier" }),
|
|
283
|
+
"--requirement": Object.freeze({ targetKey: "checkRequirement", parseType: "string", takesValue: true, valueName: "id", missingValueMessage: "--requirement requires an evidence target", description: "completion requirement covered by the check" }),
|
|
284
|
+
"--kind": Object.freeze({ targetKey: "checkKind", parseType: "string", takesValue: true, valueName: "kind", missingValueMessage: "--kind requires a check kind", description: "check kind (default: command; use manual-review for manual evidence)" }),
|
|
285
|
+
"--status": Object.freeze({ targetKey: "checkStatus", parseType: "string", takesValue: true, valueName: "status", missingValueMessage: "--status requires a check status", description: "passed, failed, blocked, or not-run" }),
|
|
286
|
+
"--evidence-kind": Object.freeze({ targetKey: "checkEvidenceKind", parseType: "string", takesValue: true, valueName: "kind", missingValueMessage: "--evidence-kind requires an evidence kind", description: "OBSERVED, INFERRED, NOT_VERIFIED, or BLOCKED" }),
|
|
287
|
+
"--command": Object.freeze({ targetKey: "checkCommand", parseType: "string", takesValue: true, valueName: "text", missingValueMessage: "--command requires recorded text", description: "recorded only as metadata; it is never executed" }),
|
|
288
|
+
"--result": Object.freeze({ targetKey: "checkResult", parseType: "string", takesValue: true, valueName: "text", missingValueMessage: "--result requires recorded text", description: "observed result supplied by the actor" }),
|
|
289
|
+
"--exit-code": Object.freeze({ targetKey: "checkExitCode", parseType: "non-negative-integer", takesValue: true, valueName: "number", missingValueMessage: "--exit-code requires a non-negative integer", description: "observed process exit code" }),
|
|
290
|
+
"--execution-ref": Object.freeze({ targetKey: "checkExecutionRef", parseType: "string", takesValue: true, valueName: "id", missingValueMessage: "--execution-ref requires an execution ID", description: "ForgeLoop execution artifact reference" }),
|
|
291
|
+
"--provenance": Object.freeze({ targetKey: "checkProvenance", parseType: "string", takesValue: true, valueName: "value", missingValueMessage: "--provenance requires a provenance value", description: "FORGELOOP_EXECUTED, ACTOR_REPORTED, or MANUAL_OBSERVATION" }),
|
|
292
|
+
"--details": Object.freeze({ targetKey: "checkDetails", parseType: "json-object", takesValue: true, valueName: "json", missingValueMessage: "--details requires a JSON object", description: "additional structured check details" }),
|
|
293
|
+
"--json": Object.freeze({ targetKey: "json", parseType: "boolean", takesValue: false, description: "emit structured output as JSON" }),
|
|
294
|
+
}),
|
|
295
|
+
writes: [".forgeloop/task-state/<taskKey>/work-state.json", ".forgeloop/task-state/<taskKey>/execution-receipt.json", ".forgeloop/task-state/<taskKey>/events.ndjson"],
|
|
296
|
+
removes: [],
|
|
297
|
+
mayExecuteExternalProcess: false,
|
|
298
|
+
description: "Records structured verification evidence (command, manual review, or test output) against a requirement.",
|
|
299
|
+
}),
|
|
300
|
+
"record-terminal-result": Object.freeze({
|
|
301
|
+
name: "record-terminal-result",
|
|
302
|
+
category: "verification",
|
|
303
|
+
mutation: "MUTATING",
|
|
304
|
+
options: Object.freeze({
|
|
305
|
+
...CLI_COMMON_OPTIONS,
|
|
306
|
+
...CLI_TASK_OPTION,
|
|
307
|
+
"--requirement": Object.freeze({ targetKey: "checkRequirement", parseType: "string", takesValue: true, valueName: "id", missingValueMessage: "--requirement requires an evidence target", description: "terminal requirement covered by the result" }),
|
|
308
|
+
"--type": Object.freeze({ targetKey: "checkType", parseType: "string", takesValue: true, valueName: "type", missingValueMessage: "--type requires a terminal type", description: "PUBLICATION or PRODUCTION_READINESS" }),
|
|
309
|
+
"--status": Object.freeze({ targetKey: "checkStatus", parseType: "string", takesValue: true, valueName: "status", missingValueMessage: "--status requires a check status", description: "observed terminal status" }),
|
|
310
|
+
"--source": Object.freeze({ targetKey: "checkSource", parseType: "string", takesValue: true, valueName: "text", missingValueMessage: "--source requires recorded text", description: "external action source (e.g. npm publish, git push)" }),
|
|
311
|
+
"--result": Object.freeze({ targetKey: "checkResult", parseType: "string", takesValue: true, valueName: "text", missingValueMessage: "--result requires recorded text", description: "observed external result description" }),
|
|
312
|
+
"--details": Object.freeze({ targetKey: "checkDetails", parseType: "json-object", takesValue: true, valueName: "json", missingValueMessage: "--details requires a JSON object", description: "additional structured result details" }),
|
|
313
|
+
"--json": Object.freeze({ targetKey: "json", parseType: "boolean", takesValue: false, description: "emit structured output as JSON" }),
|
|
314
|
+
}),
|
|
315
|
+
writes: [".forgeloop/task-state/<taskKey>/work-state.json", ".forgeloop/task-state/<taskKey>/execution-receipt.json", ".forgeloop/task-state/<taskKey>/events.ndjson"],
|
|
316
|
+
removes: [],
|
|
317
|
+
mayExecuteExternalProcess: false,
|
|
318
|
+
description: "Records external terminal result evidence (PUBLICATION or PRODUCTION_READINESS) into receipt.",
|
|
319
|
+
}),
|
|
320
|
+
complete: Object.freeze({
|
|
321
|
+
name: "complete",
|
|
322
|
+
category: "lifecycle",
|
|
323
|
+
mutation: "MUTATING",
|
|
324
|
+
options: Object.freeze({
|
|
325
|
+
...CLI_COMMON_OPTIONS,
|
|
326
|
+
...CLI_TASK_OPTION,
|
|
327
|
+
"--strict": Object.freeze({ targetKey: "strict", parseType: "boolean", takesValue: false, description: "require strict protocol compliance" }),
|
|
328
|
+
"--json": Object.freeze({ targetKey: "json", parseType: "boolean", takesValue: false, description: "emit structured output as JSON" }),
|
|
329
|
+
}),
|
|
330
|
+
writes: [".forgeloop/task-state/<taskKey>/work-state.json", ".forgeloop/task-state/<taskKey>/events.ndjson"],
|
|
331
|
+
removes: [],
|
|
332
|
+
mayExecuteExternalProcess: false,
|
|
333
|
+
description: "Evaluates verification receipt coverage, gates, and ledger integrity to authorize task completion.",
|
|
334
|
+
}),
|
|
335
|
+
audit: Object.freeze({
|
|
336
|
+
name: "audit",
|
|
337
|
+
category: "verification",
|
|
338
|
+
mutation: "READ_ONLY",
|
|
339
|
+
options: Object.freeze({
|
|
340
|
+
...CLI_COMMON_OPTIONS,
|
|
341
|
+
...CLI_TASK_OPTION,
|
|
342
|
+
"--strict": Object.freeze({ targetKey: "strict", parseType: "boolean", takesValue: false, description: "require strict protocol compliance" }),
|
|
343
|
+
"--json": Object.freeze({ targetKey: "json", parseType: "boolean", takesValue: false, description: "emit structured output as JSON" }),
|
|
344
|
+
}),
|
|
345
|
+
writes: [],
|
|
346
|
+
removes: [],
|
|
347
|
+
mayExecuteExternalProcess: false,
|
|
348
|
+
description: "Performs read-only evaluation of verification receipt coverage and gate satisfaction.",
|
|
349
|
+
}),
|
|
350
|
+
report: Object.freeze({
|
|
351
|
+
name: "report",
|
|
352
|
+
category: "verification",
|
|
353
|
+
mutation: "READ_ONLY",
|
|
354
|
+
options: Object.freeze({
|
|
355
|
+
...CLI_COMMON_OPTIONS,
|
|
356
|
+
...CLI_TASK_OPTION,
|
|
357
|
+
"--strict": Object.freeze({ targetKey: "strict", parseType: "boolean", takesValue: false, description: "require strict protocol compliance" }),
|
|
358
|
+
"--json": Object.freeze({ targetKey: "json", parseType: "boolean", takesValue: false, description: "emit structured output as JSON" }),
|
|
359
|
+
}),
|
|
360
|
+
writes: [],
|
|
361
|
+
removes: [],
|
|
362
|
+
mayExecuteExternalProcess: false,
|
|
363
|
+
description: "Emits a human-readable or structured JSON summary report of protocol state.",
|
|
364
|
+
}),
|
|
365
|
+
policy: Object.freeze({
|
|
366
|
+
name: "policy",
|
|
367
|
+
category: "policy-audit",
|
|
368
|
+
mutation: "READ_ONLY",
|
|
369
|
+
options: Object.freeze({
|
|
370
|
+
...CLI_COMMON_OPTIONS,
|
|
371
|
+
...CLI_TASK_OPTION,
|
|
372
|
+
"<name>": Object.freeze({ targetKey: "policy", parseType: "string", takesValue: true, isPositional: true, valueName: "name", description: "policy pack name" }),
|
|
373
|
+
"--json": Object.freeze({ targetKey: "json", parseType: "boolean", takesValue: false, description: "emit structured output as JSON" }),
|
|
374
|
+
}),
|
|
375
|
+
writes: [],
|
|
376
|
+
removes: [],
|
|
377
|
+
mayExecuteExternalProcess: false,
|
|
378
|
+
description: "Evaluates active task state against named enterprise policy packs.",
|
|
379
|
+
}),
|
|
380
|
+
bundle: Object.freeze({
|
|
381
|
+
name: "bundle",
|
|
382
|
+
category: "policy-audit",
|
|
383
|
+
mutation: "READ_ONLY",
|
|
384
|
+
options: Object.freeze({
|
|
385
|
+
...CLI_COMMON_OPTIONS,
|
|
386
|
+
...CLI_TASK_OPTION,
|
|
387
|
+
"--json": Object.freeze({ targetKey: "json", parseType: "boolean", takesValue: false, description: "emit structured output as JSON" }),
|
|
388
|
+
}),
|
|
389
|
+
writes: [],
|
|
390
|
+
removes: [],
|
|
391
|
+
mayExecuteExternalProcess: false,
|
|
392
|
+
description: "Exports current task artifacts into a portable task bundle archive.",
|
|
393
|
+
}),
|
|
394
|
+
inspect: Object.freeze({
|
|
395
|
+
name: "inspect",
|
|
396
|
+
category: "diagnostics",
|
|
397
|
+
mutation: "READ_ONLY",
|
|
398
|
+
options: Object.freeze({
|
|
399
|
+
...CLI_COMMON_OPTIONS,
|
|
400
|
+
...CLI_TASK_OPTION,
|
|
401
|
+
"--contract-file": Object.freeze({ targetKey: "contractFile", parseType: "string", takesValue: true, valueName: "path", missingValueMessage: "--contract-file requires a path", description: "current JSON contract used for freshness comparison" }),
|
|
402
|
+
"--json": Object.freeze({ targetKey: "json", parseType: "boolean", takesValue: false, description: "emit structured output as JSON" }),
|
|
403
|
+
}),
|
|
404
|
+
writes: [],
|
|
405
|
+
removes: [],
|
|
406
|
+
mayExecuteExternalProcess: false,
|
|
407
|
+
description: "Inspects target repository health, dirty files, active branch, and artifact freshness.",
|
|
408
|
+
}),
|
|
409
|
+
status: Object.freeze({
|
|
410
|
+
name: "status",
|
|
411
|
+
category: "diagnostics",
|
|
412
|
+
mutation: "READ_ONLY",
|
|
413
|
+
options: Object.freeze({
|
|
414
|
+
...CLI_COMMON_OPTIONS,
|
|
415
|
+
...CLI_TASK_OPTION,
|
|
416
|
+
"--contract-file": Object.freeze({ targetKey: "contractFile", parseType: "string", takesValue: true, valueName: "path", missingValueMessage: "--contract-file requires a path", description: "current JSON contract used for freshness comparison" }),
|
|
417
|
+
"--json": Object.freeze({ targetKey: "json", parseType: "boolean", takesValue: false, description: "emit structured output as JSON" }),
|
|
418
|
+
}),
|
|
419
|
+
writes: [],
|
|
420
|
+
removes: [],
|
|
421
|
+
mayExecuteExternalProcess: false,
|
|
422
|
+
description: "Displays current lifecycle phase, active checks, blockers, and artifact freshness bindings.",
|
|
423
|
+
}),
|
|
424
|
+
"validate-state": Object.freeze({
|
|
425
|
+
name: "validate-state",
|
|
426
|
+
category: "diagnostics",
|
|
427
|
+
mutation: "READ_ONLY",
|
|
428
|
+
options: Object.freeze({
|
|
429
|
+
...CLI_COMMON_OPTIONS,
|
|
430
|
+
...CLI_TASK_OPTION,
|
|
431
|
+
"--json": Object.freeze({ targetKey: "json", parseType: "boolean", takesValue: false, description: "emit structured output as JSON" }),
|
|
432
|
+
}),
|
|
433
|
+
writes: [],
|
|
434
|
+
removes: [],
|
|
435
|
+
mayExecuteExternalProcess: false,
|
|
436
|
+
description: "Validates schema adherence and internal consistency of work-state.json.",
|
|
437
|
+
}),
|
|
438
|
+
"clear-state": Object.freeze({
|
|
439
|
+
name: "clear-state",
|
|
440
|
+
category: "lifecycle",
|
|
441
|
+
mutation: "MUTATING",
|
|
442
|
+
options: Object.freeze({
|
|
443
|
+
...CLI_COMMON_OPTIONS,
|
|
444
|
+
...CLI_TASK_OPTION,
|
|
445
|
+
"--json": Object.freeze({ targetKey: "json", parseType: "boolean", takesValue: false, description: "emit structured output as JSON" }),
|
|
446
|
+
}),
|
|
447
|
+
writes: [],
|
|
448
|
+
removes: [".forgeloop/task-state/<taskKey>/work-state.json"],
|
|
449
|
+
mayExecuteExternalProcess: false,
|
|
450
|
+
description: "Removes work-state.json for the active task only, preserving sibling contract, routing, and ledger files.",
|
|
451
|
+
}),
|
|
452
|
+
"validate-receipt": Object.freeze({
|
|
453
|
+
name: "validate-receipt",
|
|
454
|
+
category: "verification",
|
|
455
|
+
mutation: "READ_ONLY",
|
|
456
|
+
options: Object.freeze({
|
|
457
|
+
...CLI_COMMON_OPTIONS,
|
|
458
|
+
"--file": Object.freeze({ targetKey: "file", parseType: "string", takesValue: true, valueName: "path", missingValueMessage: "--file requires a path", description: "receipt file relative to target" }),
|
|
459
|
+
"--json": Object.freeze({ targetKey: "json", parseType: "boolean", takesValue: false, description: "emit structured output as JSON" }),
|
|
460
|
+
}),
|
|
461
|
+
writes: [],
|
|
462
|
+
removes: [],
|
|
463
|
+
mayExecuteExternalProcess: false,
|
|
464
|
+
description: "Validates schema conformance and cryptographic bounds of an execution receipt file.",
|
|
465
|
+
}),
|
|
466
|
+
"validate-protocol": Object.freeze({
|
|
467
|
+
name: "validate-protocol",
|
|
468
|
+
category: "diagnostics",
|
|
469
|
+
mutation: "READ_ONLY",
|
|
470
|
+
options: Object.freeze({
|
|
471
|
+
...CLI_COMMON_OPTIONS,
|
|
472
|
+
...CLI_TASK_OPTION,
|
|
473
|
+
"--contract-file": Object.freeze({ targetKey: "contractFile", parseType: "string", takesValue: true, valueName: "path", missingValueMessage: "--contract-file requires a path", description: "current JSON contract used for freshness comparison" }),
|
|
474
|
+
"--route-file": Object.freeze({ targetKey: "routeFile", parseType: "string", takesValue: true, valueName: "path", missingValueMessage: "--route-file requires a path", description: "routing-result JSON relative to target" }),
|
|
475
|
+
"--state-file": Object.freeze({ targetKey: "stateFile", parseType: "string", takesValue: true, valueName: "path", missingValueMessage: "--state-file requires a path", description: "work-state JSON relative to target" }),
|
|
476
|
+
"--receipt-file": Object.freeze({ targetKey: "receiptFile", parseType: "string", takesValue: true, valueName: "path", missingValueMessage: "--receipt-file requires a path", description: "execution-receipt JSON relative to target" }),
|
|
477
|
+
"--continuity-file": Object.freeze({ targetKey: "continuityFile", parseType: "string", takesValue: true, valueName: "path", missingValueMessage: "--continuity-file requires a path", description: "optional execution-continuity JSON relative to target" }),
|
|
478
|
+
"--task-brief-file": Object.freeze({ targetKey: "taskBriefFiles", parseType: "string", takesValue: true, valueName: "path", repeatable: true, missingValueMessage: "--task-brief-file requires a path", description: "task brief JSON file" }),
|
|
479
|
+
"--delegated-result-file": Object.freeze({ targetKey: "delegatedResultFiles", parseType: "string", takesValue: true, valueName: "path", repeatable: true, missingValueMessage: "--delegated-result-file requires a path", description: "delegated result JSON file" }),
|
|
480
|
+
"--json": Object.freeze({ targetKey: "json", parseType: "boolean", takesValue: false, description: "emit structured output as JSON" }),
|
|
481
|
+
}),
|
|
482
|
+
writes: [],
|
|
483
|
+
removes: [],
|
|
484
|
+
mayExecuteExternalProcess: false,
|
|
485
|
+
description: "Validates end-to-end cryptographic freshness, fingerprint bindings, and ledger integrity.",
|
|
486
|
+
}),
|
|
487
|
+
"task-create": Object.freeze({
|
|
488
|
+
name: "task-create",
|
|
489
|
+
category: "lifecycle",
|
|
490
|
+
mutation: "MUTATING",
|
|
491
|
+
options: Object.freeze({
|
|
492
|
+
...CLI_COMMON_OPTIONS,
|
|
493
|
+
...CLI_TASK_OPTION,
|
|
494
|
+
"--claim": Object.freeze({ targetKey: "claims", parseType: "string", takesValue: true, repeatable: true, valueName: "path", missingValueMessage: "--claim requires a path", description: "scoped file path or directory prefix claimed for mutation" }),
|
|
495
|
+
"--contract-file": Object.freeze({ targetKey: "contractFile", parseType: "string", takesValue: true, valueName: "path", missingValueMessage: "--contract-file requires a path", description: "path to initial contract file" }),
|
|
496
|
+
"--json": Object.freeze({ targetKey: "json", parseType: "boolean", takesValue: false, description: "emit structured output as JSON" }),
|
|
497
|
+
}),
|
|
498
|
+
writes: [".forgeloop/task-state/<taskKey>/task.json", ".forgeloop/task-state/<taskKey>/current-contract.json"],
|
|
499
|
+
removes: [],
|
|
500
|
+
mayExecuteExternalProcess: false,
|
|
501
|
+
description: "Creates a new task descriptor and initializes its isolated task state namespace.",
|
|
502
|
+
}),
|
|
503
|
+
"task-list": Object.freeze({
|
|
504
|
+
name: "task-list",
|
|
505
|
+
category: "lifecycle",
|
|
506
|
+
mutation: "READ_ONLY",
|
|
507
|
+
options: Object.freeze({
|
|
508
|
+
...CLI_COMMON_OPTIONS,
|
|
509
|
+
"--json": Object.freeze({ targetKey: "json", parseType: "boolean", takesValue: false, description: "emit structured output as JSON" }),
|
|
510
|
+
}),
|
|
511
|
+
writes: [],
|
|
512
|
+
removes: [],
|
|
513
|
+
mayExecuteExternalProcess: false,
|
|
514
|
+
description: "Lists all discovered task descriptors and their current lifecycle phases.",
|
|
515
|
+
}),
|
|
516
|
+
"task-show": Object.freeze({
|
|
517
|
+
name: "task-show",
|
|
518
|
+
category: "lifecycle",
|
|
519
|
+
mutation: "READ_ONLY",
|
|
520
|
+
options: Object.freeze({
|
|
521
|
+
...CLI_COMMON_OPTIONS,
|
|
522
|
+
...CLI_TASK_OPTION,
|
|
523
|
+
"--json": Object.freeze({ targetKey: "json", parseType: "boolean", takesValue: false, description: "emit structured output as JSON" }),
|
|
524
|
+
}),
|
|
525
|
+
writes: [],
|
|
526
|
+
removes: [],
|
|
527
|
+
mayExecuteExternalProcess: false,
|
|
528
|
+
description: "Shows details of a specific task descriptor and its scoped artifacts.",
|
|
529
|
+
}),
|
|
530
|
+
"task-scope": Object.freeze({
|
|
531
|
+
name: "task-scope",
|
|
532
|
+
category: "lifecycle",
|
|
533
|
+
mutation: "MUTATING",
|
|
534
|
+
options: Object.freeze({
|
|
535
|
+
...CLI_COMMON_OPTIONS,
|
|
536
|
+
...CLI_TASK_OPTION,
|
|
537
|
+
"--claim": Object.freeze({ targetKey: "claims", parseType: "string", takesValue: true, repeatable: true, valueName: "path", missingValueMessage: "--claim requires a path", description: "scoped file path or directory prefix claimed for mutation" }),
|
|
538
|
+
"--json": Object.freeze({ targetKey: "json", parseType: "boolean", takesValue: false, description: "emit structured output as JSON" }),
|
|
539
|
+
}),
|
|
540
|
+
writes: [".forgeloop/task-state/<taskKey>/task.json"],
|
|
541
|
+
removes: [],
|
|
542
|
+
mayExecuteExternalProcess: false,
|
|
543
|
+
description: "Updates or inspects write claims for a task before execution.",
|
|
544
|
+
}),
|
|
545
|
+
"task-migrate": Object.freeze({
|
|
546
|
+
name: "task-migrate",
|
|
547
|
+
category: "project-maintenance",
|
|
548
|
+
mutation: "MUTATING",
|
|
549
|
+
options: Object.freeze({
|
|
550
|
+
...CLI_COMMON_OPTIONS,
|
|
551
|
+
"--dry-run": Object.freeze({ targetKey: "dryRun", parseType: "boolean", takesValue: false, description: "show planned migration actions without moving files" }),
|
|
552
|
+
"--json": Object.freeze({ targetKey: "json", parseType: "boolean", takesValue: false, description: "emit structured output as JSON" }),
|
|
553
|
+
}),
|
|
554
|
+
writes: [".forgeloop/task-state/<taskKey>/*"],
|
|
555
|
+
removes: [".forgeloop/current-contract.json", ".forgeloop/routing-result.json", ".forgeloop/work-state.json", ".forgeloop/preflight.json", ".forgeloop/execution-receipt.json", ".forgeloop/events.ndjson", ".forgeloop/continuity.json", ".forgeloop/gates", ".forgeloop/executions"],
|
|
556
|
+
mayExecuteExternalProcess: false,
|
|
557
|
+
description: "Migrates a legacy 1.0 singleton task state layout into a task-namespaced layout.",
|
|
558
|
+
}),
|
|
559
|
+
"task-unlock": Object.freeze({
|
|
560
|
+
name: "task-unlock",
|
|
561
|
+
category: "project-maintenance",
|
|
562
|
+
mutation: "MUTATING",
|
|
563
|
+
options: Object.freeze({
|
|
564
|
+
...CLI_COMMON_OPTIONS,
|
|
565
|
+
...CLI_TASK_OPTION,
|
|
566
|
+
"--force": Object.freeze({ targetKey: "force", parseType: "boolean", takesValue: false, description: "force release of an orphaned task lock" }),
|
|
567
|
+
"--json": Object.freeze({ targetKey: "json", parseType: "boolean", takesValue: false, description: "emit structured output as JSON" }),
|
|
568
|
+
}),
|
|
569
|
+
writes: [],
|
|
570
|
+
removes: [".forgeloop/task-state/<taskKey>/.lock"],
|
|
571
|
+
mayExecuteExternalProcess: false,
|
|
572
|
+
description: "Removes an orphaned task lock file to recover an interrupted task.",
|
|
573
|
+
}),
|
|
574
|
+
});
|
|
575
|
+
|
|
576
|
+
/**
|
|
577
|
+
* Builds an option lookup map for a given command or bootstrap options, resolving aliases to canonical options.
|
|
578
|
+
* Excludes positional definitions so pseudo-options never enter flag lookup.
|
|
579
|
+
* @param {string|null} command - Command name, or null for bootstrap options
|
|
580
|
+
* @returns {Map<string, { canonicalName: string, optionDef: Object }>}
|
|
581
|
+
*/
|
|
582
|
+
export function buildOptionLookup(command = null) {
|
|
583
|
+
const definition = command ? CLI_COMMAND_DEFINITIONS[command] : { options: CLI_BOOTSTRAP_OPTIONS };
|
|
584
|
+
if (!definition) return new Map();
|
|
585
|
+
|
|
586
|
+
const lookup = new Map();
|
|
587
|
+
for (const [canonicalName, optionDef] of Object.entries(definition.options)) {
|
|
588
|
+
if (optionDef.isPositional) {
|
|
589
|
+
continue;
|
|
590
|
+
}
|
|
591
|
+
lookup.set(canonicalName, { canonicalName, optionDef });
|
|
592
|
+
for (const alias of optionDef.aliases ?? []) {
|
|
593
|
+
lookup.set(alias, { canonicalName, optionDef });
|
|
594
|
+
}
|
|
595
|
+
}
|
|
596
|
+
return lookup;
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
/**
|
|
600
|
+
* Gets positional parameter definitions for a command.
|
|
601
|
+
* @param {string} command - Command name
|
|
602
|
+
* @returns {Array<Object>} List of positional option definitions
|
|
603
|
+
*/
|
|
604
|
+
export function getPositionalDefinitions(command) {
|
|
605
|
+
const definition = CLI_COMMAND_DEFINITIONS[command];
|
|
606
|
+
if (!definition) return [];
|
|
607
|
+
|
|
608
|
+
return Object.entries(definition.options)
|
|
609
|
+
.filter(([, optDef]) => optDef.isPositional)
|
|
610
|
+
.map(([name, optDef]) => ({ name, ...optDef }));
|
|
611
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { CLI_COMMAND_DEFINITIONS } from "./cli-command-definitions.js";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Canonical metadata for all 27 ForgeLoop CLI commands derived directly
|
|
5
|
+
* from CLI_COMMAND_DEFINITIONS to guarantee zero divergence.
|
|
6
|
+
*/
|
|
7
|
+
export const CLI_COMMAND_METADATA = Object.freeze(
|
|
8
|
+
Object.fromEntries(
|
|
9
|
+
Object.entries(CLI_COMMAND_DEFINITIONS).map(([name, def]) => [
|
|
10
|
+
name,
|
|
11
|
+
Object.freeze({
|
|
12
|
+
name: def.name,
|
|
13
|
+
category: def.category,
|
|
14
|
+
mutation: def.mutation,
|
|
15
|
+
options: Object.keys(def.options),
|
|
16
|
+
writes: def.writes,
|
|
17
|
+
removes: def.removes,
|
|
18
|
+
mayExecuteExternalProcess: def.mayExecuteExternalProcess,
|
|
19
|
+
description: def.description,
|
|
20
|
+
}),
|
|
21
|
+
]),
|
|
22
|
+
),
|
|
23
|
+
);
|