@promptbook/cli 0.114.0-4 → 0.114.0-5
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.
- package/README.md +3 -3
- package/esm/index.es.js +268 -74
- package/esm/index.es.js.map +1 -1
- package/esm/scripts/run-codex-prompts/common/createCoderRunStepTracker.d.ts +48 -0
- package/esm/scripts/run-codex-prompts/prompts/buildPromptStatusDetails.d.ts +43 -0
- package/esm/scripts/run-codex-prompts/prompts/formatCoderRunSteps.d.ts +6 -3
- package/esm/scripts/run-codex-prompts/prompts/isPromptSectionUnfinished.d.ts +8 -0
- package/esm/scripts/run-codex-prompts/prompts/markPromptDone.d.ts +1 -1
- package/esm/scripts/run-codex-prompts/prompts/markPromptInProgress.d.ts +27 -0
- package/esm/scripts/run-codex-prompts/prompts/resolvePromptStatusLine.d.ts +19 -0
- package/esm/scripts/run-codex-prompts/prompts/writePromptStatusLine.d.ts +9 -0
- package/esm/scripts/run-codex-prompts/server/buildCoderServerPromptResponse.d.ts +1 -1
- package/esm/scripts/run-codex-prompts/server/coderServerHtml.d.ts +1 -1
- package/esm/scripts/run-codex-prompts/server/updatePromptSection.d.ts +1 -1
- package/esm/scripts/run-codex-prompts/testing/runPromptWithTestFeedback.d.ts +6 -0
- package/esm/scripts/verify-prompts/$orderPromptFiles.d.ts +9 -0
- package/esm/scripts/verify-prompts/VerifyPromptsOrder.d.ts +26 -0
- package/esm/scripts/verify-prompts/verify-prompts.d.ts +3 -2
- package/esm/src/cli/cli-commands/coder/verify.d.ts +1 -1
- package/esm/src/version.d.ts +1 -1
- package/package.json +1 -1
- package/src/cli/cli-commands/coder/verify.ts +29 -5
- package/src/other/templates/getTemplatesPipelineCollection.ts +704 -843
- package/src/version.ts +2 -2
- package/src/versions.txt +1 -0
- package/umd/index.umd.js +268 -74
- package/umd/index.umd.js.map +1 -1
- package/umd/scripts/run-codex-prompts/common/createCoderRunStepTracker.d.ts +48 -0
- package/umd/scripts/run-codex-prompts/prompts/buildPromptStatusDetails.d.ts +43 -0
- package/umd/scripts/run-codex-prompts/prompts/formatCoderRunSteps.d.ts +6 -3
- package/umd/scripts/run-codex-prompts/prompts/isPromptSectionUnfinished.d.ts +8 -0
- package/umd/scripts/run-codex-prompts/prompts/markPromptDone.d.ts +1 -1
- package/umd/scripts/run-codex-prompts/prompts/markPromptInProgress.d.ts +27 -0
- package/umd/scripts/run-codex-prompts/prompts/resolvePromptStatusLine.d.ts +19 -0
- package/umd/scripts/run-codex-prompts/prompts/writePromptStatusLine.d.ts +9 -0
- package/umd/scripts/run-codex-prompts/server/buildCoderServerPromptResponse.d.ts +1 -1
- package/umd/scripts/run-codex-prompts/server/coderServerHtml.d.ts +1 -1
- package/umd/scripts/run-codex-prompts/server/updatePromptSection.d.ts +1 -1
- package/umd/scripts/run-codex-prompts/testing/runPromptWithTestFeedback.d.ts +6 -0
- package/umd/scripts/verify-prompts/$orderPromptFiles.d.ts +9 -0
- package/umd/scripts/verify-prompts/VerifyPromptsOrder.d.ts +26 -0
- package/umd/scripts/verify-prompts/verify-prompts.d.ts +3 -2
- package/umd/src/cli/cli-commands/coder/verify.d.ts +1 -1
- package/umd/src/version.d.ts +1 -1
- package/esm/scripts/run-codex-prompts/prompts/replacePromptTodoStatusLine.d.ts +0 -7
- package/umd/scripts/run-codex-prompts/prompts/replacePromptTodoStatusLine.d.ts +0 -7
package/README.md
CHANGED
|
@@ -526,7 +526,7 @@ Or you can install them separately:
|
|
|
526
526
|
|
|
527
527
|
Promptbook Coder is **not another standalone coding model**. It is an orchestration layer over coding agents such as **GitHub Copilot**, **OpenAI Codex**, **Claude Code**, **Opencode**, **Cline**, and **Gemini CLI**. The difference is that Promptbook Coder adds a repeatable repository workflow on top of them:
|
|
528
528
|
|
|
529
|
-
- prompt files with explicit statuses like `[ ]`, `[x]`, and `[-]`
|
|
529
|
+
- prompt files with explicit statuses like `[ ]`, `[^]`, `[x]`, and `[-]`
|
|
530
530
|
- automatic selection of the next runnable task, including priority support
|
|
531
531
|
- optional shared repo context loaded from a file such as `AGENTS.md`
|
|
532
532
|
- automatic `git add`, commit, and push after each successful prompt
|
|
@@ -541,11 +541,11 @@ In short: tools like Claude Code, Codex, or GitHub Copilot are the **engines**;
|
|
|
541
541
|
1. `ptbk coder init` prepares the project for the coder workflow, seeds project-owned generic templates in `prompts/templates/`, creates a starter `AGENTS.md` context file, adds helper `npm run coder:*` scripts, ensures `.gitignore` ignores `/.promptbook`, and configures VS Code prompt screenshots in `prompts/screenshots/`.
|
|
542
542
|
2. `ptbk coder generate-boilerplates` creates prompt files in `prompts/`.
|
|
543
543
|
3. You replace placeholder `@@@` sections with real coding tasks.
|
|
544
|
-
4. `ptbk coder run` sends the next ready `[ ]` prompt to the selected coding agent.
|
|
544
|
+
4. `ptbk coder run` sends the next ready `[ ]` prompt to the selected coding agent and immediately marks it as in progress `[^]`, naming the harness, the model and the step which is running.
|
|
545
545
|
5. Promptbook Coder marks the prompt as done `[x]`, records runner metadata, then stages, commits, and pushes the resulting changes.
|
|
546
546
|
6. `ptbk coder verify` reviews completed prompts, archives finished files to `prompts/done/`, and appends a repair prompt when more work is needed.
|
|
547
547
|
|
|
548
|
-
Prompts marked with `[-]` are not ready yet, prompts containing `@@@` are treated as not fully written, and prompts with more `!` markers have higher priority.
|
|
548
|
+
Prompts marked with `[-]` are not ready yet, prompts containing `@@@` are treated as not fully written, and prompts with more `!` markers have higher priority. A prompt left as `[^]` was interrupted in the middle of its implementation — the in-progress status is never reverted, so a killed or crashed coder always leaves that signal behind.
|
|
549
549
|
|
|
550
550
|
#### Features
|
|
551
551
|
|
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-
|
|
51
|
+
const PROMPTBOOK_ENGINE_VERSION = '0.114.0-5';
|
|
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
|
|
@@ -29748,6 +29748,32 @@ function appendCoderContext(prompt, context) {
|
|
|
29748
29748
|
`);
|
|
29749
29749
|
}
|
|
29750
29750
|
|
|
29751
|
+
/**
|
|
29752
|
+
* Creates the step tracker of one prompt round.
|
|
29753
|
+
*
|
|
29754
|
+
* The tracker is the single place which knows which steps have finished and which one is running,
|
|
29755
|
+
* so both the finished `[x]` status line and the intermediate `[^]` in-progress status lines are
|
|
29756
|
+
* built from the very same data.
|
|
29757
|
+
*/
|
|
29758
|
+
function createCoderRunStepTracker(onStepStarted) {
|
|
29759
|
+
const steps = [];
|
|
29760
|
+
let reportedLoginMethod;
|
|
29761
|
+
return {
|
|
29762
|
+
steps,
|
|
29763
|
+
async startStep(kind) {
|
|
29764
|
+
await (onStepStarted === null || onStepStarted === void 0 ? void 0 : onStepStarted({
|
|
29765
|
+
startedStepKind: kind,
|
|
29766
|
+
finishedSteps: [...steps],
|
|
29767
|
+
loginMethod: reportedLoginMethod,
|
|
29768
|
+
}));
|
|
29769
|
+
},
|
|
29770
|
+
finishStep(step, loginMethod) {
|
|
29771
|
+
steps.push(step);
|
|
29772
|
+
reportedLoginMethod = loginMethod !== null && loginMethod !== void 0 ? loginMethod : reportedLoginMethod;
|
|
29773
|
+
},
|
|
29774
|
+
};
|
|
29775
|
+
}
|
|
29776
|
+
|
|
29751
29777
|
/**
|
|
29752
29778
|
* Maximum amount of test output embedded into an agent prompt.
|
|
29753
29779
|
*/
|
|
@@ -29793,7 +29819,7 @@ const SHELL_SCRIPT_EXTENSION = '.sh';
|
|
|
29793
29819
|
async function runPromptWithTestFeedback(options) {
|
|
29794
29820
|
var _a, _b, _c, _d;
|
|
29795
29821
|
const normalizedTestCommand = (_a = options.testCommand) === null || _a === void 0 ? void 0 : _a.trim();
|
|
29796
|
-
const
|
|
29822
|
+
const stepTracker = createCoderRunStepTracker(options.onStepStarted);
|
|
29797
29823
|
if (!normalizedTestCommand) {
|
|
29798
29824
|
(_b = options.onAttemptStarted) === null || _b === void 0 ? void 0 : _b.call(options, 1);
|
|
29799
29825
|
await waitForPromptAttemptPauseCheckpoint(options.waitForPauseCheckpoint, options.runner.name, 1);
|
|
@@ -29801,9 +29827,9 @@ async function runPromptWithTestFeedback(options) {
|
|
|
29801
29827
|
runOptions: options,
|
|
29802
29828
|
prompt: options.prompt,
|
|
29803
29829
|
kind: 'implementation',
|
|
29804
|
-
|
|
29830
|
+
stepTracker,
|
|
29805
29831
|
});
|
|
29806
|
-
return { ...result, attemptCount: 1, steps };
|
|
29832
|
+
return { ...result, attemptCount: 1, steps: stepTracker.steps };
|
|
29807
29833
|
}
|
|
29808
29834
|
const runPromptTestCommandExecutor = (_c = options.runPromptTestCommandExecutor) !== null && _c !== void 0 ? _c : runPromptTestCommand;
|
|
29809
29835
|
let promptForCurrentAttempt = options.prompt;
|
|
@@ -29814,7 +29840,7 @@ async function runPromptWithTestFeedback(options) {
|
|
|
29814
29840
|
runOptions: options,
|
|
29815
29841
|
prompt: promptForCurrentAttempt,
|
|
29816
29842
|
kind: attemptCount === 1 ? 'implementation' : 'fixing',
|
|
29817
|
-
|
|
29843
|
+
stepTracker,
|
|
29818
29844
|
});
|
|
29819
29845
|
await waitForVerificationPauseCheckpoint(options.waitForPauseCheckpoint, normalizedTestCommand, attemptCount);
|
|
29820
29846
|
console.info(colors.gray(`Running verification command after attempt #${attemptCount}: ${normalizedTestCommand}`));
|
|
@@ -29822,10 +29848,10 @@ async function runPromptWithTestFeedback(options) {
|
|
|
29822
29848
|
runPromptTestCommandExecutor,
|
|
29823
29849
|
testCommand: normalizedTestCommand,
|
|
29824
29850
|
runOptions: options,
|
|
29825
|
-
|
|
29851
|
+
stepTracker,
|
|
29826
29852
|
});
|
|
29827
29853
|
if (failedVerification === undefined) {
|
|
29828
|
-
return { ...result, attemptCount, steps };
|
|
29854
|
+
return { ...result, attemptCount, steps: stepTracker.steps };
|
|
29829
29855
|
}
|
|
29830
29856
|
const fullVerificationOutput = formatUnknownErrorDetails(failedVerification.error);
|
|
29831
29857
|
const feedbackVerificationOutput = limitTestOutput(fullVerificationOutput);
|
|
@@ -29851,7 +29877,8 @@ async function runPromptWithTestFeedback(options) {
|
|
|
29851
29877
|
* Runs one coding attempt through the runner, timing it and recording it as an implementation or fixing step.
|
|
29852
29878
|
*/
|
|
29853
29879
|
async function runRunnerPromptStep(options) {
|
|
29854
|
-
const { runOptions, prompt, kind,
|
|
29880
|
+
const { runOptions, prompt, kind, stepTracker } = options;
|
|
29881
|
+
await stepTracker.startStep(kind);
|
|
29855
29882
|
const stepStartedTimeMs = Date.now();
|
|
29856
29883
|
const result = await runOptions.runner.runPrompt({
|
|
29857
29884
|
prompt,
|
|
@@ -29861,7 +29888,7 @@ async function runRunnerPromptStep(options) {
|
|
|
29861
29888
|
preserveArtifactsOnSuccess: runOptions.preserveArtifactsOnSuccess,
|
|
29862
29889
|
waitForPauseCheckpoint: runOptions.waitForPauseCheckpoint,
|
|
29863
29890
|
});
|
|
29864
|
-
|
|
29891
|
+
stepTracker.finishStep({ kind, usage: result.usage, durationMs: Date.now() - stepStartedTimeMs }, result.loginMethod);
|
|
29865
29892
|
return result;
|
|
29866
29893
|
}
|
|
29867
29894
|
/**
|
|
@@ -29869,7 +29896,8 @@ async function runRunnerPromptStep(options) {
|
|
|
29869
29896
|
* returns the failure (or `undefined` when the verification passed).
|
|
29870
29897
|
*/
|
|
29871
29898
|
async function runVerificationStep(options) {
|
|
29872
|
-
const { runPromptTestCommandExecutor, testCommand, runOptions,
|
|
29899
|
+
const { runPromptTestCommandExecutor, testCommand, runOptions, stepTracker } = options;
|
|
29900
|
+
await stepTracker.startStep('testing');
|
|
29873
29901
|
const stepStartedTimeMs = Date.now();
|
|
29874
29902
|
try {
|
|
29875
29903
|
await runPromptTestCommandExecutor({
|
|
@@ -29885,7 +29913,7 @@ async function runVerificationStep(options) {
|
|
|
29885
29913
|
return { error };
|
|
29886
29914
|
}
|
|
29887
29915
|
finally {
|
|
29888
|
-
|
|
29916
|
+
stepTracker.finishStep({ kind: 'testing', usage: null, durationMs: Date.now() - stepStartedTimeMs });
|
|
29889
29917
|
}
|
|
29890
29918
|
}
|
|
29891
29919
|
/**
|
|
@@ -41172,6 +41200,45 @@ function normalizeCommandOptionValue(value) {
|
|
|
41172
41200
|
// Note: [🟡] Code for CLI command [server](src/cli/cli-commands/coder/server.ts) should never be published outside of `@promptbook/cli`
|
|
41173
41201
|
// Note: [💞] Ignore a discrepancy between file name and entity name
|
|
41174
41202
|
|
|
41203
|
+
/**
|
|
41204
|
+
* Orders supported by `ptbk coder verify --order`.
|
|
41205
|
+
*/
|
|
41206
|
+
const VERIFY_PROMPTS_ORDER_VALUES = ['from-earliest', 'from-latest', 'random'];
|
|
41207
|
+
/**
|
|
41208
|
+
* Order used when `--order` is not provided.
|
|
41209
|
+
*/
|
|
41210
|
+
const DEFAULT_VERIFY_PROMPTS_ORDER = 'from-earliest';
|
|
41211
|
+
/**
|
|
41212
|
+
* Human-readable description of each supported order, shared by the CLI help and the verification output.
|
|
41213
|
+
*/
|
|
41214
|
+
const VERIFY_PROMPTS_ORDER_DESCRIPTIONS = {
|
|
41215
|
+
'from-earliest': 'from the earliest prompt file',
|
|
41216
|
+
'from-latest': 'from the latest prompt file',
|
|
41217
|
+
random: 'in random order',
|
|
41218
|
+
};
|
|
41219
|
+
/**
|
|
41220
|
+
* Parses and validates one raw `--order` value.
|
|
41221
|
+
*
|
|
41222
|
+
* Note: `ptbk coder verify` lets Commander validate the value, this is used by the standalone script which parses the raw arguments itself
|
|
41223
|
+
*/
|
|
41224
|
+
function parseVerifyPromptsOrder(orderValue) {
|
|
41225
|
+
if (orderValue === undefined) {
|
|
41226
|
+
return DEFAULT_VERIFY_PROMPTS_ORDER;
|
|
41227
|
+
}
|
|
41228
|
+
if (VERIFY_PROMPTS_ORDER_VALUES.includes(orderValue)) {
|
|
41229
|
+
return orderValue;
|
|
41230
|
+
}
|
|
41231
|
+
throw new NotAllowed(spaceTrim$1((block) => `
|
|
41232
|
+
Invalid value for \`--order\`: \`${orderValue}\`.
|
|
41233
|
+
|
|
41234
|
+
Use one of the supported orders:
|
|
41235
|
+
${block(VERIFY_PROMPTS_ORDER_VALUES.map((value) => `- \`${value}\` processes the prompt files ${VERIFY_PROMPTS_ORDER_DESCRIPTIONS[value]}`).join('\n'))}
|
|
41236
|
+
|
|
41237
|
+
Actionable hint:
|
|
41238
|
+
- The removed \`--reverse\` flag is now \`--order from-latest\`.
|
|
41239
|
+
`));
|
|
41240
|
+
}
|
|
41241
|
+
|
|
41175
41242
|
/**
|
|
41176
41243
|
* Initializes `coder verify` command for Promptbook CLI utilities
|
|
41177
41244
|
*
|
|
@@ -41191,21 +41258,27 @@ function $initializeCoderVerifyCommand(program) {
|
|
|
41191
41258
|
- Auto-appends repair prompts for incomplete work
|
|
41192
41259
|
- Processes files with all-done prompts first
|
|
41193
41260
|
- Supports ignoring matching prompt candidates for one verification run
|
|
41261
|
+
- Supports processing the prompt files from the earliest, from the latest or in random order
|
|
41194
41262
|
|
|
41195
41263
|
${block(CODER_GIT_SYNC_DESCRIPTION)}
|
|
41196
41264
|
|
|
41197
41265
|
Note: The git synchronization is applied around each single verification, not once per run.
|
|
41198
41266
|
`));
|
|
41199
|
-
command.
|
|
41267
|
+
command.addOption(new Option('--order <order>', spaceTrim$1((block) => `
|
|
41268
|
+
Order in which the prompt files are processed:
|
|
41269
|
+
${block(VERIFY_PROMPTS_ORDER_VALUES.map((order) => `- ${order}: ${VERIFY_PROMPTS_ORDER_DESCRIPTIONS[order]}`).join('\n'))}
|
|
41270
|
+
`))
|
|
41271
|
+
.choices([...VERIFY_PROMPTS_ORDER_VALUES])
|
|
41272
|
+
.default(DEFAULT_VERIFY_PROMPTS_ORDER));
|
|
41200
41273
|
command.option('--ignore <candidate-text>', 'Ignore prompt files whose filename or first prompt line contains the given text (repeatable)', collectStringOption, []);
|
|
41201
41274
|
addCoderGitSyncOptions(command);
|
|
41202
41275
|
command.action(handleActionErrors(async (cliOptions) => {
|
|
41203
|
-
const {
|
|
41276
|
+
const { order, ignore } = cliOptions;
|
|
41204
41277
|
const gitSync = normalizeCoderGitSyncCliOptions(cliOptions);
|
|
41205
41278
|
// Note: Import the main function dynamically to avoid loading heavy dependencies until needed
|
|
41206
41279
|
const { verifyPrompts } = await Promise.resolve().then(function () { return verifyPrompts$1; });
|
|
41207
41280
|
try {
|
|
41208
|
-
await verifyPrompts({
|
|
41281
|
+
await verifyPrompts({ order, ignore, gitSync });
|
|
41209
41282
|
}
|
|
41210
41283
|
catch (error) {
|
|
41211
41284
|
console.error(colors.bgRed('Prompt verification failed:'), error);
|
|
@@ -70350,7 +70423,7 @@ function parsePromptFile(filePath, content) {
|
|
|
70350
70423
|
}
|
|
70351
70424
|
/**
|
|
70352
70425
|
* Parses a status line like "[ ] !!", "[ ] use `gpt` !!!!!" or "[-]" into status and priority.
|
|
70353
|
-
* For [x] done
|
|
70426
|
+
* For [x] done, [!] failed and [^] in-progress prompts, allow metadata after the status marker.
|
|
70354
70427
|
*/
|
|
70355
70428
|
function parseStatusLine(line) {
|
|
70356
70429
|
var _a, _b, _c, _d;
|
|
@@ -70364,6 +70437,11 @@ function parseStatusLine(line) {
|
|
|
70364
70437
|
if (failedMatch) {
|
|
70365
70438
|
return { status: 'failed', priority: 0 };
|
|
70366
70439
|
}
|
|
70440
|
+
// For in-progress prompts [^], allow any content after (for the steps recorded so far)
|
|
70441
|
+
const inProgressMatch = line.match(/^\[(?<status>\^)\]/);
|
|
70442
|
+
if (inProgressMatch) {
|
|
70443
|
+
return { status: 'in-progress', priority: 0 };
|
|
70444
|
+
}
|
|
70367
70445
|
// For not-ready [-], keep the historical clean-line syntax.
|
|
70368
70446
|
if (/^\[-\]\s*!*\s*$/u.test(line)) {
|
|
70369
70447
|
return { status: 'not-ready', priority: 0 };
|
|
@@ -72943,14 +73021,25 @@ const CODER_RUN_STEP_LABELS = {
|
|
|
72943
73021
|
fixing: 'Fixing',
|
|
72944
73022
|
};
|
|
72945
73023
|
/**
|
|
72946
|
-
*
|
|
73024
|
+
* Suffix marking the one step which has already started but has neither a price nor a duration yet.
|
|
73025
|
+
*/
|
|
73026
|
+
const IN_PROGRESS_STEP_SUFFIX = 'in progress';
|
|
73027
|
+
/**
|
|
73028
|
+
* Formats the per-step usage breakdown recorded for one prompt.
|
|
72947
73029
|
*
|
|
72948
73030
|
* Produces a `; `-separated summary such as
|
|
72949
73031
|
* `Implementation $8.01 6 hours; Testing 1 hour; Fixing $3.14 2 hours` where each coding step carries its
|
|
72950
73032
|
* price and duration and each verification step carries only its duration.
|
|
73033
|
+
*
|
|
73034
|
+
* @param steps - Steps which have already finished
|
|
73035
|
+
* @param inProgressStepKind - Step which has started but has not finished yet, appended as `Testing in progress`
|
|
72951
73036
|
*/
|
|
72952
|
-
function formatCoderRunSteps(steps) {
|
|
72953
|
-
|
|
73037
|
+
function formatCoderRunSteps(steps, inProgressStepKind) {
|
|
73038
|
+
const formattedSteps = steps.map(formatCoderRunStep);
|
|
73039
|
+
if (inProgressStepKind !== undefined) {
|
|
73040
|
+
formattedSteps.push(`${CODER_RUN_STEP_LABELS[inProgressStepKind]} ${IN_PROGRESS_STEP_SUFFIX}`);
|
|
73041
|
+
}
|
|
73042
|
+
return formattedSteps.join('; ');
|
|
72954
73043
|
}
|
|
72955
73044
|
/**
|
|
72956
73045
|
* Formats one coder run step as `Label $price duration`, omitting the price for steps without model usage.
|
|
@@ -72979,47 +73068,78 @@ function formatPromptAttemptMetadata(status, attemptCount) {
|
|
|
72979
73068
|
}
|
|
72980
73069
|
|
|
72981
73070
|
/**
|
|
72982
|
-
*
|
|
73071
|
+
* Builds the shared body of a prompt status line, used by both the in-progress `[^]` and the done `[x]` status.
|
|
72983
73072
|
*
|
|
72984
|
-
*
|
|
72985
|
-
*
|
|
73073
|
+
* Produces details such as
|
|
73074
|
+
* ``by OpenAI Codex `gpt-5.6-luna` thinking `max` (ChatGPT account) - Implementation ~$0.2036 10 minutes``.
|
|
72986
73075
|
*/
|
|
72987
|
-
function
|
|
72988
|
-
|
|
73076
|
+
function buildPromptStatusDetails(options) {
|
|
73077
|
+
const { steps, inProgressStepKind, runnerName, modelName, attemptCount, loginMethod, thinkingLevel } = options;
|
|
73078
|
+
const runnerSignature = formatRunnerSignature(runnerName, modelName, thinkingLevel);
|
|
73079
|
+
const attemptMetadata = formatPromptAttemptMetadata('done', attemptCount);
|
|
73080
|
+
const loginMethodLabel = formatCodexLoginMethod(loginMethod);
|
|
73081
|
+
const loginMethodSuffix = loginMethodLabel ? ` (${loginMethodLabel})` : '';
|
|
73082
|
+
const stepsSummary = formatCoderRunSteps(steps, inProgressStepKind);
|
|
73083
|
+
const stepsSuffix = stepsSummary === '' ? '' : ` - ${stepsSummary}`;
|
|
73084
|
+
return `${attemptMetadata}by ${runnerSignature}${loginMethodSuffix}${stepsSuffix}`;
|
|
72989
73085
|
}
|
|
72990
73086
|
|
|
72991
73087
|
/**
|
|
72992
|
-
*
|
|
73088
|
+
* Resolves the status line of one prompt section so it can be rewritten.
|
|
72993
73089
|
*/
|
|
72994
|
-
function
|
|
73090
|
+
function resolvePromptStatusLine(file, section) {
|
|
72995
73091
|
if (section.statusLineIndex === undefined) {
|
|
72996
|
-
throw new
|
|
73092
|
+
throw new UnexpectedError(spaceTrim$1(`
|
|
73093
|
+
Prompt ${section.index + 1} in \`${file.name}\` does not have a status line.
|
|
73094
|
+
`));
|
|
72997
73095
|
}
|
|
72998
73096
|
const line = file.lines[section.statusLineIndex];
|
|
72999
73097
|
if (line === undefined) {
|
|
73000
|
-
throw new
|
|
73098
|
+
throw new UnexpectedError(spaceTrim$1(`
|
|
73099
|
+
Prompt ${section.index + 1} in \`${file.name}\` points to a missing status line.
|
|
73100
|
+
`));
|
|
73001
73101
|
}
|
|
73002
|
-
|
|
73003
|
-
|
|
73004
|
-
|
|
73005
|
-
|
|
73006
|
-
|
|
73007
|
-
|
|
73008
|
-
|
|
73009
|
-
|
|
73102
|
+
return { statusLineIndex: section.statusLineIndex, line };
|
|
73103
|
+
}
|
|
73104
|
+
|
|
73105
|
+
/**
|
|
73106
|
+
* Matches a complete todo `[ ]` or in-progress `[^]` status line, capturing its indentation.
|
|
73107
|
+
*
|
|
73108
|
+
* The complete line is replaced because a todo status can contain a required model/harness token
|
|
73109
|
+
* in addition to its priority markers, and an in-progress status already carries the metadata of
|
|
73110
|
+
* the steps recorded so far.
|
|
73111
|
+
*/
|
|
73112
|
+
const REWRITABLE_PROMPT_STATUS_LINE_PATTERN = /^(?<indentation>\s*)\[(?:\s*|\^)\].*$/u;
|
|
73113
|
+
/**
|
|
73114
|
+
* Rewrites the status line of one prompt section while preserving its indentation.
|
|
73115
|
+
*
|
|
73116
|
+
* Only a todo `[ ]` or an in-progress `[^]` status line is rewritten, so an already finalized
|
|
73117
|
+
* `[x]`, `[!]` or `[-]` status is never overwritten by accident.
|
|
73118
|
+
*/
|
|
73119
|
+
function writePromptStatusLine(file, section, replacementStatusLine) {
|
|
73120
|
+
const { statusLineIndex, line } = resolvePromptStatusLine(file, section);
|
|
73121
|
+
file.lines[statusLineIndex] = line.replace(REWRITABLE_PROMPT_STATUS_LINE_PATTERN, `$<indentation>${replacementStatusLine}`);
|
|
73122
|
+
}
|
|
73123
|
+
|
|
73124
|
+
/**
|
|
73125
|
+
* Marks a prompt section as done and records the per-step usage pricing and runner details.
|
|
73126
|
+
*/
|
|
73127
|
+
function markPromptDone(file, section, steps, runnerName, modelName, attemptCount = 1, loginMethod, thinkingLevel) {
|
|
73128
|
+
const statusDetails = buildPromptStatusDetails({
|
|
73129
|
+
steps,
|
|
73130
|
+
runnerName,
|
|
73131
|
+
modelName,
|
|
73132
|
+
attemptCount,
|
|
73133
|
+
loginMethod,
|
|
73134
|
+
thinkingLevel,
|
|
73135
|
+
});
|
|
73136
|
+
writePromptStatusLine(file, section, `[x] ${statusDetails}`);
|
|
73010
73137
|
}
|
|
73011
73138
|
|
|
73012
73139
|
/**
|
|
73013
73140
|
* Marks a prompt section as failed and records runner details.
|
|
73014
73141
|
*/
|
|
73015
73142
|
function markPromptFailed(file, section, runnerName, modelName, promptExecutionStartedDate, attemptCount = 1) {
|
|
73016
|
-
if (section.statusLineIndex === undefined) {
|
|
73017
|
-
throw new Error(`Prompt ${section.index + 1} in ${file.name} does not have a status line.`);
|
|
73018
|
-
}
|
|
73019
|
-
const line = file.lines[section.statusLineIndex];
|
|
73020
|
-
if (line === undefined) {
|
|
73021
|
-
throw new Error(`Prompt ${section.index + 1} in ${file.name} points to a missing status line.`);
|
|
73022
|
-
}
|
|
73023
73143
|
const runnerSignature = formatRunnerSignature(runnerName, modelName);
|
|
73024
73144
|
const attemptMetadata = formatPromptAttemptMetadata('failed', attemptCount);
|
|
73025
73145
|
const duration = moment().diff(promptExecutionStartedDate);
|
|
@@ -73027,7 +73147,18 @@ function markPromptFailed(file, section, runnerName, modelName, promptExecutionS
|
|
|
73027
73147
|
const failureDetails = attemptMetadata === ''
|
|
73028
73148
|
? `failed after ${durationString} by ${runnerSignature}`
|
|
73029
73149
|
: `${attemptMetadata}${durationString} by ${runnerSignature}`;
|
|
73030
|
-
file
|
|
73150
|
+
writePromptStatusLine(file, section, `[!] ${failureDetails}`);
|
|
73151
|
+
}
|
|
73152
|
+
|
|
73153
|
+
/**
|
|
73154
|
+
* Marks a prompt section as being implemented right now and records the steps finished so far.
|
|
73155
|
+
*
|
|
73156
|
+
* The `[^]` status is deliberately never reverted: when the coder is killed or crashes, the status stays
|
|
73157
|
+
* in the prompt file as the signal that this task was left in the middle of its implementation.
|
|
73158
|
+
*/
|
|
73159
|
+
function markPromptInProgress(options) {
|
|
73160
|
+
const { file, section, ...statusDetailsOptions } = options;
|
|
73161
|
+
writePromptStatusLine(file, section, `[^] ${buildPromptStatusDetails(statusDetailsOptions)}`);
|
|
73031
73162
|
}
|
|
73032
73163
|
|
|
73033
73164
|
/**
|
|
@@ -73136,6 +73267,13 @@ async function runPromptRound({ options, runner, runnerMetadata, nextPrompt, pro
|
|
|
73136
73267
|
attemptCount = nextAttemptCount;
|
|
73137
73268
|
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.setAttempt(nextAttemptCount);
|
|
73138
73269
|
},
|
|
73270
|
+
onStepStarted: (progress) => recordPromptRoundInProgress({
|
|
73271
|
+
nextPrompt,
|
|
73272
|
+
runnerMetadata,
|
|
73273
|
+
thinkingLevel: options.thinkingLevel,
|
|
73274
|
+
attemptCount,
|
|
73275
|
+
progress,
|
|
73276
|
+
}),
|
|
73139
73277
|
waitForPauseCheckpoint: waitForRequestedPause,
|
|
73140
73278
|
});
|
|
73141
73279
|
await finalizeSuccessfulPromptRound({
|
|
@@ -73187,6 +73325,30 @@ async function runPromptRound({ options, runner, runnerMetadata, nextPrompt, pro
|
|
|
73187
73325
|
throw lastError;
|
|
73188
73326
|
}, { preserveArtifactsOnSuccess: options.preserveLogs });
|
|
73189
73327
|
}
|
|
73328
|
+
/**
|
|
73329
|
+
* Records into the prompt file that the prompt is being implemented right now.
|
|
73330
|
+
*
|
|
73331
|
+
* The `[^]` in-progress status is written before every single step, so it always names the step which is
|
|
73332
|
+
* running and the steps already finished. It is intentionally never reverted: a coder which is killed or
|
|
73333
|
+
* crashes leaves the `[^]` status behind as the signal that this task was left in the middle.
|
|
73334
|
+
*/
|
|
73335
|
+
async function recordPromptRoundInProgress(options) {
|
|
73336
|
+
const { nextPrompt, runnerMetadata, thinkingLevel, attemptCount, progress } = options;
|
|
73337
|
+
markPromptInProgress({
|
|
73338
|
+
file: nextPrompt.file,
|
|
73339
|
+
section: nextPrompt.section,
|
|
73340
|
+
steps: progress.finishedSteps,
|
|
73341
|
+
inProgressStepKind: progress.startedStepKind,
|
|
73342
|
+
runnerName: runnerMetadata.runnerName,
|
|
73343
|
+
modelName: runnerMetadata.modelName,
|
|
73344
|
+
attemptCount,
|
|
73345
|
+
loginMethod: progress.loginMethod,
|
|
73346
|
+
thinkingLevel,
|
|
73347
|
+
});
|
|
73348
|
+
// Note: The prompt status is always written into the original project, an isolated round transports
|
|
73349
|
+
// its own changes back through the merge instead
|
|
73350
|
+
await writePromptFile(nextPrompt.file);
|
|
73351
|
+
}
|
|
73190
73352
|
/**
|
|
73191
73353
|
* Sleeps `options.waitAfterError` while keeping the rich UI and plain console in sync, then resets state for the retry.
|
|
73192
73354
|
*/
|
|
@@ -73847,19 +74009,9 @@ const PROMPT_STATUS_BOX_PATTERN = /^(?<indentation>\s*)\[[^\]]*\]/u;
|
|
|
73847
74009
|
* kept and only the status box turns from `[x]` into `[!]`, followed by the manual merge instructions.
|
|
73848
74010
|
*/
|
|
73849
74011
|
function markPromptIsolationMergeFailed(file, section, worktree) {
|
|
73850
|
-
|
|
73851
|
-
throw new UnexpectedError(spaceTrim$1(`
|
|
73852
|
-
Prompt ${section.index + 1} in \`${file.name}\` does not have a status line.
|
|
73853
|
-
`));
|
|
73854
|
-
}
|
|
73855
|
-
const line = file.lines[section.statusLineIndex];
|
|
73856
|
-
if (line === undefined) {
|
|
73857
|
-
throw new UnexpectedError(spaceTrim$1(`
|
|
73858
|
-
Prompt ${section.index + 1} in \`${file.name}\` points to a missing status line.
|
|
73859
|
-
`));
|
|
73860
|
-
}
|
|
74012
|
+
const { statusLineIndex, line } = resolvePromptStatusLine(file, section);
|
|
73861
74013
|
const failedStatusLine = line.replace(PROMPT_STATUS_BOX_PATTERN, '$<indentation>[!]');
|
|
73862
|
-
file.lines[
|
|
74014
|
+
file.lines[statusLineIndex] = `${failedStatusLine} - ${buildCoderIsolationMergeFailureStatusNote(worktree)}`;
|
|
73863
74015
|
}
|
|
73864
74016
|
|
|
73865
74017
|
/**
|
|
@@ -74999,7 +75151,9 @@ function getPromptColumn(options) {
|
|
|
74999
75151
|
if (section.status === 'not-ready' || isUnwritten) {
|
|
75000
75152
|
return 'backlog';
|
|
75001
75153
|
}
|
|
75002
|
-
|
|
75154
|
+
// Note: A prompt marked `[^]` stays in progress even when no agent is running it, because its
|
|
75155
|
+
// implementation was left in the middle
|
|
75156
|
+
if (isActive || section.status === 'in-progress') {
|
|
75003
75157
|
return 'in-progress';
|
|
75004
75158
|
}
|
|
75005
75159
|
if (!isPromptInPriorityFilter(section, priorityFilter)) {
|
|
@@ -75016,6 +75170,10 @@ function buildPromptTags(options) {
|
|
|
75016
75170
|
if (options.section.status === 'not-ready') {
|
|
75017
75171
|
tags.push({ id: 'not-ready', label: '[-]' });
|
|
75018
75172
|
}
|
|
75173
|
+
// Note: A `[^]` prompt which no agent is running right now was left in the middle of its implementation
|
|
75174
|
+
if (options.section.status === 'in-progress' && !options.isActive) {
|
|
75175
|
+
tags.push({ id: 'left-in-progress', label: '[^]' });
|
|
75176
|
+
}
|
|
75019
75177
|
if (options.isUnwritten) {
|
|
75020
75178
|
tags.push({ id: 'unwritten', label: '@@@' });
|
|
75021
75179
|
}
|
|
@@ -75045,7 +75203,7 @@ function getActivePrompt(uiState) {
|
|
|
75045
75203
|
* Checks whether a parsed section is the prompt currently handled by the active agent.
|
|
75046
75204
|
*/
|
|
75047
75205
|
function isPromptActive(promptFile, section, activePrompt) {
|
|
75048
|
-
if (!activePrompt || section.status !== 'todo') {
|
|
75206
|
+
if (!activePrompt || (section.status !== 'todo' && section.status !== 'in-progress')) {
|
|
75049
75207
|
return false;
|
|
75050
75208
|
}
|
|
75051
75209
|
return buildPromptLabelForDisplay(promptFile, section) === activePrompt.label;
|
|
@@ -75077,7 +75235,7 @@ function buildCoderServerRunState(uiState) {
|
|
|
75077
75235
|
* Overwrites the body of one prompt section with new content, preserving the status line.
|
|
75078
75236
|
*
|
|
75079
75237
|
* The `newContent` string is the prompt text without the status marker.
|
|
75080
|
-
* The status line (`[ ]`, `[x]`, `[!]`, `[-]`) is kept intact.
|
|
75238
|
+
* The status line (`[ ]`, `[^]`, `[x]`, `[!]`, `[-]`) is kept intact.
|
|
75081
75239
|
*
|
|
75082
75240
|
* @private internal utility of `ptbk coder server`
|
|
75083
75241
|
*/
|
|
@@ -75358,6 +75516,7 @@ const CODER_SERVER_HTML = `<!DOCTYPE html>
|
|
|
75358
75516
|
line-height: 1.35;
|
|
75359
75517
|
}
|
|
75360
75518
|
.tag-not-ready { background: #e2e8f0; color: #475569; }
|
|
75519
|
+
.tag-left-in-progress { background: #ffe4e6; color: #9f1239; }
|
|
75361
75520
|
.tag-unwritten { background: #fff4cc; color: #8a5a00; }
|
|
75362
75521
|
.tag-implementing { background: #ede9fe; color: #5b21b6; }
|
|
75363
75522
|
.tag-verifying { background: #fae8ff; color: #86198f; }
|
|
@@ -76088,6 +76247,33 @@ var runCodexPromptsServer$1 = /*#__PURE__*/Object.freeze({
|
|
|
76088
76247
|
runCodexPromptsServer: runCodexPromptsServer
|
|
76089
76248
|
});
|
|
76090
76249
|
|
|
76250
|
+
/**
|
|
76251
|
+
* Checks whether one prompt section still has open coding work.
|
|
76252
|
+
*
|
|
76253
|
+
* A `[ ]` prompt has not been started at all and a `[^]` prompt was left in the middle of its
|
|
76254
|
+
* implementation, so a file containing either of them is not finished yet.
|
|
76255
|
+
*/
|
|
76256
|
+
function isPromptSectionUnfinished(section) {
|
|
76257
|
+
return section.status === 'todo' || section.status === 'in-progress';
|
|
76258
|
+
}
|
|
76259
|
+
|
|
76260
|
+
/**
|
|
76261
|
+
* Orders the loaded prompt files for one verification pass.
|
|
76262
|
+
*
|
|
76263
|
+
* Note: `$` is used to indicate that this function is not a pure function - the `random` order is not deterministic
|
|
76264
|
+
* Note: This function does NOT mutate the given array
|
|
76265
|
+
*/
|
|
76266
|
+
function $orderPromptFiles(promptFiles, order) {
|
|
76267
|
+
switch (order) {
|
|
76268
|
+
case 'from-earliest':
|
|
76269
|
+
return [...promptFiles];
|
|
76270
|
+
case 'from-latest':
|
|
76271
|
+
return [...promptFiles].reverse();
|
|
76272
|
+
case 'random':
|
|
76273
|
+
return [...$shuffleItems(...promptFiles)];
|
|
76274
|
+
}
|
|
76275
|
+
}
|
|
76276
|
+
|
|
76091
76277
|
/**
|
|
76092
76278
|
* Path to the directory that holds the prompt markdown files.
|
|
76093
76279
|
*/
|
|
@@ -76116,8 +76302,8 @@ const DEFAULT_VERIFY_PROMPTS_OPTIONS = normalizeVerifyPromptsOptions(parseVerify
|
|
|
76116
76302
|
async function verifyPrompts(options = DEFAULT_VERIFY_PROMPTS_OPTIONS) {
|
|
76117
76303
|
const normalizedOptions = normalizeVerifyPromptsOptions(options);
|
|
76118
76304
|
console.info(colors.cyan.bold('📋 Prompt verification helper'));
|
|
76119
|
-
if (normalizedOptions.
|
|
76120
|
-
console.info(colors.gray(
|
|
76305
|
+
if (normalizedOptions.order !== DEFAULT_VERIFY_PROMPTS_ORDER) {
|
|
76306
|
+
console.info(colors.gray(`Processing files ${VERIFY_PROMPTS_ORDER_DESCRIPTIONS[normalizedOptions.order]}`));
|
|
76121
76307
|
}
|
|
76122
76308
|
if (normalizedOptions.ignore.length > 0) {
|
|
76123
76309
|
console.info(colors.gray(`Ignoring candidates matching: ${normalizedOptions.ignore.join(', ')}`));
|
|
@@ -76174,7 +76360,7 @@ async function $commitVerificationOutcome(gitSync, outcome) {
|
|
|
76174
76360
|
*/
|
|
76175
76361
|
function parseVerifyPromptsCliOptions(args) {
|
|
76176
76362
|
return {
|
|
76177
|
-
|
|
76363
|
+
order: parseVerifyPromptsOrder(readStringOption(args, '--order')),
|
|
76178
76364
|
ignore: readRepeatableStringOption(args, '--ignore'),
|
|
76179
76365
|
gitSync: {
|
|
76180
76366
|
isCommitEnabled: args.includes('--commit'),
|
|
@@ -76189,10 +76375,7 @@ function parseVerifyPromptsCliOptions(args) {
|
|
|
76189
76375
|
async function loadPromptFilesForVerification(options) {
|
|
76190
76376
|
const loadedPromptFiles = await loadPromptFiles(PROMPTS_DIR);
|
|
76191
76377
|
const { promptFiles, ignoredPromptFiles } = partitionPromptFilesByIgnore(loadedPromptFiles, options.ignore);
|
|
76192
|
-
|
|
76193
|
-
promptFiles.reverse();
|
|
76194
|
-
}
|
|
76195
|
-
return { promptFiles, ignoredPromptFiles };
|
|
76378
|
+
return { promptFiles: $orderPromptFiles(promptFiles, options.order), ignoredPromptFiles };
|
|
76196
76379
|
}
|
|
76197
76380
|
/**
|
|
76198
76381
|
* Splits prompt files into files that should be verified now and files ignored for this run.
|
|
@@ -76234,7 +76417,7 @@ async function prepareArchiveDirectory() {
|
|
|
76234
76417
|
function normalizeVerifyPromptsOptions(options) {
|
|
76235
76418
|
var _a, _b, _c;
|
|
76236
76419
|
return {
|
|
76237
|
-
|
|
76420
|
+
order: (_a = options.order) !== null && _a !== void 0 ? _a : DEFAULT_VERIFY_PROMPTS_ORDER,
|
|
76238
76421
|
ignore: normalizeIgnoreValues((_b = options.ignore) !== null && _b !== void 0 ? _b : []),
|
|
76239
76422
|
gitSync: (_c = options.gitSync) !== null && _c !== void 0 ? _c : DISABLED_CODER_GIT_SYNC_OPTIONS,
|
|
76240
76423
|
};
|
|
@@ -76259,6 +76442,13 @@ function normalizeIgnoreValues(ignoreValues) {
|
|
|
76259
76442
|
}
|
|
76260
76443
|
return normalizedIgnoreValues;
|
|
76261
76444
|
}
|
|
76445
|
+
/**
|
|
76446
|
+
* Reads one single-value string option from raw CLI arguments, keeping the last occurrence.
|
|
76447
|
+
*/
|
|
76448
|
+
function readStringOption(args, flag) {
|
|
76449
|
+
const values = readRepeatableStringOption(args, flag);
|
|
76450
|
+
return values[values.length - 1];
|
|
76451
|
+
}
|
|
76262
76452
|
/**
|
|
76263
76453
|
* Reads one repeatable string option from raw CLI arguments.
|
|
76264
76454
|
*/
|
|
@@ -76320,8 +76510,9 @@ function displayTopLevelFileList(promptFiles) {
|
|
|
76320
76510
|
for (const file of promptFiles) {
|
|
76321
76511
|
const doneCount = file.sections.filter((section) => section.status === 'done').length;
|
|
76322
76512
|
const todoCount = file.sections.filter((section) => section.status === 'todo').length;
|
|
76513
|
+
const inProgressCount = file.sections.filter((section) => section.status === 'in-progress').length;
|
|
76323
76514
|
const notReadyCount = file.sections.filter((section) => section.status === 'not-ready').length;
|
|
76324
|
-
const needsVerification = file.sections.length > 0 &&
|
|
76515
|
+
const needsVerification = file.sections.length > 0 && !file.sections.some(isPromptSectionUnfinished) && doneCount > 0;
|
|
76325
76516
|
const statusParts = [];
|
|
76326
76517
|
if (needsVerification) {
|
|
76327
76518
|
statusParts.push(colors.cyan.bold(`🔍 ${doneCount} done [x] - NEEDS VERIFICATION`));
|
|
@@ -76330,6 +76521,9 @@ function displayTopLevelFileList(promptFiles) {
|
|
|
76330
76521
|
if (todoCount > 0) {
|
|
76331
76522
|
statusParts.push(colors.yellow(`${todoCount} todo [ ]`));
|
|
76332
76523
|
}
|
|
76524
|
+
if (inProgressCount > 0) {
|
|
76525
|
+
statusParts.push(colors.magenta(`${inProgressCount} in-progress [^]`));
|
|
76526
|
+
}
|
|
76333
76527
|
if (doneCount > 0) {
|
|
76334
76528
|
statusParts.push(colors.green(`${doneCount} done [x]`));
|
|
76335
76529
|
}
|
|
@@ -76345,7 +76539,7 @@ function displayTopLevelFileList(promptFiles) {
|
|
|
76345
76539
|
console.info(colors.gray('Goal: verify all done prompts, then process remaining todo prompts.'));
|
|
76346
76540
|
}
|
|
76347
76541
|
/**
|
|
76348
|
-
* Finds the first file where at least one prompt is marked as done [x] and no prompts are todo [ ].
|
|
76542
|
+
* Finds the first file where at least one prompt is marked as done [x] and no prompts are todo [ ] or in-progress [^].
|
|
76349
76543
|
* Completely ignores not-ready prompts like [-], [.], [?], etc.
|
|
76350
76544
|
* Also excludes files that have been skipped in this session.
|
|
76351
76545
|
*/
|
|
@@ -76358,10 +76552,10 @@ function findFileWithAllDonePrompts(promptFiles, skippedFiles) {
|
|
|
76358
76552
|
if (skippedFiles.has(file.path)) {
|
|
76359
76553
|
return false;
|
|
76360
76554
|
}
|
|
76361
|
-
// File is ready for verification if it has at least one done prompt and no
|
|
76362
|
-
const
|
|
76555
|
+
// File is ready for verification if it has at least one done prompt and no unfinished prompts
|
|
76556
|
+
const hasUnfinishedPrompts = file.sections.some(isPromptSectionUnfinished);
|
|
76363
76557
|
const hasDonePrompts = file.sections.some((section) => section.status === 'done');
|
|
76364
|
-
return !
|
|
76558
|
+
return !hasUnfinishedPrompts && hasDonePrompts;
|
|
76365
76559
|
});
|
|
76366
76560
|
}
|
|
76367
76561
|
/**
|
|
@@ -76467,11 +76661,11 @@ function displayPromptOverview(promptFiles) {
|
|
|
76467
76661
|
const filesNeedingVerification = promptFiles.filter((file) => {
|
|
76468
76662
|
if (file.sections.length === 0)
|
|
76469
76663
|
return false;
|
|
76470
|
-
const
|
|
76664
|
+
const hasUnfinished = file.sections.some(isPromptSectionUnfinished);
|
|
76471
76665
|
const hasDone = file.sections.some((section) => section.status === 'done');
|
|
76472
|
-
return !
|
|
76666
|
+
return !hasUnfinished && hasDone;
|
|
76473
76667
|
});
|
|
76474
|
-
const pendingFiles = promptFiles.filter((file) => file.sections.some(
|
|
76668
|
+
const pendingFiles = promptFiles.filter((file) => file.sections.some(isPromptSectionUnfinished));
|
|
76475
76669
|
if (filesNeedingVerification.length) {
|
|
76476
76670
|
const formattedNames = formatPendingFileNames(filesNeedingVerification.map((file) => file.name));
|
|
76477
76671
|
console.info(colors.cyan(` 🔍 Files needing verification (${filesNeedingVerification.length}): ${formattedNames}`));
|