docs(01-03): complete plugin scaffold CLI and watch-loop plan
- Record make:plugin, bonfire output and summer dev results
This commit is contained in:
164
.planning/phases/01-framework-kernel-foundation/01-03-SUMMARY.md
Normal file
164
.planning/phases/01-framework-kernel-foundation/01-03-SUMMARY.md
Normal file
@@ -0,0 +1,164 @@
|
||||
---
|
||||
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/<name>/{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: <duration> 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/<name>` 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: <duration>`, 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/<name>` 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*
|
||||
Reference in New Issue
Block a user