feat: multi-candidate pins — ordered candidate list resolved by a scoped picker#16
Merged
Conversation
Finish adopting the delivery-superpowers method on this repo. Its delivery-superpowers-locations hook redirects superpowers' specs/plans to a gitignored .local/superpowers/ root (the vendored skill default would commit them under docs/superpowers/). Ignore .local so those artifacts never get committed; the SessionStart gate (`git check-ignore -q .local`) now passes. No trailing slash, so the check matches before the directory exists. Tier (.repo-visibility=public), beads, ADRs, and PR template are already in place from the discovery/delivery-base setup. Pinning delivery-superpowers alongside discovery awaits multi-candidate pins (#15); until then the local pin stays on discovery and delivery runs via UMBEL_BUNDLE=delivery-superpowers.
…ti-candidate pins
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Generalises the
.umbel-bundlepin from a single value to an ordered list of candidates (one bundle name per line), implementing the design of record indocs/adr/0007-multi-candidate-pins.md(terminology inCONTEXT.md).parsePin): trim each line, skip blanks, dedupe preserving first occurrence, full-line and inline#comments stripped.__vanilla__is an explicit candidate (renders a(vanilla)row only if listed). An empty/all-commented pin ≡ absent (never an error).arg > UMBEL_BUNDLE > pin; arg/env bypass the picker.umbel applystays single-candidate/vanilla and now refuses (exit 2) to overwrite a hand-authored multi-candidate pin (hint: runumbel unpinfirst). Candidates build lazily; the scoped picker is ephemeral (a selection resolves the launch only, never rewrites the pin).umbel listmarks every candidate in the PINNED column (yes, defaultyes*+ footnote) — which also fixes the column never marking at all.umbel show/buildkeep the full picker, pre-selecting the default candidate.README.mdanddocs/bundles-spec.mdupdated to describe the list format, comments, scoped vs full picker, and default-candidate semantics.Closes #15
Closes #5
Test plan
npm test— 337 tests pass (37 files)npx tsc --noEmitclean ·npx biome check .clean ·npm run buildOKparsePingrammar (exhaustive),readPin/isMultiCandidatePin,resolveBundleNamemultiple-kind + arg/env precedence,scopedPickerOptionsbuilder,runnon-TTY default resolution + candidate-order semantics + vanilla-default + unknown-default exit 3,applyoverwrite guard,listcandidate markingdist/cli.js: multi-candidate pin →listshowsyes*/yes+ footnote; non-TTYrunbuilds the first/default candidate (reorder flips it);applyover a multi-candidate pin refused (exit 2), pin left untouchedNotes
Built TDD, task-by-task, with per-task spec + code-quality review and a final whole-feature review. No production behaviour outside the pin/picker/list/apply paths changed; back-compat for one-line pins is preserved by the per-line parser.