odai-dsh-agent 0.2.3 → 0.2.6

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.
Files changed (166) hide show
  1. package/README.md +3 -3
  2. package/build/bin/odai-dsh-agent.d.mts +3 -0
  3. package/build/bin/odai-dsh-agent.d.mts.map +1 -0
  4. package/build/bin/odai-dsh-agent.mjs +114 -0
  5. package/build/bin/odai-dsh-agent.mjs.map +1 -0
  6. package/build/src/dsh-version.d.mts +16 -0
  7. package/build/src/dsh-version.d.mts.map +1 -0
  8. package/build/src/dsh-version.mjs +20 -0
  9. package/build/src/dsh-version.mjs.map +1 -0
  10. package/build/src/installer.d.mts +46 -0
  11. package/build/src/installer.d.mts.map +1 -0
  12. package/build/src/installer.mjs +397 -0
  13. package/build/src/installer.mjs.map +1 -0
  14. package/package.json +13 -12
  15. package/preset/odai/runtime/compaction-config.d.mts +66 -0
  16. package/preset/odai/runtime/compaction-config.d.mts.map +1 -0
  17. package/preset/odai/runtime/compaction-config.mjs +320 -342
  18. package/preset/odai/runtime/compaction-config.mjs.map +1 -0
  19. package/preset/odai/runtime/compaction-runtime.d.mts +68 -0
  20. package/preset/odai/runtime/compaction-runtime.d.mts.map +1 -0
  21. package/preset/odai/runtime/compaction-runtime.mjs +157 -0
  22. package/preset/odai/runtime/compaction-runtime.mjs.map +1 -0
  23. package/preset/odai/runtime/context-activation.d.mts +31 -0
  24. package/preset/odai/runtime/context-activation.d.mts.map +1 -0
  25. package/preset/odai/runtime/context-activation.mjs +55 -49
  26. package/preset/odai/runtime/context-activation.mjs.map +1 -0
  27. package/preset/odai/runtime/context-capability.d.mts +16 -0
  28. package/preset/odai/runtime/context-capability.d.mts.map +1 -0
  29. package/preset/odai/runtime/context-capability.mjs +79 -74
  30. package/preset/odai/runtime/context-capability.mjs.map +1 -0
  31. package/preset/odai/runtime/governance.d.mts +30 -0
  32. package/preset/odai/runtime/governance.d.mts.map +1 -0
  33. package/preset/odai/runtime/governance.mjs +126 -113
  34. package/preset/odai/runtime/governance.mjs.map +1 -0
  35. package/preset/odai/runtime/human-care.d.mts +13 -0
  36. package/preset/odai/runtime/human-care.d.mts.map +1 -0
  37. package/preset/odai/runtime/human-care.mjs +45 -42
  38. package/preset/odai/runtime/human-care.mjs.map +1 -0
  39. package/preset/odai/runtime/human-safety-continuity-store.d.mts +43 -0
  40. package/preset/odai/runtime/human-safety-continuity-store.d.mts.map +1 -0
  41. package/preset/odai/runtime/human-safety-continuity-store.mjs +193 -215
  42. package/preset/odai/runtime/human-safety-continuity-store.mjs.map +1 -0
  43. package/preset/odai/runtime/human-safety-continuity.d.mts +27 -0
  44. package/preset/odai/runtime/human-safety-continuity.d.mts.map +1 -0
  45. package/preset/odai/runtime/human-safety-continuity.mjs +205 -216
  46. package/preset/odai/runtime/human-safety-continuity.mjs.map +1 -0
  47. package/preset/odai/runtime/human-safety.d.mts +14 -0
  48. package/preset/odai/runtime/human-safety.d.mts.map +1 -0
  49. package/preset/odai/runtime/human-safety.mjs +50 -47
  50. package/preset/odai/runtime/human-safety.mjs.map +1 -0
  51. package/preset/odai/runtime/index.d.mts +8 -0
  52. package/preset/odai/runtime/index.d.mts.map +1 -0
  53. package/preset/odai/runtime/index.mjs +161 -2441
  54. package/preset/odai/runtime/index.mjs.map +1 -0
  55. package/preset/odai/runtime/lifecycle-runtime.d.mts +83 -0
  56. package/preset/odai/runtime/lifecycle-runtime.d.mts.map +1 -0
  57. package/preset/odai/runtime/lifecycle-runtime.mjs +1081 -0
  58. package/preset/odai/runtime/lifecycle-runtime.mjs.map +1 -0
  59. package/preset/odai/runtime/model-route.d.mts +22 -0
  60. package/preset/odai/runtime/model-route.d.mts.map +1 -0
  61. package/preset/odai/runtime/model-route.mjs +68 -60
  62. package/preset/odai/runtime/model-route.mjs.map +1 -0
  63. package/preset/odai/runtime/output-config.d.mts +54 -0
  64. package/preset/odai/runtime/output-config.d.mts.map +1 -0
  65. package/preset/odai/runtime/output-config.mjs +289 -315
  66. package/preset/odai/runtime/output-config.mjs.map +1 -0
  67. package/preset/odai/runtime/output-policy-state.d.mts +3 -0
  68. package/preset/odai/runtime/output-policy-state.d.mts.map +1 -0
  69. package/preset/odai/runtime/output-policy-state.mjs +41 -29
  70. package/preset/odai/runtime/output-policy-state.mjs.map +1 -0
  71. package/preset/odai/runtime/prompt-runtime.d.mts +55 -0
  72. package/preset/odai/runtime/prompt-runtime.d.mts.map +1 -0
  73. package/preset/odai/runtime/prompt-runtime.mjs +303 -0
  74. package/preset/odai/runtime/prompt-runtime.mjs.map +1 -0
  75. package/preset/odai/runtime/research-packet.d.mts +30 -0
  76. package/preset/odai/runtime/research-packet.d.mts.map +1 -0
  77. package/preset/odai/runtime/research-packet.mjs +116 -117
  78. package/preset/odai/runtime/research-packet.mjs.map +1 -0
  79. package/preset/odai/runtime/responsibility-gap.d.mts +26 -0
  80. package/preset/odai/runtime/responsibility-gap.d.mts.map +1 -0
  81. package/preset/odai/runtime/responsibility-gap.mjs +91 -85
  82. package/preset/odai/runtime/responsibility-gap.mjs.map +1 -0
  83. package/preset/odai/runtime/responsibility-scope.d.mts +69 -0
  84. package/preset/odai/runtime/responsibility-scope.d.mts.map +1 -0
  85. package/preset/odai/runtime/responsibility-scope.mjs +199 -171
  86. package/preset/odai/runtime/responsibility-scope.mjs.map +1 -0
  87. package/preset/odai/runtime/role-overlays.d.mts +5 -0
  88. package/preset/odai/runtime/role-overlays.d.mts.map +1 -0
  89. package/preset/odai/runtime/role-overlays.mjs +14 -13
  90. package/preset/odai/runtime/role-overlays.mjs.map +1 -0
  91. package/preset/odai/runtime/route-card.d.mts +42 -0
  92. package/preset/odai/runtime/route-card.d.mts.map +1 -0
  93. package/preset/odai/runtime/route-card.mjs +158 -146
  94. package/preset/odai/runtime/route-card.mjs.map +1 -0
  95. package/preset/odai/runtime/router.d.mts +79 -0
  96. package/preset/odai/runtime/router.d.mts.map +1 -0
  97. package/preset/odai/runtime/router.mjs +491 -559
  98. package/preset/odai/runtime/router.mjs.map +1 -0
  99. package/preset/odai/runtime/routing-config.d.mts +76 -0
  100. package/preset/odai/runtime/routing-config.d.mts.map +1 -0
  101. package/preset/odai/runtime/routing-config.mjs +373 -438
  102. package/preset/odai/runtime/routing-config.mjs.map +1 -0
  103. package/preset/odai/runtime/routing-context.d.mts +47 -0
  104. package/preset/odai/runtime/routing-context.d.mts.map +1 -0
  105. package/preset/odai/runtime/routing-context.mjs +238 -273
  106. package/preset/odai/runtime/routing-context.mjs.map +1 -0
  107. package/preset/odai/runtime/runtime-config.d.mts +24 -0
  108. package/preset/odai/runtime/runtime-config.d.mts.map +1 -0
  109. package/preset/odai/runtime/runtime-config.mjs +181 -0
  110. package/preset/odai/runtime/runtime-config.mjs.map +1 -0
  111. package/preset/odai/runtime/runtime-support.d.mts +91 -0
  112. package/preset/odai/runtime/runtime-support.d.mts.map +1 -0
  113. package/preset/odai/runtime/runtime-support.mjs +371 -0
  114. package/preset/odai/runtime/runtime-support.mjs.map +1 -0
  115. package/preset/odai/runtime/runtime-types.d.mts +235 -0
  116. package/preset/odai/runtime/runtime-types.d.mts.map +1 -0
  117. package/preset/odai/runtime/runtime-types.mjs +4 -0
  118. package/preset/odai/runtime/runtime-types.mjs.map +1 -0
  119. package/preset/odai/runtime/semantic-memory-store.d.mts +110 -0
  120. package/preset/odai/runtime/semantic-memory-store.d.mts.map +1 -0
  121. package/preset/odai/runtime/semantic-memory-store.mjs +271 -385
  122. package/preset/odai/runtime/semantic-memory-store.mjs.map +1 -0
  123. package/preset/odai/runtime/semantic-memory.d.mts +88 -0
  124. package/preset/odai/runtime/semantic-memory.d.mts.map +1 -0
  125. package/preset/odai/runtime/semantic-memory.mjs +790 -750
  126. package/preset/odai/runtime/semantic-memory.mjs.map +1 -0
  127. package/preset/odai/runtime/session-compat.d.mts +31 -0
  128. package/preset/odai/runtime/session-compat.d.mts.map +1 -0
  129. package/preset/odai/runtime/session-compat.mjs +301 -328
  130. package/preset/odai/runtime/session-compat.mjs.map +1 -0
  131. package/preset/odai/runtime/session-evidence.d.mts +25 -0
  132. package/preset/odai/runtime/session-evidence.d.mts.map +1 -0
  133. package/preset/odai/runtime/session-evidence.mjs +309 -287
  134. package/preset/odai/runtime/session-evidence.mjs.map +1 -0
  135. package/preset/odai/runtime/skill-bundle.d.mts +53 -0
  136. package/preset/odai/runtime/skill-bundle.d.mts.map +1 -0
  137. package/preset/odai/runtime/skill-bundle.mjs +286 -276
  138. package/preset/odai/runtime/skill-bundle.mjs.map +1 -0
  139. package/preset/odai/runtime/skill-evolution.d.mts +112 -0
  140. package/preset/odai/runtime/skill-evolution.d.mts.map +1 -0
  141. package/preset/odai/runtime/skill-evolution.mjs +1287 -1261
  142. package/preset/odai/runtime/skill-evolution.mjs.map +1 -0
  143. package/preset/odai/runtime/skill-selection-state.d.mts +5 -0
  144. package/preset/odai/runtime/skill-selection-state.d.mts.map +1 -0
  145. package/preset/odai/runtime/skill-selection-state.mjs +59 -43
  146. package/preset/odai/runtime/skill-selection-state.mjs.map +1 -0
  147. package/preset/odai/runtime/skill-selector.d.mts +28 -0
  148. package/preset/odai/runtime/skill-selector.d.mts.map +1 -0
  149. package/preset/odai/runtime/skill-selector.mjs +100 -109
  150. package/preset/odai/runtime/skill-selector.mjs.map +1 -0
  151. package/preset/odai/runtime/skill-source-config.d.mts +32 -0
  152. package/preset/odai/runtime/skill-source-config.d.mts.map +1 -0
  153. package/preset/odai/runtime/skill-source-config.mjs +200 -210
  154. package/preset/odai/runtime/skill-source-config.mjs.map +1 -0
  155. package/preset/odai/runtime/store-lock.d.mts +2 -0
  156. package/preset/odai/runtime/store-lock.d.mts.map +1 -0
  157. package/preset/odai/runtime/store-lock.mjs +92 -87
  158. package/preset/odai/runtime/store-lock.mjs.map +1 -0
  159. package/preset/odai/runtime/tool-runtime.d.mts +43 -0
  160. package/preset/odai/runtime/tool-runtime.d.mts.map +1 -0
  161. package/preset/odai/runtime/tool-runtime.mjs +221 -0
  162. package/preset/odai/runtime/tool-runtime.mjs.map +1 -0
  163. package/bin/odai-dsh-agent.mjs +0 -108
  164. package/scripts/verify-agent-load.mjs +0 -257
  165. package/src/dsh-version.mjs +0 -24
  166. package/src/installer.mjs +0 -398
