Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -366,6 +366,9 @@ That GitHub release then triggers `.github/workflows/release.yml`, which perform
```sh
gx prompt # full checklist (paste into Codex/Claude)
gx prompt --exec # commands only
gx prompt --part task-loop
gx prompt --exec --part finish --part cleanup
gx prompt --list-parts
gx prompt --snippet # AGENTS.md managed-block template
```

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
schema: spec-driven
created: 2026-04-22
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
## Why

- `gx prompt` currently emits either the full setup checklist, the full
command-only block, or the AGENTS managed snippet.
- Agents and humans often need only one slice of that guidance
(`task-loop`, `finish`, `openspec`, etc.), so they either paste the whole
checklist or copy those lines into other docs/prompts by hand.
- That wastes tokens in agent handoffs and keeps prompt-facing docs more
repetitive than they need to be.

## What Changes

- Add named prompt parts to `gx prompt` so callers can request only the needed
guidance with `--part <name>`.
- Add `gx prompt --list-parts` so the available slices are discoverable without
reading source or README prose.
- Support `gx prompt --exec --part ...` for command-capable parts only, with a
clear error when a selected part has no shell-safe command form.
- Update README/help text and focused prompt tests around the new surface.

## Impact

- Existing `gx prompt`, `gx prompt --exec`, and `gx prompt --snippet` behavior
stays intact for callers that do not request parts.
- Agent/token usage improves because handoffs can fetch just the required
prompt slices instead of the entire checklist.
- The change is limited to CLI prompt rendering, prompt docs, and focused
tests; no branch/lock/doctor workflow behavior changes.
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
## ADDED Requirements

### Requirement: `gx prompt` SHALL emit named prompt parts
`gx prompt` SHALL support selecting one or more named checklist slices with
`--part <name>` so callers can request only the needed guidance.

#### Scenario: prompt mode returns only the selected parts
- **GIVEN** the user runs `gx prompt --part task-loop --part finish`
- **WHEN** the CLI renders prompt output
- **THEN** it SHALL include the `task-loop` and `finish` guidance in the order
requested
- **AND** it SHALL omit unrelated prompt sections such as `cleanup` and
`review-bot`
- **AND** the default `gx prompt` output without `--part` SHALL remain the full
checklist.

### Requirement: `gx prompt --exec` SHALL support command-capable parts
Command-only prompt output SHALL allow part selection for sections that have a
shell-safe command form.

#### Scenario: exec mode renders only the requested command-capable parts
- **GIVEN** the user runs `gx prompt --exec --part install --part task-loop`
- **WHEN** the CLI renders command-only output
- **THEN** it SHALL emit only the `install` and `task-loop` commands in the
order requested
- **AND** it SHALL omit command lines for other sections such as `cleanup`
unless they were requested.

#### Scenario: exec mode rejects prompt-only parts
- **GIVEN** the user runs `gx prompt --exec --part openspec`
- **WHEN** `openspec` has no shell-safe command-only rendering
- **THEN** the CLI SHALL exit non-zero
- **AND** it SHALL report that the selected part is not available in exec mode.

### Requirement: `gx prompt` SHALL list available parts
The CLI SHALL expose the available prompt part names without requiring source
inspection.

#### Scenario: list parts
- **WHEN** the user runs `gx prompt --list-parts`
- **THEN** the CLI SHALL print the supported part names
- **AND** the list SHALL include both command-capable parts and prompt-only
parts.
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
## Definition of Done

This change is complete only when **all** of the following are true:

- Every checkbox below is checked.
- The agent branch reaches `MERGED` state on `origin` and the PR URL + state are recorded in the completion handoff.
- If any step blocks (test failure, conflict, ambiguous result), append a `BLOCKED:` line under section 4 explaining the blocker and **STOP**. Do not tick remaining cleanup boxes; do not silently skip the cleanup pipeline.

## Handoff

- Handoff: change=`agent-codex-improve-gx-prompt-parts-for-token-usage-2026-04-22-16-05`; branch=`agent/codex/improve-gx-prompt-parts-for-token-usage-2026-04-22-16-05`; scope=`src/context.js, src/cli/main.js, test/prompt.test.js, README.md, OpenSpec change docs`; action=`add gx prompt part selection, document the new surface, and keep the full prompt modes backward compatible`.
- Copy prompt: Continue `agent-codex-improve-gx-prompt-parts-for-token-usage-2026-04-22-16-05` on branch `agent/codex/improve-gx-prompt-parts-for-token-usage-2026-04-22-16-05`. Work inside the existing sandbox, review `openspec/changes/agent-codex-improve-gx-prompt-parts-for-token-usage-2026-04-22-16-05/tasks.md`, continue from the current state instead of creating a new sandbox, and when the work is done run `gx branch finish --branch agent/codex/improve-gx-prompt-parts-for-token-usage-2026-04-22-16-05 --base main --via-pr --wait-for-merge --cleanup`.

## 1. Specification

- [x] 1.1 Finalize proposal scope and acceptance criteria for `agent-codex-improve-gx-prompt-parts-for-token-usage-2026-04-22-16-05`.
- [x] 1.2 Define normative requirements in `specs/gx-prompt-parts/spec.md`.

## 2. Implementation

