-
Notifications
You must be signed in to change notification settings - Fork 0
feat(cli): export the knowledge prompts as @taskless/cli/prompts #87
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
thecodedrift
merged 6 commits into
main
from
openspec/export-knowledge-prompts-2-export
Aug 10, 2026
Merged
Changes from all commits
Commits
Show all changes
6 commits
Select commit
Hold shift + click to select a range
50b459c
feat(cli): export the knowledge prompts as @taskless/cli/prompts
thecodedrift 9ecc3ed
fix(cli): copy the whole dist when isolating the missing-binary test
thecodedrift 0fc58c4
docs(openspec): fill in the cli-knowledge-prompts purpose and scope i…
thecodedrift 8823b4e
docs(openspec): re-check the tasks this unit completes in the archive
thecodedrift 5dabcfb
ref(cli): type the shebang predicate against rollup, guard the untype…
thecodedrift a5c2334
docs(openspec): correct the declaration output path in the archived c…
thecodedrift File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| --- | ||
| "@taskless/cli": minor | ||
| --- | ||
|
|
||
| Add a `@taskless/cli/prompts` subpath export exposing the CLI's knowledge prompts as importable, topic-keyed render functions. | ||
|
|
||
| `getPrompt(topic, options?)` and the `PROMPTS` map return fully rendered recipe text, with every `%(KEY)s` placeholder already resolved from values the package holds, so a consumer never handles a template dialect. Topic names are typed as `PromptTopic` and start at `static`, the one recipe a service-side consumer can act on; everything else stays internal until a consumer needs it. `PromptOptions` covers the anonymous variant, a `packageManagerDlx` override, and `header: false` for callers placing the text in an LLM system prompt, where the CLI version in the header would otherwise churn the prompt-cache key on every publish. | ||
|
|
||
| The export is sourced from the same embedded recipes and the same render path `taskless help <topic>` serves, so the two surfaces cannot drift, and it carries no CLI runtime, so a Worker can import it without pulling in the command tree. |
File renamed without changes.
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
File renamed without changes.
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
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
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,142 @@ | ||
| # cli-knowledge-prompts Specification | ||
|
|
||
| ## Purpose | ||
|
|
||
| The CLI's `help/*.txt` recipes are the authoritative guidance Taskless gives an | ||
| agent about authoring and operating rules. Until now the only way to read them | ||
| was to run `taskless help`, which puts them out of reach of anything that cannot | ||
| spawn the CLI — notably the service-side generator, which needs the same text to | ||
| brief a model. | ||
|
|
||
| This capability publishes those recipes as a typed subpath export, | ||
| `@taskless/cli/prompts`, rendered through the same embed and the same render | ||
| path the `help` command uses. One source and one renderer means the two surfaces | ||
| cannot drift into giving different guidance. The export carries no CLI runtime, | ||
| so a Worker can import it without dragging in the command tree, and topic | ||
| membership is an explicit hand-maintained list so a new recipe file cannot | ||
| silently become public API. | ||
|
|
||
| ## Requirements | ||
|
|
||
| ### Requirement: The package exposes knowledge prompts via a dedicated import | ||
|
|
||
| The package SHALL expose its knowledge prompts (the `help/*.txt` recipes) through a subpath export `@taskless/cli/prompts`, built into `dist` and listed in `files`, so consumers can import them without invoking the CLI. | ||
|
|
||
| #### Scenario: Importing a prompt by topic | ||
|
|
||
| - **WHEN** a consumer imports `getPrompt` (or `PROMPTS`) from `@taskless/cli/prompts` | ||
| - **THEN** it receives the recipe text for a known topic (e.g. `static`) as a string | ||
|
|
||
| ### Requirement: The prompt export is typed | ||
|
|
||
| The export SHALL provide a `PromptTopic` union of the available canonical topics, a `PROMPTS: Record<PromptTopic, (options?: PromptOptions) => string>` map of render functions, and a `getPrompt(topic, options?)` accessor over the same. Referencing an unknown topic SHALL be a compile-time error against `PromptTopic`. | ||
|
|
||
| #### Scenario: Typed access to topics | ||
|
|
||
| - **WHEN** a consumer calls `getPrompt("static")` | ||
| - **THEN** it type-checks and returns the `static` recipe; `getPrompt("nope")` fails type-checking against `PromptTopic` | ||
|
|
||
| #### Scenario: A topic is callable from the map | ||
|
|
||
| - **WHEN** a consumer calls `PROMPTS.static()` with no arguments | ||
| - **THEN** it returns the same string as `getPrompt("static")` | ||
|
|
||
| ### Requirement: The export and the help command share one source and one renderer | ||
|
|
||
| The prompt export SHALL be sourced from the same embedded `help/*.txt` content that `commands/help.ts` serves, and SHALL render it through the same render path, with no duplicated embedding and no duplicated interpolation logic. Both surfaces SHALL return identical text for the same topic and equivalent options. | ||
|
|
||
| #### Scenario: Parity between import and help command | ||
|
|
||
| - **WHEN** the `help` command renders topic `T` and a consumer calls `getPrompt("T")` | ||
| - **THEN** the two texts are identical, including under a non-prod build target where the CLI invocation is rewritten | ||
|
|
||
| ### Requirement: The export returns fully-rendered prompt text | ||
|
|
||
| Calling a prompt SHALL return finished text with every `%(KEY)s` placeholder substituted — `CLI_VERSION` from the build-time version, `INPUT_SCHEMA` from the corresponding Zod input schema, `PACKAGE_MANAGER_DLX` from `PromptOptions.packageManagerDlx` or its default agent-fill marker — and with the build-target CLI invocation applied. The returned text SHALL NOT require further templating by the consumer. | ||
|
|
||
| #### Scenario: Placeholders are resolved | ||
|
|
||
|
thecodedrift marked this conversation as resolved.
|
||
| - **WHEN** a consumer calls a prompt for a recipe whose source contains `%(CLI_VERSION)s` | ||
| - **THEN** the returned string contains the rendered version and no literal `%(...)s` placeholder | ||
|
|
||
| #### Scenario: Schema-bearing topics render their input schema | ||
|
|
||
| - **WHEN** a recipe carrying `%(INPUT_SCHEMA)s` is rendered (today `rule-create` and `rule-improve`, both internal topics) | ||
| - **THEN** the placeholder is replaced by the JSON Schema rendered from that topic's Zod input schema | ||
|
|
||
| #### Scenario: Agent-fill marker defaults and overrides | ||
|
|
||
| - **WHEN** a recipe carrying `%(PACKAGE_MANAGER_DLX)s` is rendered without options (today `ci`, an internal topic) | ||
| - **THEN** the placeholder renders as the default `<package-manager-dlx>` marker; supplying `packageManagerDlx` substitutes that value instead | ||
|
|
||
| ### Requirement: The version header is suppressible | ||
|
|
||
| Rendered prompts SHALL begin with a header line naming the topic and the CLI version. Because that version participates in an LLM consumer's prompt-cache key, `PromptOptions.header` SHALL allow suppressing it. It SHALL default to `true`, leaving the `help` command's output and all existing behavior unchanged. | ||
|
|
||
| #### Scenario: Header suppressed for a cache-stable system prompt | ||
|
|
||
| - **WHEN** a consumer calls a prompt with `header: false` | ||
| - **THEN** the returned text omits the `# Topic: …` line and contains no CLI version string, while the body is otherwise identical to the default rendering | ||
|
|
||
| #### Scenario: Header present by default | ||
|
|
||
| - **WHEN** a prompt is called with no options, or the `help` command renders a topic | ||
| - **THEN** the header line is present, exactly as it renders today | ||
|
|
||
| #### Scenario: Build defines are inlined into the prompts entry | ||
|
|
||
| - **WHEN** a rendered prompt is inspected from the built `dist/prompts.js` | ||
| - **THEN** it contains no un-inlined build-define identifier (e.g. a literal `__VERSION__`) | ||
|
|
||
| ### Requirement: The prompts import is free of CLI runtime dependencies | ||
|
|
||
| The `@taskless/cli/prompts` module SHALL contain only embedded prompt data, types, and the render path — no `citty` command tree, telemetry, filesystem, or network imports — so importing it does not load `@taskless/cli`'s main entry. Its permitted runtime imports are the templating library and the leaf Zod input schemas required for rendering. | ||
|
|
||
| #### Scenario: Worker-safe import | ||
|
|
||
| - **WHEN** a consumer imports `@taskless/cli/prompts` | ||
| - **THEN** the module resolves without pulling in `dist/index.js` or its CLI runtime dependencies | ||
|
|
||
| ### Requirement: Anonymous variants are accessible distinctly from canonical | ||
|
|
||
| Where a `<topic>.anonymous.txt` variant exists, the export SHALL make it retrievable distinctly via `PromptOptions.anonymous`, falling back to the canonical recipe when no variant exists. | ||
|
|
||
| #### Scenario: Anonymous variant retrieval and fallback | ||
|
|
||
| - **WHEN** a consumer requests the anonymous variant of a topic that has one | ||
| - **THEN** it receives the `.anonymous` text; for a topic without a variant, it receives the canonical text | ||
|
|
||
| ### Requirement: Topic names and accessor shape are stable public API | ||
|
|
||
| The set of `PromptTopic` names, the `getPrompt`/`PROMPTS` shape, and the existing fields of `PromptOptions` SHALL be treated as public API under semver; recipe _text_ MAY change within a major version. | ||
|
|
||
| #### Scenario: Removing a topic is a breaking change | ||
|
|
||
| - **WHEN** a topic is removed or renamed, or the accessor signature changes | ||
| - **THEN** it SHALL be released as a major version bump; a text edit SHALL NOT | ||
|
|
||
| #### Scenario: Adding an option is not a breaking change | ||
|
|
||
| - **WHEN** a new optional field is added to `PromptOptions` | ||
| - **THEN** it SHALL NOT require a major version bump, since existing call sites keep their behavior | ||
|
|
||
| ### Requirement: Topic membership is explicit and verified against the recipe files | ||
|
|
||
| `PromptTopic` SHALL be derived from an explicit, hand-maintained list of exported topics rather than inferred from whatever recipe files are present, so that adding or removing a `help/*.txt` file cannot silently change the public API. Recipe files deliberately withheld from the export SHALL be recorded in an explicit internal-topics list. | ||
|
|
||
| An automated check SHALL assert that the set of canonical `help/*.txt` topics on disk is exactly the union of the exported topics and the internal-topics list, failing when the two diverge in either direction. | ||
|
|
||
| #### Scenario: A new recipe file is added without being classified | ||
|
|
||
| - **WHEN** a new canonical `help/<topic>.txt` is added and appears in neither the exported topics nor the internal-topics list | ||
| - **THEN** the completeness check SHALL fail, requiring the author to either export the topic or record it as internal | ||
|
|
||
| #### Scenario: An exported topic loses its recipe file | ||
|
|
||
| - **WHEN** a topic remains in `PromptTopic` but its canonical `help/<topic>.txt` no longer exists | ||
| - **THEN** the completeness check SHALL fail, rather than the topic rendering empty or undefined at runtime | ||
|
|
||
| #### Scenario: A deliberately internal recipe stays unexported | ||
|
|
||
| - **WHEN** a recipe file is listed as internal | ||
| - **THEN** the check SHALL pass and the topic SHALL NOT be a member of `PromptTopic` | ||
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
Oops, something went wrong.
Oops, something went wrong.
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.
Uh oh!
There was an error while loading. Please reload this page.