Skip to content

Add a conformance suite for HermitCrab, with its adequacy argument - #480

Open
johnml1135 wants to merge 53 commits into
masterfrom
integrate-conformance-framework
Open

johnml1135 wants to merge 53 commits into
masterfrom
integrate-conformance-framework

Conversation

@johnml1135

@johnml1135 johnml1135 commented Aug 19, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

This adds a conformance suite of synthetic HermitCrab grammars, with CI gates for parse results, coverage claims, and generated ledgers. This revision adds named parser-settings variants. The runner creates a fresh morpher for each run, applies its settings from constructor defaults, and compares complete parse-identity multisets and statuses against that run's expectations. A variant supplies the same ordered words as the default, with complete expectations of its own. Diagnostics name the variant; variants add no fixture or semantic-coverage credit.

Supported settings are DelReapps, MaxRoots, MakePartialsFinal, MergeAnalyses, and explicit per-call GuessRoots. The main review risk is accidentally claiming support for a setting an adapter cannot apply, or treating incomplete output as a valid empty result. Unsupported settings, missing rows, and zero-comparison variants fail; PanGloss also rejects capped or timed-out output.

  • PROTOCOL.md, the schema, and WordsYamlLoader: closed settings and strict structure; the loader also checks name uniqueness and ordered inputs.
  • WordsYamlMorpherSettingsTests: malformed and mismatched inputs, wrong variant expectations, and variants whose guesses leave no comparable rows.
  • Five selected fixtures exercise all supported settings; each engine compares all expected identities and statuses for every run.
  • Coverage credit and manifest fixture counts remain independent of variant runs.

No parser engine changed. MaxAlternatives remains unsupported because PanGloss does not implement HC's typed overflow behavior; MergeMSAs remains unsupported because it requires the FieldWorks project loader. MergeAnalyses currently verifies output preservation only; it does not measure merge-fold counts. The new C# and PanGloss contract is documented in Machine's variant protocol.

The PR targets master; review freshly fetched origin/master at 2f70c04698e13f7cf942e4245ae20d77de19ee5a (merge base a2f80e28debaffda8a65b3b11875c80479768bc7). Head: 184bcd46622571a06f1a1fdbdff2fb155714a1c6. The companion PanGloss adapter tested at e2627c9 is on feat/conformance-settings-variants.

Validation at the pinned head: local_check.sh --agent-strict passed; Release had 0 warnings/errors; HermitCrab 634 passed, SIL.Machine 887 passed / 3 skipped, Thot 93 passed, and SentencePiece 4 passed. All 72 C# runs across 62 fixtures passed. The selected five-fixture matrix passed 15/15 runs and 81 word-run rows in both C# HC and PanGloss. PanGloss harness tests: 53 passed; pinned parser tests: 117 passed / 10 marked skipped. The all-scope pin gate passed across 130 fixtures, 1,414 default words, and 10 variants, with three existing pathological/crash exclusions. Broader Rust workspace and Foma suites were not run; production parser engines are unchanged.

Oracle observations and verification detail

C# HC observations were collected on 2026-10-22 with harness draft 1836d23ccb86f1e9da123a43feb661ea76e85d0b, atop the then-current PR #480 head 72dbd4f9bd686d1193d11cf8f908d50ffa878ba1; the HC engine was unchanged. The assembly SHA-256 was 2547068882BEC56873F0678922D11D7F81ED4D68B3B99DCDB71EBF5863714444. The five measured fixture/settings pairs are deletion reapplications (DelReapps), compounding breadth (MaxRoots), final-template partial discriminators (MakePartialsFinal), final-template merge key (MergeAnalyses), and guess-roots settings (GuessRoots). Exact witness outputs and reproduction commands are in the durable observations.

The adapter matrix used the same five fixtures, each with its default plus two variants: 15 complete runs and 81 word-run rows per engine. C# self-check included pathological fixtures. PanGloss validation also included the managed pg-conformance-fixtures and pg-parse checks (both exit 0) and the 130-fixture pin gate. The C# coverage report passed with 31/31 constructs and 15 allowed dead rules. CSharpier checked the 23 changed C# files explicitly. The variant protocol forbids capped or timed-out output from matching an expected empty result; the PanGloss tests include that negative control.

Deferred suite work and prior stack notes

Deferred until after the Hermit Crab Optimizations release. Nothing stacks on this PR any more: #534, #540, #522 and #519 were retargeted to master, and #543 was closed. Their suite-side work is held back and will be added here when this resumes, each once its own PR has merged:

The earlier body also recorded these stack descriptions:

Suite review map

