@resolveio/server-lib 22.3.193 → 22.3.194

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.
@@ -255,6 +255,44 @@ export interface ResolveIOSupportClarificationContract {
255
255
  requiredEvidence: string[];
256
256
  createdAt: string;
257
257
  }
258
+ export type ResolveIOSupportCustomerReplyReadinessStatus = 'draft_ready' | 'clarification_required' | 'blocked_until_diagnosis' | 'blocked_until_probe_plan' | 'blocked_until_confidence' | 'blocked_until_runner_blocker' | 'blocked_until_release_hotfix' | 'blocked_until_business_proof' | 'blocked_until_business_proof_artifact' | 'blocked_until_human_approval' | 'internal_blocked';
259
+ export interface ResolveIOSupportCustomerReplyReadinessContract {
260
+ contractId: string;
261
+ status: ResolveIOSupportCustomerReplyReadinessStatus;
262
+ policyAction: ResolveIOSupportCustomerReplyAction;
263
+ reviewType: ResolveIOSupportHumanReviewType;
264
+ primaryCommand: string;
265
+ canDraftCustomerReply: boolean;
266
+ canSendCustomerReply: boolean;
267
+ requiresHumanApproval: boolean;
268
+ proofBacked: boolean;
269
+ businessProofReady: boolean;
270
+ releaseReady: boolean;
271
+ diagnosisReady: boolean;
272
+ issueClassProbePlanReady: boolean;
273
+ clarificationRequired: boolean;
274
+ reason: string;
275
+ blockers: string[];
276
+ requiredEvidence: string[];
277
+ evidenceRefs: string[];
278
+ nextCommands: string[];
279
+ forbiddenActions: string[];
280
+ createdAt: string;
281
+ }
282
+ export interface ResolveIOSupportCustomerReplyReadinessContractInput {
283
+ policy: ResolveIOSupportCustomerReplyPolicy;
284
+ diagnosisValidation?: ResolveIOSupportDiagnosisGateValidation;
285
+ issueClassProbePlanValidation?: ResolveIOSupportIssueClassProbePlanValidation;
286
+ businessProofReadiness?: ResolveIOSupportBusinessProofReadiness;
287
+ releaseGate?: {
288
+ blocked?: boolean;
289
+ status?: string;
290
+ blockers?: string[];
291
+ requiredEvidence?: string[];
292
+ nextCommands?: string[];
293
+ };
294
+ now?: Date | string;
295
+ }
258
296
  export interface ResolveIOSupportCustomerReplyPolicy {
259
297
  action: ResolveIOSupportCustomerReplyAction;
260
298
  canDraftCustomerReply: boolean;
@@ -273,6 +311,7 @@ export interface ResolveIOSupportCustomerReplyPolicy {
273
311
  businessProof: string;
274
312
  artifactCount: number;
275
313
  };
314
+ readinessContract?: ResolveIOSupportCustomerReplyReadinessContract;
276
315
  }
