Context
T2.12 of the harness pillar (#13349). The pipeline's mutation half is fully built and PROVEN but has no intake: resolveTarget (registry: by-id / by-title / latest-live), validateMutation (merge-then-validate — mutation-valid ⇔ merged-result-creation-valid), and mutateInstance (batched set() apply + registry markMutated) all merged. This leaf is the intake: a follow-up natural-language intent becomes {target selector, mutation partial}.
The Fix
- AMENDED (operator product-ruling on PR #14821 + spec-owner correction — the original clause below inverted the product): the mutation intake is the SAME injected model boundary as creation:
{request, currentBlueprint, generate} → the model reasons over the request AND the target's CURRENT blueprint (plus the schema's allowlist vocabulary, derived from the registry never duplicated) → returns a mutation partial → validateMutation merge-then-validates as the sole gate. NL is the product surface — a frontier model can express any mutation the validator can gate; a keyword→constant menu is the Tailwind-class anti-pattern (a fixed token vocabulary impersonating an expressive medium). A deterministic grammar may exist ONLY as the unshippable test seam (the wedge's deterministicBlueprintFallback pattern) and, if present, must be RELATIVE to current state (factors), never absolute constants — 'taller' on a 700px grid must never shrink it. Original clause (superseded): a parse step generalizing the childapp grammar with bounded intent classes → allowlisted partials. The childapp grammar is the contamination source, not the precedent — #14767's retirement direction reverses accordingly (retire INTO the model boundary).
- Target resolution phrases →
resolveTarget selectors: an explicit title match ("the sales grid") → {title}, otherwise latest-live (the "THE GRID" case). Ambiguity (two live matches by title) = a bounded refusal naming both candidates, never a guess.
- The wedge controller wires it behind the same submit affordance when the flow state is
materialized (the SSOT's follow-up affordance): intent → parse → resolve → mutateInstance → the provider's flow events. Refusals render with reasons, per the SSOT's always-a-reason bar.
Acceptance Criteria
Out of Scope
Dispose intents (the chrome affordance covers dispose) · streaming previews. NL-model parsing is NO LONGER out of scope — it IS the scope (the amendment above); the deterministic seam ships only as a test double.
Related
Parent #13349 (T2.12) · the registry + accept path (merged) · the wedge (PR #14727) · the childapp grammar (the precedent) · #14644 §4 (mutations under the same contract).
Claimable — non-Fable implementable; the pipe exists end to end, this is the intake parse + wiring.
Origin Session ID: b9b95ac6-42f5-47a3-b58f-6071f79657e8
Retrieval Hint: "keeper mutation grammar follow-up intent resolveTarget make grid bigger parse edit request"
Context
T2.12 of the harness pillar (#13349). The pipeline's mutation half is fully built and PROVEN but has no intake:
resolveTarget(registry: by-id / by-title / latest-live),validateMutation(merge-then-validate — mutation-valid ⇔ merged-result-creation-valid), andmutateInstance(batchedset()apply + registrymarkMutated) all merged. This leaf is the intake: a follow-up natural-language intent becomes{target selector, mutation partial}.The Fix
{request, currentBlueprint, generate}→ the model reasons over the request AND the target's CURRENT blueprint (plus the schema's allowlist vocabulary, derived from the registry never duplicated) → returns a mutation partial →validateMutationmerge-then-validates as the sole gate. NL is the product surface — a frontier model can express any mutation the validator can gate; a keyword→constant menu is the Tailwind-class anti-pattern (a fixed token vocabulary impersonating an expressive medium). A deterministic grammar may exist ONLY as the unshippable test seam (the wedge'sdeterministicBlueprintFallbackpattern) and, if present, must be RELATIVE to current state (factors), never absolute constants — 'taller' on a 700px grid must never shrink it.Original clause (superseded): a parse step generalizing the childapp grammar with bounded intent classes → allowlisted partials.The childapp grammar is the contamination source, not the precedent — #14767's retirement direction reverses accordingly (retire INTO the model boundary).resolveTargetselectors: an explicit title match ("the sales grid") →{title}, otherwise latest-live (the "THE GRID" case). Ambiguity (two live matches by title) = a bounded refusal naming both candidates, never a guess.materialized(the SSOT's follow-up affordance): intent → parse → resolve →mutateInstance→ the provider's flow events. Refusals render with reasons, per the SSOT's always-a-reason bar.Acceptance Criteria
mutateInstanceapplies the merged blueprint → registry snapshot updated (consuming the validator's returned merged blueprint — no hand-merging, the recorded rule).Out of Scope
Dispose intents (the chrome affordance covers dispose) · streaming previews. NL-model parsing is NO LONGER out of scope — it IS the scope (the amendment above); the deterministic seam ships only as a test double.
Related
Parent #13349 (T2.12) · the registry + accept path (merged) · the wedge (PR #14727) · the childapp grammar (the precedent) · #14644 §4 (mutations under the same contract).
Claimable — non-Fable implementable; the pipe exists end to end, this is the intake parse + wiring.
Origin Session ID: b9b95ac6-42f5-47a3-b58f-6071f79657e8 Retrieval Hint: "keeper mutation grammar follow-up intent resolveTarget make grid bigger parse edit request"