@karowanorg/orc-ops 0.1.0 → 0.1.1

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/dist/guide.d.ts CHANGED
@@ -3,4 +3,4 @@
3
3
  * - CLI: `orc guide`
4
4
  * - MCP: the `orc_guide` tool
5
5
  */
6
- export declare const GUIDE = "# orc \u2014 how to write and run a program\n\norc runs a \"program\": a script that fans out AI-agent subtasks (\"leaves\") and\nrecords each one, so a run is reproducible, resumable, and observable. You write\na program, launch it, then watch it and collect the result.\n\n## 1. Write a program\n\nA program is a `.orc.ts` file with a single default-exported async function.\nIt receives an api object and returns the run's result:\n\n import type { Program } from \"@karowanorg/orc-sdk/program\"; // optional, type-only\n\n const program: Program = async ({ agent, parallel, phase }) => {\n const inventory = await agent(\"List the modules in this repo.\", {\n schema: { type: \"object\",\n properties: { modules: { type: \"array\", items: { type: \"string\" } } },\n required: [\"modules\"] },\n });\n\n // Ordinary async/await controls the flow. Awaiting a result before the\n // next call makes it a dependency; independent calls run concurrently.\n const plans = await Promise.all((inventory.modules as string[]).map(async (m) => {\n const findings = await agent(`Audit module ${m}`, { id: `audit-${m}` });\n return agent(`Plan a fix for ${m}: ${JSON.stringify(findings)}`, { id: `plan-${m}` });\n }));\n\n return phase(\"synthesis\", () => agent(`Merge these plans: ${JSON.stringify(plans)}`, { id: \"merge\" }));\n };\n export default program;\n\n## The api\n\nIMPORTANT \u2014 leaves are isolated. Each agent() runs a FRESH subagent that shares\nNONE of your context: it cannot see this program, your conversation, other\nleaves' prompts or results, or anything you know that you haven't written into\nits prompt (plus the shared `--brief`).\n\n- agent(prompt, opts?) => Promise<result>\n Dispatch one agent. Returns its result (matching `schema` if you pass one).\n A failed leaf rejects the promise, so wrap it in try/catch if you want to\n handle failure. Options:\n id a label shown in the monitor\n schema JSON Schema; the result is structured output matching it\n harness \"claude\" | \"codex\" | a configured harness (default: auto)\n model e.g. \"claude-fable-5\", \"gpt-5.6-sol\"\n reasoningEffort \"low\" | \"medium\" | \"high\" | \"xhigh\" | \"max\"\n readOnly default true; set false for a leaf that edits files\n cwd working directory for this leaf (defaults to the run's)\n host SSH destination to run this leaf on a remote machine\n idleTimeout ms with no output before the leaf is killed (false = off)\n phase group this call under a phase label\n To see valid `harness`, `model`, and `reasoningEffort` values for your\n machine, run `orc capabilities` (or `orc capabilities --json`) \u2014 it lists\n each installed harness with its available models and reasoning levels.\n Omit any of them to use the default; an unknown value is rejected up front\n by `orc validate`.\n\n- parallel(specs[]) => Promise<outcomes[]>\n Run several agents at once from an array of option objects (each with a\n `prompt`). Every lane runs to completion INDEPENDENTLY \u2014 one lane failing\n never cancels the others. Outcomes come back in order as\n `{ status: \"ok\", value } | { status: \"error\", error }`, so you decide how to\n handle partial failure. (For fail-fast, use `Promise.all` over `agent()`,\n which rejects on the first failure.)\n\n- phase(name, fn) => Promise<result>\n Group every agent() call made inside `fn` under a phase, for a readable\n run timeline.\n\n- settle(promise) => { status: \"ok\", value } | { status: \"error\", error }\n Run a lane and capture its outcome instead of letting a failure stop the run\n \u2014 useful for \"do all of these, some may fail\" fan-outs.\n\n- log(message) \u2014 write a line to the run's live event feed.\n- ext.<name>(payload) \u2014 call a custom step you registered in orc.config.\n\nBecause leaves can't see each other, pass data between them as plain values:\nput a previous result into the next prompt with JSON.stringify so the receiving\nleaf actually has it. Use normal try/catch, Promise.all/allSettled, and bounded\nloops for control flow.\n\n## What a program may and may not do\n\n- No wall clock or randomness. `Date`, `Math.random`, timers, network, file\n access, and imports (beyond type-only) are unavailable \u2014 a program only\n decides which agents to run and how to combine their results.\n- Loops must be finite; an unbounded loop is stopped by a step limit.\n- These constraints let orc replay a program exactly when you resume it, so the\n same inputs always produce the same run.\n\n## Writing files\n\nBy default leaves are read-only. To let a leaf directly modify files or run\nmutating commands, set `readOnly: false` and launch the run with\n`--allow-writes`. Configured hooks and MCP tools are not disabled for read-only\nleaves; their side effects are outside this guarantee. A write leaf runs with\nwhatever permissions your own agent has; add `--sandbox` to confine its writes\nto the working directory. If a run stops on a write leaf, `orc resume` picks it\nback up (it re-checks the working-tree state first, never blindly redoing work).\n\n## 2. Validate and launch\n\n orc validate --program-path ./my.orc.ts # compile + preview, no run\n orc launch --program-path ./my.orc.ts --brief \"what this run is for\"\n\n`--brief` (required) is shared context added to every leaf. Common launch flags:\n`--allow-writes`, `--host <ssh>`, `--approval-mode manual|accept-edits|auto|bypass`,\n`--sandbox`, `--harness claude|codex`, `--budget <usd>` (fail the run after\nobserved estimated cost exceeds this; concurrent work may overshoot), `--wait`\n(block for the result instead of running in the background).\n\n## 3. Watch and collect\n\n orc status --run-id <id> # summary\n orc wait --run-id <id> # block until it finishes\n orc get-result --run-id <id> # the final result (or --seq N for one leaf)\n orc trace --run-id <id> # per-leaf and per-tool detail\n orc open --run-id <id> # open the live monitor, print its URL\n orc list # recent runs\n\n## 4. Approvals\n\nIn `manual` or `accept-edits` mode a leaf can pause to ask permission for a\ntool. Answer it from anywhere:\n\n orc approvals --run-id <id>\n orc respond --run-id <id> --approval-id <aid> --behavior allow|deny\n\n## Discover more\n\n orc --help # every command\n orc <command> --help # a command's flags\n orc commands # JSON catalog of all operations\n orc capabilities # available harnesses, models, and reasoning levels\n orc doctor --host <ssh> # check a local or remote machine is ready\n\nEvery command supports `--json`. Run state lives in `$ORC_HOME` (default\n`~/.orc`). Real runs need `claude` and/or `codex` installed and logged in.\n";
6
+ export declare const GUIDE = "# orc \u2014 how to write and run a program\n\norc runs a \"program\": a script that fans out AI-agent subtasks (\"leaves\") and\nrecords each one, so a run is reproducible, resumable, and observable. You write\na program, launch it, then watch it and collect the result.\n\n## 1. Write a program\n\nA program is a `.orc.ts` file with a single default-exported async function.\nIt receives an api object and returns the run's result:\n\n import type { Program } from \"@karowanorg/orc-sdk/program\"; // optional, type-only\n\n const program: Program = async ({ agent, parallel, phase }) => {\n const inventory = await agent(\"List the modules in this repo.\", {\n schema: { type: \"object\",\n properties: { modules: { type: \"array\", items: { type: \"string\" } } },\n required: [\"modules\"] },\n });\n\n // Ordinary async/await controls the flow. Awaiting a result before the\n // next call makes it a dependency; independent calls run concurrently.\n const plans = await Promise.all((inventory.modules as string[]).map(async (m) => {\n const findings = await agent(`Audit module ${m}`, { id: `audit-${m}` });\n return agent(`Plan a fix for ${m}: ${JSON.stringify(findings)}`, { id: `plan-${m}` });\n }));\n\n return phase(\"synthesis\", () => agent(`Merge these plans: ${JSON.stringify(plans)}`, { id: \"merge\" }));\n };\n export default program;\n\n## The api\n\nIMPORTANT \u2014 leaves are isolated. Each agent() runs a FRESH subagent that shares\nNONE of your context: it cannot see this program, your conversation, other\nleaves' prompts or results, or anything you know that you haven't written into\nits prompt (plus the shared `--brief`).\n\n- agent(prompt, opts?) => Promise<result>\n Dispatch one agent. Returns its result (matching `schema` if you pass one).\n A failed leaf rejects the promise, so wrap it in try/catch if you want to\n handle failure. Options:\n id a label shown in the monitor\n schema JSON Schema; the result is structured output matching it\n harness \"claude\" | \"codex\" | a configured harness (default: auto)\n model e.g. \"claude-fable-5\", \"gpt-5.6-sol\"\n reasoningEffort \"low\" | \"medium\" | \"high\" | \"xhigh\" | \"max\"\n readOnly default true; set false for a leaf that edits files\n cwd working directory for this leaf (defaults to the run's)\n idleTimeout ms with no output before the leaf is killed (false = off)\n phase group this call under a phase label\n To see valid `harness`, `model`, and `reasoningEffort` values for your\n machine, run `orc capabilities` (or `orc capabilities --json`) \u2014 it lists\n each installed harness with its available models and reasoning levels.\n Omit any of them to use the default; an unknown value is rejected up front\n by `orc validate`.\n\n- parallel(specs[]) => Promise<outcomes[]>\n Run several agents at once from an array of option objects (each with a\n `prompt`). Every lane runs to completion INDEPENDENTLY \u2014 one lane failing\n never cancels the others. Outcomes come back in order as\n `{ status: \"ok\", value } | { status: \"error\", error }`, so you decide how to\n handle partial failure. (For fail-fast, use `Promise.all` over `agent()`,\n which rejects on the first failure.)\n\n- phase(name, fn) => Promise<result>\n Group every agent() call made inside `fn` under a phase, for a readable\n run timeline.\n\n- settle(promise) => { status: \"ok\", value } | { status: \"error\", error }\n Run a lane and capture its outcome instead of letting a failure stop the run\n \u2014 useful for \"do all of these, some may fail\" fan-outs.\n\n- log(message) \u2014 write a line to the run's live event feed.\n- ext.<name>(payload) \u2014 call a custom step you registered in orc.config.\n\nBecause leaves can't see each other, pass data between them as plain values:\nput a previous result into the next prompt with JSON.stringify so the receiving\nleaf actually has it. Use normal try/catch, Promise.all/allSettled, and bounded\nloops for control flow.\n\n## What a program may and may not do\n\n- No wall clock or randomness. `Date`, `Math.random`, timers, network, file\n access, and imports (beyond type-only) are unavailable \u2014 a program only\n decides which agents to run and how to combine their results.\n- Loops must be finite; an unbounded loop is stopped by a step limit.\n- These constraints let orc replay a program exactly when you resume it, so the\n same inputs always produce the same run.\n\n## Writing files\n\nBy default leaves are read-only. To let a leaf directly modify files or run\nmutating commands, set `readOnly: false` and launch the run with\n`--allow-writes`. Configured hooks and MCP tools are not disabled for read-only\nleaves; their side effects are outside this guarantee. A write leaf runs with\nwhatever permissions your own agent has; add `--sandbox` to confine its writes\nto the working directory. If a run stops on a write leaf, `orc resume` picks it\nback up (it re-checks the working-tree state first, never blindly redoing work).\n\n## 2. Validate and launch\n\n orc validate --program-path ./my.orc.ts # compile + preview, no run\n orc launch --program-path ./my.orc.ts --brief \"what this run is for\"\n\n`--brief` (required) is shared context added to every leaf. Common launch flags:\n`--allow-writes`, `--approval-mode manual|accept-edits|auto|bypass`,\n`--sandbox`, `--harness claude|codex`, `--budget <usd>` (fail the run after\nobserved estimated cost exceeds this; concurrent work may overshoot), `--wait`\n(block for the result instead of running in the background).\n\n## 3. Watch and collect\n\n orc status --run-id <id> # summary\n orc wait --run-id <id> # block until it finishes\n orc get-result --run-id <id> # the final result (or --seq N for one leaf)\n orc trace --run-id <id> # per-leaf and per-tool detail\n orc open --run-id <id> # open the live monitor, print its URL\n orc list # recent runs\n\n## 4. Approvals\n\nIn `manual` or `accept-edits` mode a leaf can pause to ask permission for a\ntool. Answer it from anywhere:\n\n orc approvals --run-id <id>\n orc respond --run-id <id> --approval-id <aid> --behavior allow|deny\n\n## Discover more\n\n orc --help # every command\n orc <command> --help # a command's flags\n orc commands # JSON catalog of all operations\n orc capabilities # available harnesses, models, and reasoning levels\n orc doctor # check this machine is ready\n\nEvery command supports `--json`. Run state lives in `$ORC_HOME` (default\n`~/.orc`). Real runs need `claude` and/or `codex` installed and logged in.\n";
package/dist/guide.js CHANGED
@@ -52,7 +52,6 @@ its prompt (plus the shared \`--brief\`).
52
52
  reasoningEffort "low" | "medium" | "high" | "xhigh" | "max"
53
53
  readOnly default true; set false for a leaf that edits files
54
54
  cwd working directory for this leaf (defaults to the run's)
55
- host SSH destination to run this leaf on a remote machine
56
55
  idleTimeout ms with no output before the leaf is killed (false = off)
57
56
  phase group this call under a phase label
58
57
  To see valid \`harness\`, \`model\`, and \`reasoningEffort\` values for your
@@ -110,7 +109,7 @@ back up (it re-checks the working-tree state first, never blindly redoing work).
110
109
  orc launch --program-path ./my.orc.ts --brief "what this run is for"
111
110
 
112
111
  \`--brief\` (required) is shared context added to every leaf. Common launch flags:
113
- \`--allow-writes\`, \`--host <ssh>\`, \`--approval-mode manual|accept-edits|auto|bypass\`,
112
+ \`--allow-writes\`, \`--approval-mode manual|accept-edits|auto|bypass\`,
114
113
  \`--sandbox\`, \`--harness claude|codex\`, \`--budget <usd>\` (fail the run after
115
114
  observed estimated cost exceeds this; concurrent work may overshoot), \`--wait\`
116
115
  (block for the result instead of running in the background).
@@ -138,7 +137,7 @@ tool. Answer it from anywhere:
138
137
  orc <command> --help # a command's flags
139
138
  orc commands # JSON catalog of all operations
140
139
  orc capabilities # available harnesses, models, and reasoning levels
141
- orc doctor --host <ssh> # check a local or remote machine is ready
140
+ orc doctor # check this machine is ready
142
141
 
143
142
  Every command supports \`--json\`. Run state lives in \`$ORC_HOME\` (default
144
143
  \`~/.orc\`). Real runs need \`claude\` and/or \`codex\` installed and logged in.
package/dist/ops.d.ts CHANGED
@@ -18,7 +18,6 @@ interface FirstFrontierCall {
18
18
  id?: string;
19
19
  readOnly: boolean;
20
20
  harness?: string;
21
- host?: string;
22
21
  model?: string;
23
22
  reasoningEffort?: string;
24
23
  schema?: Json;
@@ -27,7 +26,6 @@ interface FirstFrontierCall {
27
26
  export declare const launch: OpDef<z.ZodObject<{
28
27
  programPath: z.ZodString;
29
28
  cwd: z.ZodOptional<z.ZodString>;
30
- host: z.ZodOptional<z.ZodString>;
31
29
  brief: z.ZodString;
32
30
  allowWrites: z.ZodDefault<z.ZodBoolean>;
33
31
  approvalMode: z.ZodDefault<z.ZodEnum<{
@@ -79,7 +77,6 @@ export declare const validate: OpDef<z.ZodObject<{
79
77
  bypass: "bypass";
80
78
  }>>;
81
79
  harness: z.ZodOptional<z.ZodString>;
82
- host: z.ZodOptional<z.ZodString>;
83
80
  checkCapabilities: z.ZodDefault<z.ZodBoolean>;
84
81
  }, z.core.$strip>, {
85
82
  ok: boolean;
@@ -137,7 +134,6 @@ export declare const getTrace: OpDef<z.ZodObject<{
137
134
  harness?: string;
138
135
  model?: string;
139
136
  reasoningEffort?: string;
140
- host?: string;
141
137
  cwd?: string;
142
138
  readOnly: boolean;
143
139
  startMs: number;
@@ -159,7 +155,6 @@ export declare const list: OpDef<z.ZodObject<{
159
155
  name: string | undefined;
160
156
  state: string;
161
157
  createdAtMs: number;
162
- host: string | undefined;
163
158
  cwd: string;
164
159
  }[]>;
165
160
  export declare const cancel: OpDef<z.ZodObject<{
@@ -194,10 +189,8 @@ export declare const respondApproval: OpDef<z.ZodObject<{
194
189
  enqueued: boolean;
195
190
  }>;
196
191
  export declare const capabilities: OpDef<z.ZodObject<{
197
- host: z.ZodOptional<z.ZodString>;
198
192
  refresh: z.ZodDefault<z.ZodBoolean>;
199
193
  }, z.core.$strip>, {
200
- host: string;
201
194
  defaultHarness: string;
202
195
  harnesses: Record<string, unknown>;
203
196
  extensions: string[];
@@ -214,16 +207,13 @@ export declare const report: OpDef<z.ZodObject<{
214
207
  path: string;
215
208
  }>;
216
209
  export declare const guide: OpDef<z.ZodObject<{
217
- host: z.ZodOptional<z.ZodString>;
218
210
  probe: z.ZodDefault<z.ZodBoolean>;
219
211
  }, z.core.$strip>, {
220
212
  guide: string;
221
213
  }>;
222
214
  export declare const doctor: OpDef<z.ZodObject<{
223
- host: z.ZodOptional<z.ZodString>;
224
215
  cwd: z.ZodOptional<z.ZodString>;
225
216
  }, z.core.$strip>, {
226
- host: string;
227
217
  checks: Record<string, unknown>;
228
218
  }>;
229
219
  export declare const ALL_OPS: OpDef[];
package/dist/ops.js CHANGED
@@ -25,7 +25,6 @@ export const launch = defineOp({
25
25
  input: z.object({
26
26
  programPath: z.string().describe("path to the program (.orc.ts/.ts/.js)"),
27
27
  cwd: z.string().optional().describe("working directory (plain path); defaults to the caller's cwd"),
28
- host: z.string().optional().describe("SSH destination (separate field; e.g. 'build@ci-box' or an ssh-config alias)"),
29
28
  brief: z.string().describe("shared context injected into every leaf"),
30
29
  allowWrites: z.boolean().default(false).describe("grant write-declared leaves permission to mutate files"),
31
30
  approvalMode: ApprovalMode.default("auto").describe("manual | accept-edits | auto | bypass"),
@@ -42,7 +41,6 @@ export const launch = defineOp({
42
41
  const manifest = await prepareRun({
43
42
  programPath: input.programPath,
44
43
  cwd: input.cwd,
45
- host: input.host,
46
44
  brief: input.brief,
47
45
  allowWrites: input.allowWrites,
48
46
  approvalMode: input.approvalMode,
@@ -87,7 +85,6 @@ export const validate = defineOp({
87
85
  allowWrites: z.boolean().default(false),
88
86
  approvalMode: ApprovalMode.default("auto").describe("check the first-frontier harnesses can honor this mode"),
89
87
  harness: z.string().optional().describe("default harness override (same precedence as launch)"),
90
- host: z.string().optional().describe("check capabilities on this remote host"),
91
88
  checkCapabilities: z.boolean().default(true).describe("probe referenced harnesses for model/effort/mode support (slower)"),
92
89
  }),
93
90
  async handler(input, ctx) {
@@ -105,7 +102,6 @@ export const validate = defineOp({
105
102
  id: spec.id,
106
103
  readOnly: spec.readOnly,
107
104
  harness: spec.harness,
108
- host: spec.host,
109
105
  model: spec.model,
110
106
  reasoningEffort: spec.reasoningEffort,
111
107
  schema: spec.schema,
@@ -127,19 +123,16 @@ export const validate = defineOp({
127
123
  finally {
128
124
  vm?.dispose();
129
125
  }
130
- // Host can change per leaf, so only share probes with the same effective
131
- // harness and executor destination.
132
126
  const capsCache = new Map();
133
- const capsFor = (harnessName, host) => {
134
- const key = JSON.stringify([harnessName, host]);
135
- const cached = capsCache.get(key);
127
+ const capsFor = (harnessName) => {
128
+ const cached = capsCache.get(harnessName);
136
129
  if (cached)
137
130
  return cached;
138
131
  const harness = ctx.registry.harnesses.get(harnessName);
139
132
  if (!harness)
140
133
  return Promise.reject(new Error(`unknown harness "${harnessName}"`));
141
- const pending = Promise.resolve().then(() => harness.discover({ executor: ctx.registry.executorFor(host) }));
142
- capsCache.set(key, pending);
134
+ const pending = Promise.resolve().then(() => harness.discover({ executor: ctx.registry.executor }));
135
+ capsCache.set(harnessName, pending);
143
136
  return pending;
144
137
  };
145
138
  for (const call of firstCalls) {
@@ -159,7 +152,6 @@ export const validate = defineOp({
159
152
  }
160
153
  if (call.kind === "agent") {
161
154
  const harnessName = call.harness ?? input.harness ?? ctx.registry.defaultHarness;
162
- const host = call.host ?? input.host;
163
155
  const harness = ctx.registry.harnesses.get(harnessName);
164
156
  if (!harness) {
165
157
  problems.push(`call ${call.seq} uses unknown harness "${harnessName}" (available: ${[...ctx.registry.harnesses.keys()].join(", ")})`);
@@ -177,10 +169,10 @@ export const validate = defineOp({
177
169
  if (harness && input.checkCapabilities) {
178
170
  let caps;
179
171
  try {
180
- caps = await capsFor(harnessName, host);
172
+ caps = await capsFor(harnessName);
181
173
  }
182
174
  catch (err) {
183
- problems.push(`call ${call.seq}: could not discover harness "${harnessName}"${host ? ` on ${host}` : ""} (${String(err instanceof Error ? err.message : err)})`);
175
+ problems.push(`call ${call.seq}: could not discover harness "${harnessName}" (${String(err instanceof Error ? err.message : err)})`);
184
176
  continue;
185
177
  }
186
178
  if (!caps.available) {
@@ -218,7 +210,7 @@ export const validate = defineOp({
218
210
  }
219
211
  const approvalMode = input.approvalMode ?? "auto";
220
212
  if (caps.approvalModes.length > 0 && !caps.approvalModes.includes(approvalMode)) {
221
- problems.push(`call ${call.seq}: harness "${harnessName}" cannot honor approval mode "${approvalMode}"${host ? " over ssh" : ""} (supports: ${caps.approvalModes.join(", ")})`);
213
+ problems.push(`call ${call.seq}: harness "${harnessName}" cannot honor approval mode "${approvalMode}" (supports: ${caps.approvalModes.join(", ")})`);
222
214
  }
223
215
  }
224
216
  }
@@ -322,13 +314,13 @@ export const list = defineOp({
322
314
  catch {
323
315
  /* partial run dir */
324
316
  }
325
- return { runId: m.runId, name: m.name, state, createdAtMs: m.createdAtMs, host: m.host, cwd: m.cwd };
317
+ return { runId: m.runId, name: m.name, state, createdAtMs: m.createdAtMs, cwd: m.cwd };
326
318
  });
327
319
  },
328
320
  });
329
321
  export const cancel = defineOp({
330
322
  name: "cancel",
331
- doc: "Queue cancellation. Local leaves get TERM→KILL; plain SSH only confirms channel teardown, so remote process state may be unknown.",
323
+ doc: "Queue cancellation. Leaves get TERM→KILL on their whole process group.",
332
324
  readOnly: false,
333
325
  input: z.object({ runId: RunId }),
334
326
  async handler(input) {
@@ -401,11 +393,10 @@ export const capabilities = defineOp({
401
393
  doc: "List harnesses, models, and reasoning levels — each discovered through the harness's native mechanism.",
402
394
  readOnly: true,
403
395
  input: z.object({
404
- host: z.string().optional().describe("probe a remote host instead of local"),
405
396
  refresh: z.boolean().default(false),
406
397
  }),
407
398
  async handler(input, ctx) {
408
- const executor = ctx.registry.executorFor(input.host);
399
+ const executor = ctx.registry.executor;
409
400
  const out = {};
410
401
  for (const [name, harness] of ctx.registry.harnesses) {
411
402
  out[name] = await harness.discover({ executor }).catch((err) => ({
@@ -414,7 +405,6 @@ export const capabilities = defineOp({
414
405
  }));
415
406
  }
416
407
  return {
417
- host: input.host ?? "(local)",
418
408
  defaultHarness: ctx.registry.defaultHarness,
419
409
  harnesses: out,
420
410
  extensions: [...ctx.registry.extensions.keys()],
@@ -450,7 +440,6 @@ export const guide = defineOp({
450
440
  doc: "How to write and run an orc program — the authoring + usage guide, with this machine's live harness/model catalog appended.",
451
441
  readOnly: true,
452
442
  input: z.object({
453
- host: z.string().optional().describe("probe this remote host's harnesses instead of local"),
454
443
  probe: z.boolean().default(true).describe("append the live capability catalog (set false for the static doc only)"),
455
444
  }),
456
445
  async handler(input, ctx) {
@@ -461,7 +450,7 @@ export const guide = defineOp({
461
450
  // values in hand instead of guessing. Never let a slow or missing harness
462
451
  // break the guide — degrade to the static doc, which already points at
463
452
  // `orc capabilities`.
464
- const caps = await withDeadline(capabilities.handler({ host: input.host, refresh: false }, ctx), 15_000).catch(() => null);
453
+ const caps = await withDeadline(capabilities.handler({ refresh: false }, ctx), 15_000).catch(() => null);
465
454
  return { guide: GUIDE + (caps ? renderCapabilitiesForGuide(caps) : "") };
466
455
  },
467
456
  });
@@ -483,7 +472,7 @@ function renderCapabilitiesForGuide(caps) {
483
472
  "",
484
473
  "## Available on this machine",
485
474
  "",
486
- `Discovered live${c.host && c.host !== "(local)" ? ` on ${c.host}` : ""} — these are the valid \`harness\`, \`model\`, and`,
475
+ "Discovered live — these are the valid \`harness\`, \`model\`, and",
487
476
  `\`reasoningEffort\` values right now, so you don't have to guess. Default harness: **${c.defaultHarness}**.`,
488
477
  "Omit any of them to take the default.",
489
478
  ];
