@resolveio/server-lib 22.3.188 → 22.3.190

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@resolveio/server-lib",
3
- "version": "22.3.188",
3
+ "version": "22.3.190",
4
4
  "description": "",
5
5
  "scripts": {
6
6
  "package": "./build_package.sh",
@@ -67,7 +67,43 @@ export interface AssistantAnswerQualityDecision {
67
67
  failedChecks: string[];
68
68
  recordedAt: string;
69
69
  }
70
+ export type AssistantAnswerActionabilityStatus = 'ready_to_answer' | 'needs_query_repair' | 'needs_permission' | 'needs_no_data_verification' | 'needs_date_window_repair' | 'needs_query_shape_repair' | 'needs_evidence' | 'needs_confidence_review' | 'needs_next_action' | 'incorrect' | 'blocked';
71
+ export interface AssistantAnswerActionabilityContract {
72
+ contractId: string;
73
+ status: AssistantAnswerActionabilityStatus;
74
+ primaryCommand: string;
75
+ label: string;
76
+ canAnswerCustomer: boolean;
77
+ canDraftSupportReply: boolean;
78
+ canSendCustomerReply: boolean;
79
+ requiresHumanReview: boolean;
80
+ canRunWithoutCodexMonitor: boolean;
81
+ codexFallbackRequired: boolean;
82
+ costRisk: 'free_or_deterministic' | 'small_model_or_qa' | 'expensive_model' | 'release_or_customer_send' | 'manual_blocked';
83
+ queryResultClass: AssistantAnswerQualityDecision['queryStatus'];
84
+ confidenceLevel: AssistantAnswerQualityDecision['confidenceLevel'];
85
+ decisionBasis: {
86
+ answerQualityStatus: AssistantAnswerQualityStatus;
87
+ queryStatus: AssistantAnswerQualityDecision['queryStatus'];
88
+ queryEvidencePresent: boolean;
89
+ noDataConfirmed: boolean;
90
+ legalQueryShape: boolean;
91
+ dateWindowRequired: boolean;
92
+ dateWindowPresent: boolean;
93
+ citationCount: number;
94
+ nextActionCount: number;
95
+ };
96
+ requiredEvidence: string[];
97
+ successEvidence: string[];
98
+ blockers: string[];
99
+ nextActions: string[];
100
+ nextCommands: string[];
101
+ forbiddenActions: string[];
102
+ evidenceRefs: string[];
103
+ recordedAt: string;
104
+ }
70
105
  export declare function evaluateAssistantAnswerQuality(input?: AssistantAnswerQualityInput): AssistantAnswerQualityDecision;
106
+ export declare function buildAssistantAnswerActionabilityContract(decision: AssistantAnswerQualityDecision, now?: Date | string): AssistantAnswerActionabilityContract;
71
107
  export declare function buildSupportAIRunFromEvidence(input: SupportAIRunAdapterInput): AIRun;
72
108
  export declare function buildAICoderAIRunFromEvidence(input: AICoderAIRunAdapterInput): AIRun;
73
109
  export declare function buildAssistantAIRunFromEvidence(input: AssistantAIRunAdapterInput): AIRun;
@@ -48,6 +48,7 @@ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
48
48
  };
49
49
  Object.defineProperty(exports, "__esModule", { value: true });
50
50
  exports.evaluateAssistantAnswerQuality = evaluateAssistantAnswerQuality;
51
+ exports.buildAssistantAnswerActionabilityContract = buildAssistantAnswerActionabilityContract;
51
52
  exports.buildSupportAIRunFromEvidence = buildSupportAIRunFromEvidence;
52
53
  exports.buildAICoderAIRunFromEvidence = buildAICoderAIRunFromEvidence;
53
54
  exports.buildAssistantAIRunFromEvidence = buildAssistantAIRunFromEvidence;
