# PromptKit v0.8.0 Upgrade Implementation Plan

## Purpose

Implement the target state defined by the
[PromptKit v0.8.0 Upgrade](promptkit-v0.8.md): adopt the useful PromptKit
v0.6.0, v0.7.0, and v0.8.0 changes; enable one bounded structural correction
by default; expose pipeline and binding overrides; preserve safe provider
diagnostics; and keep PromptKit behind Notarius's transport-neutral LLM
boundary.

This plan is ordered. Each numbered stage is one implementation prompt for a
gpt-5.6-terra coding agent. Complete and validate one stage before beginning
the next. Read `docs/development.md` and every policy under `docs/policy/` at
the start of each stage, inspect the current code and tests named by that
stage, preserve unrelated worktree changes, and update current-behavior
documentation in the same stage as the behavior it describes.

Do not retire this plan or `promptkit-v0.8.md` during implementation. Keep both
until the completed work has passed a separate review. Do not implement the
future Notarius semantic-validation retry loop, D&D combat-scene validator, or
warning redesign as part of this plan.

## Decisions Fixed For Implementation

- Pin `gitea.maximumdirect.net/eric/promptkit` v0.8.0 directly, with no
  `replace`, workspace dependency, or vendored source.
- Every maintained eligible production prompt defaults to exactly one
  PromptKit structural repair attempt.
- Add the exact configuration key
  `structured_output_repair_attempts` at pipeline scope and on LLM-backed
  module and validator bindings.
- Effective precedence is binding value, then pipeline value, then the prompt's
  declared `repair_attempts` value. Omission inherits; explicit zero disables
  structural repair at that scope.
- Accepted values are integers from zero through three. Explicit null and
  non-integer values are invalid. An explicit binding value on a deterministic
  module or validator is invalid. A pipeline value is applied only to selected
  LLM-backed bindings and does not make deterministic bindings invalid.
- Keep file configuration version 4. This is an additive pre-release field and
  does not require parallel versioned behavior.
- Use `StructuredOutputRepairAttempts *int` for presence-aware internal Go
  fields. Clone pointers at every ownership boundary.
- A configured override never replaces schema identity, output format, or
  validation mode. The PromptKit adapter calls `InspectPrompt`, copies the
  complete normalized prompt-owned output contract, changes only
  `RepairAttempts`, and supplies the complete replacement on `RunRequest`.
  Do not add an inspection cache initially.
- PromptKit repair is internal to one `CompleteStructured` call and does not
  consume or replenish a binding's existing `retries` budget.
- Add `RepairAttempts int` to Notarius's structured-completion response. It is
  the actual corrective-call count reported by PromptKit; token usage remains
  PromptKit's cumulative usage and must not be summed again.
- A valid repaired response is successful and produces no warning solely
  because repair occurred. Exhausted structural validation maps to
  `ErrInvalidStructuredOutput` with the final candidate and debug material
  retained.
- Add an application-owned generation-error sentinel and typed status-bearing
  error. PromptKit error types must not cross `internal/framework/llm`.
- HTTP status may appear in the application-owned generation error. Provider
  code, type, and message are excluded from ordinary errors, warnings,
  manifests, cache, and checkpoint identity; they may appear only in an
  explicitly requested debug trace after Notarius redaction.
- Profile inheritance is owned entirely by PromptKit. Notarius passes sources
  through, inspects and records the resolved target, and does not parse or merge
  `base_profile` itself.
- PromptKit's built-in `rakestrawhome` backend and
  `rakestrawhome-gemma-4-31b` profile are available generically. Notarius does
  not register, shadow, or select them by default.
- Missing optional credential environment values are allowed to reach the
  provider without `Authorization`; Notarius does not recreate v0.5.0's local
  failure or add provider-specific authentication logic.
- No dependency-upgrade ADR is required. Update architecture only with the
  durable ownership distinction between PromptKit structural repair and
  Notarius stage/semantic validation policy.

## Stage 1: Upgrade The Dependency And Establish A Clean v0.8.0 Baseline ✅

### Goal

Move the repository to PromptKit v0.8.0, resolve source-compatibility issues,
and establish a passing baseline before adopting new behavior.

### Implementation

1. Re-read the upstream v0.6.0, v0.7.0, and v0.8.0 release guides and the
   v0.8.0 package consumer and format documentation. Treat the pinned v0.8.0
   tag, not the sibling checkout's moving branch, as authoritative.
