Skip to content

fix(core): measure the structure filter from the #1, not the population minimum (#353) - #365

Merged
send merged 6 commits into
mainfrom
feat/structure-filter-relative
Oct 2, 2026
Merged

send merged 6 commits into
mainfrom
feat/structure-filter-relative

Conversation

@send

@send send commented Oct 1, 2026

Copy link
Copy Markdown
Owner

Summary

rerank's structure filter measured its threshold from the population's minimum structure cost + structure_cost_filter. The population depends on the oversample (1-best 10/30, N-best n×3 / 60), so a cheap-transition path that never wins (カナ|や shape) could lower the threshold and drop the paths that do win (#353 symptom 1; four earlier symptom fixes — prefix floor, transition cap, identity exemption, 4000→6000 — all patched this).

The threshold is now measured from the anchor = the pre-history #1 (the cheapest path after features, the same path cost-gap admission and Numeric measure from): anchor sc (single segment imputed at the prefix floor) + structure_cost_filter.

  • The Add IME app with romaji-to-kana and Rust FFI bridge #1 can no longer be dropped (by construction), and the threshold depends on the population only through the Add IME app with romaji-to-kana and Rust FFI bridge #1.
  • On the same population, every path that survived before still survives (threshold ≥ old one). structure_cost_filter keeps its key and default; a user-set value now means the same or looser (noted in SPEC / default_settings).
  • rerank returns the StructureFilter it used and reports each drop to on_drop; explain shows them (dropped_by_structure, structure_filter; text Dropped by structure).
  • tune's copy of the filter (hard_filter) is removed: tune scores top-1 only, and the filter can no longer touch the top-1.

Closes #353. Its symptom 2 (1-best vs N-best head disagreeing) turned out not to come from the filter — the two known cases persist with the filter off — and is tracked in #361 (PR-E2: argmin over different oversamples).

Measurements

Frozen commit-log snapshot: 7085 lines / 505 rank>0 selections / 469 distinct readings. Corpus readings: 142. Arms: main (450fa55), main with the filter disabled (oracle, structure_cost_filter = 10^9), this PR — all at the same time. Counts only.

main filter off this PR
accuracy-corpus 109/109 (28 skip) 109/109 109/109
accuracy-corpus-history 11/11 11/11 11/11

dropped_by_structure over the 142 readings: 593 paths in 67 readings; 26 within the cost-gap bound, none of them in page-1 range.

Known follow-ups

  • The filter now looks dead under admission. The pre-registered deletion check holds on all three conditions (page 1 identical to the filter-off oracle on 142/142 readings, no difference in which candidates replay selects, no filter-only drop in page-1 range). By that rule the filter (and its prefix floor / transition cap / imputation) goes in a separate PR; the API added here (StructureFilter, on_drop, explain fields) is provisional until then.
  • The width disagreement can also go the other way now: a price argmin only a large population sees is no longer dropped by chance. Measured on the 469 readings: 0 new, 3 resolved. Tracked with 1-best vs N-best top-1 mismatch comes from argmin population width, not the structure filter (PR-E2) #361.

Test plan

  • mise run test (lint + workspace tests), accuracy ×2, read-pin, task-screen, check-sources + audit, compile-swift + test-swift, msrv 1.88.0
  • Tests that fail under the old rule: the threshold depends on the population only through the Add IME app with romaji-to-kana and Rust FFI bridge #1, the Add IME app with romaji-to-kana and Rust FFI bridge #1 is never dropped, 1-best == N-best head when only the filter differed, tune top-1 == rerank index 0
  • Mutations caught: no prefix floor / anchor by Viterbi cost / identity excluded from the anchor
  • Measurements above (frozen snapshot, all arms at the same time)

🤖 Generated with Claude Code

send and others added 6 commits October 1, 2026 17:14
…ts pending)

Not for push: 3 tests still expect the old population-min threshold;
explain/SPEC/tests (R5/R6/T1-T8) not done. Parked while rule A (plan
§23-7) is re-judged.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…lain drops, docs

Not for push yet: waiting on the PR-G ordering decision (plan §23-13).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
… fixture, fmt

PR-G added fresh / stale whole-path arms to the explain == production
test against main's oversample_sensitive fixture. PR-E renamed that
fixture filter_population_sensitive and rebuilt oversample_sensitive as
the argmin case, so the learned arms now run on the multi-segment
fixture where 仮名屋 / カナや exist and are not the #1.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
rerank returns the anchor sc and threshold it filtered with, and
postprocess hands them to the observer, so explain no longer recomputes
them from index 0 (structure_filter_at removed). structure_threshold
folds into FeaturePricer::threshold_at. tune builds candidates without
the intermediate pairs. Test fixtures share testutil::entry_with_id;
comments still describing the population minimum now name the anchor.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…lain reports what ran

- rerank carries each path with its structure cost, so no unreachable
  branch can keep an unpriced path; StructureFilter.anchor_sc is the
  value the threshold is measured from (a single segment imputed at the
  prefix floor), and explain reports None, not 0, when rerank did not
  filter.
- explain's text shows the dropped sections even when no path is listed.
- Tests: the prefix-floor fixture makes Path A the anchor again (it had
  stopped testing the floor); the anchor is the cheapest after features
  (not Viterbi cost) and includes identity; explain == production now
  runs on a fixture where the filter drops.
- Docs: rerank's doc (structure cost is not priced; the single-segment
  imputation), the prefix floor's 53d207c example, the setting's
  comment / SPEC, and DEFAULT_CANDIDATE_MAX_COST_GAP's re-run under #353.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
explain carried the anchor sc and the threshold as two independent
Options that had to agree; it now carries the StructureFilter rerank
returned (null in JSON when the filter did not run), so one cannot be
set without the other. SPEC states the prefix floor as the default
3000 and documents the field.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 1, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-01T11:03:33.763590Z 3cae806 Manual request
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@send

send commented Oct 1, 2026

Copy link
Copy Markdown
Owner Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. 🎉

Reviewed commit: 3cae806ecf

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@send

send commented Oct 1, 2026

Copy link
Copy Markdown
Owner Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. 🚀

Reviewed commit: 3cae806ecf

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@send
send merged commit 61b6219 into main Oct 2, 2026
16 checks passed
@send
send deleted the feat/structure-filter-relative branch October 2, 2026 00:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

structure filter threshold depends on the oversample population (drops real paths, flips top-1)

1 participant