Sharpen each meaning of a name collision in the rename recipe #1119

Closed
opened 2026-10-18 19:10:34 +00:00 by jared · 4 comments
Owner

Problem

A rename recipe also has no step that names each meaning. The prescriber picks a new name, but nothing records which meaning keeps the old name, which meaning is domain vocabulary, or which glossary term the team must use. Ticket A supplies the type signals.

Approach

Make the rename recipe sharpen each meaning.

3. Meanings in the brief (Meanings, new). RunDirectory#type_signals reads the type signals of a saved run. Meanings.new(run, finding) gives one entry per type in the finding, in this form:

meanings:
  - type: Hash
    born_at: [plugins/os-sdlc/lib/os_sdlc/boot/inputs.rb:87, ...]   # distinct birth lines of the type signals
    sites: [OsSdlc::Crc::Census::Run, ...]
  - type: OsSdlc::CollaboratorPass::RunDirectory
    born_at: [plugins/os-sdlc/lib/os_sdlc/collaborator_pass/command/validate_recipe.rb:17, ...]
    sites: [OsSdlc::CollaboratorPass::ConceptBrief, ...]

PrescriptionBrief#to_h adds meanings for a name_collision finding only. ConceptBrief adds meanings to the detail of each name_collision finding. Other findings keep their keys.

4. Recipe schema. PrescriptionBrief::SCHEMA and Recipe gain two keys, for a name_collision recipe:

sharpen:                    # name_collision only; one entry per meaning
  - {type: <meaning type>, kind: domain|programming, meaning: <one sentence>, term: <name for this meaning>, avoid: [<names>]}   # avoid: domain only
glossary:                   # one entry per domain sharpen entry
  - {term: <term>, definition: <one sentence>, avoid: [<names>]}

5. RecipeCheck (RecipeCheck::SharpenRules, new). For a recipe whose finding shape is name_collision, with the meanings of the run:

  1. Each meaning has exactly one sharpen entry with its type. A missing, a duplicate, or an unknown type is a problem.
  2. Each domain entry has a non-empty meaning, a non-empty term, and a non-empty avoid.
  3. glossary has exactly one entry per domain entry, matched by term.
  4. For each rename, the canonical meaning is the meaning whose term equals the rename from. A target constant that is a site of the canonical meaning is a problem.

6. Ticket body. For a recipe with glossary entries, TicketDraft::Approach lists them under the Orchestrator work: line. It says: write these entries to the root GLOSSARY.md, create the file when it is absent, and make docs/agents/domain.md point to it. One line per entry: - **<term>**: <definition> Avoid: <avoid, comma-joined>.

Shared contract with ticket A. Ticket B reads type signal rows of this exact form: Signal(source: "params", kind: "type", path: <birth path>, line: <birth line>, constant: <site>, names: [name], group: <type>, weight: 1). Its tests use fixture rows of this form, and RunDirectory#type_signals is ticket B's, so ticket A and ticket B can be implemented in parallel; neither changes the other's files.

Required work:

  1. Read type signals from a saved run — check: present def type_signals in plugins/os-sdlc/lib/os_sdlc/collaborator_pass/run_directory.rb
  2. Add OsSdlc::CollaboratorPass::Meanings and use it in the finding brief — check: present Meanings.new in plugins/os-sdlc/lib/os_sdlc/collaborator_pass/prescription_brief.rb
  3. Use Meanings in the concept brief — check: present Meanings.new in plugins/os-sdlc/lib/os_sdlc/collaborator_pass/concept_brief.rb
  4. Add sharpen and glossary to the schema text — check: present sharpen: in plugins/os-sdlc/lib/os_sdlc/collaborator_pass/prescription_brief.rb
  5. Add sharpen and glossary members to Recipe — check: present :glossary in plugins/os-sdlc/lib/os_sdlc/collaborator_pass/recipe.rb
  6. Add RecipeCheck::SharpenRules with the four rules — check: present SharpenRules.new in plugins/os-sdlc/lib/os_sdlc/collaborator_pass/recipe_check.rb
  7. Explain meanings, sharpen, glossary, kind: domain|programming, and the canonical meaning in the prescriber prompt, and add the four rules to its rule list — check: present canonical meaning in plugins/os-sdlc/skills/collaborator-pass/references/prompts/prescribe.md
  8. Drop the path and node hint from the rename entry when — check: absent (path and node) in plugins/os-sdlc/references/collaborator-recipes.yml
  9. List glossary entries under Orchestrator work: in the ticket body — check: present GLOSSARY.md in plugins/os-sdlc/lib/os_sdlc/collaborator_pass/ticket_draft/approach.rb

