@zhushanwen/subagent-core 0.2.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (195) hide show
  1. package/README.md +45 -2
  2. package/agents/analyst.md +60 -0
  3. package/agents/coder.md +69 -0
  4. package/agents/debugger.md +66 -0
  5. package/agents/doc-reviewer.md +49 -0
  6. package/agents/explorer.md +63 -0
  7. package/agents/general-purpose.md +32 -0
  8. package/agents/orchestrator.md +61 -0
  9. package/agents/planner.md +53 -0
  10. package/agents/researcher.md +67 -0
  11. package/agents/reviewer.md +73 -0
  12. package/dist/chunk-4KN4TTG7.js +240 -0
  13. package/dist/chunk-APZY4IME.js +27 -0
  14. package/dist/chunk-X7SZ5HLQ.js +66 -0
  15. package/dist/execution/engine/engines/zcode/constants.cjs +65 -0
  16. package/dist/execution/engine/engines/zcode/constants.d.cts +93 -1
  17. package/dist/execution/engine/engines/zcode/constants.d.ts +93 -1
  18. package/dist/execution/engine/engines/zcode/constants.js +43 -1
  19. package/dist/execution/engine/engines/zcode/reader.d.cts +1 -1
  20. package/dist/execution/engine/engines/zcode/reader.d.ts +1 -1
  21. package/dist/execution/engine/engines/zcode/reader.js +4 -234
  22. package/dist/execution/engine/paths.js +7 -19
  23. package/dist/index.cjs +14709 -100
  24. package/dist/index.d.cts +4053 -200
  25. package/dist/index.d.ts +4053 -200
  26. package/dist/index.js +14358 -102
  27. package/dist/{types-BxyAidGf.d.cts → types-DpUO16pj.d.cts} +464 -1
  28. package/dist/{types-BxyAidGf.d.ts → types-DpUO16pj.d.ts} +464 -1
  29. package/package.json +6 -3
  30. package/src/__tests__/review-fix-loop-script.test.ts +90 -2
  31. package/src/__tests__/review-fix-loop-utils.test.ts +21 -0
  32. package/src/__tests__/smoke.test.ts +9 -2
  33. package/src/execution/__tests__/agent-profile.test.ts +232 -0
  34. package/src/execution/__tests__/agents-assembly.test.ts +219 -0
  35. package/src/execution/__tests__/chat-engine-routing.test.ts +71 -0
  36. package/src/execution/__tests__/chatmode-first-round-closure-spawn.test.ts +1 -0
  37. package/src/execution/__tests__/create-concurrency-pool.test.ts +194 -0
  38. package/src/execution/__tests__/delivery-methods.test.ts +2 -0
  39. package/src/execution/__tests__/descendant-sweep.test.ts +269 -0
  40. package/src/execution/__tests__/dialog-queue.test.ts +199 -1
  41. package/src/execution/__tests__/epipe-fallback.test.ts +2 -0
  42. package/src/execution/__tests__/execution-runtime-face.test.ts +272 -0
  43. package/src/execution/__tests__/finalize-record.test.ts +106 -0
  44. package/src/execution/__tests__/gc-timer.test.ts +2 -0
  45. package/src/execution/__tests__/get-record-for-action-restart.test.ts +2 -0
  46. package/src/execution/__tests__/get-state-handshake.test.ts +127 -0
  47. package/src/execution/__tests__/keep-alive-no-progress.test.ts +378 -0
  48. package/src/execution/__tests__/kill-all-escalation.test.ts +196 -0
  49. package/src/execution/__tests__/lifecycle-manager-idle-timer-identity.test.ts +117 -0
  50. package/src/execution/__tests__/lifecycle-manager.test.ts +39 -0
  51. package/src/execution/__tests__/manifest-store-tmp-recovery.test.ts +99 -0
  52. package/src/execution/__tests__/max-turns-to-watchdog-ms.test.ts +113 -0
  53. package/src/execution/__tests__/notify-ledger.test.ts +294 -0
  54. package/src/execution/__tests__/record-store-orphan-revive.test.ts +159 -0
  55. package/src/execution/__tests__/record-store.test.ts +83 -0
  56. package/src/execution/__tests__/run-and-finalize-chatmode.test.ts +4 -0
  57. package/src/execution/__tests__/run-spawn-chatmode-settled.test.ts +1 -0
  58. package/src/execution/__tests__/run-spawn-edges.test.ts +407 -17
  59. package/src/execution/__tests__/run-spawn-integration.test.ts +1 -1
  60. package/src/execution/__tests__/run-spawn-stdout-callback-throw.test.ts +12 -4
  61. package/src/execution/__tests__/service-kill-escalation.test.ts +89 -0
  62. package/src/execution/__tests__/session-pending.test.ts +228 -0
  63. package/src/execution/__tests__/session-runner-branch-cache-lru.test.ts +110 -0
  64. package/src/execution/__tests__/session-runner-close-prune.test.ts +181 -0
  65. package/src/execution/__tests__/session-runner-epipe.test.ts +1 -0
  66. package/src/execution/__tests__/session-runner-heartbeat-idle-fallback.test.ts +226 -0
  67. package/src/execution/__tests__/settled-watchdog.test.ts +289 -0
  68. package/src/execution/__tests__/spawned-children.test.ts +153 -10
  69. package/src/execution/__tests__/subagent-actions-core.test.ts +997 -0
  70. package/src/execution/__tests__/subagent-service-message-close.test.ts +71 -10
  71. package/src/execution/__tests__/subagent-service-multiproc-guard.test.ts +174 -0
  72. package/src/execution/__tests__/subagent-service-notify-gate.test.ts +266 -0
  73. package/src/execution/__tests__/subagent-service-parent-guard.test.ts +3 -0
  74. package/src/execution/__tests__/subagent-service-recovery-bounds.test.ts +316 -0
  75. package/src/execution/__tests__/timeout-integration.test.ts +7 -7
  76. package/src/execution/__tests__/ui-request-handler-factory.test.ts +95 -1
  77. package/src/execution/__tests__/ui-request-queue.test.ts +25 -0
  78. package/src/execution/__tests__/worktree-git-ops.test.ts +571 -0
  79. package/src/execution/__tests__/worktree-reconcile-aging.test.ts +204 -0
  80. package/src/execution/agent-registry.ts +225 -1
  81. package/src/execution/agents-assembly.ts +88 -0
  82. package/src/execution/concurrency-pool.ts +71 -9
  83. package/src/execution/dialog-queue.ts +101 -3
  84. package/src/execution/engine/__tests__/conformance/contract.abort.test.ts +49 -2
  85. package/src/execution/engine/__tests__/conformance/contract.agent-events.test.ts +87 -1
  86. package/src/execution/engine/__tests__/conformance/engine-conformance.live.test.ts +26 -0
  87. package/src/execution/engine/__tests__/conformance/golden-replay.zcode.test.ts +83 -1
  88. package/src/execution/engine/__tests__/conformance/zcode-appserver-harness.ts +131 -0
  89. package/src/execution/engine/__tests__/registry.test.ts +90 -1
  90. package/src/execution/engine/engine-discovery.ts +12 -16
  91. package/src/execution/engine/engines/pi/task-spec-mapper.ts +3 -3
  92. package/src/execution/engine/engines/zcode/__tests__/__fixtures__/fake-appserver.mjs +274 -0
  93. package/src/execution/engine/engines/zcode/__tests__/__fixtures__/zcode-golden-appserver.json +36 -0
  94. package/src/execution/engine/engines/zcode/__tests__/connection.test.ts +472 -0
  95. package/src/execution/engine/engines/zcode/__tests__/preparer-appserver.test.ts +387 -0
  96. package/src/execution/engine/engines/zcode/__tests__/session-channel.test.ts +780 -0
  97. package/src/execution/engine/engines/zcode/__tests__/zcode-engine-appserver.test.ts +815 -0
  98. package/src/execution/engine/engines/zcode/__tests__/zcode-engine-degrade.test.ts +462 -0
  99. package/src/execution/engine/engines/zcode/__tests__/zcode-engine.live.test.ts +119 -1
  100. package/src/execution/engine/engines/zcode/__tests__/zcode-engine.test.ts +136 -6
  101. package/src/execution/engine/engines/zcode/appserver-home.ts +442 -0
  102. package/src/execution/engine/engines/zcode/appserver-probe.ts +141 -0
  103. package/src/execution/engine/engines/zcode/connection.ts +585 -0
  104. package/src/execution/engine/engines/zcode/constants.ts +129 -0
  105. package/src/execution/engine/engines/zcode/golden-sample.ts +54 -8
  106. package/src/execution/engine/engines/zcode/preparer.ts +25 -22
  107. package/src/execution/engine/engines/zcode/session-channel.ts +656 -0
  108. package/src/execution/engine/engines/zcode/zcode-engine.ts +909 -41
  109. package/src/execution/engine/host-task-spec.ts +3 -3
  110. package/src/execution/engine/port.ts +41 -1
  111. package/src/execution/engine/registry.ts +53 -0
  112. package/src/execution/finalize-record.ts +63 -5
  113. package/src/execution/get-state-handshake.ts +85 -10
  114. package/src/execution/lifecycle-manager.ts +27 -3
  115. package/src/execution/manifest-store.ts +53 -62
  116. package/src/execution/notifier.ts +10 -10
  117. package/src/execution/notify-ledger.ts +117 -16
  118. package/src/execution/record-entry.ts +8 -2
  119. package/src/execution/record-store.ts +29 -15
  120. package/src/execution/session-pending.ts +213 -62
  121. package/src/execution/session-runner.ts +974 -128
  122. package/src/execution/sessions-index.ts +10 -55
  123. package/src/execution/settled-watchdog.ts +99 -0
  124. package/src/execution/subagent-actions-core.ts +686 -0
  125. package/src/execution/subagent-service.ts +396 -49
  126. package/src/execution/ui-request-handler-factory.ts +27 -4
  127. package/src/execution/worktree-git-ops.ts +397 -0
  128. package/src/execution/worktree-manager.ts +72 -10
  129. package/src/execution/worktree-registry.ts +6 -12
  130. package/src/index.ts +413 -6
  131. package/src/orchestration/__tests__/__fixtures__/worker-template.snapshot.txt +42 -3
  132. package/src/orchestration/__tests__/agent-call-catch-fallback.test.ts +2 -4
  133. package/src/orchestration/__tests__/args-meta.test.ts +358 -0
  134. package/src/orchestration/__tests__/error-recovery-handlers.test.ts +1 -8
  135. package/src/orchestration/__tests__/error-recovery-rebuild-failure.test.ts +312 -0
  136. package/src/orchestration/__tests__/error-recovery-terminal-hardening.test.ts +382 -0
  137. package/src/orchestration/__tests__/file-run-store-prune.test.ts +168 -0
  138. package/src/orchestration/__tests__/file-run-store-throttle.test.ts +168 -0
  139. package/src/orchestration/__tests__/file-run-store.test.ts +389 -0
  140. package/src/orchestration/__tests__/helpers/flush-microtasks.ts +13 -0
  141. package/src/orchestration/__tests__/launcher-nested-workflow.test.ts +34 -0
  142. package/src/orchestration/__tests__/lifecycle-abort-broadcast-signal.test.ts +357 -0
  143. package/src/orchestration/__tests__/lifecycle-recover-crashed.test.ts +289 -0
  144. package/src/orchestration/__tests__/lifecycle.test.ts +77 -0
  145. package/src/orchestration/__tests__/run-snapshot.test.ts +353 -0
  146. package/src/orchestration/__tests__/script-generate.test.ts +314 -0
  147. package/src/orchestration/__tests__/worker-pending-timeout-abort.test.ts +275 -0
  148. package/src/orchestration/__tests__/worker-script-builder-runtime.test.ts +78 -1
  149. package/src/orchestration/__tests__/workflow-files.test.ts +186 -0
  150. package/src/orchestration/__tests__/workflow-run-summary.test.ts +119 -0
  151. package/src/orchestration/__tests__/workflow-script-registry-impl.test.ts +124 -0
  152. package/src/orchestration/agent-opts-resolver.ts +7 -7
  153. package/src/orchestration/args-meta.ts +198 -0
  154. package/src/orchestration/error-recovery.ts +416 -146
  155. package/src/orchestration/execute-agent-call.ts +9 -9
  156. package/src/orchestration/file-run-store.ts +327 -0
  157. package/src/orchestration/launcher.ts +35 -26
  158. package/src/orchestration/lifecycle.ts +355 -79
  159. package/src/orchestration/models/agent-call.ts +7 -7
  160. package/src/orchestration/models/budget.ts +5 -5
  161. package/src/orchestration/models/run-runtime.ts +13 -13
  162. package/src/orchestration/models/trace.ts +8 -8
  163. package/src/orchestration/models/workflow-run.ts +27 -27
  164. package/src/orchestration/models/workflow-script.ts +4 -4
  165. package/src/orchestration/run-snapshot.ts +266 -0
  166. package/src/orchestration/script-generate.ts +154 -0
  167. package/src/orchestration/script-lint.ts +33 -33
  168. package/src/orchestration/worker-handle.ts +10 -10
  169. package/src/orchestration/worker-host.ts +10 -10
  170. package/src/orchestration/worker-script-builder.ts +401 -346
  171. package/src/orchestration/workflow-files.ts +37 -11
  172. package/src/orchestration/workflow-run-summary.ts +69 -0
  173. package/src/orchestration/workflow-script-registry-impl.ts +31 -9
  174. package/src/shared/__tests__/agent-ref.test.ts +209 -2
  175. package/src/shared/__tests__/atomic-write.test.ts +267 -0
  176. package/src/shared/__tests__/bounded-serialize.test.ts +236 -0
  177. package/src/shared/__tests__/injection-render.test.ts +518 -0
  178. package/src/shared/__tests__/resource-discovery-host-roots.test.ts +474 -0
  179. package/src/shared/__tests__/resource-discovery.test.ts +3 -2
  180. package/src/shared/agent-ref.ts +143 -2
  181. package/src/shared/atomic-write.ts +320 -0
  182. package/src/shared/bounded-serialize.ts +154 -0
  183. package/src/shared/injection-render.ts +279 -0
  184. package/src/shared/meta-parser.ts +41 -1
  185. package/src/shared/resource-discovery.ts +104 -37
  186. package/src/shared/resource-meta.ts +14 -0
  187. package/src/shared/xml-injection.ts +9 -9
  188. package/workflows/README.md +9 -9
  189. package/workflows/chain.js +4 -2
  190. package/workflows/map-reduce.js +5 -3
  191. package/workflows/parallel.js +5 -3
  192. package/workflows/review-fix-loop-utils.cjs +14 -3
  193. package/workflows/review-fix-loop.js +18 -7
  194. package/workflows/scatter-gather.js +4 -2
  195. package/dist/chunk-3VOERJPJ.js +0 -22
