Extract per-class ClassFacts in system-model #1403

Closed
opened 2026-10-26 20:13:59 +00:00 by jared · 3 comments
Owner

VERDICT: CREATE

Problem

The pattern method needs per-class facts. The system-model generator only emits stereotypes. A later detector cannot read io, entry, routing, state, or call facts from it.

Reproduce

n/a: new capability (build-plan step 4, shape detectors).

Approach

Extend system-model to emit one ClassFacts record per class (interface in docs/system-design-format/pattern-matching.md section 2; I/O kinds in proof/pattern-distance-experiment.md section 2). Start from the existing stereotypes. Output is data that a later step reads, not LikeC4 text.

Fields: io (kind :storage or :terminal, with path and line, one entry per direct primitive call), pure?, entry?, routes_to, holds_state?, calls. A call to another class is an edge, not I/O.

Required work:

  1. Add a ClassFacts value and its extractor under the system-model library — check: present ClassFacts in plugins/os-sdlc/lib/os_sdlc/system_model/**/*.rb
  2. Write the facts as data in the generated output — check: present ClassFacts in plugins/os-sdlc/lib/os_sdlc/system_model/**/*.rb

Acceptance criteria

  1. Given plugins/os at main 80a39130, when facts are generated, then the facts for Handoff::Document show no :storage io.
  2. Given the same input, when facts are generated, then the facts for Handoff::Store show :storage io with a path and line.
  3. Given any class, when facts are generated, then every io entry carries a kind, a path, and a line.

Owner sketch

OsSdlc::SystemModel::ClassFacts = Data.define(:io, :pure?, :entry?, :routes_to, :holds_state?, :calls)

Non-goals

Role predicates, patterns, and scoring belong to other tickets.

Origin

  • Trigger: pattern-distance method validated by fast-batch-17 (main 80a39130)
  • Improvised this session: none
  • Chain: no automated pattern detection ← build-plan step 4/5 not built ← DESIGN (docs/system-design-format/pattern-matching.md section 8)
  • Root candidate: none found; searched ClassFacts, pattern-matching, pattern-distance, stereotype, per-class, shape detector, system-model, facts
  • Where: plugins/os-sdlc/lib/os_sdlc/system_model/ (stereotyper), docs/system-design-format/pattern-matching.md section 2
  • Session: 4e988e4b-0efd-4090-9e80-c4ccd99e73b6
  • Transcript: /home/jared/.claude/projects/-home-jared-dev-cc-os--claude-worktrees-fast-batch-15/4e988e4b-0efd-4090-9e80-c4ccd99e73b6.jsonl
VERDICT: CREATE ## Problem The pattern method needs per-class facts. The `system-model` generator only emits stereotypes. A later detector cannot read io, entry, routing, state, or call facts from it. ## Reproduce n/a: new capability (build-plan step 4, shape detectors). ## Approach Extend `system-model` to emit one `ClassFacts` record per class (interface in `docs/system-design-format/pattern-matching.md` section 2; I/O kinds in `proof/pattern-distance-experiment.md` section 2). Start from the existing stereotypes. Output is data that a later step reads, not LikeC4 text. Fields: `io` (kind `:storage` or `:terminal`, with `path` and `line`, one entry per direct primitive call), `pure?`, `entry?`, `routes_to`, `holds_state?`, `calls`. A call to another class is an edge, not I/O. Required work: 1. Add a ClassFacts value and its extractor under the system-model library — check: present `ClassFacts` in `plugins/os-sdlc/lib/os_sdlc/system_model/**/*.rb` 2. Write the facts as data in the generated output — check: present `ClassFacts` in `plugins/os-sdlc/lib/os_sdlc/system_model/**/*.rb` ## Acceptance criteria 1. Given `plugins/os` at main 80a39130, when facts are generated, then the facts for `Handoff::Document` show no `:storage` io. 2. Given the same input, when facts are generated, then the facts for `Handoff::Store` show `:storage` io with a path and line. 3. Given any class, when facts are generated, then every io entry carries a kind, a path, and a line. ## Owner sketch ```ruby OsSdlc::SystemModel::ClassFacts = Data.define(:io, :pure?, :entry?, :routes_to, :holds_state?, :calls) ``` ## Non-goals Role predicates, patterns, and scoring belong to other tickets. ## Origin - Trigger: pattern-distance method validated by fast-batch-17 (main 80a39130) - Improvised this session: none - Chain: no automated pattern detection ← build-plan step 4/5 not built ← DESIGN (docs/system-design-format/pattern-matching.md section 8) - Root candidate: none found; searched ClassFacts, pattern-matching, pattern-distance, stereotype, per-class, shape detector, system-model, facts - Where: plugins/os-sdlc/lib/os_sdlc/system_model/ (stereotyper), docs/system-design-format/pattern-matching.md section 2 - Session: 4e988e4b-0efd-4090-9e80-c4ccd99e73b6 - Transcript: /home/jared/.claude/projects/-home-jared-dev-cc-os--claude-worktrees-fast-batch-15/4e988e4b-0efd-4090-9e80-c4ccd99e73b6.jsonl
Author
Owner