Orchestrator work: create the root GLOSSARY.md and make docs/agents/domain.md point to it; both are outside the os-sdlc target. After this ticket ships, re-measure with bin/collaborator-pass measure --runs docs/crc/os-sdlc/collaborator-runs and let the loop prescribe the run rename.

Acceptance criteria

  1. Given a saved run with a name_collision finding and its type signals, when prescribe-brief --subject runs for it, then the brief has a meanings list with one entry per type, and each entry has type, born_at, and sites.
  2. Given a rename recipe for a name_collision finding with two meanings and one sharpen entry, when the recipe is validated, then the problems name the meaning that has no sharpen entry.
  3. Given a rename recipe with a domain sharpen entry whose avoid is empty, when the recipe is validated, then there is a problem for that entry.
  4. Given a rename recipe with a domain sharpen entry and no glossary entry with its term, when the recipe is validated, then there is a problem for the missing glossary entry.
  5. Given a rename recipe whose from is the term of one meaning and whose target is a site of that meaning, when the recipe is validated, then there is a problem for that target.
  6. Given a rename recipe with complete sharpen and glossary entries whose targets are only sites of the other meaning, when the recipe is validated, then there are no problems.
  7. Given a rename recipe with two glossary entries, when ticket-body runs, then the Orchestrator work: line names GLOSSARY.md and docs/agents/domain.md and the body lists both entries.

Owner sketch

class OsSdlc::CollaboratorPass::RunDirectory
  def type_signals
end

class OsSdlc::CollaboratorPass::Meanings
  def initialize(run, finding)
  def to_a
  def canonical(term)
end

OsSdlc::CollaboratorPass::Recipe = Data.define(:id, :finding, :subjects, :object, :targets, :renames,
                                               :expected_delta, :acceptance, :also_fits, :rationale,
                                               :sharpen, :glossary)

class OsSdlc::CollaboratorPass::RecipeCheck::SharpenRules
  def initialize(recipe, meanings)
  def problems
end

class OsSdlc::CollaboratorPass::TicketDraft::Approach
  def initialize(recipe, entry)
  def to_s
end

Non-goals

  • The rename of run to arguments in the Crc sites. The loop prescribes it after this ticket ships.
  • #1117 (RunPath built in the initializer).
  • The detector is ticket A.

Origin

  • Trigger: collaborator-pass iteration 4 run 20261018T172139Z
  • Improvised this session: none
  • Chain: node reported and run not reported (docs/crc/os-sdlc/collaborator-runs/20261018T172139Z/findings.yml, name_collision node, evidence path takers 2; node takers 3) ← NameCollisions compares the path and node sides only (SIDES in plugins/os-sdlc/lib/os_sdlc/collaborator_pass/name_collisions.rb) ← UseGroup classifies a use by call shape, not by the class of the value (plugins/os-sdlc/lib/os_sdlc/collaborator_pass/parameter_uses/use_group.rb) ← DESIGN (plugins/os-sdlc/lib/os_sdlc/collaborator_pass/name_collisions.rb). The run meanings were seen by the prescriber in docs/crc/os-sdlc/collaborator-runs/20261018T172139Z/recipes/collaborator_pass.yml (rationale), and Jared ruled the detector and sharpening design on 2026-10-18 in this session.
  • Root candidate: none found; searched name_collision, name collision, rename recipe, sharpen in open issues
  • Where: plugins/os-sdlc/lib/os_sdlc/collaborator_pass/name_collisions.rb, plugins/os-sdlc/lib/os_sdlc/collaborator_pass/parameter_uses/use_group.rb
  • Session: a71a2c2a-4943-47c4-8dd1-cc16fe42d120
  • Transcript: /home/jared/.claude/projects/-home-jared-dev-cc-os/a71a2c2a-4943-47c4-8dd1-cc16fe42d120.jsonl
