@promptbook/cli 0.114.0-30 → 0.114.0-32

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 (38) hide show
  1. package/esm/index.es.js +197 -25
  2. package/esm/index.es.js.map +1 -1
  3. package/esm/scripts/run-codex-prompts/prompts/findFirstNonEmptyLineIndex.d.ts +6 -0
  4. package/esm/scripts/run-codex-prompts/prompts/writePromptStatusLine.d.ts +3 -2
  5. package/esm/src/cli/cli-commands/coder/$ensureCoderHarnessGitignoreRules.d.ts +9 -0
  6. package/esm/src/cli/cli-commands/coder/$ensureCoderHarnessGitignoreRules.test.d.ts +1 -0
  7. package/esm/src/cli/cli-commands/coder/ensureCoderGitignoreFile.d.ts +14 -1
  8. package/esm/src/cli/cli-commands/coder/server.test.d.ts +1 -0
  9. package/esm/src/cli/cli-commands/common/$askForConfirmation.d.ts +9 -0
  10. package/esm/src/cli/cli-commands/common/harness/HarnessDefinition.d.ts +10 -0
  11. package/esm/src/cli/cli-commands/common/projectInitialization.d.ts +6 -0
  12. package/esm/src/version.d.ts +1 -1
  13. package/package.json +1 -1
  14. package/src/cli/cli-commands/coder/$ensureCoderHarnessGitignoreRules.ts +51 -0
  15. package/src/cli/cli-commands/coder/ensureCoderGitignoreFile.ts +37 -3
  16. package/src/cli/cli-commands/coder/init.ts +1 -1
  17. package/src/cli/cli-commands/coder/ping.ts +3 -1
  18. package/src/cli/cli-commands/coder/run.ts +3 -0
  19. package/src/cli/cli-commands/coder/server.ts +3 -0
  20. package/src/cli/cli-commands/common/$askForConfirmation.ts +31 -0
  21. package/src/cli/cli-commands/common/harness/HarnessDefinition.ts +25 -0
  22. package/src/cli/cli-commands/common/npm/$askForNpmPackageInstallationApproval.ts +2 -18
  23. package/src/cli/cli-commands/common/projectInitialization.ts +25 -2
  24. package/src/other/templates/getTemplatesPipelineCollection.ts +645 -964
  25. package/src/version.ts +2 -2
  26. package/src/versions.txt +2 -0
  27. package/umd/index.umd.js +197 -25
  28. package/umd/index.umd.js.map +1 -1
  29. package/umd/scripts/run-codex-prompts/prompts/findFirstNonEmptyLineIndex.d.ts +6 -0
  30. package/umd/scripts/run-codex-prompts/prompts/writePromptStatusLine.d.ts +3 -2
  31. package/umd/src/cli/cli-commands/coder/$ensureCoderHarnessGitignoreRules.d.ts +9 -0
  32. package/umd/src/cli/cli-commands/coder/$ensureCoderHarnessGitignoreRules.test.d.ts +1 -0
  33. package/umd/src/cli/cli-commands/coder/ensureCoderGitignoreFile.d.ts +14 -1
  34. package/umd/src/cli/cli-commands/coder/server.test.d.ts +1 -0
  35. package/umd/src/cli/cli-commands/common/$askForConfirmation.d.ts +9 -0
  36. package/umd/src/cli/cli-commands/common/harness/HarnessDefinition.d.ts +10 -0
  37. package/umd/src/cli/cli-commands/common/projectInitialization.d.ts +6 -0
  38. package/umd/src/version.d.ts +1 -1
package/src/version.ts CHANGED
@@ -16,11 +16,11 @@ export const BOOK_LANGUAGE_VERSION: string_semantic_version = '2.0.0';
16
16
  * @generated
17
17
  * @see https://github.com/webgptorg/promptbook
18
18
  */
19
- export const PROMPTBOOK_ENGINE_VERSION: string_promptbook_version = '0.114.0-30';
19
+ export const PROMPTBOOK_ENGINE_VERSION: string_promptbook_version = '0.114.0-32';
20
20
 
21
21
  /**
22
22
  * Represents the version string of the Promptbook engine.
23
- * It follows semantic versioning (e.g., `0.114.0-29`).
23
+ * It follows semantic versioning (e.g., `0.114.0-31`).
24
24
  *
25
25
  * @generated
26
26
  */
