Commit Graph

212 Commits

Author SHA1 Message Date
CodeWhale Bot 3920028c6c refactor(tui): align shell and file internals with contract naming
Rename the lowercase bash tool struct and its bounded output
accumulator, plus the file read/write helper symbols and their
tests, to contract-based names. Tool names, schemas, and behavior
are unchanged; doc and test references updated to match; the
model-visible catalog text and budget files are untouched.

Verified: cargo test -p codewhale-tui --lib (shell/registry/file/
file_tool/tool_catalog filters) 308 passed; web
public-surface-contract 13/13 passed.
2026-08-11 19:14:00 -07:00
CodeWhale Bot 865bc79408 fix(web): sync public-surface test with the seven-name toolbox
bf6def00d added todo_write to the model-facing toolbox
(read/write/edit/bash/agent/todo_write/tool_search) and updated
docs/TOOL_SURFACE.md to 'exactly seven model-facing names', but
web/lib/public-surface-contract.test.ts still asserted six. The
release-candidate and Web Frontend proof runs fail on that stale
assertion at the frozen SHA; align the contract test with the
documented surface. Verified: vitest public-surface-contract (13/13).
2026-08-11 18:52:56 -07:00
CodeWhale Bot 9935832d9b ci(web): surface pending manual deploys
Annotate green main builds with the exact manual deployment command while preserving the credential-free, approval-gated Cloudflare boundary.
2026-08-11 15:59:04 -07:00
CodeWhale Bot 037aab9cf3 docs: align the v0.9.6 public surface
Document Work and To-do as the two product concepts, synchronize every shipped locale, publish the six-tool and typed-image contracts, and keep static web generation offline while live GitHub chrome refreshes after deployment.
2026-08-11 06:16:30 -07:00
CodeWhale Bot 4127662e98 fix(web): refresh v0.9.6 repository facts 2026-08-10 18:21:05 -07:00
CodeWhale Bot c76f2d70bf docs(release): finish the 0.9.6 public surface
Replace duplicated implementation-heavy notes with a complete user-facing release ledger, sync the embedded changelog, and align compaction math documentation with the shipped trigger.\n\nExpose the existing Skills and Plugins guides in the website documentation index while retaining v0.9.5 as the latest published release until 0.9.6 is public.
2026-08-09 19:11:00 -07:00
CodeWhale Bot 5b738bc65c feat(telemetry): make anonymous usage counting opt-out 2026-08-09 16:24:17 -07:00
CodeWhale Bot e9bce3db9d fix(web): ground FAQ and getting-started copy in the 0.9.5/0.9.6 runtime contract
- FAQ: replace the two-binary codewhale/codewhale-tui answer with the
  one-runtime contract — codew is a byte-identical short name, the updater
  refreshes legacy codewhale-tui paths from the same bytes, and the tui
  crate now compiles into codewhale-cli; drop the separate codewhale-tui
  cargo install line (EN+ZH).
- FAQ: add Mistral AI to the provider sample list (EN+ZH).
- FAQ: codewhale doctor prints its report to stdout — the claimed
  ~/.codewhale/doctor.log file does not exist (EN+ZH).
- FAQ: drop the audit.log sentence; no runtime writer for it exists (EN+ZH).
- FAQ: OpenRouter setup uses the documented route form — --provider
  openrouter plus OpenRouter's own model slugs; no provider/model prefix
  parsing exists (EN+ZH).
- getting-started: step 4 becomes 'Set up your ideal fleet' — add every
  provider, then /fleet setup, the documented authoring wizard; drop
  codewhale fleet init, which only prints the ledger path.
- fleet docs: drop codewhale fleet init from the CLI verb block.
- home dictionaries + guide: align the four-step lede with the new step 4
  (EN+ZH).
2026-08-09 13:58:32 -07:00
CodeWhale Bot be5c8f8bfd chore(release): prepare 0.9.6
Bump the workspace, every published crate, the npm CLI package and its
codewhaleBinaryVersion, the runtime SDK, and the VS Code extension to 0.9.6 —
the four version sources the release workflow cross-checks before it will
tag.

The changelog entry describes v0.9.6 as what it is: a subtractive release.
The guards that interrupted live work, the per-mode prompt doctrine, and the
deterministic second compaction system are gone; a truncated provider
response can no longer be recorded as a finished answer. Most of these were
found by running v0.9.5 against Terminal-Bench 2.1 beside Pi 0.8.41 on the
same model, effort, endpoint, and task digests, then reading the trials
Codewhale lost — so the entry names those trials rather than describing the
fixes in the abstract.

Mistral AI ships in this release; Xavier Pestel (@xavierpestel-ai) is
credited in the contributors section for #5295.
2026-08-09 01:02:51 -07:00
CodeWhale Bot f11657e77f fix(mistral): isolate the reasoning wire contract
Scope Mistral's polymorphic reasoning and replay behavior to exact first-party HTTPS routes, preserve stored thinking across real prompt construction, and keep DeepSeek's sanitizer from injecting a second dialect into tool-call history.

Align the current model registry, provider-scoped model override, generated facts, docs, and focused route-isolation tests. Split the large stream decoder test module so the source-structure gate remains below budget.

