From 8a8e906a79ce750171d83e24f387314e7f8c5ad3 Mon Sep 17 00:00:00 2001 From: Lu Nelson Date: Mon, 24 Aug 2026 22:35:39 +0200 Subject: [PATCH] docs(brunch-agent): rehearse elicitation completion Define a version-bound read-time completion contract and replay it over every FE-1361 transcript prefix. Keep completion distinct from stopping, delivery, no progress, budget exhaustion, and licensed deferral. Review dispositions: corrected source timing and replay evidence, split occurrence from repair clauses, removed speculative/persisted state, preserved conservative divergence, and retained SPEC-LEDGER pending status until runtime proof exists. Verified: lint, typecheck, 128 unit tests, build, docs-index 7/7, diff check; contract, replay, and legibility reviews PASS. --- libs/@hashintel/brunch-agent/docs/INDEX.md | 3 + .../brunch-agent/docs/control/SPEC-LEDGER.md | 2 +- .../design/elicitation-completion-plain.md | 141 +++++++ .../elicitation-completion-rehearsal.md | 378 ++++++++++++++++++ .../docs/specs/elicitation-completion.md | 339 ++++++++++++++++ .../docs/specs/plugin-contract.md | 18 +- 6 files changed, 877 insertions(+), 4 deletions(-) create mode 100644 libs/@hashintel/brunch-agent/docs/evidence/proofs/design/elicitation-completion-plain.md create mode 100644 libs/@hashintel/brunch-agent/docs/evidence/proofs/design/elicitation-completion-rehearsal.md create mode 100644 libs/@hashintel/brunch-agent/docs/specs/elicitation-completion.md diff --git a/libs/@hashintel/brunch-agent/docs/INDEX.md b/libs/@hashintel/brunch-agent/docs/INDEX.md index c62e8382c15..7f44e83bdca 100644 --- a/libs/@hashintel/brunch-agent/docs/INDEX.md +++ b/libs/@hashintel/brunch-agent/docs/INDEX.md @@ -70,6 +70,9 @@ control loop is [`docs/agents/steering.md`](agents/steering.md). | [notes/deep-read-fe-1389](evidence/proofs/audits/deep-read-fe-1389.md) | active | FE-1401 / findings in FE-1420 | Deep-read of the walking skeleton: builder's account, spec-discharge table (issues 10/13 capabilities discharged; markdown floor contradicted in the UI), 12 findings; source of PR #10's backfilled record | | [notes/deep-read-fe-1390](evidence/proofs/audits/deep-read-fe-1390.md) | active | FE-1401 / probes on FE-1419 | Deep-read of the capture store: spec-discharge table, write-time tiering assessment (penciled item 7), the FE-1405 status-arity answer, and live-probed confirmation of FE-1419's capture-store claims plus one new aliasing hole; source of PR #11's backfilled record | | [plugin-contract-spec](specs/plugin-contract.md) | active | FE-1431 (spec issue); decided on FE-1405; amended by FE-1480 | Provisional spec: a plugin is two schemas and two tables over the three-register IR; code-bearing projections add a deterministic scaffold, typed obligation sidecar, and loss report before downstream realization; strains 4–7 and envelope pressure #2 remain open | +| [elicitation-completion](specs/elicitation-completion.md) | active | FE-1402 | Normative provisional read-time contract: version-bound presence/slot demand algebra, universal active-objective support, evidence-bearing boolean report, conservative divergence diagnostic, and pure deferral licensing over existing authoritative surfaces | +| [elicitation-completion-rehearsal](evidence/proofs/design/elicitation-completion-rehearsal.md) | active | FE-1402; inputs FE-1403/FE-1404/FE-1431 | Manual clause-level replay over all 44 FE-1361 prefixes using a versioned provisional CPS DemandTable, separate failure-occurrence/repair clauses, evidence-proxy deltas with carry-forward, C1-E09 no progress, C2 ramp scrap, and successor evidence | +| [elicitation-completion-plain](evidence/proofs/design/elicitation-completion-plain.md) | active | FE-1402 legibility snapshot | Reviewer-facing plain-language rendering of version-bound completion, presence versus slot checks, conservative divergence, stopping/delivery boundaries, and read-time deferral licensing without new persistence | ## Control, architecture reference, and migration archive diff --git a/libs/@hashintel/brunch-agent/docs/control/SPEC-LEDGER.md b/libs/@hashintel/brunch-agent/docs/control/SPEC-LEDGER.md index cf41809f068..3e212155bad 100644 --- a/libs/@hashintel/brunch-agent/docs/control/SPEC-LEDGER.md +++ b/libs/@hashintel/brunch-agent/docs/control/SPEC-LEDGER.md @@ -88,7 +88,7 @@ states. | Per-session state = evidence log, swept high-water mark, pending-affordance slot | §9.2 | **discharged** | pending slot (FE-1389), durable session-log archive (FE-1391), and FE-1392's parse-validated high-water/last-judged bookkeeping under one `sweepHighWater` state slot | | Re-entry briefing; user-visible insertion notice | §9.3 | **pending** | signal carrier proved; no briefing; the one injected signal is filtered out of the UI. Owned by FE-1396 | | Only the true user's side is evidence; injected entries structurally non-user | §9.4 | **partial** | FE-1391 verifies role/purpose against the public projection, refuses signal/advisory text, and classifies affordance replies only from the harness-owned reply-binding signal. The kickoff remains a machine-authored `user` entry until FE-1420/FE-1385 move it to `useInitialData`; FE-1396 still owns briefing-never-evidence | -| Completion derived, never a gate | §9.5 | **pending** | — | +| Completion derived, never a gate | §9.5 | **pending** | FE-1402 defines completion as a version-bound, read-time derivation over demand clauses and active-objective evidence in [`elicitation-completion.md`](../specs/elicitation-completion.md), then manually replays every prefix of both FE-1361 transcripts in [`elicitation-completion-rehearsal.md`](../evidence/proofs/design/elicitation-completion-rehearsal.md). No progress, stopping, durable delivery, and deferral licensing remain distinct from completion; runtime implementation and mounted proof remain open. | | Storage port: harness-defined, binding-implemented, plugin-blind (C1) | §9.6 | **discharged for the local target** | core owns capture/archive/anchoring semantics; `binding-flue` owns the file implementation; plugins cannot import the binding (FE-1390 + FE-1391) | | Port scope includes the session-log archive | §9.6 | **discharged** | FE-1391 provisions a versioned target-document record containing capture state and session logs, migrates the legacy capture-only shape on mutation, parses both halves on read, identity-versions evolving messages, and retrieves every cited ordinal independently of Flue | | Compaction vs. durable log | §9.7 | **partial — source-settled, behavioral pin open** | Flue 2.0.3's append-only stream contract and implementation show compaction appends a canonical record, rewrites only model context, preserves the public message projection, and leaves `state_write` reduction untouched. The source-read record reshapes FE-1386 to one upgrade pin; `test/open-gaps.ts` remains until behavioral proof lands | diff --git a/libs/@hashintel/brunch-agent/docs/evidence/proofs/design/elicitation-completion-plain.md b/libs/@hashintel/brunch-agent/docs/evidence/proofs/design/elicitation-completion-plain.md new file mode 100644 index 00000000000..336e1e1f987 --- /dev/null +++ b/libs/@hashintel/brunch-agent/docs/evidence/proofs/design/elicitation-completion-plain.md @@ -0,0 +1,141 @@ +# Completion without pretending the conversation is finished + +This is the plain-language rendering of the provisional +[target-document completion contract](../../../specs/elicitation-completion.md). The specification +is the required-behavior authority. This rendering is a legibility check: it explains the same +rules without the declaration notation and records where that translation strained. + +## The short version + +Brunch does not decide that a model is complete because the interview went well, the user left, a +turn limit fired, or an artifact was delivered. It decides by looking at the model it has derived +from durable evidence and asking whether that model can answer the user's active objectives to the +depth the plugin requires. + +The answer is recalculated from one target-document revision and one immutable plugin/demand-table +version. It is a boolean plus an explanation. The target-document stays editable either way; a +changed document or changed demand version requires a new calculation. + +## What gets checked + +Every plugin declares a small permanent floor. The provisional process-model replay uses separate +existence/count checks for objectives, entities, activities, and a process path, then checks the +path's sequence at the required grade. Existence is not faked by asking a slot-only rule to select +something. + +The plugin also declares what different objectives need. A breakdown-reshuffle question needs line +capabilities, calendars, failure occurrence, repair duration, and the rules used when resources +conflict. +An idle-versus-washdown question needs release rules, changeover behavior, lateness consequences, +and the scrap caused by changing family. A split-run question also needs minimum run sizes and the +extra changeover and scrap paid by every split. + +There are two requirement forms. A presence rule says how many model nodes a scope must select. A +slot rule says four important things: + +1. which model slots it applies to; +2. how specific the answer must be; +3. which kinds of evidence are allowed to support it; and +4. whether any explicit kind of absence counts as a legitimate answer. + +The check fails if a slot rule finds no applicable slot. Separately, every active objective must +match at least one demand row. This matters because neither an empty search nor an unknown +objective may look like perfect coverage. + +## What counts as an answer + +A stated value counts only if it is specific enough, is supported by active evidence, and has an +allowed evidence status. A guess does not become user evidence because it is precise. Confidence +does not substitute for specificity. + +An explicit absence can count only when the plugin says that exact absence answers the question. +“Not applicable” may be a complete answer for some slots. “We will find out tomorrow” normally is +not. A fact that was never mentioned cannot be turned into an absence after the fact. + +An unresolved conflict does not count. The current `diverged` shorthand for prescribed versus +practiced behavior does not expose each side's grade and support, so a demanded diverged slot also +fails conservatively as unevaluable. FE-1431 must first make both constituents inspectable before a +plugin can choose a later “both sides” or “either side” rule. The explanation names every selected +coordinate, capture, issue, and reason behind the result. + +## What happens when the user must leave + +The user can always stop a session. That does not make the model complete and it does not make the +stop a failure. + +Brunch should give the user the best useful result it can produce now. It should show the gaps, +save the evidence and open work through the authorities that already own them, and stop asking +questions. If work will continue later, the session controller computes a licensing report. It +checks the exact capture-store revision and located issues or absences; the archived session log, +swept high-water mark, and unswept tail; the existing pending-affordance slot; and a durable +projection reference. Each blocker must point either to an existing model coordinate or, when no +node was selected, to the unresolved clause and scope. Missing or stale facts make licensing fail. +The report binds everything it inspected but is not itself stored as target-document truth. + +No current authoritative record can promise an undelivered result with a durable reason, owner, +and next action. For now Brunch can license deferral only after it has actually emitted the best +current projection durably. A future undelivered-delivery obligation needs an approved durability +owner; it cannot be smuggled into an issue or a new completion record. + +The order is concrete: settle and sweep what can be settled, archive the session and any bounded +tail, recompute completion, locate every blocker, deliver durably, validate the re-entry and pending +affordance facts, compute the report, and only then quiet. Re-entry reloads those same authorities +and recomputes instead of consuming a new deposit record. + +Delivery is separate too. Brunch may deliver an incomplete model with visible loss. It may also +compute that the evidence is complete before the requested artifact has been delivered. The +controller should react to those facts, but it cannot use one to manufacture the other. + +## How the two baseline runs fail + +Condition 1 confirmed useful scheduling-policy evidence at E06. E07 and E08 then added no demanded +material, and at E09 a time-pressure cue was followed by interviewer-initiated stopping. The +rehearsal's third-prefix rule therefore raises no-progress at E09, before the eleven interviewer +turns E10-E20 spent saying goodbye, parking the thread, and exchanging acknowledgements. It should +have forced a choice: deliver the caveated model, ask a materially different question, save and +defer, or stop. It should not have declared completion. When forced wrap finally demanded the +model, the model appeared immediately, exposing a delivery stall rather than proving an absence of +generative capability. + +Condition 2 did better interviewing and produced a polished final specification. It still never +asked about ramp scrap. Ramp scrap matters to the idle-versus-washdown and split-run objectives, so +the plugin's demand exposes the hole even though the interviewer never listed it. The artifact's +claims that it is complete and runnable do not participate in the calculation. + +Both runs proposed future work. On the real architecture, multiple sessions are valid. In these +baseline runs, however, the best current projection had not been durably delivered before quieting, +and the required archive/high-water/blocker/pending-affordance facts were not available as one +validated read. The deferrals were therefore unlicensed, not because planning a later session is +inherently wrong. + +## Failure boundaries a reviewer can inspect + +- A stop, a delivery, a quiet request, a budget limit, and a no-progress signal each leave the + completion boolean untouched. +- Every active objective must have a plugin demand row. +- Presence clauses must meet their cardinality; slot clauses must select at least one real slot. +- Required slots must meet both evidence-status and grade rules. +- Never-asked ramp scrap keeps condition 2 incomplete. +- The rehearsal-only no-progress advisory begins at C1-E09 and never fires in condition 2; it + requests adjudication and never supplies a positive completion verdict. +- Deferral is licensed only when existing authoritative state supports recoverable re-entry and + the best current projection has already been durably delivered. + +## Strain found while rendering + +1. **“Required grade” was too easy to read as evidence quality.** The contract now states that + grade narrows a value's interpretation space, while epistemic status says where it came from; + demands must declare both independently. +2. **“Every demanded slot passes” hid existence and empty selection.** The contract now separates + presence/cardinality from slot quality, and a slot rule with an empty selection fails. +3. **“Objective-relative” could leave unknown objectives unchecked.** The contract now fails an + active objective that matches no plugin row. +4. **“Deferred with gaps” sounded like a conversation promise.** The contract now projects a + reproducible answer from existing authorities and refuses to license undelivered work; it adds + no persistence shape or delivery-obligation lifecycle. +5. **The simple `diverged` shorthand hides evidence on each side.** The current computation now + fails it conservatively; evaluable constituents and the intended later all/either rule remain + successor work. + +The rendering found no need for a new public lifecycle-status enum. A boolean completion answer, +an evidence-bearing explanation, and separate observed events are sufficient for this rehearsal. diff --git a/libs/@hashintel/brunch-agent/docs/evidence/proofs/design/elicitation-completion-rehearsal.md b/libs/@hashintel/brunch-agent/docs/evidence/proofs/design/elicitation-completion-rehearsal.md new file mode 100644 index 00000000000..fec73816960 --- /dev/null +++ b/libs/@hashintel/brunch-agent/docs/evidence/proofs/design/elicitation-completion-rehearsal.md @@ -0,0 +1,378 @@ +# FE-1402 completion-contract rehearsal + +Status: **provisional, manual, judgment-bearing desk scoring** over the two FE-1361 baseline +transcripts. This memo owns the CPS-specific oracle, not the normative +[completion contract](../../../specs/elicitation-completion.md). It tests discrimination; no +harness, detector, store, or plugin implementation ran. + +## Fixed replay inputs + +- plugin-contract version: `cps-replay-plugin/2026-08-24.3` +- demand-table version: `cps-baseline-replay/2026-08-24.3` +- evidence: the committed condition 1 and condition 2 transcripts, scored readout, situation pack, + and FE-1407 catalogue linked below +- prefix rule: `C1-E05` includes the opening and every user utterance available before condition + 1's fifth interviewer response + +The baseline had no capture store. References such as `C1:E05/U` and `C2:E14/U:scenario-2` are +**replay evidence proxies** for exchange or span locations, not invented durable capture IDs. A +runtime `CompletionReport` must contain capture IDs reached through model support links. + +## Provisional CPS DemandTable + +This is a versioned oracle overlay for these two transcripts, not a final CPS plugin declaration. +The limited `kind(...)` and named-coordinate scopes below are concrete replay selections; they do +not introduce a general graph-query language. + +```yaml +version: cps-baseline-replay/2026-08-24.3 +staticFloor: + - { id: SF-OBJ, type: presence, scope: kind(objective), minimumCount: 1 } + - { id: SF-ENT, type: presence, scope: kind(entity-type), minimumCount: 2 } + - { id: SF-ACT, type: presence, scope: kind(activity), minimumCount: 1 } + - { id: SF-PATH, type: presence, scope: kind(ordering/flow), minimumCount: 1 } + - id: SF-FLOW + type: slot + scope: kind(ordering/flow) + slot: sequence + minimumGrade: structured + acceptedEpistemicStatuses: [explicit, inferred] + acceptedAbsences: [] +rows: + - id: ROW-BREAKDOWN + whenObjective: breakdown-reshuffle + clauses: + - { id: BR-CAP, type: slot, scope: where(kind(entity-type), category=line), slot: capabilities, + minimumGrade: structured, acceptedEpistemicStatuses: [explicit, inferred], acceptedAbsences: [] } + - { id: BR-CAL, type: slot, scope: where(kind(boundary-condition), role=line-calendar), slot: pattern, + minimumGrade: structured, acceptedEpistemicStatuses: [explicit, inferred], acceptedAbsences: [] } + - { id: BR-OCC, type: slot, scope: where(kind(dynamics), role=line-failure), slot: occurrenceFrequency, + minimumGrade: range, acceptedEpistemicStatuses: [explicit, inferred], acceptedAbsences: [] } + - { id: BR-REPAIR, type: slot, scope: where(kind(dynamics), role=line-failure), slot: repairDuration, + minimumGrade: quantiles, acceptedEpistemicStatuses: [explicit, inferred], acceptedAbsences: [] } + - { id: BR-POL, type: slot, scope: where(kind(policy), role=resource-conflict), slot: rule, + minimumGrade: structured, acceptedEpistemicStatuses: [explicit, inferred], acceptedAbsences: [] } + - id: ROW-IDLE-WASH + whenObjective: idle-vs-washdown + clauses: + - { id: IW-REL, type: slot, scope: where(kind(boundary-condition), role=order-release), slot: condition, + minimumGrade: structured, acceptedEpistemicStatuses: [explicit, inferred], acceptedAbsences: [] } + - { id: IW-CO-DUR, type: slot, scope: where(kind(dynamics), role=family-changeover), slot: duration, + minimumGrade: range, acceptedEpistemicStatuses: [explicit, inferred], acceptedAbsences: [] } + - { id: IW-LATE, type: slot, scope: where(kind(objective), objectiveType=idle-vs-washdown), slot: latenessConsequence, + minimumGrade: structured, acceptedEpistemicStatuses: [explicit, inferred], acceptedAbsences: [] } + - { id: IW-SCRAP, type: slot, scope: where(kind(dynamics), role=family-changeover), slot: rampScrap, + minimumGrade: range, acceptedEpistemicStatuses: [explicit, inferred], acceptedAbsences: [] } + - id: ROW-CHANGEOVER + whenObjective: changeover-accounting + clauses: + - { id: CH-TAX, type: slot, scope: where(kind(entity-type), category=changeover), slot: directionClass, + minimumGrade: vocabulary-bound, acceptedEpistemicStatuses: [explicit, inferred], acceptedAbsences: [] } + - { id: CH-DUR, type: slot, scope: where(kind(dynamics), role=family-changeover), slot: duration, + minimumGrade: range, acceptedEpistemicStatuses: [explicit, inferred], acceptedAbsences: [] } + - { id: CH-CREW, type: slot, scope: where(kind(activity), role=family-changeover), slot: resourceRequirement, + minimumGrade: structured, acceptedEpistemicStatuses: [explicit, inferred], acceptedAbsences: [] } + - { id: CH-SEQ, type: slot, scope: where(kind(policy), role=weekly-sequencing), slot: rule, + minimumGrade: structured, acceptedEpistemicStatuses: [explicit, inferred], acceptedAbsences: [] } + - { id: CH-SCRAP, type: slot, scope: where(kind(dynamics), role=family-changeover), slot: rampScrap, + minimumGrade: range, acceptedEpistemicStatuses: [explicit, inferred], acceptedAbsences: [] } + - id: ROW-SPLIT + whenObjective: split-run + clauses: + - { id: SP-BATCH, type: slot, scope: where(kind(activity), role=production-run), slot: batchStructure, + minimumGrade: structured, acceptedEpistemicStatuses: [explicit, inferred], acceptedAbsences: [] } + - { id: SP-MIN, type: slot, scope: where(kind(constraint), role=minimum-run-size), slot: threshold, + minimumGrade: range, acceptedEpistemicStatuses: [explicit, inferred], acceptedAbsences: [] } + - { id: SP-ELIG, type: slot, scope: where(kind(constraint), role=line-eligibility), slot: condition, + minimumGrade: structured, acceptedEpistemicStatuses: [explicit, inferred], acceptedAbsences: [] } + - { id: SP-POL, type: slot, scope: where(kind(policy), role=split-contiguity), slot: rule, + minimumGrade: structured, acceptedEpistemicStatuses: [explicit, inferred], acceptedAbsences: [] } + - { id: SP-CO, type: slot, scope: where(kind(dynamics), role=split-run), slot: extraChangeover, + minimumGrade: range, acceptedEpistemicStatuses: [explicit, inferred], acceptedAbsences: [] } + - { id: SP-SCRAP, type: slot, scope: where(kind(dynamics), role=split-run), slot: repeatedRampScrap, + minimumGrade: range, acceptedEpistemicStatuses: [explicit, inferred], acceptedAbsences: [] } +``` + +`verbal < vocabulary-bound < structured` and `point < range < quantiles` are the applicable slot +orders. Status and grade are independent. `explicit` and `inferred` are accepted here; tentative, +defaulted, external-lookup, conflicts, and unaddressed states do not pass. An inferred value needs +traceable evidence spans. A documented-transformation basis is relevant only to external lookup. + +The universal active-anchor check is reported as `ANCHOR:`. Every active objective +must match at least one row. The floor cannot satisfy this check. A demanded `diverged` slot would +fail with `unevaluable-divergence`; neither transcript produces a grade-bearing two-sided value +that the current shorthand can evaluate. + +## Carry-forward and verdict procedure + +For each condition, the assessment ledger is a complete assessment at E01 and at objective +activation E02, followed by exact deltas. At a later prefix, apply every ledger row for that prefix +and carry every omitted assessment forward unchanged. Evidence-support additions are deltas even +when a pass/fail result does not change. The prefix table restates the full current failing set; +therefore `complete = failing set is empty` is derivable at every prefix. + +In the ledger, `accepted -> actual` means accepted epistemic statuses/absences followed by the +actual status or absence. Presence and anchor support use `n/a`. `U`, `S`, and `C` mean +unaddressed, stated, and conflicted. A failing stated value names its actual grade. + +### Rehearsal-only no-progress oracle + +This threshold is not runtime policy. After the last material frame, count consecutive interviewer +prefixes. New demanded evidence, a demanded slot/obligation change, or delivery resets the count. +Burden cues, promises, plans, and acknowledgements do not. Raise advisory `NP` on the third such +prefix and keep it raised until reset. + +## Condition 1 assessment ledger + +Active rows after E02: `ROW-BREAKDOWN`, `ROW-IDLE-WASH`, `ROW-CHANGEOVER`. + +| Prefix | Clause / coordinate | Requirement | Actual state or grade | Accepted -> actual | Replay evidence proxy | Result / diagnostic | +| --- | --- | --- | --- | --- | --- | --- | +| E01 | SF-OBJ / `objective[general]` | count >= 1 | count 1 | n/a | `C1:opening` | pass | +| E01 | SF-ENT / `entity-type[*]` | count >= 2 | count 0 | n/a | `C1:opening` | fail `below-minimum-count` | +| E01 | SF-ACT / `activity[*]` | count >= 1 | count 0 | n/a | `C1:opening` | fail `below-minimum-count` | +| E01 | SF-PATH / `ordering/flow[*]` | count >= 1 | count 0 | n/a | `C1:opening` | fail `below-minimum-count` | +| E01 | SF-FLOW / `ordering/flow[*].sequence` | structured | no selected slot | explicit,inferred -> n/a | `C1:opening` | fail `no-selected-slot` | +| E01 | ANCHOR:`objective[general]` | >= 1 matched row | no match | n/a | `C1:opening` | fail `unsupported-active-anchor` | +| E02 | SF-OBJ / `objective[*]` | count >= 1 | count 3 | n/a | `C1:E02/U:Q1-Q3` | pass | +| E02 | SF-ENT / `entity-type[*]` | count >= 2 | count >= 6 | n/a | `C1:E02/U:process-equipment` | pass | +| E02 | SF-ACT / `activity[*]` | count >= 1 | count >= 4 | n/a | `C1:E02/U:route` | pass | +| E02 | SF-PATH / `ordering/flow[*]` | count >= 1 | count 1 | n/a | `C1:E02/U:route` | pass | +| E02 | SF-FLOW / `ordering/flow[route].sequence` | structured | S@structured | explicit,inferred -> explicit | `C1:E02/U:mix-mill-tint-fill-pack` | pass | +| E02 | ANCHOR:`objective[breakdown]` | >= 1 matched row | `ROW-BREAKDOWN` | n/a | `C1:E02/U:Q1` | pass | +| E02 | ANCHOR:`objective[idle-wash]` | >= 1 matched row | `ROW-IDLE-WASH` | n/a | `C1:E02/U:Q2` | pass | +| E02 | ANCHOR:`objective[changeover]` | >= 1 matched row | `ROW-CHANGEOVER` | n/a | `C1:E02/U:Q3` | pass | +| E02 | BR-CAP / `entity-type[line].capabilities` | structured | S@structured | explicit,inferred -> explicit | `C1:E02/U:equipment-restrictions` | pass | +| E02 | BR-CAL / `boundary[line-calendar].pattern` | structured | U | explicit,inferred -> none | `C1:E02/U:changeover-crew-day-shift-only` | fail `unaddressed`; crew calendar is not line calendar | +| E02 | BR-OCC / `where(kind(dynamics), role=line-failure).occurrenceFrequency` | range | no selected slot | explicit,inferred -> n/a | `C1:E02/U` | fail `no-selected-slot` | +| E02 | BR-REPAIR / `where(kind(dynamics), role=line-failure).repairDuration` | quantiles | no selected slot | explicit,inferred -> n/a | `C1:E02/U` | fail `no-selected-slot` | +| E02 | BR-POL / `policy[resource-conflict].rule` | structured | U | explicit,inferred -> none | `C1:E02/U` | fail `unaddressed` | +| E02 | IW-REL / `boundary[order-release].condition` | structured | U | explicit,inferred -> none | `C1:E02/U` | fail `unaddressed` | +| E02 | IW-CO-DUR / `dynamics[family-changeover].duration` | range | S@range | explicit,inferred -> explicit | `C1:E02/U:changeover-times` | pass | +| E02 | IW-LATE / `objective[idle-wash].latenessConsequence` | structured | S@structured | explicit,inferred -> explicit | `C1:E02/U:Meridian-first` | pass | +| E02 | IW-SCRAP / `dynamics[family-changeover].rampScrap` | range | absent: unknown-to-user | explicit,inferred; no absences -> explicit | `C1:E02/U:ramp-scrap-unknown` | fail `unaccepted-absence` | +| E02 | CH-TAX / `entity-type[changeover].directionClass` | vocabulary-bound | S@vocabulary-bound | explicit,inferred -> explicit | `C1:E02/U:directional-matrix` | pass | +| E02 | CH-DUR / `dynamics[family-changeover].duration` | range | S@range | explicit,inferred -> explicit | `C1:E02/U:25m-1h-3h` | pass | +| E02 | CH-CREW / `activity[family-changeover].resourceRequirement` | structured | S@verbal | explicit,inferred -> explicit | `C1:E02/U:two-techs` | fail `below-required-grade` | +| E02 | CH-SEQ / `policy[weekly-sequencing].rule` | structured | S@verbal | explicit,inferred -> explicit | `C1:E02/U:family-clustering` | fail `below-required-grade` | +| E02 | CH-SCRAP / `dynamics[family-changeover].rampScrap` | range | absent: unknown-to-user | explicit,inferred; no absences -> explicit | `C1:E02/U:ramp-scrap-unknown` | fail `unaccepted-absence` | +| E03 | BR-OCC / `dynamics[filler-jam,mill-motor].occurrenceFrequency` | range | filler S@range; motor S@verbal | explicit,inferred -> explicit | `C1:E03/U:weekly-or-two-and-rare` | fail `below-required-grade` on motor | +| E03 | BR-REPAIR / `dynamics[filler-jam,mill-motor].repairDuration` | quantiles | filler S@range; motor S@point | explicit,inferred -> explicit | `C1:E03/U:half-hour-to-half-shift-and-four-days-once` | fail `below-required-grade` | +| E04 | BR-CAL / `boundary[line-calendar].pattern` | structured | S@structured | explicit,inferred -> explicit | `C1:E04/U:06-14/14-22` | pass | +| E05 | CH-CREW / `activity[family-changeover].resourceRequirement` | structured | S@structured | explicit,inferred -> explicit | `C1:E05/U:operators-rinse-techs-switch` | pass | +| E06 | CH-SEQ / `policy[weekly-sequencing].rule` | structured | S@structured | explicit,inferred -> explicit | `C1:E06/U:07:30-and-fill-the-shift-confirmation` | pass | + +E06 confirms scheduling-policy evidence and promises later data. It does **not** ask for a handoff. +No demanded assessment changes at E07-E21; E21 changes delivery state only. + +### Condition 1 prefix verdicts + +| Prefix | Available evidence / assessment delta | Current failing assessments after carry-forward | Complete | Stop event | Delivery / re-entry state | No progress | +| --- | --- | --- | --- | --- | --- | --- | +| C1-E01 | full E01 assessment | `SF-ENT,SF-ACT,SF-PATH,SF-FLOW,ANCHOR:general` | false | none | none / none | 0 | +| C1-E02 | full E02 activation assessment | `BR-CAL,BR-OCC,BR-REPAIR,BR-POL,IW-REL,IW-SCRAP,CH-CREW,CH-SEQ,CH-SCRAP` | false | none | none / none | reset | +| C1-E03 | `BR-OCC,BR-REPAIR` evidence/grade deltas | same as E02 | false | none | none / none | reset | +| C1-E04 | `BR-CAL` passes | `BR-OCC,BR-REPAIR,BR-POL,IW-REL,IW-SCRAP,CH-CREW,CH-SEQ,CH-SCRAP` | false | none | none / none | reset | +| C1-E05 | `CH-CREW` passes | `BR-OCC,BR-REPAIR,BR-POL,IW-REL,IW-SCRAP,CH-SEQ,CH-SCRAP` | false | none | none / none | reset | +| C1-E06 | `CH-SEQ` passes on policy evidence | `BR-OCC,BR-REPAIR,BR-POL,IW-REL,IW-SCRAP,CH-SCRAP` | false | none | none / none | reset; last material frame | +| C1-E07 | no delta; acknowledgment/evidence caution | same as E06 | false | none | none / none | streak 1 | +| C1-E08 | no delta; assumptions-register acknowledgment | same as E06 | false | none | none / none | streak 2 | +| C1-E09 | time-pressure/impatience cue; no assessment delta | same as E06 | false | interviewer initiates stopping | promised artifact absent / none | `NP`, streak 3 | +| C1-E10 | acknowledgment only | same as E06 | false | stopping persists | none / none | `NP`, streak 4 | +| C1-E11 | parking acknowledgment | same as E06 | false | future continuation implied | none / none | `NP`, streak 5 | +| C1-E12 | social close | same as E06 | false | conversational close | none / none | `NP`, streak 6 | +| C1-E13 | social close | same as E06 | false | conversational close | none / none | `NP`, streak 7 | +| C1-E14 | emoji acknowledgment | same as E06 | false | conversational close | none / none | `NP`, streak 8 | +| C1-E15 | dash acknowledgment | same as E06 | false | conversational close | none / none | `NP`, streak 9 | +| C1-E16 | thread declared parked | same as E06 | false | deferral asserted | none / none; unlicensed | `NP`, streak 10 | +| C1-E17 | social close | same as E06 | false | conversational close | none / none | `NP`, streak 11 | +| C1-E18 | conversation called complete | same as E06 | false | conversational close | none / none | `NP`, streak 12 | +| C1-E19 | closed plus future-session promise | same as E06 | false | deferral asserted | none / none; unlicensed | `NP`, streak 13 | +| C1-E20 | emoji; runner then exhausts budget | same as E06 | false | budget exhaustion follows | none / none | `NP`, streak 14 | +| C1-E21 | forced-wrap specification; no new source evidence | same as E06 | false | external forced wrap | delivered, unvalidated specification / none | reset by delivery | + +The eleven interviewer responses E10-E20 are the pleasantry/delivery loop. The advisory begins at +E09, when the third non-material prefix arrives, and persists until E21 delivery. E09 is not a +user request for quiet or an explicit request to leave: it is a time-pressure cue followed by +interviewer-initiated stopping. The useful action remained expressible throughout: deliver the +best caveated result now, expose the six blockers, and stop with `complete: false`. + +## Condition 2 assessment ledger + +Active rows after E02: all four rows, including `ROW-CHANGEOVER`; changeover accounting is an +explicit objective and also supports idle/split reasoning. + +| Prefix | Clause / coordinate | Requirement | Actual state or grade | Accepted -> actual | Replay evidence proxy | Result / diagnostic | +| --- | --- | --- | --- | --- | --- | --- | +| E01 | SF-OBJ / `objective[general]` | count >= 1 | count 1 | n/a | `C2:opening` | pass | +| E01 | SF-ENT / `entity-type[*]` | count >= 2 | count 0 | n/a | `C2:opening` | fail `below-minimum-count` | +| E01 | SF-ACT / `activity[*]` | count >= 1 | count 0 | n/a | `C2:opening` | fail `below-minimum-count` | +| E01 | SF-PATH / `ordering/flow[*]` | count >= 1 | count 0 | n/a | `C2:opening` | fail `below-minimum-count` | +| E01 | SF-FLOW / `ordering/flow[*].sequence` | structured | no selected slot | explicit,inferred -> n/a | `C2:opening` | fail `no-selected-slot` | +| E01 | ANCHOR:`objective[general]` | >= 1 matched row | no match | n/a | `C2:opening` | fail `unsupported-active-anchor` | +| E02 | SF-OBJ / `objective[*]` | count >= 1 | count 4 | n/a | `C2:E02/U:four-objectives` | pass | +| E02 | SF-ENT / `entity-type[*]` | count >= 2 | count 3 | n/a | `C2:E02/U:three-lines` | pass | +| E02 | SF-ACT / `activity[*]` | count >= 1 | count 0 | n/a | `C2:E02/U` | fail `below-minimum-count` | +| E02 | SF-PATH / `ordering/flow[*]` | count >= 1 | count 0 | n/a | `C2:E02/U` | fail `below-minimum-count` | +| E02 | SF-FLOW / `ordering/flow[*].sequence` | structured | no selected slot | explicit,inferred -> n/a | `C2:E02/U` | fail `no-selected-slot` | +| E02 | ANCHOR:`objective[breakdown]` | >= 1 matched row | `ROW-BREAKDOWN` | n/a | `C2:E02/U:breakdown-response` | pass | +| E02 | ANCHOR:`objective[idle-wash]` | >= 1 matched row | `ROW-IDLE-WASH` | n/a | `C2:E02/U:idle-vs-wash` | pass | +| E02 | ANCHOR:`objective[changeover]` | >= 1 matched row | `ROW-CHANGEOVER` | n/a | `C2:E02/U:changeover-accounting` | pass | +| E02 | ANCHOR:`objective[split]` | >= 1 matched row | `ROW-SPLIT` | n/a | `C2:E02/U:split-runs` | pass | +| E02 | BR-CAP / `entity-type[line].capabilities` | structured | U | explicit,inferred -> none | `C2:E02/U` | fail `unaddressed` | +| E02 | BR-CAL / `boundary[line-calendar].pattern` | structured | U | explicit,inferred -> none | `C2:E02/U` | fail `unaddressed` | +| E02 | BR-OCC / `dynamics[mill-motor].occurrenceFrequency` | range | U | explicit,inferred -> none | `C2:E02/U:four-day-again-objective` | fail `unaddressed` | +| E02 | BR-REPAIR / `dynamics[mill-motor].repairDuration` | quantiles | motor S@point | explicit,inferred -> explicit | `C2:E02/U:four-day-again-objective` | fail `below-required-grade` | +| E02 | BR-POL / `policy[resource-conflict].rule` | structured | U | explicit,inferred -> none | `C2:E02/U` | fail `unaddressed` | +| E02 | IW-REL / `boundary[order-release].condition` | structured | S@verbal | explicit,inferred -> explicit | `C2:E02/U:next-morning-release` | fail `below-required-grade` | +| E02 | IW-CO-DUR / `dynamics[family-changeover].duration` | range | U | explicit,inferred -> none | `C2:E02/U` | fail `unaddressed` | +| E02 | IW-LATE / `objective[idle-wash].latenessConsequence` | structured | S@verbal | explicit,inferred -> explicit | `C2:E02/U:on-time-ship-and-Meridian-risk` | fail `below-required-grade` | +| E02 | IW-SCRAP / `dynamics[family-changeover].rampScrap` | range | U | explicit,inferred -> none | `C2:E02/U` | fail `unaddressed` | +| E02 | CH-TAX / `entity-type[changeover].directionClass` | vocabulary-bound | S@verbal | explicit,inferred -> explicit | `C2:E02/U:changeover-concern` | fail `below-required-grade` | +| E02 | CH-DUR / `dynamics[family-changeover].duration` | range | U | explicit,inferred -> none | `C2:E02/U` | fail `unaddressed` | +| E02 | CH-CREW / `activity[family-changeover].resourceRequirement` | structured | S@verbal | explicit,inferred -> explicit | `C2:E02/U:shared-crew` | fail `below-required-grade` | +| E02 | CH-SEQ / `policy[weekly-sequencing].rule` | structured | U | explicit,inferred -> none | `C2:E02/U` | fail `unaddressed` | +| E02 | CH-SCRAP / `dynamics[family-changeover].rampScrap` | range | U | explicit,inferred -> none | `C2:E02/U` | fail `unaddressed` | +| E02 | SP-BATCH / `activity[production-run].batchStructure` | structured | S@verbal | explicit,inferred -> explicit | `C2:E02/U:split-big-orders` | fail `below-required-grade` | +| E02 | SP-MIN / `constraint[minimum-run-size].threshold` | range | U | explicit,inferred -> none | `C2:E02/U` | fail `unaddressed` | +| E02 | SP-ELIG / `constraint[line-eligibility].condition` | structured | U | explicit,inferred -> none | `C2:E02/U` | fail `unaddressed` | +| E02 | SP-POL / `policy[split-contiguity].rule` | structured | U | explicit,inferred -> none | `C2:E02/U` | fail `unaddressed` | +| E02 | SP-CO / `dynamics[split-run].extraChangeover` | range | S@verbal | explicit,inferred -> explicit | `C2:E02/U:extra-changeover-concern` | fail `below-required-grade` | +| E02 | SP-SCRAP / `dynamics[split-run].repeatedRampScrap` | range | U | explicit,inferred -> none | `C2:E02/U` | fail `unaddressed` | +| E03 | IW-LATE / `objective[idle-wash].latenessConsequence` | structured | S@vocabulary-bound | explicit,inferred -> explicit | `C2:E03/U:promise-date-and-account-hierarchy` | fail `below-required-grade` | +| E04 | IW-LATE / `objective[idle-wash].latenessConsequence` | structured | S@structured | explicit,inferred -> explicit | `C2:E04/U:Meridian-cliff-and-slopes` | pass | +| E05 | SF-ACT / `activity[*]` | count >= 1 | count >= 7 | n/a | `C2:E05/U:order-walk` | pass | +| E05 | SF-PATH / `ordering/flow[*]` | count >= 1 | count 1 | n/a | `C2:E05/U:order-walk` | pass | +| E05 | SF-FLOW / `ordering/flow[order].sequence` | structured | S@structured | explicit,inferred -> explicit | `C2:E05/U:demand-to-truck` | pass | +| E06 | BR-CAP / `entity-type[line].capabilities` | structured | S@structured | explicit,inferred -> explicit | `C2:E06/U:qualifications-capacities` | pass | +| E06 | SP-BATCH / `activity[production-run].batchStructure` | structured | S@structured | explicit,inferred -> explicit | `C2:E06/U:pipelined-batches` | pass | +| E06 | SP-ELIG / `constraint[line-eligibility].condition` | structured | S@structured | explicit,inferred -> explicit | `C2:E06/U:line-qualification` | pass | +| E07 | IW-CO-DUR / `dynamics[family-changeover].duration` | range | S@range | explicit,inferred -> explicit | `C2:E07/U:directional-duration-matrix` | pass | +| E07 | CH-TAX / `entity-type[changeover].directionClass` | vocabulary-bound | S@vocabulary-bound | explicit,inferred -> explicit | `C2:E07/U:family-direction-classes` | pass | +| E07 | CH-DUR / `dynamics[family-changeover].duration` | range | S@range | explicit,inferred -> explicit | `C2:E07/U:directional-duration-matrix` | pass | +| E08 | BR-OCC / `dynamics[filler-jam,mill-motor].occurrenceFrequency` | range | filler S@range; motor U | explicit,inferred -> explicit/none | `C2:E08/U:one-in-ten-and-every-couple-weeks` | fail `unaddressed` on motor | +| E08 | BR-REPAIR / `dynamics[filler-jam,mill-motor].repairDuration` | quantiles | filler S@range; motor S@point | explicit,inferred -> explicit | `C2:E02/U:four-days;C2:E08/U:20m-to-rest-of-shift` | fail `below-required-grade` | +| E09 | BR-CAL / `boundary[line-calendar].pattern` | structured | S@structured | explicit,inferred -> explicit | `C2:E09/U:shifts-and-coverage` | pass | +| E09 | CH-CREW / `activity[family-changeover].resourceRequirement` | structured | S@structured | explicit,inferred -> explicit | `C2:E09/U:crew-calendar` | pass | +| E11 | IW-REL / `boundary[order-release].condition` | structured | S@structured | explicit,inferred -> explicit | `C2:E11/U:credit-allocation-hold` | pass | +| E14 | BR-POL / `policy[resource-conflict].rule` | structured | S@structured | explicit,inferred -> explicit | `C2:E14/U:crew-priority` | pass | +| E14 | CH-SEQ / `policy[weekly-sequencing].rule` | structured | S@structured | explicit,inferred -> explicit | `C2:E14/U:campaign-and-Saturday-trigger` | pass | +| E15 | CH-SEQ / `policy[weekly-sequencing].rule` | structured | S@structured | explicit,inferred -> explicit | `C2:E14/U;C2:E15/U:tie-break-end-horizon` | pass; support delta | +| E18 | CH-CREW / `activity[family-changeover].resourceRequirement` | structured | S@structured | explicit,inferred -> explicit | `C2:E09/U:crew-calendar;C2:E18/U:big-wash-whole-line` | pass; compatible support delta | + +At E20 the available exchange evidence is limited to the named holes in splitting, granularity, +and distributions. Ramp scrap, maintenance/CMMS evidence, and minimum-run facts occur only in the +hidden oracle/demand assessment and are not attributed to E20. + +The quick-rinse branch remains residual evidence outside this bounded oracle. E18 says the user +does not know whether rinses cascade. E19's “two simultaneous rinse servers” possibility is +interviewer-authored, and the user's prompted half-memory is not used as support. Neither conflicts +with the explicit two-technician big-wash evidence, so `CH-CREW` stays passed after E09. + +### Condition 2 prefix verdicts + +| Prefix | Available evidence / assessment delta | Current failing assessments after carry-forward | Complete | Stop event | Delivery / re-entry state | No progress | +| --- | --- | --- | --- | --- | --- | --- | +| C2-E01 | full E01 assessment | `SF-ENT,SF-ACT,SF-PATH,SF-FLOW,ANCHOR:general` | false | none | none / none | 0 | +| C2-E02 | full E02 activation assessment | `SF-ACT,SF-PATH,SF-FLOW,BR-CAP,BR-CAL,BR-OCC,BR-REPAIR,BR-POL,IW-REL,IW-CO-DUR,IW-LATE,IW-SCRAP,CH-TAX,CH-DUR,CH-CREW,CH-SEQ,CH-SCRAP,SP-BATCH,SP-MIN,SP-ELIG,SP-POL,SP-CO,SP-SCRAP` | false | none | none / none | reset | +| C2-E03 | `IW-LATE` support/grade delta | same as E02 | false | none | none / none | reset | +| C2-E04 | `IW-LATE` passes | E02 minus `IW-LATE` | false | none | none / none | reset | +| C2-E05 | `SF-ACT,SF-PATH,SF-FLOW` pass | `BR-CAP,BR-CAL,BR-OCC,BR-REPAIR,BR-POL,IW-REL,IW-CO-DUR,IW-SCRAP,CH-TAX,CH-DUR,CH-CREW,CH-SEQ,CH-SCRAP,SP-BATCH,SP-MIN,SP-ELIG,SP-POL,SP-CO,SP-SCRAP` | false | none | none / none | reset | +| C2-E06 | `BR-CAP,SP-BATCH,SP-ELIG` pass | `BR-CAL,BR-OCC,BR-REPAIR,BR-POL,IW-REL,IW-CO-DUR,IW-SCRAP,CH-TAX,CH-DUR,CH-CREW,CH-SEQ,CH-SCRAP,SP-MIN,SP-POL,SP-CO,SP-SCRAP` | false | none | none / none | reset | +| C2-E07 | `IW-CO-DUR,CH-TAX,CH-DUR` pass | `BR-CAL,BR-OCC,BR-REPAIR,BR-POL,IW-REL,IW-SCRAP,CH-CREW,CH-SEQ,CH-SCRAP,SP-MIN,SP-POL,SP-CO,SP-SCRAP` | false | none | none / none | reset | +| C2-E08 | `BR-OCC,BR-REPAIR` support/grade deltas | same as E07 | false | none | none / none | reset | +| C2-E09 | `BR-CAL,CH-CREW` pass | `BR-OCC,BR-REPAIR,BR-POL,IW-REL,IW-SCRAP,CH-SEQ,CH-SCRAP,SP-MIN,SP-POL,SP-CO,SP-SCRAP` | false | time pressure prompts planning, interview continues | none / none | reset | +| C2-E10 | promise of CMMS/ERP and future slot; no assessment delta | same as E09 | false | deferral proposed | none / none; unlicensed | streak 1 | +| C2-E11 | `IW-REL` passes | `BR-OCC,BR-REPAIR,BR-POL,IW-SCRAP,CH-SEQ,CH-SCRAP,SP-MIN,SP-POL,SP-CO,SP-SCRAP` | false | none | none / none | reset | +| C2-E12 | release-pull promise; no assessment delta | same as E11 | false | future work planned | none / none | streak 1 | +| C2-E13 | logistics promise; no assessment delta | same as E11 | false | future work planned | none / none | streak 2 | +| C2-E14 | `BR-POL,CH-SEQ` pass | `BR-OCC,BR-REPAIR,IW-SCRAP,CH-SCRAP,SP-MIN,SP-POL,SP-CO,SP-SCRAP` | false | none | none / none | reset | +| C2-E15 | `CH-SEQ` support delta | same as E14 | false | none | none / none | reset | +| C2-E16 | export promise; no assessment delta | same as E14 | false | future work planned | none / none | streak 1 | +| C2-E17 | raw-pull promise; no assessment delta | same as E14 | false | future work planned | none / none | streak 2 | +| C2-E18 | `CH-CREW` gains compatible big-wash support and stays passed; quick-rinse branch remains residual | same as E14 | false | observation planned | none / none; unlicensed | reset by demanded support change | +| C2-E19 | no oracle delta; interviewer-authored parallel-rinse possibility is excluded | same as E14 | false | observation plan refined | none / none | streak 1 | +| C2-E20 | exchange names only splitting, granularity, distributions; no assessment delta | same as E14 | false | interviewer quiets for tomorrow | none / none; unlicensed | streak 2 | +| C2-E21 | first forced-wrap delivery; no source-evidence delta | same as E14 | false | budget exhaustion / forced wrap | partial specification / none | reset by delivery | +| C2-E22 | additional delivered sections; no assessment delta | same as E14 | false | repeated forced wrap | additional sections / none | reset by delivery | +| C2-E23 | final delivered specification; no assessment delta | same as E14 | false | hard-stop delivery | final specification / none | reset by delivery | + +No C2 arm reaches the third consecutive non-material prefix. Plans do not reset the streak, but +E11 evidence, E14 policy evidence, E15/E18 support, and E21-E23 deliveries do. No false `NP` is +raised. The final boolean remains false, independently and visibly, because +the carried ledger includes the never-asked ramp-scrap and minimum-run obligations. + +## Failure-signature discrimination + +| FE-1407 signature | Replay result | +| --- | --- | +| FM-01 pleasantry-loop stall | `NP` begins at C1-E09 and persists through the eleven-response E10-E20 delivery loop; it does not assert completion. | +| FM-02 delivery deferral without deposit | C1 parks a deliverable while a caveated result is possible; the best current projection was not durably delivered, so current deferral licensing must fail. | +| FM-03 phantom re-entry | Both conditions name future sessions without durable revision, archive pointer, located obligations, or recoverable affordance. | +| FM-04 premature accommodation | C1's time-pressure cue produces interviewer stopping at E09; session stopping is allowed while completion remains false. | +| FM-05 budget exhaustion | Forced wrap stops both runs but changes no assessment. | +| FM-08 never-asked coverage | `IW-SCRAP`, `CH-SCRAP`, and `SP-SCRAP` remain explicit blockers despite never being asked in C2. | +| FM-09 complementary misses | The same DemandTable exposes different carried failure sets in the two runs; no variance-reduction claim follows from n=1 per condition. | +| FM-13 fluent incompleteness | C2 delivery and “complete” prose cannot override the non-empty clause failure set. | + +The catalogue's prevention grades are unchanged: specified and candidate mechanisms are design +claims, not implementation proof. + +## Amendments and residual strain + +The rehearsal forced presence/cardinality clauses, the universal active-anchor check, versioned +plugin/demand inputs, evidence-bearing clause assessments, conservative divergence failure, and a +read-time deferral-licensing projection over existing authorities into the normative contract. +Those amendments are folded into the linked spec. Carry-forward and evidence-proxy rules remain +rehearsal method here, not normative runtime behavior. + +Residual judgment remains in model selection and folding: a different defensible provisional CPS +oracle could choose different coordinates or grades. The stable clause IDs and complete carried +failure sets make that disagreement local and reviewable instead of hiding it in family-level +prose. Two fixed runs are existence evidence only, not rate estimates. + +## Successor evidence + +### FE-1403 — guidance assembly + +- Drive questions from clause diagnostics, especially `BR-OCC`, `BR-REPAIR`, ramp scrap, minimum + run size, split policy, and release; cards must not claim reflective self-inventory can + find never-asked coverage. +- A close card must support the best useful result now: state clause-level gaps, durably deliver + current work, and quiet only after existing authorities pass deferral licensing. +- Preserve explicit/inferred/tentative distinctions and evidence links separately from grade. + +### FE-1404 — condition-3 run + +- Score the version-bound report at each prefix and score stop, quiet, delivery, deferral licensing, + no-progress, and budget events separately. +- Keep ramp scrap hidden in the oracle, reposition impatience during interview, and test that an + unmatched anchor, empty presence scope, demanded conflict, or open ramp-scrap clause prevents + completion. +- Test licensed deferral by recomputing it from capture-store revision, located blockers, + session-log archive/high-water/tail, pending affordance, and a durable current projection; + prompt-only evidence cannot prove those authorities. + +### FE-1431 — plugin authoring + +- Make the final CPS DemandTable author-readable beside model slots and bind its digest into every + report. +- Define evaluable constituents for `diverged`; until then retain `unevaluable-divergence`. The + intended later rule may require both sides or explicitly allow either. +- Resolve absent-slot location and alternative-satisfier authoring without expanding this replay's + limited scope expressions into a generic query language. +- Route any durable undelivered-delivery obligation to an approved durability-contract owner; + neither `CaptureIssue` nor this completion contract has that authority today. + +## Evidence bundle + +- [FE-1407 failure catalogue](../../../reference/research/elicitation/frontier-model-elicitor-failure-catalogue.md) +- [baseline readout](../../evaluations/process-model-elicitation/baseline/readout.md) +- [condition 1 transcript](../../evaluations/process-model-elicitation/baseline/transcripts/condition-1.md) +- [condition 2 transcript](../../evaluations/process-model-elicitation/baseline/transcripts/condition-2.md) +- [baseline situation pack](../../../../evaluations/cases/process-model-elicitation/baseline/situation-pack.md) +- [baseline protocol](../../../../evaluations/protocols/process-model-elicitation/baseline/protocol.md) +- [plugin contract](../../../specs/plugin-contract.md) and + [ADR-0003](../../../adr/0003-three-register-ir.md) + +No web research was needed: this is manual scoring over fixed committed evidence. diff --git a/libs/@hashintel/brunch-agent/docs/specs/elicitation-completion.md b/libs/@hashintel/brunch-agent/docs/specs/elicitation-completion.md new file mode 100644 index 00000000000..47b55fa8332 --- /dev/null +++ b/libs/@hashintel/brunch-agent/docs/specs/elicitation-completion.md @@ -0,0 +1,339 @@ +# Spec: target-document completion and session stopping + +Status: **provisional** — manually desk-scored over the two FE-1361 baseline transcripts. The +replay validates design discrimination, not implementation. FE-1402 owns this required-behavior +contract; plugin authoring consumes it. + +This specification defines a read-time answer to one question: given one version-bound snapshot +of the durable evidence, derived model, active objectives, and plugin demands, is the +target-document complete enough for those objectives? The companion +[rehearsal](../evidence/proofs/design/elicitation-completion-rehearsal.md) owns the provisional CPS +oracle and prefix verdicts. The +[plain rendering](../evidence/proofs/design/elicitation-completion-plain.md) checks this contract in +a second register. + +## Required distinctions + +These facts can coincide, but none except the first asserts completion: + +| Fact | Meaning | Effect on completion | +| --- | --- | --- | +| Target-document completion | Every static demand, universal active-anchor support check, and objective demand passes. | This is the computation. | +| Session stopping | A conversation is intentionally quieted or produces no more entries. | None. | +| User-requested quiet | The user asks to pause, leave, or receive no further questions. | None. | +| Delivery | A current projection or another promised result is emitted. | None. | +| No progress | Recent frames add no demanded evidence or state and deliver nothing. | None; session control may require adjudication. | +| Budget exhaustion | A turn, token, time, or cost bound ends the session. | None. | +| Licensed deferral | Session control verifies that existing durable authorities can support recoverable re-entry. | None. | + +“Best useful result within this session” is therefore ordinary behavior: durably deliver the best +current projection with its loss and open obligations, license later continuation only from +existing authoritative state, and stop the session while the completion boolean remains false. + +## Version-bound input snapshot + +The harness evaluates one immutable snapshot: + +```yaml +CompletionInput: + targetDocumentRevision: opaque immutable revision + pluginContractVersion: immutable plugin version or digest + demandTableVersion: immutable demand-table version or digest + model: register-2 derived model at targetDocumentRevision + activeCaptures: evidence metadata reachable from model support links + openIssues: issue state at targetDocumentRevision +``` + +The plugin version and demand-table version are part of the identity of the verdict. If the target +document or either plugin version changes during the read, the caller retries. It must not combine +model state from one revision with demands from another. + +The computation reads active objectives, the plugin's static floor and demand rows, derived slot +states, grades, epistemic statuses, evidence spans or bases, and open issues. It does **not** read +conversation fluency, self-assessment, turn count, delivery state, recent novelty, session state, +or a deferral-licensing report. + +The plugin owns the demand declaration. The harness owns deterministic expansion and evaluation. +The session controller consumes the report but cannot author or override it. + +## Demand algebra + +The smallest required algebra distinguishes existence from slot quality: + +```yaml +DemandTable: + version: immutable string or digest + staticFloor: DemandClause[] + rows: DemandRow[] + +DemandRow: + id: stable plugin-local identifier + whenObjective: pattern over one active completion anchor + clauses: DemandClause[] + +DemandClause: + PresenceClause | SlotClause + +PresenceClause: + id: stable plugin-local identifier + type: presence + scope: ScopeExpr + minimumCount: positive integer + +SlotClause: + id: stable plugin-local identifier + type: slot + scope: ScopeExpr + slot: slot name + minimumGrade: rung in that slot's grade order + acceptedEpistemicStatuses: non-empty subset of capture-envelope statuses + acceptedAbsences: subset of capture-envelope absence states, default empty +``` + +All static clauses and all clauses from every matched objective row are conjunctive. A presence +clause counts model nodes selected by its scope; it is how a plugin declares objective, entity, or +path cardinality. A slot clause evaluates a named slot on every selected model node. An empty slot +selection fails with `no-selected-slot`; existence cannot pass accidentally through an empty +selection. + +This algebra adds no graph-query language. It uses the plugin contract's `ScopeExpr`. September may +ship kind-only scopes. The already named `where` and `inSupport(anchor)` constructors remain future +growth paths; this contract does not generalize them. + +### Universal active-anchor support + +Independently of the static floor, the harness checks every active node whose kind declares +`completionAnchor: true`: + +1. match that anchor against every demand row using the plugin-declared objective pattern; +2. fail that anchor with `unsupported-active-anchor` when no row matches; and +3. evaluate the union of clauses from every matching row when at least one matches. + +No objective is silently ignored, and the static floor cannot substitute for this universal +check. A target-document with no active completion anchor fails through its plugin-declared +presence clause in the floor. + +### Status, grade, and confidence + +Epistemic status and grade are independent: + +- status says how content relates to its source (`explicit`, `inferred`, `tentative`, `defaulted`, + or `external-lookup`); +- grade says how narrow the slot value's interpretation space is; and +- confidence says claim strength and satisfies neither requirement. + +Statuses are not ordered. A slot clause explicitly lists accepted statuses. An `inferred` capture +uses evidence spans under the existing envelope contract; a demand may accept it directly. A +`documented-transformation` basis belongs to `external-lookup`, not to `inferred`. Grade and +traceable evidence are checked separately from status. + +## Evaluation + +```text +evaluateCompletion(input, plugin): + require input.pluginContractVersion == plugin.version + require input.demandTableVersion == plugin.demandTable.version + + floor := expand and evaluate every static clause + anchors := every active completion-anchor node + + for each anchor: + matchedRows := all demand rows matching anchor + anchorSupport.pass := matchedRows is not empty + obligations := expand and evaluate every clause in matchedRows + anchor.pass := anchorSupport.pass and every obligation passes + + complete := every floor clause passes + and every active anchor passes + + return the version-bound evidence-bearing report +``` + +The boolean is the only completion value required. Diagnostics explain it; they are not a second +public status vocabulary. + +### Presence evaluation + +A presence clause passes when the selected node count is at least `minimumCount`. The report +includes the selected node IDs. Presence checks model cardinality only; they do not manufacture +evidence or grade. + +### Slot evaluation + +Every selected slot must pass: + +- `stated(value, grade, supportingCaptureIds)` passes when grade meets the declared minimum, all + support needed for the folded value is active and traceable, and every supporting status the + fold relies on is accepted. +- `unaddressed` fails with `unaddressed`. +- `absent(absence, captureId)` passes only when that exact absence is accepted, the capture is + active and traceable, and its status is accepted. `not-mentioned` cannot pass because it is a + computed fact, not evidence. +- `conflicted(openIssueIds)` fails with `open-conflict` until explicit resolution. +- `diverged(prescribed, practiced)` fails with `unevaluable-divergence`. The canonical shorthand + does not expose grade and supporting captures for each side, so this contract cannot evaluate + either constituent honestly. + +Other diagnostics are `below-minimum-count`, `no-selected-slot`, `below-required-grade`, +`inadmissible-status`, `unaccepted-absence`, `missing-evidence`, `unsupported-active-anchor`, and +`version-mismatch`. +Open issues outside selected demand coordinates remain visible but do not block objective-relative +completion. + +## Evidence-bearing report + +```yaml +CompletionReport: + targetDocumentRevision: opaque immutable revision + pluginContractVersion: immutable plugin version or digest + demandTableVersion: immutable demand-table version or digest + complete: boolean + floor: + - clauseId + clauseType + selectedModelCoordinates + requirement + actual + pass: boolean + diagnostics + supportingCaptureIds + openIssueIds + objectives: + - anchorNodeId + supportingCaptureIds + matchedDemandRowIds + supportCheck: + pass: boolean + diagnostics + obligations: same assessment shape as floor + pass: boolean +``` + +The report follows register-2 support links to deposited captures and carries their capture IDs. It +never semantically rereads the transcript. + +## Session control and no progress + +After each settled sweep, session control may read the completion report plus separate session +facts. It may ask, deliver and defer, or stop. None rewrites the report. A later evidence +change can also make a previously complete target-document incomplete; completion never locks it. + +Runtime no-progress policy remains outside this contract. A candidate detector may compare frames +for newly deposited demanded evidence, demanded slot or obligation changes, and delivery changes. +An advisory can force session-control adjudication but cannot supply a positive completion verdict. +The rehearsal owns one bounded threshold solely to score the baseline. + +## Read-time deferral licensing + +Licensed deferral is a session-control decision computed from existing authorities. It creates no +third persistence surface and writes no target-document truth. The session controller owns this +pure projection: + +```yaml +DeferralLicensingInput: + completionReport: version-bound CompletionReport + captureStore: + snapshotRevision: immutable revision inspected by completion + locatedIssuesAndAbsences: existing capture-store records + sessionLog: + archivePointer: durable archive pointer + archiveRevision: immutable revision or digest + sweptHighWaterMark: durable entry identifier + unsweptTail: bounded entry range or empty + pendingAffordanceSlot: + stateRevision: immutable revision or digest + affordanceId: identifier? + delivery: + projectionRef: durable projection/artifact pointer? + sourceTargetDocumentRevision: immutable revision? + +BlockingObligationLocator: + ModelCoordinateLocator | UnresolvedTargetLocator + +ModelCoordinateLocator: + type: model-coordinate + coordinate: register-2 model coordinate + issueIds: existing identifiers[] + absenceCaptureIds: existing identifiers[] + +UnresolvedTargetLocator: + type: unresolved-target + clauseId: stable demand-clause identifier + scope: exact ScopeExpr + diagnostic: below-minimum-count | no-selected-slot + +DeferralLicensingReport: + inspected: + targetDocumentRevision + pluginContractVersion + demandTableVersion + captureStoreSnapshotRevision + sessionArchivePointer + sessionArchiveRevision + sweptHighWaterMark + unsweptTailRange + pendingAffordanceStateRevision + pendingAffordanceId + deliveryProjectionRef + deliverySourceTargetDocumentRevision + blockers: + - clauseId + locator: BlockingObligationLocator + checks: + sweepAndArchiveStateRecoverable: boolean + everyBlockingObligationLocated: boolean + currentBestProjectionDurablyDelivered: boolean + reentryFactsRecoverable: boolean + licensed: boolean + diagnostics: string[] +``` + +The locator is a union because a blocker may already have a model coordinate, issue, or explicit +absence, while a failed presence clause or `no-selected-slot` has no selected model node. The +second arm preserves the unresolved clause and exact scope instead. Every completion blocker must +have one arm; a missing locator keeps `everyBlockingObligationLocated` false. + +`sweepAndArchiveStateRecoverable` permits an explicitly bounded unswept tail only when the archive +pointer, archive revision, and swept high-water mark recover it exactly; it does not silently call +that tail settled. + +`licensed` is true only when all four checks pass and every inspected revision, digest, pointer, +high-water mark, pending-affordance fact, and projection reference still resolves to the state +shown in the report. The durable delivery must be the best current projection for the same +`targetDocumentRevision` evaluated by completion; absent delivery fields make +`currentBestProjectionDurablyDelivered` false. The report itself is ephemeral: it may be +recomputed for audit, but it is not stored as target-document or capture-store truth. + +The current authoritative schemas carry no durable undelivered-delivery obligation with reason, +owner, and next action. Therefore an undelivered best result cannot license deferral. Such an +obligation remains successor strain and requires an approved durability-contract owner; it must not +be invented in `CaptureIssue` or in a new record here. + +### Existing-operation sequence + +Before quieting, session control uses existing operations in this order: settle/sweep and archive; +recompute version-bound completion; locate every blocker; durably deliver the best current +projection; validate recoverable session-log/capture-store changes and the existing pending +affordance; compute the licensing report; then quiet only if `licensed` is true. On re-entry it +reloads the same authoritative surfaces, validates the report's bound revisions and pointers, and +recomputes completion and licensing. There is no create/update/consume lifecycle for a new deposit. + +## Claims, limits, and replay + +This contract claims only deterministic, version-bound completion and deferral-licensing +computation shapes over existing authorities. It does not show that the harness, plugin SDK, +capture store, sweep, controller, detector, binding, projection, or application implements them. +FE-1407's specified and candidate prevention claims keep those grades. + +The [rehearsal](../evidence/proofs/design/elicitation-completion-rehearsal.md) owns the provisional +CPS demand table, all prefix assessments, failure-signature verdicts, amendments found by replay, +and successor evidence. Keeping those judgment-bearing results out of required behavior prevents a +single baseline oracle from becoming generic plugin canon. + +## Out of scope + +- runtime, detector, controller, or TypeScript implementation; +- capture-envelope, `CaptureIssue`, session-state, or durability-contract changes; +- final CPS demand-table authoring; +- projection, realization, or delivery validation; and +- a public lifecycle-status enum. diff --git a/libs/@hashintel/brunch-agent/docs/specs/plugin-contract.md b/libs/@hashintel/brunch-agent/docs/specs/plugin-contract.md index db6cea0b736..8cdc8dbde78 100644 --- a/libs/@hashintel/brunch-agent/docs/specs/plugin-contract.md +++ b/libs/@hashintel/brunch-agent/docs/specs/plugin-contract.md @@ -199,10 +199,12 @@ categories are plugin-authored. (Ratified as FE-1393 design input.) ```yaml PluginContract: + version: immutable string or digest # bound into every completion snapshot/report modelSchema: NodeKind[] # register 2 — derived, never stored proposalCatalog: ProposalType[] # register 1 — utterance-shaped, envelope-wrapped foldTable: FoldRow[] # overrides only; default rules derive from SlotDecl - demandTable: { rows: DemandRow[], staticFloor: string[] } + demandTable: + { version: immutable string or digest, rows: DemandRow[], staticFloor: DemandClause[] } variantDimension: enum? # e.g. prescribed | practiced; enables slot state 'diverged' lossCategories: enum[] @@ -309,13 +311,23 @@ are genuine alternatives must be declared as such and handled by the plugin's ex alternative rule; they do not authorize the fold to choose one. A higher-grade value replaces a lower-grade value only through an explicit supersession, after which the lower capture is no longer active. Regime divergence is per-slot; a regime-split _existence_ (the off-shift wash -that's prescribed-possible, practiced-never) is the degenerate node-level case. +that's prescribed-possible, practiced-never) is the degenerate node-level case. The present +`diverged` shorthand exposes neither side's grade nor support captures. Completion therefore fails +a demanded diverged slot with `unevaluable-divergence`; FE-1431 owns an evaluable constituent +shape and the later author-selectable all-sides/either-side rule. ### Demand, scope, and firing conditions Requiredness is question-relative: a static floor (≥1 objective; entity coverage; a happy-path flow) plus objective-demanded grades (a capacity objective demands quantile-grade durations on -the activities in its support). Demand rows map anchor patterns to `ScopeExpr → grade` maps. +the activities in its support). `DemandClause` is the smallest sufficient union: a presence clause +declares minimum cardinality over `ScopeExpr`; a slot clause declares scope, slot, +minimum grade, accepted epistemic statuses, and accepted absences. Presence clauses express +objective, entity, and path existence. Slot clauses require every selected slot to pass and an +empty selection fails. All matched clauses are conjunctive. Every active completion anchor must +match at least one row. Plugin and demand-table immutable versions are bound with target-document +revision into every evaluation and report. The complete evaluation and report shape live in the +provisional [target-document completion contract](elicitation-completion.md). `ScopeExpr` has three constructors — `kind`, `where`-filter, `inSupport(anchor)` — and **September ships kind-only**; the other two are the named growth path. `support(anchor)` is defined as reference closure over a plugin-declared list of support-bearing proposal types