@double-codeing/flow2spec 3.0.19 → 3.1.1
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/README.en.md +15 -6
- package/README.md +5 -5
- package/cli.js +122 -11
- package/docs/.mermaid-cache.json +1 -1
- package/docs/en/architecture.md +5 -5
- package/docs/en/commands-reference.md +29 -48
- package/docs/en/design-principles.md +12 -9
- package/docs/en/directory-conventions.md +26 -3
- package/docs/en/usage-guide.md +16 -10
- package/docs/en/usage-scenarios.md +3 -3
- package/docs//344/275/223/347/263/273/344/270/216/345/216/237/347/220/206.md +4 -4
- package/docs//344/275/277/347/224/250/346/241/210/344/276/213-/346/250/241/346/213/237/345/257/271/350/257/235.md +2 -2
- package/docs//344/275/277/347/224/250/350/257/264/346/230/216.md +15 -10
- package/docs//345/221/275/344/273/244/350/257/264/346/230/216.md +28 -51
- package/docs//347/233/256/345/275/225/344/270/216/350/267/257/345/276/204/347/272/246/345/256/232.md +26 -3
- package/docs//350/256/276/350/256/241/350/257/264/346/230/216.md +88 -57
- package/lib/claudeSettingsAdapter.js +99 -30
- package/lib/flow2specConfig.js +32 -6
- package/lib/init.js +264 -4
- package/package.json +2 -2
- package/templates/AGENTS.codex-stub.md +2 -0
- package/templates/AGENTS.md +18 -5
- package/templates/flow2spec.config.json +5 -2
- package/templates/hooks/f2s-config-inject.js +9 -147
- package/templates/hooks/f2s-config-session.js +95 -0
- package/templates/hooks/f2s-update-check.js +141 -0
- package/templates/knowledge/index.md +4 -4
- package/templates/knowledge/manifest-routing.json +34 -5
- package/templates/knowledge/template//347/273/210/347/250/277/346/250/241/347/211/210.md +2 -2
- package/templates/knowledge/topics/f2s-config-precheck.md +2 -2
- package/templates/knowledge/topics/f2s-fallback-triage.md +2 -2
- package/templates/knowledge/topics/f2s-stock-docs-vs-req-docs.md +3 -3
- package/templates/rules/f2s-config-check.mdc +3 -1
- package/templates/rules/f2s-flow2spec-unified-entry.mdc +21 -3
- package/templates/rules/f2s-implement-tech-design.mdc +1 -1
- package/templates/rules/f2s-karpathy-guidelines.mdc +1 -1
- package/templates/rules/f2s-stock-docs-vs-req-docs.mdc +3 -3
- package/templates/rules/f2s-topic-authoring.mdc +124 -0
- package/templates/skills/f2s-doc-arch/SKILL.md +37 -9
- package/templates/skills/f2s-doc-final/SKILL.md +5 -5
- package/templates/skills/f2s-git-commit/SKILL.md +21 -5
- package/templates/skills/{f2s-doc-add → f2s-kb-add}/SKILL.md +12 -7
- package/templates/skills/f2s-kb-addRules/SKILL.md +165 -0
- package/templates/skills/{f2s-ctx-build → f2s-kb-build}/SKILL.md +14 -9
- package/templates/skills/f2s-kb-feat/SKILL.md +8 -6
- package/templates/skills/f2s-kb-fix/SKILL.md +8 -6
- package/templates/skills/f2s-kb-migrate/SKILL.md +12 -10
- package/templates/skills/{f2s-ctx-rm → f2s-kb-rm}/SKILL.md +7 -5
- package/templates/skills/f2s-kb-sync/SKILL.md +13 -5
- package/templates/skills/f2s-kb-upgrade/SKILL.md +27 -11
- package/templates/skills/f2s-karpathy-guidelines/SKILL.md +0 -20
- package/templates/skills/stock-docs-vs-req-docs/SKILL.md +0 -35
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
/**
|
|
4
|
+
* flow2spec SessionStart hook — 会话开始时一次性注入 flow2spec.config.json 摘要。
|
|
5
|
+
* 该摘要不替代 f2s-* Skill 正文前的 Read("flow2spec.config.json")。
|
|
6
|
+
* 由 flow2spec init --claude 写入 .claude/hooks/f2s-config-session.js。
|
|
7
|
+
*/
|
|
8
|
+
const fs = require('fs');
|
|
9
|
+
const path = require('path');
|
|
10
|
+
|
|
11
|
+
const DEFAULT_CFG = {
|
|
12
|
+
subAgent: false,
|
|
13
|
+
switchAgentVerification: false,
|
|
14
|
+
changeTracking: { feat: true, fix: false, implement: true },
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
function normalizeBool(value, fallback) {
|
|
18
|
+
if (value === true || value === 'true' || value === 1 || value === '1')
|
|
19
|
+
return true;
|
|
20
|
+
if (value === false || value === 'false' || value === 0 || value === '0')
|
|
21
|
+
return false;
|
|
22
|
+
return fallback;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function normalizeCfg(raw) {
|
|
26
|
+
if (!raw || typeof raw !== 'object' || Array.isArray(raw)) {
|
|
27
|
+
return { ...DEFAULT_CFG, changeTracking: { ...DEFAULT_CFG.changeTracking } };
|
|
28
|
+
}
|
|
29
|
+
const ct = raw.changeTracking;
|
|
30
|
+
let changeTracking = { ...DEFAULT_CFG.changeTracking };
|
|
31
|
+
if (typeof ct === 'boolean') {
|
|
32
|
+
changeTracking = {
|
|
33
|
+
feat: normalizeBool(ct, DEFAULT_CFG.changeTracking.feat),
|
|
34
|
+
fix: normalizeBool(ct, DEFAULT_CFG.changeTracking.fix),
|
|
35
|
+
implement: normalizeBool(ct, DEFAULT_CFG.changeTracking.implement),
|
|
36
|
+
};
|
|
37
|
+
} else if (ct && typeof ct === 'object' && !Array.isArray(ct)) {
|
|
38
|
+
changeTracking = {
|
|
39
|
+
feat: normalizeBool(ct.feat, DEFAULT_CFG.changeTracking.feat),
|
|
40
|
+
fix: normalizeBool(ct.fix, DEFAULT_CFG.changeTracking.fix),
|
|
41
|
+
implement: normalizeBool(ct.implement, DEFAULT_CFG.changeTracking.implement),
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
const switchRaw = Object.prototype.hasOwnProperty.call(raw, 'switchAgentVerification')
|
|
45
|
+
? raw.switchAgentVerification
|
|
46
|
+
: raw.subAgentVerification;
|
|
47
|
+
return {
|
|
48
|
+
subAgent: normalizeBool(raw.subAgent, DEFAULT_CFG.subAgent),
|
|
49
|
+
switchAgentVerification: normalizeBool(
|
|
50
|
+
switchRaw,
|
|
51
|
+
DEFAULT_CFG.switchAgentVerification,
|
|
52
|
+
),
|
|
53
|
+
changeTracking,
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function emit(lines) {
|
|
58
|
+
process.stdout.write(
|
|
59
|
+
JSON.stringify({
|
|
60
|
+
hookSpecificOutput: {
|
|
61
|
+
hookEventName: 'SessionStart',
|
|
62
|
+
additionalContext: lines.join('\n'),
|
|
63
|
+
},
|
|
64
|
+
}) + '\n',
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function main() {
|
|
69
|
+
const configPath = path.resolve(process.cwd(), 'flow2spec.config.json');
|
|
70
|
+
if (!fs.existsSync(configPath)) {
|
|
71
|
+
const cfg = { ...DEFAULT_CFG, changeTracking: { ...DEFAULT_CFG.changeTracking } };
|
|
72
|
+
emit([
|
|
73
|
+
'[flow2spec] 本会话未找到 flow2spec.config.json;f2s-* Skill 前仍必须尝试 Read("flow2spec.config.json"),缺失字段按默认值处理。',
|
|
74
|
+
`配置摘要:subAgent=${cfg.subAgent}, switchAgentVerification=${cfg.switchAgentVerification}, changeTracking=${JSON.stringify(cfg.changeTracking)}`,
|
|
75
|
+
]);
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
try {
|
|
80
|
+
const cfg = normalizeCfg(JSON.parse(fs.readFileSync(configPath, 'utf8')));
|
|
81
|
+
emit([
|
|
82
|
+
'[flow2spec] SessionStart 配置摘要(仅作提醒,执行 f2s-* Skill 前仍必须 Read 磁盘文件):',
|
|
83
|
+
`subAgent=${cfg.subAgent}`,
|
|
84
|
+
`switchAgentVerification=${cfg.switchAgentVerification}`,
|
|
85
|
+
`changeTracking=${JSON.stringify(cfg.changeTracking)}`,
|
|
86
|
+
]);
|
|
87
|
+
} catch (err) {
|
|
88
|
+
emit([
|
|
89
|
+
`[flow2spec] flow2spec.config.json 解析失败:${err.message || String(err)}`,
|
|
90
|
+
'执行 f2s-* Skill 前必须先修复或 Read 该文件;无法读取时按缺失字段默认值处理。',
|
|
91
|
+
]);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
main();
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
/**
|
|
4
|
+
* flow2spec UserPromptSubmit hook — 每天第一次对话时检查版本更新。
|
|
5
|
+
* 比较本地知识库 manifest-routing.json 的 version 与 npm 最新版本:
|
|
6
|
+
* - 一致或本地更新 → 静默退出
|
|
7
|
+
* - 落后 → 向 Agent 上下文注入一行提示(建议执行 f2s-kb-upgrade)
|
|
8
|
+
* 已检查过(24h 内)则完全静默,不做任何输出。
|
|
9
|
+
* 由 flow2spec init 写入对应 agent 的 hooks/f2s-update-check.js。
|
|
10
|
+
*/
|
|
11
|
+
const fs = require('fs');
|
|
12
|
+
const path = require('path');
|
|
13
|
+
const { execFileSync } = require('child_process');
|
|
14
|
+
|
|
15
|
+
const MANIFEST_PATH = path.join(process.cwd(), '.Knowledge', 'manifest-routing.json');
|
|
16
|
+
const CACHE_DIR = path.join(process.cwd(), '.Knowledge');
|
|
17
|
+
const CACHE_FILE = path.join(CACHE_DIR, 'update-check.json');
|
|
18
|
+
const PACKAGE_NAME_PLACEHOLDER = '__FLOW2SPEC_' + 'PACKAGE_NAME__';
|
|
19
|
+
const PACKAGE_NAME = '__FLOW2SPEC_PACKAGE_NAME__';
|
|
20
|
+
|
|
21
|
+
// ── 缓存 ────────────────────────────────────────────────────────────────────
|
|
22
|
+
|
|
23
|
+
function readCache() {
|
|
24
|
+
if (!fs.existsSync(CACHE_FILE)) return null;
|
|
25
|
+
try {
|
|
26
|
+
const d = JSON.parse(fs.readFileSync(CACHE_FILE, 'utf8'));
|
|
27
|
+
if (!d || typeof d !== 'object') return null;
|
|
28
|
+
const checkedAt = Number(d.checkedAt || 0);
|
|
29
|
+
if (!checkedAt) return null;
|
|
30
|
+
if (new Date(checkedAt).toDateString() !== new Date().toDateString()) return null;
|
|
31
|
+
return d;
|
|
32
|
+
} catch (_) { return null; }
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function writeCache(latestNpm, manifestVersion) {
|
|
36
|
+
try {
|
|
37
|
+
fs.writeFileSync(
|
|
38
|
+
CACHE_FILE,
|
|
39
|
+
`${JSON.stringify({ latestNpm, manifestVersion, checkedAt: Date.now() }, null, 2)}\n`,
|
|
40
|
+
'utf8'
|
|
41
|
+
);
|
|
42
|
+
} catch (_) {}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// ── 版本比较 ─────────────────────────────────────────────────────────────────
|
|
46
|
+
|
|
47
|
+
function parseVer(v) {
|
|
48
|
+
return String(v || '').replace(/^v/, '').split(/[.-]/).slice(0, 3).map((p) => {
|
|
49
|
+
const n = Number.parseInt(p, 10);
|
|
50
|
+
return Number.isFinite(n) ? n : 0;
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/** a < b → 负数;a === b → 0;a > b → 正数 */
|
|
55
|
+
function cmpVer(a, b) {
|
|
56
|
+
const av = parseVer(a), bv = parseVer(b);
|
|
57
|
+
for (let i = 0; i < 3; i++) {
|
|
58
|
+
const d = (av[i] || 0) - (bv[i] || 0);
|
|
59
|
+
if (d !== 0) return d;
|
|
60
|
+
}
|
|
61
|
+
return 0;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// ── 读取 ─────────────────────────────────────────────────────────────────────
|
|
65
|
+
|
|
66
|
+
function getManifestVersion() {
|
|
67
|
+
if (!fs.existsSync(MANIFEST_PATH)) return null;
|
|
68
|
+
try {
|
|
69
|
+
return JSON.parse(fs.readFileSync(MANIFEST_PATH, 'utf8')).version || null;
|
|
70
|
+
} catch (_) { return null; }
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function getPackageName() {
|
|
74
|
+
if (PACKAGE_NAME && PACKAGE_NAME !== PACKAGE_NAME_PLACEHOLDER) {
|
|
75
|
+
return PACKAGE_NAME;
|
|
76
|
+
}
|
|
77
|
+
return '@double-codeing/flow2spec';
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function queryNpmLatest(pkgName) {
|
|
81
|
+
return execFileSync('npm', ['view', pkgName, 'version'], {
|
|
82
|
+
encoding: 'utf8',
|
|
83
|
+
timeout: 5000,
|
|
84
|
+
stdio: ['ignore', 'pipe', 'ignore'],
|
|
85
|
+
}).trim();
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// ── 配置开关 ──────────────────────────────────────────────────────────────────
|
|
89
|
+
|
|
90
|
+
function isEnabled() {
|
|
91
|
+
try {
|
|
92
|
+
const cfg = JSON.parse(fs.readFileSync(
|
|
93
|
+
path.join(process.cwd(), 'flow2spec.config.json'), 'utf8'
|
|
94
|
+
));
|
|
95
|
+
const uc = cfg && cfg.updateCheck;
|
|
96
|
+
if (uc && typeof uc.enabled === 'boolean') return uc.enabled;
|
|
97
|
+
return true;
|
|
98
|
+
} catch (_) { return true; }
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// ── 主流程 ────────────────────────────────────────────────────────────────────
|
|
102
|
+
|
|
103
|
+
function main() {
|
|
104
|
+
if (process.env.CI || process.env.CONTINUOUS_INTEGRATION) return;
|
|
105
|
+
if (!isEnabled()) return;
|
|
106
|
+
if (readCache()) return; // 今天已检查过,静默退出
|
|
107
|
+
|
|
108
|
+
const manifestVersion = getManifestVersion();
|
|
109
|
+
if (!manifestVersion) return; // 无知识库,跳过
|
|
110
|
+
|
|
111
|
+
let latestNpm;
|
|
112
|
+
try {
|
|
113
|
+
const pkgName = getPackageName();
|
|
114
|
+
latestNpm = queryNpmLatest(pkgName);
|
|
115
|
+
} catch (_) {
|
|
116
|
+
return; // 网络不通,静默退出,不写缓存(下次还会重试)
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// 写缓存(无论是否需要升级,今天不再重复检查)
|
|
120
|
+
writeCache(latestNpm, manifestVersion);
|
|
121
|
+
|
|
122
|
+
if (cmpVer(manifestVersion, latestNpm) >= 0) return; // 已是最新
|
|
123
|
+
|
|
124
|
+
// 知识库落后于 npm 最新版,注入提示
|
|
125
|
+
const notice = [
|
|
126
|
+
`[flow2spec] 知识库版本 v${manifestVersion} 低于最新包版本 v${latestNpm}。`,
|
|
127
|
+
`建议在此对话中执行 f2s-kb-upgrade 升级知识库模板与路由结构。`,
|
|
128
|
+
].join(' ');
|
|
129
|
+
|
|
130
|
+
process.stdout.write(
|
|
131
|
+
JSON.stringify({
|
|
132
|
+
additional_context: notice,
|
|
133
|
+
hookSpecificOutput: {
|
|
134
|
+
hookEventName: 'SessionStart',
|
|
135
|
+
additionalContext: notice,
|
|
136
|
+
},
|
|
137
|
+
}) + '\n'
|
|
138
|
+
);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
main();
|
|
@@ -23,14 +23,14 @@
|
|
|
23
23
|
| 主题 | 路径 | 适用场景 | 关联文档(摘要) |
|
|
24
24
|
| --- | --- | --- | --- |
|
|
25
25
|
| implement-tech-design | `.Knowledge/topics/f2s-implement-tech-design.md` | 按技术方案实现代码 | req:[技术方案](.Knowledge/req-docs/<技术方案>.md)(必填) |
|
|
26
|
-
|
|
|
26
|
+
| f2s-doc-routing | `.Knowledge/topics/f2s-stock-docs-vs-req-docs.md` | stock-docs / req-docs 目录分工 | stock:[目录边界说明](.Knowledge/stock-docs/<目录边界说明>.md)(可选) |
|
|
27
27
|
| fallback-triage | `.Knowledge/topics/f2s-fallback-triage.md` | 未命中或低置信度:分诊与澄清 | stock:[路由分诊说明](.Knowledge/stock-docs/<分诊说明>.md)(可选) |
|
|
28
28
|
| config-precheck | `.Knowledge/topics/f2s-config-precheck.md` | 执行 `f2s-*` 前读 `flow2spec.config.json` / 编排开关 | Codex 长文:仓库根 `.codex/topics/f2s-config-check.md`;[路由摘要](topics/f2s-config-precheck.md) |
|
|
29
29
|
| f2s-task | `.Knowledge/topics/f2s-task.md` | 变更追踪、`.task/` 任务清单与跨会话续作 | 长文:配置根 `rules/f2s-task.*`;Codex:`.codex/topics/f2s-task.md` |
|
|
30
30
|
| f2s-req-plan | `.Knowledge/topics/f2s-req-plan.md` | 需求/方案规划与实现;始终维护 `.task/` | 技能:`skills/f2s-req-plan/SKILL.md`;依赖 `f2s-task` |
|
|
31
31
|
|
|
32
32
|
每主题保留 **1–3 条** 可点击摘要链接;全量路径对照写入 `.Knowledge/migration-report.md`(迁移场景)。
|
|
33
|
-
其中 **`implement-tech-design`**、**`
|
|
33
|
+
其中 **`implement-tech-design`**、**`f2s-doc-routing`**、**`config-precheck`**、**`f2s-task`** 在 `topics/` 内为**路由摘要**;执行长文见配置根 **`rules/f2s-*.md(c)`**;使用 Codex 时见 **`.codex/AGENTS.md`**、**`.codex/topics/f2s-*.md`**(`f2s-config-check` 与 `AGENTS` 前置同源,按需打开)。
|
|
34
34
|
|
|
35
35
|
---
|
|
36
36
|
|
|
@@ -62,9 +62,9 @@
|
|
|
62
62
|
|
|
63
63
|
| 情况 | 你怎么做 |
|
|
64
64
|
| --- | --- |
|
|
65
|
-
| 有文档但没配到(1a) | 维护侧:`f2s-
|
|
65
|
+
| 有文档但没配到(1a) | 维护侧:`f2s-kb-build` / `f2s-kb-sync` / `f2s-kb-add` 补路由与 `includeAny`。执行侧:分诊主题澄清任务类型,**不**用全仓扫替代 manifest。 |
|
|
66
66
|
| 配到了但不够(1b) | 走依赖与次高候选 → `verify` 点名缺哪篇文档;仍缺则向用户要路径或补 `req-docs`。 |
|
|
67
67
|
| 库里没有(2) | 承认缺口 → 代码下钻或请用户补需求/方案文档。 |
|
|
68
68
|
| 反复读 manifest 费 token(2a) | 同一任务线内 routing 只当快照;只读命中项的单个 matcher;不遍历整个 `matchers/` 目录枚举;`index.md` 勿与 routing 循环互刷。 |
|
|
69
69
|
|
|
70
|
-
**说明**:「路由/知识已更新」指 `f2s-*`(如 `f2s-
|
|
70
|
+
**说明**:「路由/知识已更新」指 `f2s-*`(如 `f2s-kb-build`、`f2s-kb-sync`、`f2s-kb-add`、`f2s-kb-fix` 等)产出或手改 `manifest-routing` / `matchers` 分片;**`flow2spec init` 不撰写业务文档**,以模板补齐与配置根落盘为主,勿与知识库内容更新混为一谈。
|
|
@@ -6,15 +6,44 @@
|
|
|
6
6
|
"fallbackTopic": "fallback-triage",
|
|
7
7
|
"topicDependencies": {
|
|
8
8
|
"implement-tech-design": [
|
|
9
|
-
"
|
|
9
|
+
"f2s-doc-routing"
|
|
10
10
|
],
|
|
11
11
|
"f2s-req-plan": [
|
|
12
12
|
"f2s-task"
|
|
13
13
|
]
|
|
14
14
|
},
|
|
15
|
+
"topicMetadata": {
|
|
16
|
+
"implement-tech-design": {
|
|
17
|
+
"primary": "policy",
|
|
18
|
+
"confidence": "manual"
|
|
19
|
+
},
|
|
20
|
+
"f2s-doc-routing": {
|
|
21
|
+
"primary": "policy",
|
|
22
|
+
"confidence": "manual"
|
|
23
|
+
},
|
|
24
|
+
"fallback-triage": {
|
|
25
|
+
"primary": "policy",
|
|
26
|
+
"confidence": "manual"
|
|
27
|
+
},
|
|
28
|
+
"config-precheck": {
|
|
29
|
+
"primary": "config",
|
|
30
|
+
"tags": [
|
|
31
|
+
"policy"
|
|
32
|
+
],
|
|
33
|
+
"confidence": "manual"
|
|
34
|
+
},
|
|
35
|
+
"f2s-task": {
|
|
36
|
+
"primary": "policy",
|
|
37
|
+
"confidence": "manual"
|
|
38
|
+
},
|
|
39
|
+
"f2s-req-plan": {
|
|
40
|
+
"primary": "policy",
|
|
41
|
+
"confidence": "manual"
|
|
42
|
+
}
|
|
43
|
+
},
|
|
15
44
|
"topicPaths": {
|
|
16
45
|
"implement-tech-design": ".Knowledge/topics/f2s-implement-tech-design.md",
|
|
17
|
-
"
|
|
46
|
+
"f2s-doc-routing": ".Knowledge/topics/f2s-stock-docs-vs-req-docs.md",
|
|
18
47
|
"fallback-triage": ".Knowledge/topics/f2s-fallback-triage.md",
|
|
19
48
|
"config-precheck": ".Knowledge/topics/f2s-config-precheck.md",
|
|
20
49
|
"f2s-task": ".Knowledge/topics/f2s-task.md",
|
|
@@ -34,7 +63,7 @@
|
|
|
34
63
|
"matcherId": "m-implement-from-spec",
|
|
35
64
|
"matcherPath": ".Knowledge/matchers/m-implement-from-spec.json",
|
|
36
65
|
"topics": [
|
|
37
|
-
"
|
|
66
|
+
"f2s-doc-routing",
|
|
38
67
|
"implement-tech-design"
|
|
39
68
|
]
|
|
40
69
|
},
|
|
@@ -43,7 +72,7 @@
|
|
|
43
72
|
"matcherId": "m-doc-routing",
|
|
44
73
|
"matcherPath": ".Knowledge/matchers/m-doc-routing.json",
|
|
45
74
|
"topics": [
|
|
46
|
-
"
|
|
75
|
+
"f2s-doc-routing"
|
|
47
76
|
]
|
|
48
77
|
},
|
|
49
78
|
{
|
|
@@ -63,4 +92,4 @@
|
|
|
63
92
|
]
|
|
64
93
|
}
|
|
65
94
|
]
|
|
66
|
-
}
|
|
95
|
+
}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
# 终稿概述模版
|
|
4
4
|
|
|
5
|
-
> 本模板用于将「架构说明」「功能/技术方案」等文档整理为**终稿**形态,便于 **f2s-
|
|
5
|
+
> 本模板用于将「架构说明」「功能/技术方案」等文档整理为**终稿**形态,便于 **f2s-kb-build** 技能更新 `.Knowledge/topics`、`.Knowledge/index.md` 与(按需)路由清单(`manifest-routing` + `matchers/*.json`)。
|
|
6
6
|
> 适用:后端服务、前端/客户端、全栈、产品与设计说明等,按需保留或省略章节。
|
|
7
7
|
> **在 Flow2Spec 中**:主模板路径为 `.Knowledge/template/终稿模版.md`;配置根不再写入 `template/` 副本。
|
|
8
8
|
> **执行 f2s-doc-final 技能时**:本模版仅作为**结构参考与写作提示**,不强制套用;转换以原文内容与逻辑为主,按需采纳章节建议。
|
|
@@ -99,4 +99,4 @@
|
|
|
99
99
|
|
|
100
100
|
- 将上述括号内的占位替换为实际内容;与文档类型无关的章节可整节删除或标「(不适用)」。
|
|
101
101
|
- 至少保留 **核心概念、业务规则、关键流程** 三个二级标题,其余按需增删。
|
|
102
|
-
- 保存为 `.Knowledge/stock-docs/<方案名>_终稿.md` 后,按 **f2s-
|
|
102
|
+
- 保存为 `.Knowledge/stock-docs/<方案名>_终稿.md` 后,按 **f2s-kb-build** 技能、以该路径为入参即可更新 `.Knowledge/topics`、`.Knowledge/index.md`,并在需要时更新路由清单。
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
| --- | --- |
|
|
12
12
|
| Codex(init 镜像,与模板同源) | [f2s-config-check.md](../../.codex/topics/f2s-config-check.md) |
|
|
13
13
|
| Cursor | 仓库根 `.cursor/rules/f2s-config-check.mdc`(`flow2spec init cursor`) |
|
|
14
|
-
| Claude | `.claude/rules/f2s-config-check.md`;PreToolUse
|
|
14
|
+
| Claude | `.claude/rules/f2s-config-check.md`;SessionStart:`.claude/hooks/f2s-config-session.js`;PreToolUse 守门:`.claude/hooks/f2s-config-inject.js` |
|
|
15
15
|
| 包模板 | `templates/rules/f2s-config-check.mdc` |
|
|
16
16
|
|
|
17
17
|
## 必备步骤
|
|
@@ -21,4 +21,4 @@
|
|
|
21
21
|
|
|
22
22
|
## 禁止项
|
|
23
23
|
|
|
24
|
-
- 禁止在未读 **`flow2spec.config.json`** 的情况下进入 **`f2s-*`** 技能正文步骤(与 `AGENTS`、`.codex/topics/f2s-config-check.md`
|
|
24
|
+
- 禁止在未读 **`flow2spec.config.json`** 的情况下进入 **`f2s-*`** 技能正文步骤(与 `AGENTS`、`.codex/topics/f2s-config-check.md` 一致);Claude 的 SessionStart 摘要与 PreToolUse 守门提示不替代本次 Read。
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
不由 Agent 自行推断,直接问用户:
|
|
35
35
|
|
|
36
36
|
> 当前任务未命中路由。请确认:**这个领域的文档是否已录入知识库?**
|
|
37
|
-
> - 是 → 可能是路由词条缺失,建议执行 `f2s-
|
|
37
|
+
> - 是 → 可能是路由词条缺失,建议执行 `f2s-kb-build` / `f2s-kb-sync` 补充路由后重试
|
|
38
38
|
> - 否 → 知识库当前无此覆盖,可选择:下钻业务源码 / 补充 `req-docs` 后按方案实现
|
|
39
39
|
> - 不确定 → 请检查 `.Knowledge/stock-docs/` 是否有相关文档,再告知
|
|
40
40
|
|
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
| 分诊结论 | 下一步 |
|
|
48
48
|
|----------|--------|
|
|
49
49
|
| 已命中主题,补齐上下文后 | 跳转至该 topic,按 `match → expand → verify → act` 执行 |
|
|
50
|
-
| 用户确认文档已录入,路由词条缺失 | 提示执行 `f2s-
|
|
50
|
+
| 用户确认文档已录入,路由词条缺失 | 提示执行 `f2s-kb-build` / `f2s-kb-sync` 补路由,本次暂停或下钻源码 |
|
|
51
51
|
| 用户确认库中无覆盖 | 提供两条路:下钻源码 / 补充 `req-docs` 后实现 |
|
|
52
52
|
| 用户不确定,仍无法定位 | 停止执行,向用户说明原因,等待明确指令 |
|
|
53
53
|
|
|
@@ -1,18 +1,18 @@
|
|
|
1
|
-
#
|
|
1
|
+
# f2s-doc-routing(路由摘要)
|
|
2
2
|
|
|
3
3
|
> **唯一长文**:Cursor / Claude 以配置根 **`rules/f2s-stock-docs-vs-req-docs.md(c)`** 为准。
|
|
4
4
|
> **Codex**:不读 `rules/`,须执行 **`.codex/topics/f2s-stock-docs-vs-req-docs.md`**(由 `flow2spec init` 从模板 `rules` 自动镜像)中的等效约束。
|
|
5
5
|
|
|
6
6
|
## 本文件作用
|
|
7
7
|
|
|
8
|
-
- 供 `manifest-routing.topicPaths`、**`topicDependencies`** 与 `index.md` 锚定主题 id **`
|
|
8
|
+
- 供 `manifest-routing.topicPaths`、**`topicDependencies`** 与 `index.md` 锚定主题 id **`f2s-doc-routing`**。
|
|
9
9
|
- 仅保留**目录分工**记忆点。
|
|
10
10
|
|
|
11
11
|
## 目录分工(须与规则一致)
|
|
12
12
|
|
|
13
13
|
| 目录 | 用途 |
|
|
14
14
|
| --- | --- |
|
|
15
|
-
| `.Knowledge/stock-docs/` | 架构、终稿、沉淀;`f2s-
|
|
15
|
+
| `.Knowledge/stock-docs/` | 架构、终稿、沉淀;`f2s-kb-build` / `f2s-doc-final` 等优先落盘。 |
|
|
16
16
|
| `.Knowledge/req-docs/` | 需求澄清、**技术方案**、按方案实现时的 MD 输入。 |
|
|
17
17
|
|
|
18
18
|
**原则**:按方案写代码只读 **`req-docs`**;不要把 **`stock-docs`** 当编码直接输入。
|
|
@@ -19,7 +19,9 @@ alwaysApply: true
|
|
|
19
19
|
| `switchAgentVerification: false` | 落盘侧自验,不交叉 |
|
|
20
20
|
| 文件不存在 | 所有字段均视为 `false` |
|
|
21
21
|
|
|
22
|
-
**Claude Code
|
|
22
|
+
**Claude Code**:`f2s-config-session` 在 `SessionStart` 注入一次配置摘要;`f2s-config-inject` 在 `PreToolUse` 仅作为守门提示,提醒调用 `f2s-*` Skill 前首步必须 `Read("flow2spec.config.json")`。两者都**不替代**本条 Read 要求。
|
|
23
|
+
|
|
24
|
+
**Cursor / Codex**:配置读取仍走文本约束(Cursor:本规则 `alwaysApply`;Codex:根 `AGENTS.md` 与 `.codex/topics/f2s-config-check.md`),不依赖 hook 自动读取配置。
|
|
23
25
|
|
|
24
26
|
### changeTracking(变更追踪)
|
|
25
27
|
|
|
@@ -33,7 +33,7 @@ alwaysApply: true
|
|
|
33
33
|
- 若命中主题在 `topicDependencies` 中存在依赖,先读依赖主题,再读主主题。
|
|
34
34
|
- 路由清单仅通过 `f2s-*` 技能流程维护,不依赖额外 CLI 子命令。
|
|
35
35
|
2. `.Knowledge/index.md` 按需读取,仅用于确认主题语义与边界。
|
|
36
|
-
3. 再读 `.Knowledge/topics/<topic>.md`(**路由摘要**:主题 id、路径约定、下一步指针);若主题为 **`implement-tech-design`** 或 **`
|
|
36
|
+
3. 再读 `.Knowledge/topics/<topic>.md`(**路由摘要**:主题 id、路径约定、下一步指针);若主题为 **`implement-tech-design`** 或 **`f2s-doc-routing`**,**必须继续读取**配置根 **`rules/f2s-implement-tech-design.*` / `rules/f2s-stock-docs-vs-req-docs.*` 全文**作为执行依据(`.Knowledge/topics` 内同名文件不重复长文)。
|
|
37
37
|
4. 若需要背景,再读 `.Knowledge/stock-docs/<doc>.md`。
|
|
38
38
|
5. 仅在前四步不足时下钻业务源码。
|
|
39
39
|
6. 命中后必须执行 `match -> expand -> verify -> act`:
|
|
@@ -58,6 +58,7 @@ alwaysApply: true
|
|
|
58
58
|
- `taskToTopicRules[].matcherPath`:匹配词分片直链路径,按需读取单个 matcher 文件。
|
|
59
59
|
- `taskToTopicRules[].matcherId`:matcher 的稳定标识,需与 matcher 分片内 `id` 一致。
|
|
60
60
|
- `topicDependencies`:主主题命中后先加载依赖主题。
|
|
61
|
+
- `topicMetadata`:主题治理元数据,只影响阅读预期,不参与 matcher 命中,不决定是否读取 topic,不改变执行强制性;执行强制性始终以 `AGENTS.md`、rules、skills 与 topic 正文中的明确要求为准。读到 `topicMetadata[topicId].primary` / `tags` 时:`config` 关注配置项、开关、默认值、初始化参数;`policy` 优先检查正文中的必须/禁止/门禁/流程约束;`feature` 作为已落地业务/产品能力背景;`module` 作为目录、包、模块边界与工程结构背景。`confidence` 仅允许 `manual` / `inferred`;无明确分类证据时不写 metadata。
|
|
61
62
|
- `matcherPath(includeAny)`:任务关键词匹配词表。
|
|
62
63
|
- `fallbackTopic`:任务与关键词都未命中时必须读取,但仅作低置信度兜底,不是最终执行依据。
|
|
63
64
|
- `.Knowledge/manifest-routing.json + matcherPath 分片文件` 是机读事实源(关键词仅在 `matchers/*.json`)。
|
|
@@ -68,10 +69,10 @@ alwaysApply: true
|
|
|
68
69
|
|
|
69
70
|
| 情况 | 对策 |
|
|
70
71
|
| --- | --- |
|
|
71
|
-
| **1a 库里有文档但未配路由** | 用 `f2s-
|
|
72
|
+
| **1a 库里有文档但未配路由** | 用 `f2s-kb-build` / `f2s-kb-sync` / `f2s-kb-add` 补 `taskToTopicRules`、`matcherPath` 分片、`topicPaths`;扩充 `includeAny` 覆盖用户常用说法。Agent 侧:走 `fallbackTopic` 分诊并提示「需补路由」,**不**靠全仓扫文件代替配置。 |
|
|
72
73
|
| **1b 命中了但上下文不够** | 先 `expand`(`topicDependencies` + 次高候选),再 `verify` 点名缺哪份 `stock-docs`/`req-docs` 或哪段 topic;仍不足则 **向用户要文档或路径**,不要无门槛跨 matcher 全量补检索。**Agent 若需下钻源码**:须先对用户做**可见的缺口说明**(已读 KB、缺什么、拟读哪 1~2 个文件),见 **`f2s-knowledge-preflight`**「缺口闸门」;**禁止**无说明地连续 `Grep`/乱序探源。 |
|
|
73
74
|
| **2 库里没有对应文档** | 一次读完 routing + 已命中 matcher + 相关 topic 后,在回复中 **明确承认知识库无覆盖**,再选:下钻业务代码 / 请用户补充 `req-docs` 或 PRD。**禁止**用反复读清单假装「再找一遍就会有」。**下钻源码前**同样须满足 **`f2s-knowledge-preflight`**「缺口闸门」的可见说明。 |
|
|
74
|
-
| **2a 反复读清单耗 token** | **同一任务线内** `manifest-routing.json` 视为稳定快照:再次全文读取须说明理由(例如用户声明已通过 `f2s-
|
|
75
|
+
| **2a 反复读清单耗 token** | **同一任务线内** `manifest-routing.json` 视为稳定快照:再次全文读取须说明理由(例如用户声明已通过 `f2s-kb-build` / `f2s-kb-sync` / `f2s-kb-add` 等更新路由或知识、或**手动编辑**了 manifest/matcher)。**勿将**仅执行 **`flow2spec init`** 等同于「业务知识库已更新」:`init` 以模板补齐、配置根落盘与包级路由结构对齐为主;**stock-docs / req-docs、topics 路由摘要、matchers 词条**由 **`f2s-*` 技能流程**维护;**包模板 `templates/rules/*.mdc`** 为 Flow2Spec 规则事实源,`init` 同步到配置根 **`rules/*.mdc`**(或等价扩展名)并镜像 **`.codex/topics/*.md`**(条数与包模板一致,含统一入口与专题长文)。只读 **当前规则对应的单个** `matcherPath`;不要为枚举而遍历整个 `matchers/` 目录。`index.md` 仅在需核对主题语义时打开,禁止与 manifest 交替「刷清单」。 |
|
|
75
76
|
|
|
76
77
|
### 知识缺口的执行层要点(避免「表里有写、行为没做」)
|
|
77
78
|
|
|
@@ -88,6 +89,23 @@ alwaysApply: true
|
|
|
88
89
|
|
|
89
90
|
**例外(应显式否定)**:A、B 两种做法在逻辑上均正确,但项目已做出**排他性选择**时,须写出「不用 B」——不说清楚,读者无法判断 B 是否仍可选。
|
|
90
91
|
|
|
92
|
+
## 知识库版本自检(sessionStart 自动触发;每日首次,仅 updateCheck.enabled=true 时)
|
|
93
|
+
|
|
94
|
+
Cursor 由 `flow2spec init cursor` 写入 **`.cursor/hooks.json`**,在 `sessionStart` 自动执行 `node .cursor/hooks/f2s-update-check.js`;脚本通过 `additional_context` 把升级提示注入会话。Codex 由 `flow2spec init codex` 写入 **`.codex/hooks.json`**,在 `SessionStart` 的 `startup|resume` 事件自动执行 `node .codex/hooks/f2s-update-check.js`。
|
|
95
|
+
|
|
96
|
+
**规则层双保险**(与脚本缓存互为备份):
|
|
97
|
+
|
|
98
|
+
1. 读 `flow2spec.config.json` → 若 `updateCheck.enabled` 不为 `true`,跳过,不做任何提示。
|
|
99
|
+
2. 读 `.Knowledge/update-check.json` → 若文件存在且 `checkedAt` 与今日为同一自然日(`new Date(checkedAt).toDateString() === new Date().toDateString()`),**跳过,不执行脚本,不做任何提示**。
|
|
100
|
+
3. 上述两步均未跳过时:执行当前 agent 配置根下的更新检测脚本(Cursor:`node .cursor/hooks/f2s-update-check.js`;Codex:`node .codex/hooks/f2s-update-check.js`),解析标准输出的 JSON:
|
|
101
|
+
- 若含 `hookSpecificOutput.additionalContext`:**告知用户**该内容(建议执行 `/f2s-kb-upgrade`)。
|
|
102
|
+
- 无输出或解析失败:静默,不提示。
|
|
103
|
+
4. 以上步骤出现任何错误,静默跳过,不影响正常对话。
|
|
104
|
+
|
|
105
|
+
## 主题创作(Topic Authoring)指针
|
|
106
|
+
|
|
107
|
+
新增或修改 `.Knowledge/topics/<topic>.md`、调整 `manifest-routing.topicDependencies`、删除 / 迁移 topic 时,**创作侧** 准则以 **`rules/f2s-topic-authoring.*`** 为单一事实源(**Cursor/Claude**:`rules/f2s-topic-authoring.mdc`;**Codex**:`.codex/topics/f2s-topic-authoring.md`)。本入口为**消费侧**(如何按已有 topic 路由 / 读取 / 兜底),与之并存;硬冲突时以本入口为准。`f2s-kb-build` / `f2s-kb-add` / `f2s-kb-feat` / `f2s-kb-fix` / `f2s-kb-sync` / `f2s-kb-migrate` / `f2s-kb-rm` 在涉及 topic 落盘前须 Read 该条全文。
|
|
108
|
+
|
|
91
109
|
## 禁止项
|
|
92
110
|
|
|
93
111
|
- **`templates/` 可下发约束**(经 `init` 会克隆到任意业务仓):技能/规则/知识模板正文中的示例须**中性**——勿写特定业务域名称、单一组织 npm 包名、仅 Flow2Spec 产品仓存在的 `docs/` 路径;用 `<能力>`、`src/<模块>/` 等占位。
|
|
@@ -5,7 +5,7 @@ alwaysApply: true
|
|
|
5
5
|
|
|
6
6
|
# Karpathy 式编码行为准则
|
|
7
7
|
|
|
8
|
-
>
|
|
8
|
+
> 与项目内 Flow2Spec / `f2s-*` 规则**并行**;若某条与 f2s 强制步骤冲突,**以 f2s 与项目约定为准**。
|
|
9
9
|
|
|
10
10
|
用于减少常见「模型写代码」失误的行为约定。
|
|
11
11
|
|
|
@@ -6,11 +6,11 @@ globs:
|
|
|
6
6
|
alwaysApply: false
|
|
7
7
|
---
|
|
8
8
|
|
|
9
|
-
> **唯一长文**:本文件为 **
|
|
9
|
+
> **唯一长文**:本文件为 **f2s-doc-routing** 的完整约定。`.Knowledge/topics/f2s-stock-docs-vs-req-docs.md` 仅为路由摘要;**Codex** 读取 `.codex/topics/f2s-stock-docs-vs-req-docs.md`(由 `flow2spec init` 从本文件自动镜像)作为等效条令。
|
|
10
10
|
|
|
11
11
|
# stock-docs 与 req-docs
|
|
12
12
|
|
|
13
|
-
- **`.Knowledge/stock-docs/`**:PDF/初稿/终稿/架构说明等**存量源文档**;`f2s-
|
|
13
|
+
- **`.Knowledge/stock-docs/`**:PDF/初稿/终稿/架构说明等**存量源文档**;`f2s-kb-build`、`f2s-doc-final`、`f2s-doc-arch`、`f2s-kb-add` 的文档落盘优先在此。`sourceDoc` 统一写 `.Knowledge/stock-docs/<文件名>.md`。
|
|
14
14
|
- **`.Knowledge/req-docs/`**:需求澄清、技术方案(前后端/数据/任务等)、`f2s-doc-pdf` 输出的「按方案实现」MD;`implement-tech-design` 的触发范围为 `.Knowledge/req-docs/**/*.md`。
|
|
15
15
|
|
|
16
|
-
完整约定见本规则与 **`skills/
|
|
16
|
+
完整约定见本规则与 **`skills/f2s-doc-routing/SKILL.md`**;`.Knowledge/topics/f2s-stock-docs-vs-req-docs.md` 为路由摘要。
|