@xulthekl/team-flow 0.64.0 → 0.67.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.
- package/.claude/always/phase-guard.md +1 -1
- package/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/.codex-plugin/plugin.json +1 -1
- package/.cursor-plugin/marketplace.json +1 -1
- package/.cursor-plugin/plugin.json +1 -1
- package/.github/plugin/marketplace.json +2 -2
- package/CHANGELOG.md +60 -0
- package/GEMINI.md +1 -1
- package/INSTALL.md +1 -1
- package/README.md +1 -1
- package/agents/architecture-design.md +1 -1
- package/agents/architecture-reviewer.md +6 -2
- package/agents/prd-completeness-reviewer.md +10 -0
- package/agents/prd-writer.md +1 -0
- package/agents/release-archivist.md +2 -0
- package/docs/README_en.md +1 -1
- package/docs/team-flow /344/275/277/347/224/250/350/257/264/346/230/216/357/274/210/347/240/224/345/217/221/345/233/242/351/230/237/347/211/210/357/274/211.md" +8 -6
- package/gemini-extension.json +1 -1
- package/hooks/session-start +2 -2
- package/llms.txt +1 -1
- package/package.json +1 -1
- package/plugin.json +1 -1
- package/prd/v1/prd.md +1 -1
- package/scripts/guard/checks/arch-gate-exemptions.mjs +5 -3
- package/scripts/guard/checks/arch-readiness.mjs +1 -1
- package/scripts/guard/checks/arch-snapshot.mjs +5 -3
- package/scripts/guard/checks/history-risk.mjs +132 -0
- package/scripts/guard/checks/prd-clarity-state.mjs +41 -0
- package/scripts/guard/checks/prd-clarity.mjs +176 -0
- package/scripts/guard/guard.mjs +16 -8
- package/scripts/infer-workflow.mjs +20 -0
- package/scripts/lib/arch-merge.mjs +384 -50
- package/scripts/lib/arch-parse.mjs +5 -2
- package/scripts/lib/arch-registry.mjs +523 -0
- package/scripts/lib/arch-scan-code.mjs +518 -0
- package/scripts/lib/cmd-arch.mjs +9 -1
- package/scripts/lib/cmd-doctor.mjs +3 -3
- package/scripts/lib/cmd-prd.mjs +84 -1
- package/scripts/lib/cmd-solutions.mjs +3 -0
- package/scripts/lib/cmd-state.mjs +31 -1
- package/scripts/lib/config-loader.mjs +20 -0
- package/scripts/lib/solutions-capture.mjs +5 -0
- package/scripts/lib/solutions-index-gen.mjs +33 -3
- package/scripts/lib/solutions-inject.mjs +34 -9
- package/scripts/lib/state-loader.mjs +13 -0
- package/scripts/team-flow.mjs +3 -0
- package/skills/architecture-design/SKILL.md +29 -11
- package/skills/architecture-design/chapters/ch04-entity-to-aggregate.md +18 -7
- package/skills/architecture-design/chapters/ch06-integration.md +12 -3
- package/skills/architecture-design/glossary.md +5 -1
- package/skills/architecture-design/references/adr-templates.md +56 -0
- package/skills/architecture-design/references/context-map-8.md +47 -0
- package/skills/architecture-design/references/ddd-evented-playbook.md +41 -0
- package/skills/architecture-design/references/s3.5-architecture-template.md +36 -4
- package/skills/architecture-design/references/s3.5-loading-protocol.md +5 -4
- package/skills/architecture-design/references/s3.5-product-architecture.md +6 -6
- package/skills/architecture-design/templates/architecture.md +20 -0
- package/skills/ce-brainstorm/SKILL.md +3 -3
- package/skills/ce-brainstorm/references/grounding.md +1 -1
- package/skills/ce-brainstorm/references/prd-84-authoring-spec.md +26 -3
- package/skills/ce-brainstorm/references/prototype-loop.md +8 -0
- package/skills/ce-compound/references/concepts-vocabulary.md +1 -1
- package/skills/ce-compound/references/full-mode-workflow.md +2 -2
- package/skills/ce-compound/references/lightweight-mode.md +1 -1
- package/skills/ce-compound/references/promotion-rules.md +1 -1
- package/skills/ce-compound/references/three-tier-index.md +1 -1
- package/skills/ce-plan/references/research-workflow.md +1 -1
- package/skills/jarvis/references/protocols.md +1 -0
- package/skills/release-archivist/SKILL.md +21 -0
- package/skills/release-archivist/references/closing-procedures.md +1 -1
- package/skills/workflow-orchestrator/SKILL.md +8 -4
- package/skills/workflow-orchestrator/references/s1-path-router.md +7 -0
- package/skills/workflow-orchestrator/references/s2-prd-prototype-loop.md +16 -2
- package/skills/workflow-orchestrator/references/s3-plan-pipeline.md +1 -1
- package/skills/workflow-start/SKILL.md +1 -1
- package/templates/prd.md +9 -1
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
// scripts/guard/checks/prd-clarity-state.mjs — 变更级 PRD 清晰度维度(agent-governance P1-1)
|
|
2
|
+
//
|
|
3
|
+
// 与产品级 `prd-clarity.mjs`(checker 本体,跑在 S2 冻结前)的分工:
|
|
4
|
+
// - 产品级门:对 requirement/vN/prd.md 做机械判定(弱词/段/§8.4 漂移);
|
|
5
|
+
// - 本 runner(变更级):**只读 change state 的记录**(prd_clarity_result),不重跑判定——
|
|
6
|
+
// clarity 跨层管道 = 产品级 `tf prd check-clarity` 落 `.team-flow/prd-clarity.json`
|
|
7
|
+
// → `tf state init` 拷入 change state → 本维度在接活前转换消费。
|
|
8
|
+
//
|
|
9
|
+
// 三态语义(缺失态中性,memo §2.4 / plan §6):
|
|
10
|
+
// - `fail` → **FAIL**(阻断转换 = 强制 HITL):带病 PRD 不得接活;
|
|
11
|
+
// - `pass` → PASS;
|
|
12
|
+
// - 未记录(null;存量 change、绕过产品级的 direct change、hotfix 语义)→ **中性 PASS**,
|
|
13
|
+
// 冷启动零行为变化——缺数据不得判低(全量 HITL)也不得伪造高。
|
|
14
|
+
//
|
|
15
|
+
// 防绕过([[gate-hint-is-a-bypass]]):prd_clarity_result **不在** `tf state set` 白名单
|
|
16
|
+
// (SETTABLE_FIELDS 有意不含)——唯一写入路径 = init 从产品级落盘文件拷贝。
|
|
17
|
+
// 手改 state 的逃生通道由 hook 拦截(非 build 态禁写 .team-flow.yaml)。
|
|
18
|
+
import { readState } from '../../lib/state-loader.mjs';
|
|
19
|
+
|
|
20
|
+
export function checkPrdClarityState(changeDir) {
|
|
21
|
+
const state = readState(changeDir);
|
|
22
|
+
const result = state.prd_clarity_result;
|
|
23
|
+
|
|
24
|
+
if (result === 'fail') {
|
|
25
|
+
return {
|
|
26
|
+
pass: false,
|
|
27
|
+
failures: [
|
|
28
|
+
'product-level PRD clarity gate recorded FAIL (state.prd_clarity_result=fail) — '
|
|
29
|
+
+ '回 S2 重跑 `tf prd check-clarity` 并修 PRD 至 PASS,或重建 change(init 会重新拷贝记录)。',
|
|
30
|
+
],
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
if (result === 'pass') {
|
|
34
|
+
return { pass: true, failures: [], reason: 'prd_clarity_result=pass' };
|
|
35
|
+
}
|
|
36
|
+
return {
|
|
37
|
+
pass: true,
|
|
38
|
+
failures: [],
|
|
39
|
+
reason: 'no clarity record (neutral — 产品级门未覆盖本 change:存量/direct/hotfix)',
|
|
40
|
+
};
|
|
41
|
+
}
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
// scripts/guard/checks/prd-clarity.mjs — 产品级 PRD 清晰度机械门(agent-governance P0-1)
|
|
2
|
+
//
|
|
3
|
+
// 背景(2026-09-25):LT 拍板 Q5 推翻 DEC-8 中的弱词机械门决策(DEC-8a)——
|
|
4
|
+
// 「接活前 fail-closed」必须有机械层;LLM reviewer(prd-completeness-reviewer)保留,
|
|
5
|
+
// 与本 checker 并存:checker 管机械可判定项,reviewer 管语义完整性。
|
|
6
|
+
//
|
|
7
|
+
// 检查对象:**产品级 PRD**(requirement/vN/prd.md)。不查变更级 change spec
|
|
8
|
+
// (归 spec-writer/评审既有职责);tasks_skipped 类 change 不经产品级冻结路径,天然不适用。
|
|
9
|
+
//
|
|
10
|
+
// 接入 = 三处(SKILL 调用纪律级,非 hook 强制——如实声明):
|
|
11
|
+
// 1. `tf prd check-clarity <dir|file>`(cmd-prd.mjs,末行 STATUS: PASS | FAIL)
|
|
12
|
+
// 2. standalone:`references/prototype-loop.md` §3.5.5 前置段(ce-brainstorm SKILL QA-4 引用之)
|
|
13
|
+
// 3. orchestrated:`s2-prd-prototype-loop.md` 步骤 3.4(3.5 完整性评审之前)
|
|
14
|
+
//
|
|
15
|
+
// 判定语义 fail-closed:必需段缺失 / 判据无法执行 → FAIL,不得落 N/A 放行。
|
|
16
|
+
// 首版**不建豁免通道**(不过就改 PRD 或调 checker,走正常代码变更流程)。
|
|
17
|
+
// 产品级无 state 文件(.team-flow.yaml 属 change 级),故不使用 gates-probed 式
|
|
18
|
+
// skip-with-reason 豁免模式——那是首版不建豁免的根本原因,不得照抄。
|
|
19
|
+
//
|
|
20
|
+
// 规则源(单真相源裁定,memo v0.5 §4.1 / 反方 I7;**回写已闭合 2026-09-25**):
|
|
21
|
+
// 权威正文 = skills/ce-brainstorm/references/prd-84-authoring-spec.md §4「精确性」,
|
|
22
|
+
// DEC-8a 复议时已扩为 8 类全集(第 6–8 类:否定句/连接歧义/被动语态),
|
|
23
|
+
// 镜像弱词表(工作区 prd-business-readable-design)不再独立维护。
|
|
24
|
+
|
|
25
|
+
import fs from 'node:fs';
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* ISO/IEC/IEEE 29148 弱词 8 类规则表(数据可调——误报校准的唯一落点)。
|
|
29
|
+
* 词表来源:prd-84 §4(权威,8 类全集,DEC-8a 复议后收口于此)。
|
|
30
|
+
* 校准纪律:调词表 = 改本文件规则数据并同步权威正文,不得在调用侧打补丁。
|
|
31
|
+
* 格式:{ category, words: string[], note? };words 为子串匹配(中文无词边界)。
|
|
32
|
+
*
|
|
33
|
+
* **2026-09-25 校准排除决策(刻意不收,权威正文 §4 已留痕)**:
|
|
34
|
+
* - `处理`(§4 类 3 示例词):子串会命中模板段名「系统功能处理说明书」→ 冻结死循环;
|
|
35
|
+
* - 单字 `等`(§4 类 4 示例):子串命中「等待/等于/以及」等一切含字场景 → 噪声失控;
|
|
36
|
+
* 词表只收「等等」。两者判读由 LLM reviewer 精确性检查覆盖(并存层职责)。
|
|
37
|
+
*/
|
|
38
|
+
export const WEAK_RULES = [
|
|
39
|
+
{ category: '比较级与最高级', words: ['更好', '较好', '更快', '更佳', '更稳定', '最快', '最高级', '较快'] },
|
|
40
|
+
{ category: '主观评价词', words: ['友好', '易用', '良好', '美观', '简洁', '直观'] },
|
|
41
|
+
{ category: '歧义词', words: ['尽量', '总是', '最优', '最小化', '最大化', '适当', '必要时'] },
|
|
42
|
+
{ category: '开放式表述', words: ['至少', '不限于', '尽可能', '视情况', '等等'] },
|
|
43
|
+
{ category: '漏洞词', words: ['可能', '如适用', '一般', '通常', '支持'] },
|
|
44
|
+
{ category: '否定句', words: ['不支持'], note: '改为「当 X 时,系统执行 Y」' },
|
|
45
|
+
{ category: '连接歧义', words: ['和/或'], note: '拆分条目或用决策表' },
|
|
46
|
+
{ category: '被动语态', words: ['应被'], note: '明确动作主体' },
|
|
47
|
+
];
|
|
48
|
+
|
|
49
|
+
/** 段缺失判据(fail-closed 最小必需集):命中任一 pattern 即认为段存在。 */
|
|
50
|
+
export const REQUIRED_SECTIONS = [
|
|
51
|
+
// version-1.2:只认 1.2 修订行 / 1.1 版本信息子段(h2「版本修订记录」兜底过松——
|
|
52
|
+
// 子段全删时 h2 仍在,首版实测会漏判,故收紧到子段级)。
|
|
53
|
+
{ id: 'version-1.2', desc: '### 1.1 版本信息 / 1.2 修订记录', pattern: /^#{2,4}\s*.*(?:1\.[12]\s*(?:版本信息|修订)|版本信息\s*$)/m },
|
|
54
|
+
{ id: 'func-list', desc: '功能清单章节(## 七 / 功能清单)', pattern: /^#{2,3}\s*.*(?:七、|功能清单|系统功能)/m },
|
|
55
|
+
{ id: 'sec-8.4', desc: '### 8.4 功能模块详细说明', pattern: /^#{2,4}\s*.*8\.4/m },
|
|
56
|
+
];
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* §8.4 左列语义漂移判据(判据源 = prd-completeness-reviewer.md D6/G7 第 1 条):
|
|
60
|
+
* 左列须为画面/入口锚点;技术维度名 = 违规。
|
|
61
|
+
* 机械实现的边界:**整格匹配**(防「单据类型」这类业务词误杀),另加强技术词子串。
|
|
62
|
+
*/
|
|
63
|
+
const DRIFT_EXACT = /^(维度|字段|类型|属性|参数|枚举|单位|数据项)(列表|清单|定义)?$/;
|
|
64
|
+
const DRIFT_SUBSTRING = /(字段名|维度名|数据类型|技术维度|参数名|表字段)/;
|
|
65
|
+
|
|
66
|
+
/** 去除围栏代码块与行内 code(弱词扫描的误报源),保留原文行结构用于定位。 */
|
|
67
|
+
export function stripCode(text) {
|
|
68
|
+
const lines = text.split(/\r?\n/);
|
|
69
|
+
let inFence = false;
|
|
70
|
+
return lines.map((line) => {
|
|
71
|
+
if (/^\s*```/.test(line)) { inFence = !inFence; return ''; }
|
|
72
|
+
if (inFence) return '';
|
|
73
|
+
return line.replace(/`[^`]*`/g, '');
|
|
74
|
+
}).join('\n');
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/** 提取标题段正文(到下一个同级或更高级标题)。返回 null 表示段不存在。 */
|
|
78
|
+
export function extractSection(text, headingRe) {
|
|
79
|
+
const lines = text.split(/\r?\n/);
|
|
80
|
+
let start = -1;
|
|
81
|
+
let level = 0;
|
|
82
|
+
for (let i = 0; i < lines.length; i += 1) {
|
|
83
|
+
const m = lines[i].match(/^(#{1,6})\s/);
|
|
84
|
+
if (m && headingRe.test(lines[i])) { start = i; level = m[1].length; break; }
|
|
85
|
+
}
|
|
86
|
+
if (start === -1) return null;
|
|
87
|
+
const body = [];
|
|
88
|
+
for (let i = start + 1; i < lines.length; i += 1) {
|
|
89
|
+
const m = lines[i].match(/^(#{1,6})\s/);
|
|
90
|
+
if (m && m[1].length <= level) break;
|
|
91
|
+
body.push(lines[i]);
|
|
92
|
+
}
|
|
93
|
+
return body.join('\n');
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/** 收集段内所有 markdown 表格的首列数据单元格(跳过表头与分隔行)。 */
|
|
97
|
+
export function firstColumnCells(sectionBody) {
|
|
98
|
+
const cells = [];
|
|
99
|
+
const lines = sectionBody.split(/\r?\n/);
|
|
100
|
+
let inTable = false;
|
|
101
|
+
let headerSeen = false;
|
|
102
|
+
for (const line of lines) {
|
|
103
|
+
if (!line.trim().startsWith('|')) { inTable = false; headerSeen = false; continue; }
|
|
104
|
+
const cols = line.split('|').map((c) => c.trim());
|
|
105
|
+
// cols[0] === ''(前导竖线),数据首列在 index 1
|
|
106
|
+
if (!inTable) { inTable = true; headerSeen = false; continue; } // 表头行
|
|
107
|
+
if (!headerSeen) { headerSeen = true; continue; } // 分隔行(|---|---|)
|
|
108
|
+
const first = cols[1] || '';
|
|
109
|
+
if (first) cells.push(first);
|
|
110
|
+
}
|
|
111
|
+
return cells;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* 核心判定。
|
|
116
|
+
* @param {string} prdPath prd.md 文件绝对/相对路径
|
|
117
|
+
* @returns {{pass: boolean, failures: string[], stats: object}}
|
|
118
|
+
* 失败条目格式:`[类别] 行 N: <片段>` / `[section] ...` / `[drift] ...`
|
|
119
|
+
*/
|
|
120
|
+
export function checkPrdClarity(prdPath) {
|
|
121
|
+
const failures = [];
|
|
122
|
+
const stats = { weakHits: 0, driftCells: 0, sectionsMissing: [] };
|
|
123
|
+
|
|
124
|
+
if (!prdPath || !fs.existsSync(prdPath)) {
|
|
125
|
+
return {
|
|
126
|
+
pass: false,
|
|
127
|
+
failures: [`[section] PRD file not found: ${prdPath ?? '(unset)'} — locate requirement/vN/prd.md first`],
|
|
128
|
+
stats,
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
const raw = fs.readFileSync(prdPath, 'utf-8');
|
|
132
|
+
if (!raw.trim()) {
|
|
133
|
+
return { pass: false, failures: ['[section] PRD file is empty — write the PRD before running clarity check'], stats };
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// 1) 必需段存在性(fail-closed:缺失 = FAIL,不得 N/A 放行)。
|
|
137
|
+
for (const sec of REQUIRED_SECTIONS) {
|
|
138
|
+
if (!sec.pattern.test(raw)) {
|
|
139
|
+
stats.sectionsMissing.push(sec.id);
|
|
140
|
+
failures.push(`[section] required section missing: ${sec.desc} — template skeleton incomplete`);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// 2) 弱词 8 类扫描(排除代码块/行内 code;表格内容照扫——PRD 表格是业务正文)。
|
|
145
|
+
const clean = stripCode(raw);
|
|
146
|
+
const cleanLines = clean.split(/\r?\n/);
|
|
147
|
+
for (let i = 0; i < cleanLines.length; i += 1) {
|
|
148
|
+
const line = cleanLines[i];
|
|
149
|
+
if (!line.trim()) continue;
|
|
150
|
+
for (const rule of WEAK_RULES) {
|
|
151
|
+
for (const word of rule.words) {
|
|
152
|
+
const idx = line.indexOf(word);
|
|
153
|
+
if (idx >= 0) {
|
|
154
|
+
stats.weakHits += 1;
|
|
155
|
+
const snippet = line.slice(Math.max(0, idx - 12), idx + word.length + 12).trim();
|
|
156
|
+
failures.push(`[weak:${rule.category}] 行 ${i + 1}: …${snippet}… (${rule.note ?? '改为精确表述'})`);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// 3) §8.4 左列语义漂移(G7 第 1 条机械化)。
|
|
163
|
+
const sec84 = extractSection(clean, /8\.4/);
|
|
164
|
+
if (sec84 === null) {
|
|
165
|
+
// 必需段已在其处 FAIL(REQUIRED_SECTIONS sec-8.4),此处不重复计。
|
|
166
|
+
} else {
|
|
167
|
+
for (const cell of firstColumnCells(sec84)) {
|
|
168
|
+
if (DRIFT_EXACT.test(cell) || DRIFT_SUBSTRING.test(cell)) {
|
|
169
|
+
stats.driftCells += 1;
|
|
170
|
+
failures.push(`[drift] §8.4 左列技术维度名: "${cell}" — 左列须为画面/入口锚点(G7-1)`);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
return { pass: failures.length === 0, failures, stats };
|
|
176
|
+
}
|
package/scripts/guard/guard.mjs
CHANGED
|
@@ -17,6 +17,9 @@ import { checkCompoundCaptured } from './checks/compound-captured.mjs';
|
|
|
17
17
|
import { checkTestMatrixComplete } from './checks/test-matrix-complete.mjs';
|
|
18
18
|
import { checkTestMatrixReady } from './checks/test-matrix-ready.mjs';
|
|
19
19
|
import { checkGatesProbed } from './checks/gates-probed.mjs';
|
|
20
|
+
// agent-governance P1-1:接活前双维度(履历 experimental + clarity 跨层管道)
|
|
21
|
+
import { checkPrdClarityState } from './checks/prd-clarity-state.mjs';
|
|
22
|
+
import { checkHistoryRisk } from './checks/history-risk.mjs';
|
|
20
23
|
import { checkArchReadiness } from './checks/arch-readiness.mjs';
|
|
21
24
|
import { checkArchSnapshot } from './checks/arch-snapshot.mjs';
|
|
22
25
|
import { checkArchMerged } from './checks/arch-merged.mjs';
|
|
@@ -57,10 +60,12 @@ const TRANSITION_CHECKS = {
|
|
|
57
60
|
// 「闸门已实测可跑」文字自证物化为机械证据。检查五件:evidence 存在 / 首行 RED 基线 /
|
|
58
61
|
// CONTRACT_HASH 值新鲜 / 契约 Gate Registry 的 id 逐 id 覆盖 / **段缺失即 FAIL(fail-closed)**。
|
|
59
62
|
// hotfix 走 WORKFLOW_TRANSITION_CHECKS 自有覆盖(下方),tweak 由 skip 回退阀放行。
|
|
60
|
-
|
|
63
|
+
// agent-governance P1-1:prd-clarity + history-risk 挂接活门(full 档)——
|
|
64
|
+
// 「接活前验规格 + 履历」;两维缺失态均中性(无记录/INDEX 空 = 放行),存量零变化。
|
|
65
|
+
'bridging:approved-for-build': ['artifacts-exist', 'schema-valid', 'contract-fresh', 'dp-gate-passed', 'dp3-approved', 'gates-probed', 'prd-clarity', 'history-risk'],
|
|
61
66
|
// v0.13 §49:test-matrix-ready 门禁前移——full 模式进入 executing 前强制测试准备度
|
|
62
67
|
//(矩阵存在非空 OR 显式 skip 附理由;legacy 豁免)。hotfix/tweak 沿用 §45.3 豁免,不挂。
|
|
63
|
-
'approved-for-build:executing': ['artifacts-exist', 'contract-fresh', 'dp-gate-passed', 'execution-plan-ready', 'test-matrix-ready'],
|
|
68
|
+
'approved-for-build:executing': ['artifacts-exist', 'contract-fresh', 'dp-gate-passed', 'execution-plan-ready', 'test-matrix-ready', 'prd-clarity', 'history-risk'],
|
|
64
69
|
// v0.35.0 (v0.14 §59.4): arch-snapshot 新增——"先快照后回写"的强制化(legacy 豁免)。
|
|
65
70
|
// 仅在 full workflow 挂;hotfix/tweak 沿用 §59.4 豁免(紧急/微调不挂)。
|
|
66
71
|
//
|
|
@@ -134,15 +139,15 @@ const TRANSITION_WORKFLOW_REQUIREMENTS = {
|
|
|
134
139
|
// 必须显式列出关键跳——未列出的 key 会回落 full 基表(contract-fresh 等对轻路径恒 FAIL)。
|
|
135
140
|
const QUICK_TRANSITION_CHECKS = {
|
|
136
141
|
quick: {
|
|
137
|
-
'exploring:approved-for-build': ['direct-short-path'],
|
|
138
|
-
'approved-for-build:executing': ['direct-short-path', 'test-matrix-ready'],
|
|
142
|
+
'exploring:approved-for-build': ['direct-short-path', 'prd-clarity', 'history-risk'],
|
|
143
|
+
'approved-for-build:executing': ['direct-short-path', 'test-matrix-ready', 'prd-clarity', 'history-risk'],
|
|
139
144
|
'executing:closing': ['direct-short-path', 'direct-test-result', 'test-matrix-complete'],
|
|
140
145
|
'executing:debugging': [],
|
|
141
146
|
'debugging:executing': ['direct-test-result'],
|
|
142
147
|
},
|
|
143
148
|
lightweight: {
|
|
144
|
-
'exploring:approved-for-build': ['direct-short-path'],
|
|
145
|
-
'approved-for-build:executing': ['direct-short-path', 'test-matrix-ready'],
|
|
149
|
+
'exploring:approved-for-build': ['direct-short-path', 'prd-clarity', 'history-risk'],
|
|
150
|
+
'approved-for-build:executing': ['direct-short-path', 'test-matrix-ready', 'prd-clarity', 'history-risk'],
|
|
146
151
|
'executing:closing': ['direct-short-path', 'direct-test-result', 'lightweight-completion-evidence', 'test-matrix-complete'],
|
|
147
152
|
'executing:debugging': [],
|
|
148
153
|
'debugging:executing': ['direct-test-result'],
|
|
@@ -155,8 +160,8 @@ const PLANNED_TRANSITION_CHECKS = {
|
|
|
155
160
|
// 注:不挂 schema-valid——该 checker 强制 canonical specs/<capability>/spec.md,
|
|
156
161
|
// 与 planned「specs 按需」冲突(P1 实测修正,同步方案 §4.5);反空壳由 artifacts-planned
|
|
157
162
|
// (proposal≥10 行 + checkbox)+ 最终审查内容契约承担。
|
|
158
|
-
'exploring:approved-for-build': ['artifacts-planned'],
|
|
159
|
-
'approved-for-build:executing': ['execution-plan-ready', 'test-matrix-ready'],
|
|
163
|
+
'exploring:approved-for-build': ['artifacts-planned', 'prd-clarity', 'history-risk'],
|
|
164
|
+
'approved-for-build:executing': ['execution-plan-ready', 'test-matrix-ready', 'prd-clarity', 'history-risk'],
|
|
160
165
|
'executing:closing': [
|
|
161
166
|
'execution-plan-ready', 'execution-reviews-passed-light', 'test-matrix-complete',
|
|
162
167
|
'tests-passing', 'arch-merged-light', 'compound-writeback-light', 'test-merged-light',
|
|
@@ -293,6 +298,9 @@ async function main() {
|
|
|
293
298
|
'test-matrix-complete': (dir) => checkTestMatrixComplete(dir, CTX),
|
|
294
299
|
'test-matrix-ready': (dir) => checkTestMatrixReady(dir, CTX),
|
|
295
300
|
'gates-probed': (dir) => checkGatesProbed(dir),
|
|
301
|
+
// agent-governance P1-1(33 维):接活前双维度。缺失态中性——冷启动零行为变化。
|
|
302
|
+
'prd-clarity': (dir) => checkPrdClarityState(dir),
|
|
303
|
+
'history-risk': (dir) => checkHistoryRisk(dir),
|
|
296
304
|
'arch-readiness': (dir) => checkArchReadiness(dir),
|
|
297
305
|
'arch-snapshot': (dir) => checkArchSnapshot(dir),
|
|
298
306
|
'arch-merged': (dir) => checkArchMerged(dir),
|
|
@@ -55,6 +55,11 @@ function hasKeyword(text, patterns) {
|
|
|
55
55
|
|
|
56
56
|
function inferMode(changeDir) {
|
|
57
57
|
const state = readState(changeDir);
|
|
58
|
+
// agent-governance P1-1 双信号(轻量分值化):
|
|
59
|
+
// clarity = 产品级 prd-clarity 跨层记录(pass|fail|null=null 中性——见 prd-clarity-state.mjs);
|
|
60
|
+
// risk = 0.64 双通道信号的分档聚合(low|medium|high|null——显式档位/无产物时 null)。
|
|
61
|
+
// 消费方 = workflow-start 路由推荐(建议级;阻断由 guard 维度承担,这里只影响推荐倾向)。
|
|
62
|
+
const clarity = state.prd_clarity_result ?? null;
|
|
58
63
|
|
|
59
64
|
// Explicit override: honor any non-auto, non-null workflow value
|
|
60
65
|
// v0.64.0(§3.2 F1):VALID_WORKFLOWS 扩为五值,quick/lightweight 亦为合法显式档位。
|
|
@@ -66,6 +71,8 @@ function inferMode(changeDir) {
|
|
|
66
71
|
// 双通道(§3.2):显式 workflow 已定时不再建议前门(显式 > 推断)
|
|
67
72
|
suggested_path: null,
|
|
68
73
|
explicit: true,
|
|
74
|
+
clarity,
|
|
75
|
+
risk: null, // 显式档位不推断风险分档
|
|
69
76
|
reason: `workflow explicitly set to '${state.workflow}' in .team-flow.yaml; skipping auto-detection`,
|
|
70
77
|
};
|
|
71
78
|
}
|
|
@@ -101,6 +108,9 @@ function inferMode(changeDir) {
|
|
|
101
108
|
const archPathSignal = hasSchemaChange || hasArchAggregate;
|
|
102
109
|
// 跨模块 / 高不确定性 → full(D1:full 只留重场景)
|
|
103
110
|
const fullSignal = hasCrossModule || (taskCount > 4 && fileCount > 6);
|
|
111
|
+
// P1-1 risk 分档:四个布尔信号计数(0=low / 1=medium / ≥2=high)
|
|
112
|
+
const riskSignals = [hasSchemaChange, hasArchAggregate, hasCrossModule, fullSignal].filter(Boolean).length;
|
|
113
|
+
const risk = riskSignals >= 2 ? 'high' : riskSignals === 1 ? 'medium' : 'low';
|
|
104
114
|
|
|
105
115
|
const allExts = files.map(f => {
|
|
106
116
|
const parts = f.split('.');
|
|
@@ -115,6 +125,8 @@ function inferMode(changeDir) {
|
|
|
115
125
|
mode: 'full',
|
|
116
126
|
suggested_path: null,
|
|
117
127
|
explicit: false,
|
|
128
|
+
clarity,
|
|
129
|
+
risk,
|
|
118
130
|
reason: 'no planning artifacts detected → full (safe default)',
|
|
119
131
|
};
|
|
120
132
|
}
|
|
@@ -125,6 +137,8 @@ function inferMode(changeDir) {
|
|
|
125
137
|
mode: 'hotfix',
|
|
126
138
|
suggested_path: 'direct',
|
|
127
139
|
explicit: false,
|
|
140
|
+
clarity,
|
|
141
|
+
risk,
|
|
128
142
|
reason: `≤2 tasks, ≤2 files, no schema/API/new-module keywords → hotfix (trivial → suggest path direct; hotfix retained when reusing an existing contract)`,
|
|
129
143
|
};
|
|
130
144
|
}
|
|
@@ -135,6 +149,8 @@ function inferMode(changeDir) {
|
|
|
135
149
|
mode: 'tweak',
|
|
136
150
|
suggested_path: 'direct',
|
|
137
151
|
explicit: false,
|
|
152
|
+
clarity,
|
|
153
|
+
risk,
|
|
138
154
|
reason: `≤4 tasks, only config/doc files, no schema/API/new-module keywords → tweak (trivial → suggest path direct)`,
|
|
139
155
|
};
|
|
140
156
|
}
|
|
@@ -145,6 +161,8 @@ function inferMode(changeDir) {
|
|
|
145
161
|
mode: 'full',
|
|
146
162
|
suggested_path: 'planned',
|
|
147
163
|
explicit: false,
|
|
164
|
+
clarity,
|
|
165
|
+
risk,
|
|
148
166
|
reason: `${taskCount} tasks, ${fileCount} files${hasSchemaChange ? ', schema/API change detected' : ''}${hasArchAggregate ? ', arch/aggregate keywords detected' : ''} → suggest path planned (light architecture); front door: workflow start --path planned (new change) or tf state upgrade <dir> planned (existing change)`,
|
|
149
167
|
};
|
|
150
168
|
}
|
|
@@ -154,6 +172,8 @@ function inferMode(changeDir) {
|
|
|
154
172
|
mode: 'full',
|
|
155
173
|
suggested_path: null,
|
|
156
174
|
explicit: false,
|
|
175
|
+
clarity,
|
|
176
|
+
risk,
|
|
157
177
|
reason: `${taskCount} tasks, ${fileCount} files${codeFileCount > 0 ? ` (${codeFileCount} code files)` : ''}${hasSchemaChange ? ', schema/API change detected' : ''}${hasNewModule ? ', new module detected' : ''}${hasCrossModule ? ', cross-module detected' : ''} → full`,
|
|
158
178
|
};
|
|
159
179
|
}
|