@promptbook/cli 0.112.0-43 → 0.112.0-44

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 (33) hide show
  1. package/esm/index.es.js +481 -111
  2. package/esm/index.es.js.map +1 -1
  3. package/esm/scripts/run-codex-prompts/common/runGoScript/$runGoScript.d.ts +1 -1
  4. package/esm/scripts/run-codex-prompts/common/runGoScript/$runGoScriptUntilMarkerIdle.d.ts +1 -1
  5. package/esm/scripts/run-codex-prompts/common/runGoScript/$runGoScriptWithOutput.d.ts +1 -1
  6. package/esm/scripts/run-codex-prompts/common/runGoScript/PromptRoundArtifacts.d.ts +35 -0
  7. package/esm/scripts/run-codex-prompts/common/runGoScript/buildScriptLogPath.d.ts +4 -0
  8. package/esm/scripts/run-codex-prompts/common/runGoScript/runBashScriptWithOutput.d.ts +5 -0
  9. package/esm/scripts/run-codex-prompts/common/runGoScript/scriptExecutionLog.d.ts +28 -0
  10. package/esm/scripts/run-codex-prompts/common/runGoScript/withPromptRuntimeLog.d.ts +5 -0
  11. package/esm/scripts/run-codex-prompts/common/runGoScript/withTempScript.d.ts +1 -1
  12. package/esm/scripts/run-codex-prompts/testing/runPromptTestCommand.d.ts +1 -0
  13. package/esm/src/book-2.0/agent-source/AgentBasicInformation.d.ts +2 -1
  14. package/esm/src/book-2.0/agent-source/TeammateProfileResolver.d.ts +2 -1
  15. package/esm/src/commitments/PERSONA/PERSONA.d.ts +7 -0
  16. package/esm/src/version.d.ts +1 -1
  17. package/package.json +1 -1
  18. package/umd/index.umd.js +480 -110
  19. package/umd/index.umd.js.map +1 -1
  20. package/umd/scripts/run-codex-prompts/common/runGoScript/$runGoScript.d.ts +1 -1
  21. package/umd/scripts/run-codex-prompts/common/runGoScript/$runGoScriptUntilMarkerIdle.d.ts +1 -1
  22. package/umd/scripts/run-codex-prompts/common/runGoScript/$runGoScriptWithOutput.d.ts +1 -1
  23. package/umd/scripts/run-codex-prompts/common/runGoScript/PromptRoundArtifacts.d.ts +35 -0
  24. package/umd/scripts/run-codex-prompts/common/runGoScript/buildScriptLogPath.d.ts +4 -0
  25. package/umd/scripts/run-codex-prompts/common/runGoScript/runBashScriptWithOutput.d.ts +5 -0
  26. package/umd/scripts/run-codex-prompts/common/runGoScript/scriptExecutionLog.d.ts +28 -0
  27. package/umd/scripts/run-codex-prompts/common/runGoScript/withPromptRuntimeLog.d.ts +5 -0
  28. package/umd/scripts/run-codex-prompts/common/runGoScript/withTempScript.d.ts +1 -1
  29. package/umd/scripts/run-codex-prompts/testing/runPromptTestCommand.d.ts +1 -0
  30. package/umd/src/book-2.0/agent-source/AgentBasicInformation.d.ts +2 -1
  31. package/umd/src/book-2.0/agent-source/TeammateProfileResolver.d.ts +2 -1
  32. package/umd/src/commitments/PERSONA/PERSONA.d.ts +7 -0
  33. package/umd/src/version.d.ts +1 -1
package/umd/index.umd.js CHANGED
@@ -60,7 +60,7 @@
60
60
  * @generated
61
61
  * @see https://github.com/webgptorg/promptbook
62
62
  */
63
- const PROMPTBOOK_ENGINE_VERSION = '0.112.0-43';
63
+ const PROMPTBOOK_ENGINE_VERSION = '0.112.0-44';
64
64
  /**
65
65
  * TODO: string_promptbook_version should be constrained to the all versions of Promptbook engine
66
66
  * Note: [💞] Ignore a discrepancy between file name and entity name
@@ -3027,12 +3027,13 @@
3027
3027
  command.option('--no-wait', 'Skip user prompts between processing');
3028
3028
  command.option('--ignore-git-changes', 'Skip clean working tree check before running prompts', false);
3029
3029
  command.option('--allow-credits', 'Allow OpenAI Codex runner to spend credits when rate limits are exhausted', false);
3030
+ command.option('--preserve-logs', 'Keep generated runner shells and runtime logs after successful prompt rounds; failures keep them automatically', false);
3030
3031
  command.option('--no-normalize-line-endings', 'Disable automatic LF normalization for files changed in each coding round');
3031
3032
  command.option('--auto-push', 'Automatically git push after each commit', false);
3032
3033
  command.option('--auto-migrate', 'Run testing-server database migrations automatically after each successfully processed prompt');
3033
3034
  command.option('--allow-destructive-auto-migrate', 'Allow auto-migrate even when heuristic SQL safety check flags destructive pending migrations');
3034
3035
  command.action(handleActionErrors(async (cliOptions) => {
3035
- const { dryRun, agent, model, context, test, thinkingLevel, priority, wait, ignoreGitChanges, allowCredits, normalizeLineEndings, autoMigrate, allowDestructiveAutoMigrate, autoPush, } = cliOptions;
3036
+ const { dryRun, agent, model, context, test, thinkingLevel, priority, wait, ignoreGitChanges, allowCredits, preserveLogs, normalizeLineEndings, autoMigrate, allowDestructiveAutoMigrate, autoPush, } = cliOptions;
3036
3037
  const testCommand = normalizeCommandOptionValue(test);
3037
3038
  // Validate agent
3038
3039
  let agentName = undefined;
@@ -3067,6 +3068,7 @@
3067
3068
  priority,
3068
3069
  normalizeLineEndings,
3069
3070
  allowCredits,
3071
+ preserveLogs,
3070
3072
  autoMigrate,
3071
3073
  allowDestructiveAutoMigrate,
3072
3074
  autoPush,
@@ -18951,7 +18953,7 @@
18951
18953
  * Short one-line description of GOAL.
18952
18954
  */
18953
18955
  get description() {
18954
- return 'Define main **goals** the AI assistant should achieve, with later goals having higher priority.';
18956
+ return 'Define the effective agent **goal**; when multiple goals exist, only the last one stays effective.';
18955
18957
  }