@@ -502,19 +491,18 @@ function renderCapabilitiesForGuide(caps) {
502
491
  if (h.approvalModes?.length)
503
492
  lines.push(` - approval modes: ${h.approvalModes.join(", ")}`);
504
493
  }
505
- lines.push("", "Re-run `orc capabilities` any time, or `orc capabilities --host <ssh>` for another machine.");
494
+ lines.push("", "Re-run `orc capabilities` any time.");
506
495
  return lines.join("\n");
507
496
  }
508
497
  export const doctor = defineOp({
509
498
  name: "doctor",
510
- doc: "Preflight an executor: harness binaries, versions, cwd existence.",
499
+ doc: "Preflight this machine: harness binaries, versions, cwd existence.",
511
500
  readOnly: true,
512
501
  input: z.object({
513
- host: z.string().optional(),
514
502
  cwd: z.string().optional(),
515
503
  }),
516
504
  async handler(input, ctx) {
517
- const executor = ctx.registry.executorFor(input.host);
505
+ const executor = ctx.registry.executor;
518
506
  const checks = {};
519
507
  for (const [name, harness] of ctx.registry.harnesses) {
520
508
  const caps = await harness.discover({ executor }).catch(() => null);
@@ -523,7 +511,7 @@ export const doctor = defineOp({
523
511
  if (input.cwd) {
524
512
  checks.cwd = { path: input.cwd, exists: await executor.exists(input.cwd) };
525
513
  }
526
- return { host: input.host ?? "(local)", checks };
514
+ return { checks };
527
515
  },
528
516
  });
529
517
  // ---------------------------------------------------------------------------
package/dist/registry.js CHANGED
@@ -5,7 +5,7 @@
5
5
  * come only from an explicit orc.config.(js|json).
6
6
  */
7
7
  import { callerAffinity, loadConfig } from "@karowanorg/orc-core";
8
- import { executorFor } from "@karowanorg/orc-executors";
8
+ import { LocalExecutor } from "@karowanorg/orc-executors";
9
9
  import { claudeHarness } from "@karowanorg/orc-harness-claude";
10
10
  import { codexHarness, createCodexHarness } from "@karowanorg/orc-harness-codex";
11
11
  import { makeExecHarness } from "./exec-harness.js";
@@ -31,5 +31,5 @@ export async function buildRegistry(opts = {}) {
31
31
  config.defaultHarness ??
32
32
  callerAffinity(opts.mcpClientName) ??
33
33
  "codex";
34
- return { harnesses, extensions, defaultHarness, executorFor };
34
+ return { harnesses, extensions, defaultHarness, executor: new LocalExecutor() };
35
35
  }
package/package.json CHANGED
@@ -1,15 +1,15 @@
1
1
  {
2
2
  "name": "@karowanorg/orc-ops",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "license": "0BSD",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
7
7
  "dependencies": {
8
- "@karowanorg/orc-core": "^0.1.0",
9
- "@karowanorg/orc-executors": "^0.1.0",
10
- "@karowanorg/orc-harness-claude": "^0.1.0",
11
- "@karowanorg/orc-harness-codex": "^0.1.0",
12
- "@karowanorg/orc-ui": "^0.1.0",
8
+ "@karowanorg/orc-core": "^0.1.1",
9
+ "@karowanorg/orc-executors": "^0.1.1",
10
+ "@karowanorg/orc-harness-claude": "^0.1.1",
11
+ "@karowanorg/orc-harness-codex": "^0.1.1",
12
+ "@karowanorg/orc-ui": "^0.1.1",
13
13
  "zod": "^4.1.0"
14
14
  },
15
15
  "description": "The zod-first operation registry orc's CLI, MCP server, and SDK all interpret.",