Add the structure-change map and structure-changer agent #1107

Closed
opened 2026-10-18 16:24:52 +00:00 by jared · 3 comments
Owner

Problem

No map fits a structure-only ticket (rename, move, split).
Such tickets run on poodr-ticket-implementation, which asks for a red round, or bypass the pipeline by hand.
Runs 58 and 60 are the recurring misfit for which map-router drafts maps.

Reproduce

n/a: new map; nothing exists to reproduce.

Approach

Add plugins/os-sdlc/maps/structure-change.yaml: requires_category: structure, entries [structure-changer], and a fits: sentence so map-router can pick it on a reroute.
The map has one node: agent: structure-changer, verdict.source: gate, gates [required-work, lint, test-lint, suite, unchanged].
Decision (retired tests): the map sets ticket_shape: true, so retire_test_files! in lib/os_sdlc/implementation/open.rb deletes the tests listed under ## Retired tests at open, and the unchanged gate subtracts the same list. The structure-changer never deletes listed tests. A structure ticket therefore carries Approach, Acceptance criteria and Owner sketch sections.
Edges: pass to merge-ready; fail to a self-loop with bound 2; escalate; error.
Add plugins/os-sdlc/agents/structure-changer.md (model sonnet). It copies the wave 4 and wave 5 steps of skills/crc-refactor/references/prompts/implementation.md word for word, without the ledger columns:

  1. Run issue-show. Confirm that every old path and constant exists and every new one does not. Otherwise escalate stale_ticket.
  2. git mv the file and rename the constant with ast-grep through os-sdlc:code-write. Grep for the old paths, including .rubocop.yml Exclude globs.
  3. Move and rename the mirrored test. Change no assertion.
  4. Run os-sdlc-gate DISPATCH_ID until it is green. The agent gets two repair attempts.
  5. Submit the handoff. The Runner commits.
    In skills/implement/SKILL.md line 55 (a prose rule; no lib code resolves it), state: MAP is the map argument when given, else structure-change when the ticket has label category/structure, else poodr-ticket-implementation. Add structure-change to the allowed values. implementation-open already refuses a category mismatch (check_category!), so a wrong label fails loudly.

Required work:

  1. Add the map — check: present requires_category: structure in plugins/os-sdlc/maps/structure-change.yaml
  2. Add the agent — check: present stale_ticket in plugins/os-sdlc/agents/structure-changer.md
  3. Default the map by category — check: present structure-change in plugins/os-sdlc/skills/implement/SKILL.md
  4. Honor retired tests through ticket shape — check: present ticket_shape: true in plugins/os-sdlc/maps/structure-change.yaml
  5. Bound the self-loop repairs — check: present bound: 2 in plugins/os-sdlc/maps/structure-change.yaml
  6. Name the unchanged gate on the node — check: present unchanged in plugins/os-sdlc/maps/structure-change.yaml
  7. Copy the wave 4 and wave 5 steps — check: present os-sdlc-gate in plugins/os-sdlc/agents/structure-changer.md

Acceptance criteria

  1. Given a ticket labeled category/structure, when /os-sdlc:implement runs without a map argument, then the run opens on structure-change.
  2. Given a ticket labeled category/code-change, when os-sdlc-implementation-open runs with structure-change, then it refuses the run.
  3. Given a structure ticket whose new path already exists, when the structure-changer starts, then it escalates stale_ticket.
  4. Given a structure ticket that moves a file and its test, when all five gates pass, then the run reaches merge-ready.
  5. Given a failing gate, when the structure-changer has used two repairs, then the node escalates.
  6. Given a ticket with a ## Retired tests section, when the run starts, then the listed tests are retired as the recorded decision says.

Owner sketch

requires_category: structure
ticket_shape: true
entries: [structure-changer]

Blocking edges

Blocked by #1105 (category/structure and the categorize gate) and by #1106 (the unchanged gate).