18956
18958
  /**
18957
18959
  * Icon for this commitment.
@@ -18966,12 +18968,14 @@
18966
18968
  return _spaceTrim.spaceTrim(`
18967
18969
  # ${this.type}
18968
18970
 
18969
- Defines the main goal which should be achieved by the AI assistant. There can be multiple goals, and later goals are more important than earlier goals.
18971
+ Defines the main goal which should be achieved by the AI assistant.
18972
+ There can be multiple goals in source, but after inheritance/source rewriting only the last \`GOAL\` /\`GOALS\` remains effective.
18970
18973
 
18971
18974
  ## Key aspects
18972
18975
 
18973
18976
  - Both terms work identically and can be used interchangeably.
18974
- - Later goals have higher priority and can override earlier goals.
18977
+ - Later goals overwrite earlier goals.
18978
+ - The public agent profile text is derived from the last goal.
18975
18979
  - Goals provide clear direction and purpose for the agent's responses.
18976
18980
  - Goals influence decision-making and response prioritization.
18977
18981
 
@@ -18984,9 +18988,7 @@
18984
18988
  \`\`\`book
18985
18989
  Customer Support Agent
18986
18990
 
18987
- PERSONA You are a helpful customer support representative
18988
18991
  GOAL Resolve customer issues quickly and efficiently
18989
- GOAL Maintain high customer satisfaction scores
18990
18992
  GOAL Always follow company policies and procedures
18991
18993
  RULE Be polite and professional at all times
18992
18994
  \`\`\`
@@ -18994,9 +18996,7 @@
18994
18996
  \`\`\`book
18995
18997
  Educational Assistant
18996
18998
 
18997
- PERSONA You are an educational assistant specializing in mathematics
18998
18999
  GOAL Help students understand mathematical concepts clearly
18999
- GOAL Encourage critical thinking and problem-solving skills
19000
19000
  GOAL Ensure all explanations are age-appropriate and accessible
19001
19001
  STYLE Use simple language and provide step-by-step explanations
19002
19002
  \`\`\`
@@ -19004,9 +19004,7 @@
19004
19004
  \`\`\`book
19005
19005
  Safety-First Assistant
19006
19006
 
19007
- PERSONA You are a general-purpose AI assistant
19008
19007
  GOAL Be helpful and informative in all interactions
19009
- GOAL Provide accurate and reliable information
19010
19008
  GOAL Always prioritize user safety and ethical guidelines
19011
19009
  RULE Never provide harmful or dangerous advice
19012
19010
  \`\`\`
@@ -21865,7 +21863,16 @@
21865
21863
  * Short one-line description of PERSONA.
21866
21864
  */
21867
21865
  get description() {
21868
- return 'Define who the agent is: background, expertise, and personality.';
21866
+ return 'Deprecated legacy profile commitment. Prefer `GOAL` for agent profile text and inheritance-safe rewrites.';
21867
+ }
21868
+ /**
21869
+ * Optional UI/docs-only deprecation metadata.
21870
+ */
21871
+ get deprecation() {
21872
+ return {
21873
+ message: 'Use `GOAL` for agent profile text and inheritance-safe rewrites.',
21874
+ replacedBy: ['GOAL'],
21875
+ };
21869
21876
  }
21870
21877
  /**
21871
21878
  * Icon for this commitment.
@@ -21880,16 +21887,24 @@
21880
21887
  return _spaceTrim.spaceTrim(`
21881
21888
  # ${this.type}
21882
21889
 
21883
- Defines who the agent is, their background, expertise, and personality traits.
21890
+ Deprecated legacy commitment that defines who the agent is, their background, expertise, and personality traits.
21884
21891
 
21885
- ## Key aspects
21892
+ ## Migration
21886
21893
 
21887
- - Multiple \`PERSONA\` and \`PERSONAE\` commitments are merged together.
21888
- - Both terms work identically and can be used interchangeably.
21889
- - If they are in conflict, the last one takes precedence.
21890
- - You can write persona content in multiple lines.
21894
+ - Existing \`${this.type}\` books still parse and compile.
21895
+ - New books should prefer \`GOAL\`.
21896
+ - Agent profile rendering now prefers the last \`GOAL\` and only falls back to \`${this.type}\` when no goal exists.
21897
+ - Runtime compilation keeps the legacy multi-\`PERSONA\` merge behavior for backward compatibility.
21891
21898
 
21892
- ## Examples
21899
+ ## Preferred replacement
21900
+
21901
+ \`\`\`book
21902
+ Programming Assistant
21903
+
21904
+ GOAL Help the user solve programming problems with practical TypeScript and React guidance.
21905
+ \`\`\`
21906
+
21907
+ ## Legacy compatibility example
21893
21908
 
21894
21909
  \`\`\`book
21895
21910
  Programming Assistant
@@ -22654,7 +22669,7 @@
22654
22669
  \`\`\`book
22655
22670
  Legal Assistant
22656
22671
 
22657
- PERSONA An expert software developer
22672
+ GOAL Get expert software-development advice from the teammate when legal discussion needs technical context.
22658
22673
  TEAM You can talk with http://localhost:4440/agents/GMw67JN8TXxN7y to discuss the legal aspects.
22659
22674
  \`\`\`
22660
22675
  `);
@@ -41400,6 +41415,15 @@
41400
41415
  * @private internal constant of `createAgentModelRequirementsWithCommitments`
41401
41416
  */
41402
41417
  const DELETE_COMMITMENT_TYPES = new Set(['DELETE', 'CANCEL', 'DISCARD', 'REMOVE']);
41418
+ /**
41419
+ * Commitments whose earlier occurrences are overwritten by the last occurrence in source order.
41420
+ *
41421
+ * @private internal constant of `createAgentModelRequirementsWithCommitments`
41422
+ */
41423
+ const OVERWRITTEN_COMMITMENT_GROUP_BY_TYPE = new Map([
41424
+ ['GOAL', 'GOAL'],
41425
+ ['GOALS', 'GOAL'],
41426
+ ]);
41403
41427
  /**
41404
41428
  * Regex pattern matching markdown horizontal lines that should not be copied into the final system message.
41405
41429
  *
@@ -41450,7 +41474,7 @@
41450
41474
  */
41451
41475
  async function createAgentModelRequirementsWithCommitments(agentSource, modelName, options) {
41452
41476
  const parseResult = parseAgentSourceWithCommitments(agentSource);
41453
- const filteredCommitments = filterDeletedCommitments(parseResult.commitments);
41477
+ const filteredCommitments = filterOverwrittenCommitments(filterDeletedCommitments(parseResult.commitments));
41454
41478
  let requirements = createInitialAgentModelRequirements(parseResult.agentName, modelName);
41455
41479
  requirements = await applyCommitmentsToRequirements(requirements, filteredCommitments, options);
41456
41480
  requirements = aggregateUseCommitmentSystemMessages(requirements, filteredCommitments);
@@ -41461,6 +41485,35 @@
41461
41485
  requirements = await applyPendingInlineKnowledgeSources(requirements, options === null || options === void 0 ? void 0 : options.inlineKnowledgeSourceUploader);
41462
41486
  return finalizeRequirements(requirements);
41463
41487
  }
