ubunatic.com
STUDY // 2026-10-25-goself-bootstrap-to-v0-2-2-story.md Source (Codeberg) ↗

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()), placeholder make 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@ver fails when GOBIN is set and writes to $GOPATH/bin/<os>_<arch>/ otherwise. This corrected a muddled paragraph in the research study and shaped xbuild.Module before it was written.
  • Reuse of in-house prior art. Reading lmcoder's host.go/release_fetch.go first gave the uname mapping, shell quoting and checksum flow; goself generalized rather than reinvented them.
  • Injectable runner. One Runner interface (local /bin/sh or system ssh) 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 only issues//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 through 96b6e27, excluding this story and docs/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

  1. Run go vet after harnez release generates files, before tagging, or let release run make check on the bumped tree. A library must not export a Version symbol that collides with the generated var Version. Candidate for docs/GoRelease.md.
  2. 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 for docs/Go.md.
  3. Before planning a "publish and consume" step, check repo visibility and the vanity URL (curl '<path>?go-get=1', git ls-remote https://...).
  4. uman website sync only stages; deploying is make check && make sync in ubunatic.com.
  5. Container files: pass -f Containerfile for docker/podman portability; build test binaries with CGO_ENABLED=0 when 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.