@fabricorg/platform-host 8.5.0 → 8.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.cts CHANGED
@@ -1,4 +1,4 @@
1
- import { ActionDefinition, ActionId, ActionStatus, ActorType, AdapterCircuitBreakerProvider, AdapterImplementation, AgentActionPolicyDecision, AgentActionPolicyEvaluator, AgentActionRiskTier, AgentActionRoute, AssetEventEnvelope, EvidencePacketReference, ExecutionAttestation, ExecutionPrincipal, ExternalReconciliation, FabricRuntimeServices, GovernanceRuntimeEvidence, ModuleRegistry, MutationFootprint, MutationGovernanceResolver, PolicyObligation, PolicyObligationStatus, PolicyOutcome, RuntimePolicyDefinition, StagedInvocationRequest, canonicalJson } from "@fabricorg/platform";
1
+ import { ActionDefinition, ActionId, ActionStatus, ActorType, AdapterCircuitBreakerProvider, AdapterImplementation, AgentActionPolicyContext, AgentActionPolicyDecision, AgentActionRiskTier, AgentActionRoute, AssetEventEnvelope, EvidencePacketReference, ExecutionAttestation, ExecutionPrincipal, ExternalReconciliation, FabricRuntimeServices, GovernanceRuntimeEvidence, ModuleRegistry, MutationFootprint, MutationGovernanceResolver, PolicyObligation, PolicyObligationStatus, PolicyOutcome, RuntimePolicyDefinition, StagedInvocationRequest, canonicalJson } from "@fabricorg/platform";
2
2
  import { AssemblyLockfile } from "@fabricorg/assembly";
3
3
  //#region src/observability.d.ts
4
4
  /** Version of the vendor-neutral health/readiness contract. */
@@ -183,7 +183,7 @@ export interface IdempotencyConflict {
183
183
  code: "IDEMPOTENCY_CONFLICT";
184
184
  idempotencyKey: string;
185
185
  existingInvocationId: string;
186
- reasons: Array<"actor" | "authority_binding" | "action_version" | "parameters">;
186
+ reasons: Array<"actor" | "authority_binding" | "action_version" | "parameters" | "agent_proposal">;
187
187
  }
