Commit Graph
14 Commits
Author SHA1 Message Date
zeekay bb6928a7d7 sync: update OpenAI mirror and Just Every product changes
Mirror openai/codex c308ffb36 exactly under vendor/codex. Apply the code-rs delta from just-every/code 7d59424890 to af789f51a, retaining Hanzo defaults, authentication, branding, and vendor paths. Give the compatibility code binary its own entry file to eliminate duplicate-target warnings.

Validated: BUILD_FAST_BINS="dev code" ./build-fast.sh, both binary versions, shell completion, and interactive Hanzo TUI startup.
2026-09-06 02:28:40 -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 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 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 418d57f390 feat(tui,cli): the product says Hanzo Dev, not Code
The complaint was that the CLI and TUI still look like codex. They did, but
almost none of it was the word "ChatGPT" — the shipping tree has 69 of those
and most must stay, because they name a real OpenAI account the user actually
holds and renaming them would lie about whose login it is. What made it look
wrong was our own chrome naming itself after someone else's product.

The startup splash was the biggest piece and the one a ChatGPT/Codex grep can
never find: the ASCII art spelled EVERY over CODE — just-every's brand, not
ours. It now spells HANZO over DEV in all four size variants. While rewriting
it, `shift_left(lines, 3)` turned out to strip the first three space characters
anywhere in a line rather than three leading columns; that was invisible while
every line began with three spaces, and HANZO's first row does not. Replaced
with art written at final column positions, and the three near-duplicate
per-size word blocks collapsed into one HANZO array plus a word_lines() helper.
Added two tests for invariants nothing enforced before: declared art height
matches the line count, and each variant fits its own minimum width.

Also deleted a branding band-aid. The /help renderer ran
`cmd.description().replace("Codex", "Code")`, post-processing help text at
display time, which meant any rename that only edited slash_command.rs would be
silently mangled and "Hanzo" could never appear. Removed it and fixed the
source strings instead.

Renamed, because they name us: terminal window title, the DEFAULT_TERMINAL_TITLE
const, the desktop notification title, the assistant's label in the undo preview
("Dev", to stay balanced against "You"), the welcome banner and onboarding copy,
five slash-command descriptions, the settings-overlay upgrade line, the model
migration prompts, the `dev --help` config-override text, and `dev mcp add`.

Kept, because they name a real service or a wire contract: every "Sign in with
ChatGPT" / "your ChatGPT account" string, OPENAI_API_KEY, chatgpt.com and
openai.com URLs, OpenAI model ids including gpt-5.1-codex-max, the ~/.code/ and
~/.codex/ config paths, all CODEX_*/CODE_* env vars, config keys, OAuth client
ids, and the internal Line::from("codex") sentinels that pair with the
is_title_line matcher and are never rendered.

One upstream announcement was reworded rather than renamed: "Codex just got an
upgrade: meet gpt-5.1-codex-max" now names the model instead of the product,
since the model is real and ours is not the product being upgraded.

Verified: cargo nextest run --no-fail-fast --locked -> 1673/1674 pass. The one
failure, code-core git_info::test_collect_git_info_with_remote, is this machine's
`[email protected]:.insteadof https://github.com/` rewriting the test's URL; it
passed on CI run 31143152415.
2026-08-06 20:58:49 -07:00
zeekayandHanzo Dev daf458296f fix(tui): the header said "Every Code"; three upstream tests assumed OpenAI
The TUI header literal came across in the merge as upstream's own product
name. That is the most-looked-at string in the program:

  code-rs/tui/src/chatwidget.rs  "Every Code" -> "Hanzo Dev"

Regenerating snapshots proves the blast radius exactly — 34 snapshot files
changed, and the whole diff is 46 title lines plus 6 lines where the settings
overlay now reads "Model: ZEN5-Coder" instead of "Model: GPT-5.5". Nothing
else moved, which is the point of running them.

Two more prompts the .md sweep could not see because they live in Rust:
DEFAULT_PERSONALITY_HEADER (prepended to BASE_INSTRUCTIONS whenever a
personality is set, and it asserted "based on GPT-5" even for zen5-coder),
and the sample skill's restart hint.

Three tests arrived with the merge asserting upstream's defaults. Each is
given the provider or model it actually means to exercise, rather than having
its assertion weakened:

  app-server get_auth_status  - requires_openai_auth is false for the `hanzo`
                                provider, so the ChatGPT branch is dead by
                                design. Test now names `openai`.
  tui context_mode override   - 272k is the GPT-5 window; zen5-coder has none.
                                Test now names `gpt-5.5`.
  cli bash completion         - asserted `_code()` while CLI_COMMAND_NAME has
                                been "dev" since the rename. This one was red
                                before the merge too. Now asserts our name.