2. Update `go.mod` and `go.sum` to PromptKit v0.8.0 and run `go mod tidy` with
   `GOWORK=off`.
3. Compile before making compatibility edits. Correct only actual source or
   behavior incompatibilities. In particular:
   - convert any positional `promptkit.Profile` or
     `promptkit.OpenAICompatibleProfileConfig` literals to keyed literals;
   - confirm Notarius does not register the newly reserved `rakestrawhome`
     backend ID; and
   - preserve `PrepareExecution`/`Details`/`RunPrepared` snapshot ownership,
     `Discard`, session forwarding, reasoning override, profile preflight,
     and capacity adaptation.
4. Change `promptKitBuiltinProfileCatalogID` in
   `internal/framework/llm/promptkit_profile_fingerprint.go` from the v0.5.0
   catalog marker to an opaque v0.8.0 marker. Do not hash PromptKit internal
   files or include catalog content in manifests.
5. Update `docs/integrations/pkg-promptkit.md` to pin and link v0.8.0 and to
   state that this stage still leaves the production prompt-declared repair
   budget at its current value. Do not document later configuration or default
   behavior before it exists.
6. Update only those existing tests whose public PromptKit types or stable
   v0.8.0 behavior genuinely changed. Do not rewrite tests merely to match
   upstream diagnostic wording.

### Tests And Validation

```sh
GOWORK=off go mod tidy -diff
GOWORK=off go test ./internal/framework/llm ./internal/cli
GOWORK=off go test ./...
GOWORK=off go vet ./...
GOWORK=off go build ./cmd/notarius
git diff --check
```

### Acceptance Criteria

- `go list -m gitea.maximumdirect.net/eric/promptkit` reports v0.8.0.
- There is no PromptKit `replace`, active Go workspace dependency, or vendor
  tree.
- The adapter still uses one frozen prepared execution and all existing LLM
  tests pass.
- Checkpoint profile identity includes the v0.8.0 built-in catalog marker.
- Current integration documentation pins v0.8.0 without claiming that
  later stages are already active.
- The full ordinary test suite, vet, and command build pass.

## Stage 2: Verify v0.6.0 Compatibility And Hardening ✅

### Goal

Audit Notarius's assets and boundary values against PromptKit v0.6.0's stricter
source, path, endpoint, JSON, and cancellation contracts, fixing only concrete
incompatibilities.

### Implementation

1. Inspect `internal/framework/llm/asset_registry.go`, prompt/profile source
   composition, all registered asset roots, the conventional local backend,
   and their focused tests.
2. Exercise every production asset registry through PromptKit engine
   construction and the existing production composition tests. Confirm that:
   - YAML IDs and versions, not filenames, select definitions;
   - every `content_file` path is exact, relative, contained, and points to a
     regular embedded file;
   - every schema and JSON asset is one complete JSON value;
   - every current output contract is valid under v0.8.0; and
   - unrelated malformed definitions do not create a second Notarius identity
     or fallback mechanism.
3. Review local endpoint parsing and validation. Retain a narrower Notarius
   rule only if it has independent application value; otherwise rely on
   PromptKit's absolute HTTP/HTTPS URL contract. Never accept a value that the
   adapter will later reject.
4. Review conversion of Notarius variables, inputs, profile extras, and debug
   values at the adapter boundary for PromptKit's bounded JSON-compatible-value
   rules. Do not add a second generic JSON walker or duplicate upstream numeric
   limits.
5. Verify cancellation and deadline identity through existing adapter tests.
   Add or refine one focused regression only if Notarius currently destroys an
   `errors.Is`-relevant context or transport error that the application owns.
6. Do not add a cross-operation schema cache, artifact cache, provider-body
   reader, or duplicate JSON framing validation; v0.6.0 owns those mechanisms.

### Tests And Validation

Run the focused asset, profile-source, and adapter packages, then the ordinary
and race-enabled suites:

```sh
GOWORK=off go test ./internal/framework/llm ./internal/cli
GOWORK=off go test ./...
GOWORK=off go test -race ./...
git diff --check
```

Tests must remain offline and should validate Notarius's assembled boundary,
not reproduce PromptKit's internal path, JSON-depth, or response-size matrices.

### Acceptance Criteria

- Every maintained embedded prompt, schema, and fallback profile can be loaded
  through the assembled v0.8.0 engine.
