Skip to content

feat(prioritize): make command workspace-agnostic (drop pillar-slug + sub-spike requirements) - #41

Open
lapc506 wants to merge 2 commits into
mainfrom
andres/prioritize-agnostic
Open

feat(prioritize): make command workspace-agnostic (drop pillar-slug + sub-spike requirements)#41
lapc506 wants to merge 2 commits into
mainfrom
andres/prioritize-agnostic

Conversation

@lapc506

@lapc506 lapc506 commented Jun 2, 2026

Copy link
Copy Markdown
Collaborator

HUMAN LAYER

Summary

The /make-no-mistakes:prioritize command was opinionated against a pillar
taxonomy that's not portable to typical Linear workspaces (per Andrés analysis,
session 2026-06-02 0500 CST). This PR drops the four hard couplings of the
original dogfood design while preserving full backward compatibility with
existing pillars.<slug> configs.

Four coupling fixes

# Old (v1.0–v1.22) New (v1.23+)
1 First arg = required <pillar-slug> validated against pillars.<slug> Optional. Resolves pillars.<slug> (legacy) → projects.<slug> (agnostic) → Linear MCP exact-name match → interactive. Plus --label <name> and --filter <query> as alternative scopes.
2 Sub-spike PIBER+IDCF as required Confidence anchor Optional --evidence <path-or-issue-id> flag. Accepts a Linear issue ID OR a local markdown path. Without it, evidence-driven MoSCoW rules are skipped; Confidence defaults to 0.8.
3 Vision audit auto-discovered at <codebase>/audits/<pillar>/vision-audit-*.md Auto-discovery only in legacy pillar mode. Agnostic mode requires explicit --audit <path> (no flag → no enrichment).
4 Output path hardcoded to <codebase>/audits/<pillar>/priority-<DATE>.md Default is ./priority-<DATE>.md in cwd, with ~/ expansion. --out <path> overrides. Legacy pillar mode keeps the original default.

Backward compatibility table

Invocation Behavior
prioritize pathways (with pillars.pathways in config) Legacy mode — unchanged.
prioritize pathways (with projects.pathways only) Agnostic mode — uses Linear project, no evidence/audit unless flagged.
prioritize agent --evidence APP-101 Agnostic + evidence anchor (Linear issue).
prioritize --label "team/frontend" Agnostic + label scope (no project required).
prioritize --filter "label:Frontend state:Backlog" Agnostic + arbitrary filter.
prioritize (no args) Interactive selection — lists projects from linear-setup.json + MCP.
prioritize pathways --evidence ./vision.md --audit ./audit.md --out ~/p.md Full agnostic with all anchors + custom output.

MoSCoW rule split

Scoring rules now annotated as:

  • evidence-driven — skip when no --evidence was provided (MUST-1..4, SHOULD-1..3, COULD-1..2, WONT-1..2).
  • label-driven — always fire (DECOMPOSE, MUST-5, SHOULD-4, COULD-3..4, WONT-3..4).

New explicit MoSCoW-label rules (MUST-5, SHOULD-4, COULD-4, WONT-4)
give workspaces using moscow/{must,should,could,wont} labels deterministic
coverage without needing an evidence anchor.

Files touched

  • commands/prioritize.md — args + flag surface + workflows + legacy section
  • skills/prioritize/SKILL.md — added "Workspace-agnostic mode (v1.23+)" section, rewrote Paso A/B/E for optional anchors, expanded error table
  • skills/prioritize/references/scoring-rules.md — annotated rules as evidence-driven vs label-driven, added explicit MoSCoW-label rules
  • skills/prioritize/references/linear-mutations.md — generalized "Sub-spike comment" → "Evidence-anchor comment" + agnostic report template
  • skills/prioritize/references/frameworks/moscow-rice.md — updated edge cases 4-8 for agnostic mode
  • CHANGELOG.md — Unreleased entry

Out of scope

  • Deeper UX redesign of the report markdown template (follow-up).
  • New tests — current skill is documentation-driven, has no test suite for the
    command flow; no existing tests cover the pillar-slug path either, so
    nothing to regress.
  • Touching dogfood linear-setup.json configs (none in this repo).

AGENT LAYER

Acceptance criteria

  • prioritize pathways (legacy pillars.pathways config) still works as before.
  • prioritize with no args enters interactive selection (no pillar-slug error).
  • prioritize --label "x" and prioritize --filter "y" are accepted as valid scopes.
  • --evidence, --audit, --out, --codebase are all optional, with documented defaults.
  • --evidence accepts both a Linear issue ID and a local file path.
  • Agnostic default output is ./priority-<DATE>.md in cwd; legacy is <codebase>/audits/<pillar>/priority-<DATE>.md.
  • Without --evidence, evidence-driven MoSCoW rules are skipped; label-driven rules continue to fire.
  • Without --audit, RICE Confidence defaults to 0.8.
  • Snapshot comment is posted on the --evidence Linear issue when it is an issue ID; skipped for local files or absent evidence; legacy mode still targets pillars.<slug>.spike.
  • CHANGELOG [Unreleased] entry documents all four coupling fixes.

Context files

  • commands/prioritize.md — entrypoint with the new arg parsing rules.
  • skills/prioritize/SKILL.md — full skill flow with optional-anchor branches.
  • skills/prioritize/references/scoring-rules.md — evidence-driven vs label-driven rule families.
  • skills/prioritize/references/frameworks/moscow-rice.md — RICE formula + agnostic edge cases (4–8).
  • skills/prioritize/references/linear-mutations.md — generalized comment + report template.

Decision rationale

  1. Why preserve pillars.<slug> as legacy mode rather than delete it?
    The author dogfooded the command against two production pillars in early
    2026; deleting that path silently would break those configs. Keeping it as
    the first resolution step costs no UX (users with projects.<slug> only
    never see it) and gives a clear migration runway.

  2. Why accept both Linear issue ID and local markdown for --evidence?
    A PRD/spec/vision doc often lives outside Linear (Notion export, repo doc).
    Forcing it to be a Linear issue would reintroduce the "must own a sub-spike"
    coupling we're explicitly removing.

  3. Why split rules into evidence-driven vs label-driven instead of dropping
    evidence-driven rules entirely?

    The killshot-thesis / anti-pattern / P0-feature rules are the highest-
    signal rules in the engine when an anchor exists. Dropping them would
    regress the dogfood pillars. Annotating them lets the runtime cleanly skip
    them when no anchor is supplied.

  4. Why default output to cwd instead of a temp dir or ~/.cache?
    Reports are meant to be committed alongside the codebase / Linear backlog
    snapshot. Cwd default lets the user git add priority-*.md directly.

Constraints honored

  • No force push (Andrés memory feedback_never_force_push_without_authorization).
  • No secrets or .env touched.
  • One PR = one thing (only the prioritize command/skill surface).
  • Worktree isolation: all work in .wt-prioritize-agnostic/.
  • No existing tests deleted (none cover the pillar-slug flow to begin with).

Created by Claude Code on behalf of @lapc506.

… sub-spike requirements)

Drops the four hard couplings of the original dogfood design while preserving
full backward compatibility with existing pillars.<slug> configs:

1. Scope: first positional arg is now optional. Resolution order is
   pillars.<slug> (legacy) -> projects.<slug> (agnostic) -> Linear MCP
   exact-name match -> interactive. New --label / --filter scope flags.
2. Evidence anchor: optional --evidence <path-or-issue-id> flag accepts a
   Linear issue ID OR a local markdown path. Without it, evidence-driven
   MoSCoW rules are skipped and RICE Confidence defaults to 0.8.
3. Vision audit: auto-discovery only fires in legacy pillar mode. Agnostic
   mode requires explicit --audit <path>.
4. Output path: default is ./priority-<DATE>.md in cwd. Override with --out.
   Legacy pillar mode keeps the audits/<pillar>/ default.

Also splits MoSCoW scoring rules into evidence-driven (skip when no anchor)
vs label-driven (always fire) families, and adds explicit
moscow/{must,should,could,wont} label rules so workspaces using MoSCoW labels
get deterministic coverage without an evidence anchor.

Rationale: the original command was opinionated against a pillar taxonomy
that does not exist in typical Linear workspaces (per Andres analysis,
2026-06-02). Dogfood configs continue to work unchanged.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

@dojo-code-reviewer dojo-code-reviewer 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.

✅ Approved

Approved — 0 blockers, 2 P3. Confidence: 4/5.

🔵 P3 — Minor

  • skills/prioritize/SKILL.md:258 — 🔵 P3 (minor) — The reference to the comment template is outdated. It points to "Sub-spike comment template", but that section has been renamed to "Evidence-anchor comment template" in references/linear-mutations.md.
  `references/linear-mutations.md` "Evidence-anchor comment template".
  • skills/prioritize/references/linear-mutations.md:209 — 🔵 P3 (minor) — There is an outdated reference in the ## Mutation failure handling section (around line 290) that still refers to "Sub-spike comment template". Please update that mention to "Evidence-anchor comment template" so that it matches the newly renamed heading in this file.

Total findings: 2 business context (2 total)


