goself: bootstrap to v0.2.2 (story)
1. Header & Context
- Date: 2026-10-25, one session (Claude Opus 5.5 as host, no subagents).
- Previous story: none. Baseline is the first commit
bc30900(chore: bootstrap goself). The only earlier study is the topic study prior-art-self-replication.md, written in this session. - Starting state: a one-function library (
Version()), placeholdermake container-test, nothing pushed. Epic 001 (8 tasks) and research ticket 002 were filed right after the baseline (9edeb2e). - Goal: owner set
/goal complete the epic or exit if have blockers or end in an agentic deadloop. - Review: second-vendor review by gpt-6.1-sol (codex:sol:high, read-only). Four accounting findings fixed: ticket baseline, commit categories, count of corrective releases, and the statistics cutoff. It found no issues with the verdicts or the post-mortem.
2. Executive Summary
Epic 001 and ticket 002 are closed. goself is a public, dependency-free Go library
(ubunatic.com/goself) with five strategies (auto, self, build, release, go),
atomic local/ssh install, cross-arch builds, Deployer.Binary for callers that ship binaries
themselves, an embedded onboarding skill, a container smoke test over real ssh, and green GitHub
CI including arm64 under QEMU. Five tags were published (v0.1.0 to v0.2.2); v0.1.0 does not
compile and is retracted. The lmcoder pilot (lmcoder f8962e5) is committed locally, not pushed,
by owner choice. Three follow-up onboarding tickets (003 to 005) are open.
3. What Worked Well
- Canary before code. A 1-minute probe showed cross-arch
go install pkg@verfails whenGOBINis set and writes to$GOPATH/bin/<os>_<arch>/otherwise. This corrected a muddled paragraph in the research study and shapedxbuild.Modulebefore it was written. - Reuse of in-house prior art. Reading lmcoder's
host.go/release_fetch.gofirst gave the uname mapping, shell quoting and checksum flow; goself generalized rather than reinvented them. - Injectable runner. One
Runnerinterface (local/bin/shor systemssh) made the same code testable with a fake remote in unit tests and with real ssh in containers. - Unit tests passed on the first run for all six packages.
- Container test as a real-world check. It found the glibc-vs-musl failure (section 4) that unit tests could not.
- Stopping at outward-facing steps. The host stopped twice for owner decisions (push/release, repo visibility) instead of pushing on its own; both were then executed in minutes.
4. Honest Post-Mortem (Failures, Bugs & Near-Misses)
| # | What went wrong | How it was caught | Fix |
|---|---|---|---|
| 1 | Research section 4 first contained self-contradicting guesses about cross go install ("Actually simpler..."). |
Host re-read before committing. | Canary run; paragraph rewritten with the measured behavior. |
| 2 | self replication of the test binary failed on Alpine: "not found" (glibc dynamic binary on musl). |
make container-test locally. |
Test binary built with CGO_ENABLED=0; trap documented in SKILL.md. |
| 3 | Docker in CI did not find Containerfile (podman does). |
First CI run failed. | -f testdata/sshd/Containerfile (7d13f98). |
| 4 | Released v0.1.0 does not compile: harnez release generated var Version, clashing with func Version(). Host had not read docs/GoRelease.md "Version Wiring" closely and did not dry-run the generated file through go vet. |
Post-release go vet while checking module resolution. |
Version() renamed to BinaryVersion() (breaking, fc15a87), v0.1.1; v0.1.0 retracted in v0.2.2. |
| 5 | Vanity URL assumed working; it returned 404. Then uman website sync was assumed to deploy; it only copies into the ubunatic.com repo. |
Owner asked; then curl after sync. | website/page.yaml with go_package: true, commit + make check + make sync in ubunatic.com. |
| 6 | Repos were private; go get failed. Not checked before planning Task 8. |
go list -m after release. |
Owner made Codeberg public. |
| 7 | goself's bootstrap go 1.26.10 directive forced lmcoder's go directive up on go get. |
git diff go.mod in lmcoder. |
Directive lowered to 1.24, verified with a real go1.24.0 toolchain (v0.2.1). |
| 8 | Epic said "integrate into lmcoder install", but lmcoder uploads a local-arch llama.cpp runtime, so cross-arch deploy cannot apply there. | Reading provisionRuntimeForTarget. |
Narrowed pilot to localInstallBinary; added Deployer.Binary (v0.2.0). |
| 9 | Tried to preview the website page with sitegen build; three failed calls (missing flags, then page not in sink). |
Tool errors. | Stopped, recorded via harnez rate; relied on post-sync check. |
| 10 | go mod edit -retract rejected an inline comment; the && chain aborted before push. |
Command output. | Retract line added with Edit. |
Releases: 5 tags for 1 real feature set; three were corrective: v0.1.1 (#4), v0.2.1 (#7) and v0.2.2 (metadata only: the retraction of v0.1.0).
5. Quality & Invariants Audit
| Aspect | Verdict | Evidence |
|---|---|---|
| Architecture & module separation | Good | Thin public goself package; internal/{buildinfo,platform,xbuild,release,remote}; zero third-party deps. |
| Idempotency | Good | Install is temp-file + rename; re-deploy test installs twice and checks one file remains. |
| Backward compatibility | Diverged once | Version() -> BinaryVersion() rename in v0.1.1 (pre-1.0, no external users yet); v0.1.0 retracted. |
| Tests & verification | Improved | Unit tests in all packages; container test over real ssh; CI green on test, reuse, container-test (amd64 + arm64). Gap: xbuild.Module (network go install) has no automated test. |
| Lint | Clean | go vet (incl. -tags container), gofmt, reuse lint compliant. |
Overall quality verdict: improved from an empty skeleton to a tested, released library, with one shipped broken tag that is now retracted.
6. Efficiency & Velocity Assessment
- Commits: 22 since baseline, through
96b6e27; 7 touch onlyissues//docs/, 5 are release bumps, and 10 are other work: 7 code commits, 1 docs commit (b496e6c), 1 website commit (f850e23) and 1 tracker/config bootstrap commit (9edeb2e). - Lines outside
issues/(committed through96b6e27, excluding this story anddocs/README.md): +1792 / -26 across 27 files. Of that: tests +656, non-test Go +823, docs/skill/README/website +250, the rest Makefile, CI, Containerfile,go.mod. - Tickets: opened 5 (001 to 005); closed 2 (001, 002); 3 remain open.
- Releases: v0.1.0 (retracted), v0.1.1, v0.2.0, v0.2.1, v0.2.2.
- Flow: Tasks 1 to 7 ran autonomously in one stretch with no owner corrections. Owner input was needed only for decisions (vanity URL question, push/release, visibility, scope of lmcoder). Wasted cycles: three corrective releases, three sitegen probes, one failed retract command. No loops.
- No previous story exists, so smoothness cannot be compared; this story is the baseline.
7. Key Learnings & Evergreen Upstream
- Run
go vetafterharnez releasegenerates files, before tagging, or let release runmake checkon the bumped tree. A library must not export aVersionsymbol that collides with the generatedvar Version. Candidate fordocs/GoRelease.md. - Libraries declare the lowest go directive they need, verified with
GOTOOLCHAIN=go1.X.0 go vet ./...; bootstrap must not copy the local toolchain version. Candidate fordocs/Go.md. - Before planning a "publish and consume" step, check repo visibility and the vanity URL
(
curl '<path>?go-get=1',git ls-remote https://...). uman website synconly stages; deploying ismake check && make syncin ubunatic.com.- Container files: pass
-f Containerfilefor docker/podman portability; build test binaries withCGO_ENABLED=0when the target image is musl.
8. File & Diff Summary
- Created:
internal/{buildinfo,platform,xbuild,release,remote}/*.go(+ tests),container_test.go,testdata/sshd/Containerfile,.github/workflows/ci.yaml,skills/goself/SKILL.md,skill.go,website/page.yaml,version.go(generated),docs/studies/prior-art-self-replication.md, this story,issues/003..005. - Modified:
goself.go(full API),goself_test.go,Makefile(container-test),README.md,go.mod(go 1.24, retract v0.1.0),issues/001. - Other repos: ubunatic.com (goself page, deployed); lmcoder
f8962e5(local, unpushed). - Commits: see
git log bc30900..96b6e27.
9. Follow-Up Tickets & Review
- 003 onboard goself into harnez, 004 gokay, 005 neus.
- Learnings 1 and 2 are upstream doc changes for the harnez-managed
docs/: filed as harnez ticket 950. - Non-goal: lmcoder push (owner deferred it).
- Second-vendor review: done, see header.
- Ticket gate: all actionable follow-ups are filed (003 to 005); nothing new to file.