277
316
  export interface ResolveIOSupportIssueClassProbe {
278
317
  issue_class: ResolveIOSupportIssueClass;
@@ -831,6 +870,7 @@ export interface ResolveIOSupportV5AutonomousDecision {
831
870
  repairGate: ResolveIOSupportV5RepairGateDecision;
832
871
  continuation: ResolveIOSupportV5ContinuationDecision;
833
872
  customerReplyPolicy: ResolveIOSupportCustomerReplyPolicy;
873
+ customerReplyReadiness: ResolveIOSupportCustomerReplyReadinessContract;
834
874
  businessProofReadiness: ResolveIOSupportBusinessProofReadiness;
835
875
  evidenceFreshness: ResolveIOSupportEvidenceFreshness;
836
876
  preflightGate: ResolveIOSupportPreflightGate;
@@ -860,6 +900,13 @@ export declare function validateResolveIOSupportClarificationContract(value: any
860
900
  blockers: string[];
861
901
  normalized: ResolveIOSupportClarificationContract;
862
902
  };
903
+ export declare function buildResolveIOSupportCustomerReplyReadinessContract(input: ResolveIOSupportCustomerReplyReadinessContractInput): ResolveIOSupportCustomerReplyReadinessContract;
904
+ export declare function validateResolveIOSupportCustomerReplyReadinessContract(value: any): {
905
+ valid: boolean;
906
+ status: ResolveIOSupportCustomerReplyReadinessStatus | 'blocked';
907
+ blockers: string[];
908
+ normalized: ResolveIOSupportCustomerReplyReadinessContract;
909
+ };
863
910
  export declare function decideResolveIOSupportCustomerReplyPolicy(input?: ResolveIOSupportCustomerReplyPolicyInput): ResolveIOSupportCustomerReplyPolicy;
864
911
  export declare function buildResolveIOSupportIssueClassProbes(value: any): ResolveIOSupportIssueClassProbe[];
865
912
  export declare function validateResolveIOSupportIssueClassProbePlan(value: any, diagnosisGate?: any, now?: Date | string): ResolveIOSupportIssueClassProbePlanValidation;
@@ -57,6 +57,8 @@ exports.validateResolveIOSupportDiagnosisGate = validateResolveIOSupportDiagnosi
57
57
  exports.evaluateResolveIOSupportBusinessProofReadiness = evaluateResolveIOSupportBusinessProofReadiness;
58
58
  exports.buildResolveIOSupportClarificationContract = buildResolveIOSupportClarificationContract;
59
59
  exports.validateResolveIOSupportClarificationContract = validateResolveIOSupportClarificationContract;
60
+ exports.buildResolveIOSupportCustomerReplyReadinessContract = buildResolveIOSupportCustomerReplyReadinessContract;
61
+ exports.validateResolveIOSupportCustomerReplyReadinessContract = validateResolveIOSupportCustomerReplyReadinessContract;
60
62
  exports.decideResolveIOSupportCustomerReplyPolicy = decideResolveIOSupportCustomerReplyPolicy;
61
63
  exports.buildResolveIOSupportIssueClassProbes = buildResolveIOSupportIssueClassProbes;
62
64
  exports.validateResolveIOSupportIssueClassProbePlan = validateResolveIOSupportIssueClassProbePlan;
@@ -1752,6 +1754,185 @@ function buildResolveIOSupportHumanReviewPacket(input) {
1752
1754
  createdAt: isoNow(input.now)
1753
1755
  };
1754
1756
  }
1757
+ function supportCustomerReplyReadinessStatusFromReason(reason) {
1758
+ var statusByReason = {
1759
+ support_reply_clarification_contract_invalid: 'internal_blocked',
1760
+ support_reply_waiting_on_customer_reproduction_detail: 'clarification_required',
1761
+ support_reply_blocked_until_diagnosis_gate_validates: 'blocked_until_diagnosis',
1762
+ support_reply_requires_valid_issue_class_probe_plan: 'blocked_until_probe_plan',
1763
+ support_reply_blocked_by_confidence_gate: 'blocked_until_confidence',
1764
+ support_reply_requires_high_confidence: 'blocked_until_confidence',
1765
+ support_reply_blocked_by_unresolved_runner_blocker: 'blocked_until_runner_blocker',
1766
+ support_reply_blocked_until_release_or_hotfix_gate_finishes: 'blocked_until_release_hotfix',
1767
+ support_reply_rejects_route_only_business_proof: 'blocked_until_business_proof',
1768
+ support_reply_requires_business_assertion_pass: 'blocked_until_business_proof',
1769
+ support_reply_requires_business_proof_contract_artifact: 'blocked_until_business_proof_artifact',
1770
+ support_reply_resolution_draft_allowed_after_business_proof: 'draft_ready'
1771
+ };
1772
+ return statusByReason[reason] || 'internal_blocked';
1773
+ }
1774
+ function supportCustomerReplyReadinessDefaultPrimaryCommand(status, policy) {
1775
+ var reviewPacket = policy.humanReviewPacket;
1776
+ var preferred = cleanText(reviewPacket === null || reviewPacket === void 0 ? void 0 : reviewPacket.primaryAction, 160);
1777
+ if (preferred) {
1778
+ return preferred;
1779
+ }
1780
+ switch (status) {
1781
+ case 'draft_ready':
1782
+ return 'review_customer_reply';
1783
+ case 'clarification_required':
1784
+ return 'review_customer_clarification';
1785
+ case 'blocked_until_diagnosis':
1786
+ return 'run_support_v5_read_only_diagnosis_gate';
1787
+ case 'blocked_until_probe_plan':
1788
+ return 'repair_support_issue_class_probe_plan';
1789
+ case 'blocked_until_confidence':
1790
+ return 'review_support_confidence_evidence';
1791
+ case 'blocked_until_release_hotfix':
1792
+ return 'repair_release_hotfix_first';
1793
+ case 'blocked_until_business_proof':
1794
+ return 'run_support_v5_business_proof_qa_row';
1795
+ case 'blocked_until_business_proof_artifact':
1796
+ return 'record_business_proof_artifact';
1797
+ case 'blocked_until_runner_blocker':
1798
+ return 'review_support_runner_blocker';
1799
+ case 'blocked_until_human_approval':
1800
+ return 'review_customer_reply';
1801
+ case 'internal_blocked':
1802
+ default:
1803
+ return 'review_support_runner_blocker';
1804
+ }
1805
+ }
1806
+ function buildResolveIOSupportCustomerReplyReadinessContract(input) {
1807
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p;
1808
+ var policy = input.policy;
1809
+ var reviewPacket = policy.humanReviewPacket;
1810
+ var reason = cleanText(policy.reason, 500);
1811
+ var rawCanSend = policy.canSendCustomerReply === true || (reviewPacket === null || reviewPacket === void 0 ? void 0 : reviewPacket.customerSendAllowed) === true;
1812
+ var businessProofReady = ((_a = input.businessProofReadiness) === null || _a === void 0 ? void 0 : _a.ready) === true
1813
+ || (policy.action === 'draft_resolution_reply' && (((_b = policy.draftBasis) === null || _b === void 0 ? void 0 : _b.artifactCount) || 0) > 0);
1814
+ var releaseReady = ((_c = input.releaseGate) === null || _c === void 0 ? void 0 : _c.blocked) !== true;
1815
+ var diagnosisReady = ((_d = input.diagnosisValidation) === null || _d === void 0 ? void 0 : _d.valid) === true || policy.action === 'draft_resolution_reply';
1816
+ var issueClassProbePlanReady = ((_e = input.issueClassProbePlanValidation) === null || _e === void 0 ? void 0 : _e.valid) === true
1817
+ || ((_f = policy.draftBasis) === null || _f === void 0 ? void 0 : _f.issueClassProbePlanStatus) === 'ready';
1818
+ var initialStatus = supportCustomerReplyReadinessStatusFromReason(reason);
1819
+ var status = rawCanSend
1820
+ ? 'blocked_until_human_approval'
1821
+ : initialStatus;
1822
+ var canDraft = policy.canDraftCustomerReply === true
1823
+ && !rawCanSend
1824
+ && (status === 'draft_ready' || status === 'clarification_required');
1825
+ var requiresHumanApproval = true;
1826
+ var primaryCommand = supportCustomerReplyReadinessDefaultPrimaryCommand(status, policy);
1827
+ var blockers = Array.from(new Set(__spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray([], __read(cleanList(reviewPacket === null || reviewPacket === void 0 ? void 0 : reviewPacket.blockers, 20, 500)), false), __read(cleanList((_g = input.businessProofReadiness) === null || _g === void 0 ? void 0 : _g.blockers, 20, 500)), false), __read(cleanList((_h = input.releaseGate) === null || _h === void 0 ? void 0 : _h.blockers, 20, 500)), false), __read((rawCanSend ? ['automatic_customer_send_not_allowed'] : [])), false), __read((status === 'draft_ready' ? [] : [reason || status])), false).filter(Boolean)));
1828
+ var requiredEvidence = Array.from(new Set(__spreadArray(__spreadArray(__spreadArray(__spreadArray([], __read(cleanList(policy.requiredEvidence, 30, 500)), false), __read(cleanList(reviewPacket === null || reviewPacket === void 0 ? void 0 : reviewPacket.requiredEvidence, 30, 500)), false), __read(cleanList((_j = input.businessProofReadiness) === null || _j === void 0 ? void 0 : _j.requiredEvidence, 30, 500)), false), __read(cleanList((_k = input.releaseGate) === null || _k === void 0 ? void 0 : _k.requiredEvidence, 30, 500)), false).filter(Boolean)));
1829
+ var evidenceRefs = Array.from(new Set(__spreadArray(__spreadArray([], __read(cleanList(reviewPacket === null || reviewPacket === void 0 ? void 0 : reviewPacket.evidenceRefs, 40, 500)), false), __read(cleanList((_l = input.businessProofReadiness) === null || _l === void 0 ? void 0 : _l.artifactPaths, 40, 500)), false).filter(Boolean)));
1830
+ var nextCommands = Array.from(new Set(__spreadArray(__spreadArray([
1831
+ primaryCommand
1832
+ ], __read(cleanList(reviewPacket === null || reviewPacket === void 0 ? void 0 : reviewPacket.nextCommands, 20, 200)), false), __read(cleanList((_m = input.releaseGate) === null || _m === void 0 ? void 0 : _m.nextCommands, 20, 200)), false).filter(Boolean)));
1833
+ var forbiddenActions = Array.from(new Set(__spreadArray([
1834
+ 'Do not send customer email without explicit human approval.',
1835
+ 'Do not claim a fix is live until release or hotfix evidence is clear.',
1836
+ 'Do not draft a resolution reply from route-load, screenshot-only, scorecard-only, or model-claim proof.'
1837
+ ], __read(cleanList(reviewPacket === null || reviewPacket === void 0 ? void 0 : reviewPacket.forbiddenActions, 20, 500)), false)));
1838
+ var createdAt = isoNow(input.now || (reviewPacket === null || reviewPacket === void 0 ? void 0 : reviewPacket.createdAt));
1839
+ return {
1840
+ contractId: "support-customer-reply-".concat(hashResolveIOSupportV5Evidence({
1841
+ status: status,
1842
+ policyAction: policy.action,
1843
+ reason: reason,
1844
+ primaryCommand: primaryCommand,
1845
+ blockers: blockers,
1846
+ artifactFingerprint: (_o = input.businessProofReadiness) === null || _o === void 0 ? void 0 : _o.artifactFingerprint,
1847
+ proofFingerprint: (_p = input.businessProofReadiness) === null || _p === void 0 ? void 0 : _p.proofFingerprint,
1848
+ createdAt: createdAt.slice(0, 16)
1849
+ }).slice(0, 16)),
1850
+ status: status,
1851
+ policyAction: policy.action,
1852
+ reviewType: (reviewPacket === null || reviewPacket === void 0 ? void 0 : reviewPacket.reviewType) || (policy.action === 'draft_resolution_reply' ? 'customer_resolution_reply' : policy.action === 'ask_clarification' ? 'customer_clarification' : 'internal_hold'),
1853
+ primaryCommand: primaryCommand,
1854
+ canDraftCustomerReply: canDraft,
1855
+ canSendCustomerReply: false,
1856
+ requiresHumanApproval: requiresHumanApproval,
1857
+ proofBacked: status === 'draft_ready' && businessProofReady && evidenceRefs.length > 0,
1858
+ businessProofReady: businessProofReady,
1859
+ releaseReady: releaseReady,
1860
+ diagnosisReady: diagnosisReady,
1861
+ issueClassProbePlanReady: issueClassProbePlanReady,
1862
+ clarificationRequired: status === 'clarification_required',
1863
+ reason: reason,
1864
+ blockers: blockers,
1865
+ requiredEvidence: requiredEvidence,
1866
+ evidenceRefs: evidenceRefs,
1867
+ nextCommands: nextCommands,
1868
+ forbiddenActions: forbiddenActions,
1869
+ createdAt: createdAt
1870
+ };
1871
+ }
1872
+ function validateResolveIOSupportCustomerReplyReadinessContract(value) {
1873
+ var source = cleanObject(value);
1874
+ var validStatuses = [
1875
+ 'draft_ready',
1876
+ 'clarification_required',
1877
+ 'blocked_until_diagnosis',
1878
+ 'blocked_until_probe_plan',
1879
+ 'blocked_until_confidence',
1880
+ 'blocked_until_runner_blocker',
1881
+ 'blocked_until_release_hotfix',
1882
+ 'blocked_until_business_proof',
1883
+ 'blocked_until_business_proof_artifact',
1884
+ 'blocked_until_human_approval',
1885
+ 'internal_blocked'
1886
+ ];
1887
+ var status = cleanText(source.status, 120);
1888
+ var normalized = {
1889
+ contractId: cleanText(source.contractId || source.contract_id, 180),
1890
+ status: validStatuses.includes(status) ? status : 'internal_blocked',
1891
+ policyAction: cleanText(source.policyAction || source.policy_action, 120),
1892
+ reviewType: cleanText(source.reviewType || source.review_type, 120),
1893
+ primaryCommand: cleanText(source.primaryCommand || source.primary_command, 180),
1894
+ canDraftCustomerReply: source.canDraftCustomerReply === true || source.can_draft_customer_reply === true,
1895
+ canSendCustomerReply: source.canSendCustomerReply === true || source.can_send_customer_reply === true,
1896
+ requiresHumanApproval: source.requiresHumanApproval !== false && source.requires_human_approval !== false,
1897
+ proofBacked: source.proofBacked === true || source.proof_backed === true,
1898
+ businessProofReady: source.businessProofReady === true || source.business_proof_ready === true,
1899
+ releaseReady: source.releaseReady === true || source.release_ready === true,
1900
+ diagnosisReady: source.diagnosisReady === true || source.diagnosis_ready === true,
1901
+ issueClassProbePlanReady: source.issueClassProbePlanReady === true || source.issue_class_probe_plan_ready === true,
1902
+ clarificationRequired: source.clarificationRequired === true || source.clarification_required === true,
1903
+ reason: cleanText(source.reason, 500),
1904
+ blockers: cleanList(source.blockers, 24, 500),
1905
+ requiredEvidence: cleanList(source.requiredEvidence || source.required_evidence, 30, 500),
1906
+ evidenceRefs: cleanList(source.evidenceRefs || source.evidence_refs, 40, 500),
1907
+ nextCommands: cleanList(source.nextCommands || source.next_commands, 24, 200),
1908
+ forbiddenActions: cleanList(source.forbiddenActions || source.forbidden_actions, 24, 500),
1909
+ createdAt: cleanText(source.createdAt || source.created_at, 120)
1910
+ };
1911
+ var blockers = [
1912
+ normalized.contractId ? '' : 'Customer reply readiness contract is missing contractId.',
1913
+ validStatuses.includes(status) ? '' : 'Customer reply readiness contract has an invalid status.',
1914
+ normalized.policyAction ? '' : 'Customer reply readiness contract is missing policyAction.',
1915
+ normalized.primaryCommand ? '' : 'Customer reply readiness contract is missing primaryCommand.',
1916
+ normalized.requiresHumanApproval ? '' : 'Customer reply readiness must require human approval.',
1917
+ normalized.canSendCustomerReply === false ? '' : 'Customer reply readiness must never allow automatic customer send.',
1918
+ normalized.requiredEvidence.length ? '' : 'Customer reply readiness contract is missing requiredEvidence.',
1919
+ normalized.forbiddenActions.length ? '' : 'Customer reply readiness contract is missing forbiddenActions.',
1920
+ normalized.status === 'draft_ready' && !normalized.canDraftCustomerReply ? 'Draft-ready customer reply must allow draft creation.' : '',
1921
+ normalized.status === 'draft_ready' && !normalized.proofBacked ? 'Draft-ready customer reply must be proof-backed.' : '',
1922
+ normalized.status === 'draft_ready' && !normalized.businessProofReady ? 'Draft-ready customer reply requires businessProofReady=true.' : '',
1923
+ normalized.status === 'draft_ready' && !normalized.releaseReady ? 'Draft-ready customer reply requires releaseReady=true.' : '',
1924
+ normalized.status === 'draft_ready' && normalized.reviewType !== 'customer_resolution_reply' ? 'Draft-ready customer reply requires reviewType=customer_resolution_reply.' : '',
1925
+ normalized.status === 'clarification_required' && !normalized.clarificationRequired ? 'Clarification readiness must set clarificationRequired=true.' : '',
1926
+ normalized.status === 'clarification_required' && normalized.reviewType !== 'customer_clarification' ? 'Clarification readiness requires reviewType=customer_clarification.' : '',
1927
+ normalized.status !== 'draft_ready' && normalized.status !== 'clarification_required' && normalized.canDraftCustomerReply ? 'Blocked customer reply readiness cannot allow draft creation.' : ''
1928
+ ].filter(Boolean);
1929
+ return {
1930
+ valid: blockers.length === 0,
1931
+ status: blockers.length ? 'blocked' : normalized.status,
1932
+ blockers: blockers,
1933
+ normalized: normalized
1934
+ };
1935
+ }
1755
1936
  function supportAutonomousReviewTypeForAction(action) {
1756
1937
  switch (action) {
1757
1938
  case 'run_diagnosis_gate':
@@ -1805,6 +1986,16 @@ function decideResolveIOSupportCustomerReplyPolicy(input) {
1805
1986
  'business proof contract and artifact evidence',
1806
1987
  'no unresolved blocker or release blocker'
1807
1988
  ];
1989
+ var withReadiness = function (policy, issueClassProbePlanValidation) {
1990
+ var normalizedPolicy = policy;
1991
+ return __assign(__assign({}, normalizedPolicy), { readinessContract: buildResolveIOSupportCustomerReplyReadinessContract({
1992
+ policy: normalizedPolicy,
1993
+ diagnosisValidation: diagnosisValidation,
1994
+ issueClassProbePlanValidation: issueClassProbePlanValidation,
1995
+ businessProofReadiness: businessProofReadiness,
1996
+ releaseGate: releaseGate
1997
+ }) });
1998
+ };
1808
1999
  if (!diagnosisValidation.valid) {
1809
2000
  var canAskCustomer = (gate === null || gate === void 0 ? void 0 : gate.issue_case.reproduction_status) === 'blocked'
1810
2001
  || diagnosisValidation.blockers.some(function (blocker) { return /expected_result|observed_result|account_customer_context/.test(blocker); });
@@ -1812,7 +2003,7 @@ function decideResolveIOSupportCustomerReplyPolicy(input) {
1812
2003
  var clarificationValidation = validateResolveIOSupportClarificationContract(buildResolveIOSupportClarificationContract(gate, diagnosisValidation.blockers));
1813
2004
  var clarificationContract = clarificationValidation.normalized;
1814
2005
  if (!clarificationValidation.valid) {
1815
- return {
2006
+ return withReadiness({
1816
2007
  action: 'hold_internal',
1817
2008
  canDraftCustomerReply: false,
1818
2009
  canSendCustomerReply: false,
@@ -1834,9 +2025,9 @@ function decideResolveIOSupportCustomerReplyPolicy(input) {
1834
2025
  forbiddenActions: ['Do not send a malformed or multi-question clarification.'],
1835
2026
  costRisk: 'free_or_deterministic'
1836
2027
  })
1837
- };
2028
+ });
1838
2029
  }
1839
- return {
2030
+ return withReadiness({
1840
2031
  action: 'ask_clarification',
1841
2032
  canDraftCustomerReply: true,
1842
2033
  canSendCustomerReply: false,
@@ -1861,9 +2052,9 @@ function decideResolveIOSupportCustomerReplyPolicy(input) {
1861
2052
  forbiddenActions: clarificationContract.forbiddenActions,
1862
2053
  costRisk: 'release_or_customer_send'
1863
2054
  })
1864
- };
2055
+ });
1865
2056
  }
1866
- return {
2057
+ return withReadiness({
1867
2058
  action: 'hold_internal',
1868
2059
  canDraftCustomerReply: false,
1869
2060
  canSendCustomerReply: false,
@@ -1884,7 +2075,7 @@ function decideResolveIOSupportCustomerReplyPolicy(input) {
1884
2075
  forbiddenActions: ['Do not draft a resolution reply before root-cause diagnosis validates.'],
1885
2076
  costRisk: 'expensive_model'
1886
2077
  })
1887
- };
2078
+ });
1888
2079
  }
