Commit Graph
4258 Commits
Author SHA1 Message Date
zeekayandHanzo Dev c58a31887c fix(cli/install): verify the published checksum before running the binary
postinstall downloads a binary from a release and executes it. Until now
the only check on those bytes was the file magic — proof that they are an
executable, not proof that they are ours. Every release asset already
ships a sibling .sha256; read it and compare.

The per-user cache is keyed by version number alone, so a binary of
unknown provenance sitting under an already-cached version survived every
reinstall. A cache entry is now trusted only while a stamp beside it
still matches its bytes, and the stamp is written after the published
checksum verified the archive it came from — so a cache hit carries that
proof forward.

Verified against v0.6.100: a tampered cached binary is refused,
re-downloaded, checked and repaired.

Co-authored-by: Hanzo Dev <[email protected]>
2026-08-19 23:18:45 -07:00
zeekayandHanzo Dev 2a026abecb fix(cli/doctor): name the formula, package and binary that exist
doctor is where a user with three installs goes to find out which to
remove, and it was telling them `brew uninstall code` — a formula that
was never published — and to "prefer 'coder'", a name that is not the
canonical one. It also announced itself as "code version".

The guidance now lives in one value so a test can hold it, the way
hanzo_identity.rs holds the defaults. Prose drifts; a value with a test
does not.

Co-authored-by: Hanzo Dev <[email protected]>
2026-08-19 23:18:37 -07:00
zeekay f1e0c3ead1 say Hanzo Git, in the messages people read too
The first pass took the comments. This takes what is left: error strings a
person meets when a build fails, where a word naming no system is worst of all.

Hanzo Git is the product, git.hanzo.ai the address. ("unforgeable" stays.)
v0.6.101
2026-08-19 22:36:28 -07:00
zeekay 2cf1237ce3 read git.hanzo.ai with the token it already issues
FORGE_TOKEN was a hand-provisioned PAT kept as an org-wide Actions secret. Hanzo
Git hands every job a token — checkout writes it into http.extraheader with no
secret involved — so this was a second credential home beside KMS that rotted on
its own schedule and bought nothing.

Now GIT_TOKEN, from github.token.
2026-08-19 22:33:05 -07:00
zeekay b2484da20e say Hanzo Git, which is what it is
"Forge" named nothing in this estate. The product is Hanzo Git, the address is
git.hanzo.ai, and the in-cluster service is hanzo-git.hanzo.svc. A generic word
invented for it sends a reader looking for a system that does not exist.

Comments only. ("unforgeable" stays — different word.)
2026-08-19 22:27:52 -07:00
zeekay ab4e3adfbc chore(release): 0.6.100 [skip ci] 2026-08-19 17:26:16 +00:00
zeekayandHanzo Dev 7d65c52a4e release: publish smokes the binary it is about to ship
The asset check proved names and checksums; nothing proved the bytes
were programs. The linux binary is native to the publish runner, so it
speaks for the matrix: it must print the release's own version and emit
completions before the draft becomes real.

Co-authored-by: Hanzo Dev <[email protected]>
v0.6.100
2026-08-19 09:52:07 -07:00
zeekayandHanzo Dev a63f07ec96 chore(release): 0.6.99, and the publish job downloads bytes, not metadata [skip ci]
Co-authored-by: Hanzo Dev <[email protected]>
2026-08-18 23:31:47 -07:00
zeekayandHanzo Dev 829813d3e9 release: the xwin crate pin stops wearing cargo-xwin's own env var
XWIN_VERSION is cargo-xwin's --xwin-version (the Windows SDK manifest);
a crate version in it kills every msvc build with 'invalid digit found
in string'. The pin is renamed to what it is.

