easy-coding-harness 0.10.0-beta.6 → 0.10.0-beta.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -6,6 +6,23 @@
6
6
  - `y`:常规功能升级
7
7
  - `z`:日常 bug 修复
8
8
 
9
+ ## 0.10.0-beta.7
10
+
11
+ - Workflow floor 改为 Standard 居中的复合判定:单仓、单 Unit、非并行且最多 5 个文件的
12
+ 低风险局部修改优先 Fast;普通业务、多 Unit/文件、闭合的跨仓修改默认 Standard;只有
13
+ 明确高风险与真实复杂度/大影响面同时存在才进入 Strict。
14
+ - 仓库数量只统计 execution plan 中实际修改文件所属的 Git root。Canonical Spec 的未选
15
+ task、依赖摘要、未使用 `repo_paths`,以及 supermodule 已登记但未修改的子项目不再抬高
16
+ Workflow;风险描述、标题或文件路径中仅出现 `payment` / `schema` 等普通领域词也不再
17
+ 单独触发 Strict,并行执行本身也只作为 Standard 信号。
18
+ - ANALYSIS 新增渐进成本预算和 `Local Baseline`:只读取当前变更需要的最近邻同类代码、
19
+ 合同和测试,按证据继承命名、空值/异常处理、分层、方法粒度、常量与注释习惯,避免
20
+ 无关全仓扫描、投机性抽象和碎片化小方法。
21
+ - IMPLEMENT/REVIEW 与三平台子代理统一克制设计合同:允许符合局部惯例的直观魔法值,
22
+ 禁止为单个 getter return 创建常量;新增核心 Java 类的全部方法/字段、已有核心类中新增或
23
+ 实质修改的方法/字段必须有 Javadoc,核心或复杂逻辑补充必要意图/约束注释,且不批量改造
24
+ 未触碰历史代码。
25
+
9
26
  ## 0.10.0-beta.6
10
27
 
11
28
  - Canonical Spec 首次路由新增 `inspect-dev-spec --manifest-only`:只通过 normalized remote
package/README.md CHANGED
@@ -85,7 +85,10 @@ any stage --[user abort via ec-task-close]--> CLOSED
85
85
  逐边确认,`guard` 确认 ANALYSIS → IMPLEMENT 与 VERIFICATION → MEMORY,`confirm` 只在
86
86
  ANALYSIS → IMPLEMENT 确认一次,随后各阶段在质量门禁通过后自动推进,`auto` 从开始即
87
87
  自动推进。
88
- - 工作流模式优先级为 session 覆盖 > 项目 `behavior.workflow_mode` > `adaptive`。Adaptive 在 ANALYSIS 结束时根据风险解析、展示并冻结为 `fast`、`standard` 或 `strict`,用户可在风险下限之上调整。
88
+ - 工作流模式优先级为 session 覆盖 > 项目 `behavior.workflow_mode` > `adaptive`。Adaptive
89
+ 以 Standard 作为普通业务默认:单仓单 Unit、非并行且不超过 5 个文件的低风险局部修改
90
+ 优先 Fast;只有明确高风险与真实复杂度/大影响面同时存在才进入 Strict。仓库数只按当前
91
+ execution plan 实际修改的 Git root 计算,用户可在机械风险下限之上调整。
89
92
  - ANALYSIS 会先通过问答闭合影响技术路线、接口、模型、状态、范围或验收的实质性问题,
90
93
  并在 Dev-Spec 中记录唯一的 `decision_status: closed`。会话只展示核心方案、验收摘要、
91
94
  Workflow Mode 与主要风险;完整 `dev-spec.md` 通过绝对本地链接或路径按需查看。
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "easy-coding-harness",
3
- "version": "0.10.0-beta.6",
3
+ "version": "0.10.0-beta.7",
4
4
  "description": "CLI scaffold for installing Easy Coding harness files into agent-native directories.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -16,7 +16,17 @@ complete exactly that unit. Your reply IS the return value, not a message to a h
16
16
  file. All context you need is already in the task card.
17
17
  - Make no workflow stage-transition decisions. You do not know the state machine exists.
18
18
  - Follow the coding rules and architecture context embedded in the card.