## Problem A rename recipe also has no step that names each meaning. The prescriber picks a new name, but nothing records which meaning keeps the old name, which meaning is domain vocabulary, or which glossary term the team must use. Ticket A supplies the type signals. ## Approach Make the rename recipe sharpen each meaning. **3. Meanings in the brief (`Meanings`, new).** `RunDirectory#type_signals` reads the `type` signals of a saved run. `Meanings.new(run, finding)` gives one entry per type in the finding, in this form: ```yaml meanings: - type: Hash born_at: [plugins/os-sdlc/lib/os_sdlc/boot/inputs.rb:87, ...] # distinct birth lines of the type signals sites: [OsSdlc::Crc::Census::Run, ...] - type: OsSdlc::CollaboratorPass::RunDirectory born_at: [plugins/os-sdlc/lib/os_sdlc/collaborator_pass/command/validate_recipe.rb:17, ...] sites: [OsSdlc::CollaboratorPass::ConceptBrief, ...] ``` `PrescriptionBrief#to_h` adds `meanings` for a `name_collision` finding only. `ConceptBrief` adds `meanings` to the detail of each `name_collision` finding. Other findings keep their keys. **4. Recipe schema.** `PrescriptionBrief::SCHEMA` and `Recipe` gain two keys, for a `name_collision` recipe: ```yaml sharpen: # name_collision only; one entry per meaning - {type: <meaning type>, kind: domain|programming, meaning: <one sentence>, term: <name for this meaning>, avoid: [<names>]} # avoid: domain only glossary: # one entry per domain sharpen entry - {term: <term>, definition: <one sentence>, avoid: [<names>]} ``` **5. RecipeCheck (`RecipeCheck::SharpenRules`, new).** For a recipe whose finding shape is `name_collision`, with the meanings of the run: 1. Each meaning has exactly one `sharpen` entry with its `type`. A missing, a duplicate, or an unknown type is a problem. 2. Each `domain` entry has a non-empty `meaning`, a non-empty `term`, and a non-empty `avoid`. 3. `glossary` has exactly one entry per `domain` entry, matched by `term`. 4. For each rename, the canonical meaning is the meaning whose `term` equals the rename `from`. A target constant that is a site of the canonical meaning is a problem. **6. Ticket body.** For a recipe with `glossary` entries, `TicketDraft::Approach` lists them under the `Orchestrator work:` line. It says: write these entries to the root `GLOSSARY.md`, create the file when it is absent, and make `docs/agents/domain.md` point to it. One line per entry: `- **<term>**: <definition> Avoid: <avoid, comma-joined>.` **Shared contract with ticket A.** Ticket B reads type signal rows of this exact form: `Signal(source: "params", kind: "type", path: <birth path>, line: <birth line>, constant: <site>, names: [name], group: <type>, weight: 1)`. Its tests use fixture rows of this form, and `RunDirectory#type_signals` is ticket B's, so ticket A and ticket B can be implemented in parallel; neither changes the other's files. Required work: 1. Read type signals from a saved run — check: present `def type_signals` in `plugins/os-sdlc/lib/os_sdlc/collaborator_pass/run_directory.rb` 2. Add `OsSdlc::CollaboratorPass::Meanings` and use it in the finding brief — check: present `Meanings.new` in `plugins/os-sdlc/lib/os_sdlc/collaborator_pass/prescription_brief.rb` 3. Use `Meanings` in the concept brief — check: present `Meanings.new` in `plugins/os-sdlc/lib/os_sdlc/collaborator_pass/concept_brief.rb` 4. Add `sharpen` and `glossary` to the schema text — check: present `sharpen:` in `plugins/os-sdlc/lib/os_sdlc/collaborator_pass/prescription_brief.rb` 5. Add `sharpen` and `glossary` members to `Recipe` — check: present `:glossary` in `plugins/os-sdlc/lib/os_sdlc/collaborator_pass/recipe.rb` 6. Add `RecipeCheck::SharpenRules` with the four rules — check: present `SharpenRules.new` in `plugins/os-sdlc/lib/os_sdlc/collaborator_pass/recipe_check.rb` 7. Explain `meanings`, `sharpen`, `glossary`, `kind: domain|programming`, and the canonical meaning in the prescriber prompt, and add the four rules to its rule list — check: present `canonical meaning` in `plugins/os-sdlc/skills/collaborator-pass/references/prompts/prescribe.md` 8. Drop the path and node hint from the `rename` entry `when` — check: absent `(path and node)` in `plugins/os-sdlc/references/collaborator-recipes.yml` 9. List glossary entries under `Orchestrator work:` in the ticket body — check: present `GLOSSARY.md` in `plugins/os-sdlc/lib/os_sdlc/collaborator_pass/ticket_draft/approach.rb` Orchestrator work: create the root `GLOSSARY.md` and make `docs/agents/domain.md` point to it; both are outside the os-sdlc target. After this ticket ships, re-measure with `bin/collaborator-pass measure --runs docs/crc/os-sdlc/collaborator-runs` and let the loop prescribe the `run` rename. ## Acceptance criteria 1. Given a saved run with a `name_collision` finding and its type signals, when `prescribe-brief --subject` runs for it, then the brief has a `meanings` list with one entry per type, and each entry has `type`, `born_at`, and `sites`. 2. Given a `rename` recipe for a `name_collision` finding with two meanings and one `sharpen` entry, when the recipe is validated, then the problems name the meaning that has no `sharpen` entry. 3. Given a `rename` recipe with a `domain` sharpen entry whose `avoid` is empty, when the recipe is validated, then there is a problem for that entry. 4. Given a `rename` recipe with a `domain` sharpen entry and no `glossary` entry with its term, when the recipe is validated, then there is a problem for the missing glossary entry. 5. Given a `rename` recipe whose `from` is the `term` of one meaning and whose target is a site of that meaning, when the recipe is validated, then there is a problem for that target. 6. Given a `rename` recipe with complete `sharpen` and `glossary` entries whose targets are only sites of the other meaning, when the recipe is validated, then there are no problems. 7. Given a `rename` recipe with two glossary entries, when `ticket-body` runs, then the `Orchestrator work:` line names `GLOSSARY.md` and `docs/agents/domain.md` and the body lists both entries. ## Owner sketch ```ruby class OsSdlc::CollaboratorPass::RunDirectory def type_signals end class OsSdlc::CollaboratorPass::Meanings def initialize(run, finding) def to_a def canonical(term) end OsSdlc::CollaboratorPass::Recipe = Data.define(:id, :finding, :subjects, :object, :targets, :renames, :expected_delta, :acceptance, :also_fits, :rationale, :sharpen, :glossary) class OsSdlc::CollaboratorPass::RecipeCheck::SharpenRules def initialize(recipe, meanings) def problems end class OsSdlc::CollaboratorPass::TicketDraft::Approach def initialize(recipe, entry) def to_s end ``` ## Non-goals - The rename of `run` to `arguments` in the `Crc` sites. The loop prescribes it after this ticket ships. - #1117 (`RunPath` built in the initializer). - The detector is ticket A. ## Origin - Trigger: collaborator-pass iteration 4 run 20261018T172139Z - Improvised this session: none - Chain: `node` reported and `run` not reported (`docs/crc/os-sdlc/collaborator-runs/20261018T172139Z/findings.yml`, `name_collision` `node`, evidence `path takers 2; node takers 3`) ← `NameCollisions` compares the `path` and `node` sides only (`SIDES` in `plugins/os-sdlc/lib/os_sdlc/collaborator_pass/name_collisions.rb`) ← `UseGroup` classifies a use by call shape, not by the class of the value (`plugins/os-sdlc/lib/os_sdlc/collaborator_pass/parameter_uses/use_group.rb`) ← DESIGN (`plugins/os-sdlc/lib/os_sdlc/collaborator_pass/name_collisions.rb`). The `run` meanings were seen by the prescriber in `docs/crc/os-sdlc/collaborator-runs/20261018T172139Z/recipes/collaborator_pass.yml` (rationale), and Jared ruled the detector and sharpening design on 2026-10-18 in this session. - Root candidate: none found; searched `name_collision`, `name collision`, `rename recipe`, `sharpen` in open issues - Where: `plugins/os-sdlc/lib/os_sdlc/collaborator_pass/name_collisions.rb`, `plugins/os-sdlc/lib/os_sdlc/collaborator_pass/parameter_uses/use_group.rb` - Session: a71a2c2a-4943-47c4-8dd1-cc16fe42d120 - Transcript: /home/jared/.claude/projects/-home-jared-dev-cc-os/a71a2c2a-4943-47c4-8dd1-cc16fe42d120.jsonl
Author
Owner

