Skip to content

feat(dev-backlog): Phase 1b — sprint lifecycle track-awareness (#292)#307

Merged
sungjunlee merged 1 commit into
mainfrom
feat/multi-track-phase1b-lifecycle
Jul 12, 2026
Merged

feat(dev-backlog): Phase 1b — sprint lifecycle track-awareness (#292)#307
sungjunlee merged 1 commit into
mainfrom
feat/multi-track-phase1b-lifecycle

Conversation

@sungjunlee

Copy link
Copy Markdown
Owner

Summary

Implements #292 (Phase 1b) of the multi-track sprints initiative (epic #289, PRD §5.2): the sprint lifecycle — init, close, mirror — becomes track-aware. All overlap decisions consume the one shared scopesOverlap() from lib.js; no second overlap check exists.

sprint-init.js

  • Refusal changes from "any second active sprint" to "second active track whose scope overlaps an existing active track", named in the error: Active track overlaps on scope: <file>. …
  • New --scope "glob[,glob]" flag emits an explicit scope: ["…"] frontmatter line (D2 — scope is declared, never inferred). Omitted --scope emits nothing.
  • Cold-adopter path: scopeless new sprint next to a scopeless active track cannot be proven disjoint → warn-and-allow (warnings[] in the JSON result, Warning: lines in text), matching the doctor's informational stance. Disjoint tracks create without refusal.

sprint-close.sh

  • --track <slug> (slug or component: handle, via lib.sh resolve_track) picks which track to close out of a portfolio.
  • No flag + N>1 active still refuses (Refusing to close an ambiguous sprint) and now appends Pass --track <slug> to close one track.
  • No-match selector exits 1 listing the active tracks.

sprint-mirror.js

  • --track passes through to sprint-state.js --mode status --track <slug>; the :98 singular read is now selector-aware.
  • A portfolio without --track refuses: Multiple active tracks (a, b). Pass --track <slug> …; a no-match selector refuses naming it. N==1 default path unchanged.

Verification

Refs #292, #289.

🤖 Generated with Claude Code

Make init/close/mirror track-aware (PRD §5.2), all consuming the ONE
shared scopesOverlap() from lib.js:

- sprint-init.js: refusal changes from "any second active sprint" to
  "second active track whose scope overlaps an existing active track".
  New --scope "glob[,glob]" flag emits an explicit scope: frontmatter
  line (D2 — never inferred). Scopeless next to scopeless cannot be
  proven disjoint → warn-and-allow, matching the doctor's informational
  stance. Disjoint tracks are created without refusal.
- sprint-close.sh: --track <slug> picks which track to close; the
  ambiguous no-flag refusal remains and now hints at --track; a
  no-match selector fails loud listing active tracks.
- sprint-mirror.js: mirrors per track — --track passes through to
  sprint-state.js; a portfolio without --track refuses naming the
  active tracks; default unchanged when N==1.

G4: single-track init and close verified byte-identical against
origin/main (text, exit codes, and written/mutated files); the mirror's
no-track sprint-state invocation is assert-pinned unchanged. Smoke
grows Phase 1b fixtures (disjoint init, overlap refusal, close --track,
ambiguous-close hint, G4 init anchor): 187/187 pass.

Also fixes the pre-existing cwd-dependent sprint-init.test.js #13
("produces frontmatter compatible with find_active_sprint") by pinning
explicit hasCharter/hasCapabilities overrides (#258 rot, assigned here).

Refs #292, #289.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jul 12, 2026

Copy link
Copy Markdown

Warning

Review limit reached

@sungjunlee, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 48 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: f3a3b188-7fa7-4ae3-92de-ee513cdd74be

📥 Commits

Reviewing files that changed from the base of the PR and between b832ab2 and 897fbb0.

📒 Files selected for processing (7)
  • backlog/sprints/2026-07-multi-track-sprints.md
  • skills/dev-backlog/scripts/smoke-test.sh
  • skills/dev-backlog/scripts/sprint-close.sh
  • skills/dev-backlog/scripts/sprint-init.js
  • skills/dev-backlog/scripts/sprint-init.test.js
  • skills/dev-backlog/scripts/sprint-mirror.js
  • skills/dev-backlog/scripts/sprint-mirror.test.js
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/multi-track-phase1b-lifecycle

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@sungjunlee sungjunlee merged commit fa97ab5 into main Jul 12, 2026
2 checks passed

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 897fbb0f22

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

exit 1
fi
;;
--track=*) TRACK="${1#--track=}" ;;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Reject empty --track= selectors

When a caller supplies --track= from an empty shell variable, this branch sets TRACK to an empty string and the later [ -n "$TRACK" ] check treats the command as if no selector was provided. In a single-active-sprint repo that means sprint-close.sh backlog --track= proceeds to close the only active sprint instead of failing like the --track form does for a missing value, so an invalid selector can still mutate the sprint file.

Useful? React with 👍 / 👎.

Comment on lines +66 to +68
if (arg.startsWith("--track=")) {
options.track = arg.slice("--track=".length);
continue;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Reject empty --track= selectors

--track= currently parses as track: "", and resolveSprintState() treats that falsy value the same as omitting --track. With one active sprint, an invocation such as sprint-mirror.js backlog --track= can update/create the default sprint mirror rather than reporting the missing selector value, which is inconsistent with the guarded --track form and can publish the wrong track when an empty variable is expanded.

Useful? React with 👍 / 👎.

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.

1 participant