feat(factory): wire per-role reasoning_effort from LlmConfig through spawn pipeline#4
Closed
pippenz wants to merge 27 commits into
Closed
feat(factory): wire per-role reasoning_effort from LlmConfig through spawn pipeline#4pippenz wants to merge 27 commits into
pippenz wants to merge 27 commits into
Conversation
- Add custom option_i32/option_u8 serde deserializers so MCP count fields accept numbers sent as floats (e.g. 3.0) from Claude Code - Fix notify_rx ref mut in factory lifecycle to allow mutable drain/recv - Refactor DaemonNotifier socket to lazy tokio conversion (std socket bound before Tokio runtime, converted on first async use) - Use gcc linker instead of clang for local build
….json Workers were only getting Bash(cas :*) permissions in their generated settings.json, leaving mcp__cas__* tools unallowed. This required unreliable fallback to the global ~/.claude/settings.json. Add get_cas_mcp_permissions() alongside get_cas_bash_permissions() and merge both into the permissions.allow array in get_cas_hooks_config(). The 10 MCP tools added: task, coordination, memory, search, rule, skill, spec, verification, system, pattern. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
When workers use isolated git worktrees, .mcp.json must be committed to git or it won't appear in their checkout — leaving them with no MCP tools and silently idle. Changes: - preflight_factory_launch(): add git ls-files check for .mcp.json. Hard failure when workers > 0; advisory notice when supervisor-only. Quick-start steps show 'git add .mcp.json && git commit' when only .mcp.json is missing (not duplicated if .claude/ is also missing). - queue_codex_worker_intro_prompt(): inject MCP fallback instructions for Claude workers at startup. Tells workers to check .mcp.json, run 'cas init -y' to regenerate it, and notify supervisor via 'cas factory message' if MCP tools are unavailable — preventing silent idle loops. Closes cas-8397 (based on spike cas-4567). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace hand-written option_u8/option_i32 deserializers with a single
option_numeric_deser! macro generating 6 variants (u8, i32, i64, u32,
usize, u64). Apply to all ~30 Option<numeric> fields across MCP request
types so Claude Code's string-encoded numbers ("3") are accepted
alongside native JSON numbers (3).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- handle_mouse_up() returns selected text instead of calling arboard directly (daemon is headless, can't access system clipboard) - Daemon relays selected text to client terminal via OSC 52 escape sequence for native clipboard write - Auto-enter inject mode after image drop so user can immediately type context for pasted images Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…reen Adds a "minions" theme variant selectable via `[theme] variant = "minions"` in config.toml. When active: workers get minion names (kevin, stuart, bob), supervisor is named gru/dru/nefario, the color palette shifts to yellow primary with denim blue accents, and the boot screen shows a minion ASCII art logo with "BANANA!" ready message and "Bee-do Bee-do" launch animation. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
… test compilation - Replace generic box ASCII art with recognizable minion character (pill body, goggles with eyes, overalls, "BANANA" text) - Wire MinionsIcons (banana/eye/sleep emoji) into agent_status_icon() and agent_status_icon_simple() via is_minions() theme flag - Add missing minions_theme field to test_config() in core.rs and factory_integration.rs - Fix pre-existing mut warnings in notify.rs tests (lines 132, 155) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Redesign MINION_LOGO with better pill-shaped body silhouette, symmetric goggle strap, arm stubs (─┤/├─), and cleaner feet - Replace 8 non-canonical worker names (larry, tom, chris, john, paul, mike, ken, donny) with actual Minion film characters (jorge, otto, steve, herb, pete, donnie, abel, walter) - Add otto (main character from Minions: The Rise of Gru) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The test was failing because try_recv on a Tokio UnixDatagram requires the socket to be registered with the reactor first. Added an initial recv().await call before the drain test sequence to ensure the Tokio socket is properly registered. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- OSC 52: base64 encoding, empty string, unicode, multiline round-trip - ThemeVariant: default value, Display, FromStr, serde round-trip - ActiveTheme: minions config wiring, is_minions() check - ColorPalette::minions(): yellow primary, denim blue info, differs from dark, preserves base bg - MinionsIcons: non-empty constants, differ from default circles Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace all `mcp__cs__` prefixes with `mcp__cas__` in the hardcoded Codex worker and supervisor instructions in pty.rs. Extract inline instruction strings to module-level constants for maintainability. Add tests verifying Codex worker instructions use the correct mcp__cas__ prefix and supervisor instructions are present. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…essage
Remove the response hint ("To respond, use: coordination...") that was
appended to every agent message. This instruction is already provided at
session start via the cas-worker skill and is also enforced by the
PreToolUse hook that blocks SendMessage in factory mode. Removing the
per-message hint saves tokens on every inter-agent exchange.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Revert the prefix change per supervisor guidance: mcp__cs__ is the correct Codex tool prefix (configured in harness.rs). Keep the extraction of inline instruction strings to module-level constants (CODEX_SUPERVISOR_INSTRUCTIONS, CODEX_WORKER_INSTRUCTIONS, CODEX_WORKER_STARTUP_PREFIX) for maintainability. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The function reads CAS_AGENT_ROLE and CAS_FACTORY_WORKER_NAMES env vars and parses CSV on every call across 6+ call sites. Since env vars don't change during a session, cache the result per-thread using thread_local OnceCell. Thread-local (vs process-global OnceLock) is used so that tests which set different env vars per test thread continue to work. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
… queue messages Remove the 500-char truncation when re-queuing undelivered messages to the supervisor. The full original message is now preserved in the system-notice, so the supervisor can properly re-send or act on the complete content instead of a truncated fragment. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add priority support to the prompt queue so important messages (blockers, crashes) can jump ahead of routine status updates. Changes: - Add priority column to prompt_queue table (migration, DEFAULT 2) - Add enqueue_full() method accepting optional NotificationPriority - Change ORDER BY from created_at ASC to priority ASC, id ASC - Wire priority param through coordination message action - Add QueuedPrompt.priority field using existing NotificationPriority - Add 3 tests: priority ordering, default priority, peek_for_targets Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add an ack-back mechanism so senders can verify message delivery: - Schema: add `acked_at` column to prompt_queue table (safe migration) - Store: add `ack()`, `unacked()`, `message_status()` to PromptQueueStore trait - MessageStatus enum: Pending → Delivered → Confirmed lifecycle - Coordination: add `message_ack` and `message_status` actions - Tests: 5 new tests covering ack, idempotency, nonexistent, timeout, status Messages now have a 3-state lifecycle: 1. Pending - queued but not yet injected 2. Delivered - injected (processed_at set) but unconfirmed 3. Confirmed - target agent acked receipt (acked_at set) Agents can ack via: coordination action=message_ack notification_id=<id> Senders can check via: coordination action=message_status notification_id=<id> Unacked messages can be queried via store.unacked(timeout_secs, limit). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ool permissions - CLAUDE.md: replace abbreviated docs with comprehensive architecture guide covering workspace layout, key patterns, testing, and migration details - settings.json: add CAS MCP tool permissions to allow list Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ugh PtyConfig::claude test-first gate: new tests verify that: - custom effort value (e.g. "low") is used when provided - supervisor defaults to "high" when effort=None - worker defaults to "medium" when effort=None These tests require the new `effort: Option<&str>` parameter on PtyConfig::claude which does not exist yet — compilation failure is the expected failing state. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
… factory spawn Reads `llm.supervisor.reasoning_effort` / `llm.worker.reasoning_effort` from `.cas/config.yaml` and threads the value all the way to the `--effort` flag passed to Claude CLI at spawn time. Changes: - cas-pty: add `effort: Option<&str>` to PtyConfig::claude and PtyConfig::codex; replace hardcoded high/medium with role-based fallback that respects the config value when set (backward-compatible: None → "high" for supervisor, "medium" for worker) - cas-mux: add `effort` param to Pane::worker() and Pane::supervisor(); add supervisor_effort/worker_effort to MuxConfig and Mux, wire through factory() and add_worker() - cas-factory: add supervisor_effort/worker_effort fields to FactoryConfig; wire into FactoryCore::new() (set_worker_effort) and spawn_supervisor() - cas-cli: populate the new FactoryConfig fields via llm.reasoning_effort_for_role() in both factory entry points (mod.rs + daemon.rs) and propagate through the two MuxConfig construction sites (init.rs + fork_first.rs) Also fixes pre-existing incorrect test assertion in test_pty_config_claude_with_teams which claimed workers should NOT have --session-id (they always do). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
FactoryCore::new was calling set_worker_cli and set_worker_effort but missing set_worker_model, leaving worker model config silently ignored when using the dynamic-spawn path. Detected and applied by cas-code-review autofix loop (round 1). Refs: cas-63d9 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
Thank you for your interest in CAS! We appreciate you taking the time to contribute. CAS is source-available but does not accept pull requests at this time. Instead, please:
See CONTRIBUTING.md for more details on how to participate. |
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.
Summary
reasoning_effortconfig per-role (supervisor/worker) through the full factory spawn pipeline, mirroring the existingmodelpatternMux::factory()(static init) andFactoryCore::spawn_supervisor/spawn_worker()(dynamic)highfor supervisor,mediumfor workerFactoryCore::newnow also callsmux.set_worker_model()for symmetry withset_worker_effort()Files changed
crates/cas-pty/src/pty.rs— addedeffort: Option<&str>param; replaced hardcodedhigh/mediumwithunwrap_ordefaultcrates/cas-mux/src/pane/mod.rs— forwarded effort throughPane::supervisor()andPane::worker()crates/cas-mux/src/mux.rs— addedsupervisor_effort/worker_efforttoMuxConfig, storedworker_effortinMuxfor dynamic spawncrates/cas-factory/src/config.rs— addedsupervisor_effort/worker_efforttoFactoryConfigcrates/cas-factory/src/core.rs— wiredworker_effortandworker_modelthroughFactoryCore::new()cas-cli/src/cli/factory/mod.rs,daemon.rs— read fromLlmConfig::reasoning_effort_for_role()cas-cli/src/ui/factory/app/init.rs,daemon/fork_first.rs— forwarded throughMuxConfigTest plan
pty.rs: custom effort, supervisor default, worker defaultcargo test --package cas-ptypassescargo test --package cas-muxpassescargo test --package cas-factorypassesCloses: cas-63d9
🤖 Generated with Claude Code