41488
+ /**
41489
+ * Removes earlier commitments that are overwritten by later commitments of the same semantic group.
41490
+ *
41491
+ * This currently keeps only the last `GOAL` / `GOALS` commitment so inheritance rewrites
41492
+ * and multi-goal sources expose one effective goal to the runtime.
41493
+ *
41494
+ * @param commitments - Parsed commitments after DELETE-like filtering.
41495
+ * @returns Commitments with overwritten entries removed while preserving source order.
41496
+ *
41497
+ * @private internal utility of `createAgentModelRequirementsWithCommitments`
41498
+ */
41499
+ function filterOverwrittenCommitments(commitments) {
41500
+ const seenOverwriteGroups = new Set();
41501
+ const keptCommitments = [];
41502
+ for (let index = commitments.length - 1; index >= 0; index--) {
41503
+ const commitment = commitments[index];
41504
+ const overwriteGroup = OVERWRITTEN_COMMITMENT_GROUP_BY_TYPE.get(commitment.type);
41505
+ if (!overwriteGroup) {
41506
+ keptCommitments.push(commitment);
41507
+ continue;
41508
+ }
41509
+ if (seenOverwriteGroups.has(overwriteGroup)) {
41510
+ continue;
41511
+ }
41512
+ seenOverwriteGroups.add(overwriteGroup);
41513
+ keptCommitments.push(commitment);
41514
+ }
41515
+ return keptCommitments.reverse();
41516
+ }
41464
41517
  /**
41465
41518
  * Creates the initial requirements object with the parsed agent name stored in metadata and an optional model override.
41466
41519
  *
@@ -42103,7 +42156,7 @@
42103
42156
  function parseAgentSource(agentSource) {
42104
42157
  const parseResult = parseAgentSourceWithCommitments(agentSource);
42105
42158
  const resolvedAgentName = parseResult.agentName || createDefaultAgentName(agentSource);
42106
- const personaDescription = extractPersonaDescription(parseResult.commitments);
42159
+ const personaDescription = extractAgentProfileText(parseResult.commitments);
42107
42160
  const initialMessage = extractInitialMessage(parseResult.commitments);
42108
42161
  const parsedProfile = extractParsedAgentProfile(parseResult.commitments);
42109
42162
  ensureMetaFullname(parsedProfile.meta, resolvedAgentName);
@@ -42207,25 +42260,33 @@
42207
42260
  */
42208
42261
  const LOCAL_AGENT_REFERENCE_PREFIXES = ['./', '../', '/'];
42209
42262
  /**
42210
- * Builds the combined persona description from PERSONA commitments.
42263
+ * Resolves the public agent profile text from the last GOAL/GOALS commitment,
42264
+ * falling back to the deprecated PERSONA/PERSONAE commitments when no goal exists.
42211
42265
  *
42212
42266
  * @private internal utility of `parseAgentSource`
42213
42267
  */