1889
2080
  var explicitProbePlan = cleanObject(input.issueClassProbePlan);
1890
2081
  var generatedProbePlan = gate
@@ -1893,7 +2084,7 @@ function decideResolveIOSupportCustomerReplyPolicy(input) {
1893
2084
  var issueClassProbePlanValidation = validateResolveIOSupportIssueClassProbePlan(Object.keys(explicitProbePlan).length ? explicitProbePlan : generatedProbePlan, gate);
1894
2085
  var issueClassProbePlan = issueClassProbePlanValidation.normalized || generatedProbePlan;
1895
2086
  if (!issueClassProbePlanValidation.valid) {
1896
- return {
2087
+ return withReadiness({
1897
2088
  action: 'hold_internal',
1898
2089
  canDraftCustomerReply: false,
1899
2090
  canSendCustomerReply: false,
@@ -1915,10 +2106,10 @@ function decideResolveIOSupportCustomerReplyPolicy(input) {
1915
2106
  forbiddenActions: ['Do not draft a customer resolution from business proof that is not mapped to a validated IssueClassProbePlan.'],
1916
2107
  costRisk: 'free_or_deterministic'
1917
2108
  })
1918
- };
2109
+ }, issueClassProbePlanValidation);
1919
2110
  }
1920
2111
  if (shouldBlockConfidence || confidenceLevel !== 'high') {
1921
- return {
2112
+ return withReadiness({
1922
2113
  action: 'hold_internal',
1923
2114
  canDraftCustomerReply: false,
1924
2115
  canSendCustomerReply: false,
@@ -1938,10 +2129,10 @@ function decideResolveIOSupportCustomerReplyPolicy(input) {
1938
2129
  forbiddenActions: ['Do not draft a customer resolution from medium or low confidence.'],
1939
2130
  costRisk: 'free_or_deterministic'
1940
2131
  })
1941
- };
2132
+ }, issueClassProbePlanValidation);
1942
2133
  }
