chore(release): prepare v0.9.5 - #5292
Conversation
…t gate - structcopy.rs: simplify nonminimal boolean in next_absolute_path_start (no behavior change) - latex_render.rs: remove always-true '|| true' last-row guard in parse_rows, which emitted a spurious empty row after a trailing row separator; add regression test Boy Scout repairs of pre-existing issues on origin/main so the configured strict lint gate is green.
- New crates/tui/src/commands/discovery.rs: user_command_shadows_builtin_canonical, user_command_shadows_builtin_alias, unshadowed_builtin_aliases (order-preserving) - Semantics ported from slash-completion predicates (widgets/mod.rs) which are the explicit alias-aware reference; palette consumes them in Phase 3 - 13 unit tests: canonical claims, accepted-alias claims, hidden ownership, rejected-alias omission, alias projection order, registry-lookup agreement guard - Registered pub mod discovery in commands/mod.rs - Temporary #[allow(dead_code)] on the three predicates until Phase 3/4 consumers land (recorded in planning-analysis-report.md); MUST be removed there Generated with Claude Code
- command_palette.rs: canonical-shadow check now uses commands::discovery::user_command_shadows_builtin_canonical over a collected metadata slice instead of user_registry.get(command.name) - palette_description_for_unshadowed_aliases now consumes discovery::unshadowed_builtin_aliases (order-preserving projection) - Removed temporary #[allow(dead_code)] markers from discovery.rs (all three predicates now have consumers); module doc note removed - New palette tests: visible canonical shadow (exactly one user-owned /help row with user metadata/action), accepted-alias suppression of built-in canonical row, hidden canonical shadow (no discovery row), alias-only shadow preserving canonical row without the claimed alias - Palette suite: 34 passed (30 existing + 4 new); shared 13/13; completion 23/23 guard green; strict clippy 0 warnings Generated with Claude Code
- widgets/mod.rs: builtin_visible_for_completion_match and push_command_entry now consume commands::discovery predicates; local duplicate user_command_shadows_builtin_canonical/_alias definitions deleted - New completion test: slash_completion_accepted_user_alias_claims_builtin_canonical_token (user alias claiming a built-in canonical token suppresses the built-in suggestion and surfaces the user command) - Completion suite: 24 passed (23 existing + 1 new); discovery 13/13 and palette 34/34 guards green; strict clippy 0 warnings; no ranking/dedup/ file-move changes; slash_completion_hints stays in widgets/mod.rs Generated with Claude Code
- New tests/features/feat-012-discovery-filtering.feature: 7 scenarios (AC1-AC6 + AT-010 alias-aware unification) covering all six FEAT-012 acceptance criteria and EPIC AT-008/009/010 - New commands/epic_discovery_acceptance.rs: scenario-level cucumber worlds bound to live palette builder, live slash completion, and live dispatch; fail_on_skipped + non-zero passed-step assertions per scenario - Registered module in commands/mod.rs - docs/architecture/command-dispatch.md: module map row for shared discovery.rs owner - feat012 selector: 7/7 scenarios pass, zero skipped, non-zero steps each - Guards: discovery 13/13, palette 34/34, completion 24/24; strict clippy 0 warnings Generated with Claude Code
- git_repo_root_reports_attempted_paths_when_no_repo_found created its harness in the checkout's parent dir; when the checkout is nested inside another git repo (e.g. a workspace repo with sibling checkouts), the harness itself resolved to that parent repo and the no-repository path was never exercised - Use the system temp dir with deep nesting beyond the parent-search limit, mirroring the sibling create_isolated_worktree no-repo test Boy Scout repair found by the FEAT-012 Phase 8 full workspace gate; test-only, no behavior change to git_repo_root itself.
…eptance harness FEAT-012 adds the shared discovery-shadowing contract (discovery.rs, 235 lines) and the Gherkin acceptance harness (epic_discovery_acceptance.rs, 750 lines) mirroring the accepted FEAT-011 pattern. Aggregate owned Rust source 673375 -> 674554 (+1179 lines). No new 1000-line modules. Pay down in v0.9.5 per the existing budget TODO notes.
registry_sync now returns instantly from the local snapshot and refreshes it in the background: incremental via updated_since, with a full pagination only when the snapshot is missing or older than a month, and atomic cache replacement.
Fixes an upstream Windows-lane test failure introduced by #5212 (commit f0a6898, "fix(tui): honest large-output truncation + recovery path"). #5212 flipped the adaptive-evidence contract so the model-facing truncation footer MUST name the on-disk artifact path, but the footer kept building that path with absolute_path.display().to_string(), which on Windows emits backslashes (\artifacts\) while the acceptance test asserts the POSIX form (/artifacts/). - truncate.rs: the truncated_preview recovery_path (both the adaptive evidence path and the legacy spillover fallback) now goes through crate::artifacts::format_artifact_relative_path, which normalizes separators to '/' — the same normalization the artifact_relative_path metadata field already used. - Consumers that read the footer path back (tool_routing, retrieval, UI preview) construct PathBuf from the string, and PathBuf::from accepts forward slashes on Windows, so no behavior change beyond the model-facing text being platform-independent. The failing test (headless_bash_success_and_failure_are_distinct_ bounded_exact_evidence) fails identically on upstream main without this PR's changes; this commit lands the repair inside the Layer 5.3 PR to unblock the Windows lane. Paulo Aboim Pinto
…-3-palette-completion-and-discovery-filte # Conflicts: # scripts/source-structure-budget.json
Upstream commit b6585ea (WIP: 0.9.4 fence, turn liveness, model picker, budget, and contributor credit, merged 2026-08-06) added three #[allow(dead_code)] attributes without bumping the dead-code budget, leaving both origin/main and this branch 3 over the 451 ceiling: - stuck_guard.rs: StepFingerprint::waiting_for_subagents (test-only ctor) - turn_loop.rs: should_hold_turn_for_subagents (test-only, #3216) - behavioral_tips.rs: enum BehavioralTip (3 of 6 variants unconstructed) None are removable without deleting test-only constructors or enum variants, so re-baseline 451 -> 454 per the gate's own guidance. Our FEAT-012 code contributes 0 net allows (Phase 2 added 3, Phase 3 removed them). Pay down in the #4785 sweep.
…ename Upstream ec5747f ("fix: todo_write sole progress surface + §3d/4a test alignment", 0.9.4) renamed work_update -> todo_write in the tool catalog, and the 0.9.4 WIP prompt tightening (b6585ea) grew the system prompt and representative-stage identities. Neither re-baselined scripts/runtime-contract-budget.json, leaving origin/main itself red on this gate. Sync all 49 drifted contract metrics to the measured receipt: - tool_catalog tool_names/identity digests/bytes/tokens for plan, act, operate x active/full (work_update -> todo_write; +125 bytes per surface) - system_prompt bytes/tokens for all modes (prompt tightening) - representative_context stage identities and byte counts The contract budget is a snapshot of the code; this locks the new identity per the gate's own "explicit maintainer decision" rule. No FEAT-012 changes contribute to the drift.
8f2b622 normalized the model-facing artifact footer to forward slashes (platform-independent). Two unit tests still asserted the raw OS path against that footer, failing on the Windows lane: - truncate::adaptive_evidence_footer_names_artifact_path_and_recovery - subagent::subagent_tool_results_spill_to_disk_and_stay_bounded_inline (upstream fa7c4b0) Assert the normalized form via format_artifact_relative_path, matching what the footer actually emits.
The rustfmt pass on the footer-path test assertions (093186a) added 4 lines to production truncate.rs, pushing the aggregate to 677475, 4 over the 677471 ceiling. Tighten ceiling 677471 -> 677475 (measured).
…-3-palette-completion-and-discovery-filte # Conflicts: # scripts/dead-code-budget.json
Upstream 21ed173 renamed work_update -> todo_write (canonical; old names stay hidden replay-only aliases) and updated docs/public-surface-facts.json, docs/TOOL_SURFACE.md, and docs/RUNTIME_SIMPLIFICATION_DESIGN.md — but left web/lib/public-surface-contract.test.ts expecting work_update, breaking the Lint & Type Check gate on every branch: - defaultActive array: work_update -> todo_write (matches facts file) - RUNTIME_SIMPLIFICATION_DESIGN expectation: same rename - web docs tools page: user-visible copy now names todo_write Full web suite: 250/250 passing.
build_session_snapshot restored the title from the in-memory cache before the disk lifecycle merge, and the cache is only refreshed at the end of the function. A snapshot taken before the first user message therefore pinned the placeholder title forever: every later snapshot overwrote the conversation-derived title with the stale cached copy. Title now resolves in priority order: 1. disk record, when the session already exists (user renames survive autosave, #2934/#4397); 2. in-memory cache, when no disk record exists for the session yet; 3. the title computed from the conversation (first user message). A placeholder that survived from an earlier snapshot yields to the computed title once a user message exists, healing both fresh and pre-existing sessions. The placeholder string is centralized in DEFAULT_SESSION_TITLE so the healing rule cannot drift from the generator. Regression tests: stale cached placeholder no longer overrides the generated title; a persisted placeholder record yields to the computed title. Existing picker-rename tests (rename survives autosave) still pass. Full codewhale-tui suite: 9708 passed; 10 failures all verified pre-existing on main (6) or parallel-flaky (4, pass in isolation). Reviewed by a sub-agent reviewer: no Critical/Major findings; Minor findings addressed (comments corrected, placeholder centralized, cache assertions completed); one documented edge (a session deliberately renamed to the literal placeholder title yields to the computed title).
- runtime-contract: regenerate tool_catalog for todo_write sole surface (plan/act/operate full/active now list todo_write, not work_update); bumps bytes/sha + prompt stages (agent plugins work) - web: public-surface-contract expects todo_write (matches docs/RUNTIME_SIMPLIFICATION_DESIGN already) - source-structure: 676325 -> 676652 (+327) — 321 for bf69e7f session-title fix plus 6 for stall/UI tweaks; durable test asset - engine: raise no_user_input_continues 12 -> 20 (6 sites) to stop false 'hit (12)' stops on long todo_write loops; preserves anti-runaway - subagent: GENERAL/PLAN intros now say todo_write, not work_update (child priming fix) - palette: WHALE_TEXT_HINT #8491AA -> #8A99B3 (+0.4 contrast) - tui: add BehavioralTipTodoWrite + 15 locale keys (hint: track with todo_write) - subagent tests: fmt fixes for isolated_fleet_roster_with + assert! expansion Refs: efcf47a, 21ed173, ec5747f, #5258
build_session_snapshot restored the title from the in-memory cache before the disk lifecycle merge, and the cache is only refreshed at the end of the function. A snapshot taken before the first user message therefore pinned the placeholder title forever: every later snapshot overwrote the conversation-derived title with the stale cached copy. Title now resolves in priority order: 1. disk record, when the session already exists (user renames survive autosave, #2934/#4397); 2. in-memory cache, when no disk record exists for the session yet; 3. the title computed from the conversation (first user message). A placeholder that survived from an earlier snapshot yields to the computed title once a user message exists, healing both fresh and pre-existing sessions. The placeholder string is centralized in DEFAULT_SESSION_TITLE so the healing rule cannot drift from the generator. Regression tests: stale cached placeholder no longer overrides the generated title; a persisted placeholder record yields to the computed title. Existing picker-rename tests (rename survives autosave) still pass. Full codewhale-tui suite: 9708 passed; 10 failures all verified pre-existing on main (6) or parallel-flaky (4, pass in isolation). Reviewed by a sub-agent reviewer: no Critical/Major findings; Minor findings addressed (comments corrected, placeholder centralized, cache assertions completed); one documented edge (a session deliberately renamed to the literal placeholder title yields to the computed title).
- runtime-contract: regenerate tool_catalog for todo_write sole surface (plan/act/operate full/active now list todo_write, not work_update); bumps bytes/sha + prompt stages (agent plugins work) - web: public-surface-contract expects todo_write (matches docs/RUNTIME_SIMPLIFICATION_DESIGN already) - source-structure: 676325 -> 676652 (+327) — 321 for bf69e7f session-title fix plus 6 for stall/UI tweaks; durable test asset - engine: raise no_user_input_continues 12 -> 20 (6 sites) to stop false 'hit (12)' stops on long todo_write loops; preserves anti-runaway - subagent: GENERAL/PLAN intros now say todo_write, not work_update (child priming fix) - palette: WHALE_TEXT_HINT #8491AA -> #8A99B3 (+0.4 contrast) - tui: add BehavioralTipTodoWrite + 15 locale keys (hint: track with todo_write) - subagent tests: fmt fixes for isolated_fleet_roster_with + assert! expansion Refs: efcf47a, 21ed173, ec5747f, #5258
registry_sync now returns instantly from the local snapshot and refreshes it in the background: incremental via updated_since, with a full pagination only when the snapshot is missing or older than a month, and atomic cache replacement.
When model = auto, dispatcher analyses prompt and selects pro vs flash.
- New crates/tui/src/commands/discovery.rs: user_command_shadows_builtin_canonical, user_command_shadows_builtin_alias, unshadowed_builtin_aliases (order-preserving) - Semantics ported from slash-completion predicates (widgets/mod.rs) which are the explicit alias-aware reference; palette consumes them in Phase 3 - 13 unit tests: canonical claims, accepted-alias claims, hidden ownership, rejected-alias omission, alias projection order, registry-lookup agreement guard - Registered pub mod discovery in commands/mod.rs - Temporary #[allow(dead_code)] on the three predicates until Phase 3/4 consumers land (recorded in planning-analysis-report.md); MUST be removed there Generated with Claude Code
- command_palette.rs: canonical-shadow check now uses commands::discovery::user_command_shadows_builtin_canonical over a collected metadata slice instead of user_registry.get(command.name) - palette_description_for_unshadowed_aliases now consumes discovery::unshadowed_builtin_aliases (order-preserving projection) - Removed temporary #[allow(dead_code)] markers from discovery.rs (all three predicates now have consumers); module doc note removed - New palette tests: visible canonical shadow (exactly one user-owned /help row with user metadata/action), accepted-alias suppression of built-in canonical row, hidden canonical shadow (no discovery row), alias-only shadow preserving canonical row without the claimed alias - Palette suite: 34 passed (30 existing + 4 new); shared 13/13; completion 23/23 guard green; strict clippy 0 warnings Generated with Claude Code
Reviewing PR #5292 (chore(release): prepare v0.9.5)
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: a701490dde
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Bring the dead-code ledger back to its existing ceiling by deleting helpers that were added for unfinished follow-up slices and by modeling the OAuth callback listener as intentional RAII state. The core Engine keeps its public constructor shape but no longer stores fields that are not yet part of the runtime. Verified with the dead-code and source-structure gates, the runtime-contract gate, focused core/TUI unit tests, rustfmt, and strict Clippy for codewhale-core and codewhale-tui.
|
Claude finished @Hmbown's task in 2m 37s —— View job Reviewing PR #5292 (chore(release): prepare v0.9.5)
|
Axum rejects duplicate method/path registrations while constructing the runtime router. Keep skill toggle plus uninstall and MCP list plus create on their respective single route definitions. Add an explicit mobile router-start regression so future overlaps fail in the focused runtime API unit lane. Verified with the mobile, MCP management, skill lifecycle, and skill-state tests; codewhale-tui all-targets clippy; and the runtime-contract budget gate.
Run the ignored persistence backlog receipt test from the TUI library after the integration target move. Pin the exact Cargo command in a hermetic harness test and reject successful zero-test or missing-receipt runs so future test relocations fail clearly.
Keep only the journal-backed active history in queued snapshots, then materialize the legacy messages projection in a temporary copy at the disk boundary. This removes the near-2x paused-channel retention introduced by the session journal while preserving 0.9.4 readers and checkpoint recovery. When load-time tool-history repair changes the active projection, append the repaired suffix as a sibling branch instead of letting the stale journal overwrite it or rewriting prior evidence. Verified with the paused measurement, all persistence-actor and session-manager tests, focused append-only repair regressions, rustfmt, and strict all-target codewhale-tui Clippy. The residual 0.46% journal schema overhead and aggregate source ledger are reconciled separately after the active release lanes land.
Register the tree, branch, and resume descriptions in the complete-locale contract and provide native copy in every shipped language. Keep the todo command name code-owned through a placeholder, and remove internal issue wording from the fork description.\n\nVerified with the localization and behavioral-tip test suites plus JSON parsing for every locale pack.
Keep provider-neutral auto selection in the provider-aware TUI and launch workflow lanes from the exact running executable. Repair CNB and installer alias contracts, refresh legacy website-installed TUI bytes during upgrades, and make account pull reject an unimplemented local import truthfully.\n\nVerified with focused CLI/config tests, strict Clippy, workflow contracts, shell syntax checks, and hermetic web installer tests.
Own and abort the MCP OAuth callback task so cancelled flows release fixed ports. Preserve omitted-versus-null semantics for nullable MCP PATCH fields while rejecting a server with no endpoint, and make replacement thread goals begin a fresh lifecycle instead of inheriting usage. Agent-assisted implementation; primary review restored the existing create-validation test and added persisted-state coverage for an invalid final-endpoint clear. Verified with focused OAuth, MCP management, and thread-goal tests, rustfmt, and strict all-target TUI Clippy.
Rebaseline the paused persistence receipt after eliminating duplicate queued history: retained payload drops from 16,924,032 bytes in the broken candidate to roughly 8,528,000 bytes. The ceiling is under 0.5% above the pre-journal schema and includes 0.015% headroom over the largest of repeated clean samples. Record the final net source delta at 86 lines above the prior review ceiling with no new package, binary, or thousand-line module. Verified with both budget checker suites, repeated clean measurements, JSON validation, and the source-structure gate.
Remove the stale /sessions resume alias now that /resume is a first-class command. At the persistence disk boundary, reconcile a non-empty compatibility projection back into the append-only journal before serialization so direct SavedSession callers cannot save a newer transcript that the next load silently replaces with an older journal branch. Verified with both command registry invariants, stale-checkpoint recovery, long-history save/load, and checkpoint round-trip tests.
Keep canonical Bash.run available to Scout and Reviewer through the hardened read-only executor without reviving the retired exec_shell alias. Restore nested agent visibility below the configured depth ceiling, and align roster/setup assertions with the seeded worker, planner, and custom members. Verified with 420 subagent tests, 16 Fleet roster tests, and the focused setup override regression.
Budget the pinned background-work row only from space left after the Work strip and measured composer growth. Compact terminals now hide the redundant chip before it steals rows from chat or the idle ocean. Verified with all nine work-surface rail, resize, paint, and ambient-floor regressions.
Scope both config-path environment variables through the shared guard, and run the xAI API-key confirmation against a canonical temporary Codewhale home with the file secret backend. This removes ambient config/keychain coupling and the macOS /var symlink failure from the full parallel suite. Verified with the focused xAI provider confirmation test.
Resolve relative anchor destinations against the fetched HTTP(S) page through htmd parsed elements before Markdown conversion. Absolute, fragment, non-HTTP, and malformed destinations retain the converter existing behavior. Verified with all 19 extraction tests, including readable page chrome removal and relative-link preservation.
Reconcile the aggregate Rust ledger at 685165 lines after the release-gate repairs for session persistence, Scout authority, compact layout, provider-test isolation, and fetched relative links. Package, binary, large-module count, and largest-module ceilings do not grow. Verified with the source-structure checker and JSON parsing through the checker.
The single-binary library conversion made the private command-safety module visible to rustdoc while its examples still imported it as a public API. Render those examples as behavior tables instead of publishing an internal policy module solely for doctests.\n\nVerified with cargo fmt and the codewhale-tui all-features doctest target.
Record GitHub v0.9.4 as the latest published release while keeping the workspace and website source candidate at v0.9.5. Regenerate the build-time facts fallback so the manual Cloudflare deploy receipt compares against the same published tag already served from KV. Verified with the focused facts and deploy contracts, the complete 256-test web suite, ESLint, TypeScript, facts/docs drift checks, and a 288-page production build.
|
Claude finished @Hmbown's task in 10m 26s —— View job Reviewing PR #5292 (chore(release): prepare v0.9.5)
|
Reject rooted current-drive operands at the read-only Scout boundary, render absolute artifact footer paths with canonical forward slashes, and make the Scout cwd proof use Git-for-Windows pwd output without weakening its semantic path comparison. Verified with the four Windows-failing TUI unit regressions, the related artifact test, the strict all-target TUI Clippy gate, formatting, source-structure budget, and diff checks.
|
Claude finished @Hmbown's task in 1m 36s —— View job Reviewing PR #5292 (chore(release): prepare v0.9.5)
|
Keep pwd as a separately admitted read, but prove the ordinary Scout dispatch workspace by reading unique sentinel bytes through a bounded relative cat operand. This avoids comparing platform-specific pwd renderings and removes the temporary Windows-only pwd flag expansion. Verified with the focused Scout test, strict all-target/all-feature TUI Clippy, formatting, source-structure budget, and diff checks.
|
Claude finished @Hmbown's task in 1m 10s —— View job Reviewing PR #5292 (chore(release): prepare v0.9.5)
|
Run the isolated Skills Manager scenario through the pty integration-test binary and use its module-qualified name so --exact executes one test instead of zero. Lock the command into the workflow contract and update the durable TUI verification examples. Verified with the exact ignored PTY command, the workflow contract test, actionlint YAML/expression checks, and git diff --check.
|
Claude finished @Hmbown's task in 2m 3s —— View job Reviewing PR #5292 (chore(release): prepare v0.9.5)
|

Summary
Codewhale v0.9.5 consolidates the terminal app into one compiled runtime while keeping the
codewhaleandcodewcommands, removes default turn ceilings that interrupted long work, and aligns the updater, installers, release assets, website, and package surfaces around that contract.This branch also records the exact current heads of community PRs #5255, #5256, #5257, and #5258 as merge ancestry. Each ancestry merge was proven tree-identical, so the contributor commits and GitHub provenance are retained without replaying stale/conflicting patches over their already-integrated behavior.
Release changes
codewhaleandcodew, with v0.9.5-only byte-identicalcodewhale-tui-*asset filenames as an update bridge for installed v0.9.4 clientsSecurity boundary
The Scout evidence shell executes only a positive, direct-argv read profile. It resolves external executables canonically, validates effective-workspace operands and symlink containment, rejects Windows drive-relative paths, suppresses inherited shell hooks and Git/GitHub helper redirects, intersects parent shell/network ceilings, and keeps bounded Verifier
Runauthority typed and separate from Scout Bash.Contributors
model = "auto"routingVerification
cargo fmt --all -- --checkcargo clippy -p codewhale-tui --all-targets --locked -- -D warnings./scripts/release/publish-crates.sh dry-runcodewhale+codewThe full exact-head multi-platform CI and seven-target/34-asset release-candidate workflows will be dispatched from the merged
mainSHA before the tag is created. Android execution remains cross-build evidence only; real Termux device execution is not claimed.No-Issue: v0.9.5 release integration; the constituent fixes and community PRs are linked above, and unfinished milestone work was moved to v0.9.6.