From 6d1b1ec689c62b1ea4d13862d8927cac68417d90 Mon Sep 17 00:00:00 2001 From: Jakub Zych Date: Wed, 16 Sep 2026 13:32:33 +0200 Subject: [PATCH] docs(01-02): complete layered config services and events plan - Record six-level compass, optional services and typed festival bus - Document TDD commits and auto-fixed toolchain/singleton issues --- .../01-02-SUMMARY.md | 173 ++++++++++++++++++ 1 file changed, 173 insertions(+) create mode 100644 .planning/phases/01-framework-kernel-foundation/01-02-SUMMARY.md diff --git a/.planning/phases/01-framework-kernel-foundation/01-02-SUMMARY.md b/.planning/phases/01-framework-kernel-foundation/01-02-SUMMARY.md new file mode 100644 index 0000000..ef3db77 --- /dev/null +++ b/.planning/phases/01-framework-kernel-foundation/01-02-SUMMARY.md @@ -0,0 +1,173 @@ +--- +phase: 01-framework-kernel-foundation +plan: 02 +subsystem: kernel +tags: [go, koanf, config, plugins, events, context, services] + +requires: + - phase: 01-framework-kernel-foundation + provides: Hello app boot path, party.Activate, compass.Load, HasConfig/HasCommands +provides: + - Six-level compass config with Set/Persist/Reload + - Optional plugin composition via HasPlugin and typed backpack services + - Typed festival event bus with Fire/Collect/UntilHandled + - towel request-context accessors +affects: [01-03, 01-04, 03] + +tech-stack: + added: + - github.com/knadh/koanf/providers/file v1.2.1 + - github.com/knadh/koanf/providers/confmap v1.0.1 + - github.com/knadh/koanf/providers/env/v2 v2.0.1 + patterns: + - Config priority: runtime Set, persisted overrides, SUMMER_ env, env YAML, base YAML, plugin defaults + - Optional integration without importing the optional package (HasPlugin + pact interface) + - App-owned service registry and event bus; no process-global request state + +key-files: + created: + - compass/env.go + - compass/persist.go + - backpack/services.go + - festival/bus.go + - towel/context.go + - examples/hello/plugins/optional/plugin.go + modified: + - compass/config.go + - party/registry.go + - backpack/app.go + - pact/capabilities.go + - examples/hello/plugins/greeter/plugin.go + - examples/hello/summer.yaml + +key-decisions: + - "Runtime Set lives in a separate koanf tree so Reload drops it and rebuilds disk layers" + - "pact.OptionalMessage is the shared service interface; greeter never imports the optional module" + - "Collect/UntilHandled read Collectable/Handleable on the event so Listen stays func(ctx, T) error" + - "HasPlugin uses the full activated ID set recorded before Register, not the Booted subset" + - "Panic recovery names the owner plugin ID and omits event payload (T-01-05)" + +patterns-established: + - "Pattern: plugin embed.FS config/config.yaml merged at the bare plugin ID via MergeAt" + - "Pattern: SUMMER_ keys split only on __; single underscores stay in the leaf" + - "Pattern: Publish in Register, Lookup in Boot so optional services are visible regardless of Boot order" + +requirements-completed: [KERN-01, KERN-02, KERN-03, KERN-05, KERN-06, KERN-07, KERN-08] + +duration: 25min +completed: 2026-09-16 +--- + +# Phase 1 Plan 2: Layered Config, Services and Events Summary + +**Six-level koanf config with Set/Persist/Reload, optional plugin services without a hard import, and typed festival dispatch with context-scoped request state** + +## Performance + +- **Duration:** 25 min +- **Started:** 2026-09-16T11:06:17Z +- **Completed:** 2026-09-16T11:31:20Z +- **Tasks:** 3 +- **Files modified:** 40 + +## Accomplishments + +- Compass loads plugin defaults, sorted base YAML, env overlays, `SUMMER_` variables (split on `__`), persisted overrides and runtime Set in D-09 order; Persist is atomic with `0600` files; Reload clears Set +- `golem15.optional` is a third hello plugin that publishes `pact.OptionalMessage`; greeter uses `HasPlugin` plus typed lookup and boots with or without it +- App-owned `festival.Bus` implements Fire (join errors), Collect (later key wins, partial payload) and UntilHandled, recovers panics with owner IDs, and `towel` carries actor/org/collection/locale on `context.Context` + +## Task Commits + +Each task was committed atomically (TDD RED then GREEN): + +1. **Task 1 RED: failing layered config tests** - `255de60` (test) +2. **Task 1 GREEN: layered compass config** - `cc44a1f` (feat) +3. **Task 2 RED: failing optional service tests** - `5f22918` (test) +4. **Task 2 GREEN: optional plugin services and HasPlugin** - `8696973` (feat) +5. **Task 3 RED: failing event and context tests** - `36c152f` (test) +6. **Task 3 GREEN: typed events with request context** - `a654e96` (feat) + +**Plan metadata:** pending (docs: complete plan) + +## Files Created/Modified + +- `compass/config.go` / `env.go` / `persist.go` - layered load, env mapping, `.env` fill, Set/Persist/Reload +- `party/registry.go` - HasConfig merge and SetPlugins before Register +- `backpack/app.go` / `services.go` - HasPlugin, typed Publish/Lookup, app-owned Events bus +- `pact/capabilities.go` - OptionalMessage plus documented future KERN-03 families +- `festival/bus.go` - typed Listen/Fire/Collect/UntilHandled +- `towel/context.go` - unexported-key request accessors +- `examples/hello/plugins/optional/` - optional plugin module +- `examples/hello/plugins/greeter/plugin.go` - optional lookup and hello event demo +- `examples/hello/summer.yaml` / `plugins.gen.go` / `go.work` - third plugin wired + +## Decisions Made + +- Keep runtime Set off the disk tree so Reload is a full rebuild plus an empty overlay +- Put the optional service interface in `pact`, not in the optional plugin package +- Model Collect/UntilHandled as event interfaces (`Collected`, `IsHandled`) so one `Listen[T]` serves all three modes +- Record activated plugin IDs on the app before Register so HasPlugin sees not-yet-Booted plugins +- Recover panics as `festival: plugin panicked` without event contents + +## Deviations from Plan + +### Auto-fixed Issues + +**1. [Rule 2 - Missing Critical] Restore toolchain go1.27.0 after go mod tidy** +- **Found during:** Task 1 (provider install) +- **Issue:** `go mod tidy` dropped `toolchain go1.27.0` (same as Plan 01) +- **Fix:** Re-added the directive on root and example modules +- **Files modified:** `go.mod`, example `go.mod` files +- **Verification:** files contain `toolchain go1.27.0` +- **Committed in:** `cc44a1f` (Task 1 GREEN) + +**2. [Rule 1 - Bug] Greeter extra leaked across Activate on the init singleton** +- **Found during:** Task 2 (hello without-optional test) +- **Issue:** `party.Register` stores one plugin instance; Boot with optional set `extra`, later Boot without optional left the old string +- **Fix:** Clear `extra` at the start of Boot +- **Files modified:** `examples/hello/plugins/greeter/plugin.go` +- **Verification:** `TestGreeterRunsWithoutOptionalPlugin` passes +- **Committed in:** `8696973` (Task 2 GREEN) + +**3. [Rule 1 - Bug] Hello manifest test still expected two plugins** +- **Found during:** Task 2 (`go test ./...`) +- **Issue:** `internal/build.TestLoadHelloManifest` hard-coded plugin count 2 +- **Fix:** Expect `golem15.optional` as the third manifest entry +- **Files modified:** `internal/build/build_test.go` +- **Verification:** `go test ./internal/build` passes +- **Committed in:** `8696973` (Task 2 GREEN) + +--- + +**Total deviations:** 3 auto-fixed (1 missing critical, 2 bugs) +**Impact on plan:** Required for D-05, correct optional skip, and a green suite. No scope creep. + +## Issues Encountered + +- `go get` of koanf file/env/confmap providers pulled `fsnotify` transitively through the file provider; it is indirect only and unused by compass (no Watch). Plan 03 still owns `summer dev`. + +## Authentication Gates + +None. + +## User Setup Required + +None - no external service configuration required. + +## Next Phase Readiness + +Ready for `01-03-PLAN.md` (watch loop and CLI UX). Config, optional composition, services and events are in place on the hello path. Do not add HTTP/DB/auth here. + +## Self-Check: PASSED + +- Created files exist on disk (`compass/env.go`, `compass/persist.go`, `backpack/services.go`, `festival/bus.go`, `towel/context.go`, optional plugin) +- Commits `255de60`, `cc44a1f`, `5f22918`, `8696973`, `36c152f`, `a654e96` exist +- Root and hello `go vet ./...` and `go test ./...` passed +- `go test -race ./compass ./party ./backpack ./festival ./towel` passed +- `go run . greeter:hello` prints layered config, optional extra, and event results +- Greeter source has no import of the optional plugin module +- STATE.md and ROADMAP.md were not updated in this worktree + +--- +*Phase: 01-framework-kernel-foundation* +*Completed: 2026-09-16*