@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/esm/index.es.js CHANGED
@@ -48,7 +48,7 @@ const BOOK_LANGUAGE_VERSION = '2.0.0';
48
48
  * @generated
49
49
  * @see https://github.com/webgptorg/promptbook
50
50
  */
51
- const PROMPTBOOK_ENGINE_VERSION = '0.114.0-30';
51
+ const PROMPTBOOK_ENGINE_VERSION = '0.114.0-32';
52
52
  /**
53
53
  * TODO: string_promptbook_version should be constrained to the all versions of Promptbook engine
54
54
  * Note: [💞] Ignore a discrepancy between file name and entity name
@@ -2630,7 +2630,7 @@ async function ensureProjectEnvFile({ projectPath, emptyFileContent, envVariable
2630
2630
  async function ensureProjectGitignoreFile({ projectPath, blockHeader, rules, }) {
2631
2631
  const gitignorePath = join(projectPath, GITIGNORE_FILE_PATH);
2632
2632
  const currentGitignoreContent = await readTextFileIfExists(gitignorePath);
2633
- const missingRules = rules.filter((rule) => !hasGitignoreRule(currentGitignoreContent || '', rule));
2633
+ const missingRules = getMissingGitignoreRules(currentGitignoreContent || '', rules);
2634
2634
  if (currentGitignoreContent !== undefined && missingRules.length === 0) {
2635
2635
  return 'unchanged';
2636
2636
  }
@@ -2641,6 +2641,16 @@ async function ensureProjectGitignoreFile({ projectPath, blockHeader, rules, })
2641
2641
  await writeFile(gitignorePath, nextGitignoreContent, 'utf-8');
2642
2642
  return currentGitignoreContent === undefined ? 'created' : 'updated';
2643
2643
  }
2644
+ /**
2645
+ * Lists the ignore rules which are not yet present in a project's `.gitignore` file.
2646
+ *
2647
+ * @private internal utility of Promptbook CLI project initialization
2648
+ */
2649
+ async function getMissingProjectGitignoreRules(projectPath, rules) {
2650
+ const gitignorePath = join(projectPath, GITIGNORE_FILE_PATH);
2651
+ const currentGitignoreContent = (await readTextFileIfExists(gitignorePath)) || '';
2652
+ return getMissingGitignoreRules(currentGitignoreContent, rules);
2653
+ }
2644
2654
  /**
2645
2655
  * Reads one text file when it exists, otherwise returns `undefined`.
2646
2656
  *
@@ -2692,9 +2702,16 @@ function parseEnvVariableNames(envContent) {
2692
2702
  * Detects whether `.gitignore` already covers one exact rule.
2693
2703
  */
2694
2704
  function hasGitignoreRule(gitignoreContent, rule) {
2695
- const normalizedRulePattern = rule.startsWith('/') ? `/?${escapeRegExp$1(rule.slice(1))}` : escapeRegExp$1(rule);
2705
+ const normalizedRule = rule.startsWith('/') ? rule.slice(1) : rule;
2706
+ const normalizedRulePattern = `/?${escapeRegExp$1(normalizedRule)}`;
2696
2707
  return new RegExp(`(^|[\\r\\n])${normalizedRulePattern}(?:[\\r\\n]|$)`, 'u').test(gitignoreContent);
2697
2708
  }
2709
+ /**
2710
+ * Finds the unique rules which are not covered by existing `.gitignore` content.
2711
+ */
2712
+ function getMissingGitignoreRules(gitignoreContent, rules) {
2713
+ return Array.from(new Set(rules)).filter((rule) => !hasGitignoreRule(gitignoreContent, rule));
2714
+ }
2698
2715
  // Note: [🟡] Code for CLI project initialization [projectInitialization](src/cli/cli-commands/common/projectInitialization.ts) should never be published outside of `@promptbook/cli`
2699
2716
  // Note: [💞] Ignore a discrepancy between file name and entity name
2700
2717
 
