Commit Graph
187 Commits
Author SHA1 Message Date
zeekay b232128e54 docs(rust): native search, the exec verdict, and the lean tool surface 2026-10-14 13:41:39 -07:00
zeekay 630ec216d3 feat(rust): tools/list in one order, and --tools to serve fewer
tools/list appended the registered tools in HashMap order, which is
different in every process: two starts of the same binary listed
different orders (checked: three runs, three orders), so a client's
prompt cache over the tool schemas could not hold between sessions. The
registered tools now follow the built-ins sorted by name.

--tools fs,code,exec lists and serves only those. A client is charged
for every schema it is shown, each turn: the whole list is 34 tools and
38 KB, about 9.5K tokens; fs, code and exec together are 4.6 KB, about
1.1K, and byte for byte the same on every start. A name the server does
not carry fails at startup and lists what it does; a call outside the
list answers Unknown tool, like any other name.

ToolsConfig's flags were never read and are left alone.
2026-10-14 13:40:31 -07:00
zeekay d717c2da73 feat(rust): exec asks a classifier before it runs a command
Classify is the contract between exec and the shell parser and
classifier: command and cwd in, a Verdict (allow, ask or deny, with
reasons) out. ExecTool::with_classifier installs one; ToolRegistry::
with_classifier does the same for the MCP server; ExecTool::verdict is
the call Dev makes to ask the same classifier without running anything.

A deny is refused before a process is spawned or registered. An ask runs:
a server cannot ask the person, and the client's own permission prompt
already stood between the model and the call. Every answer then carries
the verdict. refusal() is the one place that policy lives.

With none installed, which is every build until the classifier module
lands, exec answers byte for byte as before and its input schema is
unchanged: the verdict is an output field, so the TypeScript runtime's
schema stays identical.
2026-10-14 13:37:51 -07:00
zeekay e9e6096ce4 feat(rust): fs search_text and code search_symbol on tgrep, in process
hanzo-trigram is the one search engine behind both actions: tgrep-core
(the hanzoai fork, MIT, pinned by commit, feature docs) linked as a
library, so a search is a call, not an rg spawn. It is its own crate so
Dev can link it without this crate's browser and parser dependencies;
hanzo_mcp::trigram re-exports it.

Results are ranked (matching lines a file, or definitions before uses
for a symbol), then path, then line, so a page is an offset into one
fixed list and the cursor really pages: before, rg stopped at limit and
a cursor repeated the first page. .gitignore, hidden and binary files
are skipped as rg skips them. A glob that names a document type (*.pdf,
*.docx, *.zip) reads documents too, and a hit inside one carries the
archive members and its page, slide, paragraph or cell.

fs and code keep their names, schemas and answer shapes; entry and place
appear on a document hit only. search_symbol now reads definitions by
the engine's declaration patterns, not the first-keyword guess.

Linking tgrep-core brings libsqlite3-sys (its managed-index code), which
needs a newer cc than the tree-sitter grammars allow, so Cargo resolves
tree-sitter-{c,cpp,javascript,python,rust,typescript} to their previous
patch releases. 241 library tests and the code tool's pass on them.
Gating managed/ behind a feature in the fork removes both.
2026-10-14 13:37:01 -07:00
zeekay d2dc8189bf feat(mcp): add kai_agent_step and kai_compact tools for decision-native agent workflows
Hanzo CI/CD / test (linux-amd64) (push) Skipped
Hanzo CI/CD / test (linux-arm64) (push) Skipped
Hanzo CI/CD / test-advisory (push) Skipped
publish / publish (push) Successful in 1m27s
Hanzo CI/CD / test-amd64 (push) Failing after 8m23s
Hanzo CI/CD / cicd (push) Skipped
CI/CD / cicd (push) Failing after 8m25s
2026-10-11 10:00:40 -07:00
zeekay deaf801810 chore(release): hanzo-mcp 1.1.29
Hanzo CI/CD / test (linux-amd64) (push) Skipped
Hanzo CI/CD / test (linux-arm64) (push) Skipped
Hanzo CI/CD / test-advisory (push) Skipped
publish / publish (push) Successful in 1m10s
Hanzo CI/CD / test-amd64 (push) Successful in 2m43s
Hanzo CI/CD / cicd (push) Successful in 6m22s
CI/CD / cicd (push) Successful in 9m12s
rust-v1.1.29
2026-10-04 16:28:32 -07:00
zeekay e3067ebc8e feat(rust): llm limits, catalog search, served and paid-by, plan refusals 2026-10-04 16:28:31 -07:00
zeekay 99809579e6 chore(release): @hanzo/mcp 2.4.16
Hanzo CI/CD / test (linux-amd64) (push) Skipped
Hanzo CI/CD / test (linux-arm64) (push) Skipped
Hanzo CI/CD / test-advisory (push) Skipped
publish / publish (push) Failing after 1m16s
Hanzo CI/CD / test-amd64 (push) Successful in 2m6s
Hanzo CI/CD / cicd (push) Successful in 1m37s
CI/CD / cicd (push) Successful in 3m48s
2026-10-04 16:15:00 -07:00
zeekay bd67f73a4c feat(llm): limits, catalog search, served and paid-by, plan refusals 2026-10-04 16:15:00 -07:00
zooqueenandHanzo Dev 5d256affa1 Write the release checksum in the form sha256sum -c reads
Hanzo CI/CD / test (linux-amd64) (push) Skipped
Hanzo CI/CD / test (linux-arm64) (push) Skipped
Hanzo CI/CD / test-advisory (push) Skipped
publish / publish (push) Successful in 42s
Hanzo CI/CD / test-amd64 (push) Successful in 7m10s
Hanzo CI/CD / cicd (push) Successful in 2m40s
CI/CD / cicd (push) Successful in 9m55s
rust-v1.1.26 and rust-v1.1.27 shipped .sha256 sidecars holding a bare
hash. install.sh, which hanzo.sh runs for `curl hanzo.sh/mcp | sh`,
verifies with `sha256sum -c`, which needs "<hash>  <name>", so every
Linux install of those releases stopped at "checksum MISMATCH" and
installed nothing. The sidecar is sha256sum's own line again, as it was
through rust-v1.1.23.

Release 1.1.28.

Co-authored-by: Hanzo Dev <[email protected]>
rust-v1.1.28
2026-10-04 14:01:20 -07:00
zooqueenandHanzo Dev eb0f29fc85 Give the Rust runtime kai_decide and Enso through llm
Hanzo CI/CD / test (linux-amd64) (push) Skipped
Hanzo CI/CD / test (linux-arm64) (push) Skipped
Hanzo CI/CD / test-advisory (push) Skipped
publish / publish (push) Successful in 59s
Hanzo CI/CD / test-amd64 (push) Successful in 3m22s
Hanzo CI/CD / cicd (push) Successful in 2m11s
CI/CD / cicd (push) Successful in 5m37s
The Rust hanzo-mcp could not reach Kai at all, and its llm tool defaulted
to an upstream model id, sent no routing bound, dropped the completion id
and the model that served, and returned a 402 or 429 as ok with empty
content because the client never read the status.

- kai_decide: POST /v1/decisions with the TypeScript tool's name, schema
  and shape checks (choice, score, noul; 1 to 100 questions).
- llm query: model enso-auto unless named, "auto" for Enso's pick;
  max_cost and max_latency_ms ride as X-Max-Cost and X-Max-Latency-Ms;
  the answer carries id and the model from X-Routed-Model or the body.
- llm models: one row per model with family, class and the catalog's
  per-million prices; family narrows it.
- llm feedback: POST /v1/ai/feedback with request_id, signal, rating.
- HanzoApi::call holds an answer to its status: a non-2xx, or an
  envelope that says error, is an error with the server's sentence.

Release 1.1.27.

Co-authored-by: Hanzo Dev <[email protected]>
rust-v1.1.27
2026-10-04 13:46:12 -07:00
zooqueenandHanzo Dev 58ddbc51e5 Add the llm tool to the TypeScript surface: Enso, the catalog, feedback
Hanzo CI/CD / test (linux-amd64) (push) Skipped
Hanzo CI/CD / test (linux-arm64) (push) Skipped
Hanzo CI/CD / test-advisory (push) Skipped
publish / publish (push) Failing after 59s
Hanzo CI/CD / test-amd64 (push) Successful in 1m47s
Hanzo CI/CD / cicd (push) Successful in 1m37s
CI/CD / cicd (push) Successful in 3m29s
HIP-0300 names llm among the optional tools and Python and Rust carry it,
but the TypeScript server had none, so an agent on @hanzo/mcp could ask
Kai a typed question and could not reach a model.

