@autodidacticon/orchestrator 0.1.0 → 0.2.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/README.md +44 -31
- package/dist/src/agent/mcp-shim.js +1 -1
- package/dist/src/brief/compose.js +8 -1
- package/dist/src/brief/compose.js.map +1 -1
- package/dist/src/config.js +19 -3
- package/dist/src/config.js.map +1 -1
- package/dist/src/graph/load.js +4 -0
- package/dist/src/graph/load.js.map +1 -1
- package/dist/src/import/mapping.js +19 -1
- package/dist/src/import/mapping.js.map +1 -1
- package/dist/src/index.js +7 -1
- package/dist/src/index.js.map +1 -1
- package/dist/src/launch/launch.js +5 -1
- package/dist/src/launch/launch.js.map +1 -1
- package/dist/src/loop/orchestrator.js +91 -3
- package/dist/src/loop/orchestrator.js.map +1 -1
- package/dist/src/loop/tick.js +2 -1
- package/dist/src/loop/tick.js.map +1 -1
- package/dist/src/main.js +81 -13
- package/dist/src/main.js.map +1 -1
- package/dist/src/operator/cli.js +40 -2
- package/dist/src/operator/cli.js.map +1 -1
- package/dist/src/operator/mcp-server.js +32 -6
- package/dist/src/operator/mcp-server.js.map +1 -1
- package/dist/src/operator/mcp.js +1 -1
- package/dist/src/operator/routes.js +19 -1
- package/dist/src/operator/routes.js.map +1 -1
- package/dist/src/runner/claude-code.js +1 -1
- package/dist/src/runner/claude-code.js.map +1 -1
- package/dist/src/runner/command.js +24 -0
- package/dist/src/runner/command.js.map +1 -0
- package/dist/src/runner/selection.js +20 -0
- package/dist/src/runner/selection.js.map +1 -0
- package/dist/src/runner/subprocess.js +7 -1
- package/dist/src/runner/subprocess.js.map +1 -1
- package/dist/src/runs/lifecycle.js +60 -3
- package/dist/src/runs/lifecycle.js.map +1 -1
- package/dist/src/runs/resolve.js +217 -0
- package/dist/src/runs/resolve.js.map +1 -0
- package/dist/src/runs/runDir.js +63 -13
- package/dist/src/runs/runDir.js.map +1 -1
- package/dist/src/state/store.js.map +1 -1
- package/dist/src/toolchain/branch.js +19 -0
- package/dist/src/toolchain/branch.js.map +1 -0
- package/dist/src/toolchain/detect.js +115 -0
- package/dist/src/toolchain/detect.js.map +1 -0
- package/dist/src/toolchain/tools.js +56 -0
- package/dist/src/toolchain/tools.js.map +1 -0
- package/dist/src/verify/verifier.js +5 -1
- package/dist/src/verify/verifier.js.map +1 -1
- package/hosts/claude-code/.claude-plugin/plugin.json +1 -1
- package/hosts/claude-code/package-lock.json +1247 -0
- package/hosts/claude-code/package.json +1 -1
- package/hosts/claude-code/skills/import/SKILL.md +14 -2
- package/hosts/claude-code/skills/run/SKILL.md +48 -8
- package/hosts/claude-code/skills/work/SKILL.md +11 -2
- package/hosts/claude-code/workflows/work.js +5 -2
- package/package.json +1 -1
|
@@ -17,7 +17,12 @@ session and hand over normalized records.
|
|
|
17
17
|
session; connect one (for example the Linear or Atlassian plugin) and run the import again."
|
|
18
18
|
Do not call `import_issues`.
|
|
19
19
|
- The orchestrator daemon must be running for this repository. Call the `start` tool; it is
|
|
20
|
-
idempotent and returns the run directory
|
|
20
|
+
idempotent and returns the run directory, the graph path, and the resolved configuration.
|
|
21
|
+
Report the toolchain in one line: the check command and the integration branch with the
|
|
22
|
+
source of each (for example "detected: npm test on main"). When `needsConfig` names
|
|
23
|
+
`checkCommand`, follow the run skill's section 1b (read `CLAUDE.md`, the README, and the
|
|
24
|
+
root manifests; set it with `configure` when it is stated unambiguously, otherwise ask) before
|
|
25
|
+
continuing, so that the first submission is not held.
|
|
21
26
|
|
|
22
27
|
## 2. Fetch the root and everything it references
|
|
23
28
|
|
|
@@ -56,6 +61,11 @@ One record per issue you fetched, including the root:
|
|
|
56
61
|
issue's `priority` field as is (its 0, meaning none, is dropped). Jira: send the position
|
|
57
62
|
of the issue's priority in the site's priority list, counted from the most urgent as 1.
|
|
58
63
|
Omit it when the tracker has no priority.
|
|
64
|
+
- `labels` are passed through. Two label shapes choose the worker for the task: `model:<name>`
|
|
65
|
+
(for example `model:claude-sonnet-5-5`) and `effort:<level>` (`low`, `medium`, `high`,
|
|
66
|
+
`xhigh`, or `max`). Without them a task runs with the run's defaults (`claude-opus-5-5` at
|
|
67
|
+
`medium`, changeable with `configure`). A label whose value is not recognised is left as a
|
|
68
|
+
plain label and reported under `ignoredLabels`.
|
|
59
69
|
|
|
60
70
|
## 4. Import
|
|
61
71
|
|
|
@@ -72,7 +82,9 @@ in progress, done, or cancelled, and comments appear where a human is needed.
|
|
|
72
82
|
|
|
73
83
|
## 5. Report
|
|
74
84
|
|
|
75
|
-
Show the user the summary: counts of tasks, external nodes, and milestones;
|
|
85
|
+
Show the user the summary: counts of tasks, external nodes, and milestones; any
|
|
86
|
+
`ignoredLabels` (say which issue's `model:` or `effort:` label was not recognised and that the
|
|
87
|
+
task will use the run default); the tasks missing
|
|
76
88
|
acceptance criteria, which will block at ready until someone adds them; any unknown external
|
|
77
89
|
blockers; and whether the graph was accepted by the daemon. If the import was rejected as an
|
|
78
90
|
incompatible reload, show the reasons and suggest cancelling the affected tasks first.
|
|
@@ -11,13 +11,45 @@ never raw event lists.
|
|
|
11
11
|
|
|
12
12
|
## 1. Start
|
|
13
13
|
|
|
14
|
-
Call `start`. It returns the run directory, graph path, URL,
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
14
|
+
Call `start`. It returns the run directory, graph path, URL, the runner `mode` in force, and
|
|
15
|
+
the resolved configuration: `config` (every key as `{ value, source }`, the source being
|
|
16
|
+
`argument`, `file`, `pinned`, `detected`, `default`, or `unresolved`), `toolchain` (what
|
|
17
|
+
detection found in the repository root), and `needsConfig` (keys no layer supplied). It is safe
|
|
18
|
+
to repeat. A run started from this plugin defaults to `pull`: the daemon prepares each launch
|
|
19
|
+
and this session's own subagents do the work (section 1a), so the user sees every agent here.
|
|
20
|
+
`spawn` (the daemon runs headless agents, for unattended runs) and `mixed` are explicit
|
|
21
|
+
choices: `start` with `mode`, or `runner.mode` in `orchestrator.yaml`, which wins.
|
|
22
|
+
|
|
23
|
+
Tell the user who is executing the work, and report the toolchain in one line: the check
|
|
24
|
+
command, the integration branch, and the worker model and effort (`config.model` and
|
|
25
|
+
`config.effort`, default `claude-opus-5-5` at `medium`) with the source of each and, when the
|
|
26
|
+
daemon spawns agents (`spawn`, or `mixed` after the claim window), the toolchains whose
|
|
27
|
+
commands agents may run, for example
|
|
28
|
+
"detected: npm test on main; workers claude-opus-5-5 at medium (default); agents may run npm and node".
|
|
29
|
+
When this session's subagents work the launches (`pull`), omit the allow-list part: workers
|
|
30
|
+
run under this session's own permissions.
|
|
31
|
+
When `config.model.applied` is false (a `runnerCommand` without the `{model}` slot), omit the
|
|
32
|
+
model part. A task can choose its own model or effort: `model` and `effort` in its payload, or
|
|
33
|
+
`model:<name>` and `effort:<level>` labels on its issue; `status.liveLaunches` shows what each
|
|
34
|
+
launch runs with. If `needsConfig` is not empty, resolve it now (section 1b). Then call
|
|
35
|
+
`status`. If no graph is loaded, say so and suggest the `import` skill.
|
|
36
|
+
|
|
37
|
+
## 1b. Resolve what detection could not
|
|
38
|
+
|
|
39
|
+
When `needsConfig` names `checkCommand`, in the `start` result or in a later `wait` digest,
|
|
40
|
+
submitted work is held under `verifying` until a check command is set: no attempt is spent and
|
|
41
|
+
the sealed work is kept, but nothing is published. Never leave it unresolved while a task is
|
|
42
|
+
`submitted` without having asked the user. Look for the test command in `CLAUDE.md`, the
|
|
43
|
+
README, and the manifests in the repository root (`package.json` scripts, `Makefile` targets,
|
|
44
|
+
and their counterparts). When one is stated unambiguously, call `configure` with `checkCommand`
|
|
45
|
+
and tell the user the command and where you found it ("set checkCommand to `make check` from
|
|
46
|
+
CLAUDE.md"). Otherwise propose your best reading, or say you found none, and call `configure`
|
|
47
|
+
only with what the user confirms. `configure` also takes `capacity`, `allowedTools` (rules
|
|
48
|
+
appended to the derived list for spawned agents, such as `Bash(docker:*)`), `runnerCommand`,
|
|
49
|
+
and `model` and `effort` (the worker defaults for launches prepared from then on; effort is
|
|
50
|
+
`low`, `medium`, `high`, `xhigh`, or `max`); a null clears an override so the value falls back
|
|
51
|
+
to the file, detection, or the default. The integration branch is start-only: pass `integrationBranch` to `start` before
|
|
52
|
+
the run holds any launch; a running daemon refuses it.
|
|
21
53
|
|
|
22
54
|
## 1a. Work the run with session subagents
|
|
23
55
|
|
|
@@ -47,7 +79,15 @@ answers (section 2b), then act on the digest:
|
|
|
47
79
|
|
|
48
80
|
- **openQuestions** non-empty: for each task, call `status` or `logs` only if you need
|
|
49
81
|
context, then present the question to the user verbatim and wait for their reply. Send the
|
|
50
|
-
reply with `answer`. Do not invent answers to questions that need a human decision.
|
|
82
|
+
reply with `answer`. Do not invent answers to questions that need a human decision. When the
|
|
83
|
+
question's kind is `needsAccess` and it names a command (from `status`, under the task's
|
|
84
|
+
blocked or waiting reason), offer three things: adding a rule through `configure`
|
|
85
|
+
(`allowedTools: ["Bash(<command>:*)"]`) so launches spawned afterwards can run it, saying
|
|
86
|
+
that the live agent cannot gain the rule; running the command yourself on the agent's behalf
|
|
87
|
+
in its worktree and sending the result with `answer`, which is what unblocks the live agent
|
|
88
|
+
now; or answering with an alternative. Do what the user picks.
|
|
89
|
+
- **needsConfig** names `checkCommand`: submitted tasks are held under `verifying` until a
|
|
90
|
+
check command is set. Follow section 1b now; do not call the run slow or stalled.
|
|
51
91
|
- **awaitingReview** non-empty: invoke the `review` skill for each milestone.
|
|
52
92
|
- **finished** true: report the final state (done tasks, milestones) and stop.
|
|
53
93
|
- **stalled** true: report `stallRoots` with their reasons. Offer the options that apply:
|
|
@@ -14,7 +14,15 @@ the workflow hands back: questions, reviews, and the end.
|
|
|
14
14
|
## 1. Prerequisites
|
|
15
15
|
|
|
16
16
|
- A graph must be loaded: call `start` and then `status`; if no graph is loaded, use the
|
|
17
|
-
`import` skill first.
|
|
17
|
+
`import` skill first. `start` also returns the resolved configuration: report the check
|
|
18
|
+
command, the integration branch, and the worker model and effort (`config.model`,
|
|
19
|
+
`config.effort`; default `claude-opus-5-5` at `medium`, changeable with `configure`, and
|
|
20
|
+
overridable per task by `model`/`effort` in its payload or `model:`/`effort:` labels) with
|
|
21
|
+
their sources in one line, for example "detected: npm test on main; workers claude-opus-5-5
|
|
22
|
+
at medium (default)", and when `needsConfig`
|
|
23
|
+
names `checkCommand`, follow the run skill's section 1b (find the test command in
|
|
24
|
+
`CLAUDE.md`, the README, or the root manifests and set it with `configure`, or ask the user)
|
|
25
|
+
before running workers, since submitted work is held until it is set.
|
|
18
26
|
- `start` reports the mode in force. A plugin-started run is already `pull`. To work a run in
|
|
19
27
|
`spawn` mode, call `start` with `mode: "pull"` (workers only) or `mode: "mixed"` (the
|
|
20
28
|
daemon spawns whatever nobody claims within its claim window); this switches a daemon
|
|
@@ -30,7 +38,8 @@ Workflow({ scriptPath: "<plugin dir>/workflows/work.js", args: { workers: 2, run
|
|
|
30
38
|
```
|
|
31
39
|
|
|
32
40
|
Each worker loop claims a launch with the worker id `<runTag>-<n>`, runs a worker agent on
|
|
33
|
-
the brief
|
|
41
|
+
the brief with the model and effort the claim carries (the task's choice, else the run
|
|
42
|
+
default), and claims again until nothing is claimable. The workflow runs in the background
|
|
34
43
|
and returns short outcomes per launch; never paste briefs or logs into the conversation.
|
|
35
44
|
|
|
36
45
|
## 3. Monitor while it runs
|
|
@@ -24,6 +24,8 @@ const CLAIM_SCHEMA = {
|
|
|
24
24
|
briefMarkdown: { type: 'string' },
|
|
25
25
|
pendingSeq: { type: 'number' },
|
|
26
26
|
pendingAnswer: { type: 'string' },
|
|
27
|
+
model: { type: 'string' },
|
|
28
|
+
effort: { type: 'string', enum: ['low', 'medium', 'high', 'xhigh', 'max'] },
|
|
27
29
|
finished: { type: 'boolean' },
|
|
28
30
|
stalled: { type: 'boolean' },
|
|
29
31
|
openQuestions: { type: 'array', items: { type: 'string' } },
|
|
@@ -47,7 +49,7 @@ function claimPrompt(workerId, heldCount) {
|
|
|
47
49
|
return [
|
|
48
50
|
`You are the claimer for orchestrator worker "${workerId}". Use the orchestrator operator MCP tools (names end in claim, wait, status; load them with ToolSearch if needed).`,
|
|
49
51
|
`1. Call claim with workerId "${workerId}" and access "local".`,
|
|
50
|
-
'2. If it returns a launch (status 200): read the markdown brief at briefPath and return { claimed: true, launchId, taskId, token, worktree, briefPath, briefMarkdown: <the full brief file>, pendingSeq, pendingAnswer } (pending fields only when the response carries pending).',
|
|
52
|
+
'2. If it returns a launch (status 200): read the markdown brief at briefPath and return { claimed: true, launchId, taskId, token, worktree, briefPath, briefMarkdown: <the full brief file>, model, effort, pendingSeq, pendingAnswer } (model and effort exactly as the response gives them; pending fields only when the response carries pending).',
|
|
51
53
|
'3. If it returns 404 (nothing claimable or paused): call wait with until "any" and timeoutMs 30000, then call status. Return { claimed: false, stop, finished, stalled, openQuestions, awaitingReview, claimable } from status.',
|
|
52
54
|
` stop is true when finished is true, or stalled is true, or (claimable is 0 and ${heldCount} launches are held by other loops is false and (openQuestions is non-empty or awaitingReview is non-empty)). Otherwise stop is false.`,
|
|
53
55
|
'4. On any other error return { claimed: false, stop: true }.',
|
|
@@ -89,7 +91,8 @@ async function loop(i) {
|
|
|
89
91
|
}
|
|
90
92
|
held[workerId] = c.taskId
|
|
91
93
|
log(`${workerId}: working ${c.taskId}`)
|
|
92
|
-
|
|
94
|
+
// The launch's model and effort were fixed when the daemon prepared it; the worker agent runs with them. See specs/model-selection.
|
|
95
|
+
const r = await agent(workerPrompt(c), { label: `work:${c.taskId}`, phase: 'Work', schema: OUTCOME_SCHEMA, ...(c.model ? { model: c.model } : {}), ...(c.effort ? { effort: c.effort } : {}) })
|
|
93
96
|
delete held[workerId]
|
|
94
97
|
const outcome = r || { taskId: c.taskId, outcome: 'failed', summary: 'worker agent returned nothing' }
|
|
95
98
|
outcomes.push({ worker: workerId, ...outcome })
|