Signed-off-by: CodeWhale Bot <bot@codewhale.net>
2026-08-08 17:23:14 -07:00
CodeWhale Bot 519a0d6162 docs(web): publish the v0.9.5 release snapshot
Advance the separately modeled public-release record only after the immutable GitHub release and 34-asset gate are live. Regenerate the checked-in web facts so install pages and deployed receipts resolve v0.9.5 instead of the prior release.
2026-08-08 09:50:47 -07:00
CodeWhale Bot 9a3015892d docs(web): advance published release snapshot
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.
2026-08-08 03:28:59 -07:00
CodeWhale Bot ef6104957d fix(release): close consolidated runtime contract gaps
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.
2026-08-08 02:24:47 -07:00
CodeWhale Bot 3966b014c9 fix(web): keep the canonical brand-first identity
Preserve the exact Codewhale-first identity sentence in metadata and social previews. Render it as the Open Graph heading itself so accessible and visual surfaces say the brand once without the previous duplicated prefix.
2026-08-07 23:02:07 -07:00
CodeWhale Bot 5bdfeb7146 fix(web): keep localized navigation interactive
Move translated layouts onto the compact navigation until xl, reserve wide companion labels for 2xl, and keep every masthead control inside the viewport.

Portal the compact menu to a true viewport modal with inert background roots, contained keyboard focus, an in-dialog close control, and immediate cleanup when a resize crosses the desktop breakpoint.

Verified with all 254 web tests, ESLint, TypeScript, responsive width probes, and live English, Chinese, and Spanish pointer, keyboard, focus, resize, and navigation checks.
2026-08-07 22:17:12 -07:00
CodeWhale Bot 636b84610e docs(release): reconcile 0.9.5 contributor credit
Record the four human contributors whose work is present in the 0.9.5 candidate, update the public credit matrix and website snapshot, and add the missing canonical identity for PR #5257. The candidate heading and compare links remain explicitly pre-tag until publication approval.
2026-08-07 21:52:06 -07:00
CodeWhale Bot dd84af2297 chore(release): prepare 0.9.5 candidate
Bump every tagged package and internal dependency pin to 0.9.5, refresh Cargo and npm lock records, regenerate the packaged changelog and web facts, and record the user-visible candidate contract. The changelog deliberately remains marked Unreleased candidate until the rebuilt binary is dogfooded and publication is explicitly approved.
2026-08-07 21:47:47 -07:00
CodeWhale Bot 93b14c4dde fix(web): publish truthful software schema versions
Derive SoftwareApplication softwareVersion only from the published-release receipt backing the install URL. Omit the field when no published release is known so a source candidate is never presented as downloadable.

Verified with focused schema tests, ESLint, TypeScript, and diff checking.
2026-08-07 21:46:02 -07:00
CodeWhale Bot 6fb9a9e27b fix(web): deploy one exact OpenNext bundle
Build once through the OpenNext adapter before preview or deploy, and remove Wrangler custom-build recursion so cache population and upload use the same bundle. Keep the manual main-only exact-SHA workflow and post-deploy receipt gate intact.

Verified with deploy-preflight tests, ESLint, a complete 288-page OpenNext build, Wrangler 4.113.0 deploy --dry-run, and diff checking.
2026-08-07 21:46:01 -07:00
CodeWhale Bot ade598d054 fix(web): keep shared social identity singular
Keep the identity phrase brand-free, derive one shared Open Graph alt string, and render the visual brand from the same SITE_NAME constant. Add a regression against repeated branding and use the supported neutral es-419 date locale.

Verified with metadata and dictionary tests, locale checks, ESLint, and diff checking.
2026-08-07 21:46:01 -07:00
CodeWhale Bot eb5faf754b web: sharpen EN copy, real nav icon buttons, native locale rewrites
Three fixes on the newspaper-ocean site:

- Nav: baseline-align the Han secondary labels with the Latin primary
  (inline-flex items-baseline + matching line-height), and give the
  masthead real brand buttons — GitHub mark before the star count,
  Discord logo icon-only — with a .site-discord-link rule matching
  .site-github-link and a shared .brand-mark size.
- EN copy: hero/meta/footer sharpened around "Codewhale dives into the
  deep so you don't have to"; every "local-first" claim dropped in
  favor of "any model, on your machine". heroIntro keeps the {brand}
  token the lede split and dictionary tests require.
- Locales: home/chrome rewritten natively in all nine non-English
  packs (zh, ja, ko, vi, ru, uk, es, id, pt-BR) instead of machine
  translation. zh hero uses the 一入码门深似海 allusion per community
  feedback. Key parity, template tokens, and ru/uk script purity all
  hold; check:locales and dictionaries.test.ts pass.

Verified: npm ci && prebuild && check:facts && check:docs &&
check:locales && vitest (250/250) && eslint && tsc --noEmit && build.

Agent-assisted (Kimi Code); copy reviewed against the en reference.
2026-08-07 21:46:00 -07:00
CodeWhale Bot 679e681d41 fix(web): align installs with the single runtime
Advertise codewhale and the release/npm codew convenience name without exposing the retired codewhale-tui install surface. Keep Cargo truthful: codewhale-cli installs only codewhale unless the user defines an alias.