19
+ - Follow the task card's `Local Baseline`: match nearby naming, control flow, null/error handling,
20
+ layering, object modeling, method granularity, literal usage, and comment style unless a stated
21
+ correctness, security, requirement, or hard-rule reason requires a deviation.
19
22
  - Treat the task card's `Code Comments` author value and field/member/constant rules as mandatory.
23
+ - Do not add generic defensive null checks, speculative abstractions/layers, fragmented one-use
24
+ micro-methods, or a constant that exists only to hold one getter return.
25
+ - Local, obvious magic values are allowed when they match surrounding code; create constants for
26
+ reuse, stable domain/config/protocol semantics, or established project convention.
27
+ - Every method and field in a new core Java class, and every added or materially modified method
28
+ or field in an existing core Java class, must have meaningful Javadoc; comment complex logic
29
+ where intent or constraints are not obvious.
20
30
  - Treat acceptance criteria, test points, contracts, and risks in the card as required inputs.
21
31
  - Run the exact targeted checks requested by the card and report their real outcome.
22
32
  - Preserve each existing file's original encoding; never silently convert.
@@ -15,7 +15,12 @@ dimension named in your task card. Your reply IS the return value.
15
15
  - correctness → does the implementation match the dev-spec requirement? edge cases,
16
16
  null/empty handling, races, off-by-one.
17
17
  - compliance → does the code obey the RULES sections in the card? naming, format, comment
18
- language, error handling.
18
+ language, error handling, and the evidenced Local Baseline.
19
+ - Do not request defensive null checks, abstraction, constant extraction, or legacy-wide comment
20
+ cleanup solely as generic best practice. Flag unjustified local-style deviations, speculative
21
+ layers, fragmented one-use micro-methods, constants created only for a getter return, and
22
+ missing Javadoc on any method/field in a new core Java class or any added/materially modified
23
+ method/field in an existing core Java class.
19
24
  - `error` means a demonstrated acceptance, contract, security, or build failure. Use `warning`
20
25
  for a credible risk and `info` for non-blocking maintainability advice.
21
26
 
@@ -15,7 +15,17 @@ Hard constraints:
15
15
  the card.
16
16
  - Make no workflow stage-transition decisions; you do not know the state machine exists.
17
17
  - Follow the coding rules and architecture context embedded in the card.
18
+ - Follow the task card's "Local Baseline": match nearby naming, control flow, null/error handling,
19
+ layering, object modeling, method granularity, literal usage, and comment style unless a stated
20
+ correctness, security, requirement, or hard-rule reason requires a deviation.
18
21
  - Treat the task card's "Code Comments" author value and field/member/constant rules as mandatory.
22
+ - Do not add generic defensive null checks, speculative abstractions/layers, fragmented one-use
23
+ micro-methods, or a constant that exists only to hold one getter return.
24
+ - Local, obvious magic values are allowed when they match surrounding code; create constants for
25
+ reuse, stable domain/config/protocol semantics, or established project convention.
26
+ - Every method and field in a new core Java class, and every added or materially modified method
27
+ or field in an existing core Java class, must have meaningful Javadoc; comment complex logic
28
+ where intent or constraints are not obvious.
19
29
  - Treat acceptance criteria, test points, contracts, and risks in the card as required inputs.
20
30
  - Run the exact targeted checks requested by the card and report their real outcome.
21
31
  - Preserve each existing file's original encoding; never silently convert.
@@ -14,7 +14,12 @@ Stance:
14
14
  - correctness -> does the implementation match the dev-spec requirement? edge cases,
15
15
  null/empty handling, races, off-by-one.
16
16
  - compliance -> does the code obey the RULES sections in the card? naming, format, comment
17
- language, error handling.
17
+ language, error handling, and the evidenced Local Baseline.
18
+ - Do not request defensive null checks, abstraction, constant extraction, or legacy-wide comment
19
+ cleanup solely as generic best practice. Flag unjustified local-style deviations, speculative
20
+ layers, fragmented one-use micro-methods, constants created only for a getter return, and
21
+ missing Javadoc on any method/field in a new core Java class or any added/materially modified
22
+ method/field in an existing core Java class.
18
23
  - error means a demonstrated acceptance, contract, security, or build failure. Use warning
19
24
  for a credible risk and info for non-blocking maintainability advice.
20
25
 
@@ -147,7 +147,14 @@ agent must be able to see what was generated and on what evidence.
147
147
  - Naming conventions actually in use (scan representative files)
