diff --git a/README.md b/README.md index f65186b..dd5425c 100644 --- a/README.md +++ b/README.md @@ -43,7 +43,7 @@ ckprompt v0.2.0; the published v0.2.0 pair remains matched. See the - [Maintainer release procedure](docs/release.md) - [Architecture policy](docs/policy/architecture.md) - [Policy provenance](docs/policy/meta.md) -- [Deferred capabilities and proposals](docs/roadmap/deferred.md) +- [Future work and proposals](docs/roadmap/future.md) CommandKit is licensed under the [LGPL v3.0 or later](COPYRIGHT). diff --git a/docs/development.md b/docs/development.md index f60a3eb..8b9b82c 100644 --- a/docs/development.md +++ b/docs/development.md @@ -15,8 +15,8 @@ canonical documentation owners. For application-owned aliases, use the [CLI reference](cli.md#application-owned-aliases), [Go declarations and GoDoc](../command.go), and -[ADR 0013](adr/0013-application-alias-routing.md). Keep deferred capabilities in -[deferred work](roadmap/deferred.md). +[ADR 0013](adr/0013-application-alias-routing.md). Keep unfinished work and +capability proposals in [future work](roadmap/future.md). ## Initial orientation @@ -54,17 +54,17 @@ For application-owned aliases, use the | Task | Read | | --- | --- | | Implemented CLI behavior | [CLI reference](cli.md) | -| Invocation reporting | [CLI reporting contract](cli.md#reporting), [consumer guide](consumers/guide.md#invocation-reporting), core GoDoc, [reporting roadmap](roadmap/reporting.md), and [ADR 0014](adr/0014-invocation-reporting.md) | +| Invocation reporting | [CLI reporting contract](cli.md#reporting), [consumer guide](consumers/guide.md#invocation-reporting), core GoDoc, and [ADR 0014](adr/0014-invocation-reporting.md) | | Application-owned aliases | [CLI reference](cli.md#application-owned-aliases), [Go declarations and GoDoc](../command.go), [consumer guide](consumers/guide.md#application-owned-aliases), and [ADR 0013](adr/0013-application-alias-routing.md) | | Public API usage and standard-suite wiring | [Consumer guide](consumers/guide.md), [ckconfig package](../integrations/ckconfig/doc.go), [ckprompt package](../integrations/ckprompt/doc.go), and applicable ADRs | | Dispatcher, registration, or typed inputs | [Command declarations](../command.go), [bindings](../binding.go), [invocation](../execute.go), and [ADR 0001](adr/0001-command-dispatch-and-inputs.md), refined by [ADR 0011](adr/0011-captured-declarations-and-installation.md) | | Backend integration | [Internal overview](internal/overview.md), [adapter implementation](../internal/cobra/parse.go), and [ADR 0002](adr/0002-cobra-backend.md) | | Public facade or adapter boundaries | [Internal overview](internal/overview.md), [ADR 0003](adr/0003-public-facade.md) as scoped by [ADR 0010](adr/0010-optional-integration-modules.md), and the architecture policy | | Module ownership and public contracts | [Consumer guide](consumers/guide.md), [internal overview](internal/overview.md), [core GoDoc](../doc.go), [ckconfig GoDoc](../integrations/ckconfig/doc.go), [ckprompt GoDoc](../integrations/ckprompt/doc.go), and applicable ADRs | -| Deferred capabilities and proposals | [Deferred work](roadmap/deferred.md) | +| Unfinished work and capability proposals | [Future work](roadmap/future.md) | | Completed planning and implementation history | [Completed dependency upgrades, PromptKit validation, discovery, smoke testing, and remediation](https://gitea.maximumdirect.net/eric/CommandKit/src/commit/a6278a6d9f940948ec7745955d745523aaff0734/docs/roadmap), [earlier ConfigKit and PromptKit adoption and remediation](https://gitea.maximumdirect.net/eric/CommandKit/src/commit/8a82620dfcd34c0ae56bbecb0d014eb49786bc92/docs/roadmap), [earlier retired records](https://gitea.maximumdirect.net/eric/CommandKit/src/commit/6bc37e7ba64ca0920b4d0cc77039a18d4006b24e/docs/roadmap), and [completed module implementation and remediation](https://gitea.maximumdirect.net/eric/CommandKit/src/commit/bb2528532b78d30e52f5082e491a5e1fd9b0fb99/docs/roadmap) in Git history | | Release tooling | [Maintainer release procedure](release.md) | -| Performance maintenance | [Internal overview](internal/overview.md), existing benchmarks, and [deferred efficiency work](roadmap/deferred.md#possible-further-efficiency-work) | +| Performance maintenance | [Internal overview](internal/overview.md), existing benchmarks, and [possible further efficiency work](roadmap/future.md#possible-further-efficiency-work) | | Licensing or incorporated material | [Project grant](../COPYRIGHT), [license texts](../LICENSE), and [attribution](oss/attribution.md) | | Policy provenance | [Policy provenance](policy/meta.md) | @@ -72,11 +72,12 @@ Read all applicable rows for cross-cutting work. Go declarations and GoDoc own current exported contracts; the CLI reference owns operator behavior. The [maintainer release procedure](release.md) owns current release operations. Completed roadmaps and implementation evidence remain available in Git history, -including [application-owned alias planning, implementation, and remediation](https://gitea.maximumdirect.net/eric/CommandKit/src/commit/f42aefe02d84e154855ac922173e6f367180929f/docs/roadmap) +including [ConfigKit adoption, reporting, release-tooling, and remediation records](https://forge.maximumdirect.net/base-layer/commandkit/src/commit/260256d722f52bc947103d078cb67a129f4cc9f1/docs/roadmap), +[application-owned alias planning, implementation, and remediation](https://gitea.maximumdirect.net/eric/CommandKit/src/commit/f42aefe02d84e154855ac922173e6f367180929f/docs/roadmap) and [PromptKit requirements implementation and remediation](https://gitea.maximumdirect.net/eric/CommandKit/src/commit/40499a43608bf60d1104cd8ee24caf18ac0e9e66/docs/roadmap). These records are not assignments to restart completed work. The -[deferred-work record](roadmap/deferred.md) preserves future capability targets -and unselected proposals separately from current contracts. +[future work record](roadmap/future.md) preserves unfinished work and unselected +proposals separately from current contracts. ## Documentation validation diff --git a/docs/policy/agents.md b/docs/policy/agents.md index 0c8c776..e6c94e4 100644 --- a/docs/policy/agents.md +++ b/docs/policy/agents.md @@ -56,7 +56,7 @@ invariant, not from the convenience of the selected implementation. Explain the specific failure it prevents and why a less restrictive implementation cannot satisfy the contract. -The [deferred-work record](../roadmap/deferred.md) distinguishes future proposals +The [future work record](../roadmap/future.md) distinguishes future proposals from accepted contracts. Do not approve proposed commands, grammar, statuses, or illustrative API declarations merely by repeating them in implementation or tests. Cobra/pflag defaults do not diff --git a/docs/policy/architecture.md b/docs/policy/architecture.md index 7c87ae5..bcb981d 100644 --- a/docs/policy/architecture.md +++ b/docs/policy/architecture.md @@ -294,7 +294,7 @@ recommended for application-owned commands; their names and domain behavior remain application choices. Accepted ADRs and current CLI/API owners define selected contracts; the -[deferred-work record](../roadmap/deferred.md) preserves remaining proposals. +[future work record](../roadmap/future.md) preserves remaining proposals. Backend defaults and incidental consumer behavior do not establish new contracts. A replacement backend must preserve published CLI behavior or follow deliberate compatibility changes under the release policy. diff --git a/docs/roadmap/configkit-v1.1.0.md b/docs/roadmap/configkit-v1.1.0.md deleted file mode 100644 index 8a405f0..0000000 --- a/docs/roadmap/configkit-v1.1.0.md +++ /dev/null @@ -1,247 +0,0 @@ -# ConfigKit v1.1.0 adoption - -Status: the selected ckconfig adoption is implemented and prepared for a later -release; source publication and ckprompt migration remain pending. This roadmap -defines the embedded `ckconfig` dependency and source-report target. -[Selected scope decisions](#selected-scope-decisions) distinguish adoption from -deferred extensions. The [implementation plan](implementation.md) owns stage -order, concrete changes, and validation steps. - -## Purpose and authority - -Adopt `go.maximumdirect.net/configkit v1.1.0` and expose its capabilities through -CommandKit's existing configuration commands in a neutral, consistent way. -ConfigKit owns configuration loading, composition, resolution, inspection, and -their semantics. CommandKit owns command selection, coordination, presentation, -and invocation outcomes. Adapt upstream capabilities faithfully, using current -upstream terminology, without adding independent guarantees or commentary -qualifying upstream limitations. - -This follows the clarified integration goal and the existing -[architecture policy](../policy/architecture.md#backend-and-library-integration). -The [agent](../policy/agents.md), [testing](../policy/testing.md), -[documentation](../policy/documentation.md), [release](../policy/release.md), and -[OSS](../policy/oss.md) policies govern implementation. This roadmap records -the selected target; current contracts remain in GoDoc, the -[CLI reference](../cli.md), and the [consumer guide](../consumers/guide.md) until -implementation lands. - -## Current baseline and review evidence - -Initial review revision: `60841227b7e2928d3fefd3326f0e3f4694f41e6d`. -API coverage follow-up revision: `7a9e3a1f7cdd0475f06a63ce0aababefe08651bc`; -library code and module selections are unchanged between these revisions. -The completed [dependency alignment roadmap](integration-dependency-alignment.md) -records the preceding vanity migration and releases. - -| Component | Current selection | -| --- | --- | -| Core | `go.maximumdirect.net/commandkit v0.3.0`; Go 1.26.0 minimum | -| ckconfig | `go.maximumdirect.net/ckconfig v0.2.0`; Go 1.26.0 minimum | -| ckconfig dependencies | Core v0.3.0, `gitea.maximumdirect.net/eric/ConfigKit v0.8.0`, YAML v4.0.0-rc.6 | -| ckprompt | v0.2.0; ckconfig v0.2.0, old-path ConfigKit v0.8.0 and PromptKit v0.16.0; Go 1.26.0 minimum | -| Maintainer release toolchain | Go 1.26.8, with `GOTOOLCHAIN=local` | - -The ConfigKit vanity endpoint and direct Go module discovery resolve v1.1.0 to -published commit `191015e289d7f2b91abb9fdd9c4f2f5cf75b4de9`. Its module declares -Go 1.27.0 and retains the YAML dependency and LGPL-3.0-or-later library grant. -The upstream [v1.0 migration notes](https://forge.maximumdirect.net/base-layer/configkit/src/commit/191015e289d7f2b91abb9fdd9c4f2f5cf75b4de9/docs/releases/v1.0.0.md) -and [v1.1 release notes](https://forge.maximumdirect.net/base-layer/configkit/src/commit/191015e289d7f2b91abb9fdd9c4f2f5cf75b4de9/docs/releases/v1.1.0.md) -describe the adopted API and behavior changes. Upgrading from v0.8.0 also crosses -the import, collection, CLI-assignment, and discovery changes documented in the -[v0.9 notes](https://forge.maximumdirect.net/base-layer/configkit/src/commit/191015e289d7f2b91abb9fdd9c4f2f5cf75b4de9/docs/releases/v0.9.0.md) -and [v0.10 notes](https://forge.maximumdirect.net/base-layer/configkit/src/commit/191015e289d7f2b91abb9fdd9c4f2f5cf75b4de9/docs/releases/v0.10.0.md). - -A disposable ckconfig copy passed its complete module suite and maintained -simple example tests on Go 1.27.0 after changing the dependency/import path, -minimum, two source-reader fields, and affected test APIs. This establishes that -the existing adapter structure remains suitable. It did not exercise the -proposed report-field renames, additional source evidence, or a migrated -ckprompt; final implementation still needs validation of those selected changes. - -### API coverage findings - -The follow-up compared the public API of the pinned v1.1.0 module with -ckconfig's provider facets, adapters, and report projections. These are gaps in -current integration coverage, not necessarily APIs newly introduced in v1.1.0. - -| Capability | Current ckconfig exposure | Recommendation | -| --- | --- | --- | -| `SourceInfo.EmptyImportSelections` | Omitted from the source report. | Include in adoption; OD-2. | -| `Result.Metadata()`, `Metadata.Lookup`, and `IsExplicit` | No metadata facet in `View`; explanation reports do not expose explicit input presence. | Prioritize optional field-metadata inspection as the next functional expansion; OD-3. | -| `Metadata.HistoricalPaths` and `History` | Operators must already know a path to request an explanation; metadata history records are not exposed. | Pair path discovery and provenance history with metadata inspection; OD-3. | -| `LoadError.Sources()` and `Source(id)` | Acquired sources support diagnostic context, but `config sources` returns before reporting an inventory on acquisition failure. | Consider failed-load source inspection separately; OD-4. | -| Full `Difference` records | The Go comparison provider returns native records; the CLI reduces them to additions, right-side changes, and deletion paths. | Consider an additional detailed comparison report; OD-5. | -| Structured `Diagnostic` records | Native writers present diagnostic content; there is no structured native diagnostic report. | Lower-priority candidate, coordinated with shared reporting; OD-6. | - -The upstream [metadata API](https://forge.maximumdirect.net/base-layer/configkit/src/commit/191015e289d7f2b91abb9fdd9c4f2f5cf75b4de9/metadata.go), -[source and diagnostic records](https://forge.maximumdirect.net/base-layer/configkit/src/commit/191015e289d7f2b91abb9fdd9c4f2f5cf75b4de9/records.go), -[load-error API](https://forge.maximumdirect.net/base-layer/configkit/src/commit/191015e289d7f2b91abb9fdd9c4f2f5cf75b4de9/diagnostic.go), -and [comparison API](https://forge.maximumdirect.net/base-layer/configkit/src/commit/191015e289d7f2b91abb9fdd9c4f2f5cf75b4de9/diff.go) -own the returned evidence and its semantics. - -The current explanation projection covers every field of v1.1.0's -`Explanation`: effective and historical snapshots, origin and inheritance, -reasons, dependencies, and secret-reference names. Improved list-history -behavior can flow through that existing adapter. Metadata queries add distinct -information: explicitness and null state from `FieldInfo`, observed paths -including removed ones, and `Change` records with previous origins and operation -paths. They need not replace the value-oriented explanation report. - -`Result.Source(id)` is a convenient lookup of records already available through -the source inventory. A source-ID filter is a possible usability refinement; -it does not inherently require another command or a required lookup method on -every custom source provider. Discovery, import defaults, collection identities, -and field-level resolution recording fit the application-supplied loader. -Source resource contexts and explicit secrets-directory bootstrap primarily -serve application loading and startup; there is no immediate recommendation to -add standard inspection operations for them. A consumer need could motivate -later presentation of their upstream results. - -## Targeted end state - -### Dependency and toolchain - -The [ckconfig module](../../integrations/ckconfig/go.mod) requires -`go.maximumdirect.net/configkit v1.1.0`, and its production code, tests, and -maintained example use that import identity. Raise its consumer minimum to -Go 1.27.0. Retain its core v0.3.0 requirement unless implementation identifies -a concrete need for a newer core API. Core remains independent of ConfigKit -and retains its own Go minimum. - -Use a Go 1.27 toolchain for ckconfig dependency preparation and validation. -Update the [maintainer procedure](../release.md#release-toolchain) to select an -available Go 1.27 release and distinguish the per-module consumer minimums. -The existing host-native, workspace-off launcher can use that toolchain without -a new toolchain-selection mechanism. - -### Faithful adaptation and reports - -Retain the existing scope, loader, comparison, diagnostic, and reporting -structure. Continue using ConfigKit's public results, native rendering, and -diff APIs rather than reproducing its domain logic locally. New collection, -discovery, and resolution features can be used by application loaders through -the adopted library; they do not inherently require additional CLI flags or -CommandKit-owned loading policy. - -Align the existing source report with ConfigKit's current vocabulary: - -| Current API or report spelling | Target | -| --- | --- | -| `SourceInfo.DestinationUnresolved` | `SourceInfo.DestinationIsFallback` | -| `SourceInfo.VersionCheck` / `SourceVersionCheck` | `SourceInfo.VersionEvidence` / `SourceVersionEvidence` | -| Text/YAML `destination_unresolved` | `destination_is_fallback` | -| Text/YAML `version_check` | `version_evidence` | -| Native main layer value `base` | Native main layer value `main` | - -Update DTOs and both report formats together. Preserve the upstream evidence -and its supported presence, null, location, ordering, and redaction information -through adaptation. Use the upstream terms directly in help and documentation; -link to the owning inspection contract for their semantics. Describe the report -migration plainly in the release note. The target uses the new field names -without duplicate legacy report fields. - -Include `EmptyImportSelections` as `empty_import_selections` in both text and -YAML source reports under OD-2. Project each declaration path, location, and -native selector in the returned record order. Emit `empty_import_selections: []` -when there are no records. The [CLI reference](../cli.md#list-configuration-sources) -owns the implemented report contract. - -### Deferred inspection expansion - -Metadata inspection and path discovery are the next functional work proposed -after adoption (OD-3). Failed-load source inventory, detailed comparison, -and structured diagnostics remain separate later proposals (OD-4 through OD-6). -The [configuration inspection extensions](deferred.md#configuration-inspection-extensions) -record owns their proposed capabilities and design considerations. None is part -of this adoption scope or a new requirement on existing providers. - -### Consumer migration and module coordination - -Public ckconfig signatures expose ConfigKit types, so switching import identity -requires consumers to migrate the ConfigKit values they pass across those -boundaries. Use the adopted upstream API names in maintained consumers and -fixtures. Known test changes include `Definition.Secret` to `Sensitive` and -`Resolution.Record(..., ChangeNormalization, ...)` to `RecordNormalization`. -Review other removed pre-v1 symbols where actually used. - -Migration guidance should link to upstream for source-root `configkit` controls -becoming `config`, `optional` becoming `required` with changed defaults, -identified-collection registrations and operations, and CLI-assignment ordering. -Change affected maintained fixtures when present. Application configuration and -validation choices remain application-owned; CommandKit does not introduce a -compatibility loader or impose new configuration restrictions. - -ckprompt's current ConfigKit types come from the old package identity. It cannot -simply select the new ckconfig release while retaining that wiring. Its later -adoption needs a coordinated ConfigKit/PromptKit migration and review of its -own adapters and composed example. Under OD-1, prepare ckconfig independently -first and review ckprompt next. This roadmap does not select an unreviewed -PromptKit release or claim a new matched integration set. - -### Independent module compatibility - -Once local ckconfig uses the vanity ConfigKit types, the usual three-module -`go.work` selects it for local ckprompt as well. Until ckprompt migrates, its -old-path ConfigKit inspection and comparison types cannot satisfy the new -ckconfig contracts. This is a temporary composition mismatch, even though each -module can be validated independently against its own dependencies. - -During that interval, each module's independent validation uses its own declared -dependencies with workspace discovery off. The unchanged ckprompt and composed -example retain published ckconfig v0.2.0 and their existing upstream libraries; -their success does not establish compatibility with migrated local ckconfig. -Development and consumer guidance explain the temporary mismatch. Existing -ignored workspace files remain local; restoring aligned workspace composition -belongs to the later ckprompt migration. - -### Release preparation - -The target candidate is ckconfig v0.3.0, with full tag -`integrations/ckconfig/v0.3.0`, subject to the existing fresh-version guards. -A pre-v1 minor fits the intentional ConfigKit type-identity, consumer-minimum, -and report-schema changes. Its checked-in note explains these changes and -consumer migration, with the usual immutable licensing footer. Current module -notices describe the selected graph and pinned upstream source. - -Adoption includes release preparation, not source publication or hosted -delivery. The existing [release procedure](../release.md) owns those operations -and their separate outcomes when requested; this target adds no release gate. - -## Completion evidence - -Implementation is complete when ckconfig's actual module metadata and imports -select the new dependency, the selected report changes faithfully expose its -returned evidence, the module suite and maintained consumer pass independently, -and current documentation, notices, and release preparation describe that state. -Completion evidence distinguishes independent module validation from the -temporary workspace composition mismatch. OD-3 through OD-6 remain in deferred -work; their implementation is not a completion condition for adoption. A future -source release is reported separately from implementation completion. - -## Selected scope decisions - -These dispositions record the user's selected adoption scope. -They record the selected target and do not authorize publication. Deferred -features still need focused API and CLI design. - -| Decision | Selected disposition | Reason | -| --- | --- | --- | -| OD-1: Integration sequencing | Implement and prepare ckconfig independently first; review ckprompt next. | Independent releases keep adoption focused. Document the temporary workspace mismatch and lack of a newly aligned release pair. | -| OD-2: Empty-import evidence | Include `empty_import_selections`, with `[]` when empty, in text and YAML source reports. | Exposes existing upstream evidence alongside the other report-schema changes. | -| OD-3: Metadata and path discovery | Defer to the next functional work after adoption. | A coherent optional capability needs its own field/history report and command design. | -| OD-4: Failed-load source inventory | Defer to a separate source-inspection enhancement. | Requires source evidence on error and deliberate report/failure coordination. | -| OD-5: Detailed comparison | Defer; retain the existing reduced report during adoption. | A richer form needs a report-selection and compatibility decision. | -| OD-6: Structured diagnostics | Defer; retain native diagnostic rendering during adoption. | Coordinate machine-readable records with shared reporting and outcome delivery. | - -Adoption therefore covers dependency and API migration, source-report -terminology and empty-import evidence, documentation and notices, independent -module validation, and ckconfig release preparation. Core retains its own Go -minimum. Application loaders continue to own discovery and loading policy. - -Coordinating both integrations before release remains an alternative if a -matched adoption path becomes necessary. It would expand the scope to include -PromptKit review and ckprompt migration; publication would still proceed in -dependency order. The [deferred feature record](deferred.md#configuration-inspection-extensions) -retains the capability proposals and unresolved design choices for OD-3 through -OD-6, plus the possible source-ID filter. diff --git a/docs/roadmap/deferred.md b/docs/roadmap/future.md similarity index 61% rename from docs/roadmap/deferred.md rename to docs/roadmap/future.md index a8767b9..c10f24c 100644 --- a/docs/roadmap/deferred.md +++ b/docs/roadmap/future.md @@ -1,22 +1,57 @@ -# Deferred work +# Future work -Status: retained future work and unselected proposals; no implementation schedule. +Status: pending release and integration work, plus future capability proposals. +No delivery dates are selected here. ## Purpose and authority -Completed initial delivery, performance, ReleaseKit upgrade, and remediation -records have been retired. This document preserves remaining deferred -capabilities and unselected ideas under the +Completed roadmaps, implementation plans, and review findings have been retired. +This document preserves unfinished work and unselected ideas under the [release policy](../policy/release.md#release-documentation-and-preparation). -The original records remain available in -[Git history](https://gitea.maximumdirect.net/eric/CommandKit/src/commit/6bc37e7ba64ca0920b4d0cc77039a18d4006b24e/docs/roadmap). +The completed ConfigKit adoption, reporting, dependency alignment, release-tooling, +and remediation records remain available at the +[retirement snapshot](https://forge.maximumdirect.net/base-layer/commandkit/src/commit/260256d722f52bc947103d078cb67a129f4cc9f1/docs/roadmap). +[Earlier retired records](https://gitea.maximumdirect.net/eric/CommandKit/src/commit/6bc37e7ba64ca0920b4d0cc77039a18d4006b24e/docs/roadmap) +also remain in Git history. Completed records are not assignments to restart work. Accepted [ADRs](../adr/) and the [architecture policy](../policy/architecture.md) govern any future implementation. The [CLI reference](../cli.md), public GoDoc, and [consumer guide](../consumers/guide.md) own implemented behavior. Retaining an idea here does not select its syntax, API, priority, or delivery date. -## Deferred capability targets +## Pending release and integration work + +### ckconfig release and hosted delivery + +The ckconfig v0.3.0 candidate adopts ConfigKit v1.1.0 and Go 1.27.0; its +implementation and audits are complete. Its +[candidate release note](../../integrations/ckconfig/docs/releases/v0.3.0.md) +is prepared, but source publication and hosted delivery remain pending. Complete +those operations when requested through the [release procedure](../release.md), +using the existing fresh-version guards and reporting source publication and +hosted Gitea delivery separately. Publishing this roadmap cleanup does not +publish a module version tag or deliver a release page. + +### ckprompt dependency migration and workspace alignment + +Review the upstream PromptKit vanity release and select compatible ConfigKit +and PromptKit dependencies before migrating ckprompt's adapters and maintained +composed consumer. The new ckconfig uses vanity ConfigKit types; ckprompt v0.2.0 +still uses published ckconfig v0.2.0 and old-path ConfigKit v0.8.0. Their local +sources do not currently compose in the three-module workspace. See the +[consumer guide](../consumers/guide.md#module-selection) for the current module +relationship. + +The follow-up includes migrating affected imports and public type boundaries, +selecting real released dependency versions and the required Go minimum, +updating notices and migration guidance, and validating both ckprompt's +independent graph and the aligned composed consumer. Restore three-module +workspace guidance when those dependencies align, updating the ignored workspace +Go version as needed. Until then, preserve local workspace files and validate +with workspace discovery off as described in the [development guide](../development.md). +No unreviewed PromptKit version or new compatibility bridge is selected here. + +## Future capability targets ### Comparison extensions @@ -27,8 +62,8 @@ relevant ADRs. ### Configuration inspection extensions -The [ConfigKit v1.1.0 adoption review](configkit-v1.1.0.md#selected-scope-decisions) -recommends the following work after dependency and source-report adoption. +The [completed ConfigKit v1.1.0 adoption review](https://forge.maximumdirect.net/base-layer/commandkit/src/commit/260256d722f52bc947103d078cb67a129f4cc9f1/docs/roadmap/configkit-v1.1.0.md#selected-scope-decisions) +retained the following work after dependency and source-report adoption. Metadata inspection is the recommended next functional sprint; the other features have no selected sequence or delivery date. These proposals do not establish command grammar, report schemas, or new provider requirements. @@ -51,7 +86,7 @@ ConfigKit's public APIs own the evidence and its semantics. failures together; current diagnostic context remains available meanwhile. - **Detailed comparison (OD-5).** Consider an additional form projecting native `Difference` paths, both snapshots, presence/redaction fields, and - `HiddenChanged`. The adoption sprint retains the reduced + `HiddenChanged`. The current comparison retains the reduced additions/changes/deletions report. Decide later whether a detailed form complements it or replaces it through a deliberate compatibility change. - **Structured diagnostics (OD-6).** Consider machine-readable native codes, @@ -83,7 +118,28 @@ A later design should determine how alias suggestions are presented alongside canonical suggestions while ensuring inserted continuations form valid next steps. No delivery date or final API is selected here. -## Other deferred proposals +### Reporting extensions + +Error-conversion helpers such as `WarnError` remain deferred pending demonstrated +value; applications can already use `report.Warn(err.Error())`. Terminal redraw +and progress-bar presentation were outside the completed reporting scope and +remain unselected. Whole-run buffering to make failed runs show only errors +was also outside that scope. Any later extension needs a deliberate API and +presentation decision rather than assuming those behaviors are already provided. + +### Release workflow extensions + +Historical hosted-page backfilling and automated CI delivery remain separate +future choices. The current local page-only delivery workflow is implemented; +these extensions are not prerequisites for using it. The release procedure owns +delivery, immutable content, and recovery behavior. + +Additional validation options, including race testing, full vet, compilation +matrices, size limits, and more forbidden-file paths, can be considered for +demonstrated needs. None is selected by retaining it here, and the existing +candidate checks do not become general prohibitions on development workspaces. + +## Other future proposals These capabilities remain outside the delivered scope and require a concrete operator or consumer need and an appropriate ownership/behavior decision: diff --git a/docs/roadmap/implementation.md b/docs/roadmap/implementation.md deleted file mode 100644 index ca18962..0000000 --- a/docs/roadmap/implementation.md +++ /dev/null @@ -1,332 +0,0 @@ -# ConfigKit v1.1.0 adoption implementation plan - -Status: Stages 1–6 complete. - -This plan is for a Luna coding agent implementing the selected -[ConfigKit adoption target](configkit-v1.1.0.md). Follow Stage 1 through Stage 6 -in order as one end-to-end sprint. Intermediate editing states need not compile -or form independently usable releases. Reach and validate the complete selected -end state before claiming completion; do not introduce compatibility machinery -merely to make an intermediate stage pass. - -This planning pass changes documentation only. Execution prepares a ckconfig -release candidate; source publication, hosted delivery, ckprompt migration, and -the deferred inspection extensions are outside this sprint. Do not push or -create release tags as part of these stages. The user's later publication -instructions and the [release procedure](../release.md) govern those operations. - -Start with [development guidance](../development.md) and follow the -[agent](../policy/agents.md), [architecture](../policy/architecture.md), -[testing](../policy/testing.md), [documentation](../policy/documentation.md), -[release](../policy/release.md), and [OSS](../policy/oss.md) policies for the work -they govern. Use the repository's codebase-memory tools for code discovery. -The completed [vanity migration plan and publication evidence](https://forge.maximumdirect.net/base-layer/commandkit/src/commit/16584084b1b8a87dac959334ede8a47a8cfb8c0b/docs/roadmap/implementation.md) -remain in Git history; do not restart that work or the completed ReleaseKit -adoption/remediation. - -## Baseline and fixed choices - -Source/review baseline: `16584084b1b8a87dac959334ede8a47a8cfb8c0b`. -The planning commit changes roadmap documents, not module code. - -| Item | Baseline | Selected end state | -| --- | --- | --- | -| ckconfig module | `go.maximumdirect.net/ckconfig`, published v0.2.0 | Same module identity; prepare v0.3.0 | -| ConfigKit | `gitea.maximumdirect.net/eric/ConfigKit v0.8.0` | `go.maximumdirect.net/configkit v1.1.0` | -| ckconfig Go minimum | Go 1.26.0 | Go 1.27.0 | -| Core dependency | `go.maximumdirect.net/commandkit v0.3.0` | Retain v0.3.0 | -| Maintainer toolchain | Go 1.26.8 | Go 1.27.0 for preparation, validation, and ReleaseKit execution | -| Other module minimums | Core and ckprompt: Go 1.26.0 | Retain their independent minimums | - -ConfigKit v1.1.0 is published at -`191015e289d7f2b91abb9fdd9c4f2f5cf75b4de9`. Its module requires Go 1.27.0; -the prior disposable migration passed ckconfig and its example tests on that -toolchain. The selected report changes have not yet been implemented or tested. - -The feature roadmap's selected OD-1/OD-2 choices apply: migrate ckconfig first -and include empty-import-selection evidence. OD-3 through OD-6 and source-ID -filtering remain in [deferred work](deferred.md#configuration-inspection-extensions). -Retain the existing configuration operations, provider facets, loading and -comparison coordination, diagnostics, outcomes, and reduced diff report. -ConfigKit owns domain semantics; this sprint adapts its public capabilities. - -Retain root ReleaseKit v0.9.0, the release launchers and profiles, physical -module directories, and integration tag prefixes. Core and ckprompt code and -module selections are outside this adoption. Published old releases and notes -remain immutable. A new adapter layer, legacy import bridge, duplicate legacy -report fields, or local reimplementation of ConfigKit semantics is unnecessary. - -Preserve ignored `go.work`, `go.work.sum`, and `.releasekit/gitea-token` without -reading credential contents. Use `GOWORK=off GOTOOLCHAIN=local` throughout module -preparation, validation, and example runs. Local ckprompt will not compose with -migrated local ckconfig until its later ConfigKit/PromptKit migration; its -independent suite continues to use published ckconfig v0.2.0. Do not edit -ckprompt or introduce replacements to conceal this temporary mismatch. - -## Stage 1: Migrate the dependency, imports, and removed Go APIs - -**Completed.** Ckconfig now selects ConfigKit v1.1.0 and Go 1.27.0, with -authentic downloaded sums and migrated imports and native API accesses. An -offline compile of its packages and example passed with Go 1.27.0. - -1. Inspect the worktree and preserve unrelated work. Select Go 1.27.0 on - `PATH` and confirm it with `GOWORK=off GOTOOLCHAIN=local go version`. - This version was available during planning. Reuse an existing installation, - or install/download `golang.org/dl/go1.27.0` using the established SDK setup - pattern in the release procedure. Do not change the ignored workspace to - select the toolchain. -2. In `integrations/ckconfig/go.mod`, set `go 1.27.0`, remove the old ConfigKit - requirement, and require `go.maximumdirect.net/configkit v1.1.0`. Keep the - core requirement and YAML selection unless ordinary resolution establishes - a required change. Do not tidy root/ckprompt merely to raise their minima. -3. Migrate ckconfig-owned Go imports, including tests and the simple example, - to the new ConfigKit identity. Preserve the package alias `configkit`. - Inspect literals and documentation references separately from imports; - old repository URLs in published history are not import-path defects. -4. Adapt the native source-field accesses in `sources.go` to - `DestinationIsFallback` and `VersionEvidence`. Use - `configkit.SourceVersionEvidence` in affected test fixtures. The public - `SourceReader` contract still returns `[]configkit.SourceInfo` through the - new import identity; it needs no additional methods. -5. Update removed APIs actually used by the tests: `Definition.Secret` becomes - `Sensitive` in `comparison_adapter_test.go`, `diff_execution_test.go`, and - `diff_report_render_test.go`; the normalization call in - `TestFromConfigKitCompareIgnoresDefaultAndResolutionHistoryForEqualValues` - becomes `RecordNormalization(path, reason)`. Preserve the existing - application mutation and assertions. Search for any other used removed - symbols and use the pinned upstream migration mapping, not aliases or - replacement domain logic. -6. After import migration, prepare dependencies and run `go mod tidy` from - ckconfig with workspace discovery off and the selected local toolchain. - Use normal dependency retrieval during preparation; inspect the authentic - resulting `go.mod`/`go.sum` changes. Do not fabricate sums or use a sibling - checkout as a dependency. Format changed Go files. - -**Stage result:** ckconfig selects the released vanity dependency and current -Go APIs. Report spelling and new evidence are completed by the next stages; -there is no requirement to keep this intermediate state independently usable. - -## Stage 2: Align source-report vocabulary and add empty-import evidence - -**Completed.** Text and YAML projections use the new vocabulary and include -ordered empty-import selections, including empty lists and nil version evidence. -The packages compile offline with Go 1.27.0; focused behavioral tests follow. - -Work in `integrations/ckconfig/sources.go`. Keep its existing report preparation -and delivery path; no new provider capability or operation is needed. - -1. Rename DTO fields/types and both text/YAML keys to match the upstream terms: - `DestinationIsFallback` / `destination_is_fallback`, and - `VersionEvidence` / `version_evidence`. Rename `sourceVersionCheckDTO` to - `sourceVersionEvidenceDTO`. Continue projecting all existing version, - location, presence, null, and redaction fields as returned. Allow the native - main layer value to appear as `main`; do not translate it back to `base`. -2. Add `EmptyImportSelections` to each source DTO, serialized as - `empty_import_selections` after `version_evidence`. Use an ordinary slice of - a small DTO with fields in this order: `path` string, `location` using the - existing `locationDTO`, and `selector` string. No `omitempty` is needed: - initialize the slice so sources without records serialize as `[]`. -3. For every native record, project `Path.String()`, its supplied location's - source ID/line/column, and `string(Selector)`. Preserve source and record - order, source-local coordinates, empty strings, and zero coordinates. - Forward selector strings without validating or remapping them. Apply no - additional import discovery, filesystem access, or domain interpretation. -4. Extend the text writer with the same field names and field order. For an - empty slice, print `empty_import_selections: []`. For nonempty slices, print - one indented record per entry with `path`, `location`, and `selector`. - Follow the existing text style: quote path/source-ID/selector strings with - `strconv.Quote` and render a location as - `{source_id: "...", line: N, column: N}`. YAML uses the equivalent mapping. -5. The current text writer uses `continue` after printing a null version check. - Restructure that conditional so a null `version_evidence` does not skip the - new empty-import field. Every reported source includes both fields, with - `version_evidence: null` where the upstream pointer is nil. - -**Stage result:** both report forms use the current vocabulary and expose -empty-import evidence, including when no version evidence exists. Existing -source inventory, explanation, diagnostic, and outcome semantics are retained. - -## Stage 3: Update focused report and adapter coverage - -**Completed.** Focused source tests cover the new text and YAML keys, native -main layer, ordered selections, empty lists, and nil/redacted evidence. The -offline `TestSources` suite passed with Go 1.27.0. - -1. Extend `TestSourcesProjectNativeEvidenceInTextAndYAML` in `sources_test.go` - rather than building another report-test framework. Update fixtures and - assertions to the new native fields and report keys. Check that legacy - `destination_unresolved` and `version_check` keys are absent from emitted - source records; existing published history need not be scanned away. -2. Add controlled empty-import records to the source-reader fixture. Use - multiple records with distinguishable paths, selectors, and locations so - the test detects loss, reordering, or incorrect projection. Include a - source with nil version evidence and nonempty import records to cover the - text-writer conditional, and a source with no import records to verify `[]` - in both forms. Preserve the existing null/redacted version-evidence cases, - source order, zero-value coverage, and inventory-read count assertions. -3. Use the native `LayerMain` value in an appropriate fixture and verify that - returned source/explanation layer names are presented faithfully. Reuse - existing assertions where they already cover native origin projection; - do not add a separate test of ConfigKit's layer or provenance rules. -4. Keep existing tests of loader request forwarding, comparison coordination, - diagnostics, cancellation, error identity, output failures, and safe native - snapshot adaptation. Adjust removed APIs or intentionally changed report - expectations only. Do not rewrite behavior assertions merely to make an - unexpected regression pass. -5. Run the focused source tests with prepared dependencies, from ckconfig: - - ```sh - GOWORK=off GOTOOLCHAIN=local GOPROXY=off GONOPROXY=none GOSUMDB=off \ - go test -mod=readonly -count=1 -run '^TestSources' . - ``` - -**Stage result:** durable coverage establishes CommandKit's new report -projection. The fake native inventory supplies evidence; tests do not establish -whether ConfigKit discovers imports, checks versions, matches records, or -classifies sensitive data correctly. - -## Stage 4: Update current guidance and prepare the release note - -**Completed.** Current guidance describes the new source report, consumer and -toolchain migration, and temporary ckprompt mismatch. The v0.3.0 candidate -note is prepared; published notes remain unchanged. - -1. Update ckconfig README, GoDoc, and `examples/simple/README.md` for the new - dependency identity and Go minimum, and the planned ckconfig v0.3.0 with - core v0.3.0. Keep package/provider usage consistent with actual code. - Review maintained fixtures for source controls or removed APIs; migrate - genuine old controls where present, without changing application fields - merely because they have similar names. -2. Update `docs/cli.md`'s configuration-source section with the renamed keys, - main layer value, and `empty_import_selections` schema from Stage 2, - including the empty-list shape. Update origin-layer examples where they - describe adopted ConfigKit results. Retain existing command grammar, - formats, status behavior, and reduced comparison report. Use upstream terms - directly and link to the pinned upstream contracts for their semantics. -3. Update `docs/consumers/guide.md` and README's module-selection summary to - distinguish two cases: the newly prepared ckconfig v0.3.0 with ConfigKit - v1.1.0, and the existing matched ckconfig/ckprompt v0.2.0 pair. Do not imply - that ckprompt v0.2.0 composes with new ckconfig. Qualify upstream links where - ckconfig and unchanged ckprompt now use different ConfigKit versions. -4. Document the consumer migration: ConfigKit import/type identity, Go 1.27.0, - changed report keys, and added source evidence. Link to upstream migration - guidance for source-root `configkit` controls becoming `config`, import - requiredness/defaults, collection registrations/operations, removed public - APIs, and CLI-assignment order. Keep the detailed configuration reference - upstream rather than creating a parallel CommandKit contract. -5. In `docs/release.md`, select Go 1.27.0 as the maintainer toolchain and adapt - its existing install/download/PATH example. In that procedure and the - consumer guide, distinguish ckconfig's Go 1.27.0 minimum from core and - unchanged ckprompt's Go 1.26.0 minima. Keep ReleaseKit v0.9.0 and its - existing launcher, profiles, guards, publication, delivery, and recovery - workflow. This does not require code or profile changes. -6. Replace the development guide's unqualified three-module workspace advice - with interim guidance: preserve ignored workspace files and use - `GOWORK=off GOTOOLCHAIN=local` for preparation, suites, and example runs. - Explain that ckprompt's independent suite and composed example use its - published ckconfig v0.2.0 dependency; full local workspace composition is - pending the later ckprompt migration. Restore aligned workspace guidance - during that later work, including the workspace Go version as needed. -7. Create `integrations/ckconfig/docs/releases/v0.3.0.md`, subject to the - existing fresh-version selection, explaining the complete v0.2.0-to-candidate - changes and migration actions. End with `COPYRIGHT | LICENSE | ATTRIBUTION` - links to the corresponding module-local paths under - `https://forge.maximumdirect.net/base-layer/commandkit/src/tag/integrations/ckconfig/v0.3.0/integrations/ckconfig/`. - Future tag links need not resolve before publication. Preserve old notes. - -**Stage result:** current owners describe implemented adoption and the interim -module relationship; a checked-in candidate release note is ready. No deferred -feature, release publication, or external application migration is claimed. - -## Stage 5: Align module attribution with the actual selected graph - -**Completed.** The workspace-off module graph selects ConfigKit v1.1.0 and -vanity ReleaseKit v0.9.0; old-path ReleaseKit is no longer selected. Attribution -now reflects that graph and the pinned ConfigKit copyright and license source. - -1. From ckconfig, inspect `GOWORK=off GOTOOLCHAIN=local go list -m -json all` - after tidy. Compare it with the existing module attribution. ConfigKit's - own tool requirement does not select CommandKit's release tool: retain the - root-selected ReleaseKit v0.9.0 and inspect the effective transitive graph. -2. Update `integrations/ckconfig/docs/oss/attribution.md`'s ConfigKit entry to - `go.maximumdirect.net/configkit v1.1.0` and pinned commit - `191015e289d7f2b91abb9fdd9c4f2f5cf75b4de9` on the new forge. Verify its - actual copyright, grant, license, and applicable notices. Reuse existing - complete standard license texts when they match the selected terms. -3. Remove/update entries for dependencies no longer selected or whose selected - versions changed; the baseline includes old-path ReleaseKit v0.4.1 and its - dependencies as well as vanity ReleaseKit v0.9.0. Follow the actual graph, - not a global old-host replacement or an assumption that every tool module - disappears. Keep the House Format and exact-revision notice/source links. -4. Core and ckprompt dependency selections remain unchanged. Preserve their - corresponding notices and published release records. Update shared material - only if its actual scope or selection changes; adoption alone does not - require revising unrelated grants or copying upstream policy documents. - -**Stage result:** ckconfig's notices correspond to its real selected modules, -with authentic source/license references and no unrelated attribution rewrite. - -## Stage 6: Validate the final state and finish the sprint - -**Completed.** With Go 1.27.0 and workspace discovery off, the complete core, -ckconfig, and ckprompt suites passed offline with read-only metadata. Ckconfig's -suite was repeated after adding an explicit native main-layer explanation -assertion. The simple example's text and YAML source reports and fixture diff -ran successfully; the focused source fixture covers nonempty import evidence. -Core and ckprompt were tested against their own declared dependency graphs, -not against local migrated ckconfig. Full local workspace composition remains -pending the later ckprompt migration. The v0.3.0 note is a candidate; no source -release or hosted delivery was performed. - -1. Format changed Go files; inspect final diffs and module metadata. Confirm - ckconfig-owned Go imports use the vanity ConfigKit identity, the old - requirement is gone, its Go minimum is 1.27.0, core stays at v0.3.0, and no - local replacements/workspaces enter tracked module inputs. Confirm root - and ckprompt still have their existing module selections and Go minima. -2. Prepare any missing dependency caches for all three modules using normal - retrieval with workspace discovery off. On Go 1.27.0, run each independent - complete suite with read-only offline dependencies: - - ```sh - GOWORK=off GOTOOLCHAIN=local GOPROXY=off GONOPROXY=none GOSUMDB=off \ - go test -mod=readonly -count=1 ./... - (cd integrations/ckconfig && \ - GOWORK=off GOTOOLCHAIN=local GOPROXY=off GONOPROXY=none GOSUMDB=off \ - go test -mod=readonly -count=1 ./...) - (cd integrations/ckprompt && \ - GOWORK=off GOTOOLCHAIN=local GOPROXY=off GONOPROXY=none GOSUMDB=off \ - go test -mod=readonly -count=1 ./...) - ``` - - This includes ckconfig's maintained example tests. Record the unchanged - modules' results as validation of their own published dependency graphs, - not composition with local migrated ckconfig. Do not add a workspace shim - or change ckprompt to obtain a green three-module workspace. -3. Exercise the simple example's `config sources` text/YAML reports and its - existing fixture comparison with workspace discovery off. Use a controlled - native source fixture from Stage 3 for nonempty import evidence; a new - application import system or live service is unnecessary. Confirm only the - selected presentation and wiring behavior, not upstream domain correctness. -4. Check affected current documentation, local links/fragments, whitespace, - candidate note paths, attribution entries, and pinned-source provenance. - Ensure future behavior is not described as implemented, and distinguish - prepared v0.3.0 from a published release. Run `git diff --check` and the - staged counterpart, including intended new files in the review. -5. Record stage completion, final validation evidence, and the temporary - workspace mismatch in this plan. Mark the feature roadmap's implementation - status accordingly while leaving publication and external adoption pending. - Keep deferred capabilities in their owning record without starting them. -6. Review the worktree and staged changes, commit completed units under the - agent policy with concise messages, and finish with a clean worktree apart - from explicitly preserved unrelated work. Summarize the module/dependency - changes, report migration, tests, commits, and remaining ckprompt follow-up. - Do not publish; the normal selected-module release workflow remains the - owner of future candidate validation, guards, and publication outcomes. - -**Stage result:** the selected ckconfig adoption is implemented, documented, -validated, committed, and prepared for a later release request. Intermediate -compile failures and deferred work are not substitutes for this final result. - -No required scope questions remain open. Routine implementation choices follow -the selected upstream contracts and the report shape fixed above; deferred -extensions do not need to be designed to complete this sprint. diff --git a/docs/roadmap/integration-dependency-alignment.md b/docs/roadmap/integration-dependency-alignment.md deleted file mode 100644 index a3aa849..0000000 --- a/docs/roadmap/integration-dependency-alignment.md +++ /dev/null @@ -1,207 +0,0 @@ -# Integration dependency alignment and vanity-path migration - -Status: the vanity migration and matched source releases are complete. The -[completed implementation record](https://forge.maximumdirect.net/base-layer/commandkit/src/commit/16584084b1b8a87dac959334ede8a47a8cfb8c0b/docs/roadmap/implementation.md) records candidate commits, validation, -and publication outcomes; this roadmap retains the target and review history. - -## Purpose and authority - -Align the independently released integrations with the core APIs their current -source already uses, and migrate all three CommandKit modules to the supplied -vanity paths. Publish compatible module versions in dependency order so each -integration builds and validates against its declared, downloaded dependencies -with workspace discovery off. - -The [release procedure](../release.md) owns publication commands and release -order. The [release policy](../policy/release.md), -[agent policy](../policy/agents.md), [testing policy](../policy/testing.md), -[documentation policy](../policy/documentation.md), and -[OSS policy](../policy/oss.md) govern the work. This roadmap selects the target -and release-preparation scope; it does not change those policies. - -## Baseline and investigation evidence - -Reviewed baseline: `289a171e97699ad9aa57ee2cc40bdad1c0b680a9`. -Vanity-path review baseline: `d7cbaed3ed18bc2909c8144f308e2dfd58ade7ec`. -Module declarations and library source were unchanged between these revisions. - -- Both integration module declarations require core v0.2.0. The - [ckprompt declaration](../../integrations/ckprompt/go.mod) also requires - ckconfig v0.1.0; the [ckconfig declaration](../../integrations/ckconfig/go.mod) - has no dependency on ckprompt. -- Current integration source uses newer core APIs including `CompletionHint`, - `Explanation`, and `Reporter`. Both independent Go 1.26.8 suites fail to - compile with `GOWORK=off` and their existing read-only module graphs. -- Updating core alone is insufficient for ckprompt: published ckconfig v0.1.0 - still uses removed core APIs, including `Invocation.Streams`, - `Outcome.Diagnostics`, and `SeverityError`, plus the old `Failure(error)` - call shape. -- The authoritative `origin` tag listing contains core v0.1.0 and v0.2.0, and - the two integration v0.1.0 tags. The proposed next versions below were unused - at review. Remote `main` was `230187296fae5253cb1773f16c2f1d1a39499ed0`; - the reviewed local changes still need normal publication to the authoritative - branch as part of candidate preparation. -- A checked-in [core v0.3.0 draft](../releases/v0.3.0.md) already describes the - reporting and alias migration. It is an unpublished draft, not proof that - the module version can be downloaded. - -The investigation used disposable alternate module files, Go 1.26.8, -`GOWORK=off`, and read-only offline tests. Only temporary dependency selections -changed; the real module declarations, sums, and source remained unchanged. - -| Current source under test | Temporary dependency selection | Result | -| --- | --- | --- | -| ckconfig | Current core source | Module suite and maintained example passed. | -| ckprompt | Current core source, published ckconfig v0.1.0 | Compilation failed in the old ckconfig implementation. | -| ckprompt | Current core and current ckconfig source | Module suite and maintained example passed. | - -The successful cases retained ConfigKit v0.8.0 and PromptKit v0.16.0. These -results isolate the CommandKit dependency alignment needed here; they do not -prove that future published versions or their downloaded sums already exist. - -### Verified vanity discovery - -The core endpoint at `https://go.maximumdirect.net/commandkit?go-get=1` serves -the mapping to `https://forge.maximumdirect.net/base-layer/commandkit`. Go direct -discovery finds the existing core v0.1.0 and v0.2.0 tags. Fetching v0.2.0 through -the vanity path reaches its source but reports a module-path mismatch because -that release declares `gitea.maximumdirect.net/eric/CommandKit`. - -Both integration endpoints now return HTTP 200 with these `go-import` contents: - -| Vanity path | VCS | Repository URL | Subdirectory field | -| --- | --- | --- | --- | -| `go.maximumdirect.net/ckconfig` | `git` | `https://forge.maximumdirect.net/base-layer/commandkit` | `integrations/ckconfig` | -| `go.maximumdirect.net/ckprompt` | `git` | `https://forge.maximumdirect.net/base-layer/commandkit` | `integrations/ckprompt` | - -Go 1.26.8 direct discovery finds each integration's v0.1.0 tag. Disposable -consumer fetches reach the correct nested `go.mod` and report its old declared -module path, confirming subdirectory routing. Discovery is working; the -existing tags have not migrated. The optional fourth metadata field is -supported from Go 1.25, within the existing Go 1.26.0 consumer minimum; see the -[Go discovery reference](https://go.dev/ref/mod#vcs-find). - -## Targeted end state - -### Compatible independently released modules - -Use the following proposed next versions, subject to the existing fresh-version -publication guards: - -| Module path | Physical module directory | Next release | Required CommandKit dependencies | Full tag | -| --- | --- | --- | --- | --- | -| `go.maximumdirect.net/commandkit` | `.` | v0.3.0 | None | `v0.3.0` | -| `go.maximumdirect.net/ckconfig` | `integrations/ckconfig` | v0.2.0 | `go.maximumdirect.net/commandkit v0.3.0` | `integrations/ckconfig/v0.2.0` | -| `go.maximumdirect.net/ckprompt` | `integrations/ckprompt` | v0.2.0 | `go.maximumdirect.net/commandkit v0.3.0` and `go.maximumdirect.net/ckconfig v0.2.0` | `integrations/ckprompt/v0.2.0` | - -Minor integration releases fit the existing pre-1.0 compatibility policy: the -reporting migration changes consumer-facing behavior and adopts a core version -with incompatible API changes. The vanity migration also deliberately changes -Go module and import identities. Migration notes explain the new imports and -dependency set, provider results, invocation reporting, and application changes. - -The three modules retain independent versions and source tags. Their candidates -may identify successive commits: core publication need not wait for integration -metadata that depends on that newly published core. Each selected module's -final release suite runs against its actual declared dependencies. - -### Module and import identity - -Change each module declaration and all CommandKit-owned imports to the matching -new path. Core self-imports, including its `internal` packages, use -`go.maximumdirect.net/commandkit/...`; integration self-imports use -`go.maximumdirect.net/ckconfig/...` or `go.maximumdirect.net/ckprompt/...`. -Cross-module imports and requirements use the complete new paths in the table, -including ckprompt's ckconfig dependency. Core component-version discovery uses -`go.maximumdirect.net/commandkit` as its build-info identity, retaining the -existing `version --scope commandkit` behavior with the new module path. - -Update production files, tests, maintained examples, and any import-path-based -test expectations together. A declared vanity module that still imports the -old core path would select a different Go package identity and can violate -`internal` import rules. The matched new releases compose through one core -identity rather than mixing old-path and new-path CommandKit types. - -Keep physical directories, repository URLs, and Git tag prefixes as shown. The -Go subdirectory metadata makes the short integration vanity paths resolve to -the existing layout. The existing release profiles select physical directories; -the migration does not rename those directories or flatten integration tags. - -Published old-path versions remain immutable. This scope selects the new paths -for new releases and updates consumer guidance; it makes no new promise of -type interoperability between the two identities and adds no old-path forwarding -module or compatibility layer. - -### Retained architecture and scope - -Preserve exported declaration shapes and runtime behavior while deliberately -changing module/import identities. Retain the integration adapters, Go 1.26.0 -consumer minimum, Go 1.26.8 maintainer toolchain, and root-selected ReleaseKit -v0.9.0. The earlier successful diagnostic suites establish the dependency fix -before renaming; the migrated source still needs its own validation. This work -selects no API rollback or shim for old reporting APIs. - -Retain ConfigKit v0.8.0, PromptKit v0.16.0, and other dependency selections -unless ordinary tidy changes the resolved graph as a consequence of the -CommandKit updates. Inspect and explain the resulting graph rather than -bundling unrelated upgrades. In particular, transitive tools with different -module paths may coexist; attribution must reflect the actual selection. - -Preserve the existing launchers, three release profiles, generic validators, -credential handling, and separate source-publication and hosted-delivery -outcomes. Development workspaces remain useful and ignored. Diagnostic local -replacements and the earlier temporary Go shim remain development evidence; -release validation uses normal downloaded dependencies without that redirection. - -## Release-preparation deliverables - -The core v0.3.0 draft describes the complete candidate, including completion, -reporting, aliases, tool maintenance, and the vanity-path migration. New -integration notes at `integrations/ckconfig/docs/releases/v0.2.0.md` and -`integrations/ckprompt/docs/releases/v0.2.0.md` explain the matched dependency set -and consumer migration. Their source and licensing links follow the current -release procedure; published notes and tags remain immutable. - -Current installation examples, README module selections, consumer/developer -guidance, affected GoDoc, and maintained examples use the implemented new -identities. Import-path-aware tests retain their existing boundary assertions. -Source-hosting and license URLs remain repository links, distinct from Go -import paths. Module-local attribution describes each actual resolved graph. - -The final record identifies module paths, versions, candidate revisions, -validation evidence, and independent source-publication outcomes. Current -readiness guidance reflects the aligned state; historical failures remain in -completed investigation records. The implementation plan owns the ordered -migration, dependency preparation, release, and evidence-recording steps. - -## Validation and completion boundaries - -Review current CommandKit-owned source and dependency selections for stale -self-imports or old direct dependency keys. Historical notes, source URLs, and -unrelated upstream module identities are outside that mechanical rename. -Confirm release identity still pairs each new module path with its existing -physical directory and tag prefix. The verified redirects are preparation -evidence; publishing the renamed modules is needed for real consumers to use -them through those paths. - -Use the selected module's ordinary deterministic offline suite with -`GOWORK=off` and read-only metadata after dependency preparation. Its maintained -consumer compiles and runs with that suite. ReleaseKit's publication command -owns the final candidate suite and selected file checks; validation-only checks -remain optional diagnostics. Reuse successful evidence for unchanged candidates -instead of adding a required check-then-publish repetition. - -Retrieving a newly published dependency is preparation for the next module's -release. It does not turn proxy availability or consumer installation into a -completion gate for the preceding source release. Continue to resolve failed -or ambiguous publication using the existing policy and upstream recovery flow. -Hosted Gitea delivery keeps its separate outcome; this roadmap adds no CI -polling, live provider calls, or additional publication gate. - -Alignment is complete when the matched source versions are published under all -three vanity module paths, owned imports and examples use the new identities, -each integration declares the compatible vanity-path versions with authentic -downloaded sums, each final selected-module suite passes without workspace or -replacement redirection, and current documentation and attribution agree with -that graph. Temporary local-source success alone does not establish that end -state. diff --git a/docs/roadmap/release-simplification.md b/docs/roadmap/release-simplification.md deleted file mode 100644 index ab34016..0000000 --- a/docs/roadmap/release-simplification.md +++ /dev/null @@ -1,198 +0,0 @@ -# Release tooling simplification - -Status: the selected release-tooling design has been implemented. All four -generic file checks, registered-tool execution, page-only hosted delivery, and -protection of the supplied token path are selected. -The [completed implementation record](https://forge.maximumdirect.net/base-layer/commandkit/src/commit/87eb84ccb462bf54e6250c8b287ac217efe90883/docs/roadmap/implementation.md) -contains stage order, tasks, validation, and completion evidence. Current release -behavior stays with its canonical owners. - -## Purpose and authority - -Reduce CommandKit's release infrastructure to declarative module profiles, -a small launcher, and focused tests of CommandKit-owned wiring. Delegate -reusable candidate validation and publication mechanics to ReleaseKit while -retaining CommandKit's domain-specific checks in their existing owners. Add -hosted Gitea release pages as a separate local delivery operation after source -publication. - -The [agent policy](../policy/agents.md), -[release policy](../policy/release.md#candidate-validation), and -[testing policy](../policy/testing.md#upstream-integration-testing-ownership) -govern implementation. The [release procedure](../release.md) continues to own -the current workflow. - -## Targeted end state - -### Ownership - -CommandKit retains module selectors, product identities, profile locations, -the authoritative endpoint selection, release order, release-note meaning, -compatibility decisions, and attribution accuracy. Its existing public API, -CLI, integration-adaptation, and consumer-example tests remain local and run -through the owning module's suite. No parallel release-only domain suite is -needed unless a concrete CommandKit requirement is otherwise unprotected. - -ReleaseKit supplies the standard offline candidate suite, selected generic file -checks, candidate/note and publication guards, tag creation and publication, -hosted delivery, outcome reporting, and recovery. CommandKit's launcher delegates -those operations. Existing source-release completion and immutability rules -continue to apply. Hosted pages are the added delivery channel; binary -deliverables and platform support commitments remain unchanged. - -### Profiles - -Select these existing ReleaseKit options in each profile: - -| Selection | Intended protection | -| --- | --- | -| `validation.go_format: true` | Detect unformatted committed Go source. | -| `validation.markdown: {}` | Detect broken local Markdown destinations and supported heading fragments. | -| `validation.module_distribution.workspace_files: true` | Detect committed development workspace files in selected inputs. | -| `validation.module_distribution.local_replacements: true` | Detect filesystem replacements in selected committed module declarations. | - -Also select -`validation.forbidden_files: [".releasekit/gitea-token"]` in all three profiles. -This delegates protection of the supplied credential path to ReleaseKit's -existing check. The path is repository-relative and the check applies across -the captured repository even for an integration release. It does not read token -contents, scan other paths, or inspect Git history. - -Retain the explicit shared-file lists and use ReleaseKit's existing input scope. -The root profile does not run every nested module's suite. File checks inspect -committed inputs and do not replace formatting worktree changes or reviewing -documentation meaning, attribution, and external links. Markdown keeps its -default treatment of outside-checkout destinations; no stricter boundary mode -is proposed. - -The pinned [ReleaseKit configuration reference](https://forge.maximumdirect.net/base-layer/releasekit/src/commit/23203f235cc414c4ffe0fd3941030eb0c9f9943f/docs/config.md) -owns exact scope and behavior, including nested-module boundaries and vendored -inputs. Do not expand an option's scope into a general repository prohibition. -Race testing, full vet, compilation matrices, size limits, and additional -forbidden-file paths are not selected by this roadmap. They can be considered -separately for demonstrated needs. - -### Launcher and recovery - -Use the root module's registered `go tool releasekit` through `exec`, keeping -the current selector interface and publication argument mapping. -Retain host normalization, workspace-off execution, the local toolchain, and -read-only module metadata. Preserve other effective Go settings while arranging -read-only selection. -The implementation plan specifies the wrapper interface and invocation details. - -Go's cache supplies executable storage; the launcher creates no persistent -binary directory. `/.releasekit/` remains ignored for the credential file, with -an explanatory comment. Recovery instructions use the registered tool or the -entry point printed for the saved attempt, preserving ReleaseKit's distinction -between publication outcome and record-storage errors. - -Share module selection and host-safe tool invocation between publication, -delivery, and recovery where applicable. Delivery selects the same module -profile as publication; recovery uses its recorded attempt rather than inferring -identity from a current profile. Keep the existing publication interface and -provide an explicit delivery invocation without automatically chaining the two -operations. Keep one selector mapping and shared invocation plumbing. - -ReleaseKit v0.9.0 shipped host-safe consumer launcher examples and regression -coverage. The earlier simplification used v0.8.0, which already supported -registered tools. Keep host normalization locally because the reviewed -`go tool` invocation inherited foreign `GOOS`/`GOARCH` values and failed to run. -Do not switch tool-version selection from the root module to each integration -merely to match the upstream multi-module example. - -### Hosted Gitea release pages - -Configure this delivery selection in each module profile: - -| Field | Selected value | -| --- | --- | -| `delivery.forge` | `gitea` | -| `delivery.base_url` | `https://forge.maximumdirect.net` | -| `delivery.owner` | `base-layer` | -| `delivery.repository` | `commandkit` | -| `delivery.token_file` | `.releasekit/gitea-token` | - -Preserve the profiles' distinct product identities and physical module -directories. All pages belong to the same Gitea repository and are keyed by -the complete tag: `vX.Y.Z` for core, `integrations/ckconfig/vX.Y.Z` for ckconfig, -and `integrations/ckprompt/vX.Y.Z` for ckprompt. Pass the selected profile and -semantic version to `deliver`; ReleaseKit derives the complete module tag. - -With no build targets, delivery is page-only. ReleaseKit uses the complete -checked-in module release note, including its licensing footer, as the hosted -body. No binary assets, receipts, or checksum manifests are added. Use current -forge URLs and the full module tag for future notes' immutable source and -licensing links. Existing published tags and notes remain unchanged. - -After source publication succeeds, explicitly invoke delivery from a clean -checkout whose `HEAD` identifies that published tag's commit. For later retries, -use the original tagged source and its recorded module files. Report the source -publication outcome and hosted-delivery outcome separately, including the hosted -URL on success. A delivery failure leaves the source release complete; repair -delivery without republishing or moving its tag. - -Delivery performs its own read-only credential preflight, without rerunning -candidate validation or publishing a tag. Hosted-service availability and the -Gitea token do not become source-publication gates. A nonblank -`RELEASEKIT_GITEA_TOKEN` environment value takes precedence over the configured -file. The file path resolves from the repository root for all three modules. - -ReleaseKit accepts matching hosted content and reports conflicting content -without overwriting it. Resolve uncertain hosted writes before retrying the -same immutable version. The pinned -[delivery guide](https://forge.maximumdirect.net/base-layer/releasekit/src/commit/23203f235cc414c4ffe0fd3941030eb0c9f9943f/docs/consumers/delivery.md) -owns exact delivery behavior and recovery. Start with tags containing the new -delivery configuration; historical page backfilling remains a separate decision. -This local workflow needs no CI delivery job or additional secret distribution. - -### Focused local tests - -Replace the release-test scaffolding with a small controlled Go-command boundary -that invokes the actual launcher. Cover: - -- Selector-to-profile/module routing for core, ckconfig, and ckprompt, including - consistency with the checked-in profiles' intended module and product. -- Invalid argument handling before tool invocation. -- Invocation from another directory and paths containing spaces. -- Host normalization and workspace/toolchain/read-only settings. -- Publication and delivery argument, output-stream, and child exit-status - forwarding, with the selected module profile reaching the delivery operation. -- Profile wiring for the shared Gitea destination, token path, and its selected - committed-path protection; assertions do not read the credential file. - -Exercise module routing separately from exit statuses rather than multiplying -every combination. Assert behavior and meaningful selections, not helper -implementation details or exact usage prose. - -The resulting local suite omits the disposable publication exercise, generic -tag inspection, assertion-helper self-tests, and custom build-call log/parser. -Upstream publication and delivery coverage owns those generic behaviors. No -replacement publication engine or exported test-helper API is needed. There is -no line-count target for the replacement tests. - -## Selected choices and rationale - -All four generic file checks are selected as release-time checks, in addition -to the agreed forbidden token path. Formatting and local-link validation automate -existing contributor review work. Workspace-file and filesystem-replacement -checks address accidental inclusion of development metadata that a successful -local test run can overlook. This adds specific release checks; it does not -make every optional ReleaseKit validator mandatory or prohibit development -workspaces and replacements outside the selected committed candidate inputs. -Selecting only formatting and Markdown would change less release behavior, but -would leave these distribution mistakes to manual review. The selected upstream -checks avoid a second local implementation. - -Host-normalized registered-tool execution is selected because the root module -already registers ReleaseKit and Go caches the executable. Retaining a persistent -native executable would provide a recovery entry point independent of a later -Go-driver invocation, but would retain executable-storage and bootstrap test -maintenance. Recovery instead uses the registered tool or ReleaseKit's reported -entry point. The credential directory remains ignored under either approach. - -The implementation plan records the existing integration dependency-version -mismatch separately from validation of the current source. This infrastructure -sprint does not publish releases or select new library dependency versions. -Historical hosted-page backfilling and CI delivery remain separate future -choices, not prerequisites for the selected local page-only workflow. diff --git a/docs/roadmap/releasekit-v0.9.0.md b/docs/roadmap/releasekit-v0.9.0.md deleted file mode 100644 index 261ec8d..0000000 --- a/docs/roadmap/releasekit-v0.9.0.md +++ /dev/null @@ -1,184 +0,0 @@ -# ReleaseKit v0.9.0 adoption - -Status: R1 and R2 remediation, ReleaseKit v0.9.0 adoption, and the completion -assertion repair are complete. The [completed implementation record](https://forge.maximumdirect.net/base-layer/commandkit/src/commit/c8d659dfe5ae3e834b3aeabdfd0fe29b736dc05a/docs/roadmap/implementation.md) -records stage order, tasks, and validation evidence. This document owns the -target and selected choices; it does not authorize source or hosted publication. - -## Purpose and authority - -Adopt ReleaseKit v0.9.0's improved recovery behavior while preserving -CommandKit's existing release-tooling architecture. Update current dependency -and maintainer documentation together, and make the validation evidence clear -about existing local defects. - -The [agent policy](../policy/agents.md), -[release policy](../policy/release.md#candidate-validation), -[testing policy](../policy/testing.md#upstream-integration-testing-ownership), -and [documentation policy](../policy/documentation.md) govern the work. Current -behavior remains owned by the [release procedure](../release.md), Go declarations, -and owning package tests until implementation updates them. - -## Current baseline and review evidence - -Reviewed CommandKit code baseline: `4d92ee4ee6a8403b22a4172e0f04face802b9499`. -The original upgrade review used `98e7e9933353cf43f2be4a96cb0436a0bce068d2`; -its findings and validation history are retained below. - -- The root [module](../../go.mod) selects - `go.maximumdirect.net/releasekit v0.8.0` as a Go tool. Its selected version - serves core, ckconfig, and ckprompt operations. -- The [shared helper](../../scripts/releasekit) already normalizes the Go host, - disables workspace discovery, selects the local toolchain, retains read-only - metadata, and invokes the full executable package path. The - [legacy entry point](../../scripts/release) delegates publication to it. -- All three profiles already select the agreed generic file checks, forbidden - token path, and page-only Gitea destination. Source publication and hosted - delivery are separate operations. The local token directory remains ignored. -- [R1 and R2](remediation.md) are complete. Commit `7eac3fe` rejects invalid - legacy selectors before invoking Go; commit `4d92ee4` restores explicit, - optional POSIX-shell invocation in launcher tests. The remediation record owns - their acceptance evidence, including passing focused tests, shell syntax - checks, and profile assertions running when no shell is available. -- Both integrations still require older published CommandKit dependencies than - their current source needs. The completed [release-tooling implementation record](https://forge.maximumdirect.net/base-layer/commandkit/src/commit/87eb84ccb462bf54e6250c8b287ac217efe90883/docs/roadmap/implementation.md#stage-5-verify-the-final-source-and-record-validation-boundaries) - distinguishes workspace-backed tests from independent release readiness. - -The upstream v0.9.0 tag identifies commit -`2180aa868ec2caa95fc8279fd59d5f0ebac41bd4`. The tag and direct Go-module -resolution were verified. The default proxy initially returned v0.8.0 for -`@latest`; select v0.9.0 explicitly rather than changing repository-wide proxy -settings to work around that observation. - -Upstream [release notes](https://forge.maximumdirect.net/base-layer/releasekit/src/tag/v0.9.0/docs/releases/v0.9.0.md) -describe host-safe launchers and generated recovery commands, full package-path -tool selection, preservation of wildcard and version-specific replacements in -API-only recovery, and safer manual hosted-page retries. Public Go APIs, -profiles, record formats, and the Go 1.26.0 consumer minimum remain unchanged. -The v0.8.0-to-v0.9.0 comparison also left upstream module requirements, checksums, -copyright, and license texts unchanged. - -A disposable CommandKit upgrade changed only the selected ReleaseKit version in -`go.mod`. With Go 1.26.8, the root suite passed on a subsequent run, both -workspace-backed integration suites passed, and the real helper reported v0.9.0 -under foreign target settings. No production publication or delivery was run. - -A later disposable review at `7eac3fe` confirmed that downloading and tidying -v0.9.0 changed only the ReleaseKit requirement and its checksum entries. The -offline root suite and both workspace-backed integration suites passed with -Go 1.26.8, and the helper reported v0.9.0 under Windows/ARM64 target settings. -That snapshot excluded the then-uncommitted R2 change; it does not replace -validation of the eventual adoption commit. - -The initial upgrade run failed in -[`TestCompletionCommandContext`](../../completion_context_test.go). The same -alias-order failure reproduced four times in 30 focused repetitions on the -unchanged v0.8.0 baseline. A single passing rerun therefore does not establish -stable validation. The test compares an internal alias slice in a fixed order; -commit `0acbbf4` deliberately changed completion to use unsorted lookup records -before this upgrade review. - -## Targeted end state - -### Tool adoption and retained architecture - -The root module selects ReleaseKit v0.9.0 with authentic downloaded checksums. -Its existing tool declaration and root-owned selection remain. No integration -dependency version, library import path, Go minimum, or selected Go 1.26.8 -maintainer toolchain changes as part of adoption. - -Keep host normalization and full-package invocation in the existing helper: -upgrading a dependency does not update or replace local shell scripts. Keep one -module/profile mapping and the established wrapper forms. Retain the selected -profiles, token-file handling, credential-directory ignore rule, and separation -of source and hosted outcomes. No new validator, binary target, CI workflow, -publication channel, credential preflight gate, or runtime API is needed. - -The new generated Go recovery commands complement the helper's existing host -handling. Recovery continues to use saved publication evidence and the upstream -record formats; CommandKit does not acquire a parallel recovery implementation. - -### Release-code simplification review - -The v0.9.0 review identified no additional local release implementation to remove. -The earlier simplification already delegated generic validation, publication, -delivery, and recovery to ReleaseKit. This release improves launcher examples -and generated recovery commands without adding validation options that replace -the remaining CommandKit code. - -Retain the shared helper's module/profile selection and execution environment. -Host normalization must happen before Go compiles and runs ReleaseKit. Retain -the legacy publication wrapper to preserve the established maintainer interface. -The upstream multi-module launcher example adds a module map and temporary -metadata preparation for a different tool-selection model; replacing our -root-owned registered-tool helper with it would add machinery. - -Retain the focused [wiring tests](../../scripts/release_test.go) for profile -selections, argument forwarding, environment, streams, status, and optional-shell -handling. ReleaseKit owns validation and recovery semantics; CommandKit's tests -continue to cover its own adapter. The adoption work therefore preserves the -release-code structure while updating the dependency and documentation, alongside -the separately planned completion assertion repair. - -### Current documentation and history - -Current release procedure, project-specific release policy, consumer Go-tool -selection summary, and root attribution describe v0.9.0. Upstream contract and -notice links use the corresponding immutable source revision. Record that the -host-safe launcher request has shipped upstream instead of describing it as -pending in the earlier feature roadmap. - -Continue linking to upstream recovery and delivery contracts from the maintainer -procedure. Use ReleaseKit's generated recovery commands and keep local guidance -focused on CommandKit's entry points and selections. - -Preserve the baseline and validation history in completed implementation and -review records. Do not mechanically replace every historical v0.8.0 reference. -Integration attribution describes its own selected published dependency graph; -update it only if that actual selection changes. No license-text replacement -is needed for the unchanged upstream texts. - -### Completed remediation and remaining correctness work - -R1 and R2 were delivered before the dependency upgrade, with their completion -markers and acceptance evidence in [remediation.md](remediation.md). Preserve -their selector rejection, legitimate raw helper forms, and optional-shell test -boundary during adoption; no further implementation of those findings remains. - -The completion assertion compares the expected alias source/target records -without depending on their iteration order, while detecting missing, unexpected, -or duplicate records. Its routing and visible-completion assertions remain. -Production alias ordering and public contracts are unchanged. This correction -was completed as part of the maintenance scope, separate from R1/R2 remediation; -the implementation plan records the test changes and focused verification. - -Ordinary releases retain their single selected-module publication suite and -separate hosted-delivery outcome. One-time upgrade diagnostics are maintenance -evidence, with no new recurring release gate. Credentials and live publication -are unnecessary for this adoption. - -## Completion evidence - -Adoption is demonstrated by authentic module metadata, the real helper reporting -v0.9.0 for the host, aligned current documentation and attribution, and recorded -validation of the final source. The reviewed upgrade introduced no other module -version change; verify rather than assume that result during implementation. - -R1/R2 acceptance evidence is complete in the remediation record. Completion of -the remaining maintenance work also includes a stable, order-independent -completion assertion and validation that the adopted helper retains the -corrected launcher behavior. Independent integration dependency alignment -remains separate release-preparation work; this roadmap selects no future -versions or sums. - -## Resolved choices - -R1 and R2 were corrected in separate commits before adoption, resolving the -former OD-1 scheduling question. Their acceptance evidence remains in -[remediation.md](remediation.md). - -The selected maintenance scope is the completion assertion repair, root tool -upgrade, aligned current documentation and attribution, and validation of the -resulting source. The older integration dependency-version mismatch remains -separate release-preparation work. The implementation plan defines execution -and commit sequencing. diff --git a/docs/roadmap/remediation.md b/docs/roadmap/remediation.md deleted file mode 100644 index aedbb72..0000000 --- a/docs/roadmap/remediation.md +++ /dev/null @@ -1,116 +0,0 @@ -# Release tooling review findings - -Status: R1 and R2 complete; no open findings. Review baseline: -`124a9fa57fb3f815bedbafe2d4819f6aa265ee7d`, covering the implementation commits -after `cb40f1d`. The findings below preserve the review evidence; completion -markers record the subsequent corrections. No implementation was changed during -the original review. - -The selected architecture is substantially present: three declarative profiles, -one host-normalized registered-tool helper, separate publication and page-only -delivery, retained credential-directory ignoring, and focused wiring tests. -Both issues identified by the review have been addressed. - -## R1 — P2: Reject raw helper command names as legacy module selectors - -**Completed.** The legacy entry point now checks its three module selectors -before delegating to the helper, retaining the single profile/module mapping -there. Regression cases cover all three raw-command collisions and require -usage status 2 with no Go invocation. The new regression failed before the fix; -the complete focused scripts suite and shell syntax checks passed afterward -with Go 1.26.8, including valid legacy and direct raw-command forwarding. - -**Location:** [scripts/release](../../scripts/release), lines 9–10, delegating to -the first-argument dispatch in [scripts/releasekit](../../scripts/releasekit), -lines 10–15. The invalid-form cases in -[scripts/release_test.go](../../scripts/release_test.go), lines 186–200, miss -these collisions. - -The legacy interface is `scripts/release MODULE VERSION`, with three module -selectors. It now delegates its first argument directly into a helper that also -accepts `version`, `publication-attempts`, and `reconcile` as raw commands. These -invalid module names consequently bypass selector rejection and invoke Go. - -For example, `./scripts/release version v1.2.3` reaches the tool as -`version publish v1.2.3`. With the real pinned tool it returns upstream's -"version takes no arguments" diagnostic after tool resolution. In a disposable -copy with a controlled Go boundary returning status 73, each of the three raw -command names returned 73 and invoked Go; an ordinary unknown selector returned -2 without invoking Go. Thus invalid legacy input depends on tool availability -and behavior instead of being rejected at the wrapper boundary. - -**Required correction:** Make legacy module selection unambiguous before raw -command dispatch. Keep one profile/module mapping and the supported raw helper -forms; a small selector check is preferable to another routing framework. -Preserve upstream ownership of version and flag validation. - -**Verification:** Add all three raw command names as invalid legacy selectors. -Each must return usage status 2 before any Go command runs. Valid legacy -publication and the helper's direct raw forms must retain their forwarding and -exit-status behavior. This restores the requested malformed-wrapper handling; -it adds no new accepted-version restriction. - -## R2 — P2: Restore the tests' optional POSIX-shell execution boundary - -**Completed.** Launcher execution tests now discover `sh`, invoke it explicitly -with the script path, and skip when it is unavailable. Profile assertions remain -independent of shell availability. A regression case removes the fixture -script's executable permission to verify interpreter invocation; it failed -before the correction and passes afterward. The focused scripts suite and shell -syntax checks passed with Go 1.26.8 on the available POSIX host. Running the -compiled test binary with an empty `PATH` confirmed that every launcher -execution case skips while all three profile assertions pass. Native Windows -execution was not tested and no new platform guarantee is introduced. - -**Location:** [scripts/release_test.go](../../scripts/release_test.go), especially -`fixture.run` at line 63 and the launcher test setup. - -The rewritten tests execute extensionless POSIX shell scripts directly through -`exec.Command`. They neither discover a shell nor skip launcher execution when -it is unavailable. The previous suite resolved `sh`, skipped shell-dependent -tests when it was missing, and passed the script as an argument to that shell. - -Direct execution works on this review's Linux host, but relies on Unix script -execution semantics. Native Windows process creation does not supply a POSIX -interpreter for these files. Go's -[os/exec documentation](https://pkg.go.dev/os/exec#hdr-Overview) explicitly notes -that it does not invoke a system shell. Consequently the default repository -suite now fails on hosts without compatible script execution rather than -preserving the previous optional-shell behavior. This portability finding is -based on the changed execution path and platform implementation; a native -Windows test run was not available during review. - -**Required correction:** Discover a POSIX shell for launcher execution tests, -invoke it explicitly with the script path, and skip those tests when the shell -is unavailable. Keep profile-only JSON assertions runnable without requiring a -shell. Preserve the reduced test architecture and existing argv/status checks. -No native Windows release launcher or additional supported-platform guarantee -is requested. - -**Verification:** Confirm that launcher tests use the discovered interpreter -and handle its absence explicitly, while profile assertions still run. Rerun -the focused suite on the available POSIX host. Broader platform matrices are -not a new release gate; this correction removes an incidental environment -restriction introduced by the test rewrite. - -## Review evidence and limits - -- Go 1.26.8 offline root tests and the temporary-workspace suites for both - integrations passed. Both production scripts passed shell syntax checks. -- The real helper reported ReleaseKit v0.8.0 under foreign target settings. -- ReleaseKit checks passed for a disposable committed source snapshot using - the actual profiles: ordinary root validation, then both integration checks - with the implementation plan's temporary workspace-backed test process. - Selected file checks continued to inspect the committed declarations. -- Local documentation destinations and applicable Markdown fragments passed - inspection. The credential file remained ignored and its contents were not - read. No real publication or hosted-delivery operation was invoked. -- Library code and dependency declarations were unchanged by the sprint. The - documented integration dependency-version mismatch remains a pre-existing - independent-release-readiness limitation; the workspace-backed results do - not establish that published dependencies are aligned. - -No additional architecture gaps or unrequested runtime/public-API guarantees -were identified. The selected file checks and forbidden token path match the -finalized scope. R2 concerns the default tests' execution environment rather -than a new production validator or library contract. diff --git a/docs/roadmap/reporting.md b/docs/roadmap/reporting.md deleted file mode 100644 index c1ce509..0000000 --- a/docs/roadmap/reporting.md +++ /dev/null @@ -1,890 +0,0 @@ -# Output policy and invocation reporting - -Status: behavioral decisions selected through OD-4. Message categories, all four -output modes, uniform treatment of help and version, message prefixes, and -OD-1's flag grammar and scope (including independent Progress control) are selected. -OD-2's unified reporting direction, the terminal failure model, and application -ownership of domain-specific error decisions are selected. -OD-3's failure presentation and retention boundaries are selected. -OD-4's delivery lifecycle, write-failure handling, and quiet-mode rendering are -selected. The consumer API signatures, presentation-result model, provider -diagnostic boundary, fallback explanations, and rendering callback boundary -below are also selected. Architectural preparation is complete: -[ADR 0014](../adr/0014-invocation-reporting.md) is accepted, and the -[architecture policy](../policy/architecture.md) is aligned. Implementation and -final validation are complete; Stages 1–20 are complete. The [implementation -plan](https://forge.maximumdirect.net/base-layer/commandkit/src/commit/230187296fae5253cb1773f16c2f1d1a39499ed0/docs/roadmap/implementation.md) records the stage order and validation evidence. - -## Purpose - -Provide consistent handling of `--quiet`, `--verbose`, `--debug`, and -`--progress` across application commands and optional integrations. Reduce -repeated output classification, diagnostic presentation, and delivery bookkeeping -where CommandKit can provide a meaningful benefit. - -Ordinary Go writers and formatting functions already make application output -straightforward. Design reporting conveniences around the shared output policy -and invocation lifecycle. Applications continue to own their report content, -domain behavior, and operation outcomes. - -## CLI presentation and error-handling ownership - -Applications decide how to respond to domain-specific errors: recover, retry, -continue silently, report a Warning, or end the invocation with a failure. -CommandKit may provide shared helpers for carrying, inspecting, and presenting -errors while leaving those decisions with the application. A Go `error` alone -does not determine a CLI message category. Warnings may describe issues with or -without an underlying Go error, and handling an error does not require emitting -a message. - -CommandKit handles the presentation the application requests: message category, -visibility, formatting, timing, and delivery. For terminal application failures, -the application supplies a non-zero outcome and an operator-facing explanation. -It may also supply an optional Go error cause for the execution caller to inspect. -CommandKit preserves that cause and its existing `errors.Is`/`errors.As` behavior. -Supplying a cause alone does not select an outcome, generate an operator-facing -message, or change visibility. - -Applications can explicitly present `err.Error()` as a Warning through the -ordinary message API, illustrated by `report.Warn(err.Error())`. Defer a separate -`WarnError` convenience helper pending demonstrated value; this conversion -already requires little code. - -CommandKit retains responsibility for handling its own errors, including -routing, parsing, and reporting failures. Integration-owned commands similarly -adapt their upstream APIs into deliberate command outcomes and presentations. -Ordinary Go error returns from CommandKit APIs and writers remain available where -appropriate. - -## Current baseline - -[`Streams` and `Invocation`](../../identity.go) expose caller-selected output -and diagnostic writers. [`Outcome` and `Diagnostic`](../../outcome.go) carry -operation causes, diagnostic writers, and delivery state. Handlers can return -`Failure(err)` or attach diagnostics to an outcome for presentation after the -handler returns. `MessageDiagnostic` currently writes the supplied message with -a newline; severity does not add a label automatically. - -CommandKit coordinates final diagnostic delivery and retains delivery failures -separately from the operation cause. Custom handlers can also write directly to -the supplied streams and retain responsibility for their output. The existing -outcome and channel ownership decisions are recorded in -[ADR 0005](../adr/0005-invocation-outcomes.md). - -Integration adapters already translate upstream diagnostic records into -CommandKit diagnostics while preserving native rendering and source context. -Some adapters wrap multiple records in one diagnostic writer and classify the -batch by its highest severity. This matters when designing selective visibility. - -There is currently no shared verbosity policy or invocation reporter API. - -## Selected output policy - -Distinguish substantive application output from diagnostic message categories: - -- **Substantive output (Normal):** The requested report or command result. -- **Error:** Terminal presentation of an unrecoverable invocation failure, - resulting in a non-zero status code. -- **Warning:** Something went wrong or deserves attention, but the invocation - can still succeed. The application chooses whether to report such an issue. -- **Info:** Informational context and useful explanation, such as which profile - was selected or a final operation summary. -- **Progress:** Streaming updates about work underway, such as items processed. -- **Debug:** Troubleshooting detail, including intermediate decisions and - execution-path information. - -Debug mode adds troubleshooting detail to verbose output: - -| Output category | `--quiet` | No flag | `--verbose` | `--debug` | -| --- | --- | --- | --- | --- | -| Substantive application output | Suppressed | Shown | Shown | Shown | -| Error | Shown | Shown | Shown | Shown | -| Warning | Suppressed | Suppressed | Shown | Shown | -| Info | Suppressed | Suppressed | Shown | Shown | -| Debug | Suppressed | Suppressed | Suppressed | Shown | -| Progress, without an explicit setting | Suppressed | Suppressed | Suppressed | Shown | - -Info belongs in verbose mode; debug includes verbose messages. Normal output -remains a substantive result category, separate from diagnostic severity. -The category of a message determines its visibility; stream destination alone -cannot distinguish a warning from an error. - -Progress is distinct from Info and is controlled separately as specified below. -Applications and integrations are not required to generate messages in any -category. Enabling a category adds no output when there are no messages in it; -other output remains subject to its own visibility rules. - -Error presentation follows the terminal failure model below. An application -may report a recovered problem as a Warning or continue without a message. - -Apply the same policy to help and version. There are no command-specific -exceptions for successful output: - -```text -app help --quiet # succeeds silently -app version --quiet # succeeds silently -``` - -Usage and operational failures still report their errors in quiet mode. -The feature must distinguish successful output suppression from failure -diagnostic delivery. - -### Message prefixes and channels - -Substantive output uses the result destination, conventionally stdout. Warning, -Info, Progress, Debug, and terminal explanations use the diagnostic destination, -conventionally stderr. Callers supply both destinations. - -Use `WARN:`, `DEBUG:`, and `ERROR:` prefixes for simple warning, debug, and error -messages respectively. Substantive output and Info messages have no prefix. -For multiline diagnostics, prefix the opening line and preserve the structured -detail. Integration adapters coordinate native diagnostic rendering to avoid -duplicate severity labels or loss of upstream formatting. - -Usage guidance belongs to the terminal usage explanation and remains visible in -quiet mode. Successful help output follows the substantive-output policy. - -Initially, Progress messages are unprefixed streamed lines. The diagnostic -destination keeps them separate from substantive output such as JSON or YAML. -Terminal redraw and progress-bar behavior are outside this implementation. - -### Terminal failure model - -During execution, applications can produce substantive output, Progress, Info, -Debug, and Warnings. An unrecoverable failure ends the handler by returning a -failed outcome. There is no standalone `report.Error(...)` method. Detailed -error explanations accompany the returned failure and are presented as part of -that terminal step. - -CommandKit finalizes reporting, presents the terminal failure explanation, and -returns the non-zero outcome to the application entry point. It accepts no -further normal output for that invocation after terminal error presentation. -The same boundary applies to core routing and parsing failures that prevent -handler execution. The application entry point retains ownership of process -exit; CommandKit ends the invocation and returns its outcome. - -For example, if an export operation fails and the application decides it cannot -continue, the handler returns a non-zero outcome with an explicit explanation -such as "Unable to export the requested report." The application can choose to -include detail from a Go error in that explanation. CommandKit presents the -supplied explanation without automatically deriving text from an application -error. The selected API below provides failure constructors for this purpose. -When a failed outcome supplies no explanation, CommandKit supplies the generic -fallback defined under terminal outcomes below. - -Output streamed before the failure remains visible according to its selected -mode; terminal failure does not withdraw earlier bytes. Deferred messages, -cleanup writes, and delivery failures must respect the end of normal reporting. -Their finalization and late-write behavior follow OD-4 below. A terminal -failure may have multiple explanatory records, all belonging to that failure. - -### Failure explanations and presentation ownership (OD-3) - -Make a non-zero outcome with an explicit message the convenient failure path. -Support structured explanations, including multiple records, through the same -presentation facility for richer application and integration reports. Neither -form requires an underlying Go error. - -The application or integration explicitly identifies the context belonging to -a terminal explanation. Present that context with the failure in every mode, -including quiet. Independent warnings and other messages retain their own -visibility rules. For mixed upstream batches, adapters preserve useful native -rendering while distinguishing terminal explanatory context from independent -messages. Core does not infer those relationships from error chains or text. - -Assign each submitted message one presentation path. Returning a terminal -explanation schedules its presentation once; core does not append another -message derived from an application error cause. Native renderers can supply -already-labelled content without receiving duplicate prefixes. Avoid text-based -deduplication: separate events may legitimately produce identical messages. - -Constructing a failure result attaches explanatory content without emitting or -independently scheduling an Error. Returning that result hands the explanation -to CommandKit for terminal delivery through the invocation's reporting facility. -The selected API expresses this distinction for both simple and structured -explanations. For example: - -| Handler action | Presentation | -| --- | --- | -| Construct a non-zero result with "Unable to export the requested report," then return it. | Construction emits nothing. CommandKit presents the message once during terminal delivery. | -| Return a failure with native diagnostic records and their source context, submitting independent warnings separately. | CommandKit presents the structured terminal explanation in every mode. Independent warnings follow their own visibility policy. | - -### Retention boundary (OD-3) - -CommandKit provides invocation-scoped CLI presentation. Logging and message -history collection remain application concerns. Keep terminal explanations and -any supplied cause with the returned outcome, and keep the temporary state needed -for deferred delivery, parser events awaiting mode selection, and delivery -bookkeeping. The reporting facility does not collect a transcript or retain other -emitted or suppressed messages for later inspection. No optional message-history -facility is planned for this implementation. - -## Selected flag grammar and scope - -### Mode selection and resets - -Model quiet, ordinary, verbose, and debug as mutually exclusive presentation -modes. Each invocation starts in ordinary mode. Process flag occurrences in -invocation order; the last enabled mode wins. Repetition does not increment -verbosity, and debug is selected explicitly. - -Accept presence and the existing explicit boolean syntax, including -`--quiet=true` and `--quiet=false`. A false occurrence clears its mode only if -that mode is currently selected, returning to ordinary mode. It does not restore -an earlier selection or disable a different mode. Every occurrence is converted; -invalid boolean values remain usage errors even when a later flag would replace -the selection. - -| Flag sequence | Final mode | -| --- | --- | -| `--quiet --verbose` | Verbose | -| `--debug --quiet` | Quiet | -| `--verbose --verbose` | Verbose | -| `--verbose --verbose=false` | Ordinary | -| `--quiet --verbose=false` | Quiet | -| `--verbose --quiet --quiet=false` | Ordinary | -| `--quiet=false --debug` | Debug | - -Keep verbosity a presentation choice: quiet preserves the requested operation's -semantics and rendering failures. Delivery failures depend on the output actually -requested; suppressing a destination write can avoid a delivery failure. Apply -the policy through CommandKit-managed reporting and streams. Output written -directly to process streams or external destinations remains application-owned. - -### Progress selection - -`--progress` enables Progress without enabling Info, Warning, or Debug messages. -`--progress=false` explicitly disables it. Accept the existing boolean syntax; -repeated canonical or aliased progress settings use the last value. Retain -whether a setting was explicitly supplied, separately from its boolean value. - -Determine effective Progress visibility from the final presentation mode and -explicit progress setting: - -1. Quiet mode always suppresses Progress. -2. Otherwise, an explicit progress setting controls visibility. -3. Without an explicit setting, debug enables Progress; ordinary and verbose - modes leave it disabled. - -An explicit progress setting overrides the mode's default regardless of its -position relative to mode flags. It does not select or reset the presentation -mode. Debug includes verbose detail and defaults Progress on; verbose alone -does not enable Progress. - -| Flags | Result | -| --- | --- | -| `--verbose` | Warning and Info, without Progress. | -| `--verbose --progress` | Warning, Info, and Progress. | -| `--debug` | Warning, Info, Debug, and Progress. | -| `--debug --progress=false` or `--progress=false --debug` | Debug detail without Progress. | -| `--quiet --progress` or `--progress --quiet` | Only failure diagnostics. | -| `--debug --verbose` | Verbose detail without Progress, absent an explicit progress setting. | - -Passing `--progress` to an application that emits no Progress messages adds no -visible output. It does not suppress that application's substantive results or -require a progress implementation. - -### Placement, availability, and aliases - -Core supplies `--quiet`, `--verbose`, `--debug`, and `--progress` for application -commands, integrations, the root, canonical groups, and alias-only discovery help. -Consumers do not register them individually. Preserve the existing placement -grammar: flags follow the complete command path and may be interspersed with -operands after that path. For example: - -```text -app config show --quiet -app export destination --verbose -app help config show --quiet -app version --quiet -``` - -Options before or between command-path components are outside this grammar. -Tokens consumed as values and tokens following `--` retain their ordinary -meaning. - -Reserve the four long spellings. Applications may add `-q`, `-v`, or `-d` -through the alias API; no built-in short spellings are selected. An application -flag declaration that defines a reserved long name fails installation with a -collision error. Aliases may target these flags but may not overload canonical -spellings. Apply the existing collision and atomic installation rules, including -later registration. - -Aliased and canonical occurrences participate in the same ordering. With -`-q → --quiet`, `app export --verbose -q` selects quiet mode. Document the newly -reserved canonical names as a compatibility change. - -### Routing and parsing failures - -Determine the mode through the normal parser before execution or successful -help/report presentation. Do not add a separate verbosity scanner. This keeps -token interpretation consistent and avoids reinterpreting values or operands. - -Routing and parsing failures report their errors regardless of verbosity. For -example, `app export --quiet --unknown` still reports the unknown flag. Error -visibility follows the selected output policy independently of how the mode is -determined; avoiding a separate scanner is an implementation simplification. - -## CommandKit's own diagnostics - -Use the shared reporting system for CommandKit's invocation diagnostics so -parser, integration, and application messages follow the same visibility and -delivery policy. Installation errors occur before an invocation exists and -continue to be returned to the application without automatic printing. - -Supported repetition and last-occurrence overrides are routine decisions. -Repeated singleton flags, including `--verbose --verbose`, may produce debug -detail; repetition alone does not warrant a warning. Repeatable flags retain -their intended accumulation behavior. Add warnings for concrete concerns an -operator can act on, such as a deprecated spelling if deprecation is introduced. -Unknown flags, invalid values, and invalid command paths remain invocation -failures with error diagnostics. - -Start debug instrumentation with routing, alias resolution, verbosity selection, -and handler completion. Other useful candidates can be added where they -explain a consequential decision: - -| Event | Useful detail | -| --- | --- | -| Command-alias resolution | Entered path, intermediate redirects, and final canonical path. | -| Flag-alias resolution | Entered spelling and canonical flag name. | -| Scoped alias selection | A command-scoped mapping took precedence over an application-wide mapping. | -| Verbosity selection | A later occurrence selected a different mode; for `--verbose --debug`, debug wins because it appears last. | -| Help-route selection | A canonical command or alias-only discovery context was selected. | -| Repeated singleton flag | A later occurrence replaced an earlier occurrence, without printing their values. | -| Input preparation | Canonical input validation completed and the handler is starting. | -| Handler completion | Canonical command and the handler's returned classification and status, before final delivery. | - -The handler-completion event describes the handler's result. The final returned -invocation outcome also includes delivery failures and remains authoritative. -Present this event before terminal failure presentation; do not emit a completion -message afterward. - -Use the final selected mode to present earlier parser decisions. Collect the -relevant events during parsing and apply visibility after mode selection: -`--verbose --debug` shows the selection explanation, while `--debug --quiet` -suppresses it. This collection of parser events does not require whole-run -output buffering. - -Debug messages should explain operator-relevant decisions independently of -incidental implementation steps. Use command paths, flag names, and decision -descriptions rather than raw argument or configuration-value dumps. Upstream -libraries retain ownership of their diagnostic detail and disclosure rules. - -## Selected delivery lifecycle and quiet execution (OD-4) - -### Ordering and finalization - -Use synchronous delivery. Present immediate messages and substantive writes in -submission order. After the handler returns: - -1. Deliver eligible deferred messages in queue order, without sorting by severity. -2. Finish ordinary reporting, including any handler-completion debug message and - flushing any CommandKit-owned buffers for ordinary output. Account for failures - discovered during this delivery before preparing the terminal explanation. -3. Present any terminal failure explanation and complete its delivery, including - any CommandKit-owned buffering of that explanation. -4. Close the invocation's reporting facility and return the final outcome. - -Deferred messages remain eligible when the operation fails, subject to verbosity. -Deferral controls timing; applications queue success summaries only after the -relevant operation succeeds. Ordering governs CommandKit's writes; separate -stdout and stderr destinations may be buffered or displayed differently by the -caller. - -CommandKit finalizes automatically. Consumers do not need a separate flush or -finish call. Handler cleanup, including Go `defer` functions, runs before the -handler returns and participates in normal reporting. Applications complete any -reporting goroutines before returning. After finalization, writes and message -submissions return a closed-reporter error and emit nothing. - -Reporter operations within an invocation are safe to call concurrently. -Serialize access to reporting state and delivery so individual messages do not -interleave. Concurrent submissions have no predetermined order; deferred messages -follow the order in which they enter the queue. Multiple writes composing one -application report still require application coordination if they must remain -together. This contract covers operations through one invocation's reporter; -coordination with writes outside that reporter remains caller-owned. - -Finalize any buffers owned by CommandKit. Caller-supplied writers remain -caller-owned; CommandKit does not automatically close them or invoke arbitrary -flushing interfaces. - -Visibility applies when output is emitted. A verbose or debug run may show -informational detail before subsequently failing. Progress and substantive -output may likewise be partially delivered before a failure. Previously written -bytes cannot be withdrawn. Whole-run buffering solely to make failed runs -contain only error output is outside this implementation. - -Keep errors understandable in every mode, including source locations and -related explanatory context. Unrelated warnings and informational messages -remain subject to the selected mode. Apply the selected retention boundary -without accumulating a message history. - -### Rendering failures, write failures, and execution flow - -Distinguish who invokes a renderer and whether its destination failed: - -| Failure source | Responsibility and handling | -| --- | --- | -| An encoder or renderer called directly by the application | The application handles its returned error and chooses the outcome and explanation. | -| A rendering callback invoked by CommandKit | CommandKit handles its returned error as a presentation failure and reflects it in the invocation outcome. | -| A destination rejects a write | CommandKit records the delivery failure and stops further writes to that destination. | - -A rendering failure may occur before any write or while the destination remains -healthy. It does not by itself establish a failed destination. CommandKit can -explain its rendering failure through a working diagnostic destination. These -responsibilities also apply when rendering into a discard destination under -quiet mode. - -Failure to deliver requested output makes an otherwise successful invocation -unsuccessful. Apply this rule to substantive output, Warning, Info, Progress, -Debug, and terminal explanations. Intentional suppression requests no delivery -and is not a delivery failure. - -Standard writer operations return write errors normally. Immediate reporting -methods also expose delivery errors. CommandKit records bounded delivery-failure -information so an ignored write error cannot yield a successful invocation. -Deferred delivery failures appear in the final outcome. - -Apply ADR 0005's outcome rules when presentation fails. For standard outcomes, -return operational failure with status `1`, including when the original outcome -was a usage failure. Preserve the original explanation and any supplied cause; -record the presentation failure separately in `Presentation`. - -Application-defined domain outcomes retain their domain classification. Preserve -an already non-zero domain status. If the domain status was `0`, change the -suggested status to `1` so presentation failure cannot yield a successful -invocation. The application entry point retains control of process exit. - -| Outcome before presentation fails | Final outcome | -| --- | --- | -| Success, status `0` | Operational failure, status `1`. | -| Usage failure, status `2` | Operational failure, status `1`. | -| Operational failure, status `1` | Operational failure, status `1`. | -| Domain outcome, non-zero status | Same domain classification and status. | -| Domain outcome, status `0` | Same domain classification, status `1`. | - -These rules apply to both destination-write failures and rendering failures from -callbacks invoked by CommandKit. Reporting failures remain CommandKit's own -error-handling responsibility. - -Stop writing to a destination after it fails. A substantive-output failure can -receive a terminal explanation through the diagnostic destination if it still -works. If diagnostic delivery fails, return that information to the caller. -Do not redirect diagnostics into substantive output or recursively attempt to -report the reporting failure. - -A failed write does not stop application code. The handler can inspect the error -and return immediately; otherwise, CommandKit records the failure and finalizes -when the handler returns. CommandKit does not use process exit or panic to -interrupt execution. Terminal failure presentation ends normal output. - -### Quiet-mode rendering and suppression - -Initially, run substantive report generation normally with its managed writer -discarding output in quiet mode. This preserves report generation, validation, -and serialization failures while changing presentation. For example, a report -encoder failure still fails the invocation under `--quiet`; the handler remains -responsible for handling errors returned by an encoder it calls. - -Simple suppressed messages need no formatting or destination writes. For richer -report renderers, initially render into a discard destination. Rendering may be -skipped later where doing so preserves the command's operation and failure -semantics. - -Treat suppression as intentional suppression, never as failed or incomplete -delivery. Do not retain suppressed content. Delivery needs only the deferred -queue, reporting lifecycle state, and bounded delivery-failure information, -alongside the temporary parser state and returned explanations described above. - -## Selected consumer reporting API - -Provide one reporting facility per invocation for substantive output, immediate -messages, and end-of-run diagnostics. The consumer API is chosen for its intended -long-term design; with no current consumers, preserving existing API shapes -carries no weight in this decision. - -The following declarations specify the target API and are not yet implemented. - -The reporter owns presentation: output visibility, progress settings, prefixes, -ordering, and delivery bookkeeping. Its views share invocation state, allowing -already-emitted messages, deferred messages, suppression, and write failures to -be coordinated in one place. Helpers may receive the reporter or a narrow -application-defined interface. Domain libraries can continue returning -diagnostic data for the handler to submit, independently of CommandKit. - -Use the reporter as the common diagnostic submission path, replacing the earlier -proposal to split submission between a reporter and `Outcome.Diagnostics`. -Terminal explanations accompany returned outcomes and are delivered through the -same facility. Caller-selected destinations remain at `App.Execute`; handlers -use `Invocation.Reporter()` in place of raw invocation streams. - -### Invocation reporter and structured detail - -```go -func (inv Invocation) Reporter() *Reporter - -type Reporter struct { - // Private invocation state. -} - -func (r *Reporter) Output() io.Writer -func (r *Reporter) RenderOutput(write func(io.Writer) error) error - -func (r *Reporter) Info(message string, details ...Detail) error -func (r *Reporter) Warn(message string, details ...Detail) error -func (r *Reporter) Debug(message string, details ...Detail) error -func (r *Reporter) Progress(message string, details ...Detail) error - -func (r *Reporter) AtEnd() DeferredReporter - -type Detail func(io.Writer) error -``` - -`Output()` supports ordinary writers and encoders. `RenderOutput()` coordinates -an entire rendering operation, captures its rendering error, and prevents other -reporter operations from interleaving with it. Rendering callbacks write through -their supplied writer. Each complete categorized message, including its details, -is likewise coordinated as one reporter operation. - -Rendering callbacks use their supplied writer only during the callback. They may -call rendering helpers that write through it. While a callback is running, it -must not recursively submit messages, queue deferred messages, start another -rendering operation, or write through a separate `Output()` handle belonging to -the same invocation's reporter. Make additional reporter submissions before or -after the callback. A callback must also avoid waiting for another goroutine to -submit through that reporter, since the submission may be waiting for the -callback to finish. - -This boundary applies to `RenderOutput`, immediate and deferred message details, -and terminal explanation details. Ordinary concurrent reporter calls remain -supported and serialized. Keeping each rendering operation together motivates -the boundary; it does not prescribe a lock implementation or promise runtime -detection of recursive calls. - -Message strings are literal; consumers use `fmt.Sprintf` when formatting is -needed. Initially omit parallel `Infof`, `Warnf`, and similar methods. CommandKit -formats the opening message with its category's prefix and a terminating newline. -Optional details follow in order with their formatting preserved. An empty -opening message produces no heading, prefix, or blank opening line, supporting -native renderers that supply a complete, labelled diagnostic: - -```go -_ = report.Warn("Using the default profile") -_ = report.Warn("Some configuration settings need attention.", writeNativeWarnings) -_ = report.Warn("", writeNativeWarnings) -``` - -These are alternative calls; `writeNativeWarnings` represents an -application- or integration-supplied function with signature -`func(io.Writer) error`. No generic logging method or severity enumeration is -needed to submit messages. Applications need not check verbosity before reporting -or implement categories they do not use. - -Immediate methods return rendering or delivery errors, and CommandKit records -the corresponding presentation failure even if the caller ignores the error. -A caller can inspect the returned error and end its handler immediately. - -### Deferred messages - -```go -type DeferredReporter struct { - // Private reference to the same invocation state. -} - -func (r DeferredReporter) Info(message string, details ...Detail) error -func (r DeferredReporter) Warn(message string, details ...Detail) error -func (r DeferredReporter) Debug(message string, details ...Detail) error -``` - -For example: - -```go -_ = report.AtEnd().Warn("Three optional files were unavailable.") -``` - -Copies of the deferred view share invocation state. Its methods return submission -errors, such as attempting to use a closed reporter. Errors encountered during -deferred rendering appear in the final invocation outcome. Progress remains an -immediate streaming operation; substantive output uses the main reporter. - -Copy callback lists when accepting a submission. Callers retain ownership of -data captured by rendering callbacks and keep that data valid until presentation. - -### Terminal outcomes - -Outcome construction requires no invocation state and emits nothing: - -```go -type Explanation struct { - Message string - Details []Detail -} - -type Outcome struct { - Kind OutcomeKind - Status int - Domain string - Cause error - Explanation Explanation - Presentation PresentationResult -} - -func Success() Outcome -func Failure(message string, details ...Detail) Outcome -func Usage(message string, details ...Detail) Outcome -func Domain(name string, status int) Outcome - -func (o Outcome) WithExplanation(message string, details ...Detail) Outcome -func (o Outcome) WithCause(cause error) Outcome -``` - -`Success` returns a successful outcome with status `0`. `Failure` produces an -operational failure with status `1`; `Usage` produces a usage failure with status -`2`. `Domain` constructs an outcome with the supplied application-defined -classification and status. Subsequent presentation failures follow OD-4's rules: -domain classification is preserved, and a zero status becomes `1` if presentation -fails. -`OutcomeKind` retains the success, usage, operational, and domain classifications. - -`WithExplanation` returns a modified outcome value and replaces its terminal -explanation. Explanations belong to failed outcomes; successful summaries use -Info or substantive output. Ordinary application failure, native failure -rendering, and a custom domain failure respectively can be expressed as: - -```go -return commandkit.Failure("Unable to export the requested report.") -``` - -```go -return commandkit.Failure("", writeNativeFailure) -``` - -```go -return commandkit.Domain("validation", 3). - WithExplanation("The document failed validation.", writeFindings) -``` - -The named renderers above have signature `func(io.Writer) error` and preserve the -owning library's safe diagnostic formatting. They run during terminal delivery, -not when constructing the outcome. - -Before terminal delivery, supply the explanation `Command failed.` when a -non-zero outcome has an empty `Explanation.Message` and no non-nil callback in -`Explanation.Details`. This produces `ERROR: Command failed.` in every mode, -including quiet, and becomes the explanation retained in the returned outcome. -Adding the fallback leaves classification, status, and cause unchanged; -presentation failures still follow OD-4's rules. The fallback is based on the -failed outcome and absent explanation, without deriving text from `Cause.Error()`. - -An empty heading with a non-nil detail renderer is an explicitly supplied -explanation. Trust that renderer to provide its content. Do not buffer or replay -it to decide whether the explanation is sufficiently informative, and do not -add the fallback merely because it writes no bytes. - -| Returned outcome | Terminal presentation | -| --- | --- | -| `Failure("")` | Generic fallback, operational classification and status `1`. | -| `Domain("validation", 3)` | Generic fallback, domain classification and status `3`. | -| `Failure("").WithCause(err)` | Generic fallback; the supplied cause remains available without automatic rendering. | -| `Failure("", writeNativeFailure)` | Native explanation without an added generic heading. | - -`Cause` is optional. `WithCause` returns a modified outcome value, replacing the -cause without changing the classification, status, or explanation. For example: - -```go -return commandkit.Failure("Unable to open the configuration file."). - WithCause(err) -``` - -CommandKit presents the supplied explanation and carries the original error -through to the execution caller, which can inspect it with expressions such as -`errors.Is(outcome.Cause, fs.ErrNotExist)`. It does not automatically present -`Cause.Error()` or use the cause to decide success, failure, or message category. -Providing a cause is independent of choosing the terminal explanation; neither -is inferred from the other. Warnings do not require supplying or retaining causes. - -Outcome processing preserves supplied causes, including their existing Go error -identity, when a subsequent rendering or delivery failure occurs. Presentation -failures are recorded separately in `Presentation`. The returned outcome retains -its terminal explanation and optional cause, with other retention limited to the -presentation needs described above. - -### Provider-returned diagnostic data - -Providers return values and diagnostic data without needing a reporter parameter. -Retain `Acquired[T]` with separate fields for independent messages and failure -explanations: - -```go -type Acquired[T any] struct { - Value T - Diagnostics []Diagnostic - Explanation Explanation -} -``` - -`Diagnostics` carries independent, nonterminal messages. `Diagnostic` and -`Severity` remain passive data types for those messages, with each diagnostic -carrying its `Severity` and a `Write func(io.Writer) error` renderer. Adapt their -contracts to the nonterminal reporting categories. Integrations submit the -records through the corresponding reporter methods, including the deferred view -where appropriate. Removing `Outcome.Diagnostics` removes a submission path; -provider-returned records remain available for the integration to submit. - -`Explanation` carries context to attach when the integration returns a failed -outcome. Terminal Error content uses this field rather than an independently -submitted diagnostic. An upstream warning that helps explain the failure may -belong in the explanation; unrelated warnings remain in `Diagnostics` and follow -their ordinary visibility rules. Adapters preserve this distinction and useful -native formatting when translating mixed upstream batches, instead of assigning -the whole batch its highest severity. - -Providers may return acquired data alongside a Go error. The owning integration -chooses the command outcome, attaches any terminal explanation, and decides which -cause to preserve. Returning diagnostic data does not itself emit messages or -select the invocation outcome. Diagnostic renderers follow the same callback -boundary as other details when invoked through the reporter. - -### Presentation observations and closed reporters - -```go -type PresentationResult struct { - Output DeliveryResult - Diagnostics DeliveryResult -} - -type DeliveryResult struct { - State DeliveryState - RenderError error - WriteError error -} - -type DeliveryState uint8 - -const ( - DeliveryNone DeliveryState = iota - DeliverySuppressed - DeliveryComplete - DeliveryIncomplete -) - -var ErrReporterClosed = errors.New("reporter is closed") -``` - -| State | Meaning | -| --- | --- | -| `DeliveryNone` | No content was submitted for this destination. | -| `DeliverySuppressed` | All submitted content was intentionally suppressed, and rendering succeeded. | -| `DeliveryComplete` | All requested delivery completed; other content may have been suppressed. | -| `DeliveryIncomplete` | Rendering or destination writing failed. | - -Retain the first rendering failure and first destination-write failure for each -destination. This provides bounded evidence without collecting an event history. -`Outcome.Presentation` is populated by CommandKit during execution and -finalization; it is observation data, not another submission API. - -The invocation supplies the reporter. Consumers neither construct nor finalize -it. After closure, message submissions and writer operations return -`ErrReporterClosed`, including in quiet mode. The initial API needs no explicit -flush method, transcript accessor, or verbosity checks. Error-conversion helpers -are deferred pending demonstrated value. - -### Application example - -This target-API handler uses an application-owned `exportData` operation that -returns a JSON-encodable result with a `UsedDefaults` field: - -```go -func runExport(inv commandkit.Invocation) commandkit.Outcome { - report := inv.Reporter() - - result, err := exportData(inv.Context) - if err != nil { - return commandkit.Failure("Unable to export the requested data.") - } - - if result.UsedDefaults { - _ = report.Warn("Some optional settings used defaults.") - } - - if err := report.RenderOutput(func(w io.Writer) error { - return json.NewEncoder(w).Encode(result) - }); err != nil { - return commandkit.Failure("Unable to present the export result.") - } - - _ = report.AtEnd().Info("Export completed.") - return commandkit.Success() -} -``` - -Ignored immediate reporting errors are still recorded and can make the final -invocation unsuccessful. The renderer runs in quiet mode against the discard -destination, preserving serialization failures. The deferred summary follows -the selected verbosity policy and describes the completed export operation; -the final invocation outcome also accounts for presentation failures. - -## Upstream diagnostic ownership - -ConfigKit and PromptKit remain authoritative for their diagnostic semantics, -severity, source context, and disclosure rules. Integration adapters expose -those capabilities through the shared CommandKit presentation policy. - -Support consistent reporting of ConfigKit errors and warnings as its adopted -public API evolves. This roadmap does not assume that a future warning API -already exists or prescribe its upstream shape. Integration-owned commands -select the outcome and submit useful native diagnostic detail for presentation. -Core presents those records under the shared policy. Applications using upstream -libraries directly choose how to respond to domain-specific errors and which -outcomes and messages to supply, as for their other operations. - -An integration may receive both a useful substantive report and an operation -failure, as PromptKit smoke testing supports. Preserve the report under the -ordinary substantive-output policy, then present the terminal explanation. -Quiet mode suppresses the report while retaining the explanation. Having a -report does not imply a successful outcome, and returning a failure does not -discard substantive output already prepared for delivery before the terminal step. - -Debug output follows the same upstream disclosure and safe-rendering contracts. -Enabling debug does not authorize secret disclosure or bypass owning-library -rules. - -## Delivery scope - -The completed feature includes the selected reporter and outcome API, ordered -mode/progress selection through normal parsing, shared core presentation, and -both optional integration migrations. Passive provider diagnostics distinguish -independent messages from terminal explanations while preserving native evidence -and rendering. Existing command behavior remains unchanged outside the selected -reporting policy. - -Maintained consumers demonstrate ordinary output, immediate/deferred messages, -silent recovery, explicit warnings, failure after partial output, optional cause -transport, and structured terminal explanations. Integration consumers include -native diagnostic context and useful reports returned alongside failures. - -Behavioral coverage establishes CommandKit-owned parsing, visibility, ordering, -concurrent reporter coordination, closure, presentation observations, and failure -handling. It preserves existing alias, input/state, discovery, native-report, -and upstream-adapter protections without testing upstream domain correctness. -GoDoc, CLI documentation, consumer guidance, internal documentation, and release -notes describe the implemented boundary under their canonical ownership. - -The [implementation plan](https://forge.maximumdirect.net/base-layer/commandkit/src/commit/230187296fae5253cb1773f16c2f1d1a39499ed0/docs/roadmap/implementation.md) defines the concrete migration -steps, focused validation, and completion criteria. This roadmap defines the -target behavior and selected policy choices. - -## Architectural preparation completed - -- [x] Review and accept [ADR 0014](../adr/0014-invocation-reporting.md) as an - extension for shared reporting, retaining ADR 0005's outcome and supplied-error - preservation decisions. -- [x] Align the [architecture policy](../policy/architecture.md) with the reporting - ownership model, including application ownership of domain-specific error - decisions and scope for useful shared error helpers. - -OD-1 through OD-4 and the consumer API signatures are selected. The target end -state includes maintained, executable consumers using those APIs; the -[implementation plan](https://forge.maximumdirect.net/base-layer/commandkit/src/commit/230187296fae5253cb1773f16c2f1d1a39499ed0/docs/roadmap/implementation.md) owns their delivery sequence.