LLM.md's claim that codex-rs changes nothing a user runs was false until this
merge — `dev` used to compile ten crates out of it. Upstream finished the
migration; recorded what is actually left (one models.json via include_str!).

  cargo test -p {code-core,code-tui,code-cli,code-app-server,
                 code-exec,code-mcp-server,code-protocol} -- --test-threads=1
  1310 passed; 1 failed

The one failure is git_info::test_collect_git_info_with_remote, which asserts
a literal https remote. This machine rewrites it:

  [email protected]:.insteadof https://github.com/

  $ GIT_CONFIG_GLOBAL=/dev/null cargo test -p code-core --lib -- \
      git_info::tests::test_collect_git_info_with_remote
  test result: ok. 1 passed; 0 failed

Co-authored-by: Hanzo Dev <[email protected]>
2026-08-06 00:08:26 -07:00
zeekayandHanzo Dev 23a7fe1109 feat: the product says its own name, and can be driven from outside
Branding. The reported "OpenAI Codex" was not a banner — the TUI banner has
said "Welcome to Code" all along. It was the model describing itself. Every
request carries BASE_INSTRUCTIONS, and `zen5-coder` matches none of the
OpenAI slug prefixes in find_family_for_model, so it lands on
derive_default_model_family -> core/prompt.md, whose first line read "You are
a coding agent running in the Codex CLI ... led by OpenAI". The agent was
told who it was, and it answered honestly.

Fixed the harness identity in all eight prompts (keeping each model's own
identity: "based on GPT-5" stays, the harness around it becomes Hanzo Dev),
the per-turn header, approval and model pickers, the login success page, MCP
tool titles and approval prompts on both client and server sides, seatbelt
policy header, cloud copy, two stale User-Agents, and the CLI hints that
named the wrong binary. Golden JSON fixtures moved with the code they assert.

Deliberately NOT changed, because they are wire and not text: `OPENAI_*` and
`CODEX_*` env vars, the `codex`/`codex-reply` MCP tool names and the
`code-mcp-server` server name (hosts key allowlists off them), `codex.*` OTEL
event names, the `openai` provider id, model slugs, `~/.code` on disk, and
the `https://api.openai.com/auth` JWT claim namespace.

Control. `cli/src/proto.rs` was a complete bidirectional control plane —
Submission JSON lines in, Event JSON lines out, the whole `Op` set including
QueueUserInput — exported from lib.rs with no subcommand to reach it. Wired
it up as `dev proto`. That is the difference between interrupting a turn and
steering one: `app-server`'s sendUserMessage hardcodes Op::UserInput, which
calls sess.abort() and restarts the turn.

  $ printf '%s\n' '{"id":"s1","op":{"type":"interrupt"}}' \
                  '{"id":"s2","op":{"type":"shutdown"}}' | dev proto
  {"id":"","event_seq":0,"msg":{"type":"session_configured",
   "session_id":"4d82071e-...","model":"zen5-coder",...}}
  {"id":"s2","event_seq":1,"msg":{"type":"shutdown_complete"}}

Also: upstream-merge.yml polled openai/codex every 30 minutes. That is the
wrong upstream (codex-rs reaches us through just-every) and a cron cannot
work against a disjoint history anyway — it needs a hand-supplied merge base.
Retargeted to just-every/code and made it manual, pointing at the procedure
in LLM.md. Purged @just-every/code from the release and recovery pipelines,
which would otherwise have published our binaries under their scope.

Co-authored-by: Hanzo Dev <[email protected]>
2026-08-05 23:28:50 -07:00
zeekayandHanzo Dev dc13f1609d fix(merge): restore the identity the merge reverted, and the fields it added
Three regressions the merge introduced, all caught by building and running:

- `core/src/model_provider_info.rs` — upstream added `auth`,
  `experimental_bearer_token` and `websocket_connect_timeout_ms` to
  ModelProviderInfo; the Hanzo provider now sets them (None: our bearer comes
  from HANZO_USER_KEY, not a command, and the websocket default is fine).
  This was the only compile error in 7004 changed files.
- `core/src/config.rs` — the default provider fallback had reverted to
  "openai". Back to HANZO_PROVIDER_ID. This one is the whole product.
- `cli/src/main.rs` — the entire clap identity had reverted: `--help` printed
  "Codex CLI" and `Usage: code`. Restored name/bin_name = "dev", the about
  line, subcommand help, and the doctor/preview/login hints (17 sites).
- `tui/src/updates.rs` — the in-product upgrade hint had reverted to
  `npm install -g @just-every/code@latest`, which would send our users to
  someone else's package.