148
148
  - Comment language: if more than 70% of existing comments are Chinese, the rule is
149
149
  "comments in Chinese"; same logic for English; mixed → follow each file's dominant language
150
- - Error handling style, import ordering, formatter/linter in use (read their configs)
150
+ - Null/empty handling and error-handling style, including where the project intentionally
151
+ relies on upstream contracts instead of adding defensive checks
152
+ - Existing class/method extraction granularity and architecture boundaries; do not turn a
153
+ preference for single responsibility into a generic demand for many one-use helpers
154
+ - Literal and constant conventions, including when local magic values are accepted and when
155
+ a stable domain/config/protocol value is promoted to a named constant
156
+ - Javadoc/doc-comment coverage for core code and the inline-comment style used for complex logic
157
+ - Import ordering and formatter/linter in use (read their configs)
151
158
  Structure as one section per language plus a General section. Every rule must be
152
159
  mechanically checkable — "be clean" is not a rule; "exported functions carry explicit
153
160
  return types" is.
@@ -21,6 +21,13 @@ Communicate with the user in the user's language.
21
21
  4. Inspect concrete code paths and tests. Expand context only when evidence reveals another
22
22
  dependency or risk.
23
23
 
24
+ Apply a progressive cost budget while doing this work. A likely Fast task reads only the nearest
25
+ comparable implementation, its direct contracts, and targeted tests. Standard reads the affected
26
+ module closure. Expand into cross-module or repository-wide context only after concrete evidence
27
+ shows the compound high-risk and complexity signals required for Strict. Do not scan unrelated
28
+ repositories, the full Spec, broad Git history, or every architecture section merely to prove
29
+ that a bounded task might be complicated.
30
+
24
31
  For a task with `task.json.spec_source`, re-run `inspect-dev-spec` against the stored source, exact
25
32
  `selected_spec_tasks`, and only their stored `task.repo_paths` bindings. Schema, Spec ID, design
26
33
  revision, and `design_sha256` must still match. A changed `document_sha256` with the same design is
@@ -56,6 +63,19 @@ Use shared execution dependency status directly. Do not inspect another local Ha
56
63
  history to re-prove a completed hard dependency, and do not repeat dependency or baseline
57
64
  explanations after the selected inspection has recorded them.
58
65
 
66
+ ## Local implementation baseline
67
+
68
+ For every code unit, inspect the nearest same-module, same-role implementation before planning.
69
+ Record a concise `local_baseline` covering only evidenced conventions that affect this change:
70
+ naming and control flow, null/empty and error handling, layering and dependency direction, object
71
+ modeling, method extraction granularity, literal/constant usage, and comments/Javadoc. Prefer the
72
+ closest comparable code over a repository-wide average. Explicit requirements, correctness,
73
+ security, and project hard rules still take precedence; otherwise do not replace safe local
74
+ conventions with generic best practices.
75
+
76
+ Do not ask the user to choose a style already answered consistently by comparable code. Ask only
77
+ when local evidence conflicts or a deviation can change the contract, risk, or acceptance result.
78
+
59
79
  ## Analysis artifacts
60
80
 
61
81
  Copy `.easy-coding/templates/dev-spec-skeleton.md` first, then replace every `[[EC_TODO:...]]`.
@@ -101,6 +121,7 @@ Execution plan records use:
101
121
  "test_points": ["targeted check"],
102
122
  "contracts": ["input/output/invariant or none"],
103
123
  "risks": ["known risk or none"],
124
+ "local_baseline": ["evidenced local convention and source path"],
104
125
  "repo_id": "R1",
105
126
  "source_task_id": "R1-T1",
106
127
  "source_step_ids": ["S1"],
@@ -132,8 +153,10 @@ For every selected source test, `test-strategy.md` must spell out its Test ID, s
132
153
  owning Unit ID, repository-relative test file, and exact Canonical command; the state gate checks
133
154
  these markers mechanically.
134
155
 
135
- Prefer one coherent unit over artificial file-level splitting. Use parallel only for truly
136
- independent write scopes. Better unit contracts reduce later REVIEW rework.
156
+ Prefer one coherent unit over artificial file-level splitting. Do not split a class or method by
157
+ line count, or create many one-use helpers, merely to make the plan look modular. Extract only a
158
+ clear semantic boundary, reuse point, or independently testable responsibility. Use parallel only
159
+ for truly independent write scopes. Better unit contracts reduce later REVIEW rework.
137
160
 