- Current local endpoint and JSON-compatible values either satisfy the stricter
  upstream contract or fail during preparation with safe diagnostics.
- No duplicate PromptKit-owned cache, JSON, or response-bound mechanism is
  introduced.
- Cancellation and deadline behavior remains discoverable at the Notarius
  boundary.
- Ordinary and race-enabled tests pass.

## Stage 3: Adopt Profile Inheritance, Rakestrawhome, And Optional Credentials ✅

### Goal

Make the useful PromptKit v0.7.0 profile and backend behavior work through
Notarius's existing generic profile boundary without adding provider-specific
composition logic.

### Implementation

1. Inspect `promptkit_profiles.go`, `asset_registry.go`, profile fingerprinting,
   CLI profile preflight, profile provenance recording, and their tests before
   editing.
2. Add an offline integration test using a temporary operator profile source
   whose leaf uses `base_profile`. Prove that:
   - preflight reports the leaf ID;
   - the effective backend, model, reasoning, and other inherited values match
     the resolved PromptKit target;
   - execution uses the same resolved target as inspection; and
   - a missing parent or cycle fails before provider generation with a safe
     profile-load diagnostic.
   Do not duplicate PromptKit's entire field-by-field merge test matrix.
3. Add a checkpoint-safety test showing that changing a parent definition in
   an operator profile directory changes Notarius's profile-source fingerprint
   while profile content and paths remain absent from the fingerprint value.
   Retain the v0.8.0 catalog marker as coverage for built-in-parent changes.
4. Verify `rakestrawhome-gemma-4-31b` through the ordinary profile inspector.
   Assert its selected backend reaches Notarius's application-owned inspection
   and provenance fields. Use a fake PromptKit client or transport if execution
   coverage is needed; never contact the live service or require credentials.
5. Verify that Notarius registers no `rakestrawhome` override and that the
   existing `local` registration remains independent.
6. Add one `httptest`-backed adapter integration test for a filesystem profile
   with a missing optional `api_key_env`. The request must reach the test server
   without an `Authorization` header. Add a focused in-memory PromptKit profile
   test for `APIKeyRequired` only if needed to prove Notarius preserves upstream
   preflight behavior; do not expose a new operator profile API.
7. Keep `assets/dnd/profiles/dnd-extraction.yaml` standalone and unchanged. No
   matching v0.8.0 built-in profile owns its `openai/gpt-5.6-luna` target.
8. Update the current profile-source, deployment, and pinned-integration
   sections in `docs/config.md`, `docs/operations.md`,
   `docs/internal/llm.md`, and `docs/integrations/pkg-promptkit.md`. Link to the
   pinned PromptKit format rules for inheritance. Explain that filesystem
   profiles cannot express PromptKit's in-memory `APIKeyRequired` field and
   that an optional missing credential may result in a provider 401/403.

### Tests And Validation

```sh
GOWORK=off go test ./internal/framework/llm ./internal/core/config ./internal/cli
GOWORK=off go test ./...
GOWORK=off go test -race ./internal/framework/llm ./internal/cli
git diff --check
```

### Acceptance Criteria

- Inherited operator profiles resolve identically during preflight and
  execution, with the leaf ID and effective target kept distinct.
- Parent changes invalidate checkpoint reuse without leaking profile content or
  paths.
- Rakestrawhome is available through generic PromptKit profile handling and is
  not selected by default or registered by Notarius.
- Missing optional credentials omit authorization and reach the controlled
  test provider; explicitly required credentials retain upstream behavior.
- Current documentation accurately describes the implemented profile and
  credential behavior without duplicating PromptKit's merge algorithm.

## Stage 4: Adapt Structured Generation Errors Safely ✅

### Goal

Use PromptKit v0.7.0's structured generation errors for stable status
classification and debug-only provider diagnostics without leaking PromptKit
types or sensitive provider text.

### Implementation

1. In `internal/framework/contracts`, add:
   - `ErrLLMGeneration` as the provider-neutral generation-failure sentinel;
   - an application-owned `LLMGenerationError` with private status and safe
     diagnostic fields, `Error`, `Unwrap`, and `StatusCode` methods; and
   - a constructor that accepts a nonnegative status and an already-redacted
     diagnostic. Status zero means no HTTP status was available.
   Ordinary callers may inspect status with `errors.As` and category with
   `errors.Is`, but cannot obtain provider code, type, or message from the
   error.
