Add a forbidden-edge rule evaluator that returns misfits for a pattern #1483

Closed
opened 2026-11-01 15:46:58 +00:00 by jared · 2 comments
Owner

Problem

No code evaluates a pattern's allowed and forbidden edge rules. Pattern::Rule is Data.define(:id, :text) and Pattern#forbidden_rule only looks a rule up by id. Runs 1 and 2 had no script: an agent read the code and counted each misfit by hand. The pattern-opportunity detector (#1430) needs misfits to score a Match (pattern-matching.md section 2).

Reproduce

n/a: capability does not exist. See plugins/os-sdlc/lib/os_sdlc/system_model/pattern/rule.rb.

Approach

Add a rule evaluator. It checks a Pattern's allowed and forbidden edge rules against a component's classes and returns misfits [{rule:, path:, line:}], the misfits field of the Match type in pattern-matching.md section 2. Pattern rule data stays data: no pattern ID in evaluator code. This ticket blocks #1430. README section 6 step 10 names it as a precondition.

Required work:

  1. Give Pattern::Rule a checkable form for edge rules — check: present forbidden in plugins/os-sdlc/lib/os_sdlc/system_model/pattern/rule.rb
  2. Add an evaluator that returns misfits — check: present misfits in plugins/os-sdlc/lib/os_sdlc/system_model/pattern/*.rb

Acceptance criteria

  1. Given the handoff component (pattern-matching.md section 2 worked example) and the catalog patterns that flagged it, when the evaluator runs, then the misfits match the hand counts in proof/pattern-distance-experiment.md.
  2. Given the run 2 B7 finding (project config, 13 classes), when the evaluator runs, then the misfits match the hand counts in proof/pattern-distance-run-2.md.
  3. Given a component with no forbidden edge, when the evaluator runs, then it returns an empty list.

Non-goals

The opportunity detector itself (#1430).

Origin

  • Trigger: Jared's ruling of 2026-11-01 recorded in docs/system-design-format/README.md section 6 (commit 1b4ea2d5)
  • Improvised this session: none
  • Chain: step not built ← plan from the 2026-11-01 ruling ← DESIGN (docs/system-design-format/README.md section 6 step 10 (precondition of #1430))
  • Root candidate: none found; searched forbidden edge rule evaluator, Pattern::Rule, misfits
  • Where: plugins/os-sdlc/lib/os_sdlc/system_model/pattern/rule.rb
  • Session: 313ee80d-b132-4de6-a01d-e1a57fbd3450
  • Transcript: /home/jared/.claude/projects/-home-jared-dev-cc-os/313ee80d-b132-4de6-a01d-e1a57fbd3450.jsonl

VERDICT: CREATE

## Problem No code evaluates a pattern's allowed and forbidden edge rules. `Pattern::Rule` is `Data.define(:id, :text)` and `Pattern#forbidden_rule` only looks a rule up by id. Runs 1 and 2 had no script: an agent read the code and counted each misfit by hand. The pattern-opportunity detector (#1430) needs misfits to score a Match (pattern-matching.md section 2). ## Reproduce n/a: capability does not exist. See `plugins/os-sdlc/lib/os_sdlc/system_model/pattern/rule.rb`. ## Approach Add a rule evaluator. It checks a Pattern's allowed and forbidden edge rules against a component's classes and returns misfits `[{rule:, path:, line:}]`, the `misfits` field of the Match type in pattern-matching.md section 2. Pattern rule data stays data: no pattern ID in evaluator code. This ticket blocks #1430. README section 6 step 10 names it as a precondition. Required work: 1. Give `Pattern::Rule` a checkable form for edge rules — check: present `forbidden` in `plugins/os-sdlc/lib/os_sdlc/system_model/pattern/rule.rb` 2. Add an evaluator that returns misfits — check: present `misfits` in `plugins/os-sdlc/lib/os_sdlc/system_model/pattern/*.rb` ## Acceptance criteria 1. Given the handoff component (pattern-matching.md section 2 worked example) and the catalog patterns that flagged it, when the evaluator runs, then the misfits match the hand counts in `proof/pattern-distance-experiment.md`. 2. Given the run 2 B7 finding (project config, 13 classes), when the evaluator runs, then the misfits match the hand counts in `proof/pattern-distance-run-2.md`. 3. Given a component with no forbidden edge, when the evaluator runs, then it returns an empty list. ## Non-goals The opportunity detector itself (#1430). ## Origin - Trigger: Jared's ruling of 2026-11-01 recorded in docs/system-design-format/README.md section 6 (commit 1b4ea2d5) - Improvised this session: none - Chain: step not built ← plan from the 2026-11-01 ruling ← DESIGN (docs/system-design-format/README.md section 6 step 10 (precondition of #1430)) - Root candidate: none found; searched forbidden edge rule evaluator, Pattern::Rule, misfits - Where: plugins/os-sdlc/lib/os_sdlc/system_model/pattern/rule.rb - Session: 313ee80d-b132-4de6-a01d-e1a57fbd3450 - Transcript: /home/jared/.claude/projects/-home-jared-dev-cc-os/313ee80d-b132-4de6-a01d-e1a57fbd3450.jsonl VERDICT: CREATE
Author
Owner

Work started on worktree branch worktree-agent-a13870096ee8af21e (agent worktree). TDD: rule evaluator returning misfits [{rule:, path:, line:}].

Work started on worktree branch worktree-agent-a13870096ee8af21e (agent worktree). TDD: rule evaluator returning misfits [{rule:, path:, line:}].
Author
Owner

Resolution

Done: Forgejo-free evaluator: Pattern#match(component) returns a Match with assignment, misfits [{rule:, path:, line:}] and distance; rules are data (ForbiddenEdge, ForbiddenIo, MixedRoles, Unmeasured); no pattern ID in evaluator code; a stub 7th pattern test passes unchanged. Hand counts reproduced for handoff HEX R1 and B7 HEX; the other hand flags need facts ClassFacts lacks (decides?, holds_state? scope, io_signature, warn/exit terminal io, call line numbers).

Evidence: commit fd0ffb18, merged to main at 496c2184 and pushed; ruby plugins/os-sdlc/tests/all.rb: 2928 runs, 0 failures, 35.1s; tests system_model_pattern_match_test.rb and system_model_pattern_match_hand_counts_test.rb

Follow-ups: Missing facts, Match listing unmeasured rules, and per-(rule, class) distance are absorbed into #1482 part A (in progress); no new tickets

## Resolution **Done:** Forgejo-free evaluator: Pattern#match(component) returns a Match with assignment, misfits [{rule:, path:, line:}] and distance; rules are data (ForbiddenEdge, ForbiddenIo, MixedRoles, Unmeasured); no pattern ID in evaluator code; a stub 7th pattern test passes unchanged. Hand counts reproduced for handoff HEX R1 and B7 HEX; the other hand flags need facts ClassFacts lacks (decides?, holds_state? scope, io_signature, warn/exit terminal io, call line numbers). **Evidence:** commit fd0ffb18, merged to main at 496c2184 and pushed; ruby plugins/os-sdlc/tests/all.rb: 2928 runs, 0 failures, 35.1s; tests system_model_pattern_match_test.rb and system_model_pattern_match_hand_counts_test.rb **Follow-ups:** Missing facts, Match listing unmeasured rules, and per-(rule, class) distance are absorbed into #1482 part A (in progress); no new tickets
jared closed this issue 2026-11-01 16:12:54 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
jared/cc-os#1483
No description provided.