@promptbook/cli 0.114.0-47 → 0.114.0-49

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (153) hide show
  1. package/README.md +59 -25
  2. package/apps/agents-server/tests/e2e/mockSupabaseServer.cjs +79 -2
  3. package/apps/agents-server/tests/e2e/support/ChatHistoryNavigationSupport.ts +12 -2
  4. package/apps/agents-server/tests/e2e/support/auth.ts +6 -0
  5. package/esm/index.es.js +1327 -478
  6. package/esm/index.es.js.map +1 -1
  7. package/esm/scripts/run-codex-prompts/checks/CheckBeforeMode.d.ts +20 -0
  8. package/esm/scripts/run-codex-prompts/checks/checkRepairInstructions.d.ts +4 -0
  9. package/esm/scripts/run-codex-prompts/checks/createCheckBeforeRepairPrompt.d.ts +9 -0
  10. package/esm/scripts/run-codex-prompts/checks/limitCheckOutput.d.ts +4 -0
  11. package/esm/scripts/run-codex-prompts/checks/projectCheck.d.ts +26 -0
  12. package/esm/scripts/run-codex-prompts/checks/projectScriptReferences.d.ts +7 -0
  13. package/esm/scripts/run-codex-prompts/checks/runCheckBefore.d.ts +26 -0
  14. package/esm/scripts/run-codex-prompts/checks/runPromptCheckCommand.d.ts +16 -0
  15. package/esm/scripts/run-codex-prompts/{testing/runPromptWithTestFeedback.d.ts → checks/runPromptWithCheckFeedback.d.ts} +9 -9
  16. package/esm/scripts/run-codex-prompts/common/resolveCoderContext.d.ts +1 -1
  17. package/esm/scripts/run-codex-prompts/common/resolveCoderProjectContext.d.ts +17 -0
  18. package/esm/scripts/run-codex-prompts/common/resolveInlineOrFileText.d.ts +2 -0
  19. package/esm/scripts/run-codex-prompts/common/runGoScript/quoteBashArgument.d.ts +2 -0
  20. package/esm/scripts/run-codex-prompts/isolation/mapProjectReferenceToWorktree.d.ts +5 -0
  21. package/esm/scripts/run-codex-prompts/main/runPromptRound.d.ts +3 -1
  22. package/esm/scripts/run-codex-prompts/prompts/buildPromptLabel.d.ts +1 -1
  23. package/esm/scripts/run-codex-prompts/prompts/buildPromptLabelForDisplay.d.ts +1 -1
  24. package/esm/scripts/run-codex-prompts/prompts/buildPromptRunTraceContent.d.ts +3 -1
  25. package/esm/scripts/run-codex-prompts/prompts/formatCoderRunSteps.d.ts +2 -2
  26. package/esm/scripts/run-codex-prompts/prompts/listUpcomingTasks.d.ts +1 -1
  27. package/esm/scripts/run-codex-prompts/prompts/printPromptsToBeWritten.d.ts +1 -1
  28. package/esm/scripts/run-codex-prompts/server/buildCoderServerPromptResponse.d.ts +2 -0
  29. package/esm/scripts/run-codex-prompts/team/createCoderTeamPromptRunner.d.ts +1 -1
  30. package/esm/scripts/run-codex-prompts/ui/CoderRunUiState.d.ts +1 -1
  31. package/esm/src/cli/cli-commands/coder/agentCliOptions.d.ts +5 -0
  32. package/esm/src/cli/cli-commands/coder/coderAgentRole.d.ts +5 -0
  33. package/esm/src/cli/cli-commands/coder/coderReferencedArtifacts.d.ts +2 -2
  34. package/esm/src/cli/cli-commands/coder/ensureCoderPackageJsonFile.d.ts +3 -2
  35. package/esm/src/cli/cli-commands/coder/ensureCoderPackageJsonFile.test.d.ts +1 -0
  36. package/esm/src/cli/cli-commands/coder/findLegacyCoderCheckCallers.d.ts +5 -0
  37. package/esm/src/cli/cli-commands/coder/initializeCoderProjectConfiguration.d.ts +6 -0
  38. package/esm/src/cli/cli-commands/coder/mergeStringRecordJsonFile.d.ts +5 -3
  39. package/esm/src/cli/cli-commands/coder/planning/runPlanningSession.d.ts +3 -0
  40. package/esm/src/cli/cli-commands/coder/prepareCoderPackageJsonScripts.d.ts +12 -0
  41. package/esm/src/cli/cli-commands/coder.d.ts +1 -1
  42. package/esm/src/cli/cli-commands/common/coderCheckCliOptions.d.ts +21 -0
  43. package/esm/src/cli/cli-commands/common/coderCheckCliOptions.test.d.ts +1 -0
  44. package/esm/src/cli/cli-commands/common/projectCliOptions.d.ts +30 -0
  45. package/esm/src/cli/cli-commands/common/projectCliOptions.test.d.ts +1 -0
  46. package/esm/src/cli/cli-commands/common/promptbook-cli/$checkPromptbookCliInstallations.d.ts +1 -1
  47. package/esm/src/cli/cli-commands/common/promptbook-cli/$ensurePromptbookCliInstallations.d.ts +1 -1
  48. package/esm/src/cli/cli-commands/common/promptbook-cli/$resolvePromptbookCliInstallations.d.ts +1 -1
  49. package/esm/src/cli/cli-commands/common/promptbook-cli/$updatePromptbookCliInstallation.d.ts +1 -1
  50. package/esm/src/version.d.ts +1 -1
  51. package/package.json +1 -1
  52. package/src/_packages/cli.readme.md +15 -0
  53. package/src/cli/cli-commands/agent/chat.ts +11 -2
  54. package/src/cli/cli-commands/agent/exec.ts +11 -2
  55. package/src/cli/cli-commands/agent-folder/init.ts +6 -2
  56. package/src/cli/cli-commands/agent-folder/initializeAgentRunnerCommand.ts +9 -2
  57. package/src/cli/cli-commands/coder/add.ts +7 -1
  58. package/src/cli/cli-commands/coder/agentCliOptions.ts +11 -1
  59. package/src/cli/cli-commands/coder/coderAgentRole.ts +6 -0
  60. package/src/cli/cli-commands/coder/coderReferencedArtifacts.ts +3 -3
  61. package/src/cli/cli-commands/coder/ensureCoderPackageJsonFile.ts +22 -3
  62. package/src/cli/cli-commands/coder/find-fresh-emoji-tags.ts +3 -0
  63. package/src/cli/cli-commands/coder/find-refactor-candidates.ts +3 -0
  64. package/src/cli/cli-commands/coder/find-unwritten.ts +3 -0
  65. package/src/cli/cli-commands/coder/findLegacyCoderCheckCallers.ts +87 -0
  66. package/src/cli/cli-commands/coder/generate-boilerplates.ts +3 -0
  67. package/src/cli/cli-commands/coder/getDefaultCoderPackageJsonScripts.ts +6 -7
  68. package/src/cli/cli-commands/coder/init.ts +8 -2
  69. package/src/cli/cli-commands/coder/initializeCoderProjectConfiguration.ts +16 -4
  70. package/src/cli/cli-commands/coder/list.ts +6 -1
  71. package/src/cli/cli-commands/coder/mergeStringRecordJsonFile.ts +14 -4
  72. package/src/cli/cli-commands/coder/ping.ts +7 -1
  73. package/src/cli/cli-commands/coder/plan.ts +17 -5
  74. package/src/cli/cli-commands/coder/planning/README.md +5 -3
  75. package/src/cli/cli-commands/coder/planning/fixtures/coding.cjs +22 -0
  76. package/src/cli/cli-commands/coder/planning/runPlanningSession.ts +14 -3
  77. package/src/cli/cli-commands/coder/planning/savePlanningChanges.ts +1 -3
  78. package/src/cli/cli-commands/coder/prepareCoderPackageJsonScripts.ts +304 -0
  79. package/src/cli/cli-commands/coder/printInitializationSummary.ts +5 -1
  80. package/src/cli/cli-commands/coder/promptsReadmeTemplate.ts +31 -13
  81. package/src/cli/cli-commands/coder/run.ts +31 -65
  82. package/src/cli/cli-commands/coder/server.ts +21 -39
  83. package/src/cli/cli-commands/coder/verify.ts +3 -0
  84. package/src/cli/cli-commands/coder.ts +2 -2
  85. package/src/cli/cli-commands/common/coderCheckCliOptions.ts +107 -0
  86. package/src/cli/cli-commands/common/projectCliOptions.ts +78 -0
  87. package/src/cli/cli-commands/common/promptbook-cli/$checkPromptbookCliInstallations.ts +4 -2
  88. package/src/cli/cli-commands/common/promptbook-cli/$ensurePromptbookCliInstallations.ts +3 -2
  89. package/src/cli/cli-commands/common/promptbook-cli/$resolvePromptbookCliInstallations.ts +8 -4
  90. package/src/cli/cli-commands/common/promptbook-cli/$updatePromptbookCliInstallation.ts +5 -2
  91. package/src/cli/cli-commands/common/validateCoderRunOptions.ts +12 -5
  92. package/src/cli/cli-commands/common/workspaceRepository.ts +7 -19
  93. package/src/cli/cli-commands/common/workspaceRepositoryCliOptions.ts +2 -0
  94. package/src/execution/translation/automatic-translate/translateMessages.ts +1 -3
  95. package/src/other/templates/getTemplatesPipelineCollection.ts +1060 -917
  96. package/src/version.ts +2 -2
  97. package/src/versions.txt +2 -1
  98. package/umd/index.umd.js +1324 -475
  99. package/umd/index.umd.js.map +1 -1
  100. package/umd/scripts/run-codex-prompts/checks/CheckBeforeMode.d.ts +20 -0
  101. package/umd/scripts/run-codex-prompts/checks/checkRepairInstructions.d.ts +4 -0
  102. package/umd/scripts/run-codex-prompts/checks/createCheckBeforeRepairPrompt.d.ts +9 -0
  103. package/umd/scripts/run-codex-prompts/checks/limitCheckOutput.d.ts +4 -0
  104. package/umd/scripts/run-codex-prompts/checks/projectCheck.d.ts +26 -0
  105. package/umd/scripts/run-codex-prompts/checks/projectScriptReferences.d.ts +7 -0
  106. package/umd/scripts/run-codex-prompts/checks/runCheckBefore.d.ts +26 -0
  107. package/umd/scripts/run-codex-prompts/checks/runPromptCheckCommand.d.ts +16 -0
  108. package/umd/scripts/run-codex-prompts/{testing/runPromptWithTestFeedback.d.ts → checks/runPromptWithCheckFeedback.d.ts} +9 -9
  109. package/umd/scripts/run-codex-prompts/common/resolveCoderContext.d.ts +1 -1
  110. package/umd/scripts/run-codex-prompts/common/resolveCoderProjectContext.d.ts +17 -0
  111. package/umd/scripts/run-codex-prompts/common/resolveInlineOrFileText.d.ts +2 -0
  112. package/umd/scripts/run-codex-prompts/common/runGoScript/quoteBashArgument.d.ts +2 -0
  113. package/umd/scripts/run-codex-prompts/isolation/mapProjectReferenceToWorktree.d.ts +5 -0
  114. package/umd/scripts/run-codex-prompts/main/runPromptRound.d.ts +3 -1
  115. package/umd/scripts/run-codex-prompts/prompts/buildPromptLabel.d.ts +1 -1
  116. package/umd/scripts/run-codex-prompts/prompts/buildPromptLabelForDisplay.d.ts +1 -1
  117. package/umd/scripts/run-codex-prompts/prompts/buildPromptRunTraceContent.d.ts +3 -1
  118. package/umd/scripts/run-codex-prompts/prompts/formatCoderRunSteps.d.ts +2 -2
  119. package/umd/scripts/run-codex-prompts/prompts/listUpcomingTasks.d.ts +1 -1
  120. package/umd/scripts/run-codex-prompts/prompts/printPromptsToBeWritten.d.ts +1 -1
  121. package/umd/scripts/run-codex-prompts/server/buildCoderServerPromptResponse.d.ts +2 -0
  122. package/umd/scripts/run-codex-prompts/team/createCoderTeamPromptRunner.d.ts +1 -1
  123. package/umd/scripts/run-codex-prompts/ui/CoderRunUiState.d.ts +1 -1
  124. package/umd/src/cli/cli-commands/coder/agentCliOptions.d.ts +5 -0
  125. package/umd/src/cli/cli-commands/coder/coderAgentRole.d.ts +5 -0
  126. package/umd/src/cli/cli-commands/coder/coderReferencedArtifacts.d.ts +2 -2
  127. package/umd/src/cli/cli-commands/coder/ensureCoderPackageJsonFile.d.ts +3 -2
  128. package/umd/src/cli/cli-commands/coder/ensureCoderPackageJsonFile.test.d.ts +1 -0
  129. package/umd/src/cli/cli-commands/coder/findLegacyCoderCheckCallers.d.ts +5 -0
  130. package/umd/src/cli/cli-commands/coder/initializeCoderProjectConfiguration.d.ts +6 -0
  131. package/umd/src/cli/cli-commands/coder/mergeStringRecordJsonFile.d.ts +5 -3
  132. package/umd/src/cli/cli-commands/coder/planning/runPlanningSession.d.ts +3 -0
  133. package/umd/src/cli/cli-commands/coder/prepareCoderPackageJsonScripts.d.ts +12 -0
  134. package/umd/src/cli/cli-commands/coder.d.ts +1 -1
  135. package/umd/src/cli/cli-commands/common/coderCheckCliOptions.d.ts +21 -0
  136. package/umd/src/cli/cli-commands/common/coderCheckCliOptions.test.d.ts +1 -0
  137. package/umd/src/cli/cli-commands/common/projectCliOptions.d.ts +30 -0
  138. package/umd/src/cli/cli-commands/common/projectCliOptions.test.d.ts +1 -0
  139. package/umd/src/cli/cli-commands/common/promptbook-cli/$checkPromptbookCliInstallations.d.ts +1 -1
  140. package/umd/src/cli/cli-commands/common/promptbook-cli/$ensurePromptbookCliInstallations.d.ts +1 -1
  141. package/umd/src/cli/cli-commands/common/promptbook-cli/$resolvePromptbookCliInstallations.d.ts +1 -1
  142. package/umd/src/cli/cli-commands/common/promptbook-cli/$updatePromptbookCliInstallation.d.ts +1 -1
  143. package/umd/src/version.d.ts +1 -1
  144. package/esm/scripts/run-codex-prompts/testing/TestBeforeMode.d.ts +0 -16
  145. package/esm/scripts/run-codex-prompts/testing/createTestBeforeRepairPrompt.d.ts +0 -9
  146. package/esm/scripts/run-codex-prompts/testing/limitTestOutput.d.ts +0 -4
  147. package/esm/scripts/run-codex-prompts/testing/runPromptTestCommand.d.ts +0 -14
  148. package/esm/scripts/run-codex-prompts/testing/runTestBefore.d.ts +0 -24
  149. package/umd/scripts/run-codex-prompts/testing/TestBeforeMode.d.ts +0 -16
  150. package/umd/scripts/run-codex-prompts/testing/createTestBeforeRepairPrompt.d.ts +0 -9
  151. package/umd/scripts/run-codex-prompts/testing/limitTestOutput.d.ts +0 -4
  152. package/umd/scripts/run-codex-prompts/testing/runPromptTestCommand.d.ts +0 -14
  153. package/umd/scripts/run-codex-prompts/testing/runTestBefore.d.ts +0 -24
