From c3cb82ef64ffb900a4970ec7d6e62029ce94d57d Mon Sep 17 00:00:00 2001 From: 18628386721 <18628386721@163.com> Date: Mon, 27 Jul 2026 05:50:56 +0800 Subject: [PATCH] =?UTF-8?q?=E6=89=93=E6=89=B0=E4=B8=8A=E9=99=90=E8=A6=81?= =?UTF-8?q?=E8=A6=86=E7=9B=96=E3=80=8C=E4=BA=BA=E6=AD=A5=20+=20=E4=BA=BA?= =?UTF-8?q?=E5=85=9C=E5=BA=95=E3=80=8D;=E5=8F=91=E5=8D=A1=E5=A4=B1?= =?UTF-8?q?=E8=B4=A5=E8=B5=B0=E5=A3=B0=E6=98=8E=E7=9A=84=E5=A4=B1=E8=B4=A5?= =?UTF-8?q?=E8=B5=B0=E5=90=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A7 归档卡在最后一步:调人预算 1/1 触顶,S4 放行卡发不出来, 而引擎每一拍重发一次 —— 六行一模一样的「调用:步 4」,卡永远不出现,也永远不报错。 两处修: ① 发卡被 Harness 拦下(调人预算触顶等)= **这一步失败了**,走它声明的失败走向。 不接住就是无限重发:预算照烧、负责人什么也看不到。 ② 四个 flow 活动的打扰上限只按**人步**算,没算**声明的人兜底**。 声明了 `fallback: human` 就等于承认这一步可能要调人,预算却不给它留位置 —— 兜底一触发,后面的放行卡必然发不出。按「人步 + 人兜底」重算: A1 4 / A4 3 / A6 3 / A7 2。 gates: tsc / eslint / depcruise / 399 测试 全绿 Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01KeDBx2PHLavbURXB8LJJ7m --- activities/quote-archive/src/manifest.ts | 6 ++-- activities/quote-intake/src/manifest.ts | 6 ++-- activities/quote-negotiate/src/manifest.ts | 2 +- activities/quote-pricing/src/manifest.ts | 6 ++-- .../internal/usecase/flow-runner.ts | 30 ++++++++++++++----- 5 files changed, 32 insertions(+), 18 deletions(-) diff --git a/activities/quote-archive/src/manifest.ts b/activities/quote-archive/src/manifest.ts index e8da110..f0e4b42 100644 --- a/activities/quote-archive/src/manifest.ts +++ b/activities/quote-archive/src/manifest.ts @@ -13,7 +13,7 @@ export const manifest: ActivityManifest = { identity: { activityId: ACTIVITY_ID, name: 'A7 · 情报归档', - packageVersion: '0.1.1', + packageVersion: '0.1.2', category: '统一报价', paradigm: 'flow', sdkVersion: '0.1.0-m5', @@ -56,13 +56,13 @@ export const manifest: ActivityManifest = { { key: 'bd-release', label: 'BD 放行', level: 'L5' }, ], prohibitions: [{ key: 'no-blank-archive', statement: '不得空归档 —— 每一单不成交的报价也是情报资产' }], - authorization: { discretion: [], preauthorizedActions: [], humanCallBudget: 1 }, + authorization: { discretion: [], preauthorizedActions: [], humanCallBudget: 2 }, resources: { tools: [], skills: [], models: ['quote-extractor'], roles: ['BD'], - budget: { steps: 30, tokens: 60_000, activeMinutes: 60, humanCalls: 1 }, + budget: { steps: 30, tokens: 60_000, activeMinutes: 60, humanCalls: 2 }, }, }, diff --git a/activities/quote-intake/src/manifest.ts b/activities/quote-intake/src/manifest.ts index d3daeda..7a85960 100644 --- a/activities/quote-intake/src/manifest.ts +++ b/activities/quote-intake/src/manifest.ts @@ -40,7 +40,7 @@ export const manifest: ActivityManifest = { identity: { activityId: ACTIVITY_ID, name: 'A1 · RFQ 需求分析', - packageVersion: '0.1.2', + packageVersion: '0.1.3', category: '统一报价', paradigm: 'flow', sdkVersion: '0.1.0-m5', @@ -95,14 +95,14 @@ export const manifest: ActivityManifest = { authorization: { discretion: [{ key: 'ask-back', statement: '缺次要字段可受理并追问,缺 PN/数量/交期必须退回补全' }], preauthorizedActions: [], - humanCallBudget: 3, + humanCallBudget: 4, }, resources: { tools: [{ name: 'crm.history-price-read' }], skills: [], models: ['quote-extractor'], roles: ['BD'], - budget: { steps: 40, tokens: 120_000, activeMinutes: 60, humanCalls: 3 }, + budget: { steps: 40, tokens: 120_000, activeMinutes: 60, humanCalls: 4 }, }, }, diff --git a/activities/quote-negotiate/src/manifest.ts b/activities/quote-negotiate/src/manifest.ts index 21f23d0..be44e4f 100644 --- a/activities/quote-negotiate/src/manifest.ts +++ b/activities/quote-negotiate/src/manifest.ts @@ -15,7 +15,7 @@ export const manifest: ActivityManifest = { identity: { activityId: ACTIVITY_ID, name: 'A6 · 报价议价', - packageVersion: '0.1.1', + packageVersion: '0.1.2', category: '统一报价', paradigm: 'flow', sdkVersion: '0.1.0-m5', diff --git a/activities/quote-pricing/src/manifest.ts b/activities/quote-pricing/src/manifest.ts index ef7b54a..5d3cefc 100644 --- a/activities/quote-pricing/src/manifest.ts +++ b/activities/quote-pricing/src/manifest.ts @@ -59,7 +59,7 @@ export const manifest: ActivityManifest = { identity: { activityId: ACTIVITY_ID, name: 'A4 · 成本定价', - packageVersion: '0.1.2', + packageVersion: '0.1.3', category: '统一报价', paradigm: 'flow', sdkVersion: '0.1.0-m5', @@ -110,14 +110,14 @@ export const manifest: ActivityManifest = { authorization: { discretion: [{ key: 'margin-band', statement: '在 P-01 给出的毛利区间内自决;出区间必须调人决策' }], preauthorizedActions: [], - humanCallBudget: 2, + humanCallBudget: 3, }, resources: { tools: [{ name: 'quote-pricing.basis' }, { name: 'crm.history-price-read' }], skills: [], models: ['quote-extractor'], roles: ['BD'], - budget: { steps: 60, tokens: 150_000, activeMinutes: 120, humanCalls: 2 }, + budget: { steps: 60, tokens: 150_000, activeMinutes: 120, humanCalls: 3 }, }, }, diff --git a/apps/api/src/modules/flow-engine/internal/usecase/flow-runner.ts b/apps/api/src/modules/flow-engine/internal/usecase/flow-runner.ts index c5f527c..797beb0 100644 --- a/apps/api/src/modules/flow-engine/internal/usecase/flow-runner.ts +++ b/apps/api/src/modules/flow-engine/internal/usecase/flow-runner.ts @@ -151,14 +151,28 @@ export function createFlowRunner(deps: FlowRunnerDeps): FlowEngineService { } case 'human': { - // 异步步:完成条件 = 人事件;时限必配 - const card = await deps.cards.issue({ - taskId, - ownerId: context.ownerId, - humanCallCap: context.humanCallCap, - workOrder: step.workOrder, - card: step.card, - }); + // 异步步:完成条件 = 人事件;时限必配。 + // 发卡本身可能被 Harness 拦下(调人预算触顶等)—— 那是**这一步失败了**, + // 走它声明的失败走向;不接住就会每一拍重发一次、永远发不出去也永远不报错。 + let card: { id: string }; + try { + card = await deps.cards.issue({ + taskId, + ownerId: context.ownerId, + humanCallCap: context.humanCallCap, + workOrder: step.workOrder, + card: step.card, + }); + } catch (error) { + return handleFailure( + taskId, + step, + index, + position, + attempt, + error instanceof Error ? error.message : String(error), + ); + } await deps.listeners.register({ taskId, eventType: 'human',