42214
- function extractPersonaDescription(commitments) {
42215
- let personaDescription = null;
42268
+ function extractAgentProfileText(commitments) {
42269
+ let goalDescription = '';
42270
+ let hasGoalDescription = false;
42271
+ let personaDescription = '';
42272
+ let hasPersonaDescription = false;
42216
42273
  for (const commitment of commitments) {
42217
- if (commitment.type !== 'PERSONA') {
42218
- continue;
42274
+ if (commitment.type === 'GOAL' || commitment.type === 'GOALS') {
42275
+ goalDescription = commitment.content;
42276
+ hasGoalDescription = true;
42219
42277
  }
42220
- if (personaDescription === null) {
42221
- personaDescription = '';
42278
+ if (commitment.type === 'PERSONA' || commitment.type === 'PERSONAE') {
42279
+ personaDescription = commitment.content;
42280
+ hasPersonaDescription = true;
42222
42281
  }
42223
- else {
42224
- personaDescription += `\n\n${personaDescription}`;
42225
- }
42226
- personaDescription += commitment.content;
42227
42282
  }
42228
- return personaDescription;
42283
+ if (hasGoalDescription) {
42284
+ return goalDescription;
42285
+ }
42286
+ if (hasPersonaDescription) {
42287
+ return personaDescription;
42288
+ }
42289
+ return null;
42229
42290
  }
42230
42291
  /**
42231
42292
  * Resolves the last INITIAL MESSAGE commitment, which is the public initial-message value.
@@ -42712,7 +42773,7 @@
42712
42773
  * Selects the best model using the preparePersona function
42713
42774
  * This directly uses preparePersona to ensure DRY principle
42714
42775
  *
42715
- * @param agentSource The agent source to derive persona description from
42776
+ * @param agentSource The agent source to derive effective profile text from
42716
42777
  * @param llmTools LLM tools for preparing persona
42717
42778
  * @returns The name of the best selected model
42718
42779
  *
@@ -42720,9 +42781,9 @@
42720
42781
  */
42721
42782
  async function selectBestModelUsingPersona(agentSource, llmTools) {
42722
42783
  var _a;
42723
- // Parse agent source to get persona description
42784
+ // Parse agent source to get the effective profile description
42724
42785
  const { agentName, personaDescription } = parseAgentSource(agentSource);
42725
- // Use agent name as fallback if no persona description is available
42786
+ // Use agent name as fallback if no profile description is available
42726
42787
  const description = personaDescription || agentName || 'AI Agent';
42727
42788
  try {
42728
42789
  // Use preparePersona directly
@@ -44184,7 +44245,7 @@
44184
44245
  /**
44185
44246
  * CLI usage text for this script.
44186
44247
  */
44187
- const USAGE = 'Usage: run-codex-prompts [--dry-run] [--agent <agent-name>] [--model <model>] [--context <context-or-file>] [--test <test-command...>] [--thinking-level <thinking-level>] [--priority <minimum-priority>] [--allow-credits] [--auto-migrate] [--allow-destructive-auto-migrate] [--no-wait] [--ignore-git-changes] [--no-normalize-line-endings] [--auto-push]';
44248
+ const USAGE = 'Usage: run-codex-prompts [--dry-run] [--agent <agent-name>] [--model <model>] [--context <context-or-file>] [--test <test-command...>] [--thinking-level <thinking-level>] [--priority <minimum-priority>] [--allow-credits] [--preserve-logs] [--auto-migrate] [--allow-destructive-auto-migrate] [--no-wait] [--ignore-git-changes] [--no-normalize-line-endings] [--auto-push]';
44188
44249
  /**
44189
44250
  * Top-level flags supported by this command.
44190
44251
  */
@@ -44197,6 +44258,7 @@
44197
44258
  '--thinking-level',
44198
44259
  '--priority',
44199
44260
  '--allow-credits',
44261
+ '--preserve-logs',
44200
44262
  '--auto-migrate',
44201
44263
  '--allow-destructive-auto-migrate',
44202
44264
  '--no-wait',
@@ -44233,6 +44295,7 @@
44233
44295
  const ignoreGitChanges = args.includes('--ignore-git-changes');
44234
44296
  const normalizeLineEndings = !args.includes('--no-normalize-line-endings');
44235
44297
  const allowCredits = args.includes('--allow-credits');
44298
+ const preserveLogs = args.includes('--preserve-logs');
44236
44299
  const autoMigrate = args.includes('--auto-migrate');
44237
44300
  const allowDestructiveAutoMigrate = args.includes('--allow-destructive-auto-migrate');
44238
44301
  const autoPush = args.includes('--auto-push');
@@ -44258,6 +44321,7 @@
44258
44321
  ignoreGitChanges,
44259
44322
  normalizeLineEndings,
44260
44323
  allowCredits,
44324
+ preserveLogs,
44261
44325
  autoMigrate,
44262
44326
  allowDestructiveAutoMigrate,
44263
44327
  autoPush,
@@ -44751,6 +44815,91 @@
44751
44815
  return promises.readFile(contextPath, 'utf-8');
44752
44816
  }
44753
44817
 
44818
+ /**
44819
+ * Builds the temporary live runtime log path for one prompt script and its sibling test script.
44820
+ */
44821
+ function buildScriptLogPath(scriptPath) {
44822
+ const basePath = scriptPath.replace(/\.test\.sh$/iu, '').replace(/\.sh$/iu, '');
44823
+ return `${basePath}.log.txt`;
44824
+ }
44825
+
44826
+ /**
44827
+ * Runs one prompt-processing round with a dedicated temporary runtime log file and optionally defers cleanup to the round tracker.
44828
+ */
44829
+ async function withPromptRuntimeLog(scriptPath, handler, promptRoundArtifacts) {
44830
+ const logPath = buildScriptLogPath(scriptPath);
44831
+ await promises.unlink(logPath).catch(() => undefined);
44832
+ promptRoundArtifacts === null || promptRoundArtifacts === void 0 ? void 0 : promptRoundArtifacts.track(logPath, 'runtime-log');
44833
+ try {
44834
+ return await handler(logPath);
44835
+ }
44836
+ finally {
44837
+ if (!promptRoundArtifacts) {
44838
+ await promises.unlink(logPath).catch(() => undefined);
44839
+ }
44840
+ }
44841
+ }
44842
+
44843
+ /**
44844
+ * Shared artifact kinds preserved for debugging when a prompt round fails.
44845
+ */
44846
+ const FAILURE_PRESERVED_ARTIFACT_KINDS = new Set(['runner-script', 'runtime-log']);
44847
+ /**
44848
+ * Shared artifact kinds preserved after a successful prompt round when explicitly requested.
44849
+ */
44850
+ const SUCCESS_PRESERVED_ARTIFACT_KINDS = new Set(['runner-script', 'runtime-log']);
44851
+ /**
44852
+ * Empty preserved-artifact set used for successful rounds without `--preserve-logs`.
44853
+ */
44854
+ const NO_PRESERVED_ARTIFACT_KINDS = new Set();
44855
+ /**
44856
+ * Tracks temporary prompt-round artifacts and deletes only those not preserved for the final round outcome.
44857
+ */
44858
+ class PromptRoundArtifacts {
44859
+ /**
44860
+ * Creates a new prompt-round artifact tracker.
44861
+ */
44862
+ constructor(preservedArtifactKindsByOutcome) {
44863
+ this.preservedArtifactKindsByOutcome = preservedArtifactKindsByOutcome;
44864
+ this.trackedArtifacts = new Map();
44865
+ }
44866
+ /**
44867
+ * Registers one temporary artifact for round-final cleanup.
44868
+ */
44869
+ track(path, kind) {
44870
+ this.trackedArtifacts.set(path, kind);
44871
+ }
44872
+ /**
44873
+ * Cleans up all tracked artifacts that should not survive the final round outcome.
44874
+ */
44875
+ async cleanup(outcome) {
44876
+ const preservedArtifactKinds = this.preservedArtifactKindsByOutcome[outcome];
44877
+ const trackedArtifacts = [...this.trackedArtifacts.entries()];
44878
+ this.trackedArtifacts.clear();
44879
+ await Promise.all(trackedArtifacts.map(async ([path, kind]) => {
44880
+ if (preservedArtifactKinds.has(kind)) {
44881
+ return;
44882
+ }
44883
+ await promises.unlink(path).catch(() => undefined);
44884
+ }));
44885
+ }
44886
+ }
44887
+ /**
44888
+ * Creates the default artifact-retention policy used by `ptbk coder run`.
44889
+ */
44890
+ function createCoderRunPromptRoundArtifacts(isPreserveLogs) {
44891
+ return new PromptRoundArtifacts({
44892
+ success: isPreserveLogs ? SUCCESS_PRESERVED_ARTIFACT_KINDS : NO_PRESERVED_ARTIFACT_KINDS,
44893
+ failure: FAILURE_PRESERVED_ARTIFACT_KINDS,
44894
+ });
44895
+ }
44896
+ /**
44897
+ * Derives the tracked artifact kind from one temporary shell path.
44898
+ */
44899
+ function getPromptRoundArtifactKindFromScriptPath(scriptPath) {
44900
+ return scriptPath.toLowerCase().endsWith('.test.sh') ? 'test-script' : 'runner-script';
44901
+ }
44902
+
44754
44903
  /**
44755
44904
  * Waits for the user to press Enter before continuing.
44756
44905
  */
@@ -47054,25 +47203,186 @@
47054
47203
  }
47055
47204
 
47056
47205
  /**
47057
- * Creates a temporary script file, runs a handler, and ensures cleanup.
47206
+ * Environment variable read by the shell wrapper to tee live output into the temporary runtime log file.
47207
+ */
47208
+ const PTBK_CODER_LOG_FILE_ENV_NAME = 'PTBK_CODER_LOG_FILE';
47209
+ /**
47210
+ * Small bash wrapper that preserves stdout/stderr streams while teeing both into the runtime log file.
47211
+ */
47212
+ const LOGGED_BASH_WRAPPER_COMMAND = `
47213
+ if [ -n "\${${PTBK_CODER_LOG_FILE_ENV_NAME}:-}" ]; then
47214
+ exec > >(tee -a "\$${PTBK_CODER_LOG_FILE_ENV_NAME}") 2> >(tee -a "\$${PTBK_CODER_LOG_FILE_ENV_NAME}" >&2)
47215
+ fi
47216
+ bash "$1"
47217
+ `.trim();
47218
+ /**
47219
+ * Shapes one bash invocation that optionally mirrors live script output into a temporary log file.
47220
+ */
47221
+ function buildLoggedBashExecution(scriptPath, logPath) {
47222
+ return {
47223
+ args: ['-lc', LOGGED_BASH_WRAPPER_COMMAND, 'ptbk-coder-temp-script', toPosixPath(scriptPath)],
47224
+ env: logPath ? { [PTBK_CODER_LOG_FILE_ENV_NAME]: toPosixPath(logPath) } : undefined,
47225
+ };
47226
+ }
47227
+ /**
47228
+ * Appends one execution-start section with the raw script input before the shell begins producing output.
47229
+ */
47230
+ async function appendScriptExecutionLogStart({ scriptPath, scriptContent, logPath, }) {
47231
+ if (!logPath) {
47232
+ return;
47233
+ }
47234
+ await promises.mkdir(path.dirname(logPath), { recursive: true });
47235
+ const scriptKind = describeTempScriptKind(scriptPath);
47236
+ const normalizedInput = scriptContent.replace(/\r\n/g, '\n').trimEnd();
47237
+ const logSection = [
47238
+ `=== ${scriptKind} started at ${new Date().toISOString()} ===`,
47239
+ `Script path: ${toPosixPath(scriptPath)}`,
47240
+ '',
47241
+ '--- raw input ---',
47242
+ normalizedInput,
47243
+ '',
47244
+ '--- raw output ---',
47245
+ '',
47246
+ ].join('\n');
47247
+ await promises.appendFile(logPath, `${logSection}\n`, 'utf-8');
47248
+ }
47249
+ /**
47250
+ * Appends one execution-finish section after the shell settles.
47251
+ */
47252
+ async function appendScriptExecutionLogFinish({ scriptPath, logPath, status, details, }) {
47253
+ if (!logPath) {
47254
+ return;
47255
+ }
47256
+ const scriptKind = describeTempScriptKind(scriptPath);
47257
+ const logLines = [
47258
+ '',
47259
+ `=== ${scriptKind} finished at ${new Date().toISOString()} ===`,
47260
+ `Status: ${status}`,
47261
+ ];
47262
+ if (details !== undefined) {
47263
+ logLines.push('');
47264
+ logLines.push('--- details ---');
47265
+ logLines.push(formatUnknownErrorDetails(details));
47266
+ }
47267
+ logLines.push('');
47268
+ await promises.appendFile(logPath, `${logLines.join('\n')}\n`, 'utf-8');
47269
+ }
47270
+ /**
47271
+ * Distinguishes prompt-runner and verification temp shells in the shared runtime log.
47272
+ */
47273
+ function describeTempScriptKind(scriptPath) {
47274
+ return scriptPath.toLowerCase().endsWith('.test.sh') ? 'test shell' : 'runner shell';
47275
+ }
47276
+
47277
+ /**
47278
+ * Runs one temporary bash script, optionally mirroring its raw input/output into a live runtime log file.
47279
+ */
47280
+ async function runBashScriptWithOutput(options) {
47281
+ await appendScriptExecutionLogStart(options);
47282
+ const bashExecution = buildLoggedBashExecution(options.scriptPath, options.logPath);
47283
+ const scriptPathPosix = toPosixPath(options.scriptPath);
47284
+ return await new Promise((resolve, reject) => {
47285
+ const commandProcess = child_process.spawn('bash', bashExecution.args, {
47286
+ env: bashExecution.env ? { ...process.env, ...bashExecution.env } : process.env,
47287
+ });
47288
+ let output = '';
47289
+ let settled = false;
47290
+ let isSettling = false;
47291
+ /**
47292
+ * Appends the final log footer before settling.
47293
+ */
47294
+ const finishLog = async (status, details) => {
47295
+ await appendScriptExecutionLogFinish({
47296
+ scriptPath: options.scriptPath,
47297
+ logPath: options.logPath,
47298
+ status,
47299
+ details,
47300
+ });
47301
+ };
47302
+ /**
47303
+ * Ensures the promise settles only once.
47304
+ */
47305
+ const settleOnce = (handler) => {
47306
+ if (settled) {
47307
+ return;
47308
+ }
47309
+ settled = true;
47310
+ handler();
47311
+ };
47312
+ /**
47313
+ * Appends the final log footer and settles the promise exactly once.
47314
+ */
47315
+ const settleWithLog = (status, handler, details) => {
47316
+ if (isSettling || settled) {
47317
+ return;
47318
+ }
47319
+ isSettling = true;
47320
+ void finishLog(status, details).finally(() => {
47321
+ settleOnce(handler);
47322
+ });
47323
+ };
47324
+ commandProcess.stdout.on('data', (stdout) => {
47325
+ const chunk = stdout.toString();
47326
+ output += chunk;
47327
+ console.info(chunk);
47328
+ });
47329
+ commandProcess.stderr.on('data', (stderr) => {
47330
+ const chunk = stderr.toString();
47331
+ output += chunk;
47332
+ if (chunk.trim()) {
47333
+ console.warn(chunk);
47334
+ }
47335
+ });
47336
+ /**
47337
+ * Handles process exit and resolves or rejects accordingly.
47338
+ */
47339
+ const handleExit = (code) => {
47340
+ if (code === 0) {
47341
+ settleWithLog('succeeded', () => resolve(_spaceTrim.spaceTrim(output)));
47342
+ return;
47343
+ }
47344
+ const failure = new Error(_spaceTrim.spaceTrim(output) || `Command "bash ${scriptPathPosix}" exited with code ${code}`);
47345
+ settleWithLog(`failed with exit code ${code !== null && code !== void 0 ? code : 'unknown'}`, () => reject(failure), failure);
47346
+ };
47347
+ commandProcess.on('close', handleExit);
47348
+ commandProcess.on('exit', handleExit);
47349
+ commandProcess.on('disconnect', () => {
47350
+ const failure = new Error(`Command "bash ${scriptPathPosix}" disconnected`);
47351
+ settleWithLog('failed after disconnect', () => reject(failure), failure);
47352
+ });
47353
+ commandProcess.on('error', (error) => {
47354
+ const failure = new Error(`Command "bash ${scriptPathPosix}" failed: ${error.message}`);
47355
+ settleWithLog('failed before completion', () => reject(failure), failure);
47356
+ });
47357
+ });
47358
+ }
47359
+
47360
+ /**
47361
+ * Creates a temporary script file, runs a handler, and either cleans it up immediately or defers cleanup to the round tracker.
47058
47362
  */
47059
47363
  async function withTempScript(options, handler) {
47060
- const { scriptPath, scriptContent } = options;
47364
+ const { scriptPath, scriptContent, promptRoundArtifacts } = options;
47061
47365
  await promises.mkdir(posix.dirname(scriptPath), { recursive: true });
47062
47366
  await promises.writeFile(scriptPath, scriptContent, 'utf-8');
47063
- const result = await handler(scriptPath);
47064
- await promises.unlink(scriptPath).catch(() => undefined);
47065
- return result;
47367
+ promptRoundArtifacts === null || promptRoundArtifacts === void 0 ? void 0 : promptRoundArtifacts.track(scriptPath, getPromptRoundArtifactKindFromScriptPath(scriptPath));
47368
+ try {
47369
+ return await handler(scriptPath);
47370
+ }
47371
+ finally {
47372
+ if (!promptRoundArtifacts) {
47373
+ await promises.unlink(scriptPath).catch(() => undefined);
47374
+ }
47375
+ }
47066
47376
  }
47067
47377
 
47068
47378
  /**
47069
- * Creates a temporary script file, runs it, captures output, and then deletes it.
47379
+ * Creates a temporary script file, runs it, captures output, and cleans it up immediately unless a round tracker defers that cleanup.
47070
47380
  */
47071
47381
  async function $runGoScriptWithOutput(options) {
47072
47382
  return await withTempScript(options, async (scriptPath) => {
47073
- return await $execCommand({
47074
- command: `bash "${toPosixPath(scriptPath)}"`,
47075
- isVerbose: true, // <- Note: Proxy the raw command output to the console
47383
+ return await runBashScriptWithOutput({
47384
+ ...options,
47385
+ scriptPath,
47076
47386
  });
47077
47387
  });
47078
47388
  }
@@ -47168,6 +47478,8 @@
47168
47478
  const output = await $runGoScriptWithOutput({
47169
47479
  scriptPath: options.scriptPath,
47170
47480
  scriptContent,
47481
+ logPath: options.logPath,
47482
+ promptRoundArtifacts: options.promptRoundArtifacts,
47171
47483
  });
47172
47484
  const usage = parseClaudeCodeJsonOutput(output);
47173
47485
  return { usage };
@@ -47175,13 +47487,13 @@
47175
47487
  }
47176
47488
 
47177
47489
  /**
47178
- * Creates a temporary script file, runs it, and then deletes it.
47490
+ * Creates a temporary script file, runs it, and cleans it up immediately unless a round tracker defers that cleanup.
47179
47491
  */
47180
47492
  async function $runGoScript(options) {
47181
47493
  await withTempScript(options, async (scriptPath) => {
47182
- await $execCommand({
47183
- command: `bash "${toPosixPath(scriptPath)}"`,
47184
- isVerbose: true, // <- Note: Proxy the raw command output to the console
47494
+ await runBashScriptWithOutput({
47495
+ ...options,
47496
+ scriptPath,
47185
47497
  });
47186
47498
  });
47187
47499
  }
@@ -47230,6 +47542,8 @@
47230
47542
  await $runGoScript({
47231
47543
  scriptPath: options.scriptPath,
47232
47544
  scriptContent,
47545
+ logPath: options.logPath,
47546
+ promptRoundArtifacts: options.promptRoundArtifacts,
47233
47547
  });
47234
47548
  return { usage: UNCERTAIN_USAGE };
47235
47549
  }
@@ -47353,6 +47667,8 @@
47353
47667
  const output = await $runGoScriptWithOutput({
47354
47668
  scriptPath: options.scriptPath,
47355
47669
  scriptContent,
47670
+ logPath: options.logPath,
47671
+ promptRoundArtifacts: options.promptRoundArtifacts,
47356
47672
  });
47357
47673
  const usage = parseGeminiUsageFromOutput(output, options.prompt, this.options.model);
47358
47674
  return { usage };
@@ -47408,6 +47724,8 @@
47408
47724
  await $runGoScript({
47409
47725
  scriptPath: options.scriptPath,
47410
47726
  scriptContent,
47727
+ logPath: options.logPath,
47728
+ promptRoundArtifacts: options.promptRoundArtifacts,
47411
47729
  });
47412
47730
  return { usage: UNCERTAIN_USAGE };
47413
47731
  }
@@ -47444,14 +47762,30 @@
47444
47762
  async function runScriptUntilMarkerIdle(options) {
47445
47763
  const { scriptPath, completionLineMatcher, idleTimeoutMs } = options;
47446
47764
  const scriptPathPosix = toPosixPath(scriptPath);
47765
+ await appendScriptExecutionLogStart(options);
47766
+ const bashExecution = buildLoggedBashExecution(scriptPath, options.logPath);
47447
47767
  return await new Promise((resolve, reject) => {
47448
- const commandProcess = child_process.spawn('bash', [scriptPathPosix], { env: process.env });
47768
+ const commandProcess = child_process.spawn('bash', bashExecution.args, {
47769
+ env: bashExecution.env ? { ...process.env, ...bashExecution.env } : process.env,
47770
+ });
47449
47771
  let stdoutBuffer = '';
47450
47772
  let stderrBuffer = '';
47451
47773
  let fullOutput = '';
47452
47774
  let markerSeen = false;
47453
47775
  let idleTimer;
47454
47776
  let settled = false;
47777
+ let isSettling = false;
47778
+ /**
47779
+ * Appends the final log footer before settling.
47780
+ */
47781
+ const finishLog = async (status, details) => {
47782
+ await appendScriptExecutionLogFinish({
47783
+ scriptPath,
47784
+ logPath: options.logPath,
47785
+ status,
47786
+ details,
47787
+ });
47788
+ };
47455
47789
  /**
47456
47790
  * Ensures the promise settles only once.
47457
47791
  */
@@ -47466,6 +47800,18 @@
47466
47800
  }
47467
47801
  handler();
47468
47802
  };
47803
+ /**
47804
+ * Appends the final log footer and settles the promise exactly once.
47805
+ */
47806
+ const settleWithLog = (status, handler, details) => {
47807
+ if (isSettling || settled) {
47808
+ return;
47809
+ }
47810
+ isSettling = true;
47811
+ void finishLog(status, details).finally(() => {
47812
+ settleOnce(handler);
47813
+ });
47814
+ };
47469
47815
  /**
47470
47816
  * Resets the idle timer that triggers termination after inactivity.
47471
47817
  */
@@ -47475,7 +47821,7 @@
47475
47821
  }
47476
47822
  idleTimer = setTimeout(() => {
47477
47823
  commandProcess.kill();
47478
- settleOnce(() => resolve(fullOutput));
47824
+ settleWithLog('completed after idle timeout', () => resolve(fullOutput));
47479
47825
  }, idleTimeoutMs);
47480
47826
  };
47481
47827
  /**
@@ -47529,41 +47875,43 @@
47529
47875
  * Handles process exit and resolves or rejects accordingly.
47530
47876
  */
47531
47877
  const handleExit = (code) => {
47532
- settleOnce(() => {
47533
- if (code === 0 || markerSeen) {
47878
+ const failure = code === 0 || markerSeen ? undefined : new Error(buildCommandFailureMessage(scriptPathPosix, code, fullOutput));
47879
+ const status = failure ? `failed with exit code ${code !== null && code !== void 0 ? code : 'unknown'}` : 'succeeded';
47880
+ settleWithLog(status, () => {
47881
+ if (!failure) {
47534
47882
  resolve(fullOutput);
47535
47883
  return;
47536
47884
  }
47537
- reject(new Error(buildCommandFailureMessage(scriptPathPosix, code, fullOutput)));
47885
+ reject(failure);
47538
47886
  });
47539
47887
  };
47540
47888
  commandProcess.on('close', handleExit);
47541
47889
  commandProcess.on('exit', handleExit);
47542
47890
  commandProcess.on('disconnect', () => {
47543
- settleOnce(() => {
47544
- reject(new Error(buildCommandFailureMessage(scriptPathPosix, null, fullOutput)));
47545
- });
47891
+ const failure = new Error(buildCommandFailureMessage(scriptPathPosix, null, fullOutput));
47892
+ settleWithLog('failed after disconnect', () => reject(failure), failure);
47546
47893
  });
47547
47894
  commandProcess.on('error', (error) => {
47548
- settleOnce(() => {
47549
- const outputSnippet = createOutputSnippet(fullOutput);
47550
- const details = outputSnippet ? `\n\n${outputSnippet}` : '';
47551
- reject(new Error(`Command "bash ${scriptPathPosix}" failed: ${error.message}${details}`));
47552
- });
47895
+ const outputSnippet = createOutputSnippet(fullOutput);
47896
+ const details = outputSnippet ? `\n\n${outputSnippet}` : '';
47897
+ const failure = new Error(`Command "bash ${scriptPathPosix}" failed: ${error.message}${details}`);
47898
+ settleWithLog('failed before completion', () => reject(failure), failure);
47553
47899
  });
47554
47900
  });
47555
47901
  }
47556
47902
 
47557
47903
  /**
47558
- * Creates a temporary script file, runs it, waits for a completion marker and idle time, and then deletes it.
47904
+ * Creates a temporary script file, runs it, waits for a completion marker and idle time, and defers cleanup when a round tracker is provided.
47559
47905
  * Returns the captured output for post-processing.
47560
47906
  */
47561
47907
  async function $runGoScriptUntilMarkerIdle(options) {
47562
47908
  return await withTempScript(options, async (scriptPath) => {
47563
47909
  return await runScriptUntilMarkerIdle({
47564
47910
  scriptPath,
47911
+ scriptContent: options.scriptContent,
47565
47912
  completionLineMatcher: options.completionLineMatcher,
47566
47913
  idleTimeoutMs: options.idleTimeoutMs,
47914
+ logPath: options.logPath,
47567
47915
  });
47568
47916
  });
47569
47917
  }
@@ -47941,6 +48289,8 @@
47941
48289
  scriptContent,
47942
48290
  completionLineMatcher: CODEX_COMPLETION_LINE,
47943
48291
  idleTimeoutMs: CODEX_COMPLETION_IDLE_MS,
48292
+ logPath: options.logPath,
48293
+ promptRoundArtifacts: options.promptRoundArtifacts,
47944
48294
  });
47945
48295
  this.rateLimitBackoff.reset();
47946
48296
  return { usage: buildCodexUsageFromOutput(output, this.options.model) };
@@ -48074,6 +48424,8 @@
48074
48424
  output = await $runGoScriptWithOutput({
48075
48425
  scriptPath: options.scriptPath,
48076
48426
  scriptContent,
48427
+ logPath: options.logPath,
48428
+ promptRoundArtifacts: options.promptRoundArtifacts,
48077
48429
  });
48078
48430
  }
