Skip to content

fix(prompts): render no CLI version or terminal command for a prompts host - #471

Merged
theCodeDrift merged 3 commits into
mainfrom
fix/prompts-host-invocation-marker
Oct 6, 2026
Merged

theCodeDrift merged 3 commits into
mainfrom
fix/prompts-host-invocation-marker

Conversation

@theCodeDrift

@theCodeDrift theCodeDrift commented Oct 6, 2026 •

Copy link
Copy Markdown
Member

Two defects from #469 in what @taskless/cli/prompts renders for a host that has no terminal.

1. A nightly rendered its own versioned invocation

The export fell back to the build's own invocation when a caller passed none. On a release that is the <taskless-cli> marker; on a nightly it is npx @taskless/cli-nightly@<version>, so every %(TASKLESS_CLI)s in a recipe body carried the nightly version, and getPrompt(topic, { header: false }) was no longer stable across CLI versions.

The fallback logic and the affected recipes are identical in 0.11.2. The issue's 0-vs-N comparison was release against nightly, not a regression between versions: older nightlies render the same way.

Fix: the export (getPrompt, getInstructions, PROMPTS) defaults invocation to <taskless-cli>. A host that imported the package did not launch it, which is what the invocation docs already promised. taskless agent <topic> and the other CLI render paths are unchanged and still name the build they were run from.

2. mechanics: false still named recipes as commands to fetch

In route, step 8 ("Name the command"), the failure fallback and See Also all rendered <cli> agent <topic>. With mechanics: false they now reduce to the topic name:

  • Step 8 becomes Name the destination. and ends with create-vale-rule in its fence. It is a whole-step substitution (%(NAME_DESTINATION)s) with the title included, the same way HOST_TOOLS swaps the onboard tool step.
  • Citations go through %(RECIPE_FETCH)s, written directly against the topic name (`%(RECIPE_FETCH)screate-sg-rule`). It renders <cli> agent by default and nothing with mechanics off, so the prose stays in the markdown where Vale and the cross-reference tests cover it.

route rendered with mechanics: false now contains no CLI invocation at all. The default render is byte-identical (compared from the built package, with and without an invocation), so taskless agent route output is unchanged and route stays at topic v5.

Verification

  • The issue's repro against a real build:nightly: 8 / 11 / 12 versioned invocations without the fix (route / create-sg-rule / create-vale-rule), 0 / 0 / 0 with it.
  • New test/nightly/prompts-invocation.test.ts (nightly vitest project) asserts that every exported topic's { header: false, mechanics: false } render contains no versioned invocation and no CLI version. 8 of its tests fail without fix 1.
  • New tests in test/prompts.test.ts cover the topic-name render and the unchanged default.
  • pnpm typecheck, pnpm lint, and the full suite (2114 tests) pass.

Deliberately not covered

mechanics: false still acts only on route. The authoring recipes (create-sg-rule, create-vale-rule, create-runtime-rule) carry 36 CLI commands between them, now with the version-free marker. About 20 of them are the authoring loop itself (verify, test, check), and a no-terminal replacement for those has to say how the host validates a rule, which this package cannot know. That needs the consumer's input rather than a guess, so it is left for a follow-up.

Fixes #469

…invocation

A nightly's @taskless/cli/prompts fell back to its own pinned invocation,
so every %(TASKLESS_CLI)s in a recipe body rendered as
npx @taskless/cli-nightly@<version>, and a header: false render still
carried the CLI version. The export now defaults to <taskless-cli>; the
agent command keeps naming the build it was run from.
@theCodeDrift

Copy link
Copy Markdown
Member Author

@claude /review

@claude

claude Bot commented Oct 6, 2026 •

Copy link
Copy Markdown

Claude finished @theCodeDrift's task in 12m 27s —— View job


Review mode: incremental — read 0 prior review thread(s) before reviewing.

.prior-review.json contained no review threads, review summaries, or top-level comments beyond the trigger comment itself, so this is the first review of this PR — there is nothing previously-raised to classify as addressed or still-open.

  • Read .prior-review.json
  • Fetch PR diff and metadata (gh pr diff, gh pr view)
  • Review changed files for correctness, security, performance, tests, clarity
  • Post findings

Assessment

The fix is narrow and correctly scoped: forHost() in packages/cli/src/prompts/index.ts defaults invocation to TASKLESS_CLI_MARKER only on the three public accessors backed by rendering (getPrompt, getInstructions, and transitively PROMPTS), while recipes.ts's internal resolveInvocation() fallback — used directly by taskless agent <topic>, onboard, init, and the feedback survey — is untouched. That matches the PR's stated intent exactly: the CLI's own render paths still name the build they ran from, and only the package-import surface now gets the agent-fill marker by default.

