Repository navigation
0.10.1 integration: Engine convergence, reviewed TypeScript mods and Ratatui UX - #6815
Merged
Merged
Conversation
The founder reported three problems with two ChatGPT accounts. The browser was signed into one account and Codewhale's own ChatGPT sign-in held another account that had run out of usage. Login gave no way to choose the account. Nothing showed which account Codewhale was using. The usage-limit error did not say which account hit the limit or how to switch. Choose: the ChatGPT parameter row now sends prompt=login (OIDC Core 1.0 section 3.1.2.1) on the authorize URL, and the login prints a private-window fallback. The only change is the row's authorize_extras; refresh never visits the authorize endpoint. Evidence for prompt=login, and its limits: - openai/codex @ f53f5a6 codex-rs/login/src/server.rs build_authorize_url sends id_token_add_organizations, codex_cli_simplified_flow and originator, and no prompt. openai/codex issue #17092 "No way to switch accounts without clearing browser session" is still open. So upstream Codex does not use prompt, and openai/codex uses prompt=login only in generic OAuth and gateway test fixtures (oauth/client_tests.rs, gateway_auth_tests.rs). - cnlimiter/codex-manager, a third-party multi-account tool, src/core/openai/oauth.py sends prompt=login to auth.openai.com /oauth/authorize with the same public client and parameters. - auth.openai.com/.well-known/openid-configuration does not list prompt_values_supported. - It was not tested against the live issuer. Unauthenticated curl probes of /oauth/authorize, with and without prompt, get a Cloudflare 403. If the issuer ignores prompt, the printed "open the URL in a private window" fallback still lets the user choose the account. xAI's device flow already lets the user choose the account on the issuer's page. Replace: activate_login used to merge a new grant into the previous entry for the same scope. When the new grant had no refresh token, id token or account id, account A's value stayed next to account B's access token. A login now writes a fresh entry. OAuthActivation reports the replaced account. Show: account_label_from_id_token decodes the ID token already stored with the credential. It reads email or the https://api.openai.com/profile email, plus the chatgpt_plan_type claim, entirely locally. It strips control characters and caps the length. The label is display-only, so the signature is not verified. Nothing new is stored because the label is derived from the existing id_token. Where it appears: - the end of login: "Signed in to ChatGPT as <email> (<plan>). Replaced the previous Codewhale ChatGPT sign-in (<old>)." - the TUI transcript after /provider login - the provider picker "Credential:" line - `codewhale auth status` (active source for openai-codex, "signed-in account" for xai) and `codewhale auth list` `codewhale auth list` also now reports the owned ChatGPT sign-in as owned-oauth. Before, it printed "missing" for that row. Switch: `auth chatgpt` and `auth xai-device` help now says "run again to switch accounts", and status prints a switch-account line. Usage limit: a 429 with {"error":{"type":"usage_limit_reached"}} (the openai/codex codex-api/src/api_bridge.rs mapping) is now typed QuotaExhausted, which is not retried. Before, it was a retryable RateLimited. On a ChatGPT or xAI OAuth route, plan-quota errors now include the signed-in account label and the exact switch command. The command is `codewhale auth chatgpt` or `codewhale auth xai-device`. The guidance is left out when a process token (OPENAI_CODEX_ACCESS_TOKEN) outranks the sign-in. Docs: docs/PROVIDERS.md, "Subscription sign-in accounts (ChatGPT, xAI)". Known limits: a consented Codex CLI or Grok CLI import shows no account label, because only Codewhale-owned files are read. The org title from id_token_add_organizations is not shown. Tests (targeted, local): - codewhale-tui: 11 new or touched tests, "test result: ok. 11 passed; 0 failed". Broader oauth:: / provider_picker:: / llm_client:: / credential_resolve / native_xai_oauth run: "test result: ok. 304 passed; 0 failed". - To show the fixes matter, I reverted each one (prompt=login, the usagelimitreached code, and the fresh-entry replacement). The 4 regression tests then failed ("0 passed; 4 failed"); relogin failed on refresh-a surviving into account B's credential. - codewhale-cli: "test result: ok. 26 passed; 0 failed" (owned / xai / codex / status / list filter, including the new owned_subscription_sign_ins_show_account_label_without_token_material). - cargo fmt --all -- --check clean. cargo clippy -p codewhale-tui -p codewhale-cli --all-targets --all-features --locked with the CI flags (-D warnings plus the CI allow list) printed no warnings or errors. Blocking-call and dead-code budgets pass. Refs #5778 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014ZwqatxgVFxHvovngywnks
… one Review follow-up for #6715. - Quota guidance comes from the credential the client actually sends. ChatGPT: the label is read from the same credential snapshot (owned entry or consented Codex CLI file), so a stale owned generation that fell through to consent no longer names the owned account. xAI: guidance only when the resolver's source is the xAI OAuth branch (`XAI_OAUTH_KEY_SOURCE`); an `auth_mode = "oauth"` route that fell back to an API key gets none, and the label is kept only when it belongs to credentials holding the same token. - Account labels use the runtime's usability test (fresh access token or a refresh token), shared with `credentials_valid`, so an expired entry with no refresh token names no account in the picker, `auth status` or `auth list`. - A login replaces the whole owned sign-in: other scopes are no longer carried into the new generation, so an older account under a differently spelled issuer cannot outrank the new login or keep its refresh token on disk. `replaced` names the entry that was in use; a re-login as the same account says so and how to pick another. - Guidance points to `/auth chatgpt` / `/auth xai-device` inside Codewhale and says to restart open sessions after a shell login. - `usage_not_included` (plan without Codex) is classified with `usage_limit_reached` instead of retried as a rate limit. - `prompt=login` moves to `account_choice_extras` with an opt-out, `CODEWHALE_CHATGPT_OAUTH_NO_PROMPT`. - The xAI device flow prints the same account-choice hint as ChatGPT. - Workspace-plan labels (team, business, enterprise, unknown) carry an 8-character account-id prefix so two workspaces on one email differ. - `auth status`: with an env token set, the switch line says to unset it first; login prints the same warning. xAI status reports why the account label could not be read, and no longer claims storage was unprobed on the line that now reads it. Tests (targeted, CARGO_TARGET_DIR isolated): - cargo test -p codewhale-tui --lib -- account_label usage_limit relogin stale_owned_entry authorize_url subscription_quota xai_oauth_mode chatgpt_usage_limit activation test result: ok. 46 passed; 0 failed - cargo test -p codewhale-tui --lib -- oauth codex xai provider_picker quota test result: ok. 406 passed; 0 failed - cargo test -p codewhale-cli --lib -- auth xai owned test result: ok. 44 passed; 0 failed - New regressions relogin_drops_other_scopes_and_names_the_account_it_replaced, stale_owned_entry_names_no_account and xai_oauth_mode_that_fell_back_to_an_api_key_gets_no_sign_in_guidance fail with the fixes reverted (0 passed; 3 failed) and pass with them (3 passed; 0 failed). - cargo fmt --all -- --check: clean. Not run: npm test / check:web (no web surface touched), full workspace suite. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014ZwqatxgVFxHvovngywnks
Chain-segment ("<!-- scoped instructions: ... -->") and
<project_rule source=...> labels carried absolute paths into the pinned
system prompt, so a checkout move or recase changed the prompt prefix
and could emit a spurious <context_update> history append.
Render both labels repo-relative (git-root-relative, forward slashes),
falling back to workspace-relative for rules outside any checkout and
to the absolute spelling only for paths outside the label root
(unreachable by construction). The label root is computed once and
threaded through context_chain_dirs, so the chain bounds and the
chain-segment labels derive from one and the same git walk.
Regression tests pin repo-relative chain and rule labels, the
workspace-relative fallback without a git root, the absolute escape
hatch for unplaceable paths, and byte-identity of the whole system
block for the same tree checked out at two different locations.
Adapted from the Pinvou fork (Pinvou/CodeWhale 7f04c90, PR #70);
builds on the file-name labels from the previous commit.
Signed-off-by: asto18089 <asto18089@126.com>
The launcher integration doc claimed rc.6 was the latest release; it now states once that rc.6 (August 2026) is the last verified version, and what the code does with other versions: older or no --patch is incompatible, a newer parseable version is stale-version, and a version that does not parse (for example 0.1.7-alpha.2, since only -rc.N suffixes parse) is offline and refused. The authoring guide and the importer's module doc now separate the static importer (never executes plugin code; TUI slash command and Runtime API only, no CLI subcommand) from the launcher integration and from the experimental extension host, and say which CI job exercises the pinned five-file fixture. Docs and one comment only; no cargo run. web/scripts/check-docs.mjs passes but does not cover these files. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Signed-off-by: CodeWhale Bot <bot@codewhale.net>
The launcher integration parsed only MAJOR.MINOR.PATCH[-rc.N], so a current DSH release such as 0.1.7-alpha.2 was reported as offline and refused. The hand-rolled parser is replaced by the semver crate the tui crate already uses; precedence comparison ignores build metadata. Such a version is now stale-version (launchable once connected, unverified), like rc.7 was. VERIFIED_DSH_VERSION, the --patch check and the offline mapping for text that is not a version are unchanged; no newer version is claimed verified. cargo test -p codewhale-tui --lib integrations::dsh: 42 passed; 0 failed (run by the implementing agent; rustfmt check clean on both files). Full gate not run. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Signed-off-by: CodeWhale Bot <bot@codewhale.net>
Cargo.toml declared rust-version 1.88, but a locked dependency (serde-saphyr) requires 1.89 and CI's MSRV job builds 1.89. docs/INSTALL.md already recorded that a 1.88 install of v0.10.0 fails. The declaration, the English and Chinese install guides and the npm wrapper's build-from-source hints now say 1.89. cargo metadata --locked: ok. npm wrapper tests: 75 passed, 0 failed. No Rust build run for this change. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Signed-off-by: CodeWhale Bot <bot@codewhale.net>
…ign-in summary Review repair for #6715 (choose, show and switch ChatGPT and xAI accounts): - Account labels come from the read that proved the sign-in usable: `usable_sign_in` replaces `credentials_present` in the credential resolver and `CredentialSource::OAuth` carries the label, so the provider picker opens no credential file of its own (`owned_account_label` and `get_xai_access_token` are removed). - xAI quota guidance reads its account label from the credential the client sends (`active_route_api_key_with_xai_sign_in`), one read shared by the resolver, the guidance and the picker. - `OAuthActivation::summary` / `env_override_warning` render through `tr(locale, MessageId::Auth*)`; the six keys ship in all 15 locale packs. The TUI passes its UI locale; shell commands pass `Locale::En` beside their English-only surrounding text. - A new login replaces the whole generation (it holds only the new scope), so an older account's entry can no longer outrank it in `select_entry`. Focused test results for this and the commits that follow are recorded in the merge commit of origin/wave/0.10.1-next that follows them (this commit was first authored as an untested WIP). Refs #6715 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: CodeWhale Bot <bot@codewhale.net>
`codewhale auth status xai` opens the owned generation to read the account label, so "storage unprobed" misdescribed it. `auth get xai` and the generation line now say the account label is read and only the token's availability is not verified. The owned-OAuth status test pins both lines. Focused test results are recorded in the merge commit that follows. Refs #6715 Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Signed-off-by: CodeWhale Bot <bot@codewhale.net>
Plan-limit guidance names the account whose credential the client sends: a consented Grok CLI import names the Grok file's account (the switch command replaces the consent), and a ChatGPT process token gets no guidance because a re-login would not change the sending account. The Codex consented-import, xAI owned sign-in and xAI API-key fallback cases were already pinned; the three provenance classes the review listed are now all covered. Focused test results are recorded in the merge commit that follows. Refs #6715 Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Signed-off-by: CodeWhale Bot <bot@codewhale.net>
`OAuthActivation::summary` substitutes `{provider}` and `{account}` into the
six Auth* messages, so a pack that drops a placeholder or ships English
would silently lose the account name or stay untranslated. The test checks
all complete packs for placeholder parity and non-English text.
Focused test results are recorded in the merge commit that follows.
Refs #6715
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Signed-off-by: CodeWhale Bot <bot@codewhale.net>
…run) An extension can register a slash command through the host's `commands` service (registration kind `command`); invoking it sends `command/run` to the host. A command returns text shown to the user, a prompt submitted as the user's next message, or both; it never calls the model or a tool itself, so anything that follows goes through the normal turn and its approvals. - A command cannot take a built-in's name or alias, or another plugin's command name (refused at registration with a reason). A markdown command wins a clash when the user registry loads. - Registrations are owned like tools: removed on disable, crash and generation change; handles are never reused, so a stale reference fails rather than running a newer command. - Result text is stripped of terminal escapes and bounded; an oversized prompt is refused, never truncated. The call is bounded by a 30 s deadline, then cancelled. - DSH-style command registrations work unchanged. - Protocol: generated TypeScript regenerated, corpus cases 37-45, the core-authority lint still passes. Known limits (recorded in the design's "As built" section): no keypress cancel before the deadline; TUI only (the Runtime API omits extension commands); no agent/session handle or attachments for the handler. Still behind `[features] extension_host` (experimental, off by default). cargo test -p codewhale-tui --lib -- extension_host:: commands::user_registry (real Node host, macOS): 85 passed; 0 failed. Host suite on Node 22.20: 79 passed, 1 skipped (Bun-only). Reported by the implementing agent and not re-run by the committer: host suite on Bun 1.4.0, 80 passed. CI-policy clippy not yet run on this commit; Linux and Windows unrun. Signed-off-by: CodeWhale Bot <bot@codewhale.net> Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…o 15
Test infrastructure only; no production code and no visibility change in
crates/tui/src/mcp*. The suite is the gate a host-backed MCP dispatch must
pass before the Rust pool can be removed (CURRENT_DECISIONS section 26).
New cases pin, for the Rust pool: stdio over a real child (exit mid-call is
"outcome unknown, not retried", next call reconnects), Streamable HTTP
session lifecycle and stale-session replay, an unsupported protocol version,
catalog pagination and the three catalog budget caps, approval hints,
needs-auth on 401, a bearer that is sent but never recorded, refusal of a
cross-origin redirect, and tool and server deny rules. Each has a negative
control, and three deviant dispatches (replays a failed call, refreshes its
own catalog, leaks the bearer) are caught.
The dispatch trait gains `approval_hint`, the factory takes
`DispatchSetup { config, disallowed_tools }`, and `boot` may fail while
`catalog`/`call` still answer.
Recorded as current behaviour: `notifications/tools/list_changed` is
ignored by the Rust pool (the catalog refreshes on reconnect only).
Not covered: real OAuth login, legacy SSE transport, concurrent calls, the
32 MiB aggregate cap, reviewed-launch hash refusal for stdio; stdio cases
are skipped off Unix. The fixtures README still says two transcripts.
cargo test -p codewhale-tui --lib -- conformance:: (macOS): 32 passed;
0 failed. Blocking-call and dead-code budgets pass (implementing agent's
run). CI-policy clippy not yet run on this commit.
Signed-off-by: CodeWhale Bot <bot@codewhale.net>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Brings the branch up to date with main, which now carries #6737 (the file-name labels this PR was stacked on) as merge 1d42af9. One conflict, in the import block of crates/tui/src/project_context.rs: this branch's side imported project_instructions_source_label (already present on main's side, after the #6737 rustfmt-ordering fix) and added repo_relative_source_label. Resolved by keeping main's single `pub(crate) use ...project_instructions_source_label;` and this PR's `use ...repo_relative_source_label;`, dropping the duplicate re-export. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Signed-off-by: CodeWhale Bot <bot@codewhale.net>
Merges 9626357 (the 0.10.1 wave) into the #6715 review repair. One textual conflict, crates/localization/locales/zh-Hant.json, resolved keeping both sides: this branch's six Auth* sign-in keys and the wave's TranscriptThought / TranscriptThoughtFor keys (all 15 packs now hold 2446 keys). The wave's own fix for the Rust 1.99 `fetch_update` deprecation removes the two build errors this branch hit on the stable 1.99 toolchain. No semantic break surfaced: the wave's oauth.rs-adjacent, credentials and endpoint-boundary changes compiled and passed against the account-label work. Evidence on the merged tree, via cargowhale, warnings as errors: - cargo fmt --all -- --check: clean - cargo clippy -p codewhale-tui -p codewhale-cli -p codewhale-localization --all-targets --all-features --locked -- -D warnings -A clippy::uninlined_format_args -A clippy::too_many_arguments -A clippy::unnecessary_map_or: exit 0 (after the type alias in the next commit; the merged tree alone tripped clippy::type_complexity) - cargo test -p codewhale-tui --lib -- oauth:: credential_resolve credentials:: provider_picker quota_guidance quota_errors sign_in_guidance relogin_ activation_ xai_ auth_: 408 passed, 0 failed - cargo test -p codewhale-cli --lib -- xai_ auth_ owned_oauth: 33 passed, 0 failed - cargo test -p codewhale-localization: 53 passed, 0 failed - Regression proof: with activation reverting to `previous_file.clone()` + `remove(scope)` and `summary()` forced to Locale::En, `cargo test -p codewhale-tui --lib -- relogin_` gives 0 passed, 3 failed (relogin_under_another_client_id_switches_runtime_credentials_and_label: left "access-a" right "access-b"; relogin_with_another_account_replaces_the_owned_entry: localized summary equals English; relogin_drops_other_scopes_and_names_the_account_it_replaced). Restored, the same filter passes. - python3 scripts/check-blocking-calls-budget.py: within budget (707 sites); check-dead-code-budget.py and check-provider-registry.py pass. Local tests only; no hosted CI, provider call or deploy was run. Refs #6715 Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Signed-off-by: CodeWhale Bot <bot@codewhale.net>
…er read `active_route_api_key_with_xai_sign_in` tripped clippy::type_complexity under CI's -D warnings; `ResolvedApiKey` and `XaiSignInLabel` aliases name its parts. The provider picker comment records the known limit for the account label: it adds no credential read (the resolver's structural read, formerly `credentials_present`, already ran synchronously when a row is built before #6715), and the blocking-calls ratchet stays within budget. Verified by the clippy, test and ratchet runs listed in the merge commit that precedes this one (re-run after this change: clippy exit 0; tui 408, cli 33 and localization 53 passed, 0 failed). Refs #6715 Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Signed-off-by: CodeWhale Bot <bot@codewhale.net>
…y, linked state and file-mode fixes - Task workers (#6728, #6573): an idle worker with nothing claimable naps 1 s instead of stat-ing the queue every 200 ms (about 10 stats a second with two workers, which 0.9.12 did not do). Pending work and in-process notifies are unchanged. A settled queue now notices another process's write within about 1 s rather than 200 ms. - Task store lock (#6573): the holder records its pid and acquisition time in the lock file, so "busy" names the holder and how long it has held the lock when that can be read. The repeated "Task claim unavailable" error is logged once per episode, then at debug. - Web search (#6746): when the Bing fallback is allowed, DuckDuckGo gets 60% of the budget and Bing the rest, so a hanging DuckDuckGo no longer starves the fallback. A custom search_base_url still has no public fallback and keeps the full budget. - PowerShell (#6745): CODEWHALE_POWERSHELL_EXECUTION_POLICY=inherit omits the process-scope -ExecutionPolicy Bypass. The default is unchanged. Documented in ENVIRONMENTS (en, zh_hans). Not run on Windows. - Linked .codewhale: the workflow journal creates nothing until a record is appended and appends through the confined helpers; the coordination lock rejects a linked state path before creating directories. - File modes: the runtime log is created 0600 without following symlinks and an existing log is tightened; .reconcile.lock and current.json.lock reuse the private lock-file opener. fleet.lock was already 0600; a test pins it. Verified on macOS, Rust 1.99, together with the UI fixes in the next commit: cargo fmt --all --check clean; CI-policy clippy on codewhale-tui and codewhale-localization clean; focused tui lib tests 518 passed, 0 failed, 3 ignored; blocking-call budget within budget (one ratchet entry tightened for journal.rs); dead-code budget at budget. Full suite and other platforms not run locally. Signed-off-by: CodeWhale Bot <bot@codewhale.net> Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…e revision; short paste toast - #6800: a locally cancelled or stall-recovered turn cancels its in-flight dispatch instead of leaving input blocked for up to the 60 s dispatch bound. The cancel goes through the existing dispatch-failure path, so the unsent prompt returns to the composer. - /edit: when the rollback is refused, the revised text is restored to the composer with edit mode re-armed instead of being dropped; opening /edit while a queued draft is being edited returns that draft to the queue first. - Oversized paste: the toast is a short sentence that fits, and the full message with the write error goes to the transcript once. New key in all 15 locales. - #6652: the thinking-fold set is no longer cloned every frame. Verified with the previous commit: focused tui lib tests 518 passed, 0 failed, 3 ignored; codewhale-localization 52 passed, 0 failed; fmt and CI-policy clippy clean. macOS only; the larger scroll-lag change and the main-loop idle backoff are not in this commit. Signed-off-by: CodeWhale Bot <bot@codewhale.net> Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
… segments Merges the head of #6739 (38e04c5, by asto18089) unmodified, so the original commit keeps its author. The contributor's fork refuses maintainer pushes (HTTP 403), so the merge with main that resolves the import-block conflict in crates/tui/src/project_context.rs is carried here instead of on their branch. No change to the contributor's code. cargo test -p codewhale-tui --lib project_context: 88 passed; 0 failed (run on the merge with main, before this merge with the wave; the wave's two extra commits do not touch project_context). rustfmt clean on the touched files; CI-policy clippy on codewhale-tui printed no warnings. Refs #6739 Signed-off-by: CodeWhale Bot <bot@codewhale.net> Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…ins, plugin config and context - Licence notices: the embedded host bundle carries MIT-licensed packages (cordis, schemastery, cosmokit, dsh-util-values, dsh-tools excerpts). dist/LICENSES.txt is now generated at build time from the bundler's metafile and each package's own licence, embedded, and written beside the materialised bundle. THIRD_PARTY_NOTICES.md lists the packages. A test reads the package markers in the embedded bundle and requires a notice and a third-party entry for each. - Tool input is checked against the tool's registered JSON Schema before an approval card exists and again before the call is sent; an invalid input is a tool error the model can correct. A schema that cannot be compiled is refused at registration. jsonschema moves from a dev-dependency to a dependency of codewhale-tui (already in the lock file through codewhale-workflow-js; Cargo.lock unchanged). - A plugin with several native entries activates all of them under one owner; a failing entry fails the owner and the earlier entries are disposed. - Plugin context: tools and commands receive the calling workspace and a private per-plugin data directory. `[plugins."<name>".config]` in the user's config.toml reaches the plugin (16 KiB cap; project config cannot set it); a change starts a new generation; `/plugin show` lists the configured keys, never values. - `codewhale --enable/--disable <feature>` before a subcommand is passed through by the dispatcher instead of being rejected. - Docs and config comments: Linux sandbox wording, the 30 s handshake, the macOS sandbox write allowances. Known gaps: the trust review screen does not show config keys; a running session does not watch config.toml; no end-to-end launch of a rebuilt binary for the --enable fix. Verified by the committer on macOS, Rust 1.99, real Node 22.20 host: cargo fmt --all --check clean; CI-policy clippy on codewhale-tui and codewhale-cli clean; cargo test -p codewhale-tui --lib -- extension_host:: plugins:: commands::user_registry conformance:: integrations::dsh: 411 passed, 0 failed, 1 ignored; codewhale-cli lib: 475 passed, 0 failed; host suite on Node: 88 passed, 0 failed, 1 skipped. Reported by the implementing agent, not re-run: host suite on Bun 1.4.0, 89 passed. Linux, Windows and the Rust-side Bun tests unrun. Signed-off-by: CodeWhale Bot <bot@codewhale.net> Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…nput validation, plugin config, MCP parity suite Brings the TypeScript extension work onto the 0.10.1 release branch: extension slash commands (command/run), licence notices for the embedded host bundle, tool input validation against the registered schema, multi-entry plugins, plugin config and context, the recorded MCP parity suite (2 to 15 cases), the DeepSeek Harness version fix and docs, and the declared Rust floor of 1.89. The extension host stays behind [features] extension_host (experimental, off by default). No textual conflicts. Verified on the merged tree (macOS, Rust 1.99, real Node 22.20 host): cargo fmt --all --check clean; CI-policy clippy across the workspace, all targets, clean; blocking-call and dead-code budgets pass; root npm test green (wrappers, SDK 19, extension host 88 passed and 1 skipped, web 653). Focused codewhale-tui lib tests (extension_host, plugins, commands, conformance, DSH, task manager, web search, project context, dispatch and edit paths): one failure, commands::debug_diagnostics_baseline_tests:: context_routing_and_report_branches_match_baseline, which reads the developer's real home directory and fails on this machine before and after this merge; its isolation is in progress separately. Linux and Windows are left to hosted CI. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Signed-off-by: CodeWhale Bot <bot@codewhale.net>
Adds entries for what landed after 9626357: the experimental TypeScript extension host (new in this release, off by default) with slash commands, input validation, multi-entry plugins, plugin config and context, the --enable/--disable passthrough and third-party notices; the Rust 1.89 floor; the deferred-tool first call; the Git 2.31 floor; idle task workers; the task-store lock holder; the web search fallback and its time budget; cancelled turns releasing input; /edit restoring the revision; the oversized-paste notice; repo-relative labels (#6739); linked .codewhale and owner-only log and lock files. The DeepSeek Harness version bullet moves from Unreleased into 0.10.1. Four existing bullets change wording: the PowerShell bullet gains the inherit opt-out, the stall-watchdog bullet loses the sentence that the dispatch wait still blocks input, the audit-log sentence is qualified as Unix-only, and the Bun bullet's opening is reworded. The 0.10.1 section's repeated headings (Security seven times, Fixed three) are merged into one each; a byte-level compare shows every other original bullet present verbatim and in its original order (187 bullets before, 207 after: 19 new, 1 moved). scripts/sync-changelog.sh --check, check-contributor-credit.py, check-versions.sh --range-audit-advisory and the release-body test pass. No Rust change. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Signed-off-by: CodeWhale Bot <bot@codewhale.net>
Per-frame transcript work grew with history length: ensure_iter collected every cell into a Vec, ran two full backward scans, and moved all N cached cells out of and back into a fresh Vec; the collapsed path allocated three N-length vectors with three hash lookups per cell. What changed - transcript.rs ensure_iter: cells are reached by index, the cache is updated in place, and a new contiguous `seen_revisions` mirror gives the first changed cell with one slice compare. A frame whose revisions, width, options and folds are unchanged renders, moves and allocates nothing; a tail-only frame renders only the tail. The newest-user-turn / newest-Work- receipt scans reuse the previous pass for the unchanged prefix (newest_matching_cell), asserted against the full scan in test builds. No new trust is added: reuse is still decided by the per-cell revision the cache already trusted. - app.rs / widgets/mod.rs: the collapsed row mapping (filtered->original index, summary slots) is cached per tool-run projection generation and the user's hidden-cell set; only revisions are gathered fresh each frame. - dispatch.rs: a failed dispatch rolled `history_version` back to its old value, so a cache keyed on (version, len) could match a different cell that later landed at the same version. It now bumps instead (snapshot field removed; test asserts the version moves). - transcript.rs: a tool, hidden or other cell replaced in place by a streaming answer at an unchanged cell count took the tail-only flatten and left its neighbour's group rail and spacer stale (found by the new cold- render property test; same in the pre-change code). The shortcut now requires the cell's kind/groupable/empty shape to be unchanged. Writer audit (every mutation of the state the caches key on; non-test code) - history_version bumps: app.rs add_message, maybe_fold_history, mark_history_updated, mark_live_motion_updated_inner, bump_history_cell, push_history_cell, extend_history, clear_history, pop_history, truncate_history_to, bump_active_cell_revision, cell_at_virtual_index_mut (both arms), flush_active_cell; ui/dispatch.rs failed-dispatch rollback (was a rewind, now a bump). - history_revisions writers: all in app.rs (the push/insert/drain/truncate/ clear/pop sites above, resync_history_revisions, bump_history_cell, mark_live_motion_updated_inner, cell_at_virtual_index_mut) plus the dispatch.rs rollback truncate. Every in-place `history.get_mut` / `history[i] =` site (event_loop x2, frame.rs append_streaming_text, streaming_thinking, subagent_routing x4, ui/apply.rs, ui/dispatch.rs, app.rs workflow/interrupt paths) calls bump_history_cell after it. - active_cell_revision: app.rs bump_active_cell_revision/mark_live_motion/ cell_at_virtual_index_mut, tool_routing.rs x2, ui/apply.rs; it is itself part of the tool-run key and of every active entry's revision. - collapsed_cells / thinking_folds / expanded_tool_runs: compared by value against a snapshot each frame, so their writers need no bump. The transcript cache itself keys on per-cell revisions, not on history_version, so a missed version bump cannot leave it stale; only the tool-run projection and the collapsed row mapping lean on the version, as before. history_has_live_motion is left O(N) (~3 ns/cell per tick): has_live_motion is derived from cell state mutated in place at many sites, so a maintained counter could not be proven correct. Also still O(N): the tool-run projection rebuild on every history_version bump (each streamed chunk) and mark_live_motion_updated_inner's per-tick scan. Measured (release profile, thin LTO, TestBackend 140x40, 200 frames, `cargo test -p codewhale-tui --lib --release -- --ignored bench_full_frame_scroll_cost_by_history_length --nocapture`; machine shared with other builds, so +/-10%): plain history before after 400 cells 136.3 us/scroll 155.5 us (noise) 4000 cells 198.8 181.5 20000 cells 454.2 287.2 (-37%; 16.2 -> 6.8 ns/cell) height-change 164.6/228.4/492.7 -> 172.1/206.3/309.4 An earlier run of the same final hot path gave 142.6/160.3/270.6. Collapsed history (new variant, after only): 500 cells 148.8 us, 5000 cells 199.8, 25000 cells 462.5. Isolated collapsed-input prep, same binary: 58.4 us -> 12.7 us/frame at 5000 cells, 52.3 -> 9.8 at 4021. Tests (debug, focused; code first, tests after) - New: cached_transcript_matches_a_cold_render_after_every_mutation (8 seeds x 150 mutations: append, replace, stream, finish, active replace, fold, width, options, clear, truncate, hide, owner, retarget; settled frames render zero cells), warm_chat_frame_matches_a_cold_frame_after_every_ mutation (6 seeds x 120 App-level mutations through the real widget), an_unchanged_frame_renders_and_moves_nothing, a_tail_only_change_renders_ only_the_tail_in_place, a_tool_slot_taken_by_a_streaming_answer_refreshes_ its_neighbour; rollback test now asserts the version moves. - tui::transcript:: 46 passed 0 failed 2 ignored; tui::widgets:: 258/0/2; tui::ui::tests:: 863/0/1; `tui:: golden commands::debug_diagnostics` 4049 passed 0 failed 7 ignored. Not run: the full suite, hosted CI. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Signed-off-by: CodeWhale Bot <bot@codewhale.net>
`commands::debug_diagnostics_baseline_tests::context_routing_and_report_ branches_match_baseline` failed on any machine whose real home carries global instructions or installed skills: `/context report` counts both, so the frozen token totals moved (here ~/.codewhale/instructions.md is 126,359 bytes, past the 102,400-byte cap, and the user's skills load too). The fixture owned its workspace and skills directory but not the user's home. Fix: `SealedHome` (debug_diagnostics_test_support) takes lock_test_env and pins HOME, USERPROFILE and CODEWHALE_HOME to empty temp dirs for the test's life, the same seal the restore-route tests use (81d9ec8). Applied to the two baseline tests that read the report. Sibling found by the real-home vs empty-home comparison: `context_alias_and_bare_action_are_preserved` compares `/ctx report` with `/context report` byte for byte and failed 6 of 40 real-home runs (the skills block moved between the two calls: 8103 vs 8589 tokens); 0 failures in 60 real-home and 10 empty-home runs after sealing. Nothing else in the module differed. Comparison runs (family filter `commands::debug_diagnostics`, 87 tests; the real-home loop is read-only for this family, checked by file mtimes): - before, baseline release binary: real home 86 passed 1 failed (the target); empty temp HOME+CODEWHALE_HOME 87 passed 0 failed. - after: real home 60/60 runs 87 passed 0 failed; empty home 10/10 87 passed. - `commands::debug_diagnostics_baseline_tests` 14 passed 0 failed. Not run: the full suite, hosted CI, Windows (the seal sets USERPROFILE too). Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Signed-off-by: CodeWhale Bot <bot@codewhale.net>
…pproved Records saved before the field existed now load as not auto-approved, so a missing grant never widens authority. A test loads a record with the field removed and checks the thread and turn requests built from it. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Signed-off-by: CodeWhale Bot <bot@codewhale.net>
Every update request and every redirect hop must be HTTPS and must name GitHub's release hosts, the CNB mirror, the host of the configured release mirror, or a host listed in CODEWHALE_UPDATE_ALLOWED_HOSTS. A release tag read from a page must look like a tag. The 512 MB response cap and the HTTPS-only redirect rule are now tested through the real HTTP client. docs/INSTALL.md says how to use a private mirror. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Signed-off-by: CodeWhale Bot <bot@codewhale.net>
Connecting, stalling, total time and response size are limited for the status, text and JSON requests the release check makes. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Signed-off-by: CodeWhale Bot <bot@codewhale.net>
…the workspace Agent profiles and skills read from a workspace no longer follow a link out of it; a refused entry is named in a warning or load issue. User-owned directories (personal profiles, ~/.claude/agents, home skill roots) still follow links. Adds one shared link check for paths taken by name. The pinned writer also asks again when macOS fails a concurrent create with ENOENT. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Signed-off-by: CodeWhale Bot <bot@codewhale.net>
…ined The destination is created through the pinned no-follow writer: a linked directory or file name is refused, new files are owner-only, and a dangling link at the destination name is no longer written through. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Signed-off-by: CodeWhale Bot <bot@codewhale.net>
03da342 used a matrix expression, which the #5496 guard in release-workflows.test.js rejects (every job must set a literal timeout-minutes). Use 165 for every leg; Linux/Windows finish well under it. Validation: node .github/scripts/release-workflows.test.js exit 0; the Version drift job's steps all pass locally (check-versions, feature release notes, contributor credit, bundled plugin claims, OHOS deps and all 20 release-helper contract scripts). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: CodeWhale Bot <bot@codewhale.net>
CodeQL rust/access-invalid-pointer alerts #551 and #552 (windows.rs) flagged the header reads in SecurityDescriptor::from_storage: they dereferenced the pointers GetSecurityDescriptorDacl and GetAce write into null-initialized out-parameters. The reads were already bounded (null check, then checked offsets inside the owned descriptor), but the provenance was the FFI out-pointer. Rebuild both pointers from the owned Vec storage plus the already-validated acl_offset/entry_offset — the same addresses, matching the existing acl() accessor — so every dereference is provably inside owned memory. Behavior is unchanged. Validation: cargo check -p codewhale-tui --lib --tests --all-features --locked --target x86_64-pc-windows-gnu: Finished, no errors; rustfmt --check clean. Hosted CodeQL and Windows tests are the proof. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: CodeWhale Bot <bot@codewhale.net>
…n branch Vendor the paired canonical terms/privacy body and metadata from platform4cd9450; keep existing localized wrappers, website usage disclosure and preference control. Preserve current sign-in/sign-up and error counters. Source changes: ef179c3abb2a01e9d79a0fdf3f45c0dface3bb55 and e725b2c625. Transplant exactly seven reviewed legal paths onto the fresh integration tree using an isolated index; all seven preimages verified, with the sole website disclosure reconciliation retained. Shared working tree, index, branch and concurrent Engine/merch changes stay intact. Validation: source checkout legal/usage26 passed, TypeScript/lint and Next production build875 pages passed; canonical platform sibling guard5 passed. The paragraph disclosure follow-up passed legal/usage26 and canonical guard5. Hosted validation of this integration commit remains required. No deployment or commerce qualification. Refs APPS-227
Use WEBSITE_USAGE_DISCLOSURE.body after the canonical legal adapter retired PRIVACY_SECTIONS. Preserve all assertions for actual counters and English/Chinese disclosure. Verification: original exact-wave test reproduces undefined.find; corrected usage/legal/telemetry tests 34 pass, 0 fail; scoped TypeScript check pass. Independent root usage test 8 pass, 0 fail. Local focused proof only; hosted CI pending. Source commit: 4c99a3f1a1b9e8bb5b87ae8a9bcb6fa6c12809a1. Only this verified blob integrated; shared checkout and index left unchanged. No deploy. Signed-off-by: CodeWhale Bot <noreply@codewhale.net>
Hosted Windows on 561de7c dropped from 92 to 64 failures: the isolation probe now passes, and the remaining Node hosts die before their handshake with `EPERM: operation not permitted, lstat 'C:\'`. Node resolves the main bundle with realpathSync, which lstats every ancestor from the drive root, and a Windows LPAC cannot read `C:\`. On Windows only, launch Node hosts with --preserve-symlinks and --preserve-symlinks-main so resolution keeps the granted path as given; the LPAC still decides every access. Bun's equivalent 'Module not found' failure is a separate fix. Validation: cargo test -p codewhale-tui --lib -- extension_host::tests::launch_plan_gives_each_runtime_its_own_flags: 1 passed, 0 failed (macOS). npm --prefix crates/tui/extension-host test: 405 tests, 398 passed, 0 failed, 7 skipped. cargo check -p codewhale-tui --lib --tests --all-features --locked --target x86_64-pc-windows-gnu: Finished, no errors. Hosted Windows CI is the proof of the runtime behavior. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: CodeWhale Bot <bot@codewhale.net>
Hunter moved the Codewhale repositories to github.com/codewhale-hq on 2026-10-05. Rewrite Hmbown/<moved repo> slugs to codewhale-hq/<repo> in docs, READMEs (all 19), website, CHANGELOGs, workflows, issue templates, Cargo/npm/VS Code/nix/winget metadata, install and updater code, the bundled first-party marketplace catalog and their tests: 1,795 references in 434 files, plus four escaped regex literals. Docker images publish to ghcr.io/codewhale-hq/codewhale from the next release. Old URLs keep working through GitHub's transfer redirects (verified live: API releases/latest, HTML releases/latest, release asset downloads, codeload tarballs, git clone), so released clients keep updating. Left unchanged on purpose: Hmbown/codewhale-cu-plugin (not moved yet; its shipped updater refuses redirects), Hmbown/deepseek-skills, cwc and other repos that did not move; package identities (winget Hmbown.CodeWhale, NSIS publisher); vendor/codewhale-ratatui (frozen reviewed package); and the extension-host GitHub adapter with tools/github/report.rs and their parity fixture, which need a bundle rebuild and move together in a follow-up. README translation stamps updated to the new README.md hash. Validation: npm test (wrapper 101/0, SDK 19/0, extension host 398 passed / 0 failed / 7 skipped, web 763/0) and npm run check:web exit 0 (one pre-existing facts-lib.mjs lint warning). cargo check --workspace --tests --all-features --locked: exit 0. cargo test -p codewhale-cli -p codewhale-release -p codewhale-protocol and the touched codewhale-tui modules (client, cloud_dispatch, commands, dispatch_runner, llm_client::mock, oauth, operate, plugins::marketplace, remote_control, remote_setup, tools::mcp_registry, tools::web::fetch, working_set, tui::ui::tests): all ok, 0 failed. check-readme-translations (18 in sync), readme locales, TUI locale parity, product vocabulary, web locales, contributor credit, plugin claims, release-workflows.test.js and check-versions all pass. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: CodeWhale Bot <bot@codewhale.net>
README, modeled on the strongest agent READMEs in our reference set (opencode, minimax-code, grokbuild, codex): - centered hero: wordmark, one-line tagline, five badges, nav row, locales - the real terminal capture right under the hero - one install line first; Windows/npm/Cargo folded into <details> - numbered three-step quickstart, then tables for entry points (codewhale / exec / web / review --pr / Runtime API) and for modes (Plan/Work/Operate) vs postures (Ask/Auto-Review/Full Access) - every feature claim checked against docs/features.toml - all 18 locale READMEs retranslated and restamped (sha256:bf9d6c3588f0) Website: - sync vendor/codewhale-design to tokens 1.1.2 (muted_foreground holds 5.5:1 on every ground) and regenerate web/app/tokens.css - re-capture the terminal frames from this source (0.10.1 dev, b131357) via launch_card_pty::website_current_terminal_capture; regenerate terminal-capture.generated.ts and the README PNG from the same cells; update media-manifest, public-surface-facts and the capture manifest - availability copy: the desktop app is becoming the main client and the hosted web app is being rebuilt to match it (en, zh, and 16 locales) - remove orphaned images (three old TUI screenshots, codewhalelogo.png, computer-use.png, the superseded 5765d80 capture); fix stale references in docs/PRODUCT.md and "Tidal Folio" comments Evidence (run locally in this tree): - web: vitest 65 files / 654 tests passed, 0 failed - web: npm run check passed (facts, latest-release, docs, tokens, lint, tsc --noEmit, next build) - scripts/check-readme-translations.py OK (18 in sync) - scripts/check-readme-locales.sh PASS - scripts/check-provider-registry.py passed - capture test: 1 passed; 0 failed Not run: root `npm test` workspaces/extension-host suites (untouched). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…live whale Founder direction (2026-10-04): replace the blue-wall ocean with "paper above, sea below", animate the real GPUI whale, deslop the copy, fix the sideways-scrolling terminal, and show Windows. Design - Paper (the GPUI light palette) is the site's appearance; dark is a pinned choice in the theme toggle, no longer the OS default. - One named sea ramp (--sea, --sea-band) and the tide ombré (--tide: paper -> light aqua -> logo light -> logo deep -> navy), taken from the merch's Tide ombré tee. Retired the blurred strata bands, the sea texture and the mirrored reflection whale; strata.tsx deleted. - Homepage: paper hero (category headline, install plate, CTAs), the live whale resting where the tide begins, the real terminal in the deep water, reading sections back on paper (no "01 /" eyebrows, terms in the brand face, getting-started steps as ruled columns), install band into the footer. Footer: one horizon line, no waterline band. - Terminal captures scale to their frame (container query on column count) instead of scrolling sideways; scroll hint removed. Whale - Vendored whale-character-v2 (acting/rig/props/habitat/mark-data) from codewhale-app bc1044887b4e, publication approved by the owner; see web/vendor/whale-character-v2/PROVENANCE.md. - components/whale-live.tsx: the app's own Director on a canvas, 30 fps only while visible, poster pose under prefers-reduced-motion, pointer gaze at rest. It performs a session loop (ready, reading request, planning, reading files, editing, running tests, done) with a word for each phase; picking a terminal view (Composer/Workbar/Fleet/Providers/Help) cues the matching state, Fleet shows three calves. Copy (English; other locales follow in a translation pass) - COPY_STYLE.md (UT Dallas JSOM business-communication conventions) and MESSAGING.md (positioning research across opencode, Pi, Codex, Claude Code, Cline, Zed, Kilo, Crush, Aider; translation-safety rules; glossary). - Hero: "The open-source coding agent for any model"; section headings, product/plugins/models/getting-started/runtime/community/faq strings rewritten; claims narrowed to shipped behaviour. Install - Windows tab (Scoop main bucket carries codewhale 0.10.0). No winget: the manifest is not in microsoft/winget-pkgs (checked 2026-10-04). Tests: rewrote the design-contract tests that pinned the retired look (ocean-contract, docs-theme-contract, gpui-role-tokens). The contrast test now resolves var() stops and caught a real defect (muted ink on the logo-deep tide stop was 4.38:1); the tide was re-stopped so muted text sits >= 4.5:1. Evidence (local, this tree): - web: vitest 74 files / 764 tests passed, 0 failed - web: npm run check exit 0 (facts, latest-release, docs, tokens, lint, tsc --noEmit, next build); 1 pre-existing lint warning in scripts/facts-lib.mjs - headless Chrome: whale cycles all 7 phases and cues "pod" on Fleet; pages checked at 1440 and 390 wide: home, product, install, docs/guide, models Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The docs told Windows users to run `winget install Hmbown.CodeWhale`, which does not exist. microsoft/winget-pkgs publishes HunterBown.CodeWhale (manifests/h/HunterBown/CodeWhale, versions 0.8.43..0.10.0; merged PRs The published manifest also differs from what we documented: it is a portable x64 package (codewhale-tui-windows-x64.exe), installs only the `codewhale` command, depends on the VC++ 2015+ x64 runtime, and has no ARM64 installer. The NSIS/ZIP, x64+arm64, codewhale+codew description belonged to the repo's own singleton manifest, which winget never served. - docs/INSTALL.md, docs/zh_hans/INSTALL.md: rewrite the winget section from the published manifest (id, portable x64, codewhale only, VC++ dep, lag, ARM64 alternatives); fix the known-contradictions note and anchor. - packaging/winget: rename the singleton and its .winget mirror to HunterBown.CodeWhale.yaml and fix PackageIdentifier (submitting the old id would have created a second package); README states the published manifest differs and the singleton is stale at 0.9.6. - README.md + 18 locales: the Windows install line uses winget again with the correct id (code fence only; prose unchanged, stamps refreshed). - Website: hero Windows tab uses `winget install HunterBown.CodeWhale`; install guide regenerated from docs/INSTALL.md. Evidence (local): - gh api repos/microsoft/winget-pkgs/contents/manifests/h/HunterBown/CodeWhale lists 0.10.0; its installer.yaml: PackageIdentifier HunterBown.CodeWhale, InstallerType portable, Commands [codewhale], x64 only - web: vitest 74 files / 764 tests passed, 0 failed; derive-install rendered - scripts/check-readme-translations.py OK (18 in sync, sha256:0b635e0eb430) - scripts/check-readme-locales.sh PASS - grep -F "Hmbown.CodeWhale": only the dated history note remains Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Founder approved the new English copy (2026-10-04). Translated the changed
home/chrome strings into zh, ja, ko, vi, id, es, pt-BR, ca, fr, de, it, pl,
ru, uk, tr, hi and ar; zh also covers community, contribute, faq, runtime and
the {en, zh} pairs in lib/content (getting-started, install, models, plugins,
product). Several locales were behind even the old English (five-row
surfaces list, availability rows, availabilityNote); those were retranslated
from the current English rather than patched.
Rules: web/MESSAGING.md translation rules + glossary: plain declarative
sentences, product terms untranslated (Latin script in Arabic), placeholders,
commands and URLs exact, keys and array lengths unchanged.
Also:
- whale state labels (lib/content/whale-states.ts) now carry all 18 locales;
pickText only knew en/zh, so other locales showed English.
- home title measured in em with hyphenation, and a CJK step (smaller size,
wider measure, keep-all), so German and Japanese headlines wrap in 2-3
lines instead of 4-5.
Evidence (local): tsc --noEmit clean; web vitest 74 files / 764 tests passed;
npm run check exit 0 before the label/CSS follow-up; headless renders of
en/de/ja/zh/ar heroes checked.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Rebasing onto 59e941a kept this branch's README rewrite, which still linked github.com/Hmbown/CodeWhale; apply the sweep's mapping (codewhale-hq/CodeWhale) to all 19 READMEs and packaging/winget/README.md, and restamp the 18 translations (sha256:604da19bff2c; links only, prose unchanged). Kept the winget-pkgs path manifests/h/HunterBown/CodeWhale: that is the published package directory, not a GitHub repository (the sweep had rewritten it to manifests/h/codewhale-hq/... in packaging/winget/README.md). Gate (local, this tree): npm test exit 0 (npm 101/101 + 19/19, extension host 398 pass / 0 fail of 405, web 766/766); npm run check:web exit 0; check-readme-translations OK (18); check-readme-locales PASS. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ing it 59e941a rewrote the plugin homepage links inside the generated first-party catalog by hand, so the Marketplace connection check found drift: sync-marketplace.py copies each plugin's homepage verbatim from the pinned marketplace revision (ae3dd225), whose marketplace.json still names the old owner. Regenerate from that revision. Install sources keep the codewhale-hq codeload URLs the script now writes (verified 200); homepage links redirect until the marketplace repo updates them and the pin moves. Validation: python3 scripts/sync-marketplace.py --marketplace <clone at ae3dd225> --check: First-party catalog matches marketplace ae3dd225. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: CodeWhale Bot <bot@codewhale.net>
… posture The 0.10.1 entry describing d1655c4, 0526412 and 124331e (agents follow the live permission posture, approvals delivered while busy, the workspace-delete floor) did not link the issue it fixes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: CodeWhale Bot <bot@codewhale.net>
A tool call that failed (ToolCallComplete Err) was persisted with only status=failed and detail, never tool_result_for/is_error. After a runtime restart the rebuilt transcript held a function_call with no output and the provider rejected every later turn (`No tool output found for tool call`, #6803 on 0.10.0). 9ddf26b already repairs such records on rebuild (unanswered_call_result); this records the failure correctly at the source, matching how a success:false result is stored. Old stores and interrupted/canceled calls still go through the existing repair, so there is still exactly one repair mechanism. Regression test: runtime_threads::tests::execution_identity:: a_failed_tool_call_records_its_result_and_replays_after_restart (persist a failed read, reopen the manager, restore messages, assert one ToolUse and one matching is_error ToolResult). Validation: cargo test -p codewhale-tui --lib -- runtime_threads::tests::execution_identity runtime_threads::tests::monitor_preserves_admitted_correlation_and_redacts_private_answers: 4 passed, 0 failed. With the source hunk reverted, the new test fails (0 passed; 1 failed). rustfmt --check clean. Refs #6803 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: CodeWhale Bot <bot@codewhale.net>
windows_atomic_target_name refused reserved DOS names but not ':'. A name like `notes:private` or `con:stream` passed the stem check and the lexical absolute() round trip, so the native rename wrote an NTFS alternate data stream while write_atomic reported success. Refuse any ':' in the target name; Fleet artifact paths already reject the same class (path_is_confined, fleet/files.rs). Found by an independent Muse Code review of 2680ddc (medium) and confirmed against the code. The Windows-only test write_atomic_writes_beside_live_fleet_pins_and_refuses_rewritten_names now also covers notes:private, config.json:stream, con:stream and file::$DATA. Not run locally (cfg(windows)); hosted Windows CI is the proof. rustfmt --check clean. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: CodeWhale Bot <bot@codewhale.net>
…#6842) A 6-day session kept 49,258 journal entries (99.6% off the active branch), a 98.7 MB document and 872 MB RSS. Three unbounded growers, fixed together: 1. Journal. `SessionJournal::prune_plan` (pure) keeps the root->leaf path and whole recent off-branch chains (Compaction/BranchSummary first) within a 1,024-entry budget once more than 4,096 entries sit off-branch; `remove_entries` is atomic (validates or restores). Autosaves on the persistence actor (`persistence_actor.rs` flush_inner -> `SessionManager::save_session_bounded`), never the UI loop, append the planned entries to `sessions/.journal-archive/<id>.jsonl` (0600, fsync, dir fsync on create) and only then write the pruned document. Archive failure prunes nothing. Archived ids are handed to the UI through an in-memory registry and dropped from the live journal in `build_session_snapshot` (no I/O), so RAM matches disk. Plain `save_session` never prunes. `/branch <id>` restores an archived entry and its missing ancestors; `/tree` reports the archived count; export merges the archive into the container; session delete removes it; a Runtime API fork of an archived entry fails closed with a message naming the archive. 2. Work graph. New reducer change `PruneEndedOperations` keeps the newest 256 ended, non-durable Operation nodes (not Stale, no non-Contains edges, not referenced by activities or proposals); applied at registration. These are a derived index of tool calls already in the transcript. 3. Metadata prefix. `load_session_metadata` grows its read geometrically (to 16 MB) until the metadata block closes instead of reading the whole file. `usage_source_fingerprints` is deliberately not capped: it is the money replay-idempotency set; documented as a known limit. Not addressed here: snapshot construction still runs on the UI task (now cheap with a bounded journal); resume still reads the document twice; a child forked before a prune cannot /branch into the parent's archive. Evidence (local, this checkout): - cargo test -p codewhale-runtime --lib session_tree: test result: ok. 22 passed; 0 failed (4 new prune tests) - cargo test -p codewhale-tui --lib -- journal_bound_tests canonical_journal_admission_tests ended_shell_operations container_includes_journal_archive: test result: ok. 9 passed; 0 failed (bounded save + live-journal follow, archive failure prunes nothing, archive-then-document-write-failure loses nothing, /branch to archived id round-trip, delete removes archive, >64 KB metadata listing, work-graph cap, export merge, existing superseded-entries-survive test unchanged) - Negative control: with the work-graph prune disabled, ended_shell_operations_are_capped_oldest_first FAILED (0 passed; 1 failed). - cargo test -p codewhale-tui --lib -- session_manager:: session_export:: persistence_actor:: work_graph:: thread_history session_tree commands::contract: test result: FAILED. 290 passed; 1 failed. The one failure, control_hosted_work_target_resolves_and_never_echoes_credentials, expects repo slug Hmbown/CodeWhale but the checkout's remote is codewhale-hq/CodeWhale; unrelated to this change. - RUST_MIN_STACK=16777216 cargo test -p codewhale-tui --lib -- fork canonical: test result: ok. 232 passed; 0 failed - python3 scripts/check-blocking-calls-budget.py: 530 sites across 165 files, within budget - python3 scripts/check-dead-code-budget.py: 253 suppressions, budget 258 Refs #6842 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: CodeWhale Bot <bot@codewhale.net>
59e941a rewrote the git remotes these tests feed in (git@github.com:codewhale-hq/CodeWhale.git) but not the URL-encoded expectations (Hmbown%2FCodeWhale), so control_hosted_work_target_resolves_and_never_echoes_credentials and remote_env_open_encodes_branch_and_never_echoes_credentials failed. Validation: RUST_MIN_STACK=8388608 cargo test -p codewhale-tui --lib -- commands:: session_manager:: session_export:: persistence_actor:: work_graph:: thread_history: 1403 passed; 0 failed; 2 ignored (also covers the #6842 slice 91ad8c5). No Hmbown%2F references remain. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: CodeWhale Bot <bot@codewhale.net>
Release QA on 8b20d48: resume a session, run one turn, quit, and every later `codewhale resume` / `--continue` / `fork --last` failed for good: "canonical history operation mounted-history:<uuid>; retained outcome must be recovered using this exact key / caused by: saved holder checkpoint does not cover the full source". A 0.10.1 regression (guard added in 5cf09da). Cause: the first resume mounts the saved document into a runtime holder thread; the TUI then runs later turns in its own engine and saves them to the document, so the holder stays at the history it was seeded with. On the next resume the guard demanded that the holder's seed checkpoint cover the WHOLE document (unlike every sibling checkpoint guard, which requires a prefix), and the exact live == document check then also failed because the holder is behind (local repro: holder 2 messages, document 4). Fix: the checkpoint must cover a prefix, as elsewhere. A holder that matches the document exactly is reused as before. A holder that is strictly behind (its messages are a strict prefix of the document's) and has no live work holds nothing the document lacks: release its binding through the existing compare-and-swap unbind (reconcile receipt kept, turns kept) and mount the document fresh. A holder that is ahead or diverged still fails closed. Regression test (PTY, hermetic loopback model server, sealed home): plugin_e2e_acceptance::a_continued_session_resumes_again_after_each_turn — first session with a turn, then resume + turn + quit twice. Against the installed 8b20d48 build (QA_TUI_BIN) it fails at "resume 2" with the QA error; against this fix: test result: ok. 1 passed; 0 failed. Manual repro on the actually bricked session: three more resume+turn rounds, 10 messages. cargo test -p codewhale-tui --lib -- thread_history runtime_api::tests::session_resume canonical saved_session runtime_threads::tests: 471 passed; 1 failed — the failure, monitor_separates_lifecycle_start_from_billing_dispatch_and_child_usage, is unrelated and passed 3/3 when rerun alone (timing under load). Known limit: each resume after local turns leaves the previous holder as an unbound thread with its turns (receipt recorded) rather than advancing it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: CodeWhale Bot <bot@codewhale.net>
…vider serves Two first-run defects from release QA on 8b20d48 (real DeepSeek key): Invalid key loop. With an invalid DEEPSEEK_API_KEY, sending a message dropped the user into "Getting started → Choose your model provider" with no explanation; the picker showed DeepSeek as "key saved · not checked" and Enter re-applied the same rejected key, so send → setup → send looped. The rejection was written to the transcript but hidden behind the setup screen, the readiness snapshot could not record a rejection for a key with no fingerprint (env / secret-store keys), and Enter applied any keyed row. Now: the setup screen states the key was rejected (existing OnboardApiKeyRejectedEnv wording, error colour); provider readiness records rejected credentials by provider, endpoint, auth type and fingerprint (cleared by the next success); the rejected row reads "last check failed (authentication)" and Enter opens key entry instead of reusing the key; Esc returns to the composer. The key value is never displayed or logged. Stale model list. After "The provider accepted the key" the first-run picker listed every catalog DeepSeek model (19 on the QA machine, all "price unknown"); picking one the API no longer serves (deepseek-v3.1) failed the first message with 400. verify_provider_api_key already fetched /models but discarded the body. It now returns the roster from a complete page, and setup publishes it for the exact route through the existing live-catalog path (no second catalog), filtered on a route's first roster to ids the catalog knows for that provider so embeddings/speech ids stay out. DeepSeek setup then offers deepseek-flash and deepseek-v4-pro. Catalog-unpriced rows fall back to pricing::model_rate_label. Without a live roster, an alias the route would rewrite to another listed id is hidden. Tests: tui::provider_picker::tests:: rejected_env_key_is_marked_and_enter_asks_for_a_new_key and tui::ui::provider_key_validation_tests:: provider_key_probe_roster_becomes_the_model_pick_roster (new), plus env_only_auth_failure_reopens_provider_onboarding, provider readiness, verify_provider, provider_key_, fetch_catalog_delta, the provider picker and onboarding suites: test result: ok. 253 passed; 0 failed. Follow-ups (data decisions, not in this change): DEEPSEEK_ALIAS_REPLACEMENT in catalog_corrections.json points deepseek-chat/-reasoner at deepseek-v4-flash; the bundled seed still carries rows Models.dev marks deprecated; setup writes [providers.deepseek].model without updating default_text_model. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: CodeWhale Bot <bot@codewhale.net>
The codewhale-hq link sweep lengthened string literals that rustfmt now wraps differently (update.rs, dispatch_runner.rs, marketplace store, session control tests); the Lint job failed cargo fmt --check on 0c79ef2. Also apply clippy 1.99's manual_contains in the setup model picker and needless_borrows_for_generic_args in a work-graph test. Validation: cargo fmt --all -- --check clean; cargo clippy --workspace --all-targets --all-features --locked -- -D warnings (CI allow-list): exit 0 with stable 1.99.0. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: CodeWhale Bot <bot@codewhale.net>
Hosted Windows on 54f2b1a still failed 13 tests (down from 92). Six native MCP / preset activations died with `EPERM: operation not permitted, lstat 'C:\'`: the reviewed-closure checks in the extension host (admitReviewedClosure, importReviewedModule, the Bun onLoad symlink check and the shell-hook config check) call JS realpathSync, which lstats every ancestor from the drive root, and a Windows LPAC host cannot read C:\. On Windows only, use realpathSync.native, which asks the OS for the opened file's final path and needs access to that file alone. macOS/Linux keep the JS implementation unchanged. The symlink/closure checks are unchanged. Rebuilt with a clean npm ci + node build.mjs: exactly the four bundles that embed these modules changed; the builtin harness/mcp bundles and builtin-modules.json rebuilt byte-identically. Validation (macOS): extension-host tsc clean (outside vendored upstream); npm --prefix crates/tui/extension-host test: 405 tests, 398 passed, 0 failed, 7 skipped; cargo test -p codewhale-tui --lib -- plugins::install::dsh::tests: 26 passed, 0 failed (twice). Windows runtime proof is hosted Windows CI. Not addressed here: Bun's own entry-module resolution under the LPAC (3 tests). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: CodeWhale Bot <bot@codewhale.net>
…p to C:\\" This reverts 4e1905b. On hosted Windows (job: Extension host runtimes, windows-latest) realpathSync.native returns a different spelling than the raw input (8.3 short names, drive casing, \\?\ prefix), so the `canonicalPath(path) !== path` symlink checks refused legitimate reviewed files (tests 49/50: 'hook config is absent from the reviewed regular-file closure'). Worse, closureAt() compares raw module paths against the now-native-canonical root, so on the Bun path a reviewed module could fail to match its closure and skip the receipt hash check. A correct fix must canonicalize consistently on both sides of every comparison and be proven on real Windows; it is not a release-night change. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: CodeWhale Bot <bot@codewhale.net>
Contributor
|
Follow-up on the fork-push 403 noted in 18477f3 (the #6739 landing): #6739 had been created with allow-edits-by-maintainers off — that was the 403, and it's on me. All my currently open PRs (#6847–#6860, #6863, #6864) have maintainer edits enabled, so the wave process can push conflict/fix merges straight to those branches. Two limits of that GitHub grant, in case they matter for the wave tooling: it doesn't permit force-pushes to the branch, and it's scoped to the PR head branch only. If a force-push or whole-fork access is ever needed, tell me and I'll add write collaborator access instead. |
Hmbown
pushed a commit
that referenced
this pull request
Oct 5, 2026
…der LPAC Hosted Windows (LPAC) refuses lstat on the drive root, so Node's JS realpathSync — which walks every ancestor — failed the reviewed-closure checks with EPERM lstat 'C:\' (13 failures on #6815, mostly extension_host::native_mcp and raw_agent_presets). The earlier attempt (4e1905b, reverted) used realpathSync.native but compared its spelling against raw input. New src/dsh/canonical-path.ts is the one comparison rule: canonicalize with realpathSync.native on win32 (GetFinalPathNameByHandle, no ancestor walk) and realpathSync elsewhere, strip \\?\ and \\?\UNC\, compare case-insensitively on win32, and express containment as relative(canonical root, canonical target). A canonical path is never compared to a raw one. resolve-hooks keys closures by canonical root and remembers the raw root; the Node load hook now also refuses symlinked closure modules (under --preserve-symlinks an in-closure symlink pointing outside kept its in-closure URL and loaded — reproduced on HEAD). Evidence (macOS): npm --prefix crates/tui/extension-host test: 406 tests, 399 pass, 0 fail, 7 skipped (new canonical-path test passes); cargo test -p codewhale-tui --lib -- extension_host dsh: 264-265 pass, 2-3 plugins::install::dsh failures that differ per run and pass in isolation (parallel-load flake under investigation). Windows LPAC itself cannot run here; hosted Windows CI is the proof. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 task done
Collaborator
Author
|
thank you!! all's fair in love and open source PRs I say — the agents will sort it out 🙂 thank you for changing it and contributing so much!! |
VitorEAFeliciano
pushed a commit
to Navegos/Codewhale
that referenced
this pull request
Oct 6, 2026
…der LPAC Hosted Windows (LPAC) refuses lstat on the drive root, so Node's JS realpathSync — which walks every ancestor — failed the reviewed-closure checks with EPERM lstat 'C:\' (13 failures on codewhale-hq#6815, mostly extension_host::native_mcp and raw_agent_presets). The earlier attempt (4e1905b, reverted) used realpathSync.native but compared its spelling against raw input. New src/dsh/canonical-path.ts is the one comparison rule: canonicalize with realpathSync.native on win32 (GetFinalPathNameByHandle, no ancestor walk) and realpathSync elsewhere, strip \\?\ and \\?\UNC\, compare case-insensitively on win32, and express containment as relative(canonical root, canonical target). A canonical path is never compared to a raw one. resolve-hooks keys closures by canonical root and remembers the raw root; the Node load hook now also refuses symlinked closure modules (under --preserve-symlinks an in-closure symlink pointing outside kept its in-closure URL and loaded — reproduced on HEAD). Evidence (macOS): npm --prefix crates/tui/extension-host test: 406 tests, 399 pass, 0 fail, 7 skipped (new canonical-path test passes); cargo test -p codewhale-tui --lib -- extension_host dsh: 264-265 pass, 2-3 plugins::install::dsh failures that differ per run and pass in isolation (parallel-load flake under investigation). Windows LPAC itself cannot run here; hosted Windows CI is the proof. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Codewhale uses one Rust Engine for execution, provider identity, permissions, events, sessions, storage and accounting. ACP, child agents and recursive RLM share its turn path; reviewed TypeScript mods reuse captured authority, cancellation, checkpoints, parent delivery and usage settlement. Node remains the default, Bun Native is opt-in, and Rust MCP remains the default backend. Session controls use the authenticated canonical owner, complete history and durable retry receipts.
The Ratatui components are mounted in Codewhale itself: composer, transcript, Tasks/Fleet workbars, approval controls, posture/metrics and guarded Ocean. The component gallery uses the same public components and genuine Rust renders, with desktop/narrow layouts, searchable details, shareable examples and reduced-motion controls. Homepage/product/guide and all 19 README languages use genuine native captures. Account-scoped ChatGPT sign-in source is integrated; live sign-in and plan inference remain unverified.
Original contributor history is preserved for #6819 by @Guan0923, #6829 and #6831 by @Lstarsky0, #6830 by @SparkofSpike, #6806 by @dependabot, and #6820 by @Guan0923. All three original #6820 author commits and all eighteen acceptance cases are retained.
The latest repairs (89ee629) target the previous head's hosted failures. Windows Native admission re-opened directories the grant walk already held with MAXIMUM_ALLOWED and read-only sharing, so every host launch hit a sharing violation; grant and retirement now extend the held pin chain and open only new child leaves, keeping no-follow, no-write/no-delete sharing, exact descendant validation, the traversal bound and no ACL propagation. Windows private-directory checks compare physical identity instead of lexical spelling, so 8.3 runner paths pass while replacement and reparse points are still refused. Nested extension-host dist files stay LF so materialized modules keep their admitted SHA-256. Platform fixtures keep their original assertions (canonical macOS credential homes, post-sync plugin view, OS transport kind, absolute ledger roots, the intentional Windows Fleet rename fence, the Windows unclassified-invocation floor, path-component roster checks, a real Windows launch plan, and a Linux check requiring a distinct kernel network namespace plus ECONNREFUSED). Safety, Lint, Ubuntu Test and release parity share one guarded GitHub-hosted Ubuntu headroom script; commands, filters, budgets and timeouts are unchanged. The CLI diagnostic no longer interpolates the credential line (CodeQL 541); CodeQL 533/540 were dismissed as flows from test-only MCP fixtures after the credential/proxy refusal tests passed.
The newest commit (e0a758f) follows the first hosted results. Hosted Safety reached its tests for the first time and found a real Linux defect: with Node 24.21 on x64 the host's watchdog Worker aborted at startup because each V8 isolate's code range counts in full against the 1 GiB RLIMIT_DATA cap; the watchdog now requests a 16 MiB code range (bundle rebuilt deterministically; one-line diff). Windows admission errors now name the failing step and the exact token flag or OS error, still fail-closed. The Runtime API test harness shuts the owner daemon down like the product, the scoped MCP test reports the server's error body, and Lint gets 75 minutes based on measured step times.
Hosted results on 89ee629: Test (ubuntu-latest) passed; Windows compiled the ACL and private-path repairs and dropped from 142 to 92 failures (ACL sharing violations gone; admission now stops at the LPAC token check, which never ran on hosted Windows before); Lint's runtime-contract budget passed for the first time, then the persistence-backlog budget hit the old 45-minute limit; Safety exposed the Node 24 defect above.
The newest commit (af5fa5c) follows hosted results on 02fcc3e, where the LPAC token check and the data-directory share conflict were confirmed fixed and the isolation probe ran inside the LPAC for the first time. Node then failed WSAStartup: an LPAC cannot open registry keys without the
registryReadcapability, so Native hosts now get exactly that one capability (the token check requires exactly it; network stays denied). Bun now reads an empty config from the granted directory instead of the NUL device, unprotected file ACL edits let Windows re-derive inherited entries, and ACL pointer reads are checked (CodeQL). Codewhale's own atomic writes on Windows rename through the temp handle, so they work beside Fleet's new ancestor pins (they failed with os error 32 during Fleet runs). The extension-host wire-JSON guard now refuses sparse arrays, getters and symbol keys (Copilot finding). Release notes add entries and credits for #6820, #6829, #6830, #6831 and #6827; the website credit-parity test enforced the matching website and docs credits.Source15 validation:
npm testandnpm run check:web1,185 passed / 0 failed / 7 skips; macOS extension_host 177/0, DSH 28/0, mcp 407/0, utils 38/0, tools::file 190/0; macOS release build plus npm wrapper smoke passed; Windows type-check clean. Windows runtime of the LPAC repairs is this head's hosted run.The newest commit (02fcc3e) addresses what hosted Windows and macOS reported on e0a758f. Windows: the probe token is a genuine AppContainer, but the runner rejects the LPAC token-flag query (ERROR_INVALID_PARAMETER), so Codewhale now falls back to the token's WIN://NOALLAPPPKG attribute (aligned, bounds-checked; still fail-closed). ACL edits write the exact DACL with SetKernelObjectSecurity, which fixes inherited ACEs becoming explicit after grant/retire and never propagates; that lets ACL targets drop MAXIMUM_ALLOWED, whose DELETE right collided with a live host using the data directory as its working directory (also two sessions sharing one). macOS: memory-cap tests use production hang detection so the memory limit, not heartbeat supervision, stops the hog. Release notes: an independent claim-by-claim audit corrected 13 CHANGELOG statements and the matching docs (English and zh_hans); the Native sandbox sentences now match the source.
Hosted results on e0a758f: Safety, Lint (runtime-contract and persistence-backlog budgets), Test (ubuntu-latest), CodeQL and npm wrapper smoke passed; macOS 18,741 passed / 1 failed (the memory-cap race above); Windows 17,952 passed / 91 failed (the LPAC query and data-directory share causes above).
Source14 validation:
npm testandnpm run check:web1,184 passed / 0 failed / 7 explicit skips; macOS memory-cap tests 9/9 across three runs and compiled/Node containment 3/3 with compiled host markers; Windowscargo check --target x86_64-pc-windows-gnuof codewhale-config and codewhale-tui lib and tests clean under deny(warnings); two adversarial reviews of the Windows changes; crates publish dry run packages 26 of 28 crates (codewhale-tui/cli need codewhale-ratatui 0.1.0 published first).Validation (source13, 3,792 source/mode/absence rows; owning checkout HEAD and index unchanged):
npm testandnpm run check:web: 1,184 passed / 0 failed / 7 explicit skips (wrapper 101, SDK 19, host 382, website 682); strict TypeScript and production web build passed.runtime_api::tests::runtime_store_convergence14 passed / 0 failed, and 8 host cases including the four that failed in hosted Safety: 8 passed / 0 failed. Source12's 24 focused cases (including three MCP credential/proxy refusal tests and compiled containment, memory and network markers) passed earlier.Open on this head: Windows LPAC admission (diagnostics land with this push), the Windows data-directory share conflict seen in DSH import tests, one Windows retirement test where a file's inherited ACEs become explicit after grant/retire (under investigation, not hidden), Node 24 on hosted Linux, the persistence budget, macOS hosted tests and native exports. Package/install qualification, real ChatGPT inference and native/IDE acceptance remain separate release gates. Durable Objects hosting is proposed and unimplemented. Source integration does not authorize deployment or publication.
Refs #6818
Refs #6816
Refs #6828
Fixes #6827
🤖 Generated with Claude Code