feat(trios): Queen supervisor - delegation, observability, skills, replay - #5
feat(trios): Queen supervisor - delegation, observability, skills, replay#5gHashTag wants to merge 48 commits into
Conversation
…cess sandboxing, mesh ports, Swift tests, archive dead BR-OUTPUT prototypes Cycle 7 autonomous hardening for /trios: - LLMClient.swift: remove env/API-key fallback, enforce Keychain-only supply. - QueenStatusViewModel.swift: pid-based termination, command denylist, trusted-exec validation, safe env checks. - clade-build: emit TRIOS_MESH_PORT and TRIOS_CANARY_MCP_PORT per variant into Info.plist. - ChatViewModel.swift: deduplicate conversation-management API; add selectConversation helper. - ChatSidebarView.swift: reconcile with canonical ChatConversation/ChatMessage types. - ExtensionStoreAPI.swift: drop broken ExtensionManager/PluginAPI references. - AnalyticsService.swift: explicit Decodable init for [String: Any] properties. - Package.swift + SSEEventParserTests.swift: migrate Swift SSE tests into XCTest harness. - README.md: refresh size/stats. - Archive non-compiling BR-OUTPUT prototypes (PluginAPI.swift, ToolCallFix.swift) into .archive/. Verification: build.sh OK, cargo test OK (270+), cargo clippy -D warnings OK.
…okens, HELLO auth, SafeFilePath, .aiignore Cycle 8 autonomous hardening for /trios: - KeychainSecrets.swift: generic macOS Keychain wrapper for small secrets. - GitHubAPIClient.swift: remove GITHUB_TOKEN env fallback; read token from Keychain. - MeshAuth.swift: remove TRIOS_MESH_API_TOKEN env fallback; read token from Keychain. - trios-meshd (submodule): verify HELLO src, MAC, and freshness before accepting beacons. - SafeFilePath.swift: default allowMissingBase to false. - CladeGuard.swift: remove allowMissingBase: true from snapshot validation. - .aiignore: exclude secrets, .trinity runtime state, build artifacts. - Extend AGENT-V-WAIVER expiry from 2026-07-28 to 2026-12-31 across mesh BR-OUTPUT files. Verification: cargo test (270+), cargo clippy -D warnings, build.sh OK.
- Add ./trios executable launcher: build, start backend, open app, health check - Make ecosystem.config.js portable via TRIOS_ROOT / __dirname - Update LAUNCH.md and QUICK_START.md with one-command usage Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Manifest integrity: SHA-256 + size per entry, verify on read - Atomic import with rollback on partial failure - Duplicate resolution: replace / merge / skip - Large-file safety: 16 MiB cap for log/diagnostic files - Progress overlay and cancellation hook - Version compatibility: schemaVersion, minReaderVersion - Expanded error taxonomy with LocalizedError descriptions - ASCII-only sanitization across touched source files Closes #T27-EPIC-001
…, A2A rings, and chat history - Integrate SR-00/SR-01/SR-02 rings, BR-OUTPUT canon, and local-auth token-family store. - Add BrowserOS server local-auth routes, chat-history service, task-queue, A2A registry, retry/CORS/request-auth hardening. - Update build scripts, docs, and .gitignore; keep generated artifacts out of tracked tree. - All server sources pass Biome lint/format gate. Closes #TRIOS-PORTABLE-LAND-001
Mark task done in done.json and clear active.json. Closes #TRIOS-PORTABLE-LAND-001 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add TRIOS_RELEASE_MANIFEST.md and .claude/plans/trios-portable-land-001-report.md with verification results, clean-machine blockers, and three land variants. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add trios/docs/INSTALLATION_README.md with prerequisites, install steps, permissions, troubleshooting, and migration warnings. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Update TRIOS_RELEASE_MANIFEST.md and landing report with the discovery that origin/dev has diverged via the agent-core extraction and trios switchover. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
… /doctor --model - Stop retrying fatal provider errors (402 balance, 401 auth, invalid model). - Surface actionable chat error messages with fallback model hints. - Add /doctor --model parsing and pass --model to the Claude CLI invocation. - Pin doctor skill to claude-sonnet-4-6 to avoid stale claude-opus-4-6 access issues. - Add ModelConfigurationStore fallback helpers and ChatFailureTests. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Add provider-aware fallback ordering with cheap floor model last. - Send OpenRouter native array for server-side failover. - Refactor ChatViewModel.sendMessage to retry once on model-unavailable/invalid-model errors. - Insert a user-visible banner when failover occurs; restore original model if retry fails. - Clean up stale claude-opus-4-6 references in BrowserOS agent catalog and CLI provider. - Add ChatViewModel failover tests and ChatRequestBuilder OpenRouter tests. Closes TRIOS-AUTO-FAILOVER-011 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Add .logs Trios999Destination with petal 2 (Cmd+3) and world LOGS. - Create BR-OUTPUT/LogsTabView.swift showing next-loop variants + unified log viewer. - Wire LogsTabView into QueenTabView hosted routes and build.sh LEAN_BR_OUTPUT. - Update trinity QueenUILib TriangleLogo.swift: EXPLAIN -> LOGS. - Update trinity_999_tab_map_test for 7 routes and .logs shortcut 3. Verification: - bash trios/build.sh passes (114 Swift files, QueenUILib rebuild). - cargo test --workspace passes. - cargo clippy --workspace --all-targets --all-features -- -D warnings clean. - Standalone trinity_999_tab_map_test passes. - trios.app relaunched; menu-bar logo process alive. Co-Authored-By: Claude Opus 4.8
- Add ModelHealthService actor with cached TTL probes: - Cloud providers: tiny max_tokens:1 ping via chat completion endpoint. - Ollama: free /api/tags existence check. - Two-failure threshold before marking unavailable. - Extend ModelConfigurationStore with unhealthyModels, healthStatus, refreshHealth, selectFirstHealthyModel, and invalidation on provider/URL/key changes. - Preflight check in ChatViewModel.sendMessage switches to first healthy fallback with a visible system banner before burning a real request. - Mark failing model unhealthy after any transport error for next preflight. - Models tab: Health button, unavailable badges, disabled unhealthy rows, badge on active model. Verification: - bash trios/build.sh passes (115 Swift files). - cargo test --workspace passes. - cargo clippy clean. - trinity_999_tab_map_test passes. - trios.app relaunched; health endpoint ok. Next loop options: background poller, persistent reliability scoring, provider-native status feeds. Co-Authored-By: Claude Opus 4.8
Add ModelHealthServiceProtocol so tests can mock probe results. Add ChatFailureTests for preflight switching, error marking, and no-switch healthy path. XCTest unavailable in this toolchain; production build, cargo test, and clippy pass. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add BackgroundHealthPoller actor that probes all available models every 60s. Wire poller into ModelConfigurationStore lifecycle: start on init, restart after provider/URL/key changes. Update ModelsTabView with Auto toggle and last-check timestamp. Add XCTest coverage for poller, recovery detection, and start/stop toggle. Clade audit + seal pass. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…og pre-check, UI badges, tests - Add ProviderStatusService actor with cached /models checks for OpenAI/Anthropic/OpenRouter and /api/tags for Ollama. - Inject ProviderStatusService into ModelHealthService to skip paid probes for missing/disabled models. - ModelConfigurationStore owns ProviderStatusService, exposes providerStatus(for:), invalidates on endpoint/key/provider changes. - Add hasProviderCatalog to ModelProvider. - ModelsTabView shows 'disabled' / 'not in catalog' badges after Health refresh; refreshes badges on catalog change. - XCTests: missing/disabled status skips paid probe, OpenRouter catalog parsing, status invalidation. Closes TRIOS-CHAT-PROVIDER-FAILURE-014 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- ModelReliabilityService actor with EMA scoring and bounded outcome history - MemoryStore v3 schema with encrypted model_outcomes table - MemoryStoreReliabilityAdapter bridging outcomes into agent-memory.sqlite3 - Async, reliability-ranked fallbackModels/runtimeConfiguration in ModelConfigurationStore - ChatViewModel records send/failover outcomes and awaits async runtime config - XCTests for EMA, ranking, persistence, reset, and history limits - Update E2E schema-version assertion and mock memory store stubs Verification: - ./build.sh passes (swift test skipped: no XCTest in CLI tools) - cargo test --workspace passes - cargo clippy --workspace clean - clade-audit 0 findings - clade-seal SEAL VALID - trios.app relaunched and healthy Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Add ModelCostService with ModelCostTier (any/free/cheap/premium) - Extend ModelReliabilityService.bestModel() with tier filtering - Add isPredictiveSelectionEnabled + preferredCostTier to ModelConfigurationStore - Add Smart model selection UI to ModelsTabView - Add ModelCostServiceTests and bestModel coverage - Stop e2e keychain password dialogs via TRIOS_E2E_DISABLE_KEYCHAIN=1 - Fix clade-build LEAN_BR_OUTPUT whitelist drift for LogsTabView.swift Closes #T27-EPIC-001 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Add ModelContextService.largerOutputCandidates(...) for output-ceiling-first candidate search. - Insert output-budget routing phase into resolveContextRoutingDecision before context-window routing. - Surface routing cause via lastContextRoutingReason (output budget vs context window). - Update ChatViewModel routing label to use the recorded reason. - Add tests for effectiveOutputCeiling, isOutputBudgetSaturated, and output-budget routing. - Run Trinity gates: build, mesh tests, clade-build, clade-audit (0 findings), clade-seal valid. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Closes gHashTag/trios#1086 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Limit build_*.log and chat_sse_e2e_build_*.log to 10 newest files in .trinity/logs. Previously every build and chat-SSE e2e run created a new log, flooding the LOGS tab with 120+ stale build artifacts. Closes gHashTag/trios#1087 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Add LogSourceCategory (runtime/service/build/test/artifact) and classify sources - Default LOGS tab hides build/test artifacts; add Show build/test logs toggle - Cap artifact log families at 10 files in build.sh, run_queen_autonomous_test.sh, clade-build - Add XCTest coverage for classification and filtering - Cleanup legacy cycle logs and stale archive Closes browseros-ai#2046 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Add scripts/cleanup_artifact_logs.sh dry-run-by-default cleaner - Lower artifact cap from 10 to 5 files per family - Add 7-day age eviction for artifact logs - Scan .worktrees/*/trios/.trinity/logs for stale build logs - Wire cleaner into build.sh, run_chat_sse_e2e.sh, run_queen_autonomous_test.sh - Update clade-build binary to keep 5 logs and evict logs older than 7 days Closes browseros-ai#2047 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Closes browseros-ai#2047 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Extend LogRotationPolicy with maxArchiveAgeSeconds and maxAgeBeforeRotationSeconds - Add .audit, .security, .experience static policies - Add rotateAuditLogs() for event_log, akashic-log, local-auth-audit, episodes - Add cleanupOldArchives() to prune .archive.<ts>.zlib files older than retention - Wire rotateAuditLogs() into AppDelegate.applicationDidFinishLaunching and loadLogSources - Update LogsTabViewTests for age-based rotation and cleanup Closes browseros-ai#2048 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Closes browseros-ai#2048 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Add AuditRotationScheduler (6h Timer, utility queue, NSLock serialization) - Wire start/stop in AppDelegate lifecycle - XCTest coverage for scheduler lifecycle and repeated rotateNow - Plan + spec + report for Cycle 57 Closes browseros-ai#2049 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Closes browseros-ai#2049 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Add LogRotationPolicy.worktreeAuditLogPaths(repoRoot:) to discover .worktrees/*/trios/.trinity JSONL streams - Extend rotateAuditLogs() to rotate main repo + worktree audit streams - XCTest coverage for worktree discovery edge cases - Plan + spec + report for Cycle 58 Closes browseros-ai#2050 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Closes browseros-ai#2050 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
… extensionless audit archives Closes browseros-ai#2051 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…leep Closes browseros-ai#2052 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Add LogRetentionSettings (UserDefaults) with per-policy overrides for max size, archive count, archive age, and rotate-after age. - Rename static presets to *Policy and expose computed vars that merge user overrides over hard-coded defaults. - Add LogRetentionSettingsSheet in LOGS tab (gear icon) for Audit, Security, Experience, and General/Default presets with reset action. - Add XCTest coverage for round-trip, fallback, and invalid storage. Closes browseros-ai#2053 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…play The Queen delegates to worker chats instead of coding, and everything needed to supervise that is here: the runner that actually starts a bee, the surfaces that show what it is doing, and the harness that proves both without a provider. Delegation - QueenWorkerRunner streams a worker turn on its own transport, so navigating between chats cannot cancel a bee mid-flight - QueenBranchCommitter attributes edits via a throwaway index and commit-tree; HEAD, the real index and the working tree are never touched - Workers get workingDirectory: ProjectPaths.root - the default is home, and one bee "successfully" wrote into an unrelated checkout under ~/gitbutler - Worker transports get a 3600s resource cap; the 600s chat default killed a worker after seventeen successful tool calls Supervision - QueenDashboardView above 760pt, QueenCompactSupervisorBar in the 400pt panel the user actually keeps open, QueenTaskBanner in each worker chat - SystemNotice severity: every system message used to render as a red error, so delegation success and provider failure looked identical - QueenObserver reads the live transcript for looping, spinning, out-of-bounds writes and overspending - a pure function, not a second agent - QueenSalience + SalienceLearner rank the review queue by learned intervention rate rather than age alone Capabilities - SkillCatalog/SkillStore/SkillsTabView make .claude/skills the source of truth; the Queen could previously reach 4 of 26 because the list was a Swift literal - QueenSystemPrompt puts her role, commands and skill roster in her context - a capability the agent cannot see is a capability it does not have - QueenSelfAudit (/roadmap) greps type declarations against references and reports what nothing calls Verification - ReplayTransport replays SSE cassettes through the real parser; make cassettes runs three in ~6s with no provider and is part of make check - repairOrphanToolCalls synthesises a result for interrupted tool calls, which otherwise poisoned a conversation permanently Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Two loose ends from the supervisor work. The orphan-tool-call cassette could not join the suite because nothing on the client said a run had produced one - the server repairs them, silently. The client cannot repair an orphan (the server owns the agent's history) but it can see one, and seeing it is what makes the failure assertable. That bug poisons a conversation for every later send, not just the turn that caused it, so it is worth a warning of its own. The learner's observation threshold was a number I picked. It is now derived from the priors: a rate over n Bernoulli trials has standard error at most 0.5/sqrt(n), and the estimate is worth trusting once that falls below the smallest gap the priors are trying to express. The point is not the value - it is that changing a prior moves the threshold instead of leaving behind a constant that used to make sense. make cassettes now runs four in ~8s with no provider. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…imits `SalienceLearner.evidence(for:)` had zero call sites - the learner wrote tallies to disk and nothing read them back in words. That is the exact defect /roadmap exists to find, written by the hand that built the detector. /salience now reports each signal's weight, whether it is learned or still the prior, and the evidence behind it. The orphaned-tool-call repair is now proven end to end: TRIOS_E2E_SECOND_TURN=1 sends a second turn on the same conversation, and the regression only shows itself there - the first turn leaves the orphan, the send after it is the one that used to throw. The cassette version of that test is removed. A replay yields the same recorded bytes on every turn, so a textless abort cassette produces no text twice and the assertion cannot distinguish that from a poisoned conversation. The bug lives in the server's prompt assembly, which a cassette bypasses by design. The reason is recorded next to the suite so nobody adds it back. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The app-level cassette suite launches the .app and needs a window server plus a running agent server, so CI cannot run it. These assertions cover the same code paths in-process, through the harness that already runs headless inside build.sh: same ReplayTransport, same SSEEventParser, same QueenObserver. The salience learner is proven here rather than by seeded tallies. Driving it through twenty app launches failed twice - `open` racing the single-instance flock - and a mechanism verified only by data its author typed is verified by arithmetic, not behaviour. Seven assertions feed the real API real outcomes and check the boundary in both directions: one observation short of the threshold keeps the prior, crossing it moves, and a signal that never needed the user ends up quieter than its prior. Without that last case the learner could only ever confirm what it was told. Adds .github/workflows/trios-logic.yml: bun tests for the server-side orphan repair on Linux, the Swift harness on macOS. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Three layers, found in order: the test target had no module graph, one file belonged to two modules, and the source targets an older Zig than the one installed - std.Thread.Mutex and std.time.milliTimestamp are both absent in 0.16. The first two are fixed and the patch is recorded; the third is a migration in another repository, so trinity's working tree was restored untouched. The brain-atlas skill stays a map rather than a link, and now says exactly what it would take to change that. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
"Leave it a week and see" needs something to compare against in a week. The learner kept only current tallies, so the sole observable was the present number - which cannot distinguish a signal that has settled from one that never moved. Weights are now snapshotted whenever one changes, capped at 200 entries, and /salience reports the drift from each starting estimate. Snapshots are taken only on change: one per review would fill the trail with duplicates and bury the moments that matter. The store gained a versioned shape and falls back to decoding the old bare dictionary, so counts already collected survive the upgrade. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…his branch Commit 5ca201c swept 1534 unrelated deletions into this branch. I had restored an earlier session's staged work into the index - deleting packages/browseros-agent, archiving BR-OUTPUT prototypes - and then committed without a pathspec, so all of it rode along. That is what made the PR conflict with dev. Those files are restored to their merge-base state, which makes this branch neutral on them: dev's own later changes merge cleanly instead of fighting a deletion nobody here intended. The .archive copies go too - dev does not have them, so carrying them was pure divergence. The BR-OUTPUT prototype deletions are left as they are: dev has already dropped those files, so this branch agrees with it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
Closing: this PR targets the wrong repository, and merging it would undo a deliberate migration.
That is also the real source of the conflicts: The work is not lost — the branch
It belongs in gHashTag/trios at apps/trios-macos. One thing blocks that: apps/trios-macos The failing |
The Queen delegates to worker chats instead of coding. This is everything needed
to supervise that: the runner that actually starts a bee, the surfaces that show
what it is doing, and the harness that proves both without a provider.
Delegation
QueenWorkerRunnerstreams a worker turn on its own transport, so navigatingbetween chats cannot cancel a bee mid-flight
QueenBranchCommitterattributes edits through a throwaway index andcommit-tree; HEAD, the real index and the working tree are never touched.git checkout -bpreviously dragged the whole shared checkout onto one bee'sbranch - the exact conflict the branch exists to prevent
workingDirectory: ProjectPaths.root. The default is the user'shome, and one bee "successfully" created its file in an unrelated checkout
under
~/gitbutlerwhole-stream ceiling and killed a worker after seventeen successful tool calls
Supervision
QueenDashboardViewabove 760pt,QueenCompactSupervisorBarin the 400ptpanel the user actually keeps open,
QueenTaskBannerin each worker chatSystemNoticeseverity. Every system message rendered as a red error badge,so delegation success and provider failure looked identical
QueenObserverreads the live transcript for looping, spinning,out-of-bounds writes and overspending. A pure function over the transcript,
not a second agent: these patterns are mechanical, and a mechanical check
cannot hallucinate the way the thing it watches can
QueenSalience+SalienceLearnerrank the review queue by learnedintervention rate rather than age alone
Capabilities
SkillCatalog/SkillStore/SkillsTabViewmake.claude/skillsthesource of truth. The Queen could previously reach 4 of 26 skills because the
list was a Swift literal
QueenSystemPromptputs her role, commands and skill roster in her context.A capability the agent cannot see is a capability it does not have
QueenSelfAudit(/roadmap) greps type declarations against references andreports what nothing calls
Verification
ReplayTransportreplays SSE cassettes through the real parser. Acassette of decoded events would replay around the parser, where several real
defects have lived
make cassettesruns four in ~8s with no provider, and is part ofmake checkrepairOrphanToolCallssynthesises a result for interrupted tool calls, whichotherwise threw
AI_MissingToolResultsErrorand poisoned a conversation forevery later send. 8 bun tests
Testing
make- dev app buildsmake cassettes- 4/4bun test message-validation.test.ts- 8 passone file to its own branch, task moved to
awaitingReview, HEAD stayed ondevKnown gaps
tests/TriOSKitTests/remains broken (pre-existing,unrelated)
#effect:lines, filesystemeffects - but not provider behaviour
QueenObserveris proven by cassette, not yet by a live bee going wrong🤖 Generated with Claude Code