Prepare documentation for Promptkit v0.4.0
This commit is contained in:
@@ -1,520 +0,0 @@
|
||||
# Structured Capacity Errors Implementation Plan
|
||||
|
||||
**Status:** Complete.
|
||||
|
||||
## Purpose
|
||||
|
||||
This document is the decision-complete implementation plan for
|
||||
[structured capacity errors](capacity-errors.md). It is written for a
|
||||
gpt-5.6-terra coding agent that will implement each stage in order.
|
||||
|
||||
The feature roadmap owns the motivation, public intent, compatibility policy,
|
||||
security boundary, non-goals, and target end state. This plan owns the fixed
|
||||
design, file-level work, implementation sequence, test ownership,
|
||||
documentation updates, validation commands, and completion gates.
|
||||
|
||||
## Implementation Rules
|
||||
|
||||
- Complete the stages in order. Keep the repository compiling and the focused
|
||||
tests passing at every stage boundary.
|
||||
- Preserve unrelated working-tree changes. In particular, retain the accepted
|
||||
feature roadmap and its existing future-catalog and downstream-wishlist
|
||||
edits.
|
||||
- Follow every policy under `docs/policy/`, the task-specific reading guide in
|
||||
`docs/development.md`, and the accepted behavior in
|
||||
`capacity-errors.md`.
|
||||
- Keep the supported error API in the root `promptkit` package. Internal
|
||||
capacity and use-case error values must not become consumer dependencies.
|
||||
- Do not parse error strings. Carry the selected backend ID in an internal
|
||||
typed error and translate it explicitly at the root facade.
|
||||
- Do not change capacity policy, admission ordering, limits, queueing, FIFO
|
||||
generation scheduling, lease lifetime, cancellation behavior, backend
|
||||
selection, prepared-handle lifecycle, or model-client classification.
|
||||
- Do not classify provider throttling, HTTP 429 responses, quota failures, or
|
||||
injected-client errors as engine admission rejection.
|
||||
- Preserve `errors.Is(err, ErrCapacityExceeded)` while adding discovery as
|
||||
`*CapacityError` through `errors.As`.
|
||||
- Return a fresh public typed error for each rejected operation. Do not retain
|
||||
a request, pool, registry, endpoint, credential, execution target, or live
|
||||
capacity state in either typed error.
|
||||
- Add only `BackendID` to the public type. Do not add limits, counts, queue
|
||||
depth, retry timing, retryability, transport status, provider state, or
|
||||
stable JSON.
|
||||
- Keep tests lean and behavior-focused. Extend the existing internal admission,
|
||||
public capacity, prepared-execution, and root error-boundary tests instead of
|
||||
creating a parallel test framework.
|
||||
- Update exact public contracts in declarations and GoDoc. Update current-state
|
||||
consumer and internal documentation only after the implementation exists.
|
||||
- Do not add release notes, change a module version, create a release, commit,
|
||||
or tag as part of this work.
|
||||
|
||||
## Fixed Design
|
||||
|
||||
### Internal Admission Error
|
||||
|
||||
Add `internal/usecase/capacity_error.go` with this internal boundary type:
|
||||
|
||||
```go
|
||||
// CapacityError identifies bounded admission rejected for one selected
|
||||
// backend.
|
||||
type CapacityError struct {
|
||||
BackendID string
|
||||
}
|
||||
|
||||
func (e *CapacityError) Error() string
|
||||
func (e *CapacityError) Unwrap() error
|
||||
```
|
||||
|
||||
Although exported from an `internal` package so the root facade can recognize
|
||||
it, this is not a public consumer API. Its methods have these fixed semantics:
|
||||
|
||||
- `Error` returns concise diagnostic wording that includes a quoted nonblank
|
||||
backend ID and the generic internal capacity classification;
|
||||
- a nil receiver or blank `BackendID` produces only the generic internal
|
||||
capacity wording and does not panic;
|
||||
- `Unwrap` always returns `capacity.ErrCapacityExceeded`, including for a nil
|
||||
receiver; and
|
||||
- the value contains no cause field, request reference, capacity-manager
|
||||
reference, or other structured data.
|
||||
|
||||
Update `Runner.admitRun` in `internal/usecase/runner.go`:
|
||||
|
||||
1. retain the existing nil-admitter unlimited fallback;
|
||||
2. call `RunAdmitter.Admit` exactly once with the selected backend ID;
|
||||
3. when the returned error matches `capacity.ErrCapacityExceeded` and
|
||||
`backendID` is nonblank, return a newly allocated
|
||||
`&CapacityError{BackendID: backendID}`;
|
||||
4. when a capacity error is returned for a blank backend ID by an invalid or
|
||||
test-only collaborator, pass that error through rather than manufacturing a
|
||||
structured value that violates the nonblank-ID guarantee;
|
||||
5. pass every non-capacity error through unchanged; and
|
||||
6. preserve the release function unchanged on success.
|
||||
|
||||
Do not move structured identity into `internal/capacity.Manager`. The use-case
|
||||
boundary already knows the effective selected backend used by both `Run` and
|
||||
`RunPrepared`, and it also normalizes any conforming `RunAdmitter`
|
||||
implementation into the same error contract. The capacity package continues
|
||||
to own only its generic internal sentinel and scheduling state.
|
||||
|
||||
Both ordinary and prepared execution already call `admitRun`; do not add
|
||||
separate wrapping logic to `Run` or `RunPrepared`.
|
||||
|
||||
### Public Error Type
|
||||
|
||||
Add a root file named `capacity_error.go` containing:
|
||||
|
||||
```go
|
||||
// CapacityError reports bounded admission rejected for a selected backend.
|
||||
type CapacityError struct {
|
||||
BackendID string
|
||||
}
|
||||
|
||||
func (e *CapacityError) Error() string
|
||||
func (e *CapacityError) Unwrap() error
|
||||
```
|
||||
|
||||
The declaration and method GoDoc must establish:
|
||||
|
||||
- engine-produced values identify only rejection at Promptkit's bounded
|
||||
`Run` or `RunPrepared` admission boundary;
|
||||
- `BackendID` is the normalized registered backend ID used for routing and
|
||||
capacity, and endpoint overrides do not change it;
|
||||
- every engine-produced value is nonnil and has a nonblank `BackendID`;
|
||||
- provider errors, active-generation waiting, and caller cancellation are not
|
||||
represented by this type;
|
||||
- `Error` wording is diagnostic and not a parsing contract;
|
||||
- `Unwrap` returns `ErrCapacityExceeded`, so `errors.Is` and `errors.As` can be
|
||||
used together;
|
||||
- a nil receiver and the zero value remain safe and unwrap to
|
||||
`ErrCapacityExceeded`, but a consumer-constructed value is not evidence that
|
||||
an engine rejected work;
|
||||
- the type and its default Go encoding have no stable JSON contract; and
|
||||
- consumers own returned values and may mutate `BackendID` without affecting
|
||||
engine state or another error.
|
||||
|
||||
Implement `Error` without exposing anything other than the public field and
|
||||
the generic sentinel wording. For a nil receiver or blank field, return
|
||||
`ErrCapacityExceeded.Error()`. Otherwise include the backend ID with `%q`.
|
||||
Implement `Unwrap` as an unconditional return of `ErrCapacityExceeded`.
|
||||
|
||||
Do not add an exported constructor, custom formatter, `Is` method, JSON tags,
|
||||
`MarshalJSON`, or `UnmarshalJSON`. Direct equality with
|
||||
`ErrCapacityExceeded` is not a supported contract.
|
||||
|
||||
### Root Translation
|
||||
|
||||
Update `mapPublicError` in `errors.go` before its general
|
||||
`publicErrorFor` mapping:
|
||||
|
||||
1. use `errors.As` to find an internal `*usecase.CapacityError`;
|
||||
2. require the matched pointer to be nonnil and its `BackendID` to be
|
||||
nonblank;
|
||||
3. return a newly allocated public
|
||||
`&CapacityError{BackendID: internalCapacityError.BackendID}` directly; and
|
||||
4. otherwise continue through the existing general mapping.
|
||||
|
||||
Returning the public value directly is deliberate. It prevents the internal
|
||||
typed error and internal sentinel from remaining in the returned error chain,
|
||||
while the public value's `Unwrap` supplies the supported public sentinel.
|
||||
Copy only the string field; do not retain the internal error.
|
||||
|
||||
Leave the existing `capacity.ErrCapacityExceeded` case in `publicErrorFor`.
|
||||
It remains a defensive compatibility fallback for an unstructured internal
|
||||
capacity error. No valid `Run` or `RunPrepared` capacity rejection should take
|
||||
that fallback after this feature is implemented.
|
||||
|
||||
Do not reorder unrelated error categories. In particular, generation failures
|
||||
remain `ErrLLMGenerate`, and the mapper must not infer admission rejection from
|
||||
public sentinel text, provider errors, status codes, or arbitrary errors that
|
||||
happen to expose a backend field.
|
||||
|
||||
### Operation Contracts
|
||||
|
||||
Update the existing declarations and GoDoc without duplicating the full type
|
||||
contract:
|
||||
|
||||
- the `ErrCapacityExceeded` GoDoc in `engine.go` remains the broad
|
||||
classification contract and points consumers to `CapacityError` for the
|
||||
selected backend ID;
|
||||
- `Engine.Run` states that engine admission rejection is discoverable as
|
||||
`*CapacityError` and still matches `ErrCapacityExceeded`;
|
||||
- `Engine.RunPrepared` states the same and retains its one-attempt handle
|
||||
semantics;
|
||||
- `doc.go` adds error values to its unstable-JSON category, lists
|
||||
`CapacityError` there, and notes that returned structured errors are
|
||||
caller-owned; and
|
||||
- no operation other than `Run` and `RunPrepared` claims it can return this
|
||||
type.
|
||||
|
||||
Do not change method signatures or add the type to any stable JSON list.
|
||||
|
||||
### Error And Identity Boundaries
|
||||
|
||||
The implementation must preserve all of these distinctions:
|
||||
|
||||
| Condition | `errors.Is` identity | `errors.As` to `*CapacityError` |
|
||||
| --- | --- | --- |
|
||||
| Limited selected backend has no admission slot | `ErrCapacityExceeded` | Yes, with selected backend ID |
|
||||
| Context is already done when admission checks it | Context error | No |
|
||||
| Waiting for an active generation permit is canceled | `ErrLLMGenerate` and context error | No |
|
||||
| Provider or injected client returns throttling or quota failure | `ErrLLMGenerate` and documented collaborator identity | No |
|
||||
| Invalid request, profile, credential, artifact, render, or validation failure | Existing category | No |
|
||||
| Unlimited backend or endpoint-only profile | No admission rejection | No |
|
||||
|
||||
For an ordinary `Run`, the ID is the effective registered backend selected
|
||||
during preparation. For `RunPrepared`, it is the backend frozen in the claimed
|
||||
handle. An endpoint override changes only the endpoint and must not change the
|
||||
reported ID.
|
||||
|
||||
### Test Ownership
|
||||
|
||||
Extend existing tests at their current ownership boundaries.
|
||||
|
||||
`internal/capacity/manager_test.go` continues to own admission mechanics.
|
||||
Strengthen `TestManagerAdmissionHonorsContextAndUnlimitedBackends` so the
|
||||
limited pool is full before the canceled admission attempt. This protects the
|
||||
existing rule that cancellation wins over capacity rejection without adding a
|
||||
new overlapping test.
|
||||
|
||||
`internal/usecase/runner_test.go` owns attachment of selected identity.
|
||||
Update `TestRunnerAdmissionFailureSkipsCompletionCollaborators` so:
|
||||
|
||||
- the capacity case uses `errors.As` to obtain the internal
|
||||
`*CapacityError`;
|
||||
- its `BackendID` is exactly `"custom"`;
|
||||
- the error still matches `capacity.ErrCapacityExceeded`;
|
||||
- cancellation does not produce an internal `*CapacityError`; and
|
||||
- the existing assertions about no partial result, no recategorization, the
|
||||
admitted backend ID, and skipped collaborators remain.
|
||||
|
||||
Replace the current string-content assertion with the structured assertion.
|
||||
Do not test exact diagnostic wording.
|
||||
|
||||
`errors_internal_test.go` owns root translation. Add a focused test that maps
|
||||
an internal `*usecase.CapacityError` and proves:
|
||||
|
||||
- the result is a public `*CapacityError` with the copied backend ID;
|
||||
- it matches public `ErrCapacityExceeded`;
|
||||
- it does not match unrelated public categories;
|
||||
- it no longer exposes the internal typed error through `errors.As`; and
|
||||
- mutating the source internal error after mapping does not alter the public
|
||||
value.
|
||||
|
||||
Retain the existing cancellation-preservation test.
|
||||
|
||||
`capacity_contract_test.go` owns assembled public `Run` behavior. Extend
|
||||
`TestEngineRejectsRunBeforeCompletionWhenAdmissionIsFull` to prove:
|
||||
|
||||
- no partial result is returned;
|
||||
- `errors.Is(err, promptkit.ErrCapacityExceeded)` still succeeds;
|
||||
- `errors.As` obtains a nonnil `*promptkit.CapacityError`;
|
||||
- `BackendID` is `"limited"` even though the rejected request overrides its
|
||||
endpoint;
|
||||
- unrelated public categories do not match;
|
||||
- mutating the returned error cannot alter a subsequent independently
|
||||
rejected call or its backend ID; and
|
||||
- no completion collaborator or model client is invoked for rejected calls.
|
||||
|
||||
In the same established full-pool setup, add a canceled-context assertion
|
||||
before releasing the admitted run. It must match `context.Canceled`, must not
|
||||
match `ErrCapacityExceeded`, and must not be discoverable as
|
||||
`*promptkit.CapacityError`. This is the root contract counterpart to the
|
||||
manager precedence test.
|
||||
|
||||
Extend `TestCapacityExceededSentinelContract` to cover the public type's zero
|
||||
and nil receiver behavior without asserting exact diagnostic wording:
|
||||
|
||||
- both safely match `ErrCapacityExceeded`;
|
||||
- an ordinary populated value is discoverable by `errors.As`; and
|
||||
- neither the sentinel nor the typed value matches unrelated categories.
|
||||
|
||||
`prepared_execution_contract_test.go` owns the public `RunPrepared` boundary.
|
||||
In the capacity-rejection section of
|
||||
`TestPreparedExecutionCredentialCapacityAndTimingBoundaries`, assert that
|
||||
`errors.As` obtains `*promptkit.CapacityError` with backend ID `"limited"`.
|
||||
Retain the existing assertions that the result is nil, the public sentinel
|
||||
matches, the handle is consumed, and details remain available.
|
||||
|
||||
Do not duplicate manager limit matrices, generation FIFO tests, backend
|
||||
registration tests, or provider-client failure matrices. Existing tests
|
||||
already own those behaviors.
|
||||
|
||||
### Documentation Ownership
|
||||
|
||||
After the code and contract tests pass:
|
||||
|
||||
- update `docs/consumers/pkg-promptkit.md` in **Handle Errors** with a concise
|
||||
`errors.As` example that extracts `BackendID` while retaining the existing
|
||||
`errors.Is` guidance and application-owned retry policy;
|
||||
- update `docs/internal/runner.md` to describe the internal typed attachment
|
||||
and root translation without reproducing the public API contract;
|
||||
- update `docs/internal/capacity.md` to clarify that the manager still emits
|
||||
only its internal sentinel, while the runner attaches selected identity and
|
||||
the facade translates it;
|
||||
- update `docs/internal/overview.md` only enough to include the root typed
|
||||
capacity error in the facade responsibility; and
|
||||
- update `doc.go` and `engine.go` with the exact public contract described
|
||||
above.
|
||||
|
||||
Do not update `docs/formats.md`, the OpenAI-compatible integration contract,
|
||||
backend configuration GoDoc, README, or release notes. This feature changes no
|
||||
file format, provider wire request, backend configuration, project
|
||||
orientation, or released-version record.
|
||||
|
||||
When implementation is complete:
|
||||
|
||||
- change `docs/roadmap/capacity-errors.md` to `**Status:** Complete.`;
|
||||
- change `docs/roadmap/future.md` so it no longer describes structured
|
||||
capacity errors as active planning and simply records that no ideas await
|
||||
selection;
|
||||
- change both downstream wishlist dispositions from accepted planning to
|
||||
implemented behavior, linking to the consumer guide's **Handle Errors**
|
||||
section rather than duplicating the contract; and
|
||||
- change this document to `**Status:** Complete.`
|
||||
|
||||
The feature roadmap already contains no staged or prompt-level implementation
|
||||
language. Do not add such language to it when changing its status.
|
||||
|
||||
## Stage 1: Carry Structured Identity Across Internal Admission
|
||||
|
||||
### Objective
|
||||
|
||||
Replace diagnostic-string-only backend context with a typed internal
|
||||
admission error while preserving capacity mechanics and cancellation
|
||||
precedence.
|
||||
|
||||
### Implementation Prompt
|
||||
|
||||
Implement only Stage 1 of
|
||||
`docs/roadmap/implementation.md`.
|
||||
|
||||
1. Add `internal/usecase/capacity_error.go` with the exact internal type and
|
||||
method semantics in **Fixed Design**.
|
||||
2. Update `Runner.admitRun` to create one fresh internal typed error for a
|
||||
nonblank selected backend when the admitter returns the internal capacity
|
||||
sentinel.
|
||||
3. Update the existing runner admission-failure test to assert typed identity
|
||||
instead of inspecting diagnostic text.
|
||||
4. Strengthen the existing capacity-manager context test so cancellation is
|
||||
checked while the limited pool is already full.
|
||||
5. Run the focused formatting and validation below.
|
||||
|
||||
Do not modify the root public API, root mapper, capacity-manager production
|
||||
code, public contract tests, or current-state documentation in this stage.
|
||||
|
||||
### Focused Validation
|
||||
|
||||
Run from the repository root:
|
||||
|
||||
```sh
|
||||
gofmt -w internal/usecase/capacity_error.go \
|
||||
internal/usecase/runner.go \
|
||||
internal/usecase/runner_test.go \
|
||||
internal/capacity/manager_test.go
|
||||
go test ./internal/capacity ./internal/usecase
|
||||
git diff --check
|
||||
```
|
||||
|
||||
### Completion Gate
|
||||
|
||||
Stage 1 is complete only when:
|
||||
|
||||
- capacity rejection from `admitRun` is discoverable as the internal
|
||||
`*usecase.CapacityError`;
|
||||
- its ID comes from the effective backend passed to admission;
|
||||
- both `Run` and `RunPrepared` use the shared boundary without duplicate
|
||||
wrapping;
|
||||
- `errors.Is` still reaches `capacity.ErrCapacityExceeded`;
|
||||
- cancellation and other admission errors remain untyped and unchanged;
|
||||
- capacity scheduling production code is untouched; and
|
||||
- focused tests and whitespace checks pass.
|
||||
|
||||
## Stage 2: Expose And Protect The Public Error Contract
|
||||
|
||||
### Objective
|
||||
|
||||
Add the minimal public typed error, translate the internal value without
|
||||
leaking it, and protect ordinary and prepared consumer behavior.
|
||||
|
||||
### Implementation Prompt
|
||||
|
||||
Implement only Stage 2 of
|
||||
`docs/roadmap/implementation.md` after Stage 1 satisfies its completion gate.
|
||||
|
||||
1. Add root `capacity_error.go` with the exact public type, methods, and GoDoc
|
||||
in **Fixed Design**.
|
||||
2. Update `errors.go` to translate a nonblank internal typed error into a
|
||||
fresh public value before general sentinel mapping.
|
||||
3. Preserve the existing unstructured capacity fallback and all unrelated
|
||||
error-mapping order.
|
||||
4. Update `engine.go` and `doc.go` with the exact operation, ownership, and
|
||||
unstable-JSON contracts.
|
||||
5. Add the focused root translation test.
|
||||
6. Extend the existing external-package `Run`, sentinel, cancellation, and
|
||||
`RunPrepared` contract assertions described under **Test Ownership**.
|
||||
7. Run the focused formatting and validation below.
|
||||
|
||||
Do not change admission policy, add provider classification, introduce a
|
||||
constructor or serialization contract, or update durable prose documentation
|
||||
in this stage.
|
||||
|
||||
### Focused Validation
|
||||
|
||||
Run from the repository root:
|
||||
|
||||
```sh
|
||||
gofmt -w capacity_error.go errors.go engine.go doc.go \
|
||||
errors_internal_test.go capacity_contract_test.go \
|
||||
prepared_execution_contract_test.go
|
||||
go test . -run \
|
||||
'TestMapPublicError|TestEngineRejectsRunBeforeCompletionWhenAdmissionIsFull|TestCapacityExceededSentinelContract|TestPreparedExecutionCredentialCapacityAndTimingBoundaries'
|
||||
go test .
|
||||
git diff --check
|
||||
```
|
||||
|
||||
### Completion Gate
|
||||
|
||||
Stage 2 is complete only when:
|
||||
|
||||
- every assembled `Run` and `RunPrepared` admission rejection is discoverable
|
||||
as a public `*CapacityError` with the selected backend ID;
|
||||
- the public error unwraps only to `ErrCapacityExceeded` and does not retain
|
||||
the internal typed error;
|
||||
- existing broad `errors.Is` handling remains valid;
|
||||
- endpoint overrides do not change the reported ID;
|
||||
- cancellation at a full pool remains a context error and not a capacity
|
||||
error;
|
||||
- caller mutation cannot affect another rejection or engine state;
|
||||
- provider, generation, and unrelated error mappings remain unchanged; and
|
||||
- focused and complete root-package tests pass.
|
||||
|
||||
## Stage 3: Update Canonical Documentation And Validate
|
||||
|
||||
### Objective
|
||||
|
||||
Make the implemented structured error discoverable, reconcile temporary
|
||||
planning state, and complete repository-wide validation.
|
||||
|
||||
### Implementation Prompt
|
||||
|
||||
Implement only Stage 3 of
|
||||
`docs/roadmap/implementation.md` after Stages 1 and 2 satisfy their completion
|
||||
gates.
|
||||
|
||||
1. Update the consumer and internal documents listed under
|
||||
**Documentation Ownership**. Keep exact API guarantees in GoDoc and use
|
||||
prose documents for task guidance and implementation boundaries.
|
||||
2. Update the feature-roadmap, future-catalog, implementation-plan, and
|
||||
downstream-wishlist statuses and links exactly as specified above.
|
||||
3. Follow every added or changed Markdown link and confirm its file and
|
||||
heading target.
|
||||
4. Run the full validation sequence.
|
||||
5. Inspect the complete diff for scope, sensitive data, and repository
|
||||
hygiene.
|
||||
6. Only after every check passes, leave both roadmap statuses as `Complete`
|
||||
and rerun `git diff --check`.
|
||||
|
||||
Do not add a release document, new example, new public package, retry policy,
|
||||
transport mapping, or duplicate API reference.
|
||||
|
||||
### Full Validation
|
||||
|
||||
Run from the repository root:
|
||||
|
||||
```sh
|
||||
gofmt -w internal/usecase/capacity_error.go \
|
||||
internal/usecase/runner.go \
|
||||
internal/usecase/runner_test.go \
|
||||
internal/capacity/manager_test.go \
|
||||
capacity_error.go errors.go engine.go doc.go \
|
||||
errors_internal_test.go capacity_contract_test.go \
|
||||
prepared_execution_contract_test.go
|
||||
gofmt -l $(git ls-files '*.go')
|
||||
go test ./...
|
||||
go test -race ./...
|
||||
go vet ./...
|
||||
go build ./...
|
||||
go run ./examples/go-library/prepare
|
||||
git diff --check
|
||||
git status --short
|
||||
```
|
||||
|
||||
The `gofmt -l` command must print no paths. The maintained example must remain
|
||||
offline and require no real credential or provider.
|
||||
|
||||
Inspect the final state and confirm:
|
||||
|
||||
- only files required by this feature and pre-existing user changes are
|
||||
present;
|
||||
- no credential, private source content, endpoint, workspace file, local
|
||||
replacement, generated binary, or unrelated formatting change was added;
|
||||
- the root declaration and GoDoc own the exact public contract;
|
||||
- consumer guidance summarizes the workflow and links to the canonical API;
|
||||
- internal documents describe responsibility without redefining the public
|
||||
contract;
|
||||
- no current-state document claims Promptkit owns retry, backoff, transport,
|
||||
logging, or metrics policy;
|
||||
- no roadmap retains staged language outside this implementation plan; and
|
||||
- no release, commit, or tag was created.
|
||||
|
||||
### Completion Gate
|
||||
|
||||
Implementation is complete only when:
|
||||
|
||||
- every Stage 1 and Stage 2 gate remains satisfied;
|
||||
- ordinary and race-enabled tests pass;
|
||||
- vet, build, formatting, the offline example, Markdown links, and whitespace
|
||||
checks pass;
|
||||
- public, consumer, and internal documentation agree on the implemented
|
||||
boundary;
|
||||
- future-catalog and downstream-wishlist dispositions no longer describe the
|
||||
feature as pending;
|
||||
- both roadmap statuses are `Complete`;
|
||||
- the working tree contains no unintended files or changes; and
|
||||
- the repository is ready for maintainer review without a commit or release
|
||||
having been created by this plan.
|
||||
|
||||
## Open Questions
|
||||
|
||||
None. The accepted feature roadmap and fixed design above fully specify the
|
||||
implementation boundary.
|
||||
Reference in New Issue
Block a user