Skip to content

feat: make combo generation edge/stance aware with honest transition labels#45

Open
nazroll wants to merge 5 commits into
mainfrom
feat/physics-aware-edge-stance
Open

feat: make combo generation edge/stance aware with honest transition labels#45
nazroll wants to merge 5 commits into
mainfrom
feat/physics-aware-edge-stance

Conversation

@nazroll

@nazroll nazroll commented Jun 13, 2026

Copy link
Copy Markdown
Owner

Context

The README calls wzrdbrain a "physics-aware combo generator … so generated combinations are actually executable." A review found the implementation only enforced half of that: generate_combo matched on direction (always) and point (preferred), but edge and stance were resolved, stored, and emitted in the output yet never used to constrain move selection. Adjacent tricks contradicted each other ~57% (edge) and ~69% (stance) of the time.

What changed

  • Three-tier matching cascade in generate_combo: strict (direction + point + edge + stance) → mid (direction + point) → relaxed (direction only). Direction stays the one hard invariant; tiers widen only when needed, so combos never dead-end.
  • Honest transition annotation on every emitted trick (start / linked / edge_shift / reset) via a new _transition_type helper — the output now says where an implicit body adjustment is expected instead of silently contradicting itself.
  • Surfaced previously-dead fields: exit.lead_foot and exit.feet were parsed by Pydantic but never reached to_dict; they're now resolved on Trick and included.
  • Fixed a latent consecutive-duplicate case the narrower strict tier exposed: a tier is accepted only if it offers a non-repeat move.

Results

Measured over 5,000 × 5-trick combos (same seed), old vs. new:

Metric Old New Change
Direction mismatch 0.0% 0.0% unchanged (invariant)
Edge mismatch 57.2% 7.0% ↓ 50.2 pp
Stance mismatch 68.5% 12.1% ↓ 56.4 pp
Point mismatch 5.6% 5.8% ↑ 0.2 pp (noise)
Fully-continuous links 16.7% 84.5% ↑ 67.8 pp

On links tagged linked (84.5%), mismatch is 0% across all four dimensions. The residual edge/stance % is entirely on links now explicitly labeled edge_shift/reset.

Tests & tooling

  • New assertions in tests/test_wzrdbrain.py: test_strict_links_are_fully_continuous, test_strict_links_dominate, test_transition_field_values, test_to_dict_surfaces_lead_foot_and_feet.
  • tests/simulate_continuity.py — runnable continuity report.
  • tests/show_examples.py — runnable annotated example combos.
  • Docs updated from "two-tier" to the three-tier model (README.md, AGENTS.md, docs/moves_research.md).

All CI gates pass locally: ruff, black, mypy --strict, 31 pytest tests.

Note: wzrdbrain.js is auto-generated by CI from the Python source, so it is intentionally not hand-edited here.

🤖 Generated with Claude Code

@nazroll

nazroll commented Jun 16, 2026

Copy link
Copy Markdown
Owner Author

📝 Code Review Summary

I have reviewed the changes in PR #45 and verified the implementation of the three-tier physical state matching cascade:

  1. Python Implementation (src/wzrdbrain/wzrdbrain.py):

    • The three-tier candidate matching cascade successfully resolves physical continuity issues while guaranteeing no dead-ends.
    • Surfaced previously-omitted fields (exit_lead_foot and exit_feet) correctly.
    • Verified that all 31 pytest assertions, Ruff linting, Black formatting, and Mypy strict checks pass without issues.
  2. JS Translation Fixes (utils/translate2js.py & utils/wzrdbrain.base.js):

    • Updated the JSDoc/ES6 reference file wzrdbrain.base.js and the prompt configuration in translate2js.py to match the new three-tier cascade and transition annotation logic.
    • Triggered CI again using the updated GEMINI_API_KEY. The translate workflow completed successfully and automatically committed the new fully-compliant src/wzrdbrain/wzrdbrain.js to this branch.