Co-authored-by: Hanzo Dev <[email protected]>
v0.6.99
2026-08-18 22:39:02 -07:00
zeekayandHanzo Dev b388586aed release: five targets from the Linux pool — no Mac in the path
The lane moves off the host that froze under every full build and onto
the pool that already ships hanzoai/cli's five platforms the same way:
darwin cross-linked by zig against a vendored, checksum-pinned MacOSX
SDK, musl natively, windows-msvc through cargo-xwin with LLVM's
clang-cl — five parallel jobs, each uploading its assets into a draft
release, and a publish job that refuses anything short of all 28 before
the release becomes real. The push trigger returns with it: releasing
on merge no longer crashes anyone's machine, because no machine of ours
is special anymore.

Co-authored-by: Hanzo Dev <[email protected]>
2026-08-18 22:33:24 -07:00
zeekayandHanzo Dev 2f8793b275 chore(release): 0.6.98 manifest [skip ci]
Co-authored-by: Hanzo Dev <[email protected]>
2026-08-18 19:31:30 -07:00
zeekayandHanzo Dev b097f192cf chore(release): 0.6.98 [skip ci]
Co-authored-by: Hanzo Dev <[email protected]>
2026-08-18 19:08:42 -07:00
zeekayandHanzo Dev 1ed9ff68bd release: dispatch-only until the runner host stops dying under it
Five freezes in 24 hours, each under this workflow's compile load — at
16 jobs, at 8, with and without the host's rustc wrapper. That is the
machine, not the lane. A push trigger turns every merge into another
crash of the host; dispatch keeps the lane one command away while the
Mac gets diagnosed.

Co-authored-by: Hanzo Dev <[email protected]>
v0.6.98
2026-08-17 16:36:10 -07:00
zeekayandHanzo Dev 06d28475d6 tui: sign-in leads with Hanzo, and the waiting screen holds still
A vendor key exported in the shell picked the provider implicitly, and
the onboarding screen took that as identity: it greeted a fresh user
with "Sign in with ChatGPT" and offered their ANTHROPIC_API_KEY back to
them. An inferred provider is not a decision. Sign-in now leads with
Hanzo IAM unless a provider was NAMED (flag, profile or config.toml),
a completed Hanzo sign-in flips the session onto the account it just
created, and a stored Hanzo session outranks a stray vendor key in the
next launch's implicit pick.

The sign-in waiting screens also stop shimmering: each render scheduled
another frame in 100ms, redrawing the whole terminal ten times a second
for as long as the login took — the "spazzing". A waiting screen is now
a still line, and the shimmer module goes with its last caller.

Co-authored-by: Hanzo Dev <[email protected]>
2026-08-17 15:13:31 -07:00
zeekayandHanzo Dev 1391c0d89e chore(release): 0.6.97 [skip ci]
Co-authored-by: Hanzo Dev <[email protected]>
2026-08-17 14:50:07 -07:00
zeekayandHanzo Dev 73550ed51a release: eight build jobs, because the host dies at full throttle
Three runs, three host deaths, each mid-compile of the final crates.
A release that reliably kills its own runner never finishes; capped
parallelism costs minutes and keeps the machine alive.

Co-authored-by: Hanzo Dev <[email protected]>
v0.6.97
2026-08-17 11:09:06 -07:00
zeekayandHanzo Dev 1c2d6fe91a release: the linker gets file descriptors, not a 256-fd LaunchAgent default
ProcessFdQuotaExceeded, printed in full at last: the thin-LTO link opens
thousands of objects and the runner's shell starts at macOS's default
256. Both prior failures were this error truncated to 'failed to open
object', which read as a torn cache and then as a zig defect. The limit
is raised at the top of the build; the zig pin stays as hygiene.

Co-authored-by: Hanzo Dev <[email protected]>
2026-08-17 10:40:41 -07:00
zeekayandHanzo Dev df299071fb release: zig is pinned at 0.16.0, not whatever the host bootstrapped
The musl targets fail deterministically under the runner's zig 0.14.1 —
its linker cannot open the thin-LTO objects a clean rebuild writes — and
the install step skipped itself whenever any zig existed, so the host
could never heal. 0.16.0 is the version the local release was proven on;
it is now installed versioned and preferred regardless of host state.

