--- phase: 01-framework-kernel-foundation plan: 03 subsystem: kernel tags: [go, cobra, fsnotify, cli, scaffolding, watch] requires: - phase: 01-framework-kernel-foundation provides: Manifest-driven summer build, shared bonfire.NewRoot, hello app workspace provides: - make:plugin and plugin:add scaffolding against summer.yaml - Deterministic bonfire Output widgets and prompts with non-TTY fallback - Built-in summer dev watch/rebuild/restart loop affects: [01-04, 04] tech-stack: added: - golang.org/x/term v0.46.0 - github.com/fsnotify/fsnotify v1.10.1 patterns: - summer.yaml is the sole ordered plugin list; scaffold then plugin:add then build - One injected bonfire.Output decides TTY/color once per process - summer dev calls the same build.App used by summer build key-files: created: - internal/build/manifest.go - internal/build/scaffold.go - bonfire/output.go - bonfire/widgets.go - bonfire/prompts.go - internal/dev/watch.go modified: - internal/build/build.go - cmd/summer/main.go - bonfire/root.go - bonfire/command.go - examples/hello/plugins/greeter/plugin.go - go.mod - go.sum key-decisions: - "plugin:add is idempotent on the same id+module and rejects conflicting ids" - "Child go commands override inherited GOWORK so summer build in a nested app does not use a parent workspace" - "Confirm is silent on non-TTY and uses its default so tests never hang" - "Watch ignores app-root main.go and plugins.gen.go to prevent generate loops" patterns-established: - "Pattern: make:plugin writes plugins//{go.mod,plugin.go,config/}; plugin:add wires manifest, go.work and go.mod replace" - "Pattern: plugin command names are namespace:verb; kernel names build and dev are the only colon-less exceptions" - "Pattern: summer dev prints rebuild: after each successful build.App and reaps the child on cancel" requirements-completed: [KERN-04, KERN-09, CLI-01] duration: 26min completed: 2026-09-16 --- # Phase 1 Plan 3: Plugin Scaffold, CLI Output and Watch Loop Summary **make:plugin / plugin:add wire a compiling module into summer.yaml, bonfire degrades spinner/progress/table/prompts without a TTY, and summer dev rebuilds through build.App with measured restart latency** ## Performance - **Duration:** 26 min - **Started:** 2026-09-16T11:33:58Z - **Completed:** 2026-09-16T12:00:25Z - **Tasks:** 3 - **Files modified:** 21 ## Accomplishments - `summer make:plugin` scaffolds `plugins/` with `go.mod` (`toolchain go1.27.0`), `plugin.go` and empty `config/`; `plugin:add` appends one ordered manifest entry, `go work use`, and a portable app `go.mod` require/replace - Shared cobra adapter injects one `bonfire.Output` built from stdin/stdout/stderr; non-TTY spinner is `[...] message`, progress is `[N/M] pct%` at 10% steps, tables are TSV, and `NO_COLOR` / `TERM=dumb` disable ANSI - `summer dev` watches sources, debounces, calls `build.App`, prints `rebuild: `, keeps the last child on build failure, and reaps it on cancel without looping on generated `main.go` / `plugins.gen.go` ## Task Commits Each task was committed atomically: 1. **Task 1: Add and rebuild a compiling plugin from the tool** - `9b1a25d` (feat) 2. **Task 2: Give tool and plugin commands deterministic rich output** - `a6004e4` (feat) 3. **Task 3: Rebuild and restart the hello binary during source edits** - `270b7f1` (feat) **Plan metadata:** pending (docs: complete plan) ## Files Created/Modified - `internal/build/manifest.go` - Load/Save summer.yaml, lowercase vendor.plugin IDs - `internal/build/scaffold.go` - MakePlugin / AddPlugin with path containment checks - `internal/build/build.go` - generate-and-compile plus GOWORK isolation for child `go` commands - `cmd/summer/main.go` - `make:plugin`, `plugin:add`, `build`, `dev` tool commands - `bonfire/output.go` / `widgets.go` / `prompts.go` - injected Output, spinner, progress, table, prompts - `bonfire/root.go` / `command.go` - cobra adapter, named `ErrCommandName` for plugin names without `:` - `internal/dev/watch.go` - fsnotify watch loop with debounce, serialize, restart, reap - `examples/hello/plugins/greeter/plugin.go` - table plus confirm on `greeter:hello` without hanging on closed stdin ## Decisions Made - Keep generated plugin paths under `plugins/` derived from the ID's plugin segment - Treat `build` and `dev` as the only kernel command names allowed without a colon - Detect widgets from stdout TTY and prompts from stdin+stdout TTY so piped tests use defaults - `secret` uses `term.ReadPassword` on a TTY file and a plain stdin line otherwise; answers are never written back - Watch production path always calls `build.App`; tests inject Build/Start so debounce and ignore behavior stay fast ## Deviations from Plan ### Auto-fixed Issues **1. [Rule 3 - Blocking] Child go commands inherited test GOFLAGS/GOWORK** - **Found during:** Task 1 (plugin compile on a temp hello copy) - **Issue:** `go test` sets `-mod=readonly` and a parent workspace; `go build` of a temp app then targeted the wrong module - **Fix:** Strip inherited `GOWORK`/`GOFLAGS` and set `GOWORK` to the nearest app `go.work` (or `off`) - **Files modified:** `internal/build/scaffold.go`, `internal/build/build.go` - **Verification:** `go test ./internal/build` - **Committed in:** `9b1a25d` (Task 1) **2. [Rule 3 - Blocking] NewRoot now returns a named command-name error** - **Found during:** Task 2 - **Issue:** Plugin names without `namespace:verb` must fail registration; callers and generated `main.go` still treated NewRoot as a single return - **Fix:** `NewRoot`/`NewRootIO` return `(*cobra.Command, error)`; generateMain and hello callers updated - **Files modified:** `bonfire/root.go`, `internal/build/build.go`, `examples/hello/main.go`, `examples/hello/hello_test.go`, `cmd/summer/main.go` - **Verification:** `go test ./bonfire ./cmd/summer` and hello tests - **Committed in:** `a6004e4` (Task 2) **3. [Rule 3 - Blocking] Greeter test Output stub no longer satisfied the interface** - **Found during:** Task 2 - **Issue:** Expanding Output broke `examples/hello/plugins/greeter/plugin_test.go`'s three-method stub - **Fix:** Run the command against `bonfire.NewOutput` with injected streams - **Files modified:** `examples/hello/plugins/greeter/plugin_test.go` - **Verification:** `go test` in the greeter module - **Committed in:** `a6004e4` (Task 2) --- **Total deviations:** 3 auto-fixed (3 blocking) **Impact on plan:** Required for temp-app builds, named registration errors, and a compiling greeter test. No scope creep. Choice prompts use a numbered list rather than TTY arrow keys; non-TTY behavior matches the plan. ## Issues Encountered - `go mod tidy` in a workspace still drops `toolchain go1.27.0` unless it is rewritten; Task 1 restores it after plugin tidy (same D-05 pattern as Plans 01 and 02). ## Authentication Gates None. ## User Setup Required None - no external service configuration required. ## Next Phase Readiness Ready for `01-04-PLAN.md` (phase unit-test coverage). Scaffolding, rich CLI output and `summer dev` exist on the hello path. Do not add HTTP/DB/auth here. ## Self-Check: PASSED - Created scaffold, output, watch, and SUMMARY files exist on disk - Commits `9b1a25d`, `a6004e4` and `270b7f1` exist - Root and hello `go vet ./...` and `go test ./...` passed - STATE.md and ROADMAP.md were not updated in this worktree --- *Phase: 01-framework-kernel-foundation* *Completed: 2026-09-16*