package/src/versions.txt CHANGED
@@ -1206,3 +1206,5 @@
1206
1206
  0.114.0-28
1207
1207
  0.114.0-29
1208
1208
  0.114.0-30
1209
+ 0.114.0-31
1210
+ 0.114.0-32
package/umd/index.umd.js CHANGED
@@ -58,7 +58,7 @@
58
58
  * @generated
59
59
  * @see https://github.com/webgptorg/promptbook
60
60
  */
61
- const PROMPTBOOK_ENGINE_VERSION = '0.114.0-30';
61
+ const PROMPTBOOK_ENGINE_VERSION = '0.114.0-32';
62
62
  /**
63
63
  * TODO: string_promptbook_version should be constrained to the all versions of Promptbook engine
64
64
  * Note: [💞] Ignore a discrepancy between file name and entity name
@@ -2640,7 +2640,7 @@
2640
2640
  async function ensureProjectGitignoreFile({ projectPath, blockHeader, rules, }) {
2641
2641
  const gitignorePath = path.join(projectPath, GITIGNORE_FILE_PATH);
2642
2642
  const currentGitignoreContent = await readTextFileIfExists(gitignorePath);
2643
- const missingRules = rules.filter((rule) => !hasGitignoreRule(currentGitignoreContent || '', rule));
2643
+ const missingRules = getMissingGitignoreRules(currentGitignoreContent || '', rules);
2644
2644
  if (currentGitignoreContent !== undefined && missingRules.length === 0) {
2645
2645
  return 'unchanged';
2646
2646
  }
@@ -2651,6 +2651,16 @@
2651
2651
  await promises.writeFile(gitignorePath, nextGitignoreContent, 'utf-8');
2652
2652
  return currentGitignoreContent === undefined ? 'created' : 'updated';
2653
2653
  }
2654
+ /**
2655
+ * Lists the ignore rules which are not yet present in a project's `.gitignore` file.
2656
+ *
2657
+ * @private internal utility of Promptbook CLI project initialization
2658
+ */
2659
+ async function getMissingProjectGitignoreRules(projectPath, rules) {
2660
+ const gitignorePath = path.join(projectPath, GITIGNORE_FILE_PATH);
2661
+ const currentGitignoreContent = (await readTextFileIfExists(gitignorePath)) || '';
2662
+ return getMissingGitignoreRules(currentGitignoreContent, rules);
2663
+ }
2654
2664
  /**
2655
2665
  * Reads one text file when it exists, otherwise returns `undefined`.
2656
2666
  *
@@ -2702,9 +2712,16 @@
2702
2712
  * Detects whether `.gitignore` already covers one exact rule.
2703
2713
  */
2704
2714
  function hasGitignoreRule(gitignoreContent, rule) {
2705
- const normalizedRulePattern = rule.startsWith('/') ? `/?${escapeRegExp$1(rule.slice(1))}` : escapeRegExp$1(rule);
2715
+ const normalizedRule = rule.startsWith('/') ? rule.slice(1) : rule;
2716
+ const normalizedRulePattern = `/?${escapeRegExp$1(normalizedRule)}`;
2706
2717
  return new RegExp(`(^|[\\r\\n])${normalizedRulePattern}(?:[\\r\\n]|$)`, 'u').test(gitignoreContent);
2707
2718
  }
2719
+ /**
2720
+ * Finds the unique rules which are not covered by existing `.gitignore` content.
2721
+ */
2722
+ function getMissingGitignoreRules(gitignoreContent, rules) {
2723
+ return Array.from(new Set(rules)).filter((rule) => !hasGitignoreRule(gitignoreContent, rule));
2724
+ }
2708
2725
  // Note: [🟡] Code for CLI project initialization [projectInitialization](src/cli/cli-commands/common/projectInitialization.ts) should never be published outside of `@promptbook/cli`
2709
2726
  // Note: [💞] Ignore a discrepancy between file name and entity name
2710
2727
 
@@ -24130,6 +24147,7 @@
24130
24147
  label: 'OpenAI Codex',
24131
24148
  commandName: 'codex',
24132
24149
  npmPackageName: '@openai/codex',
24150
+ projectGitignoreRules: ['.codex'],
24133
24151
  // Note: The official standalone installer keeps its package in `~/.codex` and links it onto the `PATH`
