diff --git a/docs/roadmap/implementation.md b/docs/roadmap/implementation.md index 56b5523..283d4dd 100644 --- a/docs/roadmap/implementation.md +++ b/docs/roadmap/implementation.md @@ -1,892 +1,443 @@ -# Initial CommandKit implementation plan +# ReleaseKit adoption implementation plan -Status: completed execution record; Stages 1-14 complete. +Status: ready for implementation; Stages 1–6 pending. -Date: 2026-10-07. +Date: 2026-10-08. -## Record scope and current owners +## Scope and authority -The staged instructions and API illustrations below are retained as the record -of the completed initial implementation. They describe the assignments used to -produce the [selected feature target](initial.md), not work to restart. The -[CLI reference](../cli.md) owns current operator behavior, Go declarations and -GoDoc own current API contracts, the [consumer guide](../consumers/guide.md) owns -usage guidance, and the [internal overview](../internal/overview.md) owns mechanics. +Implement the target in the [ReleaseKit feature roadmap](releasekit.md). +Read this entire plan before starting, then complete the numbered stages in +order. Each stage is one Luna implementation assignment. This plan supplies +concrete execution choices; the feature roadmap owns the target and user intent. +The [release policy](../policy/release.md), +[architecture policy](../policy/architecture.md), and accepted ADRs control +their respective boundaries. -### Subsequent code remediation +This file replaces the completed initial library implementation record. That +record remains available at +[its reconciled source revision](https://gitea.maximumdirect.net/eric/CommandKit/src/commit/3871d837489b9955998b362587a52b47282dc021/docs/roadmap/implementation.md). +Historical documents still linking here concern that record, not these new +assignments. Stage 5 repairs those references. Do not restart the completed +library implementation or its remediation work. -After original stage completion at `85f44cd`, ten code-remediation units were -committed from `d8db15f` through `cb0b8dd`. They corrected scope-specific required -selectors, inline YAML framing, cancellation boundaries, help failure delivery, -validation delivery errors, outcome defaults, nil diagnostic handling, scope -choices, selector-name collisions, and metadata-only help discovery. These -corrections are reflected in current code and its regression checks. Original -stage completion notes remain historical evidence, not a new validation run. +The implementation sprint delivers maintainer tooling, not CommandKit's first +published release. Do not push to the real repository, create release tags in +CommandKit, prepare a placeholder release note, or configure hosted delivery as +part of these stages. Local disposable Git repositories are the publication +test boundary. Publication of a real candidate remains separately authorized +work under the runbook. -## Historical instructions for the implementation agent +## Baseline and selected implementation choices -Implement the selected end state in [the feature roadmap](initial.md). Read this -whole plan before starting. Complete Stage 1, then each subsequent stage in numeric -order. Each stage is sized as a separate Luna implementation assignment. Later -stages depend on the completed earlier stages, even where their feature IDs overlap. +At planning time, HEAD is `0690ff6`, the worktree is clean, and the feature +roadmap is committed. CommandKit's initial library and documentation +reconciliation are complete. Root `go.mod` declares Go 1.25.5 and has no +ReleaseKit dependency. There is no root release profile, publication launcher, +release runbook, or release-note history. The feature roadmap records the +remote and source-only release scope. -This document owns implementation steps and the concrete design needed to execute -them. The feature roadmap owns the target and user intent. The accepted ADRs and -[architecture policy](../policy/architecture.md) control architectural boundaries. -The older numbered roadmaps are evidence; their conflicting or unselected -proposals do not override this plan or the accepted decisions. +Use ReleaseKit v0.2.0, reviewed at +`e030794969fb7787e647a90bbc4eb81bd0610f07`. Its +[CLI reference](https://gitea.maximumdirect.net/eric/ReleaseKit/src/commit/e030794969fb7787e647a90bbc4eb81bd0610f07/docs/cli.md), +[profile reference](https://gitea.maximumdirect.net/eric/ReleaseKit/src/commit/e030794969fb7787e647a90bbc4eb81bd0610f07/docs/config.md), and +[publication guide](https://gitea.maximumdirect.net/eric/ReleaseKit/src/commit/e030794969fb7787e647a90bbc4eb81bd0610f07/docs/consumers/publish.md) +own upstream behavior. `../ReleaseKit` is optional review evidence, not a build +dependency or a source tree to modify. -Before each stage, follow [development orientation](../development.md) and the -[agent policy](../policy/agents.md). Read applicable documentation, testing, and -OSS policy sections. Inspect the current implementation and previous stage work; -use the prescribed knowledge-graph discovery workflow for code. Keep changes -focused on the assigned stage. Document implemented behavior when it lands. +The execution choices are: -The implementation assignments include the behavioral evidence listed below. -Use the [testing policy](../policy/testing.md) to avoid redundant assertions or -tests of incidental private structure. Use real collaborators where deterministic; -use controlled providers/writers for failures. The default suite is offline and -uses no real credentials or model requests. Once the module exists, format touched -Go files and run the relevant tests, then `go test ./...` for the completed stage. -Dependency/toolchain preparation can happen beforehand; tests themselves must not -require network access. No coverage threshold, race/platform matrix, scanner, -publisher, or consumer migration is introduced by this plan. +- Track the executable with a root Go `tool` directive and a v0.2.0 module + requirement. Build from that selection, without an independent script pin. +- Author a small POSIX shell launcher in `scripts/release`, and use ignored + `.releasekit/bin/releasekit` for its native executable. +- Author the launcher and runbook for CommandKit, using upstream as behavioral + guidance rather than copying substantive source or prose. This avoids an + unnecessary copied-material attribution obligation. Tool use alone does not + require new component entries under the existing OSS policy; changes to + incorporated runtime dependencies still receive their applicable treatment. +- Use a minimal source-only JSON profile with the default suite and explicit + product, remote, and expected push URL. Leave optional checks and delivery + unselected. +- Keep fast launcher tests in a tests-only `scripts` Go package. Keep a real + local publication exercise explicitly opt-in in that same package, so ordinary + release validation does not repeatedly bootstrap and retest the publisher. +- Push the real candidate's branch before its tag when following the future + runbook. ReleaseKit owns validation and tag publication; the launcher does not + implement its own guards or branch push. -For each completed stage, report its deliverables, checks, and remaining work. -Apply the local commit policy to completed units. Update this document's stage -status as work completes; retain deferred work in the feature roadmap. A stage is -complete when its implemented boundary and checks are complete, not when the -entire final library already exists. Early stages may establish declarations that -later stages use, but must compile and must not claim later behavior is implemented. +These choices add no production Go package, runtime ReleaseKit import, public +API, standard command family, or changes to application version semantics. +Hosted notes, binary targets, CI delivery, and additional release gates remain +deferred as specified in the feature roadmap. -## Baseline and execution boundaries +## Instructions for every stage -At planning time, CommandKit contains documentation, policies, and nine accepted -ADRs, with no Go module or production Go code. Initial delivery uses ConfigKit -v0.5.0 and PromptKit v0.12.0. Their inspected commits and consumer reuse candidates -are recorded in the feature roadmap. Those sibling checkouts are review evidence; -the implementation uses released public APIs and module dependencies. +1. Follow [developer orientation](../development.md) and the + [agent policy](../policy/agents.md). Inspect current state and prior stage + evidence; preserve unrelated work. Prefer knowledge-graph tools for code + discovery. Read policies relevant to the assigned edits. +2. Implement only the assigned stage and its necessary supporting documentation. + Do not treat later stages or existing historical plans as already completed. + If evidence contradicts a selected choice, report the concrete issue rather + than silently substitute another version, integration, or release policy. +3. Prepare dependencies separately when needed. Checks below are implementation + evidence, not additional permanent release gates. No real credentials, + hosted-service requests, or live publication are needed for them. +4. Format changed Go files. Use focused checks for the stage, and reuse evidence + for unchanged work. The default suite is run in Stages 1, 3, and the final + audit to cover the changed module, new tests, and completed integration; + prose-only stages need document review, not another suite. This is development + validation across changing commits, not a requirement to test a real release + candidate repeatedly before `publish` tests it. +5. Update this plan's stage status and evidence with actual results. Commit each + completed stage under the local commit policy and report its commit, checks, + and remaining work. Review the staged diff and whitespace before committing. -Create exactly the two selected production packages: root `commandkit` and -`internal/cobra`. Production file names below are suggested organization, not -compatibility contracts. Root public named types retain their own declarations -and private implementation state. No root aliases, embedding, loose bridge -objects, or returned backend errors expose Cobra/pflag or internal types. +## Stage inventory -Code in the adapter may use neutral bridge types exported within `internal/cobra`; -these types are not aliased into the public API. The root imports the adapter; the -adapter never imports the root. Keep registry policy, typed input construction, -standard handlers, providers, and reports in the root. - -The implementation reuses owning writers and public records. Write the small -integration glue from those contracts. Treat Notarius/Scriptorium code as behavior -and field-inventory evidence; this plan requires no source copy. If a substantive -copy becomes desirable, resolve its actual rights and record source revision, -changes, and notices under the OSS policy before copying. Do not infer a change -from GPL application grants to CommandKit's LGPL grant from common ownership. - -Defer `config diff`, PromptKit catalogs/listing, JSON reports, shell completion, -output-file management, selectable backends, general DI/plugin machinery, -concurrent-dispatch guarantees, new library families, migrations, and publication. -Do not install placeholders or claim capabilities for deferred features. - -## Stage inventory and feature coverage - -| Stage | Deliverable | Feature IDs | +| Stage | Deliverable | Roadmap coverage | | --- | --- | --- | -| 1 | Module, identity/outcome primitives, initial dependency attribution | API-01, OUT-01 | -| 2 | Instance registry and composable command declarations | API-01, REG-01 | -| 3 | Typed flag/operand bindings, defaults, and presence | INPUT-01 | -| 4 | Internal Cobra routing/parsing bridge | BACK-01, INPUT-01 | -| 5 | Public invocation and diagnostic/delivery coordination | INV-01, OUT-01 | -| 6 | Complete generated help and version commands | HELP-01, VER-01 | -| 7 | Typed configuration suites, scopes, selectors, discovery | INT-01, CFG-01 | -| 8 | ConfigKit scope helper and validation | INT-01, CFG-02 | -| 9 | Native and aggregate YAML display | CFG-03 | -| 10 | Source inventory reports | CFG-04 | -| 11 | Safe path explanation reports | CFG-05 | -| 12 | PromptKit configuration scope | PK-01 | -| 13 | Named prompt/profile inspection, including ExtraParams | PK-02, PK-03 | -| 14 | Public examples, consumer fit, documentation and completion audit | All included IDs | +| 1 | Released Go tool dependency and applicable licensing review | RK-01, RK-05 | +| 2 | Source-only profile and native publication launcher | RK-02, RK-03 | +| 3 | Fast deterministic launcher tests | RK-03, RK-06 | +| 4 | Opt-in publication exercise against disposable local Git repositories | RK-06 | +| 5 | Maintainer runbook, policy status, and navigation reconciliation | RK-04 | +| 6 | Final adoption audit and completion record | RK-01–06 | -## Stage 1: establish the module and outcome primitives +## Stage 1: declare and prepare the released tool dependency -**Status:** complete. **Prerequisite:** repository orientation. +**Status:** pending. **Prerequisite:** repository orientation and this plan. -1. Create `go.mod` for `gitea.maximumdirect.net/eric/CommandKit`, with `go 1.25.5`. - Use the roadmap's initial pins: ConfigKit v0.5.0, PromptKit v0.12.0, - Cobra v1.10.1, pflag v1.0.9, and `go.yaml.in/yaml/v4 v4.0.0-rc.6`. - Resolve the actual graph and maintain `go.sum`. Keep required transitive - dependencies; do not use adjacent checkouts or committed local replacements. -2. Add applicable dependency notices/license texts when incorporating those - dependencies, following [the OSS policy](../policy/oss.md). Use exact imported - commits and actual upstream notices; assess relevant transitive components from - the resolved graph. Do not add fictional entries or generic legal conclusions. -3. Add `doc.go`, `identity.go`, and `outcome.go` with the root-owned types below. - Update development commands to their implemented boundary once the module exists. +**Files:** `go.mod`, `go.sum`; affected notices only if existing incorporated +dependencies change; stage evidence in this plan. -The following declarations specify public API shapes; implement bodies and GoDoc -in their owning stages. They are not files to copy verbatim with missing bodies. +1. From the repository root, add the executable tool dependency: -```go -type Identity struct { - Name, Version, Revision string -} -type Streams struct { Out, Err io.Writer } -type Invocation struct { - Context context.Context - Streams Streams -} -type OutcomeKind string -// Constants: OutcomeSuccess="success", OutcomeUsage="usage", -// OutcomeOperational="operational", OutcomeDomain="domain". -type DeliveryState string -// Constants: DeliveryNone="none", DeliveryComplete="complete", -// DeliveryIncomplete="incomplete". -type Diagnostic struct { - Severity configkit.Severity - Write func(io.Writer) error -} -type Outcome struct { - Kind OutcomeKind - Status int - Domain string - Cause error - DeliveryError error - DiagnosticDelivery DeliveryState - ReportIncomplete bool - Diagnostics []Diagnostic -} -func Success() Outcome -func Usage(cause error) Outcome -func Failure(cause error) Outcome -func Domain(name string, status int, cause error) Outcome -func MessageDiagnostic(severity configkit.Severity, message string) Diagnostic + ```sh + GOWORK=off GOTOOLCHAIN=local go get -tool gitea.maximumdirect.net/eric/ReleaseKit/cmd/releasekit@v0.2.0 + GOWORK=off GOTOOLCHAIN=local go mod tidy + ``` + +2. Review the resulting graph. Retain the tool declaration and released v0.2.0 + requirement, with its necessary indirect requirements and checksums. Preserve + CommandKit's Go 1.25.5 directive; ReleaseKit and its reviewed Goldmark and + `x/mod` requirements fit that minimum. Review any existing dependency version + changes rather than silently upgrade unrelated libraries. Do not add a local + replacement, a blank runtime import, a separate tools module, or a duplicate + version constant to retain the executable. +3. Apply [OSS policy](../policy/oss.md) to the actual result. ReleaseKit, + Goldmark, and `x/mod` are selected for development tooling, with no source copy + or tool binary distribution in this integration. Tool use alone does not + require new attribution entries. If module resolution changes an existing + incorporated dependency, update its actual notices and pinned source links + with that change. Record the review result here, not as an editorial paragraph + in the attribution document. +4. Prepare caches through normal Go access before offline checks: + + ```sh + GOWORK=off GOTOOLCHAIN=local go mod download + ``` + +**Evidence:** inspect `go list -m gitea.maximumdirect.net/eric/ReleaseKit` with +workspace discovery disabled; it selects v0.2.0. Run `go mod tidy -diff` with +the same workspace/toolchain settings; it reports no further changes. Build +`gitea.maximumdirect.net/eric/ReleaseKit/cmd/releasekit` with `-mod=readonly` +into a disposable directory outside the worktree and invoke only `version`. +Confirm that the build leaves `go.mod` and `go.sum` unchanged. Run the current +default suite once with `GOWORK=off GOTOOLCHAIN=local GOPROXY=off +GONOPROXY=none GOSUMDB=off go test -mod=readonly -count=1 ./...`. + +**Completion:** the root module retains its released tool selection through +ordinary maintenance, the executable builds, affected notices are correct, and +existing library checks pass. Commit the stage before proceeding. + +## Stage 2: implement the source-only publication entry point + +**Status:** pending. **Prerequisite:** Stage 1. + +**Files:** root `releasekit.json`, `scripts/release`, `.gitignore`, and stage +evidence in this plan. + +1. Add the root profile with exactly this initial configuration: + + ```json + { + "product": "CommandKit", + "remote": "origin", + "expected_push_url": "https://gitea.maximumdirect.net/eric/CommandKit.git" + } + ``` + + Omit `checks`, `validation`, `build`, and `delivery`. Their omission selects + the upstream defaults without installing extra gates or deliverables. +2. Write `scripts/release` with `#!/bin/sh` and `set -eu`. Require exactly one + argument; otherwise print `usage: ./scripts/release VERSION` to stderr and + exit 2 before invoking Go. Pass the version argument unchanged to ReleaseKit; + ReleaseKit owns semantic version validation. +3. Resolve the repository root from the launcher's directory, then change to + that root. Use quoted path expansions and a task-specific variable such as + `commandkit_root`. Resolve the directory with `CDPATH=` for the directory + change so an ambient `CDPATH` does not corrupt captured path output. Support + ordinary invocation from another working directory and paths containing + spaces; no general symbolic-link resolution framework is required. +4. Create `.releasekit/bin`. Query Go's `GOHOSTOS` and `GOHOSTARCH` using the + local toolchain with workspace discovery disabled, storing them separately + without replacing the version argument. Build the tool using those native + target values, `GOWORK=off`, `GOTOOLCHAIN=local`, and this argument vector: + + ```text + go build -mod=readonly -o .releasekit/bin/releasekit gitea.maximumdirect.net/eric/ReleaseKit/cmd/releasekit + ``` + + This builds the executable for the host that must run it, even when the + caller has selected an application cross-compilation target. Dependency + preparation remains separate; no launcher `go get`, `go mod tidy`, alternate + module file, linker injection, or independently selected tool version is + needed. Bootstrap can use normal module access; the candidate suite itself + is offline under ReleaseKit's environment. +5. Replace the shell process with the built executable using `exec` and this + argument vector, quoting both absolute paths and the version: + + ```text + .releasekit/bin/releasekit publish --repo ROOT --config ROOT/releasekit.json VERSION + ``` + + The flags precede `VERSION` as required by ReleaseKit. Preserve its streams + and exit status directly. Do not intercept its publication states, run `check` + first, auto-push `main`, or use `go run` as the publication process. +6. Mark the launcher executable in Git. Add `/.releasekit/` to the root ignore + file; this local bootstrap output is not a declared release artifact. + +**Evidence:** review the profile against upstream, run `sh -n scripts/release`, +and verify the executable mode and ignore rule. Exercise zero and multiple +arguments without a candidate; both return 2 without tool bootstrap. Do not +invoke a valid version against CommandKit's real repository as a smoke check. + +**Completion:** the profile and launcher match the selected target and delegate +publication to the module-selected native CLI. Commit the stage. + +## Stage 3: cover launcher behavior with fast offline tests + +**Status:** pending. **Prerequisite:** Stage 2. + +**Files:** `scripts/release_test.go`, plus launcher corrections found by the +tests and stage evidence in this plan. Use a tests-only external Go package such +as `release_test`; add no production Go file or exported helper API. + +1. Use standard-library Go tests with temporary directories. Copy the real + launcher and profile into a temporary repository-shaped directory whose path + contains spaces. Invoke the copied launcher from a different directory. + A controlled `go` executable placed first on the child process's `PATH` + supplies the two host environment answers and writes a fake executable at + the requested build output path. The fake executable logs received arguments, + writes distinct stdout/stderr messages, and exits with a test-selected status. + Keep all test controls inside fixture subprocess environments, not launcher + options or product configuration. +2. Cover these observable integration risks: + + | Case | Required observation | + | --- | --- | + | Zero or multiple arguments | Usage on stderr and status 2; Go is not invoked. | + | Valid invocation from another directory | Build occurs at the copied root; publication receives `publish`, explicit absolute repository/profile paths, and the supplied version as separate arguments. | + | Module-selected native bootstrap | The tool package has no `@version` suffix; readonly mode and the expected output are used; the local toolchain, disabled workspace, and queried host target govern the build. | + | Executable returns 0, 1, 2, or 3 | Each status is preserved, with stdout/stderr delivered to their corresponding streams. These cases test delegation, not upstream recovery semantics. | + | Bootstrap failure | The launcher stops with the build failure and never invokes the fake publication executable. | + +3. Test argument values and outcomes rather than exact shell source or private + call counts. Do not add a signal-management framework or a new guarantee + merely to test `exec`; source review plus direct process replacement establish + the selected signal handoff. The script remains a POSIX maintainer tool: + skip shell execution tests with an explicit reason if a POSIX shell is + unavailable, rather than add a Windows publisher. +4. Use per-command working directories and environments. Do not modify process + global working directories or the real repository's remote configuration. + +**Evidence:** format the test file, run the focused scripts package tests, then +the default offline suite with the Stage 1 environment. None of these tests +compiles a real publisher or contacts a service. + +**Completion:** the small launcher has regression coverage for its own parsing, +path, build, and delegation responsibilities. Commit the stage. + +## Stage 4: exercise real publication against disposable Git repositories + +**Status:** pending. **Prerequisite:** Stage 3 and prepared dependency caches. + +**Files:** `scripts/release_integration_test.go`, supporting fixture helpers in +that tests-only package if needed, and stage evidence in this plan. + +1. Add `TestReleaseIntegration`, skipped unless + `COMMANDKIT_RELEASE_INTEGRATION=1`. This explicit development opt-in is not + a profile check or a required step before ordinary releases. Keep fast tests + enabled normally. Explain the opt-in and cache prerequisite in the test; + Stage 5 exposes its command in the developer guide. +2. Construct a disposable worktree on `main` and a separate local bare Git + repository. Supply fixture-local identity and disable signing and hooks + through isolated Git configuration; do not alter the maintainer's global + settings. Clear inherited Git directory/worktree overrides for fixture + commands so every operation addresses the fixture. +3. Copy CommandKit's current `go.mod`, `go.sum`, launcher, and ignore file into + the fixture. Copy the real JSON profile, changing only `expected_push_url` + to the local bare repository's absolute path. Keep product `CommandKit` and + remote `origin`. Do not copy CommandKit's tests: the fixture is a tiny Go + package, avoiding recursive execution of these integration tests. +4. Write a fixture-only note `docs/releases/v0.0.1.md` headed + `# CommandKit v0.0.1`, and a small standard-library Go test that appends one + marker to a path supplied through its environment outside the worktree. + This marker demonstrates one candidate-suite run without adding a product + check. Commit fixture contents, configure `origin` to the local bare path, + and push fixture `HEAD:refs/heads/main`. These are local fixture operations, + not publication of CommandKit. +5. Invoke the copied launcher from another directory with the actual Go tool + and module-selected ReleaseKit. Make dependency and toolchain downloads + unavailable during the exercise. Check that it returns success, reports the + fixture candidate/version, publishes an annotated `v0.0.1` tag pointing at + that commit, leaves remote `main` at the candidate, writes one suite marker, + and leaves fixture candidate status clean. Check that only the intended tag + was added and no binary delivery outputs were produced. The ignored local + bootstrap executable is expected. +6. On that fixture, prepare and commit a second note for `v0.0.2` and change + `expected_push_url` to a different local path. Push the new fixture `main`, + then invoke the launcher. Expect known failure status 1 with an endpoint + mismatch diagnostic, no new local or remote tag, and no additional suite + marker. This protects profile wiring without rebuilding upstream's entire + remote-conflict and failed-push matrix. Status 3 propagation is already + covered by the Stage 3 executable double. +7. Use `t.TempDir` cleanup and an overall subprocess context deadline to avoid a + stalled fixture. Avoid timing-sensitive assertions and output snapshots. + Missing shell/Git support can cause an explicit platform skip; when opt-in is + selected, missing dependency caches or a real execution failure must be + reported as failure, not disguised as a successful skip. + +**Evidence:** prepare caches using the Stage 1 preparation command, then run: + +```sh +COMMANDKIT_RELEASE_INTEGRATION=1 GOWORK=off GOTOOLCHAIN=local GOPROXY=off GONOPROXY=none GOSUMDB=off go test -mod=readonly -count=1 ./scripts -run '^TestReleaseIntegration$' ``` -Use the public ConfigKit severity type deliberately rather than introducing a -parallel severity hierarchy. Diagnostic writers are caller/root functions, never -backend objects. Their output goes through Stage 5's single presentation path. - -`Success`, `Usage`, and `Failure` set kinds/statuses to success/0, usage/2, and -operational/1. `Domain` preserves the supplied domain name, status, and cause. -`Cause` is the operation's error; `DeliveryError` records writer failures separately -and may reference the same error when writing itself caused the operation failure. -Callers inspect these errors with `errors.Is`/`errors.As`; Outcome need not implement -`error`. Empty diagnostic delivery state normalizes to `DeliveryNone`. A zero -Outcome normalizes to success/0 when no classification was supplied; do not infer -domain meaning from numeric status. The explicit domain classification survives -invocation coordination. - -**Checks:** compilation; focused outcome-helper checks for classification/status -and cause identity. No invocation or inspection behavior is claimed yet. - -**Completion:** added the module and resolved dependency checksums, root identity -and outcome declarations, dependency attribution, and current development commands. -Verified with `go test ./...`, `go mod verify`, and -`git diff --check -- '*.md' COPYRIGHT`. - -## Stage 2: implement the instance registry and command declarations - -**Status:** complete. **Prerequisite:** Stage 1. - -Implement `App`, opaque `Command`, metadata, group composition, and registration -in root files such as `app.go`, `command.go`, and `registry.go`. - -```go -type App struct { /* private state */ } -type Command struct { /* private declaration */ } -type Supplied[T any] struct { Value T; Set bool } -type FlagMeta struct { Name, Short, Usage string; Required bool } -type ArgumentMeta struct { Name, Usage string } -type Flag[I any] struct { /* private binding declaration */ } -type Argument[I any] struct { /* private binding declaration */ } -type CommandSpec[I any] struct { - Name, Summary, Description string - NewInput func() I - Flags []Flag[I] - Arguments []Argument[I] - CheckInput func(I) error - Run func(Invocation, I) Outcome -} -func New(identity Identity, commands ...Command) (*App, error) -func NewCommand[I any](spec CommandSpec[I]) (Command, error) -func Group(name, summary string, children ...Command) (Command, error) -func WithChildren(parent Command, children ...Command) (Command, error) -func (a *App) Register(commands ...Command) error -``` - -1. Commands have one path component as `Name`; composition supplies the prefix. - `Group` creates a non-runnable parent. `WithChildren` returns a new declaration - retaining the parent's optional Run and bindings. Children are relative to that - parent. A runnable parent and its children can both be invoked. -2. Keep declarations independent of invocation state. Retain callbacks without - invoking NewInput, setters, handlers, or acquisition while registering. Copy - declarative slices as needed so registration owns its routing metadata; this - does not deep-copy caller closure state or arbitrary input objects. -3. Validate routable declarations: nonempty single-token command names, unique - sibling paths/flag names/short spellings, valid operand bounds, and required - parser/setter wiring. A command token must not be option syntax or `--`, since - those tokens delimit routing. Do not impose a lowercase vocabulary policy on - custom command names. Scope identifiers have their separate Stage 7 rules. -4. Reject duplicate paths; do not merge user registrations based on order. - Register a complete group with its children. Validate a registration batch - before attaching it so a rejected standard-family install leaves no half-tree. -5. New requires a nonempty identity Name and accepts optional initial command - registrations. It reserves and creates metadata for automatic root help/version; - Stage 6 supplies their complete handlers. Standard installers claim `config` and - `promptkit` ownership as their families are installed. Custom commands cannot - replace standard commands or add children under installed owned families. - A pre-existing custom tree at the same family path makes installation fail. -6. `NewInput == nil` means a fresh zero I. A supplied factory is invoked only for - execution after successful parse/help handling, and can initialize unbound - runtime fields. CommandKit overwrites bound fields from fresh parsed state and - defaults. Shared objects deliberately supplied by the factory stay caller-owned. - `CheckInput` is declared input-combination validation and returns usage failure; - domain validation belongs in Run or acquisition. - -Define the private binding storage needed by Stage 3, but add no public factories -with unimplemented bodies. Complete public type ownership without an extra engine -package or exported bridge methods. - -**Checks:** metadata construction does not invoke callbacks; independent App -registries; duplicate nested paths; runnable-parent composition; registration errors -leave the previous inventory intact. Execution remains Stage 5 work. - -**Completion:** added typed command declarations, group composition, root help and -version reservations, and atomic per-App registration. Verified with `go test ./...`. - -## Stage 3: implement typed bindings and input assembly - -**Status:** complete. **Prerequisite:** Stage 2. - -Add root factories in `binding.go` using these signatures: - -```go -func ValueFlag[I, V any](meta FlagMeta, defaultValue *V, - parse func(string) (V, error), set func(*I, Supplied[V])) Flag[I] -func BoolFlag[I any](meta FlagMeta, defaultValue bool, - set func(*I, Supplied[bool])) Flag[I] -func RepeatFlag[I, V any](meta FlagMeta, defaults []V, - parse func(string) (V, error), set func(*I, Supplied[[]V])) Flag[I] -func ValueArgument[I, V any](meta ArgumentMeta, required bool, - parse func(string) (V, error), set func(*I, Supplied[V])) Argument[I] -func RepeatArgument[I, V any](meta ArgumentMeta, min, max int, - parse func(string) (V, error), set func(*I, Supplied[[]V])) Argument[I] -``` - -1. A nil scalar default is the zero V; defaults never imply Set. With no explicit - repeat occurrence, use a fresh copy of defaults and Set=false. Once supplied, - repeated values replace the default collection and accumulate in argv order. - Explicit empty, false, and zero values set Set=true. Ordinary fields can use a - setter that assigns only `.Value`. -2. Singleton occurrences are all converted; each later successful occurrence - replaces the previous value. A malformed earlier occurrence remains a - conversion failure. Repeat conversion is one occurrence per value; do not apply - pflag's CSV/slice interpretation to a domain string containing commas. -3. Use `strconv` scalar parsers, `time.ParseDuration`, or caller domain parsers; - consumers can pass standard parsers directly. BoolFlag uses presence=true and - explicit `=true|false` conversion through `strconv.ParseBool`. ValueFlag is - available for bool-like domain values needing an ordinary value argument. -4. Parse into fresh typed binding values before constructing I. This lets help - inspect provided flag syntax without invoking NewInput. After help/parse checks, - allocate a fresh I, call NewInput if supplied, and apply typed setters. There is - no handler lookup of raw flags by name and no generic reflective field mapper. -5. ValueArgument has minimum 1 or 0 and maximum 1. RepeatArgument uses supplied - bounds; max=-1 means unbounded. Allocate operands in declaration order, greedily - within each maximum while reserving the minimum required by later arguments. - This also defines multiple/optional variable-length declarations without an - incidental final-variadic-only restriction. Reject unsatisfied total bounds. -6. Metadata exposes defaults, requiredness, repetition, and operand counts in - help. Render typed defaults for display without exposing backend flag objects. - A custom one-byte Short spelling is optional; standard options use long names - except the accepted `-h` help spelling. Names/spellings cannot collide with local help. - -**Checks:** focused binding behavior for omission, explicit zero/false/empty, -last-wins, repeated order and comma-containing strings, defaults, positional -allocation, caller parse errors, and fresh collections/input state. Adapter-level -integration of these cases belongs to Stage 4/5; avoid duplicating every case. - -**Completion evidence:** binding behavior tests and `go test ./...` pass. Input -factories remain deferred until callers build a prepared input; help-mode -preparation parses supplied values without enforcing omitted required values. - -## Stage 4: implement the internal Cobra adapter - -**Status:** complete. **Prerequisite:** Stage 3. - -1. Create `internal/cobra` with neutral tree/flag/operand declarations and fresh - per-run binding factories. A bridge declaration contains path metadata, - descriptions, local flag metadata, and conversion callbacks. A parse result - contains the selected path, help request, operands, and neutral failure data. - Backend-owned failures return message data, not backend error objects. A - caller-parser cause is retained separately where supplied. -2. Build a fresh backend tree and pflag value storage per invocation. Split argv - before its first option or `--`. Give only that leading word sequence to Cobra - Find; combine its unconsumed operands with the original tail for the selected - command's ParseFlags call. Set a neutral Args callback so root metadata, rather - than backend legacy operand policy, validates argument counts. Cobra resolves - children until a non-child operand; never resume routing after an option or - operand. A runnable parent's remaining words are its operands. A non-runnable - group with an unknown trailing command gets a usage failure. -3. This boundary adaptation avoids Cobra's ordinary flag-stripping search selecting - a child beyond an earlier option. Do not feed the tail into a second tree-wide - Execute search or write a parallel tree router. Root coordination invokes the - neutral handler after parse. The relevant machinery is in [Cobra's pinned source](https://github.com/spf13/cobra/blob/v1.10.1/command.go). -4. Adapt pflag Values to the Stage 3 conversions, boolean no-value behavior, - presence, and repeated-value rules. Enable interspersed operands; `--` ends - parsing. The [pinned pflag parser](https://github.com/spf13/pflag/blob/v1.0.9/flag.go) - is the tokenizer/conversion mechanism. Do not add a second general flag parser. -5. Keep flags local to resolved commands. Group flags are available when that - group runs; do not invent inherited/global standard flags. Reject options - before a later path component instead of silently moving them to the child. -6. Install local `--help`/`-h` metadata; `--help=false` is an ordinary execution - request. Parse supplied flags for help, but bypass missing execution-required - flags/operands and CheckInput. Unknown flags and invalid help paths remain - usage failures. Enforce supplied operand maxima and conversions where applicable. -7. Suppress automatic backend diagnostics/usage printing. Configure backend - streams/context explicitly; do not allow backend defaults to select process - streams. Do not initialize completion commands or implicit version flags. - -Do not route application outcomes through Cobra errors. Callback errors remain -root-owned. Translate only failures created by backend parsing; preserve caller -parser causes without scanning their object graphs. - -**Checks:** real adapter behavior for `config show --scope app`, rejection of -`config --scope app show`, nested runnable parents, interspersed operands, `--`, -unknown flags, boolean spellings, last-wins/repetition, help with missing required -inputs, and fresh consecutive parses. Confirm the root does not import Cobra/pflag. - -**Completion evidence:** internal adapter and root-to-adapter integration tests -cover command routing, local flags, interspersed operands, `--`, boolean presence -and explicit false, repeated raw values, help parsing, group failures, and fresh -parse state. `go test ./...` passes; the root package's direct imports include -only the internal adapter and not Cobra or pflag. - -## Stage 5: implement invocation and diagnostic delivery - -**Status:** complete. **Prerequisite:** Stage 4. - -Add `func (a *App) Execute(ctx context.Context, args []string, streams Streams) Outcome`. -It consumes argv without the executable name. Use the supplied nonnil context; -replace nil streams with `io.Discard`, so the library never silently picks process -streams. An invalid nil context returns operational failure rather than panicking -through a bundled handler. Do not create signals or terminate the process. - -1. Route/parse, handle metadata help requests, then apply execution requirements, - construct typed I, run CheckInput, and invoke Run with Invocation. A command - without Run requests group help. Stage 6 completes help/version rendering. -2. Adapt backend-owned failures into root-owned usage errors with message and - optional caller-parser cause. Do not unwrap a pflag/Cobra error into Cause. - Preserve input-check/handler/acquisition causes when those stages supply them. -3. Finalize outcomes in one root presentation path. Emit Diagnostics in their - order to Err; MessageDiagnostic writes one message with checked delivery. - Use a small checked-writer wrapper for CommandKit report/diagnostic paths that - converts a short write with nil error to `io.ErrShortWrite` and retains writer - failures. Preserve the caller's writers for custom-handler output; no general - callback-output interception is required. - An error-severity Diagnostic declares that the returned cause already has a - presentation; root does not inspect rendered text to infer this. If Cause exists - and no such diagnostic was supplied, append one cause diagnostic. - Do not repeat a caller outcome marked DeliveryComplete. Do not infer that - callbacks never print: their output remains their responsibility. -4. Usage failures append selected/root usage guidance to Err. Operational failures - do not dump usage. Help/version and standard reports use Out. Report failures - set ReportIncomplete and retain the writer cause/delivery error. -5. On diagnostic write failure, stop delivery, set DeliveryIncomplete, and retain - that error in DeliveryError; use `errors.Join` when multiple delivery failures - need preservation. Standard outcomes become operational/status 1. Explicit - application-domain kind/name/status stay supplied by the handler, with delivery - failure separately available to the application's final status mapping. -6. Keep the operation Cause when diagnostics subsequently fail. Do not substitute - cancellation with a generic wrapper that loses `context.Canceled` or deadline - identity. Standard handlers check cancellation at their operation/acquisition - boundaries and pass the context on; no universal goroutine cancellation runner - or interruption guarantee for arbitrary callbacks is introduced. -7. Repeated Execute calls construct all parsed state anew. Do not add execution - locking or claim concurrent dispatch from this property. - -**Checks:** public external-package invocations using real adapter; custom domain -status 2 remains domain rather than usage; context/writer causes remain inspectable; -warning-only success; diagnostic failure after operation failure retains both; -report failure marks incomplete delivery; no duplicate root diagnostics; no process -exit. Include a consecutive run that omits previously supplied flags/operands. - -**Completion evidence:** external-package tests exercise real parsing and dispatch, -typed state freshness, usage and input-check causes, domain outcomes, warning-only -success, completed diagnostic suppression, checked short writes, and combined -operation/delivery failures. `go test ./...` passes. Report-writing implementations -will set `ReportIncomplete` when introduced with the standard reports. - -## Stage 6: complete help and version - -**Status:** complete. **Prerequisite:** Stage 5. - -1. Complete automatically installed `help` and `version`. Root bare invocation, - `help [COMMAND…]`, root/selected `--help`/`-h`, and non-runnable groups render - metadata help. Resolve `help` operands as an exact registered path. Required - execution input is not needed. Unknown path/flag is usage failure. -2. Generate descriptions, usage, child inventory, flags/defaults/counts, and later - selector applicability from the single registry declaration. Sort sibling - command names for readable stable discovery. Keep alignment/wrapping details - out of compatibility promises. Use backend usage metadata inside the adapter, - render into a buffer using the returned-error Usage method, then write through - a checked root report path. Avoid UsageString/CheckErr convenience paths that - can invoke backend fatal handling; translate a rendering failure into neutral - failure data. A broken Out yields delivery failure rather than backend printing. -3. `version` accepts only `--scope app|commandkit` (default app) and - `--format text|yaml` (default text), plus help. It has no operands. - Empty application Version renders `dev`; empty Revision remains empty. Text is - `NAME VERSION\n`, adding ` (REVISION)` before the newline when provided. -4. Resolve embedded CommandKit metadata from `runtime/debug.ReadBuildInfo`: - inspect Main when the module itself is the main module, otherwise the matching - dependency; use Replace when present to determine the effective version. - Component Identity.Name is `CommandKit`; do not turn a replacement filesystem - path into its display name. A missing/versionless/local replacement is `dev`, - not the replaced tag. - A dependency tag does not supply a revision; leave that field empty rather - than borrowing the executable's VCS revision. Caller application identity stays - caller-supplied. Keep build-info projection as a small private pure helper for - controlled checks. Do not introduce a separate integer version or inventory. -5. Version YAML is `{name, version, revision}` with explicit keys. Configure the - common encoder for checked writes and later report DTOs. Unknown scope/format - is usage failure before any provider call. - -**Checks:** constructor/help/version invoke no NewInput or acquisition; invalid -config cannot disable these paths; group/runnable-parent help matches registration; -help stream failure is operational; default version contains only app identity; -controlled build info covers tagged/development/replacement component selection. -Create/update the substantive help/version portion of `docs/cli.md` now. - -**Completion evidence:** external tests cover root, group, runnable-parent, and -exact-path help; help without required inputs; version text/YAML and invalid -selectors; and checked report-write failures. Pure build-info tests cover main, -dependency, tagged replacement, local replacement, development, and missing -module cases. `go test ./...` passes; README and CLI reference describe the -implemented boundary. - -## Stage 7: implement configuration suites, scopes, and selector preflight - -**Status:** complete. **Prerequisite:** Stage 6. - -Add the following root contracts in `config.go`/`selectors.go`: - -```go -type Selection struct { - Config Supplied[string] - Overlay Supplied[string] -} -type ConfigOperation string -// Constants: ConfigValidate="validate", ConfigShow="show", -// ConfigSources="sources", ConfigExplain="explain". -type ConfigRequest struct { Operation ConfigOperation; Selection Selection } -type EffectiveWriter interface { WriteEffective(io.Writer) error } -type SourceReader interface { Sources() []configkit.SourceInfo } -type ExplanationReader interface { - Explain(configkit.Path) (configkit.Explanation, bool) - WriteExplanation(io.Writer, configkit.Path) error -} -type ConfigView struct { - Effective EffectiveWriter - Sources SourceReader - Explanation ExplanationReader -} -type Acquired[T any] struct { Value T; Diagnostics []Diagnostic } -type ConfigScope[C any] struct { - Name, Summary string - Operations []ConfigOperation - Acquire func(context.Context, ConfigRequest, C) (Acquired[ConfigView], error) -} -type Selector[C any] struct { Binding Flag[C]; Scopes []string } -type ConfigSuite[C any] struct { - NewContext func() C - Selectors []Selector[C] - CheckInput func(Selection, C) error - Scopes []ConfigScope[C] -} -func RegisterConfig[C any](app *App, suite ConfigSuite[C]) error -``` - -1. A successful Acquire attests required load/owning validation for the requested - operation. Validation needs no ConfigView interface. Other operations require - only their relevant nonnil view facet; missing advertised facets are operational - provider failures after acquisition. Optional facets avoid dummy implementations. - Acquired.Diagnostics is meaningful on both success and error. -2. Registration checks unique nonempty scope IDs, reserves `all` as the aggregate - selection, requires Acquire when operations are declared, and validates known - operation metadata. A metadata-only scope can omit Acquire. Preserve - exact IDs without trimming/case folding or adding a new lexical naming policy. - Deduplicate repeated capability declarations. No comparison type is installed. -3. Install `config scopes` immediately. Assemble other handlers as their Stage 8–11 - implementations land, from the union of declared capabilities. Keep declared - capabilities distinct from installed operations during these intermediate stages; - discovery/help list their intersection, so they never claim a later handler exists. - Final help and discovery expose exactly the enabled operations. A second config - suite install is a registration collision; compose scopes into one declaration - beforehand. -4. Use a private standard input type containing Selection, scope, format, path - presence, and C. `--config`/`--overlay` are singleton presence-aware strings on - acquisition-bearing commands. `--scope` defaults app; `--format` uses each - command's selected default. Scopes discovery accepts format/help only. -5. Each Selector.Binding is explicit typed flag metadata/setters for C. Empty - Scopes means all scopes in that suite; otherwise validate referenced scope IDs. - Reject collisions with standard local flags. Explain applicability in help. - An explicitly supplied selector applicable to none of the selected scopes is - usage failure. Aggregate selection routes it only to declared applicable scopes. -6. Parse selector values once. Preflight format, scope existence, operation coverage, - supplied applicability, pointer syntax when relevant, and declared input checks - before acquisition. For CheckInput, supply a zero-based typed context with all - parsed selectors; do not invoke NewContext for usage failures or help. -7. After preflight, call NewContext once (or use zero C). For each selected scope, - copy that base context and apply its applicable typed binding values/defaults; - use absent zero values for inapplicable bound fields. Unbound cache/runtime - fields from the base are retained. This supports an invocation-local cache - supplied by the consumer without a CommandKit cache/dependency graph. - Typed binding setters should assign their target fields; CommandKit does not - inspect arbitrary context objects or closure effects. -8. `all` is legal only for validate/show and covers every registered scope. Check - all capabilities before calling NewContext/Acquire. Other operations select - one scope. Default app remains app even when absent, yielding useful usage - choices. Order app, promptkit, then other IDs alphabetically. -9. `config scopes --format yaml` uses `{scopes: [{name, operations}]}`; operation - order is validate, show, sources, explain, filtered per scope. Text lists one - scope per line with its supported operations. An empty scope collection gives - an empty inventory; it does not invent app support. - -**Checks:** metadata-only discovery, partial scope metadata, order/defaults, -unsupported all before callbacks, explicit/omitted selector applicability, -typed empty/false/zero context selectors, and factories uninvoked on help/usage. -Use a small custom scope fixture; owning library helpers arrive next. - -**Completion evidence:** added typed configuration suite, scope, selector, view, -and request contracts; validates scope IDs, capability metadata, selector -bindings, and family collisions. `config scopes` reports installed capability -intersections in stable text/YAML inventories without creating a runtime context -or acquiring configuration. Added selector preflight and per-scope context -projection for later operation handlers, including explicit empty/false/zero -values and clearing inapplicable bound fields. `go test ./...` passes; the CLI -reference describes scope discovery. Configuration operation handlers remain -sequenced in Stages 8-11. - -## Stage 8: integrate ConfigKit and implement validation - -**Status:** complete. **Prerequisite:** Stage 7. - -```go -func NewConfigKitScope[C, T any](name, summary string, - load func(context.Context, Selection, C) (*configkit.Result[T], error), -) (ConfigScope[C], error) -func ConfigKitDiagnostics(scope string, sources []configkit.SourceInfo, - records []configkit.Diagnostic) []Diagnostic -``` - -1. The scope factory requires a nonnil loader, declares the four initial ConfigKit - operations, and wraps the public result as the relevant view facets. Load once - for the selected operation. The callback owns Definition, imports, source/ - filesystem/discovery construction, Overlay mapping, overrides, domain resolution, - and validation. Preserve supplied Config/Overlay absence and empty values. -2. Capture result Diagnostics/Sources on success. On load error, use `errors.As` - for public `*configkit.LoadError` to capture diagnostics/sources and retain the - original error. Do not import engine packages or reconstruct withheld causes. - A nil successful result is an operational provider failure. -3. ConfigKitDiagnostics returns a grouped Diagnostic whose severity is error when - any owning record is error, otherwise warning. Its writer emits a scope header - and source-ID legend using quoted labels/paths, then calls public - `configkit.WriteDiagnostics` once for the supplied records. Retain canonical - record order and check every legend/write result. Empty records need no group. - Stage 5 suppresses an extra generic cause message when this error group already - presents the failure. Do not deduplicate unrelated equal-looking diagnostics. -4. Implement validate after preflight. Acquire scopes in selected order, record - their diagnostics, and emit a success record immediately after each succeeds. - Stop on the first operational or writer failure. Do not acquire later scopes - after that failure. NewContext/cache reuse follows Stage 7; no second validation - engine is introduced. -5. Text success record: `SCOPE: valid\n`. YAML is one `scopes` block sequence of - `{name, valid: true}` records, appended as each completes. Emit the initial - `scopes:` header only with the first successful record; no fake false record or - success summary on first-scope failure. A later failure may leave a valid YAML - successful-prefix report; the returned outcome is incomplete. This differs - intentionally from show's all-before-output acquisition rule. - -**Checks:** real ConfigKit defaults/overlay/recorded resolution; absent versus -empty overlay callback input; warnings permit validation success; structured load -errors retain public identity and render once; all validates in order and stops -on failure. Report/diagnostic short writes retain their writer errors. - -**Completion evidence:** added the ConfigKit scope adapter and grouped diagnostic -writer. The adapter exposes native effective/source/explanation facets, captures -success and `LoadError` diagnostics, and preserves loader errors. `config validate` -now installs for declared scopes, preflights all requested capabilities, acquires -in stable order, and emits success records incrementally in text or YAML. Checks -cover ConfigKit defaults, overlay, recorded resolution, absent/empty selections, -warning success, load-error identity and single presentation, aggregate stop -behavior, and report/diagnostic short writes. `go test ./...` passes; README, -development orientation, and CLI reference describe the implemented boundary. - -## Stage 9: implement native effective YAML display - -**Status:** complete. **Prerequisite:** Stage 8. - -1. Implement `config show`; its only initial format is yaml (default and explicit). - Single scope writes Effective.WriteEffective directly to Out with no envelope, - scope header, re-marshalling, or parsing of runtime Result.Config. -2. For all, preflight availability, acquire every selected view, and finish required - provider validation/facet checks before any Out bytes. If a later acquisition - fails, return its diagnostic outcome with an empty report stream. -3. After acquisition, render each native document into an ordinary bytes buffer - and compose it in order. This is framing, not a configuration projection. If - the native document already has an opening `---`, retain it and insert the - `# scope: NAME` label after it. Preserve any leading comments/directives. If it - lacks a marker, write `---`, the label, then the native bytes. Add a terminating - newline only where necessary to separate documents. Keep labels on one comment - line (quote IDs containing line controls); do not alter native payload ordering - or scalar/null/container semantics. No native-document size cap is introduced. -4. A rendering failure can leave earlier aggregate documents; preparation guaranteed - acquisition completeness, not atomic delivery. Out failures mark incomplete - report delivery and retain causes. Do not retry a broken output stream or write - a success footer. Diagnostics remain independently directed to Err. - -**Checks:** compare single-scope bytes to public native writer output; decode -aggregate YAML with the pinned YAML dependency and verify document count/order, -labels and native values. Cover an already marked native document, missing/null/ -empty structures, a second acquisition failure with no prefix, and a writer failure -after output begins. These protect selected behavior, not encoder whitespace. - -**Completion evidence:** installed `config show` when a scope declares it, with -YAML as its only format. Single-scope output passes through the native effective -writer; aggregate output acquires and checks every view before emitting framed -native documents in scope order. Existing markers, leading comments and YAML -directives are retained, including explicit document termination where needed -between directive-bearing documents. Checks cover native single-scope bytes, -aggregate document decoding and values, invalid formats, acquisition failure with -empty output, and incomplete delivery after a writer failure. `go test ./...` -passes; README, development orientation, and CLI reference describe the feature. - -## Stage 10: implement source inventory reports - -**Status:** complete. **Prerequisite:** Stage 9. - -1. Implement single-scope `config sources`, default text with yaml alternative. - Read the captured SourceReader once. Never reload sources for this report. -2. Use private explicit DTOs and snake-case YAML fields. Root shape is - `{scope, sources}`. Each source has `id`, `label`, `path`, `layer`, `kind`, - `underlay_index`, `imported_from`. A location is `{source_id, line, column}`; - imported_from is null when absent. Retain owning scalar zero/empty values and - source record order. An empty source collection is `[]`. -3. Text emits a scope heading, then one labeled source record with the same fields - and optional import location. Quote free-form labels/paths for readability. - Do not promise column alignment or invent source IDs/file paths for synthetic - inputs. Use the common checked writer/encoder path. - -**Checks:** real ConfigKit root/import/overlay/synthetic records, source order, -one captured acquisition, YAML field types and import correlation, empty inventory, -unsupported all usage preflight, writer failure. Update the source-report CLI -reference with the implemented shape. - -**Completion evidence:** installed `config sources` for scopes declaring the -capability. The command reads the acquired source facet once and renders explicit -snake-case YAML DTOs or a quoted text inventory, preserving source order, empty -and zero values, synthetic paths, and import locations. Checks use a real -ConfigKit filesystem root, import, overlay, and mapping underlay; they verify the -YAML field types and import correlation, captured acquisition, empty inventory, -text quoting, unsupported aggregate preflight, and partial writer failure. -`go test ./...` passes; README, development orientation, and CLI reference -describe the report. - -## Stage 11: implement path explanation reports - -**Status:** complete. **Prerequisite:** Stage 10. - -1. Implement single-scope `config explain --path POINTER`. Presence is required; - explicitly empty is the root. Parse with public `configkit.ParsePath` before - acquisition. Invalid pointer is usage/status 2; a well-formed unknown current/ - historical path is operational/status 1. Check Explain's bool before calling - WriteExplanation; empty native output is not successful lookup evidence. -2. Text uses native WriteExplanation. YAML uses private DTOs with root fields - `scope`, `path`, `effective`, `origin`, `history`, `secret_reference`. - Keep value fragments as strings; do not parse them into a different value tree. -3. Define nested DTOs precisely from the reviewed public API: - - Snapshot: `{present, redacted, yaml}`; preserve false, empty, and null-fragment - distinctions rather than omitting fields. - - Origin: `{layer, locations, operation, inheritance}`. Locations use Stage 10's - DTO. Inheritance records contain `{from, to, reference, locations}` with paths - serialized through Path.String(). Empty locations/inheritance are `[]`. - - History entry: `{before, after, origin, reasons, dependencies}`. Reasons and - canonical pointer dependencies retain owning order; empty collections are `[]`. - - Secret reference: null when absent, otherwise `{name}` containing the owner's - environment-variable name, never its resolved value. -4. Preserve all public inheritance/provenance data; do not blindly marshal Path's - private representation. Keep owning redaction on effective and historical values. - -**Checks:** real known effective, historical deletion, root, escaped pointer, and -inherited values; malformed versus unknown outcomes; redacted before/after and -reference-name preservation; YAML snapshot strings and inheritance pointers; -native text equivalence; writer failure. Update explanation CLI documentation. - -**Completion evidence:** installed single-scope `config explain` with required -JSON Pointer `--path`, text as the native writer output, and explicit YAML DTOs -for snapshots, origins, history, inheritance, and secret references. Malformed -pointers return usage before context creation or acquisition; unknown paths are -operational failures checked before native writing. Checks cover root and escaped -paths, inherited and historical values, ordered resolution dependencies, secret -redaction and name-only references, exact native text, missing/invalid/unknown -paths, and writer failure. `go test ./...` passes; README, development orientation, -and CLI reference describe the feature. - -## Stage 12: integrate the PromptKit configuration scope - -**Status:** complete. **Prerequisite:** Stage 11. - -```go -func NewPromptKitScope[C any]( - load func(context.Context, Selection, C) (*promptkit.Engine, error), -) (ConfigScope[C], error) -``` - -1. Return scope name `promptkit` and its four available operations. Require a - nonnil callback; invoke it only for a selected operation. Application code - supplies engine sources/options and may derive them from its app view/context. -2. Use Engine.InspectConfiguration to obtain public ConfigurationInspection once. - Expose it through EffectiveWriter, SourceReader, and ExplanationReader; successful - engine acquisition/inspection supplies validation. Capture public source/ - diagnostic records with the Stage 8 helper. A nil returned engine is operational - failure; preserve public ErrInvalidConfig and ConfigKit LoadError identities - where supplied through the error chain. -3. Reuse configuration handlers/report DTOs exactly; no duplicate PromptKit config - YAML renderer or shadow schema. Register this scope independently of definition - commands. No prompt/model execution, credential lookup, or model availability - probe is added by bundled inspection handlers. - -**Checks:** real public NewEngine with synthetic local/in-memory sources; native -YAML/source/explanation equivalence, invalid engine config and warning delivery, -all display with app first/promptkit second, configuration-only installation, -caller context/selection propagation, and metadata discovery without engine load. -Fixtures do not depend on provider services or sibling repository runtime files. - -**Completion evidence:** `promptkit_scope_test.go` exercises a real in-memory -PromptKit engine, native reports, aggregate order, lazy discovery, and preserved -PromptKit/ConfigKit error identities. `go test ./...` passes. - -## Stage 13: implement named prompt/profile inspection - -**Status:** complete. **Prerequisite:** Stage 12. - -```go -type PromptKitSuite[C any] struct { - NewContext func() C - Selectors []Selector[C] - CheckInput func(Selection, C) error - InspectPrompt func(context.Context, Selection, C, string, string) (Acquired[*promptkit.PromptInspection], error) - InspectProfile func(context.Context, Selection, C, string) (Acquired[*promptkit.ProfileInspection], error) -} -func NewPromptKitSuite[C any]( - load func(context.Context, Selection, C) (*promptkit.Engine, error), -) (PromptKitSuite[C], error) -func RegisterPromptKit[C any](app *App, suite PromptKitSuite[C]) error -``` - -1. Suite factories require a nonnil engine loader and supply both named callbacks. - Call it once for the selected command, capture engine configuration diagnostics, - then use public InspectPrompt or InspectProfile with the caller context. Carry - successful acquisition warnings even if the named lookup fails. Retain error - identities from both acquisition and inspection without invoking execution APIs. -2. Direct suite declarations can supply either callback. Install only corresponding - `promptkit show prompt`/`profile` children. The entire installed promptkit family - stays owned. A suite with neither callback installs no definition commands or - namespace and returns success; it does not require caller feature-toggle - bookkeeping. Configuration scope installation remains independent. -3. Accept ID as one required operand. Prompt alone has singleton `--version` - (default empty). Both accept standard Config/Overlay selection, context-selector - bindings, and `--format text|yaml` (text default), plus help. No built-in - configuration-scope selector is installed for definition commands; a custom - context selector can use the name `scope` when it does not collide with an - installed flag. Selector target is `promptkit`; empty Scopes or a list containing - promptkit applies, independent of a config scope registry. - Other explicit targets are miswired metadata at registration. -4. Reuse Stage 7's input/context creation and input-check rules. Missing ID is - usage; a supplied blank/unknown/ambiguous selection reaching the owning API is - an operational inspection result, not a new CommandKit ID grammar. Pass version - omission as empty and leave owning selection rules in PromptKit. -5. Prompt YAML keys: `prompt_id`, `prompt_version`, `prompt_hash`, - `default_profile_id`, `inputs`, `output_contract`. Inputs retain declared order - with `{name, required, content_type, description}`; empty input list is `[]`. - Output contract contains `{format, validation_mode, schema_path, repair_attempts}`. - The hash is opaque; do not validate its format or length. -6. Profile YAML keys: `profile_id`, `effective_model_params`, `api_key_required`. - Effective target keys are `backend_id`, `endpoint`, `model`, `temperature`, - `max_tokens`, `top_p`, `timeout_seconds`, `service_tier`, `reasoning_effort`, - `api_key_env`, `extra_params`. Preserve owning zero values; do not infer provider - defaults from zero. Include ExtraParams without redaction, filtering, or - omission: it contains provider settings and needs no upstream enhancement for - this feature. Preserve nested maps/sequences/scalars, including null values. - A nil ExtraParams map is represented as an empty mapping for this report. -7. Text presents the same named fields with labeled sections. Use the shared YAML - encoder for nested provider parameters within that presentation rather than - inventing JSON output or flattening values. Quote free-form scalar labels where - needed. Text presentation is readable; YAML provides the defined machine shape. - -**Checks:** real captured definitions and backend/profile inheritance, exact and -omitted prompt version, opaque hash/order, unknown IDs, ambiguity/cancellation -causes, credential-reference/requirement fields, nested ExtraParams in both -formats, nil/empty parameters, independently installed prompt/profile capability, -definition-only registration, and help without engine construction. Assert no -handler enters generation rather than exercising paid/network execution paths. - -**Completion evidence:** `promptkit_test.go` exercises real captured prompt and -profile definitions, both report formats, inheritance and provider parameters, -selection errors, optional capabilities, and help without engine construction. -`go test ./...` passes. - -## Stage 14: substantiate consumer fit and complete documentation - -**Status:** complete. **Prerequisite:** Stage 13. - -1. Add complete maintained examples using only the public root API and published - upstream packages. Use two ordinary example directories (separate Go main - packages are demonstration consumers, not additional public library packages): - - `examples/simple`: synthetic typed app configuration, one ConfigKit loader - and scope helper, plus a typed custom command with presence/repetition. - - `examples/composed`: app/PromptKit scopes, definition suite, typed campaign - selection, and custom `session restore`. ConfigSuite.NewContext constructs - an invocation-local cache in an unbound field; applicable typed selectors - populate scope contexts sharing that cache. The callback composes app → engine - loading. Definition suite constructs its own invocation-local context. -2. Factor example domain loading into ordinary consumer functions reused by its - execution/inspection demonstration. This is a recommended consumer pattern, - not a new policy governing every application. Keep schemas, campaign/session - meaning, side effects, domain output/status mapping, and executable main with - the example consumer. Use minimal synthetic content, no production workspaces. -3. Verify the examples remove manual standard parsers/dispatchers/report code. - Root generic factories must remain practical for a normal input struct and - composable group. Share internal standard-input helpers across suites rather - than requiring the consumer to rebuild them. Do not solve callback boilerplate - by adding a runtime/DI framework or another public package. -4. Complete substantive GoDoc, `docs/cli.md`, consumer guidance and the two examples, - and `docs/internal/overview.md`. CLI docs own standard syntax/report/status - contracts; GoDoc owns exact symbols/lifecycle; consumer docs own walkthroughs. - Link owning-library schemas; do not copy their configuration references. -5. Update README/development to actual implemented behavior and commands. Check - attribution against incorporated dependencies/material. Do not create empty - integration docs or release tooling. Leave the selected deferred targets visible - in the feature roadmap. Mark implementation status against the included IDs. -6. Audit the complete target: supported operation metadata, independent capability - subsets, default/app/all/order behavior, typed grammar and repeated invocations, - native preservation, all-before-output acquisition, reports/diagnostics/errors, - both public consumer examples, and root/adapter dependency/type boundaries. - Inspect actual exported declarations and imports; avoid a broad architecture - scanner as a substitute for this focused boundary review. -7. Finish with formatted source, the complete offline suite, link/document checks, - and an ordinary diff review. Confirm no sibling replacement/internal import, - deferred-feature placeholder, new public package, or app-domain policy slipped - into the implementation. Record completed stage status and checks, then commit - the completed unit under the local policy. Publishing remains separate work. - -**Completion evidence:** added maintained `examples/simple` and -`examples/composed` consumers, public consumer guidance, internal architecture -overview, and updated CLI/development/README/feature-roadmap documentation. The -examples compile and use the public dispatcher with synthetic data. Shared -selector helpers serve both configuration suites. Reviewed exported declarations, -root and adapter imports, dependency replacements, attribution, and retained -deferred feature IDs. Verified with `gofmt`, `go test ./...`, `go mod tidy -diff`, -document link checks, example smoke commands, and `git diff --check`. Publishing, -downstream migrations, and deferred capabilities remain outside this stage. +Record the passed publication and preflight observations. This exercise uses +no real remote, credentials, provider, binary target, or hosted page. Retain the +opt-in test for future tooling changes, without placing it in `releasekit.json`. + +**Completion:** the actual module-selected executable and copied integration +publish a source tag locally and respect the configured endpoint guard. Commit +the stage. + +## Stage 5: document operation and reconcile release navigation + +**Status:** pending. **Prerequisite:** Stage 4. + +**Files:** new `docs/release.md`; `docs/policy/release.md`, README, +`docs/development.md`; historical roadmap references listed below; and stage +evidence in this plan. Apply documentation and OSS policy without changing +accepted ADR decisions or policy provenance. + +1. Author `docs/release.md` as the canonical, concise maintainer runbook. Name + `main`, `origin`, the expected effective push endpoint, a local compatible + Go toolchain (at least the module's 1.25.5 requirement), Git with push access, + and a POSIX shell. Describe source tag plus committed note as the selected + deliverables, with no hosted page, binary matrix, or delivery credentials. +2. Give copyable preparation commands with a task-specific version variable. + Explain stable SemVer selection and pre-1.0 compatibility policy. Prepare + `docs/releases/.md` with its product/version heading, useful summary, + compatibility/upgrade information, and exact immutable-tag footer URLs: + + ```text + https://gitea.maximumdirect.net/eric/CommandKit/src/tag/VERSION/COPYRIGHT + https://gitea.maximumdirect.net/eric/CommandKit/src/tag/VERSION/LICENSE + https://gitea.maximumdirect.net/eric/CommandKit/src/tag/VERSION/docs/oss/attribution.md + ``` + + The visible footer labels are `COPYRIGHT | LICENSE | ATTRIBUTION`. Preparation + review checks intended paths in the candidate; it does not require future + tag URLs to resolve or run a separate note checker. +3. Document cache preparation with `GOWORK=off GOTOOLCHAIN=local go mod download`. + If preparation changes module metadata, review and commit it as part of the + candidate before publication. Commit the final candidate on `main`, push + with `git push origin HEAD:refs/heads/main`, then invoke + `./scripts/release "$commandkit_version"`. State that the command bootstraps + the tool, runs the offline candidate suite once after preflight, and publishes + only the annotated tag. Do not prescribe a required `check` followed by + `publish`; earlier development checks do not replace publication validation. +4. Describe completion at successful intended-tag push or an exact-object + reconciliation confirming acceptance. Link to upstream for its CLI/status + contract. Provide a short operational summary of statuses 0 (confirmed), 1 + (known failure/conflict), 2 (input/profile), and 3 (unresolved push), keeping + this operational summary out of CommandKit's application CLI reference. +5. Include concrete recovery instructions using the endpoint, version, and tag + object reported by the failed invocation. Show the upstream pattern that + verifies `git ls-remote --get-url -- "$releasekit_endpoint"` still equals the + captured endpoint before querying its exact `refs/tags/...` ref. A failed + query or changed URL resolution leaves the result unresolved. Compare the + exact annotated tag object, not just its peeled commit. Exact match confirms + publication; a different object is conflict; proven absence permits deliberate + cleanup of an unpublished local tag only after confirming it has never been + published or used by another release channel. Explain that retained local + tags block an ordinary retry. Never move or overwrite a published tag or + treat an unreadable query as absence. Published source corrections require + a new version; transport failures alone do not. +6. Replace only stale integration-status prose in the release policy with the + implemented ReleaseKit selection and a runbook link. Retain source-only + scope, substantive rules, adopted base version, and upstream provenance; + update the local last-updated date for the edit. +7. Add runbook navigation in README and the developer guide. Add a current + release-tooling reading row and the optional Stage 4 exercise command/cache + prerequisite to developer guidance. Replace the obsolete statement that + release tooling still awaits introduction. Keep commands owned by the + runbook and use links from non-owning documents. +8. Repair links to the replaced completed implementation record. For historical + initial-library references, use the immutable snapshot linked in this plan's + introduction. Inspect and update README, `docs/development.md`, + `docs/roadmap/01-cli-plan.md`, `02-dispatch.md`, `03-backend.md`, `04-facade.md`, + `initial-plan.md`, `initial.md`, and `remediation.md`. Preserve their completed + status and historical statements. Link current ReleaseKit work separately to + `releasekit.md` and this plan. Do not copy the old plan into another maintained + implementation specification or add temporary-plan links to ADRs. + +**Evidence:** review the runbook against the implemented launcher/profile and +the selected upstream source. Check local destinations/fragments, preserved +licensing footer navigation, intended release URL paths, changed historical +references, provenance, and Markdown whitespace. No publisher invocation on +CommandKit or another full test suite is needed for these prose edits. + +**Completion:** implemented tooling has one canonical runbook, policy status is +accurate, and old library history is distinguishable from current ReleaseKit +work. Commit the stage. + +## Stage 6: audit and record adoption completion + +**Status:** pending. **Prerequisite:** Stages 1–5. + +**Files:** this plan and `releasekit.md` for completion evidence; focused fixes +only if the audit discovers a real incomplete deliverable. + +1. Audit every RK-01–06 result against current state: module/tool selection, + minimal profile, launcher and executable mode, ignored output, dependency + metadata preservation, licensing treatment, implemented runbook/navigation, + fast tests, and recorded local publication evidence. Read actual files and + results rather than infer completion from checked boxes. +2. Confirm production imports and exported declarations have not acquired + ReleaseKit APIs. The production package boundary remains root `commandkit` + and `internal/cobra`; `scripts` is tests-only. Use package/dependency + inspection or existing boundary evidence, not a new general API checker. +3. Run the default offline suite once for the completed implementation using + the Stage 1 environment. Stage 4 stays opt-in. Reuse its successful result + if its launcher, profile, tool selection, and test inputs remain unchanged; + otherwise rerun that local exercise for the changed integration. Review + affected prose, links, module diffs, and whitespace. +4. Mark stage and feature completion only when their evidence is present. Record + exact commands/outcomes and any platform skips. Keep historical baseline + descriptions historical; update the roadmap's current status and link its + completion evidence here. No real release note or tag is required to close + adoption, and no deferred capability is promoted by this audit. +5. Commit the completed audit and status updates, report all stage commits and + checks, and leave a clean workspace. The handoff is tooling ready for separately + authorized preparation of the first real release. + +**Evidence:** record the final default-suite result, the applicable Stage 4 +result, the reviewed deliverable and boundary checks, and the final clean Git +status. Correct any missing result before declaring adoption complete. + +**Completion:** all six stages and all roadmap coverage IDs have authoritative +implementation evidence. Source publication itself remains unperformed. diff --git a/docs/roadmap/releasekit.md b/docs/roadmap/releasekit.md index cef9ef5..66c1471 100644 --- a/docs/roadmap/releasekit.md +++ b/docs/roadmap/releasekit.md @@ -7,9 +7,10 @@ Date: 2026-10-08. ## Purpose and authority This roadmap defines the target state for adopting ReleaseKit as CommandKit's -maintainer release tooling and the work needed to reach it. The next planning -deliverable is a staged implementation plan based on this target. This document -does not authorize publication or claim that release tooling already exists. +maintainer release tooling and the gaps from its reviewed baseline. The +[implementation plan](implementation.md) owns ordered execution steps, +stage-specific checks, and implementation evidence. This document does not +authorize publication or claim that release tooling already exists. The [release policy](../policy/release.md), [architecture policy](../policy/architecture.md), and @@ -66,19 +67,19 @@ responsibilities continue to follow their accepted contracts. ReleaseKit's ### Tool selection and launcher -Declare `gitea.maximumdirect.net/eric/ReleaseKit/cmd/releasekit` as a Go tool -dependency in CommandKit's root `go.mod`, initially selecting ReleaseKit -v0.2.0. Commit the resulting module metadata and checksums. The Go -[tool directive](https://go.dev/doc/modules/gomod-ref#tool) retains executable +CommandKit's root `go.mod` declares +`gitea.maximumdirect.net/eric/ReleaseKit/cmd/releasekit` as a Go tool dependency, +initially selecting ReleaseKit v0.2.0, with committed metadata and checksums. The +Go [tool directive](https://go.dev/doc/modules/gomod-ref#tool) retains executable tool dependencies without importing them into the library. -Provide a small executable `scripts/release` launcher whose publication entry -point is `./scripts/release VERSION`. It builds the ReleaseKit CLI selected by +The small executable `scripts/release` launcher has publication entry point +`./scripts/release VERSION`. It builds the native ReleaseKit CLI selected by the candidate's module configuration, then executes its `publish` command for -CommandKit's repository and profile. Build the tool with committed module -metadata in readonly mode, with workspace discovery disabled and the compatible -local toolchain selected. Use an ignored `.releasekit/` directory for the local -tool binary so bootstrap output does not make the candidate dirty. +CommandKit's repository and profile. Bootstrap uses committed module metadata +in readonly mode, disabled workspace discovery, and a compatible local toolchain. +Its local tool binary lives in ignored `.releasekit/` storage so bootstrap output +does not make the candidate dirty. The launcher owns argument handling, repository location, tool bootstrap, and invocation. It preserves the executable's output, exit status, and signal @@ -94,15 +95,15 @@ it does not make their module requirements disappear. ### Source-only profile -Add a root `releasekit.json` selecting: +The root `releasekit.json` selects: - product `CommandKit`; - authoritative remote `origin`; and - expected effective push URL `https://gitea.maximumdirect.net/eric/CommandKit.git`. -Use the default candidate suite. Initially leave additional checks, optional -validation selections, binary builds, and hosted delivery unselected. In +The profile uses the default candidate suite. Additional checks, optional +validation selections, binary builds, and hosted delivery are unselected. In particular, the adoption does not establish race, full-vet, cross-platform, formatting, Markdown, module-distribution, or file-size gates. @@ -113,17 +114,12 @@ owned by the upstream ### Publication workflow -The runbook selects ReleaseKit's supported sequence: - -1. Prepare and commit the candidate and matching release note on `main`. -2. Prepare the module dependencies and tool dependencies needed by the local - compatible toolchain, separately from offline candidate validation. -3. Push the candidate commit to authoritative remote `main` using explicit refs. -4. Invoke the single publication launcher for the selected version. - -ReleaseKit requires remote `main` to identify the candidate before publication; -this adoption uses the branch-first approach permitted by CommandKit policy. -An atomic branch-and-tag publication path is not part of this target. +The supported workflow uses a clean committed candidate and matching release +note on `main`. Dependency preparation is separate from offline validation. +Authoritative remote `main` identifies the candidate before the single launcher +publishes its tag. This is the branch-first approach permitted by CommandKit +policy; an atomic branch-and-tag publication path is not part of this target. +Copyable operational steps belong in the implemented runbook. After publication preflight, ReleaseKit runs one `go test -mod=readonly -count=1 ./...` suite with module and toolchain downloads @@ -143,8 +139,8 @@ state. Never force an update to bypass a guard. ### Documentation and release notes -Create `docs/release.md` when the launcher and profile exist. It owns the -copyable preparation/publication commands, prerequisites, automated guards, +The target `docs/release.md` owns copyable preparation/publication commands, +prerequisites, automated guards, completion point, and recovery instructions. Link to ReleaseKit's owning references for detailed CLI statuses and profile definitions rather than maintaining a second upstream reference in CommandKit's CLI documentation. @@ -156,44 +152,42 @@ release note must include the immutable-tag `COPYRIGHT | LICENSE | ATTRIBUTION` links required by the OSS policy. This introduces no additional network check, manual approval gate, or custom note checker. -Update the release policy's undecided-adoption statement when integration lands, -preserving its substantive rules and provenance. Update README and developer -navigation to point to the implemented runbook and remove their obsolete -release-tooling status statements. Current procedures belong in the runbook; -this roadmap and the forthcoming staged plan retain target/status information. +The implemented release policy identifies the selected integration while +preserving substantive rules and provenance. README and developer navigation +point to the implemented runbook and describe release-tooling status accurately. +Current procedures belong in the runbook; this roadmap owns the target, and the +implementation plan owns execution and evidence. ### Licensing and incorporated material -Review the selected ReleaseKit source, dependency notices, and any copied -launcher or integration material under the OSS policy. Update applicable -attribution entries and license texts together with incorporation, identifying -selected upstream revisions and preserving required notices. +Licensing treatment follows the actual selected source, dependency notices, +and any incorporated launcher or integration material under the OSS policy. +Applicable attribution entries and license texts identify selected upstream +revisions and preserve required notices. Tool use alone does not establish an attribution requirement under that policy. Determine treatment from actual incorporation or distribution rather than add entries for every development tool. Any copied or adapted documentation needs -its own applicable treatment. Author the CommandKit runbook for this integration -and reuse upstream guidance through links where practical. +its own applicable treatment. CommandKit's runbook is written for this +integration, with links to upstream guidance where practical. -## Work needed from the baseline +## Adoption coverage -These are implementation work areas, not the staged execution instructions. -The next plan must order them, specify concrete edits and proportionate evidence, -and preserve any changes made after this baseline. +These IDs identify the target capabilities and remaining baseline gaps. +Ordered assignments and checks belong in the implementation plan. -| ID | Work | Completion result | +| ID | Capability gap | Target result | | --- | --- | --- | -| RK-01 | Add the released Go tool dependency and review module resolution. | Root module metadata selects v0.2.0 and retains the tool through normal module maintenance; no sibling replacement or library import is needed. | -| RK-02 | Add the source-only profile. | Product, authoritative remote, and effective push destination are explicit; only the default suite is selected. | -| RK-03 | Add the executable launcher and ignore its local build output. | One repository publication command builds the module-selected CLI without changing candidate metadata and preserves its outcomes. | -| RK-04 | Write the implemented release runbook and reconcile navigation/policy status. | Maintainers have one canonical procedure for preparation, publication, and recovery; current documents describe available tooling accurately. | -| RK-05 | Review licensing scope and maintain affected notices. | Incorporated material receives policy-conforming attribution and texts without blanket tooling requirements. | -| RK-06 | Establish focused integration evidence and record completion. | The launcher/profile work together and the adoption respects existing library boundaries; the roadmap records actual completion and remaining release preparation. | +| RK-01 | Released Go tool selection | Root module metadata selects v0.2.0 and retains the tool through normal module maintenance; no sibling replacement or library import is needed. | +| RK-02 | Source-only profile | Product, authoritative remote, and effective push destination are explicit; only the default suite is selected. | +| RK-03 | Publication launcher | One repository publication command builds the module-selected CLI without changing candidate metadata and preserves its outcomes; bootstrap output is ignored. | +| RK-04 | Runbook and navigation | Maintainers have one canonical procedure for preparation, publication, and recovery; current documents describe available tooling accurately. | +| RK-05 | Licensing treatment | Incorporated material receives policy-conforming attribution and texts without blanket tooling requirements. | +| RK-06 | Integration confidence | The launcher/profile work together and adoption respects existing library boundaries; completion evidence and remaining release preparation are recorded in the implementation plan. | -## Completion evidence and handoff +## Acceptance criteria -Select evidence for the new integration rather than duplicate ReleaseKit's entire -candidate and Git test inventory. During implementation, establish that: +Successful adoption has focused evidence for these integration results: - The repository's committed module configuration selects the tool, including after ordinary module maintenance; bootstrap leaves module files unchanged. @@ -210,10 +204,10 @@ candidate and Git test inventory. During implementation, establish that: affected documentation, notices, paths, and intended release links agree with the implemented integration. -The staged plan should identify the checks appropriate to these risks and reuse -existing evidence where sufficient. Adoption checks are not automatically -permanent release gates. Diagnostic `check` remains optional; the actual release -publisher validates its final candidate once. +The implementation plan selects proportionate checks and reuses existing +evidence where sufficient. Adoption checks are not automatically permanent +release gates. Diagnostic `check` remains optional; the actual release publisher +validates its final candidate once. Adoption is complete when RK-01 through RK-06 are implemented and reviewed, focused evidence is recorded, and the runbook is executable from the documented