Origin

  • Trigger: scope memo on why CRC and collaborator-pass structure tickets misroute (structure-ticket-route-scope.md, 2026-10-18)
  • Improvised this session: none
  • Chain: structure tickets run on a map built for behavior change ← no structure map exists ← DESIGN (maps in plugins/os-sdlc/maps cover code-change only)
  • Root candidate: #1105
  • Where: plugins/os-sdlc/maps/
  • Session: 26783407-6911-48d5-a818-55fbfbc70108
  • Transcript: /home/jared/.claude/projects/-home-jared-dev-cc-os/26783407-6911-48d5-a818-55fbfbc70108.jsonl

VERDICT: CREATE

## Problem No map fits a structure-only ticket (rename, move, split). Such tickets run on `poodr-ticket-implementation`, which asks for a red round, or bypass the pipeline by hand. Runs 58 and 60 are the recurring misfit for which map-router drafts maps. ## Reproduce n/a: new map; nothing exists to reproduce. ## Approach Add `plugins/os-sdlc/maps/structure-change.yaml`: `requires_category: structure`, entries `[structure-changer]`, and a `fits:` sentence so map-router can pick it on a reroute. The map has one node: `agent: structure-changer`, `verdict.source: gate`, gates `[required-work, lint, test-lint, suite, unchanged]`. Decision (retired tests): the map sets `ticket_shape: true`, so `retire_test_files!` in `lib/os_sdlc/implementation/open.rb` deletes the tests listed under `## Retired tests` at open, and the `unchanged` gate subtracts the same list. The structure-changer never deletes listed tests. A structure ticket therefore carries Approach, Acceptance criteria and Owner sketch sections. Edges: `pass` to `merge-ready`; `fail` to a self-loop with bound 2; `escalate`; `error`. Add `plugins/os-sdlc/agents/structure-changer.md` (model sonnet). It copies the wave 4 and wave 5 steps of `skills/crc-refactor/references/prompts/implementation.md` word for word, without the ledger columns: 1. Run `issue-show`. Confirm that every old path and constant exists and every new one does not. Otherwise escalate `stale_ticket`. 2. `git mv` the file and rename the constant with ast-grep through `os-sdlc:code-write`. Grep for the old paths, including `.rubocop.yml` `Exclude` globs. 3. Move and rename the mirrored test. Change no assertion. 4. Run `os-sdlc-gate DISPATCH_ID` until it is green. The agent gets two repair attempts. 5. Submit the handoff. The Runner commits. In `skills/implement/SKILL.md` line 55 (a prose rule; no lib code resolves it), state: MAP is the `map` argument when given, else `structure-change` when the ticket has label `category/structure`, else `poodr-ticket-implementation`. Add `structure-change` to the allowed values. `implementation-open` already refuses a category mismatch (`check_category!`), so a wrong label fails loudly. Required work: 1. Add the map — check: present `requires_category: structure` in `plugins/os-sdlc/maps/structure-change.yaml` 2. Add the agent — check: present `stale_ticket` in `plugins/os-sdlc/agents/structure-changer.md` 3. Default the map by category — check: present `structure-change` in `plugins/os-sdlc/skills/implement/SKILL.md` 4. Honor retired tests through ticket shape — check: present `ticket_shape: true` in `plugins/os-sdlc/maps/structure-change.yaml` 5. Bound the self-loop repairs — check: present `bound: 2` in `plugins/os-sdlc/maps/structure-change.yaml` 6. Name the unchanged gate on the node — check: present `unchanged` in `plugins/os-sdlc/maps/structure-change.yaml` 7. Copy the wave 4 and wave 5 steps — check: present `os-sdlc-gate` in `plugins/os-sdlc/agents/structure-changer.md` ## Acceptance criteria 1. Given a ticket labeled `category/structure`, when `/os-sdlc:implement` runs without a `map` argument, then the run opens on `structure-change`. 2. Given a ticket labeled `category/code-change`, when `os-sdlc-implementation-open` runs with `structure-change`, then it refuses the run. 3. Given a structure ticket whose new path already exists, when the structure-changer starts, then it escalates `stale_ticket`. 4. Given a structure ticket that moves a file and its test, when all five gates pass, then the run reaches `merge-ready`. 5. Given a failing gate, when the structure-changer has used two repairs, then the node escalates. 6. Given a ticket with a `## Retired tests` section, when the run starts, then the listed tests are retired as the recorded decision says. ## Owner sketch ```yaml requires_category: structure ticket_shape: true entries: [structure-changer] ``` ## Blocking edges Blocked by #1105 (category/structure and the categorize gate) and by #1106 (the unchanged gate). ## Origin - Trigger: scope memo on why CRC and collaborator-pass structure tickets misroute (structure-ticket-route-scope.md, 2026-10-18) - Improvised this session: none - Chain: structure tickets run on a map built for behavior change ← no structure map exists ← DESIGN (maps in plugins/os-sdlc/maps cover code-change only) - Root candidate: #1105 - Where: plugins/os-sdlc/maps/ - Session: 26783407-6911-48d5-a818-55fbfbc70108 - Transcript: /home/jared/.claude/projects/-home-jared-dev-cc-os/26783407-6911-48d5-a818-55fbfbc70108.jsonl VERDICT: CREATE
Author
Owner