24134
24152
  standaloneInstallation: {
24135
24153
  directoryNames: ['.codex'],
@@ -24141,6 +24159,7 @@
24141
24159
  label: 'GitHub Copilot',
24142
24160
  commandName: 'copilot',
24143
24161
  npmPackageName: '@github/copilot',
24162
+ projectGitignoreRules: ['.github/copilot/settings.local.json'],
24144
24163
  // Note: The GitHub Copilot CLI downloads its native binary in a postinstall script
24145
24164
  npmInstallEnvironment: { npm_config_ignore_scripts: 'false' },
24146
24165
  },
@@ -24149,30 +24168,35 @@
24149
24168
  label: 'Cline',
24150
24169
  commandName: 'cline',
24151
24170
  npmPackageName: 'cline',
24171
+ projectGitignoreRules: ['.cline'],
24152
24172
  },
24153
24173
  'claude-code': {
24154
24174
  harnessName: 'claude-code',
24155
24175
  label: 'Claude Code',
24156
24176
  commandName: 'claude',
24157
24177
  npmPackageName: '@anthropic-ai/claude-code',
24178
+ projectGitignoreRules: ['.claude'],
24158
24179
  },
24159
24180
  opencode: {
24160
24181
  harnessName: 'opencode',
24161
24182
  label: 'Opencode',
24162
24183
  commandName: 'opencode',
24163
24184
  npmPackageName: 'opencode-ai',
24185
+ projectGitignoreRules: ['.opencode'],
24164
24186
  },
24165
24187
  gemini: {
24166
24188
  harnessName: 'gemini',
24167
24189
  label: 'Gemini CLI',
24168
24190
  commandName: 'gemini',
24169
24191
  npmPackageName: '@google/gemini-cli',
24192
+ projectGitignoreRules: ['.gemini'],
24170
24193
  },
24171
24194
  'qwen-code': {
24172
24195
  harnessName: 'qwen-code',
24173
24196
  label: 'Qwen Code',
24174
24197
  commandName: 'qwen',
24175
24198
  npmPackageName: '@qwen-code/qwen-code',
24199
+ projectGitignoreRules: ['.qwen'],
24176
24200
  },
24177
24201
  };
24178
24202
  /**
@@ -24191,6 +24215,14 @@
24191
24215
  }
24192
24216
  return definition;
24193
24217
  }
24218
+ /**
24219
+ * Lists the unique project ignore rules required by the selected harnesses, in selection order.
24220
+ *
24221
+ * @private internal utility of `promptbookCli`
24222
+ */
24223
+ function getHarnessProjectGitignoreRules(harnessNames) {
24224
+ return Array.from(new Set(harnessNames.flatMap((harnessName) => getHarnessDefinition(harnessName).projectGitignoreRules)));
24225
+ }
24194
24226
 
24195
24227
  /**
24196
24228
  * Create price per one token based on the string value found on openai page
@@ -43103,16 +43135,16 @@
43103
43135
  // Note: [💞] Ignore a discrepancy between file name and entity name
43104
43136
 
43105
43137
  /**
43106
- * Asks the user in the terminal whether an npm package should be installed or updated now.
43138
+ * Asks the user in the terminal to confirm one optional change.
43107
43139
  *
43108
- * Note: `$` is used to indicate that this function is not a pure function - it reads the answer from stdin
43140
+ * Note: `$` is used to indicate that this function is not a pure function - it reads the answer from stdin.
43109
43141
  *
43110
- * @returns `true` when the user confirms, `false` when the user declines or the terminal is not interactive
43142
+ * @returns `true` when the user confirms, `false` when the user declines or the terminal is not interactive.
43111
43143
  * @private internal utility of `promptbookCli`
43112
43144
  */
43113
- async function $askForNpmPackageInstallationApproval(question) {
43145
+ async function $askForConfirmation(question) {
43114
43146
  if (!process.stdin.isTTY) {
43115
- // Note: In non-interactive environments like CI there is nobody who could confirm the installation
43147
+ // Note: In non-interactive environments like CI there is nobody who could confirm the change.
43116
43148
  return false;
43117
43149
  }
43118
43150
  const readlineInterface = readline.createInterface({ input: process.stdin, output: process.stdout });
@@ -43126,6 +43158,19 @@
43126
43158
  readlineInterface.close();
43127
43159
  }
43128
43160
  }