- [x] 2.1 Add named `gx prompt --part` / `--list-parts` support while keeping the existing full prompt, `--exec`, and `--snippet` outputs intact.
- [x] 2.2 Teach `gx prompt --exec --part ...` to emit only command-capable slices and fail clearly when a selected part has no command-only form.
- [x] 2.3 Update focused prompt docs/tests in `README.md` and `test/prompt.test.js`.

## 3. Verification

- [x] 3.1 Run targeted project verification commands (`node --check src/context.js`, `node --check src/cli/main.js`, `node --test test/prompt.test.js`) — passed on `2026-04-22`.
- [x] 3.2 Run `openspec validate agent-codex-improve-gx-prompt-parts-for-token-usage-2026-04-22-16-05 --type change --strict` — passed on `2026-04-22`.
- [x] 3.3 Run `openspec validate --specs` — passed on `2026-04-22` with `No items found to validate.`

## 4. Cleanup (mandatory; run before claiming completion)

- [ ] 4.1 Run the cleanup pipeline: `gx branch finish --branch agent/codex/improve-gx-prompt-parts-for-token-usage-2026-04-22-16-05 --base main --via-pr --wait-for-merge --cleanup`. This handles commit -> push -> PR create -> merge wait -> worktree prune in one invocation.
- [ ] 4.2 Record the PR URL and final merge state (`MERGED`) in the completion handoff.
- [ ] 4.3 Confirm the sandbox worktree is gone (`git worktree list` no longer shows the agent path; `git branch -a` shows no surviving local/remote refs for the branch).
50 changes: 43 additions & 7 deletions src/cli/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,9 @@ const {
DEPRECATED_COMMAND_ALIASES,
envFlagIsTruthy,
defaultAgentWorktreeRelativeDir,
listAiSetupPartNames,
parseAiSetupPartNames,
renderAiSetupPrompt,
AI_SETUP_PROMPT,
AI_SETUP_COMMANDS,
SCORECARD_RISK_BY_CHECK,
Expand Down Expand Up @@ -5226,26 +5229,59 @@ function copyCommands() {
function prompt(rawArgs) {
const args = Array.isArray(rawArgs) ? rawArgs : [];
let variant = 'prompt';
for (const arg of args) {
let listParts = false;
const selectedParts = [];
for (let index = 0; index < args.length; index += 1) {
const arg = args[index];
if (arg === '--exec' || arg === '--commands') variant = 'exec';
else if (arg === '--snippet' || arg === '--agents') variant = 'snippet';
else if (arg === '--prompt' || arg === '--full') variant = 'prompt';
else if (arg === '--list-parts') listParts = true;
else if (arg === '--part' || arg === '--parts') {
const rawValue = args[index + 1];
if (!rawValue || rawValue.startsWith('--')) {
throw new Error(`${arg} requires a value`);
}
selectedParts.push(...parseAiSetupPartNames(rawValue));
index += 1;
} else if (arg.startsWith('--part=')) {
selectedParts.push(...parseAiSetupPartNames(arg.slice('--part='.length)));
} else if (arg.startsWith('--parts=')) {
selectedParts.push(...parseAiSetupPartNames(arg.slice('--parts='.length)));
}
else if (arg === '-h' || arg === '--help') variant = 'help';
else throw new Error(`Unknown option: ${arg}`);
}
if (variant === 'help') {
console.log(
`${SHORT_TOOL_NAME} prompt commands:\n` +
` ${SHORT_TOOL_NAME} prompt Print AI setup checklist\n` +
` ${SHORT_TOOL_NAME} prompt --exec Print setup commands only (shell-ready)\n` +
` ${SHORT_TOOL_NAME} prompt --snippet Print the AGENTS.md managed-block template`,
` ${SHORT_TOOL_NAME} prompt Print AI setup checklist\n` +
` ${SHORT_TOOL_NAME} prompt --exec Print setup commands only (shell-ready)\n` +
` ${SHORT_TOOL_NAME} prompt --part <name> Print only the named checklist slice(s)\n` +
` ${SHORT_TOOL_NAME} prompt --exec --part <name> Print only the named exec-capable slice(s)\n` +
` ${SHORT_TOOL_NAME} prompt --list-parts List prompt part names\n` +
` ${SHORT_TOOL_NAME} prompt --exec --list-parts List exec-capable prompt part names\n` +
` ${SHORT_TOOL_NAME} prompt --snippet Print the AGENTS.md managed-block template`,
);
process.exitCode = 0;
return;
}
if (variant === 'exec') return copyCommands();
if (variant === 'snippet') return printAgentsSnippet();
return copyPrompt();
if (variant === 'snippet') {
if (listParts || selectedParts.length > 0) {
throw new Error('--snippet does not support --list-parts or --part');
}
return printAgentsSnippet();
}
if (listParts) {
if (selectedParts.length > 0) {
throw new Error('--list-parts does not support --part');
}
process.stdout.write(`${listAiSetupPartNames({ execOnly: variant === 'exec' }).join('\n')}\n`);
process.exitCode = 0;
return;
}
process.stdout.write(renderAiSetupPrompt({ exec: variant === 'exec', parts: selectedParts }));
process.exitCode = 0;
}

function branch(rawArgs) {
Expand Down
Loading