Sibling: #1118 (ticket A gathers type signals; ticket B sharpens). Both ship before the collaborator-pass loop returns to the run name collision. They may be implemented in parallel.

Sibling: #1118 (ticket A gathers type signals; ticket B sharpens). Both ship before the collaborator-pass loop returns to the run name collision. They may be implemented in parallel.
Author
Owner

Work started in session 2 (acb1c3d0). Branch: ticket-1119. Pipeline: /os-sdlc:implement.

Work started in session 2 (acb1c3d0). Branch: ticket-1119. Pipeline: /os-sdlc:implement.
Author
Owner

Resolution

Done: Implementation 69 (poodr-ticket-implementation) reached merge-ready: RunDirectory#type_signals, Meanings, meanings in PrescriptionBrief and ConceptBrief, sharpen/glossary in schema and Recipe, RecipeCheck::SharpenRules (4 rules), prescriber prompt, recipe catalog when-text, glossary lines under Orchestrator work in TicketDraft::Approach. Two reroutes: a hand-fixed expected-order test defect, and a suite rerun after a load-caused wall-time overrun.

Evidence: Commit 0bb74dce on branch ticket-1119 (not merged). Suite: 2123 runs, 0 failures (gate 631, 46.7s). Gates passed: behavior-verifier 625, contract-auditor 634; required-work R1-R9 present.