43161
+ // Note: [🟡] Code for CLI confirmations [$askForConfirmation](src/cli/cli-commands/common/$askForConfirmation.ts) should never be published outside of `@promptbook/cli`
43162
+
43163
+ /**
43164
+ * Asks the user in the terminal whether an npm package should be installed or updated now.
43165
+ *
43166
+ * Note: `$` is used to indicate that this function is not a pure function - it reads the answer from stdin
43167
+ *
43168
+ * @returns `true` when the user confirms, `false` when the user declines or the terminal is not interactive
43169
+ * @private internal utility of `promptbookCli`
43170
+ */
43171
+ async function $askForNpmPackageInstallationApproval(question) {
43172
+ return $askForConfirmation(question);
43173
+ }
43129
43174
  // Note: [🟡] Code for CLI npm package installation approval [$askForNpmPackageInstallationApproval](src/cli/cli-commands/common/npm/$askForNpmPackageInstallationApproval.ts) should never be published outside of `@promptbook/cli`
43130
43175
 
43131
43176
  /**
@@ -44029,15 +44074,38 @@
44029
44074
  */
44030
44075
  const CODER_GITIGNORE_HEADER = '# Promptbook Coder';
44031
44076
  /**
44032
- * Ensures `.gitignore` contains the standalone Promptbook temp entry.
44077
+ * Coder-owned local artifacts which every initialized project should ignore.
44078
+ */
44079
+ const CODER_GITIGNORE_RULES = [PROMPTBOOK_TEMP_GITIGNORE_RULE, CODER_ENV_GITIGNORE_RULE];
44080
+ /**
44081
+ * Ensures `.gitignore` contains Promptbook Coder's local artifacts and every supported harness's local artifacts.
44033
44082
  *
44034
44083
  * @private function of `initializeCoderProjectConfiguration`
44035
44084
  */
44036
44085
  async function ensureCoderGitignoreFile(projectPath) {
44086
+ return ensureCoderGitignoreRules(projectPath, [
44087
+ ...CODER_GITIGNORE_RULES,
44088
+ ...getHarnessProjectGitignoreRules(PROMPT_RUNNER_HARNESS_NAMES),
44089
+ ]);
44090
+ }
44091
+ /**
44092
+ * Lists missing project-local ignore rules for the selected harnesses.
44093
+ *
44094
+ * @private internal utility of `ptbk coder`
44095
+ */
44096
+ async function getMissingCoderHarnessGitignoreRules(projectPath, harnessNames) {
44097
+ return getMissingProjectGitignoreRules(projectPath, getHarnessProjectGitignoreRules(harnessNames));
44098
+ }
44099
+ /**
44100
+ * Adds the given Promptbook Coder rules to a project's `.gitignore` file.
44101
+ *
44102
+ * @private internal utility of `ptbk coder`
44103
+ */
44104
+ async function ensureCoderGitignoreRules(projectPath, rules) {
44037
44105
  return ensureProjectGitignoreFile({
44038
44106
  projectPath,
44039
44107
  blockHeader: CODER_GITIGNORE_HEADER,
44040
- rules: [PROMPTBOOK_TEMP_GITIGNORE_RULE, CODER_ENV_GITIGNORE_RULE],
44108
+ rules,
44041
44109
  });
44042
44110
  }
44043
44111
  // Note: [🟡] Code for coder init gitignore bootstrapping [ensureCoderGitignoreFile](src/cli/cli-commands/coder/ensureCoderGitignoreFile.ts) should never be published outside of `@promptbook/cli`
@@ -44402,7 +44470,7 @@
44402
44470
  - ${CODER_DEVELOPER_AGENT_FILE_PATH}
44403
44471
  - ${AGENTS_FILE_PATH}
44404
44472
  - ${AGENT_CODING_FILE_PATH}
44405
- - .gitignore
44473
+ - .gitignore with local artifacts from every supported harness
44406
44474
  - package.json
44407
44475
  - .vscode/settings.json
44408
44476
 
@@ -44499,6 +44567,40 @@
44499
44567
  }
44500
44568
  // Note: [💞] Ignore a discrepancy between file name and entity name
44501
44569
 