A few things I specifically checked and found fine:

  • getRawInstructions is not wrapped in forHost (index.ts:172-177), unlike the other two accessors. This looked like an oversight at first, but getRawRecipe (recipes.ts:676-692) never reads options.invocation at all — it returns the unrendered template with %(TASKLESS_CLI)s left as a literal placeholder for the host to substitute itself, as the docstring says. So the omission is inert, not a bug, though it's a little easy to mis-read at a glance given the other two functions now visibily differ in shape.
  • applyCliInvocation (util/invocation.ts) separately rewrites literal npx @taskless/cli text in recipe prose (independent of the %(TASKLESS_CLI)s placeholder this PR's fix controls). I checked all agent/*.md recipes for that literal string — the only hit is in ci.md, which is in INTERNAL_TOPICS and unreachable through the typed PromptTopic export, so it doesn't undermine the fix for the four publicly exported topics (create-sg-rule, create-vale-rule, create-runtime-rule, route).
  • The new test/nightly/prompts-invocation.test.ts is wired into the existing nightly vitest project (vite.config.ts) correctly, and its assertions (no versioned invocation, no CLI_VERSION, marker present, caller-supplied invocation rendered verbatim, taskless agent <topic>'s own render path unaffected) line up with what the diff actually changes.
  • The changeset is a single patch bump at .changeset/prompts-host-invocation-marker.md, consistent with this being a 0.y.z release and a bug fix rather than new surface.

No correctness, security, or test-adequacy issues found. Nothing new to flag.
· Branch

…re off

route's final step, failure fallback and See Also named a recipe as a
command to fetch, so a mechanics: false render still carried CLI
invocations. Step 8 is now a whole-step substitution that names the
destination by topic, and citations go through %(RECIPE_FETCH)s, which
renders nothing with mechanics off. The default render is byte-identical.
@theCodeDrift theCodeDrift changed the title fix(prompts): render the agent-fill marker for a host that passes no invocation fix(prompts): render no CLI version or terminal command for a prompts host Oct 6, 2026
@theCodeDrift

Copy link
Copy Markdown
Member Author

@claude /review

@claude

claude Bot commented Oct 6, 2026 •

Copy link
Copy Markdown

Claude finished @theCodeDrift's task in 15m 36s —— View job


Review mode: incremental — read 0 prior review thread(s) before reviewing.

.prior-review.json holds no inline review threads and no formal reviews — only the prior top-level /review comment and the two trigger comments. There is nothing at thread granularity to classify as addressed/still-open. That said: the prior review's text only discusses the first commit (004d7c4, the forHost()/marker-default fix); it says nothing about RECIPE_FETCH, NAME_DESTINATION, or the route.md step‑8 rewrite, which arrived in the second commit (76d58aa). I treated that material as effectively unreviewed and gave it a full pass below, alongside re-confirming the first commit's fix is still correct on current HEAD.

  • Read .prior-review.json
  • Fetch PR diff and metadata (gh pr diff, gh pr view)
  • Review changed files for correctness, security, performance, tests, clarity
  • Post findings

Previously assessed, not repeated

  • forHost() wrapping only getPrompt/getInstructions (and transitively PROMPTS) while leaving recipes.ts's resolveInvocation() fallback untouched for CLI-own render paths — confirmed still correct on current HEAD.
  • getRawInstructions not wrapped in forHost — previously checked and found inert (getRawRecipe never reads options.invocation, it leaves %(TASKLESS_CLI)s as a literal placeholder). Unchanged, still inert.
  • applyCliInvocation's literal-string rewriting vs. the %(TASKLESS_CLI)s placeholder fix, and the ci.md/INTERNAL_TOPICS exception — previously checked, unaffected by the second commit.
  • Changeset shape (single patch bump) — previously checked, still accurate for what the second commit added.

New in this pass (second commit: RECIPE_FETCH / NAME_DESTINATION)

I traced the full substitution chain for both macros:

  • RECIPE_FETCH (recipes.ts) renders "<cli> agent " by default and "" with mechanics: false, matching every citation site in route.md (`%(RECIPE_FETCH)s<topic>`). Confirmed via grep that no literal %(TASKLESS_CLI)s remains anywhere in route.md after the diff — so the PR's claim that a mechanics: false render of route carries no CLI invocation at all holds, not just for the citations the diff shows but for the whole file.
  • NAME_DESTINATION / nameDestinationStep(): traced the indentBlock interaction by hand against step 8's "8. %(NAME_DESTINATION)s" placement — the 3-space continuation indent matches the list-item's existing convention (same as the old literal step 8 and as HOST_TOOLS/SOURCE_PR_REVIEW), and the fenced topic name renders as create-vale-rule wrapped in \`` fences, consistent with the new test's regex. The branch selection (options.mechanics === false ? undefined : resolveInvocation(options)`) correctly routes to "Name the destination" (topic-only) vs. "Name the command" (full invocation).
  • Checked agent check / agent create-legacy-rule in the rewritten "See Also" list — these are pre-existing conventions used identically across a dozen other recipe files (create-remote-rule.md, rule.md, onboard.md, etc.), not something this PR introduced or changed semantically; just moved into the macro.
  • Test coverage (test/prompts.test.ts's two new tests, test/nightly/prompts-invocation.test.ts) matches the actual render output I traced by hand — no mismatch between what the tests assert and what the substitution code produces.

No correctness, security, or test-adequacy issues found in the new material. One minor clarity nit posted inline on packages/cli/src/prompts/recipes.ts:200 (a JSDoc line that runs ~115 chars vs. the ~80-col wrap of the rest of the block — cosmetic only, two sentences landed on one line during editing).
· Branch

Comment thread packages/cli/src/prompts/recipes.ts Outdated
@theCodeDrift

Copy link
Copy Markdown
Member Author

Re: @claude[bot] — "Claude finished @theCodeDrift's task in 12m 27s… The fix is narrow and correctly scoped: forHost()…"
#471 (comment)

Thanks. No findings to act on; the getRawInstructions observation matches the intent, since it hands back the unrendered template and never reads invocation.

— AI Coding Agent

@theCodeDrift

Copy link
Copy Markdown
Member Author

Re: @claude[bot] — "Claude finished @theCodeDrift's task in 15m 36s… No correctness, security, or test-adequacy issues found in the new material."
#471 (comment)

Thanks. The one nit it raised, the overlong JSDoc line in recipes.ts, is rewrapped in 695647d and the thread is resolved.

— AI Coding Agent

@theCodeDrift
theCodeDrift merged commit e8b2153 into main Oct 6, 2026
5 checks passed
@theCodeDrift
theCodeDrift deleted the fix/prompts-host-invocation-marker branch October 6, 2026 18:21
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.

prompts: header:false / mechanics:false still render versioned CLI invocations (0.12 nightly)

1 participant