Where to look

  • .github/workflows/conformance.yml -- the gate. Runs on any change under src/SIL.Machine.Morphology.HermitCrab*, src/SIL.Machine, the HermitCrab tests or conformance/: self-check of every fixture, the coverage report, and a freshness check on the generated CSVs.
  • conformance/dead-rules-allowed.tsv -- the coverage report now exits 1 on a rule no word exercises unless it is listed here with a reason, and on a listed rule that is exercised again. Today: 15 entries, all deliberate (inactive decoys, refused controls, crash pins).
  • conformance/PROTOCOL.md -- the adapter contract a second engine implements.
  • src/SIL.Machine.Morphology.HermitCrab.Conformance/Runner.cs -- self-check: fixtures run in-process against HermitCrab as the oracle.
  • global.json -- new: pins the SDK to 10.0.100 with latestFeature roll-forward, for the whole repository.

Reading order

About 25k lines are harness code (src/SIL.Machine.Morphology.HermitCrab.Conformance) and 16k are its tests. The rest is data: fixtures (conformance/edge-cases, conformance/languages, about 21k), generated ledgers and evidence cards (about 28k), and docs. Generated files are rewritten by hc-conformance --write-* and pinned by tests, so they need checking for freshness, not reading line by line.

Earlier suite revision and validation decisions
  • Rebased onto master (be5407d).
  • Dropped Trace.FailureAllomorph: an engine API change does not belong in a test-suite PR, and Trace HermitCrab failure reasons and template slot outcomes #534 adds the same fact as Trace.Allomorph. Generated CSVs regenerate byte-identical without it.
  • The coverage report could not fail; it now gates dead rules and uncovered constructs.
  • ci.yml is back to master. Its added fixture run duplicated ConformanceFixtureGateTests under dotnet test, and parity-check.py's remaining check is now enforced by the coverage report.
  • The counterfactual sweep read mutant output in the console code page, so "katibɯd" came back as "katib?d" and a mutation that changed nothing looked like evidence. It now reads UTF-8 (CounterfactualGate, plus a regression test). Regenerating the ledger demoted two surfaces that had only that false evidence: Gloss to Unobservable and HeadFeatures to RequiredByDtd. The gap ratchet moves from 25 to 26 for Gloss.
  • local_check.sh ran --semantic-coverage, which exits 1 by design while the catalog is incomplete, so it could never pass. It now runs the same gates as conformance.yml.
  • chained-output-feature-override-loss said it fails on master on purpose. It has passed since Change Add to PriorityUnion #494; checked by running it at 52d069f (red) and 7109531 (green). The header now says so.
Earlier decisions, and why
  • PCRE.NET (now on master) ships an IIncrementalGenerator. The compilation-graph loader admits it only by content hash, and a probe runs it and fails closed on any generated output.
  • An expect_crash fixture passes only if the same engine completes an ordinary fixture in the same run, so a broken adapter command cannot pass as a crash (conformance/PROTOCOL.md).
  • *.fwdata is marked binary in .gitattributes; its pinned hash depended on core.autocrlf.
  • Hand-maintained fixture totals were removed from the README and docs; the manifest is the count.
  • Four fixture grammars keep trailing whitespace: their hashes are pinned in the manifest.

🤖 Generated with Claude Code


This change is Reviewable

@johnml1135
johnml1135 requested a review from ddaspit August 19, 2026 19:27
@johnml1135
johnml1135 force-pushed the integrate-conformance-framework branch from d826869 to 8f9dcea Compare August 19, 2026 19:46
@codecov-commenter

codecov-commenter commented Aug 20, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 74.93%. Comparing base (2599204) to head (fa8d9b2).

Additional details and impacted files
@@            Coverage Diff             @@
##           master     #480      +/-   ##
==========================================
+ Coverage   74.57%   74.93%   +0.36%     
==========================================
  Files         453      556     +103     
  Lines       38314    56481   +18167     
  Branches     5280     7714    +2434     
==========================================
+ Hits        28573    42325   +13752     
- Misses       8576    12291    +3715     
- Partials     1165     1865     +700     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@johnml1135
johnml1135 force-pushed the integrate-conformance-framework branch 2 times, most recently from d0b5448 to 9dfb2f6 Compare August 20, 2026 09:10
@johnml1135
johnml1135 force-pushed the integrate-conformance-framework branch 2 times, most recently from de95458 to 4823a05 Compare September 4, 2026 00:15
johnml1135 added a commit that referenced this pull request Sep 15, 2026
Introduces an engine-agnostic conformance suite for HermitCrab-formalism
morphological parsers: a `conformance/` tree of language grammars and
edge-case micro-grammars, each an HC-XML grammar.xml paired with a
words.yaml ground truth (oracle-provenance, gloss, and per-word parse
signatures). A new SIL.Machine.Morphology.HermitCrab.Conformance project
and hc-conformance CLI tool run those fixtures against an engine adapter,
producing coverage and rules CSVs, an interface inventory, dataflow-
obligation ledgers, evidence cards, a FieldWorks-producibility table, and
a JSON manifest for external consumers. PROTOCOL.md is the adapter
contract a second engine (e.g. the in-progress Rust port) implements to
plug into the same suite.

