Shipped so far (full detail in the CHANGELOG):
- v0.1 (0.1.0 → PyPI as
heddle-mcp, 2026-06-23; the project renamed tohashloomin 0.4.0) — the engine: content-addressed contracts, a hash-keyed verification cache, and a blast-radius query, over MCP. Single-process and Python-only by design. - v0.2 (0.2.0 → PyPI, 2026-07-04) — solo → team: a shared verification
cache (
LayeredStore+RemoteStore+python -m hashloom.cache_server) with the toolchain folded into the verification key so cross-machine greens are sound; Go and TypeScript adapters behind the per-extension adapter seam; semantic diff input_contract; test source in the key (#18); invariants out of the hash (#19); therechecks/wasted_rateblock instatus(#20); contract provenance (status: inferred | confirmed); and gate-shaped verify (a hardokbit plus--radius, so one call gates a change's whole blast radius). - v0.3 (0.3.0 → PyPI, 2026-07-04) — adoption: the
getting-started walkthrough for the
contract-first agent workflow; sample projects in all three languages
(
examples/sales,examples/go-ledger,examples/ts-cart); and hashloom developing hashloom — the repo's own stable seams under contract, reviewed and confirmed. No engine changes. - v0.5 (0.5.0 → PyPI, 2026-07-26) — shared → hosted: scoped auth (publish vs read tokens), a threaded cache server with first-writer-wins verdicts, key-addressed revocation, and the declared dependency set in the verification key; plus both contract generators (graphify import, the spec-kit extension) and strict provenance mode. (v0.4 was the rename release; Java, the fourth adapter, shipped in 0.3.2; C#, the fifth, in 0.5.1.)
- v0.6 (0.6.0 → PyPI, 2026-09-01) — honest greens: the verify-time
store freshness gate (
stale_storeon pull-without-reindex) and the fixture closure in the Python test-source hash; plus thecache_protocolwire contract,get_blobre-hashing,serve --pythonstatus symmetry, and the C# example with live NUnit/MTP coverage.
What follows is where it goes next. The deferred-by-design items live in ISSUES.md and the issue tracker; this is the prioritization.
v0.2 made the cache shareable; v0.5 makes sharing it safe at team scale. The remaining hard parts from docs/hosted-store.md:
- Auth scoping — ✓ Shipped (0.5.0): the cache server takes an
optional
--publish-token; reads accept either token (publish implies read), publishes require the publish token — CI writes greens, a laptop with the read token only consumes. A single token still grants both roles, so existing deployments are unchanged. Per-project/team tokens remain deferred. - Concurrent writers — ✓ Shipped (0.5.0): the cache server is a
ThreadingHTTPServerwith a lock-serialised sqlite connection, and verdict publishes are first-writer-wins on the verification key — a duplicate publish is a no-op, never aran_atrefresh orstalereset. WAL + per-thread connections remain the documented throughput follow-up. - Cross-graph invalidation — ✓ Shipped (0.5.0) as key-addressed
revocation: analysis showed content-addressed keys already propagate
contract changes across graphs (every dependent's key moves), so the
graph-keyed shared
mark_stalewas deliberately not built. What shipped closes the real residual gap — greens that were wrong at publish time (flaky, env drift) used to be immortal team-wide;POST /staletombstones their keys (with audit, restore, and name sweeps), and a revoked key stays stale under any publish. See docs/hosted-store.md item 5 for the full argument. - Dependency set in the key — ✓ Shipped (0.5.0): the toolchain
identity now carries a
deps <file>=<sha256-12>suffix over the project's committed dependency source (lockfile, or declared manifest as fallback), CRLF-normalised so cross-OS checkouts share. A green from a different declared dependency set is never trusted; projects with no dependency source keep the version-only identity, so nothing busts for them. OS/arch stays out deliberately — the CI(Linux)-serves-laptops promise holds, and installed-env drift remains revocation's job (see docs/hosted-store.md item 3 for the decisions).
The one failure class hashloom cannot afford is serving a green it shouldn't. Two known instances make the theme:
- Store freshness at verify time — ✓ Shipped (0.6.0): a
git pullwithouthashloom indexused to let verify serve cached-passes keyed by the store's old contract hashes (ISSUES.md #15). Verify now re-hashes each unit's closure — its own contract plus every transitive dep — fromcontracts/on disk and refuses withstale_store(no tests run, no cache entry) untilhashloom index. Bounded by the closure, memoised per call. - Fixture coverage in the test-source hash — ✓ Shipped (0.6.0):
the Python test-source hash now covers each test's fixture closure —
requested names (arguments,
usefixtures, literalgetfixturevalue), autouse fixtures in scope, and fixtures of fixtures, statically resolved through the test's module and conftest chain, nearest wins. Dynamic fixture use the walk cannot see degrades to hashing the whole chain — over-busting, never under-busting. Tests that resolve no project fixtures keep byte-identical hashes, so the upgrade re-verifies only fixture-using tests. Residual (ISSUES.md #24): plain helper functions a test imports, and non-Python test helpers — a call-graph problem, deliberately not this change.
- Facet-aware invalidation
(#67) —
put_contract's semantic diff already reports which facet of a contract changed (signature / deps / examples / invariants), but invalidation ignores that precision: any hash-relevant change marks every transitive dependent stale. The sharpening is letting a dependent declare — or hashloom infer — which facets it actually leans on, so an examples-only change doesn't re-verify a dependent that only consumes the signature. Pure precision work inside the existing model — no new surface (5 MCP tools, 5 CLI commands unchanged). Unscheduled: it queues behind fixture coverage (the #18 follow-up above) and the v0.5 hosted-store theme. - The deterministic-test caveat — a cached green assumes deterministic tests, so a pass that depended on wall-clock time, network, or randomness can outlive the condition that made it pass. The README states the caveat honestly; shrinking it (flakiness detection, an optional re-verify TTL, or marking tests untrusted-for-caching) is open design work, not yet scheduled.
- Strict provenance mode (#49)
— ✓ Shipped (0.5.0):
.hashloom/config.json{"strict_provenance": true}upgrades verify's inferred-contract warnings to structured refusals (inferred_contract); reads and writes stay advisory. Landed with no schema change, as designed.
- Further languages — the adapter seam is proven five deep (Python, Go,
TypeScript, Java, C#, chosen by impl extension) and is itself under contract
(
contracts/LanguageAdapter.yaml, the adapter specification: six methods, extension routing, hashing and error-shape invariants). Each additional language is real work — a normalised-AST hasher plus a test-runner integration — but now lands against a spec, not a convention. - Tessl spec-format compatibility — an import/export adapter, once that format is stable.
- A single error-code naming convention (
bad_*vsinvalid_*).
No new contract syntax — contracts stay plain YAML. Guarding this is how the project avoids "scope creep toward Loom." Keep the surface minimal: 5 MCP tools, 5 CLI commands.
- Honest greens (the v0.6 theme): the verify-time freshness gate (✓ shipped) — then fixture coverage in the test-source hash.
- Facet-aware invalidation (#67), once the theme lands.
- Tessl compatibility and the error-code naming convention.