Commit graph

19 commits

Author SHA1 Message Date
c36e85c86c
qa(#000009): preflight stage binds into run_dag_root
Closes ticket #000009 zero-shot. Scope expanded to cover BOTH
ticket #000008 (broad-quantifier) AND ticket #000010
(meta-cognition) preflight contracts in a single combined node —
both share the same audit-replay gap and inserting two separate
nodes between question and retrieval was operationally awkward.

aborist/qa/dag.py:
  + preflight_node_hash() — combines QuestionState +
    quantifier classifier output + behavioral policy_state into
    one canonical SHA-256 hex.
  + build_run_dag() gains optional preflight_hash parameter.
    When supplied, inserts {"stage": "preflight", "hash": ...}
    at position 1 (between question and retrieval).
    Backward-compat: None → original 7/9-stage shapes preserved
    for legacy run_dag_root re-validation.

  Quote-mode: 7 → 8 stages with preflight.
  Pointer-mode CTI: 9 → 10 stages with preflight.

aborist/qa/query.py + runner.py:
  Both build the preflight payload from question_state +
  quantifier dict + 10-field policy_state (guard_enabled,
  guard_apply_caps, guard_apply_caps_mode_gated,
  claim_cap_resolved, claim_cap_actually_applied,
  reminder_enabled, reminder_eligible, reject_broad_active,
  metacognition_enabled, block_on_contradiction).

  This means two cache rows that share the same question + same
  model output + same verifier verdict but DIFFERENT preflight
  policy state now produce different run_dag_root values. Audit
  replay can pin the policy decision per row.

9 new tests in tests/test_dag.py:
  - preflight_node_hash determinism
  - hash bumps on question_state change
  - hash bumps on policy_state change (the audit-replay payoff)
  - all-None defensive shape
  - 7→8 stage transition (quote mode)
  - 9→10 stage transition (pointer mode), preflight at index 1
  - run_dag_root bumps when preflight_hash bumps
  - verify_run_dag round-trips through preflight stage

Live verification: latest providence_cache row carries
['question', 'preflight', 'retrieval', 'evidence_map', 'prompt',
'raw_answer', 'parsed_claim_lattice', 'verify', 'render',
'final_label'] — preflight stage living in the persisted DAG.

987 tests passing (9 new); 36 skipped.

Tickets:
  #000009 status: closed · landed 2026-05-03 (zero-shot)
  #000010 cross-ref updated: "DAG binding shipped via #000009"

What's NOT in this ticket (logged in §7.2):
  - CLI flag for inspecting preflight node from cache_key
  - Bench harness preflight_hash field for cross-row comparison
  - SOFT_PREFLIGHT_HINT (model-assisted preflight sidecar)
2026-05-03 18:34:16 -04:00
f2bbe512db
qa(#000010): Phases 2-4 land — wired, governed, labeled, benched
Closes ticket #000010 (Meta-Cognition Preflight Guard). Mechanism
complete; defaults preserve the dry-run discipline pattern from
#000008.

Phase 2 — wire preflight into query() and runner.ask():
  - preflight_question() runs after policy resolution + quantifier
    classification, before retrieval.
  - QuestionState surfaces on miss path, cache-hit path, AND
    reject-broad early-return path of query() — schema column-
    aligned across all four returns.
  - runner.ask() carries the same fields for `aborist ask` parity.

Phase 3 — policy fields + governance hash + CLI flags:
  - 6 new policy fields, all default-on except
    metacognition_block_on_contradiction (default False — label-
    only by default; opt-in via --block-on-contradiction).
  - All 6 folded into _VERIFIER_POLICY_FIELDS so flipping any
    invalidates prior cache records on lookup.
  - 2 new CLI flags on `aborist query`:
      --no-preflight             Level 2 master kill
      --block-on-contradiction   strict mode (hard-block on
                                 lexical contradictions)

Phase 4 — audit-line labels + bench fields + tests:
  - _render_warrant_tail extended with 5 metacog tail tokens:
      · false premise
      · contradictory
      · stale risk
      · out of corpus
      · frame ambiguous
  - Bench rows in qa_sweep.py gain 7 new bounded-size projection
    fields (logical_statuses, question_shape, preflight_result,
    temporal_sensitivity, has_false_premise, has_contradiction,
    corpus_requirement). Full QuestionState stays on result dict
    for CLI render only.
  - tests/test_metacognition.py grew from 42 → 68 tests
    (16 new: 6 governance + 6 audit-line tail + 4 default-policy
    pinning).

Live verified end-to-end:

  $ make query-dry Q="Who is the current CEO of OpenAI?" BURN=1
    UNGROUNDED · via claim_lattice · stale risk
  $ make query-dry Q="When did Mr. Burns become Homer's biological
                      father?" BURN=1
    UNGROUNDED · via claim_lattice · false premise

978 tests passing; 36 skipped.

What's NOT shipped (deferred):
  - Run-DAG node binding for metacognition_preflight stage —
    joins ticket #000009 Phase 5 (same audit-replay gap; both
    nodes can land together).
  - Reference-frame plumbing — frame_detection runs post-retrieval,
    preflight here is pre-retrieval; deferred until two-pass
    or post-classification update lands.
  - SOFT_PREFLIGHT_HINT (model-assisted sidecar) — source doc §18
    reserves this label; hard rule preserved (no LLM in preflight
    hard path).
  - Bench A/B measuring preflight on vs off — quick to run once
    stack settles.

Ticket #000010 status: closed · landed 2026-05-03.
2026-05-03 18:22:18 -04:00
55efb04a58
qa(#000010): Phase 1 — metacognition.py module + 42 tests
Implements the Meta-Cognition Preflight Guard (M0 / MCTL) per
fox's directive at ~/Downloads/meta-cognition_for_hermes(1).txt
(2026-05-03).

aborist/qa/metacognition.py:
  - QuestionState dataclass (frozen, JSON-serializable via to_dict)
  - preflight_question() pure function: classifies a question
    deterministically into a QuestionState before generation
  - 4 new detectors:
      detect_temporal_sensitivity() — current/latest/today/CEO/etc.
      detect_contradiction()        — lexical pairs (unmarried+spouse,
                                      always+never, alive+dead, etc.)
      detect_false_premise()        — presupposition patterns:
                                      when did X stop/become Y,
                                      why did X cause Y,
                                      how did X become Y
      detect_out_of_corpus()        — my-uploaded-X / file-I-sent shapes
  - Reuses #000008 quantifier classifier (no duplication)
  - Composes 8 LogicalStatus values:
      well_formed, under_specified, false_premise_suspected,
      contradictory_question, out_of_corpus_risk, stale_risk,
      reference_frame_ambiguous, broad_quantifier_unbounded
  - Three preflight results: PREFLIGHT_OK / _PARTIAL / _BLOCKED
  - Per-detector enable switches in policy:
      metacognition_enabled (master kill)
      metacognition_temporal_check
      metacognition_contradiction_check
      metacognition_false_premise_check
      metacognition_out_of_corpus_check
      metacognition_block_on_contradiction (default False — label
                                            only by default; opt-in
                                            to hard-block)
  - preflight_policy_hash for governance binding (Phase 3)
  - PREFLIGHT_VERSION = "metacognition-v0.1"

Hard rule (D1): no LLM in this hard path. Pure regex + lexical
matching. Model-assisted preflight, if added later, labels itself
SOFT_PREFLIGHT_HINT (not implemented in this phase).

42 new tests cover the seven test cases from source doc §14
(false-premise, contradictory, broad-quantifier, reference-frame,
time-sensitive, out-of-corpus, model-cutoff) plus per-detector
unit tests, gating (master kill, per-detector disable,
block-on-contradiction opt-in), determinism (question_hash
stable, policy_hash bumps on flip), and serialization.

Ticket #000010 opened with status `open · in progress
(zero-shot 2026-05-03)`. TICKETS.md index updated; Next ID bumped
to 000011.

Phases 2-4 still queued (wire into query/runner, policy fields +
governance, audit-line labels + bench fields).

962 tests passing (42 new); 36 skipped.
2026-05-03 18:10:50 -04:00
08678173e1
ticket(#000008,#000009): close #8; open #9 for DAG binding; Makefile shortcuts
Closes #000008 with status `closed · landed in 4f2b5a6` per the
docs/TICKETS.md convention. The preflight guard mechanism + bench
cycle + default flip all shipped 2026-05-03; the design log stays
in place.

Opens #000009 — Quantifier preflight run-DAG node binding. Splits
the Phase 5 follow-up out of #000008 §11.11 into its own ticket.
Scope: bind the classifier output + policy decision into
`run_dag_root` so audit replay can distinguish guard-on vs guard-off,
cap-applied vs not, reminder-injected vs skipped. Currently those
appear on the result dict but are NOT in the run-DAG hash. Required
to close the audit-replay gap that blocks the §9.5 Merkle-AGI-DAG
framing from fully holding. Estimated 3-4h. Awaiting go/no-go.

Makefile shortcuts for the #000008 CLI flags (operator ergonomics):

  BROAD=1         → --apply-quantifier-caps  (flip cap apply-gate)
  REJECT_BROAD=1  → --reject-broad           (preflight rejection)
  ALLOW_BROAD=1   → --allow-broad            (emergent search)

Available on both `make query` and `make query-dry`. Default
behavior unchanged: ANSWER_MODE=claim_lattice (JSON), reminder ON
for lattice modes, cap operator-opt-in.

Smoke-tested:

  $ make query-dry Q="winners of all major sports?" BROAD=1
      → cap applies on JSON; classifier reports ALL/unbounded
  $ make query-dry Q="winners of all major sports?" REJECT_BROAD=1
      → preflight rejection, exit-1 (consistent with UNGROUNDED)

TICKETS.md index:
  #000008  closed · landed in `4f2b5a6`
  #000009  open · awaiting go/no-go (D3, D4)
  Next ID  bumped 000009 → 000010
2026-05-03 17:57:56 -04:00
4f2b5a6685
qa(#000008): §12.10 n=5 verification + §12.11 defaults flipped (Option A)
n=5 verification of cap+reminder cell (135 runs):

  Metric              | n=3       | n=5
  --------------------+-----------+------------
  JSON SR             | 0.30      | 0.33     ← matches cap-only
  JSON UNGROUNDED rate| 1/27 (4%) | 2/45 (4%) ← matches reminder-only
  pointer SR          | 0/27      | 0/45     ← unchanged across all cells

The §12.8 0.30 was Hermes nondeterminism. n=5 confirms cap+reminder
delivers cap-only's STRICT-rate AND reminder-only's UNGROUNDED-rescue.

§10.8 strict gate met at n=5:
  vs reminder-only on JSON SR:    +11pp (clears floor)
  vs cap-only on JSON UNGROUNDED: -18pp (clears floor)
  vs cap-only on ptr mean ratio:  +12pp (clears floor)

Defaults flipped — Option A landing (per-mode tailored):

  quantifier_reminder_enabled  False → True
                              (load-bearing on both lattice modes)

  NEW field: quantifier_apply_caps_modes = ["claim_lattice"]
                              (allowlist for which modes apply caps
                               when apply_caps=True; JSON-only since
                               cap-on-pointer is wasted noise per
                               §12.10 0/45 STRICT data)

  quantifier_guard_apply_caps  False → False (UNCHANGED)
                              (operator opts in via
                               --apply-quantifier-caps; preserves
                               §10.11.3 dry-run discipline)

Cap-application gate now reads:
  if apply_caps AND mode in apply_caps_modes AND cap is not None:
      effective_max_claims = looked_up_cap

quantifier_apply_caps_modes folded into _VERIFIER_POLICY_FIELDS so
flipping the allowlist invalidates prior cache records.

5 new tests pin: reminder default ON for both runner.DEFAULT_POLICY
and query.DEFAULT_QUERY_POLICY; apply_caps_modes default
["claim_lattice"]; governance-hash invalidation on allowlist flip;
apply_caps default still False (dry-run preserved).

920 tests passing (5 new); 36 skipped.

Operator behavior:
  $ aborist query "winners of all major sports?"
      → reminder ON, cap OFF (default after this commit)
  $ aborist query --apply-quantifier-caps "..."
      → cap applies on claim_lattice (JSON) only
  $ aborist query --apply-quantifier-caps \
        --policy quantifier_apply_caps_modes='["claim_lattice","claim_lattice_pointer"]' "..."
      → Option D for one call

Phase 5 (run-DAG node binding for quantifier_preflight) and
cross-model Qwen/GPT-4 verification remain as follow-ups per §11.11.
2026-05-03 17:25:38 -04:00
9780cca4d3
docs: §12.8/§12.9 cap+reminder verdict + cross-doc updates
#000008 §12.8 — Cap+reminder A/B (2026-05-03T12-54-11Z, 81 runs):

  Metric              | Base | Rem  | Cap  | Cap+Rem
  --------------------+------+------+------+--------
  JSON SR             | 0.19 | 0.22 | 0.33 | 0.30   ← cap-only wins SR
  JSON UNGROUNDED     |  7   |  1   |  6   |  1     ← rem dominates U-rescue
  pointer mean ratio  | 0.473| 0.643| 0.516| 0.684  ← cap+rem best
  pointer FORMAT_COLL |  2   |  0   |  2   |  0     ← rem-driven

§10.8 strict gate "compound beats either alone by ≥5pp on every metric"
NOT cleanly met. Cap+reminder beats reminder-only by +8pp on JSON SR
(clears floor) and beats cap-only by +17pp on pointer mean ratio
(clears floor), but is -3pp vs cap-only on JSON SR (regression,
within noise).

#000008 §12.9 — Final verdict + recommendation:

  Mechanism asymmetry (clean signal):
    Reminder rescues UNGROUNDED → HYBRID
    Cap rescues HYBRID → STRICT

  Recommendation: Option A — single-knob defaults, per-mode tailored:
    claim_lattice (JSON):   apply_caps=True + reminder=True
    claim_lattice_pointer:  apply_caps=False + reminder=True
                            (cap can't rescue pointer-tag discipline
                             upstream of cap; cap fires 20× without
                             verdict gain)
    quote:                  guard mode-gated off (already default)

  Caveat: n=3 × 9 = 27/cell variance is ~3-4pp; recommend n=5
  verification on cap+reminder before flipping defaults.

Cross-doc updates:

- CLAUDE.md: architecture diagram now lists the three new Phase 1-3
  modules (quantifier.py, model_profiles.py, quantifier_reminder.py).
  New "Broad-quantifier preflight guard" conventions entry covers
  the 7 policy fields, six-level disable hierarchy, dry-run
  defaults, CLI flags, and §12 bench summary.

- docs/qa-modes-bench.md: addendum at end pointing at #000008 §12
  four-cell A/B + 4 bench artifact stamps. Original 2026-05-02
  journal frozen; 2026-05-03 broad-subset findings flagged as
  question-mix-dependent narrative on top of the global
  per-mode recommendation.
2026-05-03 15:45:06 -04:00
17c1cde16d
ticket(#000008): §12.7 cap-only A/B — cap and reminder help differently
§12.7 captures the 2026-05-03T12-47-23Z cap-only A/B (apply_caps=
True, reminder=False) on the 9-question broad subset.

  Mode      | Baseline | Reminder | Cap-only
  ----------+----------+----------+----------
  JSON SR   |  0.19    |  0.22    |  0.33    ← +14pp
  JSON U    |   7      |   1      |   6      ← reminder dominates
  JSON S    |   5      |   6      |   9      ← cap dominates
  ptr ratio |  0.473   |  0.643   |  0.516
  JSON ratio|  0.524   |  0.735   |  0.643

§10.8 gate MET on JSON mode (+14pp STRICT-rate).

Headline insight: cap and reminder help in DIFFERENT ways.
- Reminder rescues UNGROUNDED → HYBRID (restates citation rule).
- Cap rescues HYBRID → STRICT (forces fewer-but-better claims).

The two are complementary, not redundant. If §12.8 (cap+reminder)
confirms the compound effect, that's the §10.8 trigger to land
Option D as default. Predicted JSON SR ~0.40 if effects compound.

Pointer mode still 0/27 STRICT under cap-only — TOO_MANY_CLAIMS
fires 20× (vs 7× baseline) but pointer-tag failures upstream of
the cap still gate the verdict.
2026-05-03 08:54:58 -04:00
fa8d93c8ef
ticket(#000008,#000006,index): §12.6 reminder A/B verdict + cross-refs
§12.6 in #000008 captures the 2026-05-03T12-38-53Z reminder-only
A/B (apply_caps=False, reminder=True) on the same 9-question
broad subset:

  Mode      | Strict-rate    | Mean ratio        | UNGROUNDED
  ----------+----------------+-------------------+-----------
  quote     | 0.56 → 0.52    | 0.900 → 0.845     |  0 → 0
  pointer   | 0.00 → 0.00    | 0.473 → 0.643     |  9 → 6
  JSON      | 0.19 → 0.22    | 0.524 → 0.735     |  7 → 1

Pointer-mode violation deltas:
  FORMAT_COLLAPSED      2 →  0  (-100%)
  NO_EVIDENCE_POINTER   9 →  6  ( -33%)
  TITLE_MISMATCH       10 → 15  ( +50%)  ← side effect
  TOO_MANY_CLAIMS       7 →  8  ( +14%)

§10.8 gate verdict: MET. Both FORMAT_COLLAPSED and NO_EVIDENCE_
POINTER cleared the 5pp floor (−7pp absolute / −11pp absolute
respectively). Strongest signals are mean-ratio improvements
(+17pp pointer, +21pp JSON) — grounded rows ground BETTER under
reminder. JSON-mode UNGROUNDED dropped 7 → 1, a 22pp redistribution
from "didn't ground" to "partially grounded".

Caveat: TITLE_MISMATCH increased (+50%). Reminder may pressure
Hermes to cite *something* rather than say "no evidence", picking
up wrong-source citations as a side effect.

Recommendation: §10.8 gate met but hold default flip until §12.7
(cap-only) and §12.8 (cap+reminder) cells run, per §10.8 "if A+B
together outperform either alone by ≥5pp: land Option D".

Cross-references:

- TICKETS.md index: #000008 status flipped to "open · phases 0–4
  landed; bench A/B in progress".
- #000006 rolling log: cross-reference to #000008's bench cycles
  + the d24291b classifier-defect fix surfaced from the
  distribution scan.
2026-05-03 08:48:19 -04:00
002f84c5a4
ticket(#000008): §12 dry-run bench findings + --policy harness flag
§12 captures the 2026-05-03 post-implementation bench cycle:

  §12.1 — pre-bench classifier scan (free, no LLM). Distribution
          across the 73-question bench: 65 SINGULAR, 5 OPEN_REQUEST,
          1 ALL, 1 COMPREHENSIVE, 1 SMALL_NUM_EXPLICIT, 0 MANY.
          Documents the `how many X` defect caught + fixed in
          d24291b.
  §12.2 — live bench on 9-question broad subset (3 modes × n=3 = 81
          runs). Per-mode summary, per-question table, pointer-mode
          violation distribution.
  §12.3 — telemetry verification end-to-end. Sampled per-question
          classifier output showing intensity / scope_bound_hint /
          claim_cap_applied populated as designed.
  §12.4 — §10.8 decision-tree implications. Cap-only unlikely to
          clear 5pp gate (pointer is already 0 STRICT); NO_EVIDENCE_
          POINTER (9/27) is the load-bearing failure → Phase 3
          reminder is the strongest single-knob candidate.
  §12.5 — next bench cycles checklist (reminder-only, cap-only,
          cap+reminder).

Headline findings:
  - JSON mode hits 3/3 STRICT on bounded universal `name all members
    of the beatles`. Same model, same verifier — bounded vs unbounded
    is empirically real (validates §10.1 split).
  - Pointer mode 0/27 STRICT on broad subset. CITATION_MISMATCH(14),
    TITLE_MISMATCH(10), NO_EVIDENCE_POINTER(9), TOO_MANY_CLAIMS(7)
    dominate.
  - Quote mode 0.56 strict-rate validates keeping it out of
    quantifier_guard_modes default.

Bench harness extension:
  bench/qa_sweep.py gains --policy KEY=VALUE flag (repeatable).
  Values are json.loads-decoded so booleans/ints/lists/strings work.
  Enables §10.8 A/B cycles without monkey-patching defaults.
  Plumbed through _run_one via new policy_overrides kwarg.

bench/qa_questions_quantifier_subset.txt landed as the 9-question
A/B fixture for ticket #000008.
2026-05-03 08:39:20 -04:00
041e865132
ticket(#000008): add §11 implementation inventory
Single-source-of-truth section for what was actually built in the
2026-05-03 implementation pass. Complements §8 (commit table) and
§9.6 (per-phase notes) with a full inventory:

- §11.1 New modules: aborist/qa/{quantifier,model_profiles,quantifier_reminder}.py
- §11.2 Modified modules: query.py, runner.py, keys.py, cli.py, qa_sweep.py
- §11.3 New test files: 4 new + 1 extended; 120 new tests total
- §11.4 Seven new policy fields in _VERIFIER_POLICY_FIELDS
- §11.5 Four new CLI flags on `aborist query`
- §11.6 Four new violation kinds (3 soft + 1 hard) with audit tails
- §11.7 New result-dict fields on miss + cache-hit paths
- §11.8 Eight new bench-row fields
- §11.9 Implementation-time decisions not in §9/§10:
  RUNG_PRIORITY ordering, bounded-domain anchors, reminder templates,
  reject answer_text format, render branch, EXPLICIT_COUNT fallback,
  quote-mode opt-out
- §11.10 Live verification artifacts (Winners-of-all-major-sports
  rejected; Beatles-bounded NOT rejected)
- §11.11 What was NOT shipped: quantifier_preflight run-DAG node,
  three-clause CTI contract DAG binding, A/B/D bench measurements,
  cross-model verification — all queued as Phase 5 / bench follow-up

Implementation-time decisions section is the most operationally
useful — captures judgment calls made during coding that aren't in
the design docs but are now binding via tests.
2026-05-03 08:16:06 -04:00
c684dc17e1
ticket(#000008): mark Phases 0.x-4 landed; commit chain pinned
Updates §8 Status, §9.6 Phase details, §9.8 Test surface, §9.11
commit sequence to reflect actual implementation state:

§8 Status — Phase 0 through Phase 4 all landed 2026-05-03 across
six commits (2ffed00 → 5a60e85). 906 tests passing (120 new).
Defaults preserve §10.11.3 dry-run discipline:
  quantifier_guard_apply_caps=False, reminder=False, reject=False.
Six-level disable hierarchy fully wired. Live verification recorded
for both reject-broad-fires (Winners of all major sports?) and
reject-broad-skips (name all members of the Beatles → bounded
universal, NOT rejected).

§9.6 Phase details — each phase tagged LANDED <sha>; description
trimmed to what actually shipped vs the original proposal.

§9.8 Test surface — every check box flipped to [x] with the
matching test file path and test count. The two reject-broad
integration tests remain skipped (exercised by live bench).

§9.11 Implementation commit sequence — actual SHAs replace planned
commit numbers. Notes that DAG/audit binding for quantifier_preflight
node ("commit 7" in plan) is NOT shipped — tracked as Phase 5
follow-up. Optional now; required for §9.5 Merkle-AGI-DAG framing
to fully hold.

Next steps are bench measurement, not code: full bench under dry-run,
classifier review, then flip apply_caps and measure §10.8 deltas.
2026-05-03 08:08:03 -04:00
83ab29734a
ticket(#000008): architectural review II + disable hierarchy
Two review passes added to ticket #000008:

§9 — first architectural review (2026-05-03). De novo synthesis
applying CTI / Merkle-AGI-DAG / Reverse-RAG / PROMETHEUS-Σ stack.
Replaces the §4 "land Option D" recommendation with a phased plan
(Phase 0 telemetry → Phase 1 classifier → Phase 2 cap → Phase 3
reminder held → Phase 4 reject held). §4 marked superseded but
preserved as design log. §8 Status updated.

§10 — second-pass refinements. Where §10 conflicts with §9, §10
wins. Substantive deltas:
- §10.1 split ALL rung into bounded / unbounded / emergent
  (all-Beatles ≠ winners-of-all-major-sports)
- §10.2 entropy-pressure framing; cap is one knob among three
- §10.3 three new violation kinds, no new audit_mode token
  (BROAD_QUANTIFIER_RUNAWAY/CAP_APPLIED/SCOPE_UNBOUND)
- §10.4 three-clause CTI contract (quantifier / answer /
  evidence) instead of one flat clause
- §10.5 concrete output templates per policy mode
- §10.6 bench-field corrections; model_profile_id includes -fp8
- §10.7 explicit do-not list
- §10.8 quantitative decision tree (≥5pp deltas per mode)
- §10.9 five-step method walkthrough binding to CLAUDE.md

§10.11 — disable hierarchy + dry-run discipline. Six-level
disable hierarchy (per-test → per-call CLI → per-phase policy
→ per-mode → per-model-profile → master-via-governance-hash).
Dry-run discipline: Phase 1 classifier lands with
quantifier_guard_apply_caps=false; bench review of intensity
distribution catches mis-classification before any verdict is
affected. Per-phase regression fixtures named. Rollback playbook
prefers policy-flip over git-revert.

Honest expectation-setting: §5.1.1 baseline shows
NO_EVIDENCE_POINTER 3/3 dominates; cap-only (Phase 2) likely
moves needle barely; Phase 3 reminder might or might not move
the gate; Phase 4 reject mechanically works but carries false-
positive risk on bounded universals (handled by §10.1 split).

Telemetry-first stays the load-bearing recommendation.
2026-05-03 06:52:30 -04:00
2ffed001a4
bench(#000008): harness extension — FC rate, violation kinds, raw brackets
Closes the bench-side gap surfaced in §5.2: JSONL was carrying summary
numbers only, blinding the harness to FORMAT_COLLAPSED rate and per-
violation-kind distributions. Without these, A/B/D bench measurements
on the broad-quantifier preflight guard would be guesses.

- query() result dict surfaces format_collapsed + raw_answer (lattice
  modes only) so the bench can read them directly instead of re-deriving
  from cache rows that --burn overwrites.
- Each bench row gains format_collapsed, violation_kinds (sorted unique
  list — full payloads stay off the row to keep size bounded), and
  answer_brackets (count of [E\d+] in raw_answer for lattice modes).
- _summarize aggregates per-mode FC count (only explicit True; None
  means check didn't apply), per-kind tallies (each kind once per row),
  and lattice-only bracket sum/n.
- Markdown renderer adds a `## format-collapse + violation kinds`
  section with per-mode FC rate, mean raw brackets, and one column per
  observed violation kind. Degrades gracefully when the sweep produces
  no violations.
- 5 new bench-harness tests pin the aggregation rules.

Re-baseline (2026-05-02T20-58-57Z) sharpens §5.1 analysis dramatically:
NO_EVIDENCE_POINTER fires 3/3 in pointer mode and is the dominant gate,
not TITLE_MISMATCH (1/3) as §5.1 inferred from JSONL alone. FORMAT_
COLLAPSED actually fires 1/3 — not the rare corner the first baseline
called it. Implies Option B (prompt reminder) is the load-bearing fix
for the verdict; Option A (cap reduction) only moves secondary kinds.

§5.3 sub-investigation closed on first read — SCHEMA_INVALID:1 in
pointer mode is a legitimate kind emitted by verify_claim_lattice for
empty-claim-text (verify.py:1242) and bare-name-claim (verify.py:1270),
not a JSON-mode leak.
2026-05-02 18:35:08 -04:00
38cfea1983
qa(verify): FORMAT_COLLAPSED soft-demote + open #000008 (broad-quantifier preflight)
Sister rule to Rule 9 (SUBJECT_TOKENS_ABSENT) landed in the same
session. Both demote STRICT → HYBRID but on orthogonal signals:
Rule 9 catches premise-parroting; FORMAT_COLLAPSED catches
protocol abandonment.

Surfaced by fox's "winners of all major sports?" 2026-05-02 case:
Hermes-3-8B melted under an under-specified broad-quantifier
question, dumped 50+ free-form prose claims with zero [E\d+]
pointer tags. Verifier honestly returned UNGROUNDED 0/2 (parser
caught two line fragments), but operators couldn't distinguish
"tried & failed to ground" from "abandoned the protocol." This
soft-demote separates the two failure shapes at audit-line glance.

verify_claim_lattice (pointer-mode only — JSON collapse already
shows as SCHEMA_INVALID):
- count meaningful_lines (>20 chars after strip) and [E\d+ regex
  matches in raw answer
- ≥5 meaningful lines AND 0 bracket tags → FORMAT_COLLAPSED
  violation, soft-demote STRICT → HYBRID
- format_collapsed: bool added to verdict dict

Plumbing:
- claim_lattice_format_collapse_check_enabled: True in DEFAULT_POLICY
  and DEFAULT_QUERY_POLICY
- _VERIFIER_POLICY_FIELDS in keys.py adds the field so it folds
  into verifier_policy_hash
- threaded through ask() and query() call sites

CLI:
- _SOFT_DEMOTE_VIOLATION_KINDS includes FORMAT_COLLAPSED so the
  audit-line ladder rendering treats it as a soft demote
- _render_warrant_tail appends "· format collapsed" tail

Bench fixture: new "under-specified 'all'" section in
qa_questions.txt with `winners of all major sports?` and rationale
about cross-model resilience signal.

Tests:
- test_format_collapsed_fires_on_bracketless_multi_line_prose
- test_format_collapsed_does_not_fire_when_pointer_tags_present
- CLI render coverage
Full suite: 781 passed (up from 776).

Open Ticket #000008 — Broad-quantifier preflight guard. Cleaner
upstream fix: detect quantifier-intensity at query layer and
apply a per-model claim ceiling BEFORE the 13-second LLM call.
FORMAT_COLLAPSED stays as the downstream catch; #000008 proposes
the upstream prevention. TICKETS.md index + Next ID 000008→000009.
2026-05-02 16:43:41 -04:00
39bebe3fdb
qa(verify): Rule 9 — SUBJECT_TOKENS_ABSENT premise-parroting demote
Closes the first confirmed EVIDENCE-WARRANTED false-positive
surfaced by the 200-cycle bench-emergent run on
`steer/reply/correcter` (Ticket #000006 amend 2026-05-02b). The
model parroted three question-distinctive tokens (correcter,
steer, reply) into its claim while citing a glossary article whose
33.5K-char content contains ZERO occurrences of any of them.
Generic linguistic vocabulary (language, communication, terms,
relationships) carried Rule 5's citation-coverage check on its
own; the actual subject tokens rode along unverified.

New per-claim check `_parroted_subject_tokens_absent`: for each
resolving claim, compute the question∩claim content-token set,
then check substring presence in the union of cited evidence
spans (lower-cased, mirroring Rule 5). When ≥ threshold parroted
tokens are absent, emit `SUBJECT_TOKENS_ABSENT` and demote STRICT
→ HYBRID. Default threshold = 3 — single-token absence is often
stem-variant noise; three+ is the parrot fingerprint.

Plumbing:
- New default `DEFAULT_SUBJECT_TOKENS_ABSENT_THRESHOLD = 3`
- Both `verify_claim_lattice` and `verify_claim_lattice_json`
  gain `subject_tokens_absent_threshold` kwarg + per-claim check
  block (mirrors TITLE_MISMATCH plumbing, sits right after it
  in the rule order)
- `claim_lattice_subject_tokens_absent_threshold` policy field
  added to `DEFAULT_QUERY_POLICY` and `DEFAULT_POLICY`; folds
  into `governance_policy_hash` and (via _VERIFIER_POLICY_FIELDS)
  `verifier_policy_hash`
- All four runner/query call sites pass the policy-derived value

Live verification (cache-split cleanly via policy-hash bump):
  pre-fix cache_key 08dbd2c1… : STRICT (false positive)
  post-fix cache_key 6a519636… : UNGROUNDED

Three new unit tests in `tests/test_verify_json.py`:
- threshold-meeting parrot demotes STRICT → HYBRID
- no-op when question is None
- below-threshold absence stays STRICT

Full suite: 776 passed, 34 skipped.
2026-05-02 15:51:58 -04:00
529434ec67
ticket(#000006): 200-cycle amend — confirmed EVIDENCE-WARRANTED false-positive
Re-aggregated bench/emergent_log.jsonl at 200 cycles. Distribution
holds (79.5% UNGROUNDED, 17.5% HYBRID, 3.0% STRICT). Six STRICTs
total; five defensible (known-truth or non-relationship grounding).

The sixth — `steer/reply/correcter` — is the FIRST CONFIRMED
EVIDENCE-WARRANTED false-positive in 200 cycles. Decompressed all
10 chunks of the cited document (Glossary of language teaching
terms and ideas, 33.5K chars) and confirmed the words `correcter`,
`steer`, and `reply` appear NOWHERE in the source. Yet STRICT 1/1
verified, no violations.

Mechanism: per-claim citation-coverage Rule 5 (≥30% claim tokens
in cited span) passed on GENERIC linguistic vocabulary (language,
communication, grammar, exchange, relationships) which appears in
any linguistics article. The question-distinctive tokens
(correcter, steer, reply) rode along unverified. PREMISE_PARROTING
shape predicted in original ticket §D, exhibit A.

Headline correction: from "zero false-positives" to "one confirmed
false-positive (0.5%)."

Action item: opens design space for #000008 — PREMISE_PARROTING
detector. Lexical signal: question-distinctive tokens absent from
cited chunk while Rule 5 still passes on generic vocabulary →
SUBJECT_TOKENS_ABSENT violation, demote STRICT → HYBRID. Stays
binary, stays lexical, folds into verifier_policy_hash.
2026-05-02 15:17:05 -04:00
4a7c4aff50
ticket(#000006): move into tickets/ subdir + 134-cycle rolling amend
The ticket file was at docs/ticket-000006-... at top-level; the
tickets/ subdir convention landed before #6 was opened. Move into
docs/tickets/ to match every other ticket.

Amend with the 62-entry post-ticket delta. bench/emergent_log.jsonl
now holds 134 cycles total. Distribution stable vs original 72:
106 UNGROUNDED (79.1%), 22 HYBRID (16.4%), 6 STRICT (4.5%). Ten
new grounded cases all carry appropriate violation labels — zero
EVIDENCE-WARRANTED false-positives across all 134 cycles. Original
tuning candidates: Tomas-deflection resolved by a1dd330,
xxviii-STRICT kept as designed, metaphor sidecar calibration
deferred (still rare).

Reframe ticket as a rolling research log. Emergent stress-testing
is an ongoing thread, not a one-shot defect-fix; future
bench-emergent re-runs append new ## Amend sections here, and any
code-level tunings open their own tickets linking back.

TICKETS.md row reflects the rolling-research framing. Stale
"## Next ID" footer scrubbed from the ticket body (TICKETS.md is
canonical for the next-id counter).
2026-05-02 14:42:42 -04:00
8fb1fe51d7
qa(query): #000007 land — query-layer hyphen folding
Closes the FTS5 hyphen-tokenization asymmetry: `bi-polar is rare?`
retrieved only the Bi-Polar album/disambiguation cluster while the
medical-condition cluster (Bipolar disorder, Bipolar I/II disorder,
etc.) sat in the same shards untouched. `unicode61` splits hyphens
at index AND query time; `Bi-Polar Blues` indexes as [bi, polar, ...]
while `Bipolar disorder` indexes as [bipolar] — non-overlapping
token sets that never met.

Fix is query-layer only — no canonicalization_version bump, no
re-index, existing cache_keys stay valid:

- _hyphen_fold_variants(s): emit joined-no-hyphen variants for
  every hyphenated run.
- _title_query_tokens(s): additively merges variants symmetrically
  (queries AND titles when called on either).
- _filter_by_title_relevance: accept-path 5 — title stem-overlap
  with hyphen-fold anchors passes the breadth gate. Rescues
  `Bipolar disorder` (1-of-N qtoken match) without disrupting
  non-hyphen queries (anchors empty → zero side effect).
- DEFAULT_QUERY_POLICY / DEFAULT_POLICY: hyphen_fold_v1: True
  marker folds into governance_policy_hash; new records
  cache-split cleanly from pre-fold records.

Live verification on /home/fox/.aborist/shards: same query now
retrieves `Bipolar disorder` (#5) and `Bipolar` disambiguation
(#7); model cites both, answer reads "Bi-polar disorder is not
rare; it affects approximately 2.8% of the U.S. population".
EVIDENCE-WARRANTED 2/2, properly grounded.

Tests: 4 new (3 unit, 1 integration with regression-pinned
Bipolar-disorder retrieval). Full suite 760 passed, 34 skipped.

Also: CLAUDE.md gains a close-when-complete hint for tickets — an
open ticket whose code already shipped is a stale map.
2026-05-02 14:12:46 -04:00
7444f106fc
docs: tickets/ subdir + delete naming-deferral, ref-frame, coverage-audit
Two cleanup operations bundled (separate scopes, single commit
since they share the doc-tree settle):

1. Move ticket-NNNNNN-<slug>.md files into docs/tickets/. The
   directory makes browsing the design log easier; the index
   stays at docs/TICKETS.md (top-level pointer). Convention text
   in TICKETS.md updated to spell the new path.

2. Delete three docs whose load-bearing content has either been
   absorbed into the codebase or distilled into closed tickets:

   - docs/naming-deferral.md (147 lines) — explained why we
     don't rename claim_lattice → CTI/PROMETHEUS-Σ. Decision
     stays in place; the rationale is no longer worth a
     dedicated doc. Inline citations removed from
     cti-architecture.md (4 refs), warrant.py, ticket-000003
     (closed-ticket internal ref).
   - docs/reference-frame-failure-class.md (169 lines) — Orwell
     case journal that motivated the phrase-pattern retrieval
     route. The route shipped; the analysis is now duplicate
     with the closed Ticket #000002. Inline citation removed
     from CLAUDE.md retrieval pipeline section + frame.py.
   - docs/test-coverage-audit-2026-05-01.md (46 lines) —
     point-in-time audit checking 16/16 of fox's §11 list. Tests
     themselves live in tests/; the audit was a one-shot
     checkmark exercise.

References updated:
  CLAUDE.md, aborist/qa/frame.py, aborist/qa/retrieval_plan.py,
  aborist/qa/warrant.py, docs/cti-architecture.md, docs/TICKETS.md,
  docs/tickets/ticket-000003 + ticket-000004 (internal links).

Net: -362 lines + tickets/ subdir. 751/34 tests still pass.
2026-05-02 12:51:09 -04:00