188
188
  export declare class IdempotencyConflictError extends Error {
189
189
  readonly conflict: IdempotencyConflict;
@@ -276,7 +276,21 @@ export interface StagedInvocationOrigin {
276
276
  parentInvocationId: string;
277
277
  stageKey: string;
278
278
  }
279
+ export interface AgentProposal {
280
+ confidence?: number;
281
+ riskTier?: AgentActionRiskTier;
282
+ agentSessionId?: string;
283
+ agentRunId?: string;
284
+ reason?: string;
285
+ evidence?: ApprovalEvidence;
286
+ }
287
+ export interface HostHitlEvaluatorContext extends AgentActionPolicyContext {
288
+ actionInvocationId: string;
289
+ /** The durable (post-redaction) invocation record as read before evaluation. */
290
+ invocation: Readonly<ActionInvocationRecord>;
291
+ }
279
292
  export interface ActionInvocationRecord {
293
+ readonly agentProposal?: AgentProposal;
280
294
  id: string;
281
295
  tenantId: string;
282
296
  spaceId: string;
@@ -1335,9 +1349,12 @@ export interface PlatformActionDispatcher {
1335
1349
  * `provenance` and `authorizationBinding` are also read once there and
1336
1350
  * replaced by Host's own copies. For any other action Host uses those three
1337
1351
  * as the caller's objects, read where and as often as before (README,
1338
- * "Submission snapshot").
1352
+ * "Submission snapshot"). `agentProposal` is read once and deeply copied before
1353
+ * the first await for all actions, independently of `admitSubmission`.
1339
1354
  */
1340
1355
  export interface SubmitActionInput {
1356
+ /** Read once and deeply copied before the first await, regardless of admission. */
1357
+ agentProposal?: AgentProposal;
1341
1358
  actionId: ActionId;
1342
1359
  parameters: Record<string, unknown>;
1343
1360
  tenantId: string;
@@ -1550,7 +1567,7 @@ export interface PlatformHostOptions<TDb> {
1550
1567
  shouldPublish?(event: AssetEventEnvelope): boolean;
1551
1568
  };
1552
1569
  /** Optional vertical-owned evaluator. When absent, agent behavior is unchanged. */
1553
- hitlEvaluator?: (context: Parameters<AgentActionPolicyEvaluator>[0]) => HostHitlDecision | Promise<HostHitlDecision>;
1570
+ hitlEvaluator?: (context: HostHitlEvaluatorContext) => HostHitlDecision | Promise<HostHitlDecision>;
1554
1571
  /** Positive integer milliseconds, used when the evaluator supplies no absolute deadline. */
1555
1572
  approvalDefaultTtlMs?: number;
1556
1573
  /** Atomic approval lifecycle events and outbox writes; defaults to false. */
@@ -1607,6 +1624,8 @@ export interface PlatformHostOptions<TDb> {
1607
1624
  * copy, after the check admitted the submission.
1608
1625
  */
1609
1626
  redactActionParameters?: (actionId: ActionId, parameters: Record<string, unknown>) => Record<string, unknown>;
1627
+ /** Runs beside parameter redaction; output is validated and copied before persistence. */
1628
+ redactAgentProposal?: (actionId: ActionId, proposal: AgentProposal) => AgentProposal;
1610
1629
  /**
1611
1630
  * The bound on an action's `admitSubmission` check. An answer that
1612
1631
  * settles this many milliseconds or more after the check was called,
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { ActionDefinition, ActionId, ActionStatus, ActorType, AdapterCircuitBreakerProvider, AdapterImplementation, AgentActionPolicyDecision, AgentActionPolicyEvaluator, AgentActionRiskTier, AgentActionRoute, AssetEventEnvelope, EvidencePacketReference, ExecutionAttestation, ExecutionPrincipal, ExternalReconciliation, FabricRuntimeServices, GovernanceRuntimeEvidence, ModuleRegistry, MutationFootprint, MutationGovernanceResolver, PolicyObligation, PolicyObligationStatus, PolicyOutcome, RuntimePolicyDefinition, StagedInvocationRequest, canonicalJson } from "@fabricorg/platform";
1
+ import { ActionDefinition, ActionId, ActionStatus, ActorType, AdapterCircuitBreakerProvider, AdapterImplementation, AgentActionPolicyContext, AgentActionPolicyDecision, AgentActionRiskTier, AgentActionRoute, AssetEventEnvelope, EvidencePacketReference, ExecutionAttestation, ExecutionPrincipal, ExternalReconciliation, FabricRuntimeServices, GovernanceRuntimeEvidence, ModuleRegistry, MutationFootprint, MutationGovernanceResolver, PolicyObligation, PolicyObligationStatus, PolicyOutcome, RuntimePolicyDefinition, StagedInvocationRequest, canonicalJson } from "@fabricorg/platform";
2
2
  import { AssemblyLockfile } from "@fabricorg/assembly";
3
3
  //#region src/observability.d.ts
4
4
  /** Version of the vendor-neutral health/readiness contract. */
@@ -183,7 +183,7 @@ export interface IdempotencyConflict {
183
183
  code: "IDEMPOTENCY_CONFLICT";
184
184
  idempotencyKey: string;
185
185
  existingInvocationId: string;
186
- reasons: Array<"actor" | "authority_binding" | "action_version" | "parameters">;
186
+ reasons: Array<"actor" | "authority_binding" | "action_version" | "parameters" | "agent_proposal">;
187
187
  }
188
188
  export declare class IdempotencyConflictError extends Error {
189
189
  readonly conflict: IdempotencyConflict;
@@ -276,7 +276,21 @@ export interface StagedInvocationOrigin {
276
276
  parentInvocationId: string;
277
277
  stageKey: string;
278
278
  }
279
+ export interface AgentProposal {
280
+ confidence?: number;
281
+ riskTier?: AgentActionRiskTier;
282
+ agentSessionId?: string;
283
+ agentRunId?: string;
284
+ reason?: string;
285
+ evidence?: ApprovalEvidence;
286
+ }
287
+ export interface HostHitlEvaluatorContext extends AgentActionPolicyContext {
288
+ actionInvocationId: string;
289
+ /** The durable (post-redaction) invocation record as read before evaluation. */
290
+ invocation: Readonly<ActionInvocationRecord>;
291
+ }
279
292
  export interface ActionInvocationRecord {
293
+ readonly agentProposal?: AgentProposal;
280
294
  id: string;
281
295
  tenantId: string;
282
296
  spaceId: string;
@@ -1335,9 +1349,12 @@ export interface PlatformActionDispatcher {
1335
1349
  * `provenance` and `authorizationBinding` are also read once there and
1336
1350
  * replaced by Host's own copies. For any other action Host uses those three
1337
1351
  * as the caller's objects, read where and as often as before (README,
1338
- * "Submission snapshot").
1352
+ * "Submission snapshot"). `agentProposal` is read once and deeply copied before
1353
+ * the first await for all actions, independently of `admitSubmission`.
1339
1354
  */
1340
1355
  export interface SubmitActionInput {
1356
+ /** Read once and deeply copied before the first await, regardless of admission. */
1357
+ agentProposal?: AgentProposal;
1341
1358
  actionId: ActionId;
1342
1359
  parameters: Record<string, unknown>;
1343
1360
  tenantId: string;
@@ -1550,7 +1567,7 @@ export interface PlatformHostOptions<TDb> {
1550
1567
  shouldPublish?(event: AssetEventEnvelope): boolean;
1551
1568
  };
1552
1569
  /** Optional vertical-owned evaluator. When absent, agent behavior is unchanged. */
1553
- hitlEvaluator?: (context: Parameters<AgentActionPolicyEvaluator>[0]) => HostHitlDecision | Promise<HostHitlDecision>;
1570
+ hitlEvaluator?: (context: HostHitlEvaluatorContext) => HostHitlDecision | Promise<HostHitlDecision>;
1554
1571
  /** Positive integer milliseconds, used when the evaluator supplies no absolute deadline. */
1555
1572
  approvalDefaultTtlMs?: number;
1556
1573
  /** Atomic approval lifecycle events and outbox writes; defaults to false. */
@@ -1607,6 +1624,8 @@ export interface PlatformHostOptions<TDb> {
1607
1624
  * copy, after the check admitted the submission.
1608
1625
  */
1609
1626
  redactActionParameters?: (actionId: ActionId, parameters: Record<string, unknown>) => Record<string, unknown>;
1627
+ /** Runs beside parameter redaction; output is validated and copied before persistence. */
1628
+ redactAgentProposal?: (actionId: ActionId, proposal: AgentProposal) => AgentProposal;
1610
1629
  /**
1611
1630
  * The bound on an action's `admitSubmission` check. An answer that
1612
1631
  * settles this many milliseconds or more after the check was called,
package/dist/index.js CHANGED
@@ -296,6 +296,52 @@ async function appendLifecycleEvent(transaction, factory, invocation, kind) {
296
296
  }, metadata);
297
297
  }
298
298
  //#endregion
299
+ //#region src/agent-proposal.ts
300
+ /** Validate without invoking getters or retaining caller-owned evidence. */
301
+ function snapshotAgentProposal(value) {
302
+ const invalid = () => {
303
+ throw new Error("Invalid agent proposal.");
304
+ };
305
+ if (!value || typeof value !== "object" || Array.isArray(value) || types.isProxy(value)) return invalid();
306
+ if (Object.getPrototypeOf(value) !== Object.prototype && Object.getPrototypeOf(value) !== null) return invalid();
307
+ const allowed = [
308
+ "confidence",
309
+ "riskTier",
310
+ "agentSessionId",
311
+ "agentRunId",
312
+ "reason",
313
+ "evidence"
314
+ ];
315
+ for (const key of Reflect.ownKeys(value)) {
316
+ const descriptor = Object.getOwnPropertyDescriptor(value, key);
317
+ if (typeof key !== "string" || !allowed.includes(key) || !descriptor.enumerable || !Object.hasOwn(descriptor, "value")) return invalid();
318
+ }
319
+ if (value.confidence !== void 0 && (typeof value.confidence !== "number" || !Number.isFinite(value.confidence))) return invalid();
320
+ if (value.riskTier !== void 0 && ![
321
+ "low",
322
+ "medium",
323
+ "high"
324
+ ].includes(value.riskTier)) return invalid();
325
+ for (const key of [
326
+ "agentSessionId",
327
+ "agentRunId",
328
+ "reason"
329
+ ]) {
330
+ const field = value[key];
331
+ if (field !== void 0 && (typeof field !== "string" || field.length > (key === "reason" ? 4096 : 256) || key !== "reason" && field.trim().length === 0)) return invalid();
332
+ }
333
+ const evidence = snapshotApprovalDecision({
334
+ approved: true,
335
+ approverId: "proposal",
336
+ approverType: "agent",
337
+ ...value.evidence !== void 0 ? { evidence: value.evidence } : {}
338
+ }).evidence;
339
+ return {
340
+ ...value,
341
+ ...evidence !== void 0 ? { evidence } : {}
342
+ };
343
+ }
344
+ //#endregion
299
345
  //#region src/command-identity.ts
300
346
  const PARAMETER_DIGEST_ALGORITHM = "fabric-canonical-json-sha256-v1";
301
347
  function digestParameters(parameters) {
@@ -1001,7 +1047,11 @@ function snapshotSubmission(input) {
1001
1047
  const executionReason = scalar("executionReason");
1002
1048
  const idempotencyKey = scalar("idempotencyKey");
1003
1049
  const authorizationBindingId = scalar("authorizationBindingId");
1050
+ const proposal = input.agentProposal;
1051
+ if (proposal !== void 0 && actorType !== "agent") throw new Error("Agent proposal requires an agent actor.");
1052
+ const agentProposal = proposal === void 0 ? void 0 : snapshotAgentProposal(proposal);
1004
1053
  const live = {
1054
+ ...agentProposal !== void 0 ? { agentProposal } : {},
1005
1055
  actionId,
1006
1056
  tenantId,
1007
1057
  spaceId,
@@ -1070,6 +1120,7 @@ function privateSubmission(snapshot) {
1070
1120
  const provenance = provenanceRead ? copyProvenance(provenanceRead) : void 0;
1071
1121
  const authorizationBinding = bindingRead ? copyBinding(bindingRead) : void 0;
1072
1122
  return Object.freeze({
1123
+ ...snapshot.agentProposal !== void 0 ? { agentProposal: snapshot.agentProposal } : {},
1073
1124
  actionId: snapshot.actionId,
1074
1125
  tenantId: snapshot.tenantId,
1075
1126
  spaceId: snapshot.spaceId,
@@ -1166,6 +1217,7 @@ function parametersCopy(snapshot) {
1166
1217
  */
1167
1218
  function liveSubmissionView(snapshot, input) {
1168
1219
  const view = {
1220
+ ...snapshot.agentProposal !== void 0 ? { agentProposal: snapshotAgentProposal(snapshot.agentProposal) } : {},
1169
1221
  actionId: snapshot.actionId,
1170
1222
  tenantId: snapshot.tenantId,
1171
1223
  spaceId: snapshot.spaceId,
@@ -1207,6 +1259,7 @@ function submissionView(snapshot) {
1207
1259
  const provenance = fresh(snapshot.provenance);
1208
1260
  const authorizationBinding = fresh(snapshot.authorizationBinding);
1209
1261
  return {
1262
+ ...snapshot.agentProposal !== void 0 ? { agentProposal: snapshotAgentProposal(snapshot.agentProposal) } : {},
1210
1263
  actionId: snapshot.actionId,
1211
1264
  parameters: parametersCopy(snapshot),
1212
1265
  tenantId: snapshot.tenantId,
@@ -1543,7 +1596,8 @@ function createGovernedActionHost(options) {
1543
1596
  if (submission.authorizationBinding) validateAuthorizationBinding(submission, parameterDigest, action.execution?.authorityMoment, now());
1544
1597
  return {
1545
1598
  durableParameters,
1546
- parameterDigest
1599
+ parameterDigest,
1600
+ agentProposal: submission.agentProposal === void 0 ? void 0 : snapshotAgentProposal(options.redactAgentProposal ? options.redactAgentProposal(submission.actionId, submission.agentProposal) : submission.agentProposal)
1547
1601
  };
1548
1602
  };
1549
1603
  const early = declaresAdmission ? void 0 : prepare();
@@ -1558,9 +1612,10 @@ function createGovernedActionHost(options) {
1558
1612
  };
1559
1613
  assertGovernanceRuntimeEvidence(runtimeEvidence);
1560
1614
  const admission = declaresAdmission ? await admitSubmission(action, submission) : void 0;
1561
- const { durableParameters, parameterDigest } = early ?? prepare();
1615
+ const { durableParameters, parameterDigest, agentProposal } = early ?? prepare();
1562
1616
  const invocationInput = {
1563
1617
  id: actionInvocationId,
1618
+ ...agentProposal !== void 0 ? { agentProposal } : {},
1564
1619
  tenantId: submission.tenantId,
1565
1620
  spaceId: submission.spaceId,
1566
1621
  actionId: submission.actionId,
@@ -1614,6 +1669,7 @@ function createGovernedActionHost(options) {
1614
1669
  });
1615
1670
  if (durableInvocation.id !== actionInvocationId && submission.idempotencyKey) {
1616
1671
  const conflict = idempotencyConflict(durableInvocation, {
1672
+ agentProposal,
1617
1673
  actorId: submission.actorId,
1618
1674
  authorizationBindingId: submission.authorizationBindingId,
1619
1675
  actionVersion: action.version,
@@ -2335,21 +2391,24 @@ function createGovernedActionHost(options) {
2335
2391
  }
2336
2392
  if (invocation.actorType === "agent" && options.hitlEvaluator) {
2337
2393
  const hitlParameters = isRecord(parsed.data) ? parsed.data : invocation.parameters;
2394
+ const proposal = invocation.agentProposal;
2338
2395
  const approvalStore = asApprovalStore(options.store);
2339
2396
  if (!approvalStore) return hostOperation(() => failExecution(invocation, "failed", "The configured HITL evaluator requires a store with approval persistence support."));
2340
2397
  let evaluatedApprovalExpiresAt;
2341
2398
  if (!invocation.hitlRoute) {
2342
2399
  const decision = await options.hitlEvaluator({
2400
+ actionInvocationId: invocation.id,
2401
+ invocation,
2343
2402
  actionId: action.actionId,
2344
2403
  actorId: invocation.actorId,
2345
2404
  actorType: invocation.actorType,
2346
2405
  tenantId,
2347
2406
  spaceId,
2348
2407
  parameters: hitlParameters,
2349
- ...numberValue(hitlParameters.confidence) !== void 0 ? { confidence: numberValue(hitlParameters.confidence) } : {},
2350
- ...isRiskTier(hitlParameters.riskTier) ? { riskTier: hitlParameters.riskTier } : {},
2351
- ...stringValue(hitlParameters.agentSessionId) ? { agentSessionId: stringValue(hitlParameters.agentSessionId) } : {},
2352
- ...stringValue(hitlParameters.agentRunId) ? { agentRunId: stringValue(hitlParameters.agentRunId) } : {}
2408
+ ...(proposal?.confidence ?? numberValue(hitlParameters.confidence)) !== void 0 ? { confidence: proposal?.confidence ?? numberValue(hitlParameters.confidence) } : {},
2409
+ ...isRiskTier(proposal?.riskTier ?? hitlParameters.riskTier) ? { riskTier: proposal?.riskTier ?? hitlParameters.riskTier } : {},
2410
+ ...proposal?.agentSessionId ?? stringValue(hitlParameters.agentSessionId) ? { agentSessionId: proposal?.agentSessionId ?? stringValue(hitlParameters.agentSessionId) } : {},
2411
+ ...proposal?.agentRunId ?? stringValue(hitlParameters.agentRunId) ? { agentRunId: proposal?.agentRunId ?? stringValue(hitlParameters.agentRunId) } : {}
2353
2412
  });
2354
2413
  if (decision.approvalExpiresAt !== void 0 && !validApprovalDate(decision.approvalExpiresAt)) return hostOperation(() => failExecution(invocation, "failed", "approvalExpiresAt must be a valid Date."));
2355
2414
  evaluatedApprovalExpiresAt = decision.approvalExpiresAt === void 0 ? void 0 : new Date(decision.approvalExpiresAt);
@@ -4313,6 +4372,7 @@ function validateAuthorizationBinding(input, parameterDigest, authorityMoment, c
4313
4372
  }
4314
4373
  function idempotencyConflict(existing, incoming) {
4315
4374
  const reasons = [];
4375
+ if (canonicalJson(existing.agentProposal ?? null) !== canonicalJson(incoming.agentProposal ?? null)) reasons.push("agent_proposal");
4316
4376
  if ((existing.idempotencyActorId ?? existing.actorId) !== incoming.actorId) reasons.push("actor");
4317
4377
  if ((existing.idempotencyAuthorizationBindingId ?? existing.authorizationBindingId) !== incoming.authorizationBindingId) reasons.push("authority_binding");
4318
4378
  if (existing.actionVersion !== incoming.actionVersion) reasons.push("action_version");
@@ -5618,6 +5678,11 @@ var PostgresPlatformHostStore = class PostgresPlatformHostStore {
5618
5678
  ON fabric_platform.action_invocations (approval_expires_at, id)
5619
5679
  WHERE status='waiting_for_approval' AND approval_expires_at IS NOT NULL;
5620
5680
  `
5681
+ },
5682
+ {
5683
+ version: 13,
5684
+ name: "agent_proposal",
5685
+ sql: `ALTER TABLE fabric_platform.action_invocations ADD COLUMN IF NOT EXISTS agent_proposal jsonb;`
5621
5686
  }
5622
5687
  ]);
5623
5688
  }
@@ -5629,6 +5694,8 @@ var PostgresPlatformHostStore = class PostgresPlatformHostStore {
5629
5694
  const admitted = input.admittedAt !== void 0;
5630
5695
  const admittedColumn = admitted ? "admitted_at," : "";
5631
5696
  const admittedValue = admitted ? "$25," : "";
5697
+ const proposalColumn = input.agentProposal !== void 0 ? "agent_proposal," : "";
5698
+ const proposalValue = input.agentProposal !== void 0 ? `$${admitted ? 26 : 25}::jsonb,` : "";
5632
5699
  let result;
5633
5700
  try {
5634
5701
  result = await this.sql.query(`INSERT INTO fabric_platform.action_invocations
@@ -5636,8 +5703,8 @@ var PostgresPlatformHostStore = class PostgresPlatformHostStore {
5636
5703
  parameters,result,correlation_id,causation_id,idempotency_key,
5637
5704
  parameter_digest,parameter_digest_algorithm,idempotency_actor_id,
5638
5705
  idempotency_authorization_binding_id,invocation_provenance,authorization_binding,execution_reason,
5639
- authorization_binding_id,error,runtime_evidence,${admittedColumn}created_at,updated_at)
5640
- VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9::jsonb,$10::jsonb,$11,$12,$13,$14,$15,$16,$17,$18::jsonb,$19::jsonb,$20,$21,$22,$23::jsonb,${admittedValue}$24,$24)
5706
+ authorization_binding_id,error,runtime_evidence,${admittedColumn}${proposalColumn}created_at,updated_at)
5707
+ VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9::jsonb,$10::jsonb,$11,$12,$13,$14,$15,$16,$17,$18::jsonb,$19::jsonb,$20,$21,$22,$23::jsonb,${admittedValue}${proposalValue}$24,$24)
5641
5708
  ON CONFLICT (tenant_id,space_id,action_id,idempotency_key)
5642
5709
  WHERE idempotency_key IS NOT NULL DO UPDATE SET id=fabric_platform.action_invocations.id
5643
5710
  RETURNING *`, [
@@ -5665,9 +5732,11 @@ var PostgresPlatformHostStore = class PostgresPlatformHostStore {
5665
5732
  input.error ?? null,
5666
5733
  input.runtimeEvidence ? JSON.stringify(input.runtimeEvidence) : null,
5667
5734
  now,
5668
- ...admitted ? [input.admittedAt] : []
5735
+ ...admitted ? [input.admittedAt] : [],
5736
+ ...input.agentProposal !== void 0 ? [JSON.stringify(input.agentProposal)] : []
5669
5737
  ]);
5670
5738
  } catch (error) {
5739
+ if (input.agentProposal !== void 0 && error?.code === "42703") throw new Error("Agent proposals require PostgreSQL migration 13 (agent_proposal); run ensureSchema().", { cause: error });
5671
5740
  if (admitted && error?.code === "42703") throw new Error("An admitted invocation needs the action_invocations.admitted_at column; run ensureSchema() to apply PostgreSQL migration 6 (invocation_admission) before submitting actions that declare admitSubmission.", { cause: error });
5672
5741
  throw error;
5673
5742
  }
@@ -5679,6 +5748,8 @@ var PostgresPlatformHostStore = class PostgresPlatformHostStore {
5679
5748
  const admitted = invocation.admittedAt !== void 0;
5680
5749
  const admittedColumn = admitted ? ",admitted_at" : "";
5681
5750
  const admittedValue = admitted ? ",$30" : "";
5751
+ const proposalColumn = invocation.agentProposal !== void 0 ? ",agent_proposal" : "";
5752
+ const proposalValue = invocation.agentProposal !== void 0 ? `,$${admitted ? 31 : 30}::jsonb` : "";
5682
5753
  const values = [
5683
5754
  invocation.id,
5684
5755
  invocation.tenantId,
@@ -5709,7 +5780,8 @@ var PostgresPlatformHostStore = class PostgresPlatformHostStore {
5709
5780
  input.workerId,
5710
5781
  input.leaseToken,
5711
5782
  current,
5712
- ...admitted ? [invocation.admittedAt] : []
5783
+ ...admitted ? [invocation.admittedAt] : [],
5784
+ ...invocation.agentProposal !== void 0 ? [JSON.stringify(invocation.agentProposal)] : []
5713
5785
  ];
5714
5786
  let result;
5715
5787
  try {
@@ -5727,15 +5799,16 @@ var PostgresPlatformHostStore = class PostgresPlatformHostStore {
5727
5799
  parameters,result,correlation_id,causation_id,idempotency_key,parameter_digest,
5728
5800
  parameter_digest_algorithm,idempotency_actor_id,idempotency_authorization_binding_id,
5729
5801
  invocation_provenance,authorization_binding,execution_reason,authorization_binding_id,error,
5730
- runtime_evidence,staged_parent_invocation_id,staged_stage_key${admittedColumn},created_at,updated_at)
5802
+ runtime_evidence,staged_parent_invocation_id,staged_stage_key${admittedColumn}${proposalColumn},created_at,updated_at)
5731
5803
  SELECT $1,$2,$3,$4,$5,$6,$7,$8,$9::jsonb,$10::jsonb,$11,$12,$13,$14,$15,$16,$17,
5732
- $18::jsonb,$19::jsonb,$20,$21,$22,$23::jsonb,$24,$25${admittedValue},$29,$29
5804
+ $18::jsonb,$19::jsonb,$20,$21,$22,$23::jsonb,$24,$25${admittedValue}${proposalValue},$29,$29
5733
5805
  FROM fence
5734
5806
  ON CONFLICT (tenant_id,space_id,staged_parent_invocation_id,staged_stage_key)
5735
5807
  WHERE staged_parent_invocation_id IS NOT NULL AND staged_stage_key IS NOT NULL
5736
5808
  DO UPDATE SET id=fabric_platform.action_invocations.id
5737
5809
  RETURNING *`, values);
5738
5810
  } catch (error) {
5811
+ if (invocation.agentProposal !== void 0 && error?.code === "42703") throw new Error("Agent proposals require PostgreSQL migration 13 (agent_proposal); run ensureSchema().", { cause: error });
5739
5812
  if (error?.code === "42703" || error?.code === "42P01") throw new Error("A staged child needs PostgreSQL migration 11 (staged_descendant_invocations); run ensureSchema() before dispatching staged invocations.", { cause: error });
5740
5813
  throw error;
5741
5814
  }
@@ -6855,6 +6928,7 @@ function toActionRecord(row) {
6855
6928
  ...row.mutation_footprint ? { mutationFootprint: row.mutation_footprint } : {},
6856
6929
  ...row.execution_principal ? { executionPrincipal: row.execution_principal } : {},
6857
6930
  ...row.runtime_evidence ? { runtimeEvidence: row.runtime_evidence } : {},
6931
+ ...row.agent_proposal != null ? { agentProposal: row.agent_proposal } : {},
6858
6932
  ...row.admitted_at ? { admittedAt: new Date(row.admitted_at) } : {},
6859
6933
  ...row.error ? { error: String(row.error) } : {},
6860
6934
  createdAt: new Date(row.created_at),