Don't force init on scoped commands when PRODUCT.md is missing#277
Don't force init on scoped commands when PRODUCT.md is missing#277makappen-collab wants to merge 1 commit into
Conversation
Greptile SummaryScoped commands (
Confidence Score: 5/5Prompt-and-test-only change with no runtime application logic at risk; safe to merge. All changes are agent-instruction prose and test assertions. The three previously noted gaps (shape diversion untested, routing footnote missing shape, stale JSDoc) are fully addressed. The remaining open item — the deprecated The Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[Agent runs context.mjs] --> B{PRODUCT.md found?}
B -- Yes --> C[Print PRODUCT.md block]
B -- No --> D{Command is init / craft / shape?}
D -- Yes --> E[Divert → load reference/init.md\nWrite PRODUCT.md first]
D -- No\nScoped command --> F[Proceed with existing code as context\nOffer /impeccable init as suggestion]
C --> G[Continue with requested command]
E --> H[Finish init → refresh context\nResume original command]
F --> G
style D stroke-dasharray:5 5,stroke:#f90
style E fill:#fdd,stroke:#c00
style F fill:#dfd,stroke:#060
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
flowchart TD
A[Agent runs context.mjs] --> B{PRODUCT.md found?}
B -- Yes --> C[Print PRODUCT.md block]
B -- No --> D{Command is init / craft / shape?}
D -- Yes --> E[Divert → load reference/init.md\nWrite PRODUCT.md first]
D -- No\nScoped command --> F[Proceed with existing code as context\nOffer /impeccable init as suggestion]
C --> G[Continue with requested command]
E --> H[Finish init → refresh context\nResume original command]
F --> G
style D stroke-dasharray:5 5,stroke:#f90
style E fill:#fdd,stroke:#c00
style F fill:#dfd,stroke:#060
Reviews (2): Last reviewed commit: "Don't force init on scoped commands when..." | Re-trigger Greptile |
|
I was very much on the fence about this, but I'm coming around to the idea. A command like "bolder" doesn't strictly need to know the audience. That being said, could you please remove the generated files from the PR and just have the source files in the source folder in this PR (repo convention), plus, please clear any of the bugbot review items (if they're false positives, say so and dismiss). Happy to take a look afterwards, thanks! |
Setup step 1 told the agent: "If it reports NO_PRODUCT_MD, stop and follow reference/init.md before doing anything else." For a project with no PRODUCT.md, that turned every scoped request (polish, critique, audit, layout, ...) into a full from-scratch init detour. The user asks to polish one button and the skill instead starts writing PRODUCT.md from the beginning. Faced with that gate, agents also frequently abandon the command and do an ad-hoc pass without loading the command reference. Make the gate command-aware. A missing PRODUCT.md still routes into init for the from-scratch build flows where captured product context is the point (init, craft, shape). For any other command, a scoped request against existing code, the code is the context: proceed with the requested command, infer the register from the surface in focus, and offer /impeccable init once as a suggestion rather than a blocker. - skill/SKILL.src.md: rewrite the step 1 NO_PRODUCT_MD rule; reconcile the no-argument routing rule so it leads the menu with init instead of silently jumping into it; extend the craft init-then-resume footnote to cover shape, now also a from-scratch flow. - skill/scripts/context.mjs: soften the NO_PRODUCT_MD message to defer to the step 1 rule instead of "Stop the current task"; refresh the stale file-level JSDoc that still described the old empty-stdout signal. - tests/skill-behavior/scenarios.test.mjs: add scenario 10 (scoped command + no PRODUCT.md proceeds without forcing init) and scenario 11 (shape + no PRODUCT.md still diverts into init). Scenario 1 (craft diverts) stays green and pins the build path. Source-only per repo convention; provider and plugin copies are regenerated by the maintainer's build:skills sync. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
d865f4b to
7a12205
Compare
|
Thanks Paul, that makes sense. Both done:
|
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using default effort and found 2 potential issues.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 7a12205. Configure here.
| You MUST do these steps before proceeding: | ||
|
|
||
| 1. Run `node {{scripts_path}}/context.mjs` once per session. If the request names or implies a file, route, or app inside a monorepo, infer the concrete path and run `node {{scripts_path}}/context.mjs --target <path>` instead. If you've already seen its output in this conversation, do not re-run it. The script either prints the project's PRODUCT.md (and DESIGN.md when present) as a markdown block, or tells you it's missing. Follow whatever it prints. **If it reports `NO_PRODUCT_MD`, stop and follow `reference/init.md` before doing anything else.** If the output ends with an `UPDATE_AVAILABLE` directive, follow it (ask the user once about updating, then continue). It never blocks the current task. | ||
| 1. Run `node {{scripts_path}}/context.mjs` once per session. If the request names or implies a file, route, or app inside a monorepo, infer the concrete path and run `node {{scripts_path}}/context.mjs --target <path>` instead. If you've already seen its output in this conversation, do not re-run it. The script either prints the project's PRODUCT.md (and DESIGN.md when present) as a markdown block, or tells you it's missing. Follow whatever it prints. **If it reports `NO_PRODUCT_MD`:** divert into `reference/init.md` first only when the user invoked `init`, `craft`, or `shape` (the from-scratch build flows where captured product context is the whole point). For any other command, a scoped evaluate / refine / enhance / fix / iterate request against existing code, do **not** divert into init. The existing code is the context: proceed with the requested command, infer the register from the surface in focus (step 4), and offer `/impeccable init` once as a suggestion the user can take later. A missing PRODUCT.md must never block a scoped request. If the output ends with an `UPDATE_AVAILABLE` directive, follow it (ask the user once about updating, then continue). It never blocks the current task. |
There was a problem hiding this comment.
Intent-routed builds skip init
Medium Severity
Setup step 1 only forces reference/init.md when the user explicitly names init, craft, or shape, but Setup runs before routing rule 3 can map phrasing like “build a landing page” to craft. With NO_PRODUCT_MD, those from-scratch requests follow the scoped path and can reach craft.md without creating PRODUCT.md.
Reviewed by Cursor Bugbot for commit 7a12205. Configure here.
| You MUST do these steps before proceeding: | ||
|
|
||
| 1. Run `node {{scripts_path}}/context.mjs` once per session. If the request names or implies a file, route, or app inside a monorepo, infer the concrete path and run `node {{scripts_path}}/context.mjs --target <path>` instead. If you've already seen its output in this conversation, do not re-run it. The script either prints the project's PRODUCT.md (and DESIGN.md when present) as a markdown block, or tells you it's missing. Follow whatever it prints. **If it reports `NO_PRODUCT_MD`, stop and follow `reference/init.md` before doing anything else.** If the output ends with an `UPDATE_AVAILABLE` directive, follow it (ask the user once about updating, then continue). It never blocks the current task. | ||
| 1. Run `node {{scripts_path}}/context.mjs` once per session. If the request names or implies a file, route, or app inside a monorepo, infer the concrete path and run `node {{scripts_path}}/context.mjs --target <path>` instead. If you've already seen its output in this conversation, do not re-run it. The script either prints the project's PRODUCT.md (and DESIGN.md when present) as a markdown block, or tells you it's missing. Follow whatever it prints. **If it reports `NO_PRODUCT_MD`:** divert into `reference/init.md` first only when the user invoked `init`, `craft`, or `shape` (the from-scratch build flows where captured product context is the whole point). For any other command, a scoped evaluate / refine / enhance / fix / iterate request against existing code, do **not** divert into init. The existing code is the context: proceed with the requested command, infer the register from the surface in focus (step 4), and offer `/impeccable init` once as a suggestion the user can take later. A missing PRODUCT.md must never block a scoped request. If the output ends with an `UPDATE_AVAILABLE` directive, follow it (ask the user once about updating, then continue). It never blocks the current task. |
There was a problem hiding this comment.
Teach alias conflicts NO_PRODUCT rule
Low Severity
Setup step 1 treats every command other than init, craft, or shape as scoped: proceed and only suggest init. The deprecated teach alias is omitted from the blocker list, yet later text requires loading reference/init.md and proceeding as init, so /impeccable teach with no PRODUCT.md gets contradictory instructions.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit 7a12205. Configure here.


Problem
Setup step 1 in
SKILL.mdsays:In any project without a
PRODUCT.md, this turns every scoped request into a full from-scratchinitdetour. Ask for/impeccable polish index.htmland the skill instead stops and starts writingPRODUCT.mdfrom the beginning.context.mjsreinforces it by printing "Stop the current task, load reference/init.md...".Two failure modes follow:
This bites hardest on real, existing codebases (the common case for
polish/critique/audit/layout/ etc.), where there's plenty of context in the code itself but noPRODUCT.mdwas ever authored.Fix
Make the gate command-aware rather than blanket:
init,craft,shape) still route intoreference/init.mdwhenPRODUCT.mdis missing. That's where captured product context genuinely matters before building./impeccable initonce as a suggestion, never a blocker.Changes
skill/SKILL.src.md— rewrite the step 1NO_PRODUCT_MDrule; reconcile the no-argument routing rule so it leads the menu withinitinstead of silently jumping into it.skill/scripts/context.mjs— soften theNO_PRODUCT_MDmessage to defer to the step 1 rule. Still prefixedNO_PRODUCT_MD:and still referencesreference/init.md.tests/skill-behavior/scenarios.test.mjs— add scenario 10: a scoped command (/impeccable polish) with noPRODUCT.mdloadspolish.mdand proceeds, and must not divert intoinit.md. Scenario 1 (a from-scratchcraftstill correctly diverts to init) stays green and pins that path.bun run build:skills.Testing
node --test tests/context.test.mjs— 30 passbun test tests/build.test.js(generated-copies sync check) — 10 passtests/skill-behavior/scenarios.test.mjsparses and skips cleanly without API keys (new scenario runs in the keyed CI sweep)🤖 Generated with Claude Code
Note
Low Risk
Documentation and agent-routing logic only; no runtime app code. Risk is mis-routed agents skipping init on craft/shape, which new scenarios 1 and 11 still guard.
Overview
Missing
PRODUCT.mdno longer blocks scoped Impeccable commands (polish,audit,critique, etc.) on existing codebases. Setup andcontext.mjsnow treatNO_PRODUCT_MDas command-aware: onlyinit,craft, andshapemust divert intoreference/init.mdfirst; other commands use the code as context, infer register from the surface, and may suggest/impeccable initonce without stopping the task.Routing when the user invokes Impeccable with no sub-command changes from silently entering init to recommending
/impeccable initat the top of the menu while still showing the full command list.shapeis explicitly grouped withcraftas a from-scratch flow that can block on init.Behavior tests add scenario 10 (scoped
polishwithoutPRODUCT.mdmust loadpolish.md, notinit.md) and scenario 11 (shapewithout context still diverts to init).Reviewed by Cursor Bugbot for commit 7a12205. Bugbot is set up for automated code reviews on this repo. Configure here.