opencode-agent-skill 7.7.0 → 9.0.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/CHANGELOG.md +63 -3
- package/README.md +675 -581
- package/bin/ocskill.mjs +358 -156
- package/docs/DETERMINISTIC-TOOLS.md +25 -8
- package/docs/ENGINEERING-DESIGN.md +31 -13
- package/docs/EVALS.md +34 -12
- package/docs/NPM-PUBLISH.md +6 -6
- package/docs/OPENCODE-COMPAT.md +11 -8
- package/docs/TRACE-SCHEMA.md +15 -2
- package/docs/V8-INTELLIGENCE-RELIABILITY.md +206 -0
- package/docs/V9-SPEED-INTELLIGENCE.md +102 -0
- package/evals/live/tasks.json +6 -6
- package/evals/polyglot/fixtures/polyglot-bench/api/generated/client.ts +2 -0
- package/evals/polyglot/fixtures/polyglot-bench/api/openapi.json +25 -0
- package/evals/polyglot/fixtures/polyglot-bench/db/migrations/20260920_add_order_key.sql +1 -0
- package/evals/polyglot/fixtures/polyglot-bench/dotnet/OrderService.cs +8 -0
- package/evals/polyglot/fixtures/polyglot-bench/java/PriceService.java +5 -0
- package/evals/polyglot/fixtures/polyglot-bench/monorepo/package.json +6 -0
- package/evals/polyglot/fixtures/polyglot-bench/monorepo/packages/api/package.json +4 -0
- package/evals/polyglot/fixtures/polyglot-bench/monorepo/packages/web/package.json +7 -0
- package/evals/polyglot/fixtures/polyglot-bench/monorepo/pnpm-lock.yaml +5 -0
- package/evals/polyglot/fixtures/polyglot-bench/next/app/api/products/route.ts +7 -0
- package/evals/polyglot/fixtures/polyglot-bench/python/tenant_auth.py +4 -0
- package/evals/polyglot/fixtures/polyglot-bench/react-native/keyboard.ts +3 -0
- package/evals/polyglot/graders/polyglot-bench.mjs +101 -0
- package/evals/polyglot/tasks.json +54 -0
- package/global-config/AGENTS.md +10 -7
- package/global-config/agents/integration-verifier.md +1 -1
- package/global-config/agents/plan-checker.md +1 -1
- package/global-config/commands/run.md +9 -5
- package/global-config/plugins/ues-router/capabilities.js +4 -0
- package/global-config/plugins/ues-router/index.js +414 -21
- package/global-config/plugins/ues-router/router.js +140 -23
- package/global-config/skills/engineering-orchestrator/references/long-horizon.md +6 -4
- package/lib/aci.mjs +128 -0
- package/lib/benchmark-confidence.mjs +135 -0
- package/lib/cli-utils.mjs +41 -0
- package/lib/container-sandbox.mjs +102 -0
- package/lib/context-manifest.mjs +300 -22
- package/lib/control-center.mjs +36 -3
- package/lib/eval-order.mjs +9 -0
- package/lib/eval-telemetry.mjs +5 -2
- package/lib/gate-receipt.mjs +52 -0
- package/lib/installer.mjs +39 -25
- package/lib/learning-engine.mjs +236 -38
- package/lib/opencode-compat.mjs +25 -10
- package/lib/orchestrator-policy.mjs +101 -20
- package/lib/process-runner.mjs +30 -9
- package/lib/runtime-events.mjs +31 -0
- package/lib/semantic-index.mjs +318 -0
- package/lib/task-engine.mjs +416 -24
- package/lib/trajectory.mjs +89 -0
- package/lib/windows-shim.mjs +227 -0
- package/lib/worktree-sandbox.mjs +85 -3
- package/package.json +10 -4
- package/scripts/check-release-tag.mjs +22 -0
- package/scripts/control-center.mjs +25 -0
- package/scripts/eval-live.mjs +39 -58
- package/scripts/eval-matrix.mjs +155 -0
- package/scripts/smoke-packed-install.mjs +138 -4
- package/scripts/smoke-plain-install.mjs +91 -0
- package/scripts/validate-live-suite.mjs +3 -3
- package/scripts/validate.mjs +27 -5
package/bin/ocskill.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
2
|
+
import { writeFileSync } from "node:fs"
|
|
3
3
|
import { spawnSync } from "node:child_process"
|
|
4
4
|
import { fileURLToPath } from "node:url"
|
|
5
5
|
import path from "node:path"
|
|
@@ -15,6 +15,7 @@ import {
|
|
|
15
15
|
import { compareVersions } from "../lib/version.mjs"
|
|
16
16
|
import { resolveLatestPublishedVersion } from "../lib/update-resolver.mjs"
|
|
17
17
|
import { readRouterConfig, writeRouterConfig } from "../lib/router-config.mjs"
|
|
18
|
+
import { resolveWindowsCommand } from "../lib/windows-shim.mjs"
|
|
18
19
|
import {
|
|
19
20
|
detectStack,
|
|
20
21
|
detectTestCommands,
|
|
@@ -24,10 +25,15 @@ import {
|
|
|
24
25
|
checkWorkingTree,
|
|
25
26
|
} from "../lib/repo-inspect.mjs"
|
|
26
27
|
import { buildRepoGraph } from "../lib/repo-graph.mjs"
|
|
28
|
+
import { buildSemanticIndex, semanticIndexStatus } from "../lib/semantic-index.mjs"
|
|
29
|
+
import { aciReferences, aciSearch, aciTextSearch, aciView } from "../lib/aci.mjs"
|
|
30
|
+
import { appendTrajectoryEvent, readTrajectory } from "../lib/trajectory.mjs"
|
|
31
|
+
import { containerSandboxCapability, runContainerSandbox } from "../lib/container-sandbox.mjs"
|
|
27
32
|
import { analyzePlan } from "../lib/task-graph.mjs"
|
|
28
33
|
import {
|
|
29
34
|
addBlocker,
|
|
30
35
|
addDecision,
|
|
36
|
+
attachTaskSession,
|
|
31
37
|
approvePlan,
|
|
32
38
|
completeTask,
|
|
33
39
|
contextPack,
|
|
@@ -42,18 +48,32 @@ import {
|
|
|
42
48
|
workStatus,
|
|
43
49
|
heartbeatTask,
|
|
44
50
|
recoverStaleTasks,
|
|
51
|
+
recoverTask,
|
|
45
52
|
recordVerificationReceipt,
|
|
46
53
|
workspaceFingerprint,
|
|
54
|
+
createPlanVerificationReceipt,
|
|
55
|
+
createIntegrationVerificationReceipt,
|
|
56
|
+
runtimeEvents,
|
|
47
57
|
} from "../lib/task-engine.mjs"
|
|
48
58
|
import { reviewScope } from "../lib/review-scope.mjs"
|
|
49
59
|
import { buildVerificationPlan } from "../lib/verification-plan.mjs"
|
|
50
60
|
import { resolveAdaptiveModel, resolveModel } from "../lib/model-policy.mjs"
|
|
51
61
|
import { createVerificationReceipt } from "../lib/evidence-receipt.mjs"
|
|
52
62
|
import { classifyEngineeringTask } from "../lib/orchestrator-policy.mjs"
|
|
53
|
-
import { createTaskSandbox, listTaskSandboxes, removeTaskSandbox } from "../lib/worktree-sandbox.mjs"
|
|
54
|
-
import { analyzeEvalTraces, saveLearningAnalysis, readLearningState, acceptLearning } from "../lib/learning-engine.mjs"
|
|
63
|
+
import { createTaskSandbox, integrateTaskSandbox, listTaskSandboxes, removeTaskSandbox } from "../lib/worktree-sandbox.mjs"
|
|
64
|
+
import { analyzeEvalTraces, saveLearningAnalysis, readLearningState, acceptLearning, promoteLearning } from "../lib/learning-engine.mjs"
|
|
55
65
|
import { hermesStatus, buildHermesDelegationPrompt, hermesOneShotArgs } from "../lib/hermes-bridge.mjs"
|
|
56
66
|
import { readModelPolicy, validateModelID, writeModelPolicy } from "../lib/model-config.mjs"
|
|
67
|
+
import {
|
|
68
|
+
clipOutput,
|
|
69
|
+
errorMessage,
|
|
70
|
+
optionInt,
|
|
71
|
+
optionIntOrUndefined,
|
|
72
|
+
optionValue,
|
|
73
|
+
positionalArg,
|
|
74
|
+
readJsonFile,
|
|
75
|
+
readTextFile,
|
|
76
|
+
} from "../lib/cli-utils.mjs"
|
|
57
77
|
|
|
58
78
|
const args = process.argv.slice(2)
|
|
59
79
|
const command = args[0] || "help"
|
|
@@ -76,6 +96,11 @@ Usage:
|
|
|
76
96
|
ocskill evidence [dir] Collect stack, verification and Git evidence
|
|
77
97
|
ocskill working-tree [dir] Report Git branch/HEAD/dirty state
|
|
78
98
|
ocskill repo-graph [dir] Build a bounded source import/dependency graph
|
|
99
|
+
ocskill index <status|build|rebuild> [dir]
|
|
100
|
+
Build/reuse the persistent incremental semantic index
|
|
101
|
+
ocskill aci <search|refs|view|text> ...
|
|
102
|
+
Bounded evidence-first code search/view interface
|
|
103
|
+
ocskill trace <show|append> ... Inspect or append redacted operational trajectory events
|
|
79
104
|
ocskill review-scope [base] [dir]
|
|
80
105
|
Enumerate changed files, review coverage and risk
|
|
81
106
|
ocskill verification-plan [dir]
|
|
@@ -87,8 +112,9 @@ Usage:
|
|
|
87
112
|
ocskill model-policy <role> [--attempt N]
|
|
88
113
|
Resolve light/standard/heavy escalation tier
|
|
89
114
|
ocskill task-policy <text> Classify task mode/risk/context/model tier
|
|
90
|
-
ocskill sandbox <action> ...
|
|
91
|
-
|
|
115
|
+
ocskill sandbox <action> ... Create, integrate and clean isolated Git worktree sandboxes
|
|
116
|
+
Also supports capability/exec for fail-closed container verification
|
|
117
|
+
ocskill learn <action> ... Analyze eval traces and promote benchmark-validated lessons
|
|
92
118
|
ocskill hermes <action> ... Optional Hermes adapter/status
|
|
93
119
|
ocskill dashboard [dir] [--serve] [--port N]
|
|
94
120
|
Generate/serve the local UES Control Center
|
|
@@ -105,16 +131,20 @@ Usage:
|
|
|
105
131
|
ocskill work init <slug> [dir] --goal <text>
|
|
106
132
|
ocskill work plan <slug> <plan.json> [dir]
|
|
107
133
|
ocskill work status|resume <slug> [dir]
|
|
108
|
-
ocskill work
|
|
134
|
+
ocskill work gate-receipt <slug> <plan|integration> [dir] --evidence <text> [--verdict PASS|FAIL|PARTIAL] [--verifier <role>] [--session-id <id>] [--report-file <file>] [--out <file>]
|
|
135
|
+
ocskill work approve-plan <slug> [dir] --evidence <plan-checker-evidence> [--receipt-file <file>]
|
|
109
136
|
ocskill work start <slug> <task-id> [dir] [--lease-ms N]
|
|
110
|
-
ocskill work
|
|
137
|
+
ocskill work attach-session <slug> <task-id> [dir] --run-id <id> --session-id <id> [--execution-dir <dir>] [--sandbox-dir <dir>]
|
|
138
|
+
ocskill work heartbeat <slug> <task-id> [dir] --run-id <id>
|
|
111
139
|
ocskill work recover <slug> [dir] [--force]
|
|
112
|
-
ocskill work
|
|
113
|
-
ocskill work
|
|
114
|
-
ocskill work
|
|
140
|
+
ocskill work recover-task <slug> <task-id> [dir] [--force] [--reason <text>]
|
|
141
|
+
ocskill work events <slug> [dir] [--limit N]
|
|
142
|
+
ocskill work verify-command <slug> <task-id> [dir] --run-id <id> -- <command> [args...]
|
|
143
|
+
ocskill work complete <slug> <task-id> [dir] --run-id <id> --evidence <text> [--report-file <file>]
|
|
144
|
+
ocskill work fail <slug> <task-id> [dir] --run-id <id> --reason <text>
|
|
115
145
|
ocskill work decision <slug> [dir] --text <decision>
|
|
116
146
|
ocskill work block|unblock <slug> [dir] --text <blocker>
|
|
117
|
-
ocskill work verify-integration <slug> [dir] --verdict PASS|FAIL|PARTIAL --evidence <text> [--report-file <file>]
|
|
147
|
+
ocskill work verify-integration <slug> [dir] --verdict PASS|FAIL|PARTIAL --evidence <text> [--report-file <file>] [--receipt-file <file>]
|
|
118
148
|
ocskill work finalize <slug> [dir] --evidence <integration-evidence>
|
|
119
149
|
|
|
120
150
|
Model routing:
|
|
@@ -127,38 +157,6 @@ Usage:
|
|
|
127
157
|
`)
|
|
128
158
|
}
|
|
129
159
|
|
|
130
|
-
function findWindowsCommand(name) {
|
|
131
|
-
if (path.isAbsolute(name) && existsSync(name)) return name
|
|
132
|
-
|
|
133
|
-
const result = spawnSync("where", [name], { encoding: "utf8" })
|
|
134
|
-
if (result.status !== 0 || !result.stdout) return null
|
|
135
|
-
|
|
136
|
-
const matches = result.stdout.split(/\r?\n/).map((line) => line.trim()).filter(Boolean)
|
|
137
|
-
return matches.find((item) => /\.(cmd|bat)$/i.test(item)) || matches[0] || null
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
function quoteCmd(value) {
|
|
141
|
-
if (/^[A-Za-z0-9_@%+=:,./\\-]+$/.test(value)) return value
|
|
142
|
-
return `"${value.replaceAll('"', '""')}"`
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
function findNodeShimEntry(cmdPath) {
|
|
146
|
-
const dir = path.dirname(cmdPath)
|
|
147
|
-
|
|
148
|
-
if (/^npm(?:\.cmd|\.exe)?$/i.test(path.basename(cmdPath))) {
|
|
149
|
-
const entry = path.join(dir, "node_modules", "npm", "bin", "npm-cli.js")
|
|
150
|
-
if (existsSync(entry)) return entry
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
let shim = ""
|
|
154
|
-
try {
|
|
155
|
-
shim = readFileSync(cmdPath, "utf8")
|
|
156
|
-
} catch {}
|
|
157
|
-
const match = shim.match(/node_modules[\\/][^\s"]+?\.(?:js|mjs)/gi)?.at(-1)
|
|
158
|
-
if (!match) return null
|
|
159
|
-
const entry = path.resolve(dir, match)
|
|
160
|
-
return existsSync(entry) ? entry : null
|
|
161
|
-
}
|
|
162
160
|
|
|
163
161
|
function run(executable, commandArgs, options = {}) {
|
|
164
162
|
const common = { stdio: "inherit", ...options }
|
|
@@ -168,26 +166,22 @@ function run(executable, commandArgs, options = {}) {
|
|
|
168
166
|
return result.status ?? 1
|
|
169
167
|
}
|
|
170
168
|
|
|
171
|
-
const resolved =
|
|
172
|
-
if (!resolved)
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
const entry = findNodeShimEntry(resolved)
|
|
176
|
-
if (entry) {
|
|
177
|
-
const result = spawnSync(process.execPath, [entry, ...commandArgs], common)
|
|
178
|
-
return result.status ?? 1
|
|
179
|
-
}
|
|
180
|
-
const line = [resolved, ...commandArgs].map(quoteCmd).join(" ")
|
|
181
|
-
const result = spawnSync(process.env.ComSpec || "cmd.exe", ["/d", "/s", "/c", line], common)
|
|
182
|
-
return result.status ?? 1
|
|
169
|
+
const resolved = resolveWindowsCommand(executable)
|
|
170
|
+
if (!resolved) {
|
|
171
|
+
console.error("[ocskill] No safely executable Windows command found for: " + executable)
|
|
172
|
+
return 127
|
|
183
173
|
}
|
|
184
174
|
|
|
185
|
-
const result = spawnSync(
|
|
175
|
+
const result = spawnSync(
|
|
176
|
+
resolved.executable,
|
|
177
|
+
[...resolved.argsPrefix, ...commandArgs],
|
|
178
|
+
common,
|
|
179
|
+
)
|
|
186
180
|
return result.status ?? 1
|
|
187
181
|
}
|
|
188
182
|
|
|
189
183
|
function hasCommand(name) {
|
|
190
|
-
if (process.platform === "win32") return
|
|
184
|
+
if (process.platform === "win32") return resolveWindowsCommand(name) !== null
|
|
191
185
|
return spawnSync("which", [name], { stdio: "ignore" }).status === 0
|
|
192
186
|
}
|
|
193
187
|
|
|
@@ -198,22 +192,20 @@ function runCapture(executable, commandArgs, options = {}) {
|
|
|
198
192
|
return spawnSync(executable, commandArgs, common)
|
|
199
193
|
}
|
|
200
194
|
|
|
201
|
-
const resolved =
|
|
202
|
-
if (!resolved)
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
const line = [resolved, ...commandArgs].map(quoteCmd).join(" ")
|
|
209
|
-
return spawnSync(
|
|
210
|
-
process.env.ComSpec || "cmd.exe",
|
|
211
|
-
["/d", "/s", "/c", line],
|
|
212
|
-
common,
|
|
213
|
-
)
|
|
195
|
+
const resolved = resolveWindowsCommand(executable)
|
|
196
|
+
if (!resolved) {
|
|
197
|
+
return {
|
|
198
|
+
status: 127,
|
|
199
|
+
stdout: "",
|
|
200
|
+
stderr: `No safely executable Windows command found for: ${executable}`,
|
|
201
|
+
}
|
|
214
202
|
}
|
|
215
203
|
|
|
216
|
-
return spawnSync(
|
|
204
|
+
return spawnSync(
|
|
205
|
+
resolved.executable,
|
|
206
|
+
[...resolved.argsPrefix, ...commandArgs],
|
|
207
|
+
common,
|
|
208
|
+
)
|
|
217
209
|
}
|
|
218
210
|
|
|
219
211
|
|
|
@@ -278,8 +270,12 @@ async function doctor() {
|
|
|
278
270
|
console.log(`Node: ${process.version}`)
|
|
279
271
|
console.log(`Config: ${getConfigDir()}`)
|
|
280
272
|
console.log(`npm: ${hasCommand("npm") ? "OK" : "MISSING"}`)
|
|
281
|
-
|
|
282
|
-
|
|
273
|
+
const openCodeAvailable = hasCommand("opencode")
|
|
274
|
+
console.log(`OpenCode: ${openCodeAvailable ? "OK" : "MISSING"}`)
|
|
275
|
+
if (openCodeAvailable) {
|
|
276
|
+
const code = run("opencode", ["--version"])
|
|
277
|
+
if (code !== 0) process.exitCode = code
|
|
278
|
+
}
|
|
283
279
|
await status()
|
|
284
280
|
}
|
|
285
281
|
|
|
@@ -309,7 +305,7 @@ async function evaluateReport() {
|
|
|
309
305
|
}
|
|
310
306
|
|
|
311
307
|
async function inspectRepository() {
|
|
312
|
-
printJson(await repoMap(args
|
|
308
|
+
printJson(await repoMap(positionalArg(args, 1) || process.cwd()))
|
|
313
309
|
}
|
|
314
310
|
|
|
315
311
|
async function inspectImpact() {
|
|
@@ -319,42 +315,129 @@ async function inspectImpact() {
|
|
|
319
315
|
process.exitCode = 2
|
|
320
316
|
return
|
|
321
317
|
}
|
|
322
|
-
printJson(await impactMap(args
|
|
318
|
+
printJson(await impactMap(positionalArg(args, 2) || process.cwd(), query))
|
|
323
319
|
}
|
|
324
320
|
|
|
325
321
|
async function inspectEvidence() {
|
|
326
|
-
printJson(await collectEvidence(args
|
|
322
|
+
printJson(await collectEvidence(positionalArg(args, 1) || process.cwd()))
|
|
327
323
|
}
|
|
328
324
|
|
|
329
325
|
async function inspectWorkingTree() {
|
|
330
|
-
printJson(await checkWorkingTree(args
|
|
326
|
+
printJson(await checkWorkingTree(positionalArg(args, 1) || process.cwd()))
|
|
331
327
|
}
|
|
332
328
|
|
|
333
329
|
async function inspectStack() {
|
|
334
|
-
printJson(await detectStack(args
|
|
330
|
+
printJson(await detectStack(positionalArg(args, 1) || process.cwd()))
|
|
335
331
|
}
|
|
336
332
|
|
|
337
333
|
async function inspectTests() {
|
|
338
|
-
printJson(await detectTestCommands(args
|
|
334
|
+
printJson(await detectTestCommands(positionalArg(args, 1) || process.cwd()))
|
|
339
335
|
}
|
|
340
336
|
|
|
341
|
-
function
|
|
342
|
-
|
|
343
|
-
return index >= 0 ? args[index + 1] : null
|
|
337
|
+
async function inspectRepoGraph() {
|
|
338
|
+
printJson(await buildRepoGraph(positionalArg(args, 1) || process.cwd()))
|
|
344
339
|
}
|
|
345
340
|
|
|
346
|
-
async function
|
|
347
|
-
|
|
341
|
+
async function semanticIndexControl() {
|
|
342
|
+
const action = args[1] || "status"
|
|
343
|
+
const root = positionalArg(args, 2) || process.cwd()
|
|
344
|
+
try {
|
|
345
|
+
if (action === "status") {
|
|
346
|
+
printJson(await semanticIndexStatus(root))
|
|
347
|
+
return
|
|
348
|
+
}
|
|
349
|
+
if (action === "build" || action === "rebuild") {
|
|
350
|
+
const built = await buildSemanticIndex(root, { rebuild: action === "rebuild" })
|
|
351
|
+
printJson({ action, stats: built.stats })
|
|
352
|
+
return
|
|
353
|
+
}
|
|
354
|
+
throw new Error("Usage: ocskill index <status|build|rebuild> [dir]")
|
|
355
|
+
} catch (error) {
|
|
356
|
+
console.error(errorMessage(error))
|
|
357
|
+
process.exitCode = 1
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
async function aciControl() {
|
|
362
|
+
const action = args[1]
|
|
363
|
+
try {
|
|
364
|
+
if (action === "search") {
|
|
365
|
+
const query = args[2]
|
|
366
|
+
const root = positionalArg(args, 3) || process.cwd()
|
|
367
|
+
if (!query) throw new Error("Usage: ocskill aci search <query> [dir] [--limit N]")
|
|
368
|
+
printJson(await aciSearch(root, query, { limit: optionInt(args, "--limit", 20) }))
|
|
369
|
+
return
|
|
370
|
+
}
|
|
371
|
+
if (action === "refs") {
|
|
372
|
+
const symbol = args[2]
|
|
373
|
+
const root = positionalArg(args, 3) || process.cwd()
|
|
374
|
+
if (!symbol) throw new Error("Usage: ocskill aci refs <symbol> [dir] [--limit N]")
|
|
375
|
+
printJson(await aciReferences(root, symbol, { limit: optionInt(args, "--limit", 40) }))
|
|
376
|
+
return
|
|
377
|
+
}
|
|
378
|
+
if (action === "view") {
|
|
379
|
+
const file = args[2]
|
|
380
|
+
const root = positionalArg(args, 3) || process.cwd()
|
|
381
|
+
if (!file) throw new Error("Usage: ocskill aci view <file> [dir] [--line N] [--lines N]")
|
|
382
|
+
printJson(await aciView(root, file, {
|
|
383
|
+
line: optionInt(args, "--line", 1),
|
|
384
|
+
startLine: optionInt(args, "--start-line", 0),
|
|
385
|
+
lines: optionInt(args, "--lines", 120),
|
|
386
|
+
}))
|
|
387
|
+
return
|
|
388
|
+
}
|
|
389
|
+
if (action === "text") {
|
|
390
|
+
const query = args[2]
|
|
391
|
+
const root = positionalArg(args, 3) || process.cwd()
|
|
392
|
+
if (!query) throw new Error("Usage: ocskill aci text <query> [dir] [--limit N]")
|
|
393
|
+
printJson(await aciTextSearch(root, query, { limit: optionInt(args, "--limit", 80) }))
|
|
394
|
+
return
|
|
395
|
+
}
|
|
396
|
+
throw new Error("Usage: ocskill aci <search|refs|view|text> ...")
|
|
397
|
+
} catch (error) {
|
|
398
|
+
console.error(errorMessage(error))
|
|
399
|
+
process.exitCode = 1
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
async function traceControl() {
|
|
404
|
+
const action = args[1] || "show"
|
|
405
|
+
try {
|
|
406
|
+
if (action === "show") {
|
|
407
|
+
const traceID = args[2]
|
|
408
|
+
const root = positionalArg(args, 3) || process.cwd()
|
|
409
|
+
if (!traceID) throw new Error("Usage: ocskill trace show <trace-id> [dir] [--limit N]")
|
|
410
|
+
printJson(await readTrajectory(root, traceID, { limit: optionInt(args, "--limit", 200) }))
|
|
411
|
+
return
|
|
412
|
+
}
|
|
413
|
+
if (action === "append") {
|
|
414
|
+
const traceID = args[2]
|
|
415
|
+
const root = positionalArg(args, 3) || process.cwd()
|
|
416
|
+
const type = optionValue(args, "--type")
|
|
417
|
+
const payload64 = optionValue(args, "--payload-b64")
|
|
418
|
+
if (!traceID || !type) throw new Error("Usage: ocskill trace append <trace-id> [dir] --type <type> [--payload-b64 <base64-json>]")
|
|
419
|
+
let payload = {}
|
|
420
|
+
if (payload64) {
|
|
421
|
+
payload = JSON.parse(Buffer.from(payload64, "base64").toString("utf8"))
|
|
422
|
+
}
|
|
423
|
+
printJson(await appendTrajectoryEvent(root, traceID, type, payload))
|
|
424
|
+
return
|
|
425
|
+
}
|
|
426
|
+
throw new Error("Usage: ocskill trace <show|append> ...")
|
|
427
|
+
} catch (error) {
|
|
428
|
+
console.error(errorMessage(error))
|
|
429
|
+
process.exitCode = 1
|
|
430
|
+
}
|
|
348
431
|
}
|
|
349
432
|
|
|
350
433
|
async function inspectReviewScope() {
|
|
351
|
-
const base = args
|
|
352
|
-
const root = args
|
|
434
|
+
const base = positionalArg(args, 1)
|
|
435
|
+
const root = positionalArg(args, 2) || process.cwd()
|
|
353
436
|
printJson(reviewScope(root, base))
|
|
354
437
|
}
|
|
355
438
|
|
|
356
439
|
async function inspectVerificationPlan() {
|
|
357
|
-
printJson(await buildVerificationPlan(args
|
|
440
|
+
printJson(await buildVerificationPlan(positionalArg(args, 1) || process.cwd(), optionValue(args, "--base")))
|
|
358
441
|
}
|
|
359
442
|
|
|
360
443
|
async function inspectTaskGraph() {
|
|
@@ -365,12 +448,12 @@ async function inspectTaskGraph() {
|
|
|
365
448
|
return
|
|
366
449
|
}
|
|
367
450
|
try {
|
|
368
|
-
const plan =
|
|
451
|
+
const plan = readJsonFile(file)
|
|
369
452
|
const analysis = analyzePlan(plan)
|
|
370
453
|
printJson(analysis)
|
|
371
454
|
if (!analysis.valid) process.exitCode = 1
|
|
372
455
|
} catch (error) {
|
|
373
|
-
console.error(error
|
|
456
|
+
console.error(errorMessage(error))
|
|
374
457
|
process.exitCode = 1
|
|
375
458
|
}
|
|
376
459
|
}
|
|
@@ -383,78 +466,144 @@ async function inspectContextPack() {
|
|
|
383
466
|
process.exitCode = 2
|
|
384
467
|
return
|
|
385
468
|
}
|
|
386
|
-
printJson(await contextPack(args
|
|
469
|
+
printJson(await contextPack(positionalArg(args, 3) || process.cwd(), slug, taskID))
|
|
387
470
|
}
|
|
388
471
|
|
|
389
472
|
async function workControl() {
|
|
390
473
|
const action = args[1]
|
|
391
474
|
const slug = args[2]
|
|
392
475
|
if (!action || !slug) {
|
|
393
|
-
console.error("Usage: ocskill work <init|plan|status|resume|approve-plan|start|heartbeat|recover|verify-command|complete|fail|decision|block|unblock|verify-integration|finalize> <slug> ...")
|
|
476
|
+
console.error("Usage: ocskill work <init|plan|status|resume|gate-receipt|approve-plan|start|attach-session|heartbeat|recover|recover-task|events|verify-command|complete|fail|decision|block|unblock|verify-integration|finalize> <slug> ...")
|
|
394
477
|
process.exitCode = 2
|
|
395
478
|
return
|
|
396
479
|
}
|
|
397
480
|
|
|
398
481
|
try {
|
|
399
482
|
if (action === "init") {
|
|
400
|
-
const root = args
|
|
401
|
-
printJson(await initWork(root, slug, optionValue("--goal")))
|
|
483
|
+
const root = positionalArg(args, 3) || process.cwd()
|
|
484
|
+
printJson(await initWork(root, slug, optionValue(args, "--goal")))
|
|
402
485
|
return
|
|
403
486
|
}
|
|
404
487
|
if (action === "plan") {
|
|
405
488
|
const planFile = args[3]
|
|
406
|
-
const root = args
|
|
489
|
+
const root = positionalArg(args, 4) || process.cwd()
|
|
407
490
|
if (!planFile) throw new Error("Usage: ocskill work plan <slug> <plan.json> [dir]")
|
|
408
491
|
const result = await importPlan(root, slug, planFile)
|
|
409
492
|
printJson({ state: result.state, analysis: result.analysis, dir: result.paths.dir })
|
|
410
493
|
return
|
|
411
494
|
}
|
|
412
495
|
if (action === "status") {
|
|
413
|
-
const root = args
|
|
496
|
+
const root = positionalArg(args, 3) || process.cwd()
|
|
414
497
|
printJson(await workStatus(root, slug))
|
|
415
498
|
return
|
|
416
499
|
}
|
|
417
500
|
if (action === "resume") {
|
|
418
|
-
const root = args
|
|
501
|
+
const root = positionalArg(args, 3) || process.cwd()
|
|
419
502
|
printJson(await resumeWork(root, slug))
|
|
420
503
|
return
|
|
421
504
|
}
|
|
505
|
+
if (action === "gate-receipt") {
|
|
506
|
+
const kind = args[3]
|
|
507
|
+
const root = positionalArg(args, 4) || process.cwd()
|
|
508
|
+
if (!["plan", "integration"].includes(kind)) {
|
|
509
|
+
throw new Error("Usage: ocskill work gate-receipt <slug> <plan|integration> [dir] --evidence <text>")
|
|
510
|
+
}
|
|
511
|
+
const reportFile = optionValue(args, "--report-file")
|
|
512
|
+
const report = reportFile ? readTextFile(reportFile) : null
|
|
513
|
+
const input = {
|
|
514
|
+
verdict: optionValue(args, "--verdict") || "PASS",
|
|
515
|
+
verifier: optionValue(args, "--verifier") || undefined,
|
|
516
|
+
sessionID: optionValue(args, "--session-id"),
|
|
517
|
+
runId: optionValue(args, "--run-id"),
|
|
518
|
+
evidence: optionValue(args, "--evidence"),
|
|
519
|
+
report,
|
|
520
|
+
}
|
|
521
|
+
const receipt = kind === "plan"
|
|
522
|
+
? await createPlanVerificationReceipt(root, slug, input)
|
|
523
|
+
: await createIntegrationVerificationReceipt(root, slug, input)
|
|
524
|
+
const outputFile = optionValue(args, "--out")
|
|
525
|
+
if (outputFile) {
|
|
526
|
+
const resolved = path.resolve(outputFile)
|
|
527
|
+
writeFileSync(resolved, JSON.stringify(receipt, null, 2) + "\n", "utf8")
|
|
528
|
+
printJson({ file: resolved, receipt })
|
|
529
|
+
} else {
|
|
530
|
+
printJson(receipt)
|
|
531
|
+
}
|
|
532
|
+
return
|
|
533
|
+
}
|
|
422
534
|
if (action === "approve-plan") {
|
|
423
|
-
const root = args
|
|
424
|
-
|
|
535
|
+
const root = positionalArg(args, 3) || process.cwd()
|
|
536
|
+
const receiptFile = optionValue(args, "--receipt-file")
|
|
537
|
+
const receipt = receiptFile ? readJsonFile(receiptFile) : null
|
|
538
|
+
printJson(await approvePlan(root, slug, optionValue(args, "--evidence"), { receipt }))
|
|
425
539
|
return
|
|
426
540
|
}
|
|
427
541
|
if (action === "start") {
|
|
428
542
|
const taskID = args[3]
|
|
429
|
-
const root = args
|
|
543
|
+
const root = positionalArg(args, 4) || process.cwd()
|
|
430
544
|
if (!taskID) throw new Error("Usage: ocskill work start <slug> <task-id> [dir]")
|
|
431
545
|
printJson(await startTask(root, slug, taskID, {
|
|
432
|
-
leaseMs:
|
|
546
|
+
leaseMs: optionIntOrUndefined(args, "--lease-ms"),
|
|
433
547
|
}))
|
|
434
548
|
return
|
|
435
549
|
}
|
|
550
|
+
if (action === "attach-session") {
|
|
551
|
+
const taskID = args[3]
|
|
552
|
+
const root = positionalArg(args, 4) || process.cwd()
|
|
553
|
+
if (!taskID) throw new Error("Usage: ocskill work attach-session <slug> <task-id> [dir] --run-id <id> --session-id <id>")
|
|
554
|
+
printJson(await attachTaskSession(
|
|
555
|
+
root,
|
|
556
|
+
slug,
|
|
557
|
+
taskID,
|
|
558
|
+
optionValue(args, "--run-id"),
|
|
559
|
+
optionValue(args, "--session-id"),
|
|
560
|
+
{
|
|
561
|
+
executionDir: optionValue(args, "--execution-dir"),
|
|
562
|
+
sandboxDir: optionValue(args, "--sandbox-dir"),
|
|
563
|
+
},
|
|
564
|
+
))
|
|
565
|
+
return
|
|
566
|
+
}
|
|
436
567
|
if (action === "heartbeat") {
|
|
437
568
|
const taskID = args[3]
|
|
438
|
-
const root = args
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
569
|
+
const root = positionalArg(args, 4) || process.cwd()
|
|
570
|
+
const runId = optionValue(args, "--run-id")
|
|
571
|
+
if (!taskID || !runId) throw new Error("Usage: ocskill work heartbeat <slug> <task-id> [dir] --run-id <id>")
|
|
572
|
+
printJson(await heartbeatTask(root, slug, taskID, runId, {
|
|
573
|
+
leaseMs: optionIntOrUndefined(args, "--lease-ms"),
|
|
442
574
|
}))
|
|
443
575
|
return
|
|
444
576
|
}
|
|
445
577
|
if (action === "recover") {
|
|
446
|
-
const root = args
|
|
578
|
+
const root = positionalArg(args, 3) || process.cwd()
|
|
447
579
|
printJson(await recoverStaleTasks(root, slug, { force: args.includes("--force") }))
|
|
448
580
|
return
|
|
449
581
|
}
|
|
582
|
+
if (action === "recover-task") {
|
|
583
|
+
const taskID = args[3]
|
|
584
|
+
const root = positionalArg(args, 4) || process.cwd()
|
|
585
|
+
if (!taskID) throw new Error("Usage: ocskill work recover-task <slug> <task-id> [dir] [--force] [--reason <text>]")
|
|
586
|
+
printJson(await recoverTask(root, slug, taskID, {
|
|
587
|
+
force: args.includes("--force"),
|
|
588
|
+
reason: optionValue(args, "--reason"),
|
|
589
|
+
}))
|
|
590
|
+
return
|
|
591
|
+
}
|
|
592
|
+
if (action === "events") {
|
|
593
|
+
const root = positionalArg(args, 3) || process.cwd()
|
|
594
|
+
const limit = optionInt(args, "--limit", 200)
|
|
595
|
+
printJson(await runtimeEvents(root, slug, { limit }))
|
|
596
|
+
return
|
|
597
|
+
}
|
|
450
598
|
if (action === "verify-command") {
|
|
451
599
|
const taskID = args[3]
|
|
452
|
-
const root = args
|
|
600
|
+
const root = positionalArg(args, 4) || process.cwd()
|
|
453
601
|
const separator = args.indexOf("--")
|
|
454
602
|
const executable = separator >= 0 ? args[separator + 1] : null
|
|
455
603
|
const commandArgs = separator >= 0 ? args.slice(separator + 2) : []
|
|
456
|
-
|
|
457
|
-
|
|
604
|
+
const runId = optionValue(args, "--run-id")
|
|
605
|
+
if (!taskID || !runId || !executable) {
|
|
606
|
+
throw new Error("Usage: ocskill work verify-command <slug> <task-id> [dir] --run-id <id> -- <command> [args...]")
|
|
458
607
|
}
|
|
459
608
|
const startedAt = new Date().toISOString()
|
|
460
609
|
const before = workspaceFingerprint(root)
|
|
@@ -465,7 +614,7 @@ async function workControl() {
|
|
|
465
614
|
})
|
|
466
615
|
const receipt = createVerificationReceipt({
|
|
467
616
|
task: taskID,
|
|
468
|
-
runId
|
|
617
|
+
runId,
|
|
469
618
|
command: executable,
|
|
470
619
|
args: commandArgs,
|
|
471
620
|
cwd: path.resolve(root),
|
|
@@ -479,15 +628,11 @@ async function workControl() {
|
|
|
479
628
|
workspaceAfter: workspaceFingerprint(root),
|
|
480
629
|
})
|
|
481
630
|
const recorded = await recordVerificationReceipt(root, slug, taskID, receipt)
|
|
482
|
-
const clip = (value) => {
|
|
483
|
-
const text = String(value || "")
|
|
484
|
-
return text.length <= 8000 ? text : "...[truncated]\n" + text.slice(-8000)
|
|
485
|
-
}
|
|
486
631
|
printJson({
|
|
487
632
|
receipt: recorded,
|
|
488
633
|
output: {
|
|
489
|
-
stdout:
|
|
490
|
-
stderr:
|
|
634
|
+
stdout: clipOutput(result.stdout),
|
|
635
|
+
stderr: clipOutput(result.stderr),
|
|
491
636
|
},
|
|
492
637
|
})
|
|
493
638
|
if ((result.status ?? 1) !== 0) process.exitCode = result.status ?? 1
|
|
@@ -495,61 +640,66 @@ async function workControl() {
|
|
|
495
640
|
}
|
|
496
641
|
if (action === "complete") {
|
|
497
642
|
const taskID = args[3]
|
|
498
|
-
const root = args
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
const
|
|
643
|
+
const root = positionalArg(args, 4) || process.cwd()
|
|
644
|
+
const runId = optionValue(args, "--run-id")
|
|
645
|
+
if (!taskID || !runId) throw new Error("Usage: ocskill work complete <slug> <task-id> [dir] --run-id <id> --evidence <text>")
|
|
646
|
+
const reportFile = optionValue(args, "--report-file")
|
|
647
|
+
const report = reportFile ? readTextFile(reportFile) : null
|
|
502
648
|
printJson(await completeTask(root, slug, taskID, {
|
|
503
|
-
evidence: optionValue("--evidence"),
|
|
649
|
+
evidence: optionValue(args, "--evidence"),
|
|
504
650
|
report,
|
|
505
|
-
runId
|
|
651
|
+
runId,
|
|
506
652
|
}))
|
|
507
653
|
return
|
|
508
654
|
}
|
|
509
655
|
if (action === "fail") {
|
|
510
656
|
const taskID = args[3]
|
|
511
|
-
const root = args
|
|
512
|
-
|
|
513
|
-
|
|
657
|
+
const root = positionalArg(args, 4) || process.cwd()
|
|
658
|
+
const runId = optionValue(args, "--run-id")
|
|
659
|
+
if (!taskID || !runId) throw new Error("Usage: ocskill work fail <slug> <task-id> [dir] --run-id <id> --reason <text>")
|
|
660
|
+
printJson(await failTask(root, slug, taskID, optionValue(args, "--reason"), { runId }))
|
|
514
661
|
return
|
|
515
662
|
}
|
|
516
663
|
if (action === "decision") {
|
|
517
|
-
const root = args
|
|
518
|
-
printJson(await addDecision(root, slug, optionValue("--text")))
|
|
664
|
+
const root = positionalArg(args, 3) || process.cwd()
|
|
665
|
+
printJson(await addDecision(root, slug, optionValue(args, "--text")))
|
|
519
666
|
return
|
|
520
667
|
}
|
|
521
668
|
if (action === "block") {
|
|
522
|
-
const root = args
|
|
523
|
-
printJson(await addBlocker(root, slug, optionValue("--text")))
|
|
669
|
+
const root = positionalArg(args, 3) || process.cwd()
|
|
670
|
+
printJson(await addBlocker(root, slug, optionValue(args, "--text")))
|
|
524
671
|
return
|
|
525
672
|
}
|
|
526
673
|
if (action === "unblock") {
|
|
527
|
-
const root = args
|
|
528
|
-
printJson(await resolveBlocker(root, slug, optionValue("--text")))
|
|
674
|
+
const root = positionalArg(args, 3) || process.cwd()
|
|
675
|
+
printJson(await resolveBlocker(root, slug, optionValue(args, "--text")))
|
|
529
676
|
return
|
|
530
677
|
}
|
|
531
678
|
if (action === "verify-integration") {
|
|
532
|
-
const root = args
|
|
533
|
-
const reportFile = optionValue("--report-file")
|
|
534
|
-
const report = reportFile ?
|
|
679
|
+
const root = positionalArg(args, 3) || process.cwd()
|
|
680
|
+
const reportFile = optionValue(args, "--report-file")
|
|
681
|
+
const report = reportFile ? readTextFile(reportFile) : null
|
|
682
|
+
const receiptFile = optionValue(args, "--receipt-file")
|
|
683
|
+
const receipt = receiptFile ? readJsonFile(receiptFile) : null
|
|
535
684
|
printJson(await recordIntegrationVerification(
|
|
536
685
|
root,
|
|
537
686
|
slug,
|
|
538
|
-
optionValue("--verdict"),
|
|
539
|
-
optionValue("--evidence"),
|
|
687
|
+
optionValue(args, "--verdict"),
|
|
688
|
+
optionValue(args, "--evidence"),
|
|
540
689
|
report,
|
|
690
|
+
{ receipt },
|
|
541
691
|
))
|
|
542
692
|
return
|
|
543
693
|
}
|
|
544
694
|
if (action === "finalize") {
|
|
545
|
-
const root = args
|
|
546
|
-
printJson(await finalizeWork(root, slug, optionValue("--evidence")))
|
|
695
|
+
const root = positionalArg(args, 3) || process.cwd()
|
|
696
|
+
printJson(await finalizeWork(root, slug, optionValue(args, "--evidence")))
|
|
547
697
|
return
|
|
548
698
|
}
|
|
549
699
|
|
|
550
700
|
throw new Error("Unknown work action: " + action)
|
|
551
701
|
} catch (error) {
|
|
552
|
-
console.error(error
|
|
702
|
+
console.error(errorMessage(error))
|
|
553
703
|
if (error?.validation) printJson(error.validation)
|
|
554
704
|
process.exitCode = 1
|
|
555
705
|
}
|
|
@@ -562,10 +712,10 @@ async function modelPolicy() {
|
|
|
562
712
|
process.exitCode = 2
|
|
563
713
|
return
|
|
564
714
|
}
|
|
565
|
-
const attempt =
|
|
715
|
+
const attempt = optionInt(args, "--attempt", 1)
|
|
566
716
|
const policy = await readModelPolicy(getConfigDir())
|
|
567
717
|
const normalizedAttempt = Number.isInteger(attempt) && attempt > 0 ? attempt : 1
|
|
568
|
-
const taskText = optionValue("--text")
|
|
718
|
+
const taskText = optionValue(args, "--text")
|
|
569
719
|
if (taskText) {
|
|
570
720
|
printJson(resolveAdaptiveModel(role, normalizedAttempt, classifyEngineeringTask(taskText), policy))
|
|
571
721
|
return
|
|
@@ -627,7 +777,7 @@ async function modelsControl() {
|
|
|
627
777
|
async function routerControl() {
|
|
628
778
|
const action = args[1] || "status"
|
|
629
779
|
const maxIndex = args.indexOf("--max")
|
|
630
|
-
const maxValue = maxIndex >= 0 ? Number.parseInt(args
|
|
780
|
+
const maxValue = maxIndex >= 0 ? Number.parseInt(optionValue(args, "--max") ?? "", 10) : null
|
|
631
781
|
|
|
632
782
|
if (!["status", "on", "off"].includes(action)) {
|
|
633
783
|
console.error("Usage: ocskill router [status|on|off] [--max 1..6]")
|
|
@@ -678,42 +828,76 @@ async function taskPolicyControl() {
|
|
|
678
828
|
async function sandboxControl() {
|
|
679
829
|
const action = args[1] || "list"
|
|
680
830
|
try {
|
|
831
|
+
if (action === "capability") {
|
|
832
|
+
printJson(containerSandboxCapability(optionValue(args, "--engine")))
|
|
833
|
+
return
|
|
834
|
+
}
|
|
835
|
+
if (action === "exec") {
|
|
836
|
+
const separator = args.indexOf("--")
|
|
837
|
+
const root = positionalArg(args, 2) || process.cwd()
|
|
838
|
+
const executable = separator >= 0 ? args[separator + 1] : null
|
|
839
|
+
const commandArgs = separator >= 0 ? args.slice(separator + 2) : []
|
|
840
|
+
const image = optionValue(args, "--image")
|
|
841
|
+
if (!image || !executable) {
|
|
842
|
+
throw new Error("Usage: ocskill sandbox exec [dir] --image <image> [--engine docker|podman] -- <command> [args...]")
|
|
843
|
+
}
|
|
844
|
+
const result = runContainerSandbox(root, {
|
|
845
|
+
engine: optionValue(args, "--engine"),
|
|
846
|
+
image,
|
|
847
|
+
command: executable,
|
|
848
|
+
args: commandArgs,
|
|
849
|
+
timeoutMs: optionInt(args, "--timeout-ms", 10 * 60_000),
|
|
850
|
+
})
|
|
851
|
+
printJson({ ...result, stdout: clipOutput(result.stdout), stderr: clipOutput(result.stderr) })
|
|
852
|
+
if (result.status !== 0) process.exitCode = result.status
|
|
853
|
+
return
|
|
854
|
+
}
|
|
681
855
|
if (action === "list") {
|
|
682
|
-
printJson(listTaskSandboxes(args
|
|
856
|
+
printJson(listTaskSandboxes(positionalArg(args, 2) || process.cwd()))
|
|
683
857
|
return
|
|
684
858
|
}
|
|
685
859
|
if (action === "create") {
|
|
686
860
|
const slug = args[2]
|
|
687
861
|
const taskID = args[3]
|
|
688
|
-
const root = args
|
|
862
|
+
const root = positionalArg(args, 4) || process.cwd()
|
|
689
863
|
if (!slug || !taskID) throw new Error("Usage: ocskill sandbox create <slug> <task-id> [dir]")
|
|
690
864
|
printJson(await createTaskSandbox(root, slug, taskID))
|
|
691
865
|
return
|
|
692
866
|
}
|
|
867
|
+
if (action === "integrate") {
|
|
868
|
+
const dir = args[2]
|
|
869
|
+
const root = positionalArg(args, 3) || process.cwd()
|
|
870
|
+
if (!dir) throw new Error("Usage: ocskill sandbox integrate <worktree-path> [dir] [--keep]")
|
|
871
|
+
printJson(await integrateTaskSandbox(root, dir, { keep: args.includes("--keep") }))
|
|
872
|
+
return
|
|
873
|
+
}
|
|
693
874
|
if (action === "remove") {
|
|
694
875
|
const dir = args[2]
|
|
695
|
-
const root = args
|
|
696
|
-
if (!dir) throw new Error("Usage: ocskill sandbox remove <worktree-path> [dir] [--force]")
|
|
697
|
-
printJson(await removeTaskSandbox(root, dir, {
|
|
876
|
+
const root = positionalArg(args, 3) || process.cwd()
|
|
877
|
+
if (!dir) throw new Error("Usage: ocskill sandbox remove <worktree-path> [dir] [--force] [--delete-branch]")
|
|
878
|
+
printJson(await removeTaskSandbox(root, dir, {
|
|
879
|
+
force: args.includes("--force"),
|
|
880
|
+
deleteBranch: args.includes("--delete-branch"),
|
|
881
|
+
}))
|
|
698
882
|
return
|
|
699
883
|
}
|
|
700
|
-
throw new Error("Usage: ocskill sandbox <list|create|remove> ...")
|
|
884
|
+
throw new Error("Usage: ocskill sandbox <capability|exec|list|create|integrate|remove> ...")
|
|
701
885
|
} catch (error) {
|
|
702
|
-
console.error(error
|
|
886
|
+
console.error(errorMessage(error))
|
|
703
887
|
process.exitCode = 1
|
|
704
888
|
}
|
|
705
889
|
}
|
|
706
890
|
|
|
707
891
|
async function learningControl() {
|
|
708
892
|
const action = args[1] || "status"
|
|
709
|
-
const root = args
|
|
893
|
+
const root = positionalArg(args, 2) || process.cwd()
|
|
710
894
|
try {
|
|
711
895
|
if (action === "status") {
|
|
712
896
|
printJson(await readLearningState(root))
|
|
713
897
|
return
|
|
714
898
|
}
|
|
715
899
|
if (action === "analyze") {
|
|
716
|
-
const evalDir = optionValue("--eval-dir") || path.join(path.resolve(root), ".ues-evals")
|
|
900
|
+
const evalDir = optionValue(args, "--eval-dir") || path.join(path.resolve(root), ".ues-evals")
|
|
717
901
|
const analysis = await analyzeEvalTraces(evalDir)
|
|
718
902
|
const state = await saveLearningAnalysis(root, analysis)
|
|
719
903
|
printJson({ analysis, state })
|
|
@@ -721,14 +905,23 @@ async function learningControl() {
|
|
|
721
905
|
}
|
|
722
906
|
if (action === "accept") {
|
|
723
907
|
const id = args[2]
|
|
724
|
-
const acceptRoot = args
|
|
908
|
+
const acceptRoot = positionalArg(args, 3) || process.cwd()
|
|
725
909
|
if (!id) throw new Error("Usage: ocskill learn accept <proposal-id> [dir]")
|
|
726
910
|
printJson(await acceptLearning(acceptRoot, id))
|
|
727
911
|
return
|
|
728
912
|
}
|
|
729
|
-
|
|
913
|
+
if (action === "promote") {
|
|
914
|
+
const id = args[2]
|
|
915
|
+
const promoteRoot = positionalArg(args, 3) || process.cwd()
|
|
916
|
+
if (!id) throw new Error("Usage: ocskill learn promote <proposal-id> [dir] --report <matrix-summary.json>")
|
|
917
|
+
printJson(await promoteLearning(promoteRoot, id, {
|
|
918
|
+
report: optionValue(args, "--report"),
|
|
919
|
+
}))
|
|
920
|
+
return
|
|
921
|
+
}
|
|
922
|
+
throw new Error("Usage: ocskill learn <status|analyze|accept|promote> ...")
|
|
730
923
|
} catch (error) {
|
|
731
|
-
console.error(error
|
|
924
|
+
console.error(errorMessage(error))
|
|
732
925
|
process.exitCode = 1
|
|
733
926
|
}
|
|
734
927
|
}
|
|
@@ -742,7 +935,7 @@ async function hermesControl() {
|
|
|
742
935
|
if (action === "prompt" || action === "exec") {
|
|
743
936
|
const slug = args[2]
|
|
744
937
|
const taskID = args[3]
|
|
745
|
-
const root = args
|
|
938
|
+
const root = positionalArg(args, 4) || process.cwd()
|
|
746
939
|
if (!slug || !taskID) {
|
|
747
940
|
console.error("Usage: ocskill hermes <prompt|exec> <slug> <task-id> [dir]")
|
|
748
941
|
process.exitCode = 2
|
|
@@ -796,7 +989,7 @@ async function update() {
|
|
|
796
989
|
})
|
|
797
990
|
} catch (error) {
|
|
798
991
|
console.error("[ocskill] Could not determine the latest published npm version; refusing an unsafe self-update.")
|
|
799
|
-
console.error(error
|
|
992
|
+
console.error(errorMessage(error))
|
|
800
993
|
process.exitCode = error?.exitCode || 1
|
|
801
994
|
return
|
|
802
995
|
}
|
|
@@ -808,7 +1001,7 @@ async function update() {
|
|
|
808
1001
|
compared = compareVersions(latestVersion, currentVersion)
|
|
809
1002
|
} catch (error) {
|
|
810
1003
|
console.error("[ocskill] npm returned a version that could not be compared safely; refusing update.")
|
|
811
|
-
console.error(error
|
|
1004
|
+
console.error(errorMessage(error))
|
|
812
1005
|
process.exitCode = 1
|
|
813
1006
|
return
|
|
814
1007
|
}
|
|
@@ -906,6 +1099,15 @@ switch (command) {
|
|
|
906
1099
|
case "repo-graph":
|
|
907
1100
|
await inspectRepoGraph()
|
|
908
1101
|
break
|
|
1102
|
+
case "index":
|
|
1103
|
+
await semanticIndexControl()
|
|
1104
|
+
break
|
|
1105
|
+
case "aci":
|
|
1106
|
+
await aciControl()
|
|
1107
|
+
break
|
|
1108
|
+
case "trace":
|
|
1109
|
+
await traceControl()
|
|
1110
|
+
break
|
|
909
1111
|
case "review-scope":
|
|
910
1112
|
await inspectReviewScope()
|
|
911
1113
|
break
|