44570
+ /**
44571
+ * Offers to add missing project-local ignore rules for the selected coding harness.
44572
+ *
44573
+ * Note: `$` is used to indicate that this function is not a pure function - it may ask the user and update `.gitignore`.
44574
+ *
44575
+ * @private internal utility of `ptbk coder`
44576
+ */
44577
+ async function $ensureCoderHarnessGitignoreRules(projectPath, harnessName) {
44578
+ if (harnessName === undefined) {
44579
+ return;
44580
+ }
44581
+ const missingRules = await getMissingCoderHarnessGitignoreRules(projectPath, [harnessName]);
44582
+ if (missingRules.length === 0) {
44583
+ return;
44584
+ }
44585
+ const { label } = getHarnessDefinition(harnessName);
44586
+ const formattedRules = formatGitignoreRules(missingRules);
44587
+ const entryLabel = missingRules.length === 1 ? 'entry' : 'entries';
44588
+ const isAdditionApproved = await $askForConfirmation(`Add the missing ${label} ignore ${entryLabel} ${formattedRules} to \`.gitignore\` now?`);
44589
+ if (!isAdditionApproved) {
44590
+ console.info(colors__default["default"].gray(`Skipped, add ${formattedRules} to \`.gitignore\` manually.`));
44591
+ return;
44592
+ }
44593
+ await ensureCoderGitignoreRules(projectPath, missingRules);
44594
+ console.info(colors__default["default"].gray(`✔ Added ${formattedRules} to \`.gitignore\`.`));
44595
+ }
44596
+ /**
44597
+ * Formats one or more `.gitignore` rules for a terminal confirmation message.
44598
+ */
44599
+ function formatGitignoreRules(rules) {
44600
+ return rules.map((rule) => `\`${rule}\``).join(', ');
44601
+ }
44602
+ // Note: [🟡] Code for coder harness gitignore prompts [$ensureCoderHarnessGitignoreRules](src/cli/cli-commands/coder/$ensureCoderHarnessGitignoreRules.ts) should never be published outside of `@promptbook/cli`
44603
+
44502
44604
  /**
44503
44605
  * Initializes `coder ping` command for Promptbook CLI utilities
44504
44606
  *
@@ -44518,7 +44620,7 @@
44518
44620
  - Reports the answer of the harness, the response time and the reported usage
44519
44621
  - Starts the hourly/weekly quota window before you need it, so it is already refreshing when you do
44520
44622
  - Optional --period keeps the quota window refreshing by pinging once per period until stopped
44521
- - Leaves the project exactly as it was nothing is read, written, changed or committed
44623
+ - Makes no coding changes or commits; if the selected harness has missing local ignore rules, offers to add them to .gitignore
44522
44624
  - Checks that the selected harness is installed and up to date unless --no-harness-update is used
44523
44625
  - Use --no-ui to stream the raw harness output instead of only the compact result
44524
44626
  `));
@@ -44536,6 +44638,7 @@
44536
44638
  // Note: The period is validated before the harness installation check, so a mistyped duration fails fast
44537
44639
  const periodMs = parseOptionalPeriodDuration('--period', periodValue);
44538
44640
  await $ensureHarnessInstallations([runnerOptions.agentName], isHarnessUpdateCheckEnabled);
44641
+ await $ensureCoderHarnessGitignoreRules(process.cwd(), runnerOptions.agentName);
44539
44642
  const pingOptions = {
44540
44643
  agentName: runnerOptions.agentName,
44541
44644
  model: runnerOptions.model,
@@ -45014,6 +45117,7 @@
45014
45117
  - Optional --preserve-logs keeps temp prompt/log artifacts after successful rounds
45015
45118
  - Optional --no-ui keeps plain streaming console output for logging and debugging
45016
45119
  - Checks that the selected harness is installed and up to date before the first prompt unless --no-harness-update is used
45120
+ - Offers to add missing project-local ignore rules for the selected harness
45017
45121
  - In interactive mode, checks local and global Promptbook CLI installations and offers to update them
45018
45122
  - Supports GPG signing of commits
45019
45123
  - Optional pre-coding test run that can stop or repair pre-existing failures
@@ -45077,6 +45181,7 @@
45077
45181
  return process.exit(0);
45078
45182
  }
45079
45183
  await $ensureHarnessInstallations([runnerOptions.agentName], isHarnessUpdateCheckEnabled);
45184
+ await $ensureCoderHarnessGitignoreRules(process.cwd(), runnerOptions.agentName);
45080
45185
  const waitAfterPrompt = parseOptionalWaitDuration(waitAfterPromptValue, 0);
45081
45186
  const waitBetweenPrompts = parseOptionalWaitDuration(waitBetweenPromptsValue, 0);
45082
45187
  const waitAfterError = parseOptionalWaitDuration(waitAfterErrorValue, DEFAULT_WAIT_AFTER_ERROR_MS$1);
@@ -45171,6 +45276,7 @@
45171
45276
  Features:
45172
45277
  - Runs the same prompt processing as \`ptbk coder run\`
45173
45278
  - Checks that the selected harness is installed and up to date on startup unless --no-harness-update is used
45279
+ - Offers to add missing project-local ignore rules for the selected harness
45174
45280
  - Does not exit when all prompts are done; polls for new prompt files instead
45175
45281
  - Serves a kanban board at http://localhost:<port> for visual progress tracking
45176
45282
  - Allows editing prompt files directly from the browser (Trello-style)
@@ -45216,6 +45322,7 @@
45216
45322
  });
45217
45323
  const { isHarnessUpdateCheckEnabled } = normalizeHarnessUpdateCliOptions(cliOptions);
45218
45324
  await $ensureHarnessInstallations([runnerOptions.agentName], isHarnessUpdateCheckEnabled);
45325
+ await $ensureCoderHarnessGitignoreRules(process.cwd(), runnerOptions.agentName);
45219
45326
  // [1] Parse the wait options and --no-auto (same logic as `coder run`)
45220
45327
  const waitForUser = !auto;
45221
45328
  const waitAfterPrompt = parseOptionalWaitDuration(waitAfterPromptValue, 0);
@@ -74529,6 +74636,21 @@
74529
74636
  isPromptInPriorityFilter(prompt.section, priorityFilter));
74530
74637
  }
74531
74638
 
74639
+ /**
74640
+ * Finds the first non-empty line within the inclusive bounds.
74641
+ *
74642
+ * @private internal utility of prompt parsing and status writing
74643
+ */
74644
+ function findFirstNonEmptyLineIndex(lines, startLine, endLine) {
74645
+ for (let lineIndex = startLine; lineIndex <= endLine; lineIndex++) {
74646
+ const line = lines[lineIndex];
74647
+ if (line !== undefined && line.trim() !== '') {
74648
+ return lineIndex;
74649
+ }
74650
+ }
74651
+ return undefined;
74652
+ }
74653
+
74532
74654
  /**
74533
74655
  * Checks whether a prompt is unrestricted or matches the selected harness/model.
74534
74656
  *
@@ -74564,6 +74686,14 @@
74564
74686
  .filter((token) => token !== '');
74565
74687
  }
74566
74688
 
74689
+ /**
74690
+ * Matches the supported prompt status markers at the start of a line.
74691
+ *
74692
+ * A different bracketed prefix can be ordinary prompt content, for example an emoji tag.
74693
+ *
74694
+ * @private internal constant of `parsePromptFile`
74695
+ */
74696
+ const PROMPT_STATUS_MARKER_PATTERN = /^\[(?: |-|[xX]|\^|!)\]/u;
74567
74697
  /**
74568
74698
  * Parses a prompt markdown file into sections and metadata.
74569
74699
  */
