Commit Graph

294 Commits

Author SHA1 Message Date
CodeWhale Bot 518db2b37e debug: probe python availability on Windows runner 2026-08-11 22:05:33 -07:00
CodeWhale Bot d970495929 fix(subagent): keep route receipts under the admission limit on CI builds
The receipt embeds the build commit, which CI stamps with the full
40-hex GITHUB_SHA while local builds carry the literal 'unknown'.
A full-length sha pushed the serialized receipt to 394 bytes over the
384-byte admission cap, so every CI build refused child launches and
the receipt regression tests failed on GitHub runners (they passed
locally only because 'unknown' is short). Some legitimate routes also
reached 386 bytes even without the sha.

- Truncate the embedded build commit to 12 hex chars; version + short
  sha still identify the build for attribution.
- Raise the cap to 448 bytes with headroom for route growth.
- Remove the temporary debug workflow used to capture the runner
  failure output.

Verified with the exact CI condition reproduced locally: a build
with DEEPSEEK_BUILD_SHA set to a full 40-hex sha now passes the
receipt tests, and the full lib suite is green (10301 passed).
2026-08-11 20:47:30 -07:00
CodeWhale Bot 66df75a5a3 debug: run receipt tests with --nocapture on a GitHub runner 2026-08-11 20:35:17 -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 1ed798db56 fix(release): honor SOURCE_DATE_EPOCH in bundles (#5312)
Derive archive mtimes from the pinned source commit in release artifacts, retain reproducible archive bytes and executable modes, and cover metadata plus input validation.
2026-08-11 15:02:30 -07:00
CodeWhale Bot a77b12876f ci(release): publish npm through trusted OIDC
Bind npm publication to the exact release SHA after the public asset freshness gate, without a long-lived registry token. Document the npm-side publisher binding and interactive 2FA recovery path.\n\nCloses #5299
2026-08-11 12:52:11 -07:00
CodeWhale Bot 00aae33b44 fix(release): assemble container images from native artifacts 2026-08-10 18:12:14 -07:00
CodeWhale Bot 5798de8b39 build(release): native musl for Linux ARM64, and reconciled copy
Three v0.9.5 benchmark tasks could not launch Codewhale at all:
mteb-leaderboard, mteb-retrieve, and pytorch-model-recovery run older ARM64
images, and the aarch64-unknown-linux-gnu artifact built on ubuntu-24.04-arm
requires GLIBC_2.39.

Release and nightly now build aarch64-unknown-linux-musl on the native ARM
runner, alongside the x64 musl build that has shipped since v0.8.65. Both
gain a static check (no ELF INTERP) plus a launch smoke on the matching
native runner, so a dynamically linked or non-starting binary fails the
build rather than the user's install. docs/INSTALL.md drops the arm64 glibc
floor section and describes the v0.9.6 matrix.

Also reconciles the copy the earlier commits invalidated: setup ratification
text and all 15 locales stop attributing execution doctrine to "mode
prompts", docs/MODES.md states Auto-Review's actual deterministic
allow/deny behavior, and the source-structure, dead-code, and
runtime-contract budgets are re-measured — the last locking down 25
decreased ceilings and the new mode-agnostic prompt-stage digests.
2026-08-09 00:52:42 -07:00
CodeWhale Bot 5162341fd1 ci(cnb): match workspace test stack
Signed-off-by: CodeWhale Bot <bot@codewhale.net>
2026-08-08 19:59:20 -07:00
CodeWhale Bot b899c42be9 ci(cnb): bound Rust gate memory
Signed-off-by: CodeWhale Bot <bot@codewhale.net>
2026-08-08 19:18:47 -07:00
CodeWhale Bot 4a6933754e fix(release): validate crate publication order
Signed-off-by: CodeWhale Bot <bot@codewhale.net>
2026-08-08 17:58:32 -07:00
CodeWhale Bot cd4bf73215 fix(ci): target consolidated PTY acceptance
Run the isolated Skills Manager scenario through the pty integration-test binary and use its module-qualified name so --exact executes one test instead of zero. Lock the command into the workflow contract and update the durable TUI verification examples.

Verified with the exact ignored PTY command, the workflow contract test, actionlint YAML/expression checks, and git diff --check.
2026-08-08 05:03:43 -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 001921d056 fix(ci): target persistence measurement library test
Run the ignored persistence backlog receipt test from the TUI library after the integration target move. Pin the exact Cargo command in a hermetic harness test and reject successful zero-test or missing-receipt runs so future test relocations fail clearly.
2026-08-08 01:56:19 -07:00
CodeWhale Bot e54b8043df fix(gates): measure the library runtime contract
Run each ignored receipt test against its exact library path and reject Cargo's successful zero-test result explicitly. Keep the standalone tool-catalog measurement and current verification guidance on the same target, with hermetic command and failure regressions wired into CI.

The repaired measurement exposed a real duplicate AGENTS.md injection from the bounded fragment importer. Keep canonical project-context sources single-owned while still importing additional rule formats through the typed, capped fragment boundary; this restores the checked-in prompt identity without raising the budget.

Verified with the full 55-metric runtime-contract checker, focused core and TUI regressions, both Python harness suites, cargo fmt, and all-target clippy for codewhale-core and codewhale-tui.
2026-08-07 21:56:00 -07:00
CodeWhale Bot 471c6d8bb0 fix(ci): align nightlies with the single runtime
Build only the codewhale executable, then stage codewhale and codew from the same bytes for every retained nightly target. Native jobs smoke only the executable that Cargo actually produced, while tagged-release TUI bridge filenames remain out of the nightly command contract.\n\nExtend the workflow contract test to lock the six-target, twelve-artifact inventory, byte-identity check, native smoke selection, and 14-day retention.
2026-08-07 21:52:11 -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 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 e291350b4c fix(release): bridge the 0.9.5 single runtime
Build codewhale once, expose the verified bytes as codew across release channels, and retain seven TUI-named release aliases solely so shipped v0.9.4 clients can discover and cross the transition. Current installers and containers expose only codewhale and codew.\n\nVerified with the npm asset suite, exact 34-asset assembly, workflow contract, Homebrew renderer, release-body, dogfood installer, and shell syntax tests.\n\nRefs #5259
2026-08-07 21:36:17 -07:00
CodeWhale Bot be676502df feat(release): single-binary packaging follow-ups (5259/5260)
Complete 5259 single-binary sweep for packaging/docs: remove
codewhale-tui from .cnb.yml, nix, npm bin, installer, bundles,
locales, and docs/INSTALL matrix; add .winget + packaging/ manifests
(single-binary 27-asset inventory, FreeBSD source-build note) and
update release-artifacts comments from 34 to 27 assets. 27-asset
inventory verified via assemble-release-assets --verify.

Co-Authored-By: internal-model
2026-08-07 06:14:45 -07:00
CodeWhale Bot 69ddf337b4 feat(release): 7x1 single-binary matrix — drop codewhale-tui asset (5260)
Release CI 7 targets x 3 binaries -> 7 x 1. Removes tui_binary/tui_artifact from matrix, cargo build -p codewhale-cli only, drops tui smoke/stage/upload and windows installer copy. Single codewhale binary + codew shim only. Part of 5260 packaging sweep (I1 -> I2).
2026-08-07 06:02:27 -07:00
CodeWhale Bot b6585ea990 WIP: 0.9.4 fence, turn liveness, model picker, budget, and contributor credit
- fix rlm/turn.rs build (build_metadata_message) and honest/empty guard
- fold Unreleased� 0.9.4 dated 2026-08-07 and sync changelog
- fix Meta facts (  (3 and,�, contrib) and provider picker fallback
- tighten prompts (backticks for work_update)
- stick guard: Warn/Stop across flav...
2026-08-06 18:30:13 -07:00
CodeWhale Bot 6b7eb20ef1 ci: give test threads the stack the product gives itself
main.rs runs the owner thread and every tokio worker at
CODEWHALE_MAIN_STACK_BYTES (16 MiB) because the engine and runtime-thread
futures are genuinely deep — 8c98bedc75 landed the worker half of that
after a debug `agent` dispatch measured a 2.25-2.5 MiB high-water mark and
died on the guard page.

`#[tokio::test]` builds its own runtime and never sees that. So the test
lanes ran the same code on ~2 MiB, and ~1 MiB on Windows: a configuration
that never ships. That is what aborted the entire Windows test binary with
STATUS_STACK_OVERFLOW in start_turn_accepts_dynamic_tools_and_environment_
id, taking ~9.7k unreported results with it and masking every other
Windows failure — the same masking 78afd8d3d4 called out when it Box::pin'd
that one frame. Box::pin fixed the frame; the environment mismatch stayed,
so the abort returned as soon as codegen moved frame sizes again.

Set RUST_MIN_STACK to the same 16 MiB on the CI test lane and on
release.yml's parity gate. std reads it for any thread spawned without an
explicit size, which covers both libtest's per-test threads and tokio's
workers, so the whole suite gets production's stack instead of the
harness default.

This is not a bigger hammer for a deep-recursion bug: 16 MiB is exactly
what the product already guarantees this code, so the tests now measure
the shipped configuration rather than a stricter one no user runs.
2026-08-06 10:00:57 -07:00
CodeWhale Bot 4d89fdac42 fix(ci): map @vFONGv in AUTHOR_MAP for harvested credit (#5229)
Matthew.Fong <21223725+vFONGv@users.noreply.github.com> plus the
fangb0987612345@gmail.com commit-email alias, so harvested co-author
credit lands in the contributor graph.
2026-08-06 06:49:15 -07:00
Hmbown 76a613dae0 build: split the shipping profile from the everyday --release gate
Closes #5246 groundwork (issue stays open until release CI runs the dist
profile). [profile.release] was tuned for shipping (fat LTO,
codegen-units=1, strip) while AGENTS.md prescribes cargo build --release as
the routine pre-push gate — so every contributor paid the full fat-LTO
pipeline on a 680k-line crate for a smoke build (8-16 min community-reported
in #4991; 13m57s measured here).

Now [profile.dist] (inherits release; lto=true, codegen-units=1,
strip=true) carries today's exact shipping optimization, and
[profile.release] relaxes to lto="thin", codegen-units=16 for the local
gate — same command, same artifacts collected by nothing. The
panic-unwinding note moves with the dist profile; neither profile sets
panic=abort (the TUI's panic supervision needs unwinding).

Workflow audit: release-artifacts.yml (the only workflow uploading
user-facing binaries) builds with --profile dist and stages from
target/<triple>/dist on both build paths. nightly.yml deliberately stays on
--release: it has always overridden LTO off (CARGO_PROFILE_RELEASE_LTO=off,
codegen-units 16) for fast prerelease builds and its build/collect paths
are internally consistent. ci.yml's release-build gate stays --release and
gets the same speedup. scripts/release/prepare-local-release-assets.js
defaults to target/release but is the local npm-wrapper smoke flow with an
explicit dir argument, not a publish path.

Measured on the 14-core M-series dev machine, warm cache, one touched file
(crates/tui/src/elapsed.rs): --release rebuild 13m57s before -> 2m16s
after (real 136.67s). cargo build --profile dist compiles with the
inherited fat-LTO settings. Authored with agent assistance (Claude); spec
by the owner's build-time lane (#5246/#5249).
2026-08-04 09:24:55 -07:00
Hmbown 038f9b778b telemetry: add the first-party ingest Worker (not deployed)
Adds `telemetry-ingest/`, a Cloudflare Worker that accepts the batches
`crates/telemetry` produces and writes them to Workers Analytics Engine.
Nothing is deployed and no Cloudflare resource was created; the shipped
`telemetry_endpoint` default stays unset, `config.example.toml` and
`docs/TELEMETRY.md` are untouched. Publishing is a separate, deliberate
step.

It lives at the top level rather than inside `web/` because the site is a
separate deploy with its own Next.js/OpenNext build, and a telemetry
change should not rebuild the marketing site.

The endpoint is write-only: one POST route, every other method 405, no
route that returns data, and a zero-byte body on every status. The client
reads only the status class and drops the batch on anything non-2xx, so a
rejection here is invisible to the user by construction — which is what
lets the endpoint fail closed and refuse anything it cannot account for.

Three properties are enforced by tests rather than by intent:

`docs/TELEMETRY.md` says "Batches are IP-stripped at ingest. No IP is
stored, logged, or joined to install_id." This Worker is the whole of what
makes that true. It reads exactly two headers, never touches the request's
`cf` property, logs nothing, and turns invocation logs off in the config;
the row builder's input type is the validated batch body, so it cannot see
the connection at all. `test/no-ip.test.ts` greps the shipped source for
the header and geo names and fails the build if one appears, if the set of
headers read grows, if a console call is added, or if a Response is ever
built with a body.

The validator is a closed field set, not a permissive parse: an unexpected
key anywhere — envelope, event, counters, errors, turn_wall — rejects the
whole batch with 400. A future client bug that starts attaching a path or
a prompt is refused rather than quietly stored.
`test/schema-doc.test.ts` parses the field names and enum spellings back
out of `docs/TELEMETRY.md` and asserts set equality against the validator,
and the suite posts `crates/telemetry/tests/golden/v1.json` — the client's
own pinned wire form — asserting it is accepted and that deleting any key
from it is rejected. Doc, client, and server cannot drift apart silently.

The body cap is computed, not guessed: `parse_events` bounds a batch at
200 events and 65536 bytes, plus 199 commas and ~375 bytes of envelope,
so 66110 bytes is the conforming worst case and the cap is 72 KiB. The
512-record ring is the disk cap, not the wire cap. Rate limiting is keyed
on `install_id` from the validated body, never on an address.

Analytics Engine layout is one data point per event, indexed on
`install_id`, with the ten counters, six error classes and four turn-wall
buckets filling all twenty doubles. The README documents the exact SQL for
the two questions this exists to answer — installs and sessions, and which
error classes and panic sites dominate — one query each.

Verified locally only: 87 vitest tests, `tsc --noEmit`, `wrangler deploy
--dry-run`, and `wrangler dev --local` driven with curl (204 on the golden
batch, 400 on an unknown key and on an out-of-allowlist panic site, 413
oversized, 405 GET, 415 wrong content type, 404 other path, 429 after 20
POSTs from one install id). `wrangler dev` caught a real defect the dry
run did not: the runtime maps every named export of the entrypoint to an
entrypoint, so the route constant moved to its own module.
2026-08-03 22:44:59 -07:00
Hmbown 648bdf804e ci: run the runtime web client test and the integrations bridge suites
crates/tui/tests/runtime_web_client.test.mjs (the embedded web
client's event/snapshot state machine) ran in no workflow; it is now
a step in the always-on Version drift job. A new Integrations job
runs the five dependency-free node --test suites under integrations/
(bridge-core, feishu, telegram, wecom, weixin) on every push/PR —
6,500 LOC of bridge code previously had zero CI. weixin ships without
a lockfile by design; every suite passes with plain npm test and no
npm ci (verified locally: 11/19/39/16/3 passing, 0 failing).

Evidence: cross-surface-tech-debt-audit-2026-08-03.md §11.3 CI-wiring
rows ('Wire runtime_web_client.test.mjs into CI', 'add existing
suites to CI').
Gate: node --test crates/tui/tests/runtime_web_client.test.mjs
-> exit=0; per-bridge npm test -> all exit=0.
2026-08-02 20:59:24 -07:00
Hmbown 314f1b0482 chore(release): align published version strings with workspace 0.9.4
extensions/vscode was 0.8.53, npm/runtime-sdk 0.8.60, and the
verifiers README claimed v0.9.1 while the workspace is 0.9.4. All
three now read 0.9.4. The release.yml version gate previously checked
only workspace + npm/codewhale, which is how the drift survived
release prep; it now also requires runtime-sdk and vscode package
versions to match the tag.

Evidence: cross-surface-tech-debt-audit-2026-08-03.md TL;DR 'Stale
version strings'; §11.3 version-sweep row.
Gate: node -p require(...).version -> 0.9.4 for both packages.
2026-08-02 20:59:24 -07:00
Hmbown f6a15ac046 chore(ci): drop stale reference to deleted v0867 incident script
fleets/v0868-stopship.toml and scripts/v0867-setup-qa.sh (audit §11.3
'incident debris') are already absent from this tree; the only trace
left was the scripts/v0867-setup-qa.sh entry in ci.yml's light/heavy
path classifier and its comment. Both removed.

Evidence: cross-surface-tech-debt-audit-2026-08-03.md §11.3 incident
debris row; files verified absent with ls + rg before editing.
2026-08-02 20:59:24 -07:00
XhesicaFrost 764a1c8a6a fix(installer): preserve long Windows user PATH (#5006)
Preserve the full user PATH during Windows installer updates and retain the contributor's regression coverage for long PATH values.
2026-08-01 05:10:39 -07:00
dependabot[bot] 81e6714b43 chore(deps): bump docker/login-action from 4.4.0 to 4.5.2 (#5012)
Update docker/login-action to 4.5.2.

All substantive platform, lint, workflow, security, and source-budget checks pass.
2026-08-01 04:53:55 -07:00
dependabot[bot] 0c03169488 chore(deps): bump actions/stale from 10.4.0 to 11.0.0 (#5010)
Update actions/stale to 11.0.0.

All substantive platform, lint, workflow, security, and source-budget checks pass.
2026-08-01 04:53:14 -07:00
Hunter Bown e8d2538a9d fix(ci): repair three shared check failures blocking open PRs (#5017)
* fix(ci): skip the PR-issue link gate for bot-authored PRs

The `link` job fails on every dependabot PR (e.g. #5010-#5016): dependabot
bodies are machine-generated dependency bumps that never contain a closing
keyword, so the gate exits 1 ("This PR neither closes an issue nor says why
it doesn't", run 30665868640/job 91272641294).

Skip the gate step when the PR author is a GitHub-verified bot account
(`pull_request.user.type == 'Bot'`, set by GitHub so it cannot be spoofed).
This covers dependabot today and any other automation (renovate, etc.)
without hand-editing every bot body, while keeping the gate strict for every
human PR.

Policy choice: all verified bots, not just dependabot[bot]. Bots cannot
respond to a prompt, and their changes never close issues; the check's
purpose is keeping human work linked to its issue.

* fix(ci): provision the deny container's Rust toolchain explicitly

cargo-deny runs inside EmbarkStudios/cargo-deny-action@v2's alpine container
(host triple x86_64-unknown-linux-musl, rustup default 1.85.0-musl). The
repo's rust-toolchain.toml pins `channel = "stable"` with no target, so the
action's `rustup show` (entrypoint.sh) resolves it to
`stable-x86_64-unknown-linux-musl` — not installed — and every run prints:

  error: override toolchain 'stable-x86_64-unknown-linux-musl' is not
  installed: the toolchain file at '/github/workspace/rust-toolchain.toml'
  specifies an uninstalled toolchain

then auto-installs mid-run (network-dependent ~12s detour; hard failure if
the download stalls; seen in run 30665967039/job 91272951661).

Pass `rust-version: stable` so the entrypoint provisions the channel
(`rustup default stable`, same musl host triple) before cargo-deny touches
the workspace; the toolchain file then resolves to an installed toolchain.

* fix(deps): bump event-listener 5.4.1 -> 5.4.2 (RUSTSEC-2026-0221)

cargo-deny (advisories) fails on every dependabot PR (e.g. run
30665967039/job 91272951661) with the unsound advisory:

  error[unsound]: `event-listener` allows `!Send` tags to cross thread
  boundaries via `StackSlot`  (RUSTSEC-2026-0221)

event-listener 5.4.1 unconditionally implements Send/Sync for StackSlot,
allowing a !Send tag to cross threads via Event::with_tag. Pulled in via
codewhale-tui -> codewhale-workflow-js -> rquickjs -> rquickjs-core ->
async-lock (and event-listener-strategy). Advisory solution: >=5.4.2, the
latest published version.

`cargo update -p event-listener` lands exactly on 5.4.2 (also drops its now
unneeded concurrent-queue dependency). No deny.toml ignore needed.

* fix(ci): fetch the locked graph before the offline runtime-contract check

The Lint job's "Check runtime-contract budget" step fails on every
dependabot PR (run 30665967040/job 91273020141, PR #5016):

  error: failed to download `assert-json-diff v2.0.2`
  Caused by: attempting to make an HTTP request, but --offline was specified
  subprocess.CalledProcessError: ... returned non-zero exit status 101.
  [runtime-contract-budget] ERROR: runtime-contract measurement failed with exit code 1

Root cause: check-runtime-contract-budget.py hardcodes CARGO_NET_OFFLINE=true
and runs `cargo test --locked` on codewhale-tui, which needs the dev-dependency
graph (wiremock -> assert-json-diff). Clippy above builds no test targets, and
Swatinem/rust-cache keys its registry cache on Cargo.lock, so any lock-changing
PR (every dependabot bump) misses the cache and the offline test cannot
download the missing crate. Reproduced locally with the identical error by
removing assert-json-diff from the registry cache and re-running the exact
CI command.

Fix: fetch the full locked graph (`cargo fetch --locked`, dev-deps included)
once in the heavy path before the measurement, so the hermetic offline
measurement is deterministic on every branch. The budget contract itself is
unchanged and still enforced.

* fix(ci): reviewed source-structure budget update for merged LaTeX module

Merging #4981 (LaTeX rendering) added crates/tui/src/tui/history/
latex_render.rs (1734 lines) and grew aggregate owned Rust source to the
measured merged state (644756 lines). The ratchet's contract requires an
explicit reviewed update for new thousand-line modules and aggregate
growth; this commit allows the merged module and raises the ceiling to
the exact CI-measured value. Verified: check-source-structure-budget.py
PASS on the branch; runtime-contract budget still PASS 55/55.
2026-07-31 21:21:07 -07:00
Hmbown 02f2e03cb1 test(tui): harden persistence backlog ratchet
Bind receipts to a clean exact source SHA and toolchain, measure the version production PendingState would actually apply, reject impossible payload and type claims, and fail closed when macOS RSS evidence disappears. Exercise adversarial checker tests in CI and run the live RSS budget on the heavy macOS lane.
2026-07-30 12:59:27 -07:00
Hmbown ec44a2f837 test(tui): baseline persistence backlog pressure
Measure the production persistence request channel with a paused consumer, a frozen same-session workload, and macOS RSS samples. Record one-way retained backlog ceilings while requiring every send and the newest snapshot to survive, and run the provider-free checker in the heavy CI lane. Production channel behavior remains unchanged.
2026-07-30 12:41:53 -07:00
Hmbown 38268346f0 test: ratchet source ownership structure
Add an offline source-only budget for workspace packages, binary targets, thousand-line owned module identities, the largest owned Rust file, and aggregate owned Rust lines. Permit deletion and line-neutral consolidation while requiring explicit reviewed updates for new structural surface, then run the checker in the existing heavy CI gate.
2026-07-30 10:46:06 -07:00
Hmbown 67adf84697 test: ratchet the runtime contract
Measure the provider-free model-facing contract through production-owned seams. Keep deterministic minimal prompts by visible mode, build each Plan/Act/Operate tool surface through the canonical turn registry and request planner with inert wiring, and record full and active catalog counts, bytes, token estimates, sorted names, and stable identities.

Add a hermetic representative prompt fixture that cumulatively introduces project authority, configured instructions, one workspace skill, memory, goal, and handoff. Normalize temporary roots before hashing every stage, require stable repeated identities, prove each prior marker appears exactly once while future markers remain absent, and ratchet adjacent stage deltas plus the final envelope.

Enforce 55 one-way numeric ceilings and exact structural identities, while retaining the observable repeated skill-discovery baseline and future cached-zero payload. Reject equal-size tool substitutions, removals, missing identity, cross-mode swaps, and representative-stage substitutions; keep atomic permission-preserving budget updates and the locked offline heavy-lint gate.
2026-07-30 10:02:36 -07:00
Hmbown d52a9dae05 ci(tui): isolate Skills Manager PTY acceptance
Run the Skills Manager compatible-root scenario in its own Unix test process after the workspace suite. This preserves the exact real-PTY assertion while preventing suite-level event starvation on loaded Linux release runners.

Fixes #4941

Signed-off-by: Hmbown <101357273+Hmbown@users.noreply.github.com>
2026-07-29 07:32:46 -07:00
Hmbown 9d1f3a7bb3 ci(release): configure candidate Rust toolchain
The pinned rust-toolchain action requires an explicit toolchain input. Add stable so the exact-candidate resolver reaches its source and artifact checks.

Signed-off-by: Hmbown <101357273+Hmbown@users.noreply.github.com>
2026-07-29 03:24:14 -07:00
Kobi Hikri 0f63bcafda ci: restore trailing newline at end of file
Signed-off-by: Kobi Hikri <kobi.hikri@gmail.com>
2026-07-29 06:25:54 +03:00
Kobi Hikri 5c09915c23 ci: attach provenance and SBOM attestations to the published image
Signed-off-by: Kobi Hikri <kobi.hikri@gmail.com>
2026-07-29 06:25:54 +03:00
Nightt 1f74419703 fix(tools): preserve CRLF edits
Match edit_file searches on an LF-normalized view while mapping the unique match back to original bytes. Normalize replacement newlines to the file style and preserve non-unique/no-op safeguards.

Cover CRLF/LF, mixed duplicates, fuzzy UTF-8 matches, and reporter credit surfaces.

Reported and root-caused by @LmeSzinc in #4764.

Co-authored-by: LmeSzinc <37934724+LmeSzinc@users.noreply.github.com>
Signed-off-by: Nightt <87569709+nightt5879@users.noreply.github.com>
2026-07-28 10:39:03 +08:00
Hmbown c1b47796ce chore: land the bounded dead-code slice and stop the wall regrowing
#4785 asks for a 481-attribute sweep. This is not that sweep — it is the part
that can land without judgment calls, plus the gate that makes the sweep worth
doing.

The measurements are why the gate comes first:

    issue filed   464 attributes / 143 files
    2026-07-26    426 / 111
    2026-07-28    481 / 155

The sweep was working and the total still rose, because two large landings this
week added state whose accessors only their own tests read. A sweep is a
snapshot; a budget is a direction.

scripts/check-dead-code-budget.py counts `allow(dead_code)` across crates/ and
fails when the total exceeds a committed ceiling. Lowering it is free; raising
it needs `--update` and a sentence in the PR, so growth becomes a visible
decision rather than an accident. On failure it prints per-crate now-vs-budget
and marks which crate grew. Wired into Lint next to the other check-*.py gates.

This covers a real blind spot: CI's clippy runs without `--all-targets`, so it
never lints cfg(test) or integration-test code — and a prior strip-and-check
measured 197 attributes alive *only* because a test references them.

The three zero-risk removals from the issue's cluster list:

- `codew_legacy_shim.rs` -> `codew.rs`. The issue calls this out as a rename,
  not a deletion: it is the live `codew` binary and its own docs call it
  permanent. Every sweep flags the filename; the binary name is unchanged.
- `clap` dropped from app-server and `thiserror` from lane — no source in
  either crate references them. Cargo.lock loses exactly those two edges and no
  package versions move.

The budget baseline is recorded at today's 482, not at an aspirational number,
so the gate starts truthful and the sweep can ratchet it down.
2026-07-27 18:53:25 -07:00
Hmbown aff2cf782c feat(web): localize the site chrome and home page for eight locales
Extracts the marketing site's hard-coded English copy into per-locale
dictionaries (19 chrome keys + 40 home keys for en, es, ja, ko, pt-BR,
ru, uk, vi) and routes nav, footer, locale switcher, sitemap, and the
home page through them.

Also:

- `lib/i18n/detect.ts` pulls Accept-Language negotiation out of
  middleware into a tested module. This fixes the pt-BR bug: a browser
  sending `pt-BR` was matched on the bare `pt` prefix against the wrong
  candidate and could land on the English page.
- page-meta derives hreflang alternates from the locale registry instead
  of a hand-maintained list, so a new locale can no longer ship without
  its alternates.
- `web/scripts/check-locales.mjs` is a new CI gate: it holds every locale
  dictionary at exact key parity with `en` and fails if a translation
  drops a `{template}` token. Wired into ci.yml and `npm run
  check:locales`.

Gates: `npm test` 168 passed (24 files), `npx tsc --noEmit` clean, `npm
run lint` clean, `node web/scripts/check-locales.mjs` PASS.

Harvested from the v0.9.2 localization lane (#3092, #4749, #4791).
2026-07-27 02:41:03 -07:00
Hunter B 76c232e43d docs(contributors): map fetch URL author alias
Associate the email used on PR #4909 with the contributor existing in the canonical author map so the release credit gate can verify the preserved co-author trailer.
2026-07-26 23:33:55 -07:00
Hmbown e57554ad9a feat(tui): add truthful outbound request manifest
Route /preview-request through the same prepared outbound value used by production Chat, Anthropic Messages, and Responses dispatch. Report typed route, role/lane, requested-to-wire reasoning, catalog/body hashes, and canonical JSON sizes while failing closed on state preview cannot observe.

Add an explicit base-prompt-only disclosure, preserve protected effective system hashes, and represent provider-reported usage as unavailable because preview performs no request. Keep the command human-only and carry current Work-state/fork semantics through the engine refactor.

Harvested from PR #1099 by @GTC2080

Co-authored-by: TaoMu <140309575+GTC2080@users.noreply.github.com>
2026-07-26 23:33:54 -07:00
Hunter B 990489c9bc fix(ci): make web deploy dispatch-only
Align the workflow trigger with the fail-closed deploy preflight so normal pushes and pull requests run validation without creating an impossible deploy job. Pin manual deploys to the dispatched SHA and cover the workflow contract with tests.
2026-07-26 13:57:26 -07:00
Hunter B 4309a7a1e2 ci(link): read the live PR body so a rerun can pass
The check read the body out of the event payload. A rerun replays the payload
the run started with, so the obvious operator move — add the missing line,
rerun the failed check — re-read the old body and failed again with no hint
why, and the only way to go green was an edit that happened to fire a fresh
event. Observed on #4885: the same body failed a rerun at 14:04:36Z and passed
a fresh event at 14:09:10Z.

Fetch the current body through the API instead. The body stays in a variable
and is never interpolated into the script, so it remains untrusted text.
2026-07-26 07:11:12 -07:00
Hunter Bown 3584f189ad Merge pull request #4798 from Hmbown/chore/pr-issue-link
ci: require every PR to close an issue or say why it doesn't
2026-07-26 00:02:35 -07:00
dependabot[bot] 7b01273d65 chore(deps): update dtolnay/rust-toolchain requirement to 2c7215f132e9ebf062739d9130488b56d53c060c
Updates the requirements on [dtolnay/rust-toolchain](https://github.com/dtolnay/rust-toolchain) to permit the latest version.
- [Release notes](https://github.com/dtolnay/rust-toolchain/releases)
- [Commits](https://github.com/dtolnay/rust-toolchain/commits/2c7215f132e9ebf062739d9130488b56d53c060c)

---
updated-dependencies:
- dependency-name: dtolnay/rust-toolchain
  dependency-version: 2c7215f132e9ebf062739d9130488b56d53c060c
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-07-26 00:01:45 -07:00