1943
2134
  if (unresolvedBlockers.length) {
1944
- return {
2135
+ return withReadiness({
1945
2136
  action: 'hold_internal',
1946
2137
  canDraftCustomerReply: false,
1947
2138
  canSendCustomerReply: false,
@@ -1962,11 +2153,11 @@ function decideResolveIOSupportCustomerReplyPolicy(input) {
1962
2153
  forbiddenActions: ['Do not send customer status as resolved while blockers remain.'],
1963
2154
  costRisk: 'small_model_or_qa'
1964
2155
  })
1965
- };
2156
+ }, issueClassProbePlanValidation);
1966
2157
  }
1967
2158
  if (releaseGate.blocked) {
1968
2159
  var releaseRequiredEvidence = Array.from(new Set(__spreadArray(__spreadArray([], __read(requiredEvidence), false), __read(releaseGate.requiredEvidence), false)));
1969
- return {
2160
+ return withReadiness({
1970
2161
  action: 'hold_internal',
1971
2162
  canDraftCustomerReply: false,
1972
2163
  canSendCustomerReply: false,
@@ -1987,14 +2178,14 @@ function decideResolveIOSupportCustomerReplyPolicy(input) {
1987
2178
  forbiddenActions: ['Do not tell the customer the fix is live before release evidence passes.'],
1988
2179
  costRisk: 'release_or_customer_send'
1989
2180
  })
1990
- };
2181
+ }, issueClassProbePlanValidation);
1991
2182
  }
