Skip to content

fix: hint two-kebab-half subtraction in ILO-T004 (mandelbrot)#575

Merged
danieljohnmorris merged 4 commits into
mainfrom
fix/hyphen-id-v2
May 21, 2026
Merged

fix: hint two-kebab-half subtraction in ILO-T004 (mandelbrot)#575
danieljohnmorris merged 4 commits into
mainfrom
fix/hyphen-id-v2

Conversation

@danieljohnmorris
Copy link
Copy Markdown
Collaborator

Summary

Persona-reported: zr-sq - zi-sq written without spaces around the operator collapses to a single 4-segment ident zr-sq-zi-sq, surfacing as bare ILO-T004 with no hint. The mandelbrot dogfood persona hit this 2026-05-20 (#5aq).

The lexer is already correct: a-b is one ident, a - b (with spaces) is three tokens. The fix is purely diagnostic — when an unbound 3+ segment kebab ident splits uniquely into two halves that ARE bound, the verifier now suggests both the prefix form (- zr-sq zi-sq) and the infix-with-spaces form (zr-sq - zi-sq).

Repro before/after

Before:

$ ilo --text "f zr-sq:n zi-sq:n>n; - zr-sq-zi-sq 0" f
error[ILO-T004]: undefined variable 'zr-sq-zi-sq'
  --> 1:22
  |
1 | f zr-sq:n zi-sq:n>n; - zr-sq-zi-sq 0
  |                      ^^^^^^^^^^^^^^^
  = note: in function 'f'

After:

error[ILO-T004]: undefined variable 'zr-sq-zi-sq'
  --> 1:22
  ...
  = suggestion: 'zr-sq-zi-sq' is a single identifier (kebab-case); '-'
    between bound names never means subtraction unless surrounded by
    spaces. For subtraction write '- zr-sq zi-sq' (prefix form) or
    'zr-sq - zi-sq' (infix with spaces)

What's in the diff

  • c9aa5cc7 fix(verify): hint two-kebab-half subtraction in ILO-T004 — extends kebab_subtract_hint in src/verify.rs to scan binary split points for 3+ segment idents; fires when exactly one split yields two bound names. Falls back to the legacy "atomic clarification" only when ALL segments are also bound (ambiguous case). Three new cross-engine tests in tests/regression_kebab_precedence.rs cover the collision-no-spaces, bare-ref-position, and ambiguous-split-fallback paths.
  • 1c1225da test: pin the two-kebab-half subtraction case via examples_engines — adds a mandel zr-sq:n zi-sq:n>n;- zr-sq zi-sq line to examples/kebab-vs-subtract.ilo so the cross-engine examples harness exercises the canonical no-collision form on every engine.
  • 85e0b798 doc(spec): note hyphen-vs-subtraction whitespace rule — adds an explanatory paragraph in SPEC.md identifier-syntax section. ai.txt regenerated by build.rs.
  • 25570c34 chore: add b64/hex to SPEC reserved-names section — unrelated CI fix: regression_reserved_names_doc was failing on main since PR feature: crypto primitives - sha256, hmac-sha256, base64, hex, ct-eq (#5ag) #560 (crypto-primitives) added b64 / b64-dec / hex without updating the enumerated 3-char list. Included here so this branch passes CI; happy to split into its own PR if preferred.

Test plan

  • cargo test --release --features cranelift --test regression_kebab_precedence — 11/11 passing including 3 new tests
  • cargo test --release --features cranelift --test examples_engines — passes with new mandel line
  • cargo test --release --features cranelift --test regression_reserved_names_doc — passes after b64/hex addition
  • cargo fmt --check clean
  • cargo clippy --release --features cranelift --no-deps clean
  • full cargo test --release --features cranelift suite — passed (only fail before this PR was regression_reserved_names_doc, fixed by the chore commit)

Follow-ups

None. This is a contained diagnostic improvement plus the necessary doc-sync.

When an unbound 3+ segment kebab ident splits uniquely into two halves
that ARE bound, suggest the subtraction reading. Hit by mandelbrot
persona writing `zr-sq-zi-sq` with no spaces around the operator,
expecting it to parse as `(zr-sq) - (zi-sq)`. Pre-fix the verifier
emitted bare ILO-T004 with no hint (single segments unbound, levenshtein
distance > 3 too).

The 2-segment path now also requires both halves to resolve before
firing the existing hint, matching the new 3+ logic and dropping a
small false-positive case where only the legacy "all segments bound"
test gated.

Hint shows both prefix (`- zr-sq zi-sq`) and infix-with-spaces
(`zr-sq - zi-sq`) forms so the persona has two unambiguous canonical
spellings.
Adds a `mandel zr-sq:n zi-sq:n>n;- zr-sq zi-sq` line to the kebab-vs-
subtract example so the cross-engine examples harness exercises the
canonical "subtraction between two hyphenated names" form on every
engine. Comment block above it explains why the no-space form would
fail and points at the new diagnostic.
Pins the lexer's whitespace-sensitive disambiguation in the identifier-
syntax section: `a-b` is always one ident, `a - b` is subtraction.
Mentions the new two-kebab-half hint surfaced by ILO-T004 so agents
reading the spec see the canonical prefix and infix-with-spaces forms.

ai.txt regenerated by build.rs from SPEC.md.
regression_reserved_names_doc has been failing on main since the
crypto-primitives merge (PR #560 added b64 / b64-dec / hex without
updating the enumerated 3-char reserved list). Adds them so the test
goes green for any branch off main.

ai.txt regenerated.
@danieljohnmorris danieljohnmorris merged commit 8d0f745 into main May 21, 2026
1 of 4 checks passed
@danieljohnmorris danieljohnmorris deleted the fix/hyphen-id-v2 branch May 21, 2026 19:32
@codecov
Copy link
Copy Markdown

codecov Bot commented May 21, 2026

❌ 2 Tests Failed:

Tests completed Failed Passed Skipped
4743 2 4741 0
View the top 2 failed test(s) by shortest run time
ilo::examples_engines::examples_all_engines
Stack Traces | 7.76s run time
thread 'examples_all_engines' (42152) panicked at tests/examples_engines.rs:235:9:
9/1158 multi-engine example test(s) failed:

crypto-primitives.ilo [vm] (line 42): `ilo .../ilo/examples/crypto-primitives.ilo --vm sha-empty`
  FAILED (exit exit status: 101)
  stderr: thread 'main' (43400) panicked at src/vm/mod.rs:1887:13:
auto-unwrap on a non-Result tree-bridge builtin slipped past verify
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

crypto-primitives.ilo [vm] (line 44): `ilo .../ilo/examples/crypto-primitives.ilo --vm sha-abc`
  FAILED (exit exit status: 101)
  stderr: thread 'main' (43407) panicked at src/vm/mod.rs:1887:13:
auto-unwrap on a non-Result tree-bridge builtin slipped past verify
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

crypto-primitives.ilo [vm] (line 46): `ilo .../ilo/examples/crypto-primitives.ilo --vm hmac-rfc2`
  FAILED (exit exit status: 101)
  stderr: thread 'main' (43413) panicked at src/vm/mod.rs:1887:13:
auto-unwrap on a non-Result tree-bridge builtin slipped past verify
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

crypto-primitives.ilo [vm] (line 48): `ilo .../ilo/examples/crypto-primitives.ilo --vm b64-roundtrip`
  FAILED (exit exit status: 101)
  stderr: thread 'main' (43419) panicked at src/vm/mod.rs:1887:13:
auto-unwrap on a non-Result tree-bridge builtin slipped past verify
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

crypto-primitives.ilo [vm] (line 50): `ilo .../ilo/examples/crypto-primitives.ilo --vm b64-padded`
  FAILED (exit exit status: 101)
  stderr: thread 'main' (43425) panicked at src/vm/mod.rs:1887:13:
auto-unwrap on a non-Result tree-bridge builtin slipped past verify
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

crypto-primitives.ilo [vm] (line 52): `ilo .../ilo/examples/crypto-primitives.ilo --vm hex-abc`
  FAILED (exit exit status: 101)
  stderr: thread 'main' (43430) panicked at src/vm/mod.rs:1887:13:
auto-unwrap on a non-Result tree-bridge builtin slipped past verify
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

crypto-primitives.ilo [vm] (line 54): `ilo .../ilo/examples/crypto-primitives.ilo --vm ct-eq-yes`
  FAILED (exit exit status: 101)
  stderr: thread 'main' (43436) panicked at src/vm/mod.rs:1887:13:
auto-unwrap on a non-Result tree-bridge builtin slipped past verify
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

crypto-primitives.ilo [vm] (line 56): `ilo .../ilo/examples/crypto-primitives.ilo --vm ct-eq-no`
  FAILED (exit exit status: 101)
  stderr: thread 'main' (43441) panicked at src/vm/mod.rs:1887:13:
auto-unwrap on a non-Result tree-bridge builtin slipped past verify
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

crypto-primitives.ilo [vm] (line 58): `ilo .../ilo/examples/crypto-primitives.ilo --vm ct-eq-len`
  FAILED (exit exit status: 101)
  stderr: thread 'main' (43445) panicked at src/vm/mod.rs:1887:13:
auto-unwrap on a non-Result tree-bridge builtin slipped past verify
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
ilo::examples::examples
Stack Traces | 7.79s run time
thread 'examples' (42147) panicked at tests/examples.rs:158:9:
9/1172 example test(s) failed:

crypto-primitives.ilo (line 42): `ilo .../ilo/examples/crypto-primitives.ilo sha-empty`
  FAILED (exit exit status: 101)
  stderr: thread 'main' (43241) panicked at src/vm/mod.rs:1887:13:
auto-unwrap on a non-Result tree-bridge builtin slipped past verify
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

crypto-primitives.ilo (line 44): `ilo .../ilo/examples/crypto-primitives.ilo sha-abc`
  FAILED (exit exit status: 101)
  stderr: thread 'main' (43247) panicked at src/vm/mod.rs:1887:13:
auto-unwrap on a non-Result tree-bridge builtin slipped past verify
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

crypto-primitives.ilo (line 46): `ilo .../ilo/examples/crypto-primitives.ilo hmac-rfc2`
  FAILED (exit exit status: 101)
  stderr: thread 'main' (43253) panicked at src/vm/mod.rs:1887:13:
auto-unwrap on a non-Result tree-bridge builtin slipped past verify
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

crypto-primitives.ilo (line 48): `ilo .../ilo/examples/crypto-primitives.ilo b64-roundtrip`
  FAILED (exit exit status: 101)
  stderr: thread 'main' (43259) panicked at src/vm/mod.rs:1887:13:
auto-unwrap on a non-Result tree-bridge builtin slipped past verify
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

crypto-primitives.ilo (line 50): `ilo .../ilo/examples/crypto-primitives.ilo b64-padded`
  FAILED (exit exit status: 101)
  stderr: thread 'main' (43265) panicked at src/vm/mod.rs:1887:13:
auto-unwrap on a non-Result tree-bridge builtin slipped past verify
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

crypto-primitives.ilo (line 52): `ilo .../ilo/examples/crypto-primitives.ilo hex-abc`
  FAILED (exit exit status: 101)
  stderr: thread 'main' (43272) panicked at src/vm/mod.rs:1887:13:
auto-unwrap on a non-Result tree-bridge builtin slipped past verify
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

crypto-primitives.ilo (line 54): `ilo .../ilo/examples/crypto-primitives.ilo ct-eq-yes`
  FAILED (exit exit status: 101)
  stderr: thread 'main' (43279) panicked at src/vm/mod.rs:1887:13:
auto-unwrap on a non-Result tree-bridge builtin slipped past verify
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

crypto-primitives.ilo (line 56): `ilo .../ilo/examples/crypto-primitives.ilo ct-eq-no`
  FAILED (exit exit status: 101)
  stderr: thread 'main' (43286) panicked at src/vm/mod.rs:1887:13:
auto-unwrap on a non-Result tree-bridge builtin slipped past verify
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

crypto-primitives.ilo (line 58): `ilo .../ilo/examples/crypto-primitives.ilo ct-eq-len`
  FAILED (exit exit status: 101)
  stderr: thread 'main' (43292) panicked at src/vm/mod.rs:1887:13:
auto-unwrap on a non-Result tree-bridge builtin slipped past verify
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

To view more test analytics, go to the Test Analytics Dashboard
📋 Got 3 mins? Take this short survey to help us improve Test Analytics.

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