hanzoai/ci keeps the reusable at .github/workflows/build.yml — the one path
both planes resolve, since github.com reads a reusable only from there and the
forge reads it too. The v1 tag moved with it, so a caller still naming
.hanzo/workflows/build.yml asks for a blob that is not in the tree:
InsertRun: read hanzoai/ci@v1:.hanzo/workflows/build.yml: object does not exist
The caller itself stays at .hanzo/workflows/cicd.yml on purpose: github.com has
no runner for these labels, so a caller placed there could never be scheduled.
Co-authored-by: Hanzo Dev <[email protected]>
I built a Rust producer last night on the finding that none existed. That
finding was wrong: ml/hanzo-research already had one — 930 lines, tests, a
working kernel_perf example, from_env(), the same verbs against the same
/v1/research endpoint. I searched this repo, concluded absence, and did not
search ml.
Two SDKs for one plane is the defect the plane exists to prevent, so the
duplicate goes. ml/hanzo-research is canonical; it lives where the GPU
harnesses that must call it live.
Co-authored-by: Hanzo Dev <[email protected]>
The discipline this repo exists to serve, written down: state a hypothesis,
say what you predict, run the arms, record the verdict.
A company is a sequence of bets, most of them wrong. Being wrong is cheap;
being wrong twice about the same thing is what kills companies, and it is the
default, because the first refutation was never written anywhere the next
person would look. The scarce asset is knowing which of your bets already came
back.
Four principles: a refutation is a result; provenance or it did not happen;
measure where it happens, not in a spreadsheet afterward; private by default.
And the reason it is the company rather than a tool — an autonomous company is
one whose decide/act/measure/update loop closes without a human in the middle.
That loop IS the method. An agent can run it; what it cannot do is remember
what the last agent disproved. This plane is that memory.
Co-authored-by: Hanzo Dev <[email protected]>
Go records it and Python produces it; Rust — where every GPU harness lives — had no
way to record at all. That is why kernel results survived as loose .log files on the
box that measured them instead of as evidence anyone could query.
Verb-for-verb with the Go SDK, same JSON names, so a Rust harness and a Python
notebook upsert the same row. Inert without a key, so a record call is safe to leave
on a production path. kind stays an open string: a marketing A/B and a kernel A/B
record identically.
sha256 and base64 are inline with known-answer tests, so the only dependency beyond
serde is ureq — already in both the engine and ml lockfiles.
Co-authored-by: Hanzo Dev <[email protected]>
- Research implements Stringer + GoStringer, so %v/%+v/%#v/%s render the key
as <redacted>; a struct dump no longer leaks hk-* in plaintext.
- commitNarrative gates `since` to a git object id (hex, <=64) before it
reaches `git log <since>..HEAD`, closing arg-injection from a server value
(parity with the C++ port).
- http.Client refuses redirects (CheckRedirect -> ErrUseLastResponse) and the
response read is capped at 8 MiB, so a hostile server cannot bounce the
Bearer key to another host or OOM the client.
- Docs state the accurate contract: records are semantically identical across
languages (the server keys on project + id = kind:subject:task), not
byte-identical.
Tests: TestKeyNeverLeaksViaFmt, TestSinceMustBeAGitObjectID.
Stdlib-only client mirroring the Python producer verb-for-verb and byte-for-byte:
Experiment/Record/Log/Conclude/Finish/Snapshot/Report + Query/Totals/Grant.
- kind is an open string (marketing-experiment records identically to kernel-perf)
- Verdict is a defined type: Proven | Refuted | Inconclusive, rejected out-of-set
- zero-config provenance: git state, commit narrative since last run, build-info
lib versions, host, calling code site; git exec bounded at 5s
- encode() sets EscapeHTML=false so meta is byte-identical to CPython json.dumps
- auth is the per-org bearer key from env (KMS-sourced), never hardcoded