2. Add an application-owned `LLMDebugProviderError` with `status_code`, `code`,
   `type`, and `message` fields, referenced optionally from
   `LLMDebugResponse`. This is debug material, not a manifest or durable public
   artifact contract.
3. In `PromptKitClient.CompleteStructured`, preserve precedence in this order:
   caller context cancellation/deadline, PromptKit capacity error, structured
   PromptKit generation error, then other PromptKit generation failures.
   Map every generation failure to `ErrLLMGeneration`; map
   `*promptkit.GenerationError` to `LLMGenerationError` with its status.
   Never wrap or return the PromptKit error value itself.
4. Keep the ordinary diagnostic limited to PromptKit's safe default error
   formatting after bearer and known-credential redaction. Do not append
   `ProviderCode`, `ProviderType`, or `ProviderMessage` to it.
5. For an explicitly requested debug path, preserve prepared prompt details and
   attach the PromptKit provider code, type, and message after:
   - reading only the selected prepared target's `APIKeyEnv`, if any, to obtain
     the exact known credential solely for redaction;
   - applying `RedactSecrets` and the existing bearer/key-pattern redaction;
   - retaining PromptKit's already-normalized bounds; and
   - discarding the credential value immediately rather than storing it.
   Do not scan unrelated environment variables.
6. Return prompt/debug material alongside the error so the existing debug LLM
   wrapper can persist it only when debug recording is enabled. Confirm that
   provider fields do not appear in ordinary error text, warnings, manifests,
   cache, checkpoint data, or a run without debug output.
7. Refactor error mapping into small helpers if needed to keep
   `CompleteStructured` readable; do not create provider-specific policy in
   modules or the pipeline runner.
8. Update the error and observability sections of `docs/internal/llm.md` and
   `docs/integrations/pkg-promptkit.md`. Keep operator disclosure rules in
   `docs/operations.md` concise and link to the internal boundary where useful.

### Tests And Validation

- Use `httptest.Server` to return representative structured 400 and 503
  responses. Assert `errors.Is(ErrLLMGeneration)`, `errors.As` to the
  application-owned type, and the exact status without asserting complete
  human wording.
- Include a provider message containing the selected test credential and a
  bearer-shaped value. Verify both are absent from the ordinary error and
  debug artifact, while a non-sensitive marker appears only in the requested
  debug trace.
- Retain existing capacity and context tests to prove their more specific
  classifications still win.

```sh
GOWORK=off go test ./internal/framework/contracts ./internal/framework/llm ./internal/framework/pipeline ./internal/cli
GOWORK=off go test ./...
GOWORK=off go test -race ./internal/framework/llm ./internal/framework/pipeline
git diff --check
```

### Acceptance Criteria

- PromptKit generation errors never escape the adapter error chain.
- All generation failures match `ErrLLMGeneration`; structured non-success
  responses expose only application-owned HTTP status to ordinary callers.
- Provider code, type, and message are available only in an explicitly
  requested, redacted debug trace.
- Capacity and context classifications remain unchanged and more specific.
- Security tests prove selected credentials and bearer tokens are not leaked.

## Stage 5: Add Adapter-Level Structured Repair Support ✅

### Goal

Teach the transport-neutral completion boundary and PromptKit adapter to apply
an optional repair override and report actual repair behavior, without yet
exposing the setting in pipeline configuration.

### Implementation

1. Add `StructuredOutputRepairAttempts *int` to
   `contracts.StructuredCompletionRequest`. Copy the pointed-to value wherever
   requests are cloned or retained.
2. Add `RepairAttempts int` to `contracts.StructuredCompletionResponse`. It is
   the actual number of corrective generation calls, not the configured budget
   and not the number of total candidates.
3. Validate a non-nil request value as zero through three at the adapter
   boundary so programmatic callers cannot bypass later file/config validation.
4. When the request value is nil, leave `promptkit.RunRequest.Validation` nil
   so the prompt's complete contract remains authoritative.
5. When the value is non-nil:
   - call `Engine.InspectPrompt(ctx, promptID, promptVersion)`;
   - copy `PromptInspection.OutputContract` by value;
   - replace only `RepairAttempts`;
   - pass the complete copied contract as `RunRequest.Validation`; and
   - prepare and execute exactly as before.
   Do not infer or hard-code schema paths, validation modes, or formats. Do not
   cache inspection in this stage.
