@xfey/tutti 0.1.93 → 0.1.95

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 (85) hide show
  1. package/dist/collaboration-state/clarification-records.d.ts +2 -1
  2. package/dist/collaboration-state/clarification-records.js +18 -0
  3. package/dist/collaboration-state/index.d.ts +3 -1
  4. package/dist/collaboration-state/index.js +2 -1
  5. package/dist/collaboration-state/messages.js +15 -0
  6. package/dist/collaboration-state/run-recording.js +18 -1
  7. package/dist/collaboration-state/run-results.js +6 -0
  8. package/dist/collaboration-state/task-retry.d.ts +16 -0
  9. package/dist/collaboration-state/task-retry.js +134 -0
  10. package/dist/control-plane/command-recovery.js +9 -1
  11. package/dist/control-plane/index.d.ts +3 -2
  12. package/dist/control-plane/index.js +14 -0
  13. package/dist/control-plane/run-retry.d.ts +19 -0
  14. package/dist/control-plane/run-retry.js +103 -0
  15. package/dist/control-plane/run-start.d.ts +2 -1
  16. package/dist/control-plane/run-start.js +18 -1
  17. package/dist/control-plane/task-compile-clarification-context.d.ts +4 -0
  18. package/dist/control-plane/task-compile-clarification-context.js +9 -22
  19. package/dist/control-plane/task-compile-continuation.js +2 -0
  20. package/dist/control-plane/task-compile-start.js +2 -0
  21. package/dist/control-plane/task-source-context-types.d.ts +11 -0
  22. package/dist/control-plane/task-source-context-types.js +2 -0
  23. package/dist/control-plane/task-source-context.d.ts +7 -0
  24. package/dist/control-plane/task-source-context.js +31 -0
  25. package/dist/control-plane/types.d.ts +15 -0
  26. package/dist/control-plane/workflows/openai.d.ts +1 -0
  27. package/dist/control-plane/workflows/openai.js +87 -15
  28. package/dist/control-plane/workflows/types.d.ts +6 -14
  29. package/dist/control-plane/worklist-terminal-feedback.js +3 -0
  30. package/dist/prompt-templates/index.d.ts +1 -1
  31. package/dist/prompt-templates/index.js +4 -3
  32. package/dist/providers/openai/app-server/durable-session-smoke-cli.d.ts +2 -0
  33. package/dist/providers/openai/app-server/durable-session-smoke-cli.js +229 -0
  34. package/dist/providers/openai/app-server/read-only-procedure.d.ts +10 -0
  35. package/dist/providers/openai/app-server/read-only-procedure.js +42 -13
  36. package/dist/providers/openai/app-server/session-store.d.ts +74 -0
  37. package/dist/providers/openai/app-server/session-store.js +305 -0
  38. package/dist/providers/openai/app-server/workspace-write-run.d.ts +17 -4
  39. package/dist/providers/openai/app-server/workspace-write-run.js +92 -28
  40. package/dist/providers/openai/codex-app-server.d.ts +1 -0
  41. package/dist/providers/openai/codex-app-server.js +2 -0
  42. package/dist/run-pipeline/openai.d.ts +1 -0
  43. package/dist/run-pipeline/openai.js +15 -43
  44. package/dist/run-pipeline/task-run-invocation.js +371 -93
  45. package/dist/server-shell/http/routes/project-api/execution-routes.js +32 -2
  46. package/dist/server-shell/http/routes/project-api/invalidations.d.ts +2 -1
  47. package/dist/server-shell/http/routes/project-api/invalidations.js +13 -0
  48. package/dist/server-shell/http/routes/project-api/openapi-execution-routes.d.ts +21 -0
  49. package/dist/server-shell/http/routes/project-api/openapi-execution-routes.js +12 -1
  50. package/dist/server-shell/http/routes/project-api/openapi.d.ts +7 -0
  51. package/node_modules/@tutti/shared/dist/schemas/api/clarifications.d.ts +1 -0
  52. package/node_modules/@tutti/shared/dist/schemas/api/index.d.ts +1 -1
  53. package/node_modules/@tutti/shared/dist/schemas/api/index.js +1 -1
  54. package/node_modules/@tutti/shared/dist/schemas/api/messages.d.ts +5 -0
  55. package/node_modules/@tutti/shared/dist/schemas/api/messages.js +1 -0
  56. package/node_modules/@tutti/shared/dist/schemas/api/runtime-events.d.ts +1 -0
  57. package/node_modules/@tutti/shared/dist/schemas/api/types.d.ts +4 -1
  58. package/node_modules/@tutti/shared/dist/schemas/api/viewer-reference.d.ts +1 -0
  59. package/node_modules/@tutti/shared/dist/schemas/api/work-items.d.ts +4 -0
  60. package/node_modules/@tutti/shared/dist/schemas/api/work-items.js +3 -0
  61. package/node_modules/@tutti/shared/dist/schemas/api/workspace-commands.d.ts +33 -0
  62. package/node_modules/@tutti/shared/dist/schemas/api/workspace-commands.js +35 -1
  63. package/package.json +1 -1
  64. package/prompts/README.md +3 -1
  65. package/prompts/artifacts/README.md +1 -1
  66. package/prompts/artifacts/applicability.md +1 -1
  67. package/prompts/procedures/README.md +3 -3
  68. package/prompts/procedures/follow-up-check.md +1 -1
  69. package/prompts/procedures/reference-file-summary.md +1 -1
  70. package/prompts/procedures/task-compile.md +7 -7
  71. package/prompts/prompt-flow-map.md +16 -10
  72. package/prompts/runs/README.md +11 -16
  73. package/prompts/runs/task-execute.md +86 -0
  74. package/prompts/runs/task-finalize.md +11 -0
  75. package/prompts/runs/task-recovery.md +15 -0
  76. package/prompts/runs/task-result-contract.md +64 -0
  77. package/web/assets/{homepage-motion-scene-CLTkixIk.js → homepage-motion-scene-BFo4r4nz.js} +1 -1
  78. package/web/assets/index-CNIl4TF8.js +69 -0
  79. package/web/assets/index-quWLFJgD.css +1 -0
  80. package/web/index.html +2 -2
  81. package/prompts/runs/task-continuation.md +0 -199
  82. package/prompts/runs/task-retry.md +0 -207
  83. package/prompts/runs/task-run.md +0 -186
  84. package/web/assets/index-BTNYElB-.js +0 -69
  85. package/web/assets/index-Deu_eF5K.css +0 -1