`core/tests/hanzo_identity.rs` needed one call-site update for upstream's new
`built_in_model_providers(Option<String>)` signature; it then caught nothing
further, which is the point of it.

  cargo test -p code-core --test hanzo_identity
  4 passed; 0 failed

Co-authored-by: Hanzo Dev <[email protected]>
2026-08-05 23:17:49 -07:00
zeekayandHanzo Dev 6cbbea2d03 merge: just-every/code v0.6.169 (e4fe007150) — keep Hanzo identity
Our history is just-every's with author emails rewritten, so the graphs are
disjoint and git finds no merge base. Supplied one by hand: d1f1f51a41, the
just-every commit matching our Oct-2025 fork point (22 files apart). 9618
upstream commits, 7004 files, +1.81M/-159k, 37 conflicts.

Resolution:
- Upstream code where our side was the Oct-2025 prototype of a feature they
  have since reimplemented 3-5x larger (agent_runs, browser_sessions,
  history_cell/{agent,browser}, the vt100 harness and its snapshots).
- Upstream's config.rs module split (builder/defaults/sources/validation)
  kept; zen5-coder and the provider-follows-model rule re-applied on top.
- Ours where the file IS the identity: README, package.json, postinstall,
  release notes pipeline, integration-zed.
- Hybrid where upstream improved a file we had branded: updates.rs (their
  release-repo migration, our hanzoai/dev), release.yml (their fail-fast npm
  auth check, our package name), chatwidget.rs (their turn handling, our
  HANZO_USER_KEY hint), exec human output (their 237 lines, our banner).

Superseded and dropped deliberately: our resume_command_name() coder-alias
hack — upstream's derive_resume_command_name() reads the invocation basename
generically, which yields "dev" for us.

LLM.md now records the real topology and the sync point; AGENTS.md and
CLAUDE.md are symlinks to it again. Single parent on purpose: adopting
jecode/main as a second parent would re-import 13,742 commits carrying the
upstream author emails a prior rewrite deliberately removed.

Version 0.2.188 -> 0.2.189.

Co-authored-by: Hanzo Dev <[email protected]>
2026-08-05 23:09:12 -07:00
zeekayandHanzo Dev d3d1dfa1d3 dev is ours: the Hanzo Cloud by default, a binary named dev, our namespaces
hanzoai/dev went public defaulting to someone else's cloud. Four things were
wrong, and all four now have a test that fails if they come back.

DEFAULT PROVIDER AND MODEL. built_in_model_providers() gains `hanzo` -- the
Hanzo Cloud at api.hanzo.ai/v1, Responses wire, bearer from HANZO_USER_KEY --
and it is the default. The default model is zen5-coder. This was not cosmetic:
the old default is not in the gateway catalog, so it 400s against our own
cloud. Measured, not assumed:

  POST api.hanzo.ai/v1/responses model=gpt-5-codex -> 400 "model is not
      available. Use GET /v1/models to list available models"
  POST api.hanzo.ai/v1/responses model=zen5-coder  -> 200, clean output

Our own CLI already documented the bug from the other side -- dev.rs says
"Name the model too -- codex's built-in default is not in the gateway catalog
and would 400" and passes `-c model=` on every launch to work around it. It
also asserts that on the native gateway NO model_provider override is needed,
which is only true once `hanzo` is the built-in default. It is now.

zen5-coder over enso because dev is a coding agent and because enso returns
system-prompt text on the Responses wire that dev actually speaks; zen5-coder
returns the answer. Model ids were read from GET /v1/models with a bearer, not
guessed. Other providers stay fully configurable -- this is the default, not
the only choice.

THE LOGIN COMMAND. Messages said `code login` / `codex login`. The real command
is `hanzo auth login` (`hanzo login` is not a command -- it is swallowed as an
AI task). It now lives once, as auth::LOGIN_COMMAND, so no message can drift
into naming a command that does not exist. References to this binary's own
subcommand became `dev login`.

A BINARY NAMED dev. HEAD built `code` and `codex` and nothing named `dev`, so a
release cut today would ship no `dev` -- and `hanzo code` launches a bare `dev`
off PATH, so every new install would break. `dev` is now the canonical bin,
declared first; `code` remains as an alias to the same program, never the
reverse. The CLI identifies as `dev` / "Hanzo Dev", not "OpenAI Codex".

