Skip to content

feat: serve structured rule content and grade with program-calls (ADR-0024) - #625

Merged
Teakowa merged 7 commits into
mainfrom
feat/rules-content
Oct 11, 2026
Merged

Teakowa merged 7 commits into
mainfrom
feat/rules-content

Conversation

@e54-bot

@e54-bot e54-bot commented Oct 11, 2026 •

Copy link
Copy Markdown
Collaborator

Closes #624.

Implements the Wright side of ADR-0024.

Changed

  • rules gains content and rule: with content, each selected rule carries the workshop-rs/rule-content-v1 document plus statement spans; default bound of 20 rules, always selection-wrapped; rule selects exactly one. OverPy results report unavailable: {"names": "opy-rs"}.
  • wright inspect rules --content/--rule/--only/--file/--max; agent schema (including the unavailable member), agent-contract.md, CLI docs, and the MCP tool description updated.
  • Selection correctness: rules.rule by numeric id joins cfg's stale-id refusal after a reload; an unmatched name reports invalid-selection like other selection fields; a duplicate name keeps the ambiguous-rule refusal cfg gives.
  • Benchmark program-calls check kind (catalog id + positional argument patterns), unavailable on a Wright without rule content, read content cached by (source, maxRules); Proximity-repel fixtures (OverPy, en-US, zh-CN) and a one-short-stun negative.
  • workshop-rs 1.12.0 -> 1.16.0.
  • Metrics baseline: overwatch-ai-pve re-baselined (cli:check 514B/128.5T/diagnostics:1 -> 193B/48.2T/diagnostics:0; cli:lint/cli:analyze/cli:compile diagnostics:0; emittedBytes 341401 -> 341411) — span pruning removes the source-map-span-overflow warning from the envelopes.

Verification

  • cargo test --workspace --all-targets --all-features, cargo clippy --workspace --all-targets --all-features -- -D warnings, cargo fmt --all -- --check, git diff --check: pass.
  • Benchmark Python tests (114, including the pinned upstream oracle): pass.
  • python3 benchmarks/metrics/metrics.py check over the full corpus: within bands after the re-baseline; cli:check was the only out-of-band metric.
  • Real wright serve on the repel OverPy input: unavailable: {"names": "opy-rs"} with canonical content and resolved span paths.
  • CLI/serve parity asserted for inspect rules --content with --max and --rule; every statement's span.path resolves.
  • Content validated against the schema workshop-rs publishes (contract test).

Follow-up

rules gains content and rule: with content each selected rule carries the workshop-rs rule-content-v1 document plus statement spans, bounded to 20 rules by default and always selection-wrapped. Adds wright inspect rules, schema and contract docs, and a conformance test against the owner's published schema. OverPy results report names as unavailable pending the provider capability. Bumps workshop-rs to 1.16.0; its span pruning makes the source-map-span-overflow warning unreachable for the covered input, so that test now asserts the load still serves.
…(ADR-0024)

program-calls compiles the entry with the oracle or Wright, reads the Workshop text through rules with content, and counts calls by catalog id and positional argument patterns. A Wright that does not serve rule content makes the check unavailable instead of failing or passing it. Fixtures cover the Proximity-repel rule in OverPy and in en-US and zh-CN Workshop, with a one-short-stun negative.
rules.rule with a numeric id now joins cfg in the stale-id refusal after a reload; an unmatched name maps to invalid-selection like other selection fields while a duplicate name keeps the ambiguous-rule refusal cfg reports. Extends the CLI/agent selection parity test to inspect rules with content/max/rule, adds the provider test asserting unavailable.names=opy-rs over canonical content on an OverPy input, covers the 20-rule default bound and selection totals, and documents the unavailable member in the agent schema.
The ruleContent cache key now includes maxRules so two checks in one scenario with different bounds cannot share a truncated read. New tests pin that a withheld selection fails the check instead of passing on half the program, and that a Wright unable to serve rule content reports unavailable rather than a pass — whether it ignores the field or refuses the request.
…ostic change

workshop-rs 1.16 prunes provenance spans that do not resolve in an attached source, so the source-map-span-overflow warning no longer enters the cli envelopes: cli:check drops 514B/128.5T/diagnostics:1 to 193B/48.2T/diagnostics:0 (the pre-#619 size), and cli:lint, cli:analyze, cli:compile record diagnostics:0. compile emittedBytes 341401->341411 and small envelope shifts ride along as in-band accepted values from the same run.
#624 requires the driver test to prove resolved span paths on every statement, not a single one; the selected rule's conditions and actions all carry declarations-rules.ws.
@Teakowa
Teakowa marked this pull request as ready for review October 11, 2026 11:29

@e54-bot e54-bot left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

program-calls counts disabled calls (benchmarks/agent/bench_grade.py, count_calls).

count_calls walks content["conditions"] and content["actions"] and counts every matching call without reading disabled. workshop-rs 1.16 emits disabled at three levels: the rule document (required by the schema), each condition, and each action (rules/content.rs:61,117,229). A disabled call never runs, so an agent that disables a required applyImpulse or setStatusEffect still passes the check. That defeats the structural grading in ADR-0024 decision 5 and SPEC-414 REQ-010. Neither count_calls nor the new tests mention disabled.

Correction: skip statements with disabled: true, and skip all statements of a rule whose content["disabled"] is true. Add a test with one disabled action.

Nothing else found against #624's acceptance criteria.

count_calls counted calls inside Disabled() actions, disabled conditions, and disabled rules — none of which run — so an agent could satisfy a check with dead code. Rules with content.disabled, and statements carrying the rule-content-v1 disabled marker, are now skipped; a test pins one disabled action, one disabled condition, and one disabled rule not counting.
@e54-bot

e54-bot commented Oct 11, 2026

Copy link
Copy Markdown
Collaborator Author

Review finding addressed in 7938cc1 (pushed):

  • count_calls now skips statements carrying the rule-content-v1 disabled marker and rules whose content.disabled is true — disabled code never runs, so it cannot satisfy a check.
  • New test_program_calls_ignores_disabled_calls_and_rules covers all three levels (disabled action, disabled condition, disabled rule) and fails under the previous counting.

Verified: the 8 program-calls tests pass, including the repel fixtures in all three surface forms and the one-short-stun negative.

Follow-up review: e54-bot authored the PR so GitHub refuses a native re-request (422); flagging readiness here instead.

@e54-bot e54-bot left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. 7938cc1be skips disabled rules, conditions and actions in count_calls, and the new test covers all three levels; CI is green. (Posted as a comment because this identity is the PR author and cannot approve.)

@Teakowa
Teakowa merged commit 222930a into main Oct 11, 2026
24 checks passed
@Teakowa
Teakowa deleted the feat/rules-content branch October 11, 2026 14:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Development

Successfully merging this pull request may close these issues.

Serve structured rule content through rules and grade with program-calls (ADR-0024)

2 participants