42 KiB
Audit remediation implementation plan
Status: in progress; Stages 1–10 complete.
Baseline: d492c7747175c01a53261206c2b4356e53453621. Before this sprint,
intervening changes recorded decisions and retired the completed older
remediation. The roadmap owns the target and scope,
the catalog owns accepted decisions and finding status, and
its original audit links own defect evidence. The
analysis explains the selected designs.
Instructions for the implementing agent
Once the user approves this sprint, execute Stage 1 through Stage 23 in order under that approval. Stages are bounded work units within one continuous run, not separate prompts, approval gates, or handoffs. Proceed to the next stage without asking for confirmation after a stage, test run, or local commit. Keep progress updates concise and report the assembled result after Stage 23. Stages 11–12 split the cross-module diagnostic change for implementation clarity.
Intermediate stages need not compile independently. If a check depends on a later stage, record it as pending, continue in order, and run it when its prerequisites exist. Stage completion criteria describe what must eventually be evidenced; they do not require stopping for dependent verification before later work can proceed. Do not add temporary compatibility machinery to make an intermediate stage green. The final source must be coherent and validated through the aligned workspace.
Resolve ordinary implementation choices and fix failures within the approved scope without another design round. A real contradiction in the selected target or an unavoidable external blocker may require input; first investigate in-scope remedies and complete remaining independent work. Do not silently change the target, waive a relevant failing check, or claim blocked work is complete.
Read development guidance and the applicable agent, architecture, testing, and documentation policies. Preserve core/backend isolation and application/upstream ownership. This sprint selects no upstream upgrades, toolchain requirement changes, new commands, report formats, arbitrary input limits, or concurrent App dispatch. Keep the existing safe evidence, error identity, presence, and independent comparison-input semantics. The selected public changes need no consumer migration scaffolding. Private helper names and signatures may follow idiomatic implementation; the explicit responsibilities below are the decisions to retain.
Relevant accepted boundaries are ADR 0002, ADR 0004, and ADR 0006. Use repository graph discovery before textual code searches as directed by AGENTS.md.
For every stage, inspect its source and the catalog's linked originals before editing. Reuse existing tests; extend them only for meaningful missing coverage. Consequential correctness fixes need focused regressions that demonstrate the original defect. Refactor tests only where they depend on removed mechanics; do not rewrite behavioral expectations to accommodate accidental changes. Test CommandKit adaptation and coordination, trusting upstream domain contracts. Update the owning GoDoc, CLI, consumer or internal documentation with each change.
Record stage completion and actual verification here. Add completion evidence to the corresponding catalog finding only after its entire remedy is implemented and verified. F21 spans stages 11–12; F24 spans stages 3, 13, and 20. Preserve the original audits and accepted decisions. Commit completed nonempty work units with plain English messages under repository policy; a commit is not a user-review checkpoint. Related stages may form one validated commit when needed. Do not publish or push.
Validation conventions
Use the cached Go 1.27.0 toolchain for cross-module checks. Preserve ignored
go.work and go.work.sum. In the aligned three-module workspace, run focused
tests for the affected package during the stages; select existing test names from
the named test files plus new defect regressions. Use GOTOOLCHAIN=local,
GOPROXY=off, and -mod=readonly for offline checks with cached dependencies.
If the default cache is not writable, use a temporary GOCACHE under /tmp.
Format changed Go files with gofmt. No benchmarks, timing thresholds, complexity
score targets, or new validation framework are needed.
Focused workspace commands run from the repository root. Select the stage's
relevant tests with -run when existing coverage permits; the package targets
are . for core, ./internal/cobra for the adapter, ./internal/alias for the
resolver, ./integrations/ckconfig and ./integrations/ckprompt for integrations.
For example, reporter checks use
GOTOOLCHAIN=local GOPROXY=off go test -mod=readonly -run 'TestReporter|TestHiddenDeferred' ..
Example package targets follow their paths under the corresponding module.
Stage 23 owns the final broad checks. Root ./... excludes nested modules.
Workspace results cover current combined sources; independent checks with
GOWORK=off cover each manifest's selected dependencies. After stage 12,
ckprompt's new helper call cannot compile against its selected ckconfig v0.4.0.
Do not change manifests to invented versions, fabricate sums, or commit local
replacements. Validate combined source in the workspace, and record that released
module alignment remains pending. Temporary external-consumer modules or alternate
module files may use explicit local replacements as additional boundary evidence;
label them as local-source checks. Once appropriate releases exist, dependency
alignment and independent validation follow the release procedure
as separate work. Publication is neither authorized nor a prerequisite here.
Do not wait for those releases or request publication to advance or finish this
source sprint. Record the known independent-module limitation and continue.
Unavailable optional shell prerequisites or race-detector support are evidence limitations, not stage gates. Run the available checks, record what could not run, and continue. Deterministic regression checks remain required; failures in supported checks require investigation and in-scope correction. Revisit checks deferred for internal dependencies before the final report. A genuine inability to run required final verification must be reported as incomplete verification, not converted into a passed check or a request for per-stage approval.
Stage 1 — Retain aggregate smoke cancellation
Complete. The progress-delivery cancellation regression reproduced both
the false success and missing joined cause before the fix. The focused aligned
workspace checks passed: go test -mod=readonly -run 'TestSmokeAggregate|TestSmokeTestCancellation' ./integrations/ckprompt
with Go 1.27.0, GOTOOLCHAIN=local, and GOPROXY=off. Tests cover partial
results with and without a provider error, retained diagnostics and explanation,
omitted callbacks, and cancellation after the final check.
Findings: F01. Primary source: integrations/ckprompt/smoke_command.go.
- In runSmokeAggregate, retain cancellation observed at the later checkpoint when it omits remaining smoke kinds. Join it with prior operation causes; avoid redundantly adding cancellation already retained by an operation.
- Preserve attempted-kind order, acquired reports, diagnostics, prior errors, and explanations. Do not invent reports for unattempted kinds. Keep the existing acquisition/cancellation handling and final reporting path.
- Do not add a blanket late-cancellation failure after all requested work is complete. Distinguish the final completed kind from a stop that omits work.
- Extend smoke aggregate/outcome tests using a progress writer that cancels without reentering the Reporter. Assert a failed partial outcome and errors.Is for cancellation, both with and without an existing provider error. Check omitted callbacks, preserved evidence, and ordinary successful all-kind execution. Keep the ordinary suites offline.
Complete when the progress-delivery cancellation window cannot produce a successful incomplete aggregate or lose cancellation beside another cause.
Stage 2 — Isolate parsed provider-parameter JSON
Complete. Both captured binding replay and aggregate request seed creation
copy nested JSON objects and arrays. The two new boundary regressions failed
against the original implementation; focused request-flag and aggregate tests
passed in the aligned workspace with Go 1.27.0, GOTOOLCHAIN=local,
GOPROXY=off, and -mod=readonly. Nil, empty, integer and decimal values are
covered.
Findings: F02. Sources: ckprompt request_flags.go and smoke_command.go.
- Add one private recursive copier for the known CLI JSON object/array representation. Copy maps and arrays; preserve scalar numeric types and nil versus explicitly empty collections. Do not JSON-marshal to copy values.
- Use it when applying NewExecutionFlags.ExtraParams to a destination and when smokeRequestForKind copies each aggregate execution seed. Retain existing scalar-pointer copies and authoritative application builder replacements.
- Keep this out of generic core ValueFlag/captured-binding machinery. Do not promise cloning of arbitrary application object graphs or repair sharing introduced by application builders.
- Extend request flag and smoke tests: mutate a nested map/array in one request and inspect the next kind's original values; separately apply captured flags to independent destinations using ApplyTo and ApplySuppliedTo, mutate one, and confirm the other retains supplied values. Cover empty/nil and the current CLI numeric representation without retesting upstream preparation.
Complete when both binding replay and per-kind seed boundaries are isolated.
Stage 3 — Close deferred acceptance atomically
Complete. Finalization closes deferred acceptance while detaching its
batch; completion and terminal reporting remain available. The channel-controlled
regression failed against the original code and now passes alongside focused
reporter and hidden-deferred tests, both normally and with -race -count=1, in
the aligned Go 1.27.0 workspace with offline, read-only module resolution. The
old reporter test wrappers were replaced with real selection and finalization.
Findings: F03 and the reporter-lifecycle portion of F24. Source: reporter.go.
- Add a private deferred-acceptance/finalization state distinct from the final closed state. Under the existing mutex, end acceptance and detach the batch in one transition at the start of finalize.
- Make DeferredReporter.enqueue return ErrReporterClosed after that transition, including hidden or empty submissions. Retain pre-cutoff visibility and detail handling. Keep finalizer-owned batch delivery, completion reporting, and terminal explanations usable until final closure.
- Do not repeatedly drain arrivals or wait for application producers. Do not set the general closed flag before internal presentation finishes. Ordinary concurrent Reporter operations retain their existing lifecycle.
- Move tests using the synthetic close/setVisibility helpers to actual
finalize/applySelection entry points, preserving useful assertions. Remove
those obsolete production helpers once their callers have moved. Keep any
concise setup helpers in
_test.go, delegating to the real paths. - Extend reporter finalization tests with channels controlling a destination's
flush boundary. Submit a deferred message while the accepted batch is being
presented; assert ErrReporterClosed. Check pre-cutoff accepted delivery,
completion/terminal ordering and visibility, plus render/write failure
evidence. Avoid sleeps and callback reentry. Run the focused reporter tests
with
-race -count=1where supported, supplementing the required deterministic acceptance/finalization regression. Record unavailable race support and proceed. - Document the cutoff in Reporter/AtEnd GoDoc and relevant reporting guidance.
Complete F03 when acceptance cannot succeed into an abandoned batch. Keep F24 open for the remaining parsing and binding wrappers.
Stage 4 — Reject missing prepared-request results
Complete. Missing prepared requests produce an operational failure while retaining diagnostics and explanations. The public-command regression reproduced the original successful null preview; focused preparation tests now pass in the offline aligned workspace with Go 1.27.0 and read-only module resolution, covering valid results, provider errors, and cancellation as well.
Findings: F04. Source: ckprompt preparation.go.
- After the existing provider-error and cancellation handling in runRequestPreparation, reject a nil acquired.Value with an operational failure. Use the neighboring missing-result handling style; retain supplied diagnostic and explanation evidence and existing error identities.
- Keep core null-report support and valid preview/report-plus-error handling unchanged. Do not add new checks to upstream prepared-request contents.
- Extend preparation tests through the public command: nil result/nil error, valid result, and existing provider error/cancellation paths. Assert failure classification and absence of a successful null preview, with retained diagnostic/explanation evidence. Reuse core's existing null-report coverage.
Complete when empty successful acquisition cannot masquerade as prepared preview.
Stage 5 — Separate show preparation cancellation from rendering failures
Complete. Buffered show preparation carries cancellation outside managed
rendering without emitting the incomplete report. The two-scope regression
failed against the original behavior and now passes, including simultaneous
native rendering failure; focused show, buffered cancellation and write-failure
tests passed in the offline aligned Go 1.27.0 workspace with -mod=readonly.
Findings: F05. Source: ckconfig show.go; reference operations.go's
renderPreparedConfigReport checkpoint pattern.
- Keep buffered effective-document preparation under managed rendering so genuine native-writer/DecodeYAMLReport failures remain presentation evidence.
- Capture cancellation observed by preparation checkpoints separately; return nil from the renderer for a cancellation-only stop, then return configFailure with that cancellation outside it. Do not deliver an incomplete report.
- Preserve genuine native-writing/decoding errors even when cancellation is also visible. Do not discard cancellation identity or alter the distinction between interrupted preparation and cancellation after delivery starts.
- Extend
report_cancellation_test.go: two acquired scopes, first writer emits valid YAML and cancels while returning nil, second writer remains uncalled. Assert no output, cancellation Cause, and no manufactured RenderError or WriteError. Reuse real render/write failure and focused-show coverage.
Complete when cancellation alone is not a presentation error and actual presentation failures remain separately observable.
Stage 6 — Repair the maintained consumers
Complete. The fixture generates Bash, Zsh and Fish scripts; the available
interactive Bash backend and consumer checks passed. The full opt-in commands
reported failures for Zsh and Fish because those shells are not installed;
their interactive behavior remains unverified. The core example's bare and
explicit demo invocations succeeded, and an invalid scenario returned usage
status 2. Checks used Go 1.27.0 with offline, read-only module resolution.
Findings: F06 and F08. Sources: testdata/completion/main.go,
completion_shell_test.go, and examples/core/main.go.
- Rename the fixture's custom
formatchoice flag tochoice; retain its text/yaml choices. It tests application-owned completion, so keep it separate from core's actual format flag. Update the root consumer harness inputs, expected argv, prefix case (--cho), and terminal invocation consistently. Do not rename unrelated backend fixtures or core's reporting flag. - Generate scripts from this fixture to prove App construction succeeds. Run the opt-in consumer and backend shell checks available locally using the developer guide's shell-completion commands. Record missing prerequisites or shells as unavailable; do not count skips as successful interactive checks.
- Guard the example scenario assignment with Supplied.Set, retaining the factory
default and explicitly supplied empty-value validation. Exercise bare
go run ./examples/core report, explicit demo, and an invalid scenario. Reuse example coverage; no new default suite inventory is required for this small example correction.
Complete when the example default works and the completion fixture reaches script/shell validation. Stage 14 relies on this repaired fixture.
Stage 7 — Release finalized reporter destination references
Complete. Finalization clears both borrowed writer references after
capturing presentation, without closing them. Tests cover success, operational
failure, cancellation, late handles and writer ownership; focused reporter tests
pass in the offline aligned Go 1.27.0 workspace with -mod=readonly.
Findings: F07. Source: reporter.go; builds on stage 3.
- After deferred/completion/terminal presentation and capture of observations, mark state closed and clear both direct destination writer references while holding the existing mutex. Retain closed state and errors/observations.
- Do not Close/Flush either borrowed writer. Keep ErrReporterClosed behavior for retained Reporter, Output, and DeferredReporter handles. Return the same error identities; error objects may legitimately retain their own data.
- Extend actual-finalization tests for success, operational failure, and cancellation. Inspect that unnecessary direct references are released and late operations reject without touching writers. Reuse caller-writer ownership and presentation-evidence checks. Avoid GC-timing assertions in ordinary tests; a temporary reachability probe is supplementary only.
Complete when finalized handles no longer keep destinations through those fields, without promising immediate garbage collection or taking ownership of closers.
Stage 8 — Share reporter detail-rendering bookkeeping
Complete. Terminal and ordinary reporting share detail-rendering and error
classification under the existing lock. Focused reporter and hidden-deferred
tests passed in the offline aligned Go 1.27.0 workspace with -mod=readonly.
Findings: F20. Source: reporter.go; follows lifecycle fixes in stages 3 and 7.
- Extract a private helper running under the existing reporting lock to invoke detail callbacks through the managed writer and return render/write errors separately, retaining first errors and their joined evidence as currently done.
- Use it from renderTerminalLocked and submitMessageLocked. Keep headings, visibility/discard selection, leading-message failures, destination delivery observations, and terminal timing in the callers.
- Preserve nil details, order/lifetime, hidden callbacks against io.Discard, sticky destination failures and callback non-reentrancy. Add no locks or configurable rendering pipeline.
- Run focused reporter tests for hidden details, terminal/deferred ordering, joined renderer evidence, independent destination failures and closed handles, including stage 3's regression. Extend only uncovered behavioral cases.
Complete when both paths use one implementation of the delicate detail policy.
Stage 9 — Clarify configuration evidence and narrow explanation providers
Complete. Provider and YAML conversion GoDoc now describe the current
handoff; ExplanationReader only acquires evidence. Focused core YAML conversion
and ckconfig show, explanation, adapter and delivery tests passed in the offline
aligned Go 1.27.0 workspace with -mod=readonly, including a custom Explain-only
provider for path show and all explanation formats.
Findings: F09 and F11. Sources: ckconfig contracts.go, show.go, explain.go,
contracts_adapter_test.go; core report_value.go conversion GoDoc.
- Document EffectiveWriter's single supported safe-YAML-document handoff and link DecodeYAMLReport as the conversion contract owner. Clarify that formatting, comments and framing are not passed through; document unsupported tags, non-string mapping keys and multiple documents at the owning helper as needed. Correct View's description to reflect acquired evidence used to build reports.
- Reduce ExplanationReader to Explain(configkit.Path) (configkit.Explanation, bool). Update its GoDoc and remove writer-only provider stubs/assertions and direct interface-writer test calls across the repository.
- Retain native objects' own writer methods. Do not add compatibility adapters, another writer interface, or restore provider-owned report rendering.
- Reuse acquired-explanation cross-format and delivery-error tests. Ensure a custom provider implementing only Explain works for explanation/path show. Reuse YAML conversion tests and review GoDoc against current conversion rules; do not expand accepted YAML types to accommodate old wording.
- Update affected consumer integration guidance for the selected provider API.
Complete each finding independently: accurate effective-output documentation for F09, and acquisition-only provider wiring with preserved rendering for F11.
Stage 10 — Document the selected flag declaration contract
Complete. FlagMeta describes the existing Unicode long-name grammar,
reserved names and short spellings; rename and alias guidance links to it.
Reviewed against validateBindings, validFlagName, and the accepted catalog
decision. No runtime validation was changed.
Findings: F10. Source: command.go FlagMeta and related rename/alias GoDoc.
- Define long names once with FlagMeta: nonempty Unicode lowercase-letter or digit segments separated by single hyphens. Numeric-only and digit-leading names remain valid. Describe the implemented reserved names help, quiet, verbose, debug, progress and format.
- Describe optional one-byte short spellings, excluding
-and reservedh. Do not apply the long-name lowercase rule to short spellings. - Link RenameFlag and flag-alias helpers to that declaration contract. Retain CLI operator syntax in its existing owner and installation-time error timing.
- Compare prose with validateBindings/validFlagName and the accepted catalog decision. Make no runtime validator changes, normalization, ASCII-only rule, or new tests solely to restate documentation.
Complete when exported guidance accurately states the already selected rules.
Stage 11 — Export the shared ConfigKit diagnostic adapter
Findings: F21, ckconfig portion. Source: ckconfig configkit_adapter.go.
-
Expose the existing configKitDiagnosticsWithHeading responsibility as:
func AdaptDiagnostics(heading string, sources []configkit.SourceInfo, records []configkit.Diagnostic) ([]commandkit.Diagnostic, commandkit.Explanation) -
Route ckconfig's ordinary and comparison-side adaptation through it. Keep any small scope-to-heading constructor that serves a caller; remove the replaced duplicate implementation rather than leaving parallel helpers.
-
Retain captured sources, cloned Primary/Related locations, grouping of error records into explanation details and other records into ordinary diagnostics, within-group order, source legends, native formatting and short-write handling.
-
Document that it returns captured CLI presentation evidence; it does not print immediately, acquire configuration, determine outcomes, or schedule messages.
-
Reuse native adapter tests, extending public helper coverage for mutations of input slices/locations after adaptation and deferred rendering failures where those protections are not already exercised. Assert CommandKit's snapshots and classifications, not ConfigKit's diagnostic formatting algorithm.
Keep F21 open until stage 12 removes the other integration's duplication.
Stage 12 — Adopt shared diagnostics in ckprompt
Findings: F21 completion. Source: ckprompt adapters.go and related tests.
- Make promptKitDiagnostics call ckconfig.AdaptDiagnostics. Preserve its current
heading:
Configuration scopeplus strconv.Quote(scope), optional(side), and the existing colon/newline. Supply that complete heading to the shared helper, whose writer consumes it as provided. - Translate the returned diagnostics/explanation into the existing private acquisition record. Remove the duplicated snapshot/severity partition and writePromptKitDiagnostics implementation and now-unused imports.
- Keep operation-specific fallback explanations, causes, outcomes, scope/side labels, and both integrations' scheduling switches with their callers. No new core dependency or shared module is required.
- Run focused ckprompt acquisition/comparison tests in the aligned workspace, covering available/empty evidence, warning versus error adaptation, side labels, cause retention and deferred writer failure. Verify integration documentation describes the new helper only under ckconfig's CLI ownership.
- Record the independent ckprompt limitation stated in Validation conventions; do not conceal it with committed replacements or conditional fallbacks.
Complete F21 when both callers share one adapter and preserve their context.
Stage 13 — Remove unused parser resource plumbing
Findings: F12 and parsing portion of F24. Sources: execute.go, parser.go,
internal/commandmeta/metadata.go, and internal/cobra/parse.go.
- Remove execution.streams and ParseOptions.Context/In/Out/Err, then remove their unused propagation/default normalization from the adapter. Retain consumed alias-selection options. Normalize invocation streams once with the reporter.
- Keep Invocation.Context and real reporter destinations unchanged. Set explicit internal discard output/error destinations on the backend and preserve local RenderHelp buffering; Cobra defaults must not write to process destinations. Preserve runnable markers, help metadata, fresh sessions and session reuse within one invocation. Remove only settings associated with unused resources.
- Replace App.parse's test-only path with current execution/session preparation in its test and remove the obsolete wrapper. Keep concise test setup in tests.
- Adapt session tests to the smaller options shape, retaining behavioral help, routing, parser-state isolation and context-forwarding coverage. Run core and adapter focused tests; confirm help is delivered through core reporting.
- Update focused internal documentation for the simplified parser boundary.
Keep F24 open until the binding wrappers are handled in stage 20.
Stage 14 — Share internal flag-consumption facts
Findings: F16. Sources: internal/commandmeta/flags.go,
internal/cobra/flags.go, and completion_flags.go; stage 6 is prerequisite.
- Extend the existing neutral helpers with a small consumption operation over
lookup, token and short-cluster position. Return flag identity, attached value
presence separately from its text, next-argument need, and cluster continuation.
Use each caller's existing lookup; keep
--classification/end handling clear. - Migrate interpretFlagTokens, walkCompletionFlags and completionOptionTarget to these facts. Execution retains canonical normalization, entered spellings, occurrences, consumed failure prefixes and backend errors. Completion retains unfinished-word interpretation, pending values, suggestions and insertion text.
- Preserve boolean assignments, attached/next values (including option-looking values), explicit empties, unknown spellings and short-cluster boundaries. Keep caller-specific branches where sharing would require extensive modes.
- Reuse parser, alias/provenance and public completion tests; extend uncovered cases that compare shared grammar and intentionally different missing/partial input behavior. Run available repaired shell checks. Do not add alias discovery, public parser APIs, execution/completion modes, or a replacement backend.
Complete when common grammar mechanics have one owner and caller policies remain clear, with selected syntax and provenance preserved.
Stage 15 — Memoize each context's flag-alias graph
Findings: F13. Source: flag_aliases.go.
- Replace independent suffix walks with context-local visitation and memoized terminal results, including unavailable endpoints. Resolve canonical spellings before following a mapping of that spelling. Cache token resolution without conflating a source's collision check with its target's resolution.
- Process the existing sorted sources, resolving each mapping's target before the active-source collision check. Keep scoped overrides, inactive globals, scoped missing-target failures and useful participating-cycle diagnostics. Maintain an active traversal stack to identify cycles; no hop cap is needed.
- Keep the cache invocation/snapshot preparation local to its effective context, revalidating on registration. Do not share results across different contexts.
- Run existing flag-alias chain, cycle, duplicate/scope and discovery tests; add representative shared-suffix/inactive-endpoint coverage only if missing. Review loops to confirm each target suffix is resolved once per context. Existing sorting remains; no benchmark or whole-installation bound is required.
Complete when repeated suffix traversal is removed without routing changes.
Stage 16 — Reuse the resolver tree for prefix discovery and help
Findings: F14 and F15, one coordinated change. Sources:
internal/alias/resolver.go, flag_aliases.go, and help_view.go.
- Add two narrow internal read-only tree operations: enumerate distinct nonempty proper source prefixes, and find mapping sources strictly below a supplied prefix. Reuse trie nodes and their captured paths; keep nodes private and return owned paths/mappings so consumers cannot mutate the resolver.
- For enumeration, visit each eligible tree node once rather than rebuilding each declaration's prefixes. A node may itself end an alias and have children; leave exact-alias exclusion to the existing classification. Apply canonical, exact-source and canonical-operand-space exclusions once per distinct prefix. Update discoverFlagContexts's consumed resolver shape accordingly.
- For descendant lookup, locate the supplied prefix branch and enumerate only descendants, excluding that node's mapping. Use it for every existing ResolutionPaths entry in routeHelpAliases. Keep root help's complete catalog when needed, composed-path authoritative resolution, canonical-target checks, longer overrides, suffix deduplication and sorted presentation.
- Reuse routing snapshot lifetime, without another index or result cache. Do not replace the resolver's selected termination proof or longest-prefix rules.
- Check shared deep prefixes, alias chains with no descendant output, exact aliases with children, longer overrides, canonical operand exclusions and post-registration refresh using existing alias/help/discovery coverage plus missing focused cases. Inspect traversal to establish reduced repeated work; assert results rather than timing or private call counts.
Record evidence separately for F14 preparation and F15 repeated help lookup. Neither finding closes merely because the new tree methods exist.
Stage 17 — Format declaration paths only for diagnostics
Findings: F22. Source: command.go collectDeclarationIssues.
- Traverse with one scratch append/truncate path. Construct an owned formatted label only when emitting a retained issue or root-only-placement diagnostic. Do not capture mutable scratch slices in stored errors or declarations.
- Preserve child/issue order, error wrapping and identity, and absent/invalid declaration handling. Keep other capture/installation phases unchanged.
- Reuse registry/declaration tests for invalid children, root-only placement, retained errors and valid nested trees. Review that the successful walk no longer copies/formats every ancestral path. No timing test or new installation performance guarantee is required.
Complete when diagnostic scratch work is proportional to the traversal and actual emitted paths rather than every valid full path.
Stage 18 — Separate configuration operation preparation
Findings: F18. Source: ckconfig input.go and its command builder.
- Extract operation-specific option checks, shared scope/capability selection, and independent comparison-side preparation into small private functions over existing types. Keep an explicit orchestration function and ordinary branches.
- Extract cohesive flag groups where they clarify command construction. Preserve bare explain help, supplied-state distinctions, full aggregate capability preflight, binding application, and both input checks before shared state construction/acquisition. Do not invent a plan hierarchy or rule registry.
- Run existing operation-preflight, help/no-loading, scope-selector and comparison preparation tests. Confirm independently initialized equal selections and failure classifications remain correct. Retain stage 5's show protection.
Complete when ordinary and comparison paths can be followed separately without changing the selected lifecycle or adding machinery solely to shorten functions.
Stage 19 — Separate configuration suite capture responsibilities
Findings: F17. Source: ckconfig family.go captureSuite.
- Extract cohesive scope capture/validation and selector capture/attachment; make operation binding unions and discovery inventory construction explicit. Reuse preparedSuite/preparedScope and keep related loops together.
- Retain declaration copies, scope order, accumulated error order, selector and binding identity, comparison requiredness, empty-suite handling and availability. Setup remains metadata-only: no input factories, state or provider acquisition.
- Run family wiring/capture, operation selector and comparison contract tests. Reuse mutation-after-capture and help/discovery checks. Avoid new indexes or intermediate records merely to split the function into phases.
Complete when each capture responsibility has a clear place and behavior holds.
Stage 20 — Simplify typed preparation and retire remaining test wrappers
Findings: F19 and completion of F24. Sources: binding.go, flag_values.go,
parser.go and related tests; review reporter cleanup from stage 3 as well.
- Extract entered-spelling conversion-error attribution and operand preparation from prepareInputWithOccurrences. Keep flag preparation, ordinal identity and dense reconstruction together, in the orchestration function if appropriate.
- Preserve conversion before input construction, ordinary/ordered/argument setter order, fallback versus parser-log ordering, deferred required checks, original binding identity, supplied states, error identity and the existing replay heap merge. Do not introduce a new state container or replay framework.
- Move tests from prepareInput/prepareInputWithSpellings to occurrence-aware
preparation and remove those obsolete production wrappers. Any small setup or
read-only observation helpers used solely by tests belong in
_test.go. - Confirm all F24 targets: reporter setVisibility/close, App.parse and both preparation wrappers have been retired without losing useful assertions. Use graph call traces supplemented by text references where necessary; absence from one graph query alone is not proof of no callers.
- Run binding conversion/error, typed composition, ordered occurrence, nested capture, reversed/subset/duplicate selections and both replay-method tests. Reuse actual reporter lifecycle and routed-parser checks from prior stages.
Complete F19 for the bounded extractions and F24 for all obsolete entry points; record these outcomes separately.
Stage 21 — Decode native diff paths without revalidation
Findings: F23. Source: ckconfig diff_report.go and diff report tests.
- Change the private token helper to accept configkit.Path. Split its canonical
JSON Pointer representation, preserving root versus the empty-key token.
Decode
~1and~0in one pass, for example with strings.NewReplacer.~01must become~1, never/. - Remove arbitrary-string validation branches/error returns and corresponding unreachable malformed-string tests. Preserve real snapshot decoding errors, configkit.ParsePath for operator input, and the selected concise diff projection.
- Reuse diff report token/render coverage for root, empty/numeric/dot/percent/ Unicode/slash/tilde keys, present null/deletion, structural values and malformed present snapshots. Keep upstream path validity owned by ConfigKit.
Complete when native-path adaptation retains needed translation without duplicate validation or a new public pointer utility.
Stage 22 — Correct current documentation and historical navigation
Findings: F25, F26 and F27.
- In ADR 0006's Status section, explicitly mark remaining pre-implementation lifecycle wording as historical and point current contracts to GoDoc and the CLI reference. Preserve the accepted decision text rather than rewrite it or create a replacement ADR. Check readers no longer infer reporting is pending.
- In README retain brief status/module orientation and a link to the consumer guide's module-selection section. Remove the duplicate exact compatibility matrix; keep the consumer guide as its owner. No dependency changes follow.
- Add
integrations/ckprompt/docs/releases/errata.mdwith a brief forward-only correction for v0.2.0's consumer-guide section link. The corrected target is the existing pinned v0.2.0 guide with fragment#promptkit-configuration-definitions-and-requirements. Link this correction from the developer guide's completed-history navigation so it is discoverable. Preserve the old note, immutable tag and hosted release contents. - Verify the corrected fragment against the local tagged Git object, all new local paths/fragments, and the semantic claims of the edited prose. Run documentation whitespace checks. Do not republish or contact hosted services.
Complete when present guidance and useful historical navigation have clear owners.
Stage 23 — Verify the assembled sprint and record completion
Findings: all F01–F27; no new feature work.
-
Review the full diff against this baseline and all roadmap completion criteria. Verify every finding has its remedy and relevant evidence, including both F14/F15 costs, both F02 boundaries, all F24 wrappers, and both F21 callers. Check tests added for P2 defects fail against their original behavior and exercise the actual public/package lifecycle; avoid exact incidental wording.
-
Run the full aligned current-source workspace suites from the root:
GOTOOLCHAIN=local GOPROXY=off go test -mod=readonly ./... ./integrations/ckconfig/... ./integrations/ckprompt/...Run focused reporter race checks where supported for the final reporting changes, recording unavailable support. Broaden or repeat tests only for changed content, failures or unresolved concerns.
-
Run independent suites from the root and each integration directory with
GOWORK=off GOTOOLCHAIN=local GOPROXY=off go test -mod=readonly ./...when their selected dependencies support the changes. Record exact selections. After F21, explicitly record ckprompt's expected missing-helper limitation against ckconfig v0.4.0; it is not a workspace regression and is not a passed independent check. Do not silently switch dependencies for that claim. -
Exercise representative maintained consumers: the core reporting default, ckconfig ordinary/all-scope show and two-sided diff, and the composed ckprompt prepared preview and fixture-backed aggregate smoke operation. Use the developer guide and example READMEs for actual invocations. Run available opt-in shell checks following repaired fixture/grammar changes; record skips and environment limits accurately. No live model/service or credential use.
-
Confirm owning GoDoc/CLI/consumer/internal docs match the final code; validate local Markdown links and fragments, pinned historical links through Git, provenance and absence of template residue. Run tracked and staged Markdown whitespace checks from the developer guide. Ensure source is gofmt-clean and ignored workspace files, upstream versions and Go requirements were preserved.
-
Record each finding's completed source work and actual checks in the catalog, stage completion here, and target completion in the roadmap. Clearly preserve pending release/dependency alignment as release work in the existing future record; source remediation must not be described as independently released. Do not retire unresolved findings or mark unavailable checks passed.
-
Review status, stage only sprint changes and commit remaining completed units with plain English messages. Report the final source result, validation, pending release alignment, commit identifiers and worktree state. No release, push, or publication is part of this sprint.
Complete when the targeted source state and its verification are evidenced, with external release alignment explicitly distinguished from source completion.
Open Questions
None. Product, ownership and remediation choices are resolved in the catalog and roadmap. Publication versions remain separate release work. Routine private helper signatures and test organization are implementation choices within the boundaries above, not blockers requiring another design round.