Feature State Matrix
Status: active ledger Role: Canonical current Last updated: 2026-06-02 Source-of-truth: cross-cutting state ledger; runtime truth still lives in code, tests, and dated evidence artifacts.
Purpose:
- Keep feature state explicit for GenAI-driven development.
- Separate
implemented,default-on,verified, andplannedso current behavior is easy to recover. - Give each feature a dated checkpoint plus evidence paths.
Use this file when:
- default behavior changes,
- benchmark policy or baseline assumptions change,
- a workstream moves from scaffolded to executable,
- code inspection finds a doc/code mismatch that should be tracked.
Status Vocabulary
planned: documented idea only.scaffolded: code/docs shape exists, but behavior is not yet fully executable.implemented: code path exists and is usable.default-on: implemented and enabled in normal/default behavior.verified: implementation has recent evidence (artifact, test, or direct code inspection).
Date Fields
Last documented checkpoint: most recent dated doc milestone or spec update.Last verified: most recent artifact date, test evidence, or dated code inspection.
Rulegen Benchmark / Gate / Triage Loop
- Status:
implemented,default-on,verified - Last documented checkpoint:
2026-04-04benchmark case authoring now uses LP-specific source files underdocs/test_inputs/rulegen_benchmark_cases/, the benchmark/gate loader now accepts either a single JSON file or that directory directly, pair-scoped dataset validation now stays local to the selected LP, and bundle export now materializes a merged dataset JSON for replay - Last verified:
2026-04-04focused dataset-loader/gate/bundle tests plus localen-debenchmark/gate/triage refresh on the directory-backed dataset - Default behavior:
- Required for rulegen scoring, candidate filtering, POS normalization, and LP tuning changes.
- Canonical loop remains benchmark -> quality gate -> triage.
- Benchmark case source-of-truth is now the LP-specific directory
docs/test_inputs/rulegen_benchmark_cases/; benchmark tooling merges those files on load. - Latest rulegen artifacts now have human-facing Markdown summaries for benchmark, gate, and triage surfaces.
- Evidence:
AGENTS.mddocs/developer/ai_workflow.mddocs/developer/rulegen_test_pipeline.mdscripts/package.jsonscripts/testing/rulegen_benchmark.pyscripts/testing/rulegen_benchmark_bundle.pyscripts/testing/rulegen_benchmark_presets.pyscripts/testing/rulegen_benchmark_summary.pyscripts/testing/rulegen_quality_gate.pyscripts/testing/rulegen_quality_gate_summary.pyscripts/testing/rulegen_benchmark_triage.pyscripts/testing/rulegen_benchmark_triage_summary.pydocs/test_outputs/rulegen_benchmark_en_es_latest.mddocs/test_outputs/rulegen_benchmark_summary_latest.mddocs/test_outputs/rulegen_quality_gate_latest.jsondocs/test_outputs/rulegen_quality_gate_summary_latest.mddocs/test_outputs/rulegen_benchmark_triage_summary_latest.md
- Known gaps:
- Current
docs/test_outputs/rulegen_quality_gate_latest.jsonhas FAIL findings foren-esquality floor and delta budget. - Recommended pairs (
en-ja,en-de,es-en) are still advisory rather than hard-gated. en-denow has a named advisory latest lane, but it is still separate from the canonical stricten-eslane and not yet part ofrequired_benchmark_pairs.- Cross-machine benchmark artifacts can preserve source-machine absolute dataset paths; the gate now falls back to the repo-local dataset copy when the original path is unavailable.
- Artifact history and pair inference still depend on wrapper usage rather than a mandatory repo-wide gate.
- Benchmark artifacts now mirror resolved resources under each pair as well as in the top-level
resourcesblock, they now carry SHA-256 resource checksums, they now record the effective per-targetword_packagesnapshot used by the run, the benchmark CLI now supports named preset methodologies fromdocs/test_inputs/rulegen_benchmark_presets.json, and portable bundle export/replay now packages the exact dataset/resources/snapshots for cross-machine reruns; the remaining ergonomic gap is optional single-file archive/import support.
- Current
Rulegen Benchmark Optimization Architecture
- Status:
implemented,verified;default-on=no - Last documented checkpoint:
2026-03-28the compileden-essweep path now includesnumpyconfig-matrix score projection, a guarded optionaltorchCUDA score backend, compact selected-row preparation, backend-neutral preload caches, and a separate black-box pipeline contract doc for the full benchmark/render/gate/triage loop - Last verified:
2026-03-28focused unit coverage, latest warm-cache canonicalen-essweep smoke, guardedtorch/CUDA equivalence smoke, and pipeline/state sync - Default behavior:
- Active direction remains a non-throwaway benchmark acceleration program that keeps the current canonical preset methodology while moving the implementation toward a
compile -> sweep -> materializearchitecture, a backend-neutral pair-resource contract, and later trait-aware profile analysis on top of the same benchmark substrate. - Already landed slices include timing/profiling instrumentation, pair-context caching, compute/materialization split, compiled
en-escandidate/case/result tables, deferred case-payload materialization, a direct compiled non-varianten-essweep path that can bypass adapter-generatedVocabRules, a compiled benchmark-only variant-row path so the canonicalvar=onhalf of theen-esmatrix no longer has to use the live adapter loop, narrower overlay-demotion caching so score-table rebuilds do not recompute Kaikki policy rows for every score-weight-only config change, a backend-neutral persistent path-cache layer for translation-pack metadata plus benchmark resource checksums, and the Phase 5 serial-sweep preparation path that now prebuilds compileden-esrequests/configs/filter tables/score tables/compact selected-row tables before the remaining per-run case evaluation loop. The compiled score path now also usesnumpyarrays plus an explicit config-matrix projection for batch score/ranking computation, offers a guarded localtorchCUDA score backend behindLEXISHIFT_RULEGEN_SCORE_BACKEND, replaces string source-phrase tie-breakers with stable numeric phrase-order ids, and reuses equivalent selected-row tables across distinct configs by compiled row-selection signatures: accepted row groups, target-ranked row order, reverse-hygiene signals, and threshold pass/fail rows, rather than intermediate score-table object identity or raw confidence payloads. - Current architecture now also explicitly treats database-specific logic as a resource-layer concern: the benchmark workstream is moving toward backend-neutral translation-pack record/loader contracts, with FreeDict/Kaikki compatibility loaders as one current implementation rather than the architectural model.
- Latest warm-cache canonical
en-esbenchmark smoke on this PC stays exact at objective129.474with total wall clock about0.50s;preload_translation_gloss_recordsis about0.223s, compiled sweep-input preparation is about0.174s, and the remaining per-configrun_configloop is about0.012stotal across the 144-config serial sweep. - A guarded local
torch/CUDA score-backend smoke is also benchmark-equivalent on this PC, but it is slower on the real current sweep shape at about0.71swall clock withprepare_compiled_sweep_inputsabout0.328s, so GPU remains an explicit opt-in rather than default-on. - The latest artifact-resolved best run is now a
var=ontied winner, but the canonical best objective still has12equivalent tied winners including the earliervar=offlane; this is currently a stable tie-order detail, not a quality change. - Later slices are still expected to be:
- fuller compiled benchmark IR generalization across pairs/packs
- vectorized CPU backend
- optional GPU backend only after the sweep has been converted into a genuinely numeric feature-table problem
- Active direction remains a non-throwaway benchmark acceleration program that keeps the current canonical preset methodology while moving the implementation toward a
- Evidence:
docs/developer/rulegen_test_pipeline.mddocs/developer/rulegen_benchmark_optimization_plan.mdcore/lexishift_core/resources/path_cache.pyscripts/testing/rulegen_benchmark.pycore/lexishift_core/rulegen/adapters.pycore/lexishift_core/resources/dict_loaders.pycore/lexishift_core/rulegen/generation.pycore/lexishift_core/rulegen/pairs/en_es.pycore/tests/rulegen/test_rulegen_en_es_compiled_resources.py
- Known gaps:
- Current full canonical sweep now batch-prepares compiled score inputs and selected-row tables, but case-summary reduction still executes one config at a time; the next major performance frontier is denser config-matrix evaluation over compiled candidate rows and later batch case-summary reduction.
- The implementation is still pair-heavy in
en-es, and the newly explicit backend-neutral resource contract is only the first slice, not the final generalized pack abstraction. en-denow has a compiled resource context (EnDeCompiledResources), candidate-row IR, and a first reusable prepared score-table plus selected-row sweep path for non-variant runs, but it still lacks the fulleren-escompiled filter/score-table stack and broader compiled sweep reuse.- Current active
en-esbenchmark path still does not have a broadly profitable GPU-shaped workload because it lacks an active embedding/neural scoring backend and is still dominated by preprocessing, selection, and resource work even though the score projection path now has both numericnumpyand guarded optionaltorchimplementations.
Rulegen LP Onboarding Scaffold
- Status:
implemented,verified;default-on=no - Last documented checkpoint:
2026-04-04rulegen LP onboarding now has a machine-readable profile contract, profile validator, a profile-to-repo conformance audit, checklist/operating-model docs, and a template-driven scaffold that can render benchmark/profile stubs plus optional roadmap, pair-module, adapter-contract starter-test, integration-handoff, and benchmark-preset-starter files for a new pair - Last verified:
2026-04-04focused scaffold tests,check:lp-profiles,check:docs, andcheck:state - Default behavior:
- LP onboarding now has a documented operating model in
docs/rulegen/lp_onboarding_operating_model.mdand a reusable checklist indocs/rulegen/lp_onboarding_checklist_template.md. - Machine-readable pair contracts now live under
docs/test_inputs/rulegen_lp_profiles/and are validated bynpm --prefix scripts run check:lp-profiles. - Repo alignment for those profiles is now validated separately by
npm --prefix scripts run check:lp-conformance, which audits pair-derived path conventions, preset pair wiring, latest benchmark artifact pair presence, wrapper-command pair mentions, pair-module symbol naming, pair exports inrulegen/pairs/__init__.py, adapter registration inrulegen/adapters.py, and capability-mode registration inhelper/lp_capabilities.py. npm --prefix scripts run scaffold:rulegen:lp -- ...now acts as a thin scaffold orchestrator:- schema-driven JSON for LP profiles and benchmark case stubs
- template-driven text/code rendering for roadmaps, pair-module stubs, adapter-contract starter tests, integration-handoff docs for central wiring follow-ups, and benchmark-preset starter snippets
- The scaffold deliberately does not invent LP-specific normalization rules, family mappings, benchmark expectations, ranking decisions, adapter registration, or quality claims.
- LP onboarding now has a documented operating model in
- Evidence:
docs/rulegen/lp_onboarding_operating_model.mddocs/rulegen/lp_onboarding_checklist_template.mddocs/test_inputs/rulegen_lp_profiles/README.mddocs/test_inputs/rulegen_lp_profiles/profile.schema.jsonscripts/dev/check_rulegen_lp_profiles.pyscripts/dev/check_rulegen_lp_conformance.pyscripts/dev/scaffold_rulegen_lp.pyscripts/dev/templates/rulegen_lp/workstream_roadmap.md.tmplscripts/dev/templates/rulegen_lp/pair_module.py.tmplscripts/dev/templates/rulegen_lp/pair_test.py.tmplscripts/dev/templates/rulegen_lp/integration_handoff.md.tmplscripts/dev/templates/rulegen_lp/benchmark_preset_starter.md.tmplcore/tests/dev/test_scaffold_rulegen_lp.pyscripts/package.json
- Known gaps:
- The scaffold still does not wire adapter registration, benchmark presets, pair exports, or central routing updates for a new pair; it now generates those follow-ups as an explicit handoff instead of editing central files automatically.
- LP-specific benchmark cases, normalization profiles, metadata-family mappings, and ranking decisions remain manual by design.
- The scaffold is currently a generator plus templates, not yet a full profile-driven code registry updater.
- The conformance audit currently enforces benchmark/preset conventions plus central pair export/adapter/capability registration for profiled pairs, but it still does not inspect benchmark summary commands, package-level convenience scripts, or pair-specific roadmap freshness.
Data Source Normalization Architecture
- Status:
implemented,verified;default-on=partialfor manifest-backed translation-pack, frequency-pack, and app-managed embedding-pack installs plus helper default-pack discovery - Last documented checkpoint:
2026-04-21the data-source normalization contract now also pinswordnet-en/moby-enas explicit compatibility exceptions: panel/dialog persistence still mirrors them intowordnet_dir/moby_path, but downstream bulk-rules consumers now resolve those two packs through the shared binding-map-first effective-path helper instead of direct legacy-field reads - Last verified:
2026-04-21targeted bulk-rules, panel-state, dialog-persistence, and persistence helper tests plus state/doc safety checks - Default behavior:
- Target architecture is now explicit:
- installed packs should resolve by manifest-backed pack identity rather than flat filenames
- canonical runtime artifacts should prefer compiled SQLite
- provider-native raw archives/extraction trees should be treated as build inputs rather than runtime contracts
- raw download/extraction artifacts should be deleted after successful build unless a developer-only retention mode is explicitly enabled
- any new data-source onboarding should follow that model by default rather than inventing a new install/runtime shape
- First executable slices are now live for translation, frequency, and app-managed embedding packs:
- GUI language-pack downloads install into stable per-pack roots under
language_packs/<pack_id>/ - app-managed language-pack installs now write
manifest.json - app-managed FreeDict language-pack installs now compile provider TEI sources to canonical SQLite artifacts before completion
- helper translation-dictionary resolution now prefers manifest-backed installed pack artifacts and FreeDict SQLite filenames before falling back to TEI/path guessing
- the German frequency whitelist/build path now resolves FreeDict through the same normalized translation-pack artifact contract and shared translation headword loader
- the GUI bulk-rules FreeDict path now resolves managed SQLite artifacts first, falls back to legacy SQLite files when needed, and no longer treats extracted TEI directories as a normal managed input
- the synthetic SRS quality/journey harness helpers now emit SQLite translation resources by default
- the journey harness resource-writing logic now lives in a dedicated helper module so fixture-format changes no longer grow the main scenario-support file
- shared translation pack refs now honor managed manifests when present instead of relying only on filename/provider inference
- helper rulegen debug payloads now report translation pack id/provider/source-profile fields through the shared translation-pack seam
- installed-resource journey staging now preserves manifest-backed translation pack roots instead of flattening them into loose artifact files
- GUI frequency-pack downloads now install into stable per-pack roots under
frequency_packs/<pack_id>/ - app-managed frequency-pack installs now write
manifest.json - helper default frequency resolution now prefers manifest-backed installed pack artifacts before falling back to legacy flat filenames
- helper/runtime now expose a first frequency pack-ref seam so pair-resource resolution, runtime diagnostics, and benchmark resource payloads can report frequency pack id, provider, and POS source profile instead of only a raw SQLite path
- GUI SRS growth and the POS normalization probe now share a configured frequency-pack resolver from the helper layer instead of each carrying their own managed-id/manual-path/fallback path logic
- app-managed translation installs now converge on
language_packs/<pack_id>/main.sqlite, while panel/runtime resolution still accepts legacy<pack_id>.sqlitefilenames for older local installs - app-managed frequency installs now converge on
frequency_packs/<pack_id>/main.sqlite, while panel/runtime resolution still accepts legacyfreq-*.sqlitefilenames for older local installs - GUI embedding-pack downloads now install into stable per-pack roots under
embedding_packs/<pack_id>/ - app-managed embedding-pack downloads now normalize to SQLite and write
manifest.jsononly after successful conversion - successful app-managed embedding conversion now treats SQLite as the canonical installed artifact and cleans up the raw downloaded vector file
- managed embedding activation can now be persisted by pack id per pair, and the replacement-filter runtime resolves those pack ids back through manifest-backed SQLite artifacts
- app-state load/update now migrates old saved managed embedding artifact paths into pack-id-first per-pair activation and strips those app-owned paths from the manual embedding maps
- the settings panel now strips managed installed embedding artifacts from seed/auto-link state and keeps managed activation under per-pair embedding pack ids instead of rehydrating those artifacts into the manual path map
- managed translation settings now persist normalized app-owned translation packs by pack id while the saved manual
language_pack_pathsmap omits those managed artifact paths - managed frequency settings now persist app-owned frequency packs by pack id while the saved manual
frequency_pack_pathsmap omits those managed artifact paths - app-state load/update now migrates old saved managed translation/frequency artifact paths into that split representation
- the settings panel now keeps managed translation/frequency ids in dedicated in-memory sets instead of reconstructing those ids from unified path maps on save
- the mixed language-pack settings surface now keeps explicit
LanguageResourceBindingrecords for managed translation packs plus secondary/manual entries, and dialog persistence can derive managed ids plus manual paths from those bindings wordnet-enandmoby-enremain explicit compatibility exceptions inside that mixed surface: persistedwordnet_dir/moby_pathare still mirrored for compatibility, but bulk-rules runtime consumers now resolve them from the shared binding-map-first effective-path helper before falling back to those legacy aliases- the language-pack table, delete flow, and auto-link path now consume those
LanguageResourceBindingrecords directly, and the language-pack tab now explicitly states that app-managed packs are the default while manual selection is a temporary compatibility path - bulk-rules translation loading and source-stat reporting now use a shared configured language-pack resolver to rebuild managed translation artifacts from stored pack ids before falling back to manual path maps, while SRS growth rebuilds managed default frequency artifacts from stored pack ids before falling back to manual paths
- the settings panel now omits redundant managed embedding artifact paths from saved settings when those installs are already represented by pack id + manifest-backed resolution
- settings serialization now writes explicit
language_pack_paths,frequency_pack_paths, andembedding_pack_pathskeys instead of the older generic*_packspath maps - the settings UI now labels app-owned resolved resources as installed artifacts and external/manual paths as manual inputs, with embedding activation explicitly distinguishing active installed vs active manual rows
- the resource workspace intro plus the frequency and embedding tab copy now explicitly describe installed packs as the default path and manual paths as compatibility/import surfaces
- helper CLI/native-host execution entrypoints now accept
frequency_pack_pathas the preferred frequency override field while retainingset_source_dbas a compatibility alias, and preview/rebalance payloads expose frequency pack path/id/provider/POS-profile fields alongside the legacy execution field
- GUI language-pack downloads install into stable per-pack roots under
- Current runtime contract is still transitional rather than final:
- FreeDict and Kaikki translation packs now expose SQLite as the canonical app-managed runtime artifact, but manual TEI files, older extracted directories, and legacy
<pack_id>.sqlitefilenames remain compatibility inputs during migration - normalized translation/frequency settings are now pack-id-first for the mandatory managed families, while
wordnet-en/moby-enremain explicit compatibility aliases inside the secondary language-pack family until any later promotion decision is made - frequency packs already expose SQLite, and new app-managed installs now use
main.sqlite, but legacyfreq-*.sqlitenames still remain valid fallback paths during migration - embedding runtime still accepts raw
.vec/.binpaths as a compatibility path for manually supplied external files - managed embedding settings/runtime are now pack-id-first for app-owned installs, while manual raw/vector and external SQLite paths remain separate compatibility/import inputs
- broad manual file-path selection is not a promoted product feature; it is a transitional compatibility surface and likely phase-out candidate unless a concrete use case survives
- FreeDict and Kaikki translation packs now expose SQLite as the canonical app-managed runtime artifact, but manual TEI files, older extracted directories, and legacy
- Target architecture is now explicit:
- Evidence:
docs/developer/data_source_normalization_architecture.mddocs/developer/language_pair_generalization_roadmap.mddocs/language_pairs/de_en_workstream_roadmap.mdapps/gui/src/language_packs_catalog.pyapps/gui/src/language_packs.pyapps/gui/src/settings_language_packs_path_mixin.pyapps/gui/src/settings_language_packs.pyapps/gui/src/settings_language_packs_support.pycore/lexishift_core/helper/translation_packs.pycore/lexishift_core/helper/frequency_packs.pycore/lexishift_core/helper/embedding_packs.pycore/lexishift_core/helper/pair_resources.pycore/lexishift_core/helper/installed_packs.pycore/lexishift_core/helper/lp_capabilities.pycore/lexishift_core/helper/use_cases/runtime_diagnostics.pyapps/gui/src/main_srs_mixin.pyapps/gui/src/main_replacement_filter_mixin.pyapps/gui/src/dialogs.pycore/lexishift_core/persistence/settings.pyapps/gui/src/main_bulk_rules_mixin.pycore/lexishift_core/resources/freedict_sqlite.pycore/lexishift_core/resources/synonyms.pycore/lexishift_core/frequency/de/build_support.pycore/lexishift_core/frequency/de/pipeline.pyapps/gui/src/main_bulk_rules_mixin.pyscripts/testing/srs_quality_harness_support.pyscripts/testing/srs_journey_harness_support.pyscripts/testing/synthetic_translation_fixture_support.pyscripts/data/convert_embeddings.pyscripts/data/convert_freedict_tei_to_sqlite.pycore/tests/helper/test_installed_packs.pycore/tests/helper/test_lp_capabilities.pycore/tests/helper/test_frequency_packs.pycore/tests/dev/test_pos_normalization_probe.pycore/tests/helper/test_pair_resources.pycore/tests/helper/test_helper_engine.pyapps/gui/tests/test_main_settings_resource_persistence.pyapps/gui/tests/test_main_embedding_pack_resolution.pyapps/gui/tests/test_language_pack_panel_state_mixin.pyapps/gui/tests/test_main_bulk_rules_translation_pack_resolution.pyapps/gui/tests/test_language_pack_path_mixin.pyapps/gui/tests/test_state_resource_settings_migration.pycore/tests/helper/test_embedding_packs.pycore/tests/dev/test_srs_harness_resource_normalization.pycore/tests/frequency/test_de_build_support.pycore/tests/resources/test_dict_loaders_freedict_pos.pycore/tests/resources/test_synonyms_translation_packs.py
- Known gaps:
- Installed-pack resolution is only partially manifest-driven today; generic helper/runtime resolution and GUI auto-link use it for translation and frequency defaults, shared translation/frequency pack refs now honor manifests, and benchmark resource payloads now carry translation and source-frequency pack identity directly, but probe flows still include some legacy path assumptions.
- FreeDict packs are still effectively runtime-addressed through TEI-compatible paths in some probe/tooling flows even though app-managed installs now build to SQLite and the main helper/GUI/harness consumers now prefer SQLite-first paths.
- Managed embedding activation no longer needs persisted app-owned artifact paths, and the settings panel now strips managed installed artifacts from seed/auto-link state; remaining temporary embedding path handling is mostly limited to in-flight download/conversion/manual-link flows.
- Manual external embedding files still bypass the managed-pack manifest layout by design during migration.
wordnet-en/moby-enare still not promoted into the same normalized managed-pack model as translation/frequency/embeddings; they remain explicit compatibility exceptions until the broader secondary lexical family decision is made.- Frequency packs still preserve their legacy
freq-*.sqliteartifact names as fallback paths during migration. - Translation consumers still include TEI-compatible assumptions in some probe/tooling paths, but the shared loader-backed or SQLite-first consumers now include rulegen pairs, helper/runtime diagnostics, benchmark resource payloads, the German frequency whitelist, synonym generation, the bulk-rules GUI path, and the synthetic SRS quality/journey harnesses plus installed journey staging.
de-en Baseline Rulegen Enablement
- Status:
implemented,verified;default-on=yesfor helper/rulegen capability whenfreedict-en-deis present - Last documented checkpoint:
2026-04-03de-enhelper defaults now prefer manifest-backed app-managed translation artifacts, with legacyfreedict-en-de.sqliteand TEI inputs retained only as fallback compatibility paths - Last verified:
2026-04-03targeted helper/capability/adapter tests and doc sync - Default behavior:
de-ennow has a real rulegen mode (de_en) and participates in the generalized translation-dictionary helper seam.- Default
de-enforward resolution now prefers manifest-backed app-managed translation artifacts and otherwise falls back to legacyfreedict-en-de.sqlite/ TEI compatibility inputs when needed, with normalized translation-pack identity available in helper/resource resolution. - The first
de-enpair implementation is intentionally simple: FreeDict forward candidate extraction, generic scoring, German source-side stopword filtering, and no reverse-check path yet.
- Evidence:
core/lexishift_core/helper/lp_capabilities.pycore/lexishift_core/rulegen/pairs/de_en.pycore/lexishift_core/rulegen/adapters.pycore/tests/helper/test_lp_capabilities.pycore/tests/helper/test_pair_resources.pycore/tests/helper/test_translation_packs.pycore/tests/helper/test_helper_engine.pycore/tests/helper/test_helper_daemon.pycore/tests/rulegen/test_rulegen_adapters.pydocs/language_pairs/de_en_workstream_roadmap.md
- Known gaps:
de-enstill has no benchmark dataset or quality frontier; this slice is enablement, not tuning.de-enstill has no reverse-check implementation.- Helper CLI override naming still reflects legacy FreeDict terminology even though the generalized translation-dictionary seam is active underneath.
en-de Advisory Quality Lane
- Status:
implemented,verified;default-on=nofor the repo-wide hard gate - Last documented checkpoint:
2026-04-04en-denow has a real Kaikki tuning lane, same-sense representative selection, German register/family enrichment, and an experimental sense-level defaultness penalty in addition to the earlier source-frequency, reverse-check, and Kaikki-policy scaffolding - Last verified:
2026-04-10feature-state evidence sync against the clean branch after preserving the separateen-debenchmark WIP branch - Default behavior:
en-denow has a first-class advisory benchmark/gate/triage surface separate from the canonical stricten-eslane.- The dedicated
en-degate now runs in pair-scoped mode, so it no longer reports missing required/recommended-pair or no-delta-overlap noise from unrelated benchmark lanes. - The lane now uses a named preset:
en_de_canonical_matrix
en-denow also has an experimental default-off source-frequency prior:- benchmark/config label:
sfreq=on/off - benchmark CLI surface:
--source-frequency-prior-values,--source-frequency-db-en-de - probe CLI surface:
--enable-source-frequency-prior,--source-frequency-db-en-de
- benchmark/config label:
en-denow also has an experimental default-off reverse-check bridge:- benchmark/config labels:
rev,xamb,xspec - benchmark uses the existing reverse English->German resource resolution when
rev=on - probe flags:
--reverse-check-enabled,--translation-dict-en-de-reverse
- benchmark/config labels:
en-denow also consumes the existing Kaikki policy surface when the translation source is a Wiktionary/Kaikki-style SQLite:- benchmark/config labels:
kdem,kfam,kprov - probe flags:
--kaikki-policy-live-demotion,--kaikki-policy-late-sense-penalty - provider/profile inference now follows the translation-pack identity instead of hardcoding FreeDict POS normalization
- benchmark/config labels:
en-denow also has experimental default-off Kaikki sense-shaping / competition seams:- same-sense representative selection surfaced as
srep - sense-level defaultness competition surfaced as
sdcmp - probe flags:
--sense-representative-penalty,--sense-defaultness-competition-penalty
- same-sense representative selection surfaced as
- The app-managed translation catalog now includes:
wiktionary-de-en- build wrapper:
scripts/data/convert_kaikki_de_en_to_sqlite.py - converter path:
scripts/data/convert_kaikki_glosses_to_sqlite.py
- Dedicated outputs now live at:
docs/test_outputs/rulegen_benchmark_en_de_latest.jsondocs/test_outputs/rulegen_benchmark_en_de_latest.mddocs/test_outputs/rulegen_benchmark_en_de_latest.htmldocs/test_outputs/rulegen_quality_gate_en_de_latest.jsondocs/test_outputs/rulegen_benchmark_triage_en_de_latest.jsondocs/test_outputs/rulegen_benchmark_triage_en_de_latest.mddocs/test_outputs/rulegen_benchmark_en_de_summary_latest.mddocs/test_outputs/rulegen_quality_gate_en_de_summary_latest.mddocs/test_outputs/rulegen_benchmark_triage_en_de_summary_latest.md
- The current lane intentionally stays baseline:
- no reverse-check in the canonical advisory latest lane
- no promoted
en-deKaikki default source path yet - dataset-expansion and lexical-choice cleanup come before pair-specific frontier work
- Evidence:
docs/language_pairs/en_de_workstream_roadmap.mddocs/developer/ai_workflow.mdscripts/package.jsondocs/test_inputs/rulegen_benchmark_presets.jsondocs/test_outputs/rulegen_benchmark_en_de_latest.jsondocs/test_outputs/rulegen_quality_gate_en_de_latest.jsondocs/test_outputs/rulegen_benchmark_triage_en_de_latest.jsondocs/test_outputs/rulegen_benchmark_en_de_source_freq_experiment_latest.jsondocs/test_outputs/rulegen_quality_gate_en_de_source_freq_experiment_latest.jsondocs/test_outputs/rulegen_benchmark_triage_en_de_source_freq_experiment_latest.jsondocs/test_outputs/rulegen_benchmark_en_de_kaikki_tuning_latest.jsondocs/test_outputs/rulegen_benchmark_en_de_kaikki_tuning_summary_latest.mddocs/test_outputs/rulegen_quality_gate_en_de_kaikki_tuning_latest.jsondocs/test_outputs/rulegen_benchmark_triage_en_de_kaikki_tuning_latest.jsoncore/lexishift_core/rulegen/pairs/en_de.pycore/lexishift_core/rulegen/adapters.pyapps/gui/src/language_packs_catalog.pyscripts/data/convert_kaikki_de_en_to_sqlite.pyscripts/testing/rulegen_probe_words.pycore/tests/rulegen/test_rulegen_adapters.pycore/tests/dev/test_rulegen_probe_words.pycore/tests/resources/test_kaikki_sqlite_conversion.py
- Known gaps:
en-deremains advisory and is still not part ofrequired_benchmark_pairs.- The benchmark case set is now broader at
58targets, but the currenten-delatest run is still well below the configured top-1 floor (65.52%top1,93.10%top3). - The current
en-delatest triage surface is still heavy at21actionable items (16FAIL,5REVIEW), including hard junk-gloss failures such asZeit -> spell,Sprache -> diction,Fenster -> box, andTag -> tag. - The dedicated
en-degate is now pair-scoped, but delta checks still warn until anen-debaseline is accepted:DELTA_SCOPE_BASELINE_MISSING
en-denow has default-off reverse-check plumbing and probe support, but the first focused Kaikki reverse experiment did not beatrev=off(93.10%top1 /96.55%top3 ->91.38%/96.55%with the tested reverse setting).- The new source-frequency prior is measurable but not sufficient on its own:
- focused experiment improved
top3(93.10%->98.28%) without movingtop1(65.52%) - the mechanism currently helps expected answers re-enter top3 (
Grund,Straße,Zug) more than it fixes junk top1 defaults
- focused experiment improved
wiktionary-de-endownload/build support now exists, and the local Kaikki tuning lane is strong (93.10%top1 /96.55%top3), but it is still a local advisory comparison rather than a promoted default source path or accepted scoped baseline.- The current best local Kaikki
en-deconfig still leaves the richer parity signals off:rev=offkdem=offkprov=off
- Same-sense representative selection is now a real frontier mover in local Kaikki runs, but the first sense-level defaultness penalty (
sdcmp) proved too blunt to help. en-denow has a compiled resource context, candidate-row IR, and live/compiled prepared score-table plus selected-row sweep coverage, but it still lacks the fulleren-esprepared benchmark stack and the richeren-es-style provenance competition layer.- Practical initialize/refresh work for the German-target lane still needs the missing
freq-de-default.sqliteresource even though the benchmark lane itself can run.
Rulegen Auto Audit Wrapper
- Status:
implemented,verified,default-on=no - Last documented checkpoint:
2026-03-11 - Last verified:
2026-03-11CLI inspection - Default behavior:
- Optional wrapper for touched-pair rulegen audits.
- Preserves the canonical benchmark -> quality gate -> triage sequence by calling
rulegen_pair_audit_cycle.py. - Adds dated artifacts,
*_latestalias updates, and run manifests.
- Evidence:
docs/developer/ai_workflow.mddocs/developer/genai_workflow_architecture.mdscripts/testing/rulegen_auto_audit.pyscripts/testing/rulegen_pair_audit_cycle.py
- Known gaps:
- Pair inference is heuristic and should not replace explicit
--pairswhen the touched scope is ambiguous. - Wrapper coverage is currently specific to the rulegen quality loop and not yet mirrored for SRS quality work.
- Pair inference is heuristic and should not replace explicit
SRS Quality Harness
- Status:
implemented,verified,default-on=yesfor SRS scheduler/admission/publication/runtime-serving workflow - Last documented checkpoint:
2026-05-27feedback-cycle before/after snapshots now make the SRS quality artifact show feedback deltas separately from refresh/admission deltas; the harness also includes an encounter-watch scenario for fresh unseen, stale unseen, legacy age-unknown, reviewed, and no-enabled-rule active SRS items - Last verified:
2026-05-27targeted harness/summary tests, feedback simulation test, SRS quality harness rerun with encounter-watch coverage, and fresh normalized JSON + Markdown artifact rerender - Default behavior:
- Use the synthetic harness for SRS scheduler, admission refresh, helper publication, set execution, and runtime-serving workflow changes.
- Review scheduling is now FSRS-based.
- Current harness covers bootstrap/publication/runtime diagnostics for
en-jaanden-de, plus anen-jafeedback-cycle pause/resume scenario. - The feedback-cycle scenario now checks helper SRS due metadata and runtime due-active counts, so broad publication can pass only when runtime serving remains due-aware.
- The feedback-cycle scenario now records initial, before-refresh, and after-refresh store snapshots, including scheduler fields, selected lemmas, and separate feedback vs refresh deltas.
- The encounter-watch scenario verifies age-aware dashboard diagnostics for fresh unseen, stale unseen, legacy age-unknown, reviewed, and no-enabled-rule active items.
- The committed
latestJSON artifact is publication-normalized for review stability; raw in-memory harness details remain available before publication. - Human-facing summary is available from the JSON artifact and includes an Encounter Watch section.
- Evidence:
AGENTS.mddocs/developer/ai_workflow.mdscripts/testing/srs_quality_harness.pyscripts/testing/srs_quality_harness_support.pyscripts/testing/srs_quality_summary.pycore/tests/dev/test_srs_quality_harness.pycore/tests/dev/test_srs_quality_summary.pydocs/test_outputs/srs_quality_latest.jsondocs/test_outputs/srs_quality_summary_latest.md
- Known gaps:
- Coverage is synthetic and pair-limited; it does not yet grade pedagogical quality or real user data.
- The harness verifies runtime due-aware serving through metadata; it does not require or prove a dedicated due-only publication artifact.
es-en/en-esSRS quality scenarios are not yet represented in the synthetic harness.
Kaikki en-es Compatibility Dictionary Pipeline
- Status:
implemented,verified;default-on=yesfor forwardwiktionary-es-en.sqlitewhen present and for theen-esreverse-check path whenwiktionary-en-es.sqliteis present - Last documented checkpoint:
2026-03-23reverse-source evaluation + dedicated EN->ES converter/catalog path - Last verified:
2026-03-23targeted converter/helper/adapter tests plus rebuilt Kaikki forward artifact benchmark and Kaikki/Kaikki reverse-enableden-escomparison lane - Default behavior:
- App language-pack catalog now includes a pair-specific
wiktionary-es-enpack sourced from the English-edition Kaikki raw dump. - App language-pack catalog also includes a dedicated
wiktionary-en-esKaikki pack for EN->ES reverse-check evaluation. - Download flow now supports
download + convert + auto-linkfor this pack, producing a compatibility SQLite artifact rather than exposing raw JSONL to runtime. en-espair resource resolution now preferswiktionary-es-en.sqlitewhen present in the language-packs dir.- The normalized runtime contract stays aligned with the existing dictionary loader surface:
entries(headword, headword_lc, translation, translation_lc, rank, pos, entry_ord, gloss_ord). - Converter preserves richer Kaikki metadata in auxiliary SQLite tables for later ranking/synonym work, and the reverse converter additionally preserves translation-box metadata in
translation_meta.
- App language-pack catalog now includes a pair-specific
- Evidence:
docs/language_pairs/kaikki_en_es_integration_plan.mddocs/language_pairs/language_pack_urls.txtdocs/language_pairs/lp_resource_requirements.mddocs/language_pairs/data_source_licensing_and_distribution.mdapps/gui/src/language_packs_catalog.pyapps/gui/src/language_packs.pyapps/gui/src/settings_language_packs.pyapps/gui/src/settings_language_packs_path_mixin.pycore/lexishift_core/resources/kaikki_sqlite.pyscripts/data/convert_kaikki_glosses_to_sqlite.pyscripts/data/convert_kaikki_es_en_to_sqlite.pyscripts/data/convert_kaikki_translations_to_sqlite.pyscripts/data/convert_kaikki_en_es_to_sqlite.pycore/lexishift_core/helper/lp_capabilities.pycore/lexishift_core/pos/normalization.pycore/lexishift_core/rulegen/adapters.pycore/lexishift_core/rulegen/pairs/en_es.pycore/tests/resources/test_kaikki_sqlite_conversion.pycore/tests/helper/test_lp_capabilities.pycore/tests/pos/test_pos_normalization.pycore/tests/rulegen/test_rulegen_adapters.pydocs/test_outputs/rulegen_benchmark_en_es_kaikki_latest.jsondocs/test_outputs/rulegen_benchmark_triage_en_es_kaikki_latest.jsondocs/test_outputs/rulegen_benchmark_en_es_kaikki_bidir_reverse_latest.jsondocs/test_outputs/rulegen_benchmark_triage_en_es_kaikki_bidir_reverse_latest.json
- Known gaps:
en-esquality gate remains red in the current workspace even after the Kaikki forward ordering fix; further sense-policy and reverse-check work is still required.- The reverse Kaikki source decision is documented, the EN->ES converter exists, and the first reverse-enabled Kaikki/Kaikki lane improved
en-estop1 to81.25%, but the remaining failure classes still need review before promoting the same artifact to the generales-enforward path. - Synonym extraction from Kaikki metadata is still deferred.
- Bulk-rules GUI selection is not yet wired to use the new Kaikki pack id.
SRS Journey E2E Harness
- Status:
implemented,verified;default-on=no - Last documented checkpoint:
2026-05-27FSRS-backed journey artifacts for deterministic, synthetic-real, installed-resource, anden-esprofile-preference lanes - Last verified:
2026-05-27deterministicen-ja+en-escore and edge journey harness runs, synthetic-resource real-publication lanes, installed-resourceen-ja+en-esruns,en-es_profile_preference_journey_v1, Markdown summaries, and interactive HTML review artifacts - Default behavior:
- Deterministic
en-jaanden-escore and edge journey lanes plus matching real-publication lanes are available as analysis-first SRS E2E harnesses, but they are not yet part of the required default SRS workflow loop inAGENTS.md. - The core lane captures item-level admitted
S, dueD, and publishedPsets across bootstrap, refresh, and fade/stick phases. - Journey JSON now includes bootstrap candidate audits, refresh candidate ranking audits, and richer per-item state fields such as confidence, due rank, and lexical previews for retroactive pedagogical review.
- The edge lane captures duplicate-feedback and exposure-only behavior with the same item-level reporting contract.
- The real-publication lane keeps deterministic clocks/resources, uses the actual seed-builder plus helper/rulegen publication path, and now holds complete due publication for the current
en-jaanden-esscenarios. - Separate installed-resource review lanes now stage the user’s local frequency/dictionary packs into an isolated temp helper root, assign cohorts from actual admitted lemmas, and surface real-data pedagogical flow without mutating the live helper state.
- The
en-esprofile-preference lane proves thatprofile_bootstrapcan promote a tagged topic candidate into the initial active set, while the same scenario still grows, pauses, and resumes through feedback refresh. - Interactive HTML playback artifacts now provide step-by-step review with phase controls, admission rationale tables, and a sticky profile-state panel.
- Current contract mode defaults to observation: publication broader than the due subset is surfaced as a warning rather than a hard failure.
- Deterministic
- Evidence:
docs/srs/srs_journey_harness_workstream.mdscripts/testing/srs_journey_harness.pyscripts/testing/srs_journey_summary.pyscripts/testing/srs_journey_html.pydocs/test_outputs/srs_journey/srs_journey_en_ja_latest.jsondocs/test_outputs/srs_journey/srs_journey_en_ja_latest.mddocs/test_outputs/srs_journey/srs_journey_en_ja_latest.htmldocs/test_outputs/srs_journey/srs_journey_en_ja_edge_latest.jsondocs/test_outputs/srs_journey/srs_journey_en_ja_edge_latest.mddocs/test_outputs/srs_journey/srs_journey_en_ja_edge_latest.htmldocs/test_outputs/srs_journey/srs_journey_en_ja_real_latest.jsondocs/test_outputs/srs_journey/srs_journey_en_ja_real_latest.mddocs/test_outputs/srs_journey/srs_journey_en_ja_real_latest.htmldocs/test_outputs/srs_journey/srs_journey_en_es_latest.jsondocs/test_outputs/srs_journey/srs_journey_en_es_latest.mddocs/test_outputs/srs_journey/srs_journey_en_es_latest.htmldocs/test_outputs/srs_journey/srs_journey_en_es_edge_latest.jsondocs/test_outputs/srs_journey/srs_journey_en_es_edge_latest.mddocs/test_outputs/srs_journey/srs_journey_en_es_edge_latest.htmldocs/test_outputs/srs_journey/srs_journey_en_es_real_latest.jsondocs/test_outputs/srs_journey/srs_journey_en_es_real_latest.mddocs/test_outputs/srs_journey/srs_journey_en_es_real_latest.htmldocs/test_outputs/srs_journey/srs_journey_en_es_profile_latest.jsondocs/test_outputs/srs_journey/srs_journey_en_es_profile_latest.mddocs/test_outputs/srs_journey/srs_journey_en_es_profile_latest.htmldocs/test_outputs/srs_journey/srs_journey_en_ja_installed_latest.jsondocs/test_outputs/srs_journey/srs_journey_en_ja_installed_latest.mddocs/test_outputs/srs_journey/srs_journey_en_ja_installed_latest.htmldocs/test_outputs/srs_journey/srs_journey_en_es_installed_latest.jsondocs/test_outputs/srs_journey/srs_journey_en_es_installed_latest.mddocs/test_outputs/srs_journey/srs_journey_en_es_installed_latest.html
- Known gaps:
en-deextension is still pending.- The deterministic and synthetic-resource real-publication lanes are still useful regression surfaces, but installed-resource review currently depends on local data-pack availability and is not yet part of the default required workflow loop.
- The journey harness artifacts are not the current due-aware runtime serving authority; use the SRS quality harness for the Lane 5 helper-metadata/runtime-gate contract.
en-es SRS Beta Preflight
- Status:
implemented,verified;default-on=no - Last documented checkpoint:
2026-05-27read-only en-es SRS beta preflight now composes strict-MVP topic-picker checks, taxonomy visibility validation, latest SRS quality evidence, en-es profile-preference and installed-resource journey evidence, and explicit manual beta signoff checks. - Last verified:
2026-05-27preflight script/report generation, focused preflight tests, rerun en-es profile and installed journey artifacts plus summaries, doc-reference check, state audit, diff check, and changed-file gate. - Default behavior:
- The preflight is read-only. It does not install packs, mutate helper state, delete SRS stories, or mark beta signoff complete.
- The generated status is expected to remain
REVIEWuntil a human completes the fresh extension/helper smoke checklist. - Automated checks require the options-page topic picker to match
mvp_picker_visibility=strict_mvp_visible, require beta/hidden/register/ legal-gated families to stay out of the ordinary picker, require locale coverage for visible chips, and require latest SRS quality/journey artifacts to have no failing findings. - Current en-es journey warnings are surfaced rather than hidden. Publication
broader than due is an observation-mode warning, while the installed-resource
movimientodue-not-published warning remains a review item for manual beta smoke because it is a rulegen/data coverage symptom, not a picker/admission selector failure.
- Evidence:
docs/runbooks/srs_beta_preflight_en_es.mdscripts/testing/srs_beta_preflight_en_es.pydocs/test_outputs/srs_beta_preflight_en_es_latest.jsondocs/test_outputs/srs_beta_preflight_en_es_latest.mddocs/test_outputs/srs_journey/srs_journey_en_es_profile_latest.jsondocs/test_outputs/srs_journey/srs_journey_en_es_profile_latest.mddocs/test_outputs/srs_journey/srs_journey_en_es_installed_latest.jsondocs/test_outputs/srs_journey/srs_journey_en_es_installed_latest.mdcore/tests/dev/test_srs_beta_preflight_en_es.py
- Known gaps:
- Manual fresh-install/helper connection, runtime replacement, feedback, automatic refresh, discard, and reset smoke still require human beta signoff.
- The preflight does not replace Chrome Web Store packaging preflight, full repo safety checks, or build validation.
- It reports latest local installed-resource evidence; a tester machine can still differ if required packs are missing or manually installed differently.
Development Workflow Safeties
- Status:
implemented,default-on,verified - Last documented checkpoint:
2026-04-19Ruff fallback resolution + explicit unavailable reporting for workflow style checks - Last verified:
2026-04-19targeted dev-workflow unit tests + wrapper-drivencheck:stylereport +check:changed:local;2026-05-15Lane 3 L3-F packaging/platform parity truth pass, Windows parity audit, parity summary render, focused workflow/build/parity tests, doc-reference check, state check, and diff hygiene - Default behavior:
npm --prefix scripts run checkis the stable non-mutating repo safety command.npm --prefix scripts run checknow includes the strict Windows parity audit, so parity regressions fail the default local safety gate and pre-push hook.npm --prefix scripts run checknow includes strict repo-wide Ruff lint/format checks because the repo-wide style baseline is clean.- Workflow Ruff checks now try the selected Python’s
-m ruffentrypoint first and fall back to aruffexecutable onPATH; advisory commands reportunavailableinstead of fake style debt when neither invocation exists, while strict variants still fail. npm --prefix scripts run check:changedis the preferred branch-scope workflow command.npm --prefix scripts run check:changednow records both total changed files and substantive changed files, and uses the substantive set when inferring heavier quality loops such as rulegen audit; Python uses AST comparison, JSON uses parsed equality, and Markdown/text uses whitespace-normalized comparison.npm --prefix scripts run check:docsnow validates top metadata (Status,Role,Last updated) plus referenced repo paths for canonical routing/policy docs.npm --prefix scripts run check:changednow reruns the canonical doc integrity audit when canonical docs change or when referenced source files underapps/,core/,scripts/,.github/, or canonical root files change materially.npm --prefix scripts run health:project:changednow blocks new/regressed warning debt alongside new/regressed violation debt.npm --prefix scripts run buildis the local build smoke for maintained build surfaces.npm --prefix scripts run build:reportis the full build contract and now verifies expected BetterDiscord / GUI artifacts in the report payload.- Hosted macOS
build:reportkeeps the full GUI bundle validation path; hosted Windowsbuild:reportnow uses the full GUI build plus artifact verification, while the strict Windows parity audit remains the dedicated Windows-specific validation gate. - Hosted CI now runs both the full macOS
build:reportpath and the explicit Ubuntubuild:ci:reportpartial path. - Python-backed npm workflow commands now resolve their interpreter through
scripts/dev/run_python.jssocheck/build/ audit entrypoints remain usable on Windows hosts. npm --prefix scripts run build:ci/build:ci:reportkeep the same build workflow on unsupported hosts while recording explicit GUI-validation skips.npm --prefix scripts run check:styleis the standalone repo-wide style loop.npm --prefix scripts run check:style:reportandcheck:style:summarypublish the current repo-wide Ruff style state as JSON and Markdown artifacts.npm --prefix scripts run check:stateaudits the feature-state ledger for required fields, dated checkpoints, evidence paths, and transition-aware updates relative toHEAD.npm --prefix scripts run check:report,check:changed:report, andbuild:reportemit machine-readable JSON artifacts for automation.- Failed
check/buildcommands now record stdout/stderr tail lines and missing-artifact details in the JSON reports so hosted CI failures remain inspectable from artifacts and summaries. npm --prefix scripts run check:summaryrenders a Markdown summary from the latest workflow reports and now surfaces first-failure detail tails when present.- Hosted CI now lets report-producing steps continue long enough to upload summaries/artifacts, then fails the job via explicit JSON-based gate steps.
- Hosted Ubuntu repo-safety now uses
npm --prefix scripts run check:report:ci, which skips the redundant Windows parity audit; dedicated Windows parity/build jobs remain responsible for that surface. - Hosted repo-safety still renders the latest rulegen benchmark/gate/triage summaries, but the known-red rulegen artifact no longer blocks the generic repo-safety job.
npm --prefix scripts run hooks:installinstalls bothpre-commitandpre-push; the pre-push hook mirrorsnpm --prefix scripts run check.pre-commitnow runs repo-wide Ruff lint and Ruff format before commit, whilepre-pushkeeps the full repo-safety gate.
- Evidence:
scripts/dev/feature_state_audit.pyscripts/dev/dev_workflow_check.pyscripts/dev/dev_workflow_changed_check.pyscripts/dev/dev_workflow_build.pyscripts/dev/dev_workflow_style_check.pyscripts/dev/dev_workflow_style_summary.pyscripts/dev/ruff_support.pyscripts/dev/check_doc_references.pyscripts/dev/check_project_health.jsscripts/dev/project_health_rules.jsscripts/dev/ci_report_gate.pyscripts/dev/run_python.jsapps/betterdiscord-plugin/build_plugin.js.pre-commit-config.yaml.github/workflows/ci.ymlrequirements-build.txtscripts/package.jsondocs/test_outputs/dev_workflow/feature_state_audit_latest.jsondocs/test_outputs/dev_workflow/doc_references_latest.jsondocs/test_outputs/dev_workflow/check_latest.jsondocs/test_outputs/dev_workflow/check_changed_latest.jsondocs/test_outputs/dev_workflow/build_latest.jsondocs/test_outputs/dev_workflow/build_ci_latest.jsondocs/test_outputs/dev_workflow/summary_latest.mddocs/test_outputs/dev_workflow/style_latest.jsondocs/test_outputs/dev_workflow/style_summary_latest.mddocs/test_outputs/project_health/project_health_latest.jsondocs/developer/documentation_governance.mddocs/developer/project_health_gate_structure.mddocs/developer/local_setup.mddocs/developer/build_and_release.md
- Known gaps:
- GUI packaging makes
buildmaterially slower thancheck. - Hosted build coverage is now macOS full, Windows full-build plus artifact verification with a separate strict parity gate, and Ubuntu CI-safe partial; Ubuntu remains the explicit non-GUI proof lane rather than full desktop packaging.
- Canonical-doc metadata enforcement is currently limited to the canonical routing/policy layer, not every maintained doc in the repo.
- Pre-commit and pre-push coverage are optional until contributors run
npm --prefix scripts run hooks:install. - Branch-scope changed reports intentionally surface the whole branch delta, so long-running branches can report unrelated debt unless contributors use
check:changed:localorcheck:changed:staged.
- GUI packaging makes
GitHub Pages Docs Deployment
- Status:
implemented,default-on,verified - Last documented checkpoint:
2026-03-13 - Last verified:
2026-03-13localbundle exec jekyll build --trace+ hostedpages/pages-build-deploymentsuccess on302bba5 - Default behavior:
- Repo-owned Pages workflow now lives in
.github/workflows/pages.yml. - Pull requests touching
docs/**run a build-only Pages validation job. - Pushes to
maintouchingdocs/**build and deploy the site through GitHub Actions. - Local parity command is
cd docs && bundle exec jekyll build --trace.
- Repo-owned Pages workflow now lives in
- Evidence:
.github/workflows/pages.ymldocs/runbooks/github_pages_setup.mddocs/Gemfiledocs/Gemfile.lockdocs/_config.ymldocs/developer/local_setup.mddocs/test_outputs/dev_workflow/github_pages_workflow_verification_latest.md
- Known gaps:
- Current workflow validates Jekyll build/deploy only; it does not yet run link checking or browser-level UI smoke tests for docs JavaScript.
Windows GUI Parity Audit
- Status:
implemented,verified,default-on - Last documented checkpoint:
2026-03-12 - Last verified:
2026-03-12parity audit rerun + repo-safety integration + changed-scope/CI workflow wiring review;2026-05-15Lane 3 L3-F parity audit rerun, parity summary render, focused Windows parity tests, doc-reference check, state check, and diff hygiene - Default behavior:
npm --prefix scripts run checknow runs the strict Windows parity audit as part of repo safety and pre-push.npm --prefix scripts run check:windows:paritywrites a machine-readable parity audit of Windows GUI/helper/build parity.npm --prefix scripts run check:windows:parity:summaryrenders the current parity state into Markdown for human handoff.- Hosted CI now has a Windows full-build lane plus parity audit artifacts.
npm --prefix scripts run check:changednow runs the Windows parity audit automatically when parity-related files change.- Windows CI now uses the strict parity audit command so parity regressions fail the hosted workflow.
- Evidence:
docs/developer/windows_gui_parity_workstream.mdscripts/dev/windows_parity_audit.pyscripts/dev/windows_parity_summary.pyapps/gui/src/frozen_layout.pyapps/gui/src/helper_installer.pyapps/gui/src/helper_ui.pyapps/gui/src/helper_tray.pydocs/architecture/native_messaging_design.mddocs/test_outputs/dev_workflow/windows_parity_latest.jsondocs/test_outputs/dev_workflow/windows_parity_summary_latest.md.github/workflows/ci.yml
- Known gaps:
- The parity audit is now a required workflow gate, but it is still not a complete release certification on its own.
- Current browser coverage is limited to the supported GUI helper environments (
chrome,chromium,brave).
Browser Helper Connection Management
- Status:
implemented,default-on,verified - Last documented checkpoint:
2026-06-01browser-connections manager kept the narrowed one-click prod rows and browser+extension-ID unpacked-dev flow, workspace-host installs switched to a pinned-interpreter wrapper, native-host startup failures write deterministic local logs, resource-settings launches now carry a startup session into GUI startup telemetry, the packaged GUI now uses the canonical PyInstaller onedir EXE/COLLECT payload split, transport/browser failures expose stable helper-facing error codes, options-side helper flows localize timeout/browser-blocked cases alongside helper-missing/host-exited cases, and saved bundled/workspace connections auto-repair a narrow set of deterministic stale manifest/host states on startup or whenConnections...opens - Last verified:
2026-06-01targeted native-host resource-settings telemetry tests, GUI startup logger tests, packaged startup measurement script tests, GUI build-spec tests, native-host startup-log coverage, installed-bundle rebuild/validation, installed-bundle startup measurements, extension helper transport/localization contracts from the existing evidence set, and changed-scope repo safety - Default behavior:
- The GUI app now routes helper install/repair through a Browser Connections manager in the app menu and SRS settings instead of the older single environment prompt.
- Fixed-ID production browsers keep a one-click connect/repair path.
- Unpacked development extensions are managed separately through a narrow dialog that captures only browser + unpacked extension ID; the app uses the current workspace helper automatically for that browser.
- Workspace-host installs now target a generated wrapper script that pins the repo interpreter, so browser launches from Finder/GUI shells do not depend on whichever
python3happens to be onPATH. - Saved bundled/workspace browser connections now auto-repair a narrow set of deterministic stale states on startup and when
Connections...opens: unreadable manifests, missing host paths, missing expected origins, stale bundled copies, and pre-wrapper/stale workspace-wrapper states. - Native-host startup/import failures now append a traceback to
logs/native_host.logunder the LexiShift data root, so browser-sideNative host has exitedfailures have a deterministic local log instead of only a transient browser transport error. - Native-host resource-settings requests now log a startup session, activation timing, launch resolution, command class,
Popentiming, and total native-host handoff timing; cold GUI launches receive the same session throughLEXISHIFT_STARTUP_SESSION_ID. - GUI startup timing records now include session id, PID, parent PID, argv mode, launch source, launch mode, resource pair, UTC timestamps, and request-to-checkpoint timing when the GUI was launched by the native host.
- The packaged GUI uses PyInstaller onedir bundles with
EXE(..., exclude_binaries=True)andCOLLECT-owned binaries/zipfiles/datas, so installed main/helper app size and warm relaunch latency are no longer dominated by duplicated executable payloads. - Native-messaging manifests now merge all allowed origins for the same browser into one manifest instead of assuming only one extension ID.
- Same-browser prod and unpacked-dev entries still share one host path; the GUI only surfaces that as a targeted warning when an unpacked-dev change would switch a configured browser to the workspace host.
- Helper install inspection now distinguishes
Configured,Needs repair, andNot configured, including stale bundled-helper copies and legacy direct-script workspace manifests. - Manifest path, host path, and reveal actions are available only through an explicit technical-details toggle rather than the default card surface.
- Background/bridge transport layers now classify common browser transport failures with stable codes, and options-side helper status/test/open flows localize timeout, browser-blocked native messaging, helper-missing, and host-exited cases instead of surfacing raw browser strings by default.
- Evidence:
docs/architecture/native_messaging_design.mdapps/gui/src/helper_installer.pyapps/gui/src/helper_ui.pyapps/gui/src/main_menu_mixin.pyapps/gui/src/main_runtime.pyapps/gui/src/startup_logging.pyapps/gui/packaging/pyinstaller.specscripts/build/gui_app.pyapps/gui/src/dialogs.pyapps/gui/src/helper_connections_dialog.pycore/lexishift_core/helper/gui_startup_telemetry.pyscripts/helper/lexishift_native_host.pyscripts/dev/packaged_gui_startup_measure.pyapps/chrome-extension/background.jsapps/chrome-extension/shared/helper/helper_transport_extension.jsapps/chrome-extension/options/core/helper/base_methods.jscore/tests/dev/test_helper_installer_native_messaging.pycore/tests/dev/test_helper_browser_connections.pycore/tests/dev/test_extension_helper_error_localization_contract.pycore/tests/dev/test_native_host_startup_logging.pycore/tests/dev/test_native_host_resource_settings.pycore/tests/dev/test_packaged_gui_startup_measure.pycore/tests/dev/test_gui_app_build.pyapps/gui/tests/test_main_runtime_startup_logging.pydocs/test_outputs/dev_workflow/gui_startup_performance_open_latest.jsondocs/test_outputs/dev_workflow/gui_startup_performance_activation_latest.jsondocs/test_outputs/dev_workflow/gui_startup_performance_bundle_id_latest.jsondocs/test_outputs/dev_workflow/gui_startup_performance_direct_latest.json
- Known gaps:
- Native messaging still uses one host manifest per browser name, so same-browser prod and unpacked-dev origins still share one host path.
- Fixed-ID production rows only work in builds where
apps/gui/resources/helper_extension_ids.jsoncontains real non-placeholder production IDs. - The desktop app can verify manifest/origin/host freshness, but it still cannot prove that the browser extension is currently installed and active.
- First launch immediately after reinstall/rebuild can still be materially slower than warm relaunch on the local machine; release signing/notarization and tester-machine measurements still need confirmation.
Feature-State Evidence Audit
- Status:
implemented,default-on,verified - Last documented checkpoint:
2026-03-12 - Last verified:
2026-03-12local audit run + repo safety/base-ref integration - Default behavior:
scripts/dev/feature_state_audit.pyvalidates that feature entries include status, dated checkpoints, default behavior bullets, evidence bullets, and known gaps.- Evidence paths in
docs/developer/feature_state_matrix.mdmust resolve on disk. - Repo safety now runs this audit directly against
HEAD, pre-commit runs it when the feature ledger changes, and changed-scope workflow checks run it against the branch base when the ledger is touched.
- Evidence:
scripts/dev/feature_state_audit.pycore/tests/dev/test_feature_state_audit.pyscripts/dev/dev_workflow_check.py.pre-commit-config.yamldocs/test_outputs/dev_workflow/feature_state_audit_latest.json
- Known gaps:
- The audit enforces structure and evidence existence, not semantic correctness of every status claim.
- It does not yet require every status transition to update its verification date in the same commit.
Exact Gloss Demotion Overrides
- Status:
implemented,default-off,verified - Last documented checkpoint:
2026-04-04 - Last verified:
2026-04-04code inspection and canonicalen-es/en-debenchmark artifact refresh - Default behavior:
- Disabled for helper defaults and canonical benchmark lanes.
- Available only when
enable_exact_gloss_demotionsis explicitly enabled. semantic_demotion_scaleonly modulates this override layer when enabled.
- Evidence:
docs/rulegen/rule_generation_technical.mddocs/rulegen/rulegen_congruity_implementation_plan.mddocs/rulegen/rulegen_lp_support_guide.mdcore/lexishift_core/rulegen/semantic_demotion.pycore/lexishift_core/rulegen/adapters.pycore/lexishift_core/rulegen/pairs/en_es.pycore/lexishift_core/rulegen/pairs/es_en.pycore/lexishift_core/rulegen/pairs/en_de.pycore/lexishift_core/rulegen/pairs/en_ja.pydocs/test_outputs/rulegen_benchmark_summary_latest.mddocs/test_outputs/rulegen_benchmark_en_de_summary_latest.md
- Known gaps:
- The override map is exact phrase-level and should not be treated as a substitute for generalizable ranking signals.
- Current
en-esanden-dequality gaps still require richer ranking/source mechanisms.
Reverse-Check Scoring
- Status:
implemented,verified,default-on=no - Last documented checkpoint:
2026-04-04en-denow also wires reverse resource resolution, metadata emission, ranking consumption, and probe surface, with the first focused Kaikki reverse experiment recorded separately - Last verified:
2026-05-16root-dated rulegen evidence relocation moved the dateden-esreverse-check artifacts underdocs/test_outputs/experiments/rulegen_en_es_reverse_check_20260313/and refreshed reverse-check routing without rerunning benchmark artifacts - Default behavior:
- Configurable and pair-aware for
en-es,es-en, anden-de. - Not yet promoted to default production tuning.
- Reverse-check-specific evaluation now has a named
en-eslane vianpm --prefix scripts run quality:rulegen:reverse:en-es. - Parameter-set comparison is now tracked in
docs/test_outputs/rulegen_reverse_en_es_run_matrix_latest.md. en-dereverse-check is now available to the benchmark/probe seams, but remains off in the canonical advisory lane and off in the current best Kaikki lane.- Reverse scoring now also supports:
- an exact-hit ambiguity penalty keyed off
reverse_check_total - an additive exact-hit specificity bonus keyed off
reverse_check_total
- an exact-hit ambiguity penalty keyed off
- both signals are harness-exposed, but both are still off in the current canonical best run.
- Configurable and pair-aware for
- Evidence:
docs/rulegen/reverse_check_scoring_phase1.mddocs/rulegen/reverse_check_rollout_matrix.mddocs/archive/rulegen/reverse_check_en_es_case_review_2026-03-13.mddocs/archive/rulegen/reverse_check_en_es_aggressive_expansion_2026-03-13.mddocs/archive/rulegen/reverse_check_en_es_failure_traits_2026-03-13.mdcore/lexishift_core/rulegen/ranking.pycore/lexishift_core/rulegen/pairs/en_es.pycore/lexishift_core/rulegen/pairs/es_en.pycore/lexishift_core/rulegen/pairs/en_de.pycore/lexishift_core/rulegen/adapters.pycore/lexishift_core/rulegen/tuning.pyscripts/testing/rulegen_benchmark.pyscripts/testing/rulegen_probe_words.pydocs/test_outputs/rulegen_benchmark_en_es_latest.mddocs/test_outputs/rulegen_benchmark_triage_latest.mddocs/test_outputs/experiments/rulegen_en_es_reverse_check_20260313/rulegen_benchmark_en_es_reverse_far_hit_experiment_2026-03-13.jsondocs/test_outputs/experiments/rulegen_en_es_reverse_check_20260313/rulegen_benchmark_en_es_reverse_far_hit_experiment_2026-03-13.mddocs/test_outputs/experiments/rulegen_en_es_reverse_check_20260313/rulegen_benchmark_triage_en_es_reverse_far_hit_experiment_2026-03-13.mddocs/test_outputs/rulegen_benchmark_en_es_reverse_latest.jsondocs/test_outputs/rulegen_benchmark_en_es_reverse_latest.mddocs/test_outputs/rulegen_quality_gate_en_es_reverse_latest.jsondocs/test_outputs/rulegen_benchmark_triage_en_es_reverse_latest.mddocs/test_outputs/rulegen_reverse_en_es_run_matrix_latest.mddocs/test_outputs/rulegen_benchmark_en_es_reverse_ambiguity_experiment_latest.jsondocs/test_outputs/rulegen_benchmark_en_es_reverse_ambiguity_experiment_latest.mddocs/test_outputs/rulegen_probe_en_es_reverse_off_latest.jsondocs/test_outputs/rulegen_probe_en_es_reverse_on_latest.jsondocs/test_outputs/experiments/rulegen_en_es_reverse_check_20260313/rulegen_probe_en_es_reverse_far_hit_experiment_2026-03-13.jsondocs/test_outputs/rulegen_benchmark_en_es_latest.jsondocs/test_outputs/rulegen_reverse_en_es_run_matrix_latest.mdcore/tests/rulegen/test_rulegen_adapters.pycore/tests/dev/test_rulegen_probe_words.py
- Known gaps:
en-jastill has no reverse-check implementation, anden-dehas only a first local reverse experiment rather than a promoted pair lane.- No committed
es-enbenchmark/gate/triage artifact yet proves rollout maturity. - The first focused
en-deKaikki reverse experiment did not beatrev=off; the testedrev=onsetting dropped top1 from93.10%to91.38%while leaving top3 flat at96.55%. - The canonical benchmark loop now sweeps both
rev=offandrev=on, buten-esstill remains red on top-1 accuracy and average-rule volume even after the repaired verb reverse normalization restored the bestrev=onlane. - The current
en-esreverse-enabled best run liftstop3to98.25%, buttop1is still capped at91.23%; remaining work is now more about lexical choice than reverse plumbing. - The new exact-hit ambiguity penalty and exact-hit specificity bonus are both implemented and harness-exposed, but neither beat the existing best lane yet; current
cuadrobehavior is still more sensitive to miss/far-penalty tradeoffs and score clamping than to these exact-hit refinements alone. cuadrostill exposes a non-separable failure class for reverse evidence alone, andsacarstill needs phrase-policy work when the benchmark is judged on top-1 quality rather than only top-3 recall.- Current rollout is scoring-only, not strict candidate blocking.
Kaikki Provenance / Competition Scoring
- Status:
implemented,verified,default-on=no - Last documented checkpoint:
2026-03-27provenance scoring with second benchmark-expansion pass and live Kaikki demotion now winning - Last verified:
2026-04-04targeteden-esprovenance coverage plus newen-deadapter/probe tests and canonicalen-debenchmark/gate/triage rerun - Default behavior:
en-esKaikki candidates now support a sweepable additive provenance penalty:late_sense_clean_earlier_competition_penalty
- the signal is off unless the selected config sets a nonzero penalty
- the current canonical best run now selects:
kprov=0.10
- the signal is powered only by existing metadata already carried on candidates:
target_provenancegloss_provenancesense_provenancekaikki_policy_shadow
- benchmark and probe seams both expose it:
- benchmark label:
kprov - probe flag:
--kaikki-policy-late-sense-penalty
- benchmark label:
- Evidence:
docs/language_pairs/kaikki_en_es_integration_plan.mddocs/test_outputs/rulegen_benchmark_en_es_latest.jsondocs/test_outputs/rulegen_benchmark_en_es_latest.mddocs/test_outputs/rulegen_benchmark_triage_latest.jsoncore/lexishift_core/rulegen/pairs/en_es.pycore/lexishift_core/rulegen/pairs/en_es_support.pycore/lexishift_core/rulegen/adapters.pyscripts/testing/rulegen_benchmark.pyscripts/testing/rulegen_probe_words.pycore/tests/rulegen/test_rulegen_en_es_kaikki_provenance.pycore/tests/rulegen/test_rulegen_adapters.pycore/tests/dev/test_rulegen_benchmark.py
- Known gaps:
- only the smallest provenance signal is live so far; richer provenance/competition features are still pending
- the current signal is now selected together with live Kaikki demotion, but it still does not solve
cuadroor the new slang-side failures en-denow has default-off Kaikki-policy scaffolding plus a strong local Kaikki advisory lane when a Wiktionary/Kaikki source is supplied, but there is still no promoted default source path or richeren-es-style provenance competition layeren-jaandes-endo not yet have analogous provenance-scoring work- per-family Kaikki demotion strengths, gloss-decay shape exposure, and lexical short-phrase policy are still the next nearby sweep candidates
Trait-Conditioned Rulegen Profiles
- Status:
planned; runtime routing not implemented or verified - Last documented checkpoint:
2026-04-11 - Last verified:
2026-04-11semantic-shadow feature-vector extraction/tests plus refreshed semantic-shadow matrix/compare artifacts - Default behavior:
- No runtime profile routing exists yet.
- Current rulegen still uses one selected configuration per run rather than choosing profiles from runtime-computable target traits.
- The intended future direction is to route among a small bank of named profiles using a shared feature extractor and benchmark-backed trait analysis.
- Evidence:
docs/rulegen/trait_conditioned_rulegen_profiles.mddocs/rulegen/rule_generation_technical.mddocs/language_pairs/kaikki_en_es_integration_plan.mdscripts/testing/rulegen_benchmark.pyscripts/testing/rulegen_benchmark_presets.pyscripts/testing/rulegen_benchmark_bundle.pyscripts/testing/semantic_shadow_experiment_matrix_en_es.pyscripts/testing/semantic_shadow_experiment_compare_en_es.pycore/lexishift_core/rulegen/semantic_shadow_feature_vector.pycore/lexishift_core/rulegen/semantic_shadow_evaluation.pycore/lexishift_core/rulegen/pairs/en_es.pycore/lexishift_core/rulegen/kaikki_views.pycore/lexishift_core/rulegen/ranking.py
- Known gaps:
- There is no shared runtime trait extractor for the general rulegen benchmark yet; the new shared feature-vector surface currently exists only for the semantic-shadow veto analysis path.
- The main rulegen benchmark artifacts still do not yet emit per-case feature vectors.
- No profile bank or interpretable router is implemented.
- Current dataset size is still better suited to coarse directional experiments than fine-grained routed-policy learning.
- Learner-stage-aware routing is only conceptual at this point and must stay separate from lexical trait inference.
Semantic Routing Runtime Admission Layer
- Status:
implemented,default-on-when-capable,verified - Last documented checkpoint:
2026-05-15Lane 5 contains thrown semantic inventory/helper exceptions inside the fail-closed semantic admission fallback path - Last verified:
2026-05-15Lane 5 L5-E semantic inventory exception containment validation with focused semantic gate/runtime tests;2026-05-16routing-only evidence sync for semantic-shadow review queue path;2026-06-06route-only evidence sync from getting-started page to guide page - Default behavior:
- Semantic admission is no longer a normal user preference. The browser runtime auto-uses helper-side semantic admission only when the current pair/profile publication is actually capable of real semantic decisioning.
- If a pair/profile has semantic metadata but no ready subset yet, LexiShift stays on standard SRS replacement behavior instead of asking the user to choose a fallback posture.
- The repo now has passive semantic-routing publication scaffolding:
metadata.semantic_admissioncan be emitted on rules- helper publication can write a semantic inventory sidecar
- helper publication now also writes a generation-aligned publication manifest for the ruleset/snapshot/semantic-inventory family
- helper/native-host can now serve that semantic inventory as a first-class artifact
- helper CLI/native-host can now materialize a compiled semantic pack into a profile-local publication family and pair-level pack copy, while requiring an explicit data root unless the caller explicitly opts into the platform default; the installer can resolve a named pack id from an installed pack copy,
LEXISHIFT_SEMANTIC_PACK_CATALOG, or the current repo dev pack before falling back to a developer inventory-path override; the shared extension helper client and Advanced debug options flow now expose a namedinstallSemanticPackroute - extension helper cache/runtime can now persist and resolve semantic inventory in parallel with ruleset/snapshot
- helper source-of-truth diagnostics can inspect pointer coverage, sidecar coverage, publication generation ids, and recomputed manifest-family state from the live helper artifacts
- extension options/runtime diagnostics can surface best-effort cache counts plus cached snapshot/semantic generation ids and simple alignment, helper semantic capability/reason state, runtime semantic capability/pointer/ready counts, live semantic gate enablement, helper vs helper-cache source/error, aggregate ready/replace/abstain/soft-affordance counts, aggregate semantic fallback
reason_codes, semantic helper batch/latency metrics, semantic scan scheduler metrics, DOM context-cache reuse metrics, and the last resolveddecision_policy_idfrom the shipped runtime path - helper/native-host can now also answer
semantic_admit_batchusing a named shared policy registry, and the extension runtime can call that service when semantic admission is active
- The shipped runtime gate is still intentionally conservative:
- only SRS-origin rules that already carry
metadata.semantic_admissionare eligible - runtime activation now depends on computed capability (
active,published_unready,unavailable,error) rather than a visible toggle - the shipped runtime defaults to
abstain_on_unavailablefor ready-rule inventory/helper failure cases, so unavailable semantic scoring fails closed instead of silently allowing replacement - thrown semantic inventory-resolution and helper decision-service exceptions are contained inside the semantic gate and become existing fail-closed fallback reason codes instead of rejecting the page scan
legacy_on_unavailableremains an accepted explicit compatibility policy, but it is not the default runtime/profile postureselection_mode=active_onlyis now an explicit ready competition-set shape for active-only cue evidence with no shadows; foren-es, active-only inventories auto-selecten_es_sentence_veto_v2when the request does not provide a decision-policy override, while ordinaryautomatic,manual, andmixedready competition sets still require real shadow senses- the schema still reserves
soft_affordanceas a future optional non-replace outcome, but current DOM behavior only acts onreplaceand otherwise keeps the original text
- only SRS-origin rules that already carry
- The browser extension options page now exposes a read-only semantic-admission status row:
AutomaticNot yet availableUnavailableNeeds repair
- Current implemented E2E is now explicit:
- offline helper artifacts stay local
- extension loads ruleset plus semantic inventory from helper/cache
- lexical trie matching happens first
- semantic admission activates only when the current enabled SRS rules have nonzero
status=readycoverage and semantic inventory resolves cleanly - eligible matches are counted, but only
status=readyeligible matches are batched to helpersemantic_admit_batch - fallback decisions now roll up reason-code counts such as
semantic_status_pending,semantic_inventory_unavailable, anddecision_service_errorinto runtime diagnostics without changing replacement behavior - ready semantic helper requests use bounded block/sentence-window DOM context when inline markup splits the visible sentence across text nodes, with scan-local context-buffer reuse for small complete blocks, same-context helper-call coalescing, pair/profile inventory-resolution reuse across serial admissions, explicit
fit_scope=per_matchbatching across different context strings, and two-phase semantic preflight for budgeted scans so TF-IDF-style scoring keeps one-match semantics while native helper calls are reduced; the default semantic scan node batch is now96with no helper flush delay, based on the live Castle first-visible/throughput tuning; replacement edits remain scoped to the original text node and final page-budget enforcement remains ordered - non-ready eligible matches still resolve locally through the shipped internal legacy fallback posture
- runtime replaces only
replacedecisions and keeps the original otherwise
en-esnow has a narrow publication PoC:- if real sibling senses for the same trigger are present either in the active emitted ruleset or in the broader initialize/refresh semantic-context pool,
metadata.semantic_admission.statuscan be promoted toreadyfor the active rules without widening the visible SRS ruleset - the semantic inventory then publishes
competition_setswithselection_mode=automaticandselection_policy_version=en_es_emitted_rule_siblings_v1 - active-only generated cue rows can be tested through an isolated helper fixture using
selection_mode=active_onlyand a generation-aligned ruleset/snapshot/semantic-inventory/manifest family
- if real sibling senses for the same trigger are present either in the active emitted ruleset or in the broader initialize/refresh semantic-context pool,
- That PoC is intentionally limited to emitted siblings reachable from helper-side initialize/refresh context; it is not broad shadow mining, phrase-preemption publication, or LP-parity runtime readiness.
en-esnow also has a research-only shadow inventory path:scripts/testing/semantic_shadow_inventory_en_es.pymines sibling candidates from reviewed benchmark trigger phrases plus installed translation packsscripts/testing/semantic_shadow_inventory_triage_en_es.pyscores the resulting preview intobenchmark_aligned,same_pos_only, andno_promotionbucketsscripts/testing/semantic_shadow_policy_compare_en_es.pycompares named promotion policies (same_pos_lenient_v1,benchmark_backed_v1,cross_checked_v1,cross_checked_backoff_missing_active_v1)scripts/testing/semantic_shadow_policy_gap_queue_en_es.pyisolates the small set of rows that the stricter policy still dropsscripts/testing/semantic_shadow_review_queue_en_es.pybuilds the focused provisional keep-row queue consumed by the review-packet generatorscripts/testing/semantic_shadow_review_packet_en_es.pycombines the policy snapshot, provisional keep rows, and provisional drop rows into one adjudication packetscripts/testing/semantic_shadow_gold_proxy_en_es.pygrades the current policies against a reviewed-trigger-overlap gold proxy derived directly fromdocs/test_inputs/rulegen_benchmark_cases/en_es.jsonscripts/testing/semantic_shadow_coverage_gap_en_es.pyexplains the strict-policy underblocked rows by comparing them against current inventory and rulegen benchmark source listsscripts/testing/semantic_shadow_seed_compare_en_es.pyholds the miner and strict promotion policy fixed while swapping only the seed trigger source (benchmark_reviewed,rulegen_top3_sources,rulegen_all_sources)scripts/testing/semantic_shadow_forward_seed_sweep_en_es.pysweeps the new source-only forward-gloss trigger-length knob on top of the strict seed comparescripts/testing/semantic_shadow_support_score_sweep_en_es.pynow sweeps a small explicit support score over threshold andmax_promoted_shadows, rather than adding more named promotion branchesscripts/testing/semantic_shadow_trigger_support_sweep_en_es.pynow sweeps a compact trigger-support score before mining, while keeping the downstream shadow support policy fixed- the latest artifacts confirm that candidate mining works broadly enough to study, and the safer provisional runtime shape is now effectively the strict
cross_checked_v1family: after active-side bundled-trigger matching was fixed,cross_checked_backoff_missing_active_v1no longer widens the promoted set andcoger / catch -> vistafalls out of the review queue - the new gold-proxy artifact gives the first explicit lower-bound grading surface for automation quality, without claiming sentence-level semantic-veto readiness
- the latest miner improvement supplements reverse-headword candidates with benchmark-target forward-gloss matches for the same English trigger, which recovers real misses like
sacar/remove,malla/net, andcuadro/table - current lower-bound read from that proxy:
cross_checked_v1/cross_checked_backoff_missing_active_v1:64.3%candidate precision,90.0%candidate recall,90.0%gold-trigger hit rate,3.6%overblocking rate- candidate-pool recall is now
90.0%, which means the remaining bottleneck is concentrated in harder semantic-bridge cases likecargo/job, not simple reverse-pack asymmetry
- the newest gap audit confirms that remaining bottleneck explicitly:
- only
trabajo / job -> cargoremains underblocked on the overlap proxy - current classification is
semantic_bridge_needed, notrulegen_source_gap
- only
- the newest de-coupling compare makes the current benchmark dependence explicit:
benchmark_reviewed:64.3%precision /90.0%recall /3.6%overblockingrulegen_top3_sources:36.4%precision /40.0%recall /5.1%overblockingrulegen_all_sources:33.3%precision /40.0%recall /5.8%overblocking- interpretation: current shadow mining is not relying on manual per-target hacks, but it still depends materially on reviewed-trigger seeding; the next work is better automatic trigger seeding, not a looser blocker policy
- the newest source-only augmentation lane closes much of the recall gap without adding manual data:
rulegen_top3_plus_forward_gloss/rulegen_all_plus_forward_glossnow reach80.0%candidate recall and80.0%gold-trigger hit rate on the lower-bound proxy, but only at32.0%precision with9.4%overblocking- the numeric forward-seed sweep shows the current best source-only setting is
forward_seed_max_words=1; allowing longer phrase fragments does not improve recall on the current proxy and only worsens overblocking
- the new support-score sweep provides the first compact numeric promotion surface:
- for the reviewed-trigger control, the support score now exposes a real numeric safety/coverage ladder:
min_score=3,max_promoted=1:20.0%precision /90.0%recall /26.1%overblockingmin_score=5,max_promoted=1:100.0%precision /80.0%recall /0.0%overblocking
- for the best current source-only lane,
min_score=5andmax_promoted=2improves the old strict baseline materially without adding manual data:rulegen_top3_plus_forward_gloss/rulegen_all_plus_forward_gloss:47.1%precision /80.0%recall /5.1%overblocking- prior
cross_checked_v1baseline on that lane:32.0%precision /80.0%recall /9.4%overblocking
- interpretation: support-scored promotion is now a real numeric control surface for safety vs coverage, and a better next control surface than inventing more branchy named policies
- for the reviewed-trigger control, the support score now exposes a real numeric safety/coverage ladder:
- the refreshed trigger-support sweep clarifies where earlier automatic-seed noise lives:
- on
rulegen_top3_plus_forward_gloss,min_trigger_score=3only helps relative to a much noisier downstream threshold (shadow min=4,max_promoted=2):- precision
8.0% -> 13.6% - recall stays
80.0% - overblocking
43.5% -> 23.9%
- precision
- on
rulegen_all_plus_forward_gloss, the same trigger filter is too destructive:- precision
8.0% -> 14.3% - recall
80.0% -> 20.0% - inventory coverage
90.0% -> 50.0%
- precision
- interpretation: trigger filtering remains an upstream cleanup knob, but it is no longer the best frontier; higher downstream support thresholds still dominate it on the current miner
- on
- the new lexical-frequency sweep shows that a soft Spanish target-frequency prior does not currently improve the best lexical baseline:
scripts/testing/semantic_shadow_frequency_sweep_en_es.pykeeps the current best source-only lane fixed and only adds a representative bonus for the most frequent shadow targets within each trigger bucket- best current source-only row remains unchanged at
47.1%precision /80.0%recall /5.1%overblocking - higher frequency bonuses actively hurt precision and overblocking
- the follow-on active-vs-shadow frequency-similarity sweep also leaves the best row unchanged:
- best source-only setting still keeps
sim_weight=0.0 - positive similarity weights are effectively inert on the current reviewed overlap proxy
- best source-only setting still keeps
- interpretation: target-side frequency is still worth preserving as optional metadata, but the current
freq-es-cdepack does not justify making either raw frequency or frequency-band similarity a default blocker-selection signal
- the new representative-pruning sweep shows that one obvious condensation idea is not the current bottleneck:
scripts/testing/semantic_shadow_representative_pruning_sweep_en_es.pycollapses same-POS shadow candidates that share the same normalizedsense_label, then keeps the highest-scoring representative from each cluster- on the current reviewed overlap proxy, that leaves the best rows unchanged:
- reviewed control still prefers
offat the current best100.0%precision /80.0%recall operating point - best source-only row also still prefers pruning
off, staying at47.1%precision /80.0%recall /5.1%overblocking
- reviewed control still prefers
- interpretation: redundant same-sense variants exist in the raw inventory, but the present support threshold is already filtering most of them before they affect the reviewed denominator
- the new lower-bound veto-proxy comparison is the first direct
curated_shadowsvsauto_shadowsproduct-shape check:scripts/testing/semantic_shadow_veto_proxy_compare_en_es.pyconverts the reviewed overlap rows into proxyallow/abstaindecisions and comparescurated_shadows,reviewed_auto_shadows,auto_shadows, andno_shadows- current
en-esread:curated_shadows:100.0%abstain recall /0.0%harmful allow /0.0%overblockingreviewed_auto_shadows:80.0%abstain recall /20.0%harmful allow /0.0%overblockingauto_shadows:80.0%abstain recall /20.0%harmful allow /5.1%overblockingno_shadows:0.0%abstain recall /100.0%harmful allow /0.0%overblocking
- interpretation: the current source-only shadow lane already recovers most of the lower-bound veto benefit over
no_shadows, and the remaining gap is concentrated in the unresolvedjobfamily rather than a broad collapse of blocker discovery
- the first target-card embedding bridge has now been swept explicitly:
scripts/testing/semantic_shadow_embedding_bridge_sweep_en_es.pyaugments the current inventories with sentence-transformer nearest neighbors over source-derived target cards, but only as a backoff candidate source- it can recover
trabajo / job -> cargoat the lower support threshold (min_score=4), raising source-only recall from80.0%to90.0% - that gain is not currently worth the noise:
rulegen_top3_plus_forward_glossbaseline best lexical row stays47.1%precision /80.0%recall /5.1%overblocking- best embedding-bridge row falls to
11.8%precision /90.0%recall /35.5%overblocking
- at the safer lexical threshold (
min_score=5), the bridge does not improve recall, because the remainingcargo / job -> trabajomiss still has no active-side support - interpretation: nearest-neighbor target cards are useful as a research recall probe, but not yet a publishable improvement over the lexical baseline
- the matrix harness now exposes explicit source toggles for the newly approved source families:
semantic_bridge_include_aux_textsemantic_bridge_include_examples
- the matrix and compare runners now also accept explicit translation-pack overrides:
--translation-dict--reverse-translation-dict- intended use: replay rebuilt or temporary source artifacts without overwriting installed packs
- current local
en-esread on those rows stays flat versus the lexical control even after refreshing the forward source artifact:promotion_semantic_bridge_aux_text_onmatchessource_only_borrowedpromotion_semantic_bridge_aux_text_examples_onalso leaves veto metrics flat, while lowering gold precision from78.6%to75.9%- the installed
wiktionary-es-en.sqliteforward pack is older than the new example-preserving schema and exposes0 / 453benchmark-target forward records with examples - rebuilding the same forward pack from the local
raw-wiktextract-data.jsonl.gzraises that benchmark-target availability to132 / 453records across45targets - interpretation: forward example absence was a stale-pack issue, not a source-limitation issue, but the current examples bridge still adds mostly extra candidate mass rather than the missing blockers we need
- The next broadening step is now explicit rather than ad hoc:
docs/rulegen/semantic_shadow_source_intake_plan.mddefines the operating model for source-heavy experimentationdocs/test_inputs/semantic_shadow_source_registry.jsontracks current and proposed source families together with approval state, role, and runtime-publishability- the intended discipline is broad offline ingestion plus narrow runtime publication, with one coverage-heavy and one discrimination-heavy source family approved at a time
- The intended future direction is a conservative admission layer that can choose among:
- hard replace
- soft affordance / annotation
- abstain
- The governing product preference for that future layer is explicit:
- false abstain is cheaper than harmful replacement
- The repo now also has a research-only sentence-level runtime-veto harness:
scripts/testing/semantic_routing_sentence_veto_harness.pyevaluates one fixed active-vs-shadow scorer configuration over a curated sentence datasetscripts/testing/semantic_routing_sentence_veto_sweep.pysweeps scorer family, context view, evidence view, and threshold ladders over that same fixed dataset- the current
en-esfixed-shadow evaluation dataset lives atdocs/test_inputs/semantic_routing_cases/en_es_sentence_veto_v10.json - this harness explicitly measures runtime-scoring quality separately from upstream shadow-mining quality
- the default sweep stays on the cheap lexical scorer family, while
sentence_transformer_cosineis available as an explicit heavier model-choice lane - the shipped ordinary
en-eshelper runtime now defaults to the deployable lexical gate viaen_es_sentence_veto_v2(tfidf_cosine + masked_sentence + all_evidence_text + min_active=0.015 + min_margin=0.00); the heavieren_es_sentence_veto_v3sentence-transformer lane remains explicit because it requires model/dependency availability
- First current lexical result on that harness:
- the original higher threshold ladder (
min_active >= 0.25) collapses to total abstention - once the sweep includes
min_active_score=0.00and0.05, the best zero-harmful lexical control row wastfidf_cosine + masked_sentence + all_evidence_text + min_active=0.05 + min_margin=0.00; the current active-only product-smoke posture deliberately lowers that floor to0.015to reduce false abstains after live-page review accepted some harmful-replace risk - on the expanded
v10dataset, that row reaches73.7%decision accuracy with0.0%harmful replace,100.0%replace precision, and34.2%replace recall on the current 95-case curated dataset
- the original higher threshold ladder (
- First current model-choice result on that harness:
- the shipped
v3sentence-transformer default is still the bounded runtime experiment, but the activev10evaluation slice still does not show a clean hard-replace story - on
v10, the samemasked_sentence + all_evidence_text + noun_family_frame_guard + sense_label_near_tie_active_rescue + min_active=0.00 + min_margin=0.00row reaches89.5%decision accuracy with1.8%harmful replace,96.7%replace precision,76.3%replace recall,88.2%winner accuracy, and100.0%shadow-winner accuracy - the current hard errors on the fixed-shadow
v10slice are:- harmful replace:
en-es:sentence-veto:play:005 - false abstains:
en-es:sentence-veto:plant:002,en-es:sentence-veto:park:001,en-es:sentence-veto:drink:002,en-es:sentence-veto:play:002,en-es:sentence-veto:check:002,en-es:sentence-veto:order:002,en-es:sentence-veto:trip:002,en-es:sentence-veto:report:001,en-es:sentence-veto:report:002
- harmful replace:
- the corrected zero-noise soft ladder has collapsed on
v10:- best zero-noise row is
soft:a=0.60:m=0.00 - it adds
0soft true positives and0soft false positives
- best zero-noise row is
- the widened rescue overlay also remains non-clean on
v10, because the sameplay:005row remains harmful - first English-centric challenger
sentence-transformers/all-MiniLM-L6-v2remains worse as a gate than the multilingual default lane reportdoes not reopen the phrase-leak seam on the current strong runtime row;report backis already safely abstained, whilereport:001andreport:002widen the held-out weak-active-support residue- the current testing-only phrase-leak probe now isolates a stronger bounded candidate:
- active-sense noun phrase guarding on mixed noun/verb families
- it removes
play:005on both the hard row and the widened overlay - it now also cleanly phrase-preempts
watch:005,check:005,order:005,trip:005, andreport:005 - it preserves the existing rescue wins
- the held-out review is now more precise:
- the active-sense hard lane removes the harmful replace ceiling without improving the conservative hard corridor
- the active-sense overlay removes the harmful replace ceiling without giving back the current overlay corridor
- so the active-sense overlay is now the preferred bounded experiment, but this is still an evaluation/reference candidate rather than a shipped policy change
- current runtime-eval frontier is therefore no longer phrase-leak diagnosis by itself; it is frozen-queue cue-data preparation:
- keep the hard reference and accepted active-sense overlay fixed
- treat
playas the phrase-risk negative control - treat
check:002,order:002,trip:002,report:001, andreport:002as the current held-out weak-active-support residue - the new
example_sentence_bankfeasibility pilot shows no queued-family example rows on the current installed packs - the new reverse-aux-text pilot now lands that last cheap control:
reverse_aux_plus_all_evidenceimproves the frozen queue-slice point read without widening the current harmful count
- the new prompt-spec plus smoke harness now freeze the first wording bundle too:
- proxy
gpt-5.4-mini - target
gpt-5.4 6concrete request rows across the2active cue slots
- proxy
- after the first live proxy review, the frozen prompt contract was simplified:
- the model now emits only
evidence_text - optional
confidenceremains allowed - the runner synthesizes all fixed ids and sense metadata into the stored intake row
- the model now emits only
- that keeps prompt output cheaper and less fragile while preserving the same stored provenance
- the simplified
semantic_prompt_bakeoff_v2contract has now also passed a real live proxy run:6 / 6accepted and normalized- input tokens dropped from
3414to2545 - output tokens dropped from
1137to222 - the cross-POS slot shifted from broad noun-gloss cues toward determiner/preposition/document framing
- the same simplified contract has now also passed a real live
gpt-5.4target run:6 / 6accepted and normalized- token volume stayed close to proxy (
2545input,231output) - the frame-sensitive cross-POS behavior persisted on the target model
- so the main remaining acceptance gate is no longer prompt confirmation:
- it is downstream effect on the fixed-shadow runtime slice
- that downstream bakeoff is now also landed:
scripts/testing/semantic_llm_prompt_downstream_en_es.pydocs/test_outputs/semantic_llm_prompt_downstream_latest.md
- current downstream read is negative for tranche promotion:
- the intended safe additive lane,
llm_cue_plus_all_evidence, stays flat on both the hard reference and the active-sense overlay - on the hard row it remains
77.5%decision accuracy /50.0%replace recall /1harmful /8false abstains - on the active-sense overlay it remains
80.0%/50.0%/0/8 - it fixes
drink:002, but introducesdrink:001, so there is no net false-abstain gain
- the intended safe additive lane,
- the frozen reverse-aux control still wins:
- hard row
82.5%/62.5%/1/6 - active-sense overlay
85.0%/62.5%/0/6
- hard row
- the stronger LLM diagnostic insertions do show signal, but not safely:
llm_cue_plus_sense_labelandllm_cue_plus_glossboth reach62.5%replace recall- but both widen harmful replace from
1to3
- current conclusion:
- keep the simplified
semantic_prompt_bakeoff_v2output contract as the incumbent storage shape - keep the accepted
gpt-5.4cue tranche in analysis-only status - do not approve broader cue-generation spend until a new prompt shape beats both the hard baseline and the reverse-aux control downstream
- keep the simplified
- that next prompt shape is now prepared as a bounded challenger matrix rather than just a note:
- prompt version
semantic_prompt_bakeoff_v3 4active cue slots and12proxy requests on the same frozenv10queue- incumbent slots:
cue_contrastive_general_v1cue_cross_pos_frame_v1
- overlap challengers:
cue_contrastive_overlap_v1cue_cross_pos_overlap_v1
- next paid decision is therefore narrow:
- cheap proxy comparison first
- then another target-model pass only for slots that beat the incumbents
- prompt version
- that cheap proxy comparison has now also run:
12 / 12requests accepted and normalized- token volume stayed small enough for a bounded screening pass (
5370input /414output) - the overlap challengers are the first prompt variants that visibly move toward literal overlap-bearing evidence:
soil, water, leaves, roots, sunlightyour online order for deliveryannual report with findings, results, and recommendations
- the incumbent slots remain readable, but still rely more on meta-language like
preceded by a determiner
- the narrowed overlap target confirmation has now also run:
- only
cue_contrastive_overlap_v1andcue_cross_pos_overlap_v1were carried forward 6 / 6requests accepted and normalized ongpt-5.4- token usage stayed bounded (
2825input /179output) - target outputs preserved the intended literal-overlap shape:
green leaves, roots in soilwrite a check to pay the rentthe final report on findings and results
- only
- the refreshed downstream acceptance read is still negative for promotion:
Hard LLM cue plus all evidenceregresses the hard lane to72.5%decision accuracy /50.0%replace recall /3harmful /8false abstains- the active-sense overlay remains flat at
80.0%/50.0%/0/8 - the only fixed false abstain in the safe additive lane is
order:002, whiledrink:001is introduced - stronger LLM-only diagnostic lanes show recall but widen harmful replace to
5 reverse_aux_plus_all_evidenceremains the better control at82.5%/62.5%/1/6on the hard row and85.0%/62.5%/0/6on the active-sense overlay
- current conclusion:
- both accepted target cue tranches remain analysis-only
- do not approve broader cue-generation spend from the current prompt matrix
- stop prompt-only iteration until a downstream insertion, source-data, or evaluation-lane change explains how the next spend can beat both the frozen hard reference and the reverse-aux control
- the new no-spend failure diagnostic now preserves that explanation:
scripts/testing/semantic_llm_prompt_failure_diagnostic_en_es.pydocs/test_outputs/semantic_llm_prompt_failure_diagnostic_latest.md- reverse-aux remains the current control at
82.5%accuracy /62.5%replace recall /1harmful /6false abstains - active-only reverse-aux drops to
80.0%/56.2%/1/7, so shadow-side auxiliary evidence is material llm_cue_plus_all_evidencestays worse at72.5%/50.0%/3/8- reverse-aux plus LLM cue is identical to reverse-aux alone, so the accepted LLM cue text adds no incremental downstream value once source-derived active/shadow evidence is present
- LLM rescue-only probes also fail to beat the reverse-aux control
- the new no-spend source/insertion probe now makes the next source shape explicit:
scripts/testing/semantic_llm_source_insertion_probe_en_es.pydocs/test_outputs/semantic_llm_source_insertion_probe_latest.md- full symmetric reverse-aux remains the only winning no-spend lane at
82.5%/62.5%/1/6 - active-only reverse-aux is weaker at
80.0%/56.2%/1/7 - shadow-only reverse-aux is weaker and less safe at
77.5%/56.2%/2/7 - active LLM cues plus reverse-shadow calibration are still unsafe/weak at
72.5%/56.2%/4/7 - hard reviewed example frames remove all false abstains but reopen phrase leaks at
92.5%/100.0%/3/0 - active-guard reviewed example frames reach
100.0%/100.0%/0/0as an internal non-runtime upper bound
- the new no-spend prototype-admission probe keeps the UX binary while testing a more fundamental internal scorer shape:
scripts/testing/semantic_llm_prototype_admission_probe_en_es.pydocs/test_outputs/semantic_llm_prototype_admission_probe_latest.mddocs/test_outputs/semantic_llm_prototype_admission_probe_expanded_latest.md- active/shadow/phrase-control reviewed examples are scored as competing prototypes, then reduced to
replaceorabstain - the frozen queue clears at
100.0%/100.0%/0/0 - active/shadow prototypes plus active-sense phrase guarding still leak
ball:005andmatch:005on the expanded full-v10read at97.9%/100.0%/2/0 - adding phrase-control examples as abstain prototypes clears the expanded full-
v10oracle read at100.0%/100.0%/0/0 - the canonical intake/evidence schema path now accepts
relation_type=phrase_control_example, thephrase_containmentrole, and explicitllm/external/internalsource types, with normalization still forcingruntime_publishable=false - the no-spend example-frame contract gate now makes both the positive fixture and old active-only failure explicit:
scripts/testing/semantic_llm_reviewed_example_frame_batch_en_es.pyscripts/testing/semantic_reverse_aux_example_frame_batch_en_es.pyscripts/testing/semantic_llm_example_frame_contract_en_es.pyscripts/testing/semantic_llm_example_frame_generation_plan_en_es.pyscripts/testing/semantic_llm_example_frame_generation_run_en_es.pyscripts/testing/semantic_example_frame_batch_merge_en_es.pyscripts/testing/semantic_llm_example_frame_generation_quality_gate_en_es.pydocs/test_outputs/semantic_llm_example_frame_contract_latest.mddocs/test_outputs/semantic_llm_example_frame_contract_required_latest.mddocs/test_outputs/semantic_llm_example_frame_contract_expanded_latest.mddocs/test_outputs/semantic_llm_example_frame_contract_overlap_latest.mddocs/test_outputs/semantic_reverse_aux_example_frame_contract_latest.mddocs/test_outputs/semantic_llm_example_frame_generation_plan_latest.mddocs/test_outputs/semantic_llm_example_frame_generation_run_latest.mddocs/test_outputs/semantic_llm_example_frame_generation_contract_latest.mddocs/test_outputs/semantic_llm_example_frame_generation_quality_gate_latest.md- the reviewed frozen fixture is contract-complete at
8 / 8families and the full-v10fixture is contract-complete at19 / 19families - the current overlap target batch remains a negative read with
0 / 6complete families because all six families lack shadow and phrase-control example rows - the real external reverse-aux batch remains a negative required-family read with
0 / 8complete families: active aux exists for all six target families, shadow aux exists for four, and phrase-control rows are absent - the missing-row generation plan is no-spend and exact:
1active example forplay,2shadow examples forplant/check, and8phrase-control examples, with prompt input limited to trigger text, active/shadow sense labels and glosses, and queue role/archetype/notes rather than reviewed case sentences or translation targets - the live missing-row generation run accepted and normalized
11 / 11rows, and the merged batch is structurally complete at8 / 8required families with24rows - the generated batch remains analysis-only because the quality gate rejects it: best containment-aware prototype config is
67.5%accuracy /31.2%recall /2harmful /11false abstains - the phrase-control ablation now separates the failure modes: broad semantic phrase prototypes put phrase-overreach pressure on
12active false-abstain rows and directly add2incremental false abstains beyond the active-guard baseline, while containment-gated phrase evidence creates0incremental false-abstains and2correct containment hits - the residual remediation planner now converts those containment-aware failures into
8no-spend requests:7active examples for the11false-abstain cases and1shadow example for the2harmfulreportcases - the residual source lane is now executed and filtered:
scripts/testing/semantic_llm_example_frame_leakage_audit_en_es.pydocs/test_outputs/semantic_llm_example_frame_remediation_run_latest.mddocs/test_outputs/semantic_llm_example_frame_leakage_audit_latest.mddocs/test_outputs/semantic_llm_example_frame_balanced_remediation_run_latest.mddocs/test_outputs/semantic_llm_example_frame_balanced_remediation_leakage_audit_latest.md- the first residual pass accepted
8 / 8rows and the second replayed/rekeyed pass accepted6 / 6; benchmark-leakage admission filtered out oneplantrow from each pass before merge
- the prototype probe now has a surface-POS guard:
docs/test_outputs/semantic_llm_example_frame_balanced_remediation_prototype_admission_probe_latest.mddocs/test_outputs/semantic_llm_example_frame_balanced_remediation_quality_gate_latest.md- the best generated-source config is now
prototype_reviewed_examples_surface_pos_rescue_guard - it keeps the UX binary and phrase-control containment-only, then uses local surface syntax to rescue noun-frame active cases and preempt verb-frame shadow cases
- it clears the prototype-quality gate at
95.0%accuracy /87.5%recall /0harmful /2false abstains with8 / 8required families complete
- the post-promotion-candidate plant source check is negative:
docs/test_outputs/semantic_llm_example_frame_balanced_remediation_generalization_probe_latest.mddocs/test_outputs/semantic_llm_example_frame_plant_remediation_plan_latest.mddocs/test_outputs/semantic_llm_example_frame_plant_remediation_leakage_audit_latest.mddocs/test_outputs/semantic_llm_example_frame_plant_remediation_v2_leakage_audit_latest.md- the full-
v10generalization read keeps the surface-POS guard at0harmful replacements, but recall outside the frozen queue is source-coverage-limited - the remediation planner now tracks the current best remediation guard and reduces the next source plan to
1activeplantrequest - both bounded live plant attempts were structurally accepted but rejected by canonical benchmark-leakage admission, so the quality-gate numbers do not improve beyond the prior
95.0%/87.5%/0/2
- the prototype-admission probe now consumes the normalized reviewed evidence batches directly, not only the sentence-veto dataset oracle path
- the prototype-admission probe also consumes the normalized reverse-aux evidence batch as a real external-source comparison and currently reads
67.5%accuracy /50.0%recall /5harmful /8false abstains
- next technical direction:
- source/insertion work before any further prompt spend
- prioritize competition-symmetric active/shadow example-frame sets rather than missing-row-only fills
- keep phrase-control examples as a first-class source requirement, but treat generated phrase examples as local containment patterns or separately gated abstain evidence rather than broad semantic competitors
- rerun the failure diagnostic, source/insertion probe, and prototype-admission probe as no-spend gates before reopening paid generation
- the live prompt runner now exists too:
scripts/testing/semantic_llm_prompt_bakeoff_en_es.py- it preserves immutable raw response bundles plus raw and normalized batch artifacts under
docs/test_outputs/experiments/semantic_llm_prompt_batches/
- the repo now also has a no-spend preflight surface:
scripts/testing/semantic_llm_prompt_preflight_en_es.pydocs/test_outputs/semantic_llm_prompt_preflight_latest.md- narrowed preflight command examples now preserve selected
--request-idfilters instead of relying only on request-count guards
- the repo now also has a no-spend cost-estimate surface:
scripts/testing/semantic_llm_prompt_cost_estimate_en_es.pydocs/test_outputs/semantic_llm_prompt_cost_estimate_latest.md
- the same runner now also has a no-spend replay rehearsal path:
docs/test_inputs/semantic_routing/semantic_prompt_replay_fixture_en_es_v10.jsondocs/test_outputs/semantic_llm_prompt_replay_latest.md
- the live runner now requires explicit
--execute-live - live spend is now also fail-closed on:
- exact selected-request-count declaration
- explicit pricing inputs
- explicit estimated cost ceiling
- live execution is now also resume-safe by explicit operator choice:
- each paid run is keyed by
--run-id - completed per-request outcomes are appended to a journal under
docs/test_outputs/experiments/semantic_llm_prompt_batches/ - reruns without
--resumeare rejected over an existing journal --resumereuses completed outcomes but refuses ambiguous started-without-outcome requests
- each paid run is keyed by
- the preflight artifact now prints a spend-capped live command template rather than an uncapped one
- so prompt bakeoff work is now a real preserved execution surface, not just a plan
- the replay rehearsal has already proven the core plumbing:
- one accepted request survives into raw, intake, and normalized artifacts
- one malformed request stays raw-only and is rejected
- one forced API failure is counted separately without corrupting the batch
- the current remaining blocker is downstream acceptance, not runner/quota plumbing:
- the Codex command shell still does not inherit
OPENAI_API_KEYautomatically, but the preflight artifact keeps the sourced-shell + repo-venv path explicit - the sourced-shell + repo-venv live path is now proven on both proxy and target batches
- latest target-overlap preflight volume was
3155heuristic input tokens and540heuristic expected output tokens - actual target-overlap usage was
2825input tokens and179output tokens
- the Codex command shell still does not inherit
- the shipped
- Before any rollout, the project still needs:
- active-sense provenance carried from rulegen into runtime-consumable metadata
- automatic sibling-shadow candidate mining and a small promotion policy
- phrase/idiom preemption as a separate lane from semantic veto
- runtime observability for why a replacement applied or abstained
- Evidence:
docs/developer/productization_lane3_feature_state_truth_inventory.mddocs/rulegen/semantic_routing_runtime_readiness.mddocs/rulegen/semantic_shadow_source_intake_plan.mddocs/rulegen/semantic_llm_prompt_bakeoff_plan.mddocs/rulegen/semantic_routing_publication_contract.mddocs/rulegen/rule_generation_technical.mddocs/architecture/extension_system_map.mddocs/guide/index.mddocs/srs/srs_roadmap.mdcore/lexishift_core/replacement/core.pycore/lexishift_core/persistence/storage.pycore/lexishift_core/helper/paths.pycore/lexishift_core/helper/rulegen_outputs.pycore/lexishift_core/helper/use_cases/runtime_diagnostics.pycore/lexishift_core/helper/use_cases/semantic_admission.pycore/lexishift_core/rulegen/semantic_publication.pyscripts/testing/semantic_llm_prompt_bakeoff_en_es.pyscripts/testing/semantic_llm_prompt_preflight_en_es.pyscripts/testing/semantic_llm_prompt_cost_estimate_en_es.pyscripts/testing/semantic_llm_prompt_downstream_en_es.pyscripts/testing/semantic_llm_prompt_failure_diagnostic_en_es.pyscripts/testing/semantic_llm_source_insertion_probe_en_es.pyscripts/testing/semantic_llm_prototype_admission_probe_en_es.pyscripts/testing/semantic_llm_reviewed_example_frame_batch_en_es.pyscripts/testing/semantic_llm_example_frame_contract_en_es.pycore/lexishift_core/rulegen/semantic_evidence.pydocs/test_inputs/semantic_routing/semantic_llm_intake_batch.schema.jsondocs/test_inputs/semantic_routing/semantic_evidence_batch.schema.jsoncore/lexishift_core/rulegen/semantic_shadow_inventory.pycore/lexishift_core/rulegen/semantic_shadow_frequency.pycore/lexishift_core/rulegen/semantic_shadow_embedding_bridge.pycore/lexishift_core/rulegen/semantic_routing_runtime_policy.pycore/lexishift_core/rulegen/semantic_routing_runtime_scoring.pycore/lexishift_core/rulegen/semantic_shadow_evaluation.pycore/lexishift_core/rulegen/semantic_shadow_representative_pruning.pyapps/chrome-extension/manifest.jsonapps/chrome-extension/content/processing/replacement_semantic_debug.jsapps/chrome-extension/content/processing/replacement_semantic_override.jsapps/chrome-extension/content/processing/replacements.jsapps/chrome-extension/content/runtime/rules/helper_rules_runtime.jsapps/chrome-extension/content/runtime/rules/active_rules_runtime.jsapps/chrome-extension/content/runtime/dom_scan/semantic_context.jsapps/chrome-extension/content/runtime/dom_scan/semantic_node_scheduler.jsapps/chrome-extension/content/runtime/dom_scan/semantic_performance_metrics.jsapps/chrome-extension/content/runtime/semantic/semantic_gate_batch.jsapps/chrome-extension/content/runtime/semantic/semantic_gate_summary.jsapps/chrome-extension/content/runtime/semantic/semantic_gate_runtime.jsapps/chrome-extension/content/runtime/semantic/semantic_request_context.jsapps/chrome-extension/content/runtime/dom_scan/text_node_processor.jsapps/chrome-extension/content/runtime/dom_scan_runtime.jsapps/chrome-extension/content/runtime/apply_runtime_actions.jsapps/chrome-extension/content/runtime/apply_settings_pipeline.jsapps/chrome-extension/content/runtime/diagnostics/apply_diagnostics_reporter.jsapps/chrome-extension/shared/settings/settings_defaults.jsapps/chrome-extension/shared/srs/srs_runtime_diagnostics.jsapps/chrome-extension/options.htmlapps/chrome-extension/options/controllers/srs/profile_runtime_controller.jsapps/chrome-extension/options/controllers/srs/actions/formatters.jsapps/chrome-extension/content_script.jscore/tests/helper/test_helper_engine.pycore/tests/dev/test_extension_helper_rule_confidence_contract.pycore/tests/dev/test_extension_srs_runtime_diagnostics_contract.pycore/tests/dev/test_extension_srs_action_formatters.pycore/tests/dev/test_extension_srs_settings_contract.pycore/tests/dev/test_extension_semantic_gate_runtime_contract.pycore/tests/dev/test_extension_text_node_processor_context_contract.pycore/tests/rulegen/test_semantic_shadow_frequency.pycore/tests/rulegen/test_semantic_shadow_embedding_bridge.pycore/tests/rulegen/test_semantic_routing_runtime_policy.pycore/tests/rulegen/test_semantic_routing_runtime_scoring.pycore/tests/rulegen/test_semantic_publication.pycore/tests/rulegen/test_semantic_shadow_inventory.pycore/tests/architecture/test_extension_structure.pycore/tests/rulegen/test_semantic_shadow_evaluation.pyscripts/testing/semantic_routing_sentence_veto_harness.pyscripts/testing/semantic_routing_sentence_veto_sweep.pyscripts/testing/semantic_routing_sentence_veto_support.pyscripts/testing/semantic_shadow_inventory_en_es.pyscripts/testing/semantic_shadow_inventory_triage_en_es.pyscripts/testing/semantic_shadow_policy_compare_en_es.pyscripts/testing/semantic_shadow_policy_gap_queue_en_es.pyscripts/testing/semantic_shadow_review_queue_en_es.pyscripts/testing/semantic_shadow_review_packet_en_es.pyscripts/testing/semantic_shadow_gold_proxy_en_es.pyscripts/testing/semantic_shadow_coverage_gap_en_es.pyscripts/testing/semantic_shadow_seed_compare_en_es.pyscripts/testing/semantic_shadow_embedding_bridge_sweep_en_es.pyscripts/testing/semantic_shadow_frequency_sweep_en_es.pyscripts/testing/semantic_shadow_representative_pruning_sweep_en_es.pyscripts/testing/semantic_shadow_veto_proxy_compare_en_es.pyscripts/testing/semantic_shadow_forward_seed_sweep_en_es.pyscripts/testing/semantic_shadow_experiment_matrix_en_es.pydocs/test_inputs/semantic_shadow_source_registry.jsondocs/test_outputs/semantic_shadow_inventory_en_es_latest.mddocs/test_outputs/semantic_shadow_inventory_triage_en_es_latest.mddocs/test_outputs/semantic_shadow_policy_compare_en_es_latest.mddocs/test_outputs/semantic_shadow_policy_gap_queue_en_es_latest.mddocs/test_outputs/semantic_shadow_review_packet_en_es_latest.mddocs/test_outputs/semantic_shadow_gold_proxy_en_es_latest.mddocs/test_outputs/semantic_shadow_coverage_gap_en_es_latest.mddocs/test_outputs/semantic_shadow_seed_compare_en_es_latest.mddocs/test_outputs/semantic_shadow_forward_seed_sweep_en_es_latest.mddocs/test_outputs/semantic_shadow_frequency_sweep_en_es_latest.mddocs/test_outputs/semantic_shadow_representative_pruning_sweep_en_es_latest.mddocs/test_outputs/semantic_shadow_experiment_matrix_en_es_latest.mddocs/test_outputs/semantic_shadow_veto_proxy_compare_en_es_latest.mddocs/test_outputs/semantic_routing_sentence_veto_latest.mddocs/test_outputs/semantic_routing_sentence_veto_sweep_latest.mddocs/test_outputs/semantic_routing_sentence_veto_sweep_sentence_transformer_latest.mddocs/test_outputs/semantic_routing_sentence_veto_sweep_sentence_transformer_all_minilm_l6_latest.mddocs/test_outputs/semantic_llm_prompt_downstream_latest.mddocs/test_outputs/semantic_llm_prompt_failure_diagnostic_latest.mddocs/test_outputs/semantic_llm_source_insertion_probe_latest.mddocs/test_outputs/semantic_llm_prototype_admission_probe_latest.mddocs/test_outputs/semantic_llm_prototype_admission_probe_expanded_latest.mddocs/test_outputs/semantic_llm_reviewed_example_frame_batch_latest.mddocs/test_outputs/semantic_llm_reviewed_example_frame_batch_expanded_latest.mddocs/test_outputs/semantic_llm_example_frame_contract_latest.mddocs/test_outputs/semantic_llm_example_frame_contract_expanded_latest.mddocs/test_outputs/semantic_llm_example_frame_contract_overlap_latest.md
- Known gaps:
- No LP default path emits a fully mined competition/shadow set yet.
- All current rulegen LPs can now emit stable active-pointer ids in
metadata.semantic_admission, but pointer strength differs by locator mode:en-es/en-de: source-sense provenance first, with translation-gloss fallbackde-en/es-en: deterministic translation-gloss locator (currently FreeDict-backed)en-ja: deterministic JMDict entry locator
en-escan now emitstatus=readyin the explicit helper-side broader-contextemitted_rule_siblingsPoC mode, but that is still narrower than true shadow promotion and should not be read as end-to-end runtime readiness or LP parity.- Helper publication can now generate a semantic inventory sidecar with pair capability summary, and
en-escan publish ready competition sets in that helper-side broader-context PoC, but current default output still does not include mined shadow sets or phrase-preemption inventory. - The first live
en-esshadow inventory artifact proves that broad sibling mining is feasible, but its current promoted-shadow preview is still too noisy to serve as a runtime blocker set. - The new sentence-level runtime-veto harness is still intentionally small and curated:
- only
en-esis covered today - only 8 ambiguity families / 40 rows are labeled
- thresholds from that dataset are not production-safe defaults
- current lexical best row is still dominated by false abstains, so model-choice and evidence-view work remain open
- the latest
v2model shortlist shows that better winner ranking does not automatically translate into a better replace gate
- only
- The first triage artifact shows that the stricter preview can eliminate zero-signal rows, but the remaining top-1 promotions are still mostly justified only by
same_pos_as_active, not by clearly benchmark-aligned competition evidence. - The first policy-comparison artifact makes the current algorithm tradeoff concrete:
same_pos_lenient_v1is broad but noisybenchmark_backed_v1and especiallycross_checked_v1are much cleaner, but probably too narrow to serve as the final default without more shadow evidence
- The newest active-trigger refinement made the provisional policy safer:
- bundled forward glosses can now supply active evidence for bare triggers like
takeandcatch - benchmark-only shadows are no longer rescued when the active side is completely empty
cross_checked_backoff_missing_active_v1now converges to the same promoted set ascross_checked_v1on the latesten-esartifacts
- bundled forward glosses can now supply active evidence for bare triggers like
- There is no phrase-preemption lane separated from semantic-veto serving.
- Two additional precision ideas now have negative
en-esresults on the current reviewed overlap proxy:- active-vs-shadow frequency-band similarity leaves the best row unchanged, with the sweep preferring
frequency_similarity_weight=0.0 - same-sense representative pruning by normalized
sense_labelplus POS also leaves the best row unchanged, with the sweep preferring pruningoff
- active-vs-shadow frequency-band similarity leaves the best row unchanged, with the sweep preferring
- Runtime decision policy now exists for helper-side semantic scoring and fallback outcomes, but rendered soft-affordance UX is still not productized:
- current browser DOM behavior applies only
replace abstainandsoft_affordanceboth keep the original text today- future work still needs a visible soft-affordance interaction and rollout policy
- current browser DOM behavior applies only
- Current encouraging semantic-routing benchmark results from prototype work should not be read as proof of fully automatic end-to-end sense discovery or runtime readiness.
POS Normalization
- Status:
implemented,default-on,verified - Last documented checkpoint:
2026-02-23 - Last verified:
2026-02-23phase-6 artifacts;2026-03-11code inspection - Default behavior:
- Seed extraction and word-package metadata carry raw and canonical POS.
- Rulegen pair modules can consume normalized POS metadata.
- Evidence:
docs/rulegen/pos_normalization_workstream.mdcore/lexishift_core/pos/normalization.pycore/lexishift_core/srs/seed.pycore/lexishift_core/rulegen/pairs/pos_utils.pydocs/test_outputs/phase6_pos_inventory/phase6_pos_probe_2026-02-23_final.jsondocs/test_outputs/phase6_pos_inventory/phase6_pos_inventory_2026-02-23_final.json
- Known gaps:
- Unknown POS inventory remains for
freq-de-default.sqliteandfreq-ja-bccwj.sqlite. - POS metadata is stronger than current downstream decision usage for both rulegen ranking and SRS growth.
- Unknown POS inventory remains for
SRS Set Planner Strategies
- Status:
frequency_bootstrap:implemented,default-on,verifiedprofile_bootstrap:implemented,verified;default-on=noprofile_growth:implemented,default-onfor refresh,verifiedadaptive_refresh:scaffolded
- Last documented checkpoint:
2026-06-02Options admission preview remains read-only but now returns a seed-controlled sampled subset from the planned active pool instead of the deterministic prefix, so repeated user-facing samples can vary while advanced diagnostics retain the full planned pool and seed.2026-05-27refresh admission defaults toprofile_growth, which reuses the profile-bootstrap utility model for ongoing growth while preserving refresh capacity, due-pressure, retention, POS, and lifecycle gates.profile_bootstrapstill uses a cappedreserved_topic_laneselector by default when requested, options initialize/admission preview request it with current profile context, the preference sanity report includes a deterministic strength/proficiency matrix, and the en-es calibration report compares ranked, full-pool weighted, top-k weighted, and reserved topic-lane admission shapes with expected-vs-observed reserved-lane topic counts. Refresh payloads now report realized preferred-topic share for selected new admissions, and the preference product-loop test derives expected post-feedback topic share from topic strength, the capped topic lane, and remaining eligible topic capacity, including sparse medicine/technology cases. Automatic post-feedback refresh now triggers the sameprofile_growthrefresh path only after helper-persisted feedback thresholds are met, and extension retry-only feedback flushes do not run the refresh check. The en-es topic taxonomy now recordsmvp_picker_visibility, the options-page topic chips exactly mirrorstrict_mvp_visible, and the dev admission lab surfaces beta/hidden/register visibility metadata without removing diagnostic scenarios. - Last verified:
2026-06-02focused helper admission-preview tests covering weighted and reserved-topic seeded preview sampling, plus state and changed-file gates. Earlier2026-05-27coverage included focused profile-growth refresh/helper/native-host/options tests, preference-shaped product-loop tests with derived strong/weaker/sparse post-feedback topic-share assertions, automatic refresh policy/state tests, extension feedback-sync auto-refresh contract tests, content-runtime/background bridge auto-refresh contract tests, options SRS bridge contract tests, profile-bootstrap reserved-topic-lane selector/helper/options tests, strict-MVP options topic-picker contract tests, taxonomy visibility validation, preference sanity artifact generation, en-es admission calibration artifact generation, SRS quality harness, doc-reference check, state audit, diff check, and changed-file gate. - Default behavior:
- No-strategy helper bootstrap execution remains frequency bootstrap.
- Options initialize and admission preview request
profile_bootstrap, which applies implemented normalization, scoring, diagnostics, a proficiency readiness multiplier, and capped reserved topic-lane selection over the frequency seed frontier before initial active selection. - Options admission preview sends a fresh seed per sample request and displays a sampled subset of the planned active pool; it does not initialize, persist, or publish SRS words.
- The ordinary options-page topic picker exposes only en-es taxonomy families
marked
mvp_picker_visibility=strict_mvp_visible; beta, hidden, legal-gated, and register families stay out of that picker while remaining available to diagnostics and the advanced manual-tag field. - The local SRS admission lab may create a temporary EN-ES Zipf-bridge augmented frequency DB from committed test artifacts plus installed Kaikki POS data; this is dev-lab-only and does not install, mutate, or promote a production frequency pack.
- The local SRS admission lab still lists all taxonomy families for internal sampling, but now labels strict-MVP, beta-hidden, source-hidden, register-hidden, and legal-gated visibility so diagnostic controls cannot be mistaken for tester-facing picker scope.
- The calibration report is preview-only, but the reserved topic-lane row now exercises the real profile-bootstrap selection policy and reports expected topic count/status from lane cap plus source capacity. Full-pool weighted sampling remains too diffuse as a direct topic-preference policy.
profile_growthis executable for refresh/growth admission intoS; it transforms the seed frontier through profile-aware scoring, applies the capped reserved topic-lane selector where relevant, and then uses the existing refresh admission gates before persistence/publication. When profile-growth diagnostics are active, refresh output includesselected_preferred_topicwith selected count, preferred-topic count, realized share, and preferred-topic lemmas.- Automatic post-feedback refresh is implemented as a trigger layer for
profile_growth: the extension runs a best-effortsrs_auto_refreshcheck after one or more feedback items successfully sync to the helper, and the helper persists per-profile/pair attempt state before running the normal refresh path. Retry-only feedback flushes do not run the refresh check. Content-runtime bridge contract coverage now verifies that synced feedback routes throughrecord_feedback, thensrs_auto_refresh, to the background native-messaging bridge with the expected profile-growth payload. Options bridge contract coverage verifies SRS initialize, plan, preview, and refresh actions route through the same background native-messaging bridge with the expected profile-aware payloads. profile_growthremains executable for the dedicated rebalance preview/apply lane.adaptive_refreshstill falls back to planning-only behavior.
- Evidence:
docs/srs/srs_set_planning_technical.mdcore/lexishift_core/srs/admission_features.pycore/lexishift_core/srs/profile_bootstrap.pycore/lexishift_core/srs/profile_bootstrap_support.pycore/lexishift_core/helper/use_cases/admission_preview.pycore/lexishift_core/helper/use_cases/refresh_set.pycore/lexishift_core/helper/use_cases/auto_refresh_set.pycore/lexishift_core/srs/auto_refresh.pycore/lexishift_core/srs/growth.pycore/lexishift_core/srs/set_planner.pycore/lexishift_core/srs/selector.pydocs/test_inputs/srs_topic_preference_taxonomy_en_es.jsonapps/chrome-extension/options.htmlscripts/dev/srs_admission_lab_server.pyscripts/dev/srs_admission_lab_static.htmlcore/lexishift_core/helper/use_cases/rebalance_set.pycore/tests/srs/test_profile_bootstrap.pycore/tests/srs/test_selector.pycore/tests/dev/test_srs_admission_lab_server.pycore/tests/srs/test_srs_set_planner.pycore/tests/srs/test_srs_growth.pycore/tests/srs/test_srs_auto_refresh.pycore/tests/srs/test_srs_preference_product_loop.pycore/tests/dev/test_extension_feedback_auto_refresh_bridge_contract.pycore/tests/dev/test_extension_options_srs_bridge_contract.pycore/tests/dev/test_extension_srs_settings_contract.pycore/tests/helper/test_helper_auto_refresh_set.pycore/tests/dev/test_extension_helper_feedback_sync_auto_refresh.pycore/tests/helper/test_helper_engine.pycore/tests/dev/test_srs_planner_strategy_contract.pycore/tests/dev/test_helper_translation_dict_entrypoints.pycore/tests/dev/test_extension_srs_maintenance_workflow_contract.pycore/tests/dev/test_srs_admission_preference_sanity.pycore/tests/dev/test_srs_admission_calibration_report_en_es.pycore/tests/dev/test_srs_topic_preference_taxonomy_en_es.pycore/tests/dev/test_srs_frequency_topic_coverage.pyscripts/testing/srs_admission_preference_sanity.pyscripts/testing/srs_admission_calibration_report_en_es.pydocs/test_outputs/srs_admission_calibration_en_es_latest.mdscripts/testing/srs_frequency_topic_coverage.pycore/lexishift_core/helper/use_cases/initialize_set.py
- Known gaps:
profile_growthuses explicit profile signals supplied at refresh time; it does not yet auto-recalibrate proficiency from conquered words.- Pair policy defaults are currently near-identical across active pairs.
core/lexishift_core/srs/profile_bootstrap.pyremains a structural hotspot and should be split in a later health pass rather than folded into admission-contract edits.
Browsing-Based SRS Admission
- Status:
scaffolded,verified;default-on=no - Last documented checkpoint:
2026-05-31active-rotation release now parks mature review words out of full active inventories before refresh capacity is calculated, and reset treats the helper signal queue as story-scoped lifecycle state; pair reset removes that pair’s feedback/exposure events and all-story reset removes the queue file. This extends the2026-05-27SRS lifecycle, active-budget, stale-unseen capacity, and manual refresh diagnostics update: browsing signal aggregation has an opt-in helper dev ingest path, persisted profile-scoped aggregate store, and hidden dev extension packet builder for replacement exposures; refresh admission also respects active suppression entries before admitting new lemmas; refresh responses include preview-only browsing diagnostics without changing actual neutral admission selection;Balancedpreview can now realize one browsing slot for small budgets when fractional signal pressure is high enough; helper/native-host can now write durableuser_blockedsuppression entries and mark existing SRS itemsdiscardedfor future discard/block flows; non-active lifecycle states are now excluded from active inventory, due selection, growth capacity, and rulegen publication; refresh capacity now uses the pair’s resolved active inventory after automatic active-rotation release rather than the smaller due-only subset or every lifecycle-active store row; options refresh output now surfaces active budget, stale-unseen capacity pressure, selected lemmas, and preview-only browsing comparison diagnostics for manual SRS testing - Last verified:
2026-05-31active-rotation release, inventory-scoped capacity, helper refresh parking, product-loop regression, and reset signal-queue cleanup tests extend lifecycle marker, inventory-scoped active-budget, automatic active-rotation release, stale-unseen capacity, manual refresh diagnostics, and active-inventory filtering tests, lifecycle-aware scheduler/growth/rulegen tests, admission suppression writer tests, reset suppression-metadata tests, fractional browsing-budget tests, SRS quality harness with seeded non-empty browsing preview, refresh-path browsing preview tests, refresh-suppression lifecycle guard tests, active-capacity refresh tests, extension packet-builder and offline helper/core research probe tests, focused helper/native-host browsing ingest tests, refreshed admission-lifecycle audit, and regenerated backend simulation artifact - Default behavior:
- No live browser capture is wired by default; the extension packet builder
only runs when hidden setting
srsBrowsingAdmissionSignalsEnabledis true. - No browsing signal changes actual SRS admission refresh yet.
- Manual refresh admission now filters active admission-suppression entries; this guards future browsing boost from re-admitting suppressed lemmas.
- Manual refresh capacity is capped by the pair’s resolved active inventory after automatic active-rotation release, not by every lifecycle-active store row and not only by currently due items. Due count remains a pressure signal that can pause admission when reviews are overloaded.
- Automatic active-rotation release runs during refresh only when the active inventory is already at or above the active-size target. It parks mature review items with at least four reviews and a next due date at least seven days in the future by removing them from active inventory while preserving their SRS store rows, history, lifecycle state, and future due date.
- The
srs_admission_suppresshelper/native-host route can write durableuser_blockedsuppression; when a matching SRS item already exists, it marks that itemlifecycle_state=discardedand removes it from active inventory. The options dashboard now uses this route for confirmed learner discard. SrsItemlifecycle markers currently supportactive,discarded, andcleared; non-active lifecycle states are filtered out of active-inventory fallback, stale-inventory resolution, scheduler due selection, refresh growth admission, and helper rulegen publication.srs_resetclears matching signal-queue feedback/exposure events and suppression metadata by default. A backendpreserve_lifecycle_metadataflag exists for a future confirmation UX that keeps durable discard/block metadata, but signal-queue events are story lifecycle data and are still reset.- The SRS feedback popup remains a review-feedback surface only; it does not expose a cooldown action.
- Manual refresh responses include preview-only browsing admission diagnostics for the same candidate pool and budget; the diagnostics do not affect the persisted refresh selection.
- Options refresh output displays active count, due count, capacity budget,
active zero-exposure/zero-feedback counts, stale-unseen active capacity,
final admission budget, selected lemmas, and neutral vs
Balanced/Strongbrowsing preview selections when available. - The preview uses fractional small-budget realization so
Balancedcan show one browsing lane when signal pressure is meaningful, while actual persisted admission remains neutral. - The helper ingest path requires explicit opt-in and stores bounded target lemma aggregates only; URLs, raw page text, HTML, and context text are ignored.
- The extension packet builder currently captures replacement exposures only, not arbitrary page words. It sanitizes observations before queueing helper packets.
- The current simulation uses a helper-persisted synthetic packet to prove
capping, pruning, suppression, and monotonic
Off/Balanced/Strongbrowsing-share behavior without mutating SRS items. - Topic preference, browsing admission, review scheduling, and page replacement are documented as separate product decisions; known/learned words must not become permanent unlimited page replacements by default.
- No live browser capture is wired by default; the extension packet builder
only runs when hidden setting
- Evidence:
docs/srs/srs_admission_lifecycle_current_state.mddocs/srs/srs_browsing_based_admission_plan.mdcore/lexishift_core/srs/browsing_admission.pycore/lexishift_core/srs/admission_refresh.pycore/lexishift_core/srs/active_rotation.pycore/lexishift_core/srs/growth.pycore/lexishift_core/srs/scheduler.pycore/lexishift_core/srs/store.pycore/lexishift_core/srs/inventory.pycore/lexishift_core/srs/store_ops.pycore/lexishift_core/srs/admission_suppression.pycore/lexishift_core/helper/use_cases/admission_suppression.pycore/lexishift_core/helper/use_cases/reset.pycore/lexishift_core/helper/use_cases/browsing_admission.pycore/lexishift_core/helper/use_cases/initialize_set.pycore/lexishift_core/helper/use_cases/refresh_set.pyapps/chrome-extension/options/controllers/srs/actions/refresh_result_formatter.jsapps/chrome-extension/options/controllers/srs/actions/formatters.jscore/lexishift_core/helper/rulegen.pycore/lexishift_core/helper/paths.pyscripts/helper/lexishift_native_host.pyscripts/helper/lexishift_helper.pyapps/chrome-extension/shared/helper/helper_client.jsapps/chrome-extension/shared/srs/srs_browsing_admission_signals.jsapps/chrome-extension/content/runtime/dom_scan/text_node_processor.jsscripts/testing/srs_browsing_admission_backend_simulation.pyscripts/testing/srs_browsing_admission_research_en_es.pydocs/test_outputs/srs_browsing_admission_backend_simulation_latest.mddocs/test_outputs/srs_browsing_admission_research_en_es_latest.mdcore/tests/srs/test_srs_admission_refresh.pycore/tests/srs/test_srs_active_rotation.pycore/tests/srs/test_srs_browsing_admission.pycore/tests/srs/test_srs_preference_product_loop.pycore/tests/srs/test_srs_growth.pycore/tests/srs/test_srs_scheduler.pycore/tests/srs/test_srs_store.pycore/tests/srs/test_srs_inventory.pycore/tests/srs/test_srs_store_ops.pycore/tests/helper/test_helper_admission_suppression.pycore/tests/helper/test_helper_browsing_admission.pycore/tests/helper/test_helper_engine.pycore/tests/helper/test_helper_rulegen.pycore/tests/dev/test_extension_srs_action_workflows.pycore/tests/dev/test_helper_browsing_admission_entrypoints.pycore/tests/dev/test_extension_browsing_admission_signals.pycore/tests/dev/test_srs_browsing_admission_research_en_es.py
- Known gaps:
- Broad live page-word capture remains unwired; only LexiShift replacement exposure batches can currently become dev browsing signals.
- Browsing aggregates are not yet consumed by production admission refresh.
- User-facing settings and reset/clear controls for browsing admission signals remain planned.
- A strict calendar-day quota ledger for repeated manual refreshes remains
planned if
max_new_items_per_daymust mean more than a per-refresh cap. - Restore/release/mastered lifecycle controls remain planned.
SRS Admitted Words Dashboard
- Status:
implemented,default-on,verifiedfor visibility plus local dashboard search/filter/sort/pagination, read-only published-rule summaries, capped on-demand rule details, and confirmed durable dashboard discard; restore/mastery/release controls remainplanned - Last documented checkpoint:
2026-06-02learner-facing dashboard wording pass keeps the stablequeuedmachine state but shows it asUpcoming, renames replacement observability toPage replacement, removes raw item ids from the normal advanced row view, and moves read-only row details away from a separateView/rule-details action into row interaction; extends the2026-05-31active-rotation capacity release and2026-05-27admitted-words dashboard replacement eligibility projection, bridge/control polish, options UI, local review controls, published-rule summaries/details, first durable lifecycle action, profile-bootstrap bridge coverage, and encounter-watch visibility: helper/native-host can list pair/profile SRS items, summarize active/queued/ due/removed states, surface active zero-exposure/zero-feedback watch counts, project which active rows are currently eligible for page replacement, persistadmitted_atfor newly admitted items, and expose scheduler/lifecycle details behind an advanced toggle in options; the dashboard can locally search/filter/sort already-loaded words with page-size controls, first/previous/next/last pagination, refresh metadata, disabled-state-aware clear filters, and Escape-to-clear search; rows show read-only published-rule counts/source previews and can load capped read-only rule details on demand; eligible rows can confirm Discard, which reusessrs_admission_suppresswithreason=user_blocked; focused helper coverage now verifies profile-bootstrap initialization through rule publication and dashboard listing - Last verified:
2026-06-02learner-facing dashboard wording and row-detail interaction tests, helper label tests, architecture script-order test, JS syntax checks, locale JSON parse checks, state audit, doc-reference check, and diff check; extends the2026-05-31active-rotation release helper, inventory-scoped admission capacity, helper refresh integration, and product-loop regression tests plus the2026-05-27admitted-at dashboard encounter diagnostics, replacement-eligibility dashboard projection, bridge/meta-control, rule-summary/detail, search/filter/sort/pagination, confirmed discard route, stale-unseen encounter-watch counters/rendering, and profile-bootstrap initialize-to-dashboard bridge tests; focused helper endpoint, native-host route, helper client/manager route, resource-budget audit, suppression writer tests, SRS quality harness encounter-watch scenario, changed-file gate, doc-reference check, state audit, and diff check remain part of the broader dashboard evidence chain - Default behavior:
- The options page exposes a Learning words dashboard for the selected profile and language pair.
- Refresh words calls
srs_items_list; the listing route is read-only and does not admit, schedule, publish, discard, clear, or restore items. - The default dashboard shows learner-facing counts and rows; advanced fields are hidden behind a toggle.
- Search, status filter, sort, clear-filter, page-size, and pagination controls reshape only the already-loaded dashboard payload. They do not call helper routes, mutate SRS state, or change admission/serving order.
- Changing search, status, sort, page size, or clearing filters resets the dashboard to page 1.
- The dashboard shows refresh metadata for the already-loaded payload, including loaded/viewed counts, active-inventory source, and published ruleset state. The refresh timestamp is anchored to the helper result, not local filter renders. Clear filters is disabled until search/status/sort are adjusted, and Escape clears the current search.
- The dashboard exposes first-order encounter-watch visibility through an
Unseensummary card, anEncounter watchmetadata row, and compact row notes for active words with zero exposure plus zero feedback, stale-unseen age, unknown admission age, or no enabled published rules. Newly admitted SRS items persistadmitted_at; legacy rows without it are treated as age unknown. These are diagnostics only and do not clear, release, or park words. - The dashboard exposes a read-only
Replacingsummary card, metadata count, and per-rowReplacinglabel derived from active inventory, due state, and enabled published-rule availability. This is observability only; runtime replacement decisions still live in the extension runtime gate. - Each row can show read-only published-rule count plus a capped source-phrase preview from the current helper-published ruleset artifact. Missing or unreadable rulesets do not block item listing.
- Profile-bootstrap initialization, helper-published rule outputs, active inventory, and dashboard list summaries share the same pair/profile helper state.
- Rows with published rules can load capped read-only details for that lemma
on demand through
srs_item_rule_details; the normal list payload remains compact. - Active status uses the same active-inventory resolver as helper SRS serving;
queued admitted words remain visible but not active, and are labeled
Upcomingin learner-facing UI. - Dashboard replacement observability is labeled
Page replacementin the user-facing UI. Internal payload fields namedservingremain unchanged. - Published rule details open from the row rather than a competing normal
Viewaction; Discard remains the only explicit row mutation. - The normal advanced row view omits raw item ids. Raw ids remain developer diagnostics, not learner-facing advanced information.
- When refresh finds the active inventory at or above the active-size target, lifecycle-active review words with at least four reviews and a next due date at least seven days in the future are automatically parked out of active inventory before capacity is calculated. Their SRS store rows and history are preserved, so this is not discard, deletion, or mastered lifecycle UX.
- Eligible words expose a confirmed Discard action. It durably blocks refresh
re-admission, marks existing SRS items
discarded, and removes active inventory membership through the existing helper suppression route. - Restore/mastered/release actions remain planned and must not be inferred from dashboard discard.
- Evidence:
docs/srs/srs_admitted_words_dashboard_plan.mddocs/srs/srs_admission_lifecycle_current_state.mddocs/srs/srs_schema.mdscripts/testing/srs_resource_budget_audit.pyscripts/testing/srs_resource_budget_audit_render.pyscripts/testing/srs_resource_budget_audit_time.pycore/lexishift_core/srs/store.pycore/lexishift_core/srs/store_ops.pycore/lexishift_core/srs/growth.pycore/lexishift_core/srs/admission_refresh.pycore/lexishift_core/srs/active_rotation.pycore/lexishift_core/helper/rulegen.pycore/lexishift_core/helper/use_cases/srs_items.pycore/lexishift_core/helper/engine.pyscripts/helper/lexishift_native_host.pyscripts/helper/lexishift_helper.pyapps/chrome-extension/options.htmlapps/chrome-extension/options.cssapps/chrome-extension/options/core/ui_manager.jsapps/chrome-extension/options/core/bootstrap/controller_graph_elements.jsapps/chrome-extension/shared/helper/helper_client.jsapps/chrome-extension/options/controllers/srs/actions_controller.jsapps/chrome-extension/options/controllers/srs/actions/workflows.jsapps/chrome-extension/options/core/helper/srs_set_methods.jsapps/chrome-extension/options/controllers/srs/actions/words_dashboard_model.jsapps/chrome-extension/options/controllers/srs/actions/words_dashboard_formatting.jsapps/chrome-extension/options/controllers/srs/actions/words_dashboard_renderer.jsapps/chrome-extension/options/controllers/srs/actions/words_dashboard_rule_details.jsapps/chrome-extension/options/controllers/srs/actions/words_dashboard_workflow.jsapps/chrome-extension/options/controllers/srs/actions/maintenance_workflow.jscore/tests/srs/test_srs_store.pycore/tests/srs/test_srs_store_ops.pycore/tests/srs/test_srs_growth.pycore/tests/srs/test_srs_admission_refresh.pycore/tests/srs/test_srs_active_rotation.pycore/tests/srs/test_srs_preference_product_loop.pycore/tests/helper/test_helper_srs_items.pycore/tests/helper/test_helper_admission_suppression.pycore/tests/dev/test_srs_resource_budget_audit.pycore/tests/dev/test_helper_browsing_admission_entrypoints.pycore/tests/dev/test_extension_helper_status_profile_contract.pycore/tests/dev/test_extension_srs_maintenance_workflow_contract.py
- Known gaps:
- Dashboard virtualization is not implemented.
- Deep per-word semantic metadata inspection and morphology variant inspection are not implemented.
- User actions for restore, clear, release, and mastered-state management are not implemented; current automatic parking is backend active-inventory capacity management only.
- The extension feedback popup remains review-feedback only.
SRS Word Info API And Quick Definition Popup
- Status:
implemented,default-on,verifiedfor the shared read-only word-info API, selected-profile Vocabulary Library page with active-pair selection, and built-inquick-definitionpopup module; cross-profile library enumeration and completed/ mastered lifecycle UX remain planned. - Last documented checkpoint:
2026-06-02selected-profile Vocabulary Library page with active-pair selection and selected-profile theme application extends the source-resolution and enriched popup checkpoint: helper/core can read a profile/pair/lemma word-info payload, native host exposesword_info_lookup, the extension helper client exposeslookupWordInfo, Options exposes aHelperManager.lookupWordInfoconvenience through the shared API wrapper, content/options loadshared/helper/word_info_api.js, and the content popup registersquick-definitionahead of script/history modules; Options links tolearning_dashboard.html, whose page controller resolves the active profile, lists active pairs for that profile, lists admitted words for the selected pair, applies the selected profile’s Options background/card-theme preferences, loads current-page definition previews, opens a detail panel, and reuses confirmed discard as its only mutation. - Last verified:
2026-06-02dedicated Vocabulary Library page pair-selector/theme-loading tests plus focused helper word-info tests, native-host route tests, helper-client/API contract tests, quick-definition popup render and registry tests, extension structure tests, JS syntax checks, and Python compile checks - Default behavior:
- The route is read-only and does not admit, refresh, schedule, publish, discard, or otherwise mutate SRS state.
- The helper returns compact learner-facing word info: normalized pair/profile fields, target display/lemma, POS where known, local glosses with optional safe sense details/examples, source phrase summaries, compact SRS presence/state, deterministic external dictionary links, and sanitized diagnostics.
- Compact gloss selection prefers unrestricted senses and the first dictionary POS group; restricted usage senses such as slang/vulgar/obsolete/derogatory entries are fallback-only when no unrestricted sense is available.
- Installed local lexical resources are the canonical gloss source. For
en-es, the route resolves Spanish-to-English translation/gloss packs through existing pair-resource capability/default-pack logic rather than extension-side filenames or paths. Manifestlesslanguage_packs/<pack-id>/main.sqlitepack roots are recognized so localwiktionary-es-eninstalls keep the intended Wiktionary-first priority over FreeDict fallback. - The extension API wrapper normalizes camelCase/snake_case request fields,
caches successful lookups for the current JS runtime session, and delegates
native messaging to
HelperClient.lookupWordInfo. - The content singleton is configured with the current helper client.
quick-definitionreceives the sharedLexiShift.wordInfoApicapability through the popup descriptor context and does not call native messaging or local storage directly. quick-definitionis default-on for all target languages through the popup module registry, renders first in the popup module stack, shows an immediate loading state, and then renders target display, POS when known, up to five local glosses with compact details/examples when available, and deterministic external dictionary links.quick-definitiondegrades to localized fallback text when the helper is unavailable, the request is invalid, or installed definition data is missing.- Options code can call
HelperManager.lookupWordInfo(...). - The active Vocabulary Practice card links directly to a dedicated
Vocabulary Library page instead of rendering an embedded dashboard. The page
is scoped to the selected/current profile, lets the learner select among
that profile’s active language pairs, uses the existing read-only
srs_items_listroute, reuses local dashboard search/status/sort semantics, applies the selected profile’s Options background/card-theme preferences, and loads definition/gloss previews only for the current page, capped at 25 rows per render. - The Vocabulary Library detail panel shows local definition/glosses, external dictionary links, page-replacement source phrases, and advanced scheduler/page-replacement details behind an Advanced toggle.
- The Vocabulary Library reuses confirmed dashboard discard as its only mutation; it does not implement restore, completed/mastered state, or cross-profile enumeration.
- Local filesystem paths are intentionally excluded from learner-facing payloads and diagnostics.
- Evidence:
docs/srs/srs_vocabulary_library_and_word_info_plan.mddocs/architecture/popup_modules_pattern.mdcore/lexishift_core/helper/use_cases/word_info.pycore/lexishift_core/helper/engine.pyscripts/helper/lexishift_native_host.pyapps/chrome-extension/shared/helper/helper_client.jsapps/chrome-extension/shared/helper/word_info_api.jsapps/chrome-extension/content/ui/popup_modules/quick_definition_module.jsapps/chrome-extension/content/ui/ui.jsapps/chrome-extension/shared/srs/popup_modules_registry.jsapps/chrome-extension/options/core/helper/srs_set_methods.jsapps/chrome-extension/content_script.jsapps/chrome-extension/manifest.jsonapps/chrome-extension/options.htmlapps/chrome-extension/learning_dashboard.htmlapps/chrome-extension/learning_dashboard.cssapps/chrome-extension/learning_dashboard_model.jsapps/chrome-extension/learning_dashboard_view.jsapps/chrome-extension/learning_dashboard_table.jsapps/chrome-extension/learning_dashboard_theme.jsapps/chrome-extension/learning_dashboard.jscore/tests/helper/test_helper_word_info.pycore/tests/dev/test_helper_browsing_admission_entrypoints.pycore/tests/dev/test_extension_helper_status_profile_contract.pycore/tests/dev/test_extension_quick_definition_popup_module.pycore/tests/dev/test_extension_learning_dashboard_page.pycore/tests/architecture/test_extension_structure.py
- Known gaps:
- Cross-profile Vocabulary Library enumeration is not implemented.
- Completed/mastered lifecycle UX is not implemented in the Vocabulary Library.
- Batch lookup for a page of library rows is not implemented.
- The normalized public popup module API remains target architecture; the current module uses the existing internal popup descriptor/context pattern.
- JMDict and future-pair provider behavior has a generic path but only
en-estranslation-pack lookup has focused production-style coverage in this slice.
Vocabulary Practice Options UX
- Status:
implemented,default-on,verifiedfor the selected-story shell, direct Vocabulary Library entry, sampling curtain, switch styling, proficiency slider presentation, lazy status output, guided new-story initialization modal, and helper-backed missing-language-data setup recovery, delete-story state cleanup, and existing-GUI resource-settings deep-link activation; full multi-story enumeration remainsplanned - Last documented checkpoint:
2026-06-02Options now links directly to the dedicated Vocabulary Library instead of embedding the admitted-words dashboard, the dedicated page lets the selected profile switch among active language pairs while applying the same selected-profile background/card-theme preferences as Options, and learning-word review feedback plus automatic new-word refresh are implicit always-on defaults rather than learner-facing toggles. Manual-ruleset replacement feedback is an internal compatibility flag and remains off/not exposed for MVP.2026-06-02learner-facing naming now presents the SRS-backed learning surface asVocabulary Practice, usespractice/learning wordscopy in setup, dashboard, preference-save, discard, and delete paths, localizes the updated extension/GUI strings across English, Japanese, Chinese, and German, and keeps internalsrs_*/story identifiers as implementation details for APIs, storage, diagnostics, and tests. This naming pass extends the2026-05-31delete-story state cleanup and the2026-05-28resource-readiness setup recovery, generic installed-data hint removal, visible SRS enable-switch removal, story-scoped delete-story copy, active story preference-save/restore, flattened Advanced cleanup, theme-aware practice surfaces, and section-order polish extend the guided-flow checkpoint: controls are grouped under a selected profile/pair story block, that block is collapsed by default to a pair summary plus right-aligned active badge, the visible next-word controls are grouped into clearer subsections without repeated explanatory copy or a redundant heading, topic controls render as a contained probability-priority chip panel, the proficiency estimate is a slider that preserves the unset stored state until the user changes it and shows the previous saved value with a restore action, active-size copy now uses learner-facing practice wording, active-story candidate search depth is hidden as a backing control while the setup flow still keeps it under advanced starting-size controls, source/target pair controls and the legacy initialize button remain as hidden backing DOM anchors rather than visible active-story controls, sampling now sits next to admission settings, the Vocabulary Library entry follows sampling, sampling curtains use compact title/subtitle/action summaries, tentative free-form topic tags and advanced challenge tuning are hidden, new-word preference edits require an explicit Save preferences action, helper/semantic technical status is not shown inside the active story surface, empty status panels appear only after content is written, display controls are reduced to an inline highlight-color control plus sound toggle in the normal story surface, the collapsedAdvancedsection contains only same-level user-tunable new-word timing thresholds plus the story-scoped delete action, the visible SRS enable switch and generic installed-data hint are removed because the guided initialization flow is the learner-facing enable/readiness path, manual active-word update/learning-word refresh actions are no longer shown in the ordinary story surface, guided setup now turns missing language-data preflight failures into an inline resource-readiness panel with learner-facing resource labels that can open the GUI Resource settings tab through the native helper with the pair added/focused in the persistent Learning Languages resource view and retry the same setup check; the Learning Languages pair cards promote app-managed downloads, hide per-resource manual file selection from the learner-facing path, include the required Kaikki/Wiktionarywiktionary-es-enresource for en-es, show catalog sizes and per-resource progress, route license-restrictedfreq-es-cdethrough a manual setup instruction dialog with provider-page access, a rights-confirmed local source import forspanish_lemmas20k.txt, and managed SQLite conversion instead of showing a false download-progress state or switching tabs, expose per-resource file-location reveal and uninstall actions for installed data, and confirm before removing a pair card from the Learning Languages list when any required resources for that pair are installed; Learning Languages pair and required-resource labels now resolve through the GUI locale catalog instead of hardcoded English plan labels, and GUI confirmation dialogs now route standard buttons such as Yes/No/Cancel/Close through the app locale catalog instead of relying on Qt’s untranslated standard-button text; Resource settings tabs now keep their tab/canvas backdrops transparent to preserve the loaded GUI theme, and the shared Settings tab container explicitly paints the active theme’s panel gradient before drawing any optional background image so transparent Resource tabs do not fall through to the Qt scroll viewport/default palette; section text hierarchy, buttons, cards, and tables style through active theme tokens with contrast-safe foreground fallback instead of inheriting dark Qt defaults, floating Resource-settings titles and descriptions are contrasted against the settings canvas/background token rather than a panel token and use slightly larger text hierarchy for image or dark backdrops, Learning Languages pair/resource-slot boxes use translucent theme-tinted frames so the corrected backdrop remains visible while the resource hierarchy stays readable, detailed resource tables use a theme-schemasurface_opacities.tablevalue with a 0.90 default so table surfaces preserve backdrop visibility without losing dense-row readability, and those tables use content-width columns with horizontal scrolling below their natural width while distributing surplus width into useful text columns instead of leaving a blank viewport gutter, and table-cell action buttons use a compact theme-aware cell-control style so Download/Select/Delete actions fit cleanly inside rows without looking like oversized form buttons; combo-box dropdown lists now own and style their actual popupQListViewplus view/viewport palette through the active theme tokens, and the popup list view is frameless with zero margins/spacing so dark native popup slivers do not show above or below language-pair/theme selectors; Vocabulary Practice cards, topic panels, curtains, and the Vocabulary Library entry use the same card-theme CSS variable path as the rest of Options, the dedicated Vocabulary Library applies the selected profile’s page background and card-theme preferences, and the start-new-story block opens a guided modal that defaults missing proficiency to an explicit beginner value, inherits the active profile without exposing a profile picker or profile-selection copy, starts each fresh setup opening with no topic chips selected, lets sampling persist draft preferences without activating the story, renders preview results as learner-facing word/topic cards with sanitized technical details behind a local Advanced disclosure, and reserves story activation for the initialize workflow. Successful delete-story handling now also clears the selected profile/pair story profile and signals, publishes runtimesrsEnabled: false, reloads the active profile, and hides the current story card when the loaded profile is inactive so the deleted story does not reappear after refresh. Repeated resource-settings deep-link opens now try the GUI single-instance activation channel first, so an already-running app is raised and moved to the pair-focused Resource settings state instead of spawning another instance; if no GUI is running, the native helper now prefers the installed macOSLexiShift.appbundle before falling back to the sourcemain.pydevelopment entrypoint, macOS fallback launch no longer requestsopen -n, and the resource catalog now carries byte-exact download totals for known large/Spanish resources so progress can remain determinate even when a server omitsContent-Length. Options startup now applies the selected profile’s card-theme and page backdrop immediately after synced settings load, before i18n/profile/helper refresh work, so profile visuals no longer wait behind the full background preview/status and page initialization path; the page-background manager also skips duplicate backdrop/image/position DOM writes so late background sync does not repaint the same already-applied visual state. - Last verified:
2026-06-02focused Vocabulary Library pair-selector/theme-loading/direct-link/implicit-feedback-auto-refresh tests plus resource-plan/manual-frequency-policy/native-app-launch checks now extend the setup-flow profile inheritance, clean-topic setup opening, sanitized preview diagnostics, preview-renderer update, and focused delete-story/resource-readiness/preference-save/bridge tests covering controller-graph construction order, collapsed selected-story markup, hidden active-story word-pool backing controls, initialization-only starting-word controls, hidden backing source/target/initialize controls, polished direct-library/sampling/inline display-feedback/Advanced markup and ordering, previous-proficiency restore binding, beginner-default setup proficiency, hidden inherited setup profile with no visible setup profile-selection copy, clean setup topic defaults, non-activating setup sampling, learner-facing sample preview cards with locally toggled advanced diagnostics and no printed local source paths, Vocabulary Practice theme-token CSS contract, explicit preference-save controls, right-aligned active-story badge, generalized empty preview hiding, lazy rulegen status output, hidden SRS enable backing control, removed generic installed-data copy, story-scoped delete-story copy, switch-styled visible toggles, hidden experimental topic tags, hidden advanced challenge tuning, proficiency slider markup, active-story technical-status removal, missing-resource setup panel markup/controller behavior, native-host pair-aware resource-settings launch routing, existing-GUI local activation, installed macOS app launch preference, macOS non--nfallback launch, GUI resource-tab activation routing, persistent Learning Languages pair card, learner-facing Learning Languages card localization, per-resource installed-data file-location reveal, requiredwiktionary-es-enpair resource plan coverage, built-infreq-es-cdemanual-download block, manual-only resource progress suppression, manual resource instruction dialog routing without tab switching, removed pair-card Add manually affordance, Learning Languages resource uninstall buttons and installed-resource remove confirmation, localized Learning Languages pair/resource labels plus recursive GUI i18n catalog-shape coverage and localized QMessageBox standard-button coverage, resource-tab theme-preserving transparent-canvas, contrast fallback, and table sizing coverage plus settings Resource intro-label readability and Settings tab-container base-paint coverage plus translucent Learning Languages card-frame coverage, resource-table opacity schema/default coverage, content-width horizontal-scroll table coverage, responsive surplus-width table coverage, compact table-cell action-button coverage, and combo-box popup view/palette/frame theme-style coverage, persisted selected-pair story deletion, inactive-profile current-card hiding, and delete-workflow UI reload after helper reset; download-total fallback/catalog tests; raw-sourcefreq-es-cdemanaged-import/default-picker/rights-confirmation tests; extension structure/i18n checks, doc-reference check, state audit, changed-file gate, and diff check pass. - Default behavior:
- The Options page still operates on the selected profile and selected source/target language pair; it does not yet enumerate every persisted SRS profile/pair store.
- The selected profile/pair practice controls render inside a practice-shaped block that is collapsed by default to the language-pair summary and active-pair badge; expanding it reveals grouped settings, a direct Vocabulary Library entry, sampling, and maintenance for the same visible journey. Inner practice surfaces, topic panels, and curtains use the Options card-theme CSS variable path instead of fixed beige surfaces.
- The active story does not repeat a generic explanatory sentence above its controls; the summary row carries the pair identity and active badge.
- The main Vocabulary Practice shell does not show generic installed-data copy; language-data readiness messaging should appear in setup, diagnostics, and actionable error/status states.
- If setup sampling or initialization is blocked because required
language-data resources are missing, the guided modal shows a
language-data panel with learner-facing missing resource labels, offers to
open the LexiShift GUI Resource settings tab via the native helper with the
pair added/focused in the persistent Learning Languages view, and keeps the
learner in the same setup flow for retry. That view offers app-managed
dictionary downloads for
wiktionary-es-en/freedict-es-en, displays byte-exact catalog download sizes and per-resource determinate progress when either the response or catalog has a known total, and offers file-location reveal for installed resources. License-restricted frequency resources such asfreq-es-cderemain required when the pair needs them, but the pair card opens a manual setup instruction dialog with provider-page access and local file import instead of starting an app-managed download or switching the user to the detailed Frequency packs tab. Forfreq-es-cde, selecting a licensedspanish_lemmas20k.txtsource confirms local-use rights, keeps the Import action disabled until the local-use confirmation checkbox is checked, starts the file picker in the user’s Downloads folder and preselects the expected source filename when present, stages a temporary copy, converts it into the managedfrequency_packs/freq-es-cde/main.sqliteartifact, writes manifest and provenance sidecars, deletes the staged copy, and leaves the user’s original file untouched. Manual external SQLite path selection also remains available in the detailed resource tabs for compatibility. When the GUI is already running, the native helper sends the pair-focused Resource settings activation message to that process instead of launching a second GUI instance; if no GUI is listening, it prefers launching the installed macOSLexiShift.appbundle before falling back to the source development entrypoint. The extension does not download or import packs directly; GUI resource management remains the app-owned source of truth for MVP. - Source/target language and legacy initialize controls are retained only as hidden backing controls for the current controller path; users change source/target language through the guided new-story modal instead of editing an already-created active story in place. The setup flow inherits the active profile through a hidden backing value and does not expose profile selection or profile-selection copy as a learner-facing step; setup persistence does not change the selected profile from modal state.
- The legacy SRS enable checkbox is retained only as a hidden backing control; users enable a story by completing guided initialization, not by toggling a standalone switch.
- Topic preferences are visible as probability-priority chips without an always-visible caveat in the active-story card; the one-time setup flow can still show pair-coverage context.
- Admission sampling renders one helper preview payload into two local views: a simple learner-facing list of sampled words with topic/general badges, and an Advanced details disclosure containing sanitized diagnostic text. Opening or closing the disclosure does not re-run sampling, and local source paths are not printed.
- Free-form advanced tags stay present in the DOM for compatibility but hidden from the main MVP surface.
- The proficiency estimate is presented as a slider with a current value and an explicit Save preferences action; the saved value appears as a Previous setting row with a restore action, and if no stored estimate exists, the slider remains visually neutral while the runtime save/preview path treats it as unset until the user moves it.
- The active story surface exposes a learner-facing active-practice size control by default. Vocabulary search range remains a hidden backing value for the current controller path and is only visible in the new-story setup flow under advanced starting-size controls. Starting-word count is hidden from already-created stories and remains visible only in the initialization flow.
- Advanced challenge tuning remains in the DOM for compatibility but is hidden from the active-story beta surface.
- Helper and sentence-fit technical status are not shown inside the active practice surface; runtime diagnostics remain in the bottom Advanced debug tools area.
- The admitted-words embedded dashboard is no longer a learner-facing Options surface. The story card links directly to the dedicated Vocabulary Library, which is ordered directly after new-word sampling and can switch among the selected profile’s active language pairs while rendering with that selected profile’s Options page background and card-theme preferences.
- New-word sampling remains non-mutating and is hidden until the sampling curtain is opened from its summary panel.
- Display controls include only word highlight color and feedback sound in an inline row. Learning-word review buttons and automatic new-word addition after feedback are always-on MVP defaults, and manual-ruleset replacement feedback remains off/reserved, so none of those three flags are exposed as learner-facing toggles.
- The collapsed active-practice
Advancedsection exposes new-word timing thresholds as same-level controls, followed byDelete Vocabulary Practice. The delete action uses the existing helper reset route but is presented and confirmed as deleting only the selected profile/language-pair story. On helper reset success, Options removes the selected pair’s persisted SRS profile and signal state for the selected profile, publishes runtimesrsEnabled: false, reloads the active profile, and hides the active-story card so the deleted story stays gone after refresh. Active-word update preview/apply and manual learning-word refresh remain backend/dev workflows, but they are not promoted in the ordinary learner Options surface. - Helper-backed initialize/refresh status output stays hidden until a message is available.
- The guided new-story modal uses the same underlying Options controls and helper workflows as the existing page path; it does not introduce a second SRS initialization implementation.
- Modal sampling is non-mutating with respect to SRS admission and persists visible preference settings before calling the existing admission preview.
- Modal initialization enables SRS for the selected story, persists visible settings, then calls the existing helper-backed initialize path.
- Browsing-based admission still has no promoted user-facing opt-in in this
story surface. The current implementation keeps the hidden
srsBrowsingAdmissionSignalsEnabledflag default-off until production admission actually consumes browsing aggregates.
- Evidence:
docs/srs/srs_story_based_options_flow_plan.mdapps/chrome-extension/options.htmlapps/chrome-extension/options.cssapps/chrome-extension/options/controllers/srs/story_flow_controller.jsapps/chrome-extension/options/controllers/srs/story_flow_resource_check.jsapps/chrome-extension/options/controllers/srs/story_flow_utils.jsapps/chrome-extension/options/controllers/srs/actions/delete_story_state.jsapps/chrome-extension/options/controllers/srs/actions/maintenance_workflow.jsapps/chrome-extension/options/controllers/srs/actions/shared.jsapps/chrome-extension/options/core/settings/srs_profile_methods.jsapps/chrome-extension/options/core/ui_manager.jsapps/chrome-extension/options/core/helper/base_methods.jsapps/chrome-extension/shared/helper/helper_client.jsscripts/helper/lexishift_native_host.pycore/lexishift_core/helper/gui_app_launch.pyapps/gui/src/main_runtime.pyapps/gui/src/main.pyapps/gui/src/settings_pair_resource_plan.pyapps/gui/src/settings_language_packs_pair_setup_mixin.pycore/tests/dev/test_extension_srs_settings_contract.pycore/tests/dev/test_extension_options_srs_bridge_contract.pycore/tests/dev/test_native_host_resource_settings.pyapps/gui/tests/test_pair_resource_plan.pyapps/gui/tests/test_main_runtime_activation.pyapps/gui/tests/test_settings_resources_tab.pyapps/gui/tests/test_main_settings_resource_persistence.py
- Known gaps:
- The Options page does not yet enumerate all persisted SRS profile/pair stores as separate story blocks.
- The guided modal is a first beta implementation; it is not yet a full multi-step wizard with separate pages or richer pair capability warnings.
- The technical size labels, advanced preview details, and diagnostic outputs have not had their focused product-copy pass.
Pair-Local Active Inventory
- Status:
implemented,default-on,verified - Last documented checkpoint:
2026-04-19active-inventory observability truth pass - Last verified:
2026-04-19targeted inventory-resolution tests plus current-truth doc sync - Default behavior:
- Each profile can persist pair-local
active_item_idspluslast_initialized_at,last_refreshed_at, andlast_rebalanced_at. - Inventory resolution is intentionally forgiving rather than fully authoritative:
- if the inventory file is missing or the pair has no entry, active ids fall back to store-derived membership
- if stored active ids are stale, missing ids are dropped during resolution instead of failing helper/runtime flows
- Helper initialize/refresh/rebalance/rulegen flows can backfill inventory metadata from store-derived membership when needed.
- Runtime diagnostics surfaces the current inventory view explicitly through
inventory_source, the timestamp fields, andinventory_store_missing_item_ids_count.
- Each profile can persist pair-local
- Evidence:
docs/developer/srs_admission_selective_port_sequence.mdcore/lexishift_core/srs/inventory.pycore/lexishift_core/helper/use_cases/initialize_set.pycore/lexishift_core/helper/use_cases/refresh_set.pycore/lexishift_core/helper/use_cases/rebalance_set.pycore/lexishift_core/helper/use_cases/rulegen_job.pycore/lexishift_core/helper/use_cases/runtime_diagnostics.pycore/tests/srs/test_srs_inventory.pycore/tests/helper/test_helper_engine.py
- Known gaps:
- There is still no dedicated drift-repair artifact or hard failure signal for stale inventory state; observability relies on diagnostics plus write-path backfill.
- Inventory should not be treated as stricter authority than the store until a stronger repair/reporting model is intentionally added.
Due-Aware SRS Serving
- Status:
implemented,default-on when capable,verified - Last documented checkpoint:
2026-05-26standard page replacement density update - Last verified:
2026-05-26settings-default contract, helper annotation test, extension runtime gate contract, replacement-selection page-budget contract, SRS quality harness, and regenerated SRS quality artifacts - Default behavior:
- Scheduler code builds a due queue from
next_due. - Helper rulegen annotates matching SRS rules with
metadata.rulegen.srsdue-state metadata plus scheduler load fields when available. - Helper publication paths may still publish the active/admitted inventory for the pair, not a separately materialized due subset.
- The extension SRS gate filters future-due helper SRS rules when due metadata is present.
- When page budgets, one-per-block, or non-adjacent load constraints are active, extension replacement selection prefers new, learning, or lower-stability due SRS items over mature or future-due SRS rows inside the limited replacement slots.
- Standard extension page-density defaults are explicit and conservative:
maxReplacementsPerPage = 20,maxReplacementsPerLemmaPerPage = 2,allowAdjacentReplacements = false, andmaxOnePerTextBlock = false. - Metadata-free cached helper rules remain active as a legacy compatibility fallback until regenerated.
- Scheduler code builds a due queue from
- Evidence:
docs/developer/productization_lane5_runtime_seam_inventory.mddocs/srs/srs_hybrid_model_technical.mdcore/lexishift_core/srs/scheduler.pycore/lexishift_core/helper/use_cases/initialize_set.pycore/lexishift_core/helper/use_cases/refresh_set.pycore/lexishift_core/helper/rulegen.pyapps/chrome-extension/shared/srs/srs_gate.jsscripts/testing/srs_quality_harness.pycore/tests/helper/test_helper_rulegen.pycore/tests/dev/test_extension_settings_defaults_contract.pycore/tests/dev/test_extension_replacements_contract.pycore/tests/dev/test_extension_srs_runtime_gate_contract.pycore/tests/dev/test_srs_quality_harness.pydocs/test_outputs/srs_quality_latest.json
- Known gaps:
- No dedicated due-only helper ruleset publication artifact is currently tracked here.
- Legacy metadata-free cached helper rules are intentionally permissive until the helper ruleset is regenerated.
- Browser/native E2E coverage for automatic feedback-triggered refresh remains open beyond helper policy/state tests.
0remains available as an explicit unlimited override for page and per-lemma replacement caps.- No durable mastered/released flag is fully implemented yet.
- Synthetic harness coverage remains pair-limited.
Extension-Side Confidence Gating For Helper Rules
- Status:
planned; live helper-rule runtime gating not implemented - Last documented checkpoint:
2026-04-18confidence-gating packet and current-truth doc correction - Last verified:
2026-04-18targeted runtime contract test plus code-path audit - Default behavior:
- Helper rulegen supports generation-time
confidence_thresholdfiltering before rules are emitted. - Current extension helper-rule runtime path does not inspect
rule.confidenceor apply a live helper-rule confidence threshold before SRS gating. - Extension selector utilities can still use item confidence for scoring in other contexts; that is not the helper-rule activation gate.
- Helper rulegen supports generation-time
- Evidence:
docs/developer/project_integrity_sp2_confidence_gating_packet.mddocs/rulegen/rule_generation_technical.mddocs/reference/glossary.mdcore/lexishift_core/rulegen/generation.pycore/lexishift_core/helper/use_cases/rulegen_job.pyapps/chrome-extension/content/runtime/rules/active_rules_runtime.jsapps/chrome-extension/shared/srs/srs_gate.jsapps/chrome-extension/shared/srs/srs_selector.jscore/tests/dev/test_extension_helper_rule_confidence_contract.py
- Known gaps:
- Treat runtime confidence gating as unresolved until a real settings surface, runtime code path, and tests exist for helper-published rules.
- Do not mark confidence gating as shipped based on docs alone.
Extension Controller / Runtime Workflow Contracts
- Status:
implemented,default-on,verified - Last documented checkpoint:
2026-04-21SP5/SP6 controller-runtime truth plus the SP7 Share Center compatibility-copy follow-up now keep the post-split options bootstrap, Share Center forwarding bridge, SRS maintenance workflows, and DOM-scan budget/order seams explicit in both architecture docs and operator-facing export copy - Last verified:
2026-04-21targeted Node-backed extension workflow tests, Share Center copy contract checks, structure checks, and state/doc safety checks - Default behavior:
- The options app bootstrap remains a hard dependency seam:
options.htmlscript order matters,options.jsfails fast when required bootstrap/controller modules are missing, and successful startup still binds events before page init. - Share Center owns the grouped file-export/file-import UX, but it is still a compatibility bridge over the legacy share backend rather than a second share-schema authority.
- Current Share Center compatibility mappings stay explicit:
Full profileexport forwards to legacyprofileProfile settingsexport forwards to legacysrs- export-modal and target-hint copy now say those are the existing profile / SRS settings formats rather than implying a narrower new schema
- import only triggers a hard reload when the imported scope mutates broader runtime state; ruleset/modules-only imports resync without reload
- SRS maintenance workflows forward the active planning/profile context into initialize/refresh/reset helper calls, keep reset double-confirmed, and only mark ruleset freshness when the returned action result actually warrants it.
- Content full-scan runtime seeds page-budget state from existing replacement spans, then deterministically redistributes node order by page/profile only when page-level budgets are active.
- The options app bootstrap remains a hard dependency seam:
- Evidence:
docs/developer/project_integrity_sp6_feature_state_refresh_packet.mddocs/architecture/options_controllers_architecture.mddocs/architecture/extension_system_map.mddocs/architecture/chrome_extension_technical.mdapps/chrome-extension/options.jsapps/chrome-extension/options/controllers/rules/share_center/workflows.jsapps/chrome-extension/options/controllers/srs/actions/maintenance_workflow.jsapps/chrome-extension/content/runtime/dom_scan_runtime.jscore/tests/architecture/test_extension_structure.pycore/tests/dev/test_extension_options_bootstrap_contract.pycore/tests/dev/test_extension_share_center_workflow_contract.pycore/tests/dev/test_extension_share_center_copy_contract.pycore/tests/dev/test_extension_srs_maintenance_workflow_contract.pycore/tests/dev/test_extension_dom_scan_runtime_contract.py
- Known gaps:
- Share Center copy now states the compatibility formats explicitly, but if product wants truly narrower
Profile settingsorFull profileexports later, that still needs an explicit new schema/version rather than a silent contract change. - This seam is now directly protected at the controller/runtime-contract level, but it is still not the same thing as a full browser E2E proof for storage mutation, native-helper latency, or rendered-page UX.
- Share Center copy now states the compatibility formats explicitly, but if product wants truly narrower
GenAI Workflow Architecture
- Status:
implemented,default-on,verified - Last documented checkpoint:
2026-03-11 - Last verified:
2026-03-12 - Default behavior:
- Use the rulegen quality loop already defined in
AGENTS.mdanddocs/developer/ai_workflow.md. - Use
docs/developer/genai_workflow_architecture.mdfor agent roles, instance splitting, and harness policy. - Use
scripts/testing/rulegen_auto_audit.pyfor dated plus latest rulegen audit runs when a change-aware wrapper is helpful.
- Use the rulegen quality loop already defined in
- Evidence:
docs/developer/genai_workflow_architecture.mdscripts/testing/rulegen_auto_audit.pyscripts/testing/rulegen_pair_audit_cycle.py
- Known gaps:
- Feature-state discipline is stronger now, but status transitions are not yet enforced against commit-scoped artifact diffs.
- Hosted CI still uses an explicit CI-safe build mode rather than full macOS GUI validation.
Current State Mismatches To Preserve Explicitly
These are not accidental wording issues. Keep them explicit until code and docs converge.
- Reverse-check is implemented but not yet default-on.
- SRS serving is now due-aware at the runtime gate when helper due metadata is present, but helper publication still uses the broader active/admitted inventory rather than a dedicated due-only artifact.
- Docs mention runtime confidence filtering, but the live helper-rule runtime still has no confidence gate after emission.