Repository navigation
Integrate roadmap stack into main (Pillars 1-7 + follow-ups, v0.14.0) - #14
Merged
Merged
Conversation
One execute() interface so any runtime can be an agent. mcp-tool runs a task by calling a tool on another MCP server (the differentiator); shell runs an allowlist-gated command. Runner resolves an executor per agent from settings.executors (default llm = unchanged). Budget/approval/veto/eval wrap all runtimes uniformly. 72 tests. Bump 0.3.0 + CHANGELOG + ROADMAP.
/code-review on the executor branch found: mcp-tool leaked the spawned server (no error/close/timeout handler, never killed when the runner's outer race fired) and the shell allowlist was basename-only (bypassable by /tmp/evil/node). Add error/close/timeout handling + stderr drain + guaranteed cleanup to mcp-tool; require full-path allowlisting for path-qualified shell commands. +2 tests (bypass refused, bad mcp cmd fails fast).
…ut cap) Second /code-review found residual shell.js issues: full-path allowlist used strict string equality (rejected C:/x/node.exe vs C:\x\node.exe and case variants on Windows), the spawn 'error' path leaked the timeout timer, and stdout/stderr buffers were unbounded. Add platform-correct samePath() matching, single-settle guard that always clears the timer, a 5 MiB output cap, and a 4 KiB stderr ring. mcp-tool fixes verified clean; config wiring verified threaded from server/daemon/heartbeat. +1 test (75 total).
Tasks gain depends_on + parent_id. New lib/scheduler.js (pure): readyOrder() runs only dep-satisfied tasks (priority then age); findDeadlocks() catches unknown deps and cycles via Kahn. Heartbeat is now topological — blocks deadlocks with a reason instead of starving, then re-scans readiness after every run so a whole chain drains in one cycle. /code-review caught the gate being bypassable: depends_on was enforced only in the heartbeat, so ceo_run_task/execute:true could run an unmet-dep task. Now enforced in runner.runTask (single chokepoint, returns 'waiting'). Also surfaced deps in the backlog projection. v0.4.0, +15 tests (90 total).
config/org.yaml models the company as a reporting tree; lib/org.js (pure) resolves agent->role, walks the reporting line, collects role subtrees, and rolls budget up so an agent's spend counts against its role AND every ancestor (department envelope bounds its members; root bounds the org). Runner enforces the role envelope before dispatch (department breach blocks the task, no global pause). ceo_org tool renders the chart + live spend (16 tools). Executor resolution gains a per-role fallback. /code-review fixes: clarified the >/>= operator split (mirrors budget.js) and made runner/heartbeat tests hermetic via empty-org isolation in the workspace helper, decoupling them from the production org.yaml caps. v0.5.0, +11 tests (101 total).
Append-only events table (autoincrement id = total order). lib/events.js: emit/list/snapshot, a pure reduce() that folds the task lifecycle into derived state (replayable from the log alone), and a cursor-based drain()+subscribe() for reactive processing. Task lifecycle events emitted from tasks.js (the single mutation chokepoint); heartbeat emits cycle.ran and drains events each cycle into an append-only audit feed (reports/events-feed.md) — the loop is event-driven, not just cron. ceo_audit tool (17th) replays the log and reports fidelity vs live. /code-review caught a replay-fidelity gap: create() upserts status but only emitted on first insert, so a status change via create() was invisible to the log. Now emits task.status on an upsert that changes status; reducer handles it. +regression test. v0.6.0, +9 tests (110 total).
An agent's answer may carry a fenced ceauto directive ({subtasks, escalate};
lib/delegation.js); the llm executor surfaces it. On a done task the runner spawns
child tasks within the acting role's can_delegate_to authority (parented for the
DAG scheduler) or escalates up the reporting line, all logged to the event bus.
tasks.depth() + max_delegation_depth/max_subtasks_per_task bound runaway fan-out.
/code-review fixes: (1) isolated processDelegation in its own try/catch so a
child-spawn failure can't re-dispatch the done task and double-spawn; (2) hardened
org.canDelegate so a modelled role can't delegate to an unknown/hallucinated agent.
+regression tests (no re-dispatch on delegation error; unknown-agent denied).
v0.7.0, +14 tests (124 total).
lib/learning.js on the existing evals + memory FTS (no new tables): a high-scoring completion distills a reusable playbook that's injected as context before similar work; a quality/failure block distills a lesson recalled before similar work; per-(agent,model) success+cost stats recommend the cheapest model that works. Runner injects recalled context + records playbooks/lessons (all best-effort). ceo_insights tool (18th) surfaces the dispatch policy. /code-review fixes: (1) dispatchStats JOIN multiplied rows on retries/re-evals, skewing the recommendation — now pre-aggregates ledger+evals to one row per task before joining; (2) handleInsights null-guards toFixed and derives the agent list from real history (no hardcoded omissions). +regression test (retries don't inflate stats). v0.8.0, +10 tests (134 total).
webhook/http-webhook + claude-code executors on a shared hardened spawn helper; file-watch/inbound-webhook/@mention sources (default-off, secret- required) feeding the queue; ceo_sources tool (19th). /code-review hardening: SSRF redirect block, port-aware + roster-validated allowlists, timing-safe secret, payload-override guard, stdin EOF/SIGKILL, debounce, bounded event scan.
Local 127.0.0.1 dashboard (lib/dashboard.js + bin/ceauto-dashboard.js) projecting tasks/approvals/org/metrics/events from SQLite. Policy-as-code (config/policy.yaml) ordered rules → require_approval + quorum, legacy fallback. Multi-approver quorum in approvals (N distinct approvers, one reject vetoes). /code-review hardening: attribute-safe esc() (quote XSS), slimmed event payload, shared approverCount, explicit-verdict-only policy rules, no-op resolve on resolved approvals.
dispatch.auto_route (default-off) routes each task to the cheapest (model, provider) that has historically cleared the bar for the agent; falls back to the configured model when off or under-sampled. Partial routes are ignored to avoid a cross-provider mismatch. v0.11.0.
A task can run an ordered list of executors: chain (pipeline, result = last step) or map (fan, result = reduced doc). Usage summed across steps; bounded to 10 steps, no nesting. Runner scales the budget gate by step count so the cost is gated, not just one step. v0.12.0.
task.plan decomposes a task into a subtask DAG instead of executing it: the runner appends a planning instruction, forces the llm executor, and the agent ceauto directive is spawned as children via the existing delegation path. processDelegation maps sibling-title depends_on to new child ids (self-ref dropped, first duplicate wins). v0.13.0.
With dispatch.explore_epsilon > 0 (default 0) auto-routing occasionally re-samples an abandoned/under-sampled model so a recovered or cheaper one can be rediscovered, logged as a dispatch.explored event. recommendDispatch gains epsilon + injectable rng.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Integrate the roadmap stack into
main(Pillars 1–7 + follow-ups + nicety)Why this PR exists: PRs #2–#13 were a stacked chain — each one's
basewas theprevious feature branch, not
main. Merging them therefore updated those featurebranches, not
main; only PR #1 (base: main) ever landed. As a resultmainwasleft at v0.2.0 with just the autonomy core, while the full roadmap work
accumulated linearly on the top-of-stack branch
feat/dispatch-exploration(v0.14.0). This PR brings those 14 commits into
mainin one clean merge(verified conflict-free).
What lands (already reviewed + CI-green individually as #2–#13)
llm/mcp-tool/shell(+ hardening passes),webhook/claude-code(G1),composite(Add composite executor (Pillar 1) #11).wiring (Wire learned dispatch policy to auto-route tasks (Pillar 6) #10); epsilon-greedy exploration (Add epsilon-greedy exploration to the dispatch policy (Pillar 6) #13).
Verification
mainis conflict-free (localmerge-treeclean)./code-review+ green CI as its own PR (Pillar 1: executor abstraction (any runtime, MCP-native) #2–Add epsilon-greedy exploration to the dispatch policy (Pillar 6) #13).feat/dispatch-exploration),the exact CI jobs on Node 20.
Merging this makes
main= v0.14.0 with the roadmap fully closed. Tagv0.14.0after.