ADR-026: retire NanoClaw, MicroClaw, and NullClaw drivers - #355
Conversation
|
Status note: this is draft because the dated evidence artifact ( Why it is slow, since it is worth knowing before anyone re-runs this: fork pagination is the whole cost. GitHub throttles deep pagination of large fork lists to roughly 0.4 requests/second, and a full 4×30d sweep across all seven runners is around 600 pages. Hermes alone (43378 forks) is ~400 of them. Two mitigations are in the committed collector — it borrows the Worth being explicit that the expensive repos are the ones the decision does not turn on. OpenClaw and Hermes are unambiguous keeps on every axis; the retirement hinges on MicroClaw (0 new forks in 30 days) against the next-lowest runner (32), and both of those page in seconds. |
Evidence and policy only; no driver code is removed here. Collecting the data for #353 showed the rule the issue was opened against -- retire runners "not seeing an increase in adoption over time" -- cannot be applied as stated, which is most of why this ADR exists. Two of the three evidence sources #353 specifies do not hold up: GitHub stargazer timestamps 404 for every external upstream from this environment (verified not to be rate limiting or token scope, since the same call succeeds against our own repo), and per-release downloads normalized by release age is confounded by post-publication decay, so it flatters whichever release is newest and reports the projects that are winding down as the fastest growing. What survives is new forks bucketed into 30-day windows -- the only non-cumulative adoption series obtainable for every runner. It shows that every runner in the cohort has a declining fork rate, including OpenClaw and Hermes, so a derivative-based rule selects all seven drivers including the two the product is built on. The rule has to be a floor. It also shows PicoClaw holding the best retention in the cohort while posting the worst commit trend, which is the concrete case for never letting maintenance activity decide an adoption question. Outcome: retire MicroClaw only. NullClaw is the obvious maintenance-rule candidate but has real use, and deciding on one rule while justifying with another is not something to do quietly, so that is deferred to its own issue. The collector is committed and re-runnable. It borrows the gh token once and uses net/http rather than shelling out per page, since fork pagination is hundreds of sequential requests for the large repos, and supports -max-pages to cap that cost while marking the affected counts truncated rather than silently undercounting. Window bucketing is extracted and unit-tested. Thresholds live in the ADR, not the collector, so a future audit can refresh data without inheriting today's judgement. go test ./... , go vet ./... , gofmt, and git diff --check all pass.
The operator overrode the earlier MicroClaw-only outcome: "Just remove all the ambiguous ones. I don't need to maintain them." The ADR now states the honest basis — maintenance cost, with adoption evidence deciding which runners are worth it — instead of pretending a pure adoption rule produced this set. Retention requires all three of: an adoption floor (MicroClaw fails, 0 forks/30d), upstream viability (NullClaw fails, no release in 64 days and commits -89%), and corroboration by an independent distribution channel (NanoClaw fails — the only runner with no asset distribution at all, and the steepest retention decay at 0.07). PicoClaw is the load-bearing retained case: worst commit trend, best fork retention in the cohort, so the conjunction is what stops maintenance activity from deciding an adoption question. Also commits the dated evidence artifact from the full 4x30d collector run (which independently reproduced the second agent's fork-window numbers), identifies Nanobot's upstream as HKUDS/nanobot by matching pyproject.toml name/version against PyPI, moves the collector to direct net/http with the gh token borrowed once (per-page subprocess spawn dominated runtime), adds -max-pages with explicit truncation marking, and unit-tests the window bucketing.
Implements the ADR-026 removal across the compile-time surface.
RED-first: internal/driver/retired_test.go pins the retained set
{openclaw, hermes, nanobot, picoclaw} and requires retired CLAW_TYPEs
to fail closed with the runner named, the retirement reason, ADR-026,
and a supported migration target — not the generic unknown-driver
message. Lookup() carries a retiredRunners map to satisfy it.
Removed: internal/driver/{nanoclaw,microclaw,nullclaw}, their blank
imports, scaffold types and base-image aliases, schedule wake adapters,
shared history locations, testdata/microclaw-stub, the three rollcall
services/agents/Dockerfiles, and the trading-desk systems-monitor and
micro services.
Conformance coverage is preserved, not just shrunk:
- rollcall's nb-roll flips to the anthropic-messages proxy format so
that ingress surface keeps a default-run carrier (its previous
carriers nc-roll/nano-roll are gone and pc-roll is gated behind #137;
ADR-023 coverage assertion unchanged)
- trading-desk value-trader retargets to a nanobot stub, keeping a
third driver family in the master-claw wiring spike; assertions now
check nanobot-home/config.json and the seeded workspace AGENTS.md
- the mixed-managed spike pairs openclaw with a new testdata/
nanobot-stub; both retained drivers are container-read-only, so the
old read-only/writable contrast (a microclaw-specific property) is
replaced with env/config assertions
- the channel-digest and policy spikes retarget their stub agent to
nanobot
Docs: README, site guide pages, AGENTS.md, embedded skill text (synced
via go generate), issue template, .env.example. Historical record —
docs/plans, superseded ADRs, existing changelog entries — deliberately
untouched per ADR-026. Changelog gains an Unreleased entry only.
Verified: go build, go test ./... , go vet ./... (plus spike and
integration tags), go test -tags integration ./... against real
Docker, gofmt, git diff --check.
3fb9cd5 to
55bcd4c
Compare
|
Final cross-verification on 55bcd4c (claude). Both agents have now reviewed each other's halves: codex's 16-point adversarial review of my ADR/removal produced the hardening commit; I independently verified that commit end to end. Confirmed present and correct:
Verification on the final sha: Merging: schedule train (#349 → #354 → #346) is already on master, both reviewers are satisfied, and the removal set is the operator's explicit decision. |
Summary
The maintainer resolved #353's ambiguous cases with: “Just remove all the ambiguous ones. I don't need to maintain them.” This PR carries the full decision record, reproducible evidence, implementation, migration behavior, and retained-runner conformance updates.
Retired:
nanoclaw,microclaw,nullclawRetained:
openclaw,hermes,nanobot,picoclawCLAW_TYPEvalues fail closed with a consistent ADR-026 message pointing to HermesDecision and evidence
The evidence is deliberately not encoded as a post-hoc three-condition deletion formula. GitHub fork windows are the only non-cumulative public series available across the cohort; package, image, and release-asset figures corroborate where public. None of these metrics measures Clawdapus-side usage.
The snapshot records fork windows, two 90-day commit windows, release cadence, cumulative release-asset downloads, Docker Hub pulls where public, and PyPI history where public. A fresh full run completed without collection errors in about 39 seconds.
The evidence makes four integrations clearly worth their maintenance cost. The other three remain different kinds of ambiguity:
This is a maintenance-cost judgment under incomplete public evidence, not a claim that the retired runners have no users.
Migration behavior
For one release, old pod and Clawfile configurations fail at compile time with the retired name, ADR-026, and
CLAW_TYPE "hermes"as the supported migration target. Unknown names retain the generic typo/error path. Legacy session/history directories remain importable so changing drivers does not strand portable history.Historical and release discipline
Dated plans, superseded ADRs, and existing changelog entries remain unchanged. Only current support surfaces and the new Unreleased entry are updated. This PR does not change release pins, the latest-release badge, navigation versions, or the cllama submodule.
Verification
Completed after rebasing onto the merged scheduler work:
go test -count=1 ./...go vet ./...go test -tags integration -count=1 ./...go test -tags spike -run '^$' ./cmd/claw/...go vet -tags integration ./...go vet -tags spike ./cmd/claw/...go generate ./cmd/claw/...with embedded skill mirror equalitygit diff --checkThe live Docker/provider spike suite and independent adversarial review will be completed before this draft is marked ready.
Closes #353