Includes the FieldWorks-producibility classification campaign: for every
HermitCrab construct the suite covers, a verdict on whether FieldWorks'
own HC-XML export path can actually produce a grammar exercising it,
distinguishing genuine data-model limits from mere loader gaps, with five
previously-unresolved verdicts now classified and corrected write-ups for
two more cases initially misread as exporter silence.

Also lands one new edge-case fixture,
edge-cases/chained-output-feature-override-loss, isolating an analysis-
side OutputHeadFeatures retraction bug: a well-formed four-morph parse of
`zudiua` that the founding C# oracle currently loses. The fixture is
deliberately red against hc.dll today (expected, not a broken test) and
documents the mechanism, provenance, and the HC-Rust divergence that
motivated it.

The suite is deliberately stopped at this point rather than finished:
scope, known gaps, and next steps are documented in the suite's own
tracking docs rather than left implicit.

This commit squashes the full conformance-suite branch stack
(integrate-conformance-framework through conformance/fieldworks-
witnesses, 49 commits) into one commit on top of current master, for
PR #480.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@johnml1135
johnml1135 force-pushed the integrate-conformance-framework branch from 4823a05 to 3128301 Compare September 15, 2026 12:29
johnml1135 added a commit that referenced this pull request Sep 15, 2026
Records a break-attempt run of PR #494 (AnalysisAffixProcessRule fix)
against the conformance suite: 36/36 fixtures pass (including
pathological cases), and a generated-word fuzz sweep (every root x
every 0..3-subset of affix rules, up to 6 nonhead roots where the
grammar compounds) produced ~1,300 words across 35 grammars, parsed by
both master and the PR branch with 0 divergences attributable to
PR #494. The one observed diff (edge-cases/truncate-morphotactic,
words `a`/`ga`) is pre-existing oracle nondeterminism in analysis
multiplicity ordering, reproducible on master alone, unrelated to the
syntactic FS change.

