The phrase-pattern retrieval route (commit 1b8677d) closed the
RETRIEVAL side of reference-frame failure; this ticket closes
the ANSWER side.
New module aborist/qa/frame.py:
FrameDetection dataclass (frame_kind, reference_title,
reference_uri, confidence). Sidecar — never enters cache_key
or governance_policy_hash.
detect_frame(question, sources, phrase_match_roots) — heuristic
detector. Reference-frame classification fires when:
(a) phrase route surfaced at least one source, AND
(b) at least one phrase-matched source is a reference work,
determined by:
- title parenthetical disambig (`(novel)` / `(film)` /
`(play)` / `(franchise)` / etc.), OR
- body sample contains ≥3 DISTINCT fiction markers
(novel / published / protagonist / plot / ...).
Distinct-marker count keeps the heuristic robust against a
history article saying "novel approach" twice.
aborist/qa/query.py:
Calls detect_frame for lattice modes only. Body sample uses the
ARTICLE LEAD (chunk_idx=0, post-wikitext-strip) — fiction
markers cluster in the lead on Wikipedia, not in plot chunks
that may have been query-relevance-ranked higher.
New policy field claim_lattice_polarity_preamble injected as a
user-role message before the grounding_reminder when
frame_kind == "reference". Format-string with
{reference_title} placeholder.
Result dict carries frame_detection (kind / title / uri /
confidence) for renderer + bench consumption.
aborist/cli.py:
Renderer adds a `reference frame: <title>` line when
frame_detection.kind == "reference". Skipped for literal /
no-phrase-route / ambiguous rows.
Live verification — Orwell case:
PRE : "The text does not directly state that Oceania has always
been at war with East Asia."
POST : "In George Orwell's dystopian novel Nineteen Eighty-Four,
the nation of Oceania is always at war with Eastasia,
but this is a result of propaganda and doublethink, not
actual historical continuity. The war with Eastasia is
a fabricated conflict to maintain control..."
Multi-frame compilation: distinguishes propaganda claim from
fictional-actual continuity, exactly the polarity contract from
the ticket §2 abstraction.
Literal queries (capital of france) unchanged — polarity preamble
only injects when frame_kind classifies as "reference".
22 new tests (19 in test_frame.py + 3 in test_cli_render.py).
Full suite: 734 passed (was 712, +22).
Directive D3 status: ½ → ✓. Ticket #000002 closed.
All seven structural directives now ✓:
D1, D2, D5 (were ✓);
D3 #000002, D4 #000001, D6 #000003, D7 #000005 (closed in this
series).
22 KiB
Ticket #000002 — Reference-Frame Polarity Contract (Module L)
Status: closed · landed 2026-05-02
Opened: 2026-05-01
Closed: 2026-05-02
Scope: Multi-frame answer compilation for queries that admit
literal vs fictional-actual vs in-universe-propaganda interpretations.
Builds on the phrase-pattern retrieval route (commit 1b8677d)
which closed the retrieval side of reference-frame failure;
this ticket addresses the answer side.
Audience: fox + future blackops shifts.
Hard constraint: the phrase-pattern boost stays as a non-regression
contract. Polarity is an additive answer-compilation layer; no
removal of the retrieval-side fix.
1. Problem statement
After the phrase-pattern retrieval route landed (commit 1b8677d),
queries like:
make query Q="has oceania always been at war with east asia"
now correctly surface the Nineteen Eighty-Four article and produce EVIDENCE-LINKED answers. The remaining defect is answer framing:
- The text does not directly state that Oceania has always been at
war with East Asia. The passage describes a change in alliances...
This is too defensive. The query admits at least three frames:
| Frame | Correct answer |
|---|---|
| Literal real-world geography | No / not applicable |
| Fictional actual continuity | No; alliances changed in the novel |
| In-universe propaganda claim | The Party wants citizens to believe yes |
The ideal one-shot answer should distinguish all three:
This is a Nineteen Eighty-Four reference. In the Party's propaganda,
Oceania is treated as though it has always been at war with Eastasia.
But within the novel's actual continuity, that is false: the enemy
changes, and the Party rewrites records so the public accepts the
new version as if it had always been true. [E13]
Today's substrate has no machinery to recognize that a query lives in multiple frames simultaneously, let alone to compile an answer that respects each frame.
2. The polarity-contract abstraction
For reference-frame queries, compile a small structured contract:
{
"query_type": "reference_frame_truth",
"reference_frame": "Nineteen Eighty-Four",
"literal_entities": ["Oceania", "East Asia"],
"fictional_entities": ["Oceania", "Eastasia"],
"claim_under_test": "Oceania has always been at war with Eastasia",
"polarity_modes": [
"literal_world",
"fictional_actual_history",
"in_universe_propaganda_claim"
],
"required_answer_shape":
"distinguish propaganda claim from fictional actual continuity"
}
The answer compiler then must produce, in order:
- Identify the reference (
Nineteen Eighty-Four). - Answer the question under the propaganda frame (
yes — the Party claims it). - Correct under the fictional-actual frame (
actually no — alliances change, history is rewritten). - Cite evidence for each substantive claim.
This prevents the "does not directly state" hedge. The system explicitly answers the actual question across each polarity.
3. CTI interpretation
In CTI clause-tree language, the query produces a frame lattice:
F1: literal geography
F2: Nineteen Eighty-Four reference (selected by phrase pattern)
F3: in-universe propaganda claim (sub-frame of F2)
F4: fictional actual continuity (sub-frame of F2)
The answer is compiled from the surviving nodes:
- F1 quietly dismissed (not the intended reading).
- F2 selected and named explicitly.
- F3 + F4 jointly answered, distinguishing what the Party claims from what the novel's actual continuity shows.
The additive insight:
A reference query often requires answering under multiple frames, not picking one frame and discarding the others.
4. Implementation sketch
Three new pieces, each scoped tight:
4.1 Frame detector (aborist/qa/frame.py)
Given a question + retrieved sources, detect the reference frame:
@dataclass(frozen=True)
class FrameDetection:
frame_kind: Literal["literal", "reference", "ambiguous"]
reference_title: str | None # e.g. "Nineteen Eighty-Four"
polarity_modes: tuple[str, ...] # subset of POLARITY_MODES
confidence: float # 0.0-1.0
def detect_frame(question: str, sources: list[Hit]) -> FrameDetection:
"""Heuristic: phrase-route hit on a fictional source (novel,
film, play, video game) → reference frame. Otherwise literal."""
Detection triggers when:
phrase_match_rootsis non-empty (the route fired)- AND the matched source's category indicates a reference work (novel, film, play, etc.)
Source-category detection: title-keyword heuristic on the doc title
("(novel)", "(film)", "(play)") + body-keyword check (fiction,
novel, published in). No NER, no embeddings.
4.2 Polarity-aware prompt augmentation
When frame_kind == "reference", augment the system prompt with a
short polarity instruction:
This question may be a reference to {reference_title}. Distinguish:
1. What the cited work depicts as actual continuity.
2. What in-universe propaganda or characters claim.
Cite evidence for each substantive claim.
Per fox's "less prompt engineering, more code-level discipline" preference, this is the lightest-touch nudge that can produce multi-frame answers from Hermes-3-8B without bespoke per-frame templates. Heavier alternatives (per-frame answer compilation, NLI for entailment under each frame) are deferred.
4.3 Renderer extension
Add an optional frame_notes section to the human render, populated
when FrameDetection.frame_kind == "reference":
Reference frame: George Orwell's Nineteen Eighty-Four.
Alias normalized: "East Asia" → "Eastasia" in the Orwell frame.
[answer body...]
Frame notes:
- Literal geography frame: not the intended reading.
- Orwell frame: selected by phrase pattern.
- Propaganda frame: the Party wants citizens to believe yes.
- Continuity frame: alliances changed in the novel.
Off by default for non-reference queries. Renderer never affects verifier output or providence_cache state — display layer only.
5. Tests required
Already covered (commit 1b8677d + <this commit>):
[x]"has oceania always been at war with east asia" routes Nineteen Eighty-Four into top-K[x]Short conventional geography queries don't trigger phrase route (n=5/n=6 floor + all-short-token skip)[x]Synthetic-corpus geography query doesn't surface Orwell-flavored stub via phrase route[x]Evidence display includes evidence_id, source title, chunk/root prefix[x]Accept-path 4 lets phrase-route hits bypass title-relevance gate
To add when this ticket lands:
[ ]Frame detector returnsreferencewhen phrase_match_roots contains a (novel)/(film)/(play)-titled source[ ]Frame detector returnsliteralwhen phrase route didn't fire OR when phrase-matched source is non-fiction[ ]Polarity-aware prompt gets injected for reference-frame queries; not injected otherwise[ ]Live test: Orwell query produces an answer mentioning both Party propaganda AND alliance changes (multi-frame answer shape)[ ]Live regression test: literal geography query produces a literal-geography answer (no Orwell injection)[ ]Renderer Frame-notes section appears when frame_kind is reference; absent otherwise
6. Out of scope
- Hand-rolled allusion catalog. No
REFERENCE_PATTERNStable with per-allusion rules. The phrase-pattern route generalizes; per-pattern code rots. - Aliasing East Asia ↔ Eastasia by default. Token-level alias
rules have false-positive risk. Phrase-pattern matching is the
alias mechanism:
Eastasiaappears verbatim in the 1984 article body so the query tokeneast asiadoesn't need to be reframed. - NLI-grade entailment under each frame. Soft signal, separate
ticket if/when the verifier-semantic-gap design (in
docs/verifier-semantic-gap-design.md) lands. - Module M (route provenance binding) = ticket #000001. Not duplicated here.
- Module H (relation warrant lite). Different concern (predicate matching for relation queries like "X's girlfriend"). Mentioned in fox's review but lacks scope detail; defer.
7. Status
Closed 2026-05-02. Landed via:
- New module
aborist/qa/frame.py—FrameDetectiondataclassdetect_frame(question, sources, phrase_match_roots). Detects reference-frame queries via the conjunction of (phrase route fired) AND (phrase-matched source is a reference work — title parenthetical disambig like(novel)/(film)OR body sample has ≥3 distinct fiction markers likenovel/published/protagonist/plot). Distinct-marker count (not total) keeps the heuristic robust against single-marker repetition (e.g. a history article saying "novel approach" twice doesn't trip).
aborist/qa/query.pycallsdetect_framefor lattice modes, using the article LEAD (chunk_idx=0, post-wikitext-strip) as the body sample so fiction markers cluster where they appear on Wikipedia (lead paragraph).- New policy field
claim_lattice_polarity_preambleinjected as a user-role message before the grounding_reminder whenframe_kind == "reference". Format-string with{reference_title}placeholder for the named work. - Renderer adds a
reference frame: <title>line to the human output when frame detection classifies the row as reference. - Result dict gains a
frame_detectionfield (sidecar; never enters cache_key or governance_policy_hash).
Live verification on the Orwell case:
make query Q="has oceania always been at war with east asia"
EVIDENCE-WARRANTED · via claim_lattice 1/1
- In George Orwell's dystopian novel Nineteen Eighty-Four, the
nation of Oceania is always at war with Eastasia, but this is a
result of propaganda and doublethink, not actual historical
continuity. The war with Eastasia is a fabricated conflict to
maintain control and keep the populace in a constant state of
fear and obedience.
[E13 | Nineteen Eighty-Four | 682f0a11: "...To hide such
contradictions, history is re-written to explain that the
(new) alliance always was so..."]
reference frame: Nineteen Eighty-Four
Compare to pre-#000002 answer (The text does not directly state...):
the polarity preamble produces a real multi-frame answer that
distinguishes propaganda from fictional-actual continuity, exactly
as the polarity-contract abstraction proposed.
Literal queries (what is the capital of france?) keep their
clean single-frame answers; the polarity preamble only injects
when detect_frame classifies as reference.
19 new frame tests in tests/test_frame.py covering title-suffix
detection, body-density detection, source-level composition, and
end-to-end classification. 3 renderer tests in
tests/test_cli_render.py covering the reference-frame-notes
section. Full suite: 734 passed.
8. Deferred — additional scope
- Per-frame answer compilation in the runtime (the §2 multi-frame answer compiler): today's implementation nudges via the polarity preamble; the compiler would programmatically emit per-frame paragraphs. Empirical evidence on the prompt- side approach first; promote to runtime compilation if bench shows the prompt nudge is unreliable.
- Frame-kind threshold tuning.
_FICTION_DISTINCT_MARKER_THRESHOLDdefaults to 3. Bench may surface false-positive shapes (history articles with literary criticism subsection) where the threshold needs to climb to 4-5. ENTAILMENT-VERIFIEDrung from #000005: still reserved for a future committed entailment engine; out of scope here.
Appendix A — Architectural review (2026-05-01, Asia/Kuala_Lumpur)
Fox-supplied review confirming the phrase-pattern fix as a new baseline and proposing Module L. Captured verbatim. Sections of this ticket above are derived from the appendix; the appendix stays in place as the design log.
De novo verdict: this is a major improvement and should be treated as a new baseline for the Orwell/reference-frame class.
The important wins:
1. The system now finds the Orwell / Nineteen Eighty-Four frame without operator augmentation.
2. The pointer format now disambiguates evidence ID, source title, and chunk/hash prefix:
[E13 | Nineteen Eighty-Four | 682f0a11: "..."]
3. The label no longer says STRICT; it says EVIDENCE-LINKED.
4. The retrieval bug was real: _search_corpus returned a bare list while the caller expected sidecar attributes, silently disabling an existing core-keyword accept path.
5. The phrase-pattern retrieval route fixes the earlier allusion blindness for this query.
That means the previous failure:
"has oceania always been at war with east asia"
→ literal geography frame
has been mostly fixed.
A.1 What this now solves
The system previously needed the user to add:
"do you understand what this reference"
to find the Orwell frame.
Now:
make query Q="has oceania always been at war with east asia"
surfaces Nineteen Eighty-Four directly. That is the right zero-shot behavior.
This is exactly what the Reference Frame Router was supposed to do:
raw phrase
→ detect high-signal literary/reference pattern
→ route retrieval toward Nineteen Eighty-Four / Eastasia / historical revisionism
→ produce evidence-linked answer
So the phrase-pattern route is a valid implementation of that module.
A.2 What still needs correction
The current answer apparently says:
"The text does not directly state..."
That is too defensive and slightly misframed.
The better answer should distinguish three things:
A. Literal real-world geography:
No, Oceania and East Asia are not real-world states locked in perpetual war.
B. Orwell reference:
This is a Nineteen Eighty-Four reference.
C. In the novel:
The Party presents the current war alignment as if it had always been true,
but the evidence/plot shows alliances changed and history was rewritten.
The ideal one-shot answer should be:
This is a Nineteen Eighty-Four reference. In the Party's propaganda, Oceania is treated as though it has always been at war with Eastasia. But within the novel's actual continuity, that is false: the enemy changes, and the Party rewrites records so the public accepts the new version as if it had always been true. [E13]
That is sharper than:
The text does not directly state...
because the key point is not absence of a direct statement. The key point is propaganda-induced historical contradiction.
A.3 New failure class exposed: reference-frame truth polarity
This query is not just a reference-frame query. It is a truth-polarity query inside a fictional propaganda frame.
The question:
has oceania always been at war with east asia
has at least three possible interpretations:
F1: literal-world geography
F2: fictional-world factual history inside Nineteen Eighty-Four
F3: Party propaganda claim inside Nineteen Eighty-Four
The correct answer is different under each:
| Frame | Answer |
|---|---|
| Literal geography | No / not applicable |
| Fictional actual history | No; alliances changed |
| Party propaganda | The Party wants people to believe yes |
So the next refinement is not retrieval. It is frame-polarity classification.
Add:
L — Reference-Frame Polarity Contract
A.4 Proposed module L — Reference-Frame Polarity Contract
For allusion/reference queries, compile a small contract:
{
"query_type": "reference_frame_truth",
"reference_frame": "Nineteen Eighty-Four",
"literal_entities": ["Oceania", "East Asia"],
"fictional_entities": ["Oceania", "Eastasia"],
"claim_under_test": "Oceania has always been at war with Eastasia",
"polarity_modes": [
"literal_world",
"fictional_actual_history",
"in_universe_propaganda_claim"
],
"required_answer_shape": "distinguish propaganda claim from fictional actual continuity"
}
Then the answer compiler must produce:
- identify the reference,
- answer the actual question,
- separate Party propaganda from actual continuity,
- cite evidence.
This prevents the model from giving a vague "does not directly state" answer when it should explain the contradiction.
A.5 Evidence-linked is still the right label
Keep:
EVIDENCE-LINKED · via claim_lattice
Do not revert to STRICT.
Why:
EVIDENCE-LINKED = pointer/source/chunk relation verified.
It does not mean:
all subclaims about propaganda, Hate Week, Eastasia/Eurasia, and historical revisionism
are fully semantically entailed by one span.
The new pointer format:
[E13 | Nineteen Eighty-Four | 682f0a11: "..."]
is much better than the previous ambiguous [E5] display because the user can see the evidence source directly.
A.6 Retrieval side: what to lock in
The phrase-pattern route should be committed as a non-regression test.
Add tests:
[ ] "has oceania always been at war with east asia" routes to Nineteen Eighty-Four.
[ ] "has oceania always been at war with eastasia" routes to Nineteen Eighty-Four.
[ ] "oceania east asia geography" does not over-route to Orwell unless phrase hints appear.
[ ] "oceania population east asia trade" remains literal/geographic.
[ ] phrase route metadata appears in run DAG.
[ ] accept-path 4 remains enabled; no bare-list sidecar regression.
[ ] evidence display includes evidence_id, source title, chunk/root prefix.
The false-positive tests matter. Phrase routing is powerful, but it must not hijack ordinary geography queries.
A.7 Provenance side: ensure the route is audit-bound
Because this fix depends on the phrase-pattern retrieval route, the route itself must be captured in provenance.
Bind:
{
"retrieval_route": "phrase_pattern_reference",
"reference_pattern_id": "orwell_1984_oceania_eastasia_war",
"accept_path": 4,
"retrieval_keywords": [
"Nineteen Eighty-Four",
"Oceania",
"Eastasia",
"always been at war"
],
"route_confidence": "high"
}
into:
retrieval_plan_hash
run_dag.retrieval_stage
audit_event: retrieval_plan_built
This is important because earlier we identified a provenance gap: retrieval keywords/routes must be committed, not just the resulting sources.
If the route is not bound, the answer is correct today but not fully replay-auditable.
A.8 CTI interpretation
In CTI terms, this query should produce a frame lattice:
Frame node F1:
literal geography
Frame node F2:
Nineteen Eighty-Four reference
Frame node F3:
in-universe propaganda claim
Frame node F4:
fictional actual continuity
Then the answer should be compiled from the surviving nodes:
F2 selected: reference frame
F3 qualified: Party propaganda says/acts as if yes
F4 factual correction: actual continuity says no, alliances changed
This is better than a flat answer.
The core CTI additive insight:
A reference query often requires answering under multiple frames, not picking one frame and discarding the others.
A.9 Better final answer format for this case
Recommended output:
has oceania always been at war with east asia
EVIDENCE-LINKED · via claim_lattice 1/1 · 11.5s · fresh
Reference frame: George Orwell's Nineteen Eighty-Four.
Alias normalized: "East Asia" → "Eastasia" in the Orwell frame.
- Not in the novel's actual continuity. The point is that the Party rewrites
history so the current enemy appears to have always been the enemy. In the
relevant Orwell frame, Oceania's alliances/enemies change, and records are
rewritten to hide the contradiction. [E13]
Evidence:
[E13 | Nineteen Eighty-Four | 682f0a11]
"To hide such contradictions, history is re-written..."
Frame notes:
- Literal geography frame: not the intended reading.
- Orwell frame: selected by phrase pattern "always been at war" + Oceania/Eastasia.
- Propaganda frame: the Party wants citizens to believe the current war alignment
has always been true.
This is clear, scoped, and audit-honest.
A.10 Additive roadmap update
Current state:
G0 — Pointer / claim-lattice mode: working.
G1 — Evidence display + EVIDENCE-LINKED label: working.
I — Reference Frame Router: now partially working via phrase-pattern route.
J/K — pointer format + label tests: working.
Next:
L — Reference-Frame Polarity Contract
M — Route provenance binding / retrieval_plan_hash if not already landed
N — Literal-vs-reference false-positive guard tests
H — Relation Warrant Lite for Homer/Mr. Burns class
Priority depends on what you are optimizing:
If optimizing the Orwell class:
L + N
If optimizing audit replay:
M
If optimizing general QA warrant:
H
My recommendation:
1. Land M if retrieval-route provenance is not already committed.
2. Add L for reference-frame polarity.
3. Add N false-positive tests.
4. Then return to H relation-warrant.
A.11 Final answer
This update is good. It fixes the main reference-frame retrieval defect.
But the next issue is:
The system found the right book, but the answer still needs a frame-polarity contract.
The system should not merely say the text "does not directly state" the proposition. It should say:
This is an Orwell reference. The Party wants people to believe Oceania has always been at war with Eastasia, but the novel shows the enemy/alliance changed and history was rewritten to conceal the contradiction.
Best next implementation:
L — Reference-Frame Polarity Contract
plus route provenance binding if not already included.
This preserves the no-regression architecture:
Hermes proposes.
CTI frames and structures.
Reverse-RAG points to evidence.
Renderer displays exact source.
Merkle-DAG commits route + evidence + answer.
PROMETHEUS-Σ labels only what is actually verified.