Move the coordinator subsystem out of orchestrator.ts into coordinator.ts:
goal-decomposition parsing, coordinator prompt construction (system prompt,
roster, output format, decomposition), the synthesis pass, and task-spec loading.
The parse helpers are a pure move. The former private class methods become free
functions; two take the orchestrator config explicitly (buildCoordinatorBaseConfig,
runCoordinatorSynthesis) instead of this.config. Prompt string literals are
byte-for-byte unchanged (only code indentation shifts as methods de-indent to
module scope). One type follow-on: runCoordinatorSynthesis gains a
`?? DEFAULT_MODEL` guard because OrchestratorConfig.defaultModel is optional where
the resolved class field was not; it is dead at runtime (callers pass the resolved
config) and mirrors the same guard already in task-execution's executeQueue.
orchestrator.ts drops from 2213 to 1683 lines (57% below the original 3953). Also
updates the AGENTS.md layer map.
Verified with npm run lint, 1385 passing tests, zero diff under tests/, a
byte-identical parse block, all 87 single-quoted and 17 backtick prompt-string
literals identical, and a dist/index.d.ts identical to the pre-split build.
Third of three sequential pure-move PRs; builds on the merged #400 and #397.
Move the orchestration loop and the consensus subsystem out of orchestrator.ts
into two focused modules, with zero behavior change:
- task-execution.ts: the dependency-ordered execution loop (executeQueue),
delegation team-info, checkpoint saves, and per-task prompt assembly
- consensus.ts: the proposer/judge verification loop (runConsensusCore) and the
per-task verify hook (runTaskVerify)
orchestrator.ts drops from 3305 to 2213 lines. task-execution depends on
consensus (runTaskVerify); both build on the PR1 foundation modules. The module
graph stays acyclic.
Pure move: extracted bodies are byte-identical to the originals (only an export
prefix added) and the kept region is byte-identical. Verified with npm run lint,
1385 passing tests, zero diff under tests/, and a dist/index.d.ts identical to
the pre-split build.
Second of three sequential pure-move PRs; builds on the merged #397 foundation
modules.
Move pure module-level helpers out of the 3953-line orchestrator.ts into five
focused modules, with zero behavior change:
- run-context.ts: RunContext/ActiveCheckpoint types, run identity/metadata
helpers, and the token/error utilities (the dependency-free base)
- budget.ts: token/cost accounting, budget-cap enforcement, run-metrics rollup
- short-circuit.ts: isSimpleGoal / selectBestAgent
- retry.ts: executeWithRetry / computeRetryDelay
- agent-config.ts: buildAgent, default-tool-preset grant, model routing
orchestrator.ts drops to 3305 lines and re-exports isSimpleGoal, selectBestAgent,
computeRetryDelay, and executeWithRetry, so the index.ts barrel and all test
import paths are unchanged.
Pure move: extracted bodies are byte-identical to the originals (only an export
prefix added) and the kept region is byte-identical to origin/main. Verified with
npm run lint plus 1385 passing tests, zero diff under tests/, and a
dist/index.d.ts identical to the pre-split build.
First of three sequential pure-move PRs (PR2: consensus + task-execution;
PR3: coordinator + AGENTS.md).
* feat(core): add unified run viewer
* feat(cli): export run viewer from trace store
* docs(core): add deterministic run viewer demo
* fix(examples): resolve workspace paths in typecheck
* fix(dashboard): center detail status labels
* fix(dashboard): remove DAG status rails
* fix(dashboard): enlarge DAG task cards
* fix(dashboard): clarify run summary header
* docs: align readmes with run viewer
Clean the detached process group when stream consumption stops after the direct child has already exited. Adds a POSIX regression verifying the descendant is terminated. Fixes#387.
Third split of #96 (follow-up to #379). The onToolCall gate shipped in #377 and
the classifyBashCommand classifier in #379; this documents both and adds a
runnable example.
- docs/tool-configuration.md: a "Per-call gating with onToolCall" section (where
it sits, ToolCallContext/ToolCallDecision, deny returns an error ToolResult not
a throw, agent overrides orchestrator default, orthogonal to onApproval,
gated/gateAction/gateReason on the trace with gateReason redacted, not a
security boundary) plus a shell risk classifier subsection.
- examples/patterns/risk-gated-bash.ts: a security-audit agent that classifies
each bash command and routes safe/review/high to allow/human-approval/deny.
- AGENTS.md: cross-links in the tool-layer notes + /classifiers in the exports map.
Closes#380
Ships an opt-in, dependency-free shell risk classifier for the onToolCall gate
(#377). classifyBashCommand(command) returns safe | review | high so users get
the taxonomy from #96 without writing regex tables by hand.
- safe: read-only inspection (ls, cat, grep/rg with a path, git status/log/diff)
- review: context bombs and unknowns (ls -R, find / without -maxdepth,
grep -r / rg -r without scope, tree, du, unrecognised commands)
- high: destructive/sensitive (rm, sudo, curl | bash, dd, mkfs, chmod 777/-R,
git push --force, npm publish)
Compound commands are segmented on shell separators and the highest risk wins;
quoted strings are stripped so patterns inside a string do not match. Convenience
heuristic, not a security boundary. Exported only via
@open-multi-agent/core/classifiers so pattern tables never load unless imported.
Closes#379
The OTel JS ecosystem convention (official instrumentations, @vercel/otel, @prisma/instrumentation) is a peer dependency on the API so the application owns the single copy; npm 7+ auto-installs it. The package also moves off lockstep-with-core onto its own version track starting at 0.1.0, releasing only when it changes; compatibility is expressed by the ^1.10.0 core range.
The root and core files claimed 2025 but the project started in April 2026; the new otel file omitted the contributors wording. Align all three on the year-free form used by projects like React and OpenTelemetry so copies can never carry a wrong year.
Assert the otel tarball ships only dist/, README.md, LICENSE, and package.json with its entry points present, smoke-test the built entry import, and scan core src for @opentelemetry references since workspace hoisting makes the import-based check toothless.
span_event and span_end failures previously surfaced as span_start_failed, and the end path double-reported. Each record type now maps to its own diagnostic and ExportResult code. The default tracer instrumentationVersion moves to a PACKAGE_VERSION constant with a guard test against package.json so releases cannot drift.
Mirror the root README OTel notes into the packages/core EN/ZH READMEs: lead paragraph, dependencies section, dependency table row, and the observability documentation entry.
With a global context manager registered, batched export made root spans inherit whatever application span was active at flush time. Pin span creation to ROOT_CONTEXT and add a regression test.
run a post-release smoke test against create-oma-app and core from the public npm registry
scaffold the recommended PR-review cloud starter and verify both its declared and installed core version match the GitHub Release tag
retry registry propagation with online-preferred resolution, then prove the generated demo reaches the expected missing-key gate
use a fresh project directory per retry so failed attempts cannot contaminate later attempts
- Add an official-links row (Website / Docs / npm / Discussions) under the
title in all four READMEs (root + package, EN + ZH), pointing at
open-multi-agent.com and its docs. The language toggle keeps its own row.
Chinese links resolve to the /zh/ locale.
- Root only: move "How is this different from X?" from right after Get
started to after Ecosystem, and trim it to a two-sentence teaser that
links the full comparison on the package page (it was a verbatim copy).
- Package only: credit four contributors whose PRs merged after the credits
were last refreshed (2026-06-19).
- Package only: add an "External coding agents (ACP)" feature row; note the
run-level metrics rollup on the Observability row.
Docs-only; no source changes.
* feat(agent): orchestrate external coding agents over ACP (#204)
Add an AgentBackend seam so an Agent can run on either the LLM AgentRunner
or an external agent. First backend: an ACP client that drives a coding CLI
(e.g. Claude Code via its ACP adapter) as a first-class team member — same
task DAG, shared memory, cascade, and token budget as LLM agents.
- Extract AgentBackend ({ run, stream }) that AgentRunner already implements;
Agent.getBackend() branches on AgentConfig.backend.
- AcpBackend spawns the agent over stdio JSON-RPC and maps session updates to
a RunResult (text, tool calls, usage); handles permissions and abort.
- ACP SDK as a lazy optional peer; new /acp subpath export.
- docs/external-agents.md, a hybrid-team example, and tests (in-process fake
agent + subprocess integration).
Experimental: ACP is young; token accounting maps ACP's single context
figure and client-side fs proxying is not implemented yet.
* fix(agent): harden ACP backend after review (#204)
Follow-up fixes on the ACP external-agent backend (PR #360):
- Token accounting: usage_update.used is a cumulative context-size gauge, not a
per-turn delta. Record each turn's increment so summing across a reused session
telescopes to the latest figure instead of double-counting.
- systemPrompt: ACP has no system-prompt field, so prepend the agent's systemPrompt
to the session's first turn (once). It was previously dropped and only fed
coordinator routing.
- Abort: when the signal is already aborted before a turn starts, return empty
output without prompting (no in-flight turn to cancel).
- Startup: clear the cached start() promise on failure so a later run retries
instead of re-throwing the same rejection forever.
- Permissions: auto-approve now prefers least-privilege allow_once over a
session-wide allow_always.
Docs (external-agents.md, CLAUDE.md) updated to match. ACP tests 10 to 15;
lint + full suite (1135) green.
Drive Open Design's stdio MCP server from OMA to generate N landing-page
variants in parallel via runTasks(). Each variant's async flow
(create_project, start_run, poll get_run to a terminal status) is handled
by deterministic code, not LLM polling; the worker model only drafts the
design brief. Reference-lane example alongside mcp-github and
mcp-bilig-workpaper, plus its two README index entries.