@haaaiawd/loom 0.10.0 → 1.1.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/CHANGELOG.md +22 -0
- package/LICENSE +21 -0
- package/README.md +147 -74
- package/cli/bin/loom.js +428 -105
- package/cli/help/asset.md +36 -0
- package/cli/help/atelier.md +37 -0
- package/cli/help/capability.md +68 -0
- package/cli/help/concepts.md +100 -72
- package/cli/help/doctor.md +71 -121
- package/cli/help/loop.md +120 -135
- package/cli/help/patch.md +33 -0
- package/cli/help/preview.md +2 -1
- package/cli/help/proposals.md +21 -0
- package/cli/help/version.md +92 -16
- package/cli/help/workflow.md +101 -100
- package/cli/src/activate.js +349 -73
- package/cli/src/asset-library.js +384 -0
- package/cli/src/atelier.js +331 -0
- package/cli/src/capability-graph.js +351 -0
- package/cli/src/capability-proposals.js +225 -0
- package/cli/src/diagnostics.js +240 -44
- package/cli/src/guide.js +155 -40
- package/cli/src/init.js +58 -32
- package/cli/src/intent-draft.js +303 -0
- package/cli/src/intent-map.js +560 -54
- package/cli/src/patch.js +214 -0
- package/cli/src/philosophy.js +177 -154
- package/cli/src/preview-prompt.md +13 -6
- package/cli/src/preview.js +1 -0
- package/cli/src/shared/intent-ref.js +38 -0
- package/cli/src/shared/proof-reference.js +19 -0
- package/cli/src/shared/verification-method.js +32 -0
- package/cli/src/verify.js +202 -62
- package/cli/src/version.js +5 -4
- package/dimensions/AUTHORSHIP.md +45 -0
- package/dimensions/PART_DECOMPOSITION.md +42 -203
- package/dimensions/SEARCH_METHODOLOGY.md +101 -97
- package/dimensions/examples/AGENT_SYSTEM/README.md +1 -1
- package/dimensions/examples/CLI_TOOL/README.md +1 -1
- package/dimensions/universal/COLLABORATION_PHILOSOPHY.md +28 -77
- package/dimensions/universal/ENGINEERING_CREED.md +30 -74
- package/dimensions/universal/PRODUCT_PHILOSOPHY.md +32 -70
- package/meta/BASELINE.md +91 -276
- package/meta/INTENT_LOOP.md +289 -737
- package/meta/PHILOSOPHY_WEAVER.md +110 -343
- package/meta/ROLE_ACTIVATION.md +109 -267
- package/package.json +13 -7
- package/roles/architect.md +84 -111
- package/roles/forge.md +105 -126
- package/roles/keeper.md +109 -223
- package/roles/visionary.md +57 -86
- package/templates/ASSET_LIBRARY_MANIFEST_TEMPLATE.json +10 -0
- package/templates/ATELIER_RECORD_TEMPLATE.json +48 -0
- package/templates/CAPABILITY_BRIEF_TEMPLATE.md +34 -0
- package/templates/CAPABILITY_GRAPH_TEMPLATE.json +11 -0
- package/templates/INTENT_MAP_TEMPLATE.json +26 -10
- package/templates/PHILOSOPHY_TEMPLATE.md +44 -75
- package/templates/VISION_TEMPLATE.md +44 -67
package/cli/help/workflow.md
CHANGED
|
@@ -1,100 +1,101 @@
|
|
|
1
|
-
## LOOM 工作流
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
loom
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
-
|
|
86
|
-
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
##
|
|
96
|
-
|
|
97
|
-
-
|
|
98
|
-
-
|
|
99
|
-
-
|
|
100
|
-
|
|
1
|
+
## LOOM 工作流
|
|
2
|
+
|
|
3
|
+
## 0. 诊断
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
loom guide
|
|
7
|
+
loom context
|
|
8
|
+
```
|
|
9
|
+
|
|
10
|
+
只读探测使用 `loom guide --dry-run`。
|
|
11
|
+
|
|
12
|
+
## 1. Doctrine — Weaver
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
loom activate weaver
|
|
16
|
+
loom philosophy check
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
输出项目长期判断、卓越标准、决策原则、创作空间、反模式与 Evidence Map。
|
|
20
|
+
研究数量不设配额;只保留真实改变判断、能够追溯的证据。
|
|
21
|
+
|
|
22
|
+
## 2. Intent — Visionary
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
loom activate visionary
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
输出产品目标、成功图景、非目标与 Intent narrative。Visionary 不写 acceptance、DAG 或架构。
|
|
29
|
+
|
|
30
|
+
## 3. Capability Graph — Architect
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
loom activate architect
|
|
34
|
+
loom capability graph
|
|
35
|
+
loom capability frontier
|
|
36
|
+
loom capability coverage
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
在写 Intent Map 前,Architect 先把愿景展开为项目问题面、能力缺口、风险与证据。图谱不是待办列表:高影响节点必须继续展开、形成项目化 Capability Brief、编译为 Intent,或带理由地延后/排除。每个 Intent 必须回链图谱;只有边界清楚且可独立验证的结果才进入 Intent Map。
|
|
40
|
+
|
|
41
|
+
## 4. Contract — Architect
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
loom activate architect
|
|
45
|
+
loom intent validate
|
|
46
|
+
loom doctor
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Architect 产出系统边界、Intent DAG、完成契约和可选质量契约,并声明
|
|
50
|
+
`capability_needs` 与 `creative_scope`。
|
|
51
|
+
|
|
52
|
+
完成契约定义 **Reliability Floor**:做到什么才算可靠完成。
|
|
53
|
+
质量契约定义 **Distinctive Ceiling**:什么可观察差异让结果不止合格。
|
|
54
|
+
|
|
55
|
+
## 5. Quality Engine — Forge 与 Keeper
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
loom intent next
|
|
59
|
+
loom intent update <id> --status in_progress
|
|
60
|
+
loom activate forge --intent <id>
|
|
61
|
+
loom activate keeper --intent <id>
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Forge 编译 Expertise Pack,在 Quality Arena 中实现与比较。
|
|
65
|
+
Keeper 从当前磁盘事实和契约独立验证,不继承 Forge 的解释。
|
|
66
|
+
|
|
67
|
+
无质量契约时,四个基础维度通过即可闭合。存在质量契约时,额外验证
|
|
68
|
+
`quality_achievement`;声明相对提升时,在该维度中链接 Quality Proof:
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
loom verify pass <id> \
|
|
72
|
+
--summary "<具体证据>" \
|
|
73
|
+
--reproduction-command "<可复现命令>" \
|
|
74
|
+
--quality-proof "<基线、比较和稳定性证据的位置>"
|
|
75
|
+
|
|
76
|
+
loom intent done <id>
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
复杂或混合判定使用 `loom verify write --json-file <path>`。
|
|
80
|
+
|
|
81
|
+
## 6. Reflow
|
|
82
|
+
|
|
83
|
+
验证偏离时,不要把所有问题都扔回 Forge:
|
|
84
|
+
|
|
85
|
+
- Doctrine 不足 → Weaver
|
|
86
|
+
- 产品目标错误 → Visionary
|
|
87
|
+
- 问题面、能力缺口或 Intent 路由遗漏 → Architect 更新 Capability Graph
|
|
88
|
+
- 契约、边界或依赖错误 → Architect
|
|
89
|
+
- 专业判断或实现不足 → Forge
|
|
90
|
+
- 证据不足 → Keeper 补证或 `pending_human`
|
|
91
|
+
|
|
92
|
+
连续三次 `deviated` 自动升级为 `blocked`。所有当前 revision 和当前验证 epoch 的 Intent 都有最新 passed
|
|
93
|
+
记录,且没有 `needs_review`、`loom doctor` 没有 fatal/high 风险时,本轮收敛。
|
|
94
|
+
|
|
95
|
+
## 7. 演进
|
|
96
|
+
|
|
97
|
+
- Patch:不改变 Intent 语义,验证后记录 changelog。
|
|
98
|
+
- Minor:用 `loom intent add|revise` 创建 draft,经限定作用域的 Visionary/Architect 更新后 finalize。
|
|
99
|
+
- Major:Doctrine、北极星或主要架构边界改变,使用 `loom version new`。
|
|
100
|
+
|
|
101
|
+
原则只有一句:流程成本必须小于它降低的风险;质量声明必须小于等于它拥有的证据。
|
package/cli/src/activate.js
CHANGED
|
@@ -1,73 +1,349 @@
|
|
|
1
|
-
// activate —
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
1
|
+
// activate — compile a role- and intent-scoped Context Pack.
|
|
2
|
+
|
|
3
|
+
import { readFileSync, existsSync } from 'node:fs';
|
|
4
|
+
import { join } from 'node:path';
|
|
5
|
+
import { getLoomRoot } from './shared/paths.js';
|
|
6
|
+
import { getIntent, getNarrative } from './intent-map.js';
|
|
7
|
+
import { getIntentDraft } from './intent-draft.js';
|
|
8
|
+
import { getPhilosophy } from './philosophy.js';
|
|
9
|
+
import { getVerificationContract } from './verify.js';
|
|
10
|
+
import { extractMdSection } from './shared/md-utils.js';
|
|
11
|
+
import { compileCapabilityInputs } from './capability-graph.js';
|
|
12
|
+
import { getAtelierRecord } from './atelier.js';
|
|
13
|
+
|
|
14
|
+
const VALID_ROLES = ['weaver', 'visionary', 'architect', 'forge', 'keeper'];
|
|
15
|
+
|
|
16
|
+
const ROLE_FILES = {
|
|
17
|
+
weaver: 'meta/PHILOSOPHY_WEAVER.md',
|
|
18
|
+
visionary: 'roles/visionary.md',
|
|
19
|
+
architect: 'roles/architect.md',
|
|
20
|
+
forge: 'roles/forge.md',
|
|
21
|
+
keeper: 'roles/keeper.md',
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
const ROLE_PHILOSOPHY_FILES = {
|
|
25
|
+
visionary: ['PRODUCT_PHILOSOPHY.md', 'DECISION_RUBRIC.md'],
|
|
26
|
+
architect: ['ENGINEERING_CREED.md', 'DECISION_RUBRIC.md'],
|
|
27
|
+
forge: ['ENGINEERING_CREED.md'],
|
|
28
|
+
keeper: ['PRODUCT_PHILOSOPHY.md', 'DECISION_RUBRIC.md'],
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
const BASELINE_SUMMARY = [
|
|
32
|
+
'- B1:实质修改前理解真实结构,不创建平行体系。',
|
|
33
|
+
'- B2:秘密、环境值和可变配置不写死。',
|
|
34
|
+
'- B3:用户或系统可观察的行为具有显式契约。',
|
|
35
|
+
'- B4:重要且会影响未来的判断可追溯。',
|
|
36
|
+
'- B5:完成关联原始意图和当前 revision 证据;质量提升具有基线相对证据。',
|
|
37
|
+
].join('\n');
|
|
38
|
+
|
|
39
|
+
function section(title, body) {
|
|
40
|
+
const content = String(body || '').trim();
|
|
41
|
+
return `## ${title}\n\n${content || '无。'}`;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function readRole(role) {
|
|
45
|
+
const filePath = join(getLoomRoot(), ROLE_FILES[role]);
|
|
46
|
+
if (!existsSync(filePath)) throw new Error(`角色文件不存在: ${filePath}`);
|
|
47
|
+
return readFileSync(filePath, 'utf-8');
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function getVerificationMethod(intent) {
|
|
51
|
+
return intent?.verification_method || intent?._optional?.verification_method || null;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function resolveContractReference(versionDir, value, label) {
|
|
55
|
+
if (!value) return null;
|
|
56
|
+
if (typeof value !== 'string') return JSON.stringify(value, null, 2);
|
|
57
|
+
const match = value.trim().match(/^(?:see\s+)?([^#]+)#([\w-]+)$/i);
|
|
58
|
+
if (!match) return value;
|
|
59
|
+
const [, file, anchor] = match;
|
|
60
|
+
if (file.includes('/') || file.includes('\\') || file !== '05_VERIFICATION.md') {
|
|
61
|
+
throw new Error(`${label}引用必须位于 05_VERIFICATION.md: ${value}`);
|
|
62
|
+
}
|
|
63
|
+
const filePath = join(versionDir, file);
|
|
64
|
+
if (!existsSync(filePath)) throw new Error(`${label}引用的文件不存在: ${filePath}`);
|
|
65
|
+
return extractMdSection(readFileSync(filePath, 'utf-8'), anchor, label);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function compileEnvelope(role, intentId) {
|
|
69
|
+
const scope = intentId ? `仅 ${intentId}` : '当前角色的项目阶段';
|
|
70
|
+
const lines = [
|
|
71
|
+
`- role: ${role}`,
|
|
72
|
+
`- scope: ${scope}`,
|
|
73
|
+
'- 本 Context Pack 不会清除现有会话记忆。',
|
|
74
|
+
'- system、developer 与用户指令优先;项目事实冲突时报告,不静默混用。',
|
|
75
|
+
'- 只在当前角色权限和明确作用域内行动。',
|
|
76
|
+
];
|
|
77
|
+
if (role === 'keeper') {
|
|
78
|
+
lines.push('- Keeper 必须在新的 Agent thread 中运行;同一会话切换角色不构成独立验证。');
|
|
79
|
+
lines.push('- 无法获得独立上下文时降低声明,关键判断使用 pending_human。');
|
|
80
|
+
}
|
|
81
|
+
return lines.join('\n');
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function compileObjective(role, versionDir, intentId) {
|
|
85
|
+
if (!intentId) {
|
|
86
|
+
return {
|
|
87
|
+
body: role === 'weaver'
|
|
88
|
+
? '织造当前项目的 Project Doctrine。先读取真实项目与完整 BASELINE,不预写产品或架构。'
|
|
89
|
+
: `履行 ${role} 的当前项目阶段职责;未指定 Intent,不得自行选择并处理实现任务。`,
|
|
90
|
+
intent: null,
|
|
91
|
+
draft: null,
|
|
92
|
+
narrative: null,
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
if (role === 'visionary' || role === 'architect') {
|
|
97
|
+
const draft = getIntentDraft(versionDir, intentId);
|
|
98
|
+
const match = draft.narrative_ref.match(/^([^#]+)#([\w-]+)$/);
|
|
99
|
+
if (!match || match[1] !== '01_VISION.md') throw new Error(`draft narrative_ref 非法: ${draft.narrative_ref}`);
|
|
100
|
+
const narrative = extractMdSection(
|
|
101
|
+
readFileSync(join(versionDir, match[1]), 'utf-8'),
|
|
102
|
+
match[2],
|
|
103
|
+
'draft 意图叙事',
|
|
104
|
+
);
|
|
105
|
+
const visibleDraft = role === 'visionary'
|
|
106
|
+
? {
|
|
107
|
+
id: draft.id,
|
|
108
|
+
revision: draft.revision,
|
|
109
|
+
title: draft.title,
|
|
110
|
+
narrative_ref: draft.narrative_ref,
|
|
111
|
+
depends_on: draft.depends_on,
|
|
112
|
+
}
|
|
113
|
+
: draft;
|
|
114
|
+
return {
|
|
115
|
+
body: [
|
|
116
|
+
'只处理下面这个 draft。不要修改官方 Intent Map,不要处理其他 Intent,不要自行 finalize。',
|
|
117
|
+
'',
|
|
118
|
+
'### Draft',
|
|
119
|
+
'',
|
|
120
|
+
'```json',
|
|
121
|
+
JSON.stringify(visibleDraft, null, 2),
|
|
122
|
+
'```',
|
|
123
|
+
'',
|
|
124
|
+
'### Narrative',
|
|
125
|
+
'',
|
|
126
|
+
narrative,
|
|
127
|
+
].join('\n'),
|
|
128
|
+
intent: null,
|
|
129
|
+
draft,
|
|
130
|
+
narrative,
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
const intent = getIntent(versionDir, intentId);
|
|
135
|
+
if (['forge', 'keeper'].includes(role)) {
|
|
136
|
+
const unfinishedDependencies = intent.depends_on.filter((dependencyId) => getIntent(versionDir, dependencyId).status !== 'completed');
|
|
137
|
+
if (unfinishedDependencies.length) {
|
|
138
|
+
throw new Error(`Intent ${intentId} 的依赖尚未闭合: ${unfinishedDependencies.join(', ')}。不得通过 activate --intent 绕过执行顺序;先运行 loom intent next 或完成依赖 Intent。`);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
const narrative = getNarrative(versionDir, intentId);
|
|
142
|
+
const objectiveView = {
|
|
143
|
+
id: intent.id,
|
|
144
|
+
revision: intent.revision,
|
|
145
|
+
title: intent.title,
|
|
146
|
+
status: intent.status,
|
|
147
|
+
narrative_ref: intent.narrative_ref,
|
|
148
|
+
depends_on: intent.depends_on,
|
|
149
|
+
};
|
|
150
|
+
return {
|
|
151
|
+
body: [
|
|
152
|
+
'只实现或验证下面这个官方 Intent。不得加载或顺便处理其他 Intent。',
|
|
153
|
+
'',
|
|
154
|
+
'### Intent',
|
|
155
|
+
'',
|
|
156
|
+
'```json',
|
|
157
|
+
JSON.stringify(objectiveView, null, 2),
|
|
158
|
+
'```',
|
|
159
|
+
'',
|
|
160
|
+
'### Narrative',
|
|
161
|
+
'',
|
|
162
|
+
narrative,
|
|
163
|
+
].join('\n'),
|
|
164
|
+
intent,
|
|
165
|
+
draft: null,
|
|
166
|
+
narrative,
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
function compileInvariants(role, versionDir) {
|
|
171
|
+
const blocks = [];
|
|
172
|
+
const baselinePath = join(getLoomRoot(), 'meta/BASELINE.md');
|
|
173
|
+
blocks.push(role === 'weaver' ? readFileSync(baselinePath, 'utf-8') : BASELINE_SUMMARY);
|
|
174
|
+
if (versionDir) {
|
|
175
|
+
const projectBaseline = join(versionDir, '00_PHILOSOPHY', 'PROJECT_BASELINE.md');
|
|
176
|
+
if (existsSync(projectBaseline)) {
|
|
177
|
+
blocks.push(`### Project Baseline\n\n${readFileSync(projectBaseline, 'utf-8')}`);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
return blocks.join('\n\n');
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
function compileContracts(role, versionDir, objective) {
|
|
184
|
+
const subject = objective.intent || objective.draft;
|
|
185
|
+
if (!subject || role === 'visionary') {
|
|
186
|
+
return role === 'visionary'
|
|
187
|
+
? 'Visionary 只定义目标、非目标和 narrative;不要编写 acceptance 或架构。'
|
|
188
|
+
: '按当前角色 Output Contract 交付。';
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
const blocks = [];
|
|
192
|
+
if (subject.acceptance) {
|
|
193
|
+
const acceptance = objective.intent
|
|
194
|
+
? getVerificationContract(versionDir, subject.id)
|
|
195
|
+
: resolveContractReference(versionDir, subject.acceptance, 'draft 完成契约');
|
|
196
|
+
blocks.push(`### Acceptance / Reliability Floor\n\n${acceptance}`);
|
|
197
|
+
}
|
|
198
|
+
if (subject.quality_contract) {
|
|
199
|
+
blocks.push(
|
|
200
|
+
`### Quality Contract / Distinctive Ceiling\n\n` +
|
|
201
|
+
resolveContractReference(versionDir, subject.quality_contract, '质量契约'),
|
|
202
|
+
);
|
|
203
|
+
}
|
|
204
|
+
const verificationMethod = getVerificationMethod(subject);
|
|
205
|
+
blocks.push(`### Verification Method\n\n${verificationMethod || '未声明:Keeper 使用适当的静态检查;需要运行时或人类判断却缺少入口时回流 Architect。'}`);
|
|
206
|
+
const continuity = subject.continuity_required
|
|
207
|
+
? '此 Intent 已启用状态守恒门:通过前必须证明“旧状态 → 本轮操作 → 新状态”的完整序列中,未获明确授权删除或替换的既有价值、数据和可见结果仍被保留。'
|
|
208
|
+
: '默认不启用状态守恒门;若本 Intent 会变更既有用户数据、持久状态、迁移结果或既有工作流,Architect 必须把 continuity_required 设为 true,并在 acceptance 写出保留项与时序验证。';
|
|
209
|
+
blocks.push(
|
|
210
|
+
'### Completion Gate / Codex Goal Alignment\n\n' +
|
|
211
|
+
'将当前 Intent 视为本轮 Codex goal 的可闭合单元。goal 保持 active,直到结果达成、适用的状态守恒和可复现证据同时成立;goal/status 只是运行记录,不能替代验证证据。\n\n' +
|
|
212
|
+
continuity,
|
|
213
|
+
);
|
|
214
|
+
return blocks.join('\n\n');
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
function compileProjectJudgment(role, versionDir, objective) {
|
|
218
|
+
if (!versionDir || role === 'weaver') {
|
|
219
|
+
return role === 'weaver'
|
|
220
|
+
? '从用户目标、仓库事实与决策相关证据建立 Project Doctrine。'
|
|
221
|
+
: '当前版本目录不可用。';
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
const philosophyDir = join(versionDir, '00_PHILOSOPHY');
|
|
225
|
+
const blocks = [];
|
|
226
|
+
const missing = [];
|
|
227
|
+
const anchors = (objective.intent || objective.draft)?.philosophy_anchors || [];
|
|
228
|
+
|
|
229
|
+
if (anchors.length > 0) {
|
|
230
|
+
for (const anchor of anchors) {
|
|
231
|
+
blocks.push(`### ${anchor}\n\n${getPhilosophy(philosophyDir, anchor)}`);
|
|
232
|
+
}
|
|
233
|
+
} else {
|
|
234
|
+
for (const file of ROLE_PHILOSOPHY_FILES[role] || []) {
|
|
235
|
+
const filePath = join(philosophyDir, file);
|
|
236
|
+
if (!existsSync(filePath)) {
|
|
237
|
+
missing.push(file);
|
|
238
|
+
continue;
|
|
239
|
+
}
|
|
240
|
+
blocks.push(`### ${file}\n\n${readFileSync(filePath, 'utf-8')}`);
|
|
241
|
+
}
|
|
242
|
+
if (missing.length) {
|
|
243
|
+
blocks.push(
|
|
244
|
+
`### Context Warning\n\n缺少: ${missing.join(', ')}。` +
|
|
245
|
+
'不要用通用偏好伪造项目判断;回流 Weaver 或向用户索取必要决定。',
|
|
246
|
+
);
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
return blocks.join('\n\n');
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
function compileExpertiseInputs(role, versionDir, objective) {
|
|
253
|
+
const subject = objective.intent || objective.draft;
|
|
254
|
+
if (!subject || !['architect', 'forge', 'keeper'].includes(role)) {
|
|
255
|
+
return '当前阶段不编译任务级 Expertise Pack。';
|
|
256
|
+
}
|
|
257
|
+
const needs = Array.isArray(subject.capability_needs) ? subject.capability_needs : [];
|
|
258
|
+
const qualityStrategy = subject.quality_strategy ?? 'adaptive';
|
|
259
|
+
const lines = [
|
|
260
|
+
`- capability_needs: ${needs.length ? needs.join(', ') : '未声明;按当前任务发现必要能力'}`,
|
|
261
|
+
`- creative_scope: ${subject.creative_scope || '未声明;遵循最小完整干预'}`,
|
|
262
|
+
`- quality_strategy: ${qualityStrategy}`,
|
|
263
|
+
'- Skill、工具和资产名称只代表可发现入口;实际检查并加载后才进入 Expertise Pack。',
|
|
264
|
+
];
|
|
265
|
+
if (versionDir && objective.intent) {
|
|
266
|
+
const compiled = compileCapabilityInputs(versionDir, objective.intent.id);
|
|
267
|
+
if (!compiled.available) {
|
|
268
|
+
lines.push(`- Capability Graph: ${compiled.warnings.join(' ')}`);
|
|
269
|
+
} else if (compiled.nodes.length === 0) {
|
|
270
|
+
lines.push('- Capability Graph: 当前 Intent 没有回链节点;不得凭任务标题猜测能力,回流 Architect 补图谱或明确兼容原因。');
|
|
271
|
+
} else {
|
|
272
|
+
lines.push('- Capability Graph: 以下节点是本 Intent 的能力与风险输入:');
|
|
273
|
+
for (const node of compiled.nodes) {
|
|
274
|
+
lines.push(` - ${node.id} [${node.kind}/${node.impact}] ${node.title}${node.question ? ` — ${node.question}` : ''}`);
|
|
275
|
+
}
|
|
276
|
+
for (const brief of compiled.briefs) {
|
|
277
|
+
lines.push(`\n### Capability Brief: ${brief.node_id}\n\n${brief.content.trim()}`);
|
|
278
|
+
}
|
|
279
|
+
for (const warning of compiled.warnings) lines.push(`- Capability Graph warning: ${warning}`);
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
if (role === 'keeper') {
|
|
283
|
+
lines.push('- 不继承 Forge Expertise Pack;按契约独立准备验证能力。');
|
|
284
|
+
if (qualityStrategy === 'atelier') {
|
|
285
|
+
const record = getAtelierRecord(versionDir, subject.id);
|
|
286
|
+
lines.push(
|
|
287
|
+
'- 当前 Intent 使用 Atelier:以下 Record 是创作证据入口,不是通过结论。',
|
|
288
|
+
`\n### Atelier Record\n\n\`\`\`json\n${JSON.stringify(record, null, 2)}\n\`\`\``,
|
|
289
|
+
);
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
if (role === 'forge' && qualityStrategy === 'atelier') {
|
|
293
|
+
const authorshipPath = join(getLoomRoot(), 'dimensions', 'AUTHORSHIP.md');
|
|
294
|
+
if (!existsSync(authorshipPath)) {
|
|
295
|
+
throw new Error(`Atelier 方法文件不存在: ${authorshipPath}`);
|
|
296
|
+
}
|
|
297
|
+
lines.push(
|
|
298
|
+
'- 当前 Intent 进入 Atelier Path:先冻结基线并形成 Authorial Stance,再生成机制不同的候选。',
|
|
299
|
+
`- Atelier Record: \`09_ATELIER/${subject.id}.json\`;候选必须绑定 stance_revision。`,
|
|
300
|
+
'- Author 只能修正局部创作假设;结构性发现提交 provenance-backed Capability Graph proposal,由 Architect 裁决。',
|
|
301
|
+
`\n### Authorship Method\n\n${readFileSync(authorshipPath, 'utf-8').trim()}`,
|
|
302
|
+
);
|
|
303
|
+
}
|
|
304
|
+
return lines.join('\n');
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
function compileWorkingFacts(versionDir, objective) {
|
|
308
|
+
if (!versionDir) return '检查当前仓库、用户输入和可用工具。';
|
|
309
|
+
const subject = objective.intent || objective.draft;
|
|
310
|
+
const refs = [
|
|
311
|
+
'- architecture: `.loom/.../02_ARCHITECTURE.md`(只读取与当前决定相关部分)',
|
|
312
|
+
'- capability_graph: 从 `07_CAPABILITY_GRAPH.json` 查询与当前 Intent 回链的能力、风险与 Brief;不能用会话记忆补全未路由分支。',
|
|
313
|
+
'- artifacts: 从真实工作区检查,不从会话记忆猜测。',
|
|
314
|
+
];
|
|
315
|
+
const systemId = subject?._optional?.system_id || subject?.system_id;
|
|
316
|
+
if (systemId) refs.push(`- system_id: ${systemId}`);
|
|
317
|
+
if (subject?.quality_contract) refs.push('- baseline: 声明相对提升时,修改前证据必须在实现前保存。');
|
|
318
|
+
return refs.join('\n');
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
/**
|
|
322
|
+
* Compile a role-scoped Context Pack.
|
|
323
|
+
* @param {string} role
|
|
324
|
+
* @param {string | null} versionDir
|
|
325
|
+
* @param {string | null} intentId
|
|
326
|
+
*/
|
|
327
|
+
export function activateRole(role, versionDir, intentId = null) {
|
|
328
|
+
if (!VALID_ROLES.includes(role)) {
|
|
329
|
+
throw new Error(`未知角色: ${role}\n合法角色: ${VALID_ROLES.join(', ')}`);
|
|
330
|
+
}
|
|
331
|
+
if (intentId && !versionDir) throw new Error('--intent 需要当前 LOOM 版本');
|
|
332
|
+
if (intentId && !['visionary', 'architect', 'forge', 'keeper'].includes(role)) {
|
|
333
|
+
throw new Error(`角色 ${role} 不支持 --intent;draft 用 visionary/architect,官方 Intent 用 forge/keeper`);
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
const objective = compileObjective(role, versionDir, intentId);
|
|
337
|
+
const parts = [
|
|
338
|
+
'# LOOM Context Pack',
|
|
339
|
+
section('1. Execution Envelope', compileEnvelope(role, intentId)),
|
|
340
|
+
section('2. Active Objective', objective.body),
|
|
341
|
+
section('3. Hard Invariants', compileInvariants(role, versionDir)),
|
|
342
|
+
section('4. Success Contracts', compileContracts(role, versionDir, objective)),
|
|
343
|
+
section('5. Project Judgment', compileProjectJudgment(role, versionDir, objective)),
|
|
344
|
+
section('6. Expertise Inputs', compileExpertiseInputs(role, versionDir, objective)),
|
|
345
|
+
section('7. Working Facts', compileWorkingFacts(versionDir, objective)),
|
|
346
|
+
section('8. Role Contract / Output / Reflow / Stop', readRole(role)),
|
|
347
|
+
];
|
|
348
|
+
return `${parts.join('\n\n---\n\n')}\n`;
|
|
349
|
+
}
|