zigrix 0.1.0-alpha.8 → 0.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/LICENSE +1 -1
- package/README.md +159 -120
- package/dist/agents/registry.js +19 -2
- package/dist/agents/roles.d.ts +10 -0
- package/dist/agents/roles.js +83 -0
- package/dist/config/defaults.d.ts +88 -6
- package/dist/config/defaults.js +82 -50
- package/dist/config/load.d.ts +5 -3
- package/dist/config/load.js +69 -30
- package/dist/config/schema.d.ts +46 -4
- package/dist/config/schema.js +49 -3
- package/dist/configure.d.ts +2 -0
- package/dist/configure.js +37 -14
- package/dist/dashboard/.next/BUILD_ID +1 -1
- package/dist/dashboard/.next/app-build-manifest.json +13 -13
- package/dist/dashboard/.next/app-path-routes-manifest.json +3 -3
- package/dist/dashboard/.next/build-manifest.json +2 -2
- package/dist/dashboard/.next/prerender-manifest.json +6 -6
- package/dist/dashboard/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/dist/dashboard/.next/server/app/_not-found.html +1 -1
- package/dist/dashboard/.next/server/app/_not-found.rsc +1 -1
- package/dist/dashboard/.next/server/app/api/auth/login/route.js +1 -1
- package/dist/dashboard/.next/server/app/api/auth/login/route_client-reference-manifest.js +1 -1
- package/dist/dashboard/.next/server/app/api/auth/logout/route.js +1 -1
- package/dist/dashboard/.next/server/app/api/auth/logout/route_client-reference-manifest.js +1 -1
- package/dist/dashboard/.next/server/app/api/auth/session/route.js +1 -1
- package/dist/dashboard/.next/server/app/api/auth/session/route_client-reference-manifest.js +1 -1
- package/dist/dashboard/.next/server/app/api/auth/setup/route.js +1 -1
- package/dist/dashboard/.next/server/app/api/auth/setup/route_client-reference-manifest.js +1 -1
- package/dist/dashboard/.next/server/app/api/overview/route_client-reference-manifest.js +1 -1
- package/dist/dashboard/.next/server/app/api/stream/route_client-reference-manifest.js +1 -1
- package/dist/dashboard/.next/server/app/api/tasks/[taskId]/cancel/route_client-reference-manifest.js +1 -1
- package/dist/dashboard/.next/server/app/api/tasks/[taskId]/conversation/route_client-reference-manifest.js +1 -1
- package/dist/dashboard/.next/server/app/api/tasks/[taskId]/route_client-reference-manifest.js +1 -1
- package/dist/dashboard/.next/server/app/login/page_client-reference-manifest.js +1 -1
- package/dist/dashboard/.next/server/app/login.html +1 -1
- package/dist/dashboard/.next/server/app/login.rsc +1 -1
- package/dist/dashboard/.next/server/app/page.js +2 -2
- package/dist/dashboard/.next/server/app/page_client-reference-manifest.js +1 -1
- package/dist/dashboard/.next/server/app/setup/page_client-reference-manifest.js +1 -1
- package/dist/dashboard/.next/server/app/setup.html +1 -1
- package/dist/dashboard/.next/server/app/setup.rsc +1 -1
- package/dist/dashboard/.next/server/app-paths-manifest.json +3 -3
- package/dist/dashboard/.next/server/chunks/972.js +1 -1
- package/dist/dashboard/.next/server/functions-config-manifest.json +3 -3
- package/dist/dashboard/.next/server/middleware.js +1 -1
- package/dist/dashboard/.next/server/pages/404.html +1 -1
- package/dist/dashboard/.next/server/pages/500.html +1 -1
- package/dist/dashboard/.next/static/chunks/app/page-0314989c31e18b4b.js +1 -0
- package/dist/dashboard/.next/static/css/{94d75aff24d0c077.css → c3a7306cb2ba3f6c.css} +1 -1
- package/dist/dashboard.js +47 -0
- package/dist/doctor.js +28 -5
- package/dist/index.js +175 -171
- package/dist/onboard.d.ts +76 -2
- package/dist/onboard.js +529 -25
- package/dist/orchestration/dispatch.d.ts +3 -1
- package/dist/orchestration/dispatch.js +173 -45
- package/dist/orchestration/evidence.js +31 -4
- package/dist/orchestration/finalize.d.ts +1 -0
- package/dist/orchestration/finalize.js +5 -3
- package/dist/orchestration/report.js +9 -1
- package/dist/orchestration/worker.d.ts +1 -1
- package/dist/orchestration/worker.js +58 -8
- package/dist/rules/templates.js +3 -6
- package/dist/state/tasks.d.ts +12 -0
- package/dist/state/tasks.js +7 -0
- package/package.json +23 -2
- package/rules/defaults/README.md +9 -9
- package/rules/defaults/{back-zig.md → backend-agent.md} +4 -4
- package/rules/defaults/{front-zig.md → frontend-agent.md} +4 -4
- package/rules/defaults/orchestrator-agent.md +261 -0
- package/rules/defaults/{qa-zig.md → qa-agent.md} +11 -11
- package/rules/defaults/{sec-zig.md → security-agent.md} +4 -4
- package/rules/defaults/{sys-zig.md → system-agent.md} +8 -9
- package/rules/defaults/worker-common.md +25 -19
- package/skills/zigrix-doctor/SKILL.md +4 -2
- package/skills/zigrix-evidence/SKILL.md +7 -3
- package/skills/zigrix-main-agent-guide/SKILL.md +128 -0
- package/skills/zigrix-shared/SKILL.md +27 -3
- package/skills/zigrix-task-create/SKILL.md +8 -2
- package/skills/zigrix-task-status/SKILL.md +5 -2
- package/skills/zigrix-worker/SKILL.md +12 -4
- package/dist/dashboard/.next/static/chunks/app/page-25f54e54e74fb3af.js +0 -1
- package/rules/defaults/pro-zig.md +0 -238
- /package/dist/dashboard/.next/static/{2a4glWei05xr4Jg0Ly6cp → PT4hYxzrqxj-Zq4ZjtKNg}/_buildManifest.js +0 -0
- /package/dist/dashboard/.next/static/{2a4glWei05xr4Jg0Ly6cp → PT4hYxzrqxj-Zq4ZjtKNg}/_ssgManifest.js +0 -0
package/dist/index.js
CHANGED
|
@@ -4,12 +4,12 @@ import { Command } from 'commander';
|
|
|
4
4
|
import { addAgent, excludeAgent, includeAgent, listAgents, removeAgent, setAgentEnabled, setAgentRole, } from './agents/registry.js';
|
|
5
5
|
import { runConfigure } from './configure.js';
|
|
6
6
|
import { diffValues, getValueAtPath, parseConfigInput, resetValueAtPath, setValueAtPath } from './config/mutate.js';
|
|
7
|
-
import { defaultConfig } from './config/defaults.js';
|
|
7
|
+
import { defaultConfig, resolveAbsolutePath } from './config/defaults.js';
|
|
8
8
|
import { getConfigValue, loadConfig, writeConfigFile, writeDefaultConfig } from './config/load.js';
|
|
9
9
|
import { zigrixConfigJsonSchema } from './config/schema.js';
|
|
10
10
|
import { gatherDoctor, renderDoctorText } from './doctor.js';
|
|
11
11
|
import { runOnboard } from './onboard.js';
|
|
12
|
-
import { dispatchTask } from './orchestration/dispatch.js';
|
|
12
|
+
import { dispatchTask, resolveConfiguredProjectDir } from './orchestration/dispatch.js';
|
|
13
13
|
import { collectEvidence, mergeEvidence } from './orchestration/evidence.js';
|
|
14
14
|
import { finalizeTask } from './orchestration/finalize.js';
|
|
15
15
|
import { runPipeline } from './orchestration/pipeline.js';
|
|
@@ -19,7 +19,7 @@ import { listRules, renderTemplate, validateRules } from './rules/templates.js';
|
|
|
19
19
|
import { runWorkflow, summarizeRun } from './runner/run.js';
|
|
20
20
|
import { loadRunRecord } from './runner/store.js';
|
|
21
21
|
import { ensureBaseState, resolvePaths } from './state/paths.js';
|
|
22
|
-
import { applyStalePolicy, createTask, findStaleTasks, listTaskEvents, listTasks, loadTask, rebuildIndex, recordTaskProgress, updateTaskStatus, } from './state/tasks.js';
|
|
22
|
+
import { applyStalePolicy, createTask, findStaleTasks, listTaskEvents, listTasks, loadTask, rebuildIndex, recordTaskProgress, resolveTaskPaths, updateTaskStatus, } from './state/tasks.js';
|
|
23
23
|
import { verifyState } from './state/verify.js';
|
|
24
24
|
import { runDashboard, DASHBOARD_DEFAULT_PORT } from './dashboard.js';
|
|
25
25
|
const STATUS_MAP = {
|
|
@@ -33,19 +33,16 @@ function printValue(value, json = false) {
|
|
|
33
33
|
}
|
|
34
34
|
console.log(value);
|
|
35
35
|
}
|
|
36
|
-
function requireConfigPath(configPath
|
|
37
|
-
if (!configPath) {
|
|
38
|
-
throw new Error(`zigrix config not found under ${baseDir}; run 'zigrix onboard' first`);
|
|
39
|
-
}
|
|
36
|
+
function requireConfigPath(configPath) {
|
|
40
37
|
return configPath;
|
|
41
38
|
}
|
|
42
39
|
function persistAndPrintMutation(params) {
|
|
43
|
-
const targetPath = requireConfigPath(params.configPath
|
|
40
|
+
const targetPath = requireConfigPath(params.configPath);
|
|
44
41
|
writeConfigFile(targetPath, params.nextConfig);
|
|
45
42
|
printValue({ ok: true, action: params.action, agentId: params.agentId, configPath: targetPath }, params.json);
|
|
46
43
|
}
|
|
47
44
|
function persistConfigMutation(params) {
|
|
48
|
-
const targetPath = requireConfigPath(params.configPath
|
|
45
|
+
const targetPath = requireConfigPath(params.configPath);
|
|
49
46
|
writeConfigFile(targetPath, params.nextConfig);
|
|
50
47
|
printValue({ ok: true, action: params.action, path: params.path ?? null, configPath: targetPath }, params.json);
|
|
51
48
|
}
|
|
@@ -54,10 +51,59 @@ function requireYes(yes, action = 'perform this action') {
|
|
|
54
51
|
throw new Error(`refusing to ${action} without --yes`);
|
|
55
52
|
}
|
|
56
53
|
}
|
|
57
|
-
function loadRuntime(
|
|
58
|
-
const loaded = loadConfig(
|
|
54
|
+
function loadRuntime() {
|
|
55
|
+
const loaded = loadConfig();
|
|
59
56
|
return { ...loaded, paths: resolvePaths(loaded.config) };
|
|
60
57
|
}
|
|
58
|
+
function listRuntimePathValues(loaded) {
|
|
59
|
+
return {
|
|
60
|
+
configPath: loaded.configPath,
|
|
61
|
+
'paths.baseDir': loaded.paths.baseDir,
|
|
62
|
+
'paths.tasksDir': loaded.paths.tasksDir,
|
|
63
|
+
'paths.evidenceDir': loaded.paths.evidenceDir,
|
|
64
|
+
'paths.promptsDir': loaded.paths.promptsDir,
|
|
65
|
+
'paths.eventsFile': loaded.paths.eventsFile,
|
|
66
|
+
'paths.indexFile': loaded.paths.indexFile,
|
|
67
|
+
'paths.runsDir': loaded.paths.runsDir,
|
|
68
|
+
'paths.rulesDir': loaded.paths.rulesDir,
|
|
69
|
+
'workspace.projectsBaseDir': loaded.config.workspace.projectsBaseDir,
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
function resolveRuntimePathValue(loaded, requestedKey) {
|
|
73
|
+
const normalized = requestedKey.trim();
|
|
74
|
+
const aliases = {
|
|
75
|
+
configPath: 'configPath',
|
|
76
|
+
baseDir: 'paths.baseDir',
|
|
77
|
+
tasksDir: 'paths.tasksDir',
|
|
78
|
+
evidenceDir: 'paths.evidenceDir',
|
|
79
|
+
promptsDir: 'paths.promptsDir',
|
|
80
|
+
eventsFile: 'paths.eventsFile',
|
|
81
|
+
indexFile: 'paths.indexFile',
|
|
82
|
+
runsDir: 'paths.runsDir',
|
|
83
|
+
rulesDir: 'paths.rulesDir',
|
|
84
|
+
projectsBaseDir: 'workspace.projectsBaseDir',
|
|
85
|
+
workspaceBaseDir: 'workspace.projectsBaseDir',
|
|
86
|
+
'paths.baseDir': 'paths.baseDir',
|
|
87
|
+
'paths.tasksDir': 'paths.tasksDir',
|
|
88
|
+
'paths.evidenceDir': 'paths.evidenceDir',
|
|
89
|
+
'paths.promptsDir': 'paths.promptsDir',
|
|
90
|
+
'paths.eventsFile': 'paths.eventsFile',
|
|
91
|
+
'paths.indexFile': 'paths.indexFile',
|
|
92
|
+
'paths.runsDir': 'paths.runsDir',
|
|
93
|
+
'paths.rulesDir': 'paths.rulesDir',
|
|
94
|
+
'workspace.projectsBaseDir': 'workspace.projectsBaseDir',
|
|
95
|
+
};
|
|
96
|
+
const canonicalKey = aliases[normalized];
|
|
97
|
+
if (!canonicalKey) {
|
|
98
|
+
throw new Error(`unknown path key: ${requestedKey}`);
|
|
99
|
+
}
|
|
100
|
+
const values = listRuntimePathValues(loaded);
|
|
101
|
+
return {
|
|
102
|
+
requestedKey,
|
|
103
|
+
canonicalKey,
|
|
104
|
+
value: values[canonicalKey] ?? null,
|
|
105
|
+
};
|
|
106
|
+
}
|
|
61
107
|
const { version: pkgVersion } = JSON.parse(fs.readFileSync(new URL('../package.json', import.meta.url), 'utf-8'));
|
|
62
108
|
const program = new Command();
|
|
63
109
|
program
|
|
@@ -65,6 +111,7 @@ program
|
|
|
65
111
|
.description('Zigrix — multi-project parallel task orchestration CLI')
|
|
66
112
|
.version(pkgVersion);
|
|
67
113
|
const config = program.command('config').description('Inspect Zigrix config');
|
|
114
|
+
const pathCmd = program.command('path').description('Resolve runtime paths from Zigrix config');
|
|
68
115
|
const agent = program.command('agent').description('Manage Zigrix agent registry and orchestration membership');
|
|
69
116
|
const rule = program.command('rule').description('Inspect and validate rule assets');
|
|
70
117
|
const template = program.command('template').description('Inspect and modify prompt templates');
|
|
@@ -78,14 +125,20 @@ const pipeline = program.command('pipeline').description('High-level orchestrati
|
|
|
78
125
|
// ─── onboard ────────────────────────────────────────────────────────────────
|
|
79
126
|
program
|
|
80
127
|
.command('onboard')
|
|
81
|
-
.description('Set up Zigrix for first use (creates
|
|
128
|
+
.description('Set up Zigrix for first use (creates config.paths.baseDir state, seeds rules, registers agents, and captures workspace defaults)')
|
|
82
129
|
.option('--yes', 'non-interactive confirmation')
|
|
83
130
|
.option('--json', 'JSON output')
|
|
84
|
-
.option('--project-dir <path>', '
|
|
131
|
+
.option('--project-dir <path>', 'optional directory to import rule templates from (`rules/defaults` or `rules`); otherwise bundled defaults are used')
|
|
132
|
+
.option('--projects-base-dir <path>', 'workspace base directory to persist in zigrix.config.json')
|
|
133
|
+
.option('--orchestrator-id <agentId>', 'set orchestration orchestrator agent id')
|
|
134
|
+
.option('--gateway-url <url>', 'OpenClaw gateway URL (auto-detected from openclaw.json when available)')
|
|
85
135
|
.action(async (options) => {
|
|
86
136
|
const result = await runOnboard({
|
|
87
137
|
yes: Boolean(options.yes),
|
|
88
138
|
projectDir: options.projectDir,
|
|
139
|
+
projectsBaseDir: options.projectsBaseDir,
|
|
140
|
+
orchestratorId: options.orchestratorId,
|
|
141
|
+
gatewayUrl: options.gatewayUrl,
|
|
89
142
|
silent: Boolean(options.json),
|
|
90
143
|
});
|
|
91
144
|
printValue(result, options.json ?? true);
|
|
@@ -96,7 +149,8 @@ program
|
|
|
96
149
|
.description('Reconfigure agents, rules, PATH, skills, or workspace settings')
|
|
97
150
|
.option('--section <section>', 'reconfigure specific section (agents|rules|workspace|path|skills), repeatable', (value, prev = []) => [...prev, value], [])
|
|
98
151
|
.option('--projects-base-dir <path>', 'set projects base directory')
|
|
99
|
-
.option('--project-dir <path>', '
|
|
152
|
+
.option('--project-dir <path>', 'optional directory to import rule templates from (`rules/defaults` or `rules`); otherwise bundled defaults are used')
|
|
153
|
+
.option('--orchestrator-id <agentId>', 'set orchestration orchestrator agent id')
|
|
100
154
|
.option('--yes', 'non-interactive confirmation')
|
|
101
155
|
.option('--json', 'JSON output')
|
|
102
156
|
.action(async (options) => {
|
|
@@ -105,6 +159,7 @@ program
|
|
|
105
159
|
yes: Boolean(options.yes),
|
|
106
160
|
projectDir: options.projectDir,
|
|
107
161
|
projectsBaseDir: options.projectsBaseDir,
|
|
162
|
+
orchestratorId: options.orchestratorId,
|
|
108
163
|
silent: Boolean(options.json),
|
|
109
164
|
});
|
|
110
165
|
printValue(result, options.json ?? true);
|
|
@@ -117,8 +172,8 @@ program
|
|
|
117
172
|
.option('--json', 'JSON output')
|
|
118
173
|
.action((options) => {
|
|
119
174
|
console.error('⚠️ "zigrix init" is deprecated. Use "zigrix onboard" instead.');
|
|
120
|
-
const configPath = writeDefaultConfig(
|
|
121
|
-
const loaded = loadRuntime(
|
|
175
|
+
const configPath = writeDefaultConfig(Boolean(options.yes));
|
|
176
|
+
const loaded = loadRuntime();
|
|
122
177
|
ensureBaseState(loaded.paths);
|
|
123
178
|
rebuildIndex(loaded.paths);
|
|
124
179
|
printValue({ ok: true, path: configPath, deprecated: true, useInstead: 'zigrix onboard' }, options.json);
|
|
@@ -127,11 +182,9 @@ program
|
|
|
127
182
|
program
|
|
128
183
|
.command('doctor')
|
|
129
184
|
.description('Inspect environment, config, and runtime readiness')
|
|
130
|
-
.option('--config <path>')
|
|
131
|
-
.option('--base-dir <path>')
|
|
132
185
|
.option('--json')
|
|
133
186
|
.action((options) => {
|
|
134
|
-
const loaded = loadRuntime(
|
|
187
|
+
const loaded = loadRuntime();
|
|
135
188
|
const payload = gatherDoctor(loaded, loaded.paths);
|
|
136
189
|
if (options.json) {
|
|
137
190
|
printValue(payload, true);
|
|
@@ -139,23 +192,48 @@ program
|
|
|
139
192
|
}
|
|
140
193
|
console.log(renderDoctorText(payload));
|
|
141
194
|
});
|
|
195
|
+
// ─── path ───────────────────────────────────────────────────────────────────
|
|
196
|
+
pathCmd
|
|
197
|
+
.command('get <key>')
|
|
198
|
+
.description('Resolve one runtime path by key or alias (for example: tasksDir, paths.tasksDir, workspace.projectsBaseDir)')
|
|
199
|
+
.option('--json', 'JSON output')
|
|
200
|
+
.action((key, options) => {
|
|
201
|
+
const loaded = loadRuntime();
|
|
202
|
+
const resolved = resolveRuntimePathValue(loaded, key);
|
|
203
|
+
if (options.json) {
|
|
204
|
+
printValue({ ok: true, ...resolved }, true);
|
|
205
|
+
return;
|
|
206
|
+
}
|
|
207
|
+
printValue(resolved.value, false);
|
|
208
|
+
});
|
|
209
|
+
pathCmd
|
|
210
|
+
.command('list')
|
|
211
|
+
.description('List resolved runtime paths')
|
|
212
|
+
.option('--json', 'JSON output')
|
|
213
|
+
.action((options) => {
|
|
214
|
+
const loaded = loadRuntime();
|
|
215
|
+
const values = listRuntimePathValues(loaded);
|
|
216
|
+
if (options.json) {
|
|
217
|
+
printValue({ ok: true, values }, true);
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
220
|
+
for (const [key, value] of Object.entries(values)) {
|
|
221
|
+
console.log(`${key}=${value ?? ''}`);
|
|
222
|
+
}
|
|
223
|
+
});
|
|
142
224
|
// ─── config ─────────────────────────────────────────────────────────────────
|
|
143
225
|
config
|
|
144
226
|
.command('validate')
|
|
145
|
-
.option('--config <path>', 'explicit config path')
|
|
146
|
-
.option('--base-dir <path>', 'Zigrix base directory override')
|
|
147
227
|
.option('--json', 'JSON output')
|
|
148
228
|
.action((options) => {
|
|
149
|
-
const loaded = loadConfig(
|
|
229
|
+
const loaded = loadConfig();
|
|
150
230
|
printValue({ ok: true, configPath: loaded.configPath, baseDir: loaded.baseDir }, options.json);
|
|
151
231
|
});
|
|
152
232
|
config
|
|
153
233
|
.command('get [path]')
|
|
154
|
-
.option('--config <path>', 'explicit config path')
|
|
155
|
-
.option('--base-dir <path>', 'Zigrix base directory override')
|
|
156
234
|
.option('--json', 'JSON output')
|
|
157
235
|
.action((dottedPath, options) => {
|
|
158
|
-
const loaded = loadConfig(
|
|
236
|
+
const loaded = loadConfig();
|
|
159
237
|
printValue(getConfigValue(loaded.config, dottedPath) ?? null, true);
|
|
160
238
|
});
|
|
161
239
|
config
|
|
@@ -175,11 +253,9 @@ config
|
|
|
175
253
|
config
|
|
176
254
|
.command('set <path>')
|
|
177
255
|
.requiredOption('--value <jsonOrString>')
|
|
178
|
-
.option('--config <path>', 'explicit config path')
|
|
179
|
-
.option('--base-dir <path>', 'Zigrix base directory override')
|
|
180
256
|
.option('--json', 'JSON output')
|
|
181
257
|
.action((dottedPath, options) => {
|
|
182
|
-
const loaded = loadConfig(
|
|
258
|
+
const loaded = loadConfig();
|
|
183
259
|
const nextConfig = setValueAtPath(loaded.config, dottedPath, parseConfigInput(options.value));
|
|
184
260
|
persistConfigMutation({
|
|
185
261
|
configPath: loaded.configPath,
|
|
@@ -192,23 +268,19 @@ config
|
|
|
192
268
|
});
|
|
193
269
|
config
|
|
194
270
|
.command('diff <path>')
|
|
195
|
-
.option('--config <path>', 'explicit config path')
|
|
196
|
-
.option('--base-dir <path>', 'Zigrix base directory override')
|
|
197
271
|
.option('--json', 'JSON output')
|
|
198
272
|
.action((dottedPath, options) => {
|
|
199
|
-
const loaded = loadConfig(
|
|
273
|
+
const loaded = loadConfig();
|
|
200
274
|
printValue(diffValues(getValueAtPath(loaded.config, dottedPath), getValueAtPath(defaultConfig, dottedPath)), true);
|
|
201
275
|
});
|
|
202
276
|
config
|
|
203
277
|
.command('reset')
|
|
204
278
|
.option('--path <path>', 'dotted config path to restore from defaults', 'all')
|
|
205
|
-
.option('--config <path>', 'explicit config path')
|
|
206
|
-
.option('--base-dir <path>', 'Zigrix base directory override')
|
|
207
279
|
.option('--yes', 'confirm destructive reset')
|
|
208
280
|
.option('--json', 'JSON output')
|
|
209
281
|
.action((options) => {
|
|
210
282
|
requireYes(options.yes, 'reset config');
|
|
211
|
-
const loaded = loadConfig(
|
|
283
|
+
const loaded = loadConfig();
|
|
212
284
|
const nextConfig = resetValueAtPath(loaded.config, options.path);
|
|
213
285
|
persistConfigMutation({
|
|
214
286
|
configPath: loaded.configPath,
|
|
@@ -222,10 +294,8 @@ config
|
|
|
222
294
|
// ─── agent ──────────────────────────────────────────────────────────────────
|
|
223
295
|
agent
|
|
224
296
|
.command('list')
|
|
225
|
-
.option('--config <path>')
|
|
226
|
-
.option('--base-dir <path>')
|
|
227
297
|
.option('--json')
|
|
228
|
-
.action((options) => printValue(listAgents(loadConfig(
|
|
298
|
+
.action((options) => printValue(listAgents(loadConfig().config), true));
|
|
229
299
|
agent
|
|
230
300
|
.command('add')
|
|
231
301
|
.requiredOption('--id <agentId>')
|
|
@@ -234,102 +304,80 @@ agent
|
|
|
234
304
|
.option('--label <label>')
|
|
235
305
|
.option('--include')
|
|
236
306
|
.option('--disabled')
|
|
237
|
-
.option('--config <path>')
|
|
238
|
-
.option('--base-dir <path>')
|
|
239
307
|
.option('--json')
|
|
240
308
|
.action((options) => {
|
|
241
|
-
const loaded = loadConfig(
|
|
309
|
+
const loaded = loadConfig();
|
|
242
310
|
const result = addAgent(loaded.config, { id: options.id, role: options.role, runtime: options.runtime, label: options.label, enabled: !options.disabled, include: Boolean(options.include) });
|
|
243
311
|
persistAndPrintMutation({ configPath: loaded.configPath, baseDir: loaded.baseDir, nextConfig: result.config, json: options.json, action: 'agent.add', agentId: result.agentId });
|
|
244
312
|
});
|
|
245
313
|
agent
|
|
246
314
|
.command('remove <agentId>')
|
|
247
|
-
.option('--config <path>')
|
|
248
|
-
.option('--base-dir <path>')
|
|
249
315
|
.option('--json')
|
|
250
316
|
.action((agentId, options) => {
|
|
251
|
-
const loaded = loadConfig(
|
|
317
|
+
const loaded = loadConfig();
|
|
252
318
|
const result = removeAgent(loaded.config, agentId);
|
|
253
319
|
persistAndPrintMutation({ configPath: loaded.configPath, baseDir: loaded.baseDir, nextConfig: result.config, json: options.json, action: 'agent.remove', agentId: result.agentId });
|
|
254
320
|
});
|
|
255
321
|
agent
|
|
256
322
|
.command('include <agentId>')
|
|
257
|
-
.option('--config <path>')
|
|
258
|
-
.option('--base-dir <path>')
|
|
259
323
|
.option('--json')
|
|
260
324
|
.action((agentId, options) => {
|
|
261
|
-
const loaded = loadConfig(
|
|
325
|
+
const loaded = loadConfig();
|
|
262
326
|
const result = includeAgent(loaded.config, agentId);
|
|
263
327
|
persistAndPrintMutation({ configPath: loaded.configPath, baseDir: loaded.baseDir, nextConfig: result.config, json: options.json, action: 'agent.include', agentId: result.agentId });
|
|
264
328
|
});
|
|
265
329
|
agent
|
|
266
330
|
.command('exclude <agentId>')
|
|
267
|
-
.option('--config <path>')
|
|
268
|
-
.option('--base-dir <path>')
|
|
269
331
|
.option('--json')
|
|
270
332
|
.action((agentId, options) => {
|
|
271
|
-
const loaded = loadConfig(
|
|
333
|
+
const loaded = loadConfig();
|
|
272
334
|
const result = excludeAgent(loaded.config, agentId);
|
|
273
335
|
persistAndPrintMutation({ configPath: loaded.configPath, baseDir: loaded.baseDir, nextConfig: result.config, json: options.json, action: 'agent.exclude', agentId: result.agentId });
|
|
274
336
|
});
|
|
275
337
|
agent
|
|
276
338
|
.command('enable <agentId>')
|
|
277
|
-
.option('--config <path>')
|
|
278
|
-
.option('--base-dir <path>')
|
|
279
339
|
.option('--json')
|
|
280
340
|
.action((agentId, options) => {
|
|
281
|
-
const loaded = loadConfig(
|
|
341
|
+
const loaded = loadConfig();
|
|
282
342
|
const result = setAgentEnabled(loaded.config, agentId, true);
|
|
283
343
|
persistAndPrintMutation({ configPath: loaded.configPath, baseDir: loaded.baseDir, nextConfig: result.config, json: options.json, action: 'agent.enable', agentId: result.agentId });
|
|
284
344
|
});
|
|
285
345
|
agent
|
|
286
346
|
.command('disable <agentId>')
|
|
287
|
-
.option('--config <path>')
|
|
288
|
-
.option('--base-dir <path>')
|
|
289
347
|
.option('--json')
|
|
290
348
|
.action((agentId, options) => {
|
|
291
|
-
const loaded = loadConfig(
|
|
349
|
+
const loaded = loadConfig();
|
|
292
350
|
const result = setAgentEnabled(loaded.config, agentId, false);
|
|
293
351
|
persistAndPrintMutation({ configPath: loaded.configPath, baseDir: loaded.baseDir, nextConfig: result.config, json: options.json, action: 'agent.disable', agentId: result.agentId });
|
|
294
352
|
});
|
|
295
353
|
agent
|
|
296
354
|
.command('set-role <agentId>')
|
|
297
355
|
.requiredOption('--role <role>')
|
|
298
|
-
.option('--config <path>')
|
|
299
|
-
.option('--base-dir <path>')
|
|
300
356
|
.option('--json')
|
|
301
357
|
.action((agentId, options) => {
|
|
302
|
-
const loaded = loadConfig(
|
|
358
|
+
const loaded = loadConfig();
|
|
303
359
|
const result = setAgentRole(loaded.config, agentId, options.role);
|
|
304
360
|
persistAndPrintMutation({ configPath: loaded.configPath, baseDir: loaded.baseDir, nextConfig: result.config, json: options.json, action: 'agent.set-role', agentId: result.agentId });
|
|
305
361
|
});
|
|
306
362
|
// ─── rule ───────────────────────────────────────────────────────────────────
|
|
307
363
|
rule
|
|
308
364
|
.command('list')
|
|
309
|
-
.option('--config <path>')
|
|
310
|
-
.option('--base-dir <path>')
|
|
311
365
|
.option('--json')
|
|
312
|
-
.action((options) => printValue(listRules(loadConfig(
|
|
366
|
+
.action((options) => printValue(listRules(loadConfig().config), true));
|
|
313
367
|
rule
|
|
314
368
|
.command('get <path>')
|
|
315
|
-
.option('--config <path>')
|
|
316
|
-
.option('--base-dir <path>')
|
|
317
369
|
.option('--json')
|
|
318
|
-
.action((dottedPath, options) => printValue(getConfigValue(loadConfig(
|
|
370
|
+
.action((dottedPath, options) => printValue(getConfigValue(loadConfig().config, dottedPath) ?? null, true));
|
|
319
371
|
rule
|
|
320
372
|
.command('validate')
|
|
321
|
-
.option('--config <path>')
|
|
322
|
-
.option('--base-dir <path>')
|
|
323
373
|
.option('--json')
|
|
324
|
-
.action((options) => printValue(validateRules(loadConfig(
|
|
374
|
+
.action((options) => printValue(validateRules(loadConfig().config), true));
|
|
325
375
|
rule
|
|
326
376
|
.command('render <templateKind>')
|
|
327
377
|
.requiredOption('--context <json>')
|
|
328
|
-
.option('--config <path>')
|
|
329
|
-
.option('--base-dir <path>')
|
|
330
378
|
.option('--json')
|
|
331
379
|
.action((templateKind, options) => {
|
|
332
|
-
const loaded = loadConfig(
|
|
380
|
+
const loaded = loadConfig();
|
|
333
381
|
const tpl = getConfigValue(loaded.config, `templates.${templateKind}`);
|
|
334
382
|
if (!tpl?.body)
|
|
335
383
|
throw new Error(`template not found: ${templateKind}`);
|
|
@@ -339,59 +387,49 @@ rule
|
|
|
339
387
|
rule
|
|
340
388
|
.command('set <path>')
|
|
341
389
|
.requiredOption('--value <jsonOrString>')
|
|
342
|
-
.option('--config <path>')
|
|
343
|
-
.option('--base-dir <path>')
|
|
344
390
|
.option('--json')
|
|
345
391
|
.action((dottedPath, options) => {
|
|
346
392
|
if (!dottedPath.startsWith('rules.'))
|
|
347
393
|
throw new Error('rule path must start with rules.');
|
|
348
|
-
const loaded = loadConfig(
|
|
394
|
+
const loaded = loadConfig();
|
|
349
395
|
const nextConfig = setValueAtPath(loaded.config, dottedPath, parseConfigInput(options.value));
|
|
350
396
|
persistConfigMutation({ configPath: loaded.configPath, baseDir: loaded.baseDir, nextConfig, json: options.json, action: 'rule.set', path: dottedPath });
|
|
351
397
|
});
|
|
352
398
|
rule
|
|
353
399
|
.command('diff <path>')
|
|
354
|
-
.option('--config <path>')
|
|
355
|
-
.option('--base-dir <path>')
|
|
356
400
|
.option('--json')
|
|
357
401
|
.action((dottedPath, options) => {
|
|
358
402
|
if (!dottedPath.startsWith('rules.'))
|
|
359
403
|
throw new Error('rule path must start with rules.');
|
|
360
|
-
const loaded = loadConfig(
|
|
404
|
+
const loaded = loadConfig();
|
|
361
405
|
printValue(diffValues(getValueAtPath(loaded.config, dottedPath), getValueAtPath(defaultConfig, dottedPath)), true);
|
|
362
406
|
});
|
|
363
407
|
rule
|
|
364
408
|
.command('reset')
|
|
365
409
|
.requiredOption('--path <path>')
|
|
366
|
-
.option('--config <path>')
|
|
367
|
-
.option('--base-dir <path>')
|
|
368
410
|
.option('--yes')
|
|
369
411
|
.option('--json')
|
|
370
412
|
.action((options) => {
|
|
371
413
|
if (!options.path.startsWith('rules.'))
|
|
372
414
|
throw new Error('rule path must start with rules.');
|
|
373
415
|
requireYes(options.yes, 'reset rule config');
|
|
374
|
-
const loaded = loadConfig(
|
|
416
|
+
const loaded = loadConfig();
|
|
375
417
|
const nextConfig = resetValueAtPath(loaded.config, options.path);
|
|
376
418
|
persistConfigMutation({ configPath: loaded.configPath, baseDir: loaded.baseDir, nextConfig, json: options.json, action: 'rule.reset', path: options.path });
|
|
377
419
|
});
|
|
378
420
|
// ─── template ───────────────────────────────────────────────────────────────
|
|
379
421
|
template
|
|
380
422
|
.command('list')
|
|
381
|
-
.option('--config <path>')
|
|
382
|
-
.option('--base-dir <path>')
|
|
383
423
|
.option('--json')
|
|
384
424
|
.action((options) => {
|
|
385
|
-
const loaded = loadConfig(
|
|
425
|
+
const loaded = loadConfig();
|
|
386
426
|
printValue(Object.keys(loaded.config.templates).map((name) => ({ name, path: `templates.${name}` })), true);
|
|
387
427
|
});
|
|
388
428
|
template
|
|
389
429
|
.command('get <name>')
|
|
390
|
-
.option('--config <path>')
|
|
391
|
-
.option('--base-dir <path>')
|
|
392
430
|
.option('--json')
|
|
393
431
|
.action((name, options) => {
|
|
394
|
-
const loaded = loadConfig(
|
|
432
|
+
const loaded = loadConfig();
|
|
395
433
|
printValue(getValueAtPath(loaded.config, `templates.${name}`) ?? null, true);
|
|
396
434
|
});
|
|
397
435
|
template
|
|
@@ -400,11 +438,9 @@ template
|
|
|
400
438
|
.option('--format <format>', 'markdown|text')
|
|
401
439
|
.option('--version <version>')
|
|
402
440
|
.option('--placeholders <jsonArray>')
|
|
403
|
-
.option('--config <path>')
|
|
404
|
-
.option('--base-dir <path>')
|
|
405
441
|
.option('--json')
|
|
406
442
|
.action((name, options) => {
|
|
407
|
-
const loaded = loadConfig(
|
|
443
|
+
const loaded = loadConfig();
|
|
408
444
|
const current = getValueAtPath(loaded.config, `templates.${name}`);
|
|
409
445
|
if (!current)
|
|
410
446
|
throw new Error(`template not found: ${name}`);
|
|
@@ -420,33 +456,27 @@ template
|
|
|
420
456
|
});
|
|
421
457
|
template
|
|
422
458
|
.command('diff <name>')
|
|
423
|
-
.option('--config <path>')
|
|
424
|
-
.option('--base-dir <path>')
|
|
425
459
|
.option('--json')
|
|
426
460
|
.action((name, options) => {
|
|
427
|
-
const loaded = loadConfig(
|
|
461
|
+
const loaded = loadConfig();
|
|
428
462
|
printValue(diffValues(getValueAtPath(loaded.config, `templates.${name}`), getValueAtPath(defaultConfig, `templates.${name}`)), true);
|
|
429
463
|
});
|
|
430
464
|
template
|
|
431
465
|
.command('reset <name>')
|
|
432
|
-
.option('--config <path>')
|
|
433
|
-
.option('--base-dir <path>')
|
|
434
466
|
.option('--yes')
|
|
435
467
|
.option('--json')
|
|
436
468
|
.action((name, options) => {
|
|
437
469
|
requireYes(options.yes, 'reset template config');
|
|
438
|
-
const loaded = loadConfig(
|
|
470
|
+
const loaded = loadConfig();
|
|
439
471
|
const nextConfig = resetValueAtPath(loaded.config, `templates.${name}`);
|
|
440
472
|
persistConfigMutation({ configPath: loaded.configPath, baseDir: loaded.baseDir, nextConfig, json: options.json, action: 'template.reset', path: `templates.${name}` });
|
|
441
473
|
});
|
|
442
474
|
template
|
|
443
475
|
.command('render <name>')
|
|
444
476
|
.requiredOption('--context <json>')
|
|
445
|
-
.option('--config <path>')
|
|
446
|
-
.option('--base-dir <path>')
|
|
447
477
|
.option('--json')
|
|
448
478
|
.action((name, options) => {
|
|
449
|
-
const loaded = loadConfig(
|
|
479
|
+
const loaded = loadConfig();
|
|
450
480
|
const item = getValueAtPath(loaded.config, `templates.${name}`);
|
|
451
481
|
if (!item?.body)
|
|
452
482
|
throw new Error(`template not found: ${name}`);
|
|
@@ -456,25 +486,21 @@ template
|
|
|
456
486
|
reset
|
|
457
487
|
.command('config')
|
|
458
488
|
.option('--path <path>', 'dotted config path to restore from defaults', 'all')
|
|
459
|
-
.option('--config <path>')
|
|
460
|
-
.option('--base-dir <path>')
|
|
461
489
|
.option('--yes')
|
|
462
490
|
.option('--json')
|
|
463
491
|
.action((options) => {
|
|
464
492
|
requireYes(options.yes, 'reset config');
|
|
465
|
-
const loaded = loadConfig(
|
|
493
|
+
const loaded = loadConfig();
|
|
466
494
|
const nextConfig = resetValueAtPath(loaded.config, options.path);
|
|
467
495
|
persistConfigMutation({ configPath: loaded.configPath, baseDir: loaded.baseDir, nextConfig, json: options.json, action: 'reset.config', path: options.path });
|
|
468
496
|
});
|
|
469
497
|
reset
|
|
470
498
|
.command('state')
|
|
471
|
-
.option('--base-dir <path>')
|
|
472
|
-
.option('--config <path>')
|
|
473
499
|
.option('--yes')
|
|
474
500
|
.option('--json')
|
|
475
501
|
.action((options) => {
|
|
476
502
|
requireYes(options.yes, 'reset runtime state');
|
|
477
|
-
const loaded = loadRuntime(
|
|
503
|
+
const loaded = loadRuntime();
|
|
478
504
|
// Remove task data but preserve config and rules
|
|
479
505
|
for (const dir of [loaded.paths.tasksDir, loaded.paths.evidenceDir, loaded.paths.promptsDir, loaded.paths.runsDir]) {
|
|
480
506
|
fs.rmSync(dir, { recursive: true, force: true });
|
|
@@ -488,38 +514,32 @@ reset
|
|
|
488
514
|
// ─── state ──────────────────────────────────────────────────────────────────
|
|
489
515
|
state
|
|
490
516
|
.command('check')
|
|
491
|
-
.option('--base-dir <path>')
|
|
492
|
-
.option('--config <path>')
|
|
493
517
|
.option('--json')
|
|
494
518
|
.action((options) => {
|
|
495
|
-
const loaded = loadRuntime(
|
|
519
|
+
const loaded = loadRuntime();
|
|
496
520
|
printValue(verifyState(loaded.paths), true);
|
|
497
521
|
});
|
|
498
522
|
program
|
|
499
523
|
.command('index-rebuild')
|
|
500
|
-
.option('--config <path>')
|
|
501
|
-
.option('--base-dir <path>')
|
|
502
524
|
.option('--json')
|
|
503
525
|
.action((options) => {
|
|
504
|
-
const loaded = loadRuntime(
|
|
526
|
+
const loaded = loadRuntime();
|
|
505
527
|
printValue(rebuildIndex(loaded.paths), true);
|
|
506
528
|
});
|
|
507
529
|
// ─── task ───────────────────────────────────────────────────────────────────
|
|
508
530
|
task
|
|
509
531
|
.command('dispatch')
|
|
510
|
-
.description('Create a task with full orchestration metadata and boot prompt
|
|
532
|
+
.description('Create a task with full orchestration metadata and boot prompt')
|
|
511
533
|
.requiredOption('--title <title>')
|
|
512
534
|
.requiredOption('--description <description>')
|
|
513
535
|
.requiredOption('--scale <scale>', 'simple|normal|risky|large')
|
|
514
536
|
.option('--project-dir <path>', 'target project directory')
|
|
515
537
|
.option('--requested-by <name>', 'who requested this task')
|
|
516
538
|
.option('--constraints <constraints>', 'task constraints')
|
|
517
|
-
.option('--config <path>')
|
|
518
|
-
.option('--base-dir <path>')
|
|
519
539
|
.option('--json')
|
|
520
540
|
.action((options) => {
|
|
521
|
-
const loaded = loadRuntime(
|
|
522
|
-
const result = dispatchTask(loaded.paths, {
|
|
541
|
+
const loaded = loadRuntime();
|
|
542
|
+
const result = dispatchTask(loaded.paths, loaded.config, {
|
|
523
543
|
title: options.title,
|
|
524
544
|
description: options.description,
|
|
525
545
|
scale: options.scale,
|
|
@@ -538,37 +558,47 @@ task
|
|
|
538
558
|
.option('--project-dir <path>', 'target project directory for this task')
|
|
539
559
|
.option('--requested-by <name>', 'who requested this task')
|
|
540
560
|
.option('--prefix <prefix>', 'task ID prefix (DEV|TEST)', 'DEV')
|
|
541
|
-
.option('--config <path>')
|
|
542
|
-
.option('--base-dir <path>')
|
|
543
561
|
.option('--json')
|
|
544
562
|
.action((options) => {
|
|
545
|
-
const loaded = loadRuntime(
|
|
546
|
-
const
|
|
547
|
-
|
|
563
|
+
const loaded = loadRuntime();
|
|
564
|
+
const projectDir = options.projectDir
|
|
565
|
+
? resolveAbsolutePath(options.projectDir)
|
|
566
|
+
: resolveConfiguredProjectDir(loaded.config);
|
|
567
|
+
const created = createTask(loaded.paths, {
|
|
568
|
+
title: options.title,
|
|
569
|
+
description: options.description,
|
|
570
|
+
scale: options.scale,
|
|
571
|
+
requiredAgents: options.requiredAgent,
|
|
572
|
+
projectDir,
|
|
573
|
+
requestedBy: options.requestedBy,
|
|
574
|
+
prefix: options.prefix,
|
|
575
|
+
});
|
|
576
|
+
printValue({
|
|
577
|
+
...created,
|
|
578
|
+
...resolveTaskPaths(loaded.paths, created.taskId),
|
|
579
|
+
}, true);
|
|
548
580
|
});
|
|
549
581
|
task
|
|
550
582
|
.command('list')
|
|
551
|
-
.option('--config <path>')
|
|
552
|
-
.option('--base-dir <path>')
|
|
553
583
|
.option('--json')
|
|
554
|
-
.action((options) => printValue(listTasks(loadRuntime(
|
|
584
|
+
.action((options) => printValue(listTasks(loadRuntime().paths), true));
|
|
555
585
|
task
|
|
556
586
|
.command('status <taskId>')
|
|
557
|
-
.option('--config <path>')
|
|
558
|
-
.option('--base-dir <path>')
|
|
559
587
|
.option('--json')
|
|
560
588
|
.action((taskId, options) => {
|
|
561
|
-
const
|
|
589
|
+
const loaded = loadRuntime();
|
|
590
|
+
const payload = loadTask(loaded.paths, taskId);
|
|
562
591
|
if (!payload)
|
|
563
592
|
throw new Error(`task not found: ${taskId}`);
|
|
564
|
-
printValue(
|
|
593
|
+
printValue({
|
|
594
|
+
...payload,
|
|
595
|
+
...resolveTaskPaths(loaded.paths, taskId),
|
|
596
|
+
}, true);
|
|
565
597
|
});
|
|
566
598
|
task
|
|
567
599
|
.command('events [taskId]')
|
|
568
|
-
.option('--config <path>')
|
|
569
|
-
.option('--base-dir <path>')
|
|
570
600
|
.option('--json')
|
|
571
|
-
.action((taskId, options) => printValue(listTaskEvents(loadRuntime(
|
|
601
|
+
.action((taskId, options) => printValue(listTaskEvents(loadRuntime().paths, taskId), true));
|
|
572
602
|
task
|
|
573
603
|
.command('progress')
|
|
574
604
|
.requiredOption('--task-id <taskId>')
|
|
@@ -576,11 +606,9 @@ task
|
|
|
576
606
|
.requiredOption('--message <message>')
|
|
577
607
|
.option('--unit-id <unitId>')
|
|
578
608
|
.option('--work-package <workPackage>')
|
|
579
|
-
.option('--config <path>')
|
|
580
|
-
.option('--base-dir <path>')
|
|
581
609
|
.option('--json')
|
|
582
610
|
.action((options) => {
|
|
583
|
-
const payload = recordTaskProgress(loadRuntime(
|
|
611
|
+
const payload = recordTaskProgress(loadRuntime().paths, { taskId: options.taskId, actor: options.actor, message: options.message, unitId: options.unitId, workPackage: options.workPackage });
|
|
584
612
|
if (!payload)
|
|
585
613
|
throw new Error(`task not found: ${options.taskId}`);
|
|
586
614
|
printValue(payload, true);
|
|
@@ -590,11 +618,9 @@ task
|
|
|
590
618
|
.option('--hours <hours>', 'stale threshold hours', '24')
|
|
591
619
|
.option('--apply')
|
|
592
620
|
.option('--reason <reason>', 'block reason', 'stale_timeout')
|
|
593
|
-
.option('--config <path>')
|
|
594
|
-
.option('--base-dir <path>')
|
|
595
621
|
.option('--json')
|
|
596
622
|
.action((options) => {
|
|
597
|
-
const paths = loadRuntime(
|
|
623
|
+
const paths = loadRuntime().paths;
|
|
598
624
|
const hours = Number(options.hours);
|
|
599
625
|
const payload = options.apply ? applyStalePolicy(paths, hours, options.reason) : { ok: true, hours, count: findStaleTasks(paths, hours).length, tasks: findStaleTasks(paths, hours) };
|
|
600
626
|
printValue(payload, true);
|
|
@@ -602,11 +628,9 @@ task
|
|
|
602
628
|
for (const [name, status] of Object.entries(STATUS_MAP)) {
|
|
603
629
|
task
|
|
604
630
|
.command(`${name} <taskId>`)
|
|
605
|
-
.option('--config <path>')
|
|
606
|
-
.option('--base-dir <path>')
|
|
607
631
|
.option('--json')
|
|
608
632
|
.action((taskId, options) => {
|
|
609
|
-
const payload = updateTaskStatus(loadRuntime(
|
|
633
|
+
const payload = updateTaskStatus(loadRuntime().paths, taskId, status);
|
|
610
634
|
if (!payload)
|
|
611
635
|
throw new Error(`task not found: ${taskId}`);
|
|
612
636
|
printValue(payload, true);
|
|
@@ -614,18 +638,16 @@ for (const [name, status] of Object.entries(STATUS_MAP)) {
|
|
|
614
638
|
}
|
|
615
639
|
task
|
|
616
640
|
.command('finalize <taskId>')
|
|
617
|
-
.description('Finalize a task: merge evidence, check units,
|
|
618
|
-
.option('--auto-report', 'auto-transition to REPORTED
|
|
641
|
+
.description('Finalize a task: merge evidence, check units, and auto-report by default')
|
|
642
|
+
.option('--no-auto-report', 'skip auto-transition to REPORTED (default: auto-report enabled)')
|
|
619
643
|
.option('--sec-issues', 'flag security issues (blocks auto-report)')
|
|
620
644
|
.option('--qa-issues', 'flag QA issues (blocks auto-report)')
|
|
621
|
-
.option('--config <path>')
|
|
622
|
-
.option('--base-dir <path>')
|
|
623
645
|
.option('--json')
|
|
624
646
|
.action((taskId, options) => {
|
|
625
|
-
const loaded = loadRuntime(
|
|
647
|
+
const loaded = loadRuntime();
|
|
626
648
|
const result = finalizeTask(loaded.paths, {
|
|
627
649
|
taskId,
|
|
628
|
-
autoReport:
|
|
650
|
+
autoReport: options.autoReport !== false,
|
|
629
651
|
secIssues: Boolean(options.secIssues),
|
|
630
652
|
qaIssues: Boolean(options.qaIssues),
|
|
631
653
|
});
|
|
@@ -644,11 +666,9 @@ worker
|
|
|
644
666
|
.option('--work-package <workPackage>')
|
|
645
667
|
.option('--dod <dod>')
|
|
646
668
|
.option('--project-dir <path>', 'working directory for this worker')
|
|
647
|
-
.option('--config <path>')
|
|
648
|
-
.option('--base-dir <path>')
|
|
649
669
|
.option('--json')
|
|
650
670
|
.action((options) => {
|
|
651
|
-
const payload = prepareWorker(loadRuntime(
|
|
671
|
+
const payload = prepareWorker(loadRuntime().paths, { taskId: options.taskId, agentId: options.agentId, description: options.description, constraints: options.constraints, unitId: options.unitId, workPackage: options.workPackage, dod: options.dod, projectDir: options.projectDir });
|
|
652
672
|
if (!payload)
|
|
653
673
|
throw new Error(`task not found: ${options.taskId}`);
|
|
654
674
|
printValue(payload, true);
|
|
@@ -663,11 +683,9 @@ worker
|
|
|
663
683
|
.option('--unit-id <unitId>')
|
|
664
684
|
.option('--work-package <workPackage>')
|
|
665
685
|
.option('--reason <reason>')
|
|
666
|
-
.option('--config <path>')
|
|
667
|
-
.option('--base-dir <path>')
|
|
668
686
|
.option('--json')
|
|
669
687
|
.action((options) => {
|
|
670
|
-
const payload = registerWorker(loadRuntime(
|
|
688
|
+
const payload = registerWorker(loadRuntime().paths, { taskId: options.taskId, agentId: options.agentId, sessionKey: options.sessionKey, runId: options.runId, sessionId: options.sessionId, unitId: options.unitId, workPackage: options.workPackage, reason: options.reason });
|
|
671
689
|
if (!payload)
|
|
672
690
|
throw new Error(`task not found: ${options.taskId}`);
|
|
673
691
|
printValue(payload, true);
|
|
@@ -682,11 +700,9 @@ worker
|
|
|
682
700
|
.option('--result <result>', 'done|blocked|skipped', 'done')
|
|
683
701
|
.option('--unit-id <unitId>')
|
|
684
702
|
.option('--work-package <workPackage>')
|
|
685
|
-
.option('--config <path>')
|
|
686
|
-
.option('--base-dir <path>')
|
|
687
703
|
.option('--json')
|
|
688
704
|
.action((options) => {
|
|
689
|
-
const payload = completeWorker(loadRuntime(
|
|
705
|
+
const payload = completeWorker(loadRuntime().paths, { taskId: options.taskId, agentId: options.agentId, sessionKey: options.sessionKey, runId: options.runId, sessionId: options.sessionId, result: options.result, unitId: options.unitId, workPackage: options.workPackage });
|
|
690
706
|
if (!payload)
|
|
691
707
|
throw new Error(`task not found: ${options.taskId}`);
|
|
692
708
|
printValue(payload, true);
|
|
@@ -705,11 +721,9 @@ evidence
|
|
|
705
721
|
.option('--tool-result <toolResult>', 'repeatable', (value, prev = []) => [...prev, value], [])
|
|
706
722
|
.option('--notes <notes>')
|
|
707
723
|
.option('--limit <limit>', 'transcript line limit', '40')
|
|
708
|
-
.option('--config <path>')
|
|
709
|
-
.option('--base-dir <path>')
|
|
710
724
|
.option('--json')
|
|
711
725
|
.action((options) => {
|
|
712
|
-
const payload = collectEvidence(loadRuntime(
|
|
726
|
+
const payload = collectEvidence(loadRuntime().paths, { taskId: options.taskId, agentId: options.agentId, runId: options.runId, unitId: options.unitId, sessionKey: options.sessionKey, sessionId: options.sessionId, transcript: options.transcript, summary: options.summary, toolResults: options.toolResult, notes: options.notes, limit: Number(options.limit) });
|
|
713
727
|
if (!payload)
|
|
714
728
|
throw new Error(`task not found: ${options.taskId}`);
|
|
715
729
|
printValue(payload, true);
|
|
@@ -719,11 +733,9 @@ evidence
|
|
|
719
733
|
.requiredOption('--task-id <taskId>')
|
|
720
734
|
.option('--required-agent <agent>', 'repeatable', (value, prev = []) => [...prev, value], [])
|
|
721
735
|
.option('--require-qa')
|
|
722
|
-
.option('--config <path>')
|
|
723
|
-
.option('--base-dir <path>')
|
|
724
736
|
.option('--json')
|
|
725
737
|
.action((options) => {
|
|
726
|
-
const payload = mergeEvidence(loadRuntime(
|
|
738
|
+
const payload = mergeEvidence(loadRuntime().paths, { taskId: options.taskId, requiredAgents: options.requiredAgent, requireQa: Boolean(options.requireQa) });
|
|
727
739
|
if (!payload)
|
|
728
740
|
throw new Error(`task not found: ${options.taskId}`);
|
|
729
741
|
printValue(payload, true);
|
|
@@ -733,11 +745,9 @@ report
|
|
|
733
745
|
.command('render')
|
|
734
746
|
.requiredOption('--task-id <taskId>')
|
|
735
747
|
.option('--record-events')
|
|
736
|
-
.option('--config <path>')
|
|
737
|
-
.option('--base-dir <path>')
|
|
738
748
|
.option('--json')
|
|
739
749
|
.action((options) => {
|
|
740
|
-
const payload = renderReport(loadRuntime(
|
|
750
|
+
const payload = renderReport(loadRuntime().paths, { taskId: options.taskId, recordEvents: Boolean(options.recordEvents) });
|
|
741
751
|
if (!payload)
|
|
742
752
|
throw new Error(`task not found: ${options.taskId}`);
|
|
743
753
|
printValue(payload, true);
|
|
@@ -753,22 +763,18 @@ pipeline
|
|
|
753
763
|
.option('--require-qa')
|
|
754
764
|
.option('--auto-report')
|
|
755
765
|
.option('--record-feedback')
|
|
756
|
-
.option('--config <path>')
|
|
757
|
-
.option('--base-dir <path>')
|
|
758
766
|
.option('--json')
|
|
759
767
|
.action((options) => {
|
|
760
|
-
const payload = runPipeline(loadRuntime(
|
|
768
|
+
const payload = runPipeline(loadRuntime().paths, { title: options.title, description: options.description, scale: options.scale, requiredAgents: options.requiredAgent, evidenceSummaries: options.evidenceSummary, requireQa: Boolean(options.requireQa), autoReport: Boolean(options.autoReport), recordFeedback: Boolean(options.recordFeedback) });
|
|
761
769
|
printValue(payload, true);
|
|
762
770
|
});
|
|
763
771
|
// ─── run / inspect ──────────────────────────────────────────────────────────
|
|
764
772
|
program
|
|
765
773
|
.command('run <workflowPath>')
|
|
766
774
|
.description('Run a minimal sequential workflow file')
|
|
767
|
-
.option('--config <path>')
|
|
768
|
-
.option('--base-dir <path>')
|
|
769
775
|
.option('--json')
|
|
770
776
|
.action(async (workflowPath, options) => {
|
|
771
|
-
const loaded = loadConfig(
|
|
777
|
+
const loaded = loadConfig();
|
|
772
778
|
const result = await runWorkflow({ config: loaded.config, workflowPath });
|
|
773
779
|
if (options.json) {
|
|
774
780
|
printValue({ ...result.record, savedPath: result.savedPath }, true);
|
|
@@ -780,11 +786,9 @@ program
|
|
|
780
786
|
program
|
|
781
787
|
.command('inspect <runIdOrPath>')
|
|
782
788
|
.description('Inspect a saved run record')
|
|
783
|
-
.option('--config <path>')
|
|
784
|
-
.option('--base-dir <path>')
|
|
785
789
|
.option('--json')
|
|
786
790
|
.action((runIdOrPath, options) => {
|
|
787
|
-
const loaded = loadConfig(
|
|
791
|
+
const loaded = loadConfig();
|
|
788
792
|
printValue(loadRunRecord(loaded.config, runIdOrPath), true);
|
|
789
793
|
});
|
|
790
794
|
// ─── dashboard ──────────────────────────────────────────────────────────────
|