Per the imccyu review, the pre-existing goal, permissions, and plan units
go back to registering through the ctx.inject(['sessionProjections'], …)
child form instead of the required-inject direct register; goal returns to
zero diff (its service never reads projections). The mandatory-seam rework
for these three sites moves to a follow-up PR. New projection units keep
the required-inject direct-register form.
Regenerated catalog and subsystem docs follow the reverted service
signatures.
Reconcile the base's persist removal and later master content with the
migration branch: keep 2742's wireOnly read options, the host-inclusive
snapshot/viewCheckpoint/restore defaults, and the drive's late-event
replay (applyToCell) that bare-session reads rely on.
The note was committed on 2026-08-19 but filed under 2026-08-07 while
building on the 08-19 state-and-client-views note; rename the triplet to
align the filename with the actual date and update the inbound
architecture links.
Adapts this branch to the base's removal of the persist opt-in: the
registry folds and checkpoints every registered unit, the host-only
subagent identity drops its explicit persist: true, and the
state-and-client-views note records the uniform rule. The cordis API
catalog and session-projection subsystem signatures are regenerated.
The titleInput unit no longer retains the full eligible message history
in bounded reverse-linked chunks. It folds only {first, last, count} —
the values scheduling and fallback reads need — and the full eligible
prefix for one provider generation is scanned from the session log at
execution time. The projection state is O(1) per session instead of
growing with every user message.
The README description updates accordingly and drops the inaccurate
"latest request route" claim; the projection test now asserts the
bounded aggregate and its checkpoint row.
Drop the persist?: boolean opt-in: every unit's state — client-visible and
host-only alike — is now written to the projection cache. A unit can no
longer silently skip the durable cache, host-only units no longer need an
explicit flag to participate in cold restore, and the persist-sharing
conflict check disappears with the field.
- ProjectionDefinition/ErasedDefinition lose persist; register overloads
simplify; checkpoint/restoreFloor/restore fold every registered unit.
- Registry and cache tests drop the persist:true fixtures and the
persistence-policy sharing test.
- READMEs and the state-and-client-views note record the uniform rule;
cordis API catalog and subsystem signatures regenerated.
The upstream-type proof only ran covariantly, so it caught a profile
field wider than pi-ai's but not one narrower — the direction its own
JSDoc claimed to guard. It now asserts both directions; the reverse holds
today because every field is either derived from upstream or a boolean.
`ModelCompat` gained `BedrockCompat`, which the gate had already started
serving, and the per-field protocol lists now match what the gates
resolve: `docs/config-catalog.md` pastes that JSDoc verbatim, so a stale
list there contradicted the README in the same change. The interface
header names the Responses grouping, since a catalog reader never sees
the README passage that explains it.
Valueless keys are judged after the name, so a withheld or misspelled key
written bare is refused for being that name rather than sent back for a
value it would be refused with anyway; the remedy no longer promises an
installed catalog value that a hand-declared route does not have. The
check covers `undefined` beside `null`: schemastery keeps the key either
way, and a cordis.yml entry reaches that state through `!!js undefined`,
so it is a config boundary rather than a typed one.
Coverage follows the composed path: the rejection is asserted through a
written settings section, and a switch is carried from that section onto
the wire a provider receives.
Refs #2646
The full switch list already exists and is generated from source, so the
guide needs a way in rather than a copy: `config-catalog.md` carries 107
plugin sections, and linking the whole file leaves a reader to find the
one that configures the page they are on. Both mentions now deep-link the
`dsh-llm-pi-ai` anchor.
Refs #2646
The Models page has no field for `compat`, and the symptom it addresses —
a gateway holding a working key at a reachable address while refusing
every request — reads as a credential or connectivity problem. Give it
the same treatment `input` already has: name the symptom, show the two
switches that account for most of it, and state the resolution order.
Refs #2646
Review found two live defects in the compat surface.
A valueless key (`supportsDeveloperRole:`) survives schemastery as null,
and resolution carried it forward as a configured value. It landed on
`Model.compat` as null, which replaced the installed catalog entry's
value and left pi-ai's `??` reaching for its baseURL detection — the
catalog layer skipped entirely, and the switch written but not applied.
The vocabulary check now refuses it where it is written, matching the
`reasoningEfforts` precedent in the same file.
The gates were keyed by protocol name, but pi-ai keys compat by type:
`openai-responses`, `azure-openai-responses`, and `openai-codex-responses`
share one `OpenAIResponsesCompat`, so two shipped catalog routes were
refused the fields their own models declare. Gates now group by compat
type, `bedrock-converse-stream` gains its own, and the protocol set is
derived from `Model.compat`'s conditional so a release that gives a
further protocol a compat type fails the gate list by name.
Field types are derived from upstream rather than restated, with a proof
pinning the profile assignable to the upstream types, so a widened value
union cannot silently narrow what configuration accepts.
The `undefined` filter stays removed: `exactOptionalPropertyTypes` keeps
a typed caller from writing one, and schemastery never materializes one,
so it was validation for a value the static interface already excludes.
Refs #2646