catherd-cli 1.5.0 → 2.0.0-beta.20261022113309
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/README.md +164 -208
- package/THIRD_PARTY_NOTICES.md +217 -35
- package/catalog/jev.json +27 -1
- package/catalog/models.json +56 -247
- package/package.json +6 -8
- package/plugin/.claude-plugin/plugin.json +1 -1
- package/plugin/.codex-plugin/plugin.json +1 -1
- package/plugin/bin/catherd-mcp +1 -1
- package/plugin/commands/catherd.md +2 -2
- package/plugin/skills/catherd/SKILL.md +97 -421
- package/plugin/skills/catherd-setup/SKILL.md +20 -19
- package/src/adapters/all.ts +0 -4
- package/src/adapters/backend.ts +1 -2
- package/src/adapters/cursor/home.ts +1 -1
- package/src/adapters/cursor/index.ts +4 -4
- package/src/cli.ts +22 -27
- package/src/domain/bars.ts +33 -107
- package/src/domain/blocked.ts +72 -0
- package/src/domain/branch.ts +51 -0
- package/src/domain/brief.ts +21 -6
- package/src/domain/catalog.ts +69 -324
- package/src/domain/cost.ts +15 -30
- package/src/domain/errors.ts +2 -2
- package/src/domain/fail-lines.ts +26 -0
- package/src/domain/failover.ts +37 -87
- package/src/domain/findings.ts +47 -0
- package/src/domain/gate-brief.ts +1 -0
- package/src/domain/ids.ts +13 -2
- package/src/domain/jev.ts +47 -2
- package/src/domain/judge.ts +124 -0
- package/src/domain/lane.ts +22 -3
- package/src/domain/milestone-memory.ts +53 -0
- package/src/domain/notice.ts +25 -8
- package/src/domain/notify.ts +32 -0
- package/src/domain/plan-doc.ts +198 -0
- package/src/domain/plan-lint.ts +141 -0
- package/src/domain/profile-rules.ts +101 -160
- package/src/domain/profile.ts +116 -63
- package/src/domain/record.ts +53 -2
- package/src/domain/role-prompts.ts +131 -45
- package/src/domain/role-scope.ts +4 -34
- package/src/domain/role-tools.ts +2 -2
- package/src/domain/roles.ts +2 -0
- package/src/domain/route.ts +17 -0
- package/src/domain/rules.ts +33 -0
- package/src/domain/run-events.ts +298 -0
- package/src/domain/run-machine.ts +668 -0
- package/src/domain/run-state.ts +1310 -0
- package/src/domain/scorecard.ts +197 -0
- package/src/domain/select.ts +151 -146
- package/src/domain/slopalytics.ts +72 -0
- package/src/entry/answer-command.ts +39 -0
- package/src/entry/catalog-command.ts +25 -174
- package/src/entry/check-bin.ts +17 -0
- package/src/entry/cli-kit.ts +1 -1
- package/src/entry/daemon-bin.ts +22 -0
- package/src/entry/glyphs.ts +15 -2
- package/src/entry/init-command.ts +18 -68
- package/src/entry/knowledge-command.ts +45 -4
- package/src/entry/lock-command.ts +6 -7
- package/src/entry/mcp/role-server.ts +18 -0
- package/src/entry/mcp/server.ts +13 -40
- package/src/entry/mcp/session-tools.ts +149 -0
- package/src/entry/panel/openapi.ts +189 -0
- package/src/entry/panel/server.ts +410 -0
- package/src/entry/panel-command.ts +68 -0
- package/src/entry/profile-command.ts +10 -14
- package/src/entry/role-cli-command.ts +47 -3
- package/src/entry/runs-command.ts +3 -19
- package/src/entry/scorecard-command.ts +187 -0
- package/src/entry/supervise-bin.ts +1 -1
- package/src/infra/env.ts +0 -2
- package/src/infra/git.ts +64 -0
- package/src/infra/heavy-lock.ts +45 -7
- package/src/infra/launch.ts +63 -7
- package/src/infra/memory.ts +45 -0
- package/src/infra/ntfy.ts +40 -0
- package/src/infra/open-url.ts +42 -0
- package/src/infra/paths.ts +2 -2
- package/src/infra/slopalytics.ts +30 -0
- package/src/infra/store.ts +6 -1
- package/src/services/admission.ts +24 -9
- package/src/services/backends.ts +4 -6
- package/src/services/capture.ts +1 -22
- package/src/services/catalog-service.ts +155 -262
- package/src/services/credentials.ts +4 -20
- package/src/services/daemon.ts +181 -0
- package/src/services/dispatch-service.ts +5 -1
- package/src/services/doctor-backends.ts +1 -1
- package/src/services/doctor-checks.ts +47 -0
- package/src/services/doctor.ts +4 -9
- package/src/services/failover-rungs.ts +109 -0
- package/src/services/finalize.ts +12 -0
- package/src/services/gate-env.ts +1 -2
- package/src/services/gate-service.ts +21 -6
- package/src/services/jev-service.ts +2 -4
- package/src/services/lane-service.ts +34 -3
- package/src/services/milestone-check.ts +433 -0
- package/src/services/milestone-tree.ts +170 -0
- package/src/services/milestones.ts +35 -8
- package/src/services/notifier.ts +69 -2
- package/src/services/notify-service.ts +26 -0
- package/src/services/panel-setup.ts +116 -0
- package/src/services/plan-input.ts +151 -0
- package/src/services/ports.ts +30 -4
- package/src/services/preflight.ts +82 -8
- package/src/services/profile-service.ts +30 -3
- package/src/services/profile-store.ts +8 -3
- package/src/services/protocol.ts +4 -0
- package/src/services/provenance.ts +31 -90
- package/src/services/questions.ts +9 -0
- package/src/services/reconcile.ts +11 -0
- package/src/services/routing-service.ts +26 -15
- package/src/services/run-briefs.ts +477 -0
- package/src/services/run-client.ts +217 -0
- package/src/services/run-effects.ts +837 -0
- package/src/services/run-events-store.ts +174 -0
- package/src/services/run-evidence.ts +1 -1
- package/src/services/run-read.ts +221 -0
- package/src/services/run-report.ts +176 -0
- package/src/services/run-service.ts +55 -6
- package/src/services/run-store.ts +54 -7
- package/src/services/scorecard-metrics.ts +86 -0
- package/src/services/scorecard.ts +382 -0
- package/src/services/summary.ts +27 -3
- package/src/services/tree-path.ts +27 -0
- package/src/services/workspace-admission.ts +5 -13
- package/src/services/workspace-service.ts +5 -0
- package/web/dist/assets/Brand-PKlUX5TE.js +1 -0
- package/web/dist/assets/Brand-PKlUX5TE.js.br +0 -0
- package/web/dist/assets/Brand-PKlUX5TE.js.gz +0 -0
- package/web/dist/assets/Modal-Dxc5so53.js +1 -0
- package/web/dist/assets/Modal-Dxc5so53.js.br +0 -0
- package/web/dist/assets/Modal-Dxc5so53.js.gz +0 -0
- package/web/dist/assets/Pressable-C8-T6Ed_.js +1 -0
- package/web/dist/assets/StatusChip-B5xfI_Mn.js +153 -0
- package/web/dist/assets/StatusChip-B5xfI_Mn.js.br +0 -0
- package/web/dist/assets/StatusChip-B5xfI_Mn.js.gz +0 -0
- package/web/dist/assets/_app-Ea5cpyKe.js +1 -0
- package/web/dist/assets/_app-Ea5cpyKe.js.br +0 -0
- package/web/dist/assets/_app-Ea5cpyKe.js.gz +0 -0
- package/web/dist/assets/_runId-pTG0fXVo.js +1 -0
- package/web/dist/assets/_runId-pTG0fXVo.js.br +0 -0
- package/web/dist/assets/_runId-pTG0fXVo.js.gz +0 -0
- package/web/dist/assets/drawer-Du3cdlok.js +1 -0
- package/web/dist/assets/drawer-Du3cdlok.js.br +0 -0
- package/web/dist/assets/drawer-Du3cdlok.js.gz +0 -0
- package/web/dist/assets/geist-cyrillic-ext-wght-normal-DjL33-gN.woff2 +0 -0
- package/web/dist/assets/geist-cyrillic-wght-normal-BEAKL7Jp.woff2 +0 -0
- package/web/dist/assets/geist-latin-ext-wght-normal-DC-KSUi6.woff2 +0 -0
- package/web/dist/assets/geist-latin-wght-normal-BgDaEnEv.woff2 +0 -0
- package/web/dist/assets/geist-mono-cyrillic-ext-wght-normal-X_5orZeX.woff2 +0 -0
- package/web/dist/assets/geist-mono-cyrillic-wght-normal-DiZS0aHC.woff2 +0 -0
- package/web/dist/assets/geist-mono-latin-ext-wght-normal-Bwz-egvJ.woff2 +0 -0
- package/web/dist/assets/geist-mono-latin-wght-normal-XN7g48iV.woff2 +0 -0
- package/web/dist/assets/geist-mono-symbols2-wght-normal-CO5SzqOn.woff2 +0 -0
- package/web/dist/assets/geist-mono-vietnamese-wght-normal-DadHysG0.woff2 +0 -0
- package/web/dist/assets/geist-vietnamese-wght-normal-6IgcOCM7.woff2 +0 -0
- package/web/dist/assets/index-B6GiwDkh.js +11 -0
- package/web/dist/assets/index-B6GiwDkh.js.br +0 -0
- package/web/dist/assets/index-B6GiwDkh.js.gz +0 -0
- package/web/dist/assets/index-C5IbylvM.css +2 -0
- package/web/dist/assets/index-C5IbylvM.css.br +0 -0
- package/web/dist/assets/index-C5IbylvM.css.gz +0 -0
- package/web/dist/assets/label-DFSYBc62.js +1 -0
- package/web/dist/assets/label-DFSYBc62.js.br +0 -0
- package/web/dist/assets/label-DFSYBc62.js.gz +0 -0
- package/web/dist/assets/link-D8EcKZUt.js +1 -0
- package/web/dist/assets/link-D8EcKZUt.js.br +0 -0
- package/web/dist/assets/link-D8EcKZUt.js.gz +0 -0
- package/web/dist/assets/login-DaN5HPPW.js +1 -0
- package/web/dist/assets/login-DaN5HPPW.js.br +0 -0
- package/web/dist/assets/login-DaN5HPPW.js.gz +0 -0
- package/web/dist/assets/query-Cu--ccT3.js +1 -0
- package/web/dist/assets/questions-shoO9OVj.js +1 -0
- package/web/dist/assets/questions-shoO9OVj.js.br +0 -0
- package/web/dist/assets/questions-shoO9OVj.js.gz +0 -0
- package/web/dist/assets/react-query.gen-Bu2yV-qJ.js +12 -0
- package/web/dist/assets/react-query.gen-Bu2yV-qJ.js.br +0 -0
- package/web/dist/assets/react-query.gen-Bu2yV-qJ.js.gz +0 -0
- package/web/dist/assets/rolldown-runtime-XKyaHtl9.js +1 -0
- package/web/dist/assets/run-status-C0DRuV7U.js +1 -0
- package/web/dist/assets/runs-C3rg2zZc.js +1 -0
- package/web/dist/assets/runs-C3rg2zZc.js.br +0 -0
- package/web/dist/assets/runs-C3rg2zZc.js.gz +0 -0
- package/web/dist/assets/setup-5I4Vl9fR.js +1 -0
- package/web/dist/assets/setup-5I4Vl9fR.js.br +0 -0
- package/web/dist/assets/setup-5I4Vl9fR.js.gz +0 -0
- package/web/dist/assets/table-BOxXhqS4.js +1 -0
- package/web/dist/assets/table-BOxXhqS4.js.br +0 -0
- package/web/dist/assets/table-BOxXhqS4.js.gz +0 -0
- package/web/dist/assets/textfield-BzRFkxBF.js +1 -0
- package/web/dist/assets/textfield-BzRFkxBF.js.br +0 -0
- package/web/dist/assets/textfield-BzRFkxBF.js.gz +0 -0
- package/web/dist/assets/time--9kSQbbp.js +1 -0
- package/web/dist/assets/use-css-variable-CpnN9WtA.js +5 -0
- package/web/dist/assets/use-css-variable-CpnN9WtA.js.br +0 -0
- package/web/dist/assets/use-css-variable-CpnN9WtA.js.gz +0 -0
- package/web/dist/assets/useMutation-CVPKlR34.js +1 -0
- package/web/dist/assets/useMutation-CVPKlR34.js.br +0 -0
- package/web/dist/assets/useMutation-CVPKlR34.js.gz +0 -0
- package/web/dist/index.html +15 -0
- package/catalog/ATTRIBUTION.md +0 -44
- package/catalog/scores.json +0 -3202
- package/catalog/sources.json +0 -97
- package/src/adapters/antigravity/events.ts +0 -131
- package/src/adapters/antigravity/home.ts +0 -46
- package/src/adapters/antigravity/index.ts +0 -335
- package/src/adapters/antigravity/models.ts +0 -37
- package/src/adapters/grok/events.ts +0 -112
- package/src/adapters/grok/home.ts +0 -187
- package/src/adapters/grok/index.ts +0 -358
- package/src/adapters/grok/models.ts +0 -48
- package/src/domain/calibration.ts +0 -132
- package/src/domain/sources.ts +0 -144
- package/src/entry/mcp/dispatch-tools.ts +0 -52
- package/src/entry/mcp/lane-tools.ts +0 -131
- package/src/entry/mcp/protocol-tools.ts +0 -63
- package/src/entry/mcp/push-tools.ts +0 -16
- package/src/entry/mcp/run-tools.ts +0 -164
- package/src/entry/mcp/setup-tools.ts +0 -109
- package/src/entry/mcp/workspace-tools.ts +0 -142
- package/src/entry/tui/commands.ts +0 -563
- package/src/entry/tui/effects.ts +0 -385
- package/src/entry/tui/fixtures.ts +0 -637
- package/src/entry/tui/profile-edits.ts +0 -146
- package/src/entry/tui/profile-tree.ts +0 -429
- package/src/entry/tui/providers/app.tsx +0 -162
- package/src/entry/tui/providers/boundary.tsx +0 -57
- package/src/entry/tui/providers/data.tsx +0 -160
- package/src/entry/tui/providers/keymap.tsx +0 -166
- package/src/entry/tui/providers/root.tsx +0 -45
- package/src/entry/tui/providers/theme.tsx +0 -17
- package/src/entry/tui/providers/toast.tsx +0 -77
- package/src/entry/tui/run.tsx +0 -114
- package/src/entry/tui/state.ts +0 -400
- package/src/entry/tui/stories.ts +0 -114
- package/src/entry/tui/text.ts +0 -130
- package/src/entry/tui/theme.ts +0 -140
- package/src/entry/tui/views/app.tsx +0 -208
- package/src/entry/tui/views/dialogs.tsx +0 -41
- package/src/entry/tui/views/profile-actions.ts +0 -331
- package/src/entry/tui/views/profiles.tsx +0 -520
- package/src/entry/tui/views/runs.tsx +0 -619
- package/src/entry/tui/views/save-dialog.tsx +0 -344
- package/src/entry/tui/views/status.tsx +0 -213
- package/src/entry/tui/widgets/chrome.tsx +0 -114
- package/src/entry/tui/widgets/dialog-confirm.tsx +0 -58
- package/src/entry/tui/widgets/dialog-prompt.tsx +0 -52
- package/src/entry/tui/widgets/dialog-select.tsx +0 -212
- package/src/entry/tui/widgets/dialog.tsx +0 -68
- package/src/entry/tui/widgets/line.tsx +0 -92
- package/src/entry/tui/widgets/list.tsx +0 -197
- package/src/entry/tui/widgets/spinner.tsx +0 -49
- package/src/entry/tui/widgets/toast.tsx +0 -62
- package/src/infra/sources/arena.ts +0 -95
- package/src/infra/sources/artificial-analysis.ts +0 -119
- package/src/infra/sources/cache.ts +0 -126
- package/src/infra/sources/csv.ts +0 -38
- package/src/infra/sources/epoch.ts +0 -82
- package/src/infra/sources/http.ts +0 -75
- package/src/infra/sources/litellm.ts +0 -58
- package/src/infra/sources/models-dev.ts +0 -59
- package/src/infra/sources/openrouter-endpoints.ts +0 -52
- package/src/infra/sources/openrouter-models.ts +0 -60
- package/src/infra/sources/rows.ts +0 -38
- package/src/infra/sources/vectara.ts +0 -69
- package/src/infra/sources/zip.ts +0 -48
- package/src/services/catalog-refresh.ts +0 -201
- package/src/services/doctor-sources.ts +0 -76
- package/src/services/runs-page.ts +0 -290
- package/src/services/source-derive.ts +0 -397
- package/src/services/source-sync.ts +0 -312
- package/src/services/standins.ts +0 -238
- package/src/services/treat-likes.ts +0 -113
|
@@ -4,11 +4,12 @@ import { join } from "node:path";
|
|
|
4
4
|
import type { BackendAdapter } from "../adapters/backend.ts";
|
|
5
5
|
import { budgetStatus, formatBudget } from "../domain/budget.ts";
|
|
6
6
|
import { CatherdError, errorMessage } from "../domain/errors.ts";
|
|
7
|
-
import { assertId, formatRung, newDispatchId, parseRung } from "../domain/ids.ts";
|
|
7
|
+
import { assertId, formatRung, headlessRung, newDispatchId, parseRung } from "../domain/ids.ts";
|
|
8
8
|
import { assertLaneHeader, overlaps } from "../domain/lane.ts";
|
|
9
9
|
import { roleTimeouts } from "../domain/profile.ts";
|
|
10
10
|
import type { RunRecord } from "../domain/record.ts";
|
|
11
11
|
import { composeBrief } from "../domain/brief.ts";
|
|
12
|
+
import { rulesBlock } from "../domain/rules.ts";
|
|
12
13
|
import { briefOwns, DOCS_OWNS } from "../domain/changes.ts";
|
|
13
14
|
import { grantsScratch, ROLE_SERVER_BACKENDS } from "../domain/role-tools.ts";
|
|
14
15
|
import type { Role } from "../domain/roles.ts";
|
|
@@ -22,6 +23,7 @@ import { log } from "../infra/log.ts";
|
|
|
22
23
|
import { processStartTime } from "../infra/proc.ts";
|
|
23
24
|
import { ensurePrivateDir, PRIVATE_FILE, writeJsonAtomic, writeTextAtomic } from "../infra/store.ts";
|
|
24
25
|
import { readyAdapter, standInFor } from "./backends.ts";
|
|
26
|
+
import { failoverBackends } from "./failover-rungs.ts";
|
|
25
27
|
import { spendOf } from "./budget.ts";
|
|
26
28
|
import {
|
|
27
29
|
type Admit,
|
|
@@ -39,6 +41,8 @@ import { finalizeDispatch } from "./finalize.ts";
|
|
|
39
41
|
import { gateEnvParts, readGateEnv } from "./gate-env.ts";
|
|
40
42
|
import { assertNotPaused } from "./pause.ts";
|
|
41
43
|
import { currentOwns } from "./lane-edit.ts";
|
|
44
|
+
import { planContext } from "./plan-input.ts";
|
|
45
|
+
import { standingRules } from "./run-service.ts";
|
|
42
46
|
import { unfinishedAfter } from "./protocol.ts";
|
|
43
47
|
import { runProfile } from "./run-pin.ts";
|
|
44
48
|
import type { Deps } from "./ports.ts";
|
|
@@ -60,6 +64,8 @@ export interface AdmitInput {
|
|
|
60
64
|
/** the dispatching session (spec §3.3); absent means the session this process serves */
|
|
61
65
|
sessionId?: string | null;
|
|
62
66
|
host?: KnownHost;
|
|
67
|
+
/** plan 35: where the role works (its milestone's worktree in a base run); absent means the run's repo */
|
|
68
|
+
cwd?: string;
|
|
63
69
|
}
|
|
64
70
|
|
|
65
71
|
/** Spec §3.3: SIGTERM, then SIGKILL this long after. */
|
|
@@ -181,11 +187,15 @@ export async function admit(
|
|
|
181
187
|
throw new CatherdError("E_ADMIT_RUNG", `${i.rung} is a native Claude rung`, {
|
|
182
188
|
fix: `run it as Agent(subagent_type: "${deps.profiles.agentFor(run.meta.repo, i.role, i.rung)}"), then record_agent_run`,
|
|
183
189
|
});
|
|
184
|
-
const
|
|
190
|
+
const ladder = [
|
|
185
191
|
...rc.rungs,
|
|
186
192
|
...rc.rungs.flatMap((r) => standInFor(profile.failover, r, run.meta.repo) ?? []),
|
|
187
|
-
]
|
|
188
|
-
|
|
193
|
+
];
|
|
194
|
+
// the daemon runs every role headless (spec 2.0 decision 12): a native rung's headless twin is on its ladder too
|
|
195
|
+
const allowed = new Set([...ladder, ...ladder.map(headlessRung)]);
|
|
196
|
+
// a rung the daemon failed a limit over to may be on any configured backend (spec 2.0 decision 6)
|
|
197
|
+
const failedOver = i.failoverFrom !== null && failoverBackends(profile).has(rung.backend);
|
|
198
|
+
if (!allowed.has(formatRung(rung)) && !failedOver)
|
|
189
199
|
throw new CatherdError(
|
|
190
200
|
"E_ADMIT_RUNG",
|
|
191
201
|
`${i.rung} is not on the ${i.role} ladder of profile ${profile.name}`,
|
|
@@ -208,7 +218,7 @@ export async function admit(
|
|
|
208
218
|
`${adapter.id} keeps the access a thread started with: ${i.thread} ran ${started.access}, and the ${i.role} role runs ${rc.access}`,
|
|
209
219
|
{ fix: "dispatch a fresh thread (omit `thread`)" },
|
|
210
220
|
);
|
|
211
|
-
// and the network grant:
|
|
221
|
+
// and the network grant: a CLI that keeps a session's sandbox profile keeps it.
|
|
212
222
|
// A record from before 1.3 carries no grant to compare.
|
|
213
223
|
if (started?.network !== undefined && adapter.resume.sameAccessOnly && started.network !== network)
|
|
214
224
|
throw new CatherdError(
|
|
@@ -234,11 +244,12 @@ export async function admit(
|
|
|
234
244
|
// spec 1.5 plan 21 (#42 findings 1, 2): the role server goes in whether the harness is isolated or not, so no
|
|
235
245
|
// role is refused for isolation, and a thread an isolated run started resumes as it started
|
|
236
246
|
const roleServer = ROLE_SERVER_BACKENDS.includes(rung.backend);
|
|
247
|
+
const cwd = i.cwd ?? run.meta.repo;
|
|
237
248
|
await prepared(adapter, {
|
|
238
249
|
rung,
|
|
239
250
|
access: rc.access,
|
|
240
251
|
isolated,
|
|
241
|
-
repo:
|
|
252
|
+
repo: cwd,
|
|
242
253
|
network,
|
|
243
254
|
});
|
|
244
255
|
|
|
@@ -255,7 +266,7 @@ export async function admit(
|
|
|
255
266
|
network,
|
|
256
267
|
thread: i.thread,
|
|
257
268
|
isolated,
|
|
258
|
-
repo:
|
|
269
|
+
repo: cwd,
|
|
259
270
|
briefPath: p.brief,
|
|
260
271
|
replyPath: p.reply,
|
|
261
272
|
dispatchDir: dir,
|
|
@@ -302,7 +313,7 @@ export async function admit(
|
|
|
302
313
|
throw new CatherdError("E_RUN_BUDGET", `the run budget is spent: ${formatBudget(budget)}`, {
|
|
303
314
|
fix: "ask the user to raise profile.budget, or finish the run with what landed",
|
|
304
315
|
});
|
|
305
|
-
const before = await statusSnapshot(
|
|
316
|
+
const before = await statusSnapshot(cwd);
|
|
306
317
|
const session = currentSession(deps);
|
|
307
318
|
const sessionId = i.sessionId !== undefined ? i.sessionId : (session?.sessionId ?? null);
|
|
308
319
|
const admitted: Admit = {
|
|
@@ -325,11 +336,13 @@ export async function admit(
|
|
|
325
336
|
network,
|
|
326
337
|
cliVersion: probe.version,
|
|
327
338
|
admittedAt: new Date(deps.now()).toISOString(),
|
|
328
|
-
repo:
|
|
339
|
+
repo: cwd,
|
|
329
340
|
before,
|
|
330
341
|
...(sessionId ? { sessionId, host: i.host ?? session?.host ?? "claude-code" } : {}),
|
|
331
342
|
};
|
|
332
343
|
ensurePrivateDir(dir);
|
|
344
|
+
// plan 34: the repo's standing rules for this role; a knowledge file that cannot be read adds nothing
|
|
345
|
+
const rules = await standingRules(run.meta.repo, i.role).catch(() => "");
|
|
333
346
|
// plan 23: the verifier runs with the repo's gate environment (DOCKER_HOST, a proxy, …)
|
|
334
347
|
const gate =
|
|
335
348
|
i.role === "verifier" ? gateEnvParts(await readGateEnv(run.meta.repo)) : { values: {}, refs: {} };
|
|
@@ -345,6 +358,8 @@ export async function admit(
|
|
|
345
358
|
lane: i.lane === null ? null : { id: i.lane, text: readFileSync(laneFile(run, i.lane), "utf8") },
|
|
346
359
|
scratch,
|
|
347
360
|
roleServer,
|
|
361
|
+
version: deps.version,
|
|
362
|
+
context: [planContext(run, i.role), rulesBlock(rules, i.role)].filter(Boolean).join("\n\n") || null,
|
|
348
363
|
}),
|
|
349
364
|
);
|
|
350
365
|
// Spec §10.4: the adapter's overrides only; the supervisor adds its own inherited env at spawn
|
package/src/services/backends.ts
CHANGED
|
@@ -5,7 +5,6 @@ import { adapterFor } from "../adapters/registry.ts";
|
|
|
5
5
|
import "../adapters/all.ts";
|
|
6
6
|
import { CatherdError } from "../domain/errors.ts";
|
|
7
7
|
import { formatRung, tryParseRung } from "../domain/ids.ts";
|
|
8
|
-
import { PAIRED_FAILOVER } from "../domain/profile.ts";
|
|
9
8
|
|
|
10
9
|
const READY_TTL_MS = 10 * 60_000;
|
|
11
10
|
const ready = new Map<string, { at: number; probe: Probe }>();
|
|
@@ -17,7 +16,7 @@ export const resetReadiness = (): void => ready.clear();
|
|
|
17
16
|
function execFormatError(e: unknown): string | null {
|
|
18
17
|
if (!(e instanceof Error)) return null;
|
|
19
18
|
if ((e as { code?: unknown }).code !== "ENOEXEC" && !/exec format error/i.test(e.message)) return null;
|
|
20
|
-
// macOS names the path (posix_spawn '/…/
|
|
19
|
+
// macOS names the path (posix_spawn '/…/bin'), Linux only the command (uv_spawn 'bin')
|
|
21
20
|
const bin = /spawn '([^']+)'/.exec(e.message)?.[1];
|
|
22
21
|
return bin ? (Bun.which(bin, { PATH: process.env.PATH ?? "" }) ?? bin) : "exec format error";
|
|
23
22
|
}
|
|
@@ -64,18 +63,17 @@ export async function readyAdapter(backend: string): Promise<{ adapter: BackendA
|
|
|
64
63
|
const probe = await probeBackend(adapter);
|
|
65
64
|
const problem = probe.problems[0];
|
|
66
65
|
// spec 1.3 §3.3: a probe that finds the CLI logged out lists E_BACKEND_NOT_LOGGED_IN, so a dispatch never
|
|
67
|
-
// reaches it (
|
|
66
|
+
// reaches it (it may open a browser and wait); logged out alone is no problem where a CLI runs without a login
|
|
68
67
|
if (problem) throw new CatherdError(problem.code, problem.message, { fix: problem.fix });
|
|
69
68
|
ready.set(backend, { at: now, probe });
|
|
70
69
|
return { adapter, probe };
|
|
71
70
|
}
|
|
72
71
|
|
|
73
72
|
/**
|
|
74
|
-
* Spec §4.5: a rung's stand-in on a usage limit: the profile's, else
|
|
75
|
-
* (spec 1.3 §7.3), else its backend's default (for `repo`, when given), else none.
|
|
73
|
+
* Spec §4.5: a rung's stand-in on a usage limit: the profile's, else its backend's default (for `repo`, when given), else none.
|
|
76
74
|
*/
|
|
77
75
|
export function standInFor(failover: Record<string, string>, rung: string, repo?: string): string | null {
|
|
78
|
-
const own = failover[rung]
|
|
76
|
+
const own = failover[rung];
|
|
79
77
|
if (own) return own;
|
|
80
78
|
const r = tryParseRung(rung);
|
|
81
79
|
if (!r) return null;
|
package/src/services/capture.ts
CHANGED
|
@@ -37,11 +37,6 @@ const HAIKU = "claude-code:claude-haiku-4-5-20251001#default";
|
|
|
37
37
|
/** spec 1.3 §4.6: `auto` has no family; only the live kit and the capture run it */
|
|
38
38
|
const AUTO = "cursor:auto#default";
|
|
39
39
|
const BUNNY = "opencode:opencode/space-bunny-free#default";
|
|
40
|
-
/** spec 1.3 §5.6: grok 1.0.44's default model (research §3.4) at its cheapest effort */
|
|
41
|
-
const GROK = "grok:grok-4.6#low";
|
|
42
|
-
/** spec 1.3 §6.6: the cheapest Gemini effort; capture runs isolated, on GEMINI_API_KEY */
|
|
43
|
-
const FLASH_LOW = "antigravity:gemini-3.8-flash#low";
|
|
44
|
-
|
|
45
40
|
/** Spec §11.7–8: one cheap run per backend, plus a read-only role trying to write where enforcement is advisory. */
|
|
46
41
|
const CAPTURE_CASES: CaptureCase[] = [
|
|
47
42
|
{ backend: "codex", name: "ok", rung: "codex:gpt-6-luna#low", access: "read-only", brief: SAY_HELLO },
|
|
@@ -53,22 +48,6 @@ const CAPTURE_CASES: CaptureCase[] = [
|
|
|
53
48
|
{ backend: "cursor", name: "ok", rung: AUTO, access: "workspace-write", brief: WORK },
|
|
54
49
|
{ backend: "cursor", name: "resume", rung: AUTO, access: "read-only", brief: SAY_HELLO, resume: RECALL },
|
|
55
50
|
{ backend: "cursor", name: "read-only-write", rung: AUTO, access: "read-only", brief: TRY_WRITE },
|
|
56
|
-
// spec 1.3 §5.6: the same three on grok; its read-only is the kernel profile, or the read tools on a Mac
|
|
57
|
-
// with a symlinked docker socket
|
|
58
|
-
{ backend: "grok", name: "ok", rung: GROK, access: "workspace-write", brief: WORK },
|
|
59
|
-
{ backend: "grok", name: "resume", rung: GROK, access: "read-only", brief: SAY_HELLO, resume: RECALL },
|
|
60
|
-
{ backend: "grok", name: "read-only-write", rung: GROK, access: "read-only", brief: TRY_WRITE },
|
|
61
|
-
// spec 1.3 §6.6: the same three on agy; read-only runs under catherd's deny rules (research §8 agy 2, 5, 6)
|
|
62
|
-
{ backend: "antigravity", name: "ok", rung: FLASH_LOW, access: "workspace-write", brief: WORK },
|
|
63
|
-
{
|
|
64
|
-
backend: "antigravity",
|
|
65
|
-
name: "resume",
|
|
66
|
-
rung: FLASH_LOW,
|
|
67
|
-
access: "read-only",
|
|
68
|
-
brief: SAY_HELLO,
|
|
69
|
-
resume: RECALL,
|
|
70
|
-
},
|
|
71
|
-
{ backend: "antigravity", name: "read-only-write", rung: FLASH_LOW, access: "read-only", brief: TRY_WRITE },
|
|
72
51
|
];
|
|
73
52
|
export const CAPTURE_BACKENDS = [...new Set(CAPTURE_CASES.map((c) => c.backend))];
|
|
74
53
|
|
|
@@ -122,7 +101,7 @@ async function runOnce(
|
|
|
122
101
|
const p = Bun.spawn([plan.cmd, ...plan.args], {
|
|
123
102
|
cwd: plan.cwd,
|
|
124
103
|
env: workerEnv(process.env, plan.env, plan.cwd),
|
|
125
|
-
// spec 1.3 §3.3: the brief goes on stdin only to a CLI whose plan reads it there (
|
|
104
|
+
// spec 1.3 §3.3: the brief goes on stdin only to a CLI whose plan reads it there (one reads a file)
|
|
126
105
|
stdin: plan.stdinPath ? Bun.file(plan.stdinPath) : "ignore",
|
|
127
106
|
stdout: "pipe",
|
|
128
107
|
stderr: "pipe",
|