Add nine group A patterns to the catalog as loose patterns #1548
Labels
No labels
P0
P1
P2
P3
bug
category/code-change
category/cross-repo
category/eval-run
category/investigation
category/no-test-target
category/owner-ruling
category/prose-artifact
category/recurring-chore
category/structure
category/umbrella
crc-refactor
create
delete
enhancement
filed-by/agent
filed-by/user
frozen
lint-rule
needs-info
needs-triage
next
plugin/cc-architect
plugin/os
plugin/os-adr
plugin/os-aidd-lint
plugin/os-backlog
plugin/os-context
plugin/os-doc-hygiene
plugin/os-sdlc
plugin/os-vault
project/cc-os
ready-for-agent
ready-for-human
recurring
review
rule-proposal
update
waiting
wayfinder:grilling
wayfinder:map
wayfinder:map
wayfinder:research
wayfinder:task
wayfinder:task
wontfix
worklist/deviations
worklist/lint-rule
worklist/new-implement-build
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
jared/cc-os#1548
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Problem
docs/system-design-format/pattern-landscape.mdmarks 12 group A rows asexpressible now, andcatalog/does not hold them. The detector cannot present a pattern that the catalog does not hold, so a component that has one of these shapes gets no match.The group A threshold of 3 comes from run 3, when the catalog held six group A patterns (pattern-matching.md section 5). Many new rows overlap current patterns. For example, the landscape calls FCIS "near-identical" to HEX R1. A strict overlapping pattern adds to convergence with no new evidence. A scratch run with all nine patterns strict changed 2 group A rows in os-backlog (2 to 4) and 4 in os-sdlc (7 to 8). No review confirmed those rows.
Reproduce
n/a: this ticket adds catalog data; no defect exists to reproduce.
Approach
How the new patterns enter convergence. Each new pattern sets
strict?: false.Convergence#flagskeeps only matches whose pattern is strict, so a loose pattern adds no flag and cannot change a convergence count.OpportunityScan#findingsrejects present matches one pattern at a time, so a new pattern does not remove the misfits of another pattern. The result: every group A row and its score stay the same, and threshold 3 stays valid. A scratch run over os-backlog, os-me and os-sdlc confirmed this: group A and group C rows were identical with all new patterns loose.A loose pattern reaches a report through the
loose_presentsection ofopportunitiesand throughsystem-model gauge(#1547). A later calibration run may set a pattern to strict after a review measures its precision (pattern-matching.md section 9). This ticket does not do that.Shape::UnclearRole#groupsalso selects strict patterns only. Loose patterns therefore leave theunclear-roledetail unchanged (convergence A:3 C:0).Effect on
present.OpportunityScan#presentkeeps strict patterns only, so the baseline stays comparable. A newOpportunityScan#loose_presentholds the present matches of loose patterns.to_hand the text report print them in a separate section labeled unreviewed. This ticket does not changeMatch#present?or the 0.05 threshold. The scratch run gave these loose rows: os-backlog 107, os-me 21, os-sdlc 94. Nobody reviewed these rows, so they carry no precision figure. Ruling recorded indocs/decisions/rulings.tsv, 2026-11-04, ruled_by predicted.Pattern roles and rules. Each item quotes the
Revealing signalstext of the landscape row. The Owner sketch gives the predicates.FAC): "One class calls three or more classes of one namespace; senders outside the namespace call only this class." RoleFacadetests the first half. Rule R1 tests the second half, because only a rule sees class names.MED): "One class holds three or more injected colleagues; colleagues hold a reference back to it; colleagues do not call each other." RoleMediator; rule R1 flags a call between two colleagues.DOM): "A web of classes that hold state and behavior, call each other, and do no I/O." RoleDomainObject; rule R1 forbids I/O, except onEdgeas in HEX R1.SVC): "Non-entry classes called by entry classes; each public method is one application operation; they call domain and data-source classes." RolesEntry,Service,DataSource; rule R1 forbidsEntrytoDataSource.MVC): "Controller classes are entries and call model and view; view classes write the terminal; model classes are pure; model does not call view." RolesController,View,Model; rule R1 forbidsModeltoView.PGC): "One entry handler per command (its ownbinscript or Thor method)." RolesHandler,Worker; rule R1 forbidsHandlertoHandler.FRC): "One entry class receives every command and routes to handler classes by name." RolesFront,Handler; rule R1 forbids a decision inFront.routes_toworks only in aThorsubclass, so the scratch run filled this pattern in no component. That miss is acceptable.WHP): "The whole constructs and owns its parts ininitialize(no injection); senders outside see only the whole." RoleWhole, rolePart; rule R1 flags an outside call to a part. Known instance:Extractor::FactScan, which fitsWhole.FCIS): "Core classes are pure and hold no state; shell classes do I/O and call the core; the core never calls the shell." RolesCore,Shell; rule R1 forbidsCoretoShell.Rows left out of this batch.
callsand class names; a role predicate cannot see its own name." It is a cohesion ratio of a namespace. It has no role, and no line is wrong, so it gives no site for a rule. A journey component also crosses namespaces by design.Catalogneeds a metric, not a pattern, for this row.Constraints for the implementing agent.
idmust hold no space, becauseConvergence.pattern_countsplits each flag on whitespace.except:must also be in the roles of that pattern.Assignment#fits?raisesKeyErrorotherwise.Catalog::Edgetherefore goes in theDOMroles, as in HEX.Required work:
id: "FAC"inplugins/os-sdlc/lib/os_sdlc/system_model/catalog/facade.rbid: "MED"inplugins/os-sdlc/lib/os_sdlc/system_model/catalog/mediator.rbid: "DOM"inplugins/os-sdlc/lib/os_sdlc/system_model/catalog/domain_model.rbid: "SVC"inplugins/os-sdlc/lib/os_sdlc/system_model/catalog/service_layer.rbid: "MVC"inplugins/os-sdlc/lib/os_sdlc/system_model/catalog/model_view_controller.rbid: "PGC"inplugins/os-sdlc/lib/os_sdlc/system_model/catalog/page_controller.rbid: "FRC"inplugins/os-sdlc/lib/os_sdlc/system_model/catalog/front_controller.rbid: "WHP"inplugins/os-sdlc/lib/os_sdlc/system_model/catalog/whole_part.rbid: "FCIS"inplugins/os-sdlc/lib/os_sdlc/system_model/catalog/functional_core.rbstrict?: falseinplugins/os-sdlc/lib/os_sdlc/system_model/catalog/facade.rbBypassedOwner = Data.defineinplugins/os-sdlc/lib/os_sdlc/system_model/pattern/rule/bypassed_owner.rbColleagueCall = Data.defineinplugins/os-sdlc/lib/os_sdlc/system_model/pattern/rule/colleague_call.rbdef called_namespacesinplugins/os-sdlc/lib/os_sdlc/system_model/class_facts.rbCatalog.patterns— check: presentFunctionalCoreinplugins/os-sdlc/lib/os_sdlc/system_model/catalog.rbARCHITECTURALin the catalog test — check: presentTXS FAC MED DOM SVC MVC PGC FRC WHP FCISinplugins/os-sdlc/tests/system_model_catalog_test.rbIDSin the catalog test — check: presentSPEC FAC MED DOM SVC MVC PGC FRC WHP FCISinplugins/os-sdlc/tests/system_model_catalog_test.rbloose until a calibration runindocs/system-design-format/pattern-matching.mdstrict?and print the loose rows in a section labeled unreviewed — check: presentdef loose_presentinplugins/os-sdlc/lib/os_sdlc/system_model/opportunity_scan.rbOrchestrator work: add one History row to
docs/implementation-status/os-sdlc-system-model.md.Rejected: strict patterns with threshold 3 — overlap raises convergence with no evidence, and the threshold stops being valid. Strict patterns with a higher threshold — the threshold has no calibration run behind it, and it hides confirmed rows. Counting one overlap cluster as one pattern — this changes
Convergence, and the scale-group rules, for a problem thatstrict?already solves.Acceptance criteria
Convergencecounts the line, then the count is 2.OpportunityScan#ranked(:A)runs with threshold 3, then the finding is not ranked.opportunities --jsonoutput for os-backlog, os-me and os-sdlc before this ticket, when the command runs after this ticket, then thegroupsvalue of each plugin is the same.opportunitiesoutput before this ticket, when the command runs after this ticket, then thepresentrows of strict patterns are the same, and each row of a loose pattern is in theloose_presentsection labeled unreviewed.shapesruns after this ticket, then the detail is stillconvergence A:3 C:0.FACFacaderole tests it, then it fits.FACmatches the component, then R1 flags the line of that call.MEDMediatorrole tests it, then it fits.MEDmatches the component, then R1 flags the line of that call.initializeand has no injected collaborator, when theWHPWholerole tests it, then it fits.initialize, when theWHPWholerole tests it, then it does not fit.Modelclass that calls aViewclass, whenMVCmatches the component, then R1 flags the line of that call.Coreclass that calls aShellclass, whenFCISmatches the component, then R1 flags the line of that call.Edge, whenDOMmatches the component, then R1 flags the I/O line.Entryclass that calls aDataSourceclass, whenSVCmatches the component, then R1 flags the line of that call.Handlerclass that calls aHandlerclass, whenPGCmatches the component, then R1 flags the line of that call.Frontclass with a decision, whenFRCmatches the component, then R1 flags the decision line.Owner sketch
Non-goals
Do not set any new pattern to strict. Do not change
Catalog.thresholds, the 0.05 threshold, orMatch#present?. Do not add Module, Presentation-Abstraction-Control or View Handler.Retired tests
plugins/os-sdlc/tests/system_model_catalog_test.rb#test_transaction_script_is_the_one_loose_pattern_as_run_two_set_it
Origin
system-model opportunitiesholds nine patterns;docs/system-design-format/pattern-landscape.mdmarks 33 rowsexpressible now.docs/system-design-format/pattern-matching.mdsection 5.plugins/os-sdlc/lib/os_sdlc/system_model/catalog.rbVERDICT: CREATE
Work started on branch ticket-1548.
Resolution
Done: Added nine loose group A patterns, BypassedOwner and ColleagueCall rules, strict-only present, and a loose_present section labeled unreviewed.
Evidence: Implementation 231 merge-ready; suite gate passed twice; contract audit passed on branch ticket-1548.
Follow-ups: none