Co-authored-by: Hanzo Dev <[email protected]>
2026-08-17 08:50:36 -07:00
zeekayandHanzo Dev 1b0fda00ee release: a torn cache earns a scrub and one retry, not a red run
The shared target dir is what makes a release incremental, and a run
killed mid-write tears objects in it — the next run then fails at link
on a corrupt .rcgu.o, which is what took 78767 down after the host died.
A failing target now clears its own cache and gets one fresh chance.

Co-authored-by: Hanzo Dev <[email protected]>
2026-08-17 07:33:17 -07:00
zeekayandHanzo Dev 18b0b13a66 chore(release): 0.6.96 lockfile [skip ci]
Co-authored-by: Hanzo Dev <[email protected]>
2026-08-16 21:51:35 -07:00
zeekayandHanzo Dev 2d80aa0d7d chore(release): 0.6.96 [skip ci]
Co-authored-by: Hanzo Dev <[email protected]>
2026-08-16 19:32:37 -07:00
zeekayandHanzo Dev 537e08861e release: outlast the slow day, and unwrap the host's rustc cache
The first full run died at the 170-minute budget four targets in, killed
mid-link with nothing published. The budget now covers the slow day; the
host's wedging rustc cache wrapper is switched off for the job — every
wedge was a killed daemon and an uncached retry, slower than no cache.

Co-authored-by: Hanzo Dev <[email protected]>
v0.6.96
2026-08-16 18:14:01 -07:00
zeekayandHanzo Dev d7a7da530b release: thin LTO — five targets on one Mac, not five hours
Fat LTO with one codegen unit spent ~30 minutes linking each of the five
release targets, so a release took the runner most of three hours. Thin
LTO builds the same target in a third of that for a few percent of size.
release-prod keeps the fat profile for a deliberate small build.

Co-authored-by: Hanzo Dev <[email protected]>
2026-08-16 16:38:47 -07:00
zeekayandHanzo Dev c176bf737b tui: the plain look — no header, no frame, no gutter
The chat surface is the one the 0.6.8x builds had: `>_ hanzo dev (vX)`
and the question, the transcript flush against the edge, the composer a
line with its running status on the row above, "What would you like to
work on?" as the greeting. The status bar, the composer frame, the
gutter and its icons, and the block-letter splash are gone; the merge
that brought them in is what this walks back, on top of the current
TUI.

While here: the free-pool notice is decided by the configured run — the
Hanzo provider on the pool's model — not by which key happens to be in
the environment, so a run against another provider no longer announces
itself as free; the trust screen names Hanzo Dev, not Code.

Snapshots follow the look. Tests that read the gutter for meaning now
read the record (mid-turn state) or the exec label ("Running..."), and
the spacer hysteresis test derives its viewport heights from the
transcript instead of assuming the tall splash.

Co-authored-by: Hanzo Dev <[email protected]>
2026-08-16 15:59:31 -07:00
zeekayandHanzo Dev 6b1bf8748a release: only vX.Y.Z tags count toward the next version
Co-authored-by: Hanzo Dev <[email protected]>
2026-08-16 15:00:30 -07:00
zeekayandHanzo Dev 730e22c429 core: keep MCP tools whose optional arguments carry a null arm
The Hanzo MCP server spells every optional argument as
`anyOf: [T, {type: null}]`, and the schema sanitizer let the null arm
through to a parser that only knows six types — so `hanzo code` attached
twenty tools and dev dropped every one at the door with "unsupported JSON
schema type null". The null arm says nothing about a value the model may
send; drop it, keep T, and a bare `type: null` reads as a string.

The coder prompt now speaks as Hanzo Dev rather than a community fork, and
says how an app starts: find the open-source project to fork first, then
write only what does not exist.

