Development record
Rebuild abcd as a Go binary
Context
abcd is being rebuilt from scratch. Its implementation is a tree of Python
scripts (scripts/abcd/ (historical), ahoy.py, the doctor and hook modules), driven
in-session and glued to the host through slash-commands and pre-commit hooks.
The design record — brief, intents, ADRs — describes that Python machinery in
detail, and much of it (the directory-as-truth lifecycle, the intent/spec/phase
layering, the redaction model) is architecture, not language. The rebuild has
to answer one question before any other: what does the new abcd run as?
The requirements the rebuild locks in point the same way. abcd must ship as a single self-contained artifact an operator installs and runs (no interpreter to provision, no virtualenv), it must present a deterministic core callable from several front doors (ADR-23), and it must drop its bundled tools as hard dependencies (ADR-22) — which removes the Python-process coupling those tools relied on. A scripting runtime is a poor fit for a distributable, statically-linked, concurrency-bearing CLI.
Decision
We reimplement abcd as a Go binary. Go gives a single statically-linked artifact per platform, a standard-library HTTP/JSON/process surface sufficient for the adapters, first-class concurrency for parallel oracle and review runs, and a fast test toolchain.
The record's Python mechanics are port targets, not deletions. Each settled behaviour — the lifecycle store, the lints, the redaction stages, the launch packaging — is re-expressed in Go against the same decisions; the ADRs that describe them stay canonical for what the behaviour is, and this rebuild changes only how it is realised.
Alternatives Considered
- Continue in Python. Keeps every line already written and the in-session Python glue. Rejected: it cannot produce a single dependency-free artifact, fights the transport-agnostic core (an importable Python package is not a neutral core the way an internal Go package is), and the interpreter/venv provisioning is exactly the install friction the rebuild exists to remove.
- Rewrite in another language (Rust, TypeScript). Rust buys more than the problem needs and slows iteration; a TypeScript/Node binary reintroduces a runtime to provision. Rejected: Go sits at the fit point — compiled, single artifact, fast to write and test — without Rust's ceremony or Node's runtime.
- Chosen: Go. Single artifact, deterministic core, cheap concurrency, the distribution story the install/launch milestone needs.
Consequences
- The rebuild is a reimplementation, not a refactor: the Python tree is replaced wholesale, and every ported behaviour needs a Go test that pins the same guarantee the Python code held.
- The toolchain shifts to Go conventions (
gofmt/goimports,go test); Python-specific tooling and the interpreter-version pins leave the surface. - Distribution becomes per-platform binaries, enabling the single-repo curated release (ADR-28) to ship an artifact rather than a source tree.
- The design record's Python-implementation references now read as historical port sources; they are reconciled to the Go architecture as each behaviour is re-landed, not rewritten pre-emptively.
Frontmatter
| id | adr-21 |
|---|---|
| type | adr |
| status | accepted |
| date | 2026-07-06 |
.abcd/development/decisions/adrs/0021-rebuild-in-go.md
open on GitHub ↗ · commit history ↗
References2
Referenced by1
- adr-2611011813195749abcd never runs a foreign executable under its own name, and no code that writes records is loaded at run timerelated
mentions5
- adr-28One repository, a curated release artifact — no dev→public mirror
- iss-237Brief drift: 05-internals/04-universal-patterns.md and 01-product/03-mental-model.md describe internal/core/docfidelity, the spc-74/75 marker grammar, and a .abcd/validation_disciplines/ registry as current state; none exists in the Go tree and those spc ids belong to the pre-adr-21 spec space (live specs are spc-1..spc-22).
- iss-239Dangling pre-rebuild spec ids in the draft corpus: itd-44 (spc-56), itd-51 (spc-33/37), itd-57 (spc-48/60/62), itd-61 (spc-75) cite specs from the numbering adr-21/adr-26 reset (live store is spc-1..spc-22). Worse, intents/README.md and itd-34 assert the itd-44 lineage 'landed as itd-44 (spc-56 thin adoption)' — no such spec or decision-verdict code exists, so the record claims a delivery the tree cannot back.
- iss-2608221457227162a superseded Phase-0 pseudo-ADR sits in research/notes/ claiming ADR-01, outside every record gate
- iss-2610262032024609The dependencies page says flow-next is not a dependency and is not built; itd-34's lifecycle paths call `/flow-next:plan`.