Files
promptkit/docs/roadmap/implementation.md

15 KiB

Profile And Prompt Listing Implementation Plan

Implement the listing roadmap in the numbered order below. Each stage is scoped for one Luna coding-agent prompt and should leave a compiling, tested unit. All four stages are complete.

This replaces the completed performance plan, preserved in Git history. For older inspection-roadmap references to this pathname, the completed inspection plan is also preserved. These historical plans are not work for this sprint.

Baseline And Working Rules

Planning baseline: 7325a34c070c77c4784ab76c916fc8a4d79b5c46. There are no listing methods yet. Configuration already captures profiles in loaded.indexedProfiles and prompts in loaded.prompts, after the final ConfigKit handoff. internal/engine.Engine currently retains the runner and the operator inspection view.

Start with development, then read the applicable agent, architecture, testing, and documentation policies. Reuse unchanged documents already read. Consult internal sources, the component overview, the consumer guide, existing inspection GoDoc, and the configuration ADR.

For each stage: inspect the current worktree, preserve unrelated edits, implement only its scope, format changed Go files, run focused verification, review the diff, update this plan's stage status with brief evidence, and commit the nonempty completed unit with a plain-English message. Report any blocked validation honestly. Publication and release preparation are separate tasks.

Use the existing module versions. No dependency upgrade, configuration-format change, execution refactor, new public package, or release-tool change is needed. The storage and wiring choices below are implementation decisions, not permanent consumer invariants. Tests protect outcomes, not private helper names, clone counts, allocation counts, or timing thresholds.

Selected Public Contract

Use these root-package declarations:

type PromptIdentity struct {
    ID      string
    Version string
}

func (e *Engine) ListProfiles(ctx context.Context) ([]string, error)
func (e *Engine) ListPrompts(ctx context.Context) ([]PromptIdentity, error)
  • List final effective captured identities, including maintained and consumer profiles. Inherited profiles keep their own keys. Return each profile ID and each prompt ID/version pair once; omit historical-only contributions.
  • Preserve literal spelling. Sort profiles lexically by ID; sort prompts lexically by ID, then version. Do not interpret versions as SemVer or select a preferred version. Existing omitted-version inspection remains unchanged.
  • Results are caller-owned. Concurrent listing and other supported engine operations cannot mutate the captured inventory through these results.
  • Empty inventories succeed. Nil and zero-value public engines return an error matching ErrInvalidConfig, consistent with existing facade checks.
  • For a valid engine, context cancellation/deadline errors retain their standard identity. Return no partial inventory on error. Follow existing inspection precedence: validate the public engine before delegating context handling. Check context before and after the synchronous copy/conversion work; do not promise immediate interruption or deterministic precedence in a cancel/return race. No new nil-context behavior is selected.
  • PromptIdentity follows other inspection values: no stable JSON representation is promised. Do not add custom serialization or pin nil versus nonnil empty slices in GoDoc or tests.
  • Membership is not execution readiness. Listing performs no per-item full inspection, target validation, credential resolution, resource reads, rendering, admission, generation, or ConfigKit provenance traversal.

The roadmap owns scope and intent; implemented GoDoc will own the exact API. Do not add backend listing, filters, pagination, reloads, runtime mutation, provider discovery, new caller limits, or stronger catalog availability promises.

Stage 1 — Capture And Read Identity Inventories

Status: Complete (2026-10-09). Verified with go test ./internal/configuration ./internal/domain and go vet ./internal/configuration ./internal/domain. Adapter tests cover effective sorted identities, literal keys, partial profiles, empty loads, caller-owned results, and canceled contexts.