Follow-ups: none: GLOSSARY.md and docs/agents/domain.md are orchestrator work for when the first rename recipe with glossary entries is accepted (handoff step 2).

Needs review: Review session reads the ticket-1119 worktree diff (commit 0bb74dce) before /os:worktree finish, per handoff 2026-10-18-1910. Check: Meanings has no #canonical from the owner sketch; SharpenRules uses sites_of(type) instead.

## Resolution **Done:** Implementation 69 (poodr-ticket-implementation) reached merge-ready: RunDirectory#type_signals, Meanings, meanings in PrescriptionBrief and ConceptBrief, sharpen/glossary in schema and Recipe, RecipeCheck::SharpenRules (4 rules), prescriber prompt, recipe catalog when-text, glossary lines under Orchestrator work in TicketDraft::Approach. Two reroutes: a hand-fixed expected-order test defect, and a suite rerun after a load-caused wall-time overrun. **Evidence:** Commit 0bb74dce on branch ticket-1119 (not merged). Suite: 2123 runs, 0 failures (gate 631, 46.7s). Gates passed: behavior-verifier 625, contract-auditor 634; required-work R1-R9 present. **Follow-ups:** none: GLOSSARY.md and docs/agents/domain.md are orchestrator work for when the first rename recipe with glossary entries is accepted (handoff step 2). Needs review: Review session reads the ticket-1119 worktree diff (commit 0bb74dce) before /os:worktree finish, per handoff 2026-10-18-1910. Check: Meanings has no #canonical from the owner sketch; SharpenRules uses sites_of(type) instead.
Author
Owner

Review item resolved (orchestrator, Jared AFK): accept Meanings without #canonical(term). The term-to-type lookup needs the recipe's sharpen entries, so it belongs in SharpenRules#canonical_sites, which holds the recipe. Meanings#sites_of(type) keeps Meanings dependent only on the run and the finding. AC 5 covers the rule and passes. No correction ticket.

Review item resolved (orchestrator, Jared AFK): accept Meanings without #canonical(term). The term-to-type lookup needs the recipe's sharpen entries, so it belongs in SharpenRules#canonical_sites, which holds the recipe. Meanings#sites_of(type) keeps Meanings dependent only on the run and the finding. AC 5 covers the rule and passes. No correction ticket.
jared closed this issue 2026-10-18 20:13:44 +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#1119
No description provided.