Add Project and Label, then delete the old issue backends #1621

Closed
opened 2026-11-06 20:06:25 +00:00 by jared · 5 comments
Owner

Problem

The project commands, label commands, wakeup, and session note still use the old classes. The old backends stay in the tree until these move.

Approach

Add Project and Label. Move wakeup and the session note to them. Delete Issues, IssuesTracker, and the old backends. Keep hooks/session_start.rb, because it is live. This slice also does the work of #1040, because Project becomes the one owner of the tracker lookup. Close #1040 when this slice ships. #1594 runs first, because it changes the remote reads in project_index. Owned rules: inventory 1.7 (reserved prefixes, ten categories, one category).

Required work:

  1. Add Project — check: present class Project in plugins/os-backlog/lib/backlog/**/*.rb
  2. Add Label with scope and sync — check: present class Label in plugins/os-backlog/lib/backlog/**/*.rb
  3. Move wakeup and SessionNote to the new objects.
  4. Delete Issues, IssuesTracker, and the old backends — check: absent IssuesTracker in plugins/os-backlog/lib/backlog/**/*.rb
  5. Fix inventory defect 16 and defect 20.
  6. Remove the forwarders Tracker.valid?, Tracker.kind, and Tracker.issues_destination. Callers use Tracker::Address. Delete issues_destination, which has no library caller. Move their test pins to tests/tracker/address_test.rb. — check: absent def self.kind in plugins/os-backlog/lib/backlog/tracker.rb
  7. Stage the Resolution in Ticket#close and #request_review, and let Tracker#write_comments read posted comments and pass them to a pure Ticket method (lens A11, signal at ticket.rb:49,59). A missing-parts refusal must still come before any write. Apply the same rule at ticket/claiming.rb:43: return_to_queue returns whether it posted before save, so pass the comments in from Claim and IssueTarget.
  8. Delete IssueDraft and move PRIORITY_LABELS from Issues to Ticket; the priority rule stays only in Ticket::CreateGates (lens A12) — check: absent IssueDraft in plugins/os-backlog/lib/backlog/**/*.rb
  9. Move CategoryLabels to Label and delete issue_create.rb (lens A15). Callers: ticket.rb, canonical_labels.rb, ticket/label_set.rb, ticket/create_gates.rb, ticket/draft.rb, cli/tracker_issues.rb — check: absent class IssueCreate in plugins/os-backlog/lib/backlog/**/*.rb
  10. Change the takedown eval plugins/os-sdlc/eval/ticket-takedown/lib/takedown/adapter/backlog_tracker.rb to Project and Ticket, because it calls Backlog::Issues.build. Slice 10 still moves it to the CLI. — check: absent Backlog::Issues in plugins/os-sdlc/eval/ticket-takedown/lib/takedown/adapter/backlog_tracker.rb

Ruling 78: no shared cc-os gem in this slice. Project stays in os-backlog and owns its reader, with no behavior change. plugins/os-sdlc/tests/crc/tickets_bin_test.rb already runs through Ticket::Draft.

Acceptance criteria

  1. Given no tracker key, when a command needs a tracker, then Project refuses with the same message as before the port.
  2. Given a config file with comments, when config-write runs, then the comments and blank lines stay.
  3. Given validate-template on a passing ticket, when it runs, then it prints a confirmation line (defect 20).
  4. Given a project on any host, when a session starts, then the session note matches the note before the port.
  5. Given a project with wakeup=true, when bin/wakeup-poll runs, then it reaches the same tracker and gives the same result as before the port.
  6. Given close with a missing resolution part, when it runs, then it refuses before any write, and Tracker#save receives no comment.
  7. Given a ticket that already holds its resolution comment, when close or close --needs-review runs again, then Tracker#save posts no second comment, and the first comment keeps the same text as before the port.
  8. Given a ticket that already holds the bounce comment, when return_to_queue runs through Claim or IssueTarget, then Tracker#save posts no second comment, and the caller gets the same result as before the port.

Owner sketch

class Backlog::Project
  def self.current(root)
  def self.all
  def self.from_config(text)
  def tracker
  def configure(address)
  def inspect_tracking
  def route
class Backlog::Label
  def self.scope(tracker)
  def self.sync(tracker)

Non-goals

Do not rename a command before slice 9. Do not change ## Resolution, **Follow-ups:**, the body headings, the check form, the label names, or the issue-show JSON keys. Do not make a behavior change that this ticket does not name.

Blocking edges

Blocked by #1620
Blocked by #1594

Origin

  • Trigger: port plan, section 5 of docs/system-design-format/proof/2026-11-06-os-backlog-domain-objects.md, slice 8
  • Improvised this session: none
  • Chain: os-backlog code has no domain objects ← commands own their own reads and writes ← DESIGN (ADR-0307, plugins/os-backlog/CONTEXT.md)
  • Root candidate: none found; searched Project, Label, IssuesTracker, config (#1040 and #1039 are narrower pieces that this slice absorbs)
  • Where: plugins/os-backlog/lib/backlog/project_index.rb, plugins/os-backlog/lib/backlog/config.rb, plugins/os-backlog/lib/backlog/issues.rb, plugins/os-backlog/lib/backlog/issues_tracker.rb
  • Session: 9d8c2e15-00c1-4dec-b177-e749fa05ec67
  • Transcript: /home/jared/.claude/projects/-home-jared-dev-cc-os/9d8c2e15-00c1-4dec-b177-e749fa05ec67.jsonl

VERDICT: CREATE

## Problem The project commands, label commands, wakeup, and session note still use the old classes. The old backends stay in the tree until these move. ## Approach Add `Project` and `Label`. Move wakeup and the session note to them. Delete `Issues`, `IssuesTracker`, and the old backends. Keep `hooks/session_start.rb`, because it is live. This slice also does the work of #1040, because `Project` becomes the one owner of the tracker lookup. Close #1040 when this slice ships. #1594 runs first, because it changes the remote reads in `project_index`. Owned rules: inventory 1.7 (reserved prefixes, ten categories, one category). Required work: 1. Add `Project` — check: present `class Project` in `plugins/os-backlog/lib/backlog/**/*.rb` 2. Add `Label` with `scope` and `sync` — check: present `class Label` in `plugins/os-backlog/lib/backlog/**/*.rb` 3. Move wakeup and `SessionNote` to the new objects. 4. Delete `Issues`, `IssuesTracker`, and the old backends — check: absent `IssuesTracker` in `plugins/os-backlog/lib/backlog/**/*.rb` 5. Fix inventory defect 16 and defect 20. 6. Remove the forwarders `Tracker.valid?`, `Tracker.kind`, and `Tracker.issues_destination`. Callers use `Tracker::Address`. Delete `issues_destination`, which has no library caller. Move their test pins to `tests/tracker/address_test.rb`. — check: absent `def self.kind` in `plugins/os-backlog/lib/backlog/tracker.rb` 7. Stage the Resolution in `Ticket#close` and `#request_review`, and let `Tracker#write_comments` read posted comments and pass them to a pure `Ticket` method (lens A11, signal at `ticket.rb:49,59`). A missing-parts refusal must still come before any write. Apply the same rule at `ticket/claiming.rb:43`: `return_to_queue` returns whether it posted before save, so pass the comments in from `Claim` and `IssueTarget`. 8. Delete `IssueDraft` and move `PRIORITY_LABELS` from `Issues` to `Ticket`; the priority rule stays only in `Ticket::CreateGates` (lens A12) — check: absent `IssueDraft` in `plugins/os-backlog/lib/backlog/**/*.rb` 9. Move `CategoryLabels` to `Label` and delete `issue_create.rb` (lens A15). Callers: `ticket.rb`, `canonical_labels.rb`, `ticket/label_set.rb`, `ticket/create_gates.rb`, `ticket/draft.rb`, `cli/tracker_issues.rb` — check: absent `class IssueCreate` in `plugins/os-backlog/lib/backlog/**/*.rb` 10. Change the takedown eval `plugins/os-sdlc/eval/ticket-takedown/lib/takedown/adapter/backlog_tracker.rb` to `Project` and `Ticket`, because it calls `Backlog::Issues.build`. Slice 10 still moves it to the CLI. — check: absent `Backlog::Issues` in `plugins/os-sdlc/eval/ticket-takedown/lib/takedown/adapter/backlog_tracker.rb` Ruling 78: no shared cc-os gem in this slice. `Project` stays in os-backlog and owns its reader, with no behavior change. `plugins/os-sdlc/tests/crc/tickets_bin_test.rb` already runs through `Ticket::Draft`. ## Acceptance criteria 1. Given no tracker key, when a command needs a tracker, then `Project` refuses with the same message as before the port. 2. Given a config file with comments, when `config-write` runs, then the comments and blank lines stay. 3. Given `validate-template` on a passing ticket, when it runs, then it prints a confirmation line (defect 20). 4. Given a project on any host, when a session starts, then the session note matches the note before the port. 5. Given a project with `wakeup=true`, when `bin/wakeup-poll` runs, then it reaches the same tracker and gives the same result as before the port. 6. Given `close` with a missing resolution part, when it runs, then it refuses before any write, and `Tracker#save` receives no comment. 7. Given a ticket that already holds its resolution comment, when `close` or `close --needs-review` runs again, then `Tracker#save` posts no second comment, and the first comment keeps the same text as before the port. 8. Given a ticket that already holds the bounce comment, when `return_to_queue` runs through `Claim` or `IssueTarget`, then `Tracker#save` posts no second comment, and the caller gets the same result as before the port. ## Owner sketch ```ruby class Backlog::Project def self.current(root) def self.all def self.from_config(text) def tracker def configure(address) def inspect_tracking def route class Backlog::Label def self.scope(tracker) def self.sync(tracker) ``` ## Non-goals Do not rename a command before slice 9. Do not change `## Resolution`, `**Follow-ups:**`, the body headings, the check form, the label names, or the `issue-show` JSON keys. Do not make a behavior change that this ticket does not name. ## Blocking edges Blocked by #1620 Blocked by #1594 ## Origin - Trigger: port plan, section 5 of `docs/system-design-format/proof/2026-11-06-os-backlog-domain-objects.md`, slice 8 - Improvised this session: none - Chain: os-backlog code has no domain objects ← commands own their own reads and writes ← DESIGN (ADR-0307, `plugins/os-backlog/CONTEXT.md`) - Root candidate: none found; searched Project, Label, IssuesTracker, config (#1040 and #1039 are narrower pieces that this slice absorbs) - Where: plugins/os-backlog/lib/backlog/project_index.rb, plugins/os-backlog/lib/backlog/config.rb, plugins/os-backlog/lib/backlog/issues.rb, plugins/os-backlog/lib/backlog/issues_tracker.rb - Session: 9d8c2e15-00c1-4dec-b177-e749fa05ec67 - Transcript: /home/jared/.claude/projects/-home-jared-dev-cc-os/9d8c2e15-00c1-4dec-b177-e749fa05ec67.jsonl VERDICT: CREATE
Author
Owner

From #1615: Tracker.valid?, Tracker.kind, and Tracker.issues_destination only forward to Tracker::Address. Remove them here. Also move the two remaining address splits in issues.rb and issue_show.rb to Tracker::Address.slug, if those files survive.

From #1615: Tracker.valid?, Tracker.kind, and Tracker.issues_destination only forward to Tracker::Address. Remove them here. Also move the two remaining address splits in issues.rb and issue_show.rb to Tracker::Address.slug, if those files survive.
Author
Owner

From #857: skills/route/SKILL.md lines 30, 41, 42, 52 and references/cross-project-filing.md line 23 still tell agents to run gh. Change them with the label work here.

From #857: skills/route/SKILL.md lines 30, 41, 42, 52 and references/cross-project-filing.md line 23 still tell agents to run gh. Change them with the label work here.
Author
Owner

Skeptic dropped a follow-up ticket for the os-sdlc raw .cc-os/config reads (depth-1 rule). Note for slice 10 (#1623): tracker/backlog.rb and tracker/issue_source/tracker_lookup.rb read the file directly and skip the subdirectory override lookup, so os-sdlc and os-backlog can resolve different trackers in one directory. No separate ticket exists, which changes the 'separate ticket' part of ruling 78.

Skeptic dropped a follow-up ticket for the os-sdlc raw .cc-os/config reads (depth-1 rule). Note for slice 10 (#1623): `tracker/backlog.rb` and `tracker/issue_source/tracker_lookup.rb` read the file directly and skip the subdirectory override lookup, so os-sdlc and os-backlog can resolve different trackers in one directory. No separate ticket exists, which changes the 'separate ticket' part of ruling 78.
Author
Owner

Work started on branch ticket-1621.

Work started on branch ticket-1621.
Author
Owner

Resolution

Done: Project owns the tracker lookup, config writes, inspect, route, wakeup, and the session note. Label owns scope labels, label sync, and CategoryLabels. Each Host absorbs its old backend. Issues, IssuesTracker, IssueDraft, IssueCreate, EnsureLabels, Tracker::Resolver, and the Tracker forwarders are deleted. Ticket::Outbox stages comments, and Tracker#save reads posted comments before its first write. Defects 16 and 20 are fixed. The takedown adapter uses Project and Ticket.

Evidence: main 1fb00d98 (pins 2420b148). On main: os-backlog 525 runs, os-sdlc 3502 runs, 0 failures; takedown 623 runs, 0 failures on the branch. Lint clean on all os-backlog production code and 37 changed test files. Read-only CLI commands (issue-show, issue-comments, labels, issues, inspect, projects, resolve) give the same output on the old and new builds. Implementations 257 (failed, #1298 occurrence) and 258 (hand-finished). Output changes are listed in the commit message.

Follow-ups: Slice 10 (#1623) moves the takedown adapter to the CLI and routes the os-sdlc raw .cc-os/config reads through os-backlog (note posted on this ticket). Hosts still default env: ENV (lens A6 holds for Project only): none, because bin entry scripts pass the environment and slice 10 revisits the adapters.

## Resolution **Done:** Project owns the tracker lookup, config writes, inspect, route, wakeup, and the session note. Label owns scope labels, label sync, and CategoryLabels. Each Host absorbs its old backend. Issues, IssuesTracker, IssueDraft, IssueCreate, EnsureLabels, Tracker::Resolver, and the Tracker forwarders are deleted. Ticket::Outbox stages comments, and Tracker#save reads posted comments before its first write. Defects 16 and 20 are fixed. The takedown adapter uses Project and Ticket. **Evidence:** main 1fb00d98 (pins 2420b148). On main: os-backlog 525 runs, os-sdlc 3502 runs, 0 failures; takedown 623 runs, 0 failures on the branch. Lint clean on all os-backlog production code and 37 changed test files. Read-only CLI commands (issue-show, issue-comments, labels, issues, inspect, projects, resolve) give the same output on the old and new builds. Implementations 257 (failed, #1298 occurrence) and 258 (hand-finished). Output changes are listed in the commit message. **Follow-ups:** Slice 10 (#1623) moves the takedown adapter to the CLI and routes the os-sdlc raw .cc-os/config reads through os-backlog (note posted on this ticket). Hosts still default env: ENV (lens A6 holds for Project only): none, because bin entry scripts pass the environment and slice 10 revisits the adapters.
jared closed this issue 2026-11-07 12:22:22 +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#1621
No description provided.