Skip to content

Port the Parlance 0.15.0 runtime contract: 207/207 vectors - #4

Merged
mwburke merged 2 commits into
mainfrom
claude/release-0-15-prep-mi2lm0
Sep 26, 2026
Merged

mwburke merged 2 commits into
mainfrom
claude/release-0-15-prep-mi2lm0

Conversation

@mwburke

@mwburke mwburke commented Sep 26, 2026

Copy link
Copy Markdown
Contributor

This ports the runtime to Parlance v0.15.0. conformance/PIN points to a3c6454, the commit v0.15.0 tags. All vendored vectors and schemas are byte-identical to parlance at that commit.

Runtime (Runtime/Runtime.cs)

  • One ResolveNode walk, shared by StepDialogue and AdvanceNode:
    • only an interstitial gated node is skipped (no choices, not isEnd);
    • a gated node that has choices or isEnd is returned with textHidden: true and text: "";
    • gates are judged once, on arrival.
  • StepResolvedNode(..., arrivalState) is the presenting half of the arrival sequence.
  • Choice partition:
    • a fallback is offered only when no other choice is visible;
    • lockedChoices uses whenLocked, then rules.choices.whenLockedDefault, then "hide", and interpolates lockedText.
  • ChooseChoice returns {error} ("not selectable") for a hidden or locked choice, or a fallback that isn't offered. This is the same error shape AdvanceNode uses.
  • Pass-through: node text is optional; node and choice tags pass through unchanged; engine is an explicit no-op.
  • Tests: ConformanceTests.cs always asserts lockedChoiceIds. It asserts text, textHidden, nodeTags and visibleChoiceTags whenever a vector states them, and handles expectedError for ChooseChoice.
  • README: fixed the usage example, which passed the project dict as the dialogue.

Verification

  • Local run: dotnet test with SDK 8.0.131, matching CI's 8.0.x, passed 11/11 families, 207/207 vectors.
  • Mutation check: I broke the new code eight ways, one at a time: no locked list, skip every gated node, show the hidden line, no fallback partition, textHidden always false, accept any choice, skip gated nodes that have choices, and an engine effect that changes state. Every one turned at least one family red.
  • CI: this repo's CI runs only on PRs into main, so this PR is its first CI run.
  • Not verified in a Unity editor: the new code uses C# 8. package.json already requires Unity 2021.3, which supports C# 8.

Merge once v0.15.0 is tagged at a3c6454.

🤖 Generated with Claude Code

https://claude.ai/code/session_018SVV6KXuhgbARyUvgQKbUP


Generated by Claude Code

…mmit

Parlance 0.15.0 changes how a runtime steps a dialogue, and a 0.14 port
handed a 0.15 shape plays it wrong with no error. This ports every runtime
item in MIGRATIONS.md 0.15.0:

- One ResolveNode skip walk, shared by StepDialogue and AdvanceNode. Only
  an interstitial gated node (no choices, not isEnd) is skipped. A gated
  node with choices or isEnd is returned, and its gate hides only the line.
  Both gates are judged once, on arrival, before onEnter.
- StepDialogue returns textHidden (with node.text "" when hidden) and
  lockedChoices: failing choices whose whenLocked resolves to "show"
  (choice, then rules.choices.whenLockedDefault, then "hide"), with text
  and lockedText interpolated. A text-less node stays text-less.
- The fallback partition: a fallback choice is offered only when no
  non-fallback choice passes. PartitionChoices is the one place this
  lives, and both StepDialogue and ChooseChoice read it.
- ChooseChoice returns an error containing "not selectable" for a hidden,
  locked or unoffered-fallback choice. It reports errors the same way
  AdvanceNode does.
- StepResolvedNode presents an already-resolved node. It takes an optional
  arrivalState for textHidden, for callers that apply onEnter between the
  resolve and the present steps of the arrival sequence.
- The engine effect leaves state unchanged, with an explicit case. Node
  and choice tags pass through untouched. AdvanceNode takes an optional
  project, as the reference does, so its skip walk evaluates gates
  against the project.

The harness now checks lockedChoiceIds on every step vector. It checks
nodeId, text, textHidden, nodeTags and visibleChoiceTags whenever a vector
states them. It handles expectedError for chooseChoice the same way it
does for advanceNode.

The changed vectors (step_dialogue 24, choose_choice 17, advance 14,
apply_effect 29, resolve_quests 7), the conformance README and the common,
dialogue and rules schemas are re-copied from parlance 440369d. The new
binding schema is added. The PIN names that commit as v0.15.0 pre-tag and
must move to the tag commit once v0.15.0 is tagged.

All 207 vectors pass locally with .NET SDK 8.0.131. Eight mutants each
turn at least one family red: no locked list, skip every gated node, show
the hidden line, no fallback partition, textHidden always false, choose
anything, skip gated choice nodes, and engine mutating state.

The README usage example passed the project dict as the dialogue and
omitted the project argument to ChooseChoice. Both are fixed, and the
usage now covers textHidden, lockedChoices and engine dispatch.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018SVV6KXuhgbARyUvgQKbUP
The contract is unchanged since the release-prep commit this port was
built against (440369d): every vendored vector and schema is byte-identical
to parlance at a3c6454, which v0.15.0 tags.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018SVV6KXuhgbARyUvgQKbUP
@mwburke
mwburke merged commit ceef0d4 into main Sep 26, 2026
1 check passed
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.

2 participants