Skip to content

fix(templates): stop the bulk archive when the user picks Cancel - #1398

Merged
clay-good merged 1 commit into
mainfrom
fix/bulk-archive-honor-cancel
Jul 22, 2026
Merged

fix(templates): stop the bulk archive when the user picks Cancel#1398
clay-good merged 1 commit into
mainfrom
fix/bulk-archive-honor-cancel

Conversation

@clay-good

@clay-good clay-good commented Jul 20, 2026

Copy link
Copy Markdown
Collaborator

Status: LGTM — ready for review.

What was wrong

The generated openspec-bulk-archive-change skill (and the matching opsx:bulk-archive command) offered you a Cancel option at the confirmation prompt:

7. **Confirm batch operation**
   - Options might include:
     - "Archive all N changes"
     - "Archive only N ready changes (skip incomplete)"
     - "Cancel"

8. **Execute archive for each confirmed change**
   Process changes in the determined order...

Step 7 collected your answer, but nothing ever told the agent what to do with it. Step 8 followed immediately and archived every selected change. An agent reading the skill literally would mv your changes into archive/ after you explicitly cancelled — and the only trace of the option was a vague "Skipped: user chose not to archive (if applicable)" bullet three steps later, after the move already happened.

The single-change archive skill had the same hole; it was fixed in #1357 (46a4d78) and reworded into its current routing block by #1394. The bulk variant was left behind. Neither has shipped yet — both are post-v1.6.0.

How it was fixed

Both template bodies (skill and opsx command) now route the answer:

Route on the answer by intent, not by exact label — you wrote these labels,
so match what the user picked rather than the wording above:
- "Cancel" — stop, do not archive. Report that nothing was archived and skip the remaining steps.
- The archive-everything option — proceed with every selected change
- The ready-only option — proceed with only the changes the step 6 table marks `Ready` or `Ready*`, and record the rest as Skipped in step 8c. If a `Ready*` change's conflict partner is skipped, re-derive that conflict's resolution using only the changes being archived.
- Anything else — ask again rather than archiving

Four deliberate details, each from an adversarial review finding:

  • Routing is by intent, not by literal label. Step 7 says options "might include" those labels, and they contain an N placeholder the agent fills in ("Archive all 3 changes"). Matching the literal strings would have sent every legitimate answer into "Anything else — ask again", trading a destructive bug for an infinite re-prompt.
  • "Ready" is bound to where it's decided — the step 6 status table, including the conflict-flagged Ready* row. Otherwise the agent can't tell which subset to archive.
  • A skipped conflict partner invalidates its recorded resolution. Ready-only can archive one side of a conflict while its partner stays active; without re-deriving, step 8a's "apply in resolved order" would sync the skipped change's deltas too.
  • The Cancel wording matches the single-change skill verbatim ("Cancel" — stop, do not archive), so one assertion guards all four templates — and "skip the remaining steps" also rules out printing a "Bulk Archive Complete" summary after a cancel.

A guardrail line was added where agents skim: Never archive after the user cancels the confirmation — a cancelled batch archives nothing.

Proof it works