6. Map `result.Validation.RepairAttempts` to the response and leave
   `result.Usage` cumulative values unchanged. The existing debug validation
   object and prepared output contract should show actual and configured values
   respectively.
7. Preserve result semantics:
   - valid initial and repaired candidates decode normally;
   - repair exhaustion returns the final raw candidate/debug material with an
     error matching `ErrInvalidStructuredOutput`;
   - explicit empty or whitespace-only content follows PromptKit validation;
   - missing/null/non-string content remains a generation/provider failure;
   - corrective-call generation errors use Stage 4's application-owned mapping;
     and
   - context cancellation wins at every error boundary.
8. Keep `CompleteStructured` and its helpers provider neutral outside this
   adapter package. Do not expose PromptKit validation or inspection types.
9. Update only the adapter-owned repair behavior in `docs/internal/llm.md` and
   `docs/integrations/pkg-promptkit.md`. State that public pipeline configuration
   and the production default are added by later stages of this plan.

### Tests And Validation

Add adapter-level behavioral tests using a deterministic fake PromptKit LLM:

- nil override uses the prompt declaration;
- explicit zero overrides a positive prompt declaration without dropping its
  JSON Schema contract;
- explicit one turns an invalid first candidate followed by a valid candidate
  into one successful response with the final raw bytes, actual repair count
  one, and cumulative usage;
- repair exhaustion returns the final candidate and validation diagnostics as
  `ErrInvalidStructuredOutput`;
- explicit empty content is eligible for repair;
- a corrective generation failure maps through Stage 4; and
- invalid direct values below zero or above three fail before provider work.

Do not assert PromptKit's exact assistant/user correction prose or copy its
full internal repair matrix.

```sh
GOWORK=off go test ./internal/framework/contracts ./internal/framework/llm ./internal/framework/pipeline
GOWORK=off go test -race ./internal/framework/llm ./internal/framework/pipeline
GOWORK=off go test ./...
git diff --check
```

### Acceptance Criteria

- The adapter changes only repair count when applying a request override.
- Nil and explicit zero remain distinct.
- Repaired success returns final raw output, cumulative usage, and actual count
  without a warning.
- Exhaustion, empty content, corrective generation failure, and cancellation
  match the target semantics.
- No PromptKit type crosses the LLM package boundary.

## Stage 6: Propagate Repair Policy Through Framework Requests ✅

### Goal

Carry an optional effective repair budget from each resolved stage or validator
binding to its module request without changing public file configuration yet.

### Implementation

1. Add `StructuredOutputRepairAttempts *int` alongside `LLMProfile` to every
   stage request that can belong to an LLM-backed binding:
   - `ParseRequest`;
   - `ChunkRequest`;
   - `TypedExtractionRequest`;
   - `TypedMergeRequest`;
   - `TypedNormalizeRequest`;
   - `OutputRequest`;
   - `TypedValidationRequest`;
   - `ChunkValidationRequest`; and
   - `SerializedValidationRequest`.
2. Add the same optional field to the erased/internal request carriers used by
   registry builders, preparation, runner stage attempts, validator targets,
   retry closures, and debug wrappers. Copy pointer values; never share a
   mutable pointer owned by configuration.
3. At every runner stage invocation, obtain the value from the exact resolved
   producer binding. At every validator invocation, obtain it from that exact
   resolved validator binding. Do not use the producer's value for a validator
   or vice versa.
4. Ensure all retry attempts for the same binding receive the same effective
   structural-repair value. Do not decrement it in Notarius; PromptKit owns the
   inner budget independently on each `CompleteStructured` call.
5. Extend `semanticreconcile.Request` with the optional field and carry it into
   each generic reconciliation completion. A batched reconciliation may make
   several completion calls; each call receives the same effective budget.
6. Update registry erasure/adaptation code for typed merge, normalize, and
   validation requests so no field is lost. Preserve input/output support even
   though current production input and output modules are deterministic.
7. Add focused framework tests for one chunk producer, one extraction
   producer, one normalizer, and one LLM-backed validator. Verify exact pointer
   value propagation and separation between producer and validator settings.
   Do not add repetitive tests for every generic adapter.

### Tests And Validation