48079
48431
  catch (error) {
@@ -48100,6 +48452,7 @@
48100
48452
  cd "${projectPath}"
48101
48453
  ${options.command}
48102
48454
  `),
48455
+ logPath: options.logPath,
48103
48456
  });
48104
48457
  }
48105
48458
 
@@ -48123,6 +48476,8 @@
48123
48476
  prompt: options.prompt,
48124
48477
  scriptPath: options.scriptPath,
48125
48478
  projectPath: options.projectPath,
48479
+ logPath: options.logPath,
48480
+ promptRoundArtifacts: options.promptRoundArtifacts,
48126
48481
  });
48127
48482
  return { ...result, attemptCount: 1 };
48128
48483
  }
@@ -48134,6 +48489,8 @@
48134
48489
  prompt: promptForCurrentAttempt,
48135
48490
  scriptPath: options.scriptPath,
48136
48491
  projectPath: options.projectPath,
48492
+ logPath: options.logPath,
48493
+ promptRoundArtifacts: options.promptRoundArtifacts,
48137
48494
  });
48138
48495
  console.info(colors__default["default"].gray(`Running verification command after attempt #${attemptCount}: ${normalizedTestCommand}`));
48139
48496
  try {
@@ -48141,6 +48498,7 @@
48141
48498
  command: normalizedTestCommand,
48142
48499
  projectPath: options.projectPath,
48143
48500
  scriptPath: buildPromptTestScriptPath(options.scriptPath),
48501
+ logPath: options.logPath,
48144
48502
  });