@@ -1,683 +1,615 @@
1
+ import { isUnknownRecord } from "./runtime-types.mjs";
2
+ function isContinuationRole(value) {
3
+ return value === "planner" || value === "executor" || value === "frontend";
4
+ }
1
5
  export const HIGH_IMPACT_PLANNER_REASON = "PLANNER_UNVERIFIED_HIGH_IMPACT_CHANGE";
2
6
  export const RESEARCHER_EVIDENCE_REASON = "RESEARCHER_MULTI_SOURCE_DECISION_EVIDENCE";
3
7
  export const FRONTEND_SPECIALIST_REASON = "FRONTEND_SUBSTANTIAL_INTERFACE_WORK";
4
8
  export const EXECUTOR_ROUTE_CARD_REASON = "EXECUTOR_FROZEN_ROUTE_NET_BENEFIT";
5
9
  export const OUTPUT_LIMIT_CONTINUATION_REASON = "RESPONSIBILITY_OUTPUT_LIMIT_CONTINUATION";
6
-
7
10
  const RESPONSIBILITY_LABELS = Object.freeze({
8
- researcher: "多源事实调查",
9
- planner: "规划",
10
- executor: "执行",
11
- reviewer: "验收",
12
- frontend: "前端设计与制作",
11
+ researcher: "多源事实调查",
12
+ planner: "规划",
13
+ executor: "执行",
14
+ reviewer: "验收",
15
+ frontend: "前端设计与制作",
13
16
  });
14
-
15
17
  const PLANNER_PATTERNS = [
16
- /独立(?:判断|规划|分析|决定|决策)/iu,
17
- /比较(?:一下)?(?:方案|路线|架构)/iu,
18
- /架构选型/iu,
19
- /先(?:判断|规划)(?:路线|方案)/iu,
20
- /second opinion (?:on|for) (?:the )?(?:plan|approach|architecture)/iu,
21
- /compare (?:the )?(?:approaches|options|architectures)/iu,
22
- /architecture decision/iu,
23
- /(?:independently decide|independent decision)/iu,
24
- ];
25
-
18
+ /独立(?:判断|规划|分析|决定|决策)/iu,
19
+ /比较(?:一下)?(?:方案|路线|架构)/iu,
20
+ /架构选型/iu,
21
+ /先(?:判断|规划)(?:路线|方案)/iu,
22
+ /second opinion (?:on|for) (?:the )?(?:plan|approach|architecture)/iu,
23
+ /compare (?:the )?(?:approaches|options|architectures)/iu,
24
+ /architecture decision/iu,
25
+ /(?:independently decide|independent decision)/iu,
26
+ ];
26
27
  const PLANNER_META_PATTERNS = [
27
- /(?:你|是否|有没有|有没).{0,12}(?:规划|计划)(?:了|过|吗|没有)/iu,
28
- /(?:did you|have you).{0,24}\bplan(?:ned|ning)?\b/iu,
28
+ /(?:你|是否|有没有|有没).{0,12}(?:规划|计划)(?:了|过|吗|没有)/iu,
29
+ /(?:did you|have you).{0,24}\bplan(?:ned|ning)?\b/iu,
29
30
  ];
30
-
31
31
  const REVIEWER_PATTERNS = [
32
- /独立(?:审查|复核|评审)/iu,
33
- /(?:代码|安全|变更)(?:审查|复核|评审)/iu,
34
- /code review/iu,
35
- /security review/iu,
36
- /independent review/iu,
37
- /challenge (?:the )?(?:plan|implementation|result)/iu,
38
- ];
39
-
32
+ /独立(?:审查|复核|评审)/iu,
33
+ /(?:代码|安全|变更)(?:审查|复核|评审)/iu,
34
+ /code review/iu,
35
+ /security review/iu,
36
+ /independent review/iu,
37
+ /challenge (?:the )?(?:plan|implementation|result)/iu,
38
+ ];
40
39
  const RISK_PATTERNS = [
41
- /(?:高风险|安全|权限|删除|迁移|发布|生产环境)/iu,
42
- /(?:支付|付款|结算|扣款|退款|订单)[^。!?\n]{0,60}(?:提供方|服务|接口|请求|结果|状态|超时|重试|金额|交易|配置|回调|不稳定)/iu,
43
- /(?:high[- ]risk|security|permission|delete|migration|production)/iu,
44
- /(?:checkout|payment|billing|charge|refund)[^.!?\n]{0,80}(?:provider|service|request|result|status|timeout|retry|transaction|configuration|unstable|fail|超时|重试|不稳定)/iu,
40
+ /(?:高风险|安全|权限|删除|迁移|发布|生产环境)/iu,
41
+ /(?:支付|付款|结算|扣款|退款|订单)[^。!?\n]{0,60}(?:提供方|服务|接口|请求|结果|状态|超时|重试|金额|交易|配置|回调|不稳定)/iu,
42
+ /(?:high[- ]risk|security|permission|delete|migration|production)/iu,
43
+ /(?:checkout|payment|billing|charge|refund)[^.!?\n]{0,80}(?:provider|service|request|result|status|timeout|retry|transaction|configuration|unstable|fail|超时|重试|不稳定)/iu,
45
44
  ];
46
-
47
45
  const UNVERIFIED_CAUSAL_PATTERNS = [
48
- /(?:我看|看起来|看来|估计|大概|八成|明显|肯定)(?:就)?是/iu,
49
- /(?:问题|原因|根因)(?:应该|可能|大概|估计)(?:就)?在/iu,
50
- /\b(?:it\s+)?(?:looks?|seems)\s+like\b/iu,
51
- /\b(?:i think|probably|apparently|clearly|obviously)\b[^.!?\n]{0,80}\b(?:is|are|because|caused by|comes from)\b/iu,
46
+ /(?:我看|看起来|看来|估计|大概|八成|明显|肯定)(?:就)?是/iu,
47
+ /(?:问题|原因|根因)(?:应该|可能|大概|估计)(?:就)?在/iu,
48
+ /\b(?:it\s+)?(?:looks?|seems)\s+like\b/iu,
49
+ /\b(?:i think|probably|apparently|clearly|obviously)\b[^.!?\n]{0,80}\b(?:is|are|because|caused by|comes from)\b/iu,
52
50
  ];
53
-
54
51
  const CONCRETE_CHANGE_PATTERNS = [
55
- /把[^。!?\n]{1,120}(?:降到|提到|提高到|改成|设为|设置为|切到|换成|开启|关闭|删除|清空|迁移到|发布到|上线)/iu,
56
- /(?:降低|提高|增加|减少|修改|设置|开启|关闭|删除|清空|迁移|发布|上线)[^。!?\n]{0,80}(?:\d|配置|超时|重试|权限|数据|服务)/iu,
57
- /\b(?:set|change|reduce|lower|increase|raise|disable|enable|delete|drop|clear|migrate|deploy|release)\b[^.!?\n]{0,100}\b(?:to|from|timeout|retries|permission|data|service|production)\b/iu,
52
+ /把[^。!?\n]{1,120}(?:降到|提到|提高到|改成|设为|设置为|切到|换成|开启|关闭|删除|清空|迁移到|发布到|上线)/iu,
53
+ /(?:降低|提高|增加|减少|修改|设置|开启|关闭|删除|清空|迁移|发布|上线)[^。!?\n]{0,80}(?:\d|配置|超时|重试|权限|数据|服务)/iu,
54
+ /\b(?:set|change|reduce|lower|increase|raise|disable|enable|delete|drop|clear|migrate|deploy|release)\b[^.!?\n]{0,100}\b(?:to|from|timeout|retries|permission|data|service|production)\b/iu,
58
55
  ];
59
-
60
56
  const SPECIFIC_PARAMETER_PATTERNS = [
61
- /\d+(?:\.\d+)?\s*(?:毫秒|秒|分钟|小时|次|%|%|ms|sec(?:ond)?s?|min(?:ute)?s?|hours?|retries?|mb|gb)/iu,
57
+ /\d+(?:\.\d+)?\s*(?:毫秒|秒|分钟|小时|次|%|%|ms|sec(?:ond)?s?|min(?:ute)?s?|hours?|retries?|mb|gb)/iu,
62
58
  ];
63
-
64
59
  const URGENCY_PATTERNS = [
65
- /(?:先止血|立即|马上|赶紧|紧急|热修)/iu,
66
- /\b(?:hotfix|immediately|right away|stop the bleeding)\b/iu,
60
+ /(?:先止血|立即|马上|赶紧|紧急|热修)/iu,
61
+ /\b(?:hotfix|immediately|right away|stop the bleeding)\b/iu,
67
62
  ];
68
-
69
63
  const IRREVERSIBLE_ACTION_PATTERNS = [
70
- /(?:删除|清空|迁移|发布|上线|关闭)/iu,
71
- /\b(?:delete|drop|clear|migrate|deploy|release|disable)\b/iu,
64
+ /(?:删除|清空|迁移|发布|上线|关闭)/iu,
65
+ /\b(?:delete|drop|clear|migrate|deploy|release|disable)\b/iu,
72
66
  ];
73
-
74
67
  const CONTINUATION_PATTERNS = [
75
- /(?:继续|接着|进一步|深入|再(?:判断|分析|评估|检查|处理)|按(?:照)?(?:刚才|上面|上述|前面|这个|该)|那就|就按|能做不|能不能做|可以做不|可以做吗)/iu,
76
- /\b(?:continue|proceed|go ahead|follow up|dig deeper|based on (?:that|the previous|the above)|can you (?:do|handle|implement) (?:it|that))\b/iu,
68
+ /(?:继续|接着|进一步|深入|再(?:判断|分析|评估|检查|处理)|按(?:照)?(?:刚才|上面|上述|前面|这个|该)|那就|就按|能做不|能不能做|可以做不|可以做吗)/iu,
69
+ /\b(?:continue|proceed|go ahead|follow up|dig deeper|based on (?:that|the previous|the above)|can you (?:do|handle|implement) (?:it|that))\b/iu,
77
70
  ];
78
-
79
71
  const PURE_RESPONSIBILITY_CONTINUATION_PATTERNS = [
80
- /^\s*(?:请)?(?:继续|接着|接下去|续上|恢复)(?:(?:执行|完成|处理|做|推进|设计|分析|规划))?(?:(?:刚才|之前|上次|这个|该|原来)的?)?(?:任务|工作|实现|方案|设计|分析|规划)?(?:下去|完成|吧)?[。!!]?\s*$/iu,
81
- /^\s*(?:please\s+)?(?:continue|go on|resume|carry on|keep going)(?:\s+(?:the\s+)?(?:previous|interrupted|same)?\s*(?:task|work|implementation|plan|design|analysis))?[.!]?\s*$/iu,
72
+ /^\s*(?:请)?(?:继续|接着|接下去|续上|恢复)(?:(?:执行|完成|处理|做|推进|设计|分析|规划))?(?:(?:刚才|之前|上次|这个|该|原来)的?)?(?:任务|工作|实现|方案|设计|分析|规划)?(?:下去|完成|吧)?[。!!]?\s*$/iu,
73
+ /^\s*(?:please\s+)?(?:continue|go on|resume|carry on|keep going)(?:\s+(?:the\s+)?(?:previous|interrupted|same)?\s*(?:task|work|implementation|plan|design|analysis))?[.!]?\s*$/iu,
82
74
  ];
83
75
  const OUTPUT_LIMIT_DIAGNOSTIC_PATTERNS = [
84
- /(?:截断|断掉|中断|输出[^。!?\n]{0,12}(?:上限|预算)|(?:上限|预算)[^。!?\n]{0,12}输出|max\s*[_-]?\s*tokens?)/iu,
85
- /(?:token|令牌)[^。!?\n]{0,16}(?:limit|budget|上限|预算|截断)/iu,
86
- /(?:为什么|为何|怎么)[^。!?\n]{0,20}(?:停|断|中断|没继续|不继续)/iu,
76
+ /(?:截断|断掉|中断|输出[^。!?\n]{0,12}(?:上限|预算)|(?:上限|预算)[^。!?\n]{0,12}输出|max\s*[_-]?\s*tokens?)/iu,
77
+ /(?:token|令牌)[^。!?\n]{0,16}(?:limit|budget|上限|预算|截断)/iu,
78
+ /(?:为什么|为何|怎么)[^。!?\n]{0,20}(?:停|断|中断|没继续|不继续)/iu,
87
79
  ];
88
-
89
80
  const LOW_RISK_TRANSFORM_PATTERNS = [
90
- /(?:重述|总结|概括|压缩|翻译|改写|润色|格式化|解释(?:一下)?)/iu,
91
- /\b(?:restate|summari[sz]e|translate|shorten|rewrite|format|explain)\b/iu,
81
+ /(?:重述|总结|概括|压缩|翻译|改写|润色|格式化|解释(?:一下)?)/iu,
82
+ /\b(?:restate|summari[sz]e|translate|shorten|rewrite|format|explain)\b/iu,
92
83
  ];
93
-
94
84
  const EXPLICIT_EXECUTION_CONTINUATION_PATTERNS = [
95
- /(?:继续|接着|就按|按(?:照)?(?:(?:这个|该|上述|上面|前面|刚才)的?)?(?:方案|计划|卡片))/iu,
96
- /\b(?:continue|proceed|go ahead|follow the plan)\b/iu,
85
+ /(?:继续|接着|就按|按(?:照)?(?:(?:这个|该|上述|上面|前面|刚才)的?)?(?:方案|计划|卡片))/iu,
86
+ /\b(?:continue|proceed|go ahead|follow the plan)\b/iu,
97
87
  ];
98
88
  const IMPLEMENTATION_AUTHORIZATION_PATTERNS = [
99
- /(?:做(?:完|好|掉|这个|这项|这次|一个)|实现|修复|完成|落地|开发|添加|新增|替换|删除|执行|全都做好)/iu,
100
- /(?:请|麻烦|直接|开始|继续)(?:帮我)?(?:处理|修改|更新)|帮我(?:处理|修改|更新)|需要(?:处理|修改|更新)|可以(?:帮我)?(?:处理|修改|更新)|^(?:处理|修改|更新)(?:一下|这个|该|文件|代码|配置|依赖|问题|功能|实现|文档|测试)/iu,
101
- /\b(?:do it|implement|fix|complete|build|add|replace|remove|execute|ship)\b/iu,
102
- /^(?:please\s+)?(?:(?:change|modify)\b|update\b(?!\s+(?:me|us|them|everyone|the team)\b))|\b(?:please|can you|could you|would you|go ahead and|start to|continue to)\s+(?:(?:change|modify)\b|update\b(?!\s+(?:me|us|them|everyone|the team)\b))|\bi (?:need|want) you to\s+(?:(?:change|modify)\b|update\b(?!\s+(?:me|us|them|everyone|the team)\b))/iu,
89
+ /(?:做(?:完|好|掉|这个|这项|这次|一个)|实现|修复|完成|落地|开发|添加|新增|替换|删除|执行|全都做好)/iu,
90
+ /(?:请|麻烦|直接|开始|继续)(?:帮我)?(?:处理|修改|更新)|帮我(?:处理|修改|更新)|需要(?:处理|修改|更新)|可以(?:帮我)?(?:处理|修改|更新)|^(?:处理|修改|更新)(?:一下|这个|该|文件|代码|配置|依赖|问题|功能|实现|文档|测试)/iu,
91
+ /\b(?:do it|implement|fix|complete|build|add|replace|remove|execute|ship)\b/iu,
92
+ /^(?:please\s+)?(?:(?:change|modify)\b|update\b(?!\s+(?:me|us|them|everyone|the team)\b))|\b(?:please|can you|could you|would you|go ahead and|start to|continue to)\s+(?:(?:change|modify)\b|update\b(?!\s+(?:me|us|them|everyone|the team)\b))|\bi (?:need|want) you to\s+(?:(?:change|modify)\b|update\b(?!\s+(?:me|us|them|everyone|the team)\b))/iu,
103
93
  ];
104
94
  const PLAN_ONLY_PATTERNS = [
105
- /(?:只|仅).{0,16}(?:规划|计划|分析|评估|建议|方案|审查|复核|评审|检查)/iu,
106
- /(?:先|帮我)(?:规划|计划|分析|评估)(?:一下)?[^。!?\n]{0,40}(?:$|[。!?])/iu,
107
- /^\s*(?:请)?(?:规划|计划|分析|评估|建议|审查|复核|评审|检查)/iu,
108
- /^\s*(?:请)?(?:列一下|列出|整理(?:一份)?|给我(?:一份)?)[^。!?\n]{0,64}(?:地方|清单|列表|说明|建议|方案|示例|影响|步骤)(?:$|[。!?])/iu,
109
- /\b(?:review|audit|inspect)\s+only\b/iu,
110
- /\b(?:just|only)\s+(?:plan|analy[sz]e|assess|evaluate|review|audit|inspect|recommend|explain|describe|outline|list)\b/iu,
111
- /^\s*(?:please\s+)?(?:plan|analy[sz]e|assess|evaluate|review|audit|inspect|recommend|explain|describe|outline|list)\b/iu,
95
+ /(?:只|仅).{0,16}(?:规划|计划|分析|评估|建议|方案|审查|复核|评审|检查)/iu,
96
+ /(?:先|帮我)(?:规划|计划|分析|评估)(?:一下)?[^。!?\n]{0,40}(?:$|[。!?])/iu,
97
+ /^\s*(?:请)?(?:规划|计划|分析|评估|建议|审查|复核|评审|检查)/iu,
98
+ /^\s*(?:请)?(?:列一下|列出|整理(?:一份)?|给我(?:一份)?)[^。!?\n]{0,64}(?:地方|清单|列表|说明|建议|方案|示例|影响|步骤)(?:$|[。!?])/iu,
99
+ /\b(?:review|audit|inspect)\s+only\b/iu,
100
+ /\b(?:just|only)\s+(?:plan|analy[sz]e|assess|evaluate|review|audit|inspect|recommend|explain|describe|outline|list)\b/iu,
101
+ /^\s*(?:please\s+)?(?:plan|analy[sz]e|assess|evaluate|review|audit|inspect|recommend|explain|describe|outline|list)\b/iu,
112
102
  ];
113
103
  const PLAN_THEN_IMPLEMENT_PATTERNS = [
114
- /(?:规划|计划|分析|评估|建议|审查|复核|评审|检查)[^。!?\n]{0,48}(?:然后|再|之后|接着|并(?:且)?)[^。!?\n]{0,24}(?:实现|修复|完成|落地|开发|添加|新增|修改|更新(?![^。!?\n]{0,8}(?:我|我们|团队|进展|结果|情况|发现|消息|状态))|替换|删除|执行)/iu,
115
- /(?:列一下|列出|整理(?:一份)?|给我(?:一份)?)[^。!?\n]{0,64}(?:然后|再|之后|接着|并(?:且)?)[^。!?\n]{0,24}(?:实现|修复|完成|落地|开发|添加|新增|修改|更新|替换|删除|执行)/iu,
116
- /\b(?:plan|analy[sz]e|assess|evaluate|review|audit|inspect|recommend|explain|describe|outline|list)\b[^.!?\n]{0,64}\b(?:then|and(?: then)?|after that)\b[^.!?\n]{0,24}\b(?:implement|fix|complete|build|add|change|update(?!\s+(?:me|us|them|everyone|the team)\b)|modify|replace|remove|execute|ship)\b/iu,
104
+ /(?:规划|计划|分析|评估|建议|审查|复核|评审|检查)[^。!?\n]{0,48}(?:然后|再|之后|接着|并(?:且)?)[^。!?\n]{0,24}(?:实现|修复|完成|落地|开发|添加|新增|修改|更新(?![^。!?\n]{0,8}(?:我|我们|团队|进展|结果|情况|发现|消息|状态))|替换|删除|执行)/iu,
105
+ /(?:列一下|列出|整理(?:一份)?|给我(?:一份)?)[^。!?\n]{0,64}(?:然后|再|之后|接着|并(?:且)?)[^。!?\n]{0,24}(?:实现|修复|完成|落地|开发|添加|新增|修改|更新|替换|删除|执行)/iu,
106
+ /\b(?:plan|analy[sz]e|assess|evaluate|review|audit|inspect|recommend|explain|describe|outline|list)\b[^.!?\n]{0,64}\b(?:then|and(?: then)?|after that)\b[^.!?\n]{0,24}\b(?:implement|fix|complete|build|add|change|update(?!\s+(?:me|us|them|everyone|the team)\b)|modify|replace|remove|execute|ship)\b/iu,
117
107
  ];
118
108
  const STATUS_UPDATE_PATTERNS = [
119
- /(?:更新|同步)[^。!?\n]{0,24}(?:进展|结果|情况|发现|消息|状态)/iu,
120
- /\bupdate\b[^.!?\n]{1,48}\b(?:on|about|regarding)\b/iu,
121
- /\bupdate\b[^.!?\n]{1,48}\bwith\s+(?:the\s+)?(?:findings|progress|results|status|details|news|outcome)\b/iu,
109
+ /(?:更新|同步)[^。!?\n]{0,24}(?:进展|结果|情况|发现|消息|状态)/iu,
110
+ /\bupdate\b[^.!?\n]{1,48}\b(?:on|about|regarding)\b/iu,
111
+ /\bupdate\b[^.!?\n]{1,48}\bwith\s+(?:the\s+)?(?:findings|progress|results|status|details|news|outcome)\b/iu,
122
112
  ];
123
113
  const UNAMBIGUOUS_DELIVERY_PATTERNS = [
124
- /(?:^|[,;。]|然后|再|之后|接着|并(?:且)?|请|帮我)(?:做(?:完|好|掉)|实现|修复|完成|落地|开发|添加|新增|修改|替换|删除|执行)/iu,
125
- /更新(?:代码|项目|依赖|包|清单|文档|测试|配置|文件|运行时|服务|应用|界面|数据库|架构)/iu,
126
- /\b(?:do it|implement|execute|ship)\b/iu,
127
- /(?:^|\b(?:then|and|to|please)\s+)\b(?:fix|complete|build|add|change|modify|replace|remove)\b/iu,
128
- /\bupdate\s+(?:the\s+)?(?:code|project|dependencies?|packages?|manifest|docs?|documentation|tests?|config(?:uration)?|files?|runtime|services?|app(?:lication)?|ui|interface|schema|database|architecture)\b/iu,
114
+ /(?:^|[,;。]|然后|再|之后|接着|并(?:且)?|请|帮我)(?:做(?:完|好|掉)|实现|修复|完成|落地|开发|添加|新增|修改|替换|删除|执行)/iu,
115
+ /更新(?:代码|项目|依赖|包|清单|文档|测试|配置|文件|运行时|服务|应用|界面|数据库|架构)/iu,
116
+ /\b(?:do it|implement|execute|ship)\b/iu,
117
+ /(?:^|\b(?:then|and|to|please)\s+)\b(?:fix|complete|build|add|change|modify|replace|remove)\b/iu,
118
+ /\bupdate\s+(?:the\s+)?(?:code|project|dependencies?|packages?|manifest|docs?|documentation|tests?|config(?:uration)?|files?|runtime|services?|app(?:lication)?|ui|interface|schema|database|architecture)\b/iu,
129
119
  ];
130
120
  const NON_IMPLEMENTATION_QUERY_PATTERNS = [
131
- /(?:有什么|有何|哪些|是什么|为何|为什么|怎么样|怎么看|发生了什么|有变化吗|影响(?:是|有)?什么)[^。!?\n]*[??]?$/iu,
132
- /^\s*(?:what|why|how)\b[^.!?\n]*[?]\s*$/iu,
133
- /\b(?:what changed|what changes|what impact|which changes|difference between)\b[^.!?\n]*[?]?$/iu,
121
+ /(?:有什么|有何|哪些|是什么|为何|为什么|怎么样|怎么看|发生了什么|有变化吗|影响(?:是|有)?什么)[^。!?\n]*[??]?$/iu,
122
+ /^\s*(?:what|why|how)\b[^.!?\n]*[?]\s*$/iu,
123
+ /\b(?:what changed|what changes|what impact|which changes|difference between)\b[^.!?\n]*[?]?$/iu,
134
124
  ];