```sh
GOWORK=off go test ./internal/framework/contracts ./internal/framework/pipeline ./internal/framework/semanticreconcile
GOWORK=off go test -race ./internal/framework/pipeline ./internal/framework/semanticreconcile
GOWORK=off go test ./...
git diff --check
```

### Acceptance Criteria

- Every stage and validator request can carry a detached optional repair value.
- The runner sources the value from the exact resolved binding.
- Producer and validator values cannot overwrite one another.
- Stage retries reuse but do not mutate or consume the inner repair budget.
- Semantic reconciliation forwards the budget to every one of its completion
  calls.
- Existing behavior remains unchanged while all values are nil.

## Stage 7: Forward Repair Policy From Every LLM-Backed Module ✅

### Goal

Complete the internal end-to-end path by having every production LLM-backed
module forward its stage request value to `CompleteStructured`.

### Implementation

1. Inventory every production `CompleteStructured` call with code search before
   editing. The expected current owners include:
   - `dnd/scenes` chunking;
   - the combat-turn, enemy-event, item-occurrence, item-registry,
     location-occurrence, location-registry, NPC-occurrence, NPC-registry,
     scene-description, and spell extractors; and
   - generic semantic reconciliation used by the item, location, and NPC
     registry normalizers.
   Reconcile this list with the actual repository; do not omit a newly added
   production caller merely because it is not named here.
2. In each direct caller, set
   `StructuredCompletionRequest.StructuredOutputRepairAttempts` from the
   corresponding stage request. Clone the pointer or use a small shared helper
   if that reduces repeated ownership mistakes without moving domain logic.
3. Ensure D&D registry normalizers pass their typed normalize request value into
   `semanticreconcile.Request`, and that the generic engine forwards it as
   established in Stage 6.
4. Update existing module prompt-mapping tests that already inspect a captured
   structured-completion request to assert the new field. Do not create a new
   one-test-per-module suite solely to memorialize field plumbing; rely on the
   existing request-contract tests plus a final complete call-site audit.
5. Search again after editing for production `CompleteStructured` calls and
   verify each either forwards the field or documents why it cannot receive a
   pipeline binding. Test-only fakes need only preserve the field when their
   contract test depends on it.
6. Do not set a module-specific fallback value. Nil must reach the adapter so
   the prompt declaration remains authoritative.

### Tests And Validation

Run focused D&D and semantic-reconciliation packages, then the full suite:

```sh
GOWORK=off go test ./internal/modules/dnd/... ./internal/framework/semanticreconcile
GOWORK=off go test -race ./internal/modules/dnd/... ./internal/framework/semanticreconcile
GOWORK=off go test ./...
git diff --check
```

### Acceptance Criteria

- Every production LLM-backed completion receives the exact stage or validator
  repair value.
- No module invents a default or imports PromptKit.
- Registry normalizers preserve the value through semantic reconciliation.
- Existing request-contract tests remain concise and pass.
- A final call-site audit finds no silent production omission.

## Stage 8: Add The Public Repair Configuration Contract ✅

### Goal

Add presence-aware pipeline and binding configuration for
`structured_output_repair_attempts` without yet changing runtime resolution.

### Implementation

1. Add `StructuredOutputRepairAttempts *int` to
   `pipeline.PipelineProfile` and `pipeline.ModuleBinding`, using
   `json:"structured_output_repair_attempts,omitempty"`.
2. Add presence-aware YAML support at pipeline and object-binding scope:
   - exact key `structured_output_repair_attempts`;
   - integer values zero through three;
   - explicit null, non-integer, and out-of-range values rejected with scoped
     diagnostics; and
   - scalar shorthand bindings continue to omit the binding override.
   Preserve file configuration version 4.
3. Update every configuration clone, conversion, redaction, summary, and JSON
   round-trip carrier. Copy pointers by value into newly allocated storage so
   parsed, configured, and redacted values do not alias.
4. Preserve omission versus explicit zero through YAML parsing, profile
   inheritance, module-binding object form, and JSON round trips. Keep scalar
   shorthand bindings equivalent to omission.
5. Do not add a top-level `promptkit.repair_attempts` setting or CLI override.
6. Add concise parser and ownership tests. Defer execution-class checks,
   effective precedence, resolved digests, and runtime forwarding to Stage 9,
   where module metadata is available.

### Tests And Validation

At the parser/config boundary, test omitted, explicit zero, positive bounds,
negative, above-three, null, non-integer, scalar shorthand, cloning, redaction,
and JSON round-trip behavior. Use relational boundary tests for the allowed
range and avoid duplicating the same cases at every layer.

```sh
GOWORK=off go test ./internal/core/config ./internal/cli
GOWORK=off go test -race ./internal/core/config
GOWORK=off go test ./...
go run ./cmd/notarius config validate \
  --config examples/dnd-minimal.config.yml \
  --pipeline dnd-session
go run ./cmd/notarius config validate \
  --config examples/dnd-complete.config.yml \
  --pipeline dnd-session
git diff --check
```

### Acceptance Criteria

- The exact public field parses at pipeline and object-binding scope with the
  fixed range.
- Nil and explicit zero remain distinguishable through parsing, cloning,
  inheritance, redaction, summaries, and round trips.
- Both maintained configurations remain valid without requiring the new field.
- No runtime or prompt default has changed prematurely.

## Stage 9: Resolve And Apply Repair Configuration

### Goal

Resolve the public field against module execution classes, incorporate the
effective value into pipeline identity, and connect it to the request plumbing
completed in Stages 6 and 7.

### Implementation

1. During resolution, compute the effective value for every selected binding:
   - explicit binding value wins;
   - otherwise an explicit pipeline value applies to an LLM-backed binding;
   - otherwise leave nil for prompt-owned policy.
   Apply the pipeline value to LLM-backed validators as well as producers.
2. Reject an explicit binding value on a deterministic module or deterministic
   validator using the same execution-class knowledge used for `llm_profile`.
   Do not reject a pipeline-level value merely because a selected pipeline also
   contains deterministic bindings; simply do not apply it to those bindings.
3. Clone every resolved pointer so the parsed pipeline, resolved profile,
   redacted summaries, and runner requests have distinct ownership.
4. Include the effective field in resolved pipeline JSON and digest input. A
   change between nil, zero, and a positive value must change the resolved
   digest when it changes an LLM-backed selected binding. Unselected lanes must
   retain the repository's existing digest and selection semantics.
5. Pass the resolved value into the Stage 6 request field for every selected
   input, chunk, extract, merge, normalize, output, and validator binding.
6. Update `docs/config.md` as the canonical field, range, and precedence
   contract; `docs/internal/pipeline.md` as the resolution owner; and
   `docs/operations.md` for the distinction from binding `retries`. The
   prompt-owned production default remains unchanged until Stage 10.
7. Add focused resolution and runner tests. Cover representative execution
   classes rather than repeating the same assertion for every module type.

### Tests And Validation

Test:

- binding over pipeline over nil precedence;
- inheritance into each selected LLM-backed stage and validator;
- no inheritance into deterministic bindings;
- explicit deterministic-binding rejection;
- detached pointers;
- runner forwarding for representative producer and validator bindings; and
- digest changes for execution-relevant nil, zero, and positive changes.

```sh
GOWORK=off go test ./internal/framework/pipeline ./internal/cli
GOWORK=off go test -race ./internal/framework/pipeline
GOWORK=off go test ./...
go run ./cmd/notarius config validate \
  --config examples/dnd-minimal.config.yml \
  --pipeline dnd-session
go run ./cmd/notarius config validate \
  --config examples/dnd-complete.config.yml \
  --pipeline dnd-session
git diff --check
```

### Acceptance Criteria

- The exact public field has the fixed binding-over-pipeline-over-prompt
  precedence for every selected LLM-backed producer and validator.
- Deterministic binding misuse fails during resolution before execution, while
  a pipeline value coexists with deterministic bindings.
- Nil and explicit zero remain distinguishable through resolution, runtime,
  summaries, and digests.
- A policy change invalidates checkpoint identity when it changes an effective
  selected binding.
- Current configuration, pipeline, and operations documentation matches the
  implemented behavior.

## Stage 10: Enable The Default, Finish Documentation, And Verify The Feature

### Goal

Set the accepted production default of one repair, reconcile all canonical
documentation, and run the full repository verification pass.

### Implementation

1. Change `repair_attempts: 0` to `repair_attempts: 1` in every maintained
   production prompt manifest that produces structured output, including the
   generic semantic-reconciliation prompt and every D&D chunk, extraction, and
   registry-normalization prompt. Do not mechanically change unrelated test
   fixtures whose purpose is to exercise zero.