@@ -1,7 +1,4 @@
1
- import {
2
- Command as Program /* <- Note: [🔸] Using Program because Command is misleading name */,
3
- Option,
4
- } from 'commander';
1
+ import { Command as Program /* <- Note: [🔸] Using Program because Command is misleading name */ } from 'commander';
5
2
  import { spaceTrim } from 'spacetrim';
6
3
  import { assertsError } from '../../../errors/assertsError';
7
4
  import type { $side_effect } from '../../../utils/organization/$side_effect';
@@ -10,6 +7,7 @@ import { $assertSufficientFreeDiskSpace } from '../common/disk-space/$assertSuff
10
7
  import { validateCoderRunOptions } from '../common/validateCoderRunOptions';
11
8
  import { $preflightWorkspaceRepository } from '../common/workspaceRepository';
12
9
  import { addWorkspaceRepositoryOptions } from '../common/workspaceRepositoryCliOptions';
10
+ import { normalizeProjectCliOptions } from '../common/projectCliOptions';
13
11
  import { handleActionErrors } from '../common/handleActionErrors';
14
12
  import { $ensureHarnessInstallations } from '../common/harness/$ensureHarnessInstallations';
15
13
  import {
@@ -29,13 +27,13 @@ import {
29
27
  } from '../common/promptRunnerCliOptions';
30
28
  import { addPromptPriorityOptions } from '../common/promptPriorityCliOptions';
31
29
  import {
32
- DEFAULT_CODER_TEST_COMMAND,
33
- TEST_BEFORE_MODE_VALUES,
34
- type TestBeforeMode,
35
- } from '../../../../scripts/run-codex-prompts/testing/TestBeforeMode';
30
+ resolveCoderCheckCommand,
31
+ type CheckBeforeMode,
32
+ } from '../../../../scripts/run-codex-prompts/checks/CheckBeforeMode';
33
+ import { addCoderCheckOptions, normalizeCheckCommandOption } from '../common/coderCheckCliOptions';
36
34
  import { DEFAULT_WAIT_AFTER_ERROR_MS, parseOptionalWaitDuration } from './waitOptions';