138
161
  Code tasks require `test-strategy.md`; explicit `doc`, `analysis`, and `report` tasks do not.
139
162
 
@@ -196,19 +219,30 @@ Use its `minimum_mode` and `reasons` as the proposal floor. You may raise this r
196
219
  uncertainty or user preference requires more rigor, but never lower or replace it with a
197
220
  self-reported floor. The state API rechecks the floor when the proposal is saved and frozen.
198
221
 
199
- The calculation classifies:
200
-
201
- - `fast`: one low-risk unit, local behavior, no public contract/schema/security/concurrency or
202
- migration impact, targeted test available.
203
- - `standard`: ordinary multi-file feature/fix, bounded contract impact, existing patterns and
204
- impacted tests available.
205
- - `strict`: state machine, configuration/schema migration, security/payment/data-loss risk,
206
- public or cross-repository contract, broad concurrency, platform generators, or uncertain
207
- blast radius.
222
+ The calculation is intentionally Standard-centered:
223
+
224
+ - `fast`: one coherent, non-parallel unit in one actually modified repository, at most five
225
+ changed files, no explicit high-risk signal, and no public or cross-repository contract impact.
226
+ Small parameter changes, bounded field/mapping edits, and a few ordinary model files should
227
+ normally remain Fast.
228
+ - `standard`: the default for ordinary business work. Multiple units/files, bounded compatibility
229
+ work, actual but contained multi-repository changes, broad low-risk work, and bounded high-risk
230
+ work remain Standard.
231
+ - `strict`: requires both an explicit high-risk signal and concrete complexity/blast-radius
232
+ evidence. Complexity means actual multi-repository edits, at least four units, at least ten
233
+ changed files, or a public/cross-repository contract. Parallel execution is a Standard signal
234
+ by itself. Generic domain words in a risk description, title, file path, Spec repository
235
+ catalog, or unselected task are never sufficient evidence of high risk.
236
+
237
+ Repository count comes only from repositories that own files in current plan units. Canonical
238
+ Spec metadata, unselected tasks, dependency summaries, unused `repo_paths`, and supermodule child
239
+ registrations do not raise the mode. A real multi-repository change is a Standard signal by
240
+ itself and reaches Strict only when an explicit high-risk signal is also present.
208
241
 
209
242
  If configuration is concrete, it is also a floor. The selected mode may be raised by the user
210
- but never placed below either floor. Explain the decision and state-specific effects in the
211
- dev-spec.
243
+ but never placed below either floor. The Agent must not raise an adaptive proposal to Strict from
244
+ vague uncertainty or a domain keyword; cite both the explicit risk and the concrete complexity
245
+ signal. Explain the decision and state-specific effects in the dev-spec.
212
246
 
213
247
  Persist the proposal before requesting ANALYSIS -> IMPLEMENT:
214
248
 
@@ -47,6 +47,24 @@ Communicate with the user in the user's language.
47
47
  Describe the semantic meaning and, when relevant, units, format, allowed values, nullability,
48
48
  default behavior, or compatibility constraints. A type-level comment does not replace comments
49
49
  on its fields or members; do not add low-value comments to ordinary local variables.
50
+ 10. Treat the task card's `Local Baseline` as the default implementation shape. Match the nearest
51
+ comparable code's naming, control flow, null/empty and error handling, layering, object model,
52
+ and extraction granularity unless correctness, security, an explicit requirement, or a hard
53
+ project rule requires a deviation. Do not add defensive null checks solely because they are a
54
+ generic best practice when the evidenced local contract intentionally omits them.
55
+ 11. Implement the smallest coherent design. Do not add speculative abstractions, wrappers,
56
+ factories, layers, or extension points, and do not fragment one readable flow into many
57
+ single-use micro-methods. Extract code only for a clear semantic boundary, real reuse,
58
+ independent testability, or a material reduction in complexity.
59
+ 12. Literals and magic values are allowed when they are obvious, local, and consistent with the
60
+ surrounding code. Introduce a constant for repeated use, stable domain/config/protocol
61
+ semantics, or an established project convention—not merely to hold the single return value of
62
+ a getter.
63
+ 13. In a newly added core Java class, every method and field requires meaningful Javadoc. In an
64
+ existing core Java class, every added or materially modified method and field requires it.
65
+ Add focused inline comments to core or complex logic to explain intent, constraints, or
66
+ non-obvious tradeoffs. Do not mass-retrofit untouched legacy code, and for non-Java code
67
+ follow the language's doc-comment form plus the evidenced project convention.
50
68
 
