os-backlog: route inspect should classify issue shape and default to split, not migrate #26

Closed
opened 2026-07-13 13:14:37 +00:00 by jared · 2 comments
Owner

While running /os-status:fix -> /os-backlog:route on the servers umbrella repo, os-backlog inspect found an active Forgejo remote with 3 open issues (#4-#6) forming a sequential deployment chain (prereqs -> deploy -> cutover -> verify -> decide) with triage/blocked/triage/hitl dependency labels. The user had already chosen Planka as the tracker for new work, which raised the question: migrate the existing issues into Planka, or keep both?

The right call (per the boundary rule already stated in route's own SKILL.md, and per the cc-os ADR that "git issues = specs" / "Planka = state") was to not migrate — split by kind: planka:servers for new ad hoc backlog capture, Firecrawl issue chain stays in Forgejo as-is. But nothing in the skill or inspect output surfaced that as the recommended path; it took manual inspection (tea issue list --state all, reading labels/titles) to notice the issues were a spec chain rather than flat ad hoc items.

Suggestions:

  1. Classify issues during inspect, not just count them. inspect already fetches title/labels via tea/gh — cheap heuristics (sequential numbering, blocked/depends-on-style labels, cross-references between issue bodies) can flag "this looks like a spec chain" vs. "this looks like flat ad hoc items," and pre-populate the step-2 proposal instead of leaving the caller to eyeball it. Concretely: add an issue_shape: "sequential-chain" | "flat-adhoc" | "mixed" field to inspect's JSON output.

  2. Make "don't migrate, split by kind" a first-class recommendation, not just an option buried in the boundary-rule prose. The skill's decision gate currently frames the choice as "propose ONE destination tracker key," which nudges toward picking a single winner even when the existing tracker already fits its content. Add an explicit branch: "existing tracker already fits its content type -> recommend split (Planka for new/ephemeral, git issues stay as-is), write only the Planka key, skip migration entirely."

  3. Link the ADR. The boundary rule in route's SKILL.md (Planka = state, git issues = specs, card-as-pointer + issue-chain-as-spec for hybrid work) restates a cc-os ADR without citing it. Point /os-backlog:route at that ADR by number/link so the rule has a traceable source instead of re-derived prose that can drift from the decision it's based on.

Context: this surfaced in the servers repo (jared/servers) during a routine /os-status:fix run, 2026-07-13.

While running /os-status:fix -> /os-backlog:route on the `servers` umbrella repo, `os-backlog inspect` found an active Forgejo remote with 3 open issues (#4-#6) forming a sequential deployment chain (prereqs -> deploy -> cutover -> verify -> decide) with `triage/blocked`/`triage/hitl` dependency labels. The user had already chosen Planka as the tracker for new work, which raised the question: migrate the existing issues into Planka, or keep both? The right call (per the boundary rule already stated in `route`'s own SKILL.md, and per the cc-os ADR that "git issues = specs" / "Planka = state") was to *not* migrate — split by kind: `planka:servers` for new ad hoc backlog capture, Firecrawl issue chain stays in Forgejo as-is. But nothing in the skill or `inspect` output surfaced that as the recommended path; it took manual inspection (`tea issue list --state all`, reading labels/titles) to notice the issues were a spec chain rather than flat ad hoc items. Suggestions: 1. **Classify issues during `inspect`, not just count them.** `inspect` already fetches title/labels via `tea`/`gh` — cheap heuristics (sequential numbering, `blocked`/`depends-on`-style labels, cross-references between issue bodies) can flag "this looks like a spec chain" vs. "this looks like flat ad hoc items," and pre-populate the step-2 proposal instead of leaving the caller to eyeball it. Concretely: add an `issue_shape: "sequential-chain" | "flat-adhoc" | "mixed"` field to `inspect`'s JSON output. 2. **Make "don't migrate, split by kind" a first-class recommendation**, not just an option buried in the boundary-rule prose. The skill's decision gate currently frames the choice as "propose ONE destination tracker key," which nudges toward picking a single winner even when the existing tracker already fits its content. Add an explicit branch: *"existing tracker already fits its content type -> recommend split (Planka for new/ephemeral, git issues stay as-is), write only the Planka key, skip migration entirely."* 3. **Link the ADR.** The boundary rule in `route`'s SKILL.md (Planka = state, git issues = specs, card-as-pointer + issue-chain-as-spec for hybrid work) restates a cc-os ADR without citing it. Point `/os-backlog:route` at that ADR by number/link so the rule has a traceable source instead of re-derived prose that can drift from the decision it's based on. Context: this surfaced in the `servers` repo (jared/servers) during a routine `/os-status:fix` run, 2026-07-13.
Author
Owner

Codex review adopted (pre-implementation, 2026-07-13):

  1. inspect only counts issues today (tea/gh fetch no titles/labels) — add an explicit metadata fetch (number, title, labels, body) in bin/os-backlog; the issue's 'already fetches' premise was wrong.
  2. Keep Backlog::Inspector filesystem-only; classification is a pure classify_issue_shape(issue_records) fn; CLI does the network collection.
  3. Explicit small-set thresholds (0–2 issues → null/flat, distinguish 'no evidence' from 'no metadata fetched').
  4. Cross-reference detection bounded to the fetched issue-number set + dependency-language proximity (avoid 'fixed in #12' false positives).
  5. Label heuristic as an allowlist (blocked/depends-on/prereq/waiting …) with positive+negative tests, not a bare regex.
  6. issue_shape always present in inspect JSON: one of sequential-chain|flat-adhoc|mixed|null — never omitted.
  7. Split wording preserves ADR-0033's single-tracker-key rule: one declared tracker (planka:) for new capture; existing git issues stay unmigrated — not 'two destinations'.
  8. Step 3 migration trigger gets an explicit split exception so planka-tracker-with-forgejo-specs-by-design never re-triggers migration.
  9. ADR-0033 cited at the top of the boundary-rule section.
  10. Tests cover the CLI-level issue_shape contract, not just the pure classifier.
**Codex review adopted (pre-implementation, 2026-07-13):** 1. inspect only counts issues today (tea/gh fetch no titles/labels) — add an explicit metadata fetch (number, title, labels, body) in bin/os-backlog; the issue's 'already fetches' premise was wrong. 2. Keep Backlog::Inspector filesystem-only; classification is a pure classify_issue_shape(issue_records) fn; CLI does the network collection. 3. Explicit small-set thresholds (0–2 issues → null/flat, distinguish 'no evidence' from 'no metadata fetched'). 4. Cross-reference detection bounded to the fetched issue-number set + dependency-language proximity (avoid 'fixed in #12' false positives). 5. Label heuristic as an allowlist (blocked/depends-on/prereq/waiting …) with positive+negative tests, not a bare regex. 6. issue_shape always present in inspect JSON: one of sequential-chain|flat-adhoc|mixed|null — never omitted. 7. Split wording preserves ADR-0033's single-tracker-key rule: one declared tracker (planka:) for new capture; existing git issues stay unmigrated — not 'two destinations'. 8. Step 3 migration trigger gets an explicit split exception so planka-tracker-with-forgejo-specs-by-design never re-triggers migration. 9. ADR-0033 cited at the top of the boundary-rule section. 10. Tests cover the CLI-level issue_shape contract, not just the pure classifier.
Author
Owner

Implemented in 9415eb0: inspect metadata fetch + always-present issue_shape (pure classifier, fail-soft null), route step 2 rewritten with split-as-default for spec-shaped issue sets (single tracker key preserved), step-3 never-re-trigger exception, ADR-0033 cited from the boundary rule. 12 new tests incl. CLI contract; suite 103 runs / 0 failures. All 10 adopted review points implemented.

Implemented in 9415eb0: inspect metadata fetch + always-present issue_shape (pure classifier, fail-soft null), route step 2 rewritten with split-as-default for spec-shaped issue sets (single tracker key preserved), step-3 never-re-trigger exception, ADR-0033 cited from the boundary rule. 12 new tests incl. CLI contract; suite 103 runs / 0 failures. All 10 adopted review points implemented.
jared closed this issue 2026-07-13 14:35:23 +00:00
Sign in to join this conversation.
No description provided.