Scope: internal/domain, internal/configuration, and focused adapter tests.

  1. Add an internal domain.PromptIdentity with only ID and Version strings. Keep it separate from the eventual public declaration; no public type alias.
  2. Add private profile-ID and prompt-identity slices to loaded. Populate them once at the end of load, after both materializePrompts and buildExecutionProfiles have succeeded. Enumerate the finished indexedProfiles keys and the finished prompts ID/version keys, not ConfigKit metadata or raw contributions.
  3. Build the ordered slices with existing sortedKeys or standard-library sorting. Flatten actual prompt versions; an ID with no versions contributes no prompt identity. Store only strings, not targets, definitions, or histories.
  4. Add ListProfiles(context.Context) ([]string, error) and ListPrompts(context.Context) ([]domain.PromptIdentity, error) on loaded, in a focused internal/configuration/listing.go. Check context, copy the captured slice, check context again, and return the independent result. Ordinary slice copying suffices because elements contain only strings. Reads are linear in returned inventory size and require no repeated sorting.
  5. Add adapter tests using the real Load and existing mapping helpers. Cover a small unsorted profile/prompt fixture, multiple versions such as "10" and "2", literal whitespace/slash keys, a partial profile, and an empty load. Mutate returned entries and verify subsequent lists are unchanged. Cover an already-canceled context for each method without timing assertions.

Do not change existing lookup methods or add inventory mutation. Keep construction complexity proportionate; there is no benchmark gate.

Verify: format changed files; run go test ./internal/configuration ./internal/domain and go vet ./internal/configuration ./internal/domain.

Done when: successful loads retain sorted identity-only inventories and return owned lists without rereading ConfigKit or requiring runnable targets.

Stage 2 — Wire The Public Facade And Its Basic Contract

Status: Complete (2026-10-09). Verified with go test ./internal/engine ., go vet ./internal/engine ., and git diff --check. External contract tests cover both listing methods, inspection of listed identities, invalid engines, cancellation, and expired deadlines. Depends on Stage 1.

Scope: internal/engine, root API/conversion, and focused facade tests.

  1. Add a private, consumer-owned inventory interface in internal/engine containing just the two listing methods from Stage 1. Store the loaded snapshot through this interface during New, alongside the existing operator inspection view. Delegate new internal engine methods to it. There is no need to extend execution repository interfaces or the use-case runner, add optional capabilities, or provide a full-inspection fallback.
  2. Add listing.go at the module root, containing public PromptIdentity and the two methods. Apply the same e == nil || e.internal == nil check as existing inspection methods, returning ErrInvalidConfig with useful context. Map delegated errors through mapPublicError.
  3. Return the already-owned profile slice. Convert internal prompt identities into a separate public slice by copying their two strings. Check context after conversion so a detected cancellation yields no partial result. Do not export an internal type in any public signature.
  4. Write concise GoDoc covering effective membership, exact lexical ordering, all prompt versions, captured-state behavior, caller ownership, concurrent use, empty success, nil-engine and context errors, and absence of readiness checks or external work. Identifiers may be sensitive application data; do not describe these lists as automatically safe for disclosure.
  5. Add external-package basic tests in listing_contract_test.go: a usable public engine lists a configured profile and two exact prompt versions; returned identities can be inspected; nil/zero engines match ErrInvalidConfig; canceled and expired contexts preserve context identity with no partial inventory. Use real constructors and synthetic configuration.

Verify: format changed files; run go test ./internal/engine . and go vet ./internal/engine .. Existing root boundary tests must continue to pass; do not weaken them.

Done when: consumers can call both methods through the root facade and receive independent public values with the selected error behavior.

Stage 3 — Verify Effective Membership, Ownership, And Concurrent Use

Status: Complete (2026-10-09). Verified with go test -race ./internal/configuration ./internal/engine . and git diff --check. External tests cover layered effective membership, maintained profiles, empty inventories, caller ownership, concurrent listing and inspection, captured sources, and the absence of execution work. Depends on Stage 2.