51
69
  ## Choose the execution owner
52
70
 
@@ -92,6 +110,7 @@ Sub-agents never dispatch other sub-agents or read `.easy-coding` workflow asset
92
110
  ## Test Points {unit.test_points and exact targeted commands}
93
111
  ## Contracts {inputs, outputs, invariants shared with other units}
94
112
  ## Risks {known edge cases and compatibility risks}
113
+ ## Local Baseline {nearest comparable code conventions and evidence paths}
95
114
  ## Code Comments {resolved host Agent author value; model-field, enum-member, and constant rules}
96
115
  ## Coding Rules {pre-digested RULES sections}
97
116
  ## Architecture {pre-digested ABSTRACT sections}
@@ -110,11 +129,13 @@ deliverable|null, checks:[{command,passed,failures:[]}], issues:[], needs_attent
110
129
  hard/contract dependencies are ready; do not batch-start dependent tasks at the initial
111
130
  IMPLEMENT boundary.
112
131
  Populate `Code Comments` on every code task card with the resolved user-facing host Agent
113
- author value and the field/member/constant rules above; sub-agents do not read this Skill.
132
+ author value, the field/member/constant rules, and the core Java Javadoc rule above. Populate
133
+ `Local Baseline` from the Unit's analyzed evidence; sub-agents do not read this Skill.
114
134
  2. Execute according to dependency order and selected owner.
115
135
  3. Run targeted unit tests and self-audit scope, contracts, TODOs, and introduced warnings.
116
136
  Also audit new author attributions and every new model field, enum member, and constant against
117
- the comment requirements above before recording success.
137
+ the comment requirements above, then check local-style deviations, unnecessary abstractions,
138
+ one-use constant extraction, and affected core Java Javadoc before recording success.
118
139
  4. Append one `result` record. Only a successful unit uses `status:"completed"`; include
119
140
  unresolved issues rather than hiding them, and do not advance while `issues` or
120
141
  `needs_attention` is non-empty.
@@ -150,6 +171,10 @@ conversation overhead while keeping work observable.
150
171
  - [ ] Every unit has a dispatch/result pair and satisfied its acceptance criteria.
151
172
  - [ ] Targeted tests ran or a concrete blocker is recorded.
152
173
  - [ ] Cross-unit contracts still match.
174
+ - [ ] The implementation follows the evidenced Local Baseline or records a required deviation.
175
+ - [ ] No speculative layer, fragmented micro-method set, or single-use getter constant was added.
153
176
  - [ ] New author attributions use the user-facing host `<Current Agent Name> with Easy Coding`.
154
177
  - [ ] Every new model field, enum member, and constant has a meaningful field-level comment.
178
+ - [ ] Every method/field in a new core Java class, and every added or materially modified one in
179
+ an existing core Java class, has Javadoc.
155
180
  - [ ] Code tasks enter REVIEW, regardless of workflow mode.