Verified with focused public-surface tests, facts/docs/locale checks, ESLint, and diff checking.
2026-08-07 21:45:59 -07:00
CodeWhale Bot 18769cdbe8 fix(release): 0.9.4 stall, budget, and UI polish for session-title fix
- 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 bf69e7ff5 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: efcf47a1d, 21ed173cf, ec5747f7d, #5258
2026-08-07 04:32:55 -07:00
CodeWhale Bot 180271efaf fix(web/docs): sync 0.9.4 contributor credits and restore media plan placeholder
- add @mky and @cacdcaecawae to web release-credits and docs/CONTRIBUTORS
- restore docs/releases/v0.9.2-media-plan.md placeholder after move to ops
2026-08-06 18:37:27 -07:00
CodeWhale Bot 74b5192110 fix(web): accessibility, structured data, and metadata defects
Defect fixes ahead of relaunch — no redesign, no new copy, no media.

Accessibility:
- The mobile menu declares `aria-modal`, which promises the dialog owns
  interaction, but focus never entered it and never came back. Focus now
  moves inside on open and returns to the toggle on close. The toggle node
  is captured before cleanup rather than read from the ref inside it, which
  would race React clearing it.
- The terminal player had `role="tablist"` with none of the pattern behind
  it. Adds arrow-key/Home/End movement, a roving tabindex, and
  aria-controls/aria-labelledby wiring between each tab and the panel.
- Context text ran at white/45 on ink — 4.32:1, below the 4.5:1 WCAG AA
  floor for normal text. Now white/55, 5.78:1.

Metadata:
- SoftwareApplication JSON-LD on the home page. Every field traces to a
  repo-sourced fact already rendered on the page; `softwareVersion` is
  omitted rather than guessed when facts carry none.
- `id` was missing from the OpenGraph locale map, so Indonesian pages
  emitted no og:locale.

Drafted by Kimi K3 in Codewhale exec, reviewed here. The claimed contrast
ratio was recomputed independently (5.78:1 vs its stated 5.75:1 — a
rounding difference against the exact ink token, and the before value does
genuinely fail AA). Gates re-run here: 250 tests, eslint clean.