llm routes by action over api.hanzo.ai:
- query: POST /v1/chat/completions, model enso-auto unless named; "auto"
  lets Enso pick. max_cost and max_latency_ms ride as X-Max-Cost and
  X-Max-Latency-Ms. It returns the model that served (X-Routed-Model, else
  the body's model) and the completion id feedback takes.
- models: GET /v1/models, each model's family, class and per-million
  price as the catalog states it; family narrows to enso or kai.
- feedback: POST /v1/ai/feedback with request_id, signal and a 1-3
  rating; an envelope that says error is an error.

Co-authored-by: Hanzo Dev <[email protected]>
2026-10-04 11:23:44 -07:00
zeekay b406b542b5 Take zapd 1.1.5 from crates.io
Hanzo CI/CD / test (linux-amd64) (push) Skipped
Hanzo CI/CD / test (linux-arm64) (push) Skipped
Hanzo CI/CD / test-advisory (push) Skipped
publish / publish (push) Successful in 37s
Hanzo CI/CD / cicd (push) Successful in 1m24s
CI/CD / cicd (push) Successful in 3m26s
Hanzo CI/CD / test-amd64 (push) Successful in 1m59s
It is published there now, so the git pin goes.
2026-09-30 21:36:34 -07:00
zeekay ea08388793 Open and fill the release with the release action
Hanzo CI/CD / test (linux-amd64) (push) Skipped
Hanzo CI/CD / test (linux-arm64) (push) Skipped
Hanzo CI/CD / test-advisory (push) Skipped
publish / publish (push) Successful in 41s
Hanzo CI/CD / test-amd64 (push) Successful in 1m46s
Hanzo CI/CD / cicd (push) Successful in 1m23s
CI/CD / cicd (push) Successful in 3m12s
The runner image carries no gh CLI, so the open job died on its first
command and nothing was built. The release action talks to the API
itself, and the toolchain action installs Rust and the target rather
than trusting the image to have them. hanzo-mcp 1.1.26.
rust-v1.1.26
2026-09-30 21:23:47 -07:00
zeekay ad65572eec Release linux-arm64 by cross-building on the amd64 runners
Hanzo CI/CD / test (linux-amd64) (push) Skipped
Hanzo CI/CD / test (linux-arm64) (push) Skipped
Hanzo CI/CD / test-advisory (push) Skipped
publish / publish (push) Successful in 37s
Hanzo CI/CD / test-amd64 (push) Successful in 1m42s
Hanzo CI/CD / cicd (push) Successful in 1m41s
CI/CD / cicd (push) Successful in 3m24s
The org's runners serve linux-amd64 only, so the arm64 and darwin jobs
waited on labels nothing serves. arm64 now cross-builds on amd64 with
cargo-zigbuild, zig being the C toolchain ring needs; darwin is off the
matrix until a macOS runner exists.
rust-v1.1.25
2026-09-30 21:21:59 -07:00
zeekay 0e11347985 Add npx, uvx and jq to the TypeScript surface
Hanzo CI/CD / test (linux-amd64) (push) Skipped
Hanzo CI/CD / test (linux-arm64) (push) Skipped
Hanzo CI/CD / test-advisory (push) Skipped
publish / publish (push) Failing after 51s
Hanzo CI/CD / test-amd64 (push) Successful in 2m25s
Hanzo CI/CD / cicd (push) Successful in 3m55s
CI/CD / cicd (push) Successful in 6m24s
exec gains run(): an argv with no shell, waited on up to a deadline, then
left running in exec's process table. npx and uvx use it with Python's argv
and a two-minute deadline; jq passes its filter as one argv word.

@hanzo/mcp 2.4.14
2026-09-30 15:17:34 -07:00
zeekay 1ef1ce34a5 Add npx, uvx and jq to the Rust runtime
npx and uvx build Python's argv (package, whitespace-split args, npx -y,
uvx --python) and run it as an exec with a two-minute auto-background. jq
passes its filter as one argv word, as Python's jq tool does.
2026-09-30 15:17:29 -07:00
zeekay ed2a23156d Let presence arrive before WELCOME in the native host test
A node registering between ours entering the registry and our WELCOME
being queued is announced to us first; the extension ignores it, and so
does the test now.
2026-09-30 15:17:25 -07:00
zeekay 0bb22d833e Keep a backgrounded Rust exec's output and exit
A command past its timeout had its pipes dropped with the wait, so it lost
its output (or died of SIGPIPE) and stayed running forever in ps. Its
output now drains to a log that logs reads, and its exit is recorded; a
command that finishes in time returns inline and leaves no log.
2026-09-30 15:17:17 -07:00
zeekay 46b081c99e Give the TypeScript fs tool Python's contract
Hanzo CI/CD / test (linux-amd64) (push) Skipped
Hanzo CI/CD / test (linux-arm64) (push) Skipped
Hanzo CI/CD / test-advisory (push) Skipped
Hanzo CI/CD / cicd (push) Successful in 1m52s
CI/CD / cicd (push) Successful in 3m40s
Hanzo CI/CD / test-amd64 (push) Successful in 1m45s
publish / publish (push) Failing after 2m50s
read returns numbered lines and the full sha256 hash, write only creates,
apply_patch takes old_text and new_text under base_hash, list walks with
depth, pattern and cursor, patch takes the Rust grammar, and search_text
takes a pattern and glob. rg now runs without a shell, so a pattern is never
a shell word.

