Widen RegistryOutsideEntryPoint to root lookups by id on a model class #1450

Closed
opened 2026-10-27 21:57:25 +00:00 by jared · 5 comments
Owner

Problem

The cop Sdlc/Sequel/RegistryOutsideEntryPoint does not flag a Sequel model lookup Model[id]. That lookup is the same smell as the registry lookup, without the registry. Today the lookup is copied into seven places (Acceptance, AcceptanceCheck x2, Placing, ReportLookup, Abandon, RerouteIntake), and it causes three defects in the acceptance commands:

# boot/commands.rb:50 passes only the id; Acceptance finds the row, throws it away, AcceptanceCheck finds it again
Implementation::Acceptance.new(io).retired_tests_check(root, id)
def implementation_for(id)
  Implementation[id] || raise(Loud::Error, "retired-tests-check no implementation #{id}")  # one message for all 4 checks
end
  1. retired-tests-check and required-work-check look up the same row twice.
  2. mutation-check 999 and unchanged-check 999 print retired-tests-check no implementation 999.
  3. retired_tests, required_work and unchanged use the Boot root, not the row's worktree_root (Implementation#work_root(fallback) in implementation/targeting.rb). Only mutation_check uses it.

Analysis: docs/lint-lessons/analyses/sdlc-sequel-registry-outside-entry-point.md. Blocker #1381 landed (main e2588c72).

Ruling (2026-10-28)

Jared ruled. This replaces the earlier Implementation.fetch!(id, command) plan and the entry-point question entirely. A command class looks up its row once, in initialize. The cop allows Model[...] only inside initialize. No Exclude lists, no path lists, no entry-point classification. Moving the other TicketShape.new(ticket_body) callers to Implementation#ticket_shape is out of scope (follow-up, not filed).

Approach

Acceptance loads the row in its constructor and raises its own error. AcceptanceCheck is deleted and its logic moves into Acceptance. The cop gets a shape rule in the matcher: a constant that resolves to a Sequel model, sent [], outside a def initialize. ENV[], Thread.current[], constant hashes, Sequel[:t] stay clean.

Lookups that live elsewhere today move into initialize: implementation/abandon.rb:14, implementation/report_lookup.rb:7 (becomes a class), implementation/reroute_intake.rb:30-31 (the lazy @implementation ||=), dispatch/placing.rb:13 (Dispatch[...]; the class takes dispatch_id in its constructor).

Hits of the widened rule under plugins/os-sdlc/lib (found by grep for model-constant [] receivers; every one is covered below):

  • implementation/acceptance.rb:33 -> moves into initialize.
  • implementation/acceptance_check.rb:7, :13 -> file deleted.
  • implementation/abandon.rb:14, implementation/report_lookup.rb:7, implementation/reroute_intake.rb:30-31, dispatch/placing.rb:13 -> move into initialize.
  • Accounting has no direct lookup (it calls ReportLookup).

Test files that call AcceptanceCheck move to Acceptance.new(id, root, io).<check>: plugins/os-sdlc/tests/implementation/acceptance_check_retired_tests_test.rb, plugins/os-sdlc/tests/command/implementation/reroute_refresh_test.rb, plugins/os-sdlc/tests/command/required_work_typed_check_test.rb. Boot call sites lib/os_sdlc/boot/commands.rb:50,58,62,66 change to Acceptance.new(id, root, io).<check>; line 22 changes to Placing.new(io, dispatch_id).place(root, mode).