Note for follow-up, not introduced by this change: `npm audit` in web/ now
reports 1 high-severity js-yaml advisory. The release contract requires 0.
2026-08-06 16:11:31 -07:00
CodeWhale Bot 75be601c5a docs(credits): credit @vFONGv for the harvested zh-CN Windows guide (#5229) 2026-08-06 06:02:09 -07:00
CodeWhale Bot d9d803eb22 fix(ci): second round — budget fold, web parity, stale RLM feature step
- source-structure budget: fold the test-fix commit's 3 executor.rs lines
  (673293 -> 673296).
- docs/public-surface-facts.json: sourceCandidate toolCount 67 -> 69 to
  match the regenerated web facts (MCP-discovery surface).
- web/lib/release-credits.ts + docs/CONTRIBUTORS.md: add @bistack (#5238)
  and extend @SparkofSpike's v0.9.4 entries (#5242/#5240/#5234) — the
  changelog/credits/contributors parity test requires exact handle parity.
- core_command_surfaces.feature: the /rlm dispatch copy changed to
  'Loading that into a persistent working context...' in a50b6532b
  (pre-existing on main, hidden by the cancelled CI); align the step.
2026-08-06 05:43:19 -07:00
CodeWhale Bot fd5b6b5321 fix(ci): unbreak newer-stable gates — pub(crate) the ui-split seam types, regen web facts
CI's stable toolchain moved past local 1.97: private_interfaces now denies
the 13 tui::ui seam types (DispatchRecovery, UserDispatchPrepare,
TerminalInputPump, ProviderKeyVerifier, etc.) that the ui split's
pub(crate) fns legitimately expose, failing Lint, Test (macos/windows),
Mobile runtime smoke, and npm wrapper smoke. Make the types pub(crate) —
they were already crate-visible in practice via those signatures — and fix
the one clippy 'matching on Some with ok() is redundant' in effort.rs.

Also regenerate web/lib/facts.generated.ts: the harvested MCP-discovery
work raised the public tool surface 67 -> 69.
2026-08-06 02:59:28 -07:00
CodeWhale Bot 6cbb2616a5 fix(models): Muse Spark 1.2 Contributor keeps its own wire id + web facts sync
Contributor tier is a distinct Meta wire model, not an alias to the
standard tier — stop collapsing it in effective_muse_wire_id so the
API actually receives muse-spark-1.2-contributor. Pricing/display
already treated it as distinct; wire now matches.

Bump web facts toolCount 66 -> 67 (harness tool).
2026-08-06 00:44:45 -07:00
Hmbown f58f9d19a7 test(web): accept a dated CHANGELOG section for the release cut
Once 0.9.4 is dated, the notes are no longer a "source candidate" and the
version compare link points at the tag range. Keep the old assertions for
an Unreleased-candidate heading.
2026-08-04 23:49:16 -07:00
Hmbown 667133a887 web: trim homepage and getting-started copy for v0.9.4
Shorten dense hero, proof, decides, meta, and start lede across all ten
locale dictionaries; tighten EN/ZH getting-started step bodies and thinking
trace context while preserving key and token parity.
2026-08-04 23:40:12 -07:00
Hmbown 5f0f61519e chore(ci): refresh the two generated files the train left stale
Both #5135 fast gates were red on the new tip for generated-file drift, not
code:

- web/lib/facts.generated.ts still claimed 67 model-facing tools; the train
  removed one, and the fresh derive counts 66. Regenerated with
  `npm run prebuild` (only generatedAt and toolCount change).
- crates/tui/CHANGELOG.md is the packaged slice of the root CHANGELOG and
  had not been re-synced after the root gained the work-bar standing-register
  entry. Regenerated with scripts/sync-changelog.sh.

Verified: scripts/release/check-versions.sh passes locally (workspace=0.9.4,
npm=0.9.4, lockfile in sync) and web check:facts drift is clean. Authored
with agent assistance (Claude).
2026-08-04 08:13:56 -07:00
Hmbown c2facb653b fix(web): keep bot maintenance off the contributor wire
The wire exists to put the people behind the repository on the front page. dependabot[bot] dependency bumps and github-actions[bot] close sweeps were spending slots that belong to human contributors — the same crowding-out the draft filter already addressed.

Decision handed to me by the ticker work: filter by GitHub's own [bot] login suffix (its verdict, not our inference). Bot-authored issues and pulls stay off entirely; a published release keeps its slot no matter who pushed the button, but a bot publisher's byline is dropped instead of named.

Two new tests pin the filter and the byline-less release.
2026-08-03 23:54:56 -07:00
Hmbown 36dcdd4b5b feat(web): put contributors on the homepage wire
The ticker printed `ISS #1234 title · 3h` for whatever the issues and pulls
endpoints last touched. It proved the repo was awake and nothing else: no
merges, no releases, no names, and English chrome on nine translated pages.

It now reports events, in the reader's language, with the person who did the
work named:

- Merged pull requests carry the contributor's handle. `merged_at`,
  `author_association`, and the login all arrive in the list payload we
  already fetch, so naming @bistack or @shenjackyuanjie beside their merge
  costs nothing extra.
- Opened and closed issues carry who filed them.
- Releases appear. That is the one added endpoint — `/releases?per_page=5`,
  cached an hour, ~1 request/hour. Three cached calls total, ~13 req/h
  unauthenticated against GitHub's 60/h/IP, and no per-item follow-ups.
- GitHub's own FIRST_TIME_CONTRIBUTOR verdict marks a newcomer's
  contribution. Copied verbatim, never inferred from the size of the window
  we happened to fetch, and it stops on its own as GitHub recomputes it.

Two honesty fixes the live render forced:

Each verb is now dated by its own event — `merged_at`, `closed_at`,
`published_at` — not by `updatedAt`. An issue opened in March and commented
on this morning was reading as "opened, 12 minutes ago".

Drafts are gone from the strip. A draft is its author's own not-ready
marker, and on this repo agents open them in batches: five of the twenty
items in the first live check were draft PRs from one bot, crowding out the
merges. They return the moment they are opened or merged.

A busy week could also bury the newest release entirely, so a release
published in the last sixty days keeps a slot — carrying its real date, so a
quiet quarter still reads as a quiet quarter rather than pinning an old tag
beside today's merges.

Verbs, the by-line, the first-contribution mark, and the strip's aria-label
are dictionary keys in all ten locales; titles, tags, and handles are the
repository's own record and stay verbatim. Ages format through CLDR off the
locale's existing `dateLocale`, the same way the masthead already sets its
date, with the compact English form as fallback where Intl data is missing.

Empty stays empty: an unreachable or fully-filtered feed removes the strip
rather than rendering a skeleton. Reduced motion now lets the frozen track
scroll instead of clipping every entry past the fold.

Verified: tsc, check:locales, check:facts, check:docs, 248 tests, lint, and a
288-page production build all clean. Live `next dev` against the real repo
rendered 15 entries on /en and /zh — merges by @Inference1 and @h3c-hexin,
issues by @vFONGv, @bistack, @shenjackyuanjie, @rafaelcavalheri, the v0.9.3
release, Chinese verbs and relative times throughout. Pointed at an
unreachable repo, both locales render fully with no ticker and no leaked
dictionary tokens.
2026-08-03 23:43:20 -07:00
Hmbown 6e5feb6856 fix(docs): the default-active tool policy is nine names, not ten
`docs/public-surface-facts.json` listed `update_plan` in
`toolSurface.defaultActive`, and `public-surface-contract.test.ts` pinned that
same ten-name list in two places plus its own title. The code has never agreed:
`DEFAULT_ACTIVE_NATIVE_TOOLS` (crates/tui/src/core/engine/tool_catalog.rs:44)
holds eight names, `tool_search` is synthetic and always active for nine total,
and `update_plan` does not appear in tool_catalog.rs at all. It is a real tool,
just not a default-active one.

Found because a docs pass corrected `docs/TOOL_SURFACE.md` from "ten" to "nine"
against the code, which turned the contract test red. The doc was right and the
facts file was wrong, so the fix is to the facts file and the assertions rather
than to the doc — the test caught a genuine drift in our published surface
description, which is what it is for.

Receipt: cd web && npm test -> 28 files, 235 tests passed, exit=0;
npm run check:facts -> OK.
2026-08-03 23:06:25 -07:00
Hmbown 4532fede38 docs: describe the telemetry endpoint that now exists
Every "ships with no endpoint configured" claim in this repo was written when
it was true. It stopped being true when the ingest Worker was deployed and the
client default was wired, so each of those sentences is now a false statement
about a live service. Rewrite them from what the service actually does.

Named plainly, everywhere: batches from an enabled session go to
https://telemetry.codewhale.net/v1/telemetry, a Cloudflare Worker whose
complete source is in this repo under telemetry-ingest/. Storage is Workers
Analytics Engine, whose row is exactly `_sample_interval`, `blob1`-`blob20`,
`dataset`, `double1`-`double20`, `index1`, `timestamp` — there is no IP,
country, or geo column, so storing one is structurally impossible rather than
switched off. The handler reads two headers, never touches the request's geo
properties, logs nothing, and rate-limits on `install_id` rather than an
address. Retention is Cloudflare's fixed three months. `docs/TELEMETRY.md`'s
shipping-gate section becomes a description instead of a promise, and the
retention line it left blank is filled in.

What did NOT change, and is stated at least as loudly as before: telemetry is
opt-in and off by default; nothing is collected, and the telemetry directory is
not created, until the first-run notice is answered with Enable; the endpoint
default decides only where an already-enabled session sends, never whether one
collects; `CODEWHALE_TELEMETRY=0`, `telemetry = false`, and a persisted off
remain hard floors; and the red-line list is untouched. The local dry-run sink
is documented as what it now is — an explicit `telemetry_endpoint = ""` — so a
user can still read their own payloads instead of taking this on trust.

Also stated rather than left implied: what turning telemetry off does and does
not reach. It erases the install id, buffer, and dry-run records locally and
stops everything further; rows already accepted are keyed only by a rotating
random id and age out with the retention window. There is no deletion API and
this does not claim one.

Both roadmap entries are updated in English and Chinese — the opt-in item and
the "Always-on or silent product telemetry" ruled-out item, which now says what
remains ruled out now that an endpoint exists. The public-surface trust string
and the contract-test assertion on it move together; the assertion gains the
consent half and the endpoint name, because a trust claim that says "an
endpoint" without saying which one is not a trust claim.

Gates: cargo test -p codewhale-config, cargo test -p codewhale-telemetry,
telemetry-ingest npm test (87, including the doc weld that parses
docs/TELEMETRY.md), and web check:facts / check:locales / check:docs / lint all
pass. web npm test has one pre-existing unrelated failure in the tool-surface
assertion against docs/TOOL_SURFACE.md, which this change does not touch and
which fails identically at HEAD.
2026-08-03 23:04:13 -07:00
Hmbown 88167ed7b7 fix(web): correct locale-inverted headings, stale provider list, and dead components
Shortcut facts (this is why the contract test moved):
docs/public-surface-facts.json declared both `Tab` and `Shift+Tab` as
`when: "composer idle"`, and web/lib/public-surface-contract.test.ts pinned
that string into README.md and docs/KEYBINDINGS.md. Both halves are false —
crates/tui/src/tui/ui.rs:6978 gates Tab on `!app.input.is_empty()`, and
ui.rs:6363-6367 gates Shift+Tab only on the modal stack. The matrix now says
"composer empty" / "always (suppressed only under a non-Config modal)" and the
test asserts the corrected wording plus a negative guard so the idle claim
cannot come back. docs/MODES.md:24 already said "when the composer is empty";
it was the matrix and the test that were stale.

/runtime rendered the Chinese-primary H1 for every locale:
web/app/[locale]/runtime/page.tsx:84-88 had two byte-identical ternary
branches, both `Runtime & 集成 Integrations`. That contradicts
web/lib/i18n/dictionaries/types.ts:33-46 ("Never hardcode Han characters at a
call site") and docs/LOCALIZATION.md:80-82 ("no locale renders another
language's script by accident"). Every other page follows the correct pattern
(constitution/page.tsx:60-65). Fixed both branches; same class, smaller blast
radius, in feed/page.tsx:114 ("Section 03 · 动态" hardcoded in the EN branch).

FAQ provider list was 25 hand-maintained names against 40 real routes:
web/lib/facts.generated.ts derives 40 providers from `pub enum ApiProvider`,
and models/page.tsx already renders `facts.providers.length`. The FAQ omitted
15, including xAI, Baidu Qianfan, Meta Model API, and all four Model Studio
routes. Because ja/ko/ru/es/pt-BR/uk/vi/id fall back to English page bodies,
9 of 10 locales saw the stale list. The count is now derived from FACTS and
the enumeration is explicitly a sample ("including …") pointing at /models.

Other corrected claims:
- docs/subagents/page.tsx omitted the `consultant` role. It is one of the eight
  in FLEET_ROLE_SCHEMA_VALUES (crates/tui/src/tools/subagent/mod.rs:376-385),
  advertised to the model, and already in web/lib/content/vocabulary.ts:183-186.
- lib/media-manifest.ts:99-100 promised a recording "from the v0.9.2 release
  candidate" on a live page (/docs/guide via components/session-media.tsx:47).
  v0.9.2 and v0.9.3 both shipped; restated against 0.9.4.
- lib/docs-map.ts:39-40 advertised Nix and Scoop as contents of /install. Both
  are real (docs/INSTALL.md:356, :507) but the site page has neither; the
  description now names what the page actually contains.
- web/README.md:99/101/122/127 — "en / zh, every page is bilingual" (10 locales
  route and non-zh get English bodies), a home-page section list naming four
  sections that do not exist, and "EN ↔ ZH toggle" for what
  components/locale-switcher.tsx:13-14 builds as an N-locale dropdown.
- docs/LOCALIZATION.md stated three different TUI key counts (1248 in the table,
  1,153 at :234). `python3 scripts/check-tui-locale-parity.py` prints 1299 for
  every pack. The zh-Hant row claimed 499/1248 "missing keys fall back to
  English at runtime" — it is 1299/1299, so nothing falls back; the row now says
  so and flags the PARTIAL_PACKS promotion as an open decision. The web
  reference shape said 51/60 keys twenty-three lines above its own correct
  52/62; check:locales prints 52/62.

Deleted (verified zero importers, no barrel, no glob loader, no CI reference):
- components/stat-grid.tsx — pulled from community/page.tsx in c268cc375, which
  added the guard at lib/public-copy.test.ts:141 asserting the page must NOT
  use it. That guard reads page source as a string and is kept.
- components/mermaid-diagram.tsx — its only consumer was removed in 5abe250f3e
  ("Cut: … the Mermaid architecture diagram"). Removed with it: the dead
  `.mermaid-frame` rules in app/globals.css and the `mermaid` production
  dependency, via `npm uninstall mermaid` so package-lock.json stays consistent
  with package.json (CI runs `npm ci`, which hard-fails on drift).

Verified in web/: npm test exit=0 (28 files, 235 tests), check:facts exit=0,
check:locales exit=0, check:docs exit=0, lint exit=0.
2026-08-03 22:48:21 -07:00
Hmbown cc20f407f3 feat: link the Codewhale Discord from the README and the site
Adds https://discord.gg/37gfS3ksug in the places someone actually looks for
a community: a badge in the first badge row and an entry on the language/link
line of all ten READMEs, a Discord action in the site nav beside the star
badge, an entry in the footer Project column, and a link in the homepage
community section.

"Discord" is a brand name, so it is a literal rather than a dictionary key —
it needs no translation and every routed locale gets the identical link shape.
The one exception is the zh README's nav line, which reads "Discord 社区" so
the word is a noun phrase in context rather than a bare English token.

docs-ia.test.ts pins the footer project routes in exact locale-swap parity, so
its expectation is extended rather than relaxed — a new footer link still has
to appear in every locale or the test fails.

Receipts: cd web && npx tsc --noEmit exit=0; npm test -> 28 files, 235 tests
passed; npm run lint exit=0.
2026-08-03 22:35:58 -07:00
Hmbown 132ab14826 fix(web): extend the CJK heading line-break rule to ja and ko
`html[lang="zh"] h1/h2/h3` relaxed `overflow-wrap: anywhere` so Chinese
headings stop stranding punctuation on a line of its own. ja needs exactly the
same rule and never had it — capping the ocean headings made it visible, with
`コマンド 1 つで始める。` breaking between `1` and `つ`. ko wants it too: it has
real word boundaries and should break on them rather than anywhere.

Extended rather than duplicated, per the rule that CJK overrides are extended
and never routed around.

Verified by eye at /ja and /ko, 1440px and 390px; no horizontal page scroll in
en/zh/ja/ko at 390px. npm test (235), lint, check:locales, check:docs.
2026-08-03 21:31:30 -07:00
Hmbown 2f5538a4e3 fix(tui): repair the test target and align effort receipts with the documented ladder
These were carried as uncommitted release-preparation edits. They are not
leftovers — without them the crate's test target does not compile, so the
branch cannot show a green gate.

- prompts.rs asserted on SUGGEST_APPROVAL, which a98b184f5 deleted with the
  rest of the prompt compatibility layer. The #5146 propose-vs-execute
  contract survived the deletion but moved, so the test now pins it on
  CORE_EXECUTION_PROFILE_PROMPT and prompts/text.rs carries the contract text
  where the model actually reads it. Without this the test target fails to
  compile with E0425 at prompts.rs:2892.
- Effort receipts follow 8c5370a56: the first-party DeepSeek wire documents
  reasoning_effort [low, high, max] and has no medium, so low maps to low and
  the header renders the tier alone instead of `low→high`. Updated in
  subagent/tests.rs, ui/tests.rs, underwater.rs and the qa_pty visual contract.
- Facts regenerated: toolCount 67, @shenjackyuanjie credited in the
  public-surface contributor record.

One assertion tightened rather than carried as written: underwater.rs's
normal_header test had been relaxed to `contains("low")`, which also passes on
the old `low→high` rendering and so pinned nothing. It now additionally
asserts the arrow is absent, which is the actual regression to guard.

Receipts: the six bin-suite failures these address were reproduced at the
unmodified base and are exactly this set. Full gate runs with the workspace
suite.
2026-08-03 20:33:37 -07:00
Hmbown dcf98dbbb9 feat(web): drive the newspaper homepage and chrome from dictionaries in every locale (#4934)
FINISH-0.9.4 §0A Phase 1. The homepage, nav, footer, and layout were an
EN/ZH special case with a thin foreign fallback: English and Chinese copy
lived inline in the TSX behind isZh ternaries, and the eight routed partial
locales fell through to English for anything the dictionaries did not cover.

- HomeDict/ChromeDict extended to cover every visible homepage and shared
  chrome string (chrome 51->52 keys, home 60->62).
- New web/lib/i18n/dictionaries/zh/{chrome,home}.ts, extracted faithfully
  from the existing inline Chinese rather than retranslated.
- Real translations to exact key parity for ja, vi, ko, ru, uk, es, pt-BR
  and id. {token} placeholders preserved; no sentence is concatenated
  around a variable.
- Homepage, nav, footer and layout consume getHome(locale)/getChrome(locale)
  for all ten locales. Every isZh/foreign user-copy branch on those surfaces
  is deleted rather than left running alongside the new path.
- Footer link sets generate from the dictionaries via the new
  web/lib/i18n/links.ts instead of hardcoded per-locale arrays.

Closes a real gap found on the way: app/[locale]/layout.tsx still carried an
isZh branch governing the skip-to-content link, which renders on every page
of every locale, and the home route's metadata title and description. Eight
locales were serving an English skip link and an English <title> behind
fully translated chrome.

Honesty: zh stays `shipped` because its first-class pages (install, FAQ,
community, contribute, models, runtime, roadmap, constitution) really are
translated — chrome alone never earns it, and config.ts now records that as
the reason. The other eight stay `partial` with a localized badge;
install/faq/community/contribute still fork on isZh, which is Phase 2 scope
and is exactly what keeps those locales partial.

Contract tests strengthened, not relaxed: public-copy and
public-surface-contract now assert the rendered contract and the EN
dictionary value instead of matching raw TSX strings, and the footer's
account-copy ban is asserted across all ten locales rather than the TSX alone.

Receipts, all exit 0: npm run prebuild, check:facts, check:locales,
check:docs, test, lint, build. Ten locales fetched from a dev server and the
markup inspected: no rendered dictionary keys; masthead, 深 seal,
ocean-framed codewhale-tui.png and the partial badge intact in every locale.
2026-08-03 18:27:46 -07:00
Hmbown 3641dd4eb8 fix(web): credit @shenjackyuanjie in the 0.9.4 website contributor list
CHANGELOG.md and docs/CONTRIBUTORS.md already credit the Windows OpenHarmony
linker re-quoting (PR #5095), but web/lib/release-credits.ts did not, which
failed lib/public-copy.test.ts's exact changelog-parity assertion — the
Web Frontend / Lint & Type Check gate on release train PR #5135.

Receipt: npx vitest run lib/public-copy.test.ts -> 7/7 pass.

Co-authored-by: shenjackyuanjie <54507071+shenjackyuanjie@users.noreply.github.com>
2026-08-03 18:27:11 -07:00
Hunter Bown 99ae7d4f62 fix(web): map Model Studio provider variants in facts drift guards (#5230)
* fix(web): map Model Studio provider variants in facts drift guards

The train's Model Studio lane added four ApiProvider variants without
registering them in the web facts maps, failing check-facts (Lint & Type
Check on #5135). All four share the single MODELSTUDIO_API_KEY env var.

* chore(web): regenerate facts.generated.ts (providers 40, tools 68)
2026-08-03 08:56:46 -07:00
Copilot 99bd642db9 fix(web): admin digest post returns real GitHub Issue outcome instead of silent no-op (#5180)
* Initial plan

* fix(web): digest post returns real GitHub Issue URL instead of false ok:true

The admin digest "post" action was returning `{ ok: true, action: "digest-skipped" }`
without posting anything or marking the draft as posted. This caused the draft to
reappear in Pending forever — a false success receipt.

Fix: digest drafts are now posted as new GitHub Issues (using the existing
MAINTAINER_GITHUB_PAT + REST API). The response includes the real issue
`number` and `url`; `draft.posted` is set to true and the draft is stored back.
GitHub API failures propagate as 502 errors, never as ok:true.

Tests: two new source-contract tests in public-api-security.test.ts pin both
paths — happy path (real url/number returned) and error path (502, not ok:true).

Closes #5178

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
2026-08-03 05:48:30 -07:00
Copilot 808d517095 fix(web/admin): zh admin pre-fills and publishes bodyZh instead of bodyEn (#5179)
* Initial plan

* fix: zh admin pre-fills and publishes bodyZh not bodyEn

startEdit always set editBody to draft.bodyEn regardless of locale.
Change to isZh ? draft.bodyZh : draft.bodyEn so the /zh admin
textarea pre-fills the Chinese body.

Also fix the "Posted" preview row which displayed bodyEn unconditionally
— now respects isZh in the same way.

Add a test asserting that POST /api/admin/post with lang=zh and no
editedBody sends the zh body to GitHub, not the English one.

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
2026-08-03 05:48:25 -07:00
Hmbown 86c6e0d1c6 fix(web): detect Intel Macs for the install snippet via client hints (#5168)
detectFromBrowserSignals declared 'macos-x64' in its Arch union but
could never return it: every non-Windows, non-Linux UA fell through to
'macos-arm64', silently handing Intel Mac users the Apple Silicon
binary snippet.

Since Big Sur the macOS UA reports 'Intel Mac OS X' on Apple Silicon
too, so UA parsing fundamentally cannot distinguish the two — only
User-Agent Client Hints can. The component already requests
architecture/bitness hints; the detector now honors them on the macOS
branch (x86 -> macos-x64). Without hints the default stays arm64 (every
Mac sold since late 2020) and the page's existing arch chooser remains
the honest fallback, so nobody is silently misdetected.

Vitest pins: x86 hint -> macos-x64, arm hint -> macos-arm64, and the
deliberate no-hint arm64 default on the frozen Intel UA.

Agent-assisted change.
2026-08-02 22:55:02 -07:00
Hmbown 9967f06c5c Merge origin/main into the v0.9.4 release train
Brings the train current with main's 34 commits (managed Fleet launch,
CLI sign-in, docs restructure, locale parity, /automation, handoff skill,
DeepSeek fixes, fixture entropy fixes) so lane stacks rebase onto current
main exactly once.

Conflict resolution by class:
- 15 locale JSONs: 3-way key merge (main's reformat + train's 42 new keys;
  zero both-changed keys). Parity suite green.
- experimental_search.rs (add/add): main's f3e3232ef reshape + train's
  d335cb2e3 admission-boundary validation re-applied cleanly.
- /automation surface (add/add): kept the train's AutomationAction +
  automation_routing + localized design (matches the kept locale keys);
  removed the four orphaned main-design handlers in ui.rs.
- cloud.rs: train's side — external tests are a strict superset; keeps the
  logout-slot scrub and 401-precision fixes.
- responses.rs / skills/system.rs: train's `mod tests;` extraction (test
  bodies verified identical modulo formatting).
- subagent/tests.rs: RESTORED 13 train-side tests the auto-merge silently
  dropped (taint, checkpoint, compaction, coordination-lock coverage);
  full-file audit confirmed no main-side content lost.
- CHANGELOG.md: union, header stays "Unreleased candidate";
  crates/tui/CHANGELOG.md regenerated via scripts/sync-changelog.sh.
- source-structure-budget.json: main's values; facts.generated.ts:
  regenerated via web/scripts/derive-facts.mjs.
- Comment-only hunks: main's rewordings.
- skills-catalog fixture: train already tracked generation 9 (verified;
  the gen-8 staleness was main-only, fixed on main in 50b54bcfd).

Gates: cargo fmt --all -- --check (exit=0); cargo check --workspace
--all-targets --locked (exit=0); targeted locale/automation/skills/
workflow suites green; full bin suite 9593 passed / 2 failed — only the
pre-existing config::credential_scope_tests::* macOS symlink failures.
Line-survival audit over all 17 both-sides-changed code files: clean.
2026-08-02 19:53:45 -07:00
Hmbown c4e5badde1 docs: sync v0.9.4 release credits
Add the current release band to the canonical contributor record and keep the website credit arrays in exact changelog parity.

Replace the stale single-release @fleitz assertion with a data-driven contract over the candidate credit facts.

Signed-off-by: Hmbown <101357273+Hmbown@users.noreply.github.com>
2026-08-01 10:30:18 -07:00
Hmbown fd65176f56 chore(release): prepare v0.9.4 source candidate
Date the v0.9.4 changelog, preserve contributor credit and unpublished-release truth, and synchronize every crate, npm, lockfile, smoke-test, and generated public-fact version surface. This prepares a source candidate only; it does not tag, publish, or create a release.

Signed-off-by: Hmbown <101357273+Hmbown@users.noreply.github.com>
2026-08-01 10:12:09 -07:00
Hmbown 0defe02388 fix(release): record the published v0.9.3 surface
Update the repository-backed public release fact from v0.9.2 to the live v0.9.3 GitHub release. Regenerate the website fact module so local and public-surface checks agree before preparing v0.9.4.

Verified with npm run check:facts and npm run check:docs.

Signed-off-by: Hmbown <101357273+Hmbown@users.noreply.github.com>
(cherry picked from commit 59ba8dab1b)
Signed-off-by: Hmbown <101357273+Hmbown@users.noreply.github.com>
2026-08-01 10:11:59 -07:00