Co-authored-by: Hanzo Dev <[email protected]>
2026-08-16 14:58:40 -07:00
zeekayandHanzo Dev 6c7c3d3af4 release: one job on the Mac runner ships all five targets
The GitHub Actions lane was dropped and nothing replaced it, so v0.6.95 was
tagged and never published; npm and every installer still hand out 0.6.94.
The reason given — no runner for four of the five targets — is not true of a
Mac: it builds darwin natively, both linux-musl through cargo-zigbuild and
windows-msvc through cargo-xwin, all verified from this machine. So the
release is .hanzo/workflows/release.yml on the dbc-metal host runner, one
job, every push to main: build, GitHub Release + forge release, npm, Homebrew,
then the bump commit and tag. hanzo_identity guards the new file.

Two things found while proving it end to end:

- `dev login` on the Hanzo path died on a Cloudflare 502 page mid-poll —
  "unexpected token response: <!DOCTYPE html>". A body that is not an OAuth
  error is the edge, not the issuer; keep polling and let the device code's
  lifetime end it.
- The troubleshooting link in agent_tool still pointed at just-every/code.

Merges the forge's 0faa6fe so both remotes share one history; the blob-size
gate it ported into hanzo.yml stays.

Co-authored-by: Hanzo Dev <[email protected]>
2026-08-16 14:51:31 -07:00
zooqueen d70acafded dev answers without an account, on the free pool
Installing dev and running it got you a sentence telling you to go get a key.
The gateway will answer without one — the free pool costs nothing to serve — so
the first run now asks it instead of refusing.

The credential and the model move together, because either alone is broken: the
free key may only ask for a route that costs nothing, and a coding model asked
with it is refused. `free` is the pool's own id rather than a vendor `:free`
one, so the routes underneath can be retired without reaching this binary.

An account still wins wherever both exist, and a build with no free key behaves
exactly as it did before — the refusal it used to give is what remains when
there is nothing to ask with.

The TUI stopped offering to sign the user in to OpenAI on the way past. It was
reading auth.json alone, so a Hanzo bearer — the one `hanzo code` sets on the
child, and now the free one — looked like no credential at all.
2026-08-14 23:02:45 -07:00
zeekay 27a7c41c22 drop the GitHub Actions lane
Mirror of git.hanzo.ai/hanzoai/dev@841bd7d, applied here directly because
the push mirror cannot fast-forward this history.

CI for this repo runs on the forge, from .hanzo/workflows. The
blob-size policy moved into hanzo.yml; the release, upstream-merge,
preview-build and issue-automation workflows were dropped. The forge
commit carries the full reasoning and what each drop cost.
2026-08-13 23:47:05 -07:00
zeekay 0faa6fe918 drop the GitHub Actions lane; keep the blob-size policy
Every file here was already dark on the forge. This repo has
.hanzo/workflows, so the forge reads that directory and only that one —
251 runs, all cicd.yml — and nothing under .github/workflows has run here
since it landed.

Kept, ported into hanzo.yml: blob-size-policy. The fork added it on
purpose and it is the one gate in the directory that asks a question
answerable without GitHub. It compared HEAD^1 to HEAD^2 — GitHub's
synthetic merge commit, which only exists for a pull_request run — so it
now takes merge-base against origin/main, which resolves the same range
on a PR and to a no-op on a push.

Dropped, and what each cost:

  release.yml — the real loss. It published @hanzo/dev and five
    per-platform binary packages to npmjs plus a GitHub Release.
    Four of the five targets (both darwin, windows-msvc, linux arm64)
    need a runner this fleet does not have, so a port would publish one
    fifth of a release under a full version number. There is no
    automated release for the dev CLI now; hanzo.yml says so where
    someone will read it.
  release-npm-recovery.yml — manual re-publish of the same packages.
    Goes with it.
  upstream-merge.yml — merges upstream and opens a PR through the GitHub
    API. It was also failing 62 of its last 63 runs on GitHub.
  preview-build.yml — builds PR binaries and posts a link as a PR
    comment. No comment surface here.
  issue-triage.yml, issue-code.yml, issue-comment.yml — issues,
    issue_comment and repository_dispatch events driving actions/github-
    script against the Issues API. None of that exists on this forge.
  rusty-v8-release.yml, v8-canary.yml — bazel V8 builds across macOS,
    Windows and Linux, publishing to a GitHub Release.
  rust-release-argument-comment-lint.yml — on: workflow_call, and
    nothing in the tree calls it. Orphaned.
  README.md — described the strategy for the workflows above.

