You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Make applySavedModelConfig fail closed when the shared saved-routing authority reports an invalid source. This is the apply-safety slice after #389. It owns only invalid-config propagation through the existing apply and startup path and the profile safety proof. Missing and valid behavior remains unchanged. Direct export migration and export contract tests are owned by #395 and are not changed here.
Initial labels: create directly with enhancement and status:approved.
Approval and dependency: approval is limited to this exact scope. Implementation remains dependency-blocked until refactor(models): isolate saved-routing read authority #389 merges and the resulting main base is revalidated. Approval grants no authority to commit, push, publish a PR, merge, or approve a later slice.
Dependency diagram:
main
└─ #389 shared types/normalization, sync/async authority, compatibility wrappers
└─ 📍 #396 fail-closed apply and profile safety
└─ #395 direct export contract/tests plus UI/lifecycle consumers
└─ #391 canonical names and target authority
└─ durable write
└─ materialization
Treat an invalid authority result as a hard stop for apply. Preserve its invalid status and source path through the existing observable error or result contract, do not downgrade it to {} or treat it as missing, and do not continue to profile mutation.
Preserve invalid-global no-fallback behavior from the shared authority. An invalid global source must not select a project source or reach apply as an empty configuration.
Preserve existing behavior for missing and valid sources, including current source selection, apply behavior, startup reachability, target and path semantics, writes, profile materialization, JSON null behavior, literal string inherit behavior, and omission semantics.
Keep the real apply and startup callers production-reachable. Exercise the existing production path, not a test-only export, fake caller, or replacement startup path.
On an invalid apply, prove that an existing profile file is byte-identical, its modification time is unchanged, and no profile write operation is attempted. Keep unrelated profile fields unchanged as part of the byte-level proof.
Explicitly create every test fixture directory before writing fixtures, including any root/agents directory used by discovery-adjacent tests.
No durable saved-config write algorithm, temporary-file policy, cleanup, rename outcome, or directory durability.
No profile materialization, frontmatter rewrite, inherit-by-omission, profile-field deletion, or unrelated profile-field behavior change. The profile test is a no-write safety proof only.
No automatic branch rewrite, commit, push, PR publication, merge, or approval of a later slice.
Strict TDD and verification
Strict TDD is required. The RED phase must be an executable assertion-level failure after dependency hydration, not a missing-module or environment error. The current governance snapshot records assertion-level RED and focused GREEN 4/4 for the combined candidate only. It is not issue completion evidence for this apply-safety slice. The implementation PR must report its own observed evidence before claiming completion.
Environment prerequisite: use an authorized implementation environment with dependencies hydrated by the repository package manager, pnpm@11.1.1, including @earendil-works/pi-tui.
Run the focused and package-supported commands after the behavior tests exist:
node --experimental-strip-types --test tests/model-routing-authority.test.ts
node --experimental-strip-types --test tests/gentle-ai.test.ts
pnpm test
RED: add the smallest assertions for invalid project JSON, a non-object project configuration, invalid authority results through apply, invalid-global no-fallback, unchanged profile bytes and modification time, and no profile write before implementation. Record the observed assertion-level failures after dependencies are available.
GREEN: route only the real apply and startup path through the authority's invalid result and stop before profile mutation, while preserving missing and valid behavior. Record the focused test result.
TRIANGULATE: cover missing, valid, and invalid global/project sources, sync and async authority parity as consumed by apply, real apply and existing startup paths, invalid-source no-fallback, profile byte and modification-time preservation, no-write instrumentation, literal string inherit, JSON null, omissions, existing target and path semantics, and explicit fixture-directory creation.
REFACTOR: remove superseded apply fallback handling without changing behavior, then rerun the focused commands and check-only syntax validation.
Review workload forecast and hard stop
Forecast only, measured against the clean immediate main base after #389 merges: 95 lower / 145 realistic / 220 upper A+D. The hard stop is above 400 A+D. No size:exception is permitted. If the clean diff exceeds 400, stop before publication and return to design for another causal split. Do not line-golf the diff or remove the profile safety tests.
Outcome
Make
applySavedModelConfigfail closed when the shared saved-routing authority reports an invalid source. This is the apply-safety slice after #389. It owns only invalid-config propagation through the existing apply and startup path and the profile safety proof. Missing and valid behavior remains unchanged. Direct export migration and export contract tests are owned by #395 and are not changed here.Chain context
mainfirst. Revalidate the resultingmainbefore starting this issue. The stopped combined candidate and PR refactor(models): centralize routing persistence authority #385 evidence are not implementation bases./gentle:models, session-start reporting and wiring, and/gentle:status. refactor(models): enforce canonical routing names and target authority #391 follows refactor(models): migrate routing UI and lifecycle consumers #395 and enforces canonical names and explicit target authority. Durable write and materialization remain later slices.main. Use stacked-to-main delivery. The PR diff must contain only this fail-closed apply and profile-safety unit.enhancementandstatus:approved.mainbase is revalidated. Approval grants no authority to commit, push, publish a PR, merge, or approve a later slice.Dependency diagram:
Scope and acceptance criteria
applySavedModelConfigpath. Do not duplicate read, fallback, or invalid-source handling.{}or treat it as missing, and do not continue to profile mutation.nullbehavior, literal stringinheritbehavior, and omission semantics.root/agentsdirectory used by discovery-adjacent tests.Intentionally out of scope
/gentle:modelshandler, session-start consumer, or/gentle:statusreporting. Those consumers belong to refactor(models): migrate routing UI and lifecycle consumers #395.nullchange, literal stringinheritchange, omission-semantics change, provider/model discovery change, headless-contract change, packaging change, or changes to refactor(models): share safe routing persistence authority #382, feat(models): expose a machine-readable routing contract #381, feat(models): add headless inspect and validate contract #383, or feat(models): add apply CLI and package executable #384.Strict TDD and verification
Strict TDD is required. The RED phase must be an executable assertion-level failure after dependency hydration, not a missing-module or environment error. The current governance snapshot records assertion-level RED and focused GREEN 4/4 for the combined candidate only. It is not issue completion evidence for this apply-safety slice. The implementation PR must report its own observed evidence before claiming completion.
Environment prerequisite: use an authorized implementation environment with dependencies hydrated by the repository package manager,
pnpm@11.1.1, including@earendil-works/pi-tui.Run the focused and package-supported commands after the behavior tests exist:
inherit, JSONnull, omissions, existing target and path semantics, and explicit fixture-directory creation.Review workload forecast and hard stop
Forecast only, measured against the clean immediate
mainbase after #389 merges: 95 lower / 145 realistic / 220 upper A+D. The hard stop is above 400 A+D. Nosize:exceptionis permitted. If the clean diff exceeds 400, stop before publication and return to design for another causal split. Do not line-golf the diff or remove the profile safety tests.