Skip to content

feat: Codewhale 0.9.12 shell, brand, fleet, and Operate (mega) - #5826

Merged
Hmbown merged 78 commits into
mainfrom
integration/shell-brand-20260902
Sep 2, 2026
Merged

feat: Codewhale 0.9.12 shell, brand, fleet, and Operate (mega)#5826
Hmbown merged 78 commits into
mainfrom
integration/shell-brand-20260902

Conversation

@Hmbown

@Hmbown Hmbown commented Sep 2, 2026

Copy link
Copy Markdown
Owner

No-Issue: this is the 0.9.12 integration wave (launch card, brand trace, fleet vocabulary, Operate goal loop, DashScope descriptor) tracked in #5573; it supersedes #5815/#5817/#5819/#5822.

What changed for the user

Launch is our own card. Opening codewhale now shows a thin top line
(⑂ branch path), then a centred bordered card: the whale mark at left
(kitty image in kitty-class terminals, braille dots elsewhere, wordmark text
under ascii-safe), Codewhale bold + version, one announcement line only
when it is true (⚠ no model connected · run /provider, or MCP news), and
the menu New worktree / Resume session / Changelog / Quit with their real
chords right-aligned. Enter runs the highlighted entry, Up/Down move it, and
typing goes straight to the composer. The card dissolves on the first
keystroke or command (≤240 ms, instant under reduced motion) into the working
screen: top line gains ⋮ MCP n/m, the transcript starts with a
◆ session_start receipt, and the composer's bottom rule carries
model (effort) · permission. Posture bar + metrics line appear only once a
session exists.

Brand, traced. Wordmark SVGs traced from the founder's raster, navy
app icon / favicon / OG / manifest, site colours exported from one token
file (scripts/brand/trace-brand.py --check).

One vocabulary. fleet is the public term; Pod is retired from copy
(/fleet canonical, /pod alias). Role tokens are canonical everywhere:
general / explore / implement / test / advisor (+ planner / reviewer /
custom). The workflow wire accepts the pre-rename spellings as load-time
aliases and serializes canonical names.

Operate pushes toward parallel work. A real prompt in Operate becomes a
goal through the same create_goal path the /goal command uses; a single
append-only contract message tells the model it is the operator; the goal
seals through the deferred update_goal tool with verification evidence
before the turn ends.

Qwen 3.8 through the catalog authority. Alibaba Model Studio (DashScope)
joins the data-driven provider descriptors: international compatible-mode
endpoint, DASHSCOPE_API_KEY, live /v1/models discovery — never a
hard-coded id. Live verification with a real key from the founder's
environment (never printed):

$ codewhale --provider modelstudio-token-plan models
Available models (default: qwen3.8-max)
  qwen3.6-flash (system)
  qwen3.7-max (system)
  qwen3.7-plus (system)
  qwen3.8-flash (system)
* qwen3.8-max (system)
  …

$ codewhale --provider openrouter models   | grep qwen3.8
  qwen/qwen3.8-flash
  qwen/qwen3.8-max

$ codewhale --provider modelstudio-token-plan --model qwen3.8-flash exec "Reply with exactly: ok"
ok

