Skip to content

Create docs/queen-merge-loop.md describing when the Queen may merge a pull request and when she must wait - #7

Open
gHashTag wants to merge 198 commits into
devfrom
queen/1096-create-docs-queen-merge-loop-md
Open

Create docs/queen-merge-loop.md describing when the Queen may merge a pull request and when she must wait#7
gHashTag wants to merge 198 commits into
devfrom
queen/1096-create-docs-queen-merge-loop-md

Conversation

@gHashTag

Copy link
Copy Markdown
Owner

For gHashTag/trios#1096

Opened by the Queen for queen-swift.

gHashTagand others added 30 commits July 23, 2026 23:46
…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>
ClosesgHashTag/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.
ClosesgHashTag/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
Closesbrowseros-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
Closesbrowseros-ai#2047
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Closesbrowseros-ai#2047
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
gHashTag added 29 commits July 31, 2026 07:26
Eighteen call sites reached for QueenDelegationRegistry.shared, which reads and
writes the real .trinity state. Every command that makes the Queen do something
- delegate, approve, accept, review - goes through it, so none of them could be
tested without leaving tasks behind on whoever ran the suite. It is injected
now, defaulting to .shared; views and main.swift still observe the shared one.
The first coverage of delegation then found two things I did not know.
She refuses to open a task she cannot staff. With no worker runner configured
the delegation aborts and says why, rather than filing a task nobody will ever
start. That is the difference between a queue of work and a queue of
intentions, and it was undocumented.
And she creates a real git branch, because the registry is injectable but
ProjectPaths is not. The first run left queen/4242-do-a-thing and
queen/4243-do-a-thing in the checkout - and the cassette sweep no longer
collects those, having been narrowed weeks ago precisely so it would stop
eating branches that hold work. The test now deletes the three it makes, by
name.
The consent gate assertion was wrong twice before it was right. I first checked
it on the unstaffed view model, where no task opens whatever the gate does, so
deleting the gate entirely left it green. It is checked on the staffed one now,
where the gate is the only thing that can stop the delegation, and removing the
gate fails it. That is the third assertion in three cycles to pass for the wrong
reason, each caught only by mutating the thing under test - the habit is worth
more than any single finding it produces.
Verified: make, make cassettes, run_chat_sse_e2e.sh (392 checks, floor raised
from 385), make mutants, and the checkout has no queen/* branches afterwards.
…achable
The store-level output budget has been on the list for days as "can be read but
never set", and I had been treating it as dead code. It is not. It is half a
feature, and the missing half is a text field.
The evidence is the sibling. contextWindowMargin has exactly the same shape - a
published property, a loader, a setter that writes UserDefaults - and a control
in the Models tab wired to it. requestedOutputTokens has the property, the
loader and the setter, and no control anywhere: the key appears in one file and
nothing writes it. The symmetry says the design intends a global default the
user can set and a conversation can override, and only the output half was
never surfaced.
That changes the right action from deleting to wiring, and wiring means UI,
which wants someone looking at the screen. So this covers the behaviour instead:
a conversation with no override inherits the global value, an override beats it,
the view model reports the override exists so a control could offer to clear it,
and clearing falls back rather than to nothing. Removing the fallback fails two.
The day the field is added, what it depends on is already known to work.
Also removed a fallback written twice: `effectiveConversationOutputTokens ??
modelStore.requestedOutputTokens ?? 0` restates the fallback that
effectiveConversationOutputTokens already performs. Harmless while the store
value is always nil, which is the same defect from the other side.
Verified: make, make cassettes, run_chat_sse_e2e.sh (396 checks, floor raised
from 392), make mutants, no queen/* branches left behind.
…g from names
The boundary check reads the names of the tools a worker called, which cannot
see a write made through the shell: filesystem_bash is neither write-named nor
path-argumented, so `echo >` and `sed -i` have always been invisible. That was
asserted as a known blind spot rather than fixed, because closing it by reading
shell commands means parsing them, and a parser here would be one more thing
that guesses.
Measuring what changed needs no parser and no guess, and the machinery already
existed for the commit path: a tree snapshot is taken when a worker starts, and
the committer diffs against it. That diff is now available on its own as
changedPaths(since:), and outOfBoundsPaths takes an optional list of paths
something else knows changed, joining it with what the tool names imply.
Not wired into observeWorker, and that limit is worth being plain about.
observeWorker runs on every SSE delta; a git invocation per token would cost far
more than the warning is worth. So this closes the end-of-turn half of the blind
spot and leaves the mid-turn half open - a worker writing through the shell can
still spend its whole turn before anyone says anything, which is better than the
file silently never appearing but is not the warning I wanted.
Three assertions, including that the two sources are joined rather than one
replacing the other. Ignoring the measured writes fails two.
Verified: make, make cassettes, run_chat_sse_e2e.sh (399 checks, floor raised
from 396), make mutants.
changedPaths shipped last night with nothing calling it, which is the shape
this repository keeps producing and I keep deleting. It is called now, once,
where a worker's turn ends.
The gap it closes: the committer already drops files a worker was not allowed
to touch, so a shell write outside the boundary has always ended with the file
simply not being on the branch. Dropped without a word is indistinguishable
from work never done, and the worker had already spent the turn. The Queen now
names those paths in the same notice that reports what landed.
Only the measured half is reported here. Anything the tool names could see was
already announced during the turn by observeWorker, and repeating it at the end
reads as two separate problems, so this passes an empty transcript and adds
only what names cannot see.
The path mapping needed its inverse. git reports trios/docs/x.md and a boundary
is written as docs, so measured paths come down a level before comparison -
otherwise every file reads as a stray. A path outside the project keeps its
repository-relative form: it is out of bounds under any boundary and rewriting
it would only disguise where it is. Four assertions, including that the two
directions undo each other, which is the only reason to trust either. Stripping
the prefix without checking it is there fails two.
Verified: make, make cassettes, run_chat_sse_e2e.sh (403 checks, floor raised
from 399), make mutants.
`make mutants` shipped with three mutations and has stayed at three while I
verified perhaps a dozen guards by breaking them at the keyboard. Each of those
was proven exactly once, on the night it was written, and nothing has re-proven
any of them since. A safety net that covers a quarter of what it is believed to
cover is worse than one nobody trusts.
Four more, all guards I had already broken by hand and watched fail: the
observer ignoring what git measured, projectRelative stripping a prefix that is
not there, a disabled skill reporting itself as on, and the Queen's prompt
losing the names of the tools she may not call. Seven now, all caught.
The last one took two attempts, and the harness is what told me. My first needle
replaced prose around the interpolation and left `\(forbidden)` in place, so the
tool names still reached the prompt and the assertions still passed - reported
as SURVIVED, which is exactly right: the mutation was useless, not the coverage.
A mutation harness that says "your probe proved nothing" is doing the same job
for me that I have been doing for this codebase.
Chosen over the mid-turn boundary warning I put first on last night's list. I
had already written that I doubted it was worth building - a worker learns its
boundary at the end of the turn either way, and we have treated chat noise as a
defect before. Building it because it was next would have been the shape this
repository keeps producing: a capability nobody asked for.
Verified: make, make cassettes, run_chat_sse_e2e.sh (403 checks), make mutants
(7 caught), make mutants-logic (2 caught), clean tree afterwards.
Moved to .archive/ (gitignored). BR-OUTPUT now contains exactly
the 52-file lean whitelist from build.sh.
- Removed: AIMacroGenerator, AccessibilityEnhancements, AgentTaskBubbleView,
AnalyticsService, CommunityMacroMarketplace, ExtensionStoreAPI,
HotkeyAnalytics, HotkeyPreferences, MacroRecorder, MessageSearchOverlay,
NLHotkeyCreator, OnboardingFlow, OpenNLParser, PluginAPI, SearchOverlay,
VoiceCommandHandler
… first message
Pressing New Chat moved the user into a fresh conversation that appeared
nowhere. The sidebar draws whatever listAllConversations returns, and that
returns what has been saved - a new conversation was only a UUID held in
memory, so it showed up after the first message and not before. From the
outside that is indistinguishable from chat creation being broken, which is
exactly how it was reported.
The Queen's own conversation was already persisted empty on purpose, with a
comment saying so, and nothing did the same for the chats a user or the Queen
opens. This does.
It matters more now than it did: the Queen is meant to open one chat per issue
and watch her workers in them. A chat she cannot see in the list is a worker
she cannot supervise, and every delegation she made would have been invisible
until its bee said something.
Found by driving newConversation in the harness rather than reading it - the
first run printed a sidebar containing only "Trinity Queen" while the view
model was sitting in a different conversation entirely.
Verified: make, make cassettes, run_chat_sse_e2e.sh (406 checks, floor raised
from 403).
…s/agent-server
The agent runtime moved into trios/agent-server some time ago and the copy
under packages/ stayed behind. It was not a fallback: ProjectPaths points at
trios/agent-server with no alternative, and both live server processes run from
there. Checked before deleting rather than after, because 1516 tracked files is
not something to remove on the strength of a comment.
Forty-two references followed it - CI workflows, lefthook roots, the READMEs
and the contributing guide - all of them paths into the deleted directory.
CONTRIBUTING's directory diagram said "Chrome extension" where the agent used
to be, so that line now says where it went instead of describing a tree that no
longer exists.
Two mentions deliberately left. The HTML markers in test.yml identify an
existing PR comment; renaming them would orphan every comment already posted.
And browseros-agent-weekly.json is a real file that still exists under
trios/agent-server/apps/eval/configs/legacy - a filename, not a stale path.
Verified: make, make cassettes, run_chat_sse_e2e.sh all green after the
deletion.
…idebar
She delegates, a chat is created for the issue, and the sidebar showed only
"Trinity Queen". Every bee she started was invisible until it spoke.
Same cause as yesterday's New Chat defect, one layer along. The code renamed
the worker's conversation to "<issue> <title>" - and the comment above it said
the persister "materialises a conversation the moment messages are saved
against a fresh id", which is exactly right and exactly the problem: nothing
had been saved yet, so the rename landed on a record that did not exist. The
chat became real when the worker produced its first message, and until then the
Queen had a task in her registry pointing at a conversation nobody could open.
Saved empty first, then renamed, then the list reloaded. The sidebar now reads
"gHashTag/trios#4243 Do a thing" beside "Trinity Queen".
Proven by driving /approve and /delegate through runQueenCommand and reading
viewModel.conversations, not by reading the code - the first run printed a
sidebar containing one entry while the registry held a live task.
Still missing, and this is the next step rather than a caveat: the bees are
listed beside the Queen, not under her. There is no hierarchy in the sidebar
and no per-bee status in her chat.
Verified: make, make cassettes, run_chat_sse_e2e.sh (409 checks, floor raised
from 406), no queen/* branches left behind.
…one keeps its chat
Two defects in the sidebar, both of the same kind: a chat that quietly stops
being anywhere.
The Swarm section drew registry.active, which means "not terminal", and failed
is terminal. So the single state a supervisor most needs to see was the one
that removed the bee from her list the instant it happened. The registry
already draws the right line - `open` keeps a failure until somebody
acknowledges it, and the comment beside it says exactly why: a failure nobody
has looked at is still work, and filing it away silently is how it never gets
looked at. The sidebar was reading the wrong property, not missing a feature.
The second follows from fixing the first. The ordinary conversation list
excluded every chat that had a task at all, so once a task settled it left the
swarm section and did not reappear below - the chat existed and could not be
reached from the sidebar, and reading what a finished bee actually did was
impossible. It now excludes only what the swarm section is currently drawing.
Correcting my own claim from yesterday's log: I wrote that there was no
hierarchy and no per-bee status. There is. The Queen has her own section above
everything with a crown and a review-queue badge, and each bee row already
carries a status dot, the state in words, its issue and its branch. I asserted
otherwise without opening the file, which is the same read-free conclusion I
have spent weeks catching elsewhere.
Proven at the model level - active drops a failed task, open keeps it, a
cancelled one leaves open while its conversation remains. The view itself is
not driven by tests; the release app is rebuilt and relaunched so it can be
looked at.
The fixture was wrong once on the way: failed to accepted is refused, because
the state machine only allows failed to go to running or cancelled. Work that
fell over is retried or abandoned, not quietly approved.
Verified: make, make cassettes, run_chat_sse_e2e.sh (413 checks, floor raised
from 409), no queen/* branches left behind.
main.swift (902 → 643 lines, −29%):
- Extracted: TriosPanelMode.swift (80 lines) — panel mode enum + KeyWindow
- Extracted: TriosScreenManager.swift (72 lines) — screen management + NSScreen ext
- Extracted: CompositionRoot.swift (118 lines) — dependency injection
ModelHealthService.swift (1166 → 969 lines, −17%):
- Extracted: ModelHealthTypes.swift (202 lines) — ProviderQuotaStatus,
ModelHealthResult, ModelHealth, APIKeyValidationResult, ModelHealthServiceProtocol
Two defects in how a supervisor is told anything, both found by driving the
view model rather than reading it.
postQueenNotice appended to `messages` - whatever conversation is open. Callers
that arrive through a slash command were fine, because runQueenCommand switches
to her chat first. The ones that matter are the others: a worker finishing, the
observer seeing a stray write, the review scheduler waking. Those fire while
the user is watching a bee, so the Queen's words landed in that bee's chat -
the supervisor talking into the wrong room while her own chat stayed silent
about the work she was supervising. The correct routing already existed in
appendSystemMessageToQueenChat and half the callers used it; postQueenNotice
now delegates there.
That exposed the worse one. Routing correctly meant load, append, save - two
suspension points - and bees do not finish politely one at a time. Six
reporting together each loaded the same history, appended one line and saved,
so five were overwritten. The probe printed "Queen heard 2 of 6". Silently
losing four bees is worse than reporting late, and no amount of watching the
sidebar would have shown it.
Her chat is now held in memory while the user is elsewhere. Appending to an
array is synchronous on the main actor, so no two callers interleave between
reading and writing; only the save suspends, by which point every line is
already in. The load is re-checked after its await, because a second caller may
have filled the cache while the first was suspended.
Restoring the load-append-save form fails both assertions, so they can fail.
Also: the harness now compiles SessionGuard and CladeGuard. Both are ordinary
shipped sources that build.sh already includes; something under rings began
referring to them and the harness had never needed them before.
Verified: make, make cassettes, run_chat_sse_e2e.sh (418 checks, floor raised
from 413), no queen/* branches left behind. build.sh is modified in this
checkout by someone else and is deliberately not part of this commit.
…inity repo
QueenUILib dylib can now be used from Frameworks-dev/ (pre-built) instead
of compiling from trinity/apps/queen. Enables single-command builds on
machines without the trinity checkout.
Usage: TRIOS_VENDORED=1 ./build.sh or ./build.sh --vendored
…en's
Step 4 of the master-chat work, and the only one where the code was already
right. Context subsetting is the whole claim of the supervisor pattern - a bee
holds its issue, its boundary and its criteria, and nothing else - and it had
never been demonstrated. The runner loads only the worker's own conversation
and says so in a comment; a comment is not a demonstration.
Four assertions, driven rather than read. The Queen posts a distinctive line
while the user is standing in the bee's chat, which is where a user actually is
while a bee works, and is the case that until yesterday put her words in the
wrong conversation. The bee's history does not contain it, hers does, and the
bee's history does contain its own issue slug and boundary - that last pair
matters, because without them the negative check would pass just as happily
against an empty conversation.
The Queen and the runner share a persister here, as they do in the app. Two
separate stores cannot leak into each other, so an isolation test built on them
would prove nothing.
Restoring the old postQueenNotice - append to whatever chat is open - fails the
leak check and the one beside it, so both can fail.
Verified: make, make cassettes, run_chat_sse_e2e.sh (422 checks, floor raised
from 418), no queen/* branches left behind.
Four defects stood between an accepted task and a pull request. None was
visible from reading the code; each was found by running the cycle and asking
why it stopped.
Accepting made the task disappear. `task(forIssue:)` filters out terminal
states so `/delegate` refuses a second chat on a live issue - and `accepted` is
terminal. Opening the pull request is the step immediately after acceptance, so
the moment the Queen accepted, the lookup the next step used returned nothing,
that step said "I have no task for this issue" and returned. That single line
is why no pull request has ever been opened in this project's history.
`anyTask(forIssue:)` sits beside it for the steps that come after the end.
Nothing pushed. The commit path deliberately never touched the network and the
pull request path assumed the branch was already published; between them was
nothing at all, so GitHub was asked to open a pull request from a ref it had
never seen.
The pull request was aimed at the wrong repository. It used the issue's
owner/repo, but the issues live in gHashTag/trios and the code and every worker
branch live in gHashTag/BrowserOS. A pull request belongs where its commits
are; the issue is now a link in the body.
And the probe reviewed too early. It waited for the runner to drop its running
flag, but handleWorkerFinished commits the branch and moves the task to
awaitingReview after that - so /accept arrived while the task was still
running, which is not a legal transition. Every probe that ever "closed the
loop" was reporting a refusal as a state.
Underneath all four: this path failed silently. Three of its exits returned
without a word, so each attempt looked identical to nothing happening. They log
now, and that is what turned guessing into four straight answers.
Proven live, not in a harness: queen.pr.opened, PR #6, from
queen/1093-add-a-closing-line-to-docs-queen-spec, opened by the Queen after she
accepted a bee's work. The worktree stayed on feat/queen-supervisor throughout,
which is the branch-hijack fix holding up in a real run.
Verified: make, make cassettes, run_chat_sse_e2e.sh (422 checks).
…g when the Queen may merge a pull request and when she must wait
gHashTag added a commit that referenced this pull request Jul 31, 2026
The loop now runs end to end without a human touching it: the Queen briefs a
worker, the worker writes, the branch is committed and pushed, she accepts, the
pull request opens, the next poll merges it. Proven live, not in a harness -
#8, queen/1096-create-docs-queen-archive-rules-md merged into
feat/queen-supervisor, task state `merged`.
Three things stood in the way of the last step, and the first two were the same
mistake wearing different clothes.
The pull request was opened against a hardcoded `dev`. A bee's branch is cut
from HEAD, so basing it on a branch HEAD is not on produces a conflict that can
never resolve - which is exactly what #6 and #7 are, both CONFLICTING and both
unmergeable. Work lands where it came from, so the base is the checkout's
current branch.
Polling and merging still asked the issue's repository about a pull request
number that only exists in the checkout's origin. Creating had already been
corrected for that; the two steps after it had not, so even a mergeable pull
request would never have been found.
And the probe polled before the review, which is always before any pull request
exists - so the merge half of the loop had never once been reached. It polls
again after acceptance now.
A run in between refused with "the worker committed nothing, so the pull
request would be empty" - the worker had found the section already present.
That is the refusal working, and it was only legible because the silent exits
started logging last cycle.
Verified: make, make cassettes, run_chat_sse_e2e.sh (422 checks).
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@gHashTag