@hanzo/mcp 2.4.13
2026-09-30 15:06:58 -07:00
zeekay 03b7fd3edf Give the Rust fs tool Python's contract
Hanzo CI/CD / test (linux-amd64) (push) Skipped
Hanzo CI/CD / test (linux-arm64) (push) Skipped
Hanzo CI/CD / test-advisory (push) Skipped
Hanzo CI/CD / test-amd64 (push) Successful in 1m46s
publish / publish (push) Failing after 1m10s
Hanzo CI/CD / cicd (push) Successful in 1m53s
CI/CD / cicd (push) Successful in 3m43s
uri (path accepted), the unified envelope, sha256 hashes, write that only
creates, apply_patch guarded by the hash a read returned, list with depth,
pattern and cursor, search_text, and patch taking input. The search alias
tool goes: fs action=search_text is the one search.
2026-09-30 15:03:49 -07:00
zeekay 6dd2293590 Serve the extension's native messaging host from the Rust binary
Hanzo CI/CD / test (linux-amd64) (push) Skipped
Hanzo CI/CD / test (linux-arm64) (push) Skipped
Hanzo CI/CD / test-advisory (push) Skipped
publish / publish (push) Failing after 1m15s
Hanzo CI/CD / test-amd64 (push) Successful in 1m56s
Hanzo CI/CD / cicd (push) Successful in 2m33s
CI/CD / cicd (push) Successful in 4m33s
Run as hanzo-zap-host, hanzo-mcp relays ai.hanzo.zap messages to the ZAP
router's socket, as Python's native_host.py does, so a machine with only the
Rust server still lets Chrome and Firefox join without a door or pairing. Each
start registers it with the installed browsers, leaving any manifest whose
program exists alone.
2026-09-30 14:59:17 -07:00
zeekay b0d75abea9 Record parity with Python hanzo-mcp and the ZAP browser path in LLM.md
Hanzo CI/CD / test (linux-amd64) (push) Skipped
Hanzo CI/CD / test (linux-arm64) (push) Skipped
Hanzo CI/CD / test-advisory (push) Skipped
Hanzo CI/CD / test-amd64 (push) Successful in 2m16s
publish / publish (push) Failing after 1m12s
Hanzo CI/CD / cicd (push) Successful in 1m48s
CI/CD / cicd (push) Successful in 4m11s
2026-09-30 14:54:55 -07:00
zeekay c58488a2a3 Add browser and cdp to the TypeScript surface, over the ZAP router
Hanzo CI/CD / test (linux-amd64) (push) Skipped
Hanzo CI/CD / test (linux-arm64) (push) Skipped
Hanzo CI/CD / test-advisory (push) Skipped
publish / publish (push) Failing after 58s
Hanzo CI/CD / test-amd64 (push) Successful in 2m5s
Hanzo CI/CD / cicd (push) Successful in 1m53s
CI/CD / cicd (push) Successful in 4m32s
src/zap.ts is a consumer seat on the unix socket of whichever process the
lock elected: zapd has no JS or wasm build, so this runtime joins as
mcp/hanzo-<pid> and never stands for router. browser and cdp carry Python's
action names, parameters and extension methods; headless Playwright covers
the core, navigation and tabs when no browser is registered. The test runs
PyPI zapd as the router in another process, with a fake extension.

