All notable changes to this project will be documented in this file. The format is based on Keep a Changelog.
- Indexed scope overlap lookups —
ScopeIndexnow uses a compressed radix tree for path-prefix checks and a directory set for sibling-file checks, avoiding a full scan of every indexed pattern during repeated lookups on large scope sets. - Incremental batch indexing — scopes selected during a scheduling tick are added directly to the same index, preserving conflict detection in both parent-to-child and child-to-parent insertion order.
- Removed redundant radix-node state while preserving the existing scope size, duplicate-pattern, empty-prefix, UTF-16 prefix, and sibling-directory semantics.
- Added edge-case coverage for radix splits, surrogate pairs, root files, empty prefixes, duplicate bases, dynamic additions, and both prefix insertion directions.
- Added a real-runtime E2E scenario with filesystem stores, shell child processes, PID locking, concurrent disjoint scopes, serialized overlapping scopes, event output, and persisted run artifacts.
- Full suite: 2091 passed, 2 skipped. Coverage: 71.11% statements, 63.94% branches, 71.07% functions, and 73.43% lines.
- Pi terminal failure handling (#19) — rate limits, timeouts, aborted responses, rejected prompt commands, and stdout transport failures now finish through the orchestrator failure path instead of completing assigned tasks.
- Pi retry-aware completion — current Pi RPC sessions wait for
agent_settled, allowing automatic retries and queued continuations to finish before ORCH emits the single terminal success or failure event; older Pi versions keep theiragent_endcompatibility path.
- Added Pi adapter regression coverage for provider failures, exhausted retries, successful automatic recovery, rejected prompt commands, and broken stdout streams.
- Added an orchestrator integration scenario proving a rate-limited Pi run transitions its task to
failed, records the run error, releases the agent, and never reachesdone. - Full suite: 2082 passed, 2 skipped. Coverage: 69.99% statements, 63.55% branches, 69.71% functions, and 72.22% lines.
- Light TUI palette — a high-contrast palette for terminals with light backgrounds. Select it through
/config palette, or persist it before launching the dashboard withorch config global set palette light.
- Readable light-palette tabs — active and flashing header tabs use a semantic solid-fill foreground, keeping text above the WCAG AA 4.5:1 contrast threshold on every saturated light-palette status color.
- Stable palette transitions — light-palette gray and ghost tokens remain distinct, so live color remapping preserves their intended semantic colors when switching palettes.
- Updated
js-yaml,liquidjs, Vitest, Vite, esbuild, and tsx to patched releases. The complete production and development dependency graph now passesnpm auditwith verified registry signatures.
- Added contrast and palette-remapping regression coverage.
- Verified the production CLI in a real pseudo-terminal, including persisted light-palette loading, emitted ANSI colors, activity filtering, and clean shutdown.
- Full suite: 2078 passed, 2 skipped. Coverage: 69.72% statements, 63.37% branches, 69.64% functions, and 71.94% lines.
- First-class Shell agents — create and edit command-backed agents from the CLI, editor, and TUI. Shell agents run their configured command from the task workspace and map exit code
0to success and non-zero exits to failure. - Simplified Shell setup — selecting Shell asks only for the agent name and command, hides model, reasoning, role, skills, and team fields, and applies the automatic approval policy.
- Command-aware TUI — creation confirmations and agent details show the configured command, while Shell agent details prioritize the active task and command over AI-only model information.
- Reliable targeted run completion —
orch run <task-id>keeps its event listener until the requested run completes, preserving final output and returning a non-zero process exit code when the Shell command fails. - Immediate wizard confirmation — text and textarea validation is checked against the current value when the user confirms, eliminating stale debounce errors without allowing invalid values through.
- Safe adapter transitions — switching an existing agent to Shell clears incompatible model and effort settings, requires a command, and defaults approval to automatic.
- Centralized repeated Shell conditions and agent-creation status formatting without changing behavior.
- Added service, CLI, adapter, wizard, command-bar, and TUI regression coverage for Shell creation, editing, validation, execution, success, and failure.
- Verified the built CLI in a real pseudo-terminal TUI session.
- Full suite: 2069 passed, 2 skipped.
- Readable Codex activity text — Codex agent messages, commands, file changes, tool calls, and web searches are normalized before reaching the TUI, while provider lifecycle and reasoning noise is omitted.
- Concise provider errors — nested JSON error envelopes are reduced to their human-facing message, repeated
turn.failedcopies are suppressed per run, and recoverable model-metadata fallback notices no longer appear as failures. - Historical run compatibility — existing Codex JSONL history receives the same text, tool, lifecycle, warning, and error formatting as newly streamed events.
- Isolated PTY configuration — real terminal tests use a temporary global TUI config and never overwrite
~/.orchestry/global.yml.
- Added a real pseudo-terminal E2E that launches the built CLI and verifies
ALL → TEXT → TOOLS → ERRORS, visible Codex content, lifecycle filtering, readable errors, deduplication, and clean shutdown. - Stabilized the concurrent disk-observer assertion.
- Full suite: 2044 passed, 2 skipped.
- Global TUI color palettes — choose Amber, Ocean, Forest, or Violet through
/config palette. The selected palette is applied across the dashboard and saved in the global~/.orchestry/config.yml. - Independent TUI settings —
/configsettings now open individually instead of forcing users through a multi-step setup wizard. Palette, activity filter, concurrency, toast, and bell preferences can be changed separately. - Live model catalogs for every adapter — agent create/edit wizards load models from the installed Claude, Codex, Cursor, OpenCode, Pi, Grok, and Antigravity CLIs; Shell exposes an explicit no-model default.
- Searchable model selection — the model field filters large live catalogs while still accepting custom provider/model IDs.
- Existing agent provider changes — switching an agent to another adapter clears the previous adapter's model before showing the new catalog.
- Live wizard refresh — model suggestions update even when discovery finishes after the agent wizard is already open.
- Edited agent refresh — agent cards now detect adapter/model changes even though agent records do not carry
updated_at. - Agent Shop compatibility — templates choose a model that is actually present in the selected adapter's live catalog and otherwise fall back safely.
- English command categories — removed the remaining Russian management, monitoring, and settings headings from TUI command help.
- Palette context — palette-aware components consume one shared context instead of threading palette props through the component tree.
- Model discovery command path — shared CLI execution, stdout/stderr selection, default insertion, and parser dispatch are centralized without changing adapter fallback behavior.
- Wizard model fallback — simplified adapter lookup while preserving a neutral fallback for custom adapters.
- Added runtime parser, streamed-catalog, open-wizard refresh, searchable selection, existing-agent default, and timestamp-less agent refresh regression coverage.
- Verified all eight adapter model screens in real PTY TUI sessions.
- Full suite: 2034 passed, 2 skipped.
- Cursor print-mode prompt transport (#14) — Cursor now receives the assembled ORCH prompt as its required positional argument, trusts fresh ORCH worktrees non-interactively, and no longer opens stdin for a prompt the CLI will not read.
- Cursor token usage compatibility — result events from current Cursor releases use camelCase usage fields; the shared extractor now accepts both camelCase and the existing snake_case provider schema.
- Adapter stderr diagnostics — shared streaming adapters continuously drain stderr, retain a bounded 4 KB tail, and include it in spawn/non-zero-exit errors. Process lifecycle listeners are installed eagerly so immediate CLI failures cannot be missed before event collection starts.
- Added regression coverage for Cursor argument construction, positional system/user prompts, ignored stdin, stderr propagation, immediate process exits, and bounded stderr capture.
- Simplified shared token-usage alias lookup without changing snake_case or camelCase compatibility.
- Editable agent provider in TUI — the agent edit flow now includes a
Providerselector, so existing agents can move between adapters without recreating them. - Adapter-aware edit options — model choices refresh from the selected provider, and reasoning effort is shown only for adapters that support it.
- Agent edit persistence — adapter changes now flow through the TUI update handler into
AgentService.update, with validation for empty adapter values. - Model and effort clearing — edit submissions can clear stale model or reasoning-effort values when switching to adapters where those fields should no longer apply.
- Agent update adapter handling — adapter normalization now trims once before validation and persistence.
- Added AgentService coverage for adapter updates, adapter validation, and clearing model values.
- Extended TUI wizard coverage for editing adapter/model/effort combinations.
- Grok adapter — first-class
grokadapter backed by the Grok CLI. Supports headless execution, model selection, reasoning effort, max turns, system prompt override, tool/error event mapping, streaming text aggregation,doctor,init, TUI wizard, model tiers, docs, landing assets, and smoke/e2e coverage. - Antigravity adapter — first-class
antigravityadapter backed by Google Antigravity CLI (agy). Supports headless prompt execution, model selection, permission bypass for autonomous runs, stdout streaming,doctor,init, TUI wizard, model tiers, docs, landing assets, and smoke/e2e coverage. - Runtime model discovery in TUI — model choices now load from adapter CLIs where available (
grok models,agy models,opencode models,pi --list-models) with curated fallbacks for unavailable or non-listing CLIs. Agent creation, edit flows, and Agent Shop templates all use the same model catalog path.
- Targeted
orch run <task-id>no longer dispatches unrelated todo tasks — running a specific task now keeps ownership of that request instead of reactive-dispatching other queued tasks after the requested task completes.
- Model catalog source of truth — moved TUI model fallback options out of wizard config into
src/infrastructure/models/model-discovery.ts, so adapter model lists are centralized and guarded byAdapterKind. - Adapter type safety — model option lookup now uses the existing
isAdapterKindguard instead of string casts.
- Added unit coverage for Grok and Antigravity adapters.
- Added integration coverage for the new adapters.
- Added model discovery parser and TUI wizard catalog tests.
- Extended model tier, onboarding, and smoke coverage for
grokandantigravity.
- TUI task wizard: reliable textarea confirmation fallback (#13) —
Tabnow confirms everyFormWizardstep, including multilineDescriptionfields. This keepsEnteravailable for textarea newlines while giving Windows, WSL, CMD, PowerShell, Git Bash, and terminals without reliableCtrl+Entersupport a deterministic way to finish the step. - Wizard hints updated for the new shortcut — text/select/multiselect steps now show
Enter/Tab confirm; textarea steps show⌘+Enter/Tab confirmon macOS andCtrl+Enter/Tab confirmelsewhere.
- Added component coverage for
Tabconfirmation in text, textarea, required textarea, and multiselect steps. - Added App-level coverage for creating a task with a textarea description confirmed by
Tab. - Verified the fix manually in a real terminal PTY: task creation persisted the description after
Tabconfirmation.
- Canonical
AgentEvent.datacontract — documented per-type data shapes insrc/infrastructure/adapters/interface.ts. Each adapter now has a single target shape foroutput({text}),tool_call({name,input}),command({command,result}),file_change({paths}),error({message}) anddone({result}). Downstream consumers (TUI,orch logs,servedaemon) can render events without knowing adapter internals. Legacy adapters (claude/cursor/codex) still emit their native shapes during the migration window — the TUI renderer is defensive.
- Pi adapter: per-character text_delta flood — pi RPC emits one
text_deltaper LLM stream chunk (often per-character). The adapter was forwarding each as its ownoutputevent, drowning the activity feed with character-level fragments. Now deltas aggregate into adapter-local state and the assembled text is flushed once ontext_endas a single canonicaloutputevent. - Pi adapter:
[agent_start]/[turn_start]placeholders in logs — unknown pi RPC event types fell through adefaultcase that emitted them as rawoutputevents. The TUI renderer then displayed them as[type_name]placeholders. Unknown types are now dropped at the adapter boundary; adding a new known type is the right way to surface a new event. - Pi adapter:
tool_execution_updatenoise — pi emits one of these per chunk of streaming tool output (e.g. live bash stdout). No other adapter surfaces intermediate tool progress in its event stream. These are now dropped to keep the canonical contract uniform. - Pi adapter:
finalTextbuffer never reset aftertext_end—state.finalTextwas set to the assembled text aftertext_endbut never cleared. A follow-up assistant turn in the same pi session would build on top of the previous message, double-emitting text and growing the buffer unboundedly across turns. Buffer now resets to''after eachtext_end. - Pi adapter: API error inside
agent_end.messages[]ignored (partial) — error event payloads now use canonical{message, raw}shape and are classified viaclassifyAdapterError. (Surfacing pi'serrorMessagefield nested inside the assistant message remains a follow-up.)
firstLineTruncfast path — single-line input (the common case for agent events) short-circuits to a singleslice(0, n), skippingsplit('\n')+find+ closure allocation. The slow path uses/\S/.test(l)instead ofl.trim().length > 0to avoid allocating a trimmed copy just to test non-empty.summarizeToolResultsingle split — was splittingcontenttwice (once forlines.length, once forfind); now reuses one array.
extractToolResultTextdelegates toextractTextFromContent— pi tool results ({content: [{type:'text', text}, …]}) and pi message content ({content: [{text}, …]}) differ only by the outercontentwrap. Collapsed 16 lines of duplicated walk-and-join logic to a single line that unwraps and delegates.firstLineTrunchelper extracted inApp.tsx— replaces five copies ofs.split('\n')[0]?.slice(0, N) ?? s.slice(0, N)(including a dead??fallback and incorrect handling of leading blank lines) across the new canonical-shape branches informatAgentOutput.- Summary icons aligned with
MSG_ICONS— error glyph in canonical branch corrected from✗(U+2717) toMSG_ICONS.error(✕, U+2715); path glyph usesMSG_ICONS.filefor consistency.
- Pi adapter contract tests updated —
aggregates text_delta updates and emits one canonical output on text_endreplaces the old per-delta assertion. New testdrops tool_execution_update progress events (noise)locks in the noise-drop behavior. pi-adapter.e2e.test.ts— feedstext_delta+text_delta+text_endsequence to exercise the aggregation path end-to-end through the Orchestrator.
- Pi RPC adapter (#12) — sixth first-class adapter. Wraps
pi --mode rpc(@mariozechner/pi-coding-agent) and exposes its JSONL event stream through the orchestrator'sAgentEventcontract. Supports Pi's full provider matrix (OpenRouter, Anthropic, OpenAI Codex, Gemini, …) via the--model "<provider>/<model>"convention. Registered ininitadapter detection,doctor, agent shop, TUI wizard models (PI_MODELS), andEFFORT_ADAPTERS. Agents-tab onboarding tip now lists all six adapters; a regression test asserts it stays in sync withSUPPORTED_ADAPTERS.
- Pi stream: abort/kill cleanup — when the generator exits without a terminal
doneevent (abort signal or stream error) the adapter now schedulesprocessManager.killWithGrace(pid, 1000)from thefinallyblock. The long-lived pi process is no longer pinned alive by dangling'close'/'error'listeners. - Pi stream: unhandled error before first line — the stdout
for awaitis wrapped intry/catch. Stream errors arriving before the first JSONL line (ECONNRESET, EPIPE, immediate crashes) are now classified viaclassifyAdapterErrorand yielded as anerrorAgentEventinstead of escaping as an unhandled rejection. - Pi stream: silent stderr —
proc.stderr.resume()(which drained but dropped data) is replaced bycreateStderrTailCapture(), retaining the last 4 KB of stderr. Auth and extension-load failures now surface in the error message on non-zero exit. - Dead branch in
extractPassiveUpdate— both arms ofstate.finalText ? null : nullreturnednull; simplified to a singlereturn tokens ? { tokens } : null. The unusedParseStateargument is dropped. Buffer<ArrayBufferLike>generic — replaced with plainBuffer | nullso the line reader compiles cleanly on the^20.17.0floor of@types/node(the generic only landed in@types/node22+).as anyin test mock —pi-adapter.test.tscasts the mock child process throughunknown as ChildProcess. CLAUDE.md forbidsas any.
readPiRpcLines: O(n²) → O(n) — replaced per-chunkBuffer.concat([pending, buf])(which copied the full accumulator each time) with thechunks[] + totalLen + offsetpattern already used byreadLines()inprocess-manager.ts. Concat once per chunk arrival, scan with an offset, subarray the remainder.createStderrTailCapture: drop array-shift on overflow — keeps a single backingBufferand slices viaBuffer.from(buf.subarray(buf.length - LIMIT))when oversized.Buffer.frommaterializes an exactly-sized copy so a single 64 KB stderr burst no longer pins the largerArrayBufferalive until GC.- Token alias lookup collapsed — the eight
??chains forcacheRead/cache_read_input_tokens/etc. became a singlePI_TOKEN_ALIASESmap with onepick(keys)helper. Same wire-compatibility, far fewer lines.
src/tui/onboarding-config.ts— extractedONBOARDING_GOALS,ONBOARDING_TASKS,ONBOARDING_AGENTSout ofApp.tsx. The app and the regression test both import from the new module;App.tsxno longer needs to export internal constants for test access.
- 260 new tests (1694 → 1954):
test/unit/infrastructure/pi-adapter.test.ts(20 tests) — adapter contract: arg list, prompt JSONL write, parsing of every Pi RPC event type (extension_ui_request,message_update.text_delta,tool_execution_start,tool_execution_endforbash/write/edit, largeagent_end,responsefailure), stderr tail surfacing, abort-signal kill.test/integration/pi-adapter.e2e.test.ts— full lifecycle through the real Orchestrator with a mocked spawn: dispatch → JSONL stream → state machine transitionstodo → in_progress → review → done→ tokens persisted on the Run → process termination viakillWithGrace.test/integration/pi-tui.e2e.test.tsx— same lifecycle through the Ink/React TUI viaink-testing-library: pi agent + adapter chip on the Agents tab, activity feed showstext_delta/tool_call/file_changed/ done.test/unit/tui/onboarding-agents.test.ts— invariant that everySUPPORTED_ADAPTERSentry appears in the Agents-tab onboarding description.- Parametrized rows for
piinagent-factory.test.ts(model resolution + MCP-skill filtering),commands-init.test.ts(getDefaultAgents('pi')), andwizard-effort.test.ts(EFFORT_ADAPTERSmembership).
- Unified text input system — replaced three separate text input implementations (FormWizard text-step, InputPanel, command-bar) with a shared architecture inspired by Claude Code:
text-cursor.ts— immutableCursorclass with NFC normalization andIntl.Segmenter-based grapheme navigation (CJK, emoji, Cyrillic, combining marks)hooks/useTextInput.ts— keyboard logic hook with undo stack (Ctrl+Z / Cmd+Z), kill ring (Ctrl+K/U/W/Y), word navigation (Option+Left/Right), and all terminal editing shortcutscomponents/TextInput.tsx— display component with sliding viewport that keeps cursor visible on text overflow
- Cursor jumping on keyboard language switch — NFC normalization in Cursor constructor prevents position drift when IME sends NFD-encoded characters during layout switching
- Text overflow at screen edge — single-line text inputs now use a sliding viewport instead of truncating from the end, keeping the cursor always visible
- Undo stack over-drain — debounced undo snapshots captured current state, causing Ctrl+Z to pop identical text with no visible effect; fixed by skipping one matching snapshot before applying undo
- React anti-pattern in textarea —
setTaCursorColwas called inside asetTaLinesupdater function; moved out to prevent potential double-fire in concurrent mode - Timer leak on unmount — undo debounce timer is now cleared via
useEffectcleanup when the component unmounts mid-debounce
- Zero-cost cursor navigation — arrow keys, Home/End, word navigation reuse existing grapheme segments via
Cursor._withPos()factory instead of re-runningIntl.Segmenteron unchanged text - Single-pass insert —
Cursor.insert()usesgraphemeSegments()once instead ofgraphemeLength()+ constructor re-segmentation - Render-path optimization —
TextInputreadscursor.beforeSegs/cursor.afterSegsdirectly, avoiding join + re-segmentation on every render
- Editing shortcuts — Ctrl+A/E (start/end), Ctrl+K/U/W (kill operations), Ctrl+Y (yank), Ctrl+Z / Cmd+Z (undo), Cmd+Backspace (kill to start), Ctrl+B/F (left/right), Ctrl+D (delete forward), Ctrl+H (backspace), Home/End keys
- 96 new tests (1829 → 1923):
text-cursor.test.ts(61 tests) — grapheme segmentation, NFC normalization, CJK/emoji/Cyrillic handling, cursor navigation, editing, kill operations, display widthtext-input.test.tsx(33 tests) — E2E via ink-testing-library: FormWizard text-step input/submit, cursor navigation, backspace, all Ctrl shortcuts, Cyrillic/emoji/CJK input, undo, step transitions, validation
- Parallel runs race condition (#8) — when multiple agents completed in parallel via
orch serve, successful runs were falsely marked asfailed. Root cause: reconcile detected dead PIDs beforehandleRunSuccessacquired the mutex, treating clean exits as crashes. Fix:activeCollectorsguard prevents reconcile from interfering with tasks that have an active event collector. Also fixes orphaned runs stuck instatus: runningwhen the running entry was already cleaned up - Assignee name resolution (#7) — tasks assigned by agent name (e.g.
--assignee "Sam Altman") instead of agent ID were silently accepted but never dispatched.TaskService.resolveAssignee()now normalizes agent names to IDs at creation and assignment time, with clear error messages for unknown agents.findBestAgent()also matches by name as a fallback for legacy data
- 15 new tests: activeCollectors guard (reconcile skip, crash detection, cleanup, orphaned run finalization), assignee name→ID resolution (create, assign, unknown name/ID, backward compatibility, findBestAgent name fallback)
- Goal completion deadlock — agents could not mark their own goal as
achievedbecause the agent's running[auto]task blocked the pending-tasks guard. Autonomous tasks are now excluded from the check since they are the mechanism for achieving the goal, not a blocker paused → achievedtransition — goals inpausedstate can now be directly marked asachievedwithout requiring a resume first. State machine updated:paused → active | achieved | abandoned- TUI force-complete — pressing
Con a goal in TUI now usesforce: trueto cancel cancellable pending tasks, with an informative status message. Previously it would silently fail if any non-terminal tasks existed
- 4 new tests: autonomous task exclusion from pending check, non-auto task still blocks,
paused → achievedwith side effects,paused → achievedwith force + pending tasks
- Retry dispatch race condition — fixed a race where a task could be re-dispatched from the retry queue after it had already succeeded.
dispatchTask()now checksisDispatchable(task.status)before spawning, retry queue processing validates task status before dispatch, and_handleRunFailureskips if the running entry was already cleaned up by the success handler. This prevents zombie processes, falsetasks_failedstats, and orphanedpreparingruns - GitHub star count on landing page — navbar and CTA now show live star count fetched from GitHub API
- 5 new tests covering retry race condition guards (dispatch of done/cancelled/failed tasks, retry queue skip, failure handler race)
- Adapter-agnostic onboarding (#6) —
orch initnow auto-detects installed AI adapters (claude, opencode, codex, cursor) and lets you choose a default. Agent shop templates use semantic tiers (balanced,capable,fast) instead of hardcoded Claude model names, so agents are created with the correct model for your chosen adapter. Pass--adapter <name>to skip detection - Goal completion guard — goals can no longer be marked
achievedwhile linked tasks are still pending (todo,in_progress,retrying,review). Agents callingorch goal status <id> achievedwill see a clear error listing the blocking tasks. Use--forceto cancel pending tasks and force the transition (skipsin_progresstasks with live processes)
- MCP skills filtered for non-Claude adapters — agent shop templates and TUI wizard now strip MCP skills (colon-format like
testing-suite:generate-tests) when the default adapter is not Claude, since MCP skills only work with the Claude CLI - Cursor agent probe false-positive —
orch initadapter detection no longer probes the genericagentbinary (too common on systems), onlycursor-agent - TUI refresh after status change — fixed a race condition where
entityListChanged()compared tasks byupdated_attimestamp, causing refresh no-ops when initial and updated tasks had identical timestamps
- 32 new tests: goal pending-tasks validation (10), model tier resolution (8), agent factory (5), adapter-agnostic init (4), MCP skill filtering (3), TUI refresh fix (2)
- TUI: external tasks and goals now appear immediately — when tasks or goals are created by external processes (
orch task add,orch goal add, Claude Code/orchskill), the TUI now picks them up within 5 seconds. Previously, in watch mode the TUI only refreshed on in-process EventBus events, so externally created entities were invisible until the orchestrator dispatched them - Proof detection for Claude agents — Claude adapter emits
tool_useevents (Write, Edit, MultiEdit, NotebookEdit) but nofile_changeevents. The orchestrator now extracts file paths from tool_call data and populatesproof.files_changed, fixing empty proof for all Claude-backed agents. Also emits real-timeagent:file_changedevents for TUI visibility - Orphaned preparing runs — runs stuck in
preparingstatus (caused by a crash betweenrunService.create()andrunService.start()) are now detected and cancelled at startup. Previously these ghost runs stayed inpreparingforever and appeared inorch logsas unfinished orch logs --sincewithout filter —orch logs --since 3hnow works without requiring--task,--agent, or a run ID. Shows all recent runs within the time window with a truncation notice when >20 runs match- Per-agent stall timeout — reconcile now uses the agent's
config.stall_timeout_mswhen set, falling back to the global default. Previously all agents were killed at the global 10-minute mark regardless of per-agent configuration
- Parallel agent pre-fetch in reconcile — agent data is now fetched in parallel alongside task data during the reconcile phase, avoiding sequential reads
- No-op render guard — periodic disk poll now skips React state updates when entity data hasn't changed, preventing unnecessary re-renders every 5 seconds in idle state
- 14 new tests covering all four bug fixes: proof detection from tool_call events (3), orphaned preparing runs cleanup (3),
orch logs --sinceall-runs mode (6), per-agent stall timeout (2) - Shared
cleanupOrchhelper extracted totest/unit/application/helpers.ts(was duplicated 6×) - Added missing
listAlltocreateMockRunStoremock
- Reasoning effort setting — new
effortfield for agents (low,medium,high) controls how deeply the model reasons. Available via CLI (--effort), TUI wizard (step after model selection with descriptions), and programmatic API. Currently supported by the Claude adapter only - TUI effort step — interactive wizard shows the effort selector right after model choice, with hints for each level. Automatically skipped for adapters that don't support it
- Claude CLI flag name — fixed
--reasoning-effort→--effortto match the actual Claude CLI flag. Previously caused agents with effort set to crash with exit code 1 - Codex effort removed — Codex CLI does not support
--reasoning-effort; removed the flag to prevent spawn failures
- ORCH skill updated — added
--effortto CLI reference, usage tips for effort levels, and new "When to Use Goals vs Tasks" section with concrete criteria and examples (single action → Task, multi-step decomposition → Goal, iterative metric-driven improvement → Goal)
- 23 new tests covering effort across all layers: domain model, agent service (create/update), Claude adapter (
--effortflag), TUI wizard (step visibility, skip logic, input mapping, edit pre-fill)
- TUI Observer Mode — when another process holds the orchestrator lock (
orch run --watch,orch serve, or theorchskill in Claude Code), the TUI now enters OBSERVING mode instead of showing a dead IDLE screen. The newDiskObserverpollsstate.jsonand tails run JSONL files to deliver the same real-time activity stream as the in-process orchestrator - Full cross-process event visibility — observer mode shows agent output, file changes, errors, tool calls, lifecycle events (started/completed), task status transitions, and orchestrator ticks — identical to the native TUI experience
- OBSERVING header badge — amber
● OBSERVINGchip replaces the red error message, clearly indicating the TUI is connected to an external orchestrator
- DiskObserver JSONL tailing silent failure —
state.runningkeys are taskIds, not runIds. DiskObserver was using keys as JSONL file paths, causing ENOENT on every read (silently caught). Observer mode showed only tick events. Fixed to useentry.run_id
- Byte-offset JSONL tailing — DiskObserver tracks per-run byte offsets with partial-line buffering, reading only new bytes each tick. Handles mid-line splits across poll boundaries correctly
- Concurrent poll guard — prevents race conditions when a poll tick takes longer than the poll interval
- Stale-refresh dedup — periodic state refresh in observer mode skips if an event-driven refresh already ran recently, avoiding redundant disk reads
- Remainder cap — partial JSONL line buffer is capped at 64KB to prevent unbounded memory growth on stalled writes
- 15 new tests: 11 unit tests for DiskObserver (event translation, byte offsets, partial lines, error handling, unsubscribe), 4 integration tests (full lifecycle, failed runs, concurrent runs, orchestrator restart detection)
- Battle test script simulating real cross-process orchestration with 5 runs and 44 events
- Background auto-install — when a new version is detected, ORCH automatically downloads and installs it via
npm install -gin the background. No restart is forced — the user continues working undisturbed - TUI restart prompt — header chip changes from
UPDATE 1.0.11tov1.0.11 INSTALLED — RESTART TO APPLYafter background install completes - CLI auto-install — after printing update notification, CLI commands trigger background install so the next launch uses the new version
- Serve auto-install — headless daemon auto-installs and logs
update:installedevent for operators
- Install dedup — marker file (
~/.orchestry/update-installed.json) prevents re-installing the same version within the 4-hour check cycle - Reliable install completion — removed
child.unref()from install process so short-lived CLI commands don't exit before npm finishes
- Worktree collision on retry —
prepareWorktree()is now idempotent: reuses existing worktree directory on retry, falls back togit worktree addwithout-bwhen branch already exists, runsgit worktree pruneonly on the fallback path. Eliminatesgit worktree add failed with code 255errors - proof.files_changed always empty for Claude adapter — added
getChangedFiles()to WorkspaceManager that usesgit merge-base+git diff --name-onlyas fallback when the adapter doesn't emitfile_changeevents. Works with any trunk branch name (no hardcodedmain) orch run --watchexits after first tick — added missingawait orchestrator.waitForStop()so the process stays alive for continuous orchestration--verboseflag missing onorch run— added--verboseoption; agent output is suppressed by default in watch mode (consistent withorch serve)- Auto-goal creation spam — autonomous agents are now forbidden from creating new goals via system prompt constraints; 30-second cooldown between auto-seed tasks per agent prevents rapid re-seeding
task:cascade_failedevent not handled — added to TUI activity feed (red error message) and structured logger (warn-level entry)
- WorkspaceManager refactored —
spawnAndWait()andspawnAndCapture()helpers replace all inline promise-wrapping;requireGitRepo()andcleanup()simplified;prepareIsolated()uses absolute path instead of cwd-relative'.' - Cascade-fail cache consistency — both call sites (dispatch + collect) now invalidate task cache before cascade to ensure fresh data
- WorkspaceError retry — workspace errors no longer force-fail tasks on first attempt. Now respects
max_attemptswith exponential backoff via retry queue, matching the behavior of agent execution failures - Cascade-fail dependent tasks — when a task permanently fails (max_attempts exhausted), all direct and transitive dependents are automatically failed with
task:cascade_failedevent. Prevents dependent tasks from hanging as TODO forever - Update notifications — cold start —
checkForUpdateSWR()now awaits the npm fetch on first run (up to 5s) instead of returning null. Users see the update notification on their very first command, not the second - Update notifications — TUI re-check — if initial update check returned null, TUI retries after 5 seconds via
onCheckUpdatecallback and updates the header chip dynamically - Update notifications — orch serve — added background update check at startup with structured logger output (
update:availablewarning), so server operators see updates in JSON/text logs - Postinstall test — fixed test referencing
postinstall.jsinstead ofpostinstall.cjs
- Cascade-fail algorithm — uses reverse-dependency index (
Map<parentId, Task[]>) for O(1) lookup per BFS node instead of O(n) linear scan; parallelPromise.allsaves instead of sequential; no in-memory mutation of shared task objects - CLAUDE.md — added Skill Library and Serve Mode architecture sections
- Skill Library — 26 expert methodology skills adapted from gstack, stored as Markdown files in
skills/library/. Skills are automatically loaded and injected into agent system prompts at dispatch time. Works with all adapters (claude, opencode, codex, cursor, shell) - Two skill types — library skills (plain names like
review,investigate) inject content into prompts; MCP skills (colon-separated likefeature-dev:code-explorer) are handled natively by Claude CLI - SkillLoader — new infrastructure component with process-lifetime cache, parallel reads via
Promise.all, path traversal prevention, and lazy async directory resolution
| Category | Skills |
|---|---|
| Code Review & QA | review, qa, qa-only, investigate, careful, guard |
| Planning | plan-ceo-review, plan-eng-review, plan-design-review, autoplan, office-hours |
| Design | design-consultation, design-review |
| Shipping | ship, land-and-deploy, canary, document-release |
| Infrastructure | browse, benchmark, setup-deploy, setup-browser-cookies |
| Safety | careful, freeze, unfreeze, guard |
| Cross-AI | codex |
| Meta | upgrade, retro |
- Agent Shop upgraded — all 15 agent templates now include library skills with updated role prompts referencing skill methodologies (review, investigate, benchmark, ship, etc.)
- Agent Creator updated — knows full skill catalog with library vs MCP distinction, guides auto-created agents to use appropriate skills
/orchskill documentation — expanded with complete Skill Library section listing all 26 library skills and 13 MCP skills- Programmatic API —
ISkillLoaderandSkillLoaderexported from@oxgeneral/orchfor library consumers
- 21 new tests: SkillLoader unit tests (14), orchestrator skill injection (13), agent shop skill validation (8)
- Claude Code
/orchskill — afternpm install, the/orchslash command is automatically registered in Claude Code. Describe what you need in natural language and Claude translates it into the rightorchCLI commands - Postinstall auto-registration — skill file is copied to
~/.claude/skills/orch/during install with change detection (only writes when content differs)
- Postinstall script — renamed to
.cjsfor ESM package compatibility, hoisted requires to module scope, removed TOCTOU patterns
- Worktree branch cleanup —
git branch -Dnow runs on worktree cleanup, preventingcode 255errors on task retry (BUG-1) - Stale claimed recovery —
state.claimedis cleared on orchestrator restart so tasks are no longer stuck after crash (BUG-2, BUG-7) - Stall timeout default — increased from 5 min to 10 min to reduce false failures on complex prompts (BUG-3)
orch servelogging — fixed premature logger unsubscribe that caused silence after first tick; addedwaitForStop()lifecycle method (BUG-4)- Worktree error handling —
prepareWorktree()now throwsWorkspaceErrorso tasks are properly force-failed instead of silently stuck (BUG-5) - Stale lock detection — lock file mtime is touched every tick;
acquireLock()treats untouched locks (>60s) as stale even if PID is recycled (BUG-6)
- Parallel cleanup —
git branch -Dandfs.rmnow run concurrently viaPromise.allduring worktree cleanup - Lock heartbeat —
touchLock()usesDate.now() / 1000instead ofnew Date()to avoid per-tick heap allocation
orch serve— headless daemon mode — run the orchestrator as a background process for 24/7 operation on servers. Compatible with pm2 and systemd- Structured JSON logging to stdout (machine-parseable for Datadog, Grafana Loki,
jq) --log-format textfor human-readable output--oncemode for CI/CD — process all todo tasks and exit (exit 0 = all done, exit 1 = failures)--log-file <path>— tee logs to file in addition to stdout--verbose— include high-frequencyagent:outputevents (off by default)--tick-interval <ms>— override polling interval- Heap memory monitoring in tick events for 24/7 stability tracking
- Idle tick throttling — logs every 6th idle tick to reduce noise
- Graceful shutdown on SIGINT/SIGTERM — waits for running agents, saves state, releases lock
- Lock conflict detection — clear error when another orchestrator is already running
- Structured JSON logging to stdout (machine-parseable for Datadog, Grafana Loki,
StructuredLoggerclass (src/cli/serve/structured-logger.ts) — transformsOrchestratorEventunion into flat JSON/text log recordsrunOnce()function (src/cli/serve/once-runner.ts) — polls for task completion with orchestrator shutdown safetystartWatch()now accepts{ skipAutonomousSeeding }option — keeps CLI concerns out of the orchestrator
- Restart safety — orphaned tasks on restart are now cancelled instead of retried, preventing agents from re-executing already committed work
- FTUE parent leak —
orchin a new folder no longer picks up a parent directory's.orchestry/project - Activity feed — history now loads correctly on startup (sort by recency, filter cancelled runs, log errors instead of silently swallowing)
- Reasoning & cache token tracking —
TokenUsagenow tracksreasoning,cache_read,cache_writeseparately. Reasoning included in total; cache tokens are informational (subset of input). TUI shows 🧠 when reasoning > 0 - Daemon mode architecture — design doc for sub-10ms CLI responses via persistent background process
- IndexManager — extracted generic
IndexManager<T>with_index.jsoncache for all stores (TaskStore, AgentStore, ContextStore, GoalStore, MessageStore). List operations read one file instead of N - Parallel container init —
requireInit()+configStore.read()run in parallel during CLI startup - Buffered CLI output —
printTable/printKeyValuebuffer into singleprocess.stdout.writecall - Orchestrator tick — parallel reconcile checks,
findProjectRootcaching, lazy globalConfig + editor loading - Lazy requireInit — removed redundant
requireInit()calls in read-only commands
- IndexManager mutex — promise-chain mutex prevents TOCTOU race on concurrent index reads/writes
- Re-entrant deadlock —
rebuildIndexno longer deadlocks when called within an existing lock - Token simplification — use
createTokenUsagesingle source of truth,TokenUsagetype instead of inline duplicates,useMemofor TUI header tokens
- 3 new org templates —
sales-machine(Sales Director, SDR x2, Copywriter, Growth Analyst),bugfix-dept(Triager, Fixer x3, QA, Reviewer),docs-team(Docs Lead, Writer x2, Editor, Reviewer)
- README sync — agent descriptions in README now match actual code for
security-dept,test-factory,data-lab,sales-machine - Org template count test — tightened from
>= 7to exacttoBe(10)
First stable release. Production-ready CLI orchestrator for AI agent teams.
- 5 adapter ecosystem — Claude, OpenCode, Codex, Cursor, Shell — mix any AI providers in one team
- 1493 tests — comprehensive coverage across all layers
- Real-time TUI dashboard — tasks, agents, goals, activity feed, logs with filtering
- Smart prompt architecture — system/user split for caching, relevance-based context filtering
- Zero-config start —
npm i -g @oxgeneral/orch && orchauto-initializes
- OpenCode adapter — new
opencodeadapter for multi-provider agent support via OpenCode CLI (OpenRouter, DeepSeek, Gemini, etc.). JSONL event streaming with--format json, model pass-through asprovider/model - System/User prompt split — separate static system prompt (agent identity, rules) from dynamic user prompt (task details) for Claude API prompt caching (~40-60% fewer input tokens on repeat runs)
- Agent picker [adapter] tags — assignee lists in TUI now show
[claude],[opencode],[codex]etc. next to each agent for provider visibility - OpenCode model catalog — TUI wizard offers Default (use opencode config), Claude, Gemini, DeepSeek, and Big Pickle models when creating opencode agents
- OpenCode tool display — tool_call events from opencode now render as
⚙ grep(pattern: "...")instead of raw JSON in TUI logs - step_finish noise — intermediate
step_finishlifecycle events no longer pollute activity feed
- Context value truncation (500 char cap) — silently lost agent context
- Agent role truncation (80 char / first line) — agents couldn't see teammates' capabilities
- Goal task names cap (30 entries) — agents lost goal progress visibility
- Retry output tail reads (50 lines) — agents lost failure chain context
Design principle: token optimizations must not silently lose data that agents need. Filtering by relevance is OK; hard truncation is not.
- Parallel agent execution with configurable concurrency (
max_concurrent_agents) - State machine:
todo → in_progress → review → donewithretryingandfailedbranches - Automatic retry with exponential backoff, stall detection, zombie process cleanup
- Priority-based dispatch (P1-first, goal-linked tasks prioritized)
- Scope-based file conflict prevention (
--scope,--depends-on) - Task dependencies with topological ordering
- Claude — Claude Code CLI with
--system-promptfor prompt caching - OpenCode — OpenCode CLI with multi-provider support (OpenRouter, DeepSeek, Gemini)
- Codex — OpenAI Codex CLI with stdin prompt delivery
- Cursor — Cursor Agent CLI with auto-binary resolution
- Shell — arbitrary commands via
bash -lcwith env variable prompt
- 3-tab interface: Tasks, Agents, Goals with detail panels
- Real-time activity feed with type-based filtering (text, tools, errors, events)
- Logs view with agent/type multi-filter, duration-based queries
- Form wizards for agent/task/goal creation with inline validation
- Agent Shop — 15 pre-built agent templates
- Toast notifications, help overlay, keyboard shortcuts
- Clipboard image paste for task attachments
- LiquidJS template engine with conditional sections
- System/User split for Claude API prompt caching
- Relevance-based context filtering (top 15 of 340+ entries)
- Inter-agent messaging (
orch msg send/broadcast/inbox) - Goal context injection with progress tracking
- Autonomous goal mode with structured decomposition loop
orch run/orch tui— start orchestrationorch task— add, list, show, edit, cancel, approve, rejectorch agent— add, list, show, edit, disable, shoporch goal— add, list, show, status, deleteorch team— create, list, show, deleteorch msg— send, broadcast, inboxorch context— set, get, list, delete (shared key-value store)orch logs— view run events with filteringorch config— view/edit orchestrator settingsorch doctor— health check for all adaptersorch update— check and install updates
- File-based storage (
.orchestry/) — YAML, JSON, JSONL, no database - Atomic writes with temp file + rename
- Parallel file reads with EMFILE batching (groups of 64)
- JSONL tail reads for OOM protection
- 3-layer event data truncation pipeline (16KB → 8KB → 4KB → 2KB)
- TUI batched message queue (80ms flush) with LRU caps
- 1493 tests across 83 test files
- Coverage: orchestrator resilience, adapter event parsing, template rendering, TUI components, wizard validation, state machine transitions, storage atomicity, process management
- Goal-Task Visual Linking — task rows show
⊕ TITLEbadge linking to parent goal, goal rows display████░░ done/totalprogress bar,Gtoggle groups tasks by goal with section headers - Logs view redesign — separate command bar from filter controls, compact agent filter chips with multi-select popup
- Logs filter status bar — active filter summary showing
agent:X type:Y N/Mcount at bottom of logs view - FormWizard inline validation — validate functions on wizard steps with 300ms debounce, red border on error, Enter blocking until fixed, required field
*indicator - HelpOverlay —
?andF1toggle a 3-column help panel (Navigation / Actions / Commands) with amber design - Detail Panel Resize —
+/-/Mhotkeys to grow/shrink/maximize the detail panel height - Toast Notifications — status banners for task completion: done (green, 4s), failed (red, 8s), review (blue, 6s); configurable bell sound (
\x07) on failed/review events - ErrorHintPanel — inline error summary in AgentList showing
ERROR_HINTSmessage, detail panel shows fix suggestions withorch doctorhint - Adapter error propagation —
AdapterErrorKindpropagated through events,agent.last_errorpersisted with kind/message/timestamp for post-mortem analysis - Header tab badge flash — tab pill blinks 3 times on task status events from other tabs (done=green, failed=red, review=blue)
- Inline Agent Shop suggestions — agent templates shown as selectable hints in wizard name step, filtered by typed text
- Task titles in depends field — DetailPanel shows human-readable task titles instead of raw
tsk_IDs - Compact AgentRow layout — removed role column (visible via Enter detail), running task and errors shown inline after name, adapter/team as plain text
- Goal badge before agent — goal
⊕badge moved to appear before agent name in TaskRow for better visual grouping - Config wizard simplified —
/confignow shows all settings sequentially without intermediate "pick a setting" step
- TDZ crash in CLI bundle — disabled esbuild minify in tsup to prevent temporal dead zone crash on startup
- goalMap TS2454 error — moved
goalMapdeclaration beforesortedTasksto fix TypeScript "used before assigned" error - GoalDetailPanel key navigation — tests updated to use
leftArrowinstead ofGkey for goals tab navigation - Ink OutputCaches OOM — patched Ink's internal
OutputCacheswith LRU eviction + memoized hot-path renders to prevent memory leak - Wizard suggestion state leak — reset suggestion state on wizard step navigation to prevent stale suggestions appearing
- LogsFilterPicker
atoggle — simplified toggle logic to remove dead code where both branches were identical - Duplicate task footer — removed sticky "showing N of M tasks" footer (inline "Show all" row remains)
- 1386 tests (up from 1099 in 0.3.3)
- New coverage: Goal-Task visual linking (21 tests), FormWizard inline validation (57 tests), HelpOverlay + command categories (86 tests), toast notifications (15 tests), ErrorHintPanel (14 tests), detail panel resize (13 tests), hidden tasks footer (5 tests), wizard validate functions (34 tests), logs filter status bar (4 tests), onboarding TUI (21 tests), errorKind propagation (9 tests)
- OOM crash after ~66 minutes — TUI crashed with
Ineffective mark-compacts near heap limitbecause Ink'sIntl.Segmenterran on every render for non-ASCII box-drawing characters (━,─). All 25+.repeat()calls across 6 components now use cachedheavyRule()/lightRule()builders that allocate each unique length once - Unbounded strings in
<Text>—agent.role,skills.join(),task.description,goal.description, andgoalProgressReportwere passed to Ink without per-line truncation, forcingIntl.Segmenteron multi-KB strings every render. AddedcapLine()andcapText()utilities with safe caps - Priority-based dispatch —
dispatchAll()sorted tasks byupdated_atonly, making thepriorityfield purely cosmetic. Tasks are now dispatched P1-first, with goal-linked tasks prioritized over unlinked at the same priority, and recency as tiebreaker
- Hidden tasks footer — when task list exceeds 10 items, a sticky footer shows
showing 10 of N tasks · press S to show allso users don't think tasks disappeared - Tab badge counter — Tasks tab pill shows total count
(N)when some tasks are hidden - Adapter error classification —
AdapterErrorKindenum with 7 error categories (adapter_not_found,auth_failed,timeout,rate_limit,process_crash,spawn_failed,unknown) and human-readableERROR_HINTSwith actionable fix commands - Onboarding state machine —
onboardingCompletedflag inOrchestratorState,WelcomeScreen,OnboardingNudge, andOnboardingToastcomponents for guided first-run experience - Command categories — suggestions panel groups commands into categories;
?help hint shown for new users
- 1099 tests (up from 1020 in 0.3.2)
- New coverage: priority dispatch ordering (4 tests), adapter error classification (4 adapters), hidden tasks footer/badge (5 tests), onboarding state (unit tests)
- Agent Shop — browse and install from 15 pre-built agent templates with detailed role prompts, skills, and recommended models; accessible via TUI (
/agent shop,Ctrl+S/⌘+Sfrom agent wizard) and CLI (orch agent shop) - Agent templates catalog — Backend Dev, Frontend Dev, QA Engineer, Code Reviewer, Architect, DevOps Engineer, Bug Hunter, Technical Writer, Marketer, Content Creator, Growth Hacker, Security Auditor, Performance Engineer, Data Engineer, Full-Stack Developer
- Skills step in agent wizard — new comma-separated skills input when creating agents via TUI
- macOS shortcut support —
⌘+Vimage paste and⌘+Sagent shop now work on macOS (previously onlyCtrl+variants worked); platform-aware hints shown in footer
- Full redesign — 13 sections (was 10), conversion-optimized copy, marketing psychology applied
- New sections — Social Proof (adapter cards), Problem-Solution (Before/After), Mid-page CTA, Use Cases (9 cards across 9 personas), FAQ (7 items with accordion)
- SVG agent topology — animated particle diagram showing CTO→Backend→QA→Reviewer team coordination
- Stats bar — replaced internal metrics (tests, LOC) with user-facing stats (N+ parallel agents, 15 ready-made agents, 1 command to start, 0 cloud dependencies)
- 4-column footer — Product, Resources, Community links with GitHub/Discord icons
- FormWizard remount — wizard defaultValues (name, role, model) were not applied when switching between wizard sessions; fixed by adding React
keyto force remount - Shop template approval_policy — Code Reviewer, Architect, and Security Auditor templates had
suggestpolicy silently overwritten toautoin TUI flow; now preserved via hidden wizard step - Shop picker robustness — guarded against
process.stdout.rowsbeing undefined/zero, added raw-mode cleanup on exceptions and SIGINT - release.sh — updated to replace all
vX.Y.Zoccurrences in landing page (was only matchingvX.Y.Z — open sourcepattern)
- 1020 tests (up from 1001 in 0.3.1)
- New coverage: Agent Shop catalog validation (15 templates, unique keys/names, role format), wizard prefill injection, skills parsing, approval_policy passthrough
/goalcommand group in TUI —/goal addopens wizard,/goal list,/goal show,/goal status <active|paused|achieved|abandoned>,/goal deletewith soft-delete undo; previously the command was registered but silently did nothing
- Empty assistant messages in activity feed — tool_use-only and empty-content assistant messages no longer produce
💬 (assistant message)noise in the TUI activity feed;formatAgentOutputreturnsnullsummary with lazy detail computation to avoid slicing 100KB+ strings for discarded messages - Multiline role text in wizard hints — agent roles with markdown (e.g.
## WORKFLOW\n...) now show only the first line in wizard select options instead of breaking layout
GOAL_STATUSESreuse —/goal statusvalidation uses the canonical constant fromsrc/domain/goal.tsinstead of a hardcoded array- Type-safe status narrowing —
statusArg: string | undefinedvalidated beforeas GoalStatuscast, eliminating premature unsafe type assertion
- 1001 tests (up from 987 in 0.3.0)
- New coverage: image paste integration (4 cases), agent hint stripping in wizard (10 cases)
- Goal context in agent prompts — agents now see full goal info (title, description, status, linked tasks, progress report) and can achieve goals via
orch goal status <id> achieved - Autonomous goal mode — agents in
[auto]tasks get a structured loop: decompose → execute → track progress → achieve goal - Clipboard image paste (Ctrl+V) — paste images from system clipboard into task creation/edit wizards; cross-platform support (macOS/Linux/Windows)
- Task attachments —
orch task add --attach <file>, stored in.orchestry/attachments/<taskId>/, displayed in TUI detail panel with 📎 indicator - Goal progress tracking —
goalIdon tasks,orch context set <goalId>-progressfor agent progress reports, visible in TUI GoalDetailPanel - Scrollable GoalDetailPanel — virtual scrolling with j/k navigation, section dividers, task summary counts, progress report display
- Skills display — agent detail panel shows configured skills list
- 3.5× faster per-test (52→15ms), 60× faster dispatch (30s→500ms), 2× faster build (2.7→1.35s), CLI 1.8× (75→41ms)
- state.claimed Array→Set for O(1) lookups in dispatch hot path
- Parallel reconcile —
Promise.allfor task reads in reconciliation phase - ScopeIndex pre-computation — O(1) agent-skill matching instead of O(n) scan
- isBlocked() O(d×1) — taskMap lookup instead of O(d×n) array scan
- Lazy imports — process-manager in run-store, chalk ansi256() in output.ts
- Minified CLI bundle — tsup minify enabled, reduces bundle size
- Parallel goal context I/O —
Promise.allfor context/messages/goal fetch in dispatch - CachedAgentStore nameCache — avoid repeated name lookups in retry queue filter
- Vitest adaptive threads — dynamic thread count based on CPU cores
- Tick interval 30s→10s — faster task dispatch for responsive orchestration
- GoalDetailPanel useMemo fix —
tasks ?? []moved inside memo to prevent new array reference defeating memoization - FormWizard paste mock types — test mocks now return correct
'image'|'text'|'empty'union instead of boolean - Stale closure in clipboard paste — fixed reference capture bug in handlePasteImage callback
- TASK_STATUS_COLOR / GOAL_STATUS_COLOR — canonical status→color maps extracted to
colors.tswithRecord<Status, string>type safety - SectionDivider reuse — exported from DetailPanel, replaces duplicate GoalDivider
- GoalContext in template engine —
GoalContextinterface,goal?field inPromptContext, Liquid template section for goals - Clipboard service —
clipboard-service.tswith platform detection, image extraction, and type-safe API
- 987 tests (up from 851 in 0.2.0)
- New coverage: clipboard paste (8 cases), GoalDetailPanel (13 cases), ScopeIndex (13 cases), attachments, orchestrator perf benchmarks, lazy chalk init
orch updatecommand — check for updates and install the latest version from npm (orch update --checkfor check-only mode)- Background update notifications — CLI silently checks npm registry (4h cache) and shows a notification when a newer version is available
- Lazy command loading — commands are dynamically imported on demand, reducing CLI startup time ~40%
- Light/Full container split — read-only commands (task, agent, status, logs, config, context, msg, goal, team) use a lightweight container without loading adapters, ProcessManager, or LiquidJS
--helpfast path —orch --helpandorch --versionskip container initialization entirely
- OOM fix (runtime) — truncate event data before event bus and JSONL writes; replace unbounded
readlinewith backpressured Buffer-based stream reader - OOM fix (startup) — replace N×M file reads (277 tasks x 376 runs = 104K reads) with single
listAll()pass; add 50MB JSONL file size guard - cancelTask/forceStopAgent lock bug — both methods now auto-acquire lock via
withTemporaryLockwhen called standalone (previously always threwLockConflictErrorfrom fresh Orchestrator) - task cancel for running tasks —
orch task cancelnow usesorchestrator.cancelTaskforin_progresstasks (kills agent process, cleans state) - State machine violation — remove
in_progress → doneshortcut, enforce mandatoryreviewstep - Truncated JSON in TUI logs — add
extractSummaryFromTruncatedregex fallback for truncated event data [undefined]in TUI — fix fallback to[${type ?? role}]$EDITORwith args —code --waitno longer fails with ENOENT--sincein logs — no longer loads entire JSONL into memory- NO_COLOR compliance — respect
NO_COLORenv var per no-color.org spec - Done tasks showing wrong time — use
updated_atinstead ofcreated_at - Race condition in TUI — move
setTaCursorColout ofsetTaLinesupdater - Process spawn — add
proc.unref()after detached spawn to unblock parent exit isProcessAlive— return true on EPERM (process alive, no permission)- Retry backoff — fix off-by-one using
attempts - 1for correct backoff start - Scope overlap — fix
patternsOverlapfalse negative for sibling paths - CJK/emoji titles — fix
prepareWorktreeempty branch name sanitizeId— reject forbidden characters instead of silently strippingappendJsonl— truncate data to PIPE_BUF (4096) for atomic O_APPEND writescancelTaskabort — call.abort()on AbortController before deleteforceTaskToReview— now clearsagent.current_task
- Progressive history loading — parallel I/O in
onLoadHistorywith batched setState (80ms flush) readJsonlTail— read last N records from JSONL without loading entire file- EMFILE protection — batched
Promise.allreads in groups of 64 - Vitest threads pool — test suite runs ~12% faster
buildLightContainer/buildFullContainer— split DI container for fast startupreadLinesgenerator — Buffer-based with backpressure, replacesreadline.createInterfaceserializeEventData— DRY event serialization with 3-layer truncationresolveFailureStatus— extracted from duplicated retry logiccreateTokenUsagefactory — ensurestotal = input + output- Atomic cache writes — update-check uses temp file + rename
- 851 tests (up from 737 in 0.1.0)
- New coverage: process-manager, streamEvents, lazy routing, task cancel, progressive loading, context, token usage, retry status
Initial release.