@akagilnc/pi-workflow-roles 0.1.4745 → 0.1.4759

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.
@@ -124,7 +124,6 @@ const RESUME_SEAT_DISPATCH: Record<
124
124
  ) => Promise<{
125
125
  exitCode: number;
126
126
  terminal?: TerminalResult;
127
- staleWriterLeaseReclaimed?: true;
128
127
  }>;
129
128
  }
130
129
  > = {
@@ -473,19 +472,15 @@ export type CliResult = {
473
472
  /** Settled Terminal when an admitted Role run produced one (programmatic/tests). */
474
473
  terminal?: TerminalResult;
475
474
  hostFailure?: HostSelectionFailure;
476
- /** Typed #556 fact from public resume/dispatch when a dead holder lock was unlinked. */
477
- staleWriterLeaseReclaimed?: true;
478
475
  };
479
476
 
480
477
  function cliResultFromRoleRun(result: {
481
478
  exitCode: number;
482
479
  terminal?: TerminalResult;
483
- staleWriterLeaseReclaimed?: true;
484
480
  }): CliResult {
485
481
  return {
486
482
  exitCode: result.exitCode,
487
483
  ...(result.terminal === undefined ? {} : { terminal: result.terminal }),
488
- ...(result.staleWriterLeaseReclaimed === true ? { staleWriterLeaseReclaimed: true as const } : {}),
489
484
  };
490
485
  }
491
486
 
@@ -813,7 +813,6 @@ export function listRolesForDisplay(
813
813
 
814
814
  /**
815
815
  * Read configured credential presence from a Pi auth.json document.
816
- * Presence drives the selected-provider fail-closed seam (public-run-credentials).
817
816
  */
818
817
  export function credentialProvidersFromAuthData(
819
818
  data: unknown,
@@ -785,7 +785,7 @@ export async function runPublicCountersign(
785
785
  function countersignAdapters(options?: {
786
786
  beforeDispatch?: (
787
787
  admitted: AdmittedCountersignInvocation,
788
- lease: RunWriterLease,
788
+ lease?: RunWriterLease,
789
789
  ) => void | Promise<void>;
790
790
  }) {
791
791
  return {
@@ -76,7 +76,7 @@ export function buildDiaristTurnRequest(
76
76
  async function bindAndRelocateDiaristIfBoardBound(
77
77
  admitted: AdmittedDiaristInvocation,
78
78
  authority: DiaristRunEnv["principalAuthority"],
79
- lease: RunWriterLease,
79
+ lease?: RunWriterLease,
80
80
  ): Promise<void> {
81
81
  const boardTicket = await readBoardTicketNumber(admitted.runDirectory);
82
82
  if (boardTicket === undefined) return;
@@ -69,11 +69,6 @@ import {
69
69
  import { projectHostTransitionPriorNative } from "../host-transition-prior-native.ts";
70
70
  import type { CredentialProviders, SeatModelConfig } from "./config.ts";
71
71
  import {
72
- missingCredentialPreDispatchFailure,
73
- postRunMissingCredentialFailure,
74
- } from "./public-run-credentials.ts";
75
- import {
76
- acquireRunWriterLease,
77
72
  clearCurrentCourt,
78
73
  clearTypedProviderHttpObservation,
79
74
  describeErrorIdentity,
@@ -81,11 +76,9 @@ import {
81
76
  readCurrentCourt,
82
77
  recordCurrentCourt,
83
78
  renderResumeCommand,
84
- RunWriterLeaseHeldError,
85
79
  type CurrentCourtState,
86
80
  type RunWriterLease,
87
81
  type TypedProviderHttpObservation,
88
- type WriterLeaseDiagnosticKind,
89
82
  } from "./run-lifecycle.ts";
90
83
  import {
91
84
  processCancelDiagnostic,
@@ -234,8 +227,8 @@ async function recordBestEffortPostDispatchDiagnostic<A extends AdmittedRoleInvo
234
227
  diagnostic: string,
235
228
  io: CliIo,
236
229
  ): Promise<void> {
237
- io.stderr(formatCliDiagnostic(diagnostic));
238
230
  const payload = { diagnostic, recordedAt: new Date().toISOString() };
231
+ let retentionFailure: string | undefined;
239
232
  try {
240
233
  await env.sessionAppender(
241
234
  env.principalAuthority,
@@ -243,7 +236,6 @@ async function recordBestEffortPostDispatchDiagnostic<A extends AdmittedRoleInvo
243
236
  POST_ADMISSION_CLEANUP_DIAGNOSTIC_ENTRY_TYPE,
244
237
  payload,
245
238
  );
246
- return;
247
239
  } catch (appendError) {
248
240
  try {
249
241
  const artifactsDir = await ensureRealArtifactsDirectory(admitted.runDirectory);
@@ -253,12 +245,17 @@ async function recordBestEffortPostDispatchDiagnostic<A extends AdmittedRoleInvo
253
245
  { encoding: "utf8", flag: "wx" },
254
246
  );
255
247
  } catch (artifactError) {
256
- io.stderr(
257
- formatCliDiagnostic(
258
- `post-dispatch diagnostic durable retention failed on both channels (best-effort continue): dossier=${describeErrorIdentity(appendError)}; artifact=${describeErrorIdentity(artifactError)}`,
259
- ),
260
- );
248
+ retentionFailure =
249
+ `post-dispatch diagnostic durable retention failed on both channels (best-effort continue): dossier=${describeErrorIdentity(appendError)}; artifact=${describeErrorIdentity(artifactError)}`;
250
+ }
251
+ }
252
+ try {
253
+ io.stderr(formatCliDiagnostic(diagnostic));
254
+ if (retentionFailure !== undefined) {
255
+ io.stderr(formatCliDiagnostic(retentionFailure));
261
256
  }
257
+ } catch {
258
+ // Presentation is best-effort beside an already-formed host terminal.
262
259
  }
263
260
  }
264
261
 
@@ -327,13 +324,14 @@ export type PostAdmissionAdapters<
327
324
  result: RoleTurnResult;
328
325
  sessionFile: string;
329
326
  }) => Promise<RoleTurnKnownFailure | undefined>;
330
- beforeDispatch?: (admitted: A, lease: RunWriterLease) => Promise<void> | void;
327
+ beforeDispatch?: (admitted: A, lease?: RunWriterLease) => Promise<void> | void;
331
328
  /**
332
- * After the host turn settles and before the writer lease is released.
333
- * Post-turn bind/relocate (e.g. Diarist first assert) must run here so the
334
- * held lease follows the run directory and failures stay controlled.
329
+ * After the host turn settles and before any held writer lease is released.
330
+ * Post-turn bind/relocate (e.g. Diarist first assert) must run here so a
331
+ * held lease (when present) follows the run directory and failures stay
332
+ * controlled. Public manual resume (#987) may omit the lease.
335
333
  */
336
- afterDispatch?: (admitted: A, lease: RunWriterLease) => Promise<void> | void;
334
+ afterDispatch?: (admitted: A, lease?: RunWriterLease) => Promise<void> | void;
337
335
  };
338
336
 
339
337
  export type ControlledFailureInput = {
@@ -614,7 +612,8 @@ export async function dispatchPostAdmissionTurn<
614
612
  env: PostAdmissionEnv;
615
613
  io: CliIo;
616
614
  request: RoleTurnRequest;
617
- lease: RunWriterLease;
615
+ /** Absent on public manual resume (#987): no package lease gate before host CLI resume. */
616
+ lease?: RunWriterLease;
618
617
  adapters: PostAdmissionAdapters<A, T>;
619
618
  effectiveEngine?: string;
620
619
  persistRunState?: boolean;
@@ -707,14 +706,11 @@ export async function dispatchPostAdmissionTurn<
707
706
  if (adapters.afterDispatch !== undefined) await adapters.afterDispatch(admitted, lease);
708
707
  return result;
709
708
  } catch (error) {
710
- const primaryFailure =
711
- result.terminal !== undefined
712
- && !isLawfulTypedTerminalOutcome(result.terminal.roleOutcome);
713
- if (primaryFailure) {
709
+ if (result.terminal !== undefined) {
714
710
  await recordBestEffortPostDispatchDiagnostic(
715
711
  admitted,
716
712
  env,
717
- `afterDispatch failed beside primary terminal (best-effort continue): ${describeErrorIdentity(error)}`,
713
+ `afterDispatch failed beside host terminal (best-effort continue): ${describeErrorIdentity(error)}`,
718
714
  io,
719
715
  );
720
716
  return result;
@@ -740,23 +736,8 @@ export async function dispatchPostAdmissionTurn<
740
736
  }
741
737
  };
742
738
  try {
743
- const missingCredential = missingCredentialPreDispatchFailure(
744
- env.model,
745
- env.credentials,
746
- );
747
- if (missingCredential !== undefined) {
748
- return {
749
- ...(await presentControlledFailure(
750
- admitted,
751
- withEngineDetourInvocationScope(missingCredential, request.invocationScopeId),
752
- adapters,
753
- env.principalAuthority,
754
- io,
755
- persistRunState,
756
- )) as { exitCode: number; admitted: A; terminal: T },
757
- ...deferredPersist,
758
- };
759
- }
739
+ // #987: do not pre-block or classify host dispatch from AK credential
740
+ // catalog facts. Per-invocation runner/host evidence owns provider identity.
760
741
  // #617 DK-4: capture previous invocation host before markRunRunning overwrites it.
761
742
  // Single authority projectHostTransitionPriorNative classifies the prior native volume.
762
743
  // Same-run resume (#637) keeps host identity on the run's invocation page.
@@ -1001,15 +982,10 @@ export async function dispatchPostAdmissionTurn<
1001
982
  adapters.resolveRunnerKnownFailure !== undefined && sessionFile !== ""
1002
983
  ? await adapters.resolveRunnerKnownFailure({ result, sessionFile })
1003
984
  : result.knownFailure;
1004
- const credentialFailure = postRunMissingCredentialFailure(
1005
- result,
1006
- env.model,
1007
- env.credentials,
1008
- );
1009
985
  resolution = await resolveAuditedRunnerFailureResolution({
1010
986
  runner: runnerKnownFailure,
1011
987
  sessionFile,
1012
- credential: credentialFailure,
988
+ credential: undefined,
1013
989
  runDirectory: admitted.runDirectory,
1014
990
  });
1015
991
  // A direct, current signal from the host/runner itself (timeout / host
@@ -1030,7 +1006,6 @@ export async function dispatchPostAdmissionTurn<
1030
1006
  result.timedOut
1031
1007
  || result.knownFailure !== undefined
1032
1008
  || runnerKnownFailure !== undefined
1033
- || credentialFailure !== undefined
1034
1009
  || processCancelName !== undefined;
1035
1010
  hostSignalFailed =
1036
1011
  directHostFailureSignal
@@ -1153,35 +1128,11 @@ export async function dispatchPostAdmissionTurn<
1153
1128
  try {
1154
1129
  await persistReturnedRunState(admitted, env.principalAuthority, { lawful: true });
1155
1130
  } catch (error) {
1156
- // #836: `settledOutcome.terminal` already carries recorded
1157
- // submissions (attachRecordedSubmissions above). A real run-state
1158
- // persistence failure here must surface loudly through the same
1159
- // controlled-failure seam every other dispatch-time failure in
1160
- // this function uses (ADR 0080: one settlement disposition owner)
1161
- // — not escape uncaught to auto-resume's dispatch-retry path,
1162
- // whose exhausted-budget terminal carries no recorded submissions
1163
- // at all. skipRunStateWrite: the write that just threw is the same
1164
- // write presentControlledFailure would otherwise retry — don't
1165
- // call a known-failing operation twice.
1166
- const failed = await settleAfterTurnStarted(
1167
- admitted,
1168
- withEngineDetourInvocationScope({
1169
- timedOut: false,
1170
- code: null,
1171
- stderr: "",
1172
- thrown: error,
1173
- skipRunStateWrite: true,
1174
- }, request.invocationScopeId),
1175
- adapters,
1176
- env.principalAuthority,
1131
+ await recordBestEffortPostDispatchDiagnostic(
1132
+ admitted,
1133
+ env,
1134
+ `run-state persistence failed beside host terminal (best-effort continue): ${describeErrorIdentity(error)}`,
1177
1135
  io,
1178
- persistRunState,
1179
- );
1180
- return await finishAfterTurn(
1181
- withProcessCancelSkipAutoResume(
1182
- { ...failed, turnDispatched: true as const, ...deferredPersist },
1183
- env.signal,
1184
- ),
1185
1136
  );
1186
1137
  }
1187
1138
  }
@@ -1282,30 +1233,11 @@ export async function dispatchPostAdmissionTurn<
1282
1233
  try {
1283
1234
  await persistReturnedRunState(admitted, env.principalAuthority, { lawful: true });
1284
1235
  } catch (error) {
1285
- // #836: same run-state persistence hazard as the settled/accepted
1286
- // branch above — route through the shared controlled-failure seam so
1287
- // the real failure surfaces loudly instead of escaping uncaught to
1288
- // auto-resume's dispatch-retry path with no recorded submissions.
1289
- // skipRunStateWrite: don't retry the write that just threw.
1290
- const failed = await settleAfterTurnStarted(
1236
+ await recordBestEffortPostDispatchDiagnostic(
1291
1237
  admitted,
1292
- withEngineDetourInvocationScope({
1293
- timedOut: false,
1294
- code: null,
1295
- stderr: "",
1296
- thrown: error,
1297
- skipRunStateWrite: true,
1298
- }, request.invocationScopeId),
1299
- adapters,
1300
- env.principalAuthority,
1238
+ env,
1239
+ `run-state persistence failed beside host terminal (best-effort continue): ${describeErrorIdentity(error)}`,
1301
1240
  io,
1302
- persistRunState,
1303
- );
1304
- return await finishAfterTurn(
1305
- withProcessCancelSkipAutoResume(
1306
- { ...failed, turnDispatched: true as const, ...deferredPersist },
1307
- env.signal,
1308
- ),
1309
1241
  );
1310
1242
  }
1311
1243
  }
@@ -1318,20 +1250,23 @@ export async function dispatchPostAdmissionTurn<
1318
1250
  ...deferredPersist,
1319
1251
  });
1320
1252
  } finally {
1321
- try {
1322
- await lease.release();
1323
- } catch (error) {
1324
- // lease.release() is documented best-effort and never rejects in the
1325
- // production acquireRunWriterLease implementation (createWriterLease
1326
- // reports cleanup failures via callback, never throws) — this guard is
1327
- // structural only: an uncaught throw from a finally block silently
1328
- // replaces whatever the try already returned, including a properly
1329
- // tagged turnDispatched:true result (#840 r9 判词 class 1 boundary).
1330
- io.stderr(
1331
- formatCliDiagnostic(
1332
- `writer lease release failed unexpectedly (best-effort continue): ${describeErrorIdentity(error)}`,
1333
- ),
1334
- );
1253
+ // Public manual resume (#987) holds no package writer lease.
1254
+ if (lease !== undefined) {
1255
+ try {
1256
+ await lease.release();
1257
+ } catch (error) {
1258
+ // lease.release() is documented best-effort and never rejects in the
1259
+ // production acquireRunWriterLease implementation (createWriterLease
1260
+ // reports cleanup failures via callback, never throws) — this guard is
1261
+ // structural only: an uncaught throw from a finally block silently
1262
+ // replaces whatever the try already returned, including a properly
1263
+ // tagged turnDispatched:true result (#840 r9 判词 class 1 boundary).
1264
+ io.stderr(
1265
+ formatCliDiagnostic(
1266
+ `writer lease release failed unexpectedly (best-effort continue): ${describeErrorIdentity(error)}`,
1267
+ ),
1268
+ );
1269
+ }
1335
1270
  }
1336
1271
  }
1337
1272
  }
@@ -1543,8 +1478,10 @@ export async function runPostAdmissionSeatResume<
1543
1478
  }): Promise<{ exitCode: number; admitted?: A; terminal?: T }> {
1544
1479
  let request = input.request;
1545
1480
 
1546
- // Load once for runDirectory / structural rejection / afterAdmittedLoad;
1547
- // court identity is judged only after the writer lease is held (below).
1481
+ // Load once for runDirectory / structural rejection / afterAdmittedLoad.
1482
+ // Court identity for public manual resume is judged in the turn builder
1483
+ // (#987: no package writer-lease gate before host CLI resume). Station-child
1484
+ // auto-resume still acquires the shared lease in runWithAutoResumeLoop.
1548
1485
  let loaded;
1549
1486
  try {
1550
1487
  loaded = await input.load(request);
@@ -1575,8 +1512,9 @@ export async function runPostAdmissionSeatResume<
1575
1512
 
1576
1513
  const buildRequestAfterLease = async (): Promise<RoleTurnRequest> => {
1577
1514
  let openCourtAttemptId: string | undefined;
1578
- // Build uses the admitted judged under this lease (rehydrated when open
1579
- // court materials ride). Settlement identity stays on the outer admitted.
1515
+ // Build uses the admitted for this resume (rehydrated when open court
1516
+ // materials ride). Settlement identity stays on the outer admitted.
1517
+ // Name kept for station-child callers that still build under lease.
1580
1518
  let admittedForBuild = loaded.admitted;
1581
1519
 
1582
1520
  // Bare resume: open-court pointer is the continue signal (not ledger seal).
@@ -1652,9 +1590,10 @@ export async function runPostAdmissionSeatResume<
1652
1590
  return turnRequest;
1653
1591
  };
1654
1592
 
1655
- // Court recovery / open under lease, then dispatch.
1593
+ // Court recovery / open, then dispatch. Public manual resume does not take a
1594
+ // package writer lease before the host CLI (#987 / ADR 0080 one-shot).
1656
1595
  // Station-child same-ticket/same-parent resume is call-local auto-resume
1657
- // (#840 / #416). Public `ak-role resume` stays one-shot (ADR 0080).
1596
+ // (#840 / #416) and still acquires the shared lease in its loop.
1658
1597
  // afterAdmittedPrepare runs inside this try so mint failure and cleanup share one finally.
1659
1598
  try {
1660
1599
  if (input.afterAdmittedPrepare !== undefined) {
@@ -1873,10 +1812,11 @@ export async function runPostAdmissionResumable<
1873
1812
  }
1874
1813
 
1875
1814
  /**
1876
- * Manual resume: lease + dispatch. Pass-through to the host — no sealed-accepted
1877
- * short-circuit (#833 / #416). Court open (summons / message / open court) is
1878
- * built under lease when using buildRequestAfterLease; sole-final stays per-attempt.
1879
- * After-lease build shares dispatchAfterWriterLease with station-child auto-resume.
1815
+ * Manual resume: pass-through to the host CLI resume — no package writer-lease
1816
+ * pre-gate (#987), no sealed-accepted short-circuit (#833 / #416). Court open
1817
+ * (summons / message / open court) is built when using buildRequestAfterLease;
1818
+ * sole-final stays per-attempt. Station-child auto-resume keeps shared lease
1819
+ * acquire in runWithAutoResumeLoop + dispatchAfterWriterLease.
1880
1820
  */
1881
1821
  export async function runPostAdmissionManualResume<
1882
1822
  A extends AdmittedRoleInvocation,
@@ -1885,9 +1825,9 @@ export async function runPostAdmissionManualResume<
1885
1825
  admitted: A;
1886
1826
  env: PostAdmissionEnv;
1887
1827
  io: CliIo;
1888
- /** Eager turn request (non-court path / seats that build before lease). */
1828
+ /** Eager turn request (non-court path / seats that build before dispatch). */
1889
1829
  request?: RoleTurnRequest;
1890
- /** After-lease builder (#637). Mutually exclusive with a prebuilt request. */
1830
+ /** Turn builder (#637). Mutually exclusive with a prebuilt request. */
1891
1831
  buildRequestAfterLease?: () => Promise<RoleTurnRequest>;
1892
1832
  adapters: PostAdmissionAdapters<A, T>;
1893
1833
  /** Seat-table engine axis on resume (#600). */
@@ -1896,7 +1836,6 @@ export async function runPostAdmissionManualResume<
1896
1836
  exitCode: number;
1897
1837
  admitted?: A;
1898
1838
  terminal?: T;
1899
- staleWriterLeaseReclaimed?: true;
1900
1839
  }> {
1901
1840
  const {
1902
1841
  admitted,
@@ -1910,67 +1849,34 @@ export async function runPostAdmissionManualResume<
1910
1849
  // #617 DK-3: manual resume writes the live seat/env model (same as new legs).
1911
1850
  const effectiveModel = env.model;
1912
1851
 
1913
- let lease: RunWriterLease;
1914
- let staleWriterLeaseReclaimed: true | undefined;
1915
- try {
1916
- lease = await acquireRunWriterLease(admitted.runDirectory, (diagnostic, kind?: WriterLeaseDiagnosticKind) => {
1917
- // Record the typed fact before the fallible sink: if io.stderr throws
1918
- // (acquire deliberately swallows diagnostic-sink failures), the reclaim
1919
- // still happened and must stay observable.
1920
- if (kind === "stale-reclaimed") staleWriterLeaseReclaimed = true;
1921
- io.stderr(diagnostic);
1922
- });
1923
- } catch (error) {
1924
- if (error instanceof RunWriterLeaseHeldError) {
1925
- io.stderr(formatCliDiagnostic(error.message));
1926
- // A held rejection after our own reclaim must still carry the fact that
1927
- // this caller reclaimed the stale lock — e.g. another resumer re-locked
1928
- // before our retry create (#629).
1929
- return {
1930
- exitCode: 1,
1931
- ...(staleWriterLeaseReclaimed === true
1932
- ? { staleWriterLeaseReclaimed: true as const }
1933
- : {}),
1934
- };
1935
- }
1936
- throw error;
1937
- }
1938
-
1939
1852
  // Explicit public resume is a new counting unit — mint once for this call.
1940
1853
  const invocationScopeId = mintEngineDetourInvocationScope({
1941
1854
  ...(effectiveEngine === undefined ? {} : { effectiveEngine }),
1942
1855
  });
1943
1856
 
1944
- const result = await dispatchAfterWriterLease({
1945
- lease,
1946
- build: async () => {
1947
- if (request === undefined) {
1948
- if (buildRequestAfterLease === undefined) {
1949
- throw new Error(
1950
- "runPostAdmissionManualResume requires request or buildRequestAfterLease",
1951
- );
1952
- }
1953
- request = await buildRequestAfterLease();
1954
- }
1955
- request = withEngineDetourInvocationScope(request, invocationScopeId);
1956
- return request;
1857
+ if (request === undefined) {
1858
+ if (buildRequestAfterLease === undefined) {
1859
+ throw new Error(
1860
+ "runPostAdmissionManualResume requires request or buildRequestAfterLease",
1861
+ );
1862
+ }
1863
+ request = await buildRequestAfterLease();
1864
+ }
1865
+ request = withEngineDetourInvocationScope(request, invocationScopeId);
1866
+
1867
+ const result = await dispatchPostAdmissionTurn({
1868
+ admitted,
1869
+ env: {
1870
+ ...env,
1871
+ ...(effectiveModel === undefined ? {} : { model: effectiveModel }),
1872
+ ...(admitted.correlationId === undefined
1873
+ ? {}
1874
+ : { correlationId: admitted.correlationId }),
1957
1875
  },
1958
- dispatch: (turnRequest) =>
1959
- dispatchPostAdmissionTurn({
1960
- admitted,
1961
- env: {
1962
- ...env,
1963
- ...(effectiveModel === undefined ? {} : { model: effectiveModel }),
1964
- ...(admitted.correlationId === undefined
1965
- ? {}
1966
- : { correlationId: admitted.correlationId }),
1967
- },
1968
- io,
1969
- request: turnRequest,
1970
- lease,
1971
- adapters,
1972
- ...(effectiveEngine === undefined ? {} : { effectiveEngine }),
1973
- }),
1876
+ io,
1877
+ request,
1878
+ adapters,
1879
+ ...(effectiveEngine === undefined ? {} : { effectiveEngine }),
1974
1880
  });
1975
1881
  if (
1976
1882
  result.terminal !== undefined &&
@@ -1986,10 +1892,5 @@ export async function runPostAdmissionManualResume<
1986
1892
  if (result.terminal !== undefined) {
1987
1893
  (result.terminal as { autoResumeCount?: number }).autoResumeCount = 0;
1988
1894
  }
1989
- return {
1990
- ...result,
1991
- ...(staleWriterLeaseReclaimed === true
1992
- ? { staleWriterLeaseReclaimed: true as const }
1993
- : {}),
1994
- };
1895
+ return result;
1995
1896
  }
@@ -1,49 +0,0 @@
1
- /**
2
- * Shared public-run credential seam: one owner for missing selected-provider
3
- * detection, typed failure construction, pre-dispatch fail-closed payload, and
4
- * post-run credential annotation. Role runners supply model/credential facts only.
5
- */
6
- import { missingPublicProviderCredential, } from "./config.js";
7
- /**
8
- * Production-owned provider failure when the selected public seat provider has
9
- * no configured credential. Cause/identity come from CredentialProviders, not
10
- * stderr wording. Runner-supplied knownFailure still wins over this annotation.
11
- */
12
- export function knownFailureForMissingProviderCredential(model, credentials) {
13
- if (model === undefined || credentials === undefined)
14
- return undefined;
15
- // Only the public credential catalog is fail-closed here; offline/test providers
16
- // are not represented in auth.json shape and must not be washed into MissingProviderCredential.
17
- if (model.provider !== "openai-codex" && model.provider !== "xai")
18
- return undefined;
19
- if (!missingPublicProviderCredential(model.provider, credentials)) {
20
- return undefined;
21
- }
22
- return {
23
- cause: "provider",
24
- identity: {
25
- name: "MissingProviderCredential",
26
- code: model.provider,
27
- },
28
- };
29
- }
30
- export function missingCredentialPreDispatchFailure(model, credentials) {
31
- const knownFailure = knownFailureForMissingProviderCredential(model, credentials);
32
- if (knownFailure === undefined)
33
- return undefined;
34
- return {
35
- timedOut: false,
36
- code: 1,
37
- stderr: `Missing credential for provider ${String(knownFailure.identity?.code ?? "unknown")}`,
38
- knownFailure,
39
- };
40
- }
41
- /**
42
- * Post-run credential annotation for the shared evidence-priority chain.
43
- * Only annotates nonzero/timeout exits; never invents a credential failure on success.
44
- */
45
- export function postRunMissingCredentialFailure(result, model, credentials) {
46
- if (!(result.timedOut || result.code !== 0))
47
- return undefined;
48
- return knownFailureForMissingProviderCredential(model, credentials);
49
- }
@@ -1,71 +0,0 @@
1
- /**
2
- * Shared public-run credential seam: one owner for missing selected-provider
3
- * detection, typed failure construction, pre-dispatch fail-closed payload, and
4
- * post-run credential annotation. Role runners supply model/credential facts only.
5
- */
6
- import {
7
- missingPublicProviderCredential,
8
- type CredentialProviders,
9
- type SeatModelConfig,
10
- } from "./config.ts";
11
- import type { RoleTurnKnownFailure } from "../host-contracts.ts";
12
-
13
- /**
14
- * Production-owned provider failure when the selected public seat provider has
15
- * no configured credential. Cause/identity come from CredentialProviders, not
16
- * stderr wording. Runner-supplied knownFailure still wins over this annotation.
17
- */
18
- export function knownFailureForMissingProviderCredential(
19
- model: SeatModelConfig | undefined,
20
- credentials: CredentialProviders | undefined,
21
- ): RoleTurnKnownFailure | undefined {
22
- if (model === undefined || credentials === undefined) return undefined;
23
- // Only the public credential catalog is fail-closed here; offline/test providers
24
- // are not represented in auth.json shape and must not be washed into MissingProviderCredential.
25
- if (model.provider !== "openai-codex" && model.provider !== "xai") return undefined;
26
- if (!missingPublicProviderCredential(model.provider, credentials)) {
27
- return undefined;
28
- }
29
- return {
30
- cause: "provider",
31
- identity: {
32
- name: "MissingProviderCredential",
33
- code: model.provider,
34
- },
35
- };
36
- }
37
-
38
- /** Pre-dispatch fail-closed payload when selected public provider lacks credentials. */
39
- export type MissingCredentialPreDispatchFailure = Readonly<{
40
- timedOut: false;
41
- code: 1;
42
- stderr: string;
43
- knownFailure: RoleTurnKnownFailure;
44
- }>;
45
-
46
- export function missingCredentialPreDispatchFailure(
47
- model: SeatModelConfig | undefined,
48
- credentials: CredentialProviders | undefined,
49
- ): MissingCredentialPreDispatchFailure | undefined {
50
- const knownFailure = knownFailureForMissingProviderCredential(model, credentials);
51
- if (knownFailure === undefined) return undefined;
52
- return {
53
- timedOut: false,
54
- code: 1,
55
- stderr: `Missing credential for provider ${String(knownFailure.identity?.code ?? "unknown")}`,
56
- knownFailure,
57
- };
58
- }
59
-
60
- /**
61
- * Post-run credential annotation for the shared evidence-priority chain.
62
- * Only annotates nonzero/timeout exits; never invents a credential failure on success.
63
- */
64
- export function postRunMissingCredentialFailure(
65
- result: Readonly<{ timedOut: boolean; code: number | null }>,
66
- model: SeatModelConfig | undefined,
67
- credentials: CredentialProviders | undefined,
68
- ): RoleTurnKnownFailure | undefined {
69
- if (!(result.timedOut || result.code !== 0)) return undefined;
70
- return knownFailureForMissingProviderCredential(model, credentials);
71
- }