@@ -12,7 +12,17 @@ Every new code task enters REVIEW. Read-only tasks do not. Obtain the current fi
12
12
  ```
13
13
 
14
14
  Review the final diff against `dev-spec.md`, RULES, unit acceptance criteria, tests, contracts,
15
- and obvious security risks. Every finding cites `file:line`.
15
+ the Unit's Local Baseline, and obvious security risks. Every finding cites `file:line`.
16
+
17
+ Review local fit before recommending generic cleanup. Flag an implementation when it departs from
18
+ the nearest comparable naming, control flow, null/error handling, layering, modeling, or method
19
+ granularity without a correctness, security, requirement, or hard-rule reason. Also flag
20
+ speculative layers, fragmented one-use micro-methods, constants created only for one getter
21
+ return, and missing Javadoc in core Java code: check every method/field in a new core class and
22
+ each added or materially modified one in an existing core class. Do not demand defensive null
23
+ checks, abstraction, constant extraction, or legacy-wide comment retrofits merely because they
24
+ are generic best practices. A violation of an explicit task-card coding/comment contract is a
25
+ contract defect, not optional stylistic advice.
16
26
 
17
27
  For Canonical-backed tasks, group evidence by `repo_id` and `source_task_id`. Every selected
18
28
  Spec task needs an implementation result and source test evidence; file references remain
@@ -18,7 +18,17 @@ complete exactly that unit. Your reply IS the return value, not a message to a h
18
18
  context is in the card.
19
19
  - Make no workflow stage-transition decisions; you do not know the state machine exists.
20
20
  - Follow the coding rules and architecture context embedded in the card.
21
+ - Follow the task card's `Local Baseline`: match nearby naming, control flow, null/error handling,
22
+ layering, object modeling, method granularity, literal usage, and comment style unless a stated
23
+ correctness, security, requirement, or hard-rule reason requires a deviation.
21
24
  - Treat the task card's `Code Comments` author value and field/member/constant rules as mandatory.
25
+ - Do not add generic defensive null checks, speculative abstractions/layers, fragmented one-use
26
+ micro-methods, or a constant that exists only to hold one getter return.
27
+ - Local, obvious magic values are allowed when they match surrounding code; create constants for
28
+ reuse, stable domain/config/protocol semantics, or established project convention.
29
+ - Every method and field in a new core Java class, and every added or materially modified method
30
+ or field in an existing core Java class, must have meaningful Javadoc; comment complex logic
31
+ where intent or constraints are not obvious.
22
32
  - Treat acceptance criteria, test points, contracts, and risks in the card as required inputs.
23
33
  - Run the exact targeted checks requested by the card and report their real outcome.
24
34
  - Preserve each existing file's original encoding; never silently convert.
@@ -17,7 +17,12 @@ dimension named in your task card. Your reply IS the return value.
17
17
  - correctness → does the implementation match the dev-spec requirement? edge cases,
18
18
  null/empty handling, races, off-by-one.
19
19
  - compliance → does the code obey the RULES sections in the card? naming, format, comment
20
- language, error handling.
20
+ language, error handling, and the evidenced Local Baseline.
21
+ - Do not request defensive null checks, abstraction, constant extraction, or legacy-wide comment
22
+ cleanup solely as generic best practice. Flag unjustified local-style deviations, speculative
23
+ layers, fragmented one-use micro-methods, constants created only for a getter return, and
24
+ missing Javadoc on any method/field in a new core Java class or any added/materially modified
25
+ method/field in an existing core Java class.
21
26
  - `error` means a demonstrated acceptance, contract, security, or build failure. Use `warning`
22
27
  for a credible risk and `info` for non-blocking maintainability advice.
23
28
 
@@ -87,10 +87,24 @@ WORKFLOW_MODES = {"fast", "standard", "strict"}
87
87
  WORKFLOW_MODE_RANK = {"fast": 0, "standard": 1, "strict": 2}
88
88
  STRICT_VERIFICATION_CHECK_TYPES = {"lint", "typecheck", "test", "build"}
89
89
  REVIEW_FINDING_SEVERITIES = {"error", "warning", "info"}
90
- STRICT_WORKFLOW_RISK_PATTERN = re.compile(
91
- r"(migration|migrate|schema|state[-_ ]?machine|security|payment|data[-_ ]?loss|"
92
- r"concurren|cross[-_ ]?repo|public[-_ ]?(api|contract)|迁移|状态机|安全|支付|"
93
- r"数据丢失|并发|跨仓|公共接口|公共契约)",
90
+ HIGH_WORKFLOW_RISK_PATTERN = re.compile(
91
+ r"(\bhigh[-_ ]?risk\b|\bcritical\b|\bsevere\b|\birreversible\b|"
92
+ r"\bdata[-_ ]?loss\b|\bfinancial[-_ ]?loss\b|"
93
+ r"\bsecurity[-_ ]?(boundary|breach)\b|\bprivilege[-_ ]?escalation\b|"
94
+ r"\bproduction[-_ ]?outage\b|"
95
+ r"高风险|严重|不可逆|数据丢失|资损|安全边界|安全事件|权限提升|生产故障)",
96
+ re.IGNORECASE,
97
+ )
98
+ NEGATED_HIGH_WORKFLOW_RISK_PATTERN = re.compile(
99
+ r"(\b(?:non[-_ ]?|not[-_ ]+|no[-_ ]+)(?:high[-_ ]?risk|critical|severe|irreversible)\b|"
100
+ r"\b(?:no|without)[-_ ]+(?:risk[-_ ]+of[-_ ]+)?(?:data[-_ ]?loss|"
101
+ r"financial[-_ ]?loss|security[-_ ]?breach|production[-_ ]?outage)\b|"
102
+ r"低风险|非高风险|不严重|(?<!不)可逆|无(?:数据丢失|资损|安全事件|生产故障)|"
103
+ r"不会导致(?:数据丢失|资损|安全事件|生产故障))",
104
+ re.IGNORECASE,
105
+ )
106
+ WIDE_WORKFLOW_CONTRACT_PATTERN = re.compile(
107
+ r"(cross[-_ ]?repo|public[-_ ]?(api|contract)|跨仓|公共接口|公共契约)",
94
108
  re.IGNORECASE,
95
109
  )
96
110
  DEFAULT_APPROVAL_MODE = "guard"
@@ -1589,7 +1603,7 @@ def is_valid_execution_plan(
1589
1603
  has_empty_file_scope = True
1590
1604
  if not is_string_list(unit.get("depends_on")):
1591
1605
  return False
1592
- for optional_list in ("rules_sections", "abstract_modules"):
1606
+ for optional_list in ("rules_sections", "abstract_modules", "local_baseline"):
1593
1607
  if optional_list in unit and not is_string_list(unit.get(optional_list)):
1594
1608
  return False
1595
1609
  if require_unit_contracts:
@@ -2279,6 +2293,42 @@ def task_repository_roots(root: Path, task: dict | None, plan: dict) -> list[Pat
2279
2293
  ]
2280
2294
 
2281
2295
 
2296
+ def workflow_plan_repository_roots(root: Path, task: dict, plan: dict) -> list[Path]:
2297
+ """Resolve only repositories that own files in the current execution plan."""
2298
+ repositories: set[Path] = set()
2299
+ repo_paths = task.get("repo_paths")
2300
+ canonical = isinstance(task.get("spec_source"), dict)
2301
+
2302
+ for unit in plan.get("units", []):
2303
+ if not isinstance(unit, dict):
2304
+ continue
2305
+ if canonical:
2306
+ repo_id = unit.get("repo_id")
2307
+ if not is_non_empty_string(repo_id) or not isinstance(repo_paths, dict):
2308
+ raise StateError("Canonical workflow Unit is missing its repository binding.")
2309
+ raw_repo_path = repo_paths.get(str(repo_id))
2310
+ if not is_non_empty_string(raw_repo_path):
2311
+ raise StateError(f"Canonical workflow repository path is missing: {repo_id}")
2312
+ candidate = Path(str(raw_repo_path))
2313
+ resolved = (candidate if candidate.is_absolute() else root / candidate).resolve()
2314
+ repository = git_repository_root(resolved)
2315
+ if repository is None or repository.resolve() != resolved:
2316
+ raise StateError(f"Canonical workflow repository binding is not a Git root: {repo_id}")
2317
+ repositories.add(repository.resolve())
2318
+ continue
2319
+
2320
+ for file_name in unit.get("files", []):
2321
+ if not is_non_empty_string(file_name):
2322
+ continue
2323
+ candidate = Path(str(file_name))
2324
+ resolved = (candidate if candidate.is_absolute() else root / candidate).resolve()
2325
+ repository = git_repository_root(resolved)
2326
+ if repository is not None:
2327
+ repositories.add(repository.resolve())
2328
+
2329
+ return sorted(repositories, key=lambda item: item.as_posix())
2330
+
2331
+
2282
2332
  def tdd_repositories(root: Path, task: dict, plan: dict) -> dict[str, Path]:
2283
2333
  if isinstance(task.get("spec_source"), dict):
2284
2334
  repo_paths = task.get("repo_paths")
@@ -6083,54 +6133,65 @@ def calculate_workflow_floor(root: Path, task_id: str) -> tuple[str, list[str]]:
6083
6133
  if not plan:
6084
6134
  raise StateError("Cannot calculate workflow floor without a valid execution plan.")
6085
6135
  units = [unit for unit in plan.get("units", []) if isinstance(unit, dict)]
6136
+ missing_local_baseline = [
6137
+ str(unit.get("id") or "<unknown>")
6138
+ for unit in units
6139
+ if not is_string_list(unit.get("local_baseline"), allow_empty=False)
6140
+ ]
6141
+ if missing_local_baseline:
6142
+ raise StateError(
6143
+ "Workflow plan Units must record a non-empty local_baseline: "
6144
+ + ", ".join(missing_local_baseline)
6145
+ )
6086
6146
  files = {
6087
6147
  str(file_name)
6088
6148
  for unit in units
6089
6149
  for file_name in unit.get("files", [])
6090
6150
  if is_non_empty_string(file_name)
6091
6151
  }
6092
- repositories = task_repository_roots(root, task, plan)
6093
- repos = task.get("repos")
6094
- repo_paths = task.get("repo_paths")
6095
- metadata_repo_count = max(
6096
- len(repos) if isinstance(repos, list) else 0,
6097
- len(repo_paths) if isinstance(repo_paths, dict) else 0,
6098
- )
6099
- repo_count = max(len(repositories), metadata_repo_count)
6100
- risk_text = " ".join(
6101
- [
6102
- str(task.get("title") or ""),
6103
- task_type,
6104
- *files,
6105
- *[
6106
- str(item)
6107
- for unit in units
6108
- for field in ("risks", "contracts")
6109
- for item in unit.get(field, [])
6110
- if is_non_empty_string(item)
6111
- and str(item).strip().lower() not in {"none", "no", "n/a", "无", "无风险"}
6112
- ],
6152
+ repositories = workflow_plan_repository_roots(root, task, plan)
6153
+ ignored_values = {"none", "no", "n/a", "无", "无风险"}
6154
+ risk_values = [
6155
+ str(item)
6156
+ for unit in units
6157
+ for item in unit.get("risks", [])
6158
+ if is_non_empty_string(item) and str(item).strip().lower() not in ignored_values
6159
+ ]
6160
+ contract_values = [
6161
+ str(item)
6162
+ for unit in units
6163
+ for item in unit.get("contracts", [])
6164
+ if is_non_empty_string(item) and str(item).strip().lower() not in ignored_values
6165
+ ]
6166
+ risk_text = NEGATED_HIGH_WORKFLOW_RISK_PATTERN.sub("", " ".join(risk_values))
6167
+ high_risk = bool(HIGH_WORKFLOW_RISK_PATTERN.search(risk_text))
6168
+
6169
+ complexity_reasons: list[str] = []
6170
+ if len(repositories) > 1:
6171
+ complexity_reasons.append("cross-repository-change")
6172
+ if len(units) >= 4 or len(files) >= 10:
6173
+ complexity_reasons.append("broad-change-scope")
6174
+ if WIDE_WORKFLOW_CONTRACT_PATTERN.search(" ".join(contract_values)):
6175
+ complexity_reasons.append("wide-contract-impact")
6176
+ if high_risk and complexity_reasons:
6177
+ return "strict", [
6178
+ "compound-high-risk-and-complexity",
6179
+ "explicit-high-risk-signal",
6180
+ *complexity_reasons,
6113
6181
  ]
6114
- )
6115
- strict_reasons: list[str] = []
6116
- if repo_count > 1:
6117
- strict_reasons.append("cross-repository-scope")
6118
- if len(units) >= 4 or len(files) >= 8:
6119
- strict_reasons.append("broad-change-scope")
6120
- if STRICT_WORKFLOW_RISK_PATTERN.search(risk_text):
6121
- strict_reasons.append("high-risk-contract-or-domain")
6122
- if strict_reasons:
6123
- return "strict", strict_reasons
6124
6182
 
6125
6183
  standard_reasons: list[str] = []
6184
+ if high_risk:
6185
+ standard_reasons.append("bounded-high-risk-change")
6186
+ standard_reasons.extend(complexity_reasons)
6126
6187
  if len(units) > 1:
6127
6188
  standard_reasons.append("multiple-units")
6128
- if len(files) >= 3:
6189
+ if len(files) > 5:
6129
6190
  standard_reasons.append("multi-file-impact")
6130
6191
  if plan.get("strategy") == "parallel":
6131
6192
  standard_reasons.append("parallel-execution")
6132
6193
  if standard_reasons:
6133
- return "standard", standard_reasons
6194
+ return "standard", list(dict.fromkeys(standard_reasons))
6134
6195
  return "fast", ["single-bounded-unit"]
6135
6196
 
6136
6197