.github/blob-size-allowlist.txt and .github/merge-policy.json stay; only
workflows/ went away.
2026-08-13 23:44:28 -07:00
GitHub Action 5827346e8b Merge origin/main: adopt remote workflow changes; keep release changes [skip ci] 2026-08-08 17:21:44 +00:00
GitHub Action 7502aae9ba chore(release): 0.6.95 [skip ci] 2026-08-08 17:21:41 +00:00
GitHub Action f53e3c881d Merge origin/main: adopt remote workflow changes; keep release changes [skip ci] 2026-08-08 16:48:39 +00:00
GitHub Action 5aab47d1ed chore(release): 0.6.95 [skip ci] v0.6.95 2026-08-08 16:48:34 +00:00
zeekay 6dbfa82403 the key you already hold picks the provider
A coding agent should work with whatever credential is in the environment
rather than insisting on ours. It insisted: with no explicit choice the
provider defaulted to hanzo unconditionally, so someone holding only an
ANTHROPIC_API_KEY was told to go and get a Hanzo key before anything would run.

provider_from_env answers only after a flag, a profile and config.toml have all
declined — it is the last link in that chain, never an override. Hanzo first,
because it is the default and the one we serve; then a key that names its own
vendor. An empty or whitespace value is not a credential.

With NO key the answer is still hanzo, deliberately: that is the provider whose
env_key_instructions say how to sign in, and an empty environment is exactly
when someone needs to read them.

Anthropic was not reachable at all — zero mentions in the tree. It is built in
now through its OpenAI-compatible surface, so it needs no new wire format: a
base URL and a key. The native Messages API is a different shape and is
deliberately not spoken.
2026-08-08 09:19:01 -07:00
zeekay eb49cac620 name the env after the product, and the key after the stack it opens
457 sites carried an upstream prefix into every surface a user reaches — shell
exports, docs, CI, the SDK. CODEX_ is not our name and it was never going to
stop arriving on its own: it is what upstream writes, and every sync brings more.

Two namespaces, because they answer different questions.

  DEV_*            the app's own configuration — DEV_HOME, DEV_PROFILE, the rest
  HANZO_API_KEY    a credential for the Hanzo stack, which is not app config

CODEX_API_KEY held the literal string "CODEX_API_KEY", so the rename moves the
value and not just the constant. It becomes HANZO_API_KEY, which is what
create_hanzo_provider already reads through HANZO_MACHINE_ENV_KEYS — one name
for one credential instead of two spellings of it.

vendor/ is untouched, which is the point of vendor/: upstream code keeps
upstream names, and the boundary is a path rather than a habit.
2026-08-08 09:14:56 -07:00
zeekay db4e57be1f dev: ship @hanzo/mcp with it
`dev` launches hanzo-mcp by name (mcp_servers.hanzo.command="hanzo-mcp"), and
until now that binary had to arrive by some other route — the sandbox image
fetched it separately, and a plain `npm i -g @hanzo/dev` got an agent that
names a server it cannot start. Declaring the dependency makes the pair one
install.
2026-08-08 05:38:25 -07:00
GitHub Action 90c7c2d67a chore(release): 0.6.94 [skip ci] v0.6.94 2026-08-08 06:41:41 +00:00
zeekay c42d954ea4 fix the two preflight failures I pushed
The Auto Drive routing test asserted the gpt-5.5/gpt-5.4-mini defaults I had
just replaced, and the sync moved app-server-protocol/v2 without regenerating
the vendored schema fixtures, so MultiAgentVersion.ts was missing.