Input from blind run 2 (docs/system-design-format/proof/pattern-distance-run-2.md section 7, main after 25522a42). The class facts that decided most matches:

Rank Fact Cells decided
1 Direct storage/terminal primitive in a class that also owns a rule ~45
2 Client does storage I/O on a store that already has a repository class 12
3 Same I/O signature in 2+ classes (same gh command, same config read) 8 opportunities
5 Subcommand has logic but no own object 9
6 Command writes output (Kernel or injected stream) 10
7 Collaborator built in a method, not injected 8
8 Result shape per command 7
9 Routes by tracker or remote kind (case kind) 4

Proposed fields beyond the ticket's list: io_through_port (writes to an injected stream), constructs ([{class:, line:, in_ctor:, default_param:}]), result_shape, io_signature (normalized command or path, to find copies), loc (for size weighting). Fact 4 ("class has no role", d) was mostly noise; do not build it.

Input from blind run 2 (docs/system-design-format/proof/pattern-distance-run-2.md section 7, main after 25522a42). The class facts that decided most matches: | Rank | Fact | Cells decided | |---|---|---| | 1 | Direct storage/terminal primitive in a class that also owns a rule | ~45 | | 2 | Client does storage I/O on a store that already has a repository class | 12 | | 3 | Same I/O signature in 2+ classes (same gh command, same config read) | 8 opportunities | | 5 | Subcommand has logic but no own object | 9 | | 6 | Command writes output (Kernel or injected stream) | 10 | | 7 | Collaborator built in a method, not injected | 8 | | 8 | Result shape per command | 7 | | 9 | Routes by tracker or remote kind (`case kind`) | 4 | Proposed fields beyond the ticket's list: `io_through_port` (writes to an injected stream), `constructs` (`[{class:, line:, in_ctor:, default_param:}]`), `result_shape`, `io_signature` (normalized command or path, to find copies), `loc` (for size weighting). Fact 4 ("class has no role", d) was mostly noise; do not build it.
Author
Owner

Work started on branch ticket-1403 (os-sdlc implement pipeline, map poodr-ticket-implementation).

Work started on branch ticket-1403 (os-sdlc implement pipeline, map poodr-ticket-implementation).
Author
Owner

Resolution

Done: ClassFacts value (io entries with kind, path, line; pure?) and an Extractor IoScan/IoLedger that fills Model#facts per class.

Evidence: Implementation 176 (8 dispatches, 0 retries, 7 min 40 s), commit 3306c2fa, merged main 47c7f64e, pushed. os-sdlc suite after merging main: 2724 runs, 0 failures, 36.9 s. Acceptance criteria 1-3 (io for Handoff::Document and Handoff::Store, kind/path/line on every entry) pass.

Follow-ups: #1412: the Approach fields entry?, routes_to, holds_state?, calls were not in the acceptance criteria and were not built; Model#facts is not written to the generated output (required work item 2's check duplicated item 1's). #1412 blocks #1404.

## Resolution **Done:** ClassFacts value (io entries with kind, path, line; pure?) and an Extractor IoScan/IoLedger that fills Model#facts per class. **Evidence:** Implementation 176 (8 dispatches, 0 retries, 7 min 40 s), commit 3306c2fa, merged main 47c7f64e, pushed. os-sdlc suite after merging main: 2724 runs, 0 failures, 36.9 s. Acceptance criteria 1-3 (io for Handoff::Document and Handoff::Store, kind/path/line on every entry) pass. **Follow-ups:** #1412: the Approach fields entry?, routes_to, holds_state?, calls were not in the acceptance criteria and were not built; Model#facts is not written to the generated output (required work item 2's check duplicated item 1's). #1412 blocks #1404.
jared closed this issue 2026-10-26 21:32:57 +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#1403
No description provided.