1992
2183
  if (!businessProofReadiness.ready) {
1993
2184
  var replyReason = businessProofReadiness.reason === 'support_business_proof_route_only_or_acceptance_blocked'
1994
2185
  ? 'support_reply_rejects_route_only_business_proof'
1995
2186
  : 'support_reply_requires_business_assertion_pass';
1996
2187
  var proofRequiredEvidence = Array.from(new Set(__spreadArray(__spreadArray([], __read(requiredEvidence), false), __read(businessProofReadiness.requiredEvidence), false)));
1997
- return {
2188
+ return withReadiness({
1998
2189
  action: 'hold_internal',
1999
2190
  canDraftCustomerReply: false,
2000
2191
  canSendCustomerReply: false,
@@ -2016,10 +2207,10 @@ function decideResolveIOSupportCustomerReplyPolicy(input) {
2016
2207
  forbiddenActions: ['Route probe pass remains route evidence only.'],
2017
2208
  costRisk: 'small_model_or_qa'
2018
2209
  })
2019
- };
2210
+ }, issueClassProbePlanValidation);
2020
2211
  }
2021
2212
  if (!(gate === null || gate === void 0 ? void 0 : gate.proof_plan.business_proof_contract) || artifactCount < 1) {
2022
- return {
2213
+ return withReadiness({
2023
2214
  action: 'hold_internal',
2024
2215
  canDraftCustomerReply: false,
2025
2216
  canSendCustomerReply: false,
@@ -2040,9 +2231,9 @@ function decideResolveIOSupportCustomerReplyPolicy(input) {
2040
2231
  forbiddenActions: ['Do not draft a resolution reply without a proof artifact.'],
2041
2232
  costRisk: 'free_or_deterministic'
2042
2233
  })
2043
- };
2234
+ }, issueClassProbePlanValidation);
2044
2235
  }