@@ -24120,6 +24137,7 @@ const HARNESS_DEFINITIONS = {
24120
24137
  label: 'OpenAI Codex',
24121
24138
  commandName: 'codex',
24122
24139
  npmPackageName: '@openai/codex',
24140
+ projectGitignoreRules: ['.codex'],
24123
24141
  // Note: The official standalone installer keeps its package in `~/.codex` and links it onto the `PATH`
24124
24142
  standaloneInstallation: {
24125
24143
  directoryNames: ['.codex'],
@@ -24131,6 +24149,7 @@ const HARNESS_DEFINITIONS = {
24131
24149
  label: 'GitHub Copilot',
24132
24150
  commandName: 'copilot',
24133
24151
  npmPackageName: '@github/copilot',
24152
+ projectGitignoreRules: ['.github/copilot/settings.local.json'],
24134
24153
  // Note: The GitHub Copilot CLI downloads its native binary in a postinstall script
24135
24154
  npmInstallEnvironment: { npm_config_ignore_scripts: 'false' },
24136
24155
  },
@@ -24139,30 +24158,35 @@ const HARNESS_DEFINITIONS = {
24139
24158
  label: 'Cline',
24140
24159
  commandName: 'cline',
24141
24160
  npmPackageName: 'cline',
24161
+ projectGitignoreRules: ['.cline'],
24142
24162
  },
24143
24163
  'claude-code': {
24144
24164
  harnessName: 'claude-code',
24145
24165
  label: 'Claude Code',
24146
24166
  commandName: 'claude',
24147
24167
  npmPackageName: '@anthropic-ai/claude-code',
24168
+ projectGitignoreRules: ['.claude'],
24148
24169
  },
24149
24170
  opencode: {
24150
24171
  harnessName: 'opencode',
24151
24172
  label: 'Opencode',
24152
24173
  commandName: 'opencode',
24153
24174
  npmPackageName: 'opencode-ai',
24175
+ projectGitignoreRules: ['.opencode'],
24154
24176
  },
24155
24177
  gemini: {
24156
24178
  harnessName: 'gemini',
24157
24179
  label: 'Gemini CLI',
24158
24180
  commandName: 'gemini',
24159
24181
  npmPackageName: '@google/gemini-cli',
24182
+ projectGitignoreRules: ['.gemini'],
24160
24183
  },
24161
24184
  'qwen-code': {
24162
24185
  harnessName: 'qwen-code',
24163
24186
  label: 'Qwen Code',
24164
24187
  commandName: 'qwen',
24165
24188
  npmPackageName: '@qwen-code/qwen-code',
24189
+ projectGitignoreRules: ['.qwen'],
24166
24190
  },
24167
24191
  };
24168
24192
  /**
@@ -24181,6 +24205,14 @@ function getHarnessDefinition(harnessName) {
24181
24205
  }
24182
24206
  return definition;
24183
24207
  }
24208
+ /**
24209
+ * Lists the unique project ignore rules required by the selected harnesses, in selection order.
24210
+ *
24211
+ * @private internal utility of `promptbookCli`
24212
+ */
24213
+ function getHarnessProjectGitignoreRules(harnessNames) {
24214
+ return Array.from(new Set(harnessNames.flatMap((harnessName) => getHarnessDefinition(harnessName).projectGitignoreRules)));
24215
+ }
24184
24216
 
24185
24217
  /**
24186
24218
  * Create price per one token based on the string value found on openai page
@@ -43093,16 +43125,16 @@ function buildPromptSlug$1(templateSlugPrefix, title) {
43093
43125
  // Note: [💞] Ignore a discrepancy between file name and entity name
43094
43126
 
43095
43127
  /**
43096
- * Asks the user in the terminal whether an npm package should be installed or updated now.
43128
+ * Asks the user in the terminal to confirm one optional change.
43097
43129
  *
43098
- * Note: `$` is used to indicate that this function is not a pure function - it reads the answer from stdin
43130
+ * Note: `$` is used to indicate that this function is not a pure function - it reads the answer from stdin.
43099
43131
  *
43100
- * @returns `true` when the user confirms, `false` when the user declines or the terminal is not interactive
43132
+ * @returns `true` when the user confirms, `false` when the user declines or the terminal is not interactive.
43101
43133
  * @private internal utility of `promptbookCli`
43102
43134
  */
43103
- async function $askForNpmPackageInstallationApproval(question) {
43135
+ async function $askForConfirmation(question) {
43104
43136
  if (!process.stdin.isTTY) {
43105
- // Note: In non-interactive environments like CI there is nobody who could confirm the installation
43137
+ // Note: In non-interactive environments like CI there is nobody who could confirm the change.
43106
43138
  return false;
43107
43139
  }
43108
43140
  const readlineInterface = createInterface({ input: process.stdin, output: process.stdout });
@@ -43116,6 +43148,19 @@ async function $askForNpmPackageInstallationApproval(question) {
43116
43148
  readlineInterface.close();
43117
43149
  }
43118
43150
  }
43151
+ // Note: [🟡] Code for CLI confirmations [$askForConfirmation](src/cli/cli-commands/common/$askForConfirmation.ts) should never be published outside of `@promptbook/cli`
43152
+
43153
+ /**
43154
+ * Asks the user in the terminal whether an npm package should be installed or updated now.
43155
+ *
43156
+ * Note: `$` is used to indicate that this function is not a pure function - it reads the answer from stdin
43157
+ *
43158
+ * @returns `true` when the user confirms, `false` when the user declines or the terminal is not interactive
43159
+ * @private internal utility of `promptbookCli`
43160
+ */
43161
+ async function $askForNpmPackageInstallationApproval(question) {
43162
+ return $askForConfirmation(question);
43163
+ }
43119
43164
  // 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`
43120
43165
 
43121
43166
  /**
@@ -44019,15 +44064,38 @@ const CODER_ENV_GITIGNORE_RULE = '.env';
44019
44064
  */
44020
44065
  const CODER_GITIGNORE_HEADER = '# Promptbook Coder';
44021
44066
  /**
44022
- * Ensures `.gitignore` contains the standalone Promptbook temp entry.
44067
+ * Coder-owned local artifacts which every initialized project should ignore.
44068
+ */
44069
+ const CODER_GITIGNORE_RULES = [PROMPTBOOK_TEMP_GITIGNORE_RULE, CODER_ENV_GITIGNORE_RULE];
44070
+ /**
44071
+ * Ensures `.gitignore` contains Promptbook Coder's local artifacts and every supported harness's local artifacts.
44023
44072
  *
44024
44073
  * @private function of `initializeCoderProjectConfiguration`
44025
44074
  */
44026
44075
  async function ensureCoderGitignoreFile(projectPath) {
44076
+ return ensureCoderGitignoreRules(projectPath, [
44077
+ ...CODER_GITIGNORE_RULES,
44078
+ ...getHarnessProjectGitignoreRules(PROMPT_RUNNER_HARNESS_NAMES),
44079
+ ]);
44080
+ }
44081
+ /**
44082
+ * Lists missing project-local ignore rules for the selected harnesses.
44083
+ *
44084
+ * @private internal utility of `ptbk coder`
44085
+ */
44086
+ async function getMissingCoderHarnessGitignoreRules(projectPath, harnessNames) {
44087
+ return getMissingProjectGitignoreRules(projectPath, getHarnessProjectGitignoreRules(harnessNames));
44088
+ }
44089
+ /**
44090
+ * Adds the given Promptbook Coder rules to a project's `.gitignore` file.
44091
+ *
44092
+ * @private internal utility of `ptbk coder`
44093
+ */
44094
+ async function ensureCoderGitignoreRules(projectPath, rules) {
44027
44095
  return ensureProjectGitignoreFile({
44028
44096
  projectPath,
44029
44097
  blockHeader: CODER_GITIGNORE_HEADER,
44030
- rules: [PROMPTBOOK_TEMP_GITIGNORE_RULE, CODER_ENV_GITIGNORE_RULE],
44098
+ rules,
44031
44099
  });
44032
44100
  }
44033
44101
  // Note: [🟡] Code for coder init gitignore bootstrapping [ensureCoderGitignoreFile](src/cli/cli-commands/coder/ensureCoderGitignoreFile.ts) should never be published outside of `@promptbook/cli`
@@ -44392,7 +44460,7 @@ function $initializeCoderInitCommand(program) {
44392
44460
  - ${CODER_DEVELOPER_AGENT_FILE_PATH}
44393
44461
  - ${AGENTS_FILE_PATH}
44394
44462
  - ${AGENT_CODING_FILE_PATH}
44395
- - .gitignore
44463
+ - .gitignore with local artifacts from every supported harness
44396
44464
  - package.json
44397
44465
  - .vscode/settings.json
44398
44466
 
@@ -44489,6 +44557,40 @@ function parseOptionalPeriodDuration(optionName, value) {
44489
44557
  }
44490
44558
  // Note: [💞] Ignore a discrepancy between file name and entity name
44491
44559
 
44560
+ /**
44561
+ * Offers to add missing project-local ignore rules for the selected coding harness.
44562
+ *
44563
+ * Note: `$` is used to indicate that this function is not a pure function - it may ask the user and update `.gitignore`.
44564
+ *
44565
+ * @private internal utility of `ptbk coder`
44566
+ */
44567
+ async function $ensureCoderHarnessGitignoreRules(projectPath, harnessName) {
44568
+ if (harnessName === undefined) {
44569
+ return;
44570
+ }
44571
+ const missingRules = await getMissingCoderHarnessGitignoreRules(projectPath, [harnessName]);
44572
+ if (missingRules.length === 0) {
44573
+ return;
44574
+ }
44575
+ const { label } = getHarnessDefinition(harnessName);
44576
+ const formattedRules = formatGitignoreRules(missingRules);
44577
+ const entryLabel = missingRules.length === 1 ? 'entry' : 'entries';
44578
+ const isAdditionApproved = await $askForConfirmation(`Add the missing ${label} ignore ${entryLabel} ${formattedRules} to \`.gitignore\` now?`);
44579
+ if (!isAdditionApproved) {
44580
+ console.info(colors.gray(`Skipped, add ${formattedRules} to \`.gitignore\` manually.`));
44581
+ return;
44582
+ }
44583
+ await ensureCoderGitignoreRules(projectPath, missingRules);
44584
+ console.info(colors.gray(`✔ Added ${formattedRules} to \`.gitignore\`.`));
44585
+ }
44586
+ /**
44587
+ * Formats one or more `.gitignore` rules for a terminal confirmation message.
44588
+ */
44589
+ function formatGitignoreRules(rules) {
44590
+ return rules.map((rule) => `\`${rule}\``).join(', ');
44591
+ }
44592
+ // Note: [🟡] Code for coder harness gitignore prompts [$ensureCoderHarnessGitignoreRules](src/cli/cli-commands/coder/$ensureCoderHarnessGitignoreRules.ts) should never be published outside of `@promptbook/cli`
44593
+
44492
44594
  /**
44493
44595
  * Initializes `coder ping` command for Promptbook CLI utilities
44494
44596
  *
@@ -44508,7 +44610,7 @@ function $initializeCoderPingCommand(program) {
44508
44610
  - Reports the answer of the harness, the response time and the reported usage
44509
44611
  - Starts the hourly/weekly quota window before you need it, so it is already refreshing when you do
44510
44612
  - Optional --period keeps the quota window refreshing by pinging once per period until stopped
44511
- - Leaves the project exactly as it was nothing is read, written, changed or committed
44613
+ - Makes no coding changes or commits; if the selected harness has missing local ignore rules, offers to add them to .gitignore
44512
44614
  - Checks that the selected harness is installed and up to date unless --no-harness-update is used
44513
44615
  - Use --no-ui to stream the raw harness output instead of only the compact result
44514
44616
  `));
@@ -44526,6 +44628,7 @@ function $initializeCoderPingCommand(program) {
44526
44628
  // Note: The period is validated before the harness installation check, so a mistyped duration fails fast
44527
44629
  const periodMs = parseOptionalPeriodDuration('--period', periodValue);
44528
44630
  await $ensureHarnessInstallations([runnerOptions.agentName], isHarnessUpdateCheckEnabled);
44631
+ await $ensureCoderHarnessGitignoreRules(process.cwd(), runnerOptions.agentName);
44529
44632
  const pingOptions = {
44530
44633
  agentName: runnerOptions.agentName,
44531
44634
  model: runnerOptions.model,
@@ -45004,6 +45107,7 @@ function $initializeCoderRunCommand(program) {
45004
45107
  - Optional --preserve-logs keeps temp prompt/log artifacts after successful rounds
45005
45108
  - Optional --no-ui keeps plain streaming console output for logging and debugging
45006
45109
  - Checks that the selected harness is installed and up to date before the first prompt unless --no-harness-update is used
45110
+ - Offers to add missing project-local ignore rules for the selected harness
45007
45111
  - In interactive mode, checks local and global Promptbook CLI installations and offers to update them
45008
45112
  - Supports GPG signing of commits
45009
45113
  - Optional pre-coding test run that can stop or repair pre-existing failures
@@ -45067,6 +45171,7 @@ function $initializeCoderRunCommand(program) {
45067
45171
  return process.exit(0);
45068
45172
  }
45069
45173
  await $ensureHarnessInstallations([runnerOptions.agentName], isHarnessUpdateCheckEnabled);
45174
+ await $ensureCoderHarnessGitignoreRules(process.cwd(), runnerOptions.agentName);
45070
45175
  const waitAfterPrompt = parseOptionalWaitDuration(waitAfterPromptValue, 0);
45071
45176
  const waitBetweenPrompts = parseOptionalWaitDuration(waitBetweenPromptsValue, 0);
45072
45177
  const waitAfterError = parseOptionalWaitDuration(waitAfterErrorValue, DEFAULT_WAIT_AFTER_ERROR_MS$1);
@@ -45161,6 +45266,7 @@ function $initializeCoderServerCommand(program) {
45161
45266
  Features:
45162
45267
  - Runs the same prompt processing as \`ptbk coder run\`
45163
45268
  - Checks that the selected harness is installed and up to date on startup unless --no-harness-update is used
45269
+ - Offers to add missing project-local ignore rules for the selected harness
45164
45270
  - Does not exit when all prompts are done; polls for new prompt files instead
45165
45271
  - Serves a kanban board at http://localhost:<port> for visual progress tracking
45166
45272
  - Allows editing prompt files directly from the browser (Trello-style)
@@ -45206,6 +45312,7 @@ function $initializeCoderServerCommand(program) {
45206
45312
  });
45207
45313
  const { isHarnessUpdateCheckEnabled } = normalizeHarnessUpdateCliOptions(cliOptions);
45208
45314
  await $ensureHarnessInstallations([runnerOptions.agentName], isHarnessUpdateCheckEnabled);
45315
+ await $ensureCoderHarnessGitignoreRules(process.cwd(), runnerOptions.agentName);
45209
45316
  // [1] Parse the wait options and --no-auto (same logic as `coder run`)
45210
45317
  const waitForUser = !auto;
45211
45318
  const waitAfterPrompt = parseOptionalWaitDuration(waitAfterPromptValue, 0);
@@ -74519,6 +74626,21 @@ function listPromptsToBeWritten(files, priorityFilter = {}) {
74519
74626
  isPromptInPriorityFilter(prompt.section, priorityFilter));
74520
74627
  }
74521
74628
 
74629
+ /**
74630
+ * Finds the first non-empty line within the inclusive bounds.
74631
+ *
74632
+ * @private internal utility of prompt parsing and status writing
74633
+ */
74634
+ function findFirstNonEmptyLineIndex(lines, startLine, endLine) {
74635
+ for (let lineIndex = startLine; lineIndex <= endLine; lineIndex++) {
74636
+ const line = lines[lineIndex];
74637
+ if (line !== undefined && line.trim() !== '') {
74638
+ return lineIndex;
74639
+ }
74640
+ }
74641
+ return undefined;
74642
+ }
74643
+
74522
74644
  /**
74523
74645
  * Checks whether a prompt is unrestricted or matches the selected harness/model.
74524
74646
  *
@@ -74554,6 +74676,14 @@ function extractPromptRunnerTokens(statusLine) {
74554
74676
  .filter((token) => token !== '');
74555
74677
  }
74556
74678
 
74679
+ /**
74680
+ * Matches the supported prompt status markers at the start of a line.
74681
+ *
74682
+ * A different bracketed prefix can be ordinary prompt content, for example an emoji tag.
74683
+ *
74684
+ * @private internal constant of `parsePromptFile`
74685
+ */
74686
+ const PROMPT_STATUS_MARKER_PATTERN = /^\[(?: |-|[xX]|\^|!)\]/u;
74557
74687
  /**
74558
74688
  * Parses a prompt markdown file into sections and metadata.
74559
74689
  */
@@ -74573,11 +74703,11 @@ function parsePromptFile(filePath, content) {
74573
74703
  continue;
74574
74704
  }
74575
74705
  const endLine = i - 1;
74576
- const firstNonEmptyLine = findFirstNonEmptyLine(lines, startLine, endLine);
74706
+ const firstNonEmptyLine = findFirstNonEmptyLineIndex(lines, startLine, endLine);
74577
74707
  if (firstNonEmptyLine !== undefined) {
74578
74708
  const statusLine = (lines[firstNonEmptyLine] || '').trim();
74579
74709
  const parsedStatus = parseStatusLine(statusLine);
74580
- const status = (_a = parsedStatus === null || parsedStatus === void 0 ? void 0 : parsedStatus.status) !== null && _a !== void 0 ? _a : 'not-ready';
74710
+ const status = (_a = parsedStatus === null || parsedStatus === void 0 ? void 0 : parsedStatus.status) !== null && _a !== void 0 ? _a : (hasPromptStatusMarker(statusLine) ? 'not-ready' : 'todo');
74581
74711
  const priority = (_b = parsedStatus === null || parsedStatus === void 0 ? void 0 : parsedStatus.priority) !== null && _b !== void 0 ? _b : 0;
74582
74712
  sections.push({
74583
74713
  index,
@@ -74640,16 +74770,12 @@ function parseStatusLine(line) {
74640
74770
  return { status: 'todo', priority: (_d = (_c = details.match(/!/gu)) === null || _c === void 0 ? void 0 : _c.length) !== null && _d !== void 0 ? _d : 0 };
74641
74771
  }
74642
74772
  /**
74643
- * Finds the first non-empty line index between two bounds.
74773
+ * Checks whether a line starts with one of the supported prompt status markers.
74774
+ *
74775
+ * @private internal utility of `parsePromptFile`
74644
74776
  */
74645
- function findFirstNonEmptyLine(lines, startLine, endLine) {
74646
- for (let i = startLine; i <= endLine; i++) {
74647
- const line = lines[i];
74648
- if (line !== undefined && line.trim() !== '') {
74649
- return i;
74650
- }
74651
- }
74652
- return undefined;
74777
+ function hasPromptStatusMarker(line) {
74778
+ return PROMPT_STATUS_MARKER_PATTERN.test(line);
74653
74779
  }
74654
74780
 
74655
74781
  /**
@@ -77502,13 +77628,59 @@ const REWRITABLE_PROMPT_STATUS_LINE_PATTERN = /^(?<indentation>\s*)\[(?:\s*|\^)\
77502
77628
  /**
77503
77629
  * Rewrites the status line of one prompt section while preserving its indentation.
77504
77630
  *
77505
- * Only a todo `[ ]` or an in-progress `[^]` status line is rewritten, so an already finalized
77506
- * `[x]`, `[!]` or `[-]` status is never overwritten by accident.
77631
+ * An unmarked prompt is implicitly a todo, so its first live status line is inserted immediately before its content.
77632
+ * Only a todo `[ ]` or an in-progress `[^]` status line is otherwise rewritten, so an already finalized `[x]`, `[!]`
77633
+ * or `[-]` status is never overwritten by accident.
77507
77634
  */
77508
77635
  function writePromptStatusLine(file, section, replacementStatusLine) {
77636
+ if (section.statusLineIndex === undefined) {
77637
+ insertPromptStatusLine(file, section, replacementStatusLine);
77638
+ return;
77639
+ }
77509
77640
  const { statusLineIndex, line } = resolvePromptStatusLine(file, section);
77510
77641
  file.lines[statusLineIndex] = line.replace(REWRITABLE_PROMPT_STATUS_LINE_PATTERN, `$<indentation>${replacementStatusLine}`);
77511
77642
  }
77643
+ /**
77644
+ * Inserts the first persisted status line for an unmarked prompt and keeps parsed section positions in sync.
77645
+ *
77646
+ * @private internal utility of `writePromptStatusLine`
77647
+ */
77648
+ function insertPromptStatusLine(file, section, replacementStatusLine) {
77649
+ const statusLineIndex = findFirstNonEmptyLineIndex(file.lines, section.startLine, section.endLine);
77650
+ if (statusLineIndex === undefined) {
77651
+ const promptReference = `Prompt ${section.index + 1} in \`${file.name}\``;
77652
+ throw new UnexpectedError(spaceTrim$1(`
77653
+ ${promptReference} does not have content where its status line can be added.
77654
+ `));
77655
+ }
77656
+ file.lines.splice(statusLineIndex, 0, replacementStatusLine);
77657
+ updatePromptSectionPositionsAfterStatusInsertion(file, section, statusLineIndex);
77658
+ }
77659
+ /**
77660
+ * Updates the parsed indexes after adding a status line to an unmarked prompt.
77661
+ *
77662
+ * @private internal utility of `writePromptStatusLine`
77663
+ */
77664
+ function updatePromptSectionPositionsAfterStatusInsertion(file, section, statusLineIndex) {
77665
+ for (const promptSection of file.sections) {
77666
+ if (promptSection === section) {
77667
+ promptSection.statusLineIndex = statusLineIndex;
77668
+ promptSection.endLine += 1;
77669
+ continue;
77670
+ }
77671
+ if (promptSection.startLine >= statusLineIndex) {
77672
+ promptSection.startLine += 1;
77673
+ promptSection.endLine += 1;
77674
+ if (promptSection.statusLineIndex !== undefined) {
77675
+ promptSection.statusLineIndex += 1;
77676
+ }
77677
+ }
77678
+ }
77679
+ if (!file.sections.includes(section)) {
77680
+ section.statusLineIndex = statusLineIndex;
77681
+ section.endLine += 1;
77682
+ }
77683
+ }
77512
77684
 
77513
77685
  /**
77514
77686
  * Marks a prompt section as done and records the per-step usage pricing and runner details.