@hanzo/mcp 2.4.12
2026-09-30 14:52:19 -07:00
zeekay d9f8034726 Route the Rust browser and cdp tools to the extension over the embedded ZAP router
hanzo-mcp links zapd v1.1.5, stands for this login's router at startup and
takes the seat mcp/hanzo-<pid>, as Python hanzo-mcp does. browser takes
Python's action names and parameters (the core typed, the rest in args) and
sends each action with a wire method to the registered browser node; headless
Playwright runs only when none is registered. cdp sends raw methods to the
same node. hanzo-mcp pair prints the door's pairing code. The integration test
embeds the router on a private XDG_RUNTIME_DIR with a fake extension.
2026-09-30 12:52:05 -07:00
z f5765c149d Grant hanzoai/ci the run's ID token [skip ci] 2026-09-30 07:18:09 -07:00
zeekay 8a90c75bfd CI, publish and release also run from .hanzo/workflows, on the forge, where Actions is now on for this mirror.
Hanzo CI/CD / test (linux-amd64) (push) Skipped
Hanzo CI/CD / test (linux-arm64) (push) Skipped
Hanzo CI/CD / test-advisory (push) Skipped
Hanzo CI/CD / cicd (push) Successful in 1m29s
publish / publish (push) Successful in 1m0s
Hanzo CI/CD / test-amd64 (push) Successful in 1m48s
CI/CD / cicd (push) Successful in 3m21s
v2.4.11
2026-09-28 18:41:09 -07:00
zeekay e63e2b3e8c examples/kai.ts starts the server over stdio as a client does and asks kai_choice once. 2026-09-28 15:35:10 -07:00
zeekay 8d13859eb0 The kai tools steer a yes/no to a choice whose labels name the outcomes, which Kai answers better than yes and no. 2026-09-28 15:13:12 -07:00
zeekay 0c324b7c18 Publish, CI and release run from .github/workflows, the only directory the hanzoai org runners read. 2026-09-28 14:46:56 -07:00
zeekay e1f6a85d42 The kai tools cap no label or level count, since /v1/decisions caps none. 2026-09-28 14:46:36 -07:00
zeekay e33c38f0a2 The kai tools follow the frozen decision contract: instructions optional, 1 to 100 questions, 2 to 255 labels, 1 to 10 levels, and a noul's confidence. 2026-09-28 14:41:35 -07:00
zeekay 30fafe2616 kai_decide, kai_choice, kai_score and kai_noul ask Kai typed questions on /v1/decisions, in @hanzo/mcp 2.4.11 2026-09-28 14:31:22 -07:00
zeekayandHanzo Dev 201cdd0adc LLM.md is the one committed guide; CLAUDE.md, AGENTS.md and GEMINI.md are local links to it
Co-authored-by: Hanzo Dev <[email protected]>
2026-09-24 15:46:17 -07:00
zeekayandHanzo Dev 5d15d811d1 Publish and CI live in .hanzo/workflows, where the forge looks
publish / publish (push) Successful in 59s
Hanzo CI/CD / test (linux-amd64) (push) Successful in 2m13s
Hanzo CI/CD / test (linux-arm64) (push) Successful in 5m15s
Hanzo CI/CD / cicd (push) Successful in 2m5s
CI/CD / cicd (push) Successful in 7m49s
The forge runs the first of .hanzo/workflows and .github/workflows that
exists. release.yml created .hanzo/workflows on 09-10, and from then on
publish.yml and cicd.yml never ran: @hanzo/mcp 2.4.10 sat on main while
npm served 2.4.9. All three lanes are in one directory now.