2045
- return {
2236
+ return withReadiness({
2046
2237
  action: 'draft_resolution_reply',
2047
2238
  canDraftCustomerReply: true,
2048
2239
  canSendCustomerReply: false,
@@ -2071,7 +2262,7 @@ function decideResolveIOSupportCustomerReplyPolicy(input) {
2071
2262
  businessProof: gate.proof_plan.business_proof_contract.expected_business_state_change,
2072
2263
  artifactCount: artifactCount
2073
2264
  }
2074
- };
2265
+ }, issueClassProbePlanValidation);
2075
2266
  }
2076
2267
  function buildResolveIOSupportIssueClassProbes(value) {
2077
2268
  var validation = validateResolveIOSupportDiagnosisGate(value);
@@ -3760,6 +3951,12 @@ function decideResolveIOSupportV5AutonomousNextAction(input) {
3760
3951
  now: input.now
3761
3952
  });
3762
3953
  var humanDecisionRequest = buildHumanDecisionRequest(action, label, reason, fields, rootCauseReadiness, continuationProofCheckpoint, nextActionContract, requiredEvidence, blockers);
3954
+ var customerReplyReadiness = customerReplyPolicy.readinessContract || buildResolveIOSupportCustomerReplyReadinessContract({
3955
+ policy: customerReplyPolicy,
3956
+ diagnosisValidation: diagnosisValidation,
3957
+ issueClassProbePlanValidation: issueClassProbePlanValidation,
3958
+ businessProofReadiness: businessProofReadiness
3959
+ });
3763
3960
  return {
3764
3961
  action: action,
3765
3962
  label: label,
@@ -3792,6 +3989,7 @@ function decideResolveIOSupportV5AutonomousNextAction(input) {
3792
3989
  repairGate: repairGate,
3793
3990
  continuation: continuation,
3794
3991
  customerReplyPolicy: customerReplyPolicy,
3992
+ customerReplyReadiness: customerReplyReadiness,
3795
3993
  businessProofReadiness: businessProofReadiness,
3796
3994
  evidenceFreshness: evidenceFreshness,
3797
3995
  preflightGate: preflightGate,