Both were visible only by running the suite. I ran hanzo_identity and the TUI
tests and pushed on that, and `make check` compiles test targets without
running them — neither is the gate CI applies.
2026-08-07 22:56:51 -07:00
zeekay 9fc17e3bbe make check: compile the test targets, which build does not
The release preflight runs `cargo test --no-run --locked` and has now failed
twice on a test file that does not parse. `make build` links binaries, so it
never touched that file and reported success both times — the break was only
visible after a push.
2026-08-07 22:28:05 -07:00
zeekay 57ca4264e2 core: a struct field is not a statement — drop the one that landed in a fn body
The regex that added alt_env_keys matched `ModelProviderInfo {` at the end of a
line, and that spelling occurs twice: the struct literal, and the SIGNATURE of a
function returning one. So `fn provider_for(...) -> ModelProviderInfo {` got a
struct field as its first statement, and the same test target failed again — a
different error at the same address, which is easy to read as "the fix did not
land" rather than "the fix landed badly".

I also let a local `cargo test --no-run` be killed by my own timeout and pushed
without it. The compile was the check, and I shipped the unchecked version.
2026-08-07 22:00:19 -07:00
zeekay 6bdfb2a4fa add a Makefile, so make builds the thing that ships
The justfile sets working-directory to the vendored tree, so `just codex`
builds a binary nobody installs. This targets code-rs and delegates every
target to build-fast.sh, so there is still one build and one cache — and
`make install` puts dev on PATH with code beside it as the alias it is.
2026-08-07 21:52:09 -07:00
zeekay e45a1532a5 follow the vendored tree to its new path
The move to vendor/ left four references behind. check-codex-path-deps.sh
hard-failed every build ("Expected both code-rs/ and codex-rs/"), and the
auto-review scope excluded a prefix that now matches nothing — so all 5,624
vendored files were eligible for review context. That exclusion is vendor/
now, which covers whatever else we vendor later.
2026-08-07 21:52:03 -07:00
zeekay 901a81abe9 docs: describe this product, and only what it can do
The docs read as OpenAI's Codex CLI: a getting-started page titled for it,
`codex --enable skills` and `code sandbox macos` for commands that do not
exist, defaults given as gpt-5.1-codex-max/openai when they are
zen5-coder/hanzo, a Homebrew page describing a formula we do not publish.

Removed three tui-stream-chunking notes and the execpolicy page: they
document modules and a subcommand that live only in the vendored upstream
copy. There is no execpolicy subcommand and no .codexpolicy loader in
code-rs; the page told users to run something the binary does not have.

Rewrote tui-alternate-screen against the source. It described an
auto/always/never enum and a --no-alt-screen flag; the shipped behavior is a
tui.alternate_screen bool with Ctrl+T, which replays the transcript into
scrollback on the way out — a better answer to Zellij than the one written
down. Genuine openai-provider documentation stays.
2026-08-07 21:51:19 -07:00
zeekay b3de714dec auto drive: point at models the Hanzo Cloud serves, and guard it
Auto Drive defaulted to gpt-5.1 and routed between gpt-5.5 and gpt-5.4-mini.
api.hanzo.ai answers all three with 400 model is not available, so on the
default provider the feature was not mis-labelled — it was broken.

The seed also read auth mode alone. A Hanzo device login persists as
AuthMode::ChatGPT, so it handed our own gateway an OpenAI id; the provider
decides now, matching the rule the default model already followed.

hanzo_identity gains three assertions, because the identity table it guards
was never the thing that regressed — rendered text was, and nothing looked
at it. Each one was checked by breaking the code it guards and watching it
go red: the Homebrew formula, the Auto Drive defaults, and the first screen
a new user sees.
2026-08-07 21:51:09 -07:00
zeekay 23b29ae484 model: offer the models we actually serve, in the order we mean
/model listed seventeen OpenAI presets and no Hanzo one, so the model dev
runs by default was not selectable in the view whose job is selecting it.
Adds the Zen and enso lineup from the catalog — ids and context windows read
from /v1/models, not guessed.

Two things had to go first, both of which re-derived order from the slug:

