Fleet Harness — Delivery Board¶
Meet the team¶
Our build crew is a family of AI teammates — we call them by name. The name is the teammate; the "Runs on" column is the AI tool they work through. So when a task or review says Cedric did it, that's the teammate — the underlying tool is in the table.
| Teammate | Runs on | What they usually do |
|---|---|---|
| Clahadore Jones-Gaffney | Claude (Anthropic) | Planning, coordinating the work, reviewing, and the hard calls |
| Cedric "Cody" Jones-Gaffney | Codex / ChatGPT (OpenAI) | Writing code and giving a second-opinion review |
| Jenny Jones-Gaffney | Gemini (Google) | Writing code, research, and review |
| Gronktayvius "Gronk" Jones-Gaffney | Grok (xAI) | Tough adversarial review — trying to break things before users can |
All four share the surname Jones-Gaffney because they're family. Led by Andrew (Andrew David Jones-Gaffney).
Canonical board for the universal-harness epic (LangGraph over the C# fleet rails) and the council steal-list (2026-07-14 council: reject framework-as-brain for usage savings, steal contracts/policies; REVISED same day — outage continuity + career value make a scoped LangGraph supervisor a funded build).
Redundancy rule: this file + Vikunja (http://localhost:3456) + Jira (once trialed) move in lockstep on every status transition. This file is the source of truth until the other two prove sync.
Statuses: Backlog · Ready · In Progress · In Review · Blocked · Done
USABILITY VERDICT — 2026-07-15 22:5x CDT (WT-0026, night mode; council = authority)¶
The harness is USABLE. It shipped a real change to a real repo, end-to-end, tonight. This verdict replaces document-reading with an actual run — the earlier "~70%, blocked" read was assessed from docs and is superseded.
Evidence (one live run, python -m fleet_harness run --ticket FLT-14, NO --yes):
- Routed: implementer=claude, reviewer=grok — the blind reviewer seat convened.
- Isolated: created wt/FLT-14/harness-560d612e + its own worktree; registered the lock in the
worktree registry (which correctly DENIED a peer session touching it — the lock works).
- Validated itself: ran dotnet test and read the result — exit 0, 93 passed. FLT-3's
never-trust-agent-claims gate is real, not aspirational.
- HUMAN GATE EXERCISED LIVE, first time ever: printed Approve this work? [y/N], took y on
stdin, recorded approval:{approved:true}. The --yes bypass was NOT used. This closes FLT-1's
outstanding acceptance criterion ("human approval gate not yet exercised live; all runs use --yes").
- Output was CORRECT and landed: master 306d3d3. Verified against ground truth independently
(frontend fleet-live.service.ts listens for exactly GovernorTier/QuotaUpdated/RunUpdated/
WorkerHeartbeat — all four names the harness wrote).
- probe reports all 8 seats UP: codex, claude, gemini-flash, gemini-pro-high, grok,
agy-gpt-oss, agy-claude, ollama. 88/88 tests pass (grown from the 51 baseline).
Stale blockers now CLEARED:
- ~~"No remote / single-PC bus factor"~~ — fleet-harness now has andrewjonesdev-tools/fleet-harness.
- ~~"Human gate never exercised"~~ — exercised tonight, see above.
- ~~"FLT-63 councils unreachable"~~ — partially stale: gaming-pc council answered 200 tonight; all 8
harness seats probe UP. Streaming-pc (:37878) is genuinely down.
REAL residual gap — FLT-4. CORRECTED 2026-07-15 after reading graph.py:121-145; my first pass
here was sloppy and is superseded. Two kinds of blindness are being conflated, and they are severable:
- Blind to the IMPLEMENTER'S NARRATIVE — deliberate, correct, KEEP IT. The packet is spec + diff
- unverified test claims, with "no implementer narrative, no summary, no self-assessment" because "Reviewer anchoring on the implementer's confident prose is the failure mode this breaks". That is precisely the defense against FLT-4's own history (97/97 green, two self-reviews, unwired features shipped). Do NOT weaken this. The packet is also size-capped on purpose — a big diff trips third-party CLI input limits.
- Blind to the REPO — this is the actual gap. Grok reviewed tonight's run and said so itself:
"Event names ... could not be cross-checked against FleetHub.cs / FleetPollingService.cs ... in this
empty harness workspace", flagging
GovernorTieras the likeliest mis-name. It was right to be uncertain, and the risk was a false alarm — GovernorTier is correct (frontendfleet-live.service.tslistens for exactly those four). Five seconds ofgrepwould have settled it. It nonetheless returnedneeds_human_review:falsewhile listing risks it could not verify.
CORRECTION #2 (same session) — "point the reviewer's cwd at the worktree" is WRONG and would BREAK
the harness. Do not do it. graph.py:330-338 gives the second rationale I had not read:
"the reviewer is a full coding CLI — pointing it at the worktree would let it edit the very code we just
measured, invalidating the diff, the changed-file list, and the validation run that follows. Reviewers
judge; they do not touch." There is even a belt-and-braces check at graph.py:472 for a reviewer that
"somehow reached" the tree. So the empty sandbox is deliberate on TWO independent counts (anti-anchoring
AND write-isolation), and both are correct.
The gap is still real — grok needed FleetHub.cs, which is NOT in the diff, so the claim that "the
blind packet already contains everything a reviewer legitimately needs" does not hold for cross-file
fact-checking. But the fix must grant READ without WRITE.
Proposed fix (preserves BOTH defenses): give the reviewer a throwaway COPY of the worktree
contents as its cwd — not the live worktree. It can grep/read any file to check a fact; anything it
writes dies with the temp dir and cannot touch the measured diff, the changed-file list, or the
validation run. Packet stays exactly as-is (no narrative, size-capped), so anti-anchoring is untouched.
Cost is one tree copy per review — bound it (skip .git, node_modules, bin/obj) or reuse a detached
worktree at the same commit. A reviewer that cannot distinguish "this looks wrong" from "I cannot see
enough to tell" produces false alarms and, worse, false all-clears.
Also likely STALE on the FLT-4 entry: "agent worktrees not registered with the WorktreeOwnership
registry" — tonight the registry DID hold a lock (WT-044e owns wt/FLT-14/harness-560d612e) and
correctly DENIED a peer session touching that checkout. Re-verify before trusting that gap line.
FLT-6 anti-fork STILL unproven: only usage-governor/docs/agy-quota-policy.md (a DOC) mentions
routing.yaml. No second code reader. The shared-role-table property remains asserted, not tested.
Verdict for the Sunday deadline: the harness is usable NOW for real work with a human at the gate. It shipped a correct change to a real repo tonight and refused to take the implementer's word for anything.
UPDATE 2026-07-16 — the one blocker this verdict named is CLOSED (663c5c1). The reviewer now gets a
read-only copy of the source, so it can check facts instead of guessing at them, and still cannot touch
the measured tree. The remaining bar for UNATTENDED is now evidentiary, not architectural: nobody has
yet run the harness end-to-end with the fixed reviewer and watched it CATCH A REAL DEFECT it would
previously have missed. Until that run exists, "trustworthy overnight" is a reasonable expectation, not a
demonstrated fact — and this board's own history (FLT-4: 97/97 green, two self-reviews, unwired features
shipped) is the argument for demanding the demonstration. Next session: give the harness a task with a
planted cross-file defect and confirm the reviewer catches it. That is the negative control.
Ranked next steps: (1) ~~FLT-4 — throwaway copy as reviewer cwd~~ DONE — landed 663c5c1
(2026-07-16, implemented by codex, reviewed + independently test-verified by WT-0026).
_prepare_review_cwd() copies the implementer's worktree into the throwaway sandbox; reviewer cwd is the
COPY, never the live tree. symlinks=False so a link cannot escape back to the measured tree; entry/byte
caps fall back to the old empty-dir behavior rather than failing the ladder (so a huge repo degrades,
it does not break); partial copies are cleaned before fallback; every fallback path logs which one fired.
Packet unchanged — anti-anchoring intact. Tests 88 → 96 passed, 1 skipped, independently re-run.
The load-bearing test simulates a VANDAL reviewer that writes into its cwd, then asserts the real worktree
is byte-identical and the reviewer's new file does not exist there — it cannot pass vacuously, because if
cwd were the live tree the assert fails. Fixture is named FleetHub.cs: the exact file grok could not read. (2) FLT-6 — a second
CODE reader of routing.yaml (today: one code reader + one doc mention; the anti-fork property is
asserted, not tested). (3) streaming-pc seat (:37878 down; gaming-pc answers, all 8 harness seats probe UP).
Method note for whoever reads this: the previous "~70%, blocked" assessment was produced by reading docs, and three of its blockers were already stale (remote existed, gate worked, seats were up). This one was produced by running the thing. Run it before you rate it.
⚠ Board IDs and Jira keys are NOT the same numbering space¶
FLT-13 on this board and FLT-13 in Jira are different tickets. This board's IDs were
assigned by the 2026-07-14 council before the Jira trial existed; Jira then minted its own keys in
creation order, and the two sequences diverged the moment Jira imported the delivered work
(FLT-D1..D5) into keys 13–17 that this board was already using for live epic items.
Aligned: board FLT-1..FLT-12 ≡ Jira FLT-1..FLT-12 (same tickets, same numbers — coincidence of import order, not a guarantee).
Colliding — the board ID and the Jira key of the same number are unrelated tickets:
| This board | Jira key | What Jira's same-numbered key actually is |
|---|---|---|
| FLT-13 · Mission Control PWA | FLT-46 | FLT-13 = FLT-D1 worktree-identity |
| FLT-14 · Private IDE extensions | FLT-47 | FLT-14 = FLT-D2 usage-governor |
| FLT-15 · agy quota ledger | FLT-49 | FLT-15 = FLT-D3 fleet-dispatch |
| FLT-16 · CI tooling pack | FLT-60 | FLT-16 = FLT-D4 fleet-telegram |
| FLT-61 · Tavily narrow-adopt | FLT-61 | FLT-17 = FLT-D5 NATS fleet.v1 + MemBus |
Later entries (FLT-51, FLT-53, FLT-54, FLT-57, FLT-58, FLT-59, FLT-61, FLT-62, FLT-63) use the
Jira key as the heading — that is the convention going forward. New entries: title the section
with the Jira key, never a locally-invented number. Cite an old board ID only with its Jira key
attached (board FLT-13 / Jira FLT-46), because a bare FLT-13 is ambiguous across the two spaces
and will route a reader to the wrong ticket.
Reconciling the four legacy collisions (renumber the board vs. renumber Jira vs. leave the map) is FLT-11's job. Until FLT-11 lands, this table is the map.
Epic¶
FLT-1 · Universal harness: LangGraph/Deep Agents supervisor over all model CLIs — Acceptance VERIFIED — ceiling sign-off GRANTED (Sunday posture); gate 2 open by design; unattended gated on FLT-4 (WT-f255 built; WT-0924 reviewed 2026-07-14; WT-37e6 verified + signed off 2026-07-18)¶
ACCEPTANCE VERIFIED + ceiling sign-off GRANTED (WT-37e6, 2026-07-18, master 8b712b2). Ran the
suite under the repo .venv (Python 3.13.11): 26 passed, 1 skipped. The load-bearing test
tests/test_graph.py::test_acceptance_simulate_down_claude is not a mock-pass — it drives the REAL
compiled LangGraph (only the agent seats are faked) with simulate_down=["claude"] and asserts the
ticket still flows: implement→codex, review→grok (Claude skipped in the review ladder),
validation.passed True, and critically registry["claude"].calls == [] — Claude is TRULY never
invoked, not merely labelled down — then resumes through the human gate to approved. Sibling tests
prove the FLT-3 discipline: a failed implementer escalates AND its worktree is swept (half-edits
cannot leak forward), reviewer ≠ implementer always, and all-seats-down escalates to a human with
implementer=None (nothing pretended to work). routing.yaml confirmed on the exact Sunday posture:
ladder [claude, codex, gemini-flash, grok, agy-gpt-oss, ollama], max_pool_lockouts: 1,
agy-claude reserve_only + unreachable by any classifier. Verdict: the FLT-1 acceptance
criterion (a ticket flows route→implement→review→gate with the Claude CLI unavailable) is
demonstrably met; harness is usable now, attended. Gate 2 (fleet-global capacity ledger) stays
OPEN by design — per [[65c2553]] wiring the undercounting ledger is worse than NullLedger's
honest "unknown"; it is post-Sunday follow-up, not an acceptance blocker. Unattended operation
remains gated on FLT-4 (blind reviewer must catch a real planted defect) — a separate ticket.
Build a Claude-independent orchestration layer: LangGraph/Deep Agents supervisor (Python — stated
C#-first deviation: ecosystem-standard tooling + career skill acquisition + the orchestrator that
covers Claude outages must not depend on Claude) that routes ticket-sized work across codex,
claude, gemini (agy), grok CLIs and local Ollama. Supervisor model is swappable (any
provider) — that is the outage-continuity property. Executes through existing C# rails
(fleet-dispatch listeners, git worktrees, NATS trust tiers) via the FLT-2 contract; replaces no
working tool. Includes minimal mission-control UI (Agent Chat UI or LangSmith Studio local dev
only). Acceptance: with the Claude CLI unavailable, a board ticket still flows
route → implement (Codex) → adversarial review (Grok) → validation gate → human approval.
Driver: 2-day Claude outage this week (unacceptable); portfolio value.
Ceiling sign-off (WT-0924, 2026-07-14) — HELD, not a redo. Code is sound: FLT-3 discipline
throughout (git's answer, never the agent's), fresh worktree per escalation attempt (a failed
agent's half-edits cannot leak into the next), blind reviewer runs in a THROWAWAY EMPTY DIR
(reviewers judge, they do not touch — preserves the measured diff), approval_required halts the
graph rather than testing past a raised control point, no-reviewer degrades to mandatory human
review. Real-run codex --json fix = FLT-3 proving itself.
Blocking finding — correlated failure is live in code. routing.yaml ships
escalation_ladder: [ollama, codex, claude, gemini, grok], which predates the FLT-15/WT-df2d agy
research and contradicts it: Grok must precede agy-GPT-OSS (third scarce fixed-cap pool, not a
free lane); gemini is one lane where agy exposes four of differing scarcity; agy-Claude has no
reserve distinction, so a keyword classifier can reach the ~1-call/5h interrupt budget and
evaporate it. And graph.py treats rate_limited as "a transient vendor 429" and walks to the
next rung — the independent-capacity assumption. Per WT-df2d a locked-out agy pool transfers load
to Codex/Grok and ACCELERATES their limits, so the harness hands out bandwidth it does not have
exactly when pools are collapsing.
Gates to land: (1) FLT-6 corrects routing.yaml (order + agy lanes + agy-Claude as
governor-flag-only, unreachable by any classifier); (2) FLT-15 dependency — rate_limited must
consult the agy ledger for cap-proximity instead of assuming the next rung is fresh.
Gate 1 CLEARED + gate 2 seamed (WT-f255, 2026-07-14, 0491f9e). routing.yaml is now modelled
on pools, because seats are what we route and pools are what run out:
- pools (native-claude, codex, agy-gemini unified, agy-claude fixed-cap reserve, agy-gpt-oss
fixed-cap, grok, local) each with kind + scarcity + windows.
- The four agy lanes split out, model labels verified against live agy models (wrong labels
fail SILENTLY): gemini-flash (bulk), gemini-pro-high (escalate_only — SAME pool as Flash,
so never a fallback for it), agy-gpt-oss, agy-claude.
- Ladder corrected → claude, codex, gemini-flash, grok, agy-gpt-oss, ollama. Grok precedes
gpt-oss (third scarce fixed-cap pool, not a free lane).
- agy-claude is reserve_only: no ladder, no role, unreachable by any classifier;
--break-glass {native_red,review_gate,council_synth} appends it as the LAST resort and records
the reason in the gate packet. RoutingTable.validate() fails the build if anyone puts the
reserve on a ladder or makes it a role's primary — the config guards itself.
- review_ladder is family-distinct: agy's Claude lanes are Anthropic seats behind a Google
login, so name-only exclusion would let Claude review Claude.
rate_limited no longer means "try the next rung." A 429 locks the seat's whole POOL
(siblings share the cap and were never fallbacks). After max_pool_lockouts (1) distinct non-local
pools lock, the ladder STOPS and escalates to the human rather than spending pools whose
cap-proximity is unknown — deliberately pessimistic, since over-escalating during a correlated
collapse is the expensive failure and a human gate is cheap. One lockout is still survivable (a
single 429 is not an outage). CapacityLedger is the FLT-15 seam; NullLedger knows only what the
current run saw and answers cap_proximity() → None — unknown, said out loud, never a comforting
0.0. Lockouts live in graph state, so they survive node hops and checkpoint/resume without leaking
across runs. Gate 2 remains open until FLT-15's fleet-global ledger exists — this bounds the
damage, it does not measure capacity.
Gate 2 re-affirmed OPEN — do NOT close it by wiring the current ledger (WT-66db, 2026-07-15).
The FLT-15 ledger cannot answer cap_proximity() honestly yet, and a dishonest answer is worse
than None. Two structural holes, verified tonight, both biased the SAME direction — undercount:
- Not fleet-global. AgyConfig.SharedPath is unset in the live ~/.claude/usage-governor/config.json
(no agy block at all), so GovernorPaths.AgyLedgerPath() takes the local-BaseDir fallback.
Each PC counts only its own spend; see [[agy-gate-bypassed-by-skills]].
- Undercounts even locally. agy-wrap.ps1 still has ZERO production invokers (re-verified
2026-07-15: every agy-wrap hit across source
epos is a test, doc, CI file, or the wrap
itself). Skill-driven agy spend — /gemini-review, the council Gemini seat — calls agy.exe
direct and is never booked.
An undercounting ledger returns a LOW cap_proximity — "plenty of room" — exactly during the
correlated collapse gate 2 exists to catch, and graph.py would act on that number. This is the
Kerr shape ([[kerr-lens-standing-gate]]): closing gate 2 would reward "the ledger returns a float"
while hoping for "the harness knows real capacity." NullLedger's None — unknown, said out loud
— is the SAFER posture, and the build already got this right; wiring the ledger would undo it.
Sunday posture: ship FLT-1 usable on NullLedger + max_pool_lockouts=1. Acceptance (a ticket
flows route → implement → review → gate with the Claude CLI unavailable) does not require a ledger.
Gate 2 is post-Sunday and needs the two holes closed — shared UNC ledgerPath, plus the admit moved
into a helper the skills actually call — not a wire-up.
INDEPENDENTLY CONFIRMED, and the wire-up was built anyway before it was checked (WT-3e93,
2026-07-16). WT-3e93 built exactly the wire-up WT-66db forbade — GovernorLedger +
cap_proximity_skip=0.9 consumed in Router.is_available() — took it through a full 6-seat council
(2 High / 4 Medium found and fixed, 6 convergence passes), and only then rebased onto 65c2553 and
read this entry. WT-66db is right on both holes, and WT-3e93's own artifacts prove it:
- Hole 1 confirmed by measurement, not argument. The live ~/.claude/usage-governor/config.json
has NO agy block: ledgerPath and sharedPath are both empty, so the resolved path is the
local C:\Users\fives\.claude\usage-governor\agy-ledger.jsonl. The probe output printed that
local path and it went unread — the "fleet-global" premise was in the module docstring, never in
the config.
- Hole 2 confirmed by the numbers. Deployed agy-status --json reports gemini
spentWeekly: 83222 / 60000000 over 16 calls — ~0.2% — on a night this very session ran the agy
Gemini seat twice through agy.exe direct. capProximity came back 0.0019: a
four-PC-shared, months-old pool reporting itself untouched. That is the LOW-proximity
"plenty of room" failure in the wild, and cap_proximity_skip would have routed on it.
Held, not landed: wt/WT-3e93/FLT-15 is pushed for review but deliberately NOT on master. It
is the right code against a premise that is not true yet; landing it would trade None (honest) for
0.0019 (confident and wrong). Gate 2 stays OPEN. Revisit only once both holes close, and re-verify
the ledger is shared by reading the resolved path out of agy-status --json, not by reading the
code that supports one.
Landed prerequisite: agy-status --json (usage-governor master 2aba701, deployed + smoke-
verified on this PC via deploy.ps1; 249/249). It is orthogonal to the wiring question — a
read-only, versioned status contract that FLT-13's cockpit and any future gate-2 work both need, and
it makes nothing act on the undercount. Its ledgerPresent/capProximity: null semantics are also
what let a consumer say "unknown" out loud instead of inferring zero.
Steal list (council 2026-07-14)¶
FLT-2 · run_agent uniform contract as C# adapter layer — Done (WT-0bf0, 2026-07-14: landed master 3a027bb, 168/168 green)¶
run_agent(task, repo, branch, mode) → structured JSON (status ∈ completed/failed/timed_out/
rate_limited/approval_required, summary, changed_files, tests_attempted, known_risks,
needs_human_review) wrapping all four CLIs inside fleet-dispatch. Host owns timeouts, retries,
worktree creation, diff collection. This is the tool surface FLT-1 consumes — build first.
Shipped: IAgentRunner + adapters (codex/claude/gemini-via-agy/grok) in
fleet-dispatch/src/FleetDispatch.Core/AgentRun/; host-owned worktree ({repo}-agents/{jobId},
branch wt/{jobId}/{ticket}), 20-min default timeout, one retry, git status --porcelain -z diff
collection, and the FLT-3 validator. Two entry points: queue kind run_agent + CLI verb
run-agent. TOKENROI_CONTEXT=fleet-dispatch in child env. Schema frozen and documented for
FLT-1 in fleet-dispatch/docs/run-agent-contract.md.
Verified end-to-end (not just mocks): real codex run created a file in its worktree,
changed_files collected, summary extracted. FLT-3 gate proven live — codex reported "Succeeded
completely… All applicable tests pass" against a failing validator and the contract returned
status=failed, claim discarded, exit 1.
Council gate: Codex + Gemini + Grok seats, Codex chairing (local Ollama seat crashed OOM on the
64KB diff; house seats not run — gaming MCP transport dropped, streaming skipped under YELLOW
context-diet). 3 High fixed: status spoofing via classifiers on exit 0, unbounded/undeadlined
output drains, git option injection via base branch. Convergence pass then caught orphaned
descendants surviving the timeout → Windows job object. Real-run verification caught a wrong codex
--json event schema that every mock had agreed with.
Known gaps: agent worktrees not registered with the WorktreeOwnership registry; no GC for
abandoned {repo}-agents/*; mode recorded but not behavioral.
FLT-3 · Never-trust-agent-claims validation gate — Done (WT-0bf0, 2026-07-14: both halves landed — fleet-dispatch 3a027bb + llm-council 4f228d2)¶
Gate (council-code-review + FLT-2 host) reruns build/tests/lint itself; agent self-reported "tests pass" carries zero weight. Highest-ROI item, pure policy. Codify in the review skill and in FLT-2's validator.
Code half (fleet-dispatch 3a027bb): AgentRunValidator reruns build/tests itself and
records ACTUAL exit codes in tests_attempted; agent claims never consulted.
needs_human_review is only waivable when validation actually ran, passed, the diff is non-empty,
and no risks were recorded. Proven live — codex claimed "all applicable tests pass" against a
failing validator; contract returned status=failed.
Skill half (llm-council 4f228d2): council-code-review gains Round 4 — validation,
replacing the old Round 3 step "run the project's build/tests if they exist and are fast
enough" (which permitted verifying nothing). Now: rerun build/tests/lint yourself, take commands
from the repo's own entrypoints and name the source, paste cwd + command + exit code + evidence,
and a mandatory Validation block in the final report. The two halves are twins and must not drift
apart.
Council gate found the hole in the first draft — all three seats independently: "not a
subset… unless you say so" made disclosure into permission (run a fast subset, admit it, still
report passed). Grok also caught that Round 4 contradicted this skill's own seat contract,
which already teaches that exit code is not proof. Fixes are mechanical, not discretionary,
because the implementer IS the validator: subset/filter/0-tests → max unverified even when
disclosed; diff touching tests/mocks/CI → max unverified unless a real smoke ran and is pasted;
verdict = worst outcome any rule triggers; FAILED/unverified is not commit-ready.
Also closed en route: the tracked skill had been stale since 07-10 while the deployed
~/.claude copy gained four days of hardening (Ollama HTTP-API seat, canary probe, seat
validation contract, house-seat main-thread rule). Adopted as its own commit (35f5489) so the
policy diff stayed reviewable; live and tracked copies are now byte-identical.
Deployed fleet-wide 2026-07-14. All 4 PCs now run the same skill, verified byte-identical by
SHA256 (ACB17AAC…, 35317 bytes, 579 lines, frontmatter parses on each). Copied with scp
(byte-exact) — great-room, gaming (10.0.0.7), streaming (10.0.0.26), bedroom (10.0.0.36).
Fixed en route: streaming and bedroom were carrying mojibake — em-dashes corrupted to
replacement chars by whatever ad-hoc method placed the 07-10 copies (gaming was clean; that was
the 4-byte size difference that exposed it). The new file is dense with —/→/braille, so a
byte-unsafe deploy would have corrupted it again. scp fixed it as a side effect.
Not closed:
- Validation still runs from the agent's own tree, so an agent that weakens its own tests can
pass. The skill now caps that at unverified rather than pretending otherwise, but a true
independent oracle (pristine test pack) remains unbuilt.
- There is no standing skill-deploy mechanism. The 07-10 copies were placed ad-hoc, which is
exactly how the encoding corruption got in and how the boxes drifted 4 days behind. Today's
deploy was also manual — the next skill edit will drift again unless this is automated
(candidate: a fleet-dispatch job, since the rails now exist).
- The codex-harness-mirror carries a deliberately INVERTED council-code-review (Claude chairs,
Codex implements). It did not get the FLT-3 Round 4 policy — same never-trust argument
applies there and it is now inconsistent with this skill.
FLT-4 · Blind reviewer seat for llm-council — In Progress — built, NOT landed, does not meet acceptance (WT-aa8c, 2026-07-15)¶
Seat variant receiving ONLY spec + diff + test output — no implementer narrative — to break reviewer correlation/anchoring. Wire into /council-code-review as a standard seat.
Built by Codex on wt/WT-aa8c/FLT-4 (f2e31c1, unpushed). Codex reviewed it with its own seats
twice — "no blocking findings", 97/97 green. One independent vendor-distinct seat (Grok) then
found the feature IS NOT WIRED TO ANYTHING. Verified directly:
- SelectBlindReviewer — defined CouncilConfig.cs:111, called ONLY from tests.
- BlindCodeReview — defined CouncilEngine.cs:193, called ONLY from tests.
- CouncilEngine.RunAsync never reads IsBlindReviewer/ReviewMode/Family.
So reviewMode: "blind-review" has zero runtime effect — run the binary and Gemini gets
ordinary Stage 1/2/3. The blind pipeline is library helpers + unit tests + SKILL.md prose telling
an agent to do it by hand. 97/97 passes while proving nothing about the real flow.
Two deeper findings, both real:
- The no-narrative test is theater. It asserts by reflection that the prompt builder has no
parameter named narrative — the signature's shape, not the payload. Narrative still arrives via
caller-controlled ticketSpec, diff, or testOutput, and the prompt grants repo access
(scratchpads, BOARD notes, agent logs). This board previously recorded that pin as "structural";
that was wrong.
- "ACTUAL TEST OUTPUT" launders an agent claim as evidence. testOutput is a caller-supplied
string under an authoritative header the seat is told to trust. No capture wrapper, exit-code
binding, or runner stamp. This re-opens the FLT-3 hole upstream, inside the seat built to be
trustworthy. Real fix: the harness captures test output; the implementer never hands it over.
Also: only gemini is tagged blind-capable, so Gemini-authored work has no family-distinct
blind seat and selection throws (right instinct, brittle pool — tag several families). Families are
free strings with no load-time schema check, so a mislabelled Anthropic-behind-Google lane is taken
at face value.
Left for a fresh session, not bodged at 02:00 under RED: wiring blind selection into
CouncilEngine is a design decision (replace Stage 2 for that seat, or add a stage?) and deserves
one. Branch kept — the family/fail-closed logic and prompt builder are sound, just unconnected.
Meta-result worth keeping: one independent vendor-distinct seat caught a non-feature that a self-review passed twice. That is this ticket's own thesis, demonstrated on this ticket — and the argument for building it properly.
FLT-5 · Capability manifests in fleet-dispatch registry — Backlog¶
Per-PC manifest: GPU/VRAM/RAM, installed models + roles + context, CLIs, tools, max_jobs, online. Dispatch checks manifest before routing; improves Ollama routing (gaming=qwen3-coder primary, streaming=CPU heavyweights batch-only).
FLT-6 · Deterministic role-routing config + escalation ladder — In Review (WT-f255, 2026-07-14: table shipped)¶
Config (not code): implementation→Codex, architecture/deep review→Claude, browser/QA→Gemini, research/adversarial→Grok, high-volume cheap (triage/summaries/format checks)→Ollama; escalation local-small→local-large→cloud→independent reviewer→human. Shared by usage-governor, fleet-dispatch, and FLT-1 so all three read one table.
Shipped 2026-07-14 as fleet-harness/routing.yaml (repo root so the C# readers need no
Python package knowledge). Contains: roles table, keywords classifier, advisory_roles
(text-only roles that skip worktree/review/validation — the seam that lets the non-editing
Ollama seat own cheap-bulk), escalation_ladder, review_ladder (blind reviewer must be a
different vendor), timeouts. Read live by FLT-1. Outstanding: usage-governor and
fleet-dispatch must be pointed at this same file — until they are, this is one table with one
reader, and the anti-fork property is unproven.
Outstanding (2026-07-14, from FLT-15 council): the table models gemini as one lane, but agy
actually exposes four with different scarcity — gemini-flash (bulk default), gemini-pro-high
(escalate-only), agy-gpt-oss (burst overflow behind Grok, own small cap), and agy-claude
(out-of-band reserve, never routable by the ladder). escalation_ladder must be reordered to
… → agy-Gemini → Grok → agy-GPT-OSS → local, and agy-Claude must be expressible as a
governor-flag-only lane that no keyword classifier can reach — "hard task → agy-Claude" evaporates
the reserve. review_ladder's different-vendor rule needs family-distinct seats: agy-Sonnet/Opus is
a Claude seat, not a Google one.
Correlated-failure hazard for FLT-1 (2026-07-14, WT-df2d): the rungs are NOT independent capacity. When an agy pool locks out, load transfers to Codex/Grok and accelerates THEIR limits — correlated degradation, not graceful. FLT-1's availability probe + escalation MUST weight downstream pools by upstream cap-proximity, not treat each rung as fresh bandwidth; a model that assumes independent fallback overestimates total fleet throughput. Verify this in the FLT-1 ceiling sign-off before it lands.
FLT-7 · SARIF/machine-readable CI gates — Backlog¶
Security + accessibility + analyzer outputs emitted as SARIF/JUnit/JSON; thresholds enforced by CI before any expensive LLM review runs. Baseline-vs-PR comparison so legacy findings don't drown regressions.
FLT-54 · Ollama seat wrapper must fail loudly on empty/degraded output — Done (WT-aa8c, 2026-07-15: landed llm-council master 529ecd2)¶
The silent no-op: a RAM-starved ollama seat returned nothing and the council counted it as SUCCESS.
Ollama never errors when a model does not fit — it silently offloads to CPU, and the
"insufficient VRAM" signal is slog.Debug-only. The caller is therefore the ONLY place this can
ever be caught, which is why this is a wrapper fix and no admission gate or telemetry could
substitute for it.
Shipped: all four degraded shapes (non-zero exit, empty, whitespace-only, implausibly short) plus timeout now fail loudly at the single invocation seam every production seat call passes through, attributed with seat/model/host/condition. No fallback, no retry — council ruled loud refuse over silent degrade.
Council gate (Codex chair + Gemini + Grok, 3/3) + a Codex convergence pass. What the gate
actually bought, since this is the argument for keeping the gate:
- Exit-code asymmetry (all 3 seats). Empty output kept ExitCode 0 while merely-short output
got the -3 sentinel — the more severe shape was the one a caller reading the exit code would
wave through. It was non-silent only because Success separately checks emptiness, so the guard
would have quietly died the day someone simplified Success. Every unusable exit-0 shape now
carries the sentinel.
- Threshold (all 3 seats). 8 chars is indefensible: "I agree." is exactly 8. Now word count
+ char floor, centralized as CliResult.IsPlausibleAnswer so the rule cannot drift.
- Host attribution (Grok). An ollama seat pointed at another box via OLLAMA_HOST runs there
while the council runs here; MachineName named the wrong machine. The convergence pass then
found two real bugs in that fix (raw command tested before env expansion; substring match
catching not-ollama.exe) — now matched on the expanded basename.
- Temp-path injection (Codex). Config-controlled seat names landed in a filesystem path.
91/91 tests, rerun independently rather than taken on the builder's word; the exit-code guard is mutation-checked (revert the fix and it fails).
Deliberately not taken → FLT-57 (CliResult.Success should own the plausibility rule; ~15 fake
fixtures to rewrite, and prod has exactly one ICliRunner so the bypass is test-only) and
FLT-58 (council drops a failed seat and still exits 0 — pre-existing designed behavior, wider
than this ticket; a 5-seat verdict silently produced by 4).
Access + boards¶
FLT-8 · Mesh network: Tailscale pilot, Headscale decision gate — PHASE 1 DONE (WT-0924, 2026-07-15)¶
Phase 1 shipped 2026-07-15. Tailscale 1.98.8 on all 4 PCs, one tailnet, owner andrewjonesdev1@:
andygreatroompc 100.69.90.95 · andrewbedroomtv 100.85.245.95 · desktop-d249kd4 100.110.224.88
· desktop-scdt9hi 100.78.38.60. netcheck: UDP true, direct paths (not DERP-relayed; nearest
DERP Chicago) — bedroom verified direct 10.0.0.35:41641 with live traffic. Cost $0 (Personal plan,
unlimited own devices). Fleet installs ran via fleet-dispatch (--kind pwsh --payload-file; winget
elevated fine under the listeners); per-PC auth URLs written to
OneDrive\PC-Bootstrap\_shared ailscale\<PC>.txt, Andrew clicked each.
Two failure modes worth keeping: (1) tailscale login must run DETACHED — the auth URL dies with
its process, which cost three retries on the main PC; the fleet script starts it with Start-Process
so it survives the dispatch job. (2) --kind pwsh executes the payload as a SCRIPT — prose payloads
exit 1 with no useful error. Natural language needs --kind claude.
Outstanding (not phase 1): repoint hardcoded 10.0.0.x in council MCP configs, claude-mem, and
fleet-dispatch peers at MagicDNS names — until then the Wi-Fi-drift breakage class is only fixable,
not fixed. Phones (iPhone + Pixel Fold) not yet joined. Headscale decision gate untouched (only
pays off if tester seats would cost money).
Phase 1: Tailscale free plan on all 4 PCs + phone (unlimited own devices, $0, zero ops); testers
via node sharing. Kills Wi-Fi-drift breakage class via MagicDNS/stable addresses; SSH mesh + NATS
stay (Tailscale = connectivity layer, not exec/bus). Phase 2 gate: IF testers need full
membership (would cost $8/user/mo) OR self-host mandate → evaluate Headscale (self-hosted
open-source control plane, $0 license) with DR: config + SQLite state backed up nightly, warm
standby on second PC, documented failback. Decision recorded here before phase 2 spend.
FLT-9 · Vikunja hardening + DR (the self-hosted "Jira") — In Review — gates passed; one exposure decision open for Andrew (WT-aa8c, 2026-07-15: landed master 8ffa9c7; WT-37e6, 2026-07-17: PS 5.1 encoding fix 0f6a95a)¶
Nightly pg_dump -> OneDrive, restore verification into a throwaway container, healthz watch on
the claude-mem watchdog pattern, + Scheduled Task install/uninstall. Scripts proven against the
LIVE stack; the Scheduled Tasks are deliberately NOT registered — that would put live tasks on a
schedule unasked. One command away when wanted.
Council gate (Codex, adversarial) found 2 Criticals. Both real, both fixed:
- docker rm -f $TempContainer ran before anything proved the container was throwaway.
-TempContainer vikunja-db-1 would have destroyed the live board's Postgres. Now every removal
passes a label gate (flt9-throwaway=true, checked via docker inspect) plus a name-equality
refusal. Verified by extracting the REAL shipped guard functions and driving them against an
unlabelled stand-in: it refused, and the container survived. vikunja-db-1 carries no such
label, so it hits the same refusal. The guard was deliberately NOT tested by pointing a delete at
the live database — a guard you must risk the board to trust is not a guard.
- The dump was written inside the LIVE container's /tmp, so a mid-run failure left a full
dump (password hashes, tokens) sitting in it. Now removed in a finally on every path.
Stated deviation: the in-container temp file was KEPT rather than streaming pg_dump to stdout,
because PS 5.1 native-stdout redirection is not byte-safe for a SQL dump. Byte integrity beat
elegance.
- Also fixed: the live DB password rode on the docker.exe command line where local process
telemetry can read it (the container now resolves its own $POSTGRES_PASSWORD internally, so it
never appears host-side); docker cp ignored its exit code, so a truncated copy still logged
BACKUP OK (now byte-count verified); sh -c interpolated $DbName/$DbUser, so a hostile
param could execute arbitrary shell inside the live container (now allowlist-validated).
Verified independently, not on the agent's word: backup byte-matches (137849 bytes host ==
container); restore into the throwaway asserts 2 projects / 50 tasks / 1 user + real project titles
against a sidecar baseline captured from live at dump time, so it cannot pass vacuously by
checking the dump against itself; throwaway torn down; live vikunja-db-1 / vikunja-vikunja-1
untouched (10h uptime, healthy); live row counts unchanged; no /tmp residue.
OPEN DECISION FOR ANDREW — deliberately not made unilaterally. The dump is the FULL database (password hashes, API/session tokens, all user and task data) and lands in OneDrive, unencrypted. The ticket asked for OneDrive, so this is as-specified, and it is now documented plainly rather than buried — but it is a real exposure choice: encrypt at rest, keep local-only, or accept. Nothing is scheduled, so nothing syncs on a timer; dumps from tonight's proof runs are already in OneDrive.
Honest limit: restore verification checks projects/tasks/users counts + project titles. That proves the restore path works; it would NOT catch a future dump silently excluding labels, comments, attachments, or tokens. Deferred per ticket scope: second-PC warm standby, mesh exposure (blocked on FLT-8/Tailscale), agent API tokens, board-sync (FLT-11, owned elsewhere).
Update 2026-07-17 (WT-37e6): PS 5.1 encoding corruption fixed — landed master 0f6a95a.
Restore-verify false-failed under Windows PowerShell 5.1 (the host Install-VikunjaDrTasks.ps1
falls back to when pwsh is absent): Get-Content decoded the BOM-less UTF-8 .meta.json sidecar
as ANSI, mojibaking em-dash project titles and failing the known-project assertion (pwsh passed
the identical run). Root-causing exposed a worse writer-side bug: under 5.1 with the cp437 OEM
console (the Task Scheduler default), docker exec psql UTF-8 stdout is decoded as cp437, so
Backup-VikunjaDb.ps1 wrote mojibake sidecars corrupt at rest — hex-confirmed: em-dash stored
as the UTF-8 bytes of "ΓÇö". Fix: verifier reads the sidecar via [System.IO.File]::ReadAllText;
both scripts force [Console]::OutputEncoding to UTF-8 for the script lifetime (restored in
finally, try/catch for console-less hosts). The two corrupt 2026-07-17 sidecars (19:03, 20:17)
were repaired in place and re-verify green. Validated end to end, all exit 0: full restore-verify
under 5.1 + cp437 console, plain 5.1, and pwsh; fresh backup under 5.1 + cp437 writes true
E2 80 94 em-dash bytes. Gate: cavecrew-reviewer (0 findings) + 2-member gaming council
(qwen3-coder:30b, devstral:24b — 0 confirmed findings; note for future gates: the full 5-model
council fan-out exceeds the MCP transport timeout on both council PCs, pass a members subset).
FLT-10 · Jira Cloud Free + Rovo MCP trial (parallel, not replacement) — Backlog¶
$0 cloud tier, 10 users. NOTE: self-hosted Jira not viable (Server EOL 2024; Data Center pricing absurd for solo) — Vikunja (FLT-9) is the self-hosted lane. Trial: Andrew creates Atlassian account + site (agent cannot create accounts), then: FLEET project, agent-oriented statuses (Ready for Agent → Agent Working → Automated Review → Needs Human Review → Done), custom fields (Primary Agent, Review Agent, Risk, Branch, Run ID), Rovo MCP wired to FLT-1. Retire a board only after board-as-contract checklist passes: local export, stable ticket IDs, status transitions via API, token-roi hooks, offline fallback.
FLT-11 · Three-board redundancy sync — Done — WT-77c4, landed¶
Board sync: 2026-07-18T19:35:09Z — WT-77c4 moved FLT-11 from In Review to Done.
Board sync: 2026-07-18T19:09:59Z — WT-77c4 moved FLT-11 from In Progress to In Review.
Board sync: 2026-07-18T19:08:37Z — WT-77c4 moved FLT-11 from Backlog to In Progress.
This file + Vikunja + Jira kept in lockstep: small C# sync tool (or FLT-1 graph node) that mirrors ticket status transitions across all three; conflict rule = this file wins until Jira trial passes checklist, then re-vote. Every transition timestamps + names the mover.
FLT-51 · Skill/config deploy mechanism — byte-exact, hash-verified, drift-aware — Done (Jira key FLT-51)¶
Board sync: 2026-07-18T21:23:23Z — WT-4426 moved FLT-51 from Backlog to Done.
No standing way to deploy ~/.claude/skills (and peer config) across the 4 PCs. Every deploy is
ad-hoc, and that cost real damage twice in one day (2026-07-14, found by FLT-3):
- Silent staleness — the tracked skill sat at 07-10 while great-room's deployed copy gained 4
days of hardening never committed back; the other 3 PCs sat 4 days behind.
- Encoding corruption — streaming + bedroom carried mojibake (em-dashes → replacement chars)
from whatever ad-hoc method placed the 07-10 copies. Not cosmetic: the seat validation contract
matches on braille spinner glyphs (U+2800–U+28FF), so a mangled copy silently breaks the
check that catches dead council seats. A 4-byte size difference is the only reason it surfaced.
The non-obvious requirement: drift is bidirectional. A naive push tool would have destroyed
the good version — on great-room the live file was AHEAD of the repo. This cannot be a one-way
scp fan-out; it must detect unrecognized drift and refuse to clobber it.
Scope: canonical = the git repo, never a live ~/.claude file; byte-exact transport (scp-class,
NEVER Set-Content/Out-File — that caused the mojibake); SHA256 verify per target after write
with a printed match table (no "deployed" without an observed match — FLT-3 applies to this tool
too); drift check BEFORE write; idempotent. Rails exist: fleet-dispatch (kind pwsh or
run_agent) + the SSH mesh. C# in fleet-dispatch per standing language policy.
Acceptance: one command deploys to all 4 PCs and prints a per-PC hash table; a deliberately drifted PC is flagged, not clobbered; a file with em-dash/arrow/braille round-trips byte-identical (regression test for the real bug); a re-run reports no-op.
Also decide (don't assume): codex-harness-mirror carries a deliberately INVERTED
council-code-review. It is a variant, not a stale copy, so this tool must not overwrite it —
but it also never got FLT-3's Round 4 policy, so the two gates now disagree about whether an
agent's "tests pass" counts. Either the tool understands variants, or variants are explicitly out
of scope and tracked another way.
Origin: fell out of FLT-3 (llm-council 4f228d2). Same class as FLT-11 (keeping N copies in
lockstep) — the two may share a mechanism. ~/.claude/CLAUDE.md belongs in this tool's scope
too — see FLT-53, which is the same root cause found in the same place.
FLT-53 · CLAUDE.md drift: 3 PCs missing 4 standing policies, each with its own stale review-gate section — Backlog (Jira key FLT-53)¶
Found 2026-07-14 deploying the board-footer rule. Surfaced, not fixed — fixing means
overwriting hand-written content. The 3 remote PCs' ~/.claude/CLAUDE.md are NOT copies of
great-room's; all four differ (great-room 7510b; gaming 5904b; streaming 5480b; bedroom 5819b, all
remotes dated 07-11).
Two directions of drift at once:
1. Remotes lack four STANDING policies great-room has: language policy (C#-first — which
itself says "Applies on every machine, every model, every harness"), worktree/session
identity, model escalation ladder, usage governor. worktree-identity + claude CLI are
installed on all three, so sessions DO run there — without knowing about C#-first, the ladder,
or the governor's YELLOW/RED rules.
2. Each remote has a review-gate section great-room lacks, all three worded differently
("Review gate standard" / "Review gate (house standard)" / "Council review gate (standard)"),
and all three reference /council-review — a slash command that does not exist. The skill
is council-code-review. Three PCs point sessions at a non-existent command, three ways.
The board-footer rule was therefore appended as its own marker-fenced block
(<!-- board-footer-begin -->), built locally and scp'd byte-exact, leaving each PC's content
intact — verified block present + review-gate preserved + SHA256 match on all three.
Decide then do: which policies are genuinely fleet-wide vs deliberately great-room-only; reconcile
the three review-gate sections into one and fix the /council-review name; and whether CLAUDE.md
should be composed of marker-fenced blocks from a canonical source (the shape FLT-51 could manage)
with only machine-specific content local. Blocked on/related: FLT-51, same root cause.
FLT-13 · Mission Control frontend: Angular + NSwag PWA cockpit — In Progress — PHASE 1 SHIPPED + QUOTA SURFACE (Jira key FLT-46)¶
Phase 1 status wall DELIVERED 2026-07-14 (WT-df2b) in new repo fleet-mission-control
(local master, 2 commits, NOT pushed). ASP.NET Core net10.0 minimal API + SignalR /hubs/fleet
(WorkerHeartbeat/RunUpdated/GovernorTier, 5s poll) reading fleet-dispatch queues read-only +
governor state.json + Jira REST (60s cache). Angular 22.0.x pinned PWA, NSwag TS client generated
from build-emitted openapi/*.json (hub DTOs forced in via /api/meta/hub-events;
npm run check:drift = CI failure). 3-pane/dual-pane/card-stack via container queries, light+dark,
WW resilience interceptor. Verified LIVE against real dispatch data (4 workers probed, 50-run
stream, YELLOW governor, hub ● live). Council gate ran: seats Codex+Gemini+Grok+local qwen3:8b
+gaming:qwen3-coder:30b+streaming:llama3.3:70b (gaming devstral FAILED/canceled; local+house diffs
bounded); chairman 1 High (probe SSRF allowlist) + 6 Med + 5 Low — ALL implemented; backend 20/20,
frontend 19/19, builds green. Phase 2 (approve/reject) unblocked; FLT-14 unblocked for read-only panels.
Stack decision REVERSED 2026-07-14 by runoff council (unanimous 5/5 + 2 house seats, DECISIVE):
Angular latest + CI-generated NSwag clients beats Blazor InteractiveAuto. Deciding: time-to-cockpit
(usage bleed now), hub-DTO generation kills the type-drift argument (only hub method names stay
hand-written), Blazor prerender double-fire risk on the approve button, npm purity already dead at
the VS Code extension, McKinley innovation token already spent on the LangGraph harness. Flip
condition on record: heavy run_agent contract churn → revisit Blazor (contract is frozen, 168/168).
npm mitigations mandatory: lockfile + pins + private mirror + tailnet-only. Design/mockups unchanged
(visual language is stack-agnostic):
Design proposal: https://claude.ai/code/artifact/1849163f-6a8d-42a9-9c8a-d8a5e536a14c — steel/amber
ops cockpit. C# Blazor Server PWA on the tailnet (Tailscale Serve HTTPS; iOS + Android Tailscale
apps cover iPhone + Pixel 10 Fold, PWA install, no app stores). Responsive: desktop 3-pane
(fleet+queue | activity stream | approval gate), iPhone card-stack approvals, Fold dual-pane
unfolded. Phases: 1 status wall (SignalR read-only) → 2 approval gate (FLT-1 interrupt() +
FLT-2 approval_required) → 3 dispatch-from-phone → 4 VS Code extension panel.
Quota surface (added 2026-07-14 from FLT-15): the status wall is the natural place to make the FLT-15 agy ledger visible, because the ledger is heuristic — there is no quota API, so a human eyeballing drift is part of the design. Phase 1 shows per-pool gauges (native Claude 5h/weekly, agy-Gemini unified pool, agy-Claude reserve as remaining invocations not a percentage, agy-GPT-OSS, Codex, Grok) with the weekly cap rendered as the hard cliff it is, and a "reserve intact / spent" indicator for agy-Claude. Phase 2's approval gate is also where an agy-Claude break-glass invocation gets its reason code — the one human control point that keeps reason drift to "convenience" visible. Cockpit reads the ledger; it must never be a second writer (FLT-15's single-writer rule). VS Code fork REJECTED (TS/Electron 1.5M-LOC maintenance trap; IDE exists — gap is command & control). Native mobile SKIPPED (PWA + fleet-telegram push suffice).
✅✅ FLT-14 COMPLETE — 6/6 SURFACES LANDED ON MASTER (2026-07-16 22:5x)¶
adeb6a2 — VS 2026 extension landed. All six surfaces are real and receipted:
| Surface | Receipt |
|---|---|
| web/desktop, iPhone 17 Pro Max, Pixel Fold 10 | 236a73f, CI green, mutation FE 94.44% |
| VS Code + Antigravity x2 (ONE VSIX) | cc26da2, real extension host, VS Code 1.107.0 (the version the forks ship) |
| VS 2026 | adeb6a2, human click -> NavigationCompleted success=True — PIXELS RENDERED, then scroll confirmed docked |
The last two bugs were found by Andrew using it, not by any gate:
1. Style=Float 900x600 could not be resized at all. Now Style=Tabbed docked against Solution
Explorer (GUID 3ae79031-...), so it behaves like a normal VS tool window. The old code's comment
blamed Tabbed for a never-visible frame — that diagnosis was wrong; the frame was invisible because
of the programmatic auto-show, which no longer exists.
2. THE COCKPIT HAD NO SCROLL CONTAINER — ANYWHERE. Every overflow in the app was hidden for text
ellipsis or a gauge. So the moment the panes stacked (<600px: a phone, or the cockpit docked narrow
in VS) the stack was taller than the pane and the bottom was UNREACHABLE. Fixed 43c39bb
(overflow-y:auto on .cockpit-container; min-height:0 was already there, which is what lets a flex
child shrink and scroll). Pinned with a NEGATIVE-CONTROLLED test — remove the rule and it fails. 106->107.
This was broken on a surface already called "landed", and Lane A's screenshots could never have caught
it: a screenshot shows the TOP of a layout and says nothing about reaching the rest.
Council gate on the VS extension caught 4 real defects before landing (codex + own pass):
HIGH — missing bundled cockpit only logged exists=False then mapped+navigated anyway => BLANK cockpit,
all signals green. Now throws. HIGH — csproj packaged a VSIX with no cockpit behind a <Warning>; now an
<Error>. MED — WebView2 never disposed (owns a browser process + user-data lock) => leak per open/close.
MED — Loaded re-fires on EVERY re-parent, stacking duplicate inits; this fired live in testing 7s after
render, and it was a regression I introduced by removing a guard I had wrongly called a hack.
SESSION TALLY — 8 false success signals. frame.Show()==S_OK / IsOnScreen=1 / IsVisible=S_OK /
DocView==our pane all true while nothing rendered; VSIXInstaller exit 0 installing nothing; Stryker exit 0
running zero mutants (x2); a workflow "red X" that was actually zero jobs = CI fully off; council seats
"completing" with Argument list too long. Every real answer came from an artifact — a score, a file on
disk, a probe line, or a human looking at the screen.
✅ VS 2026 RENDERS. SOLVED 2026-07-16 21:48 — manual open works; my descope verdict was WRONG.¶
Andrew clicked View > Fleet Mission Control in a real Exp instance. Probe, verbatim:
21:48:13.937 Execute: on main thread, calling ShowToolWindowAsync
21:48:14.034 Loaded FIRED: control is parented, HWND exists -- starting WebView2 init
21:48:14.402 EnsureCoreWebView2Async OK -- WebView2 is live inside VS
21:48:14.405 virtual host mapping set: fleet.cockpit -> ...\media\webapp
21:48:14.406 Navigate() -> https://fleet.cockpit/index.html?apiBaseUrl=http%3A%2F%2Flocalhost%3A5170
21:48:14.520 NavigationCompleted success=True -- PIXELS RENDERED
Loaded fires, the control is parented with a real HWND, WebView2 initialises,
the virtual host maps the bundled Angular dist, and navigation completes. VS 2026 hosts the WebView2 cockpit
fine. DO NOT DESCOPE. The 6th surface is real.
What actually went wrong — all of it mine, none of it the platform:
1. Manual open works; programmatic auto-show does not. Every automated attempt used
ShowToolWindowAsync from InitializeAsync under [ProvideAutoLoad]. That path leaves the content
unparented (PresentationSource=NULL forever). A user-invoked .vsct command parents it instantly.
This is why the extension must open from a command, never auto-show.
2. MSYS mangled /rootsuffix into C:/Program Files/Git/rootsuffix on every bash launch, so devenv
opened the REGULAR instance where nothing was installed. Andrew's screenshot of VS's own
"these files could not be found" dialog is what exposed it. Launch via PowerShell Start-Process
-ArgumentList '/rootsuffix','Exp' — never from bash.
3. I sent Andrew to the wrong menu (View > Other Windows). The .vsct parents the group to
IDM_VS_MENU_VIEW = the View menu itself, priority 0x0600 (bottom). Lane C had documented this and
I did not read my own notes.
4. extensions.configurationchanged persisting was a red herring — the Extension Manager showed the
extension Installed + Enabled the whole time.
My "platform blocked, descope to commands-only" verdict was WRONG and is fully retracted. The council (codex/grok/gemini) refused it on VERIFIED grounds — no documented VS 18 bug, classic VSIX + ToolWindowPane + WebView2 is still supported — and they were right. Every "platform" symptom traced to my own harness.
Standing lesson: frame.Show()==S_OK, IsOnScreen=1, IsVisible=S_OK and DocView==our pane were ALL
true while nothing rendered. The only honest receipt was NavigationCompleted success=True — and it only ever
came from a human clicking. See [[verify-by-artifact-not-exit-code]].
FLT-14 · Private IDE extensions: VS Code + Visual Studio 2026 panels — In Progress — 4/6 surfaces landed; VS 2026 render unproven (Jira key FLT-47 · 2026-07-15 session WT-0026)¶
Scope corrected 2026-07-15. Requested as 6 surfaces (web/desktop, web/iPhone 17 Pro Max, web/Pixel Fold 10, VS Code, VS 2026, Antigravity). Actually 3 codebases: the Angular cockpit serves all three web postures; ONE VSIX serves VS Code + both Antigravity installs (product.json proves Antigravity = VS Code fork 1.107.0, gallery = open-vsx.org — so no separate Antigravity extension exists to build). There is no Antigravity 2.0 on this box (IDE 1.107.0, agy CLI 1.1.3); the "2.0 built from scratch" story came from content-farm blogs, not Google.
LANDED on master (repo now has a remote: andrewjonesdev-tools/fleet-mission-control, PRIVATE — it was
local-only until 2026-07-15, so CI had never run once):
- 774261e — web postures: viewport-fit=cover + env(safe-area-inset-) for Dynamic Island/home indicator.
- 0b8d416 — cleared 12 pre-existing master ESLint errors the repo's first-ever CI run exposed.
- 236a73f — fixed the dead Fold layout (see gate note below) + a safe-area overflow.
- c75883a — runtime backend origin: FLEET_API_BASE_URL (which NSwag already generated and the client already
consumed — app.config.ts just never provided it) now fed from window.__FLEET_CONFIG__; hub URL un-hardcoded.
106/106 tests, default same-origin behavior byte-identical.
- cc26da2 — VS Code + Antigravity VSIX (one extension, three installs). Proven with a REAL extension host
(@vscode/test-electron) on VS Code 1.107.0 — deliberately the version both Antigravity installs fork from —
4/4 passing, round-tripping a probe message OUT of the webview against the real 248KB ng build bundle. A
negative control (sabotaged CSP nonce) makes the probe fail, so it isn't vacuous. Distribution PRIVATE.
- 8473941 — docs: architecture (technical, file:line cited), architecture-plain (non-engineer), making-of.
6 Mermaid diagrams, all validated via mermaid.parse() (the CLI's puppeteer path was broken on a missing
webfont; the agent bypassed the renderer rather than declare it unverifiable).
- CI green both jobs (first green in repo history). Frontend mutation 94.44%* (255/270 killed).
cc26da2 CAUGHT FLT-13's EXACT FAILURE ABOUT TO REPEAT. Angular/beasties emits
<link rel=stylesheet media="print" onload="this.media='all'">. A nonce cannot whitelist an inline event
handler, so under the webview's strict CSP the onload is blocked, media stays "print", and the main stylesheet
never applies — the cockpit would render with critical CSS only while every string-assertion test stayed green.
That is FLT-13's false "rendered with CSS" verbatim, six weeks later in a different codebase. It surfaced ONLY
because the agent built the REAL frontend instead of trusting a hand-written fixture. See memory
nonce-csp-breaks-angular-deferred-css.
COUNCIL GATE CAUGHT A REAL DEFECT (the reason to keep the gate under deadline): the Fold two-pane code was
dead on the target device. @media (horizontal-viewport-segments: 2) fires only in Device Posture folded
(device bent to a book/tent angle); a Pixel Fold opened flat is continuous and reports 1 segment, so the
block never matched and the unfolded Fold fell through to the phone card-stack. 95/95 tests green, screenshots
taken, feature never ran — the FLT-4 pattern exactly. Fixed via 600dp width classes (Google's own compact/medium/
expanded), verified by screenshot (620px was card-stack, now dual-pane). See memory
viewport-segments-needs-folded-posture.
CI GATES LANDED 2026-07-16 (64e269d -> 0d20732, fleet-mission-control master). The FLT-16 pack
finally exists on this repo: 7 jobs — backend, frontend, extensions (its 38 unit + 4 real-extension-host
tests had NEVER run on push), inspectcode, semgrep, churn 5x, mutation. Codex implemented; verified locally
with real artifacts before landing: InspectCode 24 warnings -> 0 (via path-scoped .editorconfig
suppressions, NOT by renaming DTOs — see the Kerr note), semgrep SARIF 0 findings, churn 5/5 identical
(93 tests), backend mutation 80.60%, frontend 94.44%.
KERR TRAP DEFUSED, ON PURPOSE. All 24 InspectCode warnings are false positives. Gating on a raw
zero-warning count would have REWARDED breaking the wire contract: it wants Events5h->Events5H,
Pct5h->Pct5H on DTOs in Contracts/ that serialize to JSON, and the NSwag TypeScript client is
generated from that OpenAPI doc. Suppressions are path-scoped with the reason written next to each. 5h
means five hours; it is correct domain language, not a casing mistake.
I BROKE MASTER'S CI DOING THIS AND WANT IT ON THE RECORD. The first gates push was rejected by GitHub
at parse time — 0s, ZERO jobs, so nothing ran, not even the backend/frontend gates that worked before.
An ungated master that looks gated is worse than no gates. Cause: the runner context is valid ONLY at
STEP scope — not workflow-level env:, and not job-level either. My first "fix" moved it workflow->job
and I pushed that; still dead. Two runs, two 0s failures, three wrong hypotheses (I also wrongly suspected
unresolvable SHA-pinned actions — all three verified live). actionlint found it in seconds.
yaml.safe_load parses every broken variant happily; YAML-valid != Actions-schema-valid. I reverted master to
the known-good workflow first, then fixed and re-landed with actionlint proving it clean BEFORE the push.
The tell I missed for two cycles: gh run list prints the workflow FILE PATH instead of its name: when
GitHub cannot parse it. See memory actionlint-catches-dead-workflows. Follow-up: wire actionlint INTO the
workflow so a bad workflow can never silently disable CI again.
ACTIONLINT GATE LANDED 2026-07-16 (d4117cc). Deliberately a separate workflow file
(.github/workflows/actionlint.yml), NOT a job inside ci.yml: GitHub rejects an unparseable workflow before
scheduling any of its jobs, so a lint job inside ci.yml could never catch ci.yml's own parse error — it would
be theater. A separate file is parsed independently and still reports. .github/actionlint.yaml declares the
real self-hosted labels (read from the org runners API) instead of passing -ignore, because ignoring the
label rule would also blind us to REAL label typos — and a typo'd label doesn't fail, it queues forever.
Verified both directions, no ignore flag: clean on the repo (exit 0), and a negative control that
reintroduces the exact job-scope runner bug that killed master fails it (exit 1, correct line). The gate can
actually fail. Image digest read from docker inspect, not guessed.
MEASURED 2026-07-16 — the single-runner cost is no longer theoretical:
- The 7-job run (0d20732, 18:47) was still 44+ minutes in with 5 of 7 jobs QUEUED. The equivalent
GitHub-hosted 2-job runs earlier the same night: ~1m40s, green.
- home-ci capable: ["greatroom-tools"] — of three ONLINE org runners, only one carries the label.
ANDREWBEDROOMTV and ANDYGREATROOMPC do not.
- The mutation job failed after 39 minutes with every one of its steps GREEN (backend + frontend Stryker
both success), dying in post/cleanup with post-steps never completing. Logs already expired
(BlobNotFound) so the cause is unproven — but "all steps pass, job dies in cleanup" is an infrastructure
flake, not a gate finding. Consistent with one box serializing 7 heavy jobs.
ON REDUNDANCY / SWARM / K8s — the answer the data supports: "redundancy across one PC" is not redundancy;
it is a single point of failure wearing the word. But the gap is a missing label, not a missing orchestrator.
GitHub Actions runners are stateful agents that poll GitHub and execute jobs; there is no scheduling problem
for Swarm/K8s to solve here — GitHub IS the scheduler, and it already load-balances across every runner
carrying the right label. Adding home-ci to ANDREWBEDROOMTV + ANDYGREATROOMPC is a config edit per box and
buys 3x parallelism immediately; containerising the runners buys nothing on top of that and costs a
Windows-container story for .NET+VS tooling that is genuinely painful. A prior council already REJECTED
Swarm/K8s for the tool fleet (memory tool-ci-redundancy-4pc) — this data supports that verdict rather than
reopening it. Cheapest real fix, in order: (1) label the other two runners; (2) or move this repo back to
GitHub-hosted, which demonstrably works for the andrewjonesdev-tools org — the billing block in memory is
scoped to the PERSONAL account, and tonight's green runs were windows-latest/ubuntu-latest.
RESOLVED 2026-07-16 — the fleet now runs its own CI. NO GitHub-hosted minutes.
Was: 1 runner could take home-ci work, 7 jobs serialised on one box, 44+ min with 5/7 still queued.
Now: 6 org runners across 3 PCs, jobs land in parallel, gates green (backend, frontend, churn,
InspectCode, mutation all pass on the new boxes).
- Root cause was LABEL != GROUP. ANDYGREATROOMPC + ANDREWBEDROOMTV were already IN the home-ci
runner GROUP but lacked the home-ci LABEL — and runs-on: matches labels, not groups. greatroom-tools
had the label but sat in Default. Nobody was wrong about the intent; the wiring was crossed.
- Added runners to the two idle boxes: streaming DESKTOP-SCDT9HI (32c/94GB) had ZERO runners → 3;
gaming DESKTOP-D249KD4 (32c/47GB) had zero ORG runners (its only one was bound to the WorkWingman REPO,
invisible to the org) → 2, capped to leave headroom for the Ollama council models.
- Three real bugs surfaced only once jobs ran concurrently — a single serialised runner had hidden all of
them: (1) fresh runners fail EVERY powershell step with PSSecurityException until
Set-ExecutionPolicy -Scope LocalMachine RemoteSigned; (2) runners run as NETWORK SERVICE so they SHARE one
NuGet cache and concurrent restores collide — fixed in each runner's own .env, not workflow env, because
step-env covers only its step and job-env cannot use runner.* at all; (3) shell: powershell runs with
ErrorActionPreference=Stop, so docker's stderr progress lines became terminating NativeCommandErrors and
failed semgrep while the scan itself succeeded.
- Excluded until fixable, so they stop failing jobs: ANDYGREATROOMPC (ExecutionPolicy needs an elevated
shell) and ANDREWBEDROOMTV (SSH to 10.0.0.36 times out). Labels pulled; re-add after fixing.
- Remaining bottleneck: docker. Docker Desktop on Windows is per-user, so a runner service can't reach
another user's daemon. Only greatroom-tools is PROVEN to serve it, so semgrep + actionlint pin to the
docker label and serialise there. Widening needs a real per-box test, not an assumption.
- Not Swarm/K8s — GitHub is already the scheduler and load-balances across labelled runners. The gap was a
missing label and missing runners, not a missing orchestrator. Consistent with the prior council rejection.
See memory home-ci-runner-fleet.
SUPERSEDED — INFRA FINDING — home-ci is ONE runner, not four. All 7 jobs target [self-hosted, home-ci, windows]
(matching llm-council, the house pattern). But of three online org runners, only greatroom-tools carries
the home-ci label; ANDREWBEDROOMTV and ANDYGREATROOMPC do NOT. So the "CI redundancy across 4 PCs" intent
is not real — every job serializes on one PC, and CI dies when that PC is off. Worth deciding: label the
other runners, or move this repo back to GitHub-hosted (which demonstrably works — tonight's green runs
were windows-latest/ubuntu-latest; the billing block in memory is scoped to the personal account, and
andrewjonesdev-tools is a separate org that bills fine).
Also note: DOTNET_INSTALL_DIR was invented from a hint in my brief — llm-council does not use it at all,
so a follow-up could simply drop it.
IN FLIGHT:
- wt/WT-0026/FLT-14-vscode-ext — VSIX rebasing onto c75883a; deleting a fetch/XHR/WebSocket monkey-patch in
favour of a nonce'd window.__FLEET_CONFIG__ script; correcting distribution docs to PRIVATE sideload.
- wt/WT-0026/FLT-14-vs2026 @ b8dd99c — classic VSIX builds (needs FULL VS MSBuild; dotnet build fails),
33 tests pass, package loads (ActivityLog Begin/End package load), command dispatches, frame.Show()
returns S_OK — but WPF Loaded NEVER FIRES, so WebView2 init never even starts.
It has never rendered a pixel and is not claimed to.
Two of my own diagnoses here were WRONG — recording both so nobody re-buys them:
1. "The ctor-dispatch fallback is the bug." Removing it did NOT produce a render. It was a real bug (it
burns the single init attempt before an HWND exists, then _started swallows the real Loaded) and
removing it was correct — but it was not THE bug.
2. "Float vs Tabbed isn't the differentiator, because the spike used Float and also failed." Unsound —
with the hack present, the guard would have swallowed Loaded in that run regardless. I had no evidence
either way and asserted it as if I did. Float has since been tried and is not sufficient alone.
Also retracted (by the lane agent, correctly): "zero child HWNDs ⇒ WebView2 never attached." VS 18's MAIN
window also reports kids=0 — the whole shell is composition-based (same reason screenshots are black).
Zero children is normal here and proves nothing.
ANSWERED 2026-07-16 18:4x — IT IS NOT WEBVIEW2, AND VS'S OWN API LIES ABOUT IT.
Isolation spike: a plain TextBlock, zero WebView2, in a healthy Exp instance (483-707MB, responding,
correct title). Polled PresentationSource.FromVisual(this) every 5s:
t+ 5s loaded=False visible=False size=0x0 presentationSource=NULL hwnd=0x0
t+20s loaded=False visible=False size=0x0 presentationSource=NULL hwnd=0x0
frame.Show() hr=0x00000000, frame.IsOnScreen onScreen=1, and
frame.IsVisible S_OK (visible).
The WPF content is NEVER attached to a window - no PresentationSource, no HWND, IsVisible=False, forever.
So Loaded cannot fire, and EnsureCoreWebView2Async cannot complete (it needs a real sized HWND). Not a
sizing bug, not dock style, not WebView2. Show()==S_OK, IsOnScreen=1 and IsVisible=S_OK are FALSE
RECEIPTS - VS bookkeeping that does not mean the content rendered. Trusting them cost ~5 cycles chasing
WebView2. (Seventh lying success-signal of this session; see memory verify-by-artifact-not-exit-code.)
RETRACTED 2026-07-16 by council (codex/grok/gemini CLI seats, no house councils). MY "PLATFORM BLOCKED"
VERDICT WAS WRONG — DO NOT DESCOPE YET. Two seats independently, with VERIFIED citations:
- No documented VS 18/2026 breaking change exists for classic VSIX tool windows. Grok: "Known bug ->
UNKNOWN / NOT FOUND. Do not treat as platform defect until identity + command-path experiments fail."
Classic in-proc VSPackage + ToolWindowPane.Content + WebView2 is still the SUPPORTED WebView2 path.
- The real mechanism: WindowPane overrides IVsWindowPane.CreatePaneWindow, which is what creates the
HwndSource and sets RootVisual = Content. If the shell defers realization, that hook NEVER RUNS — so no
PresentationSource, no Loaded. Consistent with every symptom.
- I misread my own evidence: hwnd=0x0 on the control is EXPECTED BY DESIGN — direct-hosted WPF
content has no dedicated content HWND. It was never evidence of a platform break.
- Two likely causes, both OURS: (a) showing during [ProvideAutoLoad(NoSolution)] is too early — the
docking layout is not restored, so the frame exists but the pane is never realized; fix = defer to
KnownUIContexts.ShellInitializedContext or a real user-invoked .vsct command. (b) VsDockStyle.Float
puts the pane in a separate top-level frame whose realization the shell defers when shown early/inactive,
whereas Tabbed/Linked docks into the main window's existing visual tree and forces immediate realization.
- Also corrected: my claim that Remote UI "is WPF-only with no webview" is inaccurate (grok) — though the
Extensibility SDK still has no 18.x release, so classic VSIX remains the path regardless.
COUNCIL EXPERIMENTS RUN 2026-07-16 19:2x-19:3x — ALL FOUR HYPOTHESES ELIMINATED. Evidence:
19:33:10.740 ShellInitializedContext ACTIVE <- fired in 1ms: shell was ALREADY up. NOT too early.
19:33:10.923 OnToolWindowCreated: Content is CockpitToolWindowControl, sameInstanceAsProbe=True
<- grok's #1 (wrong instance) ELIMINATED
19:33:10.984 frame.Show() hr=0 / onScreen=1 / IsVisible=S_OK
19:33:10.986 VSFPROPID_DocView hr=0x00000000 value=VsixSpike.CockpitToolWindow isOurPane=True
<- the frame's CLIENT VIEW *IS* OUR PANE
19:33:10.987 VSFPROPID_DocData hr=0x80020003 (DISP_E_MEMBERNOTFOUND) value=NULL
t+5s..20s loaded=False visible=False size=0x0 presentationSource=NULL <- with Style=TABBED this time
KnownUIContexts.ShellInitializedContext; it was already active (1ms).
- NOT identity — OnCreate + OnToolWindowCreated both fire and sameInstanceAsProbe=True; we ARE
probing the object the shell hosts.
- NOT dock style — VsDockStyle.Tabbed behaves IDENTICALLY to Float, refuting gemini's [SPECULATION]
that Tabbed forces realization.
- NOT "frame is metadata only" — VSFPROPID_DocView is our CockpitToolWindow. Per codex's own
decision rule that means: VS created the logical pane and installed it as the client view, but failed to
HOST its WPF content. The fault is the IVsUIElementPane hosting step, nothing upstream of it.
Council value, honestly: they refuted my premature "platform bug" verdict and supplied the DocView probe
that pinned the fault — but two of three also produced APIs that DO NOT EXIST: gemini's
CreatePaneWindow override (CS0115 — and codex separately confirmed IVsWindowPane.CreatePaneWindow is
obsolete, superseded by IVsUIElementPane), and Tabbed-forces-realization was simply wrong. All three
independently found no documented VS 18 bug for this, and codex found Microsoft ships no VS 2026-specific
extension-creation docs yet — so "unsupported/undocumented" remains live, but "known platform bug" is
still NOT established.
FINAL PROBE — the shell DOES request the UI element, then does not host it. Codex identified the real
(non-obsolete) hosting contract: WindowPane implements IVsUIElementPane; IVsWindowPane.CreatePaneWindow
is obsolete. Re-implemented that interface on the pane to log it:
*** IVsUIElementPane.SetUIElementSite CALLED ***
*** IVsUIElementPane.CreateUIElementPane CALLED *** returning CockpitToolWindowControl
VSFPROPID_DocView value=VsixSpike.CockpitToolWindow isOurPane=True
t+5s..20s loaded=False visible=False size=0x0 presentationSource=NULL
IVsUIElementPane SHADOWS WindowPane's own implementation, so
in THIS run the hosting path is partly ours. The finding holds only because the earlier runs — on WindowPane's
stock implementation — failed identically. This run alone is not clean evidence.
REMAINING UNTESTED (only one left, and automation cannot do it): every attempt has shown the window PROGRAMMATICALLY. Nobody has opened it by HAND from View > Other Windows in an interactive VS. That is now the single discriminator between "VS never hosts a programmatically-shown pane" and "VS 18 cannot host this at all" — and it needs a human at the keyboard, not automation.
PRIOR NEXT EXPERIMENT (now done, see above): override CreatePaneWindow and log it; switch Float -> Tabbed;
defer the show to ShellInitializedContext. If CreatePaneWindow never logs, the shell is deferring
realization (our bug, fixable). Also assert ReferenceEquals(window.Content, control) and read
VSFPROPID_DocView to prove we are probing the object the shell actually hosts.
SUPERSEDED RECOMMENDATION (was premature) - descope the VS 2026 embedded cockpit. On VS 2026 Insiders 18.8.11925.187 a
programmatically shown ToolWindowPane.Content does not render. Ship the VS 2026 extension as commands only
(open the cockpit in a browser + status-bar state) - a real surface on the same backend - and revisit the
embedded cockpit at VS 18 GA or when MS documents the composition-shell hosting contract. The other 5 surfaces
already carry a real embedded cockpit. Untried leads: open the window MANUALLY from View > Other Windows (every
attempt so far was programmatic), IVsWindowFrameNotify3.OnShow, or ToolWindowPane.Window (raw HWND) instead
of .Content. See memory vs2026-classic-vsix-webview2.
PRIOR UPDATE 2026-07-16 12:1x - MY OWN "USE F5" RECOMMENDATION IS WRONG. Retracting it.
F5 does not use VSIXInstaller; it uses MSBuild's DeployExtension target. I set
<DeployExtension>true</DeployExtension> (the scripted equivalent of F5) and it fails immediately:
error VSSDK1048: Error trying to read the VSIX manifest file ...\obj\Debug\extension.vsixmanifest.
Could not load file or assembly 'System.Collections.Immutable, Version=10.0.0.8, ...'
Microsoft.VSSDK.BuildTools 18.9.820. Since F5 drives that same target, F5 would very likely hit the same
error. So "just open it in real VS and hit F5" is not the clean escape hatch I claimed it was. Anyone
trying it should expect VSSDK1048 first, and may need to fix the System.Collections.Immutable binding
(or find the version VS's own devenv resolves, since devenv may bind differently in-process) before F5 works.
Also newly observed: the Exp instance WEDGES ON REPEAT LAUNCH. Clean cycle (install → verify DLL on disk
→ /updateconfiguration → launch) gives pass-1 devenv healthy at 353MB responding; killing it and
launching again gives pass-2 stuck at 33MB, no probe, no load. That reproduces the "48MB empty title"
wedge seen earlier and is almost certainly what has been poisoning the last several attempts — it is a
property of repeatedly cycling the Exp hive, not of the extension.
THE BEST EVIDENCE WE HAVE IS STILL THE EARLY RUNS, when the hive was healthy and the package DID load:
21:02:59.966 ctor: control constructed
21:02:59.972 frame.Show() hr=0x00000000 <- S_OK, VS says the window is shown
21:03:00.008 CoreWebView2Environment created, runtime=150.0.4078.65
22:13:12.987 ShowToolWindowAsync returned: window=ok frame=ok (Lane C, later, hack removed)
22:13:12.989 frame.Show() hr=0x00000000
Loaded never fires. That is the finding. Everything since has been fighting the environment.
PRIOR UPDATE 2026-07-16 07:5x — hive REBUILT, and the experiment STILL has not produced a result.
Deleted both 18.0_7c1948ebExp dirs (Local + Roaming; the real 18.0_7c1948eb was never touched and is
fine) and recreated via /updateconfiguration. That fixed a real fault: devenv used to hang at startup
at ~48MB with an empty title; it now launches clean (351MB, responding, titled "Microsoft Visual Studio").
Reinstalled the TextBlock spike into the fresh hive — pkgdef registration is verifiably perfect
(CodeBase=$PackageFolder$\VsixSpike.dll, AllowsBackgroundLoad=1, AutoLoadPackages under the
NoSolution GUID {adfc4e64-...}, ToolWindow registered Style=Float) — and the package still never loads:
no probe line, no ctor. An extensions.configurationchanged marker is present, i.e. VS knows the extension
set changed but has not reconciled it.
Honest status: ~4 cycles spent on ENVIRONMENT faults (corrupt cache, hung devenv, timed-out chains,
MSYS arg mangling, a Remove-Item safety hook false-positiving on the VS path) and ZERO cycles that actually
answered the question. The question is still exactly: does ANY WPF content realize in a VS 18 tool window,
or is this WebView2-specific? Recommend the next session STOP re-running the same install/launch loop and
instead build the spike as a normal VSIX project opened in the REAL VS (F5 → Experimental Instance is the
supported, tooled path — StartAction=Program/StartArguments=/rootsuffix Exp are already in the csproj)
rather than driving VSIXInstaller + devenv from a script. The scripted path has now failed for four distinct
environmental reasons and is not earning its keep.
PRIOR STATE (superseded, kept for the record): the experiment was BLOCKED BY A CORRUPTED EXP HIVE.
The next test (strip WebView2 entirely, host a plain TextBlock, see whether ANY WPF content realizes —
if a TextBlock also never fires Loaded, this is VS 18 composition-shell hosting of ToolWindowPane.Content
and every further WebView2 cycle is wasted) could not be run. The Exp hive 18.0_7c1948eb**Exp** is
damaged after many install/uninstall cycles: ActivityLog shows CPkgDefCacheNonVolatileBase: PkgDef cache
creation failed. Going volatile and trying again., VSSDK\ResetExperimental.cmd exits 1 and does not
reset, and after a clean /updateconfiguration (exit 0, caches rebuilt 07:47) devenv still hangs at startup
at ~48MB with an empty window title. Package never loads; no probe line. This is an environment fault.
NEXT: rebuild the Exp hive from scratch (delete %LOCALAPPDATA%\Microsoft\VisualStudio\18.0_7c1948ebExp +
the matching %APPDATA% dir, then devenv /rootsuffix Exp /updateconfiguration), THEN run the TextBlock
isolation test. The real VS install (18.0_7c1948eb, no Exp suffix) was never touched and is fine.
One useful existence proof found: VS 18's own shell ships Microsoft.Web.WebView2.Core.dll in
Common7\IDE\PrivateAssemblies, so WebView2 demonstrably works inside the devenv process. The open question
is narrowly whether OUR tool window realizes its WPF content — not whether VS 2026 can host WebView2 at all.
VS 2026 path decided by spike (see memory vs2026-classic-vsix-webview2): classic in-proc VSIX + WebView2,
NOT the "modern" VisualStudio.Extensibility SDK — that SDK has no 18.x release and its WPF Remote UI cannot host
a webview at all, while Microsoft.VSSDK.BuildTools ships 18.x and VS 2026 ships v18.0 VSSDK targets. This means
ONE cockpit across all six surfaces instead of a hand-written WPF twin that drifts.
Distribution stays PRIVATE per the design below — sideloaded VSIX + tailnet gallery + fleet-dispatch to all 4 PCs. No marketplace listing. (An earlier brief in this session wrongly said "VS Code Marketplace + Open VSX"; nothing was published — corrected.)
Mockups in the FLT-13 artifact. Thin clients on the cockpit API — VS Code: activity-bar tree
(needs-you / running / queue / fleet) + status-bar gate + diffs open in the real editor (TS,
UI-only; logic stays server-side C#). VS 2026: C#/VS SDK docked tool window + status bar.
Distribution PRIVATE: sideloaded VSIX + self-hosted tailnet extension gallery (VS private
gallery atom feed; VS Code --install-extension), pushed to all 4 PCs by fleet-dispatch.
No marketplace listing.
FLT-142 · Vikunja board mirror + Option-1 failover — Done — deployed to all 4 PCs 2026-07-19 (WT-902b) (Jira FLT-142 · Vikunja proj 7/8 · master d1d1d0e)¶
Vikunja stood up as the third board-redundancy leg (Jira source + BOARD.md canonical + Vikunja derived mirror). One-way idempotent Jira→Vikunja sync (fleet-harness/ops/board-sync/), single-writer FleetBoardSync task on greatroom every 30 min (verified result 0; self-healing). Full mirror live: FLT (142) → Vikunja project 7, WING (86) → project 8. Codex review gate (6 findings, 3 HIGH on the restore path, all fixed). Backup leg = vikunja-dr VikunjaNightlyBackup (OneDrive) + VikunjaRestoreVerify (test-restore). Failover depth set by a 9-seat LLM council, unanimous Option 1 (rebuildable + replicated backup); hot HA rejected as over-engineering for a derived, minutes-to-rebuild mirror (report llm-council/reports/2026-07-19_003152_evaluate-the-right-failover-depth-for.md). Recovery on any PC: Rehydrate-Vikunja.ps1 -FromJira. Global ~/.claude/CLAUDE.md standing rule added. Known follow-up: vikunja-dr VikunjaHealthzWatch task fails to register (bad trigger duration — FLT-9 installer bug, flagged separately).
FLT-15 · agy quota ledger + agy-Claude reserve gate (usage-governor) — Done — Jira FLT-49 closed by Andrew 2026-07-17 after Raft HA landed; residual sub-items (skills-bypass undercount, fleet ledgerPath rollout, Raft deploy) tracked below, spin out new tickets if picked up (Jira key FLT-49 · Vikunja 48 · WT-902b, 2026-07-17)¶
Raft HA LIVE ON THE FLEET 2026-07-17 (WT-902b) — drill GREEN on real machines, single-writer authority replaced by the 3-voter Raft cluster + bedroom observer. Timing-stabilized (0 elections/9min). All 3 availability follow-ups (wedge watchdog, client peer-walk, E3 retro review) landed + rolled fleet-wide 2026-07-18 (usage-governor master 34418ed) — watchdog task Ready on gaming/streaming/bedroom, greatroom pending one elevated command. Runbook docs/RAFT-DEPLOY-RUNBOOK.md in usage-governor: usage-governor master → c553721 on origin
(the 10 gated commits from wt/WT-0026/FLT-17-raft-ha, tip c091939; post-land suite 273/273
green — the branch name's "FLT-17" is the legacy board-ID space, NOT Jira FLT-17). The admission authority's Raft HA (3 voters + stateless observer,
replicated quota ledger, leader-only admit, client AdmitId exactly-once) passed its final council
re-gate: the last open item — a minority-live-leader partition test (RAFT-BLOCKERS #4, a
still-running leader severed from the majority must not commit) — now runs as an executed
fault-injection test via a blockable outbound IConnectionFactory (dotNext
CustomTransportConfiguration seam; destination-side proxies provably cannot cut a dialing leader).
Negative-controlled 3 ways (no-block RED, inbound-only RED reproducing the historical failure,
executable NEGATIVE_CONTROL in CI); 273/273 green; seats codex+gemini+grok+local, codex chairman,
all findings fixed. **Raft stays opt-in (raft.enabled=false); live authority = single-writer on
gaming, untouched. Deploy = separate Andrew gate; pre-deploy gaps: WAL compaction (RAFT-BLOCKERS
2), Raft-port mTLS/firewall (#3).**¶
Follow-up 2026-07-18 (WT-902b) — Jepsen flaky-test fix committed 09184ae on wt/WT-0026/FLT-17-raft-ha (staged ONLY AgyRaftJepsenTests.cs): four converged-ledger asserts raced async follower-apply — AssertLedgersConverged reads every voter, but the tests waited on one node (or, for the happy path, not at all) before asserting, so a follower still applying committed entries could trip "expected N entries, found M" under full-parallel load. Each guard now waits on ALL voters (WaitUntil(cluster.Voters.All(v => Count == N))). Read-side race, independent of the E3 propose-timeout fix 3b33da0. Verified full suite 295/295 green + Jepsen class 8/8 under a stress loop. Local branch ahead of origin by 4 (b81270a, 2816953, 3b33da0, 09184ae) — held for the coordinated landing pass, not pushed.
Landed 2026-07-16 (2aba701, deployed + verified): agy-status --json, a versioned read-only
status contract (schema: agy-status/v1). The council pass turned it into one rule — the score
must derive from the same binding constraints as the gates — after finding four places where it
did not: Claude's locked read a display tier the gate ignores; Gemini's proximity ignored the
tapering floor (55% spend is ~92% of the way to denial under a 40% floor); weighted pools scored
against 100% when ComputeTier REDs at 85%; and the Claude reserve was counted as routable. Ledger
presence now comes from ONE open (TryReadSince) — the old Exists-then-read raced, and an
unreachable share threw instead of degrading.
NOT done, and this is the actual ticket: the ledger still is not fleet-global (no agy block in
the live config → local path) and still undercounts (skills call agy.exe direct, bypassing the
admit). Until both close, cap_proximity is a confident lie and must not be wired — see the gate-2
entry under FLT-1. The remaining work is a shared ledgerPath on all 4 PCs plus an admit helper the
skills actually call; the harness consumer already exists on wt/WT-3e93/FLT-15, held for that day.
Google AI Ultra Max ($200/mo, 20x Pro) exposes four fallback lanes through the agy/Antigravity CLI
that the fleet was not modelling: Gemini 3.5 Flash + 3.1 Pro (one unified pool, drawn at API
prices, 20x multiplier — the big pool), Claude Sonnet/Opus 4.6 and GPT-OSS 120B (separate small
fixed caps). Field-verified: one agy-Claude conversation burns ~60% of a 5h window even on Ultra;
windows are 5h refresh plus a weekly cap (Google copied Anthropic); credits are paid overage only;
no quota API exists. Probe-verified 2026-07-14: agy models lists all four; Sonnet + GPT-OSS lanes
answer live.
Council verdict (fable tier, ranking Claude > Grok > Codex > Gemini > local; report
llm-council/reports/2026-07-14_222458_fleet-routing-policy-question-context-researched.md):
- agy-Gemini = primary offload pool. Flash default; 3.1 Pro High escalate-only (second gate
failure, or security/architecture pre-escalate) — not the routine "hard" path.
- agy-Claude is NOT a ladder rung — an out-of-band interrupt budget: triple gate (native Claude
RED AND ceiling skip-list task AND no acceptable substitute), 1 call/5h window, ≤2-3/day,
gated on the weekly cap (the 5h refresh is a decoy at ~60%/convo), Sonnet-first, one-shot
print mode, size-bounded, no follow-ups (incomplete → Gemini Pro High, never a second Claude
call), reason codes (native_red/review_gate/council_synth) on every invocation.
- GPT-OSS-as-Haiku-lane REJECTED — it is a third scarce pool, not free relief. Burst overflow
behind Grok/local only; never an arbiter/correctness chair.
- Corrected ladder: Fable → Opus/Sonnet → Codex → agy-Gemini → Grok → agy-GPT-OSS → local ollama,
with agy-Claude out-of-band alongside it.
Build (C#, in usage-governor): fleet-global single-writer ledger — 4 PCs × N sessions share
one Google account, so per-session ledgers each think the pool is full and drain it 4x; must cover
every agy consumer (offload subagents, /gemini-review, the council Gemini seat, the
fleet-dispatch agy lane). Reserve units not percentages (no quota API ⇒ % is fake precision on an
unknown denominator): always ≥1 agy-Claude invocation held per window; Gemini weekly floor ~40% Monday
tapering to ~15% toward the weekly reset (floor covers remaining calendar exposure). Weekly-exhausted
= hard-deny state until rollover (else agents thrash every 5h and burn the remainder). 429s are ground
truth → recalibrate the ledger on every limit hit, distinguishing quota-lockout from transient
transport failure (misclassification either corrupts the ledger or triggers a retry storm).
allow_paid_overage=false default; floor = hard deny into the next tier, never "continue on credits".
Pre-route token estimate (a massive-diff one-shot can burn 100% of a window). Weekly agy models +
dry-run probe (labels/quotas drift silently; metering already regressed once in March 2026, so 60% is
a point-in-time number). Council accounting: agy-Sonnet/Opus counts as a Claude seat for the
≥3-frontier-seats family-diversity rule.
Feeds FLT-6 (routing.yaml grows the agy lanes) and FLT-13 (cockpit surfaces the ledger).
Memory: agy-multimodel-fallback-quotas.md. Gate via /council-code-review before landing.
FLT-16 · CI tooling pack fleet-wide (vuln gate + InspectCode + mutation baseline) — Done (Jira key FLT-60 · Vikunja 51 · WT-df2b, 2026-07-15: LANDED on origin/master, all 11 repos)¶
Standard analysis/security gates for every C# repo. Contract + rollout status:
usage-governor/docs/ci-tooling-pack.md (piloted in usage-governor, council-gated there).
Pack: (1) vulnerable-package gate — enforcing, fails the build; (2) InspectCode
(inspect.yml) — gates error-severity only (pilot: 177 findings / 0 errors; gating warnings
would red every repo on day one and train the fleet to ignore a red X); (3) Stryker
(mutation.yml) — report-only, weekly, staggered cron per repo; (4) npm audit + ESLint where
a real JS/Angular toolchain exists.
Mutation stays report-only ON PURPOSE. This infra scores VsTest socket timeouts as KILLED mutants — the usage-governor pilot run itself logged 3 timeouts at 72.40%. The WorkWingman council removed a broad enforcing gate on 2026-07-11 for exactly this; a fleet-wide threshold on the same infra would repeat that mistake at 10x blast radius. Promote per-repo only once the score is real and the runner is stable.
Council gate (pack template, 6 seats: Codex, Gemini, Grok, qwen3:8b, gaming qwen3-coder:30b +
devstral:24b; streaming llama3.3:70b FAILED at the 600s member cap). Chairman 0C/3H/4M/1L, all
implemented. The three Highs were real and would each have multiplied 10x:
- vuln gate failed OPEN — dotnet list package --vulnerable exits 0 when it FINDS
vulnerabilities but nonzero when it FAILS TO RUN, and a failed scan emits no > rows, so
parse-only reported a dead scan as a clean tree. Now checks $LASTEXITCODE first (verified:
broken sln → exit 1, rows 0 → old version passed green).
- floating dotnet tool install -g on persistent runners → results depend on leftover profile
state / whatever NuGet serves. Now pinned via .config/dotnet-tools.json + tool restore/tool run.
- identical Monday 06:00 cron in all 10 repos → hour-long jobs dogpile the shared home-ci pool,
contradicting the workflow's own anti-starvation rationale. Now staggered (table in the pack doc).
Verified per repo by the orchestrator, not on the agent's word (FLT-3): fleet-dispatch 179/179, fleet-telegram 211/211, worktree-identity 207/207, token-roi 127/127, membus 101/101, llm-council 69/69, PavlokPager 59/59, claude-mem-house 31/31, audio-loop-mcp 22/22, WorkWingman build+gate, usage-governor pilot (Stryker 72.40%). 0 vulnerable packages fleet-wide.
Implementation offloaded to Codex (governor hit RED mid-sweep — projected 173%; Claude routed, reviewed and verified only).
Open: (a) all 11 branches UNPUSHED — awaiting land decision; (b) claude-mem-house has a
stronger gate than the rest (asserts a positive clean-scan marker, so an exit-0 scan printing
nothing can't read as clean) — backport to the other 10; (c) stryker-js does not bootstrap against
Angular's builder-managed vitest ("No tests were executed") — frontend mutation parked, not claimed;
(d) fleet-mission-control mutation baseline 39.19% needs real tests.
Follow-on (2026-07-15, WT-975b): test-impact-analysis for the pack's Stryker component — RESEARCHED,
REJECTED, no work to do. Question was whether to scope mutation runs to changed code (TIA / affected-test
selection) via GHA or MCP. Council convened (llm-council opus, 5/5 seats; report
llm-council/reports/2026-07-15_195506_what-tooling-exists-to-pinpoint-test.md). The council's verdict is
moot and the log carries a correction block — do not act on it. Measurement afterward killed the premise:
--coverage-analysis perTestis already the default. Stryker.NET's documented default ISperTest(https://stryker-mutator.io/docs/stryker-net/configuration/). All 11 backend configs leave the key unset, i.e. they have been running perTest all along. The council's #1 "free headline win" is a no-op.- No .NET mutation bottleneck exists. Real durations 2026-07-15: llm-council 2m35s (75 tests), membus 3m15s (67), claude-mem-house 5m14s (26), usage-governor 10m48s (157), audio-loop-mcp 15m23s (16). Separate repos → they run in parallel; fleet mutation wall-clock ≈ 15 min, bounded by the slowest single repo. TIA buys a few minutes against false-negative selection risk + stale-baseline score inflation. Bad trade.
- No MCP server exposes TIA / coverage-diff → affected-test selection today (unanimous, and verified — Datadog/Develocity/Codecov/Sonar MCPs expose coverage queries, no selector). Nothing to adopt.
- Verified NOT broken while measuring: staggered crons are real (Mon 06:00 usage-governor / 10:00
llm-council / 12:00 membus / 20:00 claude-mem-house — the High from the pack council holds);
audio-loop-mcponly appears to lackmutation.ymllocally (checkout 2 commits behind origin — it is on origin/master).
Kerr note for whoever revisits this: the reward here is minutes-saved/tests-skipped (countable, dashboard- friendly); the goal is regressions caught (a non-event nobody gets credit for). If TIA is ever reconsidered, escape rate — mutants/tests failing a nightly unscoped run that a scoped run skipped — must be published beside minutes saved, or the number is meaningless. Stryker baselines invert the metric outright: a stale baseline raises the reported score while real coverage decays. Baseline TTL + expired-means-full-run is the mitigation, and it is not optional garnish.
WorkWingman mutation CI — NOT part of FLT-16. ⚠️ This entry was written wrong TWICE (claim, then retraction). Third version, timestamp-verified. If you are reading a "capacity" explanation anywhere, it is the bad one.
What was actually true. Commit b606a93 (2026-07-08, "route jobs to the self-hosted warm pool") moved 8
ci.yml jobs and both mutation.yml jobs onto [self-hosted, workwingman, linux, docker, x64] when cloud
minutes ran out. It pointed them at a designed pool of one Linux Docker runner + one Windows host runner per
PC. The Windows half was registered. The Linux half was never built, and no provisioning code was ever
committed. For a week, no runner matched the linux label, so those ten jobs per run queued until GitHub's
24-hour limit cancelled them. mutation.yml: 17 cancelled, 0 passed, ever. Any mutation score attributed to
CI predates this and did not come from CI. (Source: .github/runner/README.md, PR #23.)
Timeline (verified against commit timestamps and docker inspect, not inferred):
- 2026-07-08 — b606a93 routes 10 jobs to a linux label with nothing behind it.
- 07-08 → 07-15 23:11 CDT — every one of those jobs queues to the 24h limit and dies. This is the window of
the failures this entry set out to diagnose.
- 2026-07-15 23:11:49 CDT — peer session lands 0f787ef "provision the Linux runner the workflows already
required" (Dockerfile + start-runner.ps1 + README). Container ww-andygreatroompc-linux starts 41
seconds later at 04:12:30Z.
- 2026-07-16 02:15 CDT — peer lands 228c3cf, raising the container cap 5g → 6g for StrykerJS.
- 2026-07-16 04:22:25Z — mutation-gate (run 29467990821) executes for the first time in the repo's history.
- 2026-07-16 04:54:37Z — killed at 32 min by cancel-in-progress when push 6cab516 landed at 04:42:43Z.
Three wrong calls, and why. Read this part; it is worth more than the finding.
1. ~~"Nothing answers that label set."~~ — Was RIGHT for 07-08 → 07-15 23:11, i.e. for exactly the failures
being diagnosed. It only became false 34 minutes before it was checked, because a peer had just fixed it.
2. ~~"The runner is online, labels match — the cause is capacity."~~ — The retraction was itself WRONG. The
runner was online (34 min old), but there was never a capacity problem: there was a nonexistent runner.
Retracting a correct claim on a 34-minute-old observation is the worst error in this entry.
3. ~~"No OOM: zero memory errors in the log, container never restarted."~~ — Invalid method. Per
start-runner.ps1: a worker killed by the cgroup OOM killer does NOT set the container's OOMKilled flag —
only PID 1 dying does. The starvation is invisible to exactly the two measurements used, and surfaces as
Stryker's opaque "Test runner crashed." The peer's 5g→6g raise was the real fix.
Root cause of all three: sampling a system a peer session was actively repairing, and reading their in-flight
fixes as findings. Each diagnosis was published confidently and overturned within the hour. Contributing
artifact: GitHub reports run status as queued while any job in it still waits, so
runs?status=in_progress reads empty while a job is demonstrably running — run status ≠ job status; query
/actions/runs/<id>/jobs. Before diagnosing shared infra: check git log for peer commits in the window, and
date every observation against them.
Frontend mutation 94.16% on record is not merely stale — it never came from CI (local run 2026-07-15 measured 24.12%). CI had never run it.
Method lesson: five seats debated Coverlet attribution semantics and baseline TTL design for ~10 minutes of
wall-clock; a 10-minute gh run list would have ended the question before it was worth asking. Measure the
bottleneck before convening a council about it — a council will argue your premise, not tell you it is false.
Note also the chairman seat and the top-ranked seat were the same lineage ("4-of-5 ranked A first" reads more
independent than it was), and both house councils were unreachable (gaming dropped on FLT-63, streaming never
queried), so no non-Anthropic lineage checked this.
FLT-61 · Tavily narrow-adopt: shared C# web-search MCP wrapper on membus — Backlog — blocked on BYO key (Jira key FLT-61 · WT-8f94, 2026-07-15: council-approved, not started)¶
Council verdict (llm-council opus, 5/5 seats converged independently): NARROW-ADOPT. Report:
llm-council/reports/2026-07-15_103940_should-we-adopt-tavily-the-llm-oriented.md.
The gap is NOT search for Claude — WebSearch/WebFetch + the grounded Gemini/Grok seats already cover research at zero marginal cost. Three real gaps: (a) deployment — Codex and Ollama have no web tool at all, and a local model doing RAG has zero grounding today; (b) capability — WebFetch is one-URL/one-prompt, there is no primitive for "ingest all the NATS docs", so map/crawl is the actual purchase; (c) council parity — non-Claude seats can't cite the evidence the Claude seat saw. Capability purchase = crawl/map/extract; deployment reason = Codex/Ollama. Conflating the two is how this creeps into a paid fleet-wide default.
Scope: free tier only (1,000 credits/mo, alert at 800, no PAYG without an explicit decision) ·
one key server-side behind a C# MCP server on the membus, generic IWebSearch + Tavily adapter so
Brave/Exa/Firecrawl are a config swap · basic search + extract for Codex/Ollama, map/crawl page-capped
on demand · research and advanced hard-denied at the wrapper · wrapper owns credit ledger,
URL-hash cache, page caps, truncate-to-disk, shared rate limiter, per-seat quotas · fallback native →
Tavily basic → WebFetch → fail loudly.
NOT in scope: per-seat keys (ever) · routing Claude/Gemini/Grok through it by default (double taxation — you pay Tavily credits and model tokens, converting a free search into a paid one) · the vendor MCP server as permanent surface (fine for a time-boxed trial; it hands every seat a raw key with no credit accounting, exactly what the governor prevents) · a JSON-schema extraction gateway (Tavily returns cleaned page content, not schema-conformant objects — the Ollama seat proposed this from a misreading; four seats caught it).
Sharpest failure mode: the Research endpoint burns up to 250 credits in ONE call = 25% of the monthly free tier. Hard-deny it. Others: free-tier exhaustion blinding Ollama mid-overnight, crawl-loop burn, shared-key 429 starving the fleet, wrapper crash blinding seats (must degrade loudly, never hallucinate), scope creep to the Claude seats. Lock-in: near-zero — search+extract is a commodity; the only real lock-in is behavioral (prompts learning Tavily's result shape) and the interface kills it.
Unverified — do not propagate: Grok asserted (unsourced, uncorroborated) that Nebius acquired Tavily Feb 2026 and that 2026 benchmarks rank Brave/Exa/Firecrawl above Tavily. Chairman refused to certify both. Free-tier-only prices in roadmap risk either way; the exit condition is a head-to-head on our own query mix, not a leaderboard.
Exit condition: sustained >800 credits/mo → Brave/Exa head-to-head on our real query mix before paying anyone. Blocked on: BYO credentials — Andrew creates the account and supplies the key.
Caveat on the run: both house open councils were unavailable (streaming-pc MCP never connected;
gaming-pc transport dropped mid-call twice), so this verdict rests on the 5 CLI seats with no
open-model corroboration. Codex's peer-review pass also crashed on non-ASCII stdin
(input is not valid UTF-8 (invalid byte at offset 2745)) — same root cause shape as the FLT-16
PowerShell non-ASCII bomb, unticketed as of this writing.
FLT-62 · llm-council writes child stdin in the ANSI codepage, not UTF-8 — In Review — gate PASSED, awaiting land + republish (Jira key FLT-62 · WT-8f94, 2026-07-15: 2377379 on wt/WT-8f94/FLT-62, NOT pushed)¶
src/CliRunner.cs:67 pinned StandardOutputEncoding/StandardErrorEncoding to UTF-8 but never
StandardInputEncoding, so Windows wrote child stdin in cp1252. Every stage-2 review prompt (which
embeds other seats' answers — LLM prose full of em-dashes and smart quotes) crossed the pipe
corrupted. Codex refused it outright (input is not valid UTF-8, invalid byte at offset 2745) and
the council continued with 4/5 review seats and still exited 0.
Worse than the error suggests, and measured, not inferred: without the fix an em-dash (UTF-8
226 128 148) arrives at the child as byte 45 — an ASCII hyphen — because the ANSI encoder
best-fit maps rather than failing. Codex is simply the only stdin seat that validates its input
and says so. The claude and local/ollama seats (promptVia: "stdin") were silently
receiving mangled review prompts and returning confident rankings on corrupted text. The arg
seats (gemini, grok) pass via argv and were unaffected.
Fix: StandardInputEncoding = new UTF8Encoding(false) — deliberately NOT Encoding.UTF8,
whose encoderShouldEmitUTF8Identifier would prepend a BOM to the child's first stdin bytes and
trade one corruption for another. Plus a byte-level regression test proven to fail without the fix
(the pre-existing stdin test used pure ASCII, which is exactly why CI stayed green while the pipe
was broken). Same family as the FLT-16 PowerShell non-ASCII parse bomb: non-ASCII crossing a
process boundary with an unpinned encoding. FLT-58 (failed seat drops out, run still exits 0)
is what let this hide.
The runtime smoke found a SECOND live bug the 92 green tests could not. Program.cs read the
piped question via Console.In, which decodes with the console INPUT codepage (437 here) — so a
non-ASCII question was mojibake before any seat saw it, the mirror image of the same bug on the
way in. Proof, same input, real binary + real codex CLI: before, the report recorded the question as
Here they are ΓÇö µùѵ£¼Φ¬₧; after, Here they are — 日本語, echoed back intact by the seat. The
unit suite never caught it because it never feeds the real binary a real question — Program.cs is
excluded from coverage by design (TESTING.md). Both ends now pinned.
Gate (council-code-review, 5 seats seated): codex (chairman + member), gemini, grok, local
qwen3:8b, gaming-PC qwen3-coder:30b. Chairman surfaced exactly one finding — the capture path was
interpolated into a single-quoted PowerShell literal, breakable by a temp path containing an
apostrophe — applied. Dropped: the argv-has-the-same-bug claim (refuted by probe — ArgumentList
→ CreateProcessW → UTF-16, round-trips byte-identical) and the console-codepage-must-change claim
(the child reads a redirected pipe, not a console). Streaming-PC skipped (box off, TCP probe to
10.0.0.26:37878 False); gaming-PC qwen3-next:80b FAILED (canceled at 863s, server member cap).
Local seat's first canary was a false negative — $env:OLLAMA_HOST did not inherit into the
pwsh child, so it fell back to :11434 and got connection-refused; healthy on retry in 3.5s.
Validation (run by hand, FLT-3): pwsh -File tests/Invoke-CI.ps1 — the CI entrypoint per
ci.yml:33, not a hand-picked dotnet test — exit 0, 92/92, line coverage 100% (floor 70%).
Runtime smoke exit 0.
NOT DONE — the fix is committed but not live. publish/ is gitignored, and the llm-council
skill executes llm-council/publish/llm-council.exe from master. Landing the branch is not
enough: master's publish/ must be rebuilt or every council run keeps the bug. Same trap as
FLT-51 (publish/ gitignored ≠ deployed).
FLT-63 · House open councils unreachable in practice: open_council exceeds the MCP client's drop ceiling — Backlog (Jira key FLT-63 · WT-8f94, 2026-07-15)¶
Surfaced during the FLT-61 Tavily council: both house councils absent, so a council verdict shipped
with zero open-model corroboration. Not a server fault — :37800/health answers 200 in
0.11s and ask_model on gpt-oss:20b returns instantly; ICMP loss to 10.0.0.7 is the firewall
dropping ping, not an outage. Root cause is the known subagent-mcp-600s-cap: the MCP client
abandons long calls at a variable ~390-700s, and open_council serializes N models on one GPU with
weight hot-swaps between them. No member subset is both small enough to be safe and large enough to
be a council. Fix direction: submit+poll job API (open_council_submit → jobId,
open_council_status) so a client drop stops destroying completed GPU work; same treatment for
code_review_council and the CPU-bound streaming PC. Also open: the streaming-PC MCP server did
not connect at all this session.
FLT-12 · Macro self-host evaluation — Blocked (optional)¶
Only if comms-stack consolidation (email/chat/docs) becomes a goal — NOT a harness need (council: reject; MCP write surface unproven). If opened: AGPL self-host on spare capacity, DR on claude-mem pattern (Postgres replication + warm standby + watchdog), Tailscale-only exposure, license note: modifications served over network trigger AGPL source-sharing.
Delivered (pre-board fleet/tool work, retro-tracked 2026-07-14)¶
WW product work lives on the WorkWingman board (docs/BOARD.md + artifact kanban) — not duplicated here.
- FLT-D1 worktree-identity — C# CLI + UserPromptSubmit hook, session naming/governance registry · Done
- FLT-D2 usage-governor — scanner + GREEN/YELLOW/RED tiers + PreToolUse spawn gate, LIVE · Done
- FLT-D3 fleet-dispatch — C# command queue + listeners, 4/4 PCs operational · Done
- FLT-D4 fleet-telegram — C# Telegram command center, phase 1+2 · Done
- FLT-D5 NATS fleet.v1 bus + MemBus C# — wire contract, 3 trust tiers, signed envelopes · Done
- FLT-D6 llm-council — C# 5-seat council (answer/peer-review/verdict) + house council MCPs · Done
- FLT-D7 token-roi — impact-per-token metering, CPDT, Stop hook, statusline · Done (phase 2 owed)
- FLT-D8 PavlokPager — CLI + skill, wake-the-human escalation with budget · Done
- FLT-D9 claude-mem house — worker :37777 + Docker server :37877 + DR standbys (bedroom, streaming) · Done (gaming standby outstanding)
- FLT-D10 claude-session-watchdog — Scheduled Task pager on overnight session death · Done
- FLT-D11 audio-loop-mcp — C# WASAPI loopback + Whisper STT + SAPI TTS MCP · Done
- FLT-D12 caveman suite — compression skills + cavecrew subagents + savings scripts · Done
- FLT-D13 tools org — andrewjonesdev-tools, 8 private repos, pipelines, home-ci runner group on 4 PCs · Done
- FLT-D14 codex-harness-mirror — harness fleet (Codex/Gemini/NanoClaw/Odysseus/Grok) shared brief+brain, inverted review · Done
- FLT-D15 home bootstrap kit — OneDrive PC-Bootstrap per-PC setup.ps1 · Done
- FLT-D16 SSH mesh — all 4 PCs, PowerShell shells, EncodedCommand nesting · Done
- FLT-D17 Grok MCP — healthy on 4 PCs · Done
- FLT-D18 Docker update-outage fix — AutoDownloadUpdates off + root-cause writeup (2026-07-14) · Done
Prior open work (retro-boarded 2026-07-14, was tracked only in memory/repo boards)¶
- FLT-B1 CMH-5 claude-mem failover watchdog — SHIPPED master d150527 (3-fail + 5-min grace failover, 5-min failback) but NOT INSTALLED on any PC; install fleet-wide. Feeds/merges with FLT-W1. · Backlog
- FLT-B2 claude-mem gaming-PC DR standby — bedroom + streaming LIVE; gaming outstanding (blockers: logged out + UAC) · Backlog
- FLT-B3 token-roi phase 2 — owed from TROI epic (two-ledger + Kerr follow-through) · Backlog
- FLT-B4 fleet.v1 bus envelope mismatches — 2 mismatches between worktree-mail + fleet-telegram maps vs contract · Backlog
- FLT-B5 worktree-identity hook fail-open fix — ed26858 (JSON-deny + add-A rescope) built; fleet-wide redeploy pending · Backlog
- FLT-B6 fleet-dispatch listener hardening — RunLevel Highest + firewall rules on all 4 PCs · Backlog
- FLT-B7 xAI credential vaulting + Grok seat polish (SuperGrok remaining work) · Backlog
- FLT-B8 codex gpt-5.6 retest — bump llm-council fable tier when account enables it · Backlog
- FLT-B9 CI exit-code masking fix across tool repos (WinPS wrapper propagation) · Backlog
- FLT-B10 fleet-telegram acceptance completion — all worktrees × models × harnesses × councils reachable · Backlog
In flight (other sessions / blocked)¶
- FLT-W1 claude-mem auto-failover watchdog — spawned task running (own session) · In Progress
- FLT-W2 MCP dev-tool suite rollout (FLT-32) — DONE: 14 PRs merged. ESLint+Angular MCP (pinned, gated) + ReSharper CLT 12 repos + docker-autoheal (claude-mem) + read-only SQLite MCP (fleet-telegram). MSSQL deferred (no SQL/EF targets); KittySploit rejected (ZAP already in WW ci.yml). pwsh .mcp.json launchers need a Claude Code restart to verify. · Done
- FLT-W3 WW-77 LiteRT.js embeddings spike — prototype c96d601, blocked on Gemma model availability · Blocked
- FLT-W4 fleet-routine — cross-harness routines (WTS trigger + C# runner + NATS registry), not built · Backlog
- FLT-W5 polyharness parity phase 2 — fleet-dispatch mirror @9cede5b · In Progress
Log¶
- 2026-07-14 · Board created from council verdict + revised universal-harness framing (session WT-0924).
- 2026-07-14 · Vikunja bootstrapped (was empty — zero users):
fleet-agentservice user + project 2 "FLEET — Universal Harness" + all 12 tickets mirrored. Creds + 1yr API token:C:\Users\fives\docker\vikunja\fleet-agent-credentials.json(local only, NOT for any repo). Board URL: http://ANDYGREATROOMPC:3456/projects/2 · Jira mirror pending FLT-10 account step. - 2026-07-14 · Jira mirrored: sites workwingman.atlassian.net (team: WW + FLEET) and
andrewjonesdev.atlassian.net (private, invite nobody) created by Andrew (30d Premium trials,
no card — auto-drop to Free). FLEET project = KAN-1..12 mirroring FLT-1..12 titles at
https://workwingman.atlassian.net/jira/software/projects/KAN/list. Pending: Andrew's OTP
step-up at id.atlassian.com → API token
fleet-harness-sync→ descriptions via REST + Rovo MCP wiring + project key rename KAN→FLT (cosmetic). - 2026-07-14 · Jira fully wired: API token
fleet-harness-sync(expires 2027-07-12) stored atC:\Users\fives\.fleet-secrets\jira.json; project key renamed KAN→FLT (FLT-1..12 aligned); full descriptions pushed via REST; 23 retro issues created (18 Delivered → Done, 5 In-Flight); Rovo MCPatlassian-rovoregistered user-scope — OAuth grant pending (run /mcp → authenticate). FLT-10 now ~70%: remaining = OAuth grant + agent statuses + custom fields. - 2026-07-15 · FLT-1 live run CLEAN on the designed path, first time (WT-f255, run
FLT-1-finalon765fa3b):codeximplemented on the first attempt (no escalation),claudereviewed blind,locked_pools: [], zero drift, validation reran pytest itself → 3 passed, branchwt/FLT-1-final/harness-b0d2e1d1. Every prior live run had reached the gate only via failover; this is the first where the intended implementation seat did the work. Codex'struncatealso handles what gemini's missed — rejects negative limits, clampslimit<=3, keeps the ellipsis inside the bound — and the blind reviewer still added value (flagged the clamp branch and exact-fit boundary as untested). - 2026-07-15 · Two codex-seat faults found, both invisible to mocks AND to a bad live probe (WT-f255). The codex seat — the designated implementation seat — failed in 4/4 live runs while the harness looked healthy, because the escalation ladder silently carried the work to claude/gemini/grok every time. Working escalation masked a dead seat; that is worth remembering as its own lesson.
0xC0000409crashes (empty output): codex retried a configured-but-dead Figma MCP at127.0.0.1:3845and intermittently died. Fixed by the spawned config task; codex now clean 3/3 with zero rmcp fatals.- The sandbox, a SEPARATE fault (
352e96d): codex reported "every filesystem operation failed because the Windows sandbox helper codex-windows-sandbox-setup.exe could not be launched." That helper ships only in the Store/AppX package, never the standalone CLI — so codex could not read or write a single file. Fixed with-c sandbox_mode="danger-full-access"(the override council-code-review already documents; safe because agents run in a disposable worktree on a trusted workstation). Pinned by a test so it cannot be "cleaned up". Why it hid, and the rule that follows: the earlier "verified live" probe asked codex to "print OK and do not edit anything" — a task needing ZERO filesystem access. It passed against a completely broken seat. A verification that cannot fail proves nothing. Re-verified by having codex write a real file and checking the DISK, not its claim (proof.txt, contents "WROTE"). This is the same family as the--jsonschema bug: mocks agreed with the author's guess, and a live probe agreed with the author's hope. Both only fell over on real work. - 2026-07-15 · Probe race found + fixed (WT-f255,
0491f9e): splitting agy into four seats madeprobe()fire four back-to-backagy --versioncalls, and ~1 in 4 lost the race — mis-marking a healthy lane DOWN and silently dropping it from the ladder (measured: 1 false DOWN per 4 probe runs, never the same lane;agy --versionalone is 6/6 clean at 0.3–2.2s). Probes are now cached per executable and shared across the seats fronting it, with one retry: a false DOWN costs a seat for a whole run, a retry costs a second. 5/5 clean probe runs after, all 8 seats UP. Whether a LANE is spendable is a pool/quota question, never a binary-presence one. - 2026-07-14 · FLT-1 LIVE end-to-end verified against a real repo (WT-f255) — first run with real
CLIs, real git worktrees, real pytest. Target: a purpose-built sandbox repo (
textkit, real git history + passing test); deliberately NOT a fleet repo for the first live outing. Task: addtruncate(text, limit)+ tests. Both runs completed to the human gate, exit 0. - Run 1 (all seats up): codex FAILED → ladder escalated → claude implemented → grok reviewed blind → validation reran pytest itself: 3 passed. Zero review drift.
- Run 2 (
--simulate-down claude): codex FAILED and claude down → ladder walked to gemini → grok reviewed → validation: 2 passed. This is a stronger acceptance result than the scripted test: two seats were unavailable at once and the ticket still landed. - The layered defense earned itself, live. Gemini's
truncateviolated the spec (text[:limit] + "..."exceedslimitby 3) AND its own test asserted the wrong behavior — so the FLT-3 validation gate PASSED it. The blind FLT-4 reviewer (grok) caught the length violation independently and setneeds_human_review=true. Validation alone would have shipped the bug; the reviewer alone had no test signal. Confirms the known FLT-3 gap in writing: an agent's own tests are not an independent oracle. Grok also flagged__pycache__in the diff and negative-limit handling in both runs. - Real bug found + fixed (
3b56a47): the codex--jsonparser guessed the event schema wrong (msg.text; real isitem.completed→item.text). Every mock agreed with the wrong guess, so 51 green tests hid it — on every real run_extract_textreturned None and results silently degraded to the "fields inferred" fallback. Now pinned bytests/fixtures/codex-events.jsonlcaptured verbatim from a real run, and verified live (codex returns a parsed contract, no inferred-fields warning). The C# FLT-2 session hit this same class of bug, also only on a real run — mocks agreeing with the author's guess is a pattern worth a standing rule, not a one-off. - Codex seat is flaky on this box: intermittent
0xC0000409(STATUS_STACK_BUFFER_OVERRUN) with empty output, correlated withrmcptransport fatals against a configured-but-dead MCP server athttp://127.0.0.1:3845/mcp(Figma dev MCP, not running). 2 crashes then 3/3 clean on retry. The harness handled it correctly every time (escalate, don't stall), but the codex seat is degraded fleet-wide until that dead MCP entry is removed from codex's config — worth its own ticket; it silently cost the implementation seat in BOTH live runs. RESOLVED 2026-07-14 (WT-f85a). Removed[mcp_servers.figma-desktop]from~/.codex/config.toml(backup:config.toml.pre-figma-fix.20260714-233257.bak); the remote[mcp_servers.figma]stays, since that is the cross-client hub FLT-13 actually uses and the desktop server is selection-aware only — useful solely while Figma is open and Dev Mode MCP is toggled on, which it was not. Verified 7/7codex exec --jsonruns: exit 0, zero0xC0000409, zero rmcp fatals. The rmcp fatal fired on every invocation pre-fix (crashing or not), so its disappearance is the deterministic evidence; 7 green runs alone would not be, given the crash was intermittent.- "Fleet-wide" was wrong: gaming/streaming/bedroom never had any figma entry
(verified by dumping their
mcp_serversblocks over SSH). Both entries were added on great-room earlier the same day by the Figma-MCP research session, which is why both live FLT-1 runs hit it. No fleet push was needed. - Deliberately did NOT add a retry on
0xC0000409. The loud failure is the detector that found this; a silent retry would turn seat degradation into an invisible tax, and the ladder already makes a flaky seat cheap (work landed via claude/gemini both times). Instead the crash is now named —crash: STACK_BUFFER_OVERRUN (0xC0000409)inknown_risks— while still FAILED + escalating.tests/test_codex_events.py:65stays as-is; 4 tests added around it. - Prevention:
fleet-dispatch mcp-healthprobes every url-backed[mcp_servers.*]entry and exits 3 on a dead one. Run against the pre-fix backup it reportsfigma-desktop DEAD, so the next stale entry gets caught by a gate instead of by a seat dying mid-run.
- "Fleet-wide" was wrong: gaming/streaming/bedroom never had any figma entry
(verified by dumping their
- Not yet proven: the interrupt/resume gate ran with
--yes(auto-approve) in both runs; a real human answering the gate, and a--simulate-downof the whole editing ladder, remain unexercised live. 56 tests green. - 2026-07-14 · FLT-1 scaffold built + council-gated (WT-f255). Repo
fleet-harnessgit-init'd, committed LOCAL ONLY at2863033(no remote, not pushed). Python 3.13 + uv, exact pins (langgraph 1.2.9, deepagents 0.6.12, langchain 1.3.13, langchain-core 1.4.9, langchain-ollama 1.1.0, httpx 0.28.1, pyyaml 6.0.3). Shipped: swappable brain (default ChatOllama → 10.0.0.7 gaming PC, localhost fallback, zero API keys required); deterministic router over routing.yaml (FLT-6) + probes + escalation ladder; graph route → implement (git worktree) → blind cross-vendor review (FLT-4, read-only sandbox) → validation that reruns tests (FLT-3) → humaninterrupt()gate; advisory branch for text-only roles; FLT-2 contract wrappers (docs/contract.md= canonical schema shared with the C#fleet-dispatch run-agentbuild); CLIpython -m fleet_harness run|probe. Acceptance met:--simulate-down claudecompletes route → implement(codex) → review(grok) → validate → human gate, covered bytest_acceptance_simulate_down_claude. 51 tests green (real graph + shipped routing.yaml, fakes only at vendor/git edges); all 5 seats probe UP live. Council gate: Codex chairman; seats Codex + Gemini + Grok substantive. DEGRADED — local Ollama seat (gemma4) returned spinner output only, and BOTH house-council seats (gaming, streaming) failed with MCP transport drops inside their courier subagents even though TCP to 10.0.0.7:37800 and 10.0.0.26:37878 was UP and Wi-Fi was on the house SSID (not drifted) — i.e. a subagent MCP-transport fault, not a box/network fault. Worth a follow-up ticket. Verdict: 0 Critical, 3 High, 9 Medium, ~11 Low, Kerr findings none, 4 dropped as false positives. All High and Medium fixed + regression-tested (notably: reviewer was running inside the implementer's worktree and could mutate the measured diff;approval_requiredran past the human control point; freeform mode bypassed isolation; cheap-bulk could never reach Ollama; secrets rode the diff to third-party reviewers). Next: point usage-governor + fleet-dispatch at routing.yaml (FLT-6 anti-fork property is unproven with one reader); swap wrappers tofleet-dispatch run-agentwhen the C# FLT-2 lands; decide repo remote + push; live end-to-end run against a real target repo (only fakes so far). - 2026-07-14 · Rovo MCP OAuth granted by Andrew — workwingman site ONLY (private site deliberately
excluded from agent reach; REST token remains the deliberate-use path for it).
claude mcp list= Connected. New sessions get Jira tools automatically. FLT-10 remaining: agent-oriented statuses + custom fields (Primary Agent, Review Agent, Risk, Branch, Run ID), then board-as-contract checklist evaluation. - 2026-07-14 · FLT-13 phase 1 (status wall) SHIPPED (WT-df2b): new repo
fleet-mission-control, net10.0 API + SignalR + Angular 22 NSwag PWA, verified live against real fleet-dispatch data, council gate Codex+Gemini+Grok+qwen3:8b+gaming:qwen3-coder:30b+streaming:llama3.3:70b (devstral seat FAILED/canceled), chairman list (1H/6M/5L) fully implemented, backend 20/20 + frontend 19/19. Local-only, not pushed. FLT-13 → In Progress (phases 2-4 remain); FLT-14 read-only panels unblocked. - 2026-07-15 · FLT-13 quota surface + tooling gates landed (WT-df2b, fleet-mission-control local commits 4-5): /api/quota + QuotaUpdated hub event reading agy-ledger.jsonl READ-ONLY (single-writer honored); agy-Claude rendered as remaining invocations + reserve intact/spent (units, never %), weekly counts as distinct no-refresh lines, weekly limit rows → hard-deny banner + reserve spent. Tooling: angular-eslint clean, Stryker.NET 39.19% baseline (hardening chip spawned; stryker-js blocked on Angular vitest builder), ReSharper InspectCode (1 fix), ZAP baseline+API scan 0 FAIL (CORP/CSP/referrer/permissions headers added), 0 vulnerable packages (Microsoft.OpenApi 2.7.5, npm qs override). Delta council gate: Codex+Gemini+qwen3:8b+gaming:qwen3-coder:30b, chairman 3H/4M/2L all implemented incl. Kerr fix (reserve gated on weekly, not 5h proxy). 30/30 + 24/24.
- 2026-07-15 · FLT-16 CI tooling pack rolled out to 11 C# repos (WT-df2b): vuln gate (enforcing)
- InspectCode (error-severity) + Stryker (report-only, staggered) + pinned tool manifests.
Council-gated on the pilot template (6 seats; 3 Highs caught — fail-open vuln gate, floating tool
installs, cron dogpile — all fixed before replication). Every repo's build/tests/gate re-run by the
orchestrator; 0 vulnerable packages fleet-wide. Codex implemented (governor RED). All branches
wt/WT-df2b/FLT-16, committed, NOT pushed — land decision pending. - 2026-07-15 · FLT-16 LANDED on origin/master, all 11 repos (WT-32b7). Backporting the stronger
clean-marker gate surfaced a deeper fail-open the council caught: a solution-wide scan proves only
that SOME project got a verdict — one clean marker satisfies the aggregate match even if another
project was never evaluated. Gate now enumerates projects and requires a per-project verdict;
DOTNET_CLI_UI_LANGUAGE=enpinned (marker is literal English text). Council 5/7 seats (Gemini found the multi-project hole, Grok the locale brittleness; qwen3-next:80b hit the 480s cap; streaming PC down — TCP+ping fail while gaming answered from the same host). Validation: extracted each workflow's real gate script and executed it — 11/11, enumerated == clean verdicts (WW 29/29). That caught a pilot bug nothing else did: one em-dash in arun:block =Missing closing '}'under WinPS 5.1 (GH Actions writes BOM-less UTF-8, 5.1 reads ANSI) — gate bodies now ASCII-only, seewinps-run-block-nonascii-parse-bomb. Landed per the multi-session FF-push edict (rebase in worktree → lease-pinned push straight to origin); origin was ancestor of every tip, 0 peer commits lost. membus now scans 4 projects (picked up MemBus.Contracts). - 2026-07-15 · FLT-16 follow-on: test-impact analysis RESEARCHED → REJECTED, premise was false (WT-975b).
Asked whether to scope the pack's Stryker runs to changed code via GHA/MCP. Council convened (opus, 5/5
seats) and answered well — but optimized a bottleneck that does not exist, because it was never given the
numbers. Measurement:
--coverage-analysis perTestis already Stryker.NET's default (all 11 configs leave it unset = already on, so the council's #1 win is a no-op); .NET mutation wall-clock is ~15 min across the fleet (2m35s–15m23s, running in parallel across separate repos); no MCP exposes a TIA selector today. Nothing to buy, nothing to build. Council log carries a correction block — the verdict is moot. Real defect surfaced and spun out separately: WorkWingman mutation CI produces no result because thelinuxrunner its workflows require was never built (b606a93, 07-08, routed 10 jobs at a label with nothing behind it; 17 mutation runs cancelled, 0 passed, ever). A peer session provisioned it at 07-15 23:11:49 CDT (0f787ef). See the FLT-16 section — this line was retracted once on a 34-minute-old observation and the retraction was itself wrong. Cleared while measuring: staggered crons are real (Mon 06/10/12/20),audio-loop-mcphasmutation.ymlon origin (local checkout was 2 behind). Method lesson: measure the bottleneck before convening a council about it — a council argues the premise rather than telling you it is false, and here chairman and top-ranked seat were the same lineage while both house councils were unreachable (FLT-63), so no independent lineage checked it. - 2026-07-16 · ~~Retraction: the WorkWingman "runner label" defect was not real.~~ THIS RETRACTION WAS
ITSELF WRONG — superseded, see below and the FLT-16 section. It claimed the backlog was "capacity". It was
not. The
linuxrunner the workflows require did not exist from 07-08 (b606a93) until a peer session provisioned it at 07-15 23:11:49 CDT (0f787ef) — 17 mutation runs cancelled, 0 passed, ever. The original "nothing answers that label set" claim was CORRECT for that entire window; it was retracted on an observation taken 34 minutes after the peer's fix landed. - 2026-07-16 · Post-mortem: four wrong diagnoses on WorkWingman CI in one night (WT-975b). Sequence: label
unanswered → runner wedged → orphaned processes → memory-starvation-dismissed → "capacity". Every one
published confidently; every one overturned within the hour. Root cause: sampling shared infra while a peer
session was actively repairing it, and reading their in-flight fixes as findings. The peer landed the runner
(
0f787ef, 23:11 CDT), raised its cap 5g→6g (228c3cf, 02:15 CDT), and rebuilt the image three times — each change silently invalidated a conclusion drawn minutes earlier. Contributing artifacts: (a) GitHub reports run status asqueuedwhile any job in it still waits, soruns?status=in_progressreads empty while a job runs — run status ≠ job status; query/actions/runs/<id>/jobs; (b) a cgroup OOM of a worker does not setOOMKilled(only PID 1 dying does), so "no OOM in the log +restarts: 0" does not rule out memory starvation — it is exactly what starvation looks like. Standing rule: before diagnosing shared infra,git logthe window for peer commits and date every observation against them. Cost: two false claims published to the board, pushed to a remote, and one handed to a spun-out session as its premise. - 2026-07-16 · Verified by spike, and it holds: the PR #21 shell fix survives a virgin runner (WT-975b).
Reproduced the original
PSSecurityExceptionon demand (process-scopePSExecutionPolicyPreference=Restricted) on greatroom + gaming + streaming. Per box: unfixed shell under Restricted exits 1 (control fires — the simulation is real), PR #21's membus-form shell exits 0 (survives), and a failing command through it still exits 7 (no green-washing). So a NEW runner needs no machine-policy change — the in-repo fix is the anti-drift property. v1 of this spike was contaminated and reported a false pass: it was launched with-ExecutionPolicy Bypass, which exportsPSExecutionPolicyPreferenceto every child, so the "unfixed" control ran under Bypass. Caught only because gaming — which had just thrownPSSecurityExceptionin CI — reported Bypass. Also: all runners execute asNT AUTHORITY\NETWORK SERVICE, and ExecutionPolicy CurrentUser is per-user, so probing your own policy proves nothing about the runner's. - 2026-07-16 · usage-governor CI is green-washing failures — measured, not theorised (WT-975b). Its
ci.ymlshell omits the trailingexit $LASTEXITCODEthat membus carries. Measured identically on three boxes: a body ofcmd /c "exit 7"returns 7 through membus's form and 0 through usage-governor's. A red suite renders as a green check. Any recent green on that repo is unverified. Spun out as its own task; the other 9 FLT-16 pack repos need the same audit (this is the same fleet config drift that left WorkWingman without the setup-dotnet fix its 11 siblings got).
Fleet Routines build tickets (FLT-34 fleet-routine) — spun 2026-07-17 from opus council¶
Council opus 2026-07-17 (ranking D/grok>A/claude>B/codex>C/gemini>E/local; report llm-council/reports/2026-07-17_191704_should-the-fleet-harness-flt-1-the-universal.md) re-ratified the delegate seam now that FLT-1 exists: fleet-routine = C# scheduling plane (WHEN+budget); fleet-harness = the ONLY orchestration engine (HOW+adapter). Runner invokes the graph, never re-selects adapters. C# runner + Python graph, process boundary a feature. House councils 5 AGREE / 2 DISSENT (both dissents = the rejected "absorb into FLT-1/Python" minority; both heaviest votes gpt-oss:120b + qwen3-next:80b confirm).
Blocks chain: FLT-104 → FLT-105 → FLT-106 → FLT-107 → FLT-108. All anchored to FLT-34.
| Key | Phase | Status | Summary |
|---|---|---|---|
| FLT-104 | Gate 0 | To Do | GO/NO-GO non-interactive auth smoke (fleet-routine doctor --noninteractive), 6/6 harnesses as Andrew user "whether logged on or not" (NOT SYSTEM). Blocks all scheduler code. |
| FLT-105 | P1 | To Do | run-now vertical slice through the C#↔fleet-harness seam: registry+tombstones, CLI add/list/delete/run-now+cap-validate, fire-time fail-closed governor (defer=skip-tick), fleet-harness routine-fire entrypoint, emit fleet.v1. run-now BEFORE WTS. |
| FLT-106 | P2 | To Do | WTS trigger via COM/API (trigger-only), StartWhenAvailable, reboot/sleep survival. |
| FLT-107 | P3 | To Do | multi-PC JetStream durable replay + Claude-native routine normalize. Open fork: subprocess/sync (P1) vs NATS-command/async (multi-PC) — decide here. |
| FLT-108 | P4 | To Do | Pavlok dedupe/escalation + full cap enforcement (maxTokens/cost/wallclock/concurrency/cooldown), missedRunPolicy=skip-retry-never-flush, immutable audit. |