Co-authored-by: Hanzo Dev <[email protected]>
2026-09-23 18:55:38 -07:00
zeekayandHanzo Dev e7921ba12f hanzo reads what an action takes, and sends args as given
describe was filtered out of the hanzo tool's resources, and the default
surface has no other tool that reaches it, so a model there could list a
resource's actions but not learn what one takes. It is a resource again:
hanzo(resource="describe", args={subsystem, op}), and a resource's action
list points at it.

Arguments ride in args, one object. A string was spread into
{"0": "{", ...}, and a key beside args, input among them, was merged in as an
argument; both reached the fleet as some other call. Both are now refused as
INVALID_ARGS before anything is sent, and the data alias is gone.

Co-authored-by: Hanzo Dev <[email protected]>
2026-09-23 11:09:52 -07:00
zeekayandHanzo Dev a0c3a2d05b grep's test reads the description the tool now carries
70a0a04 put tgrep first in the grep tool's description and left the test
holding the old words, so the suite failed on main.

Co-authored-by: Hanzo Dev <[email protected]>
2026-09-23 05:37:21 -07:00
zeekayandHanzo Dev a03f7e6820 The graph is on the surface, and hanzo reaches it
The catalog is regenerated from cloud (plugin/gen-mcp-catalog): the graph tool
now carries all thirteen operations, answer, communities, diff, erase, extract,
ingest and path among them, and the Rust crate's copy is synced from it.

The hanzo tool sent {resource, action, ...} to a subsystem handler that reads
{op, input}, so every call from the default surface reached the fleet with no
op. It now sends {op: action, input: args}, the shape the Rust runtime sends,
lists a resource's actions when none is named, and offers only subsystems.

Co-authored-by: Hanzo Dev <[email protected]>
2026-09-23 05:37:21 -07:00
zeekayandHanzo Dev 6355e41558 @hanzo/mcp 2.4.10
Co-authored-by: Hanzo Dev <[email protected]>
2026-09-11 13:44:31 -07:00
zeekayandHanzo Dev 7dac625d9a --core-only, list-tools and install --claude-code do what they say
--core-only set enableCore, which the unified surface ignores; it now offers the core group, and serve and list-tools read their flags through one function. list-tools printed four headers for tools that no longer exist and none of the 22; it now lists each tool under its group. install --claude-code wrote ~/.config/claude-code/mcp.json, which Claude Code does not read; it now runs claude mcp add --scope user. The smoke checks all three against dist/cli.js.

Co-authored-by: Hanzo Dev <[email protected]>
2026-09-11 13:44:31 -07:00
zeekayandHanzo Dev b5ca2ba8f7 Typecheck again: search asks for rg through onPath
bad040d replaced hasRipgrep with searcher and left one caller, so tsc --noEmit failed before publish could build.

Co-authored-by: Hanzo Dev <[email protected]>
2026-09-11 13:44:30 -07:00
zeekayandHanzo Dev 87d4150032 Install from the lockfile again
package.json pins typescript 7.0.2 and the lockfile still said ^7.0.2, so pnpm install --frozen-lockfile refused and publish stopped there.

Co-authored-by: Hanzo Dev <[email protected]>
2026-09-11 13:44:30 -07:00
zeekayandHanzo Dev bd0511890f The README registers the server the way that works, and lists its tools
The README said `npx -y @hanzo/mcp serve` runs an unrelated `serve`
package. With npm 11 it starts this server, and it is the form
`claude mcp add` writes; both forms answered initialize and tools/list
the same way from an empty npm cache, and claude mcp list reports the
added server connected.

The tool section now lists what serve offers, in the groups
src/tools/unified/index.ts defines, and gives the pipe that prints the
names. The "13 tools" and "260+" counts, a --legacy flag the CLI does
not have, the installer steps and the CI claims are gone: list-tools
prints category headers with no tools under them, install --claude-code
writes a file Claude Code does not read, and no workflow runs
smoke-mcp.mjs.

