9 Commits
Author SHA1 Message Date
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
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 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 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
zeekayandHanzo Dev 0a1b157d2c feat(exec,app-server): a real JSON contract, and steering that does not abort
Three things the last pass left flagged. Two are done; the third turned out to
belong somewhere else and is reported rather than forced in.

## exec --json emits the schema instead of the SDK guessing it

`exec_events.rs` and `experimental_event_processor_with_json_output.rs` had no
`mod` declaration, so 683 lines defining the `thread.*`/`item.*` schema never
compiled. `sdk/typescript/src/events.ts` says "based on event types from
code-rs/exec/src/exec_events.rs" and then rebuilt those events client-side from
raw core events — the contract existed only in TypeScript, and nothing checked
the two halves agreed.

Declared the modules and fixed what drifted while dead: TaskStarted became a
unit variant, WebSearchEnd became WebSearchComplete, StreamError folded into
Error, ExecCommandEndEvent lost `aggregated_output`, print_config_summary lost a
parameter. `--json` now uses it (`--experimental-json` is an alias, matching
upstream), and the old raw-event processor is deleted rather than left as a
second way to do this. thread.started needed a route because exec consumes
SessionConfigured before the event loop, so EventProcessor grew a defaulted
`on_session_configured`.

Making it real immediately found a lie: the SDK's `Usage` declares five fields
and we emitted three. core::TokenUsage had `cache_write_input_tokens` and
`reasoning_output_tokens` all along; the processor dropped them. Against a mock
model:

  {"type":"thread.started","thread_id":"2bd35c77-..."}
  {"type":"turn.started"}
  {"type":"item.completed","item":{"id":"item_0","type":"agent_message","text":"Hello from the model."}}
  {"type":"turn.completed","usage":{"input_tokens":11,"cached_input_tokens":2,
   "cache_write_input_tokens":0,"output_tokens":5,"reasoning_output_tokens":1}}

The SDK now passes those through instead of reconstructing them. Its test suite
did not compile — at HEAD and in just-every upstream: runStreamed.test.ts uses
`path` and `createMockClient` without importing either, testCodex.ts passes
`config` to a type declaring `configOverrides`, and findCodexPath() referenced
four names (`moduleRequire`, `CODEX_NPM_NAME`, `createRequire`,
`PLATFORM_PACKAGE_BY_TARGET`) that were never declared anywhere. Declared them
against @hanzo/dev, added `env` to CodexOptions, pointed the harness at
code-rs/target/debug/dev instead of codex-rs/target/debug/codex.

  pnpm exec jest tests/runStreamed.test.ts --testTimeout=120000
  3 passed  (asserts thread.started, turn.started, item.completed, turn.completed
             and item.type === "agent_message" against the real binary)

## queueUserMessage: steer a turn instead of tearing it

`sendUserMessage` submits Op::UserInput, and core/src/codex/streaming.rs:998
calls `sess.abort()` before spawning a new turn — over app-server you could
interrupt a turn, never redirect one. Op::QueueUserInput folds items into the
running task instead, and only the TUI used it. It is now an app-server method.
Separate method, not a flag: interrupting and steering are different acts and a
caller should not pick the destructive one by accident.

  → {"method":"queueUserMessage","id":3,"params":{"conversationId":"999222eb-…",
     "items":[{"type":"text","data":{"text":"steer me"}}]}}
  ← {"id":3,"jsonrpc":"2.0","result":{}}
  ← {"error":{"code":-32600,"message":"conversation not found: 00000000-…"},"id":4}

## zrok: not ours to build

Assessed and deliberately not implemented here. `hanzo link` already composes
ttyd + share::start + publish_terminal into exactly this feature, and
cli/src/commands/share.rs calls itself "the ONE implementation of 'publish a
local port on the fabric'". `dev` has no framable surface anyway — app-server is
raw JSON-RPC — and no IAM identity to reach POST /v1/share/enable. The gap is in
cloud/cmd/boxd, which already execs `dev`. Details in the report.

Also: git.hanzo.ai release migration precondition written into LLM.md (four
call sites, forge serves /v1/ not /api/v1/, publish to both for a cycle before
moving the updater). SDK package was @openai/codex-sdk; now @hanzo/dev-sdk.

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

The failure is git_info::test_collect_git_info_with_remote, still environmental:
the new narrower insteadOf rule only covers hanzoai/*, and the test's URL is
github.com/example/repo, which the broad rule still rewrites.

Version 0.2.189 -> 0.2.190.

Co-authored-by: Hanzo Dev <[email protected]>
2026-08-06 01:13:15 -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 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