Required work:

  1. Acceptance takes the id and root in its constructor — check: present def initialize(id, root, io) in plugins/os-sdlc/lib/os_sdlc/implementation/acceptance.rb
  2. Remove the shared per-command lookup helper — check: absent def implementation_for in plugins/os-sdlc/lib/os_sdlc/implementation/acceptance.rb
  3. Delete AcceptanceCheck and its references in lib — check: absent AcceptanceCheck in plugins/os-sdlc/lib/**/*.rb
  4. Move the three test callers to Acceptance — check: absent AcceptanceCheck. in plugins/os-sdlc/tests/**/*.rb
  5. Memoize the ticket shape on the row — check: present def ticket_shape in plugins/os-sdlc/lib/os_sdlc/implementation.rb
  6. Boot builds Acceptance with id, root, io — check: absent Acceptance.new(io) in plugins/os-sdlc/lib/os_sdlc/boot/commands.rb
  7. Boot builds Placing with the dispatch id — check: absent Placing.new(io).place in plugins/os-sdlc/lib/os_sdlc/boot/commands.rb
  8. Add the lookup-outside-initialize matcher to the cop — check: present :initialize in plugins/os-sdlc/lib/os_sdlc/cops/sequel/registry_outside_entry_point.rb
  9. Test the widened cop — check: present Implementation[ in plugins/os-sdlc/tests/cops/registry_outside_entry_point_test.rb
  10. Abandon looks up in its constructor — check: present @implementation = Implementation[id] in plugins/os-sdlc/lib/os_sdlc/implementation/abandon.rb
  11. ReportLookup becomes a class that looks up in its constructor — check: present def initialize(id) in plugins/os-sdlc/lib/os_sdlc/implementation/report_lookup.rb
  12. RerouteIntake looks up once in its constructor — check: absent @implementation ||= in plugins/os-sdlc/lib/os_sdlc/implementation/reroute_intake.rb
  13. Placing looks up in its constructor — check: present def initialize(io, dispatch_id) in plugins/os-sdlc/lib/os_sdlc/dispatch/placing.rb

Acceptance criteria

  1. Given any of retired-tests-check, required-work-check, mutation-check, unchanged-check run for an existing id, when the command runs, then the implementation row is selected exactly once (today the first two select it twice).
  2. Given mutation-check 999 or unchanged-check 999, when the command runs, then the error is no implementation 999 and does not name retired-tests-check (today it does).
  3. Given an implementation row whose worktree_root is W and a Boot root R, with the retired test, required-work text or unchanged file present only under W, when retired-tests-check, required-work-check or unchanged-check runs from R, then each judges W (today they judge R).
  4. Given Implementation[@id] in a method other than initialize, including a lazy @x ||= Implementation[@id], when the cop runs, then it reports an offense (today it reports none). In the same test, Implementation[id] inside initialize, ENV["X"], Thread.current[:k], a constant-hash lookup and Sequel[:t] report no offense, and plugins/os-sdlc/lib/os_sdlc/ reports no offense with no Exclude entry and no path list added for the cop.

Owner sketch

class Implementation < Sequel::Model
  def ticket_shape = @ticket_shape ||= TicketShape.new(ticket_body)
end

class Implementation::Acceptance
  attr_reader :implementation, :root

  def initialize(id, root, io)
    @implementation = Implementation[id] || raise(Loud::Error, "no implementation #{id}")
    @root = implementation.work_root(root)
    @io = io
  end

  def retired_tests_check   # implementation.ticket_shape.retired_tests + RetiredTest#exists?(root)
  def required_work_check   # RequiredWorkCheck.new(root:).report(implementation.ticket_shape.required_work_items)
  def unchanged_check       # Gate::UnchangedCheck.for(root).call(implementation)
  def mutation_check        # MutationCheck.new(implementation.project(root), implementation).report
end

Origin

  • Trigger: Jared ruled "B for four cops" on the inc 7 widenings of the lint-cops track (handoff .cc-os/os/handoffs/2026-10-27-1542-lint-cops-track.md); re-ruled 2026-10-28 (see Ruling).
  • Improvised this session: none
  • Chain: cop misses a model-class root lookup <- matcher covers only the registry <- DESIGN (docs/lint-lessons/analyses/sdlc-sequel-registry-outside-entry-point.md)
  • Root candidate: none found; searched RegistryOutsideEntryPoint, registry, root lookup, Model[
  • Where: plugins/os-sdlc/lib/os_sdlc/cops/sequel/registry_outside_entry_point.rb
  • Session: 9f415790-a6bd-4850-8d70-3dd45004ce2b
  • Transcript: /home/jared/.claude/projects/-home-jared-dev-cc-os/9f415790-a6bd-4850-8d70-3dd45004ce2b.jsonl
    VERDICT: CREATE
## Problem The cop `Sdlc/Sequel/RegistryOutsideEntryPoint` does not flag a Sequel model lookup `Model[id]`. That lookup is the same smell as the registry lookup, without the registry. Today the lookup is copied into seven places (`Acceptance`, `AcceptanceCheck` x2, `Placing`, `ReportLookup`, `Abandon`, `RerouteIntake`), and it causes three defects in the acceptance commands: ```ruby # boot/commands.rb:50 passes only the id; Acceptance finds the row, throws it away, AcceptanceCheck finds it again Implementation::Acceptance.new(io).retired_tests_check(root, id) def implementation_for(id) Implementation[id] || raise(Loud::Error, "retired-tests-check no implementation #{id}") # one message for all 4 checks end ``` 1. `retired-tests-check` and `required-work-check` look up the same row twice. 2. `mutation-check 999` and `unchanged-check 999` print `retired-tests-check no implementation 999`. 3. `retired_tests`, `required_work` and `unchanged` use the Boot root, not the row's `worktree_root` (`Implementation#work_root(fallback)` in `implementation/targeting.rb`). Only `mutation_check` uses it. Analysis: `docs/lint-lessons/analyses/sdlc-sequel-registry-outside-entry-point.md`. Blocker #1381 landed (main e2588c72). ## Ruling (2026-10-28) Jared ruled. This replaces the earlier `Implementation.fetch!(id, command)` plan and the entry-point question entirely. A command class looks up its row once, in `initialize`. The cop allows `Model[...]` only inside `initialize`. No Exclude lists, no path lists, no entry-point classification. Moving the other `TicketShape.new(ticket_body)` callers to `Implementation#ticket_shape` is out of scope (follow-up, not filed). ## Approach `Acceptance` loads the row in its constructor and raises its own error. `AcceptanceCheck` is deleted and its logic moves into `Acceptance`. The cop gets a shape rule in the matcher: a constant that resolves to a Sequel model, sent `[]`, outside a `def initialize`. `ENV[]`, `Thread.current[]`, constant hashes, `Sequel[:t]` stay clean. Lookups that live elsewhere today move into `initialize`: `implementation/abandon.rb:14`, `implementation/report_lookup.rb:7` (becomes a class), `implementation/reroute_intake.rb:30-31` (the lazy `@implementation ||=`), `dispatch/placing.rb:13` (`Dispatch[...]`; the class takes `dispatch_id` in its constructor). Hits of the widened rule under `plugins/os-sdlc/lib` (found by grep for model-constant `[]` receivers; every one is covered below): - `implementation/acceptance.rb:33` -> moves into `initialize`. - `implementation/acceptance_check.rb:7`, `:13` -> file deleted. - `implementation/abandon.rb:14`, `implementation/report_lookup.rb:7`, `implementation/reroute_intake.rb:30-31`, `dispatch/placing.rb:13` -> move into `initialize`. - `Accounting` has no direct lookup (it calls `ReportLookup`). Test files that call `AcceptanceCheck` move to `Acceptance.new(id, root, io).<check>`: `plugins/os-sdlc/tests/implementation/acceptance_check_retired_tests_test.rb`, `plugins/os-sdlc/tests/command/implementation/reroute_refresh_test.rb`, `plugins/os-sdlc/tests/command/required_work_typed_check_test.rb`. Boot call sites `lib/os_sdlc/boot/commands.rb:50,58,62,66` change to `Acceptance.new(id, root, io).<check>`; line 22 changes to `Placing.new(io, dispatch_id).place(root, mode)`. Required work: 1. Acceptance takes the id and root in its constructor — check: present `def initialize(id, root, io)` in `plugins/os-sdlc/lib/os_sdlc/implementation/acceptance.rb` 2. Remove the shared per-command lookup helper — check: absent `def implementation_for` in `plugins/os-sdlc/lib/os_sdlc/implementation/acceptance.rb` 3. Delete AcceptanceCheck and its references in lib — check: absent `AcceptanceCheck` in `plugins/os-sdlc/lib/**/*.rb` 4. Move the three test callers to Acceptance — check: absent `AcceptanceCheck.` in `plugins/os-sdlc/tests/**/*.rb` 5. Memoize the ticket shape on the row — check: present `def ticket_shape` in `plugins/os-sdlc/lib/os_sdlc/implementation.rb` 6. Boot builds Acceptance with id, root, io — check: absent `Acceptance.new(io)` in `plugins/os-sdlc/lib/os_sdlc/boot/commands.rb` 7. Boot builds Placing with the dispatch id — check: absent `Placing.new(io).place` in `plugins/os-sdlc/lib/os_sdlc/boot/commands.rb` 8. Add the lookup-outside-initialize matcher to the cop — check: present `:initialize` in `plugins/os-sdlc/lib/os_sdlc/cops/sequel/registry_outside_entry_point.rb` 9. Test the widened cop — check: present `Implementation[` in `plugins/os-sdlc/tests/cops/registry_outside_entry_point_test.rb` 10. Abandon looks up in its constructor — check: present `@implementation = Implementation[id]` in `plugins/os-sdlc/lib/os_sdlc/implementation/abandon.rb` 11. ReportLookup becomes a class that looks up in its constructor — check: present `def initialize(id)` in `plugins/os-sdlc/lib/os_sdlc/implementation/report_lookup.rb` 12. RerouteIntake looks up once in its constructor — check: absent `@implementation ||=` in `plugins/os-sdlc/lib/os_sdlc/implementation/reroute_intake.rb` 13. Placing looks up in its constructor — check: present `def initialize(io, dispatch_id)` in `plugins/os-sdlc/lib/os_sdlc/dispatch/placing.rb` ## Acceptance criteria 1. Given any of `retired-tests-check`, `required-work-check`, `mutation-check`, `unchanged-check` run for an existing id, when the command runs, then the implementation row is selected exactly once (today the first two select it twice). 2. Given `mutation-check 999` or `unchanged-check 999`, when the command runs, then the error is `no implementation 999` and does not name `retired-tests-check` (today it does). 3. Given an implementation row whose `worktree_root` is W and a Boot root R, with the retired test, required-work text or unchanged file present only under W, when `retired-tests-check`, `required-work-check` or `unchanged-check` runs from R, then each judges W (today they judge R). 4. Given `Implementation[@id]` in a method other than `initialize`, including a lazy `@x ||= Implementation[@id]`, when the cop runs, then it reports an offense (today it reports none). In the same test, `Implementation[id]` inside `initialize`, `ENV["X"]`, `Thread.current[:k]`, a constant-hash lookup and `Sequel[:t]` report no offense, and `plugins/os-sdlc/lib/os_sdlc/` reports no offense with no `Exclude` entry and no path list added for the cop. ## Owner sketch ```ruby class Implementation < Sequel::Model def ticket_shape = @ticket_shape ||= TicketShape.new(ticket_body) end class Implementation::Acceptance attr_reader :implementation, :root def initialize(id, root, io) @implementation = Implementation[id] || raise(Loud::Error, "no implementation #{id}") @root = implementation.work_root(root) @io = io end def retired_tests_check # implementation.ticket_shape.retired_tests + RetiredTest#exists?(root) def required_work_check # RequiredWorkCheck.new(root:).report(implementation.ticket_shape.required_work_items) def unchanged_check # Gate::UnchangedCheck.for(root).call(implementation) def mutation_check # MutationCheck.new(implementation.project(root), implementation).report end ``` ## Origin - Trigger: Jared ruled "B for four cops" on the inc 7 widenings of the lint-cops track (handoff `.cc-os/os/handoffs/2026-10-27-1542-lint-cops-track.md`); re-ruled 2026-10-28 (see Ruling). - Improvised this session: none - Chain: cop misses a model-class root lookup <- matcher covers only the registry <- DESIGN (docs/lint-lessons/analyses/sdlc-sequel-registry-outside-entry-point.md) - Root candidate: none found; searched RegistryOutsideEntryPoint, registry, root lookup, Model[ - Where: plugins/os-sdlc/lib/os_sdlc/cops/sequel/registry_outside_entry_point.rb - Session: 9f415790-a6bd-4850-8d70-3dd45004ce2b - Transcript: /home/jared/.claude/projects/-home-jared-dev-cc-os/9f415790-a6bd-4850-8d70-3dd45004ce2b.jsonl VERDICT: CREATE
Author
Owner

Waiting on Jared's ruling (question at the top of the body) and on #1381.

Waiting on Jared's ruling (question at the top of the body) and on #1381.
Author
Owner

#1381 landed (main e2588c72): Db is matched by constant path, Db.method() is flagged, and the dead /controller//* glob is replaced by the Boot entry layer (boot.rb, boot/). Cop: 0 hits over plugins/os-sdlc before and after. #1381's test-glob shape carve-out is deferred to this ticket's ruling: the classes under tests/ that reach the registry (RollbackPerTest, SubagentStopScenario, SubagentStartScenario, CliNextInstructionHelpers, RepeatedNextRowCheck, DispatchTestCase, UnboundDbTestCase) are helpers called by entry points, the same question as Acceptance/Placing/Accounting/Abandoning. One ruling settles both.

#1381 landed (main e2588c72): Db is matched by constant path, Db.method(<registry symbol>) is flagged, and the dead **/controller/**/* glob is replaced by the Boot entry layer (boot.rb, boot/). Cop: 0 hits over plugins/os-sdlc before and after. #1381's test-glob shape carve-out is deferred to this ticket's ruling: the classes under tests/ that reach the registry (RollbackPerTest, SubagentStopScenario, SubagentStartScenario, CliNextInstructionHelpers, RepeatedNextRowCheck, DispatchTestCase, UnboundDbTestCase) are helpers called by entry points, the same question as Acceptance/Placing/Accounting/Abandoning. One ruling settles both.
Author
Owner

Ruling analysis, 2026-10-28 (session f258fae3). The ruling is still open: Jared decides. This comment replaces the A/B memo in the 2026-10-28 handoff.

Evidence: the lookup runs twice, and the message is wrong

# boot/commands.rb:50 passes only the id
->(io, id, root) { Implementation::Acceptance.new(io).retired_tests_check(root, id) }

# implementation/acceptance.rb: lookup 1, then the row is thrown away
def retired_tests_check(root, id)
  implementation_for(id)
  report(AcceptanceCheck.retired_tests_check(root, id))
end
def implementation_for(id)
  Implementation[id] || raise(Loud::Error, "retired-tests-check no implementation #{id}")  # one message for all 4 checks
end

# implementation/acceptance_check.rb:7: lookup 2 of the same row
def self.retired_tests_check(root, id)
  implementation = Implementation[id]

mutation-check 999 and unchanged-check 999 both print retired-tests-check no implementation 999. The pattern Model[id] || raise(...) is copied into 7 places: Acceptance, AcceptanceCheck, Placing, ReportLookup, Abandon, RerouteIntake, and Accounting.

Root: the row already knows it

implementation/targeting.rb: def work_root(fallback) = self[:worktree_root] || fallback. The four checks use root in different ways:

Check Root used
mutation_check implementation.project(root), so the row's worktree_root comes first
unchanged_check Gate::UnchangedCheck.for(root), the root that boot passes
retired_tests_check the root that boot passes
required_work_check the root that boot passes

Possible bug: three checks can look in the cwd and not in the run's worktree. Nobody has confirmed that this happens in practice.

Roles (Jared's restaurant analogy, mapped to patterns)

Role Pattern Code
Waiter Router / Dispatcher Boot (Inputs reads the request, Commands::TABLE routes it)
Expediter Application Service, one for each use case Acceptance, Placing, Abandoning, Accounting, ...
Pantry Repository Implementation.fetch!(id, command), a new method and the only place that does the lookup
Cooks domain objects AcceptanceCheck, MutationCheck, Gate::UnchangedCheck: they receive a row, and they read no database and write no io

Mediator does not fit here. A Mediator coordinates peer objects that talk to each other, and the cooks here do not talk to each other.

  • One pantry door. Implementation.fetch!(id, command) finds the row or raises with the command name. The cop flags Model[id] || raise everywhere except that method. This rule is simpler than a list of allowed classes. A specialist may ask the pantry. The defect is a copy of the pantry lookup.
  • Boot loses the right to call Model[id].
  • Each expediter calls fetch! once and gives the row, plus implementation.work_root(fallback), to its cooks.
  • Rejected: Boot looks up the row itself, because then the waiter goes to the pantry. Also rejected: the old option A, which allowed any class by its shape, because it makes the double lookup and the wrong message legal.

Open choice: how does the cop recognize an expediter, if it must? (a) Boot::Commands::TABLE refers to the class. (b) A role name or a place in the tree. A named role is easier for agents to find, so (b) is now the better choice. Before you name it, check the CRC job categories. #834 added "entry controllers", and that may already be this role.

#1381 test globs: that is a separate ruling. Tests build rows in setup, which is a different question.

Ruling analysis, 2026-10-28 (session f258fae3). The ruling is still open: Jared decides. This comment replaces the A/B memo in the 2026-10-28 handoff. ## Evidence: the lookup runs twice, and the message is wrong ```ruby # boot/commands.rb:50 passes only the id ->(io, id, root) { Implementation::Acceptance.new(io).retired_tests_check(root, id) } # implementation/acceptance.rb: lookup 1, then the row is thrown away def retired_tests_check(root, id) implementation_for(id) report(AcceptanceCheck.retired_tests_check(root, id)) end def implementation_for(id) Implementation[id] || raise(Loud::Error, "retired-tests-check no implementation #{id}") # one message for all 4 checks end # implementation/acceptance_check.rb:7: lookup 2 of the same row def self.retired_tests_check(root, id) implementation = Implementation[id] ``` `mutation-check 999` and `unchanged-check 999` both print `retired-tests-check no implementation 999`. The pattern `Model[id] || raise(...)` is copied into 7 places: Acceptance, AcceptanceCheck, Placing, ReportLookup, Abandon, RerouteIntake, and Accounting. ## Root: the row already knows it `implementation/targeting.rb`: `def work_root(fallback) = self[:worktree_root] || fallback`. The four checks use root in different ways: | Check | Root used | |---|---| | mutation_check | `implementation.project(root)`, so the row's worktree_root comes first | | unchanged_check | `Gate::UnchangedCheck.for(root)`, the root that boot passes | | retired_tests_check | the root that boot passes | | required_work_check | the root that boot passes | Possible bug: three checks can look in the cwd and not in the run's worktree. Nobody has confirmed that this happens in practice. ## Roles (Jared's restaurant analogy, mapped to patterns) | Role | Pattern | Code | |---|---|---| | Waiter | Router / Dispatcher | Boot (`Inputs` reads the request, `Commands::TABLE` routes it) | | Expediter | Application Service, one for each use case | Acceptance, Placing, Abandoning, Accounting, ... | | Pantry | Repository | `Implementation.fetch!(id, command)`, a new method and the only place that does the lookup | | Cooks | domain objects | AcceptanceCheck, MutationCheck, Gate::UnchangedCheck: they receive a row, and they read no database and write no io | Mediator does not fit here. A Mediator coordinates peer objects that talk to each other, and the cooks here do not talk to each other. ## Revised ruling 1 (recommended, 80%) - One pantry door. `Implementation.fetch!(id, command)` finds the row or raises with the command name. The cop flags `Model[id] || raise` everywhere except that method. This rule is simpler than a list of allowed classes. A specialist may ask the pantry. The defect is a copy of the pantry lookup. - Boot loses the right to call `Model[id]`. - Each expediter calls `fetch!` once and gives the row, plus `implementation.work_root(fallback)`, to its cooks. - Rejected: Boot looks up the row itself, because then the waiter goes to the pantry. Also rejected: the old option A, which allowed any class by its shape, because it makes the double lookup and the wrong message legal. Open choice: how does the cop recognize an expediter, if it must? (a) Boot::Commands::TABLE refers to the class. (b) A role name or a place in the tree. A named role is easier for agents to find, so (b) is now the better choice. Before you name it, check the CRC job categories. #834 added "entry controllers", and that may already be this role. #1381 test globs: that is a separate ruling. Tests build rows in setup, which is a different question.
Author
Owner

Work started 2026-10-28 via /os-sdlc:implement on branch ticket-1450 (session 6ee3ad76), on the body rewritten to Jared's 2026-10-28 ruling (lookup in initialize; AcceptanceCheck absorbed into Acceptance).

Work started 2026-10-28 via /os-sdlc:implement on branch ticket-1450 (session 6ee3ad76), on the body rewritten to Jared's 2026-10-28 ruling (lookup in initialize; AcceptanceCheck absorbed into Acceptance).
Author
Owner

Resolution

Done: Ruled shape shipped: Implementation::Acceptance.new(id, root, io) loads the row once in initialize, raises its own 'no implementation ', and judges implementation.work_root(root); AcceptanceCheck absorbed and deleted; Implementation#ticket_shape; Placing, ReportLookup, Abandon, RerouteIntake look up in initialize; RegistryOutsideEntryPoint flags Model[] outside initialize by shape only; lesson and analysis updated. Merged 5ccc305f.

Evidence: Implementation 213 escalated (95) on a test defect; hand-finished per the escalation procedure: full suite 2900 runs 0 failures; rubocop 14 changed files 0 offenses; RegistryOutsideEntryPoint over lib 938 files 0 offenses; one opus design audit, must-fix items 1,3,4,5,6 applied. Run 213 abandoned with reason.

Follow-ups: Dropped: route the other 6 TicketShape.new callers through Implementation#ticket_shape (ticket-skeptic DROP: depth-1 rule, Need-to-exist test failed; no failure, convenience only). Dropped: abandon.rb private helpers still take the row as a parameter (style only).

## Resolution **Done:** Ruled shape shipped: Implementation::Acceptance.new(id, root, io) loads the row once in initialize, raises its own 'no implementation <id>', and judges implementation.work_root(root); AcceptanceCheck absorbed and deleted; Implementation#ticket_shape; Placing, ReportLookup, Abandon, RerouteIntake look up in initialize; RegistryOutsideEntryPoint flags Model[<id expression>] outside initialize by shape only; lesson and analysis updated. Merged 5ccc305f. **Evidence:** Implementation 213 escalated (95) on a test defect; hand-finished per the escalation procedure: full suite 2900 runs 0 failures; rubocop 14 changed files 0 offenses; RegistryOutsideEntryPoint over lib 938 files 0 offenses; one opus design audit, must-fix items 1,3,4,5,6 applied. Run 213 abandoned with reason. **Follow-ups:** Dropped: route the other 6 TicketShape.new callers through Implementation#ticket_shape (ticket-skeptic DROP: depth-1 rule, Need-to-exist test failed; no failure, convenience only). Dropped: abandon.rb private helpers still take the row as a parameter (style only).
jared closed this issue 2026-10-28 16:32:04 +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#1450
No description provided.