This was previously recorded only at tag archive/pr494-conformance;
folding it into the conformance suite's own PR (#480) so the evidence
travels with the suite it was run against. Fixed two references to
branches deleted since the doc was written (perf/pr494-conformance,
conformance/fieldworks-witnesses) to point at their preserved
archive/* tags instead; no other content changed.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@johnml1135

Copy link
Copy Markdown
Collaborator Author

Added two independently justified conformance fixtures in a20bce1: final-template-partial-discriminators (10 words; #507) and template-category-sharing (6 words; #505). Fresh Release build: zero warnings/errors. Both fixtures pass with memoization on and off, zero skipped; 22 focused manifest/coverage tests pass. Four grammar counterfactuals produce the independently predicted mismatches, documented under conformance/docs. These are grammar-sensitivity controls, not proof that pruning, cache hits, or same-key feature collisions execute. No parser code changed. Generated inventory also restores previously omitted rows for the already-existing Exact-inverse fixture; its valid zudiua loss remains tracked in #504, not relabeled as correct.

@johnml1135

Copy link
Copy Markdown
Collaborator Author

Added the shared-template unconstrained-suffix conformance fixture in f150e2a. The grammar has a slot-only feature-unconstrained suffix shared by mandatory TV/IV templates, an ordinary N-to-IV verbalizer, four positive rows, and six rejection controls. The companion rationale explains complete forward derivations and loader reachability (not a FieldWorks UI round trip).

Fresh C# harness: all 10 rows pass in both template orders, memoization on/off (40 comparisons; no skips). Focused template/manifest tests: 22 passed, no skips. Regenerated manifest is current at 40 fixtures; coverage/rule reports updated. No Machine parser code changed.

PanGloss main now contains the narrow gate-only alignment (fc357daf), with this fixture mirrored unchanged until its old Machine submodule pin is upgraded. Direct state assertions provide red/green evidence; full-parse fixture checks pass both before and after the change. Issue #505 remains open for collision/correlation and broader merge-equivalence evidence.

johnml1135 added a commit that referenced this pull request Sep 26, 2026
Introduces an engine-agnostic conformance suite for HermitCrab-formalism
morphological parsers: a `conformance/` tree of language grammars and
edge-case micro-grammars, each an HC-XML grammar.xml paired with a
words.yaml ground truth (oracle-provenance, gloss, and per-word parse
signatures). A new SIL.Machine.Morphology.HermitCrab.Conformance project
and hc-conformance CLI tool run those fixtures against an engine adapter,
producing coverage and rules CSVs, an interface inventory, dataflow-
obligation ledgers, evidence cards, a FieldWorks-producibility table, and
a JSON manifest for external consumers. PROTOCOL.md is the adapter
contract a second engine (e.g. the in-progress Rust port) implements to
plug into the same suite.

Includes the FieldWorks-producibility classification campaign: for every
HermitCrab construct the suite covers, a verdict on whether FieldWorks'
own HC-XML export path can actually produce a grammar exercising it,
distinguishing genuine data-model limits from mere loader gaps, with five
previously-unresolved verdicts now classified and corrected write-ups for
two more cases initially misread as exporter silence.

Also lands one new edge-case fixture,
edge-cases/chained-output-feature-override-loss, isolating an analysis-
side OutputHeadFeatures retraction bug: a well-formed four-morph parse of
`zudiua` that the founding C# oracle currently loses. The fixture is
deliberately red against hc.dll today (expected, not a broken test) and
documents the mechanism, provenance, and the HC-Rust divergence that
motivated it.

The suite is deliberately stopped at this point rather than finished:
scope, known gaps, and next steps are documented in the suite's own
tracking docs rather than left implicit.

This commit squashes the full conformance-suite branch stack
(integrate-conformance-framework through conformance/fieldworks-
witnesses, 49 commits) into one commit on top of current master, for
PR #480.

Folds in three review fixes: AdapterEngine's contract in MaterializedRunner
now credits an expect_crash fixture only once the same engine also
completes an ordinary fixture from the same run, so a misconfigured
adapter (bad path, rejected arguments) can no longer register as
reproducing the pinned crash; GuesserSignatureTests' batch-path test is
renamed for the overload it actually calls; and .gitattributes freezes
project.fwdata as binary so its pinned SHA-256 is reproducible across
platforms and CI runners, not just this one.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@johnml1135
johnml1135 force-pushed the integrate-conformance-framework branch from 93f470c to 2933fcc Compare September 26, 2026 02:55
johnml1135 added a commit that referenced this pull request Sep 26, 2026
Records a break-attempt run of PR #494 (AnalysisAffixProcessRule fix)
against the conformance suite: 36/36 fixtures pass (including
pathological cases), and a generated-word fuzz sweep (every root x
every 0..3-subset of affix rules, up to 6 nonhead roots where the
grammar compounds) produced ~1,300 words across 35 grammars, parsed by
both master and the PR branch with 0 divergences attributable to
PR #494. The one observed diff (edge-cases/truncate-morphotactic,
words `a`/`ga`) is pre-existing oracle nondeterminism in analysis
multiplicity ordering, reproducible on master alone, unrelated to the
syntactic FS change.

This was previously recorded only at tag archive/pr494-conformance;
folding it into the conformance suite's own PR (#480) so the evidence
travels with the suite it was run against. Fixed two references to
branches deleted since the doc was written (perf/pr494-conformance,
conformance/fieldworks-witnesses) to point at their preserved
archive/* tags instead; no other content changed.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
johnml1135 added a commit that referenced this pull request Sep 26, 2026
Introduces an engine-agnostic conformance suite for HermitCrab-formalism
morphological parsers: a `conformance/` tree of language grammars and
edge-case micro-grammars, each an HC-XML grammar.xml paired with a
words.yaml ground truth (oracle-provenance, gloss, and per-word parse
signatures). A new SIL.Machine.Morphology.HermitCrab.Conformance project
and hc-conformance CLI tool run those fixtures against an engine adapter,
producing coverage and rules CSVs, an interface inventory, dataflow-
obligation ledgers, evidence cards, a FieldWorks-producibility table, and
a JSON manifest for external consumers. PROTOCOL.md is the adapter
contract a second engine (e.g. the in-progress Rust port) implements to
plug into the same suite.

Includes the FieldWorks-producibility classification campaign: for every
HermitCrab construct the suite covers, a verdict on whether FieldWorks'
own HC-XML export path can actually produce a grammar exercising it,
distinguishing genuine data-model limits from mere loader gaps, with five
previously-unresolved verdicts now classified and corrected write-ups for
two more cases initially misread as exporter silence.

Also lands one new edge-case fixture,
edge-cases/chained-output-feature-override-loss, isolating an analysis-
side OutputHeadFeatures retraction bug: a well-formed four-morph parse of
`zudiua` that the founding C# oracle currently loses. The fixture is
deliberately red against hc.dll today (expected, not a broken test) and
documents the mechanism, provenance, and the HC-Rust divergence that
motivated it.

The suite is deliberately stopped at this point rather than finished:
scope, known gaps, and next steps are documented in the suite's own
tracking docs rather than left implicit.

This commit squashes the full conformance-suite branch stack
(integrate-conformance-framework through conformance/fieldworks-
witnesses, 49 commits) into one commit on top of current master, for
PR #480.

Folds in three review fixes: AdapterEngine's contract in MaterializedRunner
now credits an expect_crash fixture only once the same engine also
completes an ordinary fixture from the same run, so a misconfigured
adapter (bad path, rejected arguments) can no longer register as
reproducing the pinned crash; GuesserSignatureTests' batch-path test is
renamed for the overload it actually calls; and .gitattributes freezes
project.fwdata as binary so its pinned SHA-256 is reproducible across
platforms and CI runners, not just this one.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
johnml1135 added a commit that referenced this pull request Sep 26, 2026
Records a break-attempt run of PR #494 (AnalysisAffixProcessRule fix)
against the conformance suite: 36/36 fixtures pass (including
pathological cases), and a generated-word fuzz sweep (every root x
every 0..3-subset of affix rules, up to 6 nonhead roots where the
grammar compounds) produced ~1,300 words across 35 grammars, parsed by
both master and the PR branch with 0 divergences attributable to
PR #494. The one observed diff (edge-cases/truncate-morphotactic,
words `a`/`ga`) is pre-existing oracle nondeterminism in analysis
multiplicity ordering, reproducible on master alone, unrelated to the
syntactic FS change.

This was previously recorded only at tag archive/pr494-conformance;
folding it into the conformance suite's own PR (#480) so the evidence
travels with the suite it was run against. Fixed two references to
branches deleted since the doc was written (perf/pr494-conformance,
conformance/fieldworks-witnesses) to point at their preserved
archive/* tags instead; no other content changed.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@johnml1135
johnml1135 force-pushed the integrate-conformance-framework branch from 2933fcc to f412c25 Compare September 26, 2026 04:15
johnml1135 added a commit that referenced this pull request Sep 30, 2026
Introduces an engine-agnostic conformance suite for HermitCrab-formalism
morphological parsers: a `conformance/` tree of language grammars and
edge-case micro-grammars, each an HC-XML grammar.xml paired with a
words.yaml ground truth (oracle-provenance, gloss, and per-word parse
signatures). A new SIL.Machine.Morphology.HermitCrab.Conformance project
and hc-conformance CLI tool run those fixtures against an engine adapter,
producing coverage and rules CSVs, an interface inventory, dataflow-
obligation ledgers, evidence cards, a FieldWorks-producibility table, and
a JSON manifest for external consumers. PROTOCOL.md is the adapter
contract a second engine (e.g. the in-progress Rust port) implements to
plug into the same suite.

Includes the FieldWorks-producibility classification campaign: for every
HermitCrab construct the suite covers, a verdict on whether FieldWorks'
own HC-XML export path can actually produce a grammar exercising it,
distinguishing genuine data-model limits from mere loader gaps, with five
previously-unresolved verdicts now classified and corrected write-ups for
two more cases initially misread as exporter silence.

Also lands one new edge-case fixture,
edge-cases/chained-output-feature-override-loss, isolating an analysis-
side OutputHeadFeatures retraction bug: a well-formed four-morph parse of
`zudiua` that the founding C# oracle currently loses. The fixture is
deliberately red against hc.dll today (expected, not a broken test) and
documents the mechanism, provenance, and the HC-Rust divergence that
motivated it.

The suite is deliberately stopped at this point rather than finished:
scope, known gaps, and next steps are documented in the suite's own
tracking docs rather than left implicit.

This commit squashes the full conformance-suite branch stack
(integrate-conformance-framework through conformance/fieldworks-
witnesses, 49 commits) into one commit on top of current master, for
PR #480.

Folds in three review fixes: AdapterEngine's contract in MaterializedRunner
now credits an expect_crash fixture only once the same engine also
completes an ordinary fixture from the same run, so a misconfigured
adapter (bad path, rejected arguments) can no longer register as
reproducing the pinned crash; GuesserSignatureTests' batch-path test is
renamed for the overload it actually calls; and .gitattributes freezes
project.fwdata as binary so its pinned SHA-256 is reproducible across
platforms and CI runners, not just this one.

Also folds in the follow-up PR commits: fuzz/break-attempt evidence;
admitting PCRE.NET's source generator via a vetted content-hash allowlist;
final-template and template-sharing controls; oracle-verified fixtures for
per-piece environments, simultaneous mode and iterative epenthesis;
reduplication x phonology cases; and a regenerated manifest, ledgers and
evidence cards.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@johnml1135
johnml1135 force-pushed the integrate-conformance-framework branch from f412c25 to d8ff628 Compare September 30, 2026 20:29
Comment thread local_check.sh
Comment thread src/SIL.Machine.Morphology.HermitCrab.Conformance/Runner.cs Outdated
Comment thread src/SIL.Machine.Morphology.HermitCrab.Conformance/Runner.cs Outdated
Comment thread eng/HcRoslynCompilerReferences.props
johnml1135 and others added 16 commits October 26, 2026 07:44
The scratch word list went beside the grammar it was evaluated with,
which for a baseline is a fixture's grammar.xml. A killed sweep skips
the finally that deletes it and leaves an untracked file in the
checkout.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Graduate 67 shared fixtures and add two rule-order variants, bringing the corpus to
131 fixtures and 141 exact C# runs. Map exercises to canonical shared construct tags
while preserving PanGloss-specific capability extensions. Match rule traces as multisets
keyed by exact analysis signature and sorted distinct rule IDs; retain identity
multiplicity.

Add four measured ordering counterexamples and a named baseline of 32 open coverage
gaps. Six new gaps remain unresolved.

Validation: standard local_check passed; 26 focused primary tests passed; authoritative
C# self-check passed 141/141. Historical fixture whitespace retained to preserve
source evidence.
…reshness tests

blocked_by is asserted, not verified. The coverage report now fails when a
blocked_by label is not a rule id declared in that fixture's grammar, with unit
tests (a bogus label fails) and a gate test over every checked-in fixture. The
README, the CoverageReport doc and the FailureRuleAttributor doc now say
blocked_by is asserted and point to #552 for trace verification.

The two [Explicit] ledger freshness tests gain [Category("Counterfactual")] so
counterfactual-coverage.yml runs them. The engine-gate inventory was stale
(fixtures added since it was last written) and is regenerated.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ue a pruned final-template derivation

Issue 551 suspected that the lexical-entry half of Morpher.IsPartial protects parses
that the final-template prune (491) would reject, because a word inherits partiality
from its root and synthesis lets a non-partial rule follow a final template when the
input is partial. final-template-partial-root pins the opposite: SynthesisAffixTemplatesRule
skips every template for a partial root morpheme, so no final template ever applies to such
a word. Partial roots in a lower stratum and in the template's own stratum both have no
analysis for the final-template strings, with non-partial controls beside them.

The expected rows also pass in a scratch copy where Morpher.IsPartial ignores lexical
entries and the prune is therefore on for this grammar.

Ledgers, manifest and pinned counts regenerated. Regeneration also picks up fixtures
graduated in the previous commit whose ledger rows were stale, and records the one
resulting open gap: the simultaneous mutant of quantified-alpha-bounded-ltr-left does
not terminate.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Pin full parse multiplicity and application histories from combined Machine
#500 and #556 in three derivatives of the #480 truncation grammar. Update
fixture-derived coverage, interaction ledgers and their audit pins.

The original grammar is unchanged. The complete expectations intentionally
remain red on the conformance branch until both engine fixes are applied.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ds (F34)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
….yaml comment edit (F33)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@johnml1135
johnml1135 force-pushed the integrate-conformance-framework branch from 0bbb45c to ed5cf05 Compare October 26, 2026 12:13
@claude

This comment has been minimized.

johnml1135 and others added 4 commits October 26, 2026 13:24
…mplate gates

clitic-proclitic-after-final-template: a prefix clitic in the Clitics stratum attaches outside
a final template, while an ordinary prefix is refused after it and allowed before it.
clitic-enclitic-and-proclitic: a proclitic and an enclitic on one word, in either application order.
clitic-stem-entry: a clitic stem entry of the Clitics stratum needs no Morphology-stratum template,
takes Clitics-stratum rules and refuses Morphology-stratum rules.
clitic-flex-layout-blocking-morphology: a Morphology, Clitics, Surface layout whose Morphology
stratum has a phonological rule, so IsBlockingStratum resets the final-template state and an
isCliticRule=false rule may follow the template in the next stratum.
non-clitic-after-final-template-layout: the same layout without phonology, where the state carries
through the non-blocking strata and ordinary rules in Morphology, Clitics and Surface are refused.

Adds the construct "Clitics stratum: clitic designation by stratum name alone" so that words
relying on the stratum name are not claimed against the isCliticRule attribute.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…ticRule

Both template gates skip a clitic rule, so MorphologicalRule.isCliticRule feeds them as much as
AffixTemplate.final and MorphologicalRule.partial do. Severing isCliticRule flips 'sagdt' of
non-clitic-after-final-template-layout from no parse to a parse while its baseline trace names the
gate, which evidences the Blocked arm, and 'kolt' evidences the Control arm. The attributes that
were listed before cannot flip a word to a parse, because severing final falls back to the default
true and severing partial only makes a rule stricter.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…e five clitic fixtures

The corpus grows from 135 to 140 fixtures. The counterfactual and evidence ledgers keep their
Gloss, HeadFeatures and truncate-morphotactic rows from before: those fixtures yield different
engine output on every run while they wait on the truncation fix, and a fresh sweep turned that
noise into evidence rows.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@johnml1135

Copy link
Copy Markdown
Collaborator Author

Added five clitic conformance fixtures (all edge-cases/), each pinning one behaviour, plus ledger evidence for the final-template gate:

  • clitic-proclitic-after-final-template: a prefix clitic in the Clitics stratum attaches outside a final template; an ordinary prefix is refused after the template and allowed before it.
  • clitic-enclitic-and-proclitic: a proclitic and an enclitic on the same word, reachable in either order in the unordered Clitics stratum.
  • clitic-stem-entry: a clitic stem entry of the Clitics stratum needs no Morphology-stratum template, takes Clitics-stratum rules, and refuses Morphology-stratum rules.
  • clitic-flex-layout-blocking-morphology: FieldWorks layout (Morphology, Clitics, Surface) with a phonological rule in Morphology. That stratum is blocking, so the final-template state resets and an isCliticRule="false" rule may follow the template in the next stratum.
  • non-clitic-after-final-template-layout: the same layout without phonology. The state carries through the non-blocking strata, so ordinary rules in Morphology, Clitics and Surface are refused after the final template; nouns without a template are the controls.

NonPartialRuleProhibitedAfterFinalTemplate is now evidenced (Blocked: sagdt, Control: kolt). Severing final or partial can never flip a word to a parse, so I added MorphologicalRule.isCliticRule to the attributes feeding both template gates in EngineGateInventoryLedger. Manifest, coverage.csv/rules.csv, the ledgers and the pinned counts are regenerated (135 to 140 fixtures).

EveryConformanceFixturePassesSelfCheck still fails only on the truncate-morphotactic fixtures that wait on #556 (the four named above, plus truncate-morphotactic itself). Those fixtures give different engine output from run to run, so I kept their Gloss/HeadFeatures/ordering rows out of the counterfactual and evidence ledgers.

MorphologicalRule requiredPartsOfSpeech edge-cases/stem-name-restricted-root-allomorph Unobservable removed requiredPartsOfSpeech from 2 <MorphologicalRule> element(s) all 6 word(s) unchanged - - None -
MorphologicalRule requiredPartsOfSpeech edge-cases/strrep-identity Unobservable removed requiredPartsOfSpeech from 2 <MorphologicalRule> element(s) all 12 word(s) unchanged - - None -
MorphologicalRule requiredPartsOfSpeech edge-cases/template-category-sharing Unobservable removed requiredPartsOfSpeech from 4 <MorphologicalRule> element(s) all 6 word(s) unchanged - - None -
MorphologicalRule requiredPartsOfSpeech edge-cases/truncate-morphotactic Evidenced removed requiredPartsOfSpeech from 3 <MorphologicalRule> element(s) 'a': ok::++|a;++|a -> ok::++|a;+|a a ok::++|a;++|a Word ok::++|a;+|a

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor: F35. Five truncate-fixture rows flipped from Unobservable to Evidenced only because those fixtures give different output from run to run. Removing the interface had no effect. This row records 'a': ok::++|a;++|a -> ok::++|a;+|a. The -identity baseline for a at line 483 (A+ROOT+B;B+ROOT) is not the parse its words.yaml declares. The pins at InterfaceWitnessLedgerTests.cs:47-51 include these flips: evidenced +13 = 8 clitic + 5 truncate. A fresh recompute can therefore disagree. Leave the truncate fixtures out of this sweep until #556 merges, as you did for the counterfactual and evidence ledgers.

parses:
- signature: "KA|ka"
rules: []
exercises: ["Clitics stratum: clitic designation by stratum name alone"]

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FYI: F36. ka and kaz (line 41) are tagged as exercising "clitic designation by stratum name alone", but neither word depends on it. ka applies no rule. For kaz, no template applied before mrEnc, so IsLastAppliedRuleFinal is null and the gate in SynthesisAffixProcessRule.cs:63 cannot fire, clitic or not. Renaming the Clitics stratum would leave both words unchanged. Tag them with the construct they actually show (a stem rooted in a later stratum). Unverified by a run.

parses:
- signature: "SAG+PAST+ENC|sagdis"
rules: [mrPast, prEpenthesis, mrEnc]
exercises: ["Clitic rules (isCliticRule / Clitics stratum) after a final template"]

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FYI: F37. sagdis claims "Clitic rules (isCliticRule / Clitics stratum) after a final template", but mrEnc's clitic status cannot matter here. Morphology is blocking, so the final-template state is reset before the Clitics stratum, and sagdit shows the non-clitic mrNotClitic getting through in the same position. The note describes phonology feeding the next stratum, and that is what the tag should name.

@claude

claude Bot commented Oct 26, 2026

Copy link
Copy Markdown
Contributor

Request changes. Follow-up on ed5cf05. The branch moved forward by four commits (fast-forward). They add five clitic conformance fixtures, add MorphologicalRule.isCliticRule to the template-gate inventory, and regenerate the ledgers and pins. I reviewed ed5cf05..4a66977.

  1. Verdict: request changes. The conformance gate still fails at this head because of F32, whose code this round did not touch.
  2. Most important: F32, conformance/edge-cases/truncate-morphotactic/words.yaml:157. Four truncate fixtures still expect output that only the unmerged Fix a dropped morpheme ID when a zero-width rule wraps one ending at the same node #500 and Fix directional annotation tie boundaries #556 produce. New this round: F35, conformance/interface-witness.tsv:655. Those same fixtures, whose output changes from run to run, turned five ledger rows to Evidenced, and the pins now include them.
  3. Counts: 1 Critical open (F32). 1 Important new (F35). 2 Low new (F36, F37).
  4. Ran:
    • gh pr checks 480: both Conformance suite runs fail, and both Comment hygiene runs pass. Both Build jobs and claude-review are pending.
    • Locally, dotnet test tests/SIL.Machine.Morphology.HermitCrab.Tests -c Release filtered to the fixture gate, manifest and the six ledger test classes passed 66 of 67. The one failure is EveryConformanceFixturePassesSelfCheck, on truncate-morphotactic-copy-u, -identity and -subsumption only. All five new clitic fixtures pass.
    • /code-review high on the delta returned 9 candidates. Three are posted. The other six I dropped: a duplicate of F35, a kpsag tag that works as a negative control, pinned duplicate parses (a deliberate fixture convention), the evidence ledger choosing a multiplicity witness (selector code unchanged), a loosely worded gate-inventory comment, and Unmapped construct claims (651 rows already are).
    • I confirmed the F35 arithmetic: the new clitic fixtures contribute 8 Evidenced and 8 Unobservable rows, against a pinned +13 and +3.
  5. Could not verify: F36 rests on reading the code. I did not rename the Clitics stratum and rerun. I did not run ./local_check.sh --agent-strict or a fresh interface-witness recompute.

Public API, target framework, package, or sillsdev/machine.py parity: None verified.

Finding Severity Status
F1 Critical addressed (cc947db)
F2 Important addressed (bcb3d62)
F3 Important addressed (bcb3d62)
F4 Important accepted, unverified
F5 Low addressed (bcb3d62)
F6 Low addressed (067de6f)
F7 Low addressed (0a1212b)
F8 Low addressed (067de6f)
F9 Low addressed (067de6f)
F10 Important addressed (cd0c909)
F11 Low accepted, unverified
F12 Low addressed (cd0c909)
F13 Low addressed (0a1212b)
F14 Low addressed (0a1212b)
F15 Low addressed (067de6f)
F16 Low addressed (067de6f)
F17 Low addressed (0a1212b)
F18 Low addressed (0a1212b)
F19 Critical addressed (e7fe733)
F20 Low addressed (8b5d74e)
F21 Low addressed (1c5c3a5)
F22 Low addressed (a3b4c0e)
F23 Important addressed (49ba481)
F24 Important addressed (49ba481)
F25 Low addressed (9671b28)
F26 Low addressed (641f613)
F27 Low addressed (8b5d74e)
F28 Critical addressed (dd5f00f, 2cd68e8)
F29 Low addressed (bb42ff4)
F30 Low addressed (f592706)
F31 Low addressed (6c6fbb3)
F32 Critical open
F33 Low addressed (b9c7c8a, ed5cf05)
F34 Low addressed (382168a)
F35 Important new
F36 Low new, unverified
F37 Low new

Reviewed at 4a66977

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants