Skip to content

Deepen issue labels into one labels module, ending the case-sensitive needs-triage check - #318

Merged
JacobStephens2 merged 3 commits into
mainfrom
issue-317
Oct 3, 2026
Merged

JacobStephens2 merged 3 commits into
mainfrom
issue-317

Conversation

@JacobStephens2

Copy link
Copy Markdown
Owner

Summary

Every label rule now lives in one labels module. An issue's labels are a Labels value that hides its list, and every question it answers ignores case. Marking an Architect plan ready no longer keeps a Needs-Triage spelled in another case, which used to reject the plan.

 src/
+├── labels.rs     # Label (name, description; prints as its name), Labels (has, spelled, unready, swapped)
+│                 # NEEDS_TRIAGE, READY_FOR_AGENT, UNREADY
 ├── github.rs     # the adapter: reads Labels, writes one Labels set per request, lists/creates by Label
-│                 # has_label, label_as_spelled, drop_label, set_labels_adding
 ├── claim.rs      # IN_PROGRESS: Label
 ├── base_fix.rs   # BASE_FIX: Label
 ├── architect.rs  # ARCHITECT_PLAN: Label
-└── spec_run.rs   # NEEDS_TRIAGE, READY_FOR_AGENT, UNREADY_LABELS, unready_label
+└── spec_run.rs
 mark_plan_ready
-  kept = issue.labels.retain(!= "needs-triage")     # case-sensitive
+  kept = issue.labels.swapped(off: [NEEDS_TRIAGE], on: [])
   refuse if kept.unready()
-  set_labels_adding(kept, [ready-for-agent, architect-plan])
+  set_labels(kept.swapped(off: [], on: [READY_FOR_AGENT, ARCHITECT_PLAN]))

The Claim's make and release go through the same pure swapped, followed by one PUT. Every gh call and progress line stays the same, in the same order.

Evidence

  • Before: a_plan_labelled_needs_triage_in_another_case_is_marked_ready_and_dispatched (repo label Needs-Triage, run thirdshift architect) fails: the plan is rejected as labelled needs-triage.
    After: it passes. The plan is labelled architect-plan, in-progress, dispatched, and a PR is opened.
  • The new unit tests in src/labels.rs cover has and spelled-as in mixed case, the Unready Ticket label in any case, taking off, the Claim's swap and its release, and putting on a label that is already there.
  • cargo test (30 suites), cargo clippy --all-targets -- -D warnings and cargo fmt --check all pass. No generated prompt changed.

Merge Danger

Door: two-way

This is an in-process refactor plus one bug fix, with no data or schema change. Reverting it is enough to undo it.

Blast Radius: labels

Every label read and write goes through the new module: the Claim, the Pickup run, the Spec run, the Architect run and the Base fix. The existing end-to-end tests cover each one unchanged.

Unaddressed findings

Standards

  • Descriptions on labels never created (needs-triage, the Unready labels): skipped. The spec says each Label carries its description, and the text comes from docs/agents/triage-labels.md.
  • Two-step swap in the Architect plan (swapped with an empty slice): skipped. The Unready check has to run between taking needs-triage off and putting the ready labels on.
  • The fake gh and integration tests keep their own case matching and &str label constants: skipped. They sit on the far side of the binary's seam, and the spec keeps the existing tests unchanged.

Spec

  • Labels::names() is reachable by any caller: skipped. The GitHub adapter needs the spellings to write them, and Rust has no friend visibility. Its doc limits it to writing. The case-sensitive PartialEq was removed, so == on Labels no longer compiles.
  • github::remove_label takes &str, not Label: skipped. It deletes the label as the issue spells it, which only that issue's Labels::spelled knows. That keeps the request the same as today.
  • The spec_run unit tests changed how they build labels: no change needed. The type change forces it, and the assertions are unchanged.

Closes #317

🤖 Generated with Claude Code

JacobStephens2 and others added 3 commits October 3, 2026 02:14
… needs-triage check

An issue's labels are now a Labels value that hides its list and answers
every question without case, and each label thirdshift knows is a Label
carrying its description. Marking an Architect plan ready takes needs-triage
off whatever its case.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…el names, Labels without a case-sensitive ==

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@JacobStephens2
JacobStephens2 merged commit 8e88895 into main Oct 3, 2026
13 checks passed
@JacobStephens2
JacobStephens2 deleted the issue-317 branch October 3, 2026 06:34
@JacobStephens2 JacobStephens2 mentioned this pull request Oct 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Deepen issue labels into one labels module, ending the case-sensitive needs-triage check

1 participant