37
35
  import { $ensureCoderHarnessGitignoreRules } from './$ensureCoderHarnessGitignoreRules';
38
- import { addCoderAgentOption, type CoderAgentCliOptions } from './agentCliOptions';
36
+ import { addCoderExecutionOptions, type CoderAgentCliOptions } from './agentCliOptions';
39
37
  import { printCoderRunFailure } from './printCoderRunFailure';
40
38
 
41
39
  /**
@@ -75,8 +73,8 @@ export function $initializeCoderRunCommand(program: Program): $side_effect {
75
73
  - Offers to add missing project-local ignore rules for the selected harness
76
74
  - In interactive mode, checks local and global Promptbook CLI installations and offers to update them
77
75
  - Supports GPG signing of commits
78
- - Optional pre-coding test run that can stop or repair pre-existing failures
79
- - Optional post-prompt verification with test-feedback retries
76
+ - Optional pre-coding check run that can stop or repair pre-existing failures
77
+ - Optional post-prompt checks with check-feedback retries
80
78
  - Progress tracking and interactive P/S/X terminal controls; O changes only the dashboard output view
81
79
  - Dry-run mode to preview prompts
82
80
  `,
@@ -86,25 +84,8 @@ export function $initializeCoderRunCommand(program: Program): $side_effect {
86
84
  command.option('--dry-run', 'Print unwritten prompts without executing', false);
87
85
  addPromptRunnerSelectionOptions(command);
88
86
  addQuestionsOption(command);
89
- addCoderAgentOption(command, 'developer');
90
- command.option(
91
- '--context <context-or-file>',
92
- 'Append extra instructions either inline or from a file path relative to the current project',
93
- );
94
- command.option(
95
- '--test <test-command...>',
96
- 'Run a verification command after each prompt; quote it when the command itself contains top-level flags',
97
- );
98
- command.addOption(
99
- new Option(
100
- '--test-before <mode>',
101
- `Run tests before coding: ${TEST_BEFORE_MODE_VALUES.join(
102
- ', ',
103
- )} (defaults to no; uses npm test when --test is omitted)`,
104
- )
105
- .choices([...TEST_BEFORE_MODE_VALUES])
106
- .default('no'),
107
- );
87
+ addCoderExecutionOptions(command);
88
+ addCoderCheckOptions(command, true);
108
89
  command.option(
109
90
  '--preserve-logs',
110
91
  'Keep generated temp prompt/log artifacts after successful rounds for debugging and analytics',
@@ -166,12 +147,13 @@ export function $initializeCoderRunCommand(program: Program): $side_effect {
166
147
 
167
148
  command.action(
168
149
  handleActionErrors(async (cliOptions) => {
150
+ const projectOptions = normalizeProjectCliOptions(cliOptions);
169
151
  const {
170
152
  dryRun,
171
153
  agent,
172
154
  context,
173
- test,
174
- testBefore,
155
+ check,
156
+ checkBefore,
175
157
  preserveLogs,
176
158
  isolate: isIsolated,
177
159
  priority,
@@ -188,8 +170,8 @@ export function $initializeCoderRunCommand(program: Program): $side_effect {
188
170
  readonly dryRun: boolean;
189
171
  readonly agent?: string;
190
172
  readonly context?: string;
191
- readonly test?: string | string[];
192
- readonly testBefore: TestBeforeMode;
173
+ readonly check?: string | string[];
174
+ readonly checkBefore: CheckBeforeMode;
193
175
  readonly preserveLogs: boolean;
194
176
  readonly isolate: boolean;
195
177
  readonly priority?: number;
@@ -205,8 +187,7 @@ export function $initializeCoderRunCommand(program: Program): $side_effect {
205
187
  } & PromptRunnerCliOptions &
206
188
  CoderAgentCliOptions;
207
189
 
208
- const configuredTestCommand = normalizeCommandOptionValue(test);
209
- const testCommand = configuredTestCommand ?? (testBefore === 'no' ? undefined : DEFAULT_CODER_TEST_COMMAND);
190
+ const checkCommand = resolveCoderCheckCommand(normalizeCheckCommandOption(check), checkBefore);
210
191
  const runnerOptions = normalizePromptRunnerCliOptions(cliOptions as PromptRunnerCliOptions, {
211
192
  isAgentRequired: !dryRun,
212
193
  });
@@ -239,8 +220,8 @@ export function $initializeCoderRunCommand(program: Program): $side_effect {
239
220
  model: runnerOptions.model,
240
221
  agent,
241
222
  context,
242
- testCommand,
243
- testBefore,
223
+ checkCommand,
224
+ checkBefore,
244
225
  preserveLogs,
245
226
  isIsolated,
246
227
  noUi: runnerOptions.noUi,
@@ -260,20 +241,25 @@ export function $initializeCoderRunCommand(program: Program): $side_effect {
260
241
 
261
242
  validateCoderRunOptions(runOptions);
262
243
  const workspace = await $preflightWorkspaceRepository({
244
+ ...projectOptions,
263
245
  policy: dryRun ? 'read-only' : 'mutate',
264
246
  ...questionsOptions,
265
247
  });
266
248
 
249
+ const { resolveCoderProjectContext } = await import(
250
+ '../../../../scripts/run-codex-prompts/common/resolveCoderProjectContext'
251
+ );
252
+ const projectContext = await resolveCoderProjectContext({
253
+ projectPath: workspace.projectPath,
254
+ agent,
255
+ context,
256
+ });
257
+
267
258
  if (!dryRun) {
268
- // Reject missing or unreadable Books before offering installations or project configuration writes.
269
- const { resolveCoderAgentBook } = await import(
270
- '../../../../scripts/run-codex-prompts/common/resolveCoderAgent'
271
- );
272
- await resolveCoderAgentBook(agent, workspace.projectPath, { defaultRole: 'developer' });
273
259
  // Check disk space before installations and repository writes; previews require no setup.
274
260
  await $assertSufficientFreeDiskSpace(workspace.projectPath);
275
261
 
276
- if (await $ensurePromptbookCliInstallations(questionsOptions)) {
262
+ if (await $ensurePromptbookCliInstallations(questionsOptions, workspace.projectPath)) {
277
263
  return process.exit(0);
278
264
  }
279
265
 
@@ -289,8 +275,7 @@ export function $initializeCoderRunCommand(program: Program): $side_effect {
289
275
  const { runCodexPrompts } = await import('../../../../scripts/run-codex-prompts/main/runCodexPrompts');
290
276
 
291
277
  try {
292
- // Override process.argv to pass options to the legacy parseRunOptions if needed
293
- await runCodexPrompts({ ...runOptions, workspace });
278
+ await runCodexPrompts({ ...runOptions, workspace, projectContext });
294
279
  } catch (error) {
295
280
  assertsError(error);
296
281
  printCoderRunFailure(error);
@@ -302,24 +287,5 @@ export function $initializeCoderRunCommand(program: Program): $side_effect {
302
287
  );
303
288
  }
304
289
 
305
- /**
306
- * Joins one Commander option that may be parsed either as a single string or a variadic token array.
307
- *
308
- * @private internal utility of `coder run` command
309
- */
310
- function normalizeCommandOptionValue(value: string | string[] | undefined): string | undefined {
311
- if (value === undefined) {
312
- return undefined;
313
- }
314
-
315
- const parts = Array.isArray(value) ? value : [value];
316
- const normalizedValue = parts
317
- .map((part) => part.trim())
318
- .filter(Boolean)
319
- .join(' ')
320
- .trim();
321
- return normalizedValue === '' ? undefined : normalizedValue;
322
- }
323
-
324
290
  // Note: [🟡] Code for CLI command [run](src/cli/cli-commands/coder/run.ts) should never be published outside of `@promptbook/cli`