Two regression tests in test/core/templates/skill-templates-parity.test.ts:

  • honors Cancel at every archive confirmation (#1381) — covers all four templates (bulk skill, bulk command, single skill, single command). The single-change routing has been correct since feat(skills): publish workflow skills to skills.sh #1357 but was never pinned by a test; this closes the whole issue rather than half of it.
  • routes the bulk archive confirmation by intent, not by literal label (#1381) — pins the intent-based wording, the ready-only binding, and the guardrail.

Both verified failing-then-passing. With the template change reverted:

× honors Cancel at every archive confirmation (#1381)
  → bulk skill: expected '---\nname: openspec-bulk-archive-chan…' to contain '"Cancel" — stop, do not archive'
× routes the bulk archive confirmation by intent, not by literal label (#1381)
  → bulk skill: expected '---\nname: openspec-bulk-archive-chan…' to contain 'Route on the answer by intent, not by…'

Full suite after npm run build: 2029 passed / 2046, 104 of 105 files green. The sole failing file is test/core/completions/installers/zsh-installer.test.ts (17 failures) — the known environment-only oh-my-zsh issue noted in CLAUDE.md and tracked in #1321, untouched by this branch and green in CI.

Notes / nits

Closes #1381

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Bug Fixes
    • Bulk archive now properly honors “Cancel”—stops the operation and archives nothing.
    • Archive confirmation routing is now intent-based (not exact label matching): Archive everything archives all selected changes; Archive only ready archives only Ready/Ready*.
    • Non-ready (and other non-selected) changes are recorded as Skipped; for Ready* conflicts whose partners are skipped, conflict resolution is re-derived from the archived set.
    • Any unrecognized confirmation response re-prompts the user instead of proceeding.

@coderabbitai

coderabbitai Bot commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 18df8b4b-f2cf-40ed-aff5-d8cb7bdd8c1a

📥 Commits

Reviewing files that changed from the base of the PR and between 078a2f5 and bbed2a3.

📒 Files selected for processing (4)
  • .changeset/bulk-archive-honors-cancel.md
  • skills/openspec-bulk-archive-change/SKILL.md
  • src/core/templates/workflows/bulk-archive-change.ts
  • test/core/templates/skill-templates-parity.test.ts
🚧 Files skipped from review as they are similar to previous changes (4)
  • .changeset/bulk-archive-honors-cancel.md
  • skills/openspec-bulk-archive-change/SKILL.md
  • src/core/templates/workflows/bulk-archive-change.ts
  • test/core/templates/skill-templates-parity.test.ts

📝 Walkthrough

Walkthrough

Bulk archive instructions now stop on “Cancel”, proceed for the two archive options, and re-prompt for other responses. Generated template hashes and parity tests are updated accordingly.

Changes

Bulk archive confirmation

Layer / File(s) Summary
Confirmation response routing
.changeset/bulk-archive-honors-cancel.md, skills/openspec-bulk-archive-change/SKILL.md, src/core/templates/workflows/bulk-archive-change.ts
Bulk archive guidance explicitly stops on “Cancel”, archives all or only ready changes for the corresponding options, and re-prompts for unrecognized responses.
Generated template parity validation
test/core/templates/skill-templates-parity.test.ts
Expected template hashes are updated, and parity tests verify cancellation, re-prompting, and intent-based routing text in generated variants.

Estimated code review effort: 2 (Simple) | ~10 minutes

Possibly related PRs

Suggested reviewers: tabishb, alfred-openspec

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely summarizes the main change: stopping bulk archive when Cancel is chosen.
Linked Issues check ✅ Passed The changes make Cancel stop archiving and route only explicit archive choices forward, matching #1381.
Out of Scope Changes check ✅ Passed The tests, hashes, and regenerated skill file all support the archive-confirmation fix and stay in scope.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/bulk-archive-honor-cancel

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.

@clay-good
clay-good force-pushed the fix/bulk-archive-honor-cancel branch 2 times, most recently from 3c6c3e8 to 078a2f5 Compare July 20, 2026 20:28

@alfred-openspec alfred-openspec left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

The routing closes the destructive fall-through in both bulk templates: Cancel exits before sync or move, unknown responses re-prompt, and ready-only selection re-derives conflicts without skipped changes. All nine focused parity tests pass locally at 078a2f5 and the exact-head CI/CodeQL matrix is green, so this is approved.

The bulk archive confirmation offered a "Cancel" option but never told
the agent what to do with it. Step 8 then archived every selected
change, so an agent following the skill literally moved the changes
even after the user cancelled.

Route each answer by intent rather than by literal label: the option
labels are written by the agent and carry an `N` placeholder, so
matching them verbatim would send every legitimate answer down the
"ask again" path. Cancel now stops without archiving and skips the
remaining steps, the ready-only option is bound to the status table
that decides what "ready" means (re-deriving conflict resolutions when
a Ready* partner is skipped), and a guardrail repeats that a cancelled
batch archives nothing.

Regression tests cover both archive paths, so the single-change
routing can no longer be silently reverted either.

Instruction text only — no CLI behavior changes.

Closes #1381

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

@alfred-openspec alfred-openspec left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

The rebase preserves the reviewed Cancel routing and cleanly composes with the current archive-path guidance. Exact-head build, all 10 focused parity tests, and the full CI/CodeQL matrix pass.

@clay-good
clay-good added this pull request to the merge queue Jul 22, 2026
Merged via the queue into main with commit 97d441a Jul 22, 2026
14 checks passed
@clay-good
clay-good deleted the fix/bulk-archive-honor-cancel branch July 22, 2026 14:31
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.

Generated openspec-archive-change skill archives even when the user selects Cancel

2 participants