Skip to content

refactor(models): isolate fail-closed saved-routing apply #396

Description

@decode2

Outcome

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.

Chain context

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

Scope and acceptance criteria

  • Consume the status-carrying authority delivered by refactor(models): isolate saved-routing read authority #389 from the existing applySavedModelConfig path. Do not duplicate read, fallback, or invalid-source handling.
  • 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.

Intentionally out of scope

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requeststatus:approvedIssue approved by maintainer; PR may be opened

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions