Skip to content

Feat/jeg complete - #105

Merged
hyperpolymath merged 3 commits into
mainfrom
feat/jeg-complete
Jul 29, 2026
Merged

Feat/jeg complete#105
hyperpolymath merged 3 commits into
mainfrom
feat/jeg-complete

Conversation

@hyperpolymath

Copy link
Copy Markdown
Owner

Summary

Closes #

Type of change

  • 🐛 Bug fix (non-breaking change that fixes an issue)
  • ✨ New feature (non-breaking change that adds functionality)
  • 💥 Breaking change (would change existing behaviour)
  • 🕳️ Soundness fix (fixes a checker/proof false-negative)
  • 📖 Documentation
  • 🧹 Refactor / tech debt (behaviour-preserving)
  • ⚡ Performance
  • 🔧 Build / CI / tooling

How has this been verified?

Checklist

  • My commits are signed (git commit -S).
  • I ran the project's own checks/tests locally and they pass.
  • New files carry the correct SPDX-License-Identifier (code/config MPL-2.0,
    prose CC-BY-SA-4.0); I did not relicense existing files.
  • Docs are updated, and no public claim now overstates what the code does.
  • I have not introduced a soundness hole (or I have flagged where I might have).

Notes for reviewers

hyperpolymath and others added 3 commits July 29, 2026 08:18
`weave` performed no usage checking at all. It built the strand context,
checked the body, computed `Tangle[A,B]` — and discarded it, returning gamma
unchanged. Three unsound programs were accepted in silence:

    weave strands a, b into (a > a) yield strands a, b     # contraction
    weave strands a, b into (a > b) yield strands a, b, a  # contraction
    weave strands a, b into (a > b) yield strands a        # weakening

The spec already forbade the first (`i != j` on [T-Cross-Over]) and the third
("yield declarations match B"). Both side conditions were written down and
never enforced.

## Why a semiring and not "make the language linear"

The requirement is genuinely mixed, so a single discipline is the wrong answer
in both directions:

  * braid WORDS are unrestricted (omega) — `x . x` is sigma_1^2, a legitimate
    braid. Blanket linearity would reject valid programs.
  * STRANDS are linear (1) — a strand is a physical thread. A braid on n
    strands is a permutation of those n strands, so strand count is a
    conservation law. AFFINE is specifically wrong here: affine permits
    discarding, and a strand cannot vanish. That case is what decides it.
  * the CLAIM in `Epi[k, rho, tau]` is erased (0) — A-TG-11.1's recorded gap.

`compiler/lib/quantity.ml` provides {0, 1, omega} with add/mul/permits.
Independent uses combine with semiring addition, so two uses of one strand give
1 + 1 = omega, which is not permitted where 1 was declared.

## Applied in BOTH weave forms

Wiring the check into the weave STATEMENT rule alone left `def x = weave ...`
— the idiomatic spelling — entirely unchecked, because it reaches the weave
EXPRESSION rule and never touches the statement rule. The new conformance tier
caught this on its first run.

## Gating

New `conformance/ill-typed/` tier with a DOUBLE assertion: the file must PARSE
and then FAIL to typecheck. Asserting only "the compiler rejects it" is the
failure this suite already had once, when three invalid/ cases scored points
because the command was wrong and failed on every input. Requiring the parse
first proves the rejection came from the typechecker, not from a typo in the
fixture.

Wired into `scripts/check-corpus.sh` (what CI runs) as well as
`run_conformance.sh`, and verified with a negative control: making one
ill-typed fixture well-typed turns the gate red, restoring it turns it green.

`valid/` is now also required to TYPECHECK, not merely parse. All 16 already do.

## Verification

  * semiring laws checked EXHAUSTIVELY over all 27 triples — a "semiring"
    whose operations don't satisfy the laws is two arbitrary tables, and every
    soundness claim resting on it is worth nothing
  * 677 compiler tests pass (`dune runtest --force`)
  * conformance 23/23; 8/8 examples evaluate; stdlib typechecks
  * corpus + RSR gates green

Spec: new section 3.10.1 with the [T-Weave-Linear] rule and the quantity table.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Seventeen rules matched a `-> ()` arm in `check`. That is not a partial
check — it is an ACCEPT. A forged node naming T-Close, T-App or T-Weave could
conclude any type at all and the graph still checked green. Since the JEG's
whole claim is "evidence, not a log", those arms were the part that made the
claim false.

## What made them underivable, and the fix

Three of them (T-App, T-Crossing, T-Weave) genuinely could not be re-derived
from the recorded data, because the judgement did not carry what the rule
reads. So the judgement was widened:

  * `j_ctx` now holds `env_entry`, not `ty` — a T-App node cannot be checked
    without the callee's SIGNATURE.
  * `j_sigma` (new) holds the strand context — T-Crossing and T-Weave read
    Sigma rather than premise types. They were previously bare LEAVES:
    nodes asserting a type with nothing licensing it at all.

The rest were derivable all along and simply had not been written.

## Shared rule functions, so the JEG cannot drift

`infer_binop` was already a type-in/type-out function. The remaining rules
were inline in `infer_expr`, so the JEG would have had to RE-IMPLEMENT them —
and a JEG that re-implements the rules can drift from the typechecker, at
which point it certifies a rule the compiler does not apply and the evidence
is worthless.

Extracted 16 of them (`infer_close`, `infer_mirror`, `infer_echo_eq`,
`join_arm_ty`, ...) into one definition each, called by BOTH. Drift is now
impossible by construction rather than by discipline. The extraction is
behaviour-preserving: all pre-existing tests pass unchanged.

## Two rules with real substance

  * T-Let checks the conclusion is the BODY's type AND that the body was
    checked under the binding the let actually makes. Checking only the type
    would accept a derivation whose body silently assumed `x` had some more
    convenient type — there is a test for exactly that forgery.
  * T-Weave re-runs the strand LINEARITY check, so a graph cannot launder a
    weave that duplicates or drops a strand.

## The remaining hole is reported, not hidden

T-Add-Block's island has its own judgement (|-_hd). Rather than a silent
accept, it is recorded: new `unchecked : derivation -> (string * judgement)
list`. "check succeeded" and "check succeeded and re-derived every node" are
now distinguishable, and `--derive` prints which it was:

    == c ==  (3 nodes, depth 3, every node re-derived)

## Verification

  * JEG suite 19 -> 51 tests; an honest/forged PAIR for each rule closed, so
    each test's forged half is a case that would have PASSED before
  * 709 compiler tests pass (`dune runtest --force`)
  * conformance 23/23, corpus + RSR gates green

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@hyperpolymath
hyperpolymath merged commit f29e136 into main Jul 29, 2026
@hyperpolymath
hyperpolymath deleted the feat/jeg-complete branch July 29, 2026 07:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant