Skip to content

Don't force init on scoped commands when PRODUCT.md is missing#277

Open
makappen-collab wants to merge 1 commit into
pbakaus:mainfrom
makappen-collab:fix/scoped-commands-no-forced-init
Open

Don't force init on scoped commands when PRODUCT.md is missing#277
makappen-collab wants to merge 1 commit into
pbakaus:mainfrom
makappen-collab:fix/scoped-commands-no-forced-init

Conversation

@makappen-collab

@makappen-collab makappen-collab commented Jun 20, 2026

Copy link
Copy Markdown

Problem

Setup step 1 in SKILL.md says:

If it reports NO_PRODUCT_MD, stop and follow reference/init.md before doing anything else.

In any project without a PRODUCT.md, this turns every scoped request into a full from-scratch init detour. Ask for /impeccable polish index.html and the skill instead stops and starts writing PRODUCT.md from the beginning. context.mjs reinforces it by printing "Stop the current task, load reference/init.md...".

Two failure modes follow:

  1. The agent runs the whole unwanted init onboarding for a one-line request.
  2. Faced with the heavy gate, the agent abandons the command entirely and does an ad-hoc pass without ever loading the command reference, so the skill effectively doesn't fire.

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 no PRODUCT.md was ever authored.

Fix

Make the gate command-aware rather than blanket:

  • From-scratch build flows (init, craft, shape) still route into reference/init.md when PRODUCT.md is missing. That's where captured product context genuinely matters before building.
  • Every other (scoped) command against existing code no longer diverts. The 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, never a blocker.

Changes

  • 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.
  • skill/scripts/context.mjs — soften the NO_PRODUCT_MD message to defer to the step 1 rule. Still prefixed NO_PRODUCT_MD: and still references reference/init.md.
  • tests/skill-behavior/scenarios.test.mjs — add scenario 10: a scoped command (/impeccable polish) with no PRODUCT.md loads polish.md and proceeds, and must not divert into init.md. Scenario 1 (a from-scratch craft still correctly diverts to init) stays green and pins that path.
  • Regenerated provider + plugin copies via bun run build:skills.

Testing

  • node --test tests/context.test.mjs — 30 pass
  • bun test tests/build.test.js (generated-copies sync check) — 10 pass
  • tests/skill-behavior/scenarios.test.mjs parses and skips cleanly without API keys (new scenario runs in the keyed CI sweep)
  • Build passes both prose validators

🤖 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.md no longer blocks scoped Impeccable commands (polish, audit, critique, etc.) on existing codebases. Setup and context.mjs now treat NO_PRODUCT_MD as command-aware: only init, craft, and shape must divert into reference/init.md first; other commands use the code as context, infer register from the surface, and may suggest /impeccable init once without stopping the task.

Routing when the user invokes Impeccable with no sub-command changes from silently entering init to recommending /impeccable init at the top of the menu while still showing the full command list. shape is explicitly grouped with craft as a from-scratch flow that can block on init.

Behavior tests add scenario 10 (scoped polish without PRODUCT.md must load polish.md, not init.md) and scenario 11 (shape without 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.

@makappen-collab makappen-collab requested a review from pbakaus as a code owner June 20, 2026 05:32
@greptile-apps

greptile-apps Bot commented Jun 20, 2026

Copy link
Copy Markdown

Greptile Summary

Scoped commands (polish, audit, critique, etc.) on existing codebases no longer divert into the full init flow when PRODUCT.md is absent; only the three from-scratch build commands (init, craft, shape) keep that gate. The no-argument menu routing is also corrected to recommend /impeccable init rather than silently entering it.

  • skill/SKILL.src.md: Step 1 NO_PRODUCT_MD rule is now command-aware; routing footnote extended to cover shape alongside craft; no-argument menu rule leads with init recommendation instead of jumping into it.
  • skill/scripts/context.mjs: JSDoc and NO_PRODUCT_MD stdout message updated to describe the new branching behaviour rather than the old empty-stdout/blanket-block approach.
  • tests/skill-behavior/scenarios.test.mjs: Scenario 10 asserts a scoped /impeccable polish never loads init.md when PRODUCT.md is absent; scenario 11 pins shape as a from-scratch flow that still diverts correctly.

Confidence Score: 5/5

Prompt-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 teach alias not appearing in the new command guard — creates conflicting instructions for an edge-case command but has no effect on the common paths the tests exercise. No application code is touched.

The teach-alias gap spans both skill/SKILL.src.md (step 1 guard) and skill/scripts/context.mjs (the NO_PRODUCT_MD message); both would need a one-word addition to be consistent.

Important Files Changed

Filename Overview
skill/SKILL.src.md Core routing rule updated: NO_PRODUCT_MD now diverts only for init/craft/shape; all other scoped commands proceed. Routing footnote and no-argument menu rule also updated consistently. The deprecated teach alias (treated as init) is absent from the new guard.
skill/scripts/context.mjs JSDoc updated to match current stdout behaviour; NO_PRODUCT_MD message softened to echo the command-aware rule. Same teach gap is present in the command enumeration.
tests/skill-behavior/scenarios.test.mjs Scenario 10 (scoped polish with no PRODUCT.md must not load init.md) and scenario 11 (shape with no PRODUCT.md must load init.md) added, addressing the previously noted gaps in test coverage. Uses trace.writePaths consistently with scenario 1.

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
Loading
%%{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
Loading

Fix All in Codex Fix All in Claude Code

Reviews (2): Last reviewed commit: "Don't force init on scoped commands when..." | Re-trigger Greptile

Comment thread tests/skill-behavior/scenarios.test.mjs
@pbakaus

pbakaus commented Jun 21, 2026

Copy link
Copy Markdown
Owner

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>
@makappen-collab makappen-collab force-pushed the fix/scoped-commands-no-forced-init branch from d865f4b to 7a12205 Compare June 21, 2026 19:35
@makappen-collab

Copy link
Copy Markdown
Author

Thanks Paul, that makes sense. Both done:

  1. Generated files removed - the PR is now source-only (skill/SKILL.src.md, skill/scripts/context.mjs, and the test), and I rebased onto latest main so it's no longer conflicting. The provider and plugin copies will regenerate from your build:skills sync.
  2. The three Greptile items were all genuine, not false positives, so I fixed rather than dismissed:
    • context.mjs file-level JSDoc still described the old empty-stdout signal, now refreshed to the NO_PRODUCT_MD: behaviour.
    • the craft init-then-resume footnote now covers shape too, since it's a from-scratch flow as well.
    • added scenario 11 (shape + no PRODUCT.md still diverts to init) alongside scenario 10 (scoped command proceeds).

build:skills is green (version and prose validators pass). Ready for another look, thanks.

@cursor cursor 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.

Cursor Bugbot has reviewed your changes using default effort and found 2 potential issues.

Fix All in Cursor

❌ 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.

Comment thread skill/SKILL.src.md
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.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

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.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 7a12205. Configure here.

Comment thread skill/SKILL.src.md
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.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

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)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 7a12205. Configure here.

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.

2 participants