Skip to content

Context-aware ILO-P009 hints for ternary-brace misfires#508

Merged
danieljohnmorris merged 4 commits into
mainfrom
feature/ternary-parse-hint
May 21, 2026
Merged

Context-aware ILO-P009 hints for ternary-brace misfires#508
danieljohnmorris merged 4 commits into
mainfrom
feature/ternary-parse-hint

Conversation

@danieljohnmorris
Copy link
Copy Markdown
Collaborator

Summary

Two parser-diagnostic improvements on the ?-syntax family. Pending #5x and #6 in the assessment log, both tagged S, paired in one PR because they share a code path (the { token interception during prefix-ternary operand parse).

Manifesto framing: a bare ILO-P009 expected expression, got {`` is the worst kind of diagnostic for an LLM agent. No hint = no recovery path = a re-prompt that re-emits the same code (or worse, restructures and breaks something else). One persona run (cron-explainer) burned 167k tokens partly on this. All ten date/time personas tripped on the ?h cond{body} variant. This PR turns those into actionable one-line hints.

Repro before / after

?h x{0:1;_:2} (match-on-value shape):

Before:

ILO-P009 expected expression, got `{`

After:

ILO-P009 expected ternary operand, got `{` (looks like match-on-value arms)
  hint: match arms need a single bracketed subject. Drop `?h` and write `?x{<lit>:body; _:fallback}`;
        for a multi-token subject use `?(<expr>){...}`

?h ok{1} (three-form conditional confusion):

Before:

ILO-P009 expected expression, got `{`

After:

ILO-P009 expected ternary operand, got `{`
  hint: three conditional shapes: prefix-ternary `?h ok a b` (no braces),
        brace-ternary `ok{a}{b}` (no `?h`), braced-conditional `ok{body}`
        (no `?h`, single brace). Pick one

What's in the diff

Three commits:

  1. add context-aware ILO-P009 hint for ternary-brace misfires (src/parser/mod.rs, +93)
    • New prefix_ternary_brace_hint helper called from both statement (parse_match_stmt) and expression (parse_prefix_ternary) positions
    • Match-arm shape detected by peeking one token past { for <num>: or <text>:
    • First-operand source threaded through so the hint substitutes the condition the agent actually wrote
  2. test: cover ternary-brace hint shapes across both positions (tests/regression_ternary_brace_hint.rs, +151)
    • Six tests: match-arm fires + correct subject substitution, three-shape fires + does NOT misfire as match-arm, expr-position parity, canonical ?(expr){...} and ?h a b c still parse
  3. docs: add match-on-value example and conditional contrast in skill (examples/match-on-value.ilo, skills/ilo/ilo-language.md)

Test plan

  • cargo build --release --features cranelift clean
  • cargo test --release --features cranelift all green, 0 failures
  • cargo clippy --release --features cranelift --all-targets -- -D warnings clean
  • cargo fmt --check clean
  • Manual repros verify hint text for both shapes
  • Canonical ?(expr){...} and ?h cond a b still parse cleanly

Follow-ups

None blocking. The match-arm detector is intentionally conservative (one-token lookahead for <num>: or <text>:); pattern arms with ~v: / ^e: / _: deliberately do NOT trigger the match-on-value framing since those are Result/Option destructuring, not value-equality matches.

When the parser hits `{` mid prefix-ternary operand parse, emit one of
two hints instead of the bare "expected expression, got `{`":

1. Match-on-value shape (`?h x{0:1;_:2}`): the agent reached for
   Rust-style `match x { 0 => ..., _ => ... }` with a leading `?h`
   keyword. Hint funnels them to `?<oper>{...}` (single-token) or
   `?(<expr>){...}` (multi-token).

2. Three-form conditional confusion (`?h cond{body}`): the brace body
   is not a match arm. Hint enumerates all three canonical shapes,
   prefix-ternary `?h cond a b`, brace-ternary `cond{a}{b}`, and
   braced-conditional `cond{body}`, with the parsed condition
   substituted in so the agent can copy directly.

Match-arm shape is detected by peeking one token past the `{` for a
literal-and-colon pattern (`<num>: ...` or `"text": ...`). Pure
lookahead, no token consumption.

Hint fires in both statement (parse_match_stmt) and expression
(parse_prefix_ternary) positions so RHS-of-binding usage gets the
same diagnostic.
Six regression tests:

- match-arm shape fires the match-on-value hint and points at the
  parenthesised or single-token recovery form
- match-arm hint uses the parsed first operand as the suggested match
  subject (not the outer subject `h`)
- `?h cond{body}` fires the three-shape hint and does NOT misfire as
  match-on-value
- same shape in expr position (RHS of binding) gets the same hint
- canonical `?(<expr>){...}` and `?h cond a b` still parse cleanly

Parser-layer codes are front-end only, so VM exercises the same path
the tree and Cranelift engines would. No engine-specific assertions
needed.
examples/match-on-value.ilo pins the two shapes the new ILO-P009 hint
funnels agents toward: single-token `?subj{lit:body;...}` and
multi-token `?(<expr>){lit:body;...}`. The example is picked up by
the examples_engines test harness so it doubles as a higher-level
regression test for the canonical match forms.

skills/ilo/ilo-language.md gets a one-line conditional section
contrasting the three canonical shapes so the persona-side agent
spec mirrors what the hint suggests. Also notes the multi-token
match-subject paren form on the existing match line.
@codecov
Copy link
Copy Markdown

codecov Bot commented May 20, 2026

Codecov Report

❌ Patch coverage is 95.55556% with 2 lines in your changes missing coverage. Please review.
✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
src/parser/mod.rs 95.55% 2 Missing ⚠️

📢 Thoughts on this report? Let us know!

The conditional contrast addition pushed the file from 987 to 1096
tokens, over the per-module budget enforced by scripts/check-skill-
tokens.py. Drop the bool-conditional section, the three shapes are
already covered exhaustively in examples/conditional-shapes.ilo and
SPEC.md (section 'Conditionals and Guards'). Keep the multi-token
match-subject parens note since that's the canonical shape the new
ILO-P009 hint funnels agents toward, and a one-line callout next to
the match arms is the highest-value placement for it.

Final: ilo-language at 999 tokens, total 6789.
@danieljohnmorris danieljohnmorris merged commit a9baee4 into main May 21, 2026
5 checks passed
@danieljohnmorris danieljohnmorris deleted the feature/ternary-parse-hint branch May 21, 2026 08:27
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