@@ -0,0 +1,198 @@
1
+ // src/orchestration/args-meta.ts
2
+ //
3
+ // U9(D9 / B3 / B4):workflow @pi-meta parameters(JSON Schema)→ 已知参数键集、
4
+ // args 平铺检测、参数归一组装。平移自 pi-sw tool-workflow.ts:136-196(m6「schema 即
5
+ // SSOT」——替代 21 键硬编码 KNOWN_ARG_KEYS,消除与参数定义的漂移面)。
6
+ //
7
+ // 相对 pi-sw 原实现的两处平台耦合剥离(行为等值,见实施计划偏差登记表):
8
+ // - TOOL_TOP_LEVEL(pi workflow tool 顶层键集,pi 侧 schema 事实)→ 参数化 reservedKeys
9
+ // 由宿主注入(同 U1 knownNames / D7 queuePolicy 的宿主差异参数化先例);core 引擎
10
+ // 无关,不内嵌任何宿主 tool schema。pi-sw 消费改造时传自己的 TOOL_TOP_LEVEL 即得
11
+ // 等值行为。
12
+ // - @zhushanwen/pi-extension-logger → core logger facade(同语义 warn,平台中立)。
13
+ //
14
+ // 平铺检测语义(m6 定稿,勿改):弱模型把 args 子字段平铺到 params 顶层是 P0 级
15
+ // 静默失败(args ?? {} 会静默空启动),检测命中必须显式暴露——core 以 warnings 数据
16
+ // 承载,是否升级为 fatal 由宿主裁决(pi 现行为是 throw,消费改造时 adapter 对
17
+ // flattened_args 警告 throw 即等值)。
18
+
19
+ import { getLogger } from "../core/logger.ts";
20
+
21
+ const logger = getLogger("args-meta");
22
+
23
+ const EMPTY_RESERVED_KEYS: ReadonlySet<string> = new Set<string>();
24
+
25
+ /** 已知参数键集:exact = properties 精确键;patterns = patternProperties 原样转正则。 */
26
+ export interface ArgKeySet {
27
+ readonly exact: ReadonlySet<string>;
28
+ readonly patterns: readonly RegExp[];
29
+ }
30
+
31
+ /** 键集构建选项(宿主差异注入点)。 */
32
+ export interface ArgMetaOptions {
33
+ /**
34
+ * 宿主调用信封顶层保留键(如 pi workflow tool 的 action/name/slug/args/model/...)。
35
+ * workflow 参数名与保留键撞名时,顶层同名键是信封参数而非平铺(m6 评审 M-3):
36
+ * exact 构建排除保留键;能命中任一保留键的 pattern 整条跳过(^run.*$ 类会误伤
37
+ * runId/name 等合法调用,m6 exec-review S1)。缺省空集(core 中性形态)。
38
+ */
39
+ readonly reservedKeys?: ReadonlySet<string>;
40
+ }
41
+
42
+ /**
43
+ * properties → exact 精确键集(排除 reservedKeys——workflow 参数名与保留键撞名时,
44
+ * 顶层同名键是信封参数而非平铺,m6 评审 M-3)。非对象形状(含 undefined/null)
45
+ * 返回空集。
46
+ */
47
+ function collectExactKeys(props: unknown, reserved: ReadonlySet<string>): Set<string> {
48
+ const exact = new Set<string>();
49
+ if (props === null || typeof props !== "object") return exact;
50
+ for (const k of Object.keys(props as Record<string, unknown>)) {
51
+ if (!reserved.has(k)) exact.add(k);
52
+ }
53
+ return exact;
54
+ }
55
+
56
+ /**
57
+ * patternProperties → 正则数组(schema pattern 已是正则源码,直接 new RegExp;
58
+ * 自动兼容 \d{2} 等变体)。跳过能命中保留键的 pattern——否则 ^run.*$ 类 pattern
59
+ * 会匹配 runId/name 等信封键,合法调用恒误报(m6 exec-review S1)。非法 pattern
60
+ * (schema 校验 m3 已保证合法,双保险)跳过并 warn。
61
+ */
62
+ function compilePatterns(pp: unknown, reserved: ReadonlySet<string>): RegExp[] {
63
+ const patterns: RegExp[] = [];
64
+ if (pp === null || typeof pp !== "object") return patterns;
65
+ for (const p of Object.keys(pp as Record<string, unknown>)) {
66
+ try {
67
+ const re = new RegExp(p);
68
+ if ([...reserved].some((tk) => re.test(tk))) continue;
69
+ patterns.push(re);
70
+ } catch (err) {
71
+ logger.warn(`[args-meta] patternProperties 非法正则跳过: ${p}`, {
72
+ reason: err instanceof Error ? err.message : String(err),
73
+ });
74
+ }
75
+ }
76
+ return patterns;
77
+ }
78
+
79
+ /**
80
+ * 从 workflow 参数 schema(@pi-meta parameters)动态构建平铺检测的已知键集。
81
+ *
82
+ * - exact:properties keys(精确匹配,排除 reservedKeys)
83
+ * - patterns:patternProperties 原样转正则数组(schema pattern 已是正则源码,
84
+ * 直接 new RegExp;自动兼容 \d{2} 等变体)
85
+ * - meta 缺失/非对象 → 空键集(legacy const-meta 类无参数契约,检测跳过)
86
+ */
87
+ export function argKeysFromMeta(
88
+ meta: Record<string, unknown> | undefined | null,
89
+ options?: ArgMetaOptions,
90
+ ): ArgKeySet {
91
+ const reserved = options?.reservedKeys ?? EMPTY_RESERVED_KEYS;
92
+ if (meta === undefined || meta === null || typeof meta !== "object") {
93
+ return { exact: new Set<string>(), patterns: [] };
94
+ }
95
+ const schema = meta as Record<string, unknown>;
96
+ return {
97
+ exact: collectExactKeys(schema.properties, reserved),
98
+ patterns: compilePatterns(schema.patternProperties, reserved),
99
+ };
100
+ }
101
+
102
+ /**
103
+ * 平铺检测内部谓词(接收已构建键集)——normalizeArgsByMeta 复用以避免二次构建
104
+ * 键集触发重复 warn;公开入口 findFlattenedArgKeys(params, meta) 按设计签名接收
105
+ * meta 并内联构建。两路径谓词逐字同源,行为必然一致。
106
+ */
107
+ function filterFlattenedKeys(p: Record<string, unknown>, keys: ArgKeySet): string[] {
108
+ const args = typeof p.args === "object" && p.args !== null ? p.args : undefined;
109
+ const isKnownKey = (k: string) =>
110
+ keys.exact.has(k) || keys.patterns.some((re) => re.test(k));
111
+ // hasOwnProperty.call 而非 in(原型链——constructor/toString 类参数名不被继承键掩盖)
112
+ return Object.keys(p).filter(
113
+ (k) =>
114
+ isKnownKey(k) &&
115
+ !(args !== undefined && Object.prototype.hasOwnProperty.call(args, k)),
116
+ );
117
+ }
118
+
119
+ /**
120
+ * 检测弱模型把 args 子字段平铺到 params 顶层(P0 静默失败防护)。
121
+ * 返回被平铺的键名列表(空 = 未平铺)。匹配谓词:exact 命中 || pattern 命中
122
+ * (pattern 自带数字后缀语义——loose startsWith 会误报 batchl/target1);args 内
123
+ * 已存在的键不算平铺(顶层 + args 共存不算平铺)。
124
+ *
125
+ * 参数取 unknown 以解耦宿主 params 类型限制、便于测试构造任意对象。
126
+ */
127
+ export function findFlattenedArgKeys(
128
+ params: unknown,
129
+ meta: Record<string, unknown> | undefined | null,
130
+ options?: ArgMetaOptions,
131
+ ): string[] {
132
+ if (typeof params !== "object" || params === null) return [];
133
+ const keys = argKeysFromMeta(meta, options);
134
+ return filterFlattenedKeys(params as Record<string, unknown>, keys);
135
+ }
136
+
137
+ /** 组装层警告(结构化承载,宿主决定展示/日志/fatal 升级)。 */
138
+ export type ArgMetaWarning =
139
+ | {
140
+ /** 无参数契约(meta 未声明或解析为空)——平铺检测跳过,args 不校验(m6 M-2 显式信号)。 */
141
+ code: "no_parameter_contract";
142
+ message: string;
143
+ }
144
+ | {
145
+ /** args 子字段被平铺到顶层——修正动作留宿主(pi 现行为是带 Correct 正例 throw)。 */
146
+ code: "flattened_args";
147
+ message: string;
148
+ keys: readonly string[];
149
+ };
150
+
151
+ /** normalizeArgsByMeta 产物。 */
152
+ export interface NormalizedArgs {
153
+ /**
154
+ * 归一后的 args:params.args ?? {}(params 非对象时为 {})。args 字段为非对象
155
+ * 标量时原样透传——类型校验责任在 args-validator(schema chokepoint),本函数
156
+ * 不发明约束(与 m3 exec-review M2 裁决一致)。
157
+ */
158
+ readonly args: unknown;
159
+ readonly warnings: readonly ArgMetaWarning[];
160
+ }
161
+
162
+ /**
163
+ * 组装函数:按 meta 归一 params 为 { args, warnings }(pi actionRun 参数处理段的
164
+ * 纯函数化——argKeysFromMeta + 空契约信号 + 平铺检测 + args 归一四步单点收口)。
165
+ *
166
+ * 警告语义与 pi 现行为对位:
167
+ * - no_parameter_contract ↔ pi logger.warn「未声明参数契约——平铺检测跳过」(M-2)
168
+ * - flattened_args ↔ pi throw「Detected ... they belong inside 'args'」(Correct
169
+ * 正例含宿主 tool 键 action/name——平台事实留宿主拼接,core 文案保持中立)
170
+ */
171
+ export function normalizeArgsByMeta(
172
+ params: unknown,
173
+ meta: Record<string, unknown> | undefined | null,
174
+ options?: ArgMetaOptions,
175
+ ): NormalizedArgs {
176
+ const keys = argKeysFromMeta(meta, options);
177
+ const warnings: ArgMetaWarning[] = [];
178
+ if (keys.exact.size === 0 && keys.patterns.length === 0) {
179
+ // m6 exec-review M1:无参数契约(未声明/解析空)→ 显式警告——静默退化变显式
180
+ warnings.push({
181
+ code: "no_parameter_contract",
182
+ message: "未声明参数契约(或解析为空)——平铺检测跳过,args 不校验",
183
+ });
184
+ }
185
+ if (typeof params === "object" && params !== null) {
186
+ const p = params as Record<string, unknown>;
187
+ const flattened = filterFlattenedKeys(p, keys);
188
+ if (flattened.length > 0) {
189
+ warnings.push({
190
+ code: "flattened_args",
191
+ keys: flattened,
192
+ message: `Detected ${flattened.join(", ")} at top level — they belong inside 'args'.`,
193
+ });
194
+ }
195
+ return { args: p.args ?? {}, warnings };
196
+ }
197
+ return { args: {}, warnings };
198
+ }