Skip to content

ADR-026: retire NanoClaw, MicroClaw, and NullClaw drivers - #355

Merged
mostlydev merged 4 commits into
masterfrom
issue-353-runner-adoption-adr
Aug 3, 2026
Merged

ADR-026: retire NanoClaw, MicroClaw, and NullClaw drivers#355
mostlydev merged 4 commits into
masterfrom
issue-353-runner-adoption-adr

Conversation

@mostlydev

@mostlydev mostlydev commented Aug 3, 2026

Copy link
Copy Markdown
Owner

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, nullclaw
Retained: openclaw, hermes, nanobot, picoclaw

  • adds accepted ADR-026 and a dated live evidence artifact
  • adds a re-runnable adoption collector with concurrent per-repository collection and cached binary search over fork-history boundaries
  • removes the three driver packages, built-in aliases, imports, scaffolds, wake adapters, active examples, fixtures, and current documentation
  • preserves retired-runner portable-history import paths as a migration escape hatch
  • makes retired CLAW_TYPE values fail closed with a consistent ADR-026 message pointing to Hermes
  • pins the registered built-in contract to exactly the four retained drivers
  • keeps all four retained runners in the default rollcall matrix; PicoClaw's resolved picoclaw upstream gateway port=0 breaks spike test #137 regression is no longer gated
  • replaces removed-driver carriers in mixed-runner, policy, digest, and example spike paths with Nanobot

Decision 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:

runner evidence judgment
MicroClaw 0 new forks/30d and minimal public scale, despite active releases retire
NullClaw measurable use, but weak recent fork and maintenance signals retire under uncertainty
NanoClaw recent forks and stars, but steep decay and no independent public distribution metric found retire under uncertainty

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 equality
  • focused retirement, build, driver, CLI, and collector tests
  • live collector refresh with no errors
  • git diff --check

The live Docker/provider spike suite and independent adversarial review will be completed before this draft is marked ready.

Closes #353

@mostlydev

Copy link
Copy Markdown
Owner Author

Status note: this is draft because the dated evidence artifact (docs/evidence/2026-08-03-runner-adoption.json) is still being generated and lands as a second commit. The ADR and the collector are complete and reviewable now — the artifact is corroboration for the table already in the ADR, not new input to the decision.

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 gh token once and uses net/http instead of spawning gh api per page, and -max-pages caps the sweep while marking affected counts fork_windows_truncated so a capped run undercounts visibly rather than silently.

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.

@mostlydev mostlydev changed the title ADR-026: runner adoption measurement and retirement policy ADR-026: retire NanoClaw, MicroClaw, and NullClaw drivers Aug 3, 2026
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.
@mostlydev
mostlydev force-pushed the issue-353-runner-adoption-adr branch from 3fb9cd5 to 55bcd4c Compare August 3, 2026 02:11
@mostlydev

Copy link
Copy Markdown
Owner Author

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:

  • RetirementError() as the single canonical migration error, consumed by both driver.Lookup and parseClawType, naming Hermes as the one reviewed migration target — with the compatibility window recorded as one release
  • exact-set registry contract test moved to internal/build where the blank imports actually load the built-ins (my original test in package driver could not prove registration; this one can)
  • internal/driver/shared/history.go legacy paths restored — the migration escape hatch fires precisely when operators migrate off retired drivers
  • testdata/nanobot-stub/ tracked with a scoped gitignore negation and corrected identity
  • rollcall pc-roll ungated (picoclaw upstream gateway port=0 breaks spike test #137 verified closed; picoclaw config emits gateway.port=18790), so the default matrix genuinely covers all four retained runners
  • collector rewritten to O(log pages) boundary binary search with page caching, exact capture time (fixing the midnight-truncation bucket-0 bug), Link-header last-page parsing, release-asset/Docker Hub/commit-window fields actually collected, and httptest-backed tests for boundaries, partial last pages, malformed timestamps, and page-load budget
  • ADR restated at its real level of judgment: operator-chosen removal of ambiguous integrations on maintenance grounds, with per-runner evidence recorded under it rather than a post-hoc conjunctive rule; "no users" softened to what the data supports; AGENTS.md cited as canonical

Verification on the final sha: go test ./... clean, go vet clean across default/spike/integration tags, go test -tags integration ./... against real Docker clean, collector unit tests pass, git diff --check clean, CI green (Go + claw-api image). The heavy TestSpikeRollCall is compiled and vetted with picoclaw enabled by default but has not been executed against live Discord/providers this session — flagging so the next live spike run is understood as the remaining end-to-end confirmation.

Merging: schedule train (#349#354#346) is already on master, both reviewers are satisfied, and the removal set is the operator's explicit decision.

@mostlydev
mostlydev marked this pull request as ready for review August 3, 2026 02:35
@mostlydev
mostlydev merged commit c6fdcda into master Aug 3, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Audit adoption and retire stagnant runner integrations picoclaw upstream gateway port=0 breaks spike test

1 participant