@@ -8,7 +8,7 @@ import { CodexAppServerJsonRpcClient, CodexAppServerProtocolError, } from "./jso
8
8
  import { CodexAppServerInvocation, CodexAppServerLifecycleError, createManagedProcess, } from "./invocation-lifecycle.js";
9
9
  import { CodexAppServerAdmissionError, } from "./invocation-coordinator.js";
10
10
  import { createCodexAppServerRuntimeObserver, } from "./runtime-telemetry.js";
11
- import { createWorkspaceWriteSandboxPolicy } from "./sandbox-policy.js";
11
+ import { createReadOnlySandboxPolicy, createWorkspaceWriteSandboxPolicy, } from "./sandbox-policy.js";
12
12
  import { buildCodexAppServerProviderConfigOverrides, resolveCodexAppServerModelProvider, } from "./provider-config.js";
13
13
  import { buildCodexAppServerTurnInput, resolveCodexAppServerContextRuntimeHint, resolveCodexAppServerSkillsListWarmup, resolveCodexAppServerSkillInputs, CodexAppServerSkillSelectionError, } from "./skills.js";
14
14
  import { compactText, containsKnownSecret, createCodexSpawnEnv, extractAgentText, extractServerRequestMethod, findJsonObjectCandidates, isApiKeyAccount, readThreadId, readTurnError, readTurnStatus, redactWithKnownValues, } from "./runtime-helpers.js";