@@ -2307,22 +2308,30 @@ function aicoderNextActionContractGate(contract, now) {
2307
2308
  var requiresHumanApproval = booleanFlag((_b = contract.requiresHumanApproval) !== null && _b !== void 0 ? _b : contract.requires_human_approval) === true;
2308
2309
  var canRunWithoutCodexMonitor = booleanFlag((_c = contract.canRunWithoutCodexMonitor) !== null && _c !== void 0 ? _c : contract.can_run_without_codex_monitor) === true;
2309
2310
  var codexFallbackRequired = booleanFlag((_d = contract.codexFallbackRequired) !== null && _d !== void 0 ? _d : contract.codex_fallback_required) === true;
2310
- var blockers = cleanStringList(contract.blockers, 40, 500);
2311
+ var sourceBlockers = cleanStringList(contract.blockers, 40, 500);
2311
2312
  var primaryCommand = cleanText(contract.primaryCommand || contract.primary_command, 200);
2312
- var gateStatus = canRunWithoutCodexMonitor
2313
- ? 'pass'
2314
- : requiresHumanApproval
2315
- ? 'blocked'
2316
- : codexFallbackRequired
2317
- ? 'warn'
2318
- : safeToAutoRun ? 'warn' : 'blocked';
2313
+ var liveHotfixBlockedUntilCommit = booleanFlag((_g = (_f = (_e = contract.liveHotfixBlockedUntilCommit) !== null && _e !== void 0 ? _e : contract.live_hotfix_blocked_until_commit) !== null && _f !== void 0 ? _f : plainObject(contract.decisionBasis || contract.decision_basis).liveHotfixBlockedUntilCommit) !== null && _g !== void 0 ? _g : plainObject(contract.decisionBasis || contract.decision_basis).live_hotfix_blocked_until_commit) === true;
2314
+ var safetyBlockers = Array.from(new Set(__spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray([], __read((safeToAutoRun ? [] : ['AICoder next action is not marked safe to auto-run.'])), false), __read((canRunWithoutCodexMonitor ? [] : ['AICoder next action requires Codex fallback/monitoring instead of manager-only execution.'])), false), __read((codexFallbackRequired ? [cleanText(contract.codexFallbackReason || contract.codex_fallback_reason, 1000) || 'AICoder next action contract requires Codex fallback.'] : [])), false), __read((requiresHumanApproval ? ['AICoder next action requires human approval.'] : [])), false), __read((liveHotfixBlockedUntilCommit ? ['Live AICoder hotfix is blocked until GitHub commit and push proof is recorded.'] : [])), false))).filter(Boolean).slice(0, 40);
2315
+ var contractBlockers = safetyBlockers.length
2316
+ ? Array.from(new Set(__spreadArray(__spreadArray([], __read(sourceBlockers), false), __read(safetyBlockers), false))).slice(0, 40)
2317
+ : [];
2318
+ var missingSafetyFlags = [
2319
+ contract.safeToAutoRun === undefined && contract.safe_to_auto_run === undefined ? 'safeToAutoRun' : '',
2320
+ contract.canRunWithoutCodexMonitor === undefined && contract.can_run_without_codex_monitor === undefined ? 'canRunWithoutCodexMonitor' : '',
2321
+ contract.codexFallbackRequired === undefined && contract.codex_fallback_required === undefined ? 'codexFallbackRequired' : ''
2322
+ ].filter(Boolean);
2323
+ var gateStatus = contractBlockers.length
2324
+ ? 'blocked'
2325
+ : missingSafetyFlags.length
2326
+ ? 'warn'
2327
+ : 'pass';
2319
2328
  return {
2320
2329
  key: 'aicoder_next_action_contract',
2321
2330
  label: 'AICoder next action contract',
2322
2331
  status: gateStatus,
2323
2332
  reason: gateStatus === 'pass'
2324
2333
  ? "AICoder can run ".concat(primaryCommand || 'the next action', " without a Codex monitor.")
2325
- : (blockers.join(' ') || cleanText(contract.codexFallbackReason || contract.codex_fallback_reason || contract.expectedStateTransition || contract.expected_state_transition, 1200) || 'AICoder next action is not safe to run unattended.'),
2334
+ : (contractBlockers.join(' ') || cleanText(contract.codexFallbackReason || contract.codex_fallback_reason || contract.expectedStateTransition || contract.expected_state_transition, 1200) || 'AICoder next action is not safe to run unattended.'),
2326
2335
  evidenceRefs: cleanStringList(__spreadArray(__spreadArray(__spreadArray([], __read(asArray(contract.preconditions)), false), __read(asArray(contract.successEvidence || contract.success_evidence)), false), __read(asArray(contract.stopConditions || contract.stop_conditions)), false), 40, 500),
2327
2336
  recordedAt: isoNow(now || contract.createdAt || contract.created_at || contract.recordedAt || contract.recorded_at),
2328
2337
  metadata: {
@@ -2338,9 +2347,9 @@ function aicoderNextActionContractGate(contract, now) {
2338
2347
  codexFallbackRequired: codexFallbackRequired,
2339
2348
  codexFallbackReason: cleanText(contract.codexFallbackReason || contract.codex_fallback_reason, 1000),
2340
2349
  costRisk: cleanText(contract.costRisk || contract.cost_risk, 120),
2341
- workflowFirstSatisfied: booleanFlag((_e = contract.workflowFirstSatisfied) !== null && _e !== void 0 ? _e : contract.workflow_first_satisfied) === true,
2342
- hotfixCommitRequired: booleanFlag((_h = (_g = (_f = contract.hotfixCommitRequired) !== null && _f !== void 0 ? _f : contract.hotfix_commit_required) !== null && _g !== void 0 ? _g : plainObject(contract.decisionBasis || contract.decision_basis).hotfixCommitRequired) !== null && _h !== void 0 ? _h : plainObject(contract.decisionBasis || contract.decision_basis).hotfix_commit_required) === true,
2343
- liveHotfixBlockedUntilCommit: booleanFlag((_l = (_k = (_j = contract.liveHotfixBlockedUntilCommit) !== null && _j !== void 0 ? _j : contract.live_hotfix_blocked_until_commit) !== null && _k !== void 0 ? _k : plainObject(contract.decisionBasis || contract.decision_basis).liveHotfixBlockedUntilCommit) !== null && _l !== void 0 ? _l : plainObject(contract.decisionBasis || contract.decision_basis).live_hotfix_blocked_until_commit) === true,
2350
+ workflowFirstSatisfied: booleanFlag((_h = contract.workflowFirstSatisfied) !== null && _h !== void 0 ? _h : contract.workflow_first_satisfied) === true,
2351
+ hotfixCommitRequired: booleanFlag((_l = (_k = (_j = contract.hotfixCommitRequired) !== null && _j !== void 0 ? _j : contract.hotfix_commit_required) !== null && _k !== void 0 ? _k : plainObject(contract.decisionBasis || contract.decision_basis).hotfixCommitRequired) !== null && _l !== void 0 ? _l : plainObject(contract.decisionBasis || contract.decision_basis).hotfix_commit_required) === true,
2352
+ liveHotfixBlockedUntilCommit: liveHotfixBlockedUntilCommit,
2344
2353
  decisionBasis: plainObject(contract.decisionBasis || contract.decision_basis),
2345
2354
  preconditions: cleanStringList(contract.preconditions, 40, 500),
2346
2355
  expectedStateTransition: cleanText(contract.expectedStateTransition || contract.expected_state_transition, 1000),
@@ -2349,7 +2358,10 @@ function aicoderNextActionContractGate(contract, now) {
2349
2358
  stopConditions: cleanStringList(contract.stopConditions || contract.stop_conditions, 40, 500),
2350
2359
  forbiddenActions: cleanStringList(contract.forbiddenActions || contract.forbidden_actions, 40, 500),
2351
2360
  nextCommands: cleanStringList(contract.nextCommands || contract.next_commands, 40, 240),
2352
- blockers: blockers,
2361
+ blockers: contractBlockers,
2362
+ contextBlockers: sourceBlockers,
2363
+ safetyBlockers: safetyBlockers,
2364
+ missingSafetyFlags: missingSafetyFlags,
2353
2365
  ownerFiles: cleanStringList(contract.ownerFiles || contract.owner_files, 40, 500)
2354
2366
  }
2355
2367
  };
@@ -2714,6 +2726,185 @@ function assistantAnswerQualityGate(decision, now) {
2714
2726
  }
2715
2727
  };
2716
2728
  }
