Repository navigation
Providers phase 3a: open condition snapshot union, policy-driven selectors, ungated resolution - #403
Merged
Conversation
…selectors, ungated resolution The conditions system was the last closed provider surface (#394 phase 3 / §5). Three changes, none touching the vendored conditions-core slice (no submodule churn): 1. ProviderConditionSnapshot opens from the closed ClaudeConditionSnapshot | CodexConditionSnapshot union to the generic { provider: AgentProviderKind; conditions: Partial<Record<string, ProviderConditionRecord>>; ts } shape — mirroring conditions-core's ConditionSnapshot<P>, which was already generic. Condition kinds are globally namespaced (<provider>.<kind>), so kind-keyed access was always provider-safe; the union bought nothing except closure (a third provider couldn't TYPE a snapshot without editing the file). The per-provider specializations remain as the shapes the provider session event maps emit; the new conditionStateByKind<S>() helper is the one sanctioned typed lookup. Wire format unchanged. 2. workspace/conditions/selectors.ts becomes generic loops over a new conditionPolicy on RendererProviderCapabilities (attention set, action set, priority-ordered label rules, composer picker kind) — the exact deferred seam docs/design/conditions-system.md called out ("the migration is a deletion, not a re-derivation"). Policies live in providers/<kind>/renderer/conditions/policy.ts. WHY data, not derivation from views' attention() fns: the sets and views deliberately disagree (AUQ is attention-worthy with NO view; compaction has a view but is excluded from the set). applyConditionSnapshot's two-provider fork becomes kind-keyed derivation for the same reason; the pending* mirrors stay (still documented for deletion; pendingCompaction + picker remain the only live consumers). 3. sessionManager.resolveCondition drops its claude-only gate. A provider that implements AgentSession.resolveCondition previously dead-ended in 'no-session' at the manager; now any agent kind routes through, and one WITHOUT a resolver (Codex today — its approvals answer via raw keystrokes) truthfully returns 'no-resolver' from the existing capability check. Also: TileLeaf's AUQ extraction and the debug module's two copies use conditionStateByKind instead of snapshot-level provider narrowing; the outlet's Partial→dense-Record erasure is the one sanctioned cast (same role as eraseRegistry). NOT in this slice (3b): structured actions replacing raw keystrokes, Codex-side resolveConditionAction parity (a codex-headless submodule change), and pending*-mirror deletion. Verified: tsc clean on both projects, electron-vite build clean, vitest 170/170 — including selectors.test.ts against the policy-driven rewrite. Part of #394. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Part of #394 (phase 3, slice a). Deliberately avoids the vendored conditions-core slice — no submodule churn.
ProviderConditionSnapshot→ generic{provider: AgentProviderKind; conditions; ts}(kinds are globally namespaced, so kind-keyed access was always provider-safe);conditionStateByKind<S>()is the sanctioned typed lookup. Per-provider specializations remain for the session event maps. Wire format unchanged.conditionPolicycapability (attention set / action set / ordered label rules / picker kind, inproviders/*/renderer/conditions/policy.ts);selectors.tsloses its hardcoded kind lists andprovider === 'claude'branches — the exact deferred seam the design doc named.applyConditionSnapshot's fork becomes kind-keyed derivation.sessionManager.resolveConditiondrops the claude-only gate; any agent kind routes to its session's resolver, absent resolvers truthfully returnno-resolver.Not in this slice (3b): structured actions, Codex resolver parity (codex-headless submodule work), pending*-mirror deletion.
Verified: tsc both projects, build, vitest 170/170 (incl.
selectors.test.tsagainst the rewrite).🤖 Generated with Claude Code