|
|
|
|
@@ -1,334 +1,458 @@
|
|
|
|
|
# Optional Request-Parameter Omission Implementation Plan
|
|
|
|
|
# Application Fallback Profiles Implementation Plan
|
|
|
|
|
|
|
|
|
|
**Status:** Complete.
|
|
|
|
|
**Status:** Ready for implementation.
|
|
|
|
|
|
|
|
|
|
## Purpose
|
|
|
|
|
|
|
|
|
|
This document is the decision-complete implementation plan for
|
|
|
|
|
[omitting unset optional request parameters](optional-request-parameters.md).
|
|
|
|
|
It is written for a `gpt-5.6-terra` coding agent that will implement each stage
|
|
|
|
|
in order.
|
|
|
|
|
[application fallback profiles](fallback-profiles.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, policy choices, compatibility
|
|
|
|
|
boundary, non-goals, and target end state. This document owns the concrete
|
|
|
|
|
design, file-level work, test ownership, documentation updates, validation,
|
|
|
|
|
and completion gates.
|
|
|
|
|
|
|
|
|
|
The separate [application fallback profiles](fallback-profiles.md) roadmap is
|
|
|
|
|
not part of this implementation plan. Preserve it unchanged for its own later
|
|
|
|
|
planning and implementation cycle.
|
|
|
|
|
|
|
|
|
|
## Implementation Rules
|
|
|
|
|
|
|
|
|
|
- Complete the stages in order. Stage 1 must leave code, tests, GoDoc, and
|
|
|
|
|
current-state documentation mutually accurate; Stage 2 performs the final
|
|
|
|
|
audit and repository-wide acceptance.
|
|
|
|
|
- Preserve unrelated working-tree changes. In particular, do not edit,
|
|
|
|
|
implement, retire, or reclassify `fallback-profiles.md`.
|
|
|
|
|
- Complete the stages in order. Every stage must leave the repository
|
|
|
|
|
buildable, tested for the behavior changed in that stage, and accurately
|
|
|
|
|
documented for its implemented state.
|
|
|
|
|
- Preserve unrelated working-tree changes. Inspect `git status --short` and
|
|
|
|
|
the relevant diffs before editing, and do not overwrite or reformat
|
|
|
|
|
pre-existing user work.
|
|
|
|
|
- Follow every policy under `docs/policy/`, the task-specific reading guide in
|
|
|
|
|
`docs/development.md`, and the accepted behavior in
|
|
|
|
|
`optional-request-parameters.md`.
|
|
|
|
|
- Keep the existing package boundaries. Framework defaults remain in
|
|
|
|
|
`internal/defaults`, resolution remains in `internal/usecase`, and outbound
|
|
|
|
|
OpenAI-compatible serialization remains in `internal/llm`.
|
|
|
|
|
- Do not add an exported type, field, option, method, error, or public package.
|
|
|
|
|
This feature changes default and wire semantics within existing contracts.
|
|
|
|
|
- Do not replace numeric profile fields with pointers or add profile presence
|
|
|
|
|
tracking. File and in-memory profile zero values retain their existing
|
|
|
|
|
inheritance semantics; runtime pointer overrides remain the only supported
|
|
|
|
|
way to select an explicit numeric zero.
|
|
|
|
|
- Preserve required request fields, session IDs, structured output,
|
|
|
|
|
credentials, extra-parameter validation, reasoning clearing, deadlines,
|
|
|
|
|
capacity management, and all existing precedence rules.
|
|
|
|
|
- Do not query a provider for defaults or capabilities and do not add
|
|
|
|
|
backend- or model-specific serialization branches.
|
|
|
|
|
- Keep tests lean and behavioral. Use the existing root precedence test to own
|
|
|
|
|
resolved public/injected-client metadata and the existing model-client tests
|
|
|
|
|
to own wire inclusion and omission. Do not duplicate those matrices in a
|
|
|
|
|
new end-to-end fixture.
|
|
|
|
|
- Update exact exported semantics in GoDoc, profile/default semantics in
|
|
|
|
|
`docs/formats.md`, and provider request-body semantics in
|
|
|
|
|
`docs/integrations/openai-compatible-chat.md` in the same stage as the code.
|
|
|
|
|
`fallback-profiles.md`.
|
|
|
|
|
- Keep the module root as the public facade. The root package owns profile
|
|
|
|
|
source selection and composition; `internal/profile` owns repository,
|
|
|
|
|
parsing, validation, and error-preserving overlay behavior; and
|
|
|
|
|
`internal/profile/builtin` owns only the embedded built-in catalog.
|
|
|
|
|
- Add only the public `WithFallbackProfileFS` option. Do not add an exported
|
|
|
|
|
repository type, source-provenance value, fallback-specific error, config
|
|
|
|
|
field, programmatic fallback-profile option, or public package.
|
|
|
|
|
- Reuse `profile.NewFSRepository` and `profile.NewOverlayRepository`. Do not
|
|
|
|
|
add another parser, validator, repository implementation, or merge model.
|
|
|
|
|
- Preserve lazy loading. Engine construction validates the option arguments,
|
|
|
|
|
not every file in the supplied filesystem. A profile source is read only
|
|
|
|
|
when resolution reaches it.
|
|
|
|
|
- Preserve existing error identities and mappings. Only
|
|
|
|
|
`profile.ErrProfileNotFound` permits an overlay to consult its next layer;
|
|
|
|
|
every other error from a higher layer must be returned and mapped through
|
|
|
|
|
the existing public profile-load path.
|
|
|
|
|
- Keep tests classical and behavior-focused. Public source precedence and
|
|
|
|
|
exported option semantics belong in external-package root tests; generic
|
|
|
|
|
overlay behavior remains owned by `internal/profile` tests.
|
|
|
|
|
- Update GoDoc and current-state documentation in the same stage that exposes
|
|
|
|
|
the public option. Do not describe the feature as implemented before that
|
|
|
|
|
stage is complete.
|
|
|
|
|
- Do not add release notes, change a module version, commit, tag, push, or
|
|
|
|
|
publish a release as part of this plan.
|
|
|
|
|
|
|
|
|
|
## Fixed Design
|
|
|
|
|
|
|
|
|
|
### Framework Defaults
|
|
|
|
|
### Public API
|
|
|
|
|
|
|
|
|
|
In `internal/defaults/defaults.go`, remove these constants:
|
|
|
|
|
Add this function to `engine.go` beside the existing profile-source options:
|
|
|
|
|
|
|
|
|
|
```go
|
|
|
|
|
ExecutionDefaultTemperature
|
|
|
|
|
ExecutionDefaultMaxTokens
|
|
|
|
|
ExecutionDefaultTopP
|
|
|
|
|
func WithFallbackProfileFS(fsys fs.FS, root string) Option
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
They currently encode zero for `temperature` and `max_tokens` and one for
|
|
|
|
|
`top_p`. Optional provider controls are no longer framework defaults, so
|
|
|
|
|
retaining zero-valued constants under default-oriented names would obscure the
|
|
|
|
|
new contract.
|
|
|
|
|
The option accepts the same filesystem and root forms as `WithProfileFS` and
|
|
|
|
|
constructs its repository with `profile.NewFSRepository(fsys, root)`. It must
|
|
|
|
|
return `ErrInvalidConfig` from option application when `fsys` is nil or when
|
|
|
|
|
`strings.TrimSpace(root)` is empty. Do not normalize or replace a valid root
|
|
|
|
|
before passing it to the repository.
|
|
|
|
|
|
|
|
|
|
Keep `ExecutionDefaultTimeoutSeconds` at its current positive value. Timeout is
|
|
|
|
|
a Promptkit-owned generation deadline and is not an OpenAI-compatible request
|
|
|
|
|
body field.
|
|
|
|
|
The fallback source is its own last-value-wins option category. Add these two
|
|
|
|
|
private fields to `engineOptions`:
|
|
|
|
|
|
|
|
|
|
Keep `ExecutionTargetDefault` as the common resolution baseline, but have it
|
|
|
|
|
initialize only `TimeoutSeconds`. The zero Go values for `Temperature`,
|
|
|
|
|
`MaxTokens`, and `TopP` then represent unspecified provider controls. Do not
|
|
|
|
|
rename this internal function or add a second defaults constructor.
|
|
|
|
|
```go
|
|
|
|
|
fallbackProfiles profile.Repository
|
|
|
|
|
fallbackProfileSource bool
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### Resolution And Public Metadata
|
|
|
|
|
Use the repository field for the selected source and the boolean only to
|
|
|
|
|
distinguish an unapplied option from an applied option. A later valid
|
|
|
|
|
`WithFallbackProfileFS` replaces both values. Option application remains
|
|
|
|
|
sequential, so an invalid option fails `NewEngine` immediately even if a later
|
|
|
|
|
option could otherwise replace it.
|
|
|
|
|
|
|
|
|
|
Do not change the merge functions or precedence in
|
|
|
|
|
`internal/usecase/runner.go`:
|
|
|
|
|
The exact GoDoc for `WithFallbackProfileFS` must state:
|
|
|
|
|
|
|
|
|
|
1. the baseline target supplies only the Promptkit timeout;
|
|
|
|
|
2. nonzero profile numeric fields replace the baseline;
|
|
|
|
|
3. non-nil runtime numeric overrides replace profile values; and
|
|
|
|
|
4. `ExecutionTargetPresence` records runtime overrides, including explicit
|
|
|
|
|
zero values.
|
|
|
|
|
- that it supplies application-owned fallback profile definitions;
|
|
|
|
|
- the full four-layer lookup order;
|
|
|
|
|
- that definitions are whole profiles and are not field-merged;
|
|
|
|
|
- that only a missing ID falls through, while a matching read, parse,
|
|
|
|
|
duplicate, validation, or credential-format failure stops resolution;
|
|
|
|
|
- that loading and validation are lazy;
|
|
|
|
|
- that files use the ordinary strict profile YAML and `api_key_env` rules;
|
|
|
|
|
- that nil filesystems and blank roots cause `NewEngine` to match
|
|
|
|
|
`ErrInvalidConfig`;
|
|
|
|
|
- that repeated calls use the last valid fallback source; and
|
|
|
|
|
- that this is definition lookup, not provider or generation failover.
|
|
|
|
|
|
|
|
|
|
Consequently, when a profile omits the optional provider controls, resolved
|
|
|
|
|
`ExecutionTarget` values contain zero for `Temperature`, `MaxTokens`, and
|
|
|
|
|
`TopP`. That zero is stable metadata for “unspecified” unless the accompanying
|
|
|
|
|
`GenerateRequest.TargetPresence` bit reports an explicit runtime zero.
|
|
|
|
|
Update the `Option`, `Config.ProfileDir`, `WithProfileFS`, `WithProfileFile`,
|
|
|
|
|
and `WithProfiles` GoDoc in `engine.go` where necessary so their relative
|
|
|
|
|
precedence is unambiguous. Exact declarations and behavior remain owned by
|
|
|
|
|
GoDoc; consumer documentation should summarize the workflow and link readers
|
|
|
|
|
back to the API rather than reproduce every error clause.
|
|
|
|
|
|
|
|
|
|
Do not expose target presence in `PreparedRun`, `RunResult`, or
|
|
|
|
|
`ProfileInspection`, and do not change their stable JSON shapes. As already
|
|
|
|
|
true for `max_tokens`, those metadata values report the resolved numeric value
|
|
|
|
|
rather than provenance. A prepared result containing `top_p: 0` therefore does
|
|
|
|
|
not distinguish an unspecified value from an explicit runtime zero; injected
|
|
|
|
|
clients receive the separate presence value when the distinction affects
|
|
|
|
|
execution.
|
|
|
|
|
### Repository Composition
|
|
|
|
|
|
|
|
|
|
Update root GoDoc in `types.go` so it no longer calls an unspecified optional
|
|
|
|
|
provider control an effective provider value:
|
|
|
|
|
Move all profile-source composition into one private root helper in
|
|
|
|
|
`engine.go`:
|
|
|
|
|
|
|
|
|
|
- `ExecutionTarget.Temperature`, `MaxTokens`, and `TopP` must each state that
|
|
|
|
|
zero leaves the field unspecified to compatible providers unless the
|
|
|
|
|
corresponding `ExecutionTargetPresence` bit is true;
|
|
|
|
|
- `ExecutionTarget.TimeoutSeconds` retains its existing deadline semantics;
|
|
|
|
|
- `Profile` and `ExecutionTargetOverride` documentation must describe zero or
|
|
|
|
|
nil as inheriting a lower-precedence value and otherwise leaving the provider
|
|
|
|
|
control unspecified, rather than implying that every field receives a
|
|
|
|
|
concrete framework value; and
|
|
|
|
|
- `PreparedRun`, `ProfileInspection`, and other effective-target summaries may
|
|
|
|
|
continue to describe precedence, but must not imply that Promptkit knows a
|
|
|
|
|
provider's omitted default.
|
|
|
|
|
```go
|
|
|
|
|
func newProfileRepository(profileDir string, options engineOptions) profile.Repository
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Do not change field types, field order, JSON tags, conversion functions, string
|
|
|
|
|
formatting, or copying behavior.
|
|
|
|
|
`NewEngine` must call this helper once and pass its returned repository to the
|
|
|
|
|
runner. The helper must build from lowest to highest precedence:
|
|
|
|
|
|
|
|
|
|
### Outbound Request Semantics
|
|
|
|
|
1. begin with `builtin.NewRepository()`;
|
|
|
|
|
2. if `options.fallbackProfileSource` is true, overlay
|
|
|
|
|
`options.fallbackProfiles` over the built-in repository;
|
|
|
|
|
3. select exactly one ordinary configured source: use `options.profiles` when
|
|
|
|
|
`options.profileSource` is true; otherwise, when `profileDir` is nonblank,
|
|
|
|
|
use `profile.NewFilesystemRepository(profileDir)`; overlay that selected
|
|
|
|
|
source over the current repository;
|
|
|
|
|
4. if `options.memorySource` is true, overlay `options.memoryProfiles` over
|
|
|
|
|
the current repository; and
|
|
|
|
|
5. return the resulting chain.
|
|
|
|
|
|
|
|
|
|
The current built-in client already has the required mechanism:
|
|
|
|
|
`openAIChatRequestFromGenerateRequest` includes `temperature`, `max_tokens`, or
|
|
|
|
|
`top_p` when the resolved value is nonzero or the corresponding target-presence
|
|
|
|
|
bit is true, and `openAIChatRequestPayload` omits nil fields. Preserve that
|
|
|
|
|
logic.
|
|
|
|
|
This preserves the existing rule that `WithProfileFS` or `WithProfileFile`
|
|
|
|
|
replaces `Config.ProfileDir`; those sources are alternatives in one ordinary
|
|
|
|
|
configured-source category, not two independent layers. `WithProfiles` remains
|
|
|
|
|
a distinct highest-precedence category.
|
|
|
|
|
|
|
|
|
|
No production change should be needed in
|
|
|
|
|
`internal/llm/openai_compatible_client.go`. Change it only if a focused failing
|
|
|
|
|
test demonstrates that the existing implementation does not meet this plan;
|
|
|
|
|
do not special-case `top_p`, inspect profile provenance, or move framework
|
|
|
|
|
default policy into the transport.
|
|
|
|
|
The final lookup order is therefore:
|
|
|
|
|
|
|
|
|
|
The resulting behavior is:
|
|
|
|
|
```text
|
|
|
|
|
WithProfiles
|
|
|
|
|
-> WithProfileFile / WithProfileFS / Config.ProfileDir
|
|
|
|
|
-> WithFallbackProfileFS
|
|
|
|
|
-> Promptkit built-ins
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
- an omitted profile `top_p` resolves to zero and is absent from the body;
|
|
|
|
|
- a nonzero profile or runtime `top_p` is included;
|
|
|
|
|
- an explicit runtime `top_p` of zero is included because presence is true;
|
|
|
|
|
- the same rules continue to apply to `temperature` and `max_tokens`;
|
|
|
|
|
- empty `service_tier` and effective `reasoning_effort` remain absent;
|
|
|
|
|
- configured `extra_params` remain present after validation; and
|
|
|
|
|
- `model`, `messages`, conditional `session_id`, and conditional
|
|
|
|
|
`response_format` remain unchanged.
|
|
|
|
|
Every arrow is a whole-profile, not-found-only fallback. Do not inspect or
|
|
|
|
|
copy profile fields in the composition helper.
|
|
|
|
|
|
|
|
|
|
### Profile Formats And Built-In Profiles
|
|
|
|
|
### Built-In Package Boundary
|
|
|
|
|
|
|
|
|
|
Do not change YAML or public `Profile` field shapes. Numeric zero in a file or
|
|
|
|
|
in-memory profile continues to mean “do not replace the lower layer.” With no
|
|
|
|
|
lower provider value, zero therefore resolves to unspecified. An explicit
|
|
|
|
|
profile-level numeric zero remains unsupported; consumers use a runtime
|
|
|
|
|
pointer override when zero itself must be sent.
|
|
|
|
|
Reduce `internal/profile/builtin/repository.go` to the embedded catalog leaf:
|
|
|
|
|
|
|
|
|
|
Do not edit files under `internal/profile/builtin/assets/`. Values declared in
|
|
|
|
|
those files are explicit profile policy and remain effective. Existing
|
|
|
|
|
nonzero-profile tests are sufficient to protect explicit inclusion; do not add
|
|
|
|
|
one test per built-in asset or parameter.
|
|
|
|
|
```go
|
|
|
|
|
func NewRepository() profile.Repository
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Remove `NewRepositoryWithPrimary` and `NewRepositoryWithDirectory`. Remove
|
|
|
|
|
their now-obsolete tests from `internal/profile/builtin/repository_test.go` and
|
|
|
|
|
remove imports used only by those helpers or tests. Do not move their tests to
|
|
|
|
|
another private helper: existing root public-behavior tests own assembled
|
|
|
|
|
precedence, and `internal/profile.TestOverlayRepository` owns not-found-only
|
|
|
|
|
overlay semantics.
|
|
|
|
|
|
|
|
|
|
Do not change built-in YAML assets, built-in validation, the `profile.Repository`
|
|
|
|
|
interface, `profile.NewOverlayRepository`, or filesystem repository behavior.
|
|
|
|
|
|
|
|
|
|
### Resolution And Error Semantics
|
|
|
|
|
|
|
|
|
|
The runner receives one assembled `profile.Repository`; do not add fallback
|
|
|
|
|
logic to `InspectProfile`, `Prepare`, `PrepareExecution`, `Run`, or
|
|
|
|
|
`RunPrepared`. Those paths must continue to resolve through the runner's one
|
|
|
|
|
repository dependency.
|
|
|
|
|
|
|
|
|
|
The existing overlay contract is authoritative:
|
|
|
|
|
|
|
|
|
|
- a successful lookup returns the complete higher-layer profile;
|
|
|
|
|
- `profile.ErrProfileNotFound` consults the next layer;
|
|
|
|
|
- cancellation, filesystem read failures, malformed YAML, duplicate matches,
|
|
|
|
|
raw `api_key`, invalid profiles, and all other errors stop lookup; and
|
|
|
|
|
- the root facade maps failures through the existing public identities such as
|
|
|
|
|
`ErrProfileNotFound` and `ErrProfileLoad`.
|
|
|
|
|
|
|
|
|
|
Do not add eager filesystem walking in the option or `NewEngine`. A malformed
|
|
|
|
|
asset unrelated to the requested ID retains the existing ordinary
|
|
|
|
|
`FSRepository` behavior; this plan does not strengthen that package's global
|
|
|
|
|
validation guarantees.
|
|
|
|
|
|
|
|
|
|
### Test Ownership
|
|
|
|
|
|
|
|
|
|
Use these existing boundaries:
|
|
|
|
|
Use the following test boundaries and avoid duplicating the profile parser's
|
|
|
|
|
existing case matrix.
|
|
|
|
|
|
|
|
|
|
- In `engine_test.go`, update the “framework defaults” row of
|
|
|
|
|
`TestEngineExecutionSettingPrecedence` so the zero-valued profile expects
|
|
|
|
|
`TopP: 0` while retaining `Temperature: 0`, `MaxTokens: 0`, and the positive
|
|
|
|
|
timeout. Rename that row to describe unspecified provider controls plus the
|
|
|
|
|
framework timeout. Keep the rows proving nonzero profile precedence and
|
|
|
|
|
explicit runtime-zero presence unchanged.
|
|
|
|
|
- Remove
|
|
|
|
|
`TestRunnerRunBuiltInDefaultsUsedWhenProfileOmitsOptionalFields` from
|
|
|
|
|
`internal/usecase/runner_test.go`. Its literal-default assertions duplicate
|
|
|
|
|
the stronger assembled root precedence test and depend on the internal
|
|
|
|
|
constants being removed. Do not replace it with another internal
|
|
|
|
|
default-value test.
|
|
|
|
|
- Keep
|
|
|
|
|
`TestOpenAICompatibleClientOmitsImplicitZeroNumericFields` and
|
|
|
|
|
`TestOpenAICompatibleClientSerializesExplicitZeroNumericOverrides` in
|
|
|
|
|
`internal/llm/openai_compatible_client_test.go`. Together they own the wire
|
|
|
|
|
distinction and should pass without weakening their assertions.
|
|
|
|
|
- Keep the existing nonzero request serialization and profile-precedence tests
|
|
|
|
|
passing. They prove that explicitly configured values continue to be sent
|
|
|
|
|
and selected.
|
|
|
|
|
In `public_contract_test.go`:
|
|
|
|
|
|
|
|
|
|
Do not add snapshots, golden files, provider calls, or a broad duplicate
|
|
|
|
|
integration test. Add a new test only if the implementation exposes a distinct
|
|
|
|
|
contract risk not covered by the tests above, and record that reason in the
|
|
|
|
|
test name or nearby test structure rather than in a new planning document.
|
|
|
|
|
- Add `TestFallbackProfileSourcePrecedence`. Use minimal synthetic
|
|
|
|
|
`fstest.MapFS` profiles and, where `Config.ProfileDir` is under test, a
|
|
|
|
|
`t.TempDir`. Cover these distinct relationships: an in-memory profile beats
|
|
|
|
|
both ordinary and fallback definitions; an ordinary `WithProfileFS` source
|
|
|
|
|
beats a fallback definition; `Config.ProfileDir` beats a fallback
|
|
|
|
|
definition when no ordinary source option replaces it; a fallback
|
|
|
|
|
definition beats a built-in definition with the same ID; and an ID absent
|
|
|
|
|
from the fallback source still resolves from the built-in catalog. Assert
|
|
|
|
|
the selected model or another stable complete-profile field rather than
|
|
|
|
|
internal repository structure.
|
|
|
|
|
- Extend `TestRepeatedOptionsUseLastValueInEachCategory` with a
|
|
|
|
|
`fallback profile source` subtest proving that the later valid fallback
|
|
|
|
|
filesystem is selected.
|
|
|
|
|
- Add `TestFallbackProfileSourcePreservesLazyLoadingAndErrors`. Prove that
|
|
|
|
|
engine construction succeeds without reading malformed fallback YAML, that
|
|
|
|
|
an unrelated malformed file does not prevent a valid requested fallback
|
|
|
|
|
definition from resolving under existing FS-repository semantics, that a
|
|
|
|
|
malformed fallback file whose stem matches a built-in profile ID yields
|
|
|
|
|
`ErrProfileLoad` instead of silently reaching the built-in, and that a
|
|
|
|
|
malformed ordinary configured definition yields `ErrProfileLoad` instead of
|
|
|
|
|
reaching a valid application fallback definition. Use `errors.Is`; do not
|
|
|
|
|
assert complete error strings.
|
|
|
|
|
- Add one representative workflow test that supplies a fallback-only profile
|
|
|
|
|
and verifies the same effective model through `InspectProfile`, `Prepare`,
|
|
|
|
|
a `PrepareExecution` followed by `RunPrepared`, and direct `Run`. Use the
|
|
|
|
|
existing deterministic injected-client style, no live provider, and no real
|
|
|
|
|
credential. This test owns the cross-workflow repository wiring; do not
|
|
|
|
|
repeat the full precedence matrix through every method.
|
|
|
|
|
|
|
|
|
|
In `engine_test.go`, extend `TestSourceOptionsRejectInvalidInputs` with nil
|
|
|
|
|
filesystem and blank-root cases for `WithFallbackProfileFS`. Both must make
|
|
|
|
|
`NewEngine` match `ErrInvalidConfig`.
|
|
|
|
|
|
|
|
|
|
Retain `internal/profile.TestOverlayRepository` unchanged unless a genuine
|
|
|
|
|
existing defect is found. It already owns success, not-found fallback, and
|
|
|
|
|
non-not-found error preservation. Do not add package-private tests for the new
|
|
|
|
|
root helper, snapshots, golden files, provider calls, or one test per profile
|
|
|
|
|
format error already covered by `internal/profile`.
|
|
|
|
|
|
|
|
|
|
### Canonical Documentation
|
|
|
|
|
|
|
|
|
|
Update current-state documentation in Stage 1:
|
|
|
|
|
Update current-state documentation when the option is implemented:
|
|
|
|
|
|
|
|
|
|
- In `docs/formats.md`, replace the optional provider-control entries in the
|
|
|
|
|
framework-default table with clear unspecified/omitted semantics, while
|
|
|
|
|
retaining the positive `timeout_seconds` framework default. Explain that
|
|
|
|
|
profile numeric zero inherits a lower layer and otherwise remains
|
|
|
|
|
unspecified; an explicit runtime pointer zero is retained.
|
|
|
|
|
- In `docs/integrations/openai-compatible-chat.md`, state that
|
|
|
|
|
`temperature`, `max_tokens`, and `top_p` are included only when selected by a
|
|
|
|
|
profile or runtime override, including explicit runtime zero, and are absent
|
|
|
|
|
when unspecified. Keep the existing ownership of required fields,
|
|
|
|
|
`session_id`, structured output, extra parameters, and timeout behavior.
|
|
|
|
|
- In `types.go`, apply the GoDoc changes described above; these declarations
|
|
|
|
|
own the exact public value semantics.
|
|
|
|
|
- In `docs/formats.md`, make the source-precedence section the canonical
|
|
|
|
|
four-layer definition lookup order. State that ordinary configured sources
|
|
|
|
|
override application fallbacks, application fallbacks override built-ins,
|
|
|
|
|
profiles are whole values, and only a missing ID falls through. Retain this
|
|
|
|
|
document's ownership of strict YAML, credentials, validation, and source
|
|
|
|
|
discovery details.
|
|
|
|
|
- In `docs/consumers/pkg-promptkit.md`, add a short task-oriented section that
|
|
|
|
|
shows an illustrative `embed.FS` declaration and
|
|
|
|
|
`WithFallbackProfileFS`. Explain that application defaults belong in the
|
|
|
|
|
embedded fallback and operator overrides belong in the ordinary configured
|
|
|
|
|
source. Link to `docs/formats.md` for exact format and precedence rules, and
|
|
|
|
|
do not turn the snippet into a second complete maintained application.
|
|
|
|
|
- In `docs/internal/sources.md`, describe the root-owned four-layer
|
|
|
|
|
composition and the existing not-found-only overlay mechanism. Remove any
|
|
|
|
|
claim that the built-in package composes caller-selected repositories.
|
|
|
|
|
- In `docs/internal/overview.md`, keep the root facade responsible for source
|
|
|
|
|
assembly, describe `internal/profile/builtin` only as the embedded catalog,
|
|
|
|
|
and reflect the implemented fallback layer without duplicating the exact
|
|
|
|
|
public API contract.
|
|
|
|
|
- In `engine.go`, apply the GoDoc changes under Public API. GoDoc owns the
|
|
|
|
|
exact option signature, validation, category, and public semantics.
|
|
|
|
|
|
|
|
|
|
Do not add a README or release-document note. The consumer guide already
|
|
|
|
|
routes exact field behavior to GoDoc and profile/default behavior to the format
|
|
|
|
|
reference, so do not duplicate the new contract there. The internal LLM
|
|
|
|
|
document describes flow rather than exact field omission and does not require
|
|
|
|
|
a change unless its current text is found to contradict the implementation.
|
|
|
|
|
The architecture policy already assigns assembly to the root facade and the
|
|
|
|
|
built-in catalog to `internal/profile/builtin`; do not edit it unless the
|
|
|
|
|
implementation reveals an actual contradiction. No integration protocol,
|
|
|
|
|
outbound request body, profile YAML shape, README orientation, or maintained
|
|
|
|
|
example changes as part of this feature.
|
|
|
|
|
|
|
|
|
|
## Stage 1: Implement Omission Semantics And Canonical Contracts
|
|
|
|
|
## Stage 1: Move Existing Profile Composition To The Root Facade
|
|
|
|
|
|
|
|
|
|
### Objective
|
|
|
|
|
|
|
|
|
|
Remove optional provider controls from the framework baseline, preserve
|
|
|
|
|
explicit profile and runtime values, update the canonical contracts, and prove
|
|
|
|
|
the behavior at the existing resolution and wire boundaries.
|
|
|
|
|
Establish the intended ownership boundary and a single root composition point
|
|
|
|
|
without changing public behavior or adding the fallback option.
|
|
|
|
|
|
|
|
|
|
### Implementation Prompt
|
|
|
|
|
|
|
|
|
|
Implement only Stage 1 of `docs/roadmap/implementation.md`. Read the complete
|
|
|
|
|
feature roadmap, implementation rules, and fixed design above before editing.
|
|
|
|
|
|
|
|
|
|
1. In `internal/defaults/defaults.go`, remove the three provider-control
|
|
|
|
|
constants and make `ExecutionTargetDefault` initialize only
|
|
|
|
|
`TimeoutSeconds`.
|
|
|
|
|
2. In `engine_test.go`, update and rename the default-precedence table row
|
|
|
|
|
exactly as described under Test Ownership.
|
|
|
|
|
3. Remove the redundant literal-default test from
|
|
|
|
|
`internal/usecase/runner_test.go`; do not weaken other precedence,
|
|
|
|
|
profile-value, or runtime-zero tests.
|
|
|
|
|
4. Update the affected exported GoDoc in `types.go` without changing any
|
|
|
|
|
declaration, JSON tag, or serialization shape.
|
|
|
|
|
5. Update `docs/formats.md` and
|
|
|
|
|
`docs/integrations/openai-compatible-chat.md` according to Canonical
|
|
|
|
|
Documentation.
|
|
|
|
|
6. Run the focused validation below. Repair regressions in scope, but do not
|
|
|
|
|
broaden the feature or change the established serializer merely to make a
|
|
|
|
|
mistaken expectation pass.
|
|
|
|
|
1. In `engine.go`, add `newProfileRepository(profileDir string, options
|
|
|
|
|
engineOptions) profile.Repository` and move the existing three-layer
|
|
|
|
|
assembly into it: built-ins, then the selected ordinary configured source,
|
|
|
|
|
then `WithProfiles`. Do not add fallback fields or the public option yet.
|
|
|
|
|
2. Replace the inline profile assembly in `NewEngine` with one call to the
|
|
|
|
|
helper. Preserve the existing replacement relationship between
|
|
|
|
|
`Config.ProfileDir` and `WithProfileFS`/`WithProfileFile`.
|
|
|
|
|
3. In `internal/profile/builtin/repository.go`, remove
|
|
|
|
|
`NewRepositoryWithPrimary` and `NewRepositoryWithDirectory`, leaving
|
|
|
|
|
`NewRepository` as the only constructor.
|
|
|
|
|
4. Remove the three tests dedicated to the deleted built-in composition
|
|
|
|
|
helpers from `internal/profile/builtin/repository_test.go`. Preserve tests
|
|
|
|
|
that validate the embedded catalog itself.
|
|
|
|
|
5. Update `docs/internal/sources.md` and `docs/internal/overview.md` so they
|
|
|
|
|
describe the implemented Stage 1 ownership accurately. At this boundary
|
|
|
|
|
the source order is still in-memory, ordinary configured source, built-ins;
|
|
|
|
|
do not document the application fallback as implemented yet.
|
|
|
|
|
6. Run the focused validation below. Fix in-scope regressions without adding
|
|
|
|
|
fallback behavior early.
|
|
|
|
|
|
|
|
|
|
Do not edit built-in profile assets, fallback-profile work, backend
|
|
|
|
|
registration, profile parsing, target merge logic, public value shapes,
|
|
|
|
|
prepared-execution lifecycle, capacity management, or release material.
|
|
|
|
|
Do not add or mention an implemented `WithFallbackProfileFS` in Stage 1. Do
|
|
|
|
|
not change exported declarations, profile parsing, profile assets, error
|
|
|
|
|
mapping, runner behavior, or consumer and format documentation.
|
|
|
|
|
|
|
|
|
|
### Focused Validation
|
|
|
|
|
|
|
|
|
|
Run from the repository root:
|
|
|
|
|
|
|
|
|
|
```sh
|
|
|
|
|
gofmt -w internal/defaults/defaults.go types.go engine_test.go \
|
|
|
|
|
internal/usecase/runner_test.go
|
|
|
|
|
go test . -run 'TestEngineExecutionSettingPrecedence'
|
|
|
|
|
go test ./internal/llm -run \
|
|
|
|
|
'TestOpenAICompatibleClient(GenerateSuccess|OmitsImplicitZeroNumericFields|SerializesExplicitZeroNumericOverrides)'
|
|
|
|
|
go test ./internal/usecase -run \
|
|
|
|
|
'Test(ResolveExecutionTarget|RunnerPrepareRequestNumericOverridePresence|RunnerPrepareSelectedProfileBeatsBuiltInDefault|RunnerRunSelectedProfileBeatsBuiltInDefault)'
|
|
|
|
|
go test . ./internal/defaults ./internal/usecase ./internal/llm
|
|
|
|
|
go vet . ./internal/defaults ./internal/usecase ./internal/llm
|
|
|
|
|
gofmt -w engine.go internal/profile/builtin/repository.go \
|
|
|
|
|
internal/profile/builtin/repository_test.go
|
|
|
|
|
go test . -run \
|
|
|
|
|
'Test(PrepareUsesBuiltInProfileWithoutProfileDir|CustomProfileOverridesBuiltInProfile|InMemoryProfilesOverrideBuiltInsAndProfileSources)$'
|
|
|
|
|
go test ./internal/profile/...
|
|
|
|
|
go test . ./internal/profile/...
|
|
|
|
|
go vet . ./internal/profile/...
|
|
|
|
|
git diff --check
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
If a focused regular expression does not match an existing test name, inspect
|
|
|
|
|
the current names and run the narrowest equivalent set; do not silently skip
|
|
|
|
|
the intended resolution, explicit-profile, explicit-zero, and wire-omission
|
|
|
|
|
coverage.
|
|
|
|
|
If a focused expression does not match an existing test name, inspect the
|
|
|
|
|
current suite and run the narrowest equivalent public precedence coverage; do
|
|
|
|
|
not silently skip the intended relationship.
|
|
|
|
|
|
|
|
|
|
### Completion Gate
|
|
|
|
|
|
|
|
|
|
Stage 1 is complete only when:
|
|
|
|
|
|
|
|
|
|
- the resolution baseline contains no provider tuning value and retains the
|
|
|
|
|
Promptkit timeout;
|
|
|
|
|
- an omitted `top_p` resolves to zero and the built-in client omits it;
|
|
|
|
|
- nonzero profile and runtime values remain effective and serialized;
|
|
|
|
|
- explicit runtime zero values remain distinguishable and serialized through
|
|
|
|
|
`ExecutionTargetPresence`;
|
|
|
|
|
- no public type or stable JSON shape changed;
|
|
|
|
|
- required fields, structured output, session IDs, extra parameters,
|
|
|
|
|
reasoning, credentials, and deadlines retain their existing behavior;
|
|
|
|
|
- GoDoc, format documentation, and the integration contract describe the
|
|
|
|
|
implemented behavior without conflicting ownership; and
|
|
|
|
|
- the root facade assembles the unchanged three-layer profile chain in one
|
|
|
|
|
private helper;
|
|
|
|
|
- ordinary source options still replace `Config.ProfileDir` and in-memory
|
|
|
|
|
profiles still have highest precedence;
|
|
|
|
|
- built-in profiles remain available and remain lower than consumer sources;
|
|
|
|
|
- only `internal/profile` owns generic overlay behavior and the built-in
|
|
|
|
|
package owns only its embedded catalog;
|
|
|
|
|
- no public API or behavior changed;
|
|
|
|
|
- internal current-state documentation matches that boundary; and
|
|
|
|
|
- all focused tests, vet, formatting, and whitespace checks pass.
|
|
|
|
|
|
|
|
|
|
## Stage 2: Audit Compatibility And Validate The Repository
|
|
|
|
|
## Stage 2: Add Application Fallback Profiles And Public Contracts
|
|
|
|
|
|
|
|
|
|
### Objective
|
|
|
|
|
|
|
|
|
|
Confirm that the narrow semantic change is complete across all public,
|
|
|
|
|
injected-client, built-in-profile, documentation, and repository surfaces,
|
|
|
|
|
then mark the temporary planning documents complete.
|
|
|
|
|
Add the public option, insert the application fallback into the root-owned
|
|
|
|
|
repository chain, prove its precedence and failure behavior through public
|
|
|
|
|
workflows, and publish the canonical current-state documentation.
|
|
|
|
|
|
|
|
|
|
### Implementation Prompt
|
|
|
|
|
|
|
|
|
|
Implement only Stage 2 of `docs/roadmap/implementation.md` after Stage 1
|
|
|
|
|
satisfies its completion gate.
|
|
|
|
|
|
|
|
|
|
1. Search tracked Go and Markdown files for the removed constant names,
|
|
|
|
|
framework `top_p` defaults, claims that all effective provider controls have
|
|
|
|
|
concrete framework values, and request-body inclusion rules. Correct only
|
|
|
|
|
stale statements or tests owned by this feature.
|
|
|
|
|
2. Confirm that `internal/profile/builtin/assets/` has no feature-related diff
|
|
|
|
|
and that its explicit nonzero optional controls still pass ordinary profile
|
|
|
|
|
validation and resolution tests.
|
|
|
|
|
3. Confirm that `internal/llm/openai_compatible_client.go` either has no diff or
|
|
|
|
|
contains only a change required by a focused failing contract test. The
|
|
|
|
|
default policy must remain outside the transport.
|
|
|
|
|
4. Follow every changed Markdown link and confirm its target exists. Verify
|
|
|
|
|
that current-state documents describe implemented behavior and that exact
|
|
|
|
|
contracts remain with GoDoc, the format reference, and the integration
|
|
|
|
|
contract.
|
|
|
|
|
5. Run the complete validation sequence below and repair only in-scope
|
|
|
|
|
failures.
|
|
|
|
|
6. After all checks pass, change the status of
|
|
|
|
|
`optional-request-parameters.md` and this document to `Complete`. Do not
|
|
|
|
|
change the status or contents of `fallback-profiles.md`.
|
|
|
|
|
7. Re-run `git diff --check` and inspect the final working tree and diff.
|
|
|
|
|
1. Add `fallbackProfiles` and `fallbackProfileSource` to `engineOptions`, then
|
|
|
|
|
implement `WithFallbackProfileFS` exactly as specified under Public API.
|
|
|
|
|
2. Extend `newProfileRepository` so it constructs the fixed four-layer chain
|
|
|
|
|
in the prescribed low-to-high order. Do not alter generic overlay logic or
|
|
|
|
|
add fallback branches to runner methods.
|
|
|
|
|
3. Update all affected `engine.go` GoDoc, including the option category list
|
|
|
|
|
and the relative precedence descriptions for existing profile sources.
|
|
|
|
|
4. Add and extend the external-package root tests exactly as specified under
|
|
|
|
|
Test Ownership. Reuse small existing fakes and fixture helpers where they
|
|
|
|
|
remain clear; add only minimal synthetic YAML helpers needed by these tests.
|
|
|
|
|
5. Extend `TestSourceOptionsRejectInvalidInputs` with the two fallback option
|
|
|
|
|
validation cases.
|
|
|
|
|
6. Update `docs/formats.md`, `docs/consumers/pkg-promptkit.md`,
|
|
|
|
|
`docs/internal/sources.md`, and `docs/internal/overview.md` according to
|
|
|
|
|
Canonical Documentation.
|
|
|
|
|
7. Run the focused validation below. Repair in-scope failures without
|
|
|
|
|
weakening existing parser, error-identity, prepared-execution, or profile
|
|
|
|
|
precedence guarantees.
|
|
|
|
|
|
|
|
|
|
Do not delete temporary roadmaps in this stage; retirement is a separate
|
|
|
|
|
maintainer action. Do not add release notes, change versions, or create a
|
|
|
|
|
commit, tag, push, or release.
|
|
|
|
|
Do not add a config field, in-memory fallback API, source provenance, profile
|
|
|
|
|
inheritance, provider failover, eager validation, application-specific assets,
|
|
|
|
|
or backend/model policy. Do not edit `internal/profile/builtin/assets/`.
|
|
|
|
|
|
|
|
|
|
### Focused Validation
|
|
|
|
|
|
|
|
|
|
Run from the repository root:
|
|
|
|
|
|
|
|
|
|
```sh
|
|
|
|
|
gofmt -w engine.go engine_test.go public_contract_test.go
|
|
|
|
|
go test . -run \
|
|
|
|
|
'Test(FallbackProfileSource|RepeatedOptionsUseLastValueInEachCategory|SourceOptionsRejectInvalidInputs)'
|
|
|
|
|
go test ./internal/profile/...
|
|
|
|
|
go test . ./internal/profile/... ./internal/usecase
|
|
|
|
|
go vet . ./internal/profile/... ./internal/usecase
|
|
|
|
|
git diff --check
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
The focused root expression must execute the precedence, lazy/error,
|
|
|
|
|
cross-workflow, repeated-option, and invalid-input coverage described above.
|
|
|
|
|
If the implemented names differ slightly, run explicit equivalent expressions
|
|
|
|
|
and record no skipped contract category.
|
|
|
|
|
|
|
|
|
|
### Completion Gate
|
|
|
|
|
|
|
|
|
|
Stage 2 is complete only when:
|
|
|
|
|
|
|
|
|
|
- `WithFallbackProfileFS` is the sole new public declaration and has complete,
|
|
|
|
|
accurate GoDoc;
|
|
|
|
|
- nil filesystem and blank root inputs fail construction with
|
|
|
|
|
`ErrInvalidConfig`, and the last valid repeated fallback option wins;
|
|
|
|
|
- the assembled order is in-memory, ordinary configured, application
|
|
|
|
|
fallback, built-ins;
|
|
|
|
|
- existing ordinary source options still replace `Config.ProfileDir`;
|
|
|
|
|
- lookup falls through only on a missing ID and never after a matching
|
|
|
|
|
higher-layer failure;
|
|
|
|
|
- profiles remain whole values and loading remains lazy;
|
|
|
|
|
- inspection, preparation, prepared execution, and ordinary execution resolve
|
|
|
|
|
the same fallback definition through one runner repository;
|
|
|
|
|
- no built-in asset, profile format, public error identity, provider request,
|
|
|
|
|
or existing consumer behavior changed unintentionally;
|
|
|
|
|
- GoDoc and all affected canonical documents describe implemented behavior
|
|
|
|
|
without duplicating ownership; and
|
|
|
|
|
- all focused tests, vet, formatting, links, and whitespace checks pass.
|
|
|
|
|
|
|
|
|
|
## Stage 3: Audit Compatibility And Validate The Repository
|
|
|
|
|
|
|
|
|
|
### Objective
|
|
|
|
|
|
|
|
|
|
Confirm that the implementation is complete, minimal, and consistent across
|
|
|
|
|
the public facade, internal boundaries, tests, and documentation, then mark
|
|
|
|
|
the temporary planning documents complete.
|
|
|
|
|
|
|
|
|
|
### Implementation Prompt
|
|
|
|
|
|
|
|
|
|
Implement only Stage 3 of `docs/roadmap/implementation.md` after Stage 2
|
|
|
|
|
satisfies its completion gate.
|
|
|
|
|
|
|
|
|
|
1. Search tracked Go and Markdown files for
|
|
|
|
|
`NewRepositoryWithPrimary`, `NewRepositoryWithDirectory`, profile source
|
|
|
|
|
precedence lists, and descriptions of built-in repository composition.
|
|
|
|
|
Remove stale references and correct only feature-owned contradictions.
|
|
|
|
|
2. Review `newProfileRepository` directly and confirm it has exactly four
|
|
|
|
|
possible layers in the required order, selects only one ordinary configured
|
|
|
|
|
source, and contains no profile field merging or eager I/O.
|
|
|
|
|
3. Review the public tests as a suite. Confirm that each distinct risk in Test
|
|
|
|
|
Ownership is protected once, generic parser and overlay cases remain with
|
|
|
|
|
`internal/profile`, and no test depends on private helper shape.
|
|
|
|
|
4. Confirm that `internal/profile/builtin/assets/`, external wire behavior,
|
|
|
|
|
backend configuration, credential resolution, public result shapes, and
|
|
|
|
|
stable JSON tags have no feature-related changes.
|
|
|
|
|
5. Follow every added or changed Markdown link and confirm that its target and
|
|
|
|
|
relevant heading exist. Verify that exact API details live in GoDoc, exact
|
|
|
|
|
profile format and precedence details live in `docs/formats.md`, consumer
|
|
|
|
|
guidance remains task-oriented, and internal documents describe only
|
|
|
|
|
implementation responsibility.
|
|
|
|
|
6. Run the complete validation sequence below and repair only in-scope
|
|
|
|
|
failures.
|
|
|
|
|
7. After every check passes, change the status of
|
|
|
|
|
`fallback-profiles.md` and this document to `Complete`. Do not delete or
|
|
|
|
|
retire either roadmap; retirement is a separate maintainer action.
|
|
|
|
|
8. Re-run `git diff --check`, inspect `git status --short`, and review the full
|
|
|
|
|
diff while distinguishing pre-existing user changes from this feature.
|
|
|
|
|
|
|
|
|
|
Do not add release notes, change versions, or create a commit, tag, push, or
|
|
|
|
|
release during this stage.
|
|
|
|
|
|
|
|
|
|
### Full Validation
|
|
|
|
|
|
|
|
|
|
Run from the repository root:
|
|
|
|
|
|
|
|
|
|
```sh
|
|
|
|
|
gofmt -w internal/defaults/defaults.go types.go engine_test.go \
|
|
|
|
|
internal/usecase/runner_test.go
|
|
|
|
|
gofmt -w engine.go engine_test.go public_contract_test.go \
|
|
|
|
|
internal/profile/builtin/repository.go \
|
|
|
|
|
internal/profile/builtin/repository_test.go
|
|
|
|
|
gofmt -l $(git ls-files '*.go')
|
|
|
|
|
go test ./...
|
|
|
|
|
go test -race ./...
|
|
|
|
|
@@ -345,34 +469,34 @@ offline and require no real credential or provider.
|
|
|
|
|
Inspect the final diff and confirm:
|
|
|
|
|
|
|
|
|
|
- only this feature's files and pre-existing user changes are present;
|
|
|
|
|
- no built-in profile asset, public declaration shape, stable JSON tag,
|
|
|
|
|
credential rule, workspace file, local module replacement, generated binary,
|
|
|
|
|
or unrelated formatting changed;
|
|
|
|
|
- the removed provider-default constants have no remaining references;
|
|
|
|
|
- the provider omission policy is implemented by resolution plus the existing
|
|
|
|
|
generic serializer, not by a `top_p` transport special case;
|
|
|
|
|
- the optional-parameter roadmap and this plan are complete while the fallback
|
|
|
|
|
roadmap remains selected; and
|
|
|
|
|
- no built-in asset, public value shape, stable JSON tag, provider payload,
|
|
|
|
|
workspace file, local module replacement, generated binary, or unrelated
|
|
|
|
|
formatting changed;
|
|
|
|
|
- deleted built-in composition helpers have no remaining references;
|
|
|
|
|
- the fallback option reuses the ordinary FS repository and generic overlay;
|
|
|
|
|
- the root constructs one repository used by every resolution workflow;
|
|
|
|
|
- the feature roadmap and this plan are both complete; and
|
|
|
|
|
- no commit, tag, push, or release was created.
|
|
|
|
|
|
|
|
|
|
### Completion Gate
|
|
|
|
|
|
|
|
|
|
The implementation is complete only when:
|
|
|
|
|
|
|
|
|
|
- every Stage 1 gate remains satisfied;
|
|
|
|
|
- every Stage 1 and Stage 2 gate remains satisfied;
|
|
|
|
|
- the ordinary and race-enabled suites pass;
|
|
|
|
|
- vet, build, formatting, the maintained offline example, Markdown links, and
|
|
|
|
|
whitespace checks pass;
|
|
|
|
|
- public metadata, injected-client presence, profile inheritance, and outbound
|
|
|
|
|
omission semantics are mutually consistent;
|
|
|
|
|
- explicit built-in and consumer profile values retain their behavior;
|
|
|
|
|
- both feature-specific roadmap statuses are `Complete`;
|
|
|
|
|
- `fallback-profiles.md` remains unchanged and selected for later work; and
|
|
|
|
|
- the four-layer precedence and not-found-only fallthrough are consistent in
|
|
|
|
|
code, GoDoc, public tests, format reference, consumer guidance, and internal
|
|
|
|
|
documentation;
|
|
|
|
|
- engines without `WithFallbackProfileFS` retain their previous behavior;
|
|
|
|
|
- the public surface contains no speculative companion API or provenance;
|
|
|
|
|
- both temporary roadmap statuses are `Complete`; and
|
|
|
|
|
- the repository is ready for maintainer review without a commit or release
|
|
|
|
|
having been created by this plan.
|
|
|
|
|
|
|
|
|
|
## Open Questions
|
|
|
|
|
|
|
|
|
|
None. The feature roadmap and fixed design above fully specify the behavior,
|
|
|
|
|
compatibility boundary, implementation, documentation ownership, and test
|
|
|
|
|
strategy.
|
|
|
|
|
None. The feature roadmap and fixed design above fully specify the public API,
|
|
|
|
|
repository composition, error and validation behavior, compatibility boundary,
|
|
|
|
|
documentation ownership, test strategy, and staged implementation sequence.
|
|
|
|
|
|