576 Commits
Author SHA1 Message Date
zeekay ab4e3adfbc chore(release): 0.6.100 [skip ci] 2026-08-19 17:26:16 +00: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 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 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 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
GitHub Action 7502aae9ba chore(release): 0.6.95 [skip ci] 2026-08-08 17:21:41 +00: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] 2026-08-08 06:41:41 +00:00
GitHub Action fa8cdc132b chore(release): 0.6.93 [skip ci] 2026-08-07 04:35:29 +00:00
zeekay 5480a29f95 Merge origin/main: adopt the release-pipeline fixes, keep our TUI and CLI
origin/main carried five commits our sync branch had not seen, four of them
repairs to a release pipeline that had published nothing to npm since April.
Resolved eleven conflicts by combining rather than choosing, because on every
one of them the two sides were additive, not opposed:

- .github/workflows/release.yml — ours is the superset (npm-auth-check and
  release-notes jobs, and `cancel-in-progress: false`, which is what you want
  for a release; theirs said true). Grafted in their three real fixes: the
  ubuntu-24.04 pin (ubuntu-latest sat fifteen minutes unacquired on run
  31128398197 and took the release with it), and the "assert every architecture
  built" step, which is the actual cure for a green release that shipped a
  partial matrix. Dropped their inline OpenAI proxy step: our release-notes job
  already starts that proxy on port 5058, so taking it would have run two.

- code-rs/tui/src/chatwidget/smoke_helpers.rs — kept both sides. Theirs pins
  the snapshot cwd to /snapshot so snapshots stop embedding the recording
  machine's checkout path; ours forces the minimal header and test mode. The
  minimal header means the Directory line never renders, so the pin is
  belt-and-braces, but it is correct and cheap to keep.

- code-rs/cli/src/main.rs — kept ours whole. Both sides made the same semantic
  fix (derive the expected completion name from CLI_COMMAND_NAME instead of
  restating "_code"); theirs was only the tidier phrasing of it.

- the 8 vt100 snapshots — regenerated, not hand-merged, and the regenerated
  output is byte-identical to what this branch already had. The header they
  record now reads "Hanzo Dev" where origin/main's read "Code".

- codex-cli/package.json — took theirs (0.6.92); ours was a stale 0.2.190.

Verified: cargo test -p code-tui --test vt100_chatwidget_snapshot 43/43 pass;
cargo test -p code-core --test hanzo_identity 4/4 pass.
2026-08-06 20:02:42 -07:00
GitHub Action 88c5c7b53a chore(release): 0.6.92 [skip ci] 2026-08-06 22:42:11 +00: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 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 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
GitHub Action 983e0dc75f chore(release): 0.2.188 [skip ci] 2025-10-06 11:15:56 +00:00
GitHub Action aa714875fc chore(release): 0.2.187 [skip ci] 2025-10-06 08:47:41 +00:00
GitHub Action 52d6aabef1 chore(release): 0.2.186 [skip ci] 2025-10-06 02:23:01 +00:00
GitHub Action 796e3fb020 chore(release): 0.2.185 [skip ci] 2025-10-03 20:50:36 +00:00
GitHub Action 3861c5360b chore(release): 0.2.184 [skip ci] 2025-10-03 12:36:06 +00:00
GitHub Action cac04e9711 chore(release): 0.2.183 [skip ci] 2025-10-03 09:53:21 +00:00
GitHub Action 63f7d94996 chore(release): 0.2.182 [skip ci] 2025-10-03 07:11:02 +00:00
James Peter 9f4221ec4a feat(protocol): add MCP shim and sync tool stack 2025-10-03 14:36:00 +10:00
GitHub Action 4c26cfad4a chore(release): 0.2.181 [skip ci] 2025-10-01 12:12:51 +00:00
GitHub Action 9265d55a2a chore(release): 0.2.180 [skip ci] 2025-10-01 00:00:07 +00:00
GitHub Action c7d70e1c33 chore(release): 0.2.179 [skip ci] 2025-09-30 13:17:04 +00:00
GitHub Action 918ee0e103 chore(release): 0.2.178 [skip ci] 2025-09-30 01:47:07 +00:00
GitHub Action e683e6870a chore(release): 0.2.177 [skip ci] 2025-09-29 22:43:32 +00:00
James Peter 093fb65073 feat(process-hardening): share hardening crate and update proxy 2025-09-30 08:23:01 +10:00
GitHub Action f14912c9c2 chore(release): 0.2.176 [skip ci] 2025-09-29 12:04:59 +00:00
GitHub Action 22f540844a docs(changelog): update for v0.2.175 [skip ci] 2025-09-29 11:36:33 +00:00
GitHub Action a982c450e3 chore(release): 0.2.175 [skip ci] 2025-09-29 11:32:29 +00:00
GitHub Action 4fab0312f0 chore(release): 0.2.174 [skip ci] 2025-09-29 02:20:12 +00:00
GitHub Action 702f674b87 chore(release): 0.2.173 [skip ci] 2025-09-29 01:26:27 +00:00
GitHub Action bc22304954 chore(release): 0.2.172 [skip ci] 2025-09-28 22:51:47 +00:00
GitHub Action c8386bd284 chore(release): 0.2.171 [skip ci] 2025-09-27 07:47:46 +00:00
GitHub Action 67b3dae038 chore(release): 0.2.170 [skip ci] 2025-09-27 03:35:41 +00:00
GitHub Action 47c99f5716 chore(release): 0.2.169 [skip ci] 2025-09-26 13:12:38 +00:00
GitHub Action e93d328461 chore(release): 0.2.168 [skip ci] 2025-09-26 12:50:42 +00:00
GitHub Action 0883e9bb76 chore(release): 0.2.167 [skip ci] 2025-09-26 01:37:27 +00:00
GitHub Action 3d3bcd3e12 docs(changelog): update for v0.2.166 [skip ci] 2025-09-25 12:20:57 +00:00
GitHub Action 7987db3a39 chore(release): 0.2.166 [skip ci] 2025-09-25 12:17:10 +00:00
GitHub Action fd0aadd1fd chore(release): 0.2.165 [skip ci] 2025-09-25 11:32:48 +00:00
GitHub Action c27b426b20 chore(release): 0.2.164 [skip ci] 2025-09-25 07:28:39 +00:00
James Peter 31412ca2e4 fix(cli/postinstall): restore shim detector 2025-09-25 17:01:19 +10:00
James Peter 5fa4f5e85c merge code-branch-20250925-045812 via /merge 2025-09-25 16:30:29 +10:00
James Peter 1b46db1586 fix(cli/postinstall): avoid overwriting existing code shim 2025-09-25 15:43:26 +10:00
James Peter 701a40c624 merge main into code-branch-20250925-040059 before merge 2025-09-25 14:59:28 +10:00