OUR NAMESPACES. The pipeline published to @just-every/* on npm and pushed
formulae to just-every/homebrew-tap. Both of ours already exist and are already
populated at v0.6.91 -- @hanzo/dev plus all five @hanzo/dev-<target> packages,
and hanzoai/homebrew-tap's Formula/hanzo-dev.rb, which installs `dev` and
expects assets named dev-<triple>. Nothing here is squatted; this is our own
distribution, reclaimed. Assets are renamed to match the formula.

Two live supply-chain bugs fell out of that, both worse than a naming problem:
postinstall.js (runs on every npm install) and the tui auto-updater fetched
from a third party's releases -- the updater also told our users to
`npm install -g @just-every/code@latest`. Worse, a shadowed `isWSL` const put
the two fast paths in the temporal dead zone, so their catch blocks swallowed
the error and EVERY install fell through to that download: the five published
platform packages were never used, and the third-party fetch was not an edge
case but the only path that ran. Fixed and exercised in a sandbox across all
three paths. codex-cli/.pack/ -- a committed `npm pack` artifact CI
regenerates, and the reason the bad URL had two homes -- is now untracked.

DURABILITY, because upstream-merge.yml merges openai/codex every 30 minutes.
A one-time edit to a default is a suggestion that survives until the next
merge. Two mechanisms:

  - .github/merge-policy.json prefer_ours_globs listed only codex-rs/** while
    the workspace that SHIPS is code-rs/**, so it protected nothing that
    ships. The identity-bearing code-rs files are now listed.
  - code-rs/core/tests/hanzo_identity.rs asserts all four properties -- the
    provider, a Zen default, a bin named dev, and no third-party publish
    target. Upstream has no such file, so a merge cannot conflict with it or
    carry the guard away with the thing it guards. Policy can be edited;
    a red build cannot be ignored.

The gate is not decorative: it failed on the un-retargeted pipeline
("release.yml still references `@just-every/`") and went green only when the
pipeline was actually fixed.

Verified: cargo build --bin dev clean; hanzo_identity 4/4; code-core lib
332 passed, 1 failed -- git_info::test_collect_git_info_with_remote, which
fails identically on a clean origin/main checkout here because this machine
has a global [email protected]:.insteadof rewrite. Pre-existing and
environmental, not from this change.

  $ dev exec "say OK"        # fresh profile, no config
  Hanzo Dev v0.0.0
  model: zen5-coder
  provider: hanzo

Co-authored-by: Hanzo Dev <[email protected]>
2026-08-01 14:05:00 -07:00
James Peter 8d138ed9bd UX: match resume hint to coder alias 2025-10-07 21:12:35 +10:00
James Peter ab3d651a23 test: run nextest in release and harden smokes 2025-10-06 16:26:26 +10:00
James PeterandHanzo Dev 7deab83fc3 chore: complete legacy test retirement and upstream crate adoption
This commit completes Phase 1 of the codebase cleanup plan documented in
ROADMAP.md and related migration documents.

Major changes:
- Removed legacy test suites from code-rs/ crates (~35,000 lines)
- Adopted upstream codex-mcp-client and codex-responses-api-proxy
- Deleted TUI compat layer, agent task planning docs, and orphaned modules
- Updated documentation to reflect current state and future phases

Test Coverage:
- Deleted tests from: app-server, apply-patch, chatgpt, cli, core, exec,
  login, mcp-server
- Documented 9 remaining coverage gaps requiring new tests (see
  docs/migration/legacy-tests-retirement.md)
- Preserved smoke test infrastructure in tui/tests/ui_smoke.rs

Crate Adoptions:
- mcp-client: Now re-exports codex-mcp-client with fork-specific buffer config
- responses-api-proxy: Now re-exports codex-responses-api-proxy with minimal
  wrapper
- mcp-types: Updated to use upstream types where possible

TUI Cleanup:
- Removed compat.rs ratatui adapter layer
- Deleted obsolete modules: app_backtrack, custom_terminal, scroll_view,
  text_block, transcript_app
- Archived agent_tasks/ planning docs to docs/archive/

Documentation Updates:
- ROADMAP.md: Marked Phases 1-2 complete, updated next actions
- TEST_SUITE_RESET.md: Documented Phase 1 completion
- DEAD_CODE_INVENTORY.md: Updated with deletion outcomes
- Added docs/migration/legacy-tests-retirement.md with 6-week plan
- Added docs/maintenance/prompt-architecture.md

Next Steps (Phase 2-3):
- Port critical test coverage (9 test files identified)
- Expand smoke test scenarios
- Continue upstream tracking per monthly cadence

See docs/migration/ for detailed migration status and roadmap.

Co-authored-by: Hanzo Dev <[email protected]>
2025-10-06 05:15:48 +10:00
James Peter 220a6b3b9c feat(code-rs): add forked workspace and dual build support 2025-10-05 04:27:49 +10:00