2729
+ function assistantActionabilityStatus(decision) {
2730
+ switch (decision.status) {
2731
+ case 'ready':
2732
+ return 'ready_to_answer';
2733
+ case 'query_error':
2734
+ return 'needs_query_repair';
2735
+ case 'permission_error':
2736
+ return 'needs_permission';
2737
+ case 'no_data_unverified':
2738
+ return 'needs_no_data_verification';
2739
+ case 'date_incorrect':
2740
+ case 'missing_date_window':
2741
+ return 'needs_date_window_repair';
2742
+ case 'illegal_query_shape':
2743
+ return 'needs_query_shape_repair';
2744
+ case 'missing_data_source':
2745
+ case 'missing_query_proof':
2746
+ case 'missing_citations':
2747
+ return 'needs_evidence';
2748
+ case 'low_confidence':
2749
+ return 'needs_confidence_review';
2750
+ case 'missing_next_action':
2751
+ return 'needs_next_action';
2752
+ case 'incorrect':
2753
+ return 'incorrect';
2754
+ default:
2755
+ return 'blocked';
2756
+ }
2757
+ }
2758
+ function assistantActionabilityCommand(status) {
2759
+ switch (status) {
2760
+ case 'ready_to_answer':
2761
+ return 'answer_from_verified_system_data';
2762
+ case 'needs_query_repair':
2763
+ return 'repair_assistant_query_and_rerun';
2764
+ case 'needs_permission':
2765
+ return 'request_assistant_data_permission';
2766
+ case 'needs_no_data_verification':
2767
+ return 'verify_no_data_with_scoped_probe';
2768
+ case 'needs_date_window_repair':
2769
+ return 'repair_assistant_date_window_and_rerun';
2770
+ case 'needs_query_shape_repair':
2771
+ return 'repair_assistant_mongo_query_shape';
2772
+ case 'needs_confidence_review':
2773
+ return 'review_assistant_confidence_evidence';
2774
+ case 'needs_next_action':
2775
+ return 'add_assistant_next_action';
2776
+ case 'incorrect':
2777
+ return 'repair_assistant_answer_from_failed_check';
2778
+ case 'needs_evidence':
2779
+ case 'blocked':
2780
+ default:
2781
+ return 'collect_assistant_answer_evidence';
2782
+ }
2783
+ }
2784
+ function assistantActionabilityLabel(status) {
2785
+ switch (status) {
2786
+ case 'ready_to_answer':
2787
+ return 'Answer From Verified Data';
2788
+ case 'needs_query_repair':
2789
+ return 'Repair Query';
2790
+ case 'needs_permission':
2791
+ return 'Request Data Permission';
2792
+ case 'needs_no_data_verification':
2793
+ return 'Verify No Data';
2794
+ case 'needs_date_window_repair':
2795
+ return 'Repair Date Window';
2796
+ case 'needs_query_shape_repair':
2797
+ return 'Repair Query Shape';
2798
+ case 'needs_confidence_review':
2799
+ return 'Review Confidence';
2800
+ case 'needs_next_action':
2801
+ return 'Add Next Action';
2802
+ case 'incorrect':
2803
+ return 'Repair Incorrect Answer';
2804
+ default:
2805
+ return 'Collect Answer Evidence';
2806
+ }
2807
+ }
2808
+ function buildAssistantAnswerActionabilityContract(decision, now) {
2809
+ var status = assistantActionabilityStatus(decision);
2810
+ var primaryCommand = assistantActionabilityCommand(status);
2811
+ var ready = status === 'ready_to_answer';
2812
+ var noDataReady = ready && decision.queryStatus === 'no_data' && decision.noDataConfirmed;
2813
+ var canAnswerCustomer = ready && (decision.queryStatus === 'ok'
2814
+ || noDataReady
2815
+ || decision.queryEvidenceRequired === false);
2816
+ var canDraftSupportReply = canAnswerCustomer && decision.confidenceLevel === 'high';
2817
+ var requiresHumanReview = !canAnswerCustomer || canDraftSupportReply;
2818
+ var cheapRepair = /needs_(?:no_data|date_window|query_shape|next_action)|needs_evidence/.test(status);
2819
+ var blockers = decision.blockers.length
2820
+ ? decision.blockers
2821
+ : (ready ? [] : [decision.reason]);
2822
+ var requiredEvidence = Array.from(new Set(__spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray([], __read((decision.queryEvidenceRequired ? ['structured query/tool execution proof'] : [])), false), __read((decision.dateWindowRequired ? ['concrete date-window start and end'] : [])), false), __read((decision.queryStatus === 'no_data' ? ['noDataConfirmed=true from scoped probe or query evidence'] : [])), false), __read((decision.legalQueryShape ? [] : ['legal Mongo query/projection shape'])), false), __read((decision.citationRefs.length || decision.evidenceRefs.length ? [] : ['citationRefs or evidenceRefs'])), false), __read((decision.nextActions.length ? [] : ['one explicit next action or no-action state'])), false), __read((decision.confidenceLevel === 'low' || decision.confidenceLevel === 'unknown' ? ['medium/high confidence evidence'] : [])), false))).slice(0, 20);
2823
+ return {
2824
+ contractId: "assistant-actionability:".concat(decision.status, ":").concat(decision.queryStatus, ":").concat(decision.recordedAt),
2825
+ status: status,
2826
+ primaryCommand: primaryCommand,
2827
+ label: assistantActionabilityLabel(status),
2828
+ canAnswerCustomer: canAnswerCustomer,
2829
+ canDraftSupportReply: canDraftSupportReply,
2830
+ canSendCustomerReply: false,
2831
+ requiresHumanReview: requiresHumanReview,
2832
+ canRunWithoutCodexMonitor: ready || cheapRepair,
2833
+ codexFallbackRequired: !ready && !cheapRepair,
2834
+ costRisk: ready
2835
+ ? 'free_or_deterministic'
2836
+ : status === 'needs_permission'
2837
+ ? 'manual_blocked'
2838
+ : (status === 'needs_query_repair' || status === 'incorrect' ? 'small_model_or_qa' : 'free_or_deterministic'),
2839
+ queryResultClass: decision.queryStatus,
2840
+ confidenceLevel: decision.confidenceLevel,
2841
+ decisionBasis: {
2842
+ answerQualityStatus: decision.status,
2843
+ queryStatus: decision.queryStatus,
2844
+ queryEvidencePresent: decision.queryEvidencePresent,
2845
+ noDataConfirmed: decision.noDataConfirmed,
2846
+ legalQueryShape: decision.legalQueryShape,
2847
+ dateWindowRequired: decision.dateWindowRequired,
2848
+ dateWindowPresent: decision.dateWindowPresent,
2849
+ citationCount: decision.citationRefs.length + decision.evidenceRefs.length,
2850
+ nextActionCount: decision.nextActions.length
2851
+ },
2852
+ requiredEvidence: requiredEvidence,
2853
+ successEvidence: Array.from(new Set(__spreadArray(__spreadArray(__spreadArray(__spreadArray([], __read((ready ? ['assistant answer quality gate passed'] : [])), false), __read((decision.queryEvidenceRefs.length ? decision.queryEvidenceRefs : [])), false), __read((decision.citationRefs.length ? decision.citationRefs : [])), false), __read((decision.evidenceRefs.length ? decision.evidenceRefs : [])), false))).slice(0, 20),
2854
+ blockers: blockers,
2855
+ nextActions: decision.nextActions,
2856
+ nextCommands: Array.from(new Set(__spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray([
2857
+ primaryCommand
2858
+ ], __read((status === 'needs_query_repair' ? ['fix_query_error', 'rerun_assistant_query'] : [])), false), __read((status === 'needs_no_data_verification' ? ['run_tiny_shape_probe', 'record_no_data_confirmed'] : [])), false), __read((status === 'needs_date_window_repair' ? ['resolve_current_date', 'record_concrete_date_window', 'rerun_assistant_query'] : [])), false), __read((status === 'needs_query_shape_repair' ? ['rewrite_illegal_projection', 'rerun_query_shape_validator'] : [])), false), __read((status === 'needs_permission' ? ['request_permission_or_choose_allowed_route'] : [])), false), [
2859
+ 'record_assistant_actionability_result'
2860
+ ], false))).slice(0, 20),
2861
+ forbiddenActions: Array.from(new Set(__spreadArray(__spreadArray(__spreadArray(__spreadArray([
2862
+ 'Do not answer from keyword or route guesses without verified query evidence.',
2863
+ 'Do not claim no data when queryStatus is query_error or permission_error.'
2864
+ ], __read((decision.queryStatus === 'no_data' && !decision.noDataConfirmed ? ['Do not present no-data answer until noDataConfirmed=true.'] : [])), false), __read((decision.legalQueryShape ? [] : ['Do not answer from illegal Mongo projection/query shape.'])), false), __read((decision.dateWindowRequired && !decision.dateWindowPresent ? ['Do not answer dated questions without concrete start/end date evidence.'] : [])), false), __read((decision.confidenceLevel === 'low' || decision.confidenceLevel === 'unknown' ? ['Do not draft support/customer reply from low or unknown confidence.'] : [])), false))).slice(0, 20),
2865
+ evidenceRefs: Array.from(new Set(__spreadArray(__spreadArray(__spreadArray([], __read(decision.queryEvidenceRefs), false), __read(decision.citationRefs), false), __read(decision.evidenceRefs), false))).slice(0, 40),
2866
+ recordedAt: isoNow(now || decision.recordedAt)
2867
+ };
2868
+ }
2869
+ function assistantAnswerActionabilityGate(contract, now) {
2870
+ var status = contract.status === 'ready_to_answer'
2871
+ ? 'pass'
2872
+ : contract.status === 'incorrect' || contract.status === 'needs_query_shape_repair' || contract.status === 'needs_date_window_repair'
2873
+ ? 'fail'
2874
+ : 'blocked';
2875
+ return {
2876
+ key: 'assistant_answer_actionability',
2877
+ label: 'Assistant answer actionability',
2878
+ status: status,
2879
+ reason: status === 'pass'
2880
+ ? 'Assistant answer can proceed from verified structured evidence.'
2881
+ : (contract.blockers.join(' ') || 'Assistant answer is blocked until actionability evidence is complete.'),
2882
+ evidenceRefs: contract.evidenceRefs,
2883
+ recordedAt: isoNow(now || contract.recordedAt),
2884
+ metadata: {
2885
+ contractId: contract.contractId,
2886
+ status: contract.status,
2887
+ primaryCommand: contract.primaryCommand,
2888
+ label: contract.label,
2889
+ canAnswerCustomer: contract.canAnswerCustomer,
2890
+ canDraftSupportReply: contract.canDraftSupportReply,
2891
+ canSendCustomerReply: contract.canSendCustomerReply,
2892
+ requiresHumanReview: contract.requiresHumanReview,
2893
+ canRunWithoutCodexMonitor: contract.canRunWithoutCodexMonitor,
2894
+ codexFallbackRequired: contract.codexFallbackRequired,
2895
+ costRisk: contract.costRisk,
2896
+ queryResultClass: contract.queryResultClass,
2897
+ confidenceLevel: contract.confidenceLevel,
2898
+ decisionBasis: contract.decisionBasis,
2899
+ requiredEvidence: contract.requiredEvidence,
2900
+ successEvidence: contract.successEvidence,
2901
+ blockers: contract.blockers,
2902
+ nextActions: contract.nextActions,
2903
+ nextCommands: contract.nextCommands,
2904
+ forbiddenActions: contract.forbiddenActions
2905
+ }
2906
+ };
2907
+ }
2717
2908
  function applyAssistantAnswerQualityGate(qa, decision, now) {
2718
2909
  var gate = assistantAnswerQualityGate(decision, now);
2719
2910
  if (decision.ready) {
@@ -3418,6 +3609,16 @@ function buildAssistantAIRunFromEvidence(input) {
3418
3609
  recordedAt: answerQualityGate.recordedAt,
3419
3610
  metadata: answerQualityGate.metadata
3420
3611
  });
3612
+ var answerActionabilityContract = buildAssistantAnswerActionabilityContract(answerQualityDecision, input.now);
3613
+ var answerActionabilityGate = assistantAnswerActionabilityGate(answerActionabilityContract, input.now);
3614
+ pushEvent(events, {
3615
+ type: 'assistant_message',
3616
+ category: 'assistant_answer_actionability',
3617
+ message: answerActionabilityGate.reason,
3618
+ artifactPaths: answerActionabilityGate.evidenceRefs,
3619
+ recordedAt: answerActionabilityGate.recordedAt,
3620
+ metadata: answerActionabilityGate.metadata
3621
+ });
3421
3622
  var correctnessChecks = asArray(input.correctnessChecks);
3422
3623
  var hasPassedCorrectnessCheck = correctnessChecks.some(function (check) { return /^(pass|passed|success|ok)$/i.test(cleanText(check.status || (check.passed === true ? 'pass' : ''), 80)); });
3423
3624
  var correctnessEvidence = {
@@ -3461,6 +3662,7 @@ function buildAssistantAIRunFromEvidence(input) {
3461
3662
  startedAt: dateValue(conversation, ['startedAt', 'createdAt']),
3462
3663
  completedAt: dateValue(conversation, ['completedAt', 'closedAt', 'updatedAt']),
3463
3664
  events: events,
3665
+ gates: [answerActionabilityGate],
3464
3666
  qa: qa,
3465
3667
  cost: cost,
3466
3668
  rejected: failedReports.length > 0 || conversation.rejected === true,
@@ -3491,6 +3693,28 @@ function buildAssistantAIRunFromEvidence(input) {
3491
3693
  queryExecutionCount: answerQualityDecision.queryExecutionCount,
3492
3694
  nextActions: answerQualityDecision.nextActions,
3493
3695
  blockers: answerQualityDecision.blockers
3696
+ },
3697
+ answerActionability: {
3698
+ contractId: answerActionabilityContract.contractId,
3699
+ status: answerActionabilityContract.status,
3700
+ primaryCommand: answerActionabilityContract.primaryCommand,
3701
+ label: answerActionabilityContract.label,
3702
+ canAnswerCustomer: answerActionabilityContract.canAnswerCustomer,
3703
+ canDraftSupportReply: answerActionabilityContract.canDraftSupportReply,
3704
+ canSendCustomerReply: answerActionabilityContract.canSendCustomerReply,
3705
+ requiresHumanReview: answerActionabilityContract.requiresHumanReview,
3706
+ canRunWithoutCodexMonitor: answerActionabilityContract.canRunWithoutCodexMonitor,
3707
+ codexFallbackRequired: answerActionabilityContract.codexFallbackRequired,
3708
+ costRisk: answerActionabilityContract.costRisk,
3709
+ queryResultClass: answerActionabilityContract.queryResultClass,
3710
+ confidenceLevel: answerActionabilityContract.confidenceLevel,
3711
+ decisionBasis: answerActionabilityContract.decisionBasis,
3712
+ requiredEvidence: answerActionabilityContract.requiredEvidence,
3713
+ successEvidence: answerActionabilityContract.successEvidence,
3714
+ blockers: answerActionabilityContract.blockers,
3715
+ nextActions: answerActionabilityContract.nextActions,
3716
+ nextCommands: answerActionabilityContract.nextCommands,
3717
+ forbiddenActions: answerActionabilityContract.forbiddenActions
3494
3718
  }
3495
3719
  }
3496
3720
  });