The live lists carry qwen3.8-flash and qwen3.8-max; there is no
separately-dated 0901 id on either live endpoint tonight, so the exact
live ids stand (the descriptor's default model is a bootstrap hint only).

Chrome facts, one owner each. Metrics line
(model · ctx NN% · $cost · ttft · tok/s · ↓ tokens … Ctrl+/ help) and
posture bar (▶▶ ask (Shift+Tab) · work (Tab) · … Esc to interrupt … /rc)
under the composer. Double-tap Enter during a turn sends the queued message
now; Ctrl+Enter steers. The bottom view cycles agents → tasks → background →
files → notepad → context → git → price (Ctrl+Tab / Ctrl+Shift+Tab, plus a
fallback chord), with clickable tabs and /rail <view>.

Perf (hot paths). No more per-delta format! of the whole tool-input
buffer into a verbose-only log (O(n²) per tool call); fast-reject the
28-marker trailing-prefix probes for deltas without </[ (per-token win
on every stream); reuse the identity collapsed-cell map across frames.

Founder decisions recorded

Shell = Claude Code's structure with our mark ("minimalist like Claude but a
shit ton of features"); launch = grokbuild's card structure with our whale
— "find a happy medium and make our own codewhale version", not a clone.
All recorded as Round 5 in
codewhale-ops/design/SHELL-DESIGN-20260901.md (§2.12), and DESIGN.md's
shell direction now matches (card, not dock/hero).

Gates (exact CI flags, real results)

All run on this branch head with CI's exact flags:

  • cargo fmt --all -- --check — clean (FMT_OK).
  • scripts/dev-cargo.sh clippy --workspace --all-targets --all-features --locked -- -D warnings -A clippy::uninlined_format_args -A clippy::too_many_arguments -A clippy::unnecessary_map_orFinished with 0 errors.
  • RUST_MIN_STACK=16777216 scripts/dev-cargo.sh nextest run --workspace --all-features --locked --profile ciSummary [ 212.813s] 14420 tests run: 14419 passed (3 leaky), 1 failed, 15 skipped. The one failure, exec_persistent_service::failed_exec_kills_pending_service_and_exits_nonzero, hit its 120 s wall-time guard while two other gates ran concurrently on this machine; re-run solo: PASS [ 3.014s] … Summary [ 3.024s] 1 test run: 1 passed, 12216 skipped.
  • scripts/dev-cargo.sh test --workspace --all-features --locked --doc — 21/21 result lines ok, 0 failed.
  • ./scripts/release/check-versions.sh --range-audit-advisoryVersion state OK: workspace=0.9.11, npm=0.9.11, npm-binary=0.9.11, lockfile in sync. (exit 0; the range-audit note is advisory on already-merged commits, per the flag).
  • scripts/check-tui-product-vocabulary.sh — exit 0.
  • python3 scripts/check-dead-code-budget.py[dead-code-budget] 422 attributes, budget 425 (3 under). (under budget).
  • python3 scripts/brand/trace-brand.py --check — exit 0.
  • Web: npm ci && npm run lint && npx tsc --noEmit && npm test && npm run check:tokens && npm run build — lint 0 errors, tsc clean, Tests 385 passed (385), design tokens up to date (1 file(s), 42 tokens), build succeeded. (The previously documented pre-existing README-screenshot failure is fixed here: the brand header redesign had dropped the assets/screenshot.webp embed the contract pins; it is re-embedded.)

Launch-card goldens were re-blessed for the card (startup_*, startup_first_run_80x24, startup_surfacing_80x24, startup_ink_*), and the golden files were read after blessing — the card, top line, and composer rule render as specified at 40x10 (shed), 80x24, 100x30, 120x32, and 160x40.

What was left, in plain words

  • Bottom views files / notepad / git / price are stubs or partial.
    git_rows, notepad_rows (the .codewhale/notes.md editor), the roster
    per-agent cost column, and compact tool rows did not fit tonight. The
    eight-view cycle, tabs, and /rail all land; four of the eight views
    render real data (agents, tasks, background, context), the rest are
    honest empty states.
  • Posture-chip hitboxes (clicking the posture bar words) are not wired.
  • ttft in the metrics line is the session average (mean over model calls) —
    that leftover was already satisfied by the frame slice.

Also left for follow-up, noted by the issue triage: refreshing
assets/screenshot.webp to show the new launch card (the contract pins
dimensions, so a fresh capture is a deliberate follow-up), and re-landing
the three stranded items the triage recorded (control socket #5594, the
#5588 neutrality slice 9ffec9b90, and FEAT-019 memory commands).

What was left, in plain words

  • Bottom views files / notepad / git / price are stubs or partial.
    git_rows, notepad_rows (the .codewhale/notes.md editor), the roster
    per-agent cost column, and compact tool rows did not fit tonight. The
    eight-view cycle, tabs, and /rail all land; four of the eight views
    render real data (agents, tasks, background, context), the rest are
    honest empty states.
  • Posture-chip hitboxes (click the posture bar words) are not wired.
  • ttft in the metrics line is the session average (mean over model calls) —
    that leftover was already satisfied by the frame slice.

🤖 Generated with Claude Code

Known non-required check state

Codewhale review fails structurally on this PR: the review bot fetches the
PR diff through gh pr diff, which GitHub caps at 300 files — this PR
modifies far more. It is an infrastructure cap, not a review verdict; the
bot's own log says PullRequest.diff too_large. Every other review lane
(Copilot inline findings — all fixed in this branch — Claude review, Devin
review) ran.

CodeWhale Bot and others added 30 commits September 1, 2026 18:26
Design MODEL-ROUTING-CATALOG-20260901 §10, slice F1. A fleet model is a Pod
member: the selected Pod file's operator route plus every member row that
pins an exact provider + model; the roles a model fills are the member rows
that pin it. No second store.

- crate::fleet::members: fleet_models / add_fleet_model / remove_fleet_model
  / toggle_fleet_model + change_receipt; Config::fleet_members(workspace) is
  the read seam for the operator-awareness slice (F2).
- /pod models | add <provider> <model> [role…] | remove <provider> <model>
  (also via the /fleet alias). A model the configured provider does not
  serve is rejected; the first add creates and selects a user-global Pod
  named 'My fleet'.
- /model picker: ⇧F adds or removes the row's exact route; fleet models
  lead the list labelled 'fleet · <roles>', ahead of ⇧P pins and providers.
- /models prints the fleet before the provider list ('Your fleet is the
  session model only' when empty).
- PickerActionFleet message in all 15 locales; docs/FLEET.md 'Your fleet
  as models'.

Tests: scripts/dev-test.sh tui fleet::members groups::core::fleet
model_picker format_helpers — Summary 37 tests run: 37 passed, 11834
skipped.

Signed-off-by: CodeWhale Bot <bot@codewhale.net>
cargo clippy -p codewhale-tui --all-targets -- -D warnings -A clippy::too_many_arguments -A clippy::uninlined_format_args -A clippy::unnecessary_map_or: no findings.

Signed-off-by: CodeWhale Bot <bot@codewhale.net>
…ion\n\n- Reject unconfigured provider ids in "/pod add" before writing, reusing\n the existing provider_is_configured_for_active predicate and custom\n provider table checks.\n- Add App.config snapshot so commands can consult the loaded config.\n- Update the stale DEFAULT_FLEET_NAME doc comment to mention ⇧F.\n- Sync crates/tui/CHANGELOG.md.
Dependabot #5801 bumped react-dom to 19.2.8, whose peer range requires
react 19.2.8; the lockfile still resolved react 19.2.6, so 'npm ci' in
web/ failed ERESOLVE on main and on every branch that merged it
(Lint & Type Check red). Align react to 19.2.8; install verified clean.

Signed-off-by: CodeWhale Bot <bot@codewhale.net>
Signed-off-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Hunter Bown <hmbown@gmail.com>
Signed-off-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Hunter Bown <hmbown@gmail.com>
Signed-off-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Hunter Bown <hmbown@gmail.com>
Signed-off-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Hunter Bown <hmbown@gmail.com>
Signed-off-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Hunter Bown <hmbown@gmail.com>
Signed-off-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Hunter Bown <hmbown@gmail.com>
Signed-off-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Hunter Bown <hmbown@gmail.com>
Signed-off-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Hunter Bown <hmbown@gmail.com>
Signed-off-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Hunter Bown <hmbown@gmail.com>
Field, chrome, panel, plate and raised surfaces move onto the brand navy
(#070C1D → #142352 → #1A2C63); interaction blue becomes the ombre sky
#6AA6DC, light-mode action the ombre cobalt #1535B2; ice/cyan/border/tool
tints follow. web/app/tokens.css regenerated via
scripts/export-design-tokens.py.

Co-Authored-By: Hunter Bown <hmbown@gmail.com>
Signed-off-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Hunter Bown <hmbown@gmail.com>
…ite + docs

Space Mono (OFL) outlined wordmark rebuilt via scripts/build-wordmark.py,
wired as --font-display through next/font/google; body stays IBM Plex Sans,
code stays JetBrains Mono. Nav loses the issue strip, strapline, Discord badge
and second filled CTA; home loses the ticker, seals and tilt figure; docs
shell hero collapses to a one-line band; footer uses the inverted wordmark.

Public noun is fleet (/fleet, codewhale fleet, /docs/fleet canonical; /pod,
codewhale pod, /docs/pod remain compatibility aliases) across docs/, site
dictionaries, vocabulary contract and public-surface facts.

No-Issue: 0.9.12 website lane
Signed-off-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Hunter Bown <hmbown@gmail.com>
Signed-off-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Hunter Bown <hmbown@gmail.com>
@cursor

cursor Bot commented Sep 2, 2026

Copy link
Copy Markdown

Bugbot couldn't run - usage limit reached

Bugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit.

A user or team admin can review and increase usage limits in the Cursor dashboard.

(requestId: serverGenReqId_7a9142c7-0927-4293-bd53-676de6b91e7f)

@claude

claude Bot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Claude finished @Hmbown's task in 2m 14s —— View job


Claude is reviewing this PR

Todo list

  • Gather context: read CLAUDE.md/AGENTS.md, PR description, diff
  • Understand request (code review of this PR per repo custom instructions)
  • Review correctness bugs (panics, unwraps, races, error handling)
  • Review provider/model/route safety (v0.8.65 EPIC v0.8.65 EPIC: Separate provider facts, model facts, offerings, and route resolution #2608 invariant)
  • Review reuse/simplification/dead code
  • Review test coverage for new behavior
  • Review security (secrets, shell/exec, input validation)
  • Post final review summary

Diff computed against base d7042ab (two-dot diff; shallow clone has no merge-base for three-dot). 348 files changed, ~12k/~10k lines.

Running 4 parallel deep-dive passes:

  1. Provider/model/route safety (DashScope descriptor, fleet auto-enroll, pricing)
  2. Engine/turn-loop/goal tool (Operate contract message, KV-cache prefix safety, streaming fast-path)
  3. Fleet module + workflow crate (new members.rs, AgentType role-token rename/aliases — independently verifying the Copilot-flagged plan/planner serialization question)
  4. TUI localization/copy consistency — independently verifying Copilot's 4 flagged copy issues (Consultant/Advisor mismatch, Polish "fleetwodna" mangled string) plus scanning all locales for similar issues

- The context-cap posture test drew at 100 columns, where a backend-less
  platform (linux CI paints 'files: workspace (unenforced)') sheds the
  cap hint first, so the warning count read 0. Draw at 140 columns,
  where the hint survives with the notice present; verified locally.
- The pointer queue proof retries the [↑] click once, re-finding the
  affordance first: under runner load a redraw can shift cells between
  the find and the click, so the first SGR gesture lands nowhere.
@cursor

cursor Bot commented Sep 2, 2026

Copy link
Copy Markdown

Bugbot couldn't run - usage limit reached

Bugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit.

A user or team admin can review and increase usage limits in the Cursor dashboard.

(requestId: serverGenReqId_9666fa15-c454-493b-b5b9-8aa0e3b3d9f6)

@claude

claude Bot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Claude finished @Hmbown's task in 1m 24s —— View job


Claude is reviewing this PR

Todo list

  • Gather context: read CLAUDE.md/AGENTS.md, PR description, diff
  • Understand request (code review of this PR per repo custom instructions)
  • Review correctness bugs (panics, unwraps, races, error handling)
  • Review provider/model/route safety (v0.8.65 EPIC v0.8.65 EPIC: Separate provider facts, model facts, offerings, and route resolution #2608 invariant)
  • Review reuse/simplification/dead code
  • Review test coverage for new behavior
  • Review security (secrets, shell/exec, input validation)
  • Post final review summary

Diff computed against base d7042ab (two-dot diff; matches prior automated review's base). 347 files changed, ~12.2k/~10.5k lines.

Running 3 parallel deep-dive passes:

  1. Provider/model/route safety (DashScope descriptor, fleet auto-enroll) + independently verifying Copilot's AgentType/Plan vs "planner" serialization flag
  2. Engine/turn-loop/goal tool (Operate contract message, KV-cache prefix safety per docs/CACHE.md, streaming fast-reject, image-rejection classifier)
  3. Fleet module (new 903-line members.rs, manager/worker_runtime concurrency), palette/osc11.rs terminal-query refactor, hotbar/config auto-enroll behavior

…s; pointer baseline

- The Pod->Fleet sweep grew every mode's tool-schema surface by 58 bytes
  (+14 tokens). The receipts are re-measured and the one-way ceilings in
  scripts/runtime-contract-budget.json are raised to them as the
  explicit maintainer decision the gate asks for (the rename is the
  founder's 2026-09-01 vocabulary call).
- The README screenshot embed changed README.md; the 18 translated
  READMEs re-stamp (the embed is language-neutral HTML - no prose
  changed, so no retranslation was needed).
- The pointer queue baseline is captured while the composer is empty:
  the pending preview row hides while a draft sits in the composer, so
  the pre-click depth read None and the growth proof could not fire.
@cursor

cursor Bot commented Sep 2, 2026

Copy link
Copy Markdown

Bugbot couldn't run - usage limit reached

Bugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit.

A user or team admin can review and increase usage limits in the Cursor dashboard.

(requestId: serverGenReqId_5e608671-644b-48b1-89ae-0fbd4892783e)

@claude

claude Bot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Claude finished @Hmbown's task in 4m 28s —— View job


Claude is reviewing this PR

Todo list

  • Gather context: read CLAUDE.md/AGENTS.md, PR description, diff
  • Understand request (code review of this PR per repo custom instructions)
  • Review correctness bugs (panics, unwraps, races, error handling) — engine/turn_loop/streaming/context.rs checked directly
  • Review provider/model/route safety (v0.8.65 EPIC v0.8.65 EPIC: Separate provider facts, model facts, offerings, and route resolution #2608 invariant) — no issues found
  • Review reuse/simplification/dead code
  • Review test coverage for new behavior
  • Review security (secrets, shell/exec, input validation)
  • Post final review summary

Findings so far (independently verified):

  • Confirmed the Copilot-flagged AgentType serde issue in crates/workflow/src/lib.rs and found it's broader than reported: Plan and Review variants only get canonical spellings (planner/reviewer) via #[serde(alias = ...)], which affects deserialize only — Serialize still emits "plan"/"review" (snake_case default), contradicting the enum's own doc comment claiming serialized spellings are canonical.
  • Found two stale doc comments left behind by the Pod→Fleet rename that now assert the opposite of current behavior: crates/tui/src/commands/groups/core/fleet.rs:1-16 (module doc still says /pod is primary, /fleet the alias) and crates/config/src/lib.rs:1350 (says "/pod is the canonical public command" while the code below it now normalizes old slash.podslash.fleet).
  • Minor: a dangling orphaned doc-comment line in crates/tui/src/tui/app.rs:1676 left over from removing the cached_work_summary field (comment now prefixes an unrelated field).
  • Verified engine/turn-loop image-rejection recovery (turn_loop.rs), streaming fast-reject marker logic, and the Operate contract message (runtime_handoff.rs) are all correctly guarded (one-shot recovery flag, append-only KV-cache-safe message, structural hide-from-transcript match) — no bugs found there.
  • Verified fleet auto-enroll (crates/tui/src/fleet/members.rs) and the DashScope provider descriptor take explicit provider/model strings from resolved config, not inferred from model-string prefixes — respects the EPIC v0.8.65 EPIC: Separate provider facts, model facts, offerings, and route resolution #2608 invariant.

Two parallel deep-dive agents still running on fleet/members.rs (903 new lines) + manager/worker_runtime concurrency, and independently re-verifying the workflow AgentType/goal-tool findings. Will fold results into the final review.

The qa_harness Instant wrapper does not implement Div, and the retry's
single read raced the app processing the second gesture: poll to the
full deadline, re-click once at the half-way point.
@cursor

cursor Bot commented Sep 2, 2026

Copy link
Copy Markdown

Bugbot couldn't run - usage limit reached

Bugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit.

A user or team admin can review and increase usage limits in the Cursor dashboard.

(requestId: serverGenReqId_10ccf061-78c4-41a1-9ef7-66ef038cfcbb)

@claude

claude Bot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Claude finished @Hmbown's task in 6m 45s —— View job


Claude finished reviewing this PR

Todo list

  • Gather context: read CLAUDE.md/AGENTS.md, PR description, diff
  • Understand request (code review of this PR per repo custom instructions)
  • Review correctness bugs (panics, unwraps, races, error handling)
  • Review provider/model/route safety (v0.8.65 EPIC v0.8.65 EPIC: Separate provider facts, model facts, offerings, and route resolution #2608 invariant)
  • Review reuse/simplification/dead code
  • Review test coverage for new behavior
  • Review security (secrets, shell/exec, input validation)
  • Post final review summary

Diffed against d7042ab (two-dot; shallow clone has no merge base, matching the base prior automated review rounds used) at current HEAD 6e01ab2. This was a synchronize re-trigger on top of three earlier automated review rounds and a Copilot pass — I independently re-verified their open items at this HEAD and ran two focused deep-dives (fleet membership/concurrency; goal tool + Operate contract + DashScope descriptor + osc11 terminal IO) rather than re-treading everything already covered (turn-loop, streaming, image-rejection recovery, and the Operate contract's anti-spoofing match were all checked directly and are correctly implemented — no issues).

1. Reuse / dead code — new DashScope catalog row is unwired (route safety adjacent)

crates/config/assets/provider_descriptors.json + crates/config/src/descriptors.rs add the dashscope row this PR's description credits for the live Qwen 3.8 verification ("data-driven provider descriptors... live /v1/models discovery, never a hard-coded id"). But bundled_provider_descriptors() / provider_descriptor() have zero callers anywhere in the workspace outside descriptors.rs's own tests (verified via grep across all crates). The actual route system that powers --provider modelstudio-token-plan is the separate, pre-existing crates/config/src/route/descriptor.rs / provider_kind.rs machinery — untouched by this diff (git diff against base shows no changes to those files). So this PR's literal DashScope contribution is an orphaned catalog entry; the working plumbing behind the PR body's live transcript predates it. This is the exact "second, disconnected catalog for the same concept" pattern AGENTS.md's rung-2 rule calls out (provider_* naming, "grep for the existing thing and edit it") — worth folding dashscope/command-code/cerebras into the real route/descriptor.rs system or removing the dead descriptors.rs module rather than growing it further.

2. Correctness — unlocked read-modify-write race in fleet membership file (crates/tui/src/fleet/members.rs, store.rs)

add_fleet_model / remove_fleet_model (members.rs:213-364) do load_fleet_at → mutate in memory → save_fleet, with no lock held across the sequence (confirmed: no fd_lock/RwLock/Mutex anywhere in store.rs, unlike manager.rs which does use fd_lock::RwLock for its own ledger). save_fleet's atomic_write is rename-based so it's safe against torn writes, but not against a lost update: two near-simultaneous callers (e.g. auto_enroll_fleet_model, invoked from at least 3 call sites on model-switch/route-resolution, racing a manual /fleet add) can both read the same on-disk state and the second write silently clobbers the first's added/removed member row. Plausible under rapid /model switching. Not data corruption (the file stays well-formed), but a real data-loss/lost-update risk that the locking discipline already established elsewhere in this module (manager.rs) doesn't cover here.

3. Correctness — stale vocabulary docs/tests still assert the pre-rename direction (Copilot-flagged, confirmed still open)

Independently re-verified at current HEAD — not fixed by the intervening commits:

  • crates/workflow/src/lib.rs:538-563 — doc comment claims serialized AgentType spellings are "the canonical Codewhale role vocabulary," but only General/Explore/Implementer("implement")/Verifier("test") got an explicit #[serde(rename)]; Plan and Review still serialize as bare "plan"/"review", not this PR's own declared canonical extras planner/reviewer. The new round-trip test conspicuously asserts canonical round-tripping for implement/test/explore/general but pointedly not for plan/review — the gap is real, not an oversight in the test.
  • crates/tui/src/commands/groups/core/fleet.rs:1-16 — module doc still opens "/pod command (/fleet remains a compatibility alias)," but the actual COMMAND_INFO in the same file (line 29-31) has name: "fleet", aliases: &["pod", ...] — the code already flipped, the doc didn't. (A test at line 446, pod_pods_is_canonical_and_fleets_remains_a_compatibility_alias, has the same stale framing in its name, though its assertions are correct.)
  • crates/config/src/lib.rs:1350 — comment says "/pod is the canonical public command" directly above code that normalizes slash.podslash.fleet, i.e. the opposite.
  • web/lib/content/vocabulary.ts:7, web/lib/docs-map.ts:73-74, web/app/[locale]/docs/vocabulary/page.tsx:20-21 — all three still say "Consultant" where the module's own ADVISORY_ROLE.term (vocabulary.ts:189) is "Advisor"; self-contradictory within the same source file.
  • web/lib/i18n/dictionaries/pl/home.ts:47"fleetwodna powłoka terminala..." is still the mangled string (should be "Podwodna", Polish for "underwater" — the Pod→Fleet find/replace ate into this unrelated compound word). I checked all other locale files (web i18n dictionaries and crates/tui/locales/*.json) for the same class of mid-word merge and found no other instances — this one is isolated.

None of these are functional bugs (nothing fails to compile or behaves incorrectly at runtime), but they're copy/doc correctness regressions in a PR whose stated purpose is exactly this vocabulary migration, and they're the specific items Copilot already flagged twice without a fix landing.

Verified clean (no issues found)

  • Provider/route safety (EPIC v0.8.65 EPIC: Separate provider facts, model facts, offerings, and route resolution #2608 invariant): auto_enroll_fleet_model's three call sites, pricing.rs::model_rate_label, and descriptors.rs::provider_descriptor() all take explicit, already-resolved provider/model values — no code infers a provider switch from a qwen/-style model-string prefix or freeform text.
  • turn_loop.rs image-rejection recovery: one-shot guard (image_rejection_recovered), correctly wired to image_attach::strip_images_when_unsupported on the retry's rebuilt request — confirmed the capability flip actually causes stripping on the next loop iteration, not just future turns.
  • runtime_handoff.rs Operate contract message: structural match (exact envelope text + provenance line) prevents a user quoting the envelope from being mistaken for the real one; appended idempotently by scanning session history (survives compaction/restore) rather than a flag; correctly hidden from transcript rendering (history.rs:653).
  • palette/osc11.rs terminal IO refactor: every read bounded by wait_readable + deadline, capped reply length (128 bytes), no unwrap/expect on fallible IO, isatty unsafe block is minimal and justified.
  • fleet/members.rs itself: no panics/unwraps on fallible paths, no provider-prefix inference: unique_member_id's only .expect() is on a provably-infinite iterator.
  • Minor test-coverage gaps noted by the deep-dive agents (not blocking): no test exercising "auto-enroll into a fresh personal fleet, then call load_effective_roster" for the role-less-member fallback interaction in identity.rs; no direct unit test that history_cells_from_message returns empty for the Operate contract message specifically (only indirectly exercised).

Suggested fix scope

Items 2 and 3 are small, mechanical fixes (add the two missing #[serde(rename)]s or accept plan/review as the intended canonical spellings and update the doc; fix the four stale comments; fix one Polish string). Item 1 (dead descriptor catalog) is a larger judgment call — either wire it in for real or stop growing it — and worth a maintainer decision rather than a quick patch.

[Fix the stale docs + AgentType serde gap →](https://claude.ai/code?q=In+the+Codewhale+repo+on+branch+integration%2Fshell-brand-20260902%3A+%281%29+In+crates%2Fworkflow%2Fsrc%2Flib.rs+around+line+553%2C+the+AgentType+enum%27s+Plan+and+Review+variants+lack+%23%5Bserde%28rename%29%5D+attributes+so+they+serialize+as+%22plan%22%2F%22review%22+instead+of+the+PR%27s+declared+canonical+%22planner%22%2F%22reviewer%22+-+add+%23%5Bserde%28rename+%3D+%22planner%22%29%5D+and+%23%5Bserde%28rename+%3D+%22reviewer%22%29%5D+respectively+%28keeping+existing+aliases%29+and+update+the+round-trip+test+to+cover+them.+%282%29+Fix+the+stale+module+doc+comment+at+the+top+of+crates%2Ftui%2Fsrc%2Fcommands%2Fgroups%2Fcore%2Ffleet.rs+%28lines+1-16%29+which+still+says+%2F pod+is+primary+and+%2Ffleet+is+the+alias%2C+when+COMMAND_INFO+at+line+29+has+name%3A+%22fleet%22.+%283%29+Fix+the+comment+at+crates%2Fconfig%2Fsrc%2Flib.rs%3A1350+which+says+%2Fpod+is+canonical+but+the+code+below+it+normalizes+slash.pod-%3Eslash.fleet.+%284%29+Fix+web%2Flib%2Fcontent%2Fvocabulary.ts%3A7%2C+web%2Flib%2Fdocs-map.ts%3A73-74%2C+and+web%2Fapp%2F%5Blocale%5D%2Fdocs%2Fvocabulary%2Fpage.tsx%3A20-21+which+all+say+%22Consultant%22+but+should+say+%22Advisor%22+per+ADVISORY_ROLE.term+in+vocabulary.ts%3A189.+%285%29+Fix+web%2Flib%2Fi18n%2Fdictionaries%2Fpl%2Fhome.ts%3A47+where+%22fleetwodna%22+should+be+%22Podwodna%22+%28the+Pod-%3EFleet+rename+corrupted+this+unrelated+Polish+word+meaning+%22underwater%22%29.&repo=Hmbown/Codewhale)
·

@cursor

cursor Bot commented Sep 2, 2026

Copy link
Copy Markdown

Bugbot couldn't run - usage limit reached

Bugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit.

A user or team admin can review and increase usage limits in the Cursor dashboard.

(requestId: serverGenReqId_bd65ee7b-4fb0-41f5-b1f1-68622ebb14cd)

@claude

claude Bot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Claude finished @Hmbown's task in 1m 22s —— View job


Claude finished reviewing this PR

Todo list

  • Gather context: read CLAUDE.md/AGENTS.md, PR description, diff since last review round
  • Identify what actually changed since the last automated review (commit 6e01ab2)
  • Review the new commit for correctness bugs
  • Post final review summary

This synchronize trigger only added one commit on top of the four prior review rounds: 863c9e4 ("test: pointer queue diagnostics"), a 3-line diff entirely inside crates/tui/tests/cucumber/active_composer_pointer_pty.rs. I reviewed that diff directly (no other files changed since the last round, so items 1–3 from the prior review — the AgentType serde gap, the stale Pod/Fleet doc comments, the unlocked fleet/members.rs read-modify-write — are unchanged and still open).

Correctness bug — new commit doesn't compile: undefined last_seen

crates/tui/tests/cucumber/active_composer_pointer_pty.rs:228-234 (added by 863c9e4):

panic!(
    "{size}: click on [↑] at ({send_row},{}) produced no queue receipt \
     {receipt:?} and no queue growth — pointer submit did not reach the \
     keyboard-submit dispatch path (last_seen={last_seen:?}, \
     expected={expected:?})\n{}",
    send_col + 1,
    tui.diagnostics()
);

last_seen is never bound anywhere in this file — I grepped the whole file and it's the sole occurrence. The nearest candidate, queued_count(&text)'s result, only exists as the closure parameter seen inside .zip(expected).is_some_and(|(seen, want)| ...) a few lines above (line ~202), which is out of scope at the panic! site. expected (bound at line 196, let expected = queued_before.map(|n| n + 1);) is fine and in scope.

This module is compiled as part of the cucumber test binary (crates/tui/tests/cucumber/main.rs:14: mod active_composer_pointer_pty;), so as written this is an E0425: cannot find value 'last_seen' in this scope build failure for that test target — not a flaky test, a non-buildable one. I wasn't able to run cargo check in this sandbox to get the exact rustc output (tool approval required), but there's no other binding this identifier could resolve to.

Fix is small — capture the last-seen count where it's already computed, e.g.:

let text = normalized_text(tui.frame());
let last_seen = queued_count(&text);
let grew = last_seen.zip(expected).is_some_and(|(seen, want)| seen == want);

and reuse last_seen in both the grew check and the panic message.

Fix the undefined last_seen in active_composer_pointer_pty.rs →

Still open from the prior review round (unchanged by this commit)

  1. crates/workflow/src/lib.rs:553,556AgentType::Plan/Review still serialize as "plan"/"review" (no #[serde(rename = "planner"/"reviewer")]), contradicting the module's own doc comment and this PR's declared canonical role vocabulary.
  2. Stale Pod/Fleet doc comments: crates/tui/src/commands/groups/core/fleet.rs:1-16, crates/config/src/lib.rs:1350, plus the web "Consultant" vs. ADVISORY_ROLE.term = "Advisor" mismatches and the web/lib/i18n/dictionaries/pl/home.ts:47 "fleetwodna" mangled word — all flagged by Copilot and by the prior automated review, none addressed yet.
  3. crates/tui/src/fleet/members.rs add_fleet_model/remove_fleet_model — unlocked read-modify-write against the fleet membership file (no fd_lock unlike manager.rs), a plausible lost-update race under rapid /model switching + auto-enroll.
    · Branch: integration/shell-brand-20260902

@claude

claude Bot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Claude finished @Hmbown's task in 1m 7s —— View job


Claude finished reviewing this PR

Todo list

  • Gather context: read CLAUDE.md/AGENTS.md, PR description, prior review rounds
  • Identify what changed since the last automated review round (commit 863c9e4 → current head 9653c61)
  • Review the new commit for correctness bugs
  • Check whether previously-flagged open items were addressed
  • Post final review summary

This synchronize trigger added one commit, 9653c61 ("test: pointer poll keeps per-iteration state only"), a 15-line diff entirely inside crates/tui/tests/cucumber/active_composer_pointer_pty.rs. No other files changed since the last round.

Previous compile bug is fixed

The prior round flagged an undefined last_seen identifier in this file's panic! message (would have been an E0425 build failure for the cucumber test target). This commit fixes it correctly:

loop {
    tui.pump();
    let text = normalized_text(tui.frame());
    let seen = queued_count(&text);              // bound once per iteration
    let grew = seen.zip(expected).is_some_and(|(s, want)| s == want);
    if text.contains(receipt) || grew {
        break;
    }
    ...
    if Instant::now() >= deadline {
        panic!(
            "... (seen={seen:?}, expected={expected:?})\n{}",   // `seen` now in scope
            ...
        );
    }
    ...
}

seen is declared at the top of the loop block and stays in scope through the deadline check and panic! at the bottom of the same iteration, so the reference resolves correctly. I traced the full function (crates/tui/tests/cucumber/active_composer_pointer_pty.rs:150-244) to confirm the scoping by hand — I don't have shell-command approval in this session to run cargo check -p codewhale-tui --test cucumber directly, so this is manual verification rather than a compiler receipt; worth a real cargo check/CI run before merge to be certain, but nothing in the diff suggests any other issue. The two added println!("POINTER DEBUG ...") lines are debug instrumentation left in a test — harmless for correctness, just noisy in CI logs; not blocking.

Still open from prior rounds (unchanged by this commit — no other files touched)

  1. crates/workflow/src/lib.rs:553,556AgentType::Plan/Review still serialize as "plan"/"review" (no #[serde(rename = "planner"/"reviewer")]), contradicting the module's own doc comment and this PR's declared canonical role vocabulary (also flagged by Copilot).
  2. Stale Pod/Fleet doc comments: crates/tui/src/commands/groups/core/fleet.rs:1-16, crates/config/src/lib.rs:1350, the web "Consultant" vs. ADVISORY_ROLE.term = "Advisor" mismatches (web/lib/content/vocabulary.ts:7, web/lib/docs-map.ts:75, web/app/[locale]/docs/vocabulary/page.tsx:22), and web/lib/i18n/dictionaries/pl/home.ts:47 ("fleetwodna" should be "Podwodna") — all flagged by Copilot and prior automated review rounds, none addressed yet.
  3. crates/tui/src/fleet/members.rs add_fleet_model/remove_fleet_model — unlocked read-modify-write against the fleet membership file (no fd_lock, unlike manager.rs), a plausible lost-update race under rapid /model switching + auto-enroll.
  4. crates/config/src/descriptors.rs / provider_descriptors.json — the new dashscope catalog row appears to have no callers outside its own tests; the live route machinery behind the PR's DashScope verification is the separate, untouched crates/config/src/route/descriptor.rs. Worth a maintainer call: wire the descriptor in for real or stop growing an orphaned catalog.

Fix the still-open items →
· Branch: integration/shell-brand-20260902

@cursor

cursor Bot commented Sep 2, 2026

Copy link
Copy Markdown

Bugbot couldn't run - usage limit reached

Bugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit.

A user or team admin can review and increase usage limits in the Cursor dashboard.

(requestId: serverGenReqId_54ea7729-4f55-4609-a9c3-537ea22ada89)

- workflow::AgentType::Plan serializes as the canonical 'planner'
  ('plan'/'awaiter' stay accepted aliases), matching the FleetRole
  vocabulary the mega PR declares.
- Web: the vocabulary docs metadata, the vocabulary module header, and
  the docs-map topic description say Advisor (the public advisory term)
  instead of the retired Consultant spelling.
- Polish home dictionary: restore 'Podwodna powłoka terminala' — the
  fleet-vocabulary sweep had merged 'Fleet' into the compound word
  'Podwodna' (underwater), producing the non-word 'fleetwodna'.
@cursor

cursor Bot commented Sep 2, 2026

Copy link
Copy Markdown

Bugbot couldn't run - usage limit reached

Bugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit.

A user or team admin can review and increase usage limits in the Cursor dashboard.

(requestId: serverGenReqId_86101471-b0d8-4021-8f97-9b45ea0fbcdf)

@claude

claude Bot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Claude finished @Hmbown's task in 1m 10s —— View job


Claude finished reviewing this PR

Todo list

  • Gather context: read CLAUDE.md/AGENTS.md, PR description, prior review rounds
  • Identify what changed since the last automated review round (commit 9653c61 → current head ad638fa)
  • Review the new commit for correctness
  • Check whether previously-flagged open items were addressed
  • Post final review summary

This synchronize trigger added one commit, ad638fa ("fix: Copilot review findings — planner wire spelling and Advisor copy"), a 5-file/7-line diff aimed squarely at the items Copilot and the prior automated review rounds had flagged repeatedly. No other files changed since the last round.

Web/copy fixes: correct and complete

All four copy fixes are right:

  • web/app/[locale]/docs/vocabulary/page.tsx and web/lib/docs-map.ts — "Consultant" → "Advisor" in both locales, now matching ADVISORY_ROLE.term in vocabulary.ts.
  • web/lib/content/vocabulary.ts — module header comment updated to say "Advisor" instead of "Consultant".
  • web/lib/i18n/dictionaries/pl/home.ts"fleetwodna powłoka..." restored to "Podwodna powłoka..." (the Pod→Fleet sweep had eaten into the unrelated Polish word for "underwater"). I checked no other locale file has a matching mangled compound.

crates/workflow/src/lib.rs — only half of the flagged serde gap is fixed

Copilot's comment on this file explicitly said "This issue also appears on line 556 of the same file", i.e. it applies to both the Plan and Review variants of AgentType. This commit only fixes Plan:

#[serde(rename = "planner", alias = "plan", alias = "awaiter")]
Plan,
#[serde(
    alias = "review",
    alias = "reviewer",
    alias = "consultant",
    alias = "oracle"
)]
Review,   // <- still no `rename`, still serializes as "review" (snake_case default)

Review still has no #[serde(rename = "reviewer")], so it still serializes as "review", not the canonical "reviewer" the module's own doc comment claims ("The serialized spellings are the canonical Codewhale role vocabulary") and that the PR description declares (general / explore / implement / test / advisor (+ planner / reviewer / custom)). This is inconsistent with the fleet-profile layer, where "reviewer" is already an established canonical role slot (crates/tui/src/fleet/profile.rs, e.g. role_hint: "reviewer", loaded.profile.role.name == "reviewer").

The existing round-trip test wasn't updated either — json_accepts_pre_rename_agent_type_spellings_as_aliases (crates/workflow/src/lib.rs:2601-2632) still lists ("review", AgentType::Review) only in the legacy-alias, parse-only loop, and the canonical round-trip loop (which asserts serialize(parsed) == canonical spelling) still doesn't include planner or reviewer at all — so this gap wouldn't be caught by CI even after a fix.

Minimal fix, mirroring what was just done for Plan:

#[serde(
    rename = "reviewer",
    alias = "review",
    alias = "consultant",
    alias = "oracle"
)]
Review,

plus adding ("planner", AgentType::Plan) and ("reviewer", AgentType::Review) to the canonical round-trip assertions.

Fix the remaining Review→"reviewer" serde gap →

Still open from prior rounds (unchanged by this commit — no other files touched)

  1. crates/tui/src/fleet/members.rs add_fleet_model/remove_fleet_model — unlocked read-modify-write against the fleet membership file (no fd_lock, unlike manager.rs), a plausible lost-update race under rapid /model switching + auto-enroll.
  2. Stale Pod/Fleet doc comments: crates/tui/src/commands/groups/core/fleet.rs:1-16 (module doc still says /pod is primary), crates/config/src/lib.rs:1350 (says /pod is canonical, contradicting the normalization code right below it).
  3. crates/config/src/descriptors.rs / provider_descriptors.json — the new dashscope catalog row appears to have no callers outside its own tests; the live route machinery behind the PR's DashScope verification is the separate, untouched crates/config/src/route/descriptor.rs. Worth a maintainer call rather than a quick patch: wire the descriptor in for real or stop growing an orphaned catalog.

Branch: integration/shell-brand-20260902

@cursor

cursor Bot commented Sep 2, 2026

Copy link
Copy Markdown

Bugbot couldn't run - usage limit reached

Bugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit.

A user or team admin can review and increase usage limits in the Cursor dashboard.

(requestId: serverGenReqId_08035bb5-ee29-4377-bfed-a3ddb392e128)

@claude

claude Bot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Claude finished @Hmbown's task in 49s —— View job


Claude finished reviewing this PR

Todo list

  • Gather context: read CLAUDE.md/AGENTS.md, PR description, prior review rounds
  • Identify what changed since the last automated review round (commit ad638fa → current head 83bb338)
  • Review the new commit for correctness
  • Check whether previously-flagged open items were addressed
  • Post final review summary

This synchronize trigger added one commit, 83bb338 ("test: pointer proof accepts preview-appears when no baseline count is painted"), a 1-line diff entirely inside crates/tui/tests/cucumber/active_composer_pointer_pty.rs. No other files changed since the last round.

The diff itself: trivial, no bug

The only change is trimming the deadline panic! message (crates/tui/tests/cucumber/active_composer_pointer_pty.rs:234-240):

             panic!(
                 "{size}: click on [↑] at ({send_row},{}) produced no queue receipt \
                  {receipt:?} and no queue growth — pointer submit did not reach the \
-                 keyboard-submit dispatch path (seen={seen:?}, \
-                 expected={expected:?})\n{}",
+                 keyboard-submit dispatch path (seen={seen:?})\n{}",
                 send_col + 1,
                 tui.diagnostics()
             );

expected is dropped only from this format string; it's still bound at line 196 and still used at lines 207 and 210 (the grew check and the debug println!), so this doesn't introduce an unused-variable warning or any scoping issue — I traced the full function to confirm. Not a correctness bug, just a smaller panic message.

One minor note: the commit message ("accepts preview-appears when no baseline count is painted") describes behavior broader than what the diff actually does (a pure message-formatting trim, no logic change to how queued_before/expected/baseline handling works). Not blocking, just flagging the mismatch in case a behavioral change was intended but not included.

Still open from prior rounds (unchanged by this commit — no other files touched)

  1. crates/tui/src/fleet/members.rs add_fleet_model/remove_fleet_model — unlocked read-modify-write against the fleet membership file (no fd_lock, unlike manager.rs), a plausible lost-update race under rapid /model switching + auto-enroll.
  2. crates/workflow/src/lib.rs:554-560AgentType::Review still has no #[serde(rename = "reviewer")] (only Plan"planner" was fixed in ad638fa), so it still serializes as the non-canonical "review", contradicting the module's own doc comment and the PR's declared canonical vocabulary. The round-trip test also still doesn't assert planner/reviewer in the canonical-spelling loop.
  3. Stale Pod/Fleet doc comments: crates/tui/src/commands/groups/core/fleet.rs:1-16 (module doc still says /pod is primary), crates/config/src/lib.rs:1350 (says /pod is canonical, contradicting the normalization code right below it).
  4. crates/config/src/descriptors.rs / provider_descriptors.json — the new dashscope catalog row appears to have no callers outside its own tests; the live route machinery behind the PR's DashScope verification is the separate, untouched crates/config/src/route/descriptor.rs. Worth a maintainer call: wire the descriptor in for real or stop growing an orphaned catalog.
    · Branch: integration/shell-brand-20260902

@cursor

cursor Bot commented Sep 2, 2026

Copy link
Copy Markdown

Bugbot couldn't run - usage limit reached

Bugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit.

A user or team admin can review and increase usage limits in the Cursor dashboard.

(requestId: serverGenReqId_7d60c4d2-f69b-4f09-8d62-cc56d9c636ca)

@claude

claude Bot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Claude finished @Hmbown's task in 59s —— View job


Claude finished reviewing this PR

Todo list

  • Gather context: read CLAUDE.md/AGENTS.md, PR description, prior review rounds
  • Identify what changed since the last automated review round (commit 83bb338 → current head a746116)
  • Review the new commit for correctness
  • Check whether previously-flagged open items were addressed
  • Post final review summary

This synchronize trigger added one commit, a746116 ("test: the tolerant preview-appears proof (the arm the last commit missed)"), an 8-line diff entirely inside crates/tui/tests/cucumber/active_composer_pointer_pty.rs. No other files changed since the last round.

The diff itself: correct, no bug

run_pointer_submit_case's poll loop (lines 203-221) previously computed grew via seen.zip(expected).is_some_and(|(s, want)| s == want), where expected = queued_before.map(|n| n + 1). That meant whenever queued_before was None (no pending-preview row painted before the click — the common case when the queue starts empty), expected was also None, so zip always failed and grew was always false — the loop could only succeed via the receipt-toast text match, never via the queue-preview signal, for the empty-baseline case. This commit fixes exactly that gap:

let grew = match (queued_before, seen) {
    (Some(before), Some(now)) => now == before + 1,
    (None, Some(_)) => true,
    _ => false,
};

This now accepts "no baseline count was painted, but a count is visible now" as proof, alongside the existing "baseline + 1" proof. I traced the whole function: queued_before (line 144) and expected (line 196, still used only in the two debug println!s at lines 201/217, so no unused-variable issue) are unchanged; the new match arm binds a before: usize inside the match, shadowing the outer before: String from line 175 (the pre-click receipt-baseline snapshot) — valid Rust shadowing, scoped to the arm, not a bug, just worth knowing if reading the two befores side by side.

This new tolerant-match shape is also consistent with the pattern already used a few lines later in the same function for the final durable-queue proof (lines 260-263):

let grew = match (queued_count(&after), queued_before) {
    (Some(after_n), Some(before_n)) => after_n == before_n + 1,
    _ => after.contains("Queued "),
};

so this brings the polling-loop check in line with the function's own established idiom rather than inventing a new one.

I don't have shell-command approval in this session to run cargo check -p codewhale-tui --test cucumber directly, so this is manual trace verification rather than a compiler receipt — nothing in the diff suggests a compile or logic issue, but worth a real CI run to confirm before merge.

Still open from prior rounds (unchanged by this commit — no other files touched)

  1. crates/tui/src/fleet/members.rs add_fleet_model/remove_fleet_model — unlocked read-modify-write against the fleet membership file (no fd_lock, unlike manager.rs), a plausible lost-update race under rapid /model switching + auto-enroll.
  2. crates/workflow/src/lib.rs:554-560AgentType::Review still has no #[serde(rename = "reviewer")] (only Plan"planner" was fixed in ad638fa), so it still serializes as the non-canonical "review", contradicting the module's own doc comment and the PR's declared canonical vocabulary. The round-trip test also still doesn't assert planner/reviewer in the canonical-spelling loop.
  3. Stale Pod/Fleet doc comments: crates/tui/src/commands/groups/core/fleet.rs:1-16 (module doc still says /pod is primary), crates/config/src/lib.rs:1350 (says /pod is canonical, contradicting the normalization code right below it).
  4. crates/config/src/descriptors.rs / provider_descriptors.json — the new dashscope catalog row appears to have no callers outside its own tests; the live route machinery behind the PR's DashScope verification is the separate, untouched crates/config/src/route/descriptor.rs. Worth a maintainer call: wire the descriptor in for real or stop growing an orphaned catalog.
    · Branch: integration/shell-brand-20260902

@Hmbown
Hmbown merged commit 329960f into main Sep 2, 2026
33 of 34 checks passed
@Hmbown
Hmbown deleted the integration/shell-brand-20260902 branch September 2, 2026 16:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants