@haaaiawd/loom 0.1.0 → 0.8.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.
@@ -0,0 +1,121 @@
1
+ ## 诊断与恢复指南
2
+
3
+ ## 健康检查
4
+
5
+ \`\`\`bash
6
+ loom doctor
7
+ \`\`\`
8
+
9
+ 检测 7 类问题:
10
+
11
+ | 问题类型 | 严重度 | 说明 |
12
+ |---|---|---|
13
+ | cycle | fatal | 循环依赖(Intent Map 有环) |
14
+ | orphan_philosophy_ref | high | 哲学锚点指向不存在的文件 |
15
+ | orphan_dependency | high | depends_on 引用不存在的 Intent |
16
+ | completed_no_record | high | completed 但无验证记录 |
17
+ | completed_depends_blocked | high | completed 依赖 blocked 的 Intent |
18
+ | inspiration_source | high/medium | 灵感来源质量不达标(源太少/全是 Wikipedia/缺理由) |
19
+ | part_decomposition | high/medium | 缺少实现部分拆解清单(Weaver 跳过了拆解步骤) |
20
+ | in_progress_no_record | medium | in_progress 但无验证记录(可能中断) |
21
+ | zombie | medium | in_progress/blocked 超过 7 天无活动 |
22
+
23
+ ## 灵感来源校验
24
+
25
+ \`\`\`bash
26
+ loom philosophy check
27
+ \`\`\`
28
+
29
+ 单独校验哲学文档的灵感来源质量。防止 Weaver 从训练数据"背"几个名字就交差。
30
+
31
+ 校验规则:
32
+ - 至少 3 个独立源
33
+ - 至少 2 个非 Wikipedia 链接
34
+ - 每个源必须有选取理由(萃取/转译/启发关系)
35
+ - Wikipedia 占比不超过 70%
36
+
37
+ 不达标时,需要重新织造哲学——真正走搜索漏斗,找原著、论文、工程博客等深度源。
38
+
39
+ ## 实现部分拆解校验
40
+
41
+ \`\`\`bash
42
+ loom philosophy check
43
+ \`\`\`
44
+
45
+ 同时校验哲学文档是否包含"实现部分清单"——Weaver 是否按 PART_DECOMPOSITION.md 拆解了项目的实现部分。
46
+
47
+ 校验规则:
48
+ - 哲学文档中必须有"实现部分清单"章节(或"部分拆解""Part Decomposition"等)
49
+ - 至少识别到 2 个实现部分(小项目建议 3-5 个,大项目 6-10 个)
50
+
51
+ 缺少时,说明 Weaver 跳过了拆解步骤,需要重新织造——按 PART_DECOMPOSITION.md 的方法论识别项目的实现部分。
52
+
53
+ ## 上下文摘要
54
+
55
+ \`\`\`bash
56
+ loom context
57
+ \`\`\`
58
+
59
+ 一条命令获取:进度 + 下一个 Intent + 待验证 + 不一致项 + 风险。
60
+ Agent 重启后先跑这个,快速知道"我在哪、接下来做什么"。
61
+
62
+ ## 只读阶段诊断
63
+
64
+ \`\`\`bash
65
+ loom guide --dry-run
66
+ \`\`\`
67
+
68
+ 用于审计、子代理预演、只读探测。它输出和 `loom guide` 同样的阶段判断,但不写 `.loom/heartbeat.json`。
69
+
70
+ ## Preview 新鲜度诊断
71
+
72
+ \`\`\`bash
73
+ loom preview status
74
+ \`\`\`
75
+
76
+ 检查 `loom-preview.html` 是否比当前 `.loom/v{N}` 源文件更新。人类要求看 preview 时,Agent 先跑这个命令:
77
+ - `fresh=true`:可以 `loom preview`
78
+ - `fresh=false`:不要打开旧投影,先 `loom preview --regen`
79
+ - 必须看旧投影:`loom preview --stale`
80
+
81
+ ## 崩溃恢复
82
+
83
+ ### Forge 崩溃(Intent 留在 in_progress)
84
+
85
+ 1. 跑 \`loom doctor\` 确认哪些 Intent 状态不一致
86
+ 2. 跑 \`loom context\` 看整体状态
87
+ 3. 用户决定:
88
+ - 继续:重新激活 Forge,从当前代码接着做
89
+ - 重置:\`loom intent update <id> --status pending\`,从头来
90
+
91
+ ### Intent Map 文件损坏
92
+
93
+ 1. \`loom intent validate\` 会检测到格式错误
94
+ 2. 从 Git 恢复(.loom/ 应纳入版本控制)
95
+
96
+ ### 验证记录丢失
97
+
98
+ 1. \`loom doctor\` 会检测到 completed 无记录
99
+ 2. 重新验证该 Intent,或从 Git 恢复
100
+
101
+ ## 追溯工具
102
+
103
+ \`\`\`bash
104
+ # Intent 完整追溯链(依赖+验证+哲学+叙事)
105
+ loom intent trace <id>
106
+
107
+ # 反向依赖(谁依赖这个 Intent → 变更影响评估)
108
+ loom intent reverse-dep <id>
109
+
110
+ # 反向哲学引用(哪些 Intent 引用这个锚点 → 哲学变更影响评估)
111
+ loom intent reverse-ref <anchor>
112
+ \`\`\`
113
+
114
+ ## 版本控制是前提
115
+
116
+ LOOM 假设项目使用 Git。所有 .loom/ 下的文件都应纳入版本控制:
117
+ - 文件损坏 → 从 Git 恢复
118
+ - 误操作 → 从 Git 回滚
119
+ - 变更追溯 → Git log 就是审计日志
120
+
121
+ LOOM 不内置备份、审计、回滚——这些是版本控制的职责。
@@ -0,0 +1,135 @@
1
+ ## Intent Loop 详细流程
2
+
3
+ 每个 Intent 独立走一圈。Loop 终止条件:所有 Intent 为 completed 且无 needs_review(不动点达成)。
4
+
5
+ ## Step 1:Keeper 选 Intent
6
+
7
+ \`\`\`bash
8
+ loom intent next # 返回下一个可执行 Intent(pending 且依赖都 completed)
9
+ loom context # 当前状态摘要(进度+下一步+风险)
10
+ \`\`\`
11
+
12
+ 如果没有可执行的 Intent:
13
+ - 全部 completed → 项目阶段完成
14
+ - 有 blocked → 需要人工介入
15
+ - 有 in_progress 但无验证记录 → 可能上次中断,跑 \`loom doctor\` 诊断
16
+
17
+ ## Step 2:更新状态
18
+
19
+ \`\`\`bash
20
+ loom intent update <id> --status in_progress
21
+ \`\`\`
22
+
23
+ ## Step 3:Forge 实现
24
+
25
+ \`\`\`bash
26
+ loom activate forge
27
+ \`\`\`
28
+
29
+ Forge 加载:意图叙事 + 哲学锚点 + 验收契约,在约束下自主实现代码。
30
+ 辅助命令(三个命令的分工):
31
+ - \`loom intent narrative <id>\` — 读意图叙事("为什么做")
32
+ - \`loom verify contract <id>\` — 读验收契约("做成什么样才算数")
33
+ - \`loom intent trace <id>\` — 完整追溯链(叙事+契约+哲学锚点一次性加载,最常用)
34
+ - \`loom philosophy get <anchor>\` — 读哲学原则(遇到取舍时查)
35
+
36
+ ## Step 4:Keeper 验证
37
+
38
+ \`\`\`bash
39
+ loom activate keeper
40
+ loom verify contract <id> # 重新加载验收契约
41
+ \`\`\`
42
+
43
+ Keeper 独立验证四维度:
44
+ 1. 意图忠实度 — 实现是否忠于原始意图叙事
45
+ 2. 哲学一致性 — 实现是否符合哲学原则
46
+ 3. 底线合规 — 是否违反 BASELINE
47
+ 4. 验收达成 — 是否满足验收契约
48
+
49
+ 写入验证记录:
50
+ \`\`\`bash
51
+ loom verify write --json-file verification.json
52
+ \`\`\`
53
+
54
+ 验证记录格式(\`loom verify write\` 的输入):
55
+ \`\`\`json
56
+ {
57
+ "intent_id": "INT-001",
58
+ "verdict": "passed",
59
+ "timestamp": "2026-06-28T12:00:00.000Z",
60
+ "summary": "具体证据描述——不是'看起来没问题'",
61
+ "reproduction_command": "LLM_API_KEY=mock npm test",
62
+ "dimensions": {
63
+ "intent_fidelity": {
64
+ "verdict": "passed",
65
+ "evidence": "对照意图叙事第 2 段,extract.js 实现了完整编排"
66
+ },
67
+ "philosophy_consistency": {
68
+ "verdict": "passed",
69
+ "evidence": "AI_PHILOSOPHY 反模式逐条对照:JSON.parse 有 try/catch、fetch 有超时、无硬编码密钥"
70
+ },
71
+ "baseline_compliance": {
72
+ "verdict": "passed",
73
+ "evidence": "B1-B5 逐条合规"
74
+ },
75
+ "acceptance_achievement": {
76
+ "verdict": "passed",
77
+ "evidence": "6 条契约全部达成,npm test 6/6 pass"
78
+ }
79
+ }
80
+ }
81
+ \`\`\`
82
+ CLI 自动包装成 \`{ intent_id, records: [{ round, ... }] }\` 追加到验证文件。
83
+ \`dimensions\` 每个维度必须是 \`{ verdict, evidence }\` 对象——不允许只写"合规",必须写具体证据。
84
+ \`reproduction_command\` 是复现验证的命令——别人跑这个命令能复现你的验证结果。L2 必填。
85
+
86
+ **evidence 写法参考**:
87
+ - 长度:每条 evidence 50-300 字符为宜。太短("合规")不达标,太长难读。
88
+ - 哲学一致性维度:按哲学锚点逐条对照反模式(见 keeper.md 的"承诺验证法")
89
+ - 其他维度:写"对照了什么 + 在代码哪里看到/没看到"
90
+ - \`reproduction_command\` 注意平台差异:
91
+ - Unix/Mac: \`LLM_API_KEY=mock npm test\`
92
+ - Windows PowerShell: \`$env:LLM_API_KEY='mock'; npm test\`
93
+ - Windows cmd: \`set LLM_API_KEY=mock && npm test\`
94
+ - \`node --test\` 在 Windows 上不能用目录路径(\`node --test test/\` 会报错),用 glob:\`node --test test/*.test.js\`
95
+
96
+ ## Step 5:根据判定结果
97
+
98
+ | verdict | 处理 |
99
+ |---|---|
100
+ | passed | \`loom intent update <id> --status completed\`,回到 Step 1 |
101
+ | deviated | 与 Forge 对话修正,重新实现重新验证。连续 3 轮升级 blocked |
102
+ | blocked | \`loom intent update <id> --status blocked\`,停下报告用户 |
103
+ | pending_human | **手动模式**:等用户补充判定(L3 人类反馈)。7 天超时升级 blocked |
104
+
105
+ **AUTO 模式下的判定规则**(关键差异):
106
+ - AUTO 模式开启时(\`loom auto on\`),**不允许 pending_human**
107
+ - Keeper 遇到 L3 verification_method 时,用 L1+L2 能耐自主判定所有维度
108
+ - 要么 passed(有证据),要么 deviated(有偏离说明),不停下等人类
109
+ - **持续运行,除非出意外否则不允许私自停止**
110
+ - "出意外" = blocked(依赖阻塞/契约无法判定/连续 3 轮 deviated 升级)、fatal 错误
111
+
112
+ ## 变更回流
113
+
114
+ 如果 Forge 发现验收契约不合理、或 Architect 的设计需要调整:
115
+ 1. Keeper 评估变更范围(微调 vs 结构性变更)
116
+ 2. 微调(验收措辞、验证方式)→ Keeper 直接改
117
+ 3. 结构性变更(增减 Intent、改依赖)→ 重新激活 Architect
118
+ 4. 受影响的已完成 Intent 标记为 needs_review
119
+
120
+ ## 不动点收敛
121
+
122
+ 默认单趟:所有 Intent 按拓扑序验证完毕且全 passed → done。
123
+
124
+ 触发收敛:Pass 1 结束后还有 needs_review 的 Intent → 自动进入 Pass 2。
125
+ - Pass 2: 重验所有 needs_review 的 Intent
126
+ - deviated → 修 → 重验
127
+ - 修的时候又影响别的 → 标记 needs_review
128
+ - passed → completed
129
+ - Pass 2 结束还有 needs_review → Pass 3
130
+ - Pass 3 结束还有 needs_review → blocked,报告"无法收敛"
131
+
132
+ 收敛达成 = 一趟完整 pass 没有产生任何新的 needs_review(不动点)。
133
+ 最大 3 趟,超过判定为系统性问题,需 Architect 介入。
134
+
135
+ 详细规则见 .loom/v{N}/ 下的 INTENT_LOOP.md。
@@ -0,0 +1,59 @@
1
+ ## Preview 指南
2
+
3
+ preview 是给人看的只读投影。它把 `.loom/v{N}` 的哲学、愿景、架构、Intent Map 和验证记录压缩成 `loom-preview.html`。
4
+
5
+ ## 常用命令
6
+
7
+ ```bash
8
+ loom preview status # 只读检查 preview 是否存在、是否新鲜
9
+ loom preview # 新鲜则打开;过期则提示重新生成
10
+ loom preview --regen # 输出生成提示词,让 Agent 重写 loom-preview.html
11
+ loom preview --stale # 强行打开过期 preview
12
+ loom preview --help # 查看 preview 命令用法
13
+ ```
14
+
15
+ ## Agent 使用规则
16
+
17
+ 当用户说“看看进度”“打开 preview”“让我看全局”时:
18
+
19
+ 1. 先运行 `loom preview status`
20
+ 2. 如果 `fresh=true`,运行 `loom preview`
21
+ 3. 如果 `fresh=false`,不要打开旧页面,运行 `loom preview --regen`
22
+ 4. 按提示词读取 `.loom/`,重写 `loom-preview.html`
23
+ 5. 再运行 `loom preview` 打开
24
+
25
+ 只有用户明确说要看旧版时,才使用 `loom preview --stale`。
26
+
27
+ ## 新鲜度判断
28
+
29
+ LOOM 使用最小 mtime 机制,不做 hash:
30
+
31
+ ```text
32
+ preview_mtime = loom-preview.html 修改时间
33
+ source_latest_mtime = 当前 .loom/v{N} 核心源文件最新修改时间
34
+
35
+ preview_mtime >= source_latest_mtime → fresh
36
+ 否则 → stale
37
+ ```
38
+
39
+ 核心源文件包括:
40
+ - `00_PHILOSOPHY/`
41
+ - `01_VISION.md`
42
+ - `02_ARCHITECTURE.md`
43
+ - `03_DECISIONS/`
44
+ - `04_INTENT_MAP.json`
45
+ - `05_VERIFICATION.md`
46
+ - `06_CHANGELOG.md`
47
+ - `verifications/`
48
+
49
+ ## 为什么不直接打开旧 preview
50
+
51
+ 旧 preview 是假仪表盘风险:`.loom/` 已经进入 blocked、deviated 或完成新 Intent,但 HTML 仍显示旧状态。
52
+
53
+ 所以普通 `loom preview` 在 stale 时会停止并提示 `loom preview --regen`。
54
+
55
+ ## 生成责任
56
+
57
+ 当前 CLI 不直接生成 HTML。`loom preview --regen` 输出提示词,要求 Agent 读取 `.loom/` 后生成 `loom-preview.html`。
58
+
59
+ CLI 负责判断是否过期和打开文件,Agent 负责把信息做成高质量视觉投影。
@@ -0,0 +1,60 @@
1
+ ## 版本演进指南
2
+
3
+ LOOM 用 .loom/v{N}/ 目录支持多版本共存与演进。
4
+
5
+ ## 什么时候升级版本
6
+
7
+ | 变更类型 | 判定标准 | 处理方式 |
8
+ |---|---|---|
9
+ | Minor | 不改哲学前提、不改愿景北极星、不改架构边界 | 当前版本内改(变更回流机制) |
10
+ | Major | 哲学前提变了、愿景北极星变了、架构边界变了 | 创建新版本 |
11
+
12
+ 判定由用户 + Agent 对话完成,CLI 不做决策。
13
+
14
+ ## Major 升级流程
15
+
16
+ \`\`\`bash
17
+ # 1. 创建新版本(空目录 + 模板,自动切换为当前)
18
+ loom version new
19
+
20
+ # 2. 看看旧版本有什么(Agent 决定参考什么)
21
+ loom version diff v1 v2
22
+
23
+ # 3. Weaver 读旧哲学,织造新哲学
24
+ loom activate weaver
25
+ # → 必须读 .loom/v1/00_PHILOSOPHY/,记录"相对 v1 变了什么"
26
+
27
+ # 4. Visionary 读旧愿景,定义新愿景
28
+ loom activate visionary
29
+ # → 必须读 .loom/v1/01_VISION.md
30
+
31
+ # 5. Architect 读旧架构,设计新架构
32
+ loom activate architect
33
+ # → 必须读 .loom/v1/02_ARCHITECTURE.md + 04_INTENT_MAP.json
34
+
35
+ # 6. 进入新版本的 Intent Loop
36
+ \`\`\`
37
+
38
+ ## 关键设计
39
+
40
+ - **空目录 + 模板**:\`loom version new\` 不自动复制旧版本内容。强制重新思考——参考 ≠ 复制。
41
+ - **旧版本只读**:当前指针指向的版本是当前真相,旧版本保留作历史参考。
42
+ - **Intent ID 重新编号**:v2 的 INT-001 和 v1 的 INT-001 没有关系。追溯靠 Git history 和 \`loom version diff\`。
43
+
44
+ ## 版本管理命令
45
+
46
+ \`\`\`bash
47
+ loom version list # 列出所有版本(* 标记当前)
48
+ loom version current # 显示当前版本
49
+ loom version new # 创建 v{N+1} + 自动切换
50
+ loom version use <v> # 切换当前版本
51
+ loom version diff <v1> <v2> # 对比文件差异
52
+ \`\`\`
53
+
54
+ ## 切换回旧版本
55
+
56
+ \`\`\`bash
57
+ loom version use v1 # 切回 v1 查看历史
58
+ loom intent trace <id> # 在 v1 中追溯 Intent 历史
59
+ loom version use v2 # 切回 v2 继续
60
+ \`\`\`
@@ -0,0 +1,100 @@
1
+ ## LOOM 工作流
2
+
3
+ 从零到交付的完整流程。每个阶段有明确的产出和验收标准。
4
+
5
+ ## 第一步:诊断当前阶段
6
+
7
+ \`\`\`bash
8
+ loom guide
9
+ \`\`\`
10
+
11
+ guide 检测项目当前在哪个阶段,输出"你在阶段 X,下一步做 Y"。
12
+ Agent 每完成一步都跑 guide 确认下一步。
13
+ 审计、预演、子代理探测时用 `loom guide --dry-run`,避免写 `.loom/heartbeat.json`。
14
+
15
+ ## AUTO 模式
16
+
17
+ \`\`\`bash
18
+ loom auto on # 开启:Agent 自动连续执行,不等确认
19
+ loom auto off # 关闭:每步需要用户确认
20
+ \`\`\`
21
+
22
+ AUTO on 时 Agent 一路跑到底,跑完生成 preview 给人看。
23
+ AUTO off 时每步停下等用户说继续。
24
+
25
+ ## 阶段 1:织造哲学(Weaver)
26
+
27
+ \`\`\`bash
28
+ loom activate weaver
29
+ \`\`\`
30
+
31
+ Weaver 根据项目特征从真实思想体系织造定制化哲学。产出:
32
+ - PRODUCT_PHILOSOPHY.md — 产品价值观、反模式清单、决策取舍规则
33
+ - ENGINEERING_CREED.md — 工程原则(按需)
34
+ - DECISION_RUBRIC.md — 冲突时的优先级(按需)
35
+ - PROJECT_BASELINE.md — 项目特定底线(按需)
36
+
37
+ **验收**:哲学有北极星、有反模式、有决策标准。全是空话就重做。
38
+
39
+ ## 阶段 2:定义愿景(Visionary)
40
+
41
+ \`\`\`bash
42
+ loom activate visionary
43
+ \`\`\`
44
+
45
+ 基于哲学定义产品愿景,为每个 Intent 写意图叙事("为什么存在")。产出:
46
+ - 01_VISION.md — 北极星 + 意图叙事列表
47
+
48
+ **验收**:叙事是"为什么"不是"做什么"。写成功能列表就重做。
49
+
50
+ ## 阶段 3:设计系统(Architect)
51
+
52
+ \`\`\`bash
53
+ loom activate architect
54
+ \`\`\`
55
+
56
+ 基于愿景设计系统结构,绘制 Intent Map。产出:
57
+ - 02_ARCHITECTURE.md — 系统设计
58
+ - 04_INTENT_MAP.json — Intent 依赖图 + 验收契约 + 哲学锚点
59
+
60
+ **验收**:验收契约具体到可验证,依赖无环,每个 Intent 有叙事引用。
61
+ 跑 \`loom intent validate\` 校验结构,跑 \`loom doctor\` 检查完整性。
62
+
63
+ ## 阶段 4:Intent Loop
64
+
65
+ \`\`\`bash
66
+ loom activate keeper # Keeper 选 Intent、验证
67
+ loom activate forge # Forge 实现
68
+ loom intent next # 下一个可执行 Intent
69
+ loom context # 当前状态摘要
70
+ \`\`\`
71
+
72
+ 每个 Intent 独立走一圈:选 → 实现 → 验证 → 闭合或修正。
73
+ 详细流程见 \`loom help loop\`。
74
+
75
+ ## 阶段 5:人类预览
76
+
77
+ \`\`\`bash
78
+ loom preview status
79
+ loom preview
80
+ loom preview --regen
81
+ \`\`\`
82
+
83
+ preview 是给人看的只读投影。Agent 应先跑 `loom preview status`:
84
+ - `fresh=true` → 运行 `loom preview` 打开
85
+ - `fresh=false` → 运行 `loom preview --regen`,按提示词重写 `loom-preview.html`,再打开
86
+ - 用户明确要看旧版 → `loom preview --stale`
87
+
88
+ 详细规则见 `loom help preview`。
89
+
90
+ ## 阶段 6:版本演进(按需)
91
+
92
+ 当哲学前提/愿景北极星/架构边界变了,需要 Major 升级。
93
+ 详细流程见 \`loom help version\`。
94
+
95
+ ## 核心原则
96
+
97
+ - **哲学是经线,意图是纬线** — 所有角色共享哲学锚点
98
+ - **底线不可协商** — BASELINE 5 条 + 项目特定底线,角色激活时强制加载
99
+ - **意图可回溯** — 每个 Intent 携带叙事,Keeper 独立验证忠实度
100
+ - **文档开销不超过开发开销** — 小项目可以粗粒度,不必教条
@@ -4,13 +4,10 @@
4
4
  import { readFileSync, existsSync } from 'node:fs';
5
5
  import { join, resolve, dirname } from 'node:path';
6
6
  import { fileURLToPath } from 'node:url';
7
+ import { getLoomRoot } from './shared/paths.js';
7
8
 
8
9
  const __dirname = dirname(fileURLToPath(import.meta.url));
9
10
 
10
- function getLoomRoot() {
11
- return resolve(__dirname, '..', '..');
12
- }
13
-
14
11
  /** 合法角色名 */
15
12
  const VALID_ROLES = ['weaver', 'visionary', 'architect', 'forge', 'keeper'];
16
13
 
@@ -26,10 +23,10 @@ const ROLE_FILES = {
26
23
  /**
27
24
  * 输出角色激活提示词。
28
25
  * @param {string} role — 角色名
29
- * @param {string} loomDir — .loom/v{N} 目录(可选,weaver 不需要)
26
+ * @param {string} versionDir — .loom/v{N} 目录(可选,weaver 不需要)
30
27
  * @returns {string} 激活提示词
31
28
  */
32
- export function activateRole(role, loomDir) {
29
+ export function activateRole(role, versionDir) {
33
30
  if (!VALID_ROLES.includes(role)) {
34
31
  throw new Error(`未知角色: ${role}\n合法角色: ${VALID_ROLES.join(', ')}`);
35
32
  }
@@ -44,13 +41,25 @@ export function activateRole(role, loomDir) {
44
41
  }
45
42
  parts.push(readFileSync(roleFile, 'utf-8'));
46
43
 
47
- // 2. BASELINE(所有角色都需要)
48
- const baselineFile = join(loomRoot, 'meta/BASELINE.md');
49
- parts.push('\n---\n\n## 强制加载:BASELINE\n\n' + readFileSync(baselineFile, 'utf-8'));
44
+ // 2. BASELINE 摘要(不重复全文——全文见 meta/BASELINE.md)
45
+ // 5 条底线压缩成摘要,角色需要知道底线存在 + 一句话内容。
46
+ // 如果角色需要底线细节(如 Weaver 织造哲学时),自行 readFileSync 全文。
47
+ parts.push('\n---\n\n## 强制加载:BASELINE 摘要\n\n');
48
+ parts.push('> 完整底线见 `meta/BASELINE.md`。以下是 5 条底线的摘要——\n');
49
+ parts.push('> 角色激活时必须知道这些底线存在,违反任何一条必须立即停止。\n');
50
+ parts.push('> Philosophy Weaver 织造哲学时必须读取完整 BASELINE.md 作为硬约束输入。\n\n');
51
+ parts.push('| 编号 | 底线 | 一句话 |\n');
52
+ parts.push('|------|------|--------|\n');
53
+ parts.push('| B1 | 必须有结构设计 | 编码前必须有明确的目录结构 + 模块职责边界 + 显式依赖关系 |\n');
54
+ parts.push('| B2 | 禁止硬编码 | 密钥/配置/环境特定值/魔法数字不进代码,用环境变量或集中配置 |\n');
55
+ parts.push('| B3 | 接口契约必须显式 | API/CLI/配置/错误语义/跨系统协议必须有显式定义,变更可追溯 |\n');
56
+ parts.push('| B4 | 决策必须可追溯 | 影响架构/接口/技术栈/依赖的决策必须记录(ADR 或等效格式) |\n');
57
+ parts.push('| B5 | 意图必须可回溯 | 每个实现单元有意图叙事("为什么存在"),可被 Keeper 引用对照 |\n');
58
+ parts.push('\n> 底线不可被哲学覆盖。如果织造的哲学与底线冲突,底线优先。\n');
50
59
 
51
- // 3. 项目特定底线(如果有 loomDir
52
- if (loomDir) {
53
- const projectBaseline = join(loomDir, '00_PHILOSOPHY/PROJECT_BASELINE.md');
60
+ // 3. 项目特定底线(如果有 versionDir
61
+ if (versionDir) {
62
+ const projectBaseline = join(versionDir, '00_PHILOSOPHY/PROJECT_BASELINE.md');
54
63
  if (existsSync(projectBaseline)) {
55
64
  parts.push('\n---\n\n## 强制加载:项目特定底线\n\n' + readFileSync(projectBaseline, 'utf-8'));
56
65
  }
package/cli/src/auto.js CHANGED
@@ -1,6 +1,8 @@
1
- // auto — AUTO 模式开关
1
+ // auto — AUTO 模式开关 + 心跳机制
2
2
  // 存储机制:.loom/auto 文件存在 = on,不存在 = off
3
- // 影响 guide 输出语气和 Agent 行为:on 时直接跑,off 时等确认
3
+ // 心跳:每次 guide 调用时写 .loom/heartbeat.json(时间戳 + stage + next_command)
4
+ // AUTO on(默认):stage 4+(Intent Loop)自动跑,stage 1-3(哲学/愿景/架构)仍需人类 review
5
+ // AUTO off:所有阶段都需人类确认,每步拆得更碎
4
6
 
5
7
  import { existsSync, writeFileSync, unlinkSync, readFileSync } from 'node:fs';
6
8
  import { join } from 'node:path';
@@ -34,11 +36,58 @@ export function autoOff(loomRoot) {
34
36
  /**
35
37
  * 获取 AUTO 状态描述。
36
38
  * @param {string} loomRoot — .loom 目录路径
37
- * @returns {{ on: boolean, since: string|null }}
39
+ * @returns {{ on: boolean, since: string|null, heartbeat: object|null }}
38
40
  */
39
41
  export function autoStatus(loomRoot) {
40
42
  const path = join(loomRoot, 'auto');
41
- if (!existsSync(path)) return { on: false, since: null };
43
+ if (!existsSync(path)) return { on: false, since: null, heartbeat: null };
42
44
  const since = readFileSync(path, 'utf-8').trim();
43
- return { on: true, since };
45
+ const heartbeat = readHeartbeat(loomRoot);
46
+ return { on: true, since, heartbeat };
47
+ }
48
+
49
+ /**
50
+ * 写入心跳——每次 guide 调用时记录当前状态。
51
+ * @param {string} loomRoot — .loom 目录路径
52
+ * @param {{ stage: string, stage_num: number, next_command: string, next_action: string }} info
53
+ */
54
+ export function writeHeartbeat(loomRoot, info) {
55
+ const heartbeat = {
56
+ timestamp: new Date().toISOString(),
57
+ stage: info.stage,
58
+ stage_num: info.stage_num,
59
+ next_command: info.next_command,
60
+ next_action: info.next_action,
61
+ };
62
+ writeFileSync(join(loomRoot, 'heartbeat.json'), JSON.stringify(heartbeat, null, 2), 'utf-8');
63
+ }
64
+
65
+ /**
66
+ * 读取心跳。
67
+ * @param {string} loomRoot — .loom 目录路径
68
+ * @returns {object|null}
69
+ */
70
+ export function readHeartbeat(loomRoot) {
71
+ const path = join(loomRoot, 'heartbeat.json');
72
+ if (!existsSync(path)) return null;
73
+ try {
74
+ return JSON.parse(readFileSync(path, 'utf-8'));
75
+ } catch {
76
+ return null;
77
+ }
78
+ }
79
+
80
+ /**
81
+ * 判断当前阶段是否需要人类 review。
82
+ * AUTO on 时:stage 1-3(哲学/愿景/架构)需要人类 review,stage 4+ 自动跑
83
+ * AUTO off 时:所有阶段都需要人类 review
84
+ * @param {string} loomRoot — .loom 目录路径
85
+ * @param {number} stageNum — 阶段号
86
+ * @returns {boolean} 是否需要人类 review
87
+ */
88
+ export function needsHumanReview(loomRoot, stageNum) {
89
+ const autoOn = isAutoOn(loomRoot);
90
+ if (!autoOn) return true; // AUTO off:所有阶段都需人类 review
91
+ // AUTO on:stage 1-3 需人类 review,stage 4+ 自动
92
+ return stageNum > 0 && stageNum < 4;
44
93
  }