135
125
  const NO_IMPLEMENTATION_PATTERNS = [
136
- /(?:不要|别|请勿|禁止|无需|不用|不需要|不能)[^。!?\n]{0,28}(?:改|修改|编辑|写入|实现|执行|落地|动文件|动代码)/iu,
137
- /\b(?:do not|don't|never|without)\b[^.!?\n]{0,48}\b(?:implement|modify|edit|change|write|execute|apply|make changes?)\b/iu,
138
- /\b(?:plan|analyze|assess|evaluate|recommend)(?: only)?\b[^.!?]{0,30}\b(?:do not|don't|without) (?:implementing|changes?)\b/iu,
126
+ /(?:不要|别|请勿|禁止|无需|不用|不需要|不能)[^。!?\n]{0,28}(?:改|修改|编辑|写入|实现|执行|落地|动文件|动代码)/iu,
127
+ /\b(?:do not|don't|never|without)\b[^.!?\n]{0,48}\b(?:implement|modify|edit|change|write|execute|apply|make changes?)\b/iu,
128
+ /\b(?:plan|analyze|assess|evaluate|recommend)(?: only)?\b[^.!?]{0,30}\b(?:do not|don't|without) (?:implementing|changes?)\b/iu,
139
129
  ];
140
130
  const GLOBAL_NO_EDIT_PATTERNS = [
141
- /(?:不要|别|请勿|禁止)[^,;。!?\n]{0,12}(?:改|修改|编辑|写入)[^,;。!?\n]{0,12}(?:任何|全部|所有|整个)[^,;。!?\n]{0,12}(?:文件|代码|内容|实现|东西)/iu,
142
- /\b(?:do not|don't|never)\b[^,;.!?\n]{0,12}\b(?:modify|edit|change|write)\b[^,;.!?\n]{0,16}\b(?:anything|any (?:files?|code|changes?)|all (?:files?|code|changes?)|the (?:whole|entire) codebase)\b/iu,
131
+ /(?:不要|别|请勿|禁止)[^,;。!?\n]{0,12}(?:改|修改|编辑|写入)[^,;。!?\n]{0,12}(?:任何|全部|所有|整个)[^,;。!?\n]{0,12}(?:文件|代码|内容|实现|东西)/iu,
132
+ /\b(?:do not|don't|never)\b[^,;.!?\n]{0,12}\b(?:modify|edit|change|write)\b[^,;.!?\n]{0,16}\b(?:anything|any (?:files?|code|changes?)|all (?:files?|code|changes?)|the (?:whole|entire) codebase)\b/iu,
143
133
  ];
144
134
  const SCOPED_NO_EDIT_WITH_EXECUTION_PATTERNS = [
145
- /(?:不要|别|请勿)[^,;。!?\n]{0,12}(?:改|修改|编辑|写入)(?![^,;。!?\n]{0,12}(?:任何|全部|所有|整个))[^,;。!?\n]{1,28}[,;。](?![^,;。!?\n]{0,20}(?:不要|别|请勿|禁止|无需|不用|不需要|不能))[ \t]*[^,;。!?\n]{0,20}(?:实现|修复|修改|更新|执行|落地)/iu,
146
- /\b(?:do not|don't|never)\b[^,;.!?\n]{0,12}\b(?:modify|edit|change|write)\b(?![^,;.!?\n]{0,16}\b(?:anything|any (?:files?|code|changes?)|all (?:files?|code|changes?)|the (?:whole|entire) codebase)\b)[^,;.!?\n]{1,36}[,;.](?![^,;.!?\n]{0,24}\b(?:do not|don't|never|no need to|without|skip)\b)\s*[^,;.!?\n]{0,24}\b(?:implement|fix|change|update|execute|apply)\b/iu,
135
+ /(?:不要|别|请勿)[^,;。!?\n]{0,12}(?:改|修改|编辑|写入)(?![^,;。!?\n]{0,12}(?:任何|全部|所有|整个))[^,;。!?\n]{1,28}[,;。](?![^,;。!?\n]{0,20}(?:不要|别|请勿|禁止|无需|不用|不需要|不能))[ \t]*[^,;。!?\n]{0,20}(?:实现|修复|修改|更新|执行|落地)/iu,
136
+ /\b(?:do not|don't|never)\b[^,;.!?\n]{0,12}\b(?:modify|edit|change|write)\b(?![^,;.!?\n]{0,16}\b(?:anything|any (?:files?|code|changes?)|all (?:files?|code|changes?)|the (?:whole|entire) codebase)\b)[^,;.!?\n]{1,36}[,;.](?![^,;.!?\n]{0,24}\b(?:do not|don't|never|no need to|without|skip)\b)\s*[^,;.!?\n]{0,24}\b(?:implement|fix|change|update|execute|apply)\b/iu,
147
137
  ];
148
138
  const EXECUTION_ACTION_PATTERNS = [
149
- /(?:开始|执行|实施|落实|动手)/iu,
150
- /\b(?:start|execute|implement|apply)\b/iu,
139
+ /(?:开始|执行|实施|落实|动手)/iu,
140
+ /\b(?:start|execute|implement|apply)\b/iu,
151
141
  ];
152
142
  const ROUTE_CARD_REFERENCE_PATTERNS = [
153
- /(?:(?:这个|该|上述|上面|前面|刚才)的?(?:方案|计划|卡片|实现|改动|工作))/iu,
154
- /\b(?:(?:this|that|the|above|previous)\s+(?:plan|proposal|route card|implementation|change)|(?:it|that))\b/iu,
143
+ /(?:(?:这个|该|上述|上面|前面|刚才)的?(?:方案|计划|卡片|实现|改动|工作))/iu,
144
+ /\b(?:(?:this|that|the|above|previous)\s+(?:plan|proposal|route card|implementation|change)|(?:it|that))\b/iu,
155
145
  ];
156
146
  const NEW_TASK_PATTERNS = [
157
- /(?:另一个|另一项|另一件|另外(?:一个|一项|一件)|新(?:的)?(?:问题|任务|需求|工作))/iu,
158
- /\b(?:another|(?:a )?new|different|separate)\s+(?:task|issue|problem|request|change|project)\b/iu,
147
+ /(?:另一个|另一项|另一件|另外(?:一个|一项|一件)|新(?:的)?(?:问题|任务|需求|工作))/iu,
148
+ /\b(?:another|(?:a )?new|different|separate)\s+(?:task|issue|problem|request|change|project)\b/iu,
159
149
  ];
160
-
161
150
  const FRONTEND_SCOPE_PATTERNS = [
162
- /(?:前端|界面|页面|网页|网站|着陆页|应用界面|仪表盘|控制台|组件|交互界面|移动端|桌面端|游戏界面|3D场景)/iu,
163
- /\b(?:front[- ]?end|ui|ux|interface|web(?:site| app)?|landing page|page|dashboard|component|mobile|desktop|game ui|3d scene)\b/iu,
151
+ /(?:前端|界面|页面|网页|网站|着陆页|应用界面|仪表盘|控制台|组件|交互界面|移动端|桌面端|游戏界面|3D场景)/iu,
152
+ /\b(?:front[- ]?end|ui|ux|interface|web(?:site| app)?|landing page|page|dashboard|component|mobile|desktop|game ui|3d scene)\b/iu,
164
153
  ];
165
154
  const FRONTEND_DELIVERY_PATTERNS = [
166
- /(?:设计|制作|实现|开发|构建|创建|搭建|改版|重做|重构|优化|美化|修复)/iu,
167
- /\b(?:design|build|implement|develop|create|craft|redesign|revamp|rework|optimi[sz]e|fix)\b/iu,
155
+ /(?:设计|制作|实现|开发|构建|创建|搭建|改版|重做|重构|优化|美化|修复)/iu,
156
+ /\b(?:design|build|implement|develop|create|craft|redesign|revamp|rework|optimi[sz]e|fix)\b/iu,
168
157
  ];
169
158
  const FRONTEND_STRONG_WORK_PATTERNS = [
170
- /(?:从零|新建|新做|整页|整站|整体改版|完整界面|设计并实现|重新设计|重做|改版|搭建)/iu,
171
- /\b(?:build|create|design and implement|redesign|revamp|rebuild)\b[^.!?\n]{0,60}\b(?:ui|interface|page|website|web app|dashboard|component|game)\b/iu,
159
+ /(?:从零|新建|新做|整页|整站|整体改版|完整界面|设计并实现|重新设计|重做|改版|搭建)/iu,
160
+ /\b(?:build|create|design and implement|redesign|revamp|rebuild)\b[^.!?\n]{0,60}\b(?:ui|interface|page|website|web app|dashboard|component|game)\b/iu,
172
161
  ];
173
162
  const FRONTEND_SURFACE_PATTERNS = [
174
- /登录(?:页|页面)/iu,
175
- /(?:登录后)?首页/iu,
176
- /(?:个人空间|个人中心|用户中心|个人主页)/iu,
177
- /(?:注册|设置|搜索|列表|详情|结算|支付)(?:页|页面)/iu,
178
- /\b(?:login page|home page|profile|personal space|settings page|search page|list page|detail page|checkout page)\b/iu,
163
+ /登录(?:页|页面)/iu,
164
+ /(?:登录后)?首页/iu,
165
+ /(?:个人空间|个人中心|用户中心|个人主页)/iu,
166
+ /(?:注册|设置|搜索|列表|详情|结算|支付)(?:页|页面)/iu,
167
+ /\b(?:login page|home page|profile|personal space|settings page|search page|list page|detail page|checkout page)\b/iu,
179
168
  ];
180
169
  const FRONTEND_NON_UI_PATTERNS = [
181
- /(?:API|接口)(?:调用|请求|响应|超时|缓存|鉴权|数据|字段|契约)/iu,
182
- /\b(?:api|endpoint|backend|server-side)\b/iu,
170
+ /(?:API|接口)(?:调用|请求|响应|超时|缓存|鉴权|数据|字段|契约)/iu,
171
+ /\b(?:api|endpoint|backend|server-side)\b/iu,
183
172
  ];
184
173
  const FRONTEND_UI_PRODUCTION_PATTERNS = [
185
- /(?:UI|UX|用户界面|界面介绍|布局|样式|排版|配色|交互|视觉|响应式|移动端|桌面端|截图|浏览器验收)/iu,
186
- /\b(?:ui|ux|interface|layout|styling|typography|interaction|visual|responsive|mobile|desktop|screenshot|browser acceptance)\b/iu,
174
+ /(?:UI|UX|用户界面|界面介绍|布局|样式|排版|配色|交互|视觉|响应式|移动端|桌面端|截图|浏览器验收)/iu,
175
+ /\b(?:ui|ux|interface|layout|styling|typography|interaction|visual|responsive|mobile|desktop|screenshot|browser acceptance)\b/iu,
187
176
  ];
188
177
  const FRONTEND_EXPLICIT_SPECIALIST_PATTERNS = [
189
- /(?:交给|使用|用)[^。!?\n]{0,30}(?:前端|UI|UX)(?:专长|专家|模型)/iu,
190
- /\b(?:use|with|via)\b[^.!?\n]{0,30}\b(?:front[- ]?end|ui|ux) (?:specialist|expert|model)\b/iu,
178
+ /(?:交给|使用|用)[^。!?\n]{0,30}(?:前端|UI|UX)(?:专长|专家|模型)/iu,
179
+ /\b(?:use|with|via)\b[^.!?\n]{0,30}\b(?:front[- ]?end|ui|ux) (?:specialist|expert|model)\b/iu,
191
180
  ];
192
181
  const FRONTEND_AXIS_PATTERNS = Object.freeze({
193
- responsive: [/(?:响应式|移动端|桌面端|多端|窄屏|宽屏|视口)/iu, /\b(?:responsive|mobile|desktop|viewport|breakpoint)\b/iu],
194
- interaction: [/(?:交互|动效|动画|拖拽|手势|状态流转|多状态)/iu, /\b(?:interaction|animation|motion|drag|gesture|state flow|multiple states)\b/iu],
195
- visual: [/(?:视觉|品牌|排版|配色|设计系统|素材|图片|图标|3D|游戏界面)/iu, /\b(?:visual|brand|typography|palette|design system|asset|image|icon|3d|game ui)\b/iu],
196
- comprehension: [/(?:一眼(?:就)?(?:看懂|明白|理解)|做什么|首屏认知|价值表达|信息架构|界面介绍)/iu, /\b(?:understand at a glance|first-screen comprehension|value proposition|information architecture|what (?:it|the product) does)\b/iu],
197
- acceptance: [/(?:截图|浏览器验收|视觉验收|无障碍|Playwright|真机)/iu, /\b(?:screenshot|browser acceptance|visual acceptance|accessibility|playwright|device testing)\b/iu],
182
+ responsive: [/(?:响应式|移动端|桌面端|多端|窄屏|宽屏|视口)/iu, /\b(?:responsive|mobile|desktop|viewport|breakpoint)\b/iu],
183
+ interaction: [/(?:交互|动效|动画|拖拽|手势|状态流转|多状态)/iu, /\b(?:interaction|animation|motion|drag|gesture|state flow|multiple states)\b/iu],
184
+ visual: [/(?:视觉|品牌|排版|配色|设计系统|素材|图片|图标|3D|游戏界面)/iu, /\b(?:visual|brand|typography|palette|design system|asset|image|icon|3d|game ui)\b/iu],
185
+ comprehension: [/(?:一眼(?:就)?(?:看懂|明白|理解)|做什么|首屏认知|价值表达|信息架构|界面介绍)/iu, /\b(?:understand at a glance|first-screen comprehension|value proposition|information architecture|what (?:it|the product) does)\b/iu],
186
+ acceptance: [/(?:截图|浏览器验收|视觉验收|无障碍|Playwright|真机)/iu, /\b(?:screenshot|browser acceptance|visual acceptance|accessibility|playwright|device testing)\b/iu],
198
187
  });
199
-
200
188
  function matchesAny(text, patterns) {
201
- return patterns.some((pattern) => pattern.test(text));
189
+ return patterns.some((pattern) => pattern.test(text));
202
190
  }
203
-
204
191
  function stripQuotedMaterial(text) {
205
- return text
206
- .replace(/```[\s\S]*?```/gu, " ")
207
- .replace(/^\s*>.*$/gmu, " ")
208
- .replace(/`[^`\n]*`/gu, " ")
209
- .replace(/“[^”\n]*”|‘[^’\n]*’|「[^」\n]*」|『[^』\n]*』|《[^》\n]*》|"[^"\n]*"/gu, " ");
192
+ return text
193
+ .replace(/```[\s\S]*?```/gu, " ")
194
+ .replace(/^\s*>.*$/gmu, " ")
195
+ .replace(/`[^`\n]*`/gu, " ")
196
+ .replace(/“[^”\n]*”|‘[^’\n]*’|「[^」\n]*」|『[^』\n]*』|《[^》\n]*》|"[^"\n]*"/gu, " ");
210
197
  }
211
-
212
198
  export function classifyResponsibilityInterruptionText(text) {
213
- const explicit = stripQuotedMaterial(String(text ?? "")).trim();
214
- if (!explicit) return "clear";
215
- if (matchesAny(explicit, PURE_RESPONSIBILITY_CONTINUATION_PATTERNS)) return "continue";
216
- if (matchesAny(explicit, OUTPUT_LIMIT_DIAGNOSTIC_PATTERNS)) return "preserve";
217
- return "clear";
199
+ const explicit = stripQuotedMaterial(String(text ?? "")).trim();
200
+ if (!explicit)
201
+ return "clear";
202
+ if (matchesAny(explicit, PURE_RESPONSIBILITY_CONTINUATION_PATTERNS))
203
+ return "continue";
204
+ if (matchesAny(explicit, OUTPUT_LIMIT_DIAGNOSTIC_PATTERNS))
205
+ return "preserve";
206
+ return "clear";
218
207
  }
219
-
220
208
  function isExecutionContinuation(text) {
221
- if (matchesAny(text, NEW_TASK_PATTERNS)) return false;
222
- if (matchesAny(text, EXPLICIT_EXECUTION_CONTINUATION_PATTERNS)) return true;
223
- return matchesAny(text, EXECUTION_ACTION_PATTERNS)
224
- && matchesAny(text, ROUTE_CARD_REFERENCE_PATTERNS);
209
+ if (matchesAny(text, NEW_TASK_PATTERNS))
210
+ return false;
211
+ if (matchesAny(text, EXPLICIT_EXECUTION_CONTINUATION_PATTERNS))
212
+ return true;
213
+ return matchesAny(text, EXECUTION_ACTION_PATTERNS)
214
+ && matchesAny(text, ROUTE_CARD_REFERENCE_PATTERNS);
225
215
  }
226
-
227
216
  export function classifyImplementationAuthorization(text) {
228
- const explicit = stripQuotedMaterial(String(text ?? "")).trim();
229
- if (!explicit) return Object.freeze({ status: "unknown" });
230
- if (matchesAny(explicit, GLOBAL_NO_EDIT_PATTERNS)) return Object.freeze({ status: "plan-only" });
231
- if (matchesAny(explicit, SCOPED_NO_EDIT_WITH_EXECUTION_PATTERNS)) return Object.freeze({ status: "authorized" });
232
- if (matchesAny(explicit, NO_IMPLEMENTATION_PATTERNS)) return Object.freeze({ status: "plan-only" });
233
- if (matchesAny(explicit, STATUS_UPDATE_PATTERNS)
234
- && !matchesAny(explicit, UNAMBIGUOUS_DELIVERY_PATTERNS)
235
- && !matchesAny(explicit, CONCRETE_CHANGE_PATTERNS)) {
236
- return Object.freeze({ status: matchesAny(explicit, PLAN_ONLY_PATTERNS) ? "plan-only" : "unknown" });
237
- }
238
- if (isExecutionContinuation(explicit) || matchesAny(explicit, PLAN_THEN_IMPLEMENT_PATTERNS)) {
239
- return Object.freeze({ status: "authorized" });
240
- }
241
- if (matchesAny(explicit, PLAN_ONLY_PATTERNS)) return Object.freeze({ status: "plan-only" });
242
- if (matchesAny(explicit, NON_IMPLEMENTATION_QUERY_PATTERNS)) return Object.freeze({ status: "unknown" });
243
- if (matchesAny(explicit, IMPLEMENTATION_AUTHORIZATION_PATTERNS)
244
- || matchesAny(explicit, CONCRETE_CHANGE_PATTERNS)) {
245
- return Object.freeze({ status: "authorized" });
246
- }
247
- return Object.freeze({ status: "unknown" });
217
+ const explicit = stripQuotedMaterial(String(text ?? "")).trim();
218
+ if (!explicit)
219
+ return Object.freeze({ status: "unknown" });
220
+ if (matchesAny(explicit, GLOBAL_NO_EDIT_PATTERNS))
221
+ return Object.freeze({ status: "plan-only" });
222
+ if (matchesAny(explicit, SCOPED_NO_EDIT_WITH_EXECUTION_PATTERNS))
223
+ return Object.freeze({ status: "authorized" });
224
+ if (matchesAny(explicit, NO_IMPLEMENTATION_PATTERNS))
225
+ return Object.freeze({ status: "plan-only" });
226
+ if (matchesAny(explicit, STATUS_UPDATE_PATTERNS)
227
+ && !matchesAny(explicit, UNAMBIGUOUS_DELIVERY_PATTERNS)
228
+ && !matchesAny(explicit, CONCRETE_CHANGE_PATTERNS)) {
229
+ return Object.freeze({ status: matchesAny(explicit, PLAN_ONLY_PATTERNS) ? "plan-only" : "unknown" });
230
+ }
231
+ if (isExecutionContinuation(explicit) || matchesAny(explicit, PLAN_THEN_IMPLEMENT_PATTERNS)) {
232
+ return Object.freeze({ status: "authorized" });
233
+ }
234
+ if (matchesAny(explicit, PLAN_ONLY_PATTERNS))
235
+ return Object.freeze({ status: "plan-only" });
236
+ if (matchesAny(explicit, NON_IMPLEMENTATION_QUERY_PATTERNS))
237
+ return Object.freeze({ status: "unknown" });
238
+ if (matchesAny(explicit, IMPLEMENTATION_AUTHORIZATION_PATTERNS)
239
+ || matchesAny(explicit, CONCRETE_CHANGE_PATTERNS)) {
240
+ return Object.freeze({ status: "authorized" });
241
+ }
242
+ return Object.freeze({ status: "unknown" });
248
243
  }
249
-
250
244
  function hasContextualPlannerGap(text) {
251
- return matchesAny(text, RISK_PATTERNS)
252
- && matchesAny(text, UNVERIFIED_CAUSAL_PATTERNS)
253
- && matchesAny(text, CONCRETE_CHANGE_PATTERNS)
254
- && (matchesAny(text, SPECIFIC_PARAMETER_PATTERNS)
255
- || matchesAny(text, URGENCY_PATTERNS)
256
- || matchesAny(text, IRREVERSIBLE_ACTION_PATTERNS));
245
+ return matchesAny(text, RISK_PATTERNS)
246
+ && matchesAny(text, UNVERIFIED_CAUSAL_PATTERNS)
247
+ && matchesAny(text, CONCRETE_CHANGE_PATTERNS)
248
+ && (matchesAny(text, SPECIFIC_PARAMETER_PATTERNS)
249
+ || matchesAny(text, URGENCY_PATTERNS)
250
+ || matchesAny(text, IRREVERSIBLE_ACTION_PATTERNS));
257
251
  }
258
-
259
252
  function isLowRiskTransform(text) {
260
- return matchesAny(stripQuotedMaterial(text), LOW_RISK_TRANSFORM_PATTERNS);
253
+ return matchesAny(stripQuotedMaterial(text), LOW_RISK_TRANSFORM_PATTERNS);
261
254
  }
262
-
263
255
  function frontendSpecializationSignals(text) {
264
- const explicit = matchesAny(text, FRONTEND_EXPLICIT_SPECIALIST_PATTERNS);
265
- const surfaceCount = FRONTEND_SURFACE_PATTERNS.filter((pattern) => pattern.test(text)).length;
266
- const explicitScope = matchesAny(text, FRONTEND_SCOPE_PATTERNS);
267
- const scope = surfaceCount > 0 || explicitScope;
268
- const delivery = matchesAny(text, FRONTEND_DELIVERY_PATTERNS);
269
- const strongWork = matchesAny(text, FRONTEND_STRONG_WORK_PATTERNS);
270
- const axes = Object.entries(FRONTEND_AXIS_PATTERNS)
271
- .filter(([, patterns]) => matchesAny(text, patterns))
272
- .map(([axis]) => axis);
273
- const nonUiRequest = matchesAny(text, FRONTEND_NON_UI_PATTERNS)
274
- && !matchesAny(text, FRONTEND_UI_PRODUCTION_PATTERNS);
275
- const specialistDepth = explicit
276
- || strongWork
277
- || axes.length >= 2
278
- || (surfaceCount >= 2 && (explicitScope || axes.length >= 1));
279
- return Object.freeze({
280
- explicit,
281
- scope,
282
- delivery,
283
- strongWork,
284
- nonUiRequest,
285
- specialistDepth,
286
- surfaceCount,
287
- axes: Object.freeze(axes),
288
- substantial: scope && delivery && specialistDepth && !nonUiRequest,
289
- });
256
+ const explicit = matchesAny(text, FRONTEND_EXPLICIT_SPECIALIST_PATTERNS);
257
+ const surfaceCount = FRONTEND_SURFACE_PATTERNS.filter((pattern) => pattern.test(text)).length;
258
+ const explicitScope = matchesAny(text, FRONTEND_SCOPE_PATTERNS);
259
+ const scope = surfaceCount > 0 || explicitScope;
260
+ const delivery = matchesAny(text, FRONTEND_DELIVERY_PATTERNS);
261
+ const strongWork = matchesAny(text, FRONTEND_STRONG_WORK_PATTERNS);
262
+ const axes = Object.entries(FRONTEND_AXIS_PATTERNS)
263
+ .filter(([, patterns]) => matchesAny(text, patterns))
264
+ .map(([axis]) => axis);
265
+ const nonUiRequest = matchesAny(text, FRONTEND_NON_UI_PATTERNS)
266
+ && !matchesAny(text, FRONTEND_UI_PRODUCTION_PATTERNS);
267
+ const specialistDepth = explicit
268
+ || strongWork
269
+ || axes.length >= 2
270
+ || (surfaceCount >= 2 && (explicitScope || axes.length >= 1));
271
+ return Object.freeze({
272
+ explicit,
273
+ scope,
274
+ delivery,
275
+ strongWork,
276
+ nonUiRequest,
277
+ specialistDepth,
278
+ surfaceCount,
279
+ axes: Object.freeze(axes),
280
+ substantial: scope && delivery && specialistDepth && !nonUiRequest,
281
+ });
290
282
  }
291
-
292
283
  function frontendRouteSignals(frontend) {
293
- return [
294
- ...(frontend.scope ? ["frontend-interface-scope"] : []),
295
- ...(frontend.delivery ? ["frontend-delivery-request"] : []),
296
- ...(frontend.explicit ? ["explicit-frontend-specialist"] : []),
297
- ...(frontend.strongWork ? ["substantial-frontend-work"] : []),
298
- ...(frontend.surfaceCount >= 2 ? ["frontend-multi-surface"] : []),
299
- ...frontend.axes.map((axis) => `frontend-${axis}`),
300
- ];
284
+ return [
285
+ ...(frontend.scope ? ["frontend-interface-scope"] : []),
286
+ ...(frontend.delivery ? ["frontend-delivery-request"] : []),
287
+ ...(frontend.explicit ? ["explicit-frontend-specialist"] : []),
288
+ ...(frontend.strongWork ? ["substantial-frontend-work"] : []),
289
+ ...(frontend.surfaceCount >= 2 ? ["frontend-multi-surface"] : []),
290
+ ...frontend.axes.map((axis) => `frontend-${axis}`),
291
+ ];
301
292
  }
302
-
303
293
  function genuineUserText(message) {
304
- if (message?.role !== "user" || message?.source?.kind !== "user" || !Array.isArray(message.content)) return "";
305
- return message.content
306
- .filter((block) => block?.type === "text" && typeof block.text === "string")
307
- .map((block) => block.text)
308
- .join("\n")
309
- .trim();
294
+ const source = message?.source;
295
+ if (message?.role !== "user" || !isUnknownRecord(source) || source.kind !== "user" || !Array.isArray(message.content))
296
+ return "";
297
+ return message.content
298
+ .filter((block) => block?.type === "text" && typeof block.text === "string")
299
+ .map((block) => block.text)
300
+ .join("\n")
301
+ .trim();
310
302
  }
311
-
312
303
  function genuineUserTexts(messages, sessionEvents = []) {
313
- const candidates = [
314
- ...(Array.isArray(messages) ? [...messages].reverse() : []),
315
- ...(Array.isArray(sessionEvents)
316
- ? [...sessionEvents].reverse()
317
- .filter((event) => event?.type === "user/message")
318
- .map((event) => event.data)
319
- : []),
320
- ];
321
- const seen = new Set();
322
- const texts = [];
323
- for (const message of candidates) {
324
- const text = genuineUserText(message);
325
- if (!text || seen.has(text)) continue;
326
- seen.add(text);
327
- texts.push(text);
328
- }
329
- return texts;
304
+ const candidates = [
305
+ ...(Array.isArray(messages) ? [...messages].reverse() : []),
306
+ ...(Array.isArray(sessionEvents)
307
+ ? [...sessionEvents].reverse()
308
+ .filter((event) => event?.type === "user/message")
309
+ .map((event) => event.data)
310
+ : []),
311
+ ];
312
+ const seen = new Set();
313
+ const texts = [];
314
+ for (const message of candidates) {
315
+ const text = genuineUserText(message);
316
+ if (!text || seen.has(text))
317
+ continue;
318
+ seen.add(text);
319
+ texts.push(text);
320
+ }
321
+ return texts;
330
322
  }
331
-
332
323
  function route(role, reasonCode, reason, signals, action = role === "controller" ? "direct" : "delegate", targetRole) {
333
- return Object.freeze({
334
- role,
335
- mode: action,
336
- action,
337
- ...(targetRole === undefined ? {} : { targetRole }),
338
- reasonCode,
339
- reason,
340
- signals: Object.freeze([...new Set(signals)]),
341
- });
324
+ return Object.freeze({
325
+ role,
326
+ mode: action,
327
+ action,
328
+ ...(targetRole === undefined ? {} : { targetRole }),
329
+ reasonCode,
330
+ reason,
331
+ signals: Object.freeze([...new Set(signals)]),
332
+ });
342
333
  }
343
-
344
334
  export function decideResearchPrefetch(input = {}) {
345
- const text = typeof input.text === "string" ? input.text.trim() : "";
346
- const explicitIntentText = stripQuotedMaterial(text);
347
- const proposal = input.proposal?.responsibility === "researcher" ? input.proposal : undefined;
348
- if (!proposal || !explicitIntentText || isLowRiskTransform(explicitIntentText)) {
349
- return route("controller", "RESEARCHER_PREFETCH_NOT_NEEDED", "No evidence-grounded multi-source compression gap was proposed.", ["no-research-prefetch"]);
350
- }
351
- return route(
352
- "researcher",
353
- RESEARCHER_EVIDENCE_REASON,
354
- proposal.gap,
355
- ["evidence-grounded-responsibility-gap", `state:${proposal.stateDigest}`],
356
- );
335
+ const text = typeof input.text === "string" ? input.text.trim() : "";
336
+ const explicitIntentText = stripQuotedMaterial(text);
337
+ const proposal = input.proposal?.responsibility === "researcher" ? input.proposal : undefined;
338
+ if (!proposal || !explicitIntentText || isLowRiskTransform(explicitIntentText)) {
339
+ return route("controller", "RESEARCHER_PREFETCH_NOT_NEEDED", "No evidence-grounded multi-source compression gap was proposed.", ["no-research-prefetch"]);
340
+ }
341
+ return route("researcher", RESEARCHER_EVIDENCE_REASON, proposal.gap, ["evidence-grounded-responsibility-gap", `state:${proposal.stateDigest}`]);
357
342
  }
358
-
359
343
  /**
360
344
  * Choose the smallest useful odai role. Risk alone never creates another role.
361
345
  * Executor routing requires a frozen route card and observable net benefit;
362
346
  * those facts cannot be inferred from task prose.
363
347
  */
364
348
  export function decideRoute(input = {}) {
365
- const text = typeof input.text === "string" ? input.text.trim() : "";
366
- const explicitIntentText = stripQuotedMaterial(text);
367
- const proposal = input.proposal;
368
- const signals = [];
369
- const considerations = [];
370
- const riskPresent = matchesAny(text, RISK_PATTERNS);
371
- const unverifiedCausalClaim = matchesAny(text, UNVERIFIED_CAUSAL_PATTERNS);
372
- const concreteChangeRequest = matchesAny(text, CONCRETE_CHANGE_PATTERNS);
373
- const specificOperationalParameter = matchesAny(text, SPECIFIC_PARAMETER_PATTERNS);
374
- const urgencyPressure = matchesAny(text, URGENCY_PATTERNS);
375
- const irreversibleAction = matchesAny(text, IRREVERSIBLE_ACTION_PATTERNS);
376
- const frontend = frontendSpecializationSignals(explicitIntentText);
377
-
378
- if (riskPresent) signals.push("risk-present");
379
- if (unverifiedCausalClaim) signals.push("unverified-causal-claim");
380
- if (concreteChangeRequest) signals.push("concrete-change-request");
381
- if (specificOperationalParameter) signals.push("specific-operational-parameter");
382
- if (urgencyPressure) signals.push("urgency-pressure");
383
- if (irreversibleAction) signals.push("irreversible-action");
384
-
385
- const interruption = input.interruption;
386
- if (["planner", "executor", "frontend"].includes(interruption?.responsibility)
387
- && classifyResponsibilityInterruptionText(interruption?.continuationText) === "continue") {
388
- return route(
389
- "controller",
390
- OUTPUT_LIMIT_CONTINUATION_REASON,
391
- `The verified ${interruption.responsibility} responsibility was interrupted by the provider output limit and the user explicitly continued it.`,
392
- ["verified-output-limit-interruption", "explicit-continuation"],
393
- "upgrade",
394
- interruption.responsibility,
395
- );
396
- }
397
-
398
- const executionAuthorizedByState = proposal?.responsibility === "executor"
399
- && input.routeCard?.authorization?.status === "authorized";
400
- if (input.routeCard?.frozen === true
401
- && input.routeCard?.observableBenefit === true
402
- && (isExecutionContinuation(explicitIntentText) || executionAuthorizedByState)) {
403
- signals.push(
404
- "route-card-frozen",
405
- "observable-net-benefit",
406
- ...(executionAuthorizedByState ? ["evidence-grounded-responsibility-gap", `state:${proposal.stateDigest}`] : ["explicit-execution-continuation"]),
407
- );
408
- return route(
409
- "controller",
410
- EXECUTOR_ROUTE_CARD_REASON,
411
- executionAuthorizedByState
412
- ? proposal.gap
413
- : "A frozen route card exists, executor separation has an observable net benefit, and the user explicitly continued implementation.",
414
- signals,
415
- "upgrade",
416
- "executor",
417
- );
418
- }
419
-
420
- if (proposal?.responsibility === "user") {
421
- signals.push("user-decision-gap", `state:${proposal.stateDigest}`);
422
- return route(
423
- "controller",
424
- "USER_DECISION_REQUIRED",
425
- proposal.gap,
426
- signals,
427
- );
428
- }
429
- if (proposal?.responsibility === "reviewer") {
430
- signals.push("evidence-grounded-responsibility-gap", `state:${proposal.stateDigest}`);
431
- return route("reviewer", "REVIEWER_EVIDENCE_STATE_GAP", proposal.gap, signals);
432
- }
433
- if (proposal?.responsibility === "planner") {
434
- signals.push("evidence-grounded-responsibility-gap", `state:${proposal.stateDigest}`);
435
- return route("controller", "PLANNER_EVIDENCE_STATE_GAP", proposal.gap, signals, "upgrade", "planner");
436
- }
437
- if (proposal?.responsibility === "frontend") {
438
- signals.push("evidence-grounded-responsibility-gap", `state:${proposal.stateDigest}`);
439
- return route("controller", "FRONTEND_EVIDENCE_STATE_GAP", proposal.gap, signals, "upgrade", "frontend");
440
- }
441
-
442
- if (matchesAny(explicitIntentText, REVIEWER_PATTERNS)) {
443
- signals.push("review-language-present");
444
- considerations.push(Object.freeze({
445
- role: "reviewer",
446
- match: "lexical",
447
- action: "skip",
448
- reasonCode: "REVIEWER_GAP_NOT_PROVEN",
449
- signals: Object.freeze(["review-language-present"]),
450
- unmet: Object.freeze(["current-evidence-package", "acceptance-impact"]),
451
- }));
452
- }
453
-
454
- if (matchesAny(explicitIntentText, PLANNER_PATTERNS)) {
455
- signals.push("planning-language-present");
456
- considerations.push(Object.freeze({
457
- role: "planner",
458
- match: "lexical",
459
- action: "skip",
460
- reasonCode: "PLANNER_GAP_NOT_PROVEN",
461
- signals: Object.freeze(["planning-language-present"]),
462
- unmet: Object.freeze(["evidence-grounded-decision-branch", "observable-capability-benefit"]),
463
- }));
464
- } else if (matchesAny(explicitIntentText, PLANNER_META_PATTERNS)) {
465
- signals.push("planner-meta-question");
466
- considerations.push(Object.freeze({
467
- role: "planner",
468
- match: "meta-question",
469
- action: "skip",
470
- reasonCode: "PLANNER_META_QUERY_NO_INDEPENDENT_GAP",
471
- signals: Object.freeze(["planner-meta-question"]),
472
- unmet: Object.freeze(["prior-task-state-with-unresolved-decision-branch"]),
473
- }));
474
- }
475
-
476
- const contextualPlannerGap = riskPresent
477
- && unverifiedCausalClaim
478
- && concreteChangeRequest
479
- && (specificOperationalParameter || urgencyPressure || irreversibleAction);
480
- if (contextualPlannerGap) {
481
- return route(
482
- "controller",
483
- HIGH_IMPACT_PLANNER_REASON,
484
- "An unverified causal claim is being used to justify a concrete high-impact change, so the controller needs a stronger decision route.",
485
- signals,
486
- "upgrade",
487
- "planner",
488
- );
489
- }
490
-
491
- const frontendSignals = frontend.scope || frontend.explicit ? frontendRouteSignals(frontend) : [];
492
- if (frontend.substantial && !isLowRiskTransform(explicitIntentText)) {
493
- signals.push(...frontendSignals);
494
- return route(
495
- "controller",
496
- FRONTEND_SPECIALIST_REASON,
497
- "Substantial user-facing interface work can benefit from a configured frontend specialist without a child handoff.",
498
- signals,
499
- "upgrade",
500
- "frontend",
501
- );
502
- }
503
-
504
- signals.push(...frontendSignals, "no-independent-gap");
505
- const direct = route(
506
- "controller",
507
- "DIRECT_DEFAULT_NO_INDEPENDENT_GAP",
508
- "No evidence-grounded independent decision, execution, or acceptance gap was found.",
509
- signals,
510
- );
511
- if (frontendSignals.length > 0) {
512
- const lowRiskTransform = isLowRiskTransform(explicitIntentText);
513
- considerations.push(Object.freeze({
514
- role: "frontend",
515
- match: "partial",
516
- action: "skip",
517
- reasonCode: frontend.nonUiRequest
518
- ? "FRONTEND_API_REQUEST"
519
- : lowRiskTransform
520
- ? "FRONTEND_LOW_RISK_TRANSFORM"
521
- : "FRONTEND_BELOW_SPECIALIST_THRESHOLD",
522
- signals: Object.freeze(frontendSignals),
523
- unmet: Object.freeze(frontend.nonUiRequest
524
- ? ["ui-production-request"]
525
- : [
526
- ...(frontend.scope ? [] : ["interface-scope"]),
527
- ...(frontend.delivery ? [] : ["delivery-request"]),
528
- ...(frontend.specialistDepth ? [] : ["specialist-or-substantial-scope"]),
529
- ]),
530
- }));
531
- }
532
- return considerations.length === 0
533
- ? direct
534
- : Object.freeze({ ...direct, considerations: Object.freeze(considerations) });
349
+ const text = typeof input.text === "string" ? input.text.trim() : "";
350
+ const explicitIntentText = stripQuotedMaterial(text);
351
+ const proposal = input.proposal;
352
+ const signals = [];
353
+ const considerations = [];
354
+ const riskPresent = matchesAny(text, RISK_PATTERNS);
355
+ const unverifiedCausalClaim = matchesAny(text, UNVERIFIED_CAUSAL_PATTERNS);
356
+ const concreteChangeRequest = matchesAny(text, CONCRETE_CHANGE_PATTERNS);
357
+ const specificOperationalParameter = matchesAny(text, SPECIFIC_PARAMETER_PATTERNS);
358
+ const urgencyPressure = matchesAny(text, URGENCY_PATTERNS);
359
+ const irreversibleAction = matchesAny(text, IRREVERSIBLE_ACTION_PATTERNS);
360
+ const frontend = frontendSpecializationSignals(explicitIntentText);
361
+ if (riskPresent)
362
+ signals.push("risk-present");
363
+ if (unverifiedCausalClaim)
364
+ signals.push("unverified-causal-claim");
365
+ if (concreteChangeRequest)
366
+ signals.push("concrete-change-request");
367
+ if (specificOperationalParameter)
368
+ signals.push("specific-operational-parameter");
369
+ if (urgencyPressure)
370
+ signals.push("urgency-pressure");
371
+ if (irreversibleAction)
372
+ signals.push("irreversible-action");
373
+ const interruption = input.interruption;
374
+ if (isContinuationRole(interruption?.responsibility)
375
+ && classifyResponsibilityInterruptionText(interruption?.continuationText) === "continue") {
376
+ return route("controller", OUTPUT_LIMIT_CONTINUATION_REASON, `The verified ${interruption.responsibility} responsibility was interrupted by the provider output limit and the user explicitly continued it.`, ["verified-output-limit-interruption", "explicit-continuation"], "upgrade", interruption.responsibility);
377
+ }
378
+ const executionAuthorizedByState = proposal?.responsibility === "executor"
379
+ && input.routeCard?.authorization?.status === "authorized";
380
+ if (input.routeCard?.frozen === true
381
+ && input.routeCard?.observableBenefit === true
382
+ && (isExecutionContinuation(explicitIntentText) || executionAuthorizedByState)) {
383
+ signals.push("route-card-frozen", "observable-net-benefit", ...(executionAuthorizedByState ? ["evidence-grounded-responsibility-gap", `state:${proposal.stateDigest}`] : ["explicit-execution-continuation"]));
384
+ return route("controller", EXECUTOR_ROUTE_CARD_REASON, executionAuthorizedByState
385
+ ? proposal.gap
386
+ : "A frozen route card exists, executor separation has an observable net benefit, and the user explicitly continued implementation.", signals, "upgrade", "executor");
387
+ }
388
+ if (proposal?.responsibility === "user") {
389
+ signals.push("user-decision-gap", `state:${proposal.stateDigest}`);
390
+ return route("controller", "USER_DECISION_REQUIRED", proposal.gap, signals);
391
+ }
392
+ if (proposal?.responsibility === "reviewer") {
393
+ signals.push("evidence-grounded-responsibility-gap", `state:${proposal.stateDigest}`);
394
+ return route("reviewer", "REVIEWER_EVIDENCE_STATE_GAP", proposal.gap, signals);
395
+ }
396
+ if (proposal?.responsibility === "planner") {
397
+ signals.push("evidence-grounded-responsibility-gap", `state:${proposal.stateDigest}`);
398
+ return route("controller", "PLANNER_EVIDENCE_STATE_GAP", proposal.gap, signals, "upgrade", "planner");
399
+ }
400
+ if (proposal?.responsibility === "frontend") {
401
+ signals.push("evidence-grounded-responsibility-gap", `state:${proposal.stateDigest}`);
402
+ return route("controller", "FRONTEND_EVIDENCE_STATE_GAP", proposal.gap, signals, "upgrade", "frontend");
403
+ }
404
+ if (matchesAny(explicitIntentText, REVIEWER_PATTERNS)) {
405
+ signals.push("review-language-present");
406
+ considerations.push(Object.freeze({
407
+ role: "reviewer",
408
+ match: "lexical",
409
+ action: "skip",
410
+ reasonCode: "REVIEWER_GAP_NOT_PROVEN",
411
+ signals: Object.freeze(["review-language-present"]),
412
+ unmet: Object.freeze(["current-evidence-package", "acceptance-impact"]),
413
+ }));
414
+ }
415
+ if (matchesAny(explicitIntentText, PLANNER_PATTERNS)) {
416
+ signals.push("planning-language-present");
417
+ considerations.push(Object.freeze({
418
+ role: "planner",
419
+ match: "lexical",
420
+ action: "skip",
421
+ reasonCode: "PLANNER_GAP_NOT_PROVEN",
422
+ signals: Object.freeze(["planning-language-present"]),
423
+ unmet: Object.freeze(["evidence-grounded-decision-branch", "observable-capability-benefit"]),
424
+ }));
425
+ }
426
+ else if (matchesAny(explicitIntentText, PLANNER_META_PATTERNS)) {
427
+ signals.push("planner-meta-question");
428
+ considerations.push(Object.freeze({
429
+ role: "planner",
430
+ match: "meta-question",
431
+ action: "skip",
432
+ reasonCode: "PLANNER_META_QUERY_NO_INDEPENDENT_GAP",
433
+ signals: Object.freeze(["planner-meta-question"]),
434
+ unmet: Object.freeze(["prior-task-state-with-unresolved-decision-branch"]),
435
+ }));
436
+ }
437
+ const contextualPlannerGap = riskPresent
438
+ && unverifiedCausalClaim
439
+ && concreteChangeRequest
440
+ && (specificOperationalParameter || urgencyPressure || irreversibleAction);
441
+ if (contextualPlannerGap) {
442
+ return route("controller", HIGH_IMPACT_PLANNER_REASON, "An unverified causal claim is being used to justify a concrete high-impact change, so the controller needs a stronger decision route.", signals, "upgrade", "planner");
443
+ }
444
+ const frontendSignals = frontend.scope || frontend.explicit ? frontendRouteSignals(frontend) : [];
445
+ if (frontend.substantial && !isLowRiskTransform(explicitIntentText)) {
446
+ signals.push(...frontendSignals);
447
+ return route("controller", FRONTEND_SPECIALIST_REASON, "Substantial user-facing interface work can benefit from a configured frontend specialist without a child handoff.", signals, "upgrade", "frontend");
448
+ }
449
+ signals.push(...frontendSignals, "no-independent-gap");
450
+ const direct = route("controller", "DIRECT_DEFAULT_NO_INDEPENDENT_GAP", "No evidence-grounded independent decision, execution, or acceptance gap was found.", signals);
451
+ if (frontendSignals.length > 0) {
452
+ const lowRiskTransform = isLowRiskTransform(explicitIntentText);
453
+ considerations.push(Object.freeze({
454
+ role: "frontend",
455
+ match: "partial",
456
+ action: "skip",
457
+ reasonCode: frontend.nonUiRequest
458
+ ? "FRONTEND_API_REQUEST"
459
+ : lowRiskTransform
460
+ ? "FRONTEND_LOW_RISK_TRANSFORM"
461
+ : "FRONTEND_BELOW_SPECIALIST_THRESHOLD",
462
+ signals: Object.freeze(frontendSignals),
463
+ unmet: Object.freeze(frontend.nonUiRequest
464
+ ? ["ui-production-request"]
465
+ : [
466
+ ...(frontend.scope ? [] : ["interface-scope"]),
467
+ ...(frontend.delivery ? [] : ["delivery-request"]),
468
+ ...(frontend.specialistDepth ? [] : ["specialist-or-substantial-scope"]),
469
+ ]),
470
+ }));
471
+ }
472
+ return considerations.length === 0
473
+ ? direct
474
+ : Object.freeze({ ...direct, considerations: Object.freeze(considerations) });
535
475
  }
536
-
537
476
  export function extractLatestUserText(messages) {
538
- return genuineUserTexts(messages)[0] ?? "";
477
+ return genuineUserTexts(messages)[0] ?? "";
539
478
  }
540
-
541
479
  export function extractRoutingText(messages, sessionEvents) {
542
- const texts = genuineUserTexts(messages, sessionEvents);
543
- const latest = texts[0] ?? "";
544
- if (!latest
545
- || hasContextualPlannerGap(latest)
546
- || !matchesAny(stripQuotedMaterial(latest), CONTINUATION_PATTERNS)
547
- || isLowRiskTransform(latest)) {
548
- return latest;
549
- }
550
-
551
- let referencedHighImpact;
552
- let referencedFrontend;
553
- for (const text of texts.slice(1)) {
554
- if (hasContextualPlannerGap(text)) {
555
- referencedHighImpact = text;
556
- break;
480
+ const texts = genuineUserTexts(messages, sessionEvents);
481
+ const latest = texts[0] ?? "";
482
+ if (!latest
483
+ || hasContextualPlannerGap(latest)
484
+ || !matchesAny(stripQuotedMaterial(latest), CONTINUATION_PATTERNS)
485
+ || isLowRiskTransform(latest)) {
486
+ return latest;
487
+ }
488
+ let referencedHighImpact;
489
+ let referencedFrontend;
490
+ for (const text of texts.slice(1)) {
491
+ if (hasContextualPlannerGap(text)) {
492
+ referencedHighImpact = text;
493
+ break;
494
+ }
495
+ const frontend = frontendSpecializationSignals(stripQuotedMaterial(text));
496
+ if (frontend.scope && frontend.delivery) {
497
+ referencedFrontend = text;
498
+ break;
499
+ }
500
+ if (!isLowRiskTransform(text))
501
+ break;
502
+ }
503
+ if (referencedHighImpact) {
504
+ return `${latest}\n\nReferenced earlier high-impact user context:\n${referencedHighImpact}`;
557
505
  }
558
- const frontend = frontendSpecializationSignals(stripQuotedMaterial(text));
559
- if (frontend.scope && frontend.delivery) {
560
- referencedFrontend = text;
561
- break;
506
+ if (referencedFrontend) {
507
+ return `${latest}\n\nReferenced earlier frontend user context:\n${referencedFrontend}`;
562
508
  }
563
- if (!isLowRiskTransform(text)) break;
564
- }
565
- if (referencedHighImpact) {
566
- return `${latest}\n\nReferenced earlier high-impact user context:\n${referencedHighImpact}`;
567
- }
568
- if (referencedFrontend) {
569
- return `${latest}\n\nReferenced earlier frontend user context:\n${referencedFrontend}`;
570
- }
571
- return latest;
509
+ return latest;
572
510
  }
573
-
574
511
  export function requiresFailClosedProtection(decision) {
575
- if (decision?.reasonCode === HIGH_IMPACT_PLANNER_REASON) return true;
576
-
577
- const decisionRole = decision?.targetRole ?? decision?.role;
578
- if (!["planner", "executor", "reviewer"].includes(decisionRole)) return false;
579
-
580
- const signals = new Set(Array.isArray(decision.signals) ? decision.signals : []);
581
- if (!signals.has("risk-present")) return false;
582
- return signals.has("irreversible-action")
583
- || (signals.has("concrete-change-request")
584
- && (signals.has("specific-operational-parameter") || signals.has("urgency-pressure")));
512
+ if (decision?.reasonCode === HIGH_IMPACT_PLANNER_REASON)
513
+ return true;
514
+ if (!decision)
515
+ return false;
516
+ const decisionRole = decision.targetRole ?? decision.role;
517
+ if (decisionRole !== "planner" && decisionRole !== "executor" && decisionRole !== "reviewer")
518
+ return false;
519
+ const signals = new Set(decision.signals);
520
+ if (!signals.has("risk-present"))
521
+ return false;
522
+ return signals.has("irreversible-action")
523
+ || (signals.has("concrete-change-request")
524
+ && (signals.has("specific-operational-parameter") || signals.has("urgency-pressure")));
585
525
  }
586
-
587
526
  function observeProtocol(decision) {
588
- const shared = [
589
- "Observe-mode controller protocol:",
590
- "- No independent role was run. Do not claim independent planning or review.",
591
- "- Perform the missing responsibility locally: separate facts from assumptions, inspect decisive project evidence, and state what remains unverified.",
592
- "- Ground the path in capabilities and evidence that actually exist. Treat unavailable environments, tools, owners, thresholds, and protections as missing conditions, not facts.",
593
- "- End with concrete evidence-gathering steps and explicit decision criteria that let the user safely continue; objection alone is not a complete delivery.",
594
- ];
595
- if (!requiresFailClosedProtection(decision)) return shared;
596
-
597
- return [
598
- ...shared,
599
- "- High-impact fail-closed boundary: do not implement, persist, or publish the requested change in this turn. Use read-only evidence only.",
600
- "- Explain the protection-chain gap and keep the current state unchanged until the decision basis and end-to-end safety dependency are verified.",
601
- ];
527
+ const shared = [
528
+ "Observe-mode controller protocol:",
529
+ "- No independent role was run. Do not claim independent planning or review.",
530
+ "- Perform the missing responsibility locally: separate facts from assumptions, inspect decisive project evidence, and state what remains unverified.",
531
+ "- Ground the path in capabilities and evidence that actually exist. Treat unavailable environments, tools, owners, thresholds, and protections as missing conditions, not facts.",
532
+ "- End with concrete evidence-gathering steps and explicit decision criteria that let the user safely continue; objection alone is not a complete delivery.",
533
+ ];
534
+ if (!requiresFailClosedProtection(decision))
535
+ return shared;
536
+ return [
537
+ ...shared,
538
+ "- High-impact fail-closed boundary: do not implement, persist, or publish the requested change in this turn. Use read-only evidence only.",
539
+ "- Explain the protection-chain gap and keep the current state unchanged until the decision basis and end-to-end safety dependency are verified.",
540
+ ];
602
541
  }
603
-
604
542
  export function renderRouteNotice(decision, runtimeMode, actualRoute) {
605
- const routeRole = decision.targetRole ?? decision.role;
606
- const isUpgrade = decision.action === "upgrade"
607
- && (runtimeMode === "auto" || ["executor", "frontend"].includes(routeRole));
608
- const action = isUpgrade
609
- ? "The current controller turn requested an in-place upgrade; no child was started."
610
- : runtimeMode === "observe"
611
- ? `The ${routeRole} gap was selected in observe mode; do not start a child automatically.`
612
- : `The ${routeRole} route was selected and executed as an independent child.`;
613
- const routeIdentity = actualRoute
614
- ? [`${isUpgrade ? "requested controller route" : "verified child route"}: ${actualRoute.provider}/${actualRoute.model} (reasoning: ${actualRoute.reasoningEffort ?? "unspecified"}, maxTokens: ${actualRoute.maxTokens ?? (isUpgrade ? "inherited from Controller policy" : "provider default")})`]
615
- : [];
616
-
617
- return [
618
- "odai automatic routing decision",
619
- `role: ${decision.role}`,
620
- `action: ${isUpgrade ? "upgrade" : decision.action}`,
621
- ...(decision.targetRole ? [`target responsibility: ${decision.targetRole}`] : []),
622
- `reason: ${decision.reasonCode}`,
623
- `runtime: ${runtimeMode}`,
624
- action,
625
- ...routeIdentity,
626
- ...(runtimeMode === "observe" ? ["", ...observeProtocol(decision)] : []),
627
- ].join("\n");
543
+ const routeRole = decision.targetRole ?? decision.role;
544
+ const isUpgrade = decision.action === "upgrade"
545
+ && (runtimeMode === "auto" || ["executor", "frontend"].includes(routeRole));
546
+ const action = isUpgrade
547
+ ? "The current controller turn requested an in-place upgrade; no child was started."
548
+ : runtimeMode === "observe"
549
+ ? `The ${routeRole} gap was selected in observe mode; do not start a child automatically.`
550
+ : `The ${routeRole} route was selected and executed as an independent child.`;
551
+ const routeIdentity = actualRoute
552
+ ? [`${isUpgrade ? "requested controller route" : "verified child route"}: ${actualRoute.provider}/${actualRoute.model} (reasoning: ${actualRoute.reasoningEffort ?? "unspecified"}, maxTokens: ${actualRoute.maxTokens ?? (isUpgrade ? "inherited from Controller policy" : "provider default")})`]
553
+ : [];
554
+ return [
555
+ "odai automatic routing decision",
556
+ `role: ${decision.role}`,
557
+ `action: ${isUpgrade ? "upgrade" : decision.action}`,
558
+ ...(decision.targetRole ? [`target responsibility: ${decision.targetRole}`] : []),
559
+ `reason: ${decision.reasonCode}`,
560
+ `runtime: ${runtimeMode}`,
561
+ action,
562
+ ...routeIdentity,
563
+ ...(runtimeMode === "observe" ? ["", ...observeProtocol(decision)] : []),
564
+ ].join("\n");
628
565
  }
629
-
630
566
  export function renderMissingRouteConfigNotice(decision, runtimeMode, configFailure) {
631
- const routeRole = decision.targetRole ?? decision.role;
632
- const naturalRole = RESPONSIBILITY_LABELS[routeRole] ?? routeRole;
633
- const invalidConfig = typeof configFailure === "string" && configFailure !== "";
634
- return [
635
- `odai routing capability is ${invalidConfig ? "invalid" : "not configured"}`,
636
- `required responsibility: ${routeRole}`,
637
- `runtime: ${runtimeMode}`,
638
- `${invalidConfig ? "untrusted" : "missing"} responsibility mapping: ${routeRole}`,
639
- ...(invalidConfig ? [`configuration error: ${configFailure}`] : []),
640
- `No ${routeRole} model was called. Do not claim that this responsibility ran or that the controller was upgraded.`,
641
- `Tell the user that the required ${routeRole} model is ${invalidConfig ? "unavailable because its saved configuration is invalid" : "not configured"}. Ask them to name the provider, model, and optional reasoning effort in natural language.`,
642
- `Example: “把${naturalRole}模型设为 <provider>/<model>,推理档设为 <effort>。”`,
643
- `When the user specifies that mapping, call the odai_routing_config tool to ${invalidConfig ? "repair and " : ""}persist it. Do not ask the user to edit YAML or JSON, run a command, or add routing terminology to future task prompts.`,
644
-
645
- ...(requiresFailClosedProtection(decision) ? [
646
- "High-impact fail-closed protection is active for this turn.",
647
- "Do not implement, persist, or publish the requested change. Use read-only evidence only until the missing responsibility is configured or the decision gap is otherwise resolved.",
648
- ] : [
649
- "Continue only with parts that do not depend on the missing independent responsibility.",
650
- ]),
651
- ].join("\n");
567
+ const routeRole = decision.targetRole ?? decision.role;
568
+ const naturalRole = RESPONSIBILITY_LABELS[routeRole] ?? routeRole;
569
+ const invalidConfig = typeof configFailure === "string" && configFailure !== "";
570
+ return [
571
+ `odai routing capability is ${invalidConfig ? "invalid" : "not configured"}`,
572
+ `required responsibility: ${routeRole}`,
573
+ `runtime: ${runtimeMode}`,
574
+ `${invalidConfig ? "untrusted" : "missing"} responsibility mapping: ${routeRole}`,
575
+ ...(invalidConfig ? [`configuration error: ${configFailure}`] : []),
576
+ `No ${routeRole} model was called. Do not claim that this responsibility ran or that the controller was upgraded.`,
577
+ `Tell the user that the required ${routeRole} model is ${invalidConfig ? "unavailable because its saved configuration is invalid" : "not configured"}. Ask them to name the provider, model, and optional reasoning effort in natural language.`,
578
+ `Example: “把${naturalRole}模型设为 <provider>/<model>,推理档设为 <effort>。”`,
579
+ `When the user specifies that mapping, call the odai_routing_config tool to ${invalidConfig ? "repair and " : ""}persist it. Do not ask the user to edit YAML or JSON, run a command, or add routing terminology to future task prompts.`,
580
+ ...(requiresFailClosedProtection(decision) ? [
581
+ "High-impact fail-closed protection is active for this turn.",
582
+ "Do not implement, persist, or publish the requested change. Use read-only evidence only until the missing responsibility is configured or the decision gap is otherwise resolved.",
583
+ ] : [
584
+ "Continue only with parts that do not depend on the missing independent responsibility.",
585
+ ]),
586
+ ].join("\n");
652
587
  }
653
-
654
588
  export function renderRouteFailureNotice(decision, failure) {
655
- const routeRole = decision.targetRole ?? decision.role;
656
- if (!requiresFailClosedProtection(decision)) {
657
- return `odai ${routeRole} route failed (${failure}); continue directly as controller and do not claim delegated evidence.`;
658
- }
659
-
660
- return [
661
- `odai ${routeRole} route failed (${failure}); no independent evidence was obtained.`,
662
- "High-impact fail-closed protection is active for this turn.",
663
- "Do not implement, persist, or publish the requested change. Use read-only evidence only.",
664
- "Ground the path in capabilities and evidence that actually exist. Treat unavailable environments, tools, owners, thresholds, and protections as missing conditions, not facts.",
665
- "Explain the unresolved decision-evidence and protection-chain gaps, then provide concrete evidence-gathering steps and explicit decision criteria. Objection alone is not a complete delivery.",
666
- ].join("\n");
589
+ const routeRole = decision.targetRole ?? decision.role;
590
+ if (!requiresFailClosedProtection(decision)) {
591
+ return `odai ${routeRole} route failed (${failure}); continue directly as controller and do not claim delegated evidence.`;
592
+ }
593
+ return [
594
+ `odai ${routeRole} route failed (${failure}); no independent evidence was obtained.`,
595
+ "High-impact fail-closed protection is active for this turn.",
596
+ "Do not implement, persist, or publish the requested change. Use read-only evidence only.",
597
+ "Ground the path in capabilities and evidence that actually exist. Treat unavailable environments, tools, owners, thresholds, and protections as missing conditions, not facts.",
598
+ "Explain the unresolved decision-evidence and protection-chain gaps, then provide concrete evidence-gathering steps and explicit decision criteria. Objection alone is not a complete delivery.",
599
+ ].join("\n");
667
600
  }
668
-
669
601
  export function renderDelegationPrompt(decision, taskText, roleContract) {
670
- if (typeof roleContract !== "string" || roleContract.trim() === "") {
671
- throw new TypeError(`canonical ${decision.role} role contract must be a non-empty string`);
672
- }
673
-
674
- return [
675
- `You are the odai ${decision.role}.`,
676
- roleContract.trim(),
677
- "Runtime boundary: do not edit files, run shell commands, ask the user, or delegate further. The controller owns all final decisions and delivery.",
678
- "Context boundary: this is a bounded task and evidence packet, not an inherited controller transcript. Use only the supplied contract, task, evidence, and source pointers; do not request or reconstruct the controller's full history.",
679
- "",
680
- "Task:",
681
- taskText,
682
- ].join("\n");
602
+ if (typeof roleContract !== "string" || roleContract.trim() === "") {
603
+ throw new TypeError(`canonical ${decision.role} role contract must be a non-empty string`);
604
+ }
605
+ return [
606
+ `You are the odai ${decision.role}.`,
607
+ roleContract.trim(),
608
+ "Runtime boundary: do not edit files, run shell commands, ask the user, or delegate further. The controller owns all final decisions and delivery.",
609
+ "Context boundary: this is a bounded task and evidence packet, not an inherited controller transcript. Use only the supplied contract, task, evidence, and source pointers; do not request or reconstruct the controller's full history.",
610
+ "",
611
+ "Task:",
612
+ taskText,
613
+ ].join("\n");
683
614
  }
615
+ //# sourceMappingURL=router.mjs.map