2. Inspect every production prompt output contract after the edit. Confirm that
   each positive budget uses `basic`, `json`, or `json_schema`, remains no
   greater than three, and retains its existing format and schema path.
3. Add or refine the smallest durable assembled-assets test that proves the
   production engine can prepare the maintained prompts with the activated
   contracts. Do not add a brittle test that asserts an exact prompt count,
   file count, message prose, correction text, or asset length. The public
   default may be tested at one canonical assembled boundary because its
   literal value is an operational contract.
4. Confirm a successful repair does not create a warning and that exhausted
   repair remains `ErrInvalidStructuredOutput`. Verify the debug prompt records
   the configured contract, the debug response records actual repair count,
   and cumulative usage is not double-counted.
5. Confirm scheduling behavior with one focused test or existing coverage: the
   Notarius scheduled client admits one logical `CompleteStructured` operation
   while PromptKit may make serial corrective provider calls inside it. Do not
   attempt to reacquire a Notarius permit from inside PromptKit or add a second
   scheduler.
6. Reconcile current-state documentation:
   - `docs/integrations/pkg-promptkit.md` owns the pinned upstream boundary;
   - `docs/config.md` owns field names, range, default, and precedence;
   - `docs/operations.md` owns latency/cost, optional credentials, concurrency,
     timeout, and the upper-bound formula;
   - `docs/internal/llm.md` owns inspection-based contract replacement,
     cumulative usage, actual repair count, generation errors, and debug data;
   - `docs/internal/pipeline.md` owns effective policy propagation and the
     separation from stage retries; and
   - `docs/policy/architecture.md` adds only the durable rule that PromptKit
     owns deterministic structural repair inside one completion while Notarius
     owns stage attempts and semantic validation.
7. Remove current-behavior claims that PromptKit is v0.5.0, that every
   production repair budget is zero, or that PromptKit is always single-pass.
   Do not alter historical release notes or archived roadmaps.
8. Keep the maintained minimal and complete examples secret-free and valid.
   They may omit the new field to demonstrate the default; do not add a
   redundant complete profile or Rakestrawhome example merely to exercise an
   upstream catalog entry.
9. Review `docs/roadmap/future.md` only for consistency. Leave the future
   feedback-aware stage retry, combat-scene validator, and warning-reform work
   unimplemented and clearly separate.

### Tests And Validation

Run focused tests first, then all repository checks:

```sh
GOWORK=off go test ./internal/framework/llm ./internal/framework/pipeline ./internal/framework/semanticreconcile ./internal/modules/dnd/...
GOWORK=off go test ./...
GOWORK=off go test -race ./...
GOWORK=off go vet ./...
GOWORK=off go build ./cmd/notarius
GOWORK=off go mod tidy -diff
go run ./cmd/notarius config validate \
  --config examples/dnd-minimal.config.yml \
  --pipeline dnd-session
go run ./cmd/notarius config validate \
  --config examples/dnd-complete.config.yml \
  --pipeline dnd-session
git diff --check
```

Also perform focused repository searches that exclude `docs/roadmap/archive/`
and historical release notes:

- no active v0.5.0 PromptKit pins or links remain;
- no maintained production prompt still declares `repair_attempts: 0`;
- every production `CompleteStructured` caller forwards the repair field; and
- no provider code, type, or message is added to ordinary errors, warnings,
  manifests, cache, or checkpoint schemas.

If the repository's source-release checker is available and the ordinary
checks above pass, run `./scripts/check-release-source.sh v0.0.0` as the final
integrated validation. It must not create a tag, release note, or repository
artifact.

### Acceptance Criteria

- Every maintained structured prompt defaults to one corrective call and can
  be overridden to zero through three at pipeline or binding scope.
- A real assembled Notarius completion follows the PromptKit v0.8.0 repair
  contract without changing prompt schema identity or cacheable prefix.
- Actual repair count, cumulative usage, error classification, debug-only
  provider diagnostics, scheduling, and checkpoint identity match the feature
  roadmap.
- Profile inheritance, Rakestrawhome availability, optional credentials, and
  v0.6.0 hardening remain covered and documented.
- All canonical documentation describes implemented v0.8.0 behavior in its
  assigned home and leaves future semantic validation work in the roadmap.
- Maintained examples validate, all ordinary/race/vet/build/module checks pass,
  and the worktree contains no generated or sensitive artifacts.