ℹ️ The findings below could not be anchored to a diff line (line not part of any hunk); they are listed here instead.

  • skills/prioritize/SKILL.md:258 — 🔵 P3 (minor) — The reference to the comment template is outdated. It points to "Sub-spike comment template", but that section has been renamed to "Evidence-anchor comment template" in references/linear-mutations.md.
  `references/linear-mutations.md` "Evidence-anchor comment template".

@@ -201,13 +209,21 @@ First priority snapshot. No comparison available.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔵 P3 (minor) — There is an outdated reference in the ## Mutation failure handling section (around line 290) that still refers to "Sub-spike comment template". Please update that mention to "Evidence-anchor comment template" so that it matches the newly renamed heading in this file.

main advanced 8 commits while this branch sat open. Only CHANGELOG.md
conflicted; the branch's actual contribution (commands/prioritize.md,
skills/prioritize/SKILL.md and its three references) merged cleanly.

CHANGELOG: the two sides were never in competition — the branch's block sits
under [Unreleased] and main's side is the released 1.35.0...1.24.0 entries.
Both kept, in that order.

Also aligned two README rows that main carries and this branch's own change
contradicts. README advertised `/make-no-mistakes:prioritize <pillar-slug>`
as requiring a pillar taxonomy, a PIBER+IDCF sub-spike and a vision audit —
exactly the four couplings this branch drops. Left as-is, merging would have
shipped a README documenting requirements the command no longer has. Rows now
match the command's own argument-hint; nothing else in README touched.

Verified on the merge result: vitest 60/60, hooks/test-hooks.sh 328/328,
hooks/test-sentinel-walkup.sh 5/5, and `npm run build-rules` leaves
hooks/rules/rules.json unchanged.

@dojo-code-reviewer dojo-code-reviewer 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.

✅ Approved

Approved — 0 blockers, 1 P3. Confidence: 4.80/5.00. NITs: 1 (shown).

Walkthrough

⚠️ Governance Warning: This PR targets the main branch directly. Per standard GitFlow practices, features should target develop first (i.e. featuredevelopmain). Since this PR targets main directly, please proceed with merge only if authorized by repository governance or if hotfixing/force-merging is intentionally allowed in this instance.

PR Walkthrough

This PR transitions the /make-no-mistakes:prioritize command from its original, opinionated pillar taxonomy to a workspace-agnostic model. It makes the <pillar-slug> positional argument optional (allowing project, label, or filter scopes), decouples the sub-spike and vision audit requirements (providing robust defaults like a 0.8 Confidence score when absent), and introduces new explicit MoSCoW label-driven scoring rules.

Areas Reviewed

I reviewed all modified specification and documentation files:

  • commands/prioritize.md (argument parsing, run-control flags, modes of invocation)
  • skills/prioritize/SKILL.md (subagent instructions, Main Flow Paso A/B/E, output resolution)
  • skills/prioritize/references/frameworks/moscow-rice.md (agnostic mode edge cases)
  • skills/prioritize/references/linear-mutations.md (Priority report template, evidence-anchor comments)
  • skills/prioritize/references/scoring-rules.md (evidence-driven vs. label-driven scoring rule families)
  • README.md and CHANGELOG.md

Safety Rationale

This is a documentation-driven skill specification with no executable code logic changes, and legacy configuration schemas and execution modes are fully preserved, ensuring complete backward compatibility.

Approved — 0 blockers, 1 P3.

🔵 P3 — Minor

  • skills/prioritize/SKILL.md:236 — 🔵 P3 (minor) — The section reference 'Sub-spike comment template' does not match the renamed 'Evidence-anchor comment template' header in references/linear-mutations.md. A reader looking for this template will experience confusion. Changing the reference name keeps the files synchronized.

[pass 1]

⚪ P4 — Nitpicks

  • commands/prioritize.md:166 — [NIT] ⚪ P4 (nit) — The word 'espanol' is missing the tilde 'ñ'. Writing it as 'español' matches standard spelling.

[pass 1]


Total findings: 1 business context, 1 nit (2 total)

Comment thread commands/prioritize.md

Si el `pillar-slug` no existe en `linear-setup.json`, preguntar:
If the user invokes `/prioritize` without positional args AND without
`--label`/`--filter`:

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

[NIT] ⚪ P4 (nit) — The word 'espanol' is missing the tilde 'ñ'. Writing it as 'español' matches standard spelling.

[pass 1]

- `description.length < 100` -> Reach/Impact inferidos solo del titulo.
- `--no-audit` fue pasado pero el audit existe -> Confidence default=0.8.
- Subagent-2 parse warnings presentes (ambiguity en spike sections).
Mark each issue with `low-confidence-estimate` if:

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔵 P3 (minor) — The section reference 'Sub-spike comment template' does not match the renamed 'Evidence-anchor comment template' header in references/linear-mutations.md. A reader looking for this template will experience confusion. Changing the reference name keeps the files synchronized.

[pass 1]

lapc506 added a commit that referenced this pull request Jul 31, 2026
Measured on origin/main @ ee0ba47: the three version files all read 1.36.0,
and `gh pr diff 55 | grep -E '^\+.*"version"'` shows #55 already bumps to
1.37.0 in package.json, plugin.json and marketplace.json. Taking 1.37.0 here
collides with it in all three. The same probe over #52, #46, #44 and #41
returns nothing, so 1.38.0 is free. Skipping a version costs nothing;
colliding does.

Minor and not major, decided by reading. A skill auto-activates on its
`description` rather than being invoked by name like a command, so a renamed
`name:` changes no call site. The reference search returns nothing:

  grep -rniI "rebase.advisor" . --exclude-dir=node_modules \
    --exclude-dir=.git --exclude=CHANGELOG.md   ->  no hits

That negative is real and not a broken search -- the same grep for
`spike-recommend` returns 10 files, so cross-references of this shape are
found when they exist.

One surface does break and is stated rather than folded in: a user who typed
`/make-no-mistakes:rebase-advisor` explicitly (README:137 documents that
skills can be invoked that way) now gets an unknown skill. It fails loudly,
the replacement is one row away in the same table, and the installer prunes
the old file rather than leaving both live.

The `[1.37.0]:` CHANGELOG reference slot is deliberately left for #55 to fill.

Suite: 337/337 hooks, 60/60 vitest.

Created by Claude Code on behalf of @lapc506
lapc506 added a commit that referenced this pull request Jul 31, 2026
…(v1.38.0) (#56)

* feat(skills): sync-advisor — measure the drift before naming the fix (v1.37.0)

Renames `rebase-advisor` to `sync-advisor` and turns a blind router into an
advisor that measures.

The old skill was 43 lines and measured nothing. Its step 1 was "Confirm the
user wants a full team sync" -- a question back to the user about something
three git commands answer. Its description then over-routed: it triggered on
"align with develop" and "branches are behind", both of which are `git pull`,
and sent them to /make-no-mistakes:rebase, which stashes every worktree,
rebases every local branch and auto-merges PRs. Between `git pull` and that
the toolkit offered nothing, and nothing read-only at all.

Six read-only predicates now run before anything is named: distance,
fast-forward possible, dirty tree split by stage, untracked files the ref
already tracks, worktrees behind, and branches with unpushed commits. The
fifth is the threshold between a plain pull and the team command.

The fourth is the one nothing else reports, and it was verified on a throwaway
pair of repos rather than asserted. An untracked local file at a path the ref
tracks aborts the pull outright while being invisible everywhere else:
`git status` shows a plain `?? newfile.txt`, distance reports a clean 0 ahead
1 behind, and `merge-base --is-ancestor` says a fast-forward is possible. The
pull then exits 1 with "The following untracked working tree files would be
overwritten by merge ... Please move or remove them before you merge" -- the
message names the user's own file and offers deletion as the remedy, which is
the one irreversible move available. The skill reports these by name and
recommends copying them out of the repo, never deleting them. Both controls
were run: the pipeline printed nothing before the collision existed and named
the file after.

It never acts. Every fix is printed for the user to run. The single write is
`git fetch origin --quiet`, which touches remote-tracking refs and nothing
else, and the skill says so out loud -- without it every measurement is taken
against a stale origin/<base> and reports a drift that stopped being true days
ago, which is the failure this skill exists to catch.

Adds `syncAdvisor.governedPaths` to make-no-mistakes.config.json: the paths
whose changes get reported by name, turning "you are 12 behind" into "three
hooks changed, two of them fix defects you may be looking at right now". No
default -- with the key unset the skill drops the consequence line rather than
falling back to a built-in list, which would be wrong in every repo but the one
it was copied from and would read as measured.

commands/rebase.md is untouched and stays a real destination. What changed is
who decides when it applies.

Origin (2026-07-31, as reported): a developer filed two bug reports against a
hook with clean reproductions. One was a real defect; the other described
behaviour fixed days earlier against a stale checkout, and nothing in the
report separated them.

Suite: 337/337 hooks, 60/60 vitest.

Created by Claude Code on behalf of @lapc506

* chore(release): take 1.38.0 instead of 1.37.0 — #55 owns 1.37.0

Measured on origin/main @ ee0ba47: the three version files all read 1.36.0,
and `gh pr diff 55 | grep -E '^\+.*"version"'` shows #55 already bumps to
1.37.0 in package.json, plugin.json and marketplace.json. Taking 1.37.0 here
collides with it in all three. The same probe over #52, #46, #44 and #41
returns nothing, so 1.38.0 is free. Skipping a version costs nothing;
colliding does.

Minor and not major, decided by reading. A skill auto-activates on its
`description` rather than being invoked by name like a command, so a renamed
`name:` changes no call site. The reference search returns nothing:

  grep -rniI "rebase.advisor" . --exclude-dir=node_modules \
    --exclude-dir=.git --exclude=CHANGELOG.md   ->  no hits

That negative is real and not a broken search -- the same grep for
`spike-recommend` returns 10 files, so cross-references of this shape are
found when they exist.

One surface does break and is stated rather than folded in: a user who typed
`/make-no-mistakes:rebase-advisor` explicitly (README:137 documents that
skills can be invoked that way) now gets an unknown skill. It fails loudly,
the replacement is one row away in the same table, and the installer prunes
the old file rather than leaving both live.

The `[1.37.0]:` CHANGELOG reference slot is deliberately left for #55 to fill.

Suite: 337/337 hooks, 60/60 vitest.

Created by Claude Code on behalf of @lapc506

* fix(sync-advisor): make the collision predicate correct from any subdirectory

Reviewer P3 on `ea8c46e` claimed `git ls-tree` "always outputs
repository-relative paths" while `git ls-files` is prefix-relative, so the two
would fail to match from a subdirectory, and proposed `--full-name` on
`ls-files`.

Measured: the premise is false and the proposed fix introduces the bug it
claims to prevent. From `sub/`, `ls-tree -r --name-only` prints `newfile.txt`,
not `sub/newfile.txt` -- it strips the prefix exactly like `ls-files` does, so
the original command matched fine and found the collision. Adding
`--full-name` alone then makes `ls-files` emit `sub/newfile.txt` against
`ls-tree`'s `newfile.txt`, they stop matching, and `comm -12` returns empty --
a clean bill of health for a tree about to abort the pull.

But it pointed at a real weakness of a different kind. From a subdirectory both
commands are SCOPED to that subtree, so a collision at the repo root is not
seen at all. That is scope, not format, and no combination of format flags
fixes it: `--full-name` changes how a path prints, never which paths are
considered. The pathspec does.

Shipped: `--full-name -- :/` on ls-files, `--full-tree` on ls-tree. Four cases
run, with the command extracted verbatim from SKILL.md so the test cannot drift
from the doc -- negative control from the root and from `sub/` (both empty),
positive from the root and from `sub/` with one collision in each location
(both list `rootfile.txt` and `sub/newfile.txt`).

Suite: 340/340 hooks, 60/60 vitest.

Created by Claude Code on behalf of @lapc506

* fix(sync-advisor): resolve the base ref correctly, and in a bare form

Reviewer P2 on `00e2c08`, and it is right. Step 0 returned values carrying the
remote prefix while every predicate interpolates `origin/$BASE`, so the run
died on `origin/origin/develop`:

  $ git rev-list --left-right --count "HEAD...origin/origin/main"
  fatal: ambiguous argument … unknown revision          exit=128

Fixed by normalising unconditionally (`${BASE#refs/remotes/}`, `${BASE#origin/}`)
whichever branch of the resolution produced the value. Verified both branches
with a control that must fail: where `origin/HEAD` IS set it returns
`origin/main`, normalises to `main`, and `origin/main` resolves; the
un-normalised form exits 128.

The P2 understated it. Step 0's first command resolved the base from
`@{upstream}`, which on a feature branch is that branch's OWN remote copy --
here `origin/andres/sync-advisor`. That answers "am I pushed?", which is
predicate 6's question, and would report 0 behind on a branch far behind the
real base. Stripping a prefix would have left it pointing at the wrong ref, so
the command is gone from base resolution rather than patched.

Also measured while there: `git symbolic-ref --short refs/remotes/origin/HEAD`
fails outright in this repo (`not a symbolic ref`), so it is documented as a
fall-through into the develop/main/master/trunk probe rather than as a step
that is expected to succeed.

P4 (`--abbrev-ref` and `--symbolic-full-name` redundant) is also correct --
both forms return `origin/andres/sync-advisor` here -- and is moot: that
command no longer appears.

Suite: 340/340 hooks, 60/60 vitest.

Created by Claude Code on behalf of @lapc506
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