0013 — Phase 5a close: hearth scaffold + Driver interface locked
Date: 2026-05-24 Status: Accepted Phase: 5a (of Phase 5 — HEARTH LocalDocker)
Context
Phase 5a is the bootstrap sub-phase for HEARTH per
docs/specs/2026-05-04-rocky-phase-5.md §5a: stand up rocky-hq/hearth
(Go, MIT), declare the locked Driver interface, ship FakeDriver with
the protocol-contract test suite, wire CI (lint + test + gated
integration stub), and add the submodule to the parent superproject.
Decision
5a is closed. The artefacts landed:
rocky-hq/hearthrepo created (MIT). First merged commit:a8edf46bbf9f977d6a617b1e694142ad09ea9f53.Driverinterface ininternal/driver/driver.gomatches Phase 5 spec §5 verbatim.- Placeholder types in
internal/driver/types_local.gocarry thePHASE-5A-LOCALbanner. 5b replaces them wholesale. FakeDriver+ 5 contract tests (fake_test.go) cover all four guarantees (idempotent Provision, read-only Status, slug-preserving Upgrade, terminal Teardown, ctx-cancel honour) for every future driver.- CI:
lint,test, and a gatedintegrationstub job (5c populates it). - Parent submodule pin landed.
Drift from D0004 (Go conventions)
D0004 says "kahn-hq baseline .golangci.yml copied verbatim". On
2026-05-24 no such file was located in ~/code/workspace/kahn-hq. The
.golangci.yml landed by 5a is derived from k41ex/kalnet/.golangci.yml
(a sibling repo by the same operator), trimmed for a small interface-only
module. If the real kahn-hq baseline turns up later, swap is a one-PR
diff. D0004 is unchanged (append-only); this decision records the drift
so future Go submodules know not to assume the kahn-hq path resolves.
Consequences
- Phase 5b can proceed: it adds the
./hearthsubpath tocontracts/, bumps to0.2.0, and emitsgo/hearth/types.govia quicktype. The hearth-side change in 5b is a wholesale replacement ofinternal/driver/types_local.gowith thegithub.com/rocky-hq/contracts/go/hearthimport — every reference uses the same exported names, so the diff is mechanical. - Phase 5c can proceed independently: implementing
LocalDockeragainst the locked interface, withfake_test.goas the contract to satisfy. - Parent
verify-scaffold.shnow requireshearth/to be present.
Carry-forwards (deferred to 5b/5c)
The following items surfaced during the Phase 5a review and are explicitly deferred. Each future sub-phase's implementer should read this section.
1. CI integration trigger needs a path filter (defer to 5c)
The current integration job in hearth/.github/workflows/ci.yml fires
on every push to main. D0004 says it should be path-filtered to
internal/driver/localdocker/** or test/integration/**. In 5a this is
harmless (the stub job exits immediately). The 5c PR that lands
testcontainers MUST add the path filter as part of the same PR, otherwise
CI will run the full Docker suite on doc-only pushes.
2. map[string]interface{} → map[string]any in internal/driver/types_local.go
Pre-1.18 spelling in a Go 1.25 module. Skip the patch: types_local.go
is replaced wholesale by github.com/rocky-hq/contracts/go/hearth codegen
in 5b, so churning the placeholder is wasted work. Listing it here so 5b's
implementer knows the swap is the fix.
3. golangci-lint version drift from D0004
D0004 names v1.62.2; hearth CI uses v1.64.8 because pre-built
v1.62.2 was built with go1.23 and refuses to load configs for Go 1.25
modules. Resolution: go install ...@v1.64.8 so the binary is compiled
against the CI toolchain. D0004 is append-only (MR-7), so don't amend it;
this decision records the operational reality.
4. British→US spelling in internal/driver/driver.go godoc
"honour"→"honor", "cancelled"→"canceled". Required by the misspell
linter with locale: US. Contract semantics preserved; consistency with
the linter config.
5. .golangci.yml stutter exclusion for DriverName and FakeDriver
These names are locked by the spec/plan and cannot be renamed. The exclusion is global rather than path-scoped — if future packages add genuinely problematic stutters, this could mask them. Acceptable for 5a's tiny surface; revisit at the end of Phase 5.
Note: the kahn-hq .golangci.yml baseline reference in D0004 was not
located on disk (the original drift the plan already calls out) — the lint
baseline derives from k41ex/kalnet/.golangci.yml, trimmed.
References
- Phase 5 spec:
docs/specs/2026-05-04-rocky-phase-5.md - Plan:
docs/plans/2026-05-24-hearth-bootstrap-phase-5a.md - D0004:
docs/decisions/2026-05-03-phase-5-go-conventions.md - Hearth PR: https://github.com/rocky-hq/hearth/pull/1
- Parent PR: https://github.com/rocky-hq/rocky/pull/55