268 lines
15 KiB
Markdown
268 lines
15 KiB
Markdown
# Profile And Prompt Listing Implementation Plan
|
|
|
|
Implement the [listing roadmap](listing.md) 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 pending.
|
|
|
|
This replaces the completed performance plan, preserved in
|
|
[Git history](https://gitea.maximumdirect.net/eric/promptkit/src/commit/7325a34c070c77c4784ab76c916fc8a4d79b5c46/docs/roadmap/implementation.md).
|
|
For older inspection-roadmap references to this pathname, the completed
|
|
[inspection plan](https://gitea.maximumdirect.net/eric/promptkit/src/commit/481e2d494c5a4e8b7f3a2a6f1cceaeb3f7c71d05/docs/roadmap/implementation.md)
|
|
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](../development.md), then read the applicable
|
|
[agent](../policy/agents.md), [architecture](../policy/architecture.md),
|
|
[testing](../policy/testing.md), and
|
|
[documentation](../policy/documentation.md) policies. Reuse unchanged documents
|
|
already read. Consult [internal sources](../internal/sources.md), the
|
|
[component overview](../internal/overview.md), the
|
|
[consumer guide](../consumers/pkg-promptkit.md), existing inspection GoDoc, and
|
|
the [configuration ADR](../adr/0001-configuration-boundary.md).
|
|
|
|
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:
|
|
|
|
```go
|
|
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: Pending.** 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):
|
|
|
|
```sh
|
|
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.
|