model_selection_view parsed a version out of `gpt-N.M`; everything else fell
to a branch that sorted it below every OpenAI model, so declaring zen5-coder
first would still have placed it sixth. chatwidget hoisted a hardcoded
five-slug shortlist to the front regardless of catalog order.

Both deleted. Order is the catalog's job now, decided once, and a test holds
the picker to leading with our default. The OpenAI presets stay: they serve
the openai provider as its offline fallback and for effort clamping.
2026-08-07 21:50:59 -07:00
zeekay 383f8e92a9 login: sign in to Hanzo, over the standard device grant
The default provider is hanzo, yet the first screen offered a ChatGPT plan
and the only device flow spoke OpenAI's proprietary /api/accounts/deviceauth.
This ports the RFC 8628 device grant into code-rs — the workspace that ships;
the earlier attempt landed in the vendored mirror, where it ran for nobody.

Routing keys off model_provider_id, not a new flag: the config already
carries the one notion of provider. openai keeps device_code_auth.rs
untouched, and every branded string is provider-conditional, so that path
renders exactly what it did before.

The client is hanzo-cli. hanzo-app answers "client authentication failed" —
it is confidential, and a CLI cannot hold a secret. Sibling brands need a
public <org>-cli client provisioned before the issuer override is useful.

One row, not two: the Hanzo browser loopback is not provisioned
(invalid redirect_uri), and a row promising hanzo.id that opened
auth.openai.com would be a lie. The device grant covers headless anyway.
2026-08-07 21:50:49 -07:00
zeekay ad27f9279c tui: say our own name where the product speaks
`brew upgrade code` names no formula — ours is hanzo-dev — and the TUI ran
that string, it did not merely print it. The rest is copy the product says
about itself: the approval line on every command, the update pane, /limits,
the theme and spinner pickers, `dev exec --help`.

The model-migration prompt kept its mechanism, since our own catalog can
declare a successor through it, but loses the GPT marketing and the three
openai.com links it showed on first run.

Dropped format_model_name: it rewrote only `gpt-` slugs, so for a Hanzo
model it was a no-op wrapped around someone else's brand. The status line
now shows the model id the user configured — the only name we can vouch for.
2026-08-07 21:50:38 -07:00
zeekay 25f1f1da4f vendor: upstream lives under vendor/, so ours is what is left
codex-rs/ is a read-only mirror of openai/codex that just-every refreshes and
we never edit. It sat at the repo root next to code-rs/, the product, and the
only thing separating them was that everyone knew. Nothing checked it.

That knowing is what makes branding endless. There are ~400 upstream-brand
literals in code-rs today and ~224 of ours, hand-placed on the same lines the
sync delta lands on, so every sync re-fights the same 17 files. You cannot fix
that while the line between "theirs" and "ours" is a convention.

vendor/codex/ makes it a boundary. Everything under vendor/ is upstream: never
branded, never edited, replaced wholesale on sync. Everything outside it is
ours and must carry our name — which is now a question a test can ask.

code-rs coupled to the mirror through exactly one line, an include_str! of
models.json, and it still does. The other 17 files are path strings.

Syncing changes by one sed: just-every's delta names codex-rs/, so rewrite the
patch paths to vendor/codex/ before applying it.
2026-08-07 21:22:34 -07:00
zeekay 68d83e82e6 core: the four test literals that have failed three releases
alt_env_keys was added to ModelProviderInfo so a sandbox run can present a
machine credential instead of a human session. Three construction sites were
updated. These four are in TEST targets, and `cargo check` does not compile
those — so it printed nothing, I read nothing as clean, and every release since
has died in preflight on E0063.

A check that cannot see test targets cannot clear a change to a public struct:
literals must name every field, so ADDING one breaks every construction in the
workspace, including those only `cargo test --no-run` compiles.

Vec::new() rather than a Default on the struct — a #[serde(default)] field still
has to be written in a literal, and a Default would let the next new field land
silently in tests that should have been made to state it.
2026-08-07 21:21:19 -07:00