241 lines
14 KiB
Markdown
241 lines
14 KiB
Markdown
# Go-Based Example Testing Implementation Plan
|
|
|
|
Implement [example-testing.md](example-testing.md) as one end-to-end sprint.
|
|
Each sequential stage below is a single prompt-sized assignment for a Luna
|
|
coding agent. The feature roadmap owns intent and scope; this document owns
|
|
the implementation steps and local design choices.
|
|
|
|
## Baseline And Working Rules
|
|
|
|
The reviewed baseline is `79dfd97afa2acc3cbf1ba6936b3a11b116702cf4`:
|
|
Go 1.27.0, module `go.maximumdirect.net/promptkit`, ConfigKit v1.0.0,
|
|
ReleaseKit v0.8.0, and three maintained programs under `examples/go-library/`.
|
|
There are no Go tests alongside those programs. `scripts/check-examples.py`
|
|
executes them and checks JSON results through the sole custom ReleaseKit hook.
|
|
`scripts/test-release.py` is a separate development-only diagnostic with a
|
|
synthetic replacement for that hook.
|
|
|
|
This plan replaces the completed ConfigKit migration plan. Its historical
|
|
instructions remain available with
|
|
`git show 79dfd97:docs/roadmap/implementation.md`; they are not assignments for
|
|
this sprint.
|
|
|
|
Read `docs/development.md` and the applicable agent, architecture, testing,
|
|
documentation, and release policies before work. Preserve unrelated changes.
|
|
Use the module-compatible local Go toolchain and prepare caches before offline
|
|
validation. No dependency, Go-minimum, consumer API, or source/hosted-release
|
|
workflow change is needed.
|
|
|
|
Intermediate stages may be incomplete or temporarily inconsistent: there is no
|
|
requirement to introduce compatibility scaffolding, compile every intermediate
|
|
state, or stop for human review. Finish all stages before claiming completion.
|
|
Run focused checks when useful; if a check depends on later work, record that
|
|
dependency rather than claiming it passed. Do not publish or contact providers.
|
|
Follow the agent policy for focused local commits.
|
|
|
|
## Implementation Choices
|
|
|
|
- Put tests in `main_test.go` with `package main` beside each example. Test
|
|
actual workflow and encoding paths directly, not reconstructed engine setups.
|
|
- For preparation and execution, extract
|
|
`run(ctx context.Context, exampleDir string, out io.Writer) error`.
|
|
`exampleDir` is that example's resource directory, not an application-wide
|
|
configuration root. Use `filepath.Join` to locate its existing files.
|
|
Each `main` passes its existing repository-relative example directory and
|
|
`os.Stdout`; tests pass `"."` and a buffer from the package directory.
|
|
- Observation already has `run() (summary, error)` and embedded assets. Keep
|
|
that workflow and add a small `execute(out io.Writer) error` which calls it
|
|
and encodes its result. Both `main` and its test use `execute`.
|
|
- Keep stderr reporting and nonzero exit handling in the thin `main` functions.
|
|
Workflow helpers return errors instead of exiting. Preserve current successful
|
|
summaries and existing example-side semantic checks.
|
|
- Use one representative happy-path workflow test per example to carry the
|
|
existing useful assertions. Decode JSON independently of production summary
|
|
tags: test-local structs or maps are sufficient. Check presence where a
|
|
missing field could masquerade as an expected false, zero, or null value.
|
|
Do not reject harmless extra fields, require exact JSON formatting, or add
|
|
whole-document golden snapshots.
|
|
- Use buffers and explicit resource directories rather than redirecting global
|
|
stdout or changing the process working directory. These are local design
|
|
choices for these examples, not new library contracts.
|
|
- No subprocess example test is needed for this baseline: the small extractions
|
|
cover the workflow and output without complicating the examples. Verify the
|
|
actual `go run` commands once during integration instead of adding redundant
|
|
executable tests to every default run.
|
|
|
|
## Stage 1: Test The Execution Example In Go
|
|
|
|
Scope: `examples/go-library/run/main.go` and a new `main_test.go` there.
|
|
|
|
1. Extract its current engine construction, injected deterministic client,
|
|
request, and summary encoding into `run(ctx, exampleDir, out)`. Resolve
|
|
`prompt.yaml` relative to `exampleDir`. Pass the supplied context to
|
|
`engine.Run` instead of creating another background context there.
|
|
2. Return construction, execution, and encoding errors. Keep the existing
|
|
indented JSON output. Make `main` call this helper with a background context,
|
|
`"examples/go-library/run"`, and stdout; retain stderr/exit handling at that
|
|
boundary. Remove obsolete error-exit helper code if no longer used.
|
|
3. Add `TestRunExample` calling the helper with `t.Context()`, `"."`, and a
|
|
`bytes.Buffer`. Decode and assert the current output:
|
|
- `output`: `Ada finished the migration review.`;
|
|
- `is_valid`: true;
|
|
- `validation_status`: `passed`;
|
|
- `model`: `offline-model`;
|
|
- `total_tokens`: 18.
|
|
4. Keep this local to the example: no new shared test framework or public API.
|
|
|
|
Validation: format changed Go files and run
|
|
`go test ./examples/go-library/run`. Confirm the test executes the workflow,
|
|
not just the summary type. These expected values describe this fixture only.
|
|
|
|
Completion: extracted the execution workflow and JSON encoding into a helper
|
|
with explicit context, resource directory, and writer. The focused Go test
|
|
executes the workflow and checks its summary; it passed on Go 1.27.0.
|
|
|
|
## Stage 2: Test Preparation With Explicit Resource Context
|
|
|
|
Scope: `examples/go-library/prepare/main.go` and its new `main_test.go`.
|
|
|
|
1. Extract the current composition, inspection, validation, preparation, and
|
|
summary encoding into the chosen `run(ctx, exampleDir, out)` helper. Replace
|
|
the three hard-coded file prefixes with paths under `exampleDir`; retain
|
|
the existing collections, source ordering, imports, and later override.
|
|
2. Preserve the inline checks for the discovered required `note` input, the
|
|
override explanation, and the effective timeout. Return their errors.
|
|
Keep those checks readable in the example instead of duplicating their
|
|
complete machinery in the test. Use the supplied context for engine calls.
|
|
3. Keep `main` callable through the existing repository-root command by passing
|
|
`"examples/go-library/prepare"` and stdout. Retain current indented encoding
|
|
and error presentation while removing exits from the workflow helper.
|
|
4. Add `TestPrepareExample` using the helper, package-local resources, and a
|
|
buffer. Assert these retained JSON results:
|
|
- `prompt_id`: `support/prepare`; `selected_profile`: `support/fast`;
|
|
- `model`: `offline-model`; `message_count` greater than zero;
|
|
- `profile_timeout_seconds`: 30;
|
|
- `namespaces`: `review`, then `support`;
|
|
- `collections`: review with an explicit null `release_version`, followed
|
|
by support with `release_version` equal to `1.4.0`;
|
|
- `scoped_prompts`: `support/prepare`; `review_prompts`: `review/check`.
|
|
Preserve the distinction between an omitted member and the explicit null
|
|
currently checked for the review collection.
|
|
|
|
Validation: format and run `go test ./examples/go-library/prepare`. Ensure
|
|
imports and relative content still resolve from their contributing sources;
|
|
do not rewrite configuration fixtures merely to bypass path handling.
|
|
|
|
Completion: the preparation workflow accepts an explicit context, example
|
|
directory, and writer while preserving its inline checks and source contexts.
|
|
Its Go test verifies the retained summary, including explicit null collection
|
|
metadata, and passed on Go 1.27.0.
|
|
|
|
## Stage 3: Test The Observation Example And Its Output
|
|
|
|
Scope: `examples/go-library/observe/main.go` and its new `main_test.go`.
|
|
|
|
1. Retain its existing `run`, embedded files, scripted HTTP transport, event
|
|
recorder, and application-owned assessment logic.
|
|
2. Extract only the workflow/encoding coordination into `execute(out)` as
|
|
specified above. It returns workflow or encoding errors. Make `main` call
|
|
it with stdout and retain the current stderr/exit behavior. Do not redesign
|
|
the transport or add a new client abstraction.
|
|
3. Add `TestObserveExample` calling `execute` with a buffer. Decode and assert:
|
|
- `proposal_attempts`: 2; `proposal_transient_retries`: 1;
|
|
- `proposal_usage_complete`: false;
|
|
- `assessment_attempts`: 1; `assessment_transient_retries`: 0;
|
|
- `assessment_outcome`: `accepted`.
|
|
Missing false/zero fields must not silently pass. Run the workflow once per
|
|
test rather than separately recomputing typed and encoded results.
|
|
|
|
Validation: format and run `go test ./examples/go-library/observe`, followed
|
|
by `go test ./examples/go-library/...`. Existing deterministic collaborators
|
|
remain the network boundary; no live provider or credential is needed.
|
|
|
|
Completion: observation workflow encoding now goes through a writer-based
|
|
helper shared by the executable and its Go test. The test checks all retained
|
|
summary fields, including false and zero presence; the observation and complete
|
|
example package tests passed on Go 1.27.0.
|
|
|
|
## Stage 4: Remove The Custom Release Hook And Adapt Its Diagnostic
|
|
|
|
Scope: `scripts/check-examples.py`, `releasekit.json`, and
|
|
`scripts/test-release.py`.
|
|
|
|
1. Delete the Python example runner after the Go tests carry its useful
|
|
coverage. Remove the profile's `checks` property and its example-specific
|
|
environment overlay. Retain every existing built-in validator, delivery
|
|
setting, and token-file protection. Do not add a replacement custom command.
|
|
2. In the release-wiring fixture, remove the generated example-check stub,
|
|
`FIXTURE_CHECK_MARKER`, `FIXTURE_CHECK_FAILURE`, related environment setup,
|
|
and assertions about invocation of that removed hook. Update its docstring
|
|
to describe launcher/profile wiring, not product-check dispatch.
|
|
3. Retain bootstrap/version/build-info checks, native usage status 2, successful
|
|
publication of the intended local fixture candidate without delivery
|
|
credentials, selected race/local-Go verification, token-path selection and
|
|
ignore checks, and module/worktree preservation.
|
|
4. Preserve a small status-1 wrapper check without manufacturing a product
|
|
hook: create only the successful version's note in the fixture, then invoke
|
|
the publication wrapper with `FAILED_VERSION`, whose note is absent.
|
|
Expect status 1 and retain the remote-tag absence check. This exercises
|
|
forwarding a native candidate failure, not a new publication algorithm.
|
|
5. Keep this diagnostic development-only and in Python. Do not add it to the
|
|
default Go suite or the release profile. The native launchers are unchanged.
|
|
|
|
Validation: run `python3 scripts/test-release.py` using the selected Go on
|
|
`PATH` and prepared caches. Its remotes must remain disposable local bare
|
|
repositories. Check the profile diff to confirm only the obsolete custom hook
|
|
was removed. Do not test by publishing a real tag or hosted page.
|
|
|
|
## Stage 5: Align Documentation And Verify The Complete Sprint
|
|
|
|
Scope: the development guide, local testing/release policies, release runbook,
|
|
affected example guidance, and integration verification.
|
|
|
|
1. Update `docs/development.md` to use normal Go testing for example validation.
|
|
Offer `go test ./examples/go-library/...` for targeted development without
|
|
making it a separate required release pass. Keep the Python release-wiring
|
|
command documented as a focused optional diagnostic.
|
|
2. Update the Promptkit-specific sections of `docs/policy/testing.md` and
|
|
`docs/policy/release.md`: example assertions now run inside the existing Go
|
|
suite, not after it as a custom check. Keep the examples' distinct coverage
|
|
ownership, all other selected checks, and the publication completion rules.
|
|
3. Remove Python from normal release prerequisites in `docs/release.md`.
|
|
Preserve Go selection, credentials, source publication, hosted delivery, and
|
|
recovery. Update any other current guidance pointing to the deleted runner.
|
|
Historical release notes remain unchanged.
|
|
4. Update the feature roadmap's completion/baseline text when recording the
|
|
implemented result. Remove its now-dead Markdown link to the deleted Python
|
|
file, using a plain historical path if still useful. Avoid leaving a broken
|
|
link in a completed coordination document. Do not retire unrelated roadmaps.
|
|
5. Format changed Go files, review the full diff, and run the integrated checks
|
|
below with the same compatible local Go toolchain:
|
|
|
|
```sh
|
|
go test -race -vet=off ./...
|
|
go vet ./...
|
|
go run ./examples/go-library/prepare
|
|
go run ./examples/go-library/run
|
|
go run ./examples/go-library/observe
|
|
python3 scripts/test-release.py
|
|
git diff --check
|
|
```
|
|
|
|
Run the three programs from the repository root. Confirm their outputs
|
|
retain the meanings checked by the new tests; JSON spacing is not a new
|
|
contract. Reuse successful focused checks for unchanged content rather than
|
|
repeating them solely to finish a stage. The separate full vet invocation
|
|
above pairs with `-vet=off` to avoid duplicate vet work.
|
|
6. As a one-time proof, temporarily make one meaningful expected value wrong in
|
|
an example test, run its package test, and confirm failure. Restore the value
|
|
and rerun the affected package before final review. Do not commit that probe
|
|
or add a permanent self-test of the testing framework.
|
|
7. Search current code/configuration/guidance for obsolete runner and hook
|
|
references, verify local documentation links, and confirm `go.mod`, `go.sum`,
|
|
public library code, and the native release launchers were not changed by
|
|
this tooling migration. Commit the focused completed work under agent policy.
|
|
|
|
Completion requires all three workflows to have real Go test coverage,
|
|
successful ordinary suite discovery, preserved useful assertions, removal of
|
|
the runner and custom hook, and accurate current documentation. No performance,
|
|
coverage-percentage, platform, or release-service gate is added. There are no
|
|
unresolved product decisions or upstream publication dependencies for this sprint.
|