All tests and CI checks are now green! The PR is ready for approval and merge.

@nazroll

nazroll commented Jun 16, 2026

Copy link
Copy Markdown
Owner Author

Pushed 8d532f1 addressing the review feedback:

Fix #1 — closure artifact (utils/wzrdbrain.base.js)
Replaced the pool => relaxed wrapper + typeof pool === "function" check with a plain for (const pool of [strict, mid, relaxed]). This matches the already-clean generated wzrdbrain.js, so no regeneration is needed.

Docs — "always returns exactly N tricks"
Softened the guarantee across AGENTS.md, docs/moves_research.md, and docs/usage.md to reflect the new explicit dead-end break (returns the partial combo when no direction-compatible continuation exists — never reachable with the current library, but the code path now exists). docs/usage.md had been missed entirely by the PR and still described the old two-tier matching; it's now updated to the three-tier cascade and documents the transition field.

All 31 pytest tests pass; node --check passes on base.js.

nazroll and others added 4 commits June 16, 2026 17:57
…labels

The generator resolved and emitted edge/stance/point but only ever matched on
direction (always) and point (preferred). Edge and stance were never used to
constrain selection, so adjacent tricks contradicted each other ~57% (edge) and
~69% (stance) of the time despite the "physics-aware" claim.

- generate_combo now uses a three-tier cascade: strict (direction + point + edge
  + stance) -> mid (direction + point) -> relaxed (direction only). Direction
  stays the one hard invariant; tiers widen only when needed, so combos never
  dead-end.
- Each emitted trick carries a transition annotation (start/linked/edge_shift/
  reset) describing how continuous its link is, so output never silently
  contradicts itself.
- Surface previously-dead exit.lead_foot and exit.feet in to_dict.
- Fix a latent consecutive-duplicate case the narrower strict tier exposed: a
  tier is accepted only if it offers a non-repeat move.

Result over 5000x5 combos: edge mismatch 57.2%->7.0%, stance 68.5%->12.1%,
fully-continuous links 16.7%->84.5%. On "linked" links, mismatch is 0% across
all dimensions.

Adds tests/simulate_continuity.py (continuity report) and tests/show_examples.py
(annotated example combos), plus assertions in test_wzrdbrain.py. Docs updated
from "two-tier" to the three-tier model.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Replace the `pool => relaxed` closure artifact in wzrdbrain.base.js with
  a plain `[strict, mid, relaxed]` loop (matches the generated wzrdbrain.js).
- Correct the "always returns exactly N tricks" claim across docs to reflect
  the partial-combo dead-end path; update docs/usage.md, which still described
  the old two-tier matching, to the three-tier cascade + transition field.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@nazroll nazroll force-pushed the feat/physics-aware-edge-stance branch from 8d532f1 to 77be4cd Compare June 16, 2026 15:58
@nazroll

nazroll commented Jun 16, 2026

Copy link
Copy Markdown
Owner Author

Rebased onto main after #44 merged. Resolved the expected conflict in generate_combo's worst-case fallback by combining both fixes: it now prefers a non-repeat candidate (from this PR) and keeps the absolute 2-slide hard cap (from #44):

# Absolute worst-case fallback, should rarely be hit given the library size.
# Prefer a non-repeat, but keep the 2-slide hard cap absolute even here.
candidates = [m for m in relaxed if m.id != last_id] or relaxed
if (
    len(combo) >= 2
    and MOVES[combo[-1].move_id].category == "slide"
    and MOVES[combo[-2].move_id].category == "slide"
):
    candidates = [m for m in candidates if m.category != "slide"]

Both PRs' test sets merged cleanly (34 tests total). The generated wzrdbrain.js conflict was resolved by taking this branch's version; CI will regenerate it from the merged Python on merge.

Quality gate: ruff ✅ · black ✅ · mypy --strict ✅ · pytest 34/34 ✅

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