@@ -204,12 +204,14 @@ export async function runCodexAppServerWorkspaceWriteRun(options) {
204
204
  }
205
205
  const model = options.defaultModel ?? DEFAULT_OPENAI_MODEL;
206
206
  const tempRoot = mkdtempSync(join(tmpdir(), "tutti-codex-workspace-write-run-"));
207
- const codexHome = join(tempRoot, "codex-home");
207
+ const codexHome = options.session?.codexHome ?? join(tempRoot, "codex-home");
208
208
  mkdirSync(codexHome, { recursive: true, mode: 0o700 });
209
209
  const requestTimeoutMs = options.requestTimeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS;
210
210
  const turnTimeoutMs = options.turnTimeoutMs ?? DEFAULT_TURN_TIMEOUT_MS;
211
211
  const networkEnabled = options.networkAccess ?? true;
212
- const approvalPolicy = options.approvalPolicy ?? DEFAULT_WORKSPACE_WRITE_APPROVAL_POLICY;
212
+ const sandboxMode = options.sandboxMode ?? "workspace-write";
213
+ const approvalPolicy = options.approvalPolicy ??
214
+ (sandboxMode === "read-only" ? "never" : DEFAULT_WORKSPACE_WRITE_APPROVAL_POLICY);
213
215
  const approvalsReviewer = resolveWorkspaceWriteApprovalsReviewer({
214
216
  ...(options.approvalsReviewer === undefined ? {} : { explicit: options.approvalsReviewer }),
215
217
  env: options.baseEnv ?? process.env,
@@ -269,6 +271,7 @@ export async function runCodexAppServerWorkspaceWriteRun(options) {
269
271
  let primaryError;
270
272
  let runResult;
271
273
  let lifecycleError;
274
+ let turnStartState = "not_started";
272
275
  try {
273
276
  await client.request("initialize", {
274
277
  clientInfo: {
@@ -291,22 +294,43 @@ export async function runCodexAppServerWorkspaceWriteRun(options) {
291
294
  if (skillsListWarmup !== undefined) {
292
295
  await client.request("skills/list", skillsListWarmup, requestTimeoutMs);
293
296
  }
294
- const threadStartResponse = await client.request("thread/start", {
295
- cwd: options.workspaceRoot,
296
- model,
297
- modelProvider,
298
- approvalPolicy,
299
- approvalsReviewer,
300
- sandbox: "workspace-write",
301
- config: buildWorkspaceWriteThreadConfig(options),
302
- ephemeral: true,
303
- experimentalRawEvents: false,
304
- persistExtendedHistory: false,
305
- }, requestTimeoutMs);
306
- const threadId = readThreadId(threadStartResponse);
297
+ let threadId;
298
+ if (options.session?.threadId === undefined) {
299
+ const threadStartResponse = await client.request("thread/start", {
300
+ cwd: options.workspaceRoot,
301
+ model,
302
+ modelProvider,
303
+ approvalPolicy,
304
+ approvalsReviewer,
305
+ sandbox: sandboxMode,
306
+ config: buildWorkspaceWriteThreadConfig(options),
307
+ ephemeral: options.session === undefined,
308
+ experimentalRawEvents: false,
309
+ persistExtendedHistory: false,
310
+ }, requestTimeoutMs);
311
+ threadId = readThreadId(threadStartResponse);
312
+ }
313
+ else {
314
+ if (options.session.unarchive === true) {
315
+ await client.request("thread/unarchive", { threadId: options.session.threadId }, requestTimeoutMs);
316
+ }
317
+ const threadResumeResponse = await client.request("thread/resume", {
318
+ threadId: options.session.threadId,
319
+ cwd: options.workspaceRoot,
320
+ model,
321
+ modelProvider,
322
+ approvalPolicy,
323
+ approvalsReviewer,
324
+ sandbox: sandboxMode,
325
+ config: buildWorkspaceWriteThreadConfig(options),
326
+ }, requestTimeoutMs);
327
+ threadId = readThreadId(threadResumeResponse) ?? options.session.threadId;
328
+ }
307
329
  if (threadId === null) {
308
330
  throw new CodexAppServerWorkspaceWriteRunError("thread_start_failed", "Codex app-server did not return a thread id.");
309
331
  }
332
+ await options.session?.onThreadReady?.(threadId);
333
+ turnStartState = "start_requested";
310
334
  await client.request("turn/start", {
311
335
  threadId,
312
336
  input: buildCodexAppServerTurnInput({
@@ -319,12 +343,14 @@ export async function runCodexAppServerWorkspaceWriteRun(options) {
319
343
  cwd: options.workspaceRoot,
320
344
  approvalPolicy,
321
345
  approvalsReviewer,
322
- sandboxPolicy: createWorkspaceWriteSandboxPolicy(options.workspaceRoot, {
323
- networkEnabled,
324
- }),
346
+ sandboxPolicy: sandboxMode === "read-only"
347
+ ? createReadOnlySandboxPolicy({ networkEnabled })
348
+ : createWorkspaceWriteSandboxPolicy(options.workspaceRoot, {
349
+ networkEnabled,
350
+ }),
325
351
  model,
326
352
  modelProvider,
327
- outputSchema: options.outputSchema,
353
+ ...(options.outputSchema === undefined ? {} : { outputSchema: options.outputSchema }),
328
354
  }, requestTimeoutMs);
329
355
  const turnCompletedNotification = await waitForWorkspaceWriteTurnCompletion({
330
356
  client,
@@ -349,6 +375,7 @@ export async function runCodexAppServerWorkspaceWriteRun(options) {
349
375
  sensitiveValues,
350
376
  },
351
377
  });
378
+ turnStartState = "terminal";
352
379
  if (client.serverRequests.length > 0) {
353
380
  const unresolved = client.serverRequests.find((request) => client.isServerRequestPending(request.id));
354
381
  if (unresolved !== undefined) {
@@ -385,17 +412,51 @@ export async function runCodexAppServerWorkspaceWriteRun(options) {
385
412
  const agentText = client.notifications
386
413
  .map((notification) => extractAgentText(notification))
387
414
  .join("");
388
- const parsed = parseWorkspaceWriteStructuredJson(agentText);
389
- if (!options.validateOutput(parsed)) {
390
- throw new CodexAppServerWorkspaceWriteRunError("output_validation_failed", "Codex app-server structured output did not match the expected schema.");
415
+ let output;
416
+ if (options.outputSchema === undefined && options.validateOutput === undefined) {
417
+ output = agentText;
418
+ }
419
+ else {
420
+ if (options.outputSchema === undefined || options.validateOutput === undefined) {
421
+ throw new CodexAppServerWorkspaceWriteRunError("output_validation_failed", "Codex app-server structured output configuration is incomplete.");
422
+ }
423
+ let parsed;
424
+ try {
425
+ parsed = parseWorkspaceWriteStructuredJson(agentText);
426
+ }
427
+ catch (error) {
428
+ if (error instanceof CodexAppServerWorkspaceWriteRunError) {
429
+ throw new CodexAppServerWorkspaceWriteRunError(error.code, error.message, {
430
+ ...error.details,
431
+ agent_output: redactWithKnownValues(agentText, sensitiveValues).slice(0, 16_000),
432
+ });
433
+ }
434
+ throw error;
435
+ }
436
+ if (!options.validateOutput(parsed)) {
437
+ throw new CodexAppServerWorkspaceWriteRunError("output_validation_failed", "Codex app-server structured output did not match the expected schema.", {
438
+ agent_output: redactWithKnownValues(agentText, sensitiveValues).slice(0, 16_000),
439
+ });
440
+ }
441
+ output = parsed;
391
442
  }
392
443
  const rawOutput = `${client.rawStdout}\n${client.stderr}`;
393
444
  if (options.strictLeakCheck === true && containsKnownSecret(rawOutput, strictLeakCheckValues)) {
394
445
  throw new CodexAppServerWorkspaceWriteRunError("secret_leak_detected", "Codex app-server output contained a sensitive runtime value.");
395
446
  }
396
447
  const usage = extractCodexAppServerTokenUsage(client.notifications);
448
+ if (options.session?.archiveAfterTurn?.(output) === true) {
449
+ try {
450
+ await client.request("thread/archive", { threadId }, requestTimeoutMs);
451
+ await options.session.onThreadArchived?.();
452
+ }
453
+ catch {
454
+ await options.session.onThreadArchiveFailure?.();
455
+ }
456
+ }
397
457
  runResult = {
398
- output: parsed,
458
+ output,
459
+ thread_id: threadId,
399
460
  model,
400
461
  turn_status: "completed",
401
462
  notification_count: client.notifications.length,
@@ -409,14 +470,17 @@ export async function runCodexAppServerWorkspaceWriteRun(options) {
409
470
  }
410
471
  catch (error) {
411
472
  if (error instanceof CodexAppServerWorkspaceWriteRunError) {
412
- primaryError = error;
473
+ primaryError = new CodexAppServerWorkspaceWriteRunError(error.code, error.message, {
474
+ ...error.details,
475
+ turn_start_state: turnStartState,
476
+ });
413
477
  }
414
478
  else if (error instanceof CodexAppServerProtocolError) {
415
- primaryError = new CodexAppServerWorkspaceWriteRunError("app_server_protocol_error", redactWithKnownValues(error.message, sensitiveValues));
479
+ primaryError = new CodexAppServerWorkspaceWriteRunError("app_server_protocol_error", redactWithKnownValues(error.message, sensitiveValues), { turn_start_state: turnStartState });
416
480
  }
417
481
  else {
418
482
  const message = error instanceof Error ? error.message : String(error);
419
- primaryError = new CodexAppServerWorkspaceWriteRunError("app_server_protocol_error", redactWithKnownValues(message, sensitiveValues));
483
+ primaryError = new CodexAppServerWorkspaceWriteRunError("app_server_protocol_error", redactWithKnownValues(message, sensitiveValues), { turn_start_state: turnStartState });
420
484
  }
421
485
  }
422
486
  finally {
@@ -435,7 +499,7 @@ export async function runCodexAppServerWorkspaceWriteRun(options) {
435
499
  if (lifecycleError !== undefined) {
436
500
  throw new CodexAppServerWorkspaceWriteRunError("process_lifecycle_failed", lifecycleError instanceof CodexAppServerLifecycleError
437
501
  ? lifecycleError.message
438
- : "Codex app-server process lifecycle did not close cleanly.");
502
+ : "Codex app-server process lifecycle did not close cleanly.", { turn_start_state: turnStartState });
439
503
  }
440
504
  return runResult;
441
505
  }
@@ -1,3 +1,4 @@
1
+ export declare const CODEX_APP_SERVER_VERSION: string;
1
2
  export declare const CODEX_APP_SERVER_ENTRYPOINT: string;
2
3
  export declare const CODEX_APP_SERVER_COMMAND: string;
3
4
  export declare const CODEX_APP_SERVER_LISTEN_URL: "stdio://";
@@ -2,6 +2,8 @@ import { createRequire } from "node:module";
2
2
  import { dirname, isAbsolute, join } from "node:path";
3
3
  import { DEFAULT_OPENAI_MODEL } from "./model-config.js";
4
4
  const require = createRequire(import.meta.url);
5
+ const codexPackage = require("@openai/codex/package.json");
6
+ export const CODEX_APP_SERVER_VERSION = codexPackage.version;
5
7
  export const CODEX_APP_SERVER_ENTRYPOINT = join(dirname(require.resolve("@openai/codex/package.json")), "bin", "codex.js");
6
8
  export const CODEX_APP_SERVER_COMMAND = process.execPath;
7
9
  export const CODEX_APP_SERVER_LISTEN_URL = "stdio://";
@@ -18,6 +18,7 @@ export type OpenAiRunPipelineRunnerOptions = {
18
18
  workspaceRoot: string;
19
19
  promptsRoot?: string;
20
20
  tuttiHome?: string;
21
+ projectId?: ProjectId;
21
22
  userSkillsRoot?: string;
22
23
  builtInSkillsRoot?: string;
23
24
  agentContext?: CodexAppServerAgentContextRuntime;
@@ -17,17 +17,18 @@ function summarizeProviderError(error) {
17
17
  error.message.includes("invalid_json_schema") ||
18
18
  error.message.includes("Invalid schema") ||
19
19
  error.message.includes("response_format");
20
+ const turnStateUnknown = error.details.turn_start_state === "start_requested";
20
21
  const errorCode = looksLikeSchemaError
21
22
  ? "codex_app_server_output_schema_invalid"
22
- : `codex_app_server_${error.code}`;
23
+ : turnStateUnknown
24
+ ? "codex_app_server_turn_state_unknown"
25
+ : `codex_app_server_${error.code}`;
23
26
  return failedBeforeChecks({
24
27
  summary: `Provider execution failed before checks. (${errorCode})`,
25
28
  errorCode,
26
29
  retryable: !looksLikeSchemaError &&
27
- (error.code === "app_server_protocol_error" ||
28
- error.code === "turn_timeout" ||
29
- error.code === "turn_failed" ||
30
- error.code === "thread_start_failed"),
30
+ error.details.turn_start_state === "not_started" &&
31
+ (error.code === "app_server_protocol_error" || error.code === "thread_start_failed"),
31
32
  });
32
33
  }
33
34
  function summarizeWorkspaceOpsError(error, changedPaths) {
@@ -153,12 +154,12 @@ function loggedSyncStage(options, input, stage, run, completedFields = () => ({}
153
154
  }
154
155
  }
155
156
  const MAX_SELF_CORRECTION_RETRIES = 1;
156
- const MAX_PROVIDER_TRANSIENT_RETRIES = 1;
157
157
  function runPipelineResultPromotion(result) {
158
158
  return "promotion" in result ? result.promotion : undefined;
159
159
  }
160
160
  function buildCorrectionContext(input) {
161
161
  const correction = {
162
+ previous_provider_result: input.previousProviderResult,
162
163
  summary: input.result.summary,
163
164
  reason_code: input.reasonCode,
164
165
  guidance: input.guidance,
@@ -189,23 +190,12 @@ function selfCorrectionInput(input, nextAttempt, correctionContext) {
189
190
  return {
190
191
  ...input,
191
192
  run_lineage: {
192
- kind: "retry",
193
+ ...input.run_lineage,
193
194
  attempt: nextAttempt,
194
- parent_activity_ref: input.activity_ref,
195
- root_activity_ref: input.run_lineage.root_activity_ref ?? input.activity_ref,
196
195
  },
197
196
  correction_context: correctionContext,
198
197
  };
199
198
  }
200
- function providerTransientRetryInput(input) {
201
- return {
202
- ...input,
203
- run_lineage: {
204
- ...input.run_lineage,
205
- attempt: input.run_lineage.attempt + 1,
206
- },
207
- };
208
- }
209
199
  function appendSelfCorrectionExhaustedSummary(input) {
210
200
  if (input.attemptedRetries <= 0) {
211
201
  return input.result;
@@ -218,12 +208,6 @@ function appendSelfCorrectionExhaustedSummary(input) {
218
208
  function isSelfCorrectionRequest(result) {
219
209
  return "request_kind" in result && result.request_kind === "self_correction";
220
210
  }
221
- function isProviderTransientRunFailure(result) {
222
- return (!isSelfCorrectionRequest(result) &&
223
- result.result_kind === "failed" &&
224
- result.retryable &&
225
- result.error_code.startsWith("codex_app_server_"));
226
- }
227
211
  async function runTaskAttempt(options, input) {
228
212
  let changedPaths;
229
213
  try {
@@ -289,8 +273,9 @@ async function runTaskAttempt(options, input) {
289
273
  });
290
274
  return requestSelfCorrection({
291
275
  result,
276
+ previousProviderResult: taskOutput,
292
277
  reasonCode: "no_candidate_changes",
293
- guidance: "Produce a concrete candidate diff for the frozen task contract.",
278
+ guidance: "Produce a concrete candidate diff for the current task goal and scope.",
294
279
  });
295
280
  }
296
281
  const artifactGate = await loggedAsyncStage(options, input, "artifact_candidate_validate", () => runArtifactCandidateGate({
@@ -336,6 +321,7 @@ async function runTaskAttempt(options, input) {
336
321
  }
337
322
  return requestSelfCorrection({
338
323
  result: artifactResult,
324
+ previousProviderResult: taskOutput,
339
325
  reasonCode: artifactGate.failure.reason_code,
340
326
  guidance: artifactGate.failure.guidance,
341
327
  diagnostic: artifactGate.failure.diagnostic,
@@ -361,6 +347,7 @@ async function runTaskAttempt(options, input) {
361
347
  });
362
348
  return requestSelfCorrection({
363
349
  result,
350
+ previousProviderResult: taskOutput,
364
351
  reasonCode: "checks_failed",
365
352
  guidance: "Use the failed checks summary to fix the candidate so the task can pass Tutti checks.",
366
353
  });
@@ -378,8 +365,9 @@ async function runTaskAttempt(options, input) {
378
365
  });
379
366
  return requestSelfCorrection({
380
367
  result,
368
+ previousProviderResult: taskOutput,
381
369
  reasonCode: "no_candidate_changes",
382
- guidance: "Produce a concrete final candidate diff for the frozen task contract.",
370
+ guidance: "Produce a concrete final candidate diff for the current task goal and scope.",
383
371
  });
384
372
  }
385
373
  const checkpoint = loggedSyncStage(options, input, "accepted_checkpoint", () => createAcceptedCheckpoint({
@@ -444,25 +432,8 @@ export function createOpenAiRunPipelineRunner(options) {
444
432
  async runTask(input) {
445
433
  let currentInput = input;
446
434
  let selfCorrectionRetries = 0;
447
- let providerTransientRetries = 0;
448
435
  for (;;) {
449
436
  const result = await runTaskAttempt(options, currentInput);
450
- if (isProviderTransientRunFailure(result) &&
451
- providerTransientRetries < MAX_PROVIDER_TRANSIENT_RETRIES) {
452
- providerTransientRetries += 1;
453
- input.on_stage?.({
454
- stage: "provider_retry",
455
- summary: "retrying Codex task after a transient provider failure.",
456
- });
457
- logRunPipelineStage(options, currentInput, {
458
- stage: "provider_retry",
459
- next_attempt: currentInput.run_lineage.attempt + 1,
460
- error_code: result.error_code,
461
- }, "Run pipeline scheduling provider transient retry");
462
- currentInput = providerTransientRetryInput(currentInput);
463
- continue;
464
- }
465
- providerTransientRetries = 0;
466
437
  if (!isSelfCorrectionRequest(result)) {
467
438
  return result;
468
439
  }
@@ -512,6 +483,7 @@ export function resolveProjectOpenAiRunPipelineRunner(options) {
512
483
  apiKey: credential.secret,
513
484
  workspaceRoot: options.workspaceRoot,
514
485
  tuttiHome: options.tuttiHome,
486
+ projectId: options.projectId,
515
487
  userSkillsRoot: getProjectUserSkillsRoot(options.tuttiHome, options.projectId),
516
488
  ...(options.agentContext === undefined ? {} : { agentContext: options.agentContext }),
517
489
  ...(options.approvalManager === undefined