Work started on branch ticket-1107 via /os-sdlc:implement. Blockers #1105 and #1106 are closed.

Work started on branch ticket-1107 via /os-sdlc:implement. Blockers #1105 and #1106 are closed.
Author
Owner

Run 67 escalated at change-auditor: the ticket deferred the retired-tests decision and AC2-AC5 had no checks. Decision recorded as ticket_shape: true on the map. Required work 4-7 added. Rerouting.

Run 67 escalated at change-auditor: the ticket deferred the retired-tests decision and AC2-AC5 had no checks. Decision recorded as ticket_shape: true on the map. Required work 4-7 added. Rerouting.
Author
Owner

Resolution

Done: maps/structure-change.yaml: one structure-changer node, requires_category structure, ticket_shape true, gates [required-work, lint, test-lint, suite, unchanged], fail self-loop bound 2, fits sentence for map-router. agents/structure-changer.md (sonnet): stale_ticket precheck, git mv plus ast-grep rename through code-write, rubocop Exclude glob check, mirrored test move, two repairs. /os-sdlc:implement defaults MAP to structure-change when the ticket carries category/structure.

Evidence: ticket-1107 branch: Runner commit (map + open_structure_change_test + structure_change_routing_test) plus hand commit for the agent and SKILL.md; run 67: 14 dispatches, 2 retries, 12 min 1 s; suite 2115 runs green on re-run (first run tripped the 47s budget at 49.1s, load 1.4); contract-auditor pass.

Follow-ups: Batch intake (several structure tickets per run) and CRC-loop retirement wait on Jared's rulings 2 and 3 (predicted: splits are structure; one route). Runner commit omitted files not in the handoff items; captured this session. Suite wall-time budget 47s is at its edge after #1104 (49.1s then 34.2s); not filed, watch.

## Resolution **Done:** maps/structure-change.yaml: one structure-changer node, requires_category structure, ticket_shape true, gates [required-work, lint, test-lint, suite, unchanged], fail self-loop bound 2, fits sentence for map-router. agents/structure-changer.md (sonnet): stale_ticket precheck, git mv plus ast-grep rename through code-write, rubocop Exclude glob check, mirrored test move, two repairs. /os-sdlc:implement defaults MAP to structure-change when the ticket carries category/structure. **Evidence:** ticket-1107 branch: Runner commit (map + open_structure_change_test + structure_change_routing_test) plus hand commit for the agent and SKILL.md; run 67: 14 dispatches, 2 retries, 12 min 1 s; suite 2115 runs green on re-run (first run tripped the 47s budget at 49.1s, load 1.4); contract-auditor pass. **Follow-ups:** Batch intake (several structure tickets per run) and CRC-loop retirement wait on Jared's rulings 2 and 3 (predicted: splits are structure; one route). Runner commit omitted files not in the handoff items; captured this session. Suite wall-time budget 47s is at its edge after #1104 (49.1s then 34.2s); not filed, watch.
jared closed this issue 2026-10-18 17:22:55 +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#1107
No description provided.