|
|
|
|
@@ -0,0 +1,126 @@
|
|
|
|
|
# Phase 1: Framework kernel foundation — Research
|
|
|
|
|
|
|
|
|
|
**Researched:** 2026-09-16
|
|
|
|
|
**Domain:** Go 1.27 compiled plugin kernel, layered configuration, CLI and watch loop
|
|
|
|
|
**Confidence:** High for documented library behavior; medium for proposed API shapes until the `examples/hello` integration proves them.
|
|
|
|
|
|
|
|
|
|
<user_constraints>
|
|
|
|
|
## User Constraints
|
|
|
|
|
|
|
|
|
|
The locked decisions are D-01 through D-17 in [01-CONTEXT.md](01-CONTEXT.md). In particular: two binaries and one `bonfire` command kernel; canonical module path `git.golem15.com/golem15/summercms`; root `go.work` plus permanent `examples/hello`; bare plugin-ID config namespaces; the exact six-level config priority; required `Plugin` plus optional capability interfaces; deterministic lifecycle and event dispatch; hand-rolled output; `fsnotify` watch loop. The framework repository must not import Płytarium or grow the Phase 3 HTTP/ORM/auth stack.
|
|
|
|
|
|
|
|
|
|
The context leaves the exact event and service APIs, file manifest format, and package dependency direction to implementation. Defer model/migration/controller scaffolding, admin config editing, shared-plugin extraction, and all `surf`/`lagoon`/`bouncer` implementation.
|
|
|
|
|
</user_constraints>
|
|
|
|
|
|
|
|
|
|
<architectural_responsibility_map>
|
|
|
|
|
## Architectural Responsibility Map
|
|
|
|
|
|
|
|
|
|
Single-tier CLI and backend framework. `cmd/summer` owns tool entry, generated app `main.go` owns runtime entry, `party` owns plugin ordering, `backpack` owns app-scoped services, `compass` owns configuration, `festival` owns events, and `bonfire` owns commands and terminal output. The generated app binary is the integration boundary.
|
|
|
|
|
</architectural_responsibility_map>
|
|
|
|
|
|
|
|
|
|
<research_summary>
|
|
|
|
|
## Summary
|
|
|
|
|
|
|
|
|
|
Build the first executable path through `examples/hello`: explicit `summer.yaml` manifest → generated `plugins.gen.go` → app main → config load → all plugin Register calls → all Boot calls → a namespaced plugin command. Extend that path with configuration precedence, optional service integration, event dispatch, and `summer dev`; do not build unused framework layers first. The source-of-truth design is the phase context, with project research supplying examples and pitfalls.
|
|
|
|
|
|
|
|
|
|
`go.work` can develop multiple modules together, but a root `go test ./...` does not by itself prove nested example modules. Plans need separate `go test`/`go vet` checks from `examples/hello` and a built-binary invocation. Go's `toolchain` directive needs a concrete release, so `toolchain go1.27.0` matches the installed `go1.27.0` and fulfills D-05 without an invalid wildcard. The `go`/`toolchain` directive behavior is documented by [Go](https://go.dev/doc/toolchain), and workspace module membership by the [Go workspace tutorial](https://go.dev/doc/tutorial/workspaces).
|
|
|
|
|
|
|
|
|
|
**Primary recommendation:** Keep every package API driven by a real hello plugin and its CLI path, then verify the kernel with reordered plugin input, config precedence, non-TTY output, generated code stability, and a measured watch rebuild.
|
|
|
|
|
</research_summary>
|
|
|
|
|
|
|
|
|
|
<standard_stack>
|
|
|
|
|
## Standard Stack
|
|
|
|
|
|
|
|
|
|
| Component | Phase 1 choice | Use |
|
|
|
|
|
|---|---|---|
|
|
|
|
|
| Compiler/workspace | Go 1.27.0, `go.work` | Root framework plus separate hello app/plugin modules. |
|
|
|
|
|
| Config | `github.com/knadh/koanf/v2`, file/confmap/env v2 providers, koanf YAML parser | Ordered deep merges, typed section decode, dot paths. |
|
|
|
|
|
| CLI | `github.com/spf13/cobra` | One root command constructor shared by tool and app. |
|
|
|
|
|
| Terminal | `golang.org/x/term` plus standard library | TTY detection, password prompt, simple widgets. |
|
|
|
|
|
| Watch | `github.com/fsnotify/fsnotify` | Observe app workspace directories and rebuild. |
|
|
|
|
|
| Tests | `go test`, `go test -race`, `go vet`; `testify` only if helpful | Unit and example integration coverage. |
|
|
|
|
|
|
|
|
|
|
The context authorizes these dependencies. Resolve exact module tags during implementation and commit `go.sum`; do not use `@latest` in repeatable plan commands. The [koanf docs](https://pkg.go.dev/github.com/knadh/koanf/v2) confirm successive `Load` calls merge into the existing tree. The current [env/v2 provider](https://pkg.go.dev/github.com/knadh/koanf/providers/env/v2) has `Opt{Prefix, TransformFunc, EnvironFunc}` and can inject an environment source in tests. The earlier project STACK.md's unversioned env-provider example is a sketch, not a required import path.
|
|
|
|
|
</standard_stack>
|
|
|
|
|
|
|
|
|
|
<architecture_patterns>
|
|
|
|
|
## Architecture Patterns
|
|
|
|
|
|
|
|
|
|
```text
|
|
|
|
|
summer.yaml → summer build → generated imports + app main → go build → hello binary
|
|
|
|
|
↓
|
|
|
|
|
config → Register all → Boot all
|
|
|
|
|
↓
|
|
|
|
|
bonfire root → plugin command → Output
|
|
|
|
|
summer dev → fsnotify/debounce → same build function → restart hello binary
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### Package boundaries
|
|
|
|
|
|
|
|
|
|
- `pact` holds neutral plugin and capability contracts. If `Plugin.Register`/`Boot` take an app type, define a narrow app-facing interface in `pact` or place the contract in `party` so `pact → backpack → pact` cannot occur. `backpack` implements the interface; `party` orchestrates it.
|
|
|
|
|
- `backpack.App` owns config, services and event bus per instance. Typed lookup may be a generic method on a concrete type with Go 1.27, or a generic helper; no package-global service state.
|
|
|
|
|
- `festival.Bus` uses typed struct event identity, synchronous listeners, priority descending with stable registration order, and a snapshot of listeners at dispatch. Define collision behavior for collect payloads before implementation (recommended: later invoked listener wins for duplicate keys), then test it.
|
|
|
|
|
- `party` may have an `init()` registration slice as the sole allowed process-global registry. Copy it into each app, reject duplicate IDs, validate `Requires()` against the complete set, topologically order with deterministic tie-breaking, then run every Register before any Boot. Return missing/cycle errors with plugin IDs.
|
|
|
|
|
- `compass` builds a fresh tree on Reload. Load plugin defaults → sorted base section files → sorted env section files → env variables → persisted overrides → runtime Set. Keep runtime overrides separate so Reload clears them; protect live reads/writes with a lock or immutable snapshot swap. Decode YAML under logical `golem15.fonoteka.*` paths consistently with `SUMMER_GOLEM15__FONOTEKA__*`.
|
|
|
|
|
- `bonfire` constructs cobra commands with injected `Input` and `Output`, sets writers explicitly and executes with context. Cobra supports [`AddCommand`, `ExecuteContext`, `SetOut`, and `SetErr`](https://pkg.go.dev/github.com/spf13/cobra). One kernel factory avoids separate tool/app wiring.
|
|
|
|
|
|
|
|
|
|
### Watch loop
|
|
|
|
|
|
|
|
|
|
`fsnotify` does not recursively watch subdirectories and recommends watching parent directories rather than individual files because editors replace files atomically. Walk the workspace initially, add new directories on Create, ignore generated binaries/`.git`, debounce bursts, terminate/reap the old process, rebuild through the `summer build` function, and start only a successful new binary. Drain both Events and Errors. See the [fsnotify README](https://github.com/fsnotify/fsnotify/blob/main/README.md).
|
|
|
|
|
|
|
|
|
|
### MVP boundary
|
|
|
|
|
|
|
|
|
|
The roadmap marks Phase 1 `mvp`, and the generic GSD Walking Skeleton recipe would include DB/UI. That conflicts with the explicit Phase 1 boundary in CONTEXT.md, which excludes ORM, router, and UI until Phase 3. For this phase the real user is a framework developer: the vertical proof is a generated, bootable hello binary with a working plugin command and live rebuild. `SKELETON.md` should record this phase-specific boundary and hand the DB/HTTP/UI slice to Phase 3.
|
|
|
|
|
</architecture_patterns>
|
|
|
|
|
|
|
|
|
|
<common_pitfalls>
|
|
|
|
|
## Common Pitfalls
|
|
|
|
|
|
|
|
|
|
| Risk | Detection and prevention |
|
|
|
|
|
|---|---|
|
|
|
|
|
| Import cycles from optional capability signatures | Compile the minimal hello plugin before adding more capabilities; keep future adapters out of `pact` imports. |
|
|
|
|
|
| Non-deterministic generated imports or lifecycle | Manifest is an ordered list; regenerate idempotently; use explicit tie-breaking and reordered-input test. |
|
|
|
|
|
| Env key ambiguity and `.env` clobbering | Split only on `__`, preserve single underscores, lowercase path segments; do not overwrite `os.LookupEnv` values. |
|
|
|
|
|
| Config merge semantics hidden by filenames | Sort files, validate duplicate sections and malformed YAML, test all six priority layers including persisted overrides and Reload. |
|
|
|
|
|
| Nested modules skipped by root checks | Run checks in both root and `examples/hello`; execute built app binary. |
|
|
|
|
|
| Watcher churn or stale process | Test create/rename/write bursts, rebuild failure, restart, cancellation, and measured rebuild latency. |
|
|
|
|
|
| Terminal tests hang in CI | Inject streams and terminal capability; test non-TTY tables, progress, spinner and prompts with pipes. [`x/term`](https://pkg.go.dev/golang.org/x/term) supplies terminal detection and password/raw-mode primitives. |
|
|
|
|
|
| Phase 1 grows into a generic CMS | Require each kernel API to have a hello consumer or an explicit Phase 3 handoff; defer unused adapters. |
|
|
|
|
|
</common_pitfalls>
|
|
|
|
|
|
|
|
|
|
<validation_architecture>
|
|
|
|
|
## Validation Architecture
|
|
|
|
|
|
|
|
|
|
The phase has no existing Go tests. Execution should create small smoke tests alongside each functional slice and reserve a final, dedicated unit-test plan for complete behavior coverage, per CLAUDE.md. After every implementation task, run `go vet ./... && go test ./...` at the framework root and, after hello exists, `go vet ./... && go test ./...` from `examples/hello`. The last plan adds `go test -race ./...` for both modules and an integration script/test that runs `summer build` and the generated hello binary in a temporary workspace. Avoid tests that require an interactive terminal.
|
|
|
|
|
|
|
|
|
|
| Requirement | Automated evidence |
|
|
|
|
|
|---|---|
|
|
|
|
|
| KERN-01 | Table-driven deep-merge, six-layer precedence, env mapping, `.env`, Set/Persist/Reload, typed decode tests. |
|
|
|
|
|
| KERN-02/03/05/08 | Reordered lifecycle input, missing/cycle/duplicate ID, optional interface, HasPlugin and typed service lookup tests. |
|
|
|
|
|
| KERN-04 | Stable codegen golden test, `plugin:add` workspace/manifest test, hello `go build` and boot smoke. |
|
|
|
|
|
| KERN-06/07 | Three dispatch modes, ordering, errors/panics, app isolation, context propagation and race tests. |
|
|
|
|
|
| KERN-09 | Temp workspace create/write/rename and restart test, latency line assertion. |
|
|
|
|
|
| CLI-01 | Cobra command discovery and output capture, non-TTY widgets/prompts and color policy tests. |
|
|
|
|
|
|
|
|
|
|
The fast feedback command should take seconds once dependencies are cached. CI can measure actual duration rather than assume a fixed latency threshold. Test a single plugin source change with `summer dev` and record the measured rebuild time; the acceptance criterion asks for a measurement, not an arbitrary pass threshold.
|
|
|
|
|
</validation_architecture>
|
|
|
|
|
|
|
|
|
|
<open_questions>
|
|
|
|
|
## Open Questions
|
|
|
|
|
|
|
|
|
|
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.
|
|
|
|
|
</open_questions>
|
|
|
|
|
|
|
|
|
|
<sources>
|
|
|
|
|
## Sources
|
|
|
|
|
|
|
|
|
|
- Project decisions: [01-CONTEXT.md](01-CONTEXT.md), [ARCHITECTURE.md](../../research/ARCHITECTURE.md), [PITFALLS.md](../../research/PITFALLS.md), [STACK.md](../../research/STACK.md), `../modules/summer-compass/README.md`, `../modules/summer-bonfire/README.md`.
|
|
|
|
|
- Primary references: [Go toolchain](https://go.dev/doc/toolchain), [Go workspaces](https://go.dev/doc/tutorial/workspaces), [koanf](https://pkg.go.dev/github.com/knadh/koanf/v2), [koanf env/v2](https://pkg.go.dev/github.com/knadh/koanf/providers/env/v2), [Cobra](https://pkg.go.dev/github.com/spf13/cobra), [fsnotify](https://github.com/fsnotify/fsnotify/blob/main/README.md), [x/term](https://pkg.go.dev/golang.org/x/term).
|
|
|
|
|
</sources>
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
*Phase: 01-framework-kernel-foundation*
|
|
|
|
|
*Ready for planning: yes*
|