Scope: focused additions to the external-package listing contract tests. Production edits are limited to defects those tests reveal.

  1. Build one representative layered engine with a consumer base profile, an inherited child, an overlay of the same profile ID, and multiple prompt versions. Verify effective identities, no duplicate overlay entry, and child/base identities remaining distinct. Inspect one listed identity to confirm it resolves to the effective captured definition.
  2. Verify maintained profiles are included without asserting a complete catalog inventory or a specific upstream model. The two PromptKit-owned standard profile names may serve as stable membership examples under the existing release policy; other expectations should use fixture-controlled identities.
  3. Exercise empty effective inventories through a public engine: a final main mapping with profiles: null and prompts: null clears the sections above the catalog underlays. Assert successful zero-length lists, not a particular nil/empty representation. This also checks that lower-layer historical profile paths are not returned. Use existing ConfigKit semantics; add no source-validation pass or special listing-only removal rule.
  4. Mutate elements in both public results and relist to verify independent storage across calls. Add one bounded concurrent test that lists and mutates independent results while other goroutines list/inspect the same captured engine. Coordinate deterministically; avoid sleeps or shared test-owned mutable result slices.
  5. Cover snapshot/no-execution behavior with a compact fixture: construct from an application filesystem, then remove/change its content after construction and verify listing still reports the captured identities. Inject existing model-client and artifact-reader stubs that fail if invoked. Include a partial profile or a named but unavailable API-key environment variable; listing succeeds without provider readiness. Do not add new extension points or exact private-call-count assertions solely for these tests.

Place effective-loading/ordering mechanics in Stage 1's adapter tests and public assembled outcomes here. Avoid duplicating every loader, inheritance, or existing inspection case. No execution/network call is required to prove identity discovery.

Verify: go test -race ./internal/configuration ./internal/engine ..

Done when: public tests demonstrate effective—not historical—membership, independent results, concurrent safety, and listing without execution work.

Stage 4 — Document And Verify The Completed Feature

Status: Complete (2026-10-09). Verified with the full offline race suite, repository-wide vet, maintained consumer examples, changed documentation-link checks, and git diff --check. The listing roadmap and canonical consumer, format, and internal documentation now describe the implemented API. Depends on Stage 3.

Scope: owning documentation, final review, and complete offline verification.

  1. Update doc.go to include listing in its operation and concurrent-use summaries, and PromptIdentity among values without stable JSON contracts. Keep exact behavior in the method/type GoDoc from Stage 2.
  2. Add a short consumer-guide discovery example listing identities and then inspecting a selected entry. Distinguish listing from configuration history and from execution readiness; link to the exact GoDoc. A new runnable example project or CLI is unnecessary.
  3. Update docs/internal/sources.md and docs/internal/overview.md for captured inventories and direct internal-engine delegation. The execution runner has not acquired a listing responsibility. Add a brief format-reference link to the listing guidance where it currently introduces inspection, without changing configuration semantics.
  4. Repair old implementation.md links in the completed performance.md, inspection.md, and historical sections of remediation.md to their respective history links at the top of this plan. Preserve finding statuses and recorded evidence; do not retire unrelated roadmaps or imply their work remains pending. This is navigation repair, not another feature.
  5. Review the entire feature diff against the listing roadmap and selected contract. Confirm only effective indexes are used; no runtime imports of ConfigKit, provenance traversal, readiness checks, resource reads, new limits, or stable serialization promises have been introduced.
  6. Run the complete offline race suite and full vet, plus maintained examples if changed or affected. Validate changed documentation links and git diff --check. Reuse successful focused checks for unchanged content.
  7. Mark the listing roadmap and this plan complete with concise verification evidence. Commit the completed unit. Leave release notes, roadmap retirement, tags, and publication for the later release-preparation task.

Use the existing local Go installation and prepared module cache. Suggested final commands (not new release gates):

GOTOOLCHAIN=local GOWORK=off GOPROXY=off GONOPROXY=none GOSUMDB=off \
  go test -race -vet=off -mod=readonly -count=1 ./...
GOTOOLCHAIN=local GOWORK=off GOPROXY=off go vet -mod=readonly ./...
git diff --check

Done when: all four stages are verified, listing is documented by its canonical owners, and the feature is ready for ordinary release preparation.

Open Questions

None. The selected signatures, result shape, ordering, ownership, error behavior, implementation boundary, and verification scope are specified above.