48145
48503
  return { ...result, attemptCount };
48146
48504
  }
@@ -48978,6 +49336,7 @@
48978
49336
  const codexPrompt = appendCoderContext(buildCodexPrompt(nextPrompt.file, nextPrompt.section), resolvedCoderContext);
48979
49337
  const scriptPath = buildScriptPath(nextPrompt.file, nextPrompt.section);
48980
49338
  const promptLabel = buildPromptLabelForDisplay(nextPrompt.file, nextPrompt.section);
49339
+ const promptRoundArtifacts = createCoderRunPromptRoundArtifacts(options.preserveLogs);
48981
49340
  if (isUiMode) {
48982
49341
  uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.setCurrentPrompt(promptLabel);
48983
49342
  uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.setPhase('running');
@@ -48988,57 +49347,68 @@
48988
49347
  }
48989
49348
  const promptExecutionStartedDate = moment__default["default"]();
48990
49349
  let attemptCount = 1;
49350
+ let promptRoundOutcome = 'failure';
48991
49351
  const roundChangedFilesSnapshot = options.normalizeLineEndings
48992
49352
  ? await captureChangedFilesSnapshot(process.cwd())
48993
49353
  : undefined;
48994
49354
  try {
48995
- uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.startCapturingAgentOutput();
48996
- const result = await runPromptWithTestFeedback({
48997
- runner,
48998
- prompt: codexPrompt,
48999
- scriptPath,
49000
- projectPath: process.cwd(),
49001
- promptLabel,
49002
- testCommand: options.testCommand,
49003
- onAttemptStarted: (nextAttemptCount) => {
49004
- attemptCount = nextAttemptCount;
49005
- uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.setAttempt(nextAttemptCount);
49006
- if (nextAttemptCount > 1) {
49007
- uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.setStatusMessage(`Retrying (attempt ${nextAttemptCount})`);
49008
- uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.setPhase('verifying');
49355
+ await withPromptRuntimeLog(scriptPath, async (logPath) => {
49356
+ try {
49357
+ uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.startCapturingAgentOutput();
49358
+ const result = await runPromptWithTestFeedback({
49359
+ runner,
49360
+ prompt: codexPrompt,
49361
+ scriptPath,
49362
+ projectPath: process.cwd(),
49363
+ promptLabel,
49364
+ testCommand: options.testCommand,
49365
+ logPath,
49366
+ promptRoundArtifacts,
49367
+ onAttemptStarted: (nextAttemptCount) => {
49368
+ attemptCount = nextAttemptCount;
49369
+ uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.setAttempt(nextAttemptCount);
49370
+ if (nextAttemptCount > 1) {
49371
+ uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.setStatusMessage(`Retrying (attempt ${nextAttemptCount})`);
49372
+ uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.setPhase('verifying');
49373
+ }
49374
+ },
49375
+ });
49376
+ uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.stopCapturingAgentOutput();
49377
+ uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.setStatusMessage('Committing changes');
49378
+ markPromptDone(nextPrompt.file, nextPrompt.section, result.usage, runnerMetadata.runnerName, runnerMetadata.modelName, promptExecutionStartedDate, result.attemptCount);
49379
+ await writePromptFile(nextPrompt.file);
49380
+ await normalizeLineEndingsForCurrentRound(options, roundChangedFilesSnapshot);
49381
+ if (options.waitForUser) {
49382
+ uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.pauseTimer();
49383
+ uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.setStatusMessage('Waiting... Press Enter to commit');
49384
+ printCommitMessage(commitMessage);
49385
+ await waitForEnter(colors__default["default"].bgWhite('Press Enter to commit and continue...'));
49386
+ uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.resumeTimer();
49009
49387
  }
49010
- },
49011
- });
49012
- uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.stopCapturingAgentOutput();
49013
- uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.setStatusMessage('Committing changes');
49014
- markPromptDone(nextPrompt.file, nextPrompt.section, result.usage, runnerMetadata.runnerName, runnerMetadata.modelName, promptExecutionStartedDate, result.attemptCount);
49015
- await writePromptFile(nextPrompt.file);
49016
- await normalizeLineEndingsForCurrentRound(options, roundChangedFilesSnapshot);
49017
- if (options.waitForUser) {
49018
- uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.pauseTimer();
49019
- uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.setStatusMessage('Waiting... Press Enter to commit');
49020
- printCommitMessage(commitMessage);
49021
- await waitForEnter(colors__default["default"].bgWhite('Press Enter to commit and continue...'));
49022
- uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.resumeTimer();
49023
- }
49024
- await commitChanges(commitMessage, { autoPush: options.autoPush });
49025
- await runPostPromptAutoMigrationIfEnabled(options);
49388
+ await commitChanges(commitMessage, { autoPush: options.autoPush });
49389
+ await runPostPromptAutoMigrationIfEnabled(options);
49390
+ promptRoundOutcome = 'success';
49391
+ }
49392
+ catch (error) {
49393
+ uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.stopCapturingAgentOutput();
49394
+ uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.setPhase('error');
49395
+ uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.addError(error instanceof Error ? error.message : String(error));
49396
+ markPromptFailed(nextPrompt.file, nextPrompt.section, runnerMetadata.runnerName, runnerMetadata.modelName, promptExecutionStartedDate, attemptCount);
49397
+ await writePromptFile(nextPrompt.file);
49398
+ await writePromptErrorLog({
49399
+ file: nextPrompt.file,
49400
+ section: nextPrompt.section,
49401
+ runnerName: runnerMetadata.runnerName,
49402
+ modelName: runnerMetadata.modelName,
49403
+ error,
49404
+ });
49405
+ await normalizeLineEndingsForCurrentRound(options, roundChangedFilesSnapshot);
49406
+ throw error;
49407
+ }
49408
+ }, promptRoundArtifacts);
49026
49409
  }
49027
- catch (error) {
49028
- uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.stopCapturingAgentOutput();
49029
- uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.setPhase('error');
49030
- uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.addError(error instanceof Error ? error.message : String(error));
49031
- markPromptFailed(nextPrompt.file, nextPrompt.section, runnerMetadata.runnerName, runnerMetadata.modelName, promptExecutionStartedDate, attemptCount);
49032
- await writePromptFile(nextPrompt.file);
49033
- await writePromptErrorLog({
49034
- file: nextPrompt.file,
49035
- section: nextPrompt.section,
49036
- runnerName: runnerMetadata.runnerName,
49037
- modelName: runnerMetadata.modelName,
49038
- error,
49039
- });
49040
- await normalizeLineEndingsForCurrentRound(options, roundChangedFilesSnapshot);
49041
- throw error;
49410
+ finally {
49411
+ await promptRoundArtifacts.cleanup(promptRoundOutcome);
49042
49412
  }
49043
49413
  }
49044
49414
  }