Co-authored-by: Hanzo Dev <[email protected]>
2026-09-11 11:44:09 -07:00
zeekayandHanzo Dev 313702d178 The release lane belongs on the native CI, not on GitHub
GitHub Actions is switched off for this repository on purpose — the API
reports enabled=false — so the lane I put under .github/ registered, showed as
active, and could never run. A pipeline that looks alive and does nothing is
worse than one that is plainly absent.

.hanzo/workflows is the native path: git.hanzo.ai runs it on our own fleet and
cd.hanzo.ai delivers. The runner labels follow the canonical <org>-build-<os>-<arch>
form, including hanzo-build-darwin-arm64, which is the target that was never
published and the reason for this lane.

The matrix key is `runner` rather than `on`. YAML 1.1 reads a bare `on` as the
boolean true, so as a key it comes back as True in anything that parses this
file — including the checks that read it.

Co-authored-by: Hanzo Dev <[email protected]>
2026-09-10 20:18:21 -07:00
zeekayandHanzo Dev b31f1113af Open the release before four jobs try to
gh release upload attaches to a release that exists. With the matrix creating
it, four jobs race and three lose — so one job opens it and the builds wait.

Idempotent on purpose: a re-run of a tag that already has a release attaches to
it rather than failing, which is what makes a retry after one target fails a
safe thing to do.

Co-authored-by: Hanzo Dev <[email protected]>
rust-v1.1.24
2026-09-10 20:13:33 -07:00
zeekayandHanzo Dev 318d998101 Build hanzo-mcp for every target the installer offers
hanzo.sh offers `mcp` as a native download and names five published targets.
Nothing in this repository built any of them: hanzo.yml declares a TypeScript
gate, publish.yml ships the npm package, and the tarballs on the last release
covered Linux alone. On macOS the installer asked for a file nobody had built.

So this lane builds the Rust crate — the one whose Cargo.toml calls itself
hanzo-mcp — on the rust-v* tags it is already released under, and attaches each
tarball with the checksum the installer refuses to install without.

Both macOS targets build on the arm64 machine, because the Apple toolchain
cross-compiles to x86_64 without a second host.

fail-fast is off. One target failing leaves the others published, which is a
missing file somebody can chase; fail-fast leaves an empty release, which is an
install that breaks for everyone.

Co-authored-by: Hanzo Dev <[email protected]>
2026-09-10 20:10:47 -07:00
zeekayandHanzo Dev 70a0a046bf Prefer tgrep where the tree carries an index
Trigram index prunes files a query cannot match: 23ms against ripgrep's 78ms
for an absent symbol, which is most of what a search asks. It loses where many
files match (128ms against 78ms), and with no index it scans everything and is
slower than plain grep — so the index is the condition, not the binary.

Co-authored-by: Hanzo Dev <[email protected]>
2026-09-10 17:25:10 -07:00
zeekayandHanzo Dev 2171304110 go 1.26.8
One toolchain across the estate. The tree carried 1.26.0, .1, .3, .4 and .5
at once, so which compiler built a binary depended on which repo it came
from.

Co-authored-by: Hanzo Dev <[email protected]>
2026-09-08 23:53:37 -07:00
zeekayandHanzo Dev e1af6af4f4 Move the workflows to .github/workflows
The forge reads .github/workflows natively and github.com reads nothing else,
so one directory serves both planes instead of two conventions that disagree
about which one is live. The reusable in hanzoai/ci already lives there, so a
caller naming that path now resolves to a file that exists.

Co-authored-by: Hanzo Dev <[email protected]>
2026-09-08 19:00:20 -07:00
zeekayandHanzo Dev f24a1aafad ci: a runner label names the platform, not the org
hanzo-build-linux-amd64, lux-build-linux-amd64, zoo-build-linux-amd64 and
every other org-prefixed spelling all meant the same machine. Which org a
job belongs to does not change which host can build it, so the org bought
one pool name per org per arch and each could go stale on its own -- the
evo host alone answered to fourteen names for one label.

One vocabulary now: linux-amd64, linux-arm64, macos-arm64, win-amd64. The
generic labels every plain workflow uses (ubuntu-latest, self-hosted) are
untouched, so naive CI keeps working.

Co-authored-by: Hanzo Dev <[email protected]>
2026-09-08 12:09:48 -07:00