325
291
  // Note: [💞] Ignore a discrepancy between file name and entity name
@@ -3,6 +3,7 @@ import {
3
3
  Option,
4
4
  } from 'commander';
5
5
  import { spaceTrim } from 'spacetrim';
6
+ import { addCoderCheckOptions, normalizeCheckCommandOption } from '../common/coderCheckCliOptions';
6
7
  import { NETWORK_LIMITS } from '../../../constants';
7
8
  import { assertsError } from '../../../errors/assertsError';
8
9
  import { NotAllowed } from '../../../errors/NotAllowed';
@@ -12,6 +13,7 @@ import { $assertSufficientFreeDiskSpace } from '../common/disk-space/$assertSuff
12
13
  import { validateCoderRunOptions } from '../common/validateCoderRunOptions';
13
14
  import { $preflightWorkspaceRepository } from '../common/workspaceRepository';
14
15
  import { addWorkspaceRepositoryOptions } from '../common/workspaceRepositoryCliOptions';
16
+ import { normalizeProjectCliOptions } from '../common/projectCliOptions';
15
17
  import { handleActionErrors } from '../common/handleActionErrors';
16
18
  import { $ensureHarnessInstallations } from '../common/harness/$ensureHarnessInstallations';
17
19
  import {
@@ -31,7 +33,7 @@ import {
31
33
  import { addPromptPriorityOptions } from '../common/promptPriorityCliOptions';
32
34
  import { DEFAULT_WAIT_AFTER_ERROR_MS, parseOptionalWaitDuration } from './waitOptions';
33
35
  import { $ensureCoderHarnessGitignoreRules } from './$ensureCoderHarnessGitignoreRules';
34
- import { addCoderAgentOption, type CoderAgentCliOptions } from './agentCliOptions';
36
+ import { addCoderExecutionOptions, type CoderAgentCliOptions } from './agentCliOptions';
35
37
  import { printCoderRunFailure } from './printCoderRunFailure';
36
38
 
37
39
  /**
@@ -84,15 +86,8 @@ export function $initializeCoderServerCommand(program: Program): $side_effect {
84
86
  command.option('--dry-run', 'Print unwritten prompts without executing', false);
85
87
  addPromptRunnerSelectionOptions(command);
86
88
  addQuestionsOption(command);
87
- addCoderAgentOption(command, 'developer');
88
- command.option(
89
- '--context <context-or-file>',
90
- 'Append extra instructions either inline or from a file path relative to the current project',
91
- );
92
- command.option(
93
- '--test <test-command...>',
94
- 'Run a verification command after each prompt; quote it when the command itself contains top-level flags',
95
- );
89
+ addCoderExecutionOptions(command);
90
+ addCoderCheckOptions(command, false);
96
91
  command.option(
97
92
  '--preserve-logs',
98
93
  'Keep generated temp prompt/log artifacts after successful rounds for debugging and analytics',
@@ -139,12 +134,13 @@ export function $initializeCoderServerCommand(program: Program): $side_effect {
139
134
 
140
135
  command.action(
141
136
  handleActionErrors(async (cliOptions) => {
137
+ const projectOptions = normalizeProjectCliOptions(cliOptions);
142
138
  const {
143
139
  port: rawPort,
144
140
  dryRun,
145
141
  agent,
146
142
  context,
147
- test,
143
+ check,
148
144
  preserveLogs,
149
145
  priority,
150
146
  minPriority: minimumPriority,
@@ -160,7 +156,7 @@ export function $initializeCoderServerCommand(program: Program): $side_effect {
160
156
  readonly dryRun: boolean;
161
157
  readonly agent?: string;
162
158
  readonly context?: string;
163
- readonly test?: string | string[];
159
+ readonly check?: string | string[];
164
160
  readonly preserveLogs: boolean;
165
161
  readonly priority?: number;
166
162
  readonly minPriority?: number;
@@ -175,7 +171,7 @@ export function $initializeCoderServerCommand(program: Program): $side_effect {
175
171
  CoderAgentCliOptions;
176
172
 
177
173
  const port = parseCoderServerPort(rawPort);
178
- const testCommand = normalizeCommandOptionValue(test);
174
+ const checkCommand = normalizeCheckCommandOption(check);
179
175
  const runnerOptions = normalizePromptRunnerCliOptions(cliOptions as PromptRunnerCliOptions, {
180
176
  isAgentRequired: !dryRun,
181
177
  });
@@ -203,7 +199,7 @@ export function $initializeCoderServerCommand(program: Program): $side_effect {
203
199
  model: runnerOptions.model,
204
200
  agent,
205
201
  context,
206
- testCommand,
202
+ checkCommand,
207
203
  preserveLogs,
208
204
  noUi: runnerOptions.noUi,
209
205
  thinkingLevel: runnerOptions.thinkingLevel,
@@ -221,16 +217,21 @@ export function $initializeCoderServerCommand(program: Program): $side_effect {
221
217
 
222
218
  validateCoderRunOptions(runOptions);
223
219
  const workspace = await $preflightWorkspaceRepository({
220
+ ...projectOptions,
224
221
  policy: dryRun ? 'read-only' : 'mutate',
225
222
  ...questionsOptions,
226
223
  });
227
224
 
225
+ const { resolveCoderProjectContext } = await import(
226
+ '../../../../scripts/run-codex-prompts/common/resolveCoderProjectContext'
227
+ );
228
+ const projectContext = await resolveCoderProjectContext({
229
+ projectPath: workspace.projectPath,
230
+ agent,
231
+ context,
232
+ });
233
+
228
234
  if (!dryRun) {
229
- // Reject missing or unreadable Books before offering installations or project configuration writes.
230
- const { resolveCoderAgentBook } = await import(
231
- '../../../../scripts/run-codex-prompts/common/resolveCoderAgent'
232
- );
233
- await resolveCoderAgentBook(agent, workspace.projectPath, { defaultRole: 'developer' });
234
235
  // Check disk space before installations and repository writes; previews require no setup.
235
236
  await $assertSufficientFreeDiskSpace(workspace.projectPath);
236
237
 
@@ -248,7 +249,7 @@ export function $initializeCoderServerCommand(program: Program): $side_effect {
248
249
  );
249
250
 
250
251
  try {
251
- await runCodexPromptsServer({ ...runOptions, workspace });
252
+ await runCodexPromptsServer({ ...runOptions, workspace, projectContext });
252
253
  } catch (error) {
253
254
  assertsError(error);
254
255
  printCoderRunFailure(error);
@@ -281,24 +282,5 @@ function parseCoderServerPort(rawPort: string): number_port {
281
282
  return port as number_port;
282
283
  }
283
284
 
284
- /**
285
- * Joins one Commander option that may be parsed either as a single string or a variadic token array.
286
- *
287
- * @private internal utility of `coder server` command
288
- */
289
- function normalizeCommandOptionValue(value: string | string[] | undefined): string | undefined {
290
- if (value === undefined) {
291
- return undefined;
292
- }
293
-
294
- const parts = Array.isArray(value) ? value : [value];
295
- const normalizedValue = parts
296
- .map((part) => part.trim())
297
- .filter(Boolean)
298
- .join(' ')
299
- .trim();
300
- return normalizedValue === '' ? undefined : normalizedValue;
301
- }
302
-
303
285
  // Note: [🟡] Code for CLI command [server](src/cli/cli-commands/coder/server.ts) should never be published outside of `@promptbook/cli`
304
286
  // Note: [💞] Ignore a discrepancy between file name and entity name
@@ -20,6 +20,7 @@ import {
20
20
  } from '../common/coderGitSyncCliOptions';
21
21
  import { $preflightWorkspaceRepository } from '../common/workspaceRepository';
22
22
  import { addWorkspaceRepositoryOptions } from '../common/workspaceRepositoryCliOptions';
23
+ import { normalizeProjectCliOptions } from '../common/projectCliOptions';
23
24
  import { handleActionErrors } from '../common/handleActionErrors';
24
25
 
25
26
  /**
@@ -81,6 +82,7 @@ export function $initializeCoderVerifyCommand(program: Program): $side_effect {
81
82
 
82
83
  command.action(
83
84
  handleActionErrors(async (cliOptions) => {
85
+ const projectOptions = normalizeProjectCliOptions(cliOptions);
84
86
  const { order, ignore } = cliOptions as {
85
87
  readonly order: VerifyPromptsOrder;
86
88
  readonly ignore: ReadonlyArray<string>;
@@ -89,6 +91,7 @@ export function $initializeCoderVerifyCommand(program: Program): $side_effect {
89
91
  const gitSync = normalizeCoderGitSyncCliOptions(cliOptions as CoderGitSyncCliOptions);
90
92
 
91
93
  const workspace = await $preflightWorkspaceRepository({
94
+ ...projectOptions,
92
95
  policy: 'mutate',
93
96
  isAskingQuestionsEnabled: cliOptions.questions,
94
97
  });
@@ -24,7 +24,7 @@ import { $initializeCoderVerifyCommand } from './coder/verify';
24
24
  * The coder command provides utilities for automated coding:
25
25
  * - init: Initialize coder configuration in current project
26
26
  * - add: Add one ready-to-run prompt file to the queue
27
- * - plan: Discuss features with Planner and author reviewed PRDs
27
+ * - plan: Discuss features with Developer and author reviewed PRDs
28
28
  * - generate-boilerplates: Generate prompt boilerplate files
29
29
  * - find-refactor-candidates: Find files that need refactoring
30
30
  * - list: List ready prompts in priority order without running them
@@ -46,7 +46,7 @@ export function $initializeCoderCommand(program: Program): $side_effect {
46
46
  Subcommands:
47
47
  - init: Initialize coder configuration in current project
48
48
  - add: Add one ready-to-run prompt file to the queue
49
- - plan: Discuss features with Planner and author reviewed PRDs
49
+ - plan: Discuss features with Developer and author reviewed PRDs
50
50
  - generate-boilerplates: Generate prompt boilerplate files
51
51
  - find-refactor-candidates: Find files that need refactoring
52
52
  - find-unwritten: List prompt sections that still need to be authored
@@ -0,0 +1,107 @@
1
+ import { Command, Option } from 'commander';
2
+ import { spaceTrim } from 'spacetrim';
3
+ import { CHECK_BEFORE_MODE_VALUES } from '../../../../scripts/run-codex-prompts/checks/CheckBeforeMode';
4
+ import { quoteBashArgument } from '../../../../scripts/run-codex-prompts/common/runGoScript/quoteBashArgument';
5
+ import { NotAllowed } from '../../../errors/NotAllowed';
6
+
7
+ /** Standalone shell composition tokens remain operators when a command is supplied as several arguments. */
8
+ const SHELL_COMPOSITION_TOKENS = new Set([
9
+ '&&',
10
+ '||',
11
+ '|',
12
+ '|&',
13
+ '&',
14
+ ';',
15
+ '(',
16
+ ')',
17
+ '>',
18
+ '>>',
19
+ '<',
20
+ '2>',
21
+ '2>>',
22
+ '2>&1',
23
+ ]);
24
+
25
+ /**
26
+ * Retired aggregate option spellings and their canonical replacements, used only for migration diagnostics.
27
+ * @private shared CLI migration definitions for Coder execution
28
+ */
29
+ export const LEGACY_CODER_CHECK_OPTIONS = [
30
+ ['--test', '--check'],
31
+ ['--test-before', '--check-before'],
32
+ ] as const;
33
+
34
+ /**
35
+ * Registers the shared project check command and rejects retired aggregate-test spellings.
36
+ * @private shared CLI registration for Coder execution
37
+ */
38
+ export function addCoderCheckOptions(command: Command, isCheckBeforeSupported: boolean): void {
39
+ command.option(
40
+ '--check <check-command...>',
41
+ 'Run project checks after each prompt; quote the full command when it contains flags or shell composition',
42
+ );
43
+ if (isCheckBeforeSupported) {
44
+ command.addOption(
45
+ new Option(
46
+ '--check-before <mode>',
47
+ `Check before coding: ${CHECK_BEFORE_MODE_VALUES.join(
48
+ ', ',
49
+ )} (defaults to no; uses npm run check when --check is omitted)`,
50
+ )
51
+ .choices([...CHECK_BEFORE_MODE_VALUES])
52
+ .default('no'),
53
+ );
54
+ }
55
+
56
+ // These diagnostic-only options never forward a value or start execution.
57
+ for (const [legacyFlag, replacementFlag] of LEGACY_CODER_CHECK_OPTIONS) {
58
+ command.addOption(new Option(`${legacyFlag} [value...]`).hideHelp());
59
+ command.on(`option:${legacyFlag.slice(2)}`, () => {
60
+ command.error(formatLegacyCoderCheckOptionError(legacyFlag, replacementFlag));
61
+ });
62
+ }
63
+ }
64
+
65
+ /**
66
+ * Builds the same actionable migration diagnostic for registered and direct-script entrypoints.
67
+ * @private shared CLI diagnostic for Coder execution
68
+ */
69
+ export function formatLegacyCoderCheckOptionError(legacyFlag: string, replacementFlag: string): string {
70
+ return `Aggregate verification option \`${legacyFlag}\` was renamed to \`${replacementFlag}\`. Update your command and package.json scripts.`;
71
+ }
72
+
73
+ /**
74
+ * Normalizes shell command tokens without parsing a quoted command again or losing spaced argument boundaries.
75
+ * @private shared command normalization for Coder execution
76
+ */
77
+ export function normalizeCheckCommandOption(value: string | ReadonlyArray<string> | undefined): string | undefined {
78
+ if (value === undefined) return undefined;
79
+ const parts = typeof value === 'string' ? [value] : value;
80
+ const firstPart = parts[0]?.trim() ?? '';
81
+ for (const [legacyFlag, replacementFlag] of LEGACY_CODER_CHECK_OPTIONS) {
82
+ if (firstPart === legacyFlag || firstPart.startsWith(`${legacyFlag}=`)) {
83
+ throw new NotAllowed(formatLegacyCoderCheckOptionError(legacyFlag, replacementFlag));
84
+ }
85
+ }
86
+ const command =
87
+ parts.length === 1
88
+ ? parts[0]!.trim()
89
+ : parts
90
+ .map((part) =>
91
+ !SHELL_COMPOSITION_TOKENS.has(part) && (!part || /[\s'"\\$`;&|<>()*?]/u.test(part))
92
+ ? quoteBashArgument(part)
93
+ : part,
94
+ )
95
+ .join(' ')
96
+ .trim();
97
+ if (!command || !firstPart || firstPart.startsWith('-')) {
98
+ throw new NotAllowed(
99
+ spaceTrim(`
100
+ Option \`--check\` requires a non-empty shell command, for example \`--check "npm run check"\`.
101
+ `),
102
+ );
103
+ }
104
+ return command;
105
+ }
106
+
107
+ // Note: [💞] Ignore a discrepancy between file name and exported helper names
@@ -0,0 +1,78 @@
1
+ import type { Command } from 'commander';
2
+ import { constants } from 'fs';
3
+ import { access, realpath, stat } from 'fs/promises';
4
+ import { resolve } from 'path';
5
+ import { EnvironmentMismatchError } from '../../../errors/EnvironmentMismatchError';
6
+ import { spaceTrim } from '../../../utils/organization/spaceTrim';
7
+
8
+ /**
9
+ * Optional project selection shared by workspace actions, independently of Book and harness selection.
10
+ * @private internal CLI options
11
+ */
12
+ export type ProjectCliOptions = { readonly path?: string };
13
+
14
+ /**
15
+ * Registers project selection without capturing a directory during command registration.
16
+ * @private internal CLI registration helper
17
+ */
18
+ export function addProjectPathOption(command: Command): void {
19
+ command.option(
20
+ '--path <directory>',
21
+ 'Project directory (default: invocation current directory); relative paths start there',
22
+ );
23
+ }
24
+
25
+ /**
26
+ * Registers additional context independently of primary-agent selection.
27
+ * @private internal CLI registration helper
28
+ */
29
+ export function addProjectContextOption(command: Command): void {
30
+ command.option(
31
+ '--context <context-or-file>',
32
+ 'Additional instructions (default: project AGENTS.md); inline text or a project-relative file replaces the default; an empty value disables it',
33
+ );
34
+ }
35
+
36
+ /**
37
+ * Captures an invocation's directory at action time. No process-global state is changed.
38
+ * @private internal CLI normalization helper
39
+ */
40
+ export function normalizeProjectCliOptions(
41
+ options: ProjectCliOptions,
42
+ invocationDirectory = process.cwd(),
43
+ ): { readonly projectDirectory: string } {
44
+ const selectedPath = options.path;
45
+ if (selectedPath !== undefined && !selectedPath.trim()) {
46
+ throw new EnvironmentMismatchError(
47
+ spaceTrim('Pass a non-empty project directory in `--path`, or omit it to use the current directory.'),
48
+ );
49
+ }
50
+ return { projectDirectory: resolve(invocationDirectory, selectedPath ?? '.') };
51
+ }
52
+
53
+ /**
54
+ * Validates the selected directory before any setup writes, without selecting an enclosing Git root.
55
+ * @private shared project resolution for CLI services
56
+ */
57
+ export async function resolveProjectDirectory(projectDirectory: string): Promise<string> {
58
+ const requestedPath = resolve(projectDirectory);
59
+ try {
60
+ const projectPath = await realpath(requestedPath);
61
+ if (!(await stat(projectPath)).isDirectory()) {
62
+ throw new EnvironmentMismatchError(spaceTrim(`Project path \`${requestedPath}\` is not a directory.`));
63
+ }
64
+ await access(projectPath, constants.R_OK | constants.X_OK);
65
+ return projectPath;
66
+ } catch (error) {
67
+ throw new EnvironmentMismatchError(
68
+ spaceTrim(`
69
+ Cannot access project directory \`${requestedPath}\`.
70
+ Check that it exists, is a directory, and is readable and searchable; correct \`--path\` before retrying.
71
+
72
+ ${error instanceof Error ? error.message : String(error)}
73
+ `),
74
+ );
75
+ }
76
+ }
77
+
78
+ // Note: [💞] Shared project registration and resolution helpers.
@@ -14,8 +14,10 @@ import type {
14
14
  *
15
15
  * @private internal utility of `promptbookCli`
16
16
  */
17
- export async function $checkPromptbookCliInstallations(): Promise<ReadonlyArray<PromptbookCliInstallationStatus>> {
18
- const installations = await $resolvePromptbookCliInstallations();
17
+ export async function $checkPromptbookCliInstallations(
18
+ projectPath = process.cwd(),
19
+ ): Promise<ReadonlyArray<PromptbookCliInstallationStatus>> {
20
+ const installations = await $resolvePromptbookCliInstallations(projectPath);
19
21
 
20
22
  if (installations.length === 0) {
21
23
  return [];
@@ -23,6 +23,7 @@ import { formatPromptbookCliInstallationWarning } from './formatPromptbookCliIns
23
23
  */
24
24
  export async function $ensurePromptbookCliInstallations(
25
25
  questionsOptions: NormalizedQuestionsCliOptions,
26
+ projectPath = process.cwd(),
26
27
  ): Promise<boolean> {
27
28
  if (!questionsOptions.isAskingQuestionsEnabled) {
28
29
  // Note: `--no-questions` forbids asking for the approval, so the registry checks would be useless
@@ -34,7 +35,7 @@ export async function $ensurePromptbookCliInstallations(
34
35
  return false;
35
36
  }
36
37
 
37
- const statuses = await $checkPromptbookCliInstallations();
38
+ const statuses = await $checkPromptbookCliInstallations(projectPath);
38
39
  const outdatedStatuses = statuses.filter(({ installationState }) => installationState === 'outdated');
39
40
 
40
41
  if (outdatedStatuses.length === 0) {
@@ -57,7 +58,7 @@ export async function $ensurePromptbookCliInstallations(
57
58
  const updateResults: Array<boolean> = [];
58
59
 
59
60
  for (const status of outdatedStatuses) {
60
- updateResults.push(await $updatePromptbookCliInstallation(status));
61
+ updateResults.push(await $updatePromptbookCliInstallation(status, projectPath));
61
62
  }
62
63
 
63
64
  const isAnyInstallationUpdated = updateResults.some(Boolean);
@@ -41,9 +41,11 @@ type JsonObject = Readonly<Record<string, unknown>>;
41
41
  *
42
42
  * @private internal utility of `promptbookCli`
43
43
  */
44
- export async function $resolvePromptbookCliInstallations(): Promise<ReadonlyArray<PromptbookCliInstallation>> {
44
+ export async function $resolvePromptbookCliInstallations(
45
+ projectPath = process.cwd(),
46
+ ): Promise<ReadonlyArray<PromptbookCliInstallation>> {
45
47
  const [localInstallations, globalInstallations] = await Promise.all([
46
- $resolveLocalPromptbookCliInstallations(),
48
+ $resolveLocalPromptbookCliInstallations(projectPath),
47
49
  $resolveGlobalPromptbookCliInstallations(),
48
50
  ]);
49
51
 
@@ -53,8 +55,10 @@ export async function $resolvePromptbookCliInstallations(): Promise<ReadonlyArra
53
55
  /**
54
56
  * Finds the closest ancestor `package.json` which directly declares a Promptbook CLI package.
55
57
  */
56
- async function $resolveLocalPromptbookCliInstallations(): Promise<ReadonlyArray<LocalPromptbookCliInstallation>> {
57
- let candidateProjectPath = resolve(process.cwd());
58
+ async function $resolveLocalPromptbookCliInstallations(
59
+ projectPath: string,
60
+ ): Promise<ReadonlyArray<LocalPromptbookCliInstallation>> {
61
+ let candidateProjectPath = resolve(projectPath);
58
62
  let isFileSystemRootReached = false;
59
63
 
60
64
  while (!isFileSystemRootReached) {
@@ -13,10 +13,13 @@ import type { PromptbookCliInstallationStatus } from './PromptbookCliInstallatio
13
13
  * @returns `true` when the package update succeeds, `false` when it fails
14
14
  * @private internal utility of `promptbookCli`
15
15
  */
16
- export async function $updatePromptbookCliInstallation(status: PromptbookCliInstallationStatus): Promise<boolean> {
16
+ export async function $updatePromptbookCliInstallation(
17
+ status: PromptbookCliInstallationStatus,
18
+ projectPath = process.cwd(),
19
+ ): Promise<boolean> {
17
20
  const { npmPackageName, installationLocation } = status.installation;
18
21
  const installCommand = buildPromptbookCliInstallCommand(status.installation);
19
- const updateWorkingDirectory = installationLocation === 'global' ? process.cwd() : status.installation.projectPath;
22
+ const updateWorkingDirectory = installationLocation === 'global' ? projectPath : status.installation.projectPath;
20
23
 
21
24
  console.info(colors.cyan(`Updating Promptbook CLI package \`${npmPackageName}\` with \`${installCommand}\`...`));
22
25