diff --git a/.planning/ROADMAP.md b/.planning/ROADMAP.md
index 5eb56c1..99ed3e2 100644
--- a/.planning/ROADMAP.md
+++ b/.planning/ROADMAP.md
@@ -7,6 +7,7 @@ v1 ports the Płytarium (fonoteka) headless PHP backend to a single Go binary wi
## Phases
**Phase Numbering:**
+
- Integer phases (1, 2, 3): Planned milestone work
- Decimal phases (2.1, 2.2): Urgent insertions (marked with INSERTED)
@@ -31,209 +32,271 @@ Decimal phases appear between their surrounding integers in numeric order.
## Phase Details
### Phase 1: Framework kernel foundation
+
**Goal**: The `summer` binary boots from layered YAML config, plugins self-register through one required interface plus optional capability interfaces, a typed event bus and service registry are available, and a CLI command framework with a dev watch loop exists — built only as far as the first vertical slice will need it, per the interleaved-not-sequential kernel approach.
**Mode:** mvp
**Depends on**: Nothing (first phase)
**Repos:** summercms.go
**Requirements**: KERN-01, KERN-02, KERN-03, KERN-04, KERN-05, KERN-06, KERN-07, KERN-08, KERN-09, CLI-01
**Success Criteria** (what must be TRUE):
+
1. `summer build` regenerates the blank-import plugin list and produces a binary that boots from a layered YAML config (base files, env overlay directory, per-plugin namespace, environment variables) with dot-path access.
2. A throwaway plugin registered via the Plugin interface has its Register phase run for all plugins before any Boot phase runs, in `Requires()`-topological order, verified by a test with reordered input.
3. A plugin can type-assert an optional capability interface (e.g. `HasModels`) and skip integration with another plugin that isn't registered, with no hard import.
4. The typed event bus supports fire-and-forget, fire-and-collect, and fire-until-handled dispatch, exercised by unit tests; per-request state travels only through `context.Context`, never a package-level global.
5. The `summer` CLI discovers a registered command and renders rich output (spinner, progress, table, prompts) with non-TTY degradation, and a dev watch loop rebuilds and restarts the binary on source change.
-**Plans**: TBD
+
+**Plans**: 4 plans
+
+Plans:
+**Wave 1**
+
+- [ ] 01-01-PLAN.md — Build and boot the separate hello app through the shared command kernel
+
+**Wave 2** *(blocked on Wave 1 completion)*
+
+- [ ] 01-02-PLAN.md — Add layered config, optional plugin composition, services and typed events
+
+**Wave 3** *(blocked on Wave 2 completion)*
+
+- [ ] 01-03-PLAN.md — Add plugin scaffolding, rich output and the watch rebuild loop
+
+**Wave 4** *(blocked on Wave 3 completion)*
+
+- [ ] 01-04-PLAN.md — Complete unit, integration and race-enabled verification
### Phase 2: API parity harness bootstrap
+
**Goal**: A fixture recorder captures request/response pairs from the running PHP backend — including real Nuxt and MCP flows — and a replay-and-diff harness with a normalizer for nondeterministic fields can run against any HTTP backend. This is a day-one workstream with no dependency on framework progress, since it only needs a running PHP backend to record against.
**Mode:** mvp
**Depends on**: Nothing (parallel with Phase 1)
**Repos:** summercms.go, fonoteka.go
**Requirements**: QA-01, QA-02, QA-03
**Success Criteria** (what must be TRUE):
+
1. The fixture recorder captures a request/response pair from the live PHP backend for at least one route and stores it as a replayable fixture.
2. The replay-and-diff harness runs a recorded fixture against an arbitrary `httptest.Server` backend and reports a byte-level diff.
3. The harness's normalizer and assertions explicitly catch the parity classes named in research (nil vs `[]`, date format, tri-state booleans, envelope/conditional keys) on a synthetic test case, not just status codes.
4. `go vet` and `go test ./...` are green, and the harness's own integration tests run against testcontainers Postgres.
+
**Plans**: TBD
### Phase 3: First vertical slice — genres end to end
+
**Goal**: `GET /_fonoteka/api/v1/genres` passes the parity diff end to end (config → DB → plugin registry → JWT-guarded routing → GORM → JSON), proving every kernel layer together before any further kernel abstraction. Touches the JWT auth guard on the request path — treat as security-load-bearing and apply the security-review agent even though the guard is a throwaway seeded-token implementation at this stage.
**Mode:** mvp
**Depends on**: Phase 1, Phase 2
**Repos:** summercms.go, fonoteka.go
**Requirements**: DATA-01, DATA-02, HTTP-01, HTTP-02, QA-04
**Success Criteria** (what must be TRUE):
+
1. GORM connects to Postgres over one shared `*sql.DB` (pgx stdlib); a gormigrate migration set runs up and down for a single plugin with per-plugin version tracking, and `AutoMigrate` is not the schema source.
2. A plugin registers a route group on `net/http` ServeMux with typed params, and a request is served through the full middleware pipeline (recover, CORS, locale, auth group, must-change-password, org context, rate limit, handler).
3. A JWT-guarded `GET /_fonoteka/api/v1/genres` route returns a real `Genre` row read from Postgres.
4. The response is diffed byte-for-byte against a fixture recorded from the live PHP backend using the Phase 2 harness, and the diff is green.
+
**Plans**: TBD
### Phase 4: CLI scaffolding, i18n and mail
+
**Goal**: Scaffolding commands generate compiling stubs for every plugin artifact type, and plugins can register translated, CLDR-pluralized, namespaced strings and mail templates rendered through a pluggable driver interface.
**Mode:** mvp
**Depends on**: Phase 1
**Repos:** summercms.go
**Requirements**: CLI-02, I18N-01, I18N-03
**Success Criteria** (what must be TRUE):
+
1. `summer make:plugin`, `make:model`, `make:migration`, `make:command`, `make:job` and `make:admin-controller` each generate stubs that compile and pass `go vet`.
2. A translation key `vendor.plugin::group.key` resolves for pl and en, including a CLDR plural form, loaded from per-plugin per-locale YAML files with parameter substitution.
3. A plugin registers a mail template and layout by dotted name with the per-locale suffix convention, and it renders via `html/template` through a driver interface (SMTP via go-mail) in a test send.
+
**Plans**: TBD
### Phase 5: Data layer full fidelity
+
**Goal**: All 25 Płytarium models and 27 migrations are ported with matching relations, casts, hooks, and the fillable/hidden/encrypted-cast mass-assignment and serialization discipline. This is security-load-bearing — mass-assignment boundaries and encrypted-at-rest credential casts are named security invariants in the PHP source — apply the security-review agent and the DTO-vs-model convention from the first model onward.
**Mode:** mvp
**Depends on**: Phase 1, Phase 3
**Repos:** summercms.go, fonoteka.go
**Requirements**: DATA-03, DATA-04, DATA-05, DATA-06, DATA-07, DATA-08, DATA-09, DATA-10, DATA-11, CLI-03
**Success Criteria** (what must be TRUE):
+
1. All 25 models exist with matching table names, columns, indexes and defaults; all 27 migrations run up and down individually, and `summer migrate:rollback --plugin=fonoteka` rolls back only that plugin's last migration.
2. A many-to-many relation with pivot business columns (`album_artists.sort_order`, `CollectionEditor.role/granted_at/granted_by`) round-trips correctly for a 3+ artist album; belongsTo/hasOne/hasMany relations return ordered results.
3. Every write endpoint uses a request DTO that enforces its model's fillable allow-list (a fuzz test posting unknown fields asserts they are rejected or ignored, never persisted), and serialization honors the hidden deny-list with an explicit per-call override.
4. The money cast round-trips the PHP ceiling and blank-string cases as a fixed 4-decimal JSON string (never `float64`), and an encrypted-at-rest credential column is AES-GCM encrypted at rest and hidden from serialization.
5. Paginated responses use the exact `{data, meta{current_page,last_page,per_page,total}}` envelope with no `links` key; another plugin extends a model's lifecycle through the GORM callback registry and a companion migration without editing the owning plugin's file; soft-deletable + uniquely-keyed tables pass a delete-then-recreate test.
+
**Plans**: TBD
### Phase 6: HTTP routing, auth groups and rate limiting
+
**Goal**: The three mutually exclusive auth groups (JWT, personal token, public/onboarding) share handlers with correct route subsets, named rate-limit buckets are ported 1:1, and OAuth/RFC routes are structurally exempted from any house envelope or error middleware. Security-load-bearing — auth guard registry, rate limiting and the SSRF-guarded outbound fetch helper all live here; apply the security-review agent.
**Mode:** mvp
**Depends on**: Phase 3, Phase 5
**Repos:** summercms.go, fonoteka.go
**Requirements**: HTTP-03, HTTP-04, HTTP-05, HTTP-06, HTTP-07, HTTP-08, HTTP-09
**Success Criteria** (what must be TRUE):
+
1. The same handler serves both a JWT-authenticated request under `/_fonoteka/api/v1` and a personal-token request under `/api/v1/fonoteka`, with public/onboarding groups reachable without auth; unknown and malformed ids on ownership-scoped resources both return 404.
2. All seven named rate-limit buckets are enforced with the documented keys and limits, including a route stacking two limiters.
3. Response conventions hold under test: empty arrays serialize as `[]`, timestamps carry `+00:00`, tri-state booleans keep `null`, conditional keys are omitted not nulled; an OAuth-group route carries no house envelope or error middleware, verified by route-registration inspection.
4. The guarded outbound fetch helper rejects a non-allow-listed host and enforces a byte cap and timeout on a user-supplied cover URL fetch (manual cover URL, Discogs cover).
5. OpenAPI is generated from swaggo/swag annotations on handlers and `openapi-typescript` produces valid TypeScript types from it; CORS and JSON body-size limits match the PHP deployment.
+
**Plans**: TBD
### Phase 7: User plugin and authentication
+
**Goal**: The user plugin is ported with registration, login, JWT issue/refresh, organizations, personal API tokens and the must-change-password lock. Security-load-bearing — password auth, token scope ceilings and the session lock all live here; apply the security-review agent.
**Mode:** mvp
**Depends on**: Phase 6
**Repos:** summercms.go, fonoteka.go
**Requirements**: AUTH-01, AUTH-02, AUTH-03, AUTH-04, I18N-02
**Success Criteria** (what must be TRUE):
+
1. A user can register, log in, log out, reset a forgotten password by email, verify email, and receive/refresh a JWT (golang-jwt) with the same claims and cookie behavior the Nuxt app expects.
2. Organization fields appear on the user payload through a fire-and-collect event the fonoteka plugin populates, without the user plugin importing fonoteka.
3. A personal API token is created with a read|write|ai scope ceiling, listed, and revoked; a scope-checking middleware rejects an out-of-scope request.
4. The must-change-password flag returns 423 on the authenticated surface except the locale and password-change routes, and locale resolves per request from the user's persisted `preferred_locale` with header fallback even while the lock is active.
+
**Plans**: TBD
### Phase 8: OAuth2.1 authorization server
+
**Goal**: An RFC 8414/6749/7591-compliant OAuth2.1 server on zitadel/oidc serves fonoteka-mcp and the ChatGPT connector unchanged, including exact `WWW-Authenticate` and protected-resource-metadata headers. Security-load-bearing — bearer tokens, PKCE and constant-time secret comparison all live here; apply the security-review agent.
**Mode:** mvp
**Depends on**: Phase 6, Phase 7
**Repos:** summercms.go, fonoteka.go
**Requirements**: AUTH-05, AUTH-06, AUTH-07
**Success Criteria** (what must be TRUE):
+
1. RFC 8414 metadata is served unenveloped at its well-known path; authorize with PKCE and a consent screen works, and the token endpoint issues/refreshes authorization_code and refresh_token flows, all as unwrapped RFC 6749 bodies with the PHP cache headers (`Cache-Control: no-store`, `Pragma: no-cache`).
2. RFC 7591 dynamic client registration and RFC 8707 resource parameter tolerance both work against a real client registration call.
3. A 401 on a protected route carries the exact `WWW-Authenticate` and protected-resource-metadata header contract, verified against fonoteka-mcp's actual discovery flow, not just a Go unit test.
4. Connected apps can be listed and revoked; `OAuthClient`/`OAuthAuthCode`/`OAuthRefreshToken` models persist correctly; fonoteka-mcp completes its install and auth flow unchanged; client-secret comparison uses `crypto/subtle.ConstantTimeCompare`.
+
**Plans**: TBD
**Research flag:** yes
### Phase 9: Backend admin authentication and schema pipeline
+
**Goal**: Backend admin users with roles are separate from frontend users and gate navigation and controller access; `fields.yaml`/`columns.yaml` drive a JSON form/list schema, including a first-class relation-manager schema replacing the one `partial` field. Security-load-bearing — separate admin authentication and permissions registry live here; apply the security-review agent. This is also the least-precedented design surface in the research (one real relation-manager usage in the PHP source, no direct library equivalent).
**Mode:** mvp
**Depends on**: Phase 5, Phase 6
**Repos:** summercms.go, fonoteka.go
**Requirements**: AUTH-08, ADMIN-01, ADMIN-02, ADMIN-03, ADMIN-04, ADMIN-05
**Success Criteria** (what must be TRUE):
+
1. A backend admin user with a role logs in separately from frontend users, and navigation/controller access is gated by the permissions registry.
2. `fields.yaml` for a real controller parses (goccy/go-yaml) into a JSON form schema covering text, textarea, checkbox, switch, dropdown (model-method options) and relation (nameFrom, emptyOption), with span/tabs/context/attributes layout hints.
3. `columns.yaml` parses into a JSON list schema with searchable/sortable/relation columns and datetime/switch renderers.
4. The relation-manager schema supports search/link/unlink/manage-or-view lists for Collections' editors tab, replacing the `partial` field entirely.
5. Admin CRUD endpoints expose `listExtendQuery`/`formExtendQuery`/`formBeforeCreate`/`formBeforeUpdate`/`relationExtendManageQuery` hooks, bulk delete runs each record's lifecycle hooks, and the Settings model binds to a settings screen through the same schema pipeline.
+
**Plans**: TBD
**Research flag:** yes
### Phase 10: Admin Vue SPA
+
**Goal**: A minimal Vue 3 + TypeScript admin SPA renders login, permission-gated navigation, lists, forms and the relation manager for Albums, Artists, Collections, Genres and Styles, typed from the generated OpenAPI document.
**Mode:** mvp
**Depends on**: Phase 9
**Repos:** summercms.go, fonoteka.go
**Requirements**: ADMIN-06
**Success Criteria** (what must be TRUE):
+
1. An admin logs in through the SPA and sees only the navigation items their permissions allow.
2. Each of the five controllers (Albums, Artists, Collections, Genres, Styles) renders a working list and form generated from its JSON schema.
3. The Collections form's relation manager lets an admin search, link and unlink an editor.
4. API calls in the SPA use TypeScript types generated from the OpenAPI document, with no hand-maintained duplicate type.
+
**Plans**: TBD
**UI hint**: yes
### Phase 11: Jobs, realtime and search infrastructure
+
**Goal**: River jobs run on the correct dual-driver split, Centrifugo publishing and channel authorization match the existing server, and Typesense sync stays a re-gated pre-filter — all brought up before the API phases that depend on them (album search needs Typesense sync, CSV import needs River jobs, notifications need the realtime publisher). River's dual-driver split and the Centrifugo/Typesense contracts are the least-implemented-and-verified parts of this research pass.
**Mode:** mvp
**Depends on**: Phase 5, Phase 7
**Repos:** summercms.go, fonoteka.go
**Requirements**: JOBS-01, CLI-04, CLI-06, RT-01, RT-02, RT-03, SRCH-01
**Success Criteria** (what must be TRUE):
+
1. River runs on the shared `*sql.DB` (`riverdatabasesql`, transactional enqueue) with a separate `riverpgxv5` client for LISTEN/NOTIFY dispatch, verified by a timed test that job pickup is not poll-interval latency; job outcomes (complete, fail, skip) are queryable through a job manager service.
2. The queue worker runs via `summer queue:work` and the scheduler runs recurring commands via `summer schedule:run`.
3. The websockets plugin issues connection and subscription JWTs and publishes to the existing Centrifugo server with the same secret, claims and channel names, served at `GET /api/realtime/token`.
4. A channel-namespace authorizer registry re-validates on every subscribe; a broadcastable model interface with bulk-write suppression emits exactly one summary event for a bulk operation.
5. Typesense sync is scoped by `collection_id` behind a settings kill-switch and degrades gracefully without DB/config.
+
**Plans**: TBD
**Research flag:** yes
### Phase 12: Płytarium API — Collections and Albums
+
**Goal**: Collections and Albums endpoints are ported with byte-compatible request/response shapes, including active-context switching, editor invitations, ratings, reservations, cover handling and search.
**Mode:** mvp
**Depends on**: Phase 5, Phase 6, Phase 7, Phase 11
**Repos:** fonoteka.go
**Requirements**: API-01, API-02
**Success Criteria** (what must be TRUE):
+
1. Collections CRUD, the `me/context` active-collection switch (returning an opaque channel name), editor invitation/acceptance, share-link regeneration and public token views all pass the parity diff.
2. Albums CRUD, ratings, reservations, photo upload, manual cover URL and Discogs cover price all pass the parity diff.
3. Album search treats Typesense results as a pre-filter re-gated in SQL, verified by a security test that a stale/mis-scoped search document cannot leak an unauthorized result.
4. Artists/genres/styles lookup endpoints used by the Albums UI pass the parity diff.
+
**Plans**: TBD
### Phase 13: Płytarium API — wishlist, notifications, CSV, credentials, public routes
+
**Goal**: The remaining core API surface — wishlist, notifications, CSV import/export, per-user/org credentials, and onboarding/public/invitation routes — is ported with byte-compatible shapes and their own public rate-limit buckets.
**Mode:** mvp
**Depends on**: Phase 11, Phase 12
**Repos:** fonoteka.go
**Requirements**: API-03, API-04, API-05, API-06, API-07
**Success Criteria** (what must be TRUE):
+
1. Wishlist items, subscriptions, `public-wishlist/{token}` views and purchase/digest triggers pass the parity diff.
2. Notifications list/mark-read/prune endpoints pass the parity diff (the realtime token endpoint itself is owned by the websockets plugin, ported in Phase 11).
3. CSV import runs as a multi-step session (store, show/poll, mapping patch, per-row edit, commit, cancel) and CSV export works on both authenticated groups, all passing the parity diff.
4. Per-user and per-org Discogs/AI credentials CRUD store encrypted values, honor the org-lock flag, and resolve env-to-org-to-user correctly.
5. Onboarding, public and invitation-inspection routes are reachable without auth and enforce their own public rate-limit buckets.
+
**Plans**: TBD
### Phase 14: Domain jobs and external integrations
+
**Goal**: The domain-specific River jobs (CSV import write, Discogs match, wishlist digest), the reindex command, the Discogs client and AI cover recognition are ported on top of the Phase 11 jobs/realtime/search infrastructure and the Phase 13 API surface they serve.
**Mode:** mvp
**Depends on**: Phase 11, Phase 13
**Repos:** fonoteka.go (plus summercms.go only if a framework helper is needed)
**Requirements**: JOBS-02, JOBS-03, SRCH-02, INTG-01, INTG-02, API-08, CLI-05
**Success Criteria** (what must be TRUE):
+
1. The CSV import write job and the self-redispatching Discogs match job (240s timeout, self-redispatching with a delay on a Discogs rate-limit error) both complete correctly.
2. The wishlist digest job coalesces a 30-minute window and deletes its queue row on completion.
3. The `reindex` command asserts zero `collection_id`-0 documents before and after and can drop the legacy index.
4. The Discogs client enforces its proactive rate threshold, bounded wait budget, retry-after fallback and host-locked cover fetch.
5. AI cover recognition works through both Anthropic and OpenAI-compatible adapters with per-credential model/base-URL overrides.
6. Feedback submissions and sitemap output work; the ported `oauth-client`/`prune-notifications`/`reindex` commands all run correctly.
+
**Plans**: TBD
### Phase 15: Cutover
+
**Goal**: The parity harness is green on all 154 routes and `vue-fonoteka-app` and `fonoteka-mcp` run unchanged against the Go backend in daily use — the project's definition of done.
**Mode:** mvp
**Depends on**: Phase 2, Phase 8, Phase 9, Phase 10, Phase 12, Phase 13, Phase 14
**Repos:** fonoteka.go, summercms.go
**Requirements**: API-09, QA-05
**Success Criteria** (what must be TRUE):
+
1. All 154 routes are registered on the correct auth groups with identical paths, methods and status codes.
2. The parity harness runs green across recorded fixtures for all 154 routes.
3. `vue-fonoteka-app` runs unchanged against the Go backend for a full manual session (browse, edit, upload, invite, OAuth-connect an MCP client).
4. `fonoteka-mcp` completes its install/auth flow and a representative set of tool calls unchanged against the Go backend.
+
**Plans**: TBD
## Progress
@@ -244,7 +307,7 @@ Phases execute in numeric order: 1 → 2 → 3 → 4 → 5 → 6 → 7 → 8 →
| Phase | Plans Complete | Status | Completed |
|-------|----------------|--------|-----------|
-| 1. Framework kernel foundation | 0/TBD | Not started | - |
+| 1. Framework kernel foundation | 0/4 | Planned | - |
| 2. API parity harness bootstrap | 0/TBD | Not started | - |
| 3. First vertical slice — genres end to end | 0/TBD | Not started | - |
| 4. CLI scaffolding, i18n and mail | 0/TBD | Not started | - |
diff --git a/.planning/STATE.md b/.planning/STATE.md
index a4803ab..cf18dd6 100644
--- a/.planning/STATE.md
+++ b/.planning/STATE.md
@@ -2,14 +2,14 @@
gsd_state_version: 1.0
milestone: v1.0
milestone_name: milestone
-status: planning
-stopped_at: Phase 1 context gathered
-last_updated: "2026-09-16T10:03:21.568Z"
-last_activity: 2026-09-16 — ROADMAP.md and STATE.md created from PROJECT.md, REQUIREMENTS.md and research/{SUMMARY,ARCHITECTURE,PITFALLS}.md
+status: executing
+stopped_at: Phase 1 plans ready
+last_updated: "2026-09-16T10:29:26.505Z"
+last_activity: 2026-09-16 -- Phase 1 planning complete
progress:
total_phases: 15
completed_phases: 0
- total_plans: 0
+ total_plans: 4
completed_plans: 0
percent: 0
---
@@ -26,9 +26,9 @@ See: .planning/PROJECT.md (updated 2026-09-16)
## Current Position
Phase: 1 of 15 (Framework kernel foundation)
-Plan: TBD (roadmap just created, plans not yet written)
-Status: Ready to plan
-Last activity: 2026-09-16 — ROADMAP.md and STATE.md created from PROJECT.md, REQUIREMENTS.md and research/{SUMMARY,ARCHITECTURE,PITFALLS}.md
+Plan: 0 of 4 (Phase 1 plans ready)
+Status: Ready to execute
+Last activity: 2026-09-16 -- Phase 1 planning complete
Progress: [░░░░░░░░░░] 0%
diff --git a/.planning/phases/01-framework-kernel-foundation/01-01-PLAN.md b/.planning/phases/01-framework-kernel-foundation/01-01-PLAN.md
new file mode 100644
index 0000000..23ebd97
--- /dev/null
+++ b/.planning/phases/01-framework-kernel-foundation/01-01-PLAN.md
@@ -0,0 +1,145 @@
+---
+phase: 01-framework-kernel-foundation
+plan: 01
+type: execute
+wave: 1
+depends_on: []
+files_modified:
+ - go.mod
+ - go.sum
+ - go.work
+ - party/registry.go
+ - backpack/app.go
+ - pact/capabilities.go
+ - compass/config.go
+ - bonfire/command.go
+ - bonfire/root.go
+ - internal/build/build.go
+ - cmd/summer/main.go
+ - examples/hello/summer.yaml
+ - examples/hello/go.mod
+ - examples/hello/main.go
+ - examples/hello/plugins.gen.go
+ - examples/hello/hello_test.go
+ - examples/hello/plugins/base/go.mod
+ - examples/hello/plugins/base/plugin.go
+ - examples/hello/plugins/greeter/go.mod
+ - examples/hello/plugins/greeter/plugin.go
+ - examples/hello/config/app.yaml
+autonomous: true
+requirements: [KERN-01, KERN-02, KERN-03, KERN-04, CLI-01]
+must_haves:
+ truths:
+ - "D-01 D-02: An installed `summer` tool builds a separate hello app binary, and both entry points use the same `bonfire` root-command constructor."
+ - "D-03 D-04 D-05: The permanent hello app has separate plugin modules in root `go.work`, imports `git.golem15.com/golem15/summercms`, and uses a concrete Go 1.27 toolchain directive."
+ - "D-15 D-17: The hello app boots plugins and executes `greeter:hello` through a `bonfire.Command` adapter with injected Input and Output."
+ - "The generated import list preserves the explicit manifest order while the plugin registry orders lifecycle by `Requires()`."
+ artifacts:
+ - path: internal/build/build.go
+ provides: Manifest-driven code generation and app build
+ - path: party/registry.go
+ provides: Required plugin interface and activation
+ - path: bonfire/root.go
+ provides: Shared cobra command construction
+ - path: examples/hello/summer.yaml
+ provides: Ordered hello plugin manifest
+ key_links:
+ - from: cmd/summer/main.go
+ to: bonfire/root.go
+ via: Shared root command constructor
+ - from: examples/hello/main.go
+ to: party/registry.go
+ via: Generated app activation with ordered plugin IDs
+ - from: examples/hello/plugins.gen.go
+ to: examples/hello/plugins/greeter/plugin.go
+ via: Blank import triggers self-registration
+---
+
+
+As a framework developer, I can build a tiny app from two compiled plugins and run its namespaced hello command, so the first kernel API is proven by a real binary.
+
+Purpose: Establish the thinnest executable path that future Phase 1 work can extend.
+Output: Framework tool, shared runtime command kernel, plugin registry, minimal config, root workspace, and permanent `examples/hello` app.
+
+
+
+@$HOME/.codex/get-shit-done/workflows/execute-plan.md
+@$HOME/.codex/get-shit-done/templates/summary.md
+
+
+
+@.planning/PROJECT.md
+@.planning/ROADMAP.md
+@.planning/REQUIREMENTS.md
+@.planning/phases/01-framework-kernel-foundation/01-CONTEXT.md
+@.planning/phases/01-framework-kernel-foundation/01-RESEARCH.md
+@.planning/phases/01-framework-kernel-foundation/01-VALIDATION.md
+@../modules/summer-compass/README.md
+@../modules/summer-bonfire/PLAN.md
+
+
+
+
+
+ Task 1: Make the hello app boot and dispatch a plugin command
+ go.mod, go.sum, go.work, party/registry.go, backpack/app.go, pact/capabilities.go, compass/config.go, bonfire/command.go, bonfire/root.go, examples/hello/go.mod, examples/hello/main.go, examples/hello/summer.yaml, examples/hello/plugins.gen.go, examples/hello/hello_test.go, examples/hello/plugins/base/go.mod, examples/hello/plugins/base/plugin.go, examples/hello/plugins/greeter/go.mod, examples/hello/plugins/greeter/plugin.go, examples/hello/config/app.yaml
+ go.mod, go.sum, go.work, .planning/phases/01-framework-kernel-foundation/01-CONTEXT.md, .planning/phases/01-framework-kernel-foundation/01-RESEARCH.md, .planning/research/ARCHITECTURE.md, ../modules/summer-bonfire/PLAN.md, party/registry.go, backpack/app.go, pact/capabilities.go, compass/config.go, bonfire/command.go, bonfire/root.go, examples/hello/go.mod, examples/hello/main.go, examples/hello/summer.yaml, examples/hello/plugins.gen.go, examples/hello/hello_test.go, examples/hello/plugins/base/go.mod, examples/hello/plugins/base/plugin.go, examples/hello/plugins/greeter/go.mod, examples/hello/plugins/greeter/plugin.go, examples/hello/config/app.yaml
+ The hello binary loads `app.name` from `config/app.yaml`, runs Register for both plugins before Boot, and executes `greeter:hello` through an injected Output writer.
+ Implement the smallest real boot path. Pin `toolchain go1.27.0` in root and generated/example modules and root `go.work` (D-05). Put the required `Plugin` interface (`ID`, `Requires`, `Register`, `Boot`) and `Register`/`Activate` in `party`, with `Register(*backpack.App) error` and `Boot(*backpack.App) error`; `backpack` must not import `party`. `Activate` must resolve IDs from the manifest order, topologically sort Requires, run every Register before any Boot, and expose the resulting plugins to command collection. Define `pact.HasCommands` returning `[]bonfire.Command` and `pact.HasConfig` returning `fs.FS` as optional type-asserted capabilities; reserve the remaining KERN-03 capability names in documentation for their first consumers. `bonfire.Command` has Name, Description, flag/argument definition and `Run(ctx, Input, Output) error`; its root factory accepts command values, not a party registry, to avoid an import cycle (D-02, D-17). Use `cobra` v1.10.2, `koanf/v2` v2.3.6 and `koanf/parsers/yaml` v1.1.1 with an injected output writer. Create two hello plugin modules with IDs `golem15.hello` and `golem15.greeter`; greeter Requires hello and provides `greeter:hello`. Create `summer.yaml` with `module`, `binary`, and an ordered `plugins` list of `{id, module}` entries; write initial `main.go` and `plugins.gen.go` from those two entries so the app already runs before codegen is automated in Task 2. Add root `go.work` entries for framework, app and both plugins. Keep compass at a working `config/app.yaml` section load and dot-path String lookup here; Plan 02 fills the full precedence contract. Write the smoke test before implementation inside this task, but commit only once both root and hello module tests are green.
+ go vet ./... && go test ./... && (cd examples/hello && go vet ./... && go test ./...)
+
+ - `party.Plugin` has ID, Requires, Register and Boot; `backpack` has no import of `party`.
+ - `bonfire.NewRoot` or equivalent takes a slice of `bonfire.Command` and is used by the hello main.
+ - `examples/hello` contains two independently versioned plugin modules and a working `greeter:hello` command.
+ - Root and hello `go vet ./...` and `go test ./...` exit 0.
+
+ The initial hello command executes through a real app activation path with no package import cycle.
+
+
+
+ Task 2: Generate and build the hello app from its ordered manifest
+ internal/build/build.go, cmd/summer/main.go, examples/hello/summer.yaml, examples/hello/main.go, examples/hello/plugins.gen.go, examples/hello/hello_test.go, go.sum
+ go.mod, go.sum, go.work, party/registry.go, bonfire/root.go, examples/hello/go.mod, examples/hello/main.go, examples/hello/summer.yaml, examples/hello/plugins.gen.go, examples/hello/hello_test.go, .planning/phases/01-framework-kernel-foundation/01-CONTEXT.md, .planning/phases/01-framework-kernel-foundation/01-RESEARCH.md, internal/build/build.go, cmd/summer/main.go
+ Implement `summer build` in the framework-owned `cmd/summer` (D-01, D-04). Parse `examples/hello/summer.yaml` as an explicit ordered `plugins` list of `{id, module}` entries, reject duplicate/invalid entries, generate app-root `main.go` and `plugins.gen.go` containing blank imports plus an ordered plugin-ID slice, and invoke `go build -o bin/hello .` with `exec.CommandContext` in the app directory. Keep generated bytes stable and rewrite only when changed. `main.go` calls the same `bonfire` root constructor as the tool, then activates the manifest IDs; never rely on Go package init order for lifecycle order. Tool `build` prints measured build duration. `go install ./cmd/summer` builds a reusable tool while the app binary remains a distinct artifact. Update the smoke test to run the built binary's `greeter:hello` command and assert its config value. Do not add HTTP, DB, auth or full scaffolding.
+ go vet ./... && go test ./... && (cd examples/hello && go vet ./... && go test ./... && go run ../../cmd/summer build && ./bin/hello greeter:hello)
+
+ - `summer build` creates `examples/hello/plugins.gen.go` with imports in `summer.yaml` order and creates an executable `examples/hello/bin/hello`.
+ - Two consecutive `summer build` calls produce byte-identical generated files.
+ - `./bin/hello greeter:hello` exits 0 and prints a value from `config/app.yaml`.
+ - The tool does not import an example plugin package or contain a hard-coded example module path.
+
+ A developer can build and run the independent hello app through the installed framework tool.
+
+
+
+
+
+## Trust Boundaries
+
+| Boundary | Description |
+|---|---|
+| App manifest → generated Go and build process | A repository-controlled YAML file supplies module import paths and output name. |
+
+## STRIDE Threat Register
+
+| Threat ID | Category | Component | Disposition | Mitigation Plan |
+|---|---|---|---|---|
+| T-01-01 | Tampering | `internal/build` manifest parser | mitigate | Validate module path syntax and duplicate IDs before generating code; render imports with Go string quoting. |
+| T-01-02 | Elevation of privilege | `summer build` process launch | mitigate | Use `exec.CommandContext("go", ...)` with separate args and fixed app working directory; never invoke a shell string from YAML. |
+
+
+
+- Run `go vet ./...` and `go test ./...` in the root and hello modules after each task commit.
+- Run `summer build` twice; compare generated file hashes and execute `bin/hello greeter:hello`.
+- Confirm the app binary imports the framework module but the framework tool does not import hello.
+
+
+
+- A separate `summer` tool and generated hello binary build under Go 1.27.0.
+- The hello plugin command runs from the app binary using shared `bonfire` wiring.
+- Two plugins Register before either Boots, irrespective of manifest order.
+
+
+
diff --git a/.planning/phases/01-framework-kernel-foundation/01-02-PLAN.md b/.planning/phases/01-framework-kernel-foundation/01-02-PLAN.md
new file mode 100644
index 0000000..cb3ccb7
--- /dev/null
+++ b/.planning/phases/01-framework-kernel-foundation/01-02-PLAN.md
@@ -0,0 +1,168 @@
+---
+phase: 01-framework-kernel-foundation
+plan: 02
+type: execute
+wave: 2
+depends_on: ["01-01"]
+files_modified:
+ - go.mod
+ - go.sum
+ - compass/config.go
+ - compass/env.go
+ - compass/persist.go
+ - party/registry.go
+ - pact/capabilities.go
+ - backpack/app.go
+ - backpack/services.go
+ - festival/bus.go
+ - towel/context.go
+ - examples/hello/plugins/base/plugin.go
+ - examples/hello/plugins/base/config/config.yaml
+ - examples/hello/plugins/greeter/plugin.go
+ - examples/hello/plugins/optional/go.mod
+ - examples/hello/plugins/optional/plugin.go
+ - examples/hello/plugins/optional/config/config.yaml
+ - examples/hello/summer.yaml
+ - examples/hello/go.mod
+ - examples/hello/plugins.gen.go
+ - examples/hello/hello_test.go
+ - examples/hello/config/env/development/app.yaml
+ - go.work
+autonomous: true
+requirements: [KERN-01, KERN-02, KERN-03, KERN-05, KERN-06, KERN-07, KERN-08]
+must_haves:
+ truths:
+ - "D-06 D-07 D-08 D-09: `golem15.optional.*` config resolves from embedded plugin defaults, sorted base/env YAML, `SUMMER_` variables, persisted overrides and runtime Set in the specified priority; Reload clears Set."
+ - "D-10: A missing required plugin or cycle stops app boot with an error naming the involved plugin IDs and exits non-zero."
+ - "D-11: An app-scoped HasPlugin check and typed `backpack` lookup let greeter skip an absent optional plugin without importing its package."
+ - "D-12 D-13: Typed struct event listeners run by descending priority with stable ties; the three dispatch modes obey their error and panic rules."
+ - "Request actor, organization, collection and locale values pass through `context.Context`, with no package-global request state."
+ artifacts:
+ - path: compass/config.go
+ provides: Config precedence and dot-path access
+ - path: backpack/services.go
+ provides: Typed app-scoped service registry
+ - path: festival/bus.go
+ provides: Typed event dispatch
+ - path: towel/context.go
+ provides: Typed request context accessors
+ key_links:
+ - from: party/registry.go
+ to: compass/config.go
+ via: `HasConfig` discovery before plugin Register
+ - from: examples/hello/plugins/greeter/plugin.go
+ to: backpack/services.go
+ via: Optional typed service lookup during Boot
+ - from: backpack/app.go
+ to: festival/bus.go
+ via: Bus instance owned by each app
+---
+
+
+As a framework developer, I can change a hello plugin's config, compose it with an optional plugin, and observe a typed event through the built app, so kernel extension behavior is proven in use.
+
+Purpose: Complete only the config, lifecycle, service and event behavior needed by the first real app slice.
+Output: Full `compass` layering, deterministic `party` failures, typed `backpack` services, `festival` dispatch and context accessors.
+
+
+
+@$HOME/.codex/get-shit-done/workflows/execute-plan.md
+@$HOME/.codex/get-shit-done/templates/summary.md
+
+
+
+@.planning/PROJECT.md
+@.planning/ROADMAP.md
+@.planning/REQUIREMENTS.md
+@.planning/phases/01-framework-kernel-foundation/01-CONTEXT.md
+@.planning/phases/01-framework-kernel-foundation/01-RESEARCH.md
+@.planning/phases/01-framework-kernel-foundation/01-VALIDATION.md
+@.planning/phases/01-framework-kernel-foundation/01-01-SUMMARY.md
+@../modules/summer-compass/README.md
+
+
+
+
+
+ Task 1: Make the hello command observe full layered config
+ go.mod, go.sum, compass/config.go, compass/env.go, compass/persist.go, pact/capabilities.go, party/registry.go, examples/hello/plugins/base/plugin.go, examples/hello/plugins/base/config/config.yaml, examples/hello/config/env/development/app.yaml, examples/hello/hello_test.go
+ go.mod, go.sum, compass/config.go, compass/env.go, compass/persist.go, pact/capabilities.go, party/registry.go, examples/hello/plugins/base/plugin.go, examples/hello/plugins/base/config/config.yaml, examples/hello/config/app.yaml, examples/hello/config/env/development/app.yaml, examples/hello/hello_test.go, .planning/phases/01-framework-kernel-foundation/01-CONTEXT.md, ../modules/summer-compass/README.md
+ With `SUMMER_ENV=development`, the hello command sees a deep-merged env overlay; `SUMMER_GOLEM15__HELLO__POSTS_PER_PAGE` overrides plugin defaults, and Set/Persist/Reload follow D-09.
+ Extend `compass` from Plan 01 with deterministic layers (D-06, D-07, D-08, D-09), using pinned koanf providers/file v1.2.1, providers/confmap v1.0.1 and providers/env/v2 v2.0.1: embedded `HasConfig.ConfigFS() fs.FS` files, with `config/config.yaml` merged at the bare plugin ID path (for example `golem15.hello.posts_per_page`) via koanf `MergeAt`; sorted `config/.yaml` base files; sorted `config/env//.yaml` overlays excluding `overrides.yaml`; `SUMMER_` variables split only on `__` so `POSTS_PER_PAGE` remains one snake_case leaf; `config/env//overrides.yaml`; then in-memory Set. Read `.env` in the app root into an injected env list only for keys absent from real `os.Environ`; do not mutate process environment. Add `Lookup(path) (any,bool)`, `String`, `Int`, `Bool`, `Has` and typed `LoadSection(path,out)` using `koanf` tags. `SUMMER_ENV` defaults to `production` and explicit constructor env wins. `Persist` atomically writes runtime overrides to the env-specific overrides file with restrictive permissions; `Reload` rebuilds from disk and clears runtime Set. Guard concurrent access with a lock or immutable snapshot. Sanitize env names before creating paths. Keep all behavior visible through the hello command.
+ go test ./compass ./pact && (cd examples/hello && go test ./...)
+
+ - `SUMMER_DATABASE__HOST` resolves to `database.host`; `SUMMER_GOLEM15__HELLO__POSTS_PER_PAGE` resolves to `golem15.hello.posts_per_page`.
+ - Single underscores remain literal in leaf keys and real environment variables win over `.env` values.
+ - `Set` wins over persisted overrides; `Persist` writes `config/env//overrides.yaml`; `Reload` clears Set and re-reads files.
+ - Untouched keys in nested YAML maps survive later overlays.
+
+ The hello app reads exactly the D-09 priority order through typed and dot-path config access.
+
+
+
+ Task 2: Let a hello plugin use optional services without a hard import
+ party/registry.go, pact/capabilities.go, backpack/app.go, backpack/services.go, examples/hello/plugins/greeter/plugin.go, examples/hello/plugins/optional/go.mod, examples/hello/plugins/optional/plugin.go, examples/hello/plugins/optional/config/config.yaml, examples/hello/summer.yaml, examples/hello/go.mod, examples/hello/plugins.gen.go, examples/hello/hello_test.go, go.work
+ party/registry.go, pact/capabilities.go, backpack/app.go, backpack/services.go, examples/hello/plugins/greeter/plugin.go, examples/hello/plugins/optional/go.mod, examples/hello/plugins/optional/plugin.go, examples/hello/plugins/optional/config/config.yaml, examples/hello/summer.yaml, examples/hello/go.mod, examples/hello/plugins.gen.go, examples/hello/hello_test.go, go.work, .planning/phases/01-framework-kernel-foundation/01-CONTEXT.md, .planning/research/ARCHITECTURE.md
+ Greeter boots whether `golem15.optional` is present or absent; when present it uses a service published under a shared interface, and when absent it skips that integration. Invalid Requires graphs fail before any Boot.
+ Add a third trivial hello plugin `golem15.optional` as its own module and optional manifest entry (D-03, D-11). Put the small shared service interface in `pact`, not in the optional plugin package. Implement app-owned `backpack.Registry` with typed `Publish[T]` and `Lookup[T] (T,bool)` on a concrete Go 1.27 type (or equivalent typed helpers), duplicate-provider handling, and no process-global state. `backpack.App.HasPlugin(id)` must use the complete registered set, not only already-Booted plugins. During greeter Boot, use `HasPlugin("golem15.optional")` and typed lookup; the greeter package must not import the optional package. Harden `party.Activate` to reject duplicate IDs, missing Requires and dependency cycles with named IDs (D-10), then keep stable ordering of independent plugins while guaranteeing all Register calls precede every Boot. Define and type-assert the Phase 1 `HasConfig`/`HasCommands` capabilities. Document the future KERN-03 capability families (`HasModels`, `HasMigrations`, `HasRoutes`, `HasMiddleware`, `HasJobs`, `HasListeners`, `HasAdminControllers`, `HasNavigation`, `HasPermissions`, `HasSchedule`, `HasMailTemplates`, `HasLang`) without coupling their payloads to absent Phase 3 packages. Do not implement their adapters in this phase.
+ go test ./party ./backpack ./pact && (cd examples/hello && go test ./...)
+
+ - Reordered manifest input still causes all Register calls to precede every Boot and respects `Requires()`.
+ - Missing dependency and cycle errors include the plugin IDs involved and make app boot exit non-zero.
+ - Greeter runs with and without `golem15.optional`; its source has no import of the optional plugin module.
+ - Typed service lookup returns `(value, false)` for an absent interface and a concrete value when published.
+
+ The hello app demonstrates optional plugin composition and deterministic failure handling.
+
+
+
+ Task 3: Dispatch typed hello events with request context
+ festival/bus.go, backpack/app.go, towel/context.go, examples/hello/plugins/base/plugin.go, examples/hello/plugins/greeter/plugin.go, examples/hello/hello_test.go
+ festival/bus.go, backpack/app.go, towel/context.go, examples/hello/plugins/base/plugin.go, examples/hello/plugins/greeter/plugin.go, examples/hello/hello_test.go, .planning/phases/01-framework-kernel-foundation/01-CONTEXT.md, .planning/research/ARCHITECTURE.md, .planning/phases/01-framework-kernel-foundation/01-RESEARCH.md
+ The hello command fires a typed struct event; listeners can notify, collect merged values, or stop at the first handled result. Context values remain scoped to that invocation.
+ Implement an app-owned `festival.Bus` keyed by concrete Go event type, with synchronous dispatch on the caller goroutine and owner plugin IDs. Expose plain `Listen[T]` at priority 0 plus `ListenPriority[T]`; run higher integer priorities first and ties by registration order (D-12). Provide `Fire[T] error`, `Collect[T] (map[string]any,error)` with later invoked listener winning duplicate keys, and `UntilHandled[T] (bool,error)`. For Fire, invoke every listener and return `errors.Join`; for Collect, return partial merged data and joined errors; for UntilHandled, stop on first handled result or first error. Recover listener panics into an error naming its owner plugin ID (D-13). Do not add async fan-out. Add `towel.WithActor/Actor`, `WithOrganization/Organization`, `WithCollection/Collection`, and `WithLocale/Locale` typed context helpers using unexported key types; no package-global request values (KERN-07). Pass ctx from cobra Run into event dispatch and demonstrate one hello event listener.
+ go test ./festival ./towel ./backpack && (cd examples/hello && go test ./...)
+
+ - Fire runs all listeners and joins their errors; Collect returns partial payload plus joined errors.
+ - UntilHandled stops on its first error or first handled listener.
+ - Higher priority runs first and equal priority preserves registration order.
+ - A recovered panic error names the owning plugin ID; two app instances have isolated listener sets.
+ - Context values are retrieved only from the passed `context.Context` and no request-state package globals exist.
+
+ The hello path demonstrates all three event modes and context-scoped request state.
+
+
+
+
+
+## Trust Boundaries
+
+| Boundary | Description |
+|---|---|
+| YAML and `.env` → live config | Local files can change runtime behavior and persisted overrides. |
+| Plugin listener → app dispatch | A compiled plugin can panic or return an error during another plugin's event. |
+
+## STRIDE Threat Register
+
+| Threat ID | Category | Component | Disposition | Mitigation Plan |
+|---|---|---|---|---|
+| T-01-03 | Tampering | `compass.Persist` path | mitigate | Validate env name; write only beneath configured `config/env/` and use atomic replacement with restrictive file permissions. |
+| T-01-04 | Denial of service | `festival.Bus` listener | mitigate | Recover panics with owner ID and keep dispatch error behavior deterministic; no implicit goroutine fan-out. |
+| T-01-05 | Information disclosure | `.env` and config logging | mitigate | Do not print config values or secret env contents in errors or build logs. |
+
+
+
+- Run root and nested hello `go vet ./...` and `go test ./...` after each task commit.
+- Run focused `go test -race ./compass ./party ./backpack ./festival ./towel` before this plan closes.
+- Exercise the hello command with and without the optional plugin entry.
+
+
+
+- All six config priority levels are observable and Reload semantics are tested.
+- Optional plugin lookup and typed services work without a hard import.
+- Typed event modes obey D-12/D-13 and do not share state across apps.
+
+
+
diff --git a/.planning/phases/01-framework-kernel-foundation/01-03-PLAN.md b/.planning/phases/01-framework-kernel-foundation/01-03-PLAN.md
new file mode 100644
index 0000000..852a636
--- /dev/null
+++ b/.planning/phases/01-framework-kernel-foundation/01-03-PLAN.md
@@ -0,0 +1,158 @@
+---
+phase: 01-framework-kernel-foundation
+plan: 03
+type: execute
+wave: 3
+depends_on: ["01-02"]
+files_modified:
+ - internal/build/build.go
+ - internal/build/manifest.go
+ - internal/build/scaffold.go
+ - internal/dev/watch.go
+ - cmd/summer/main.go
+ - bonfire/root.go
+ - bonfire/command.go
+ - bonfire/output.go
+ - bonfire/widgets.go
+ - bonfire/prompts.go
+ - bonfire/output_test.go
+ - bonfire/prompts_test.go
+ - internal/build/build_test.go
+ - internal/dev/watch_test.go
+ - examples/hello/plugins/greeter/plugin.go
+ - go.mod
+ - go.sum
+autonomous: true
+requirements: [KERN-04, KERN-09, CLI-01]
+must_haves:
+ truths:
+ - "D-01 D-03 D-04 D-05: `summer make:plugin` scaffolds a compiling plugin and `summer plugin:add` adds it to the ordered manifest/workspace; `summer build` regenerates imports and a separate app binary."
+ - "D-14: Spinner, progress, table, ask/confirm/choice/secret prompts and color policy use standard library plus `x/term`, with deterministic non-TTY output."
+ - "D-15 D-17: Tool and app commands use colon-style names; plugin command metadata, flags, arguments and injected Output are wrapped by the shared cobra kernel."
+ - "D-16: `summer dev` watches sources/config/manifests, debounces, calls the same build function, restarts the app only after successful build, and prints measured rebuild latency."
+ artifacts:
+ - path: internal/build/scaffold.go
+ provides: Minimal plugin scaffold and manifest/workspace registration
+ - path: bonfire/widgets.go
+ provides: Spinner, progress and table rendering
+ - path: bonfire/prompts.go
+ provides: Prompt handling and non-TTY fallback
+ - path: internal/dev/watch.go
+ provides: Built-in watch rebuild loop
+ key_links:
+ - from: cmd/summer/main.go
+ to: internal/build/scaffold.go
+ via: `make:plugin` and `plugin:add` tool commands
+ - from: internal/dev/watch.go
+ to: internal/build/build.go
+ via: One shared build function
+ - from: bonfire/root.go
+ to: bonfire/output.go
+ via: Output injection into plugin commands
+---
+
+
+As a framework developer, I can add a plugin, rebuild, see useful CLI output, and keep an app running while editing source, so compiled plugins have a practical development loop.
+
+Purpose: Complete the Phase 1 tool experience around the already bootable hello app.
+Output: `make:plugin`, `plugin:add`, rich CLI output and built-in `summer dev` watch loop.
+
+
+
+@$HOME/.codex/get-shit-done/workflows/execute-plan.md
+@$HOME/.codex/get-shit-done/templates/summary.md
+
+
+
+@.planning/PROJECT.md
+@.planning/ROADMAP.md
+@.planning/REQUIREMENTS.md
+@.planning/phases/01-framework-kernel-foundation/01-CONTEXT.md
+@.planning/phases/01-framework-kernel-foundation/01-RESEARCH.md
+@.planning/phases/01-framework-kernel-foundation/01-VALIDATION.md
+@.planning/phases/01-framework-kernel-foundation/01-02-SUMMARY.md
+@../modules/summer-bonfire/PLAN.md
+
+
+
+
+
+ Task 1: Add and rebuild a compiling plugin from the tool
+ internal/build/build.go, internal/build/manifest.go, internal/build/scaffold.go, internal/build/build_test.go, cmd/summer/main.go
+ internal/build/build.go, internal/build/manifest.go, internal/build/scaffold.go, internal/build/build_test.go, cmd/summer/main.go, examples/hello/summer.yaml, examples/hello/go.mod, examples/hello/plugins.gen.go, examples/hello/plugins/base/plugin.go, go.work, .planning/phases/01-framework-kernel-foundation/01-CONTEXT.md, .planning/phases/01-framework-kernel-foundation/01-RESEARCH.md
+ Complete D-01/D-03/D-04/D-05 using `summer.yaml` as the sole ordered source of plugin IDs and module paths. `summer make:plugin ` scaffolds `plugins//go.mod` with module path `/plugins/` and `toolchain go1.27.0`, `plugin.go` implementing ID/Requires/Register/Boot and `init(){ party.Register(...) }`, plus an empty `config/` placeholder; no model/migration/controller/command stubs. `summer plugin:add ` reads the module path from that directory's `go.mod`, validates the ID and module path, adds the plugin once to `summer.yaml`, updates the nearest app `go.work` with `go work use`, and updates app `go.mod` as needed for a portable dependency graph. Preserve manifest order and reject conflicting IDs. `summer build` must regenerate both app files from the updated manifest and print elapsed build time; no map iteration controls output. Keep tool source independent of app/plugin imports. Exercise the commands on a temporary copy of `examples/hello` so the permanent testbed stays small.
+ go test ./internal/build ./cmd/summer && (cd examples/hello && go test ./...)
+
+ - `make:plugin golem15.demo` produces a compiling plugin module with only `go.mod`, `plugin.go` and `config/`.
+ - `plugin:add` adds one manifest entry and workspace module; repeating it is idempotent.
+ - `summer build` produces byte-stable `main.go` and `plugins.gen.go` from the updated manifest.
+ - The framework tool has no import of an app-specific plugin package.
+
+ A new local plugin can be scaffolded, added and compiled into the hello app.
+
+
+
+ Task 2: Give tool and plugin commands deterministic rich output
+ bonfire/root.go, bonfire/command.go, bonfire/output.go, bonfire/widgets.go, bonfire/prompts.go, bonfire/output_test.go, bonfire/prompts_test.go, cmd/summer/main.go, examples/hello/plugins/greeter/plugin.go, go.mod, go.sum
+ bonfire/root.go, bonfire/command.go, bonfire/output.go, bonfire/widgets.go, bonfire/prompts.go, bonfire/output_test.go, bonfire/prompts_test.go, cmd/summer/main.go, examples/hello/plugins/greeter/plugin.go, go.mod, go.sum, ../modules/summer-bonfire/PLAN.md, .planning/phases/01-framework-kernel-foundation/01-CONTEXT.md, .planning/phases/01-framework-kernel-foundation/01-RESEARCH.md
+ Implement D-14/D-15/D-17 with stdlib formatting and `golang.org/x/term` v0.46.0 only for terminal capability/raw/password primitives. `bonfire.Output` is constructed once from injected stdin/stdout/stderr and terminal/color policy; the cobra adapter passes `ctx`, parsed `Input`, and that Output to every `bonfire.Command`. Command metadata defines arguments and flags without duplicating root wiring; reject plugin command names without `:`, while kernel tool commands are `make:plugin`, `plugin:add`, `build`, `dev`. Implement braille spinner and gradient progress for TTY, box-drawing table, ask/confirm/choice/secret prompts. For non-TTY: spinner prints one `[...] message`; progress prints `[N/M] pct%` at 10% steps; table is tab-separated; ask/choice/secret read stdin lines; confirm uses its default. `NO_COLOR` or `TERM=dumb` disables ANSI; `FORCE_COLOR` enables it only when neither disable condition is present. `secret` uses `term.ReadPassword` on TTY and a plain stdin line otherwise. Make the hello plugin command exercise table and one prompt without hanging when stdin is closed.
+ go test ./bonfire ./cmd/summer && (cd examples/hello && go test ./...)
+
+ - `summer make:plugin --help` and the app's `greeter:hello --help` are generated through the shared `bonfire` cobra adapter.
+ - Non-TTY output has no ANSI when `NO_COLOR=1` or `TERM=dumb` and uses the exact spinner/progress/table fallback shapes above.
+ - Injected streams let tests capture Output and feed prompt answers without a real TTY.
+ - Plugin command names without `:` fail registration with a named error.
+
+ Both binaries expose namespaced commands and usable output in interactive and CI environments.
+
+
+
+ Task 3: Rebuild and restart the hello binary during source edits
+ internal/dev/watch.go, internal/dev/watch_test.go, internal/build/build.go, cmd/summer/main.go, go.mod, go.sum
+ internal/build/build.go, internal/dev/watch.go, internal/dev/watch_test.go, cmd/summer/main.go, go.mod, go.sum, examples/hello/summer.yaml, .planning/phases/01-framework-kernel-foundation/01-CONTEXT.md, .planning/phases/01-framework-kernel-foundation/01-RESEARCH.md
+ Implement `summer dev` with `github.com/fsnotify/fsnotify` v1.10.1 (D-16). Watch app workspace directories recursively by walking them and adding new directories on Create; include `.go`, `.yaml`, `.yml`, `.env`, `go.mod`, `go.work` and plugin manifests. Ignore `.git`, `bin`, temp build outputs and generated app files to prevent loops. Debounce bursts (for example 200ms) and serialize builds. Call the exact `internal/build` function used by `summer build`; after success stop and reap the old child, start the new app binary with inherited streams, and print `rebuild: ` measured from build start to completion. On build failure keep the old process running and print the build error; on context cancellation stop/reap the child and close the watcher. Do not execute manifest-derived shell commands. Add a smoke test with a temporary workspace to assert one restart after a source edit, no restart after ignored generated output and a latency line.
+ go test ./internal/dev ./internal/build ./cmd/summer && (cd examples/hello && go test ./...)
+
+ - Editing a watched hello plugin `.go` file causes one debounced rebuild and successful restart.
+ - Build failure leaves the last successful child running; cancellation reaps it.
+ - A generated `plugins.gen.go` write does not cause an infinite rebuild loop.
+ - Every rebuild cycle prints measured elapsed time, including the cycle after a single-plugin edit.
+
+ The local development loop rebuilds and restarts without an external watcher install.
+
+
+
+
+
+## Trust Boundaries
+
+| Boundary | Description |
+|---|---|
+| CLI plugin input → filesystem | Plugin ID and directory values select paths and module names. |
+| Filesystem event → build/restart | File changes trigger local tool execution and process replacement. |
+| Prompt → terminal | Secret values may be echoed or captured if mode detection is wrong. |
+
+## STRIDE Threat Register
+
+| Threat ID | Category | Component | Disposition | Mitigation Plan |
+|---|---|---|---|---|
+| T-01-06 | Tampering | `make:plugin` and `plugin:add` paths | mitigate | Validate lowercase vendor.plugin ID and keep generated paths under the app root; reject traversal and duplicate/conflicting entries. |
+| T-01-07 | Denial of service | `summer dev` watcher | mitigate | Debounce, ignore output dirs, serialize builds, and reap child processes on cancellation. |
+| T-01-08 | Information disclosure | `bonfire` secret prompt | mitigate | Use `term.ReadPassword` for TTY and document plain stdin fallback; never log answers. |
+
+
+
+- After each task commit, run `go vet ./... && go test ./...` in root and hello modules.
+- Smoke-test `make:plugin`, `plugin:add`, `build` and `dev` against temporary copies of `examples/hello`.
+- Capture non-TTY output with pipes; manually inspect one TTY command during phase verification.
+
+
+
+- A new plugin is scaffolded, registered and built using only the framework tool.
+- CLI output degrades predictably without a TTY.
+- A plugin source change triggers a measured rebuild and app restart.
+
+
+
diff --git a/.planning/phases/01-framework-kernel-foundation/01-04-PLAN.md b/.planning/phases/01-framework-kernel-foundation/01-04-PLAN.md
new file mode 100644
index 0000000..6654751
--- /dev/null
+++ b/.planning/phases/01-framework-kernel-foundation/01-04-PLAN.md
@@ -0,0 +1,131 @@
+---
+phase: 01-framework-kernel-foundation
+plan: 04
+type: execute
+wave: 4
+depends_on: ["01-03"]
+files_modified:
+ - compass/config_test.go
+ - party/registry_test.go
+ - backpack/services_test.go
+ - festival/bus_test.go
+ - towel/context_test.go
+ - bonfire/output_test.go
+ - bonfire/prompts_test.go
+ - internal/build/build_test.go
+ - internal/dev/watch_test.go
+ - examples/hello/hello_test.go
+ - scripts/check-phase1.sh
+ - .planning/phases/01-framework-kernel-foundation/01-VALIDATION.md
+autonomous: true
+requirements: [KERN-01, KERN-02, KERN-03, KERN-04, KERN-05, KERN-06, KERN-07, KERN-08, KERN-09, CLI-01]
+must_haves:
+ truths:
+ - "Every KERN-01 through KERN-09 and CLI-01 contract has a behavioral test, including failure and non-TTY paths."
+ - "The final check runs `go vet`, `go test`, and `go test -race` in the framework, hello app and each hello plugin module."
+ - "A temporary app can run `summer build` and its generated binary; source edit under `summer dev` records measured rebuild time and restarts the child."
+ artifacts:
+ - path: scripts/check-phase1.sh
+ provides: Repeatable phase-wide verification command
+ - path: compass/config_test.go
+ provides: Config precedence regression tests
+ - path: festival/bus_test.go
+ provides: Event dispatch regression tests
+ - path: examples/hello/hello_test.go
+ provides: Built-app integration test
+ key_links:
+ - from: scripts/check-phase1.sh
+ to: examples/hello/go.mod
+ via: Checks nested app and plugin modules independently
+ - from: examples/hello/hello_test.go
+ to: cmd/summer/main.go
+ via: Builds and executes a generated app binary
+---
+
+
+As a framework maintainer, I can run one repeatable check that proves the Phase 1 kernel and development loop before Phase 3 depends on them.
+
+Purpose: Add the phase's dedicated unit and integration test plan, with broad behavior and failure coverage.
+Output: Focused Go tests, a nested-module check script, a generated-binary smoke and completed Nyquist validation map.
+
+
+
+@$HOME/.codex/get-shit-done/workflows/execute-plan.md
+@$HOME/.codex/get-shit-done/templates/summary.md
+
+
+
+@.planning/PROJECT.md
+@.planning/ROADMAP.md
+@.planning/REQUIREMENTS.md
+@.planning/phases/01-framework-kernel-foundation/01-CONTEXT.md
+@.planning/phases/01-framework-kernel-foundation/01-RESEARCH.md
+@.planning/phases/01-framework-kernel-foundation/01-VALIDATION.md
+@.planning/phases/01-framework-kernel-foundation/01-03-SUMMARY.md
+
+
+
+
+
+ Task 1: Cover config, lifecycle, services, events and context behavior
+ compass/config_test.go, party/registry_test.go, backpack/services_test.go, festival/bus_test.go, towel/context_test.go
+ compass/config.go, compass/env.go, compass/persist.go, party/registry.go, backpack/app.go, backpack/services.go, festival/bus.go, towel/context.go, compass/config_test.go, party/registry_test.go, backpack/services_test.go, festival/bus_test.go, towel/context_test.go, .planning/phases/01-framework-kernel-foundation/01-CONTEXT.md
+ Expand earlier smoke tests into table-driven behavioral tests for all config precedence levels, malformed YAML, snake_case env keys, `.env` non-override, dotted plugin namespace, typed section decode, Set/Persist/Reload and concurrent reads. Test plugin duplicate/missing/cycle errors, reordered manifest inputs, all-Register-before-any-Boot, HasConfig/HasCommands assertions, absent/present HasPlugin and typed service lookup with two separate App instances. Test three typed event dispatch modes, priority and stable ties, partial collect payload, joined errors, stop-on-error, owner-labelled panic recovery and concurrent independent app buses. Test actor/organization/collection/locale context accessors and nested context isolation. Fix any production defect exposed by these tests in the same task, keeping API behavior from D-01–D-13 intact. Report per-package coverage for these packages; cover contract branches rather than chasing an arbitrary percentage.
+ go test -race ./compass ./party ./backpack ./festival ./towel ./pact
+
+ - Each KERN-01/02/03/05/06/07/08 behavior above has at least one source-to-observable assertion.
+ - `go test -race ./compass ./party ./backpack ./festival ./towel ./pact` exits 0.
+ - No test asserts only implementation structure when a behavior can be observed.
+
+ The kernel's core behavioral and failure contracts are regression tested.
+
+
+
+ Task 2: Cover tool, output, watch loop and every workspace module
+ bonfire/output_test.go, bonfire/prompts_test.go, internal/build/build_test.go, internal/dev/watch_test.go, examples/hello/hello_test.go, scripts/check-phase1.sh, .planning/phases/01-framework-kernel-foundation/01-VALIDATION.md
+ bonfire/root.go, bonfire/output.go, bonfire/widgets.go, bonfire/prompts.go, internal/build/build.go, internal/build/manifest.go, internal/build/scaffold.go, internal/dev/watch.go, cmd/summer/main.go, examples/hello/summer.yaml, bonfire/output_test.go, bonfire/prompts_test.go, internal/build/build_test.go, internal/dev/watch_test.go, examples/hello/hello_test.go, scripts/check-phase1.sh, .planning/phases/01-framework-kernel-foundation/01-VALIDATION.md
+ Test namespaced command discovery and flag/argument parsing, injected output capture, all non-TTY widget/prompt fallbacks, `NO_COLOR`/`FORCE_COLOR`/`TERM=dumb` policy and closed stdin. In a temporary copied hello workspace, assert `make:plugin` minimal files, `plugin:add` idempotence, stable generated bytes, malicious ID/path rejection, `summer build` success, built hello command output and non-zero failure on invalid Requires. Use deterministic build/process hooks for debounce/cancellation tests, plus a real fsnotify temp-workspace edit for one successful rebuild/restart; capture and assert a `rebuild: ` line without assuming a threshold. Add `scripts/check-phase1.sh` that runs `go vet ./...`, `go test ./...` and `go test -race ./...` from root, `examples/hello`, and each nested plugin module; include built-binary integration. Update VALIDATION.md's per-task map/status and set `nyquist_compliant: true` only when every planned automated check exists and passes. Fix production defects the tests expose, while keeping this plan focused on verification.
+ bash scripts/check-phase1.sh
+
+ - `bash scripts/check-phase1.sh` exits 0 and names root, hello app, base, greeter and optional plugin modules.
+ - Test suite observes `summer build` and a separately executed hello binary, not only package compilation.
+ - Watch test observes a source-change rebuild, restart and measured latency line; generated-file edits do not loop.
+ - Non-TTY spinner/progress/table/prompt and color policy assertions run without a terminal.
+ - VALIDATION.md records passing automated checks and `nyquist_compliant: true` only after the full script passes.
+
+ The phase has a repeatable, race-enabled verification command and completed validation evidence.
+
+
+
+
+
+## Trust Boundaries
+
+| Boundary | Description |
+|---|---|
+| Test fixture input → tool/process | Malformed manifests and source edits should fail safely during local tooling. |
+
+## STRIDE Threat Register
+
+| Threat ID | Category | Component | Disposition | Mitigation Plan |
+|---|---|---|---|---|
+| T-01-09 | Tampering | Manifest and scaffold inputs | mitigate | Add negative tests for invalid IDs, duplicate modules and path traversal. |
+| T-01-10 | Denial of service | Watch loop | mitigate | Test debounce, ignored outputs, failed build and child cleanup. |
+| T-01-11 | Information disclosure | CLI secret and config | mitigate | Assert secret prompt answer and config values do not leak into captured error/output streams. |
+
+
+
+- Run `bash scripts/check-phase1.sh` and inspect its per-module output.
+- Confirm `go test -race` passes in all five modules and `go vet` is green.
+- Record measured single-plugin rebuild time in 01-04-SUMMARY.md.
+
+
+
+- All ten phase requirement IDs have automated behavioral evidence.
+- The final testing plan runs after implementation and passes across all workspace modules.
+- VALIDATION.md can be signed off without missing tests or broken Wave 0 references.
+
+
+
diff --git a/.planning/phases/01-framework-kernel-foundation/01-RESEARCH.md b/.planning/phases/01-framework-kernel-foundation/01-RESEARCH.md
index 2a4e791..1c5669c 100644
--- a/.planning/phases/01-framework-kernel-foundation/01-RESEARCH.md
+++ b/.planning/phases/01-framework-kernel-foundation/01-RESEARCH.md
@@ -121,11 +121,11 @@ The fast feedback command should take seconds once dependencies are cached. CI c
-## Open Questions
+## Open Questions (RESOLVED)
-1. **Exact optional capability method signatures for Phase 3+** — `HasModels`, `HasRoutes` and peers are named in KERN-03, but their concrete adapters do not exist yet. Prefer contracts that compile without importing future packages and document that signatures may be refined when the first consumer arrives.
-2. **Plugin config representation with dotted IDs** — test koanf lookup behavior for a YAML key `golem15.fonoteka` versus nested `golem15: {fonoteka: ...}` before locking the on-disk form. The public logical path and env mapping remain fixed by D-06/D-08.
-3. **Dev watch process ownership across platforms** — implement and test Linux first in this environment; keep command execution behind a small abstraction if later platform handling needs adjustment.
+1. **Exact optional capability method signatures for Phase 3+ — RESOLVED:** Phase 1 implements the type-asserted `HasConfig` and `HasCommands` adapters and documents the remaining named capability families. Their payload methods are declared when the first relevant phase has concrete consumer types, per the context's interleaved kernel rule. No `[]any` placeholders are introduced just to fill an interface list.
+2. **Plugin config representation with dotted IDs — RESOLVED:** Each plugin's embedded `config/config.yaml` contains keys relative to its ID; `compass` merges it at the logical path `golem15.fonoteka` using koanf `MergeAt`. Additional embedded section files, if used later, merge at `golem15.fonoteka.`. App-level `config/.yaml` retains filename-as-section behavior. This avoids relying on a dotted YAML root key while preserving the D-06/D-08 public paths.
+3. **Dev watch process ownership across platforms — RESOLVED:** Use `exec.CommandContext` and an explicit child stop/reap path. Test Linux in this environment and keep build/process launch behind small test hooks; no platform-specific daemon API is required for Phase 1.
diff --git a/.planning/phases/01-framework-kernel-foundation/01-SKELETON.md b/.planning/phases/01-framework-kernel-foundation/01-SKELETON.md
new file mode 100644
index 0000000..b67c4dd
--- /dev/null
+++ b/.planning/phases/01-framework-kernel-foundation/01-SKELETON.md
@@ -0,0 +1,37 @@
+# Walking Skeleton — SummerCMS (Go)
+
+**Phase:** 1
+**Generated:** 2026-09-16
+
+## Capability Proven End-to-End
+
+A framework developer can run `summer build` in `examples/hello`, boot a separately compiled app from YAML config and generated plugin imports, then execute a plugin command through the app binary.
+
+## Architectural Decisions
+
+| Decision | Choice | Rationale |
+|---|---|---|
+| Framework | Go 1.27.0, module `git.golem15.com/golem15/summercms` | Locked by Phase 1 context. |
+| Plugin linkage | App `summer.yaml` → generated `plugins.gen.go` blank imports | Compiled plugins with an explicit ordered manifest. |
+| App composition | `party` lifecycle, `backpack.App`, `compass`, `festival`, `bonfire` | The smallest Phase 1 kernel path with a real consumer. |
+| Data layer | Phase 3: Postgres + GORM/gormigrate | Phase 1 context excludes ORM and DB; the first real data slice is `GET /_fonoteka/api/v1/genres`. |
+| HTTP/auth/UI | Phase 3 HTTP/auth; existing Nuxt UI remains the app frontend | Phase 1 is a framework CLI phase and excludes router, auth and UI. |
+| Dev target | Local `summer build` and `summer dev` in `examples/hello` | Makes plugin development observable before deployment is introduced. |
+| Directory layout | Framework packages at root, tool in `cmd/summer`, app/modules under `examples/hello` | Proves two-binary and two-repository architecture without importing the real app. |
+
+## Stack Touched in Phase 1
+
+- [ ] Framework module and root `go.work` with separate hello app/plugin modules
+- [ ] Generated app entry point and plugin import list
+- [ ] YAML config → Register-all → Boot-all → plugin command
+- [ ] Built-in watch rebuild and restart loop
+- [ ] Local run command: `cd examples/hello && summer build && ./bin/hello greeter:hello`
+
+## Phase Boundary
+
+The generic Walking Skeleton recipe calls for routing, a DB read/write and a UI interaction. Phase 1's locked CONTEXT.md explicitly excludes `surf`, `lagoon`, `bouncer` and UI until Phase 3. This skeleton proves the complete **kernel developer path** and records the later app slice as its handoff. No substitute fake DB/UI is added to satisfy a generic template.
+
+## Subsequent Slice Plan
+
+- Phase 2 builds the API parity harness independently.
+- Phase 3 adds the first real Postgres-backed Płytarium endpoint and exercises the framework from the separate app repository.
diff --git a/.planning/phases/01-framework-kernel-foundation/01-VALIDATION.md b/.planning/phases/01-framework-kernel-foundation/01-VALIDATION.md
index b49ec4e..4839e18 100644
--- a/.planning/phases/01-framework-kernel-foundation/01-VALIDATION.md
+++ b/.planning/phases/01-framework-kernel-foundation/01-VALIDATION.md
@@ -16,14 +16,14 @@ created: 2026-09-16
| Framework | `go test` (Go 1.27.0) |
| Config file | No test harness yet; first implementation slice adds Go tests |
| Quick run | `go vet ./... && go test ./...` from repo root, then from `examples/hello` once created |
-| Full suite | Both modules: `go vet ./...`, `go test ./...`, `go test -race ./...`; generated binary integration |
+| Full suite | Framework, hello app and three hello plugin modules: `go vet ./...`, `go test ./...`, `go test -race ./...`; generated binary integration |
| Estimated runtime | Measure after dependencies are cached; no assumed threshold |
## Sampling Rate
- After each implementation task commit, run root `go vet ./... && go test ./...`; run the same from `examples/hello` after it exists.
- After each plan wave, run both module checks plus the relevant built-binary smoke.
-- Before verify-work, run race tests in both modules and an end-to-end `summer build`/hello invocation.
+- Before verify-work, run race tests in all five modules and an end-to-end `summer build`/hello invocation.
- Record actual feedback latency and single-plugin rebuild latency; no fixed performance promise has been set.
## Per-Requirement Verification Map
@@ -41,6 +41,21 @@ created: 2026-09-16
| KERN-09 | integration | Temp app source edit triggers one debounced rebuild and restart, latency line captured | Pending |
| CLI-01 | unit + integration | Plugin command discovery, injected output, non-TTY spinner/progress/table/prompt behavior | Pending |
+## Per-Task Verification Map
+
+| Task ID | Plan | Wave | Requirements | Automated check | Status |
+|---|---|---|---|---|---|
+| 01-01-01 | 01 | 1 | KERN-01/02/03/04, CLI-01 | Root and hello `go vet ./...` + `go test ./...` | Pending |
+| 01-01-02 | 01 | 1 | KERN-04, CLI-01 | Same checks plus `summer build` and built hello command | Pending |
+| 01-02-01 | 02 | 2 | KERN-01/03 | `go test ./compass ./pact`; hello tests | Pending |
+| 01-02-02 | 02 | 2 | KERN-02/03/05/08 | `go test ./party ./backpack ./pact`; hello tests | Pending |
+| 01-02-03 | 02 | 2 | KERN-06/07 | `go test ./festival ./towel ./backpack`; hello tests | Pending |
+| 01-03-01 | 03 | 3 | KERN-04 | `go test ./internal/build ./cmd/summer`; hello tests | Pending |
+| 01-03-02 | 03 | 3 | CLI-01 | `go test ./bonfire ./cmd/summer`; hello tests | Pending |
+| 01-03-03 | 03 | 3 | KERN-09 | `go test ./internal/dev ./internal/build ./cmd/summer`; hello tests | Pending |
+| 01-04-01 | 04 | 4 | KERN-01/02/03/05/06/07/08 | `go test -race ./compass ./party ./backpack ./festival ./towel ./pact` | Pending |
+| 01-04-02 | 04 | 4 | KERN-04/09, CLI-01 | `bash scripts/check-phase1.sh` | Pending |
+
## Wave 0 Requirements
- [ ] First implementation slice creates `examples/hello`, its `go.mod`, and a root `go.work` that names every example module.
@@ -58,8 +73,8 @@ created: 2026-09-16
- [ ] Every plan task has an automated verification or an explicit Wave 0 dependency.
- [ ] No three consecutive implementation tasks lack automated feedback.
-- [ ] Root and nested example modules both run `go vet`, tests and race tests.
+- [ ] Root, hello app and three plugin modules run `go vet`, tests and race tests.
- [ ] No watch-mode flags in CI commands.
-- [ ] Set `nyquist_compliant: true` after plan-task mapping is complete.
+- [ ] Set `nyquist_compliant: true` after all mapped checks exist and pass.
**Approval:** pending plan verification