@@ -74583,11 +74713,11 @@
74583
74713
  continue;
74584
74714
  }
74585
74715
  const endLine = i - 1;
74586
- const firstNonEmptyLine = findFirstNonEmptyLine(lines, startLine, endLine);
74716
+ const firstNonEmptyLine = findFirstNonEmptyLineIndex(lines, startLine, endLine);
74587
74717
  if (firstNonEmptyLine !== undefined) {
74588
74718
  const statusLine = (lines[firstNonEmptyLine] || '').trim();
74589
74719
  const parsedStatus = parseStatusLine(statusLine);
74590
- const status = (_a = parsedStatus === null || parsedStatus === void 0 ? void 0 : parsedStatus.status) !== null && _a !== void 0 ? _a : 'not-ready';
74720
+ const status = (_a = parsedStatus === null || parsedStatus === void 0 ? void 0 : parsedStatus.status) !== null && _a !== void 0 ? _a : (hasPromptStatusMarker(statusLine) ? 'not-ready' : 'todo');
74591
74721
  const priority = (_b = parsedStatus === null || parsedStatus === void 0 ? void 0 : parsedStatus.priority) !== null && _b !== void 0 ? _b : 0;
74592
74722
  sections.push({
74593
74723
  index,
@@ -74650,16 +74780,12 @@
74650
74780
  return { status: 'todo', priority: (_d = (_c = details.match(/!/gu)) === null || _c === void 0 ? void 0 : _c.length) !== null && _d !== void 0 ? _d : 0 };
74651
74781
  }
74652
74782
  /**
74653
- * Finds the first non-empty line index between two bounds.
74783
+ * Checks whether a line starts with one of the supported prompt status markers.
74784
+ *
74785
+ * @private internal utility of `parsePromptFile`
74654
74786
  */
74655
- function findFirstNonEmptyLine(lines, startLine, endLine) {
74656
- for (let i = startLine; i <= endLine; i++) {
74657
- const line = lines[i];
74658
- if (line !== undefined && line.trim() !== '') {
74659
- return i;
74660
- }
74661
- }
74662
- return undefined;
74787
+ function hasPromptStatusMarker(line) {
74788
+ return PROMPT_STATUS_MARKER_PATTERN.test(line);
74663
74789
  }
74664
74790
 
74665
74791
  /**
@@ -77512,13 +77638,59 @@
77512
77638
  /**
77513
77639
  * Rewrites the status line of one prompt section while preserving its indentation.
77514
77640
  *
77515
- * Only a todo `[ ]` or an in-progress `[^]` status line is rewritten, so an already finalized
77516
- * `[x]`, `[!]` or `[-]` status is never overwritten by accident.
77641
+ * An unmarked prompt is implicitly a todo, so its first live status line is inserted immediately before its content.
77642
+ * Only a todo `[ ]` or an in-progress `[^]` status line is otherwise rewritten, so an already finalized `[x]`, `[!]`
77643
+ * or `[-]` status is never overwritten by accident.
77517
77644
  */
77518
77645
  function writePromptStatusLine(file, section, replacementStatusLine) {
77646
+ if (section.statusLineIndex === undefined) {
77647
+ insertPromptStatusLine(file, section, replacementStatusLine);
77648
+ return;
77649
+ }
77519
77650
  const { statusLineIndex, line } = resolvePromptStatusLine(file, section);
77520
77651
  file.lines[statusLineIndex] = line.replace(REWRITABLE_PROMPT_STATUS_LINE_PATTERN, `$<indentation>${replacementStatusLine}`);
77521
77652
  }
77653
+ /**
77654
+ * Inserts the first persisted status line for an unmarked prompt and keeps parsed section positions in sync.
77655
+ *
77656
+ * @private internal utility of `writePromptStatusLine`
77657
+ */
77658
+ function insertPromptStatusLine(file, section, replacementStatusLine) {
77659
+ const statusLineIndex = findFirstNonEmptyLineIndex(file.lines, section.startLine, section.endLine);
77660
+ if (statusLineIndex === undefined) {
77661
+ const promptReference = `Prompt ${section.index + 1} in \`${file.name}\``;
77662
+ throw new UnexpectedError(_spaceTrim.spaceTrim(`
77663
+ ${promptReference} does not have content where its status line can be added.
77664
+ `));
77665
+ }
77666
+ file.lines.splice(statusLineIndex, 0, replacementStatusLine);
77667
+ updatePromptSectionPositionsAfterStatusInsertion(file, section, statusLineIndex);
77668
+ }
77669
+ /**
77670
+ * Updates the parsed indexes after adding a status line to an unmarked prompt.
77671
+ *
77672
+ * @private internal utility of `writePromptStatusLine`
77673
+ */
77674
+ function updatePromptSectionPositionsAfterStatusInsertion(file, section, statusLineIndex) {
77675
+ for (const promptSection of file.sections) {
77676
+ if (promptSection === section) {
77677
+ promptSection.statusLineIndex = statusLineIndex;
77678
+ promptSection.endLine += 1;
77679
+ continue;
77680
+ }
77681
+ if (promptSection.startLine >= statusLineIndex) {
77682
+ promptSection.startLine += 1;
77683
+ promptSection.endLine += 1;
77684
+ if (promptSection.statusLineIndex !== undefined) {
77685
+ promptSection.statusLineIndex += 1;
77686
+ }
77687
+ }
77688
+ }
77689
+ if (!file.sections.includes(section)) {
77690
+ section.statusLineIndex = statusLineIndex;
77691
+ section.endLine += 1;
77692
+ }
77693
+ }
77522
77694
 
77523
77695
  /**
77524
77696
  * Marks a prompt section as done and records the per-step usage pricing and runner details.