@haaaiawd/loom 1.0.0 → 1.2.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 +39 -0
- package/EXTERNAL_ACQUISITION_DESIGN.md +143 -0
- package/README.md +71 -30
- package/cli/bin/loom.js +176 -7
- package/cli/help/asset.md +36 -0
- package/cli/help/atelier.md +37 -0
- package/cli/help/capability.md +73 -0
- package/cli/help/concepts.md +13 -3
- package/cli/help/expertise.md +51 -0
- package/cli/help/loop.md +4 -2
- package/cli/help/proposals.md +21 -0
- package/cli/help/workflow.md +26 -4
- package/cli/src/activate.js +85 -2
- package/cli/src/asset-library.js +384 -0
- package/cli/src/atelier.js +331 -0
- package/cli/src/capability-graph.js +416 -0
- package/cli/src/capability-proposals.js +225 -0
- package/cli/src/diagnostics.js +132 -3
- package/cli/src/expertise-pack.js +336 -0
- package/cli/src/guide.js +148 -21
- package/cli/src/init.js +11 -5
- package/cli/src/intent-map.js +20 -0
- package/cli/src/verify.js +35 -1
- package/dimensions/AUTHORSHIP.md +45 -0
- package/meta/INTENT_LOOP.md +59 -5
- package/meta/ROLE_ACTIVATION.md +17 -6
- package/package.json +11 -5
- package/roles/architect.md +24 -11
- package/roles/forge.md +30 -5
- package/roles/keeper.md +12 -0
- package/templates/ASSET_LIBRARY_MANIFEST_TEMPLATE.json +10 -0
- package/templates/ATELIER_RECORD_TEMPLATE.json +48 -0
- package/templates/CAPABILITY_BRIEF_TEMPLATE.md +35 -0
- package/templates/CAPABILITY_GRAPH_TEMPLATE.json +11 -0
- package/templates/EXPERTISE_PACK_TEMPLATE.json +22 -0
- package/templates/INTENT_MAP_TEMPLATE.json +2 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 1.2.0 — 2026-07-31
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
|
|
7
|
+
- External Acquisition Gate:Capability Graph 只声明 `acquisition_mode`,Forge 按当前
|
|
8
|
+
Intent 信号派生 Search Plan,并实际通过 Skill registry、网络、官方文档或研究资料获取信息。
|
|
9
|
+
- revision-scoped Expertise Pack 与 `loom expertise init|get|validate`,以来源、检索证据和
|
|
10
|
+
Capability Capsules 形成类似 Skill 的项目化核心信息组,但不复制或内置第三方内容。
|
|
11
|
+
- `guide`、Forge/Keeper activation、`verify pass`、`intent done` 与 `doctor` 的外部能力
|
|
12
|
+
获取强门;passed 记录绑定当前 Pack 内容摘要,Keeper 必须独立重开关键来源。
|
|
13
|
+
|
|
14
|
+
### Compatibility
|
|
15
|
+
|
|
16
|
+
- 中低影响 capability 默认为 `adaptive`;高影响 capability 未显式豁免时,以及任意 capability
|
|
17
|
+
显式声明 `external_required` 时启用持久化强门。
|
|
18
|
+
- `project_only` 保留内部协议与机械任务路径,但必须说明 `acquisition_rationale`。
|
|
19
|
+
|
|
20
|
+
## 1.1.0 — 2026-07-30
|
|
21
|
+
|
|
22
|
+
### Added
|
|
23
|
+
|
|
24
|
+
- Capability Graph、Capability Brief 与 coverage/compile 命令,将项目问题面、能力缺口、
|
|
25
|
+
风险和证据显式回链到 Intent。
|
|
26
|
+
- provenance-backed Capability Graph Proposal 工作流,由 Architect 裁决新发现对 Graph、
|
|
27
|
+
Intent、acceptance 或版本边界的影响。
|
|
28
|
+
- 版本化 Asset Library,校验来源、作者、许可、本地哈希、批准状态与 evidence 双向引用。
|
|
29
|
+
- Authorship System:第五种认知职能 Author、Identity Compiler、可选 Atelier Path,以及
|
|
30
|
+
`loom atelier init|get|validate`。
|
|
31
|
+
- Atelier Record 的 `intent_revision`、`stance_revision`、候选、修正、基线与选择证据校验。
|
|
32
|
+
- Keeper/Quality Proof 的 Atelier 闭合门;`doctor`、`guide` 与 `intent done` 可识别缺失、
|
|
33
|
+
过期或未绑定的创作证据。
|
|
34
|
+
|
|
35
|
+
### Compatibility
|
|
36
|
+
|
|
37
|
+
- 旧 Intent 缺少 `quality_strategy` 时等价于 `adaptive`,不会创建 Atelier Record。
|
|
38
|
+
- Atelier 是按需深路径,不增加角色、Intent 状态或验证维度。
|
|
39
|
+
- 旧项目缺少 Capability Graph 时保留兼容诊断,可在后续架构修订中迁移。
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
# External Acquisition Gate — 来源化能力网络设计
|
|
2
|
+
|
|
3
|
+
> 状态:Implemented
|
|
4
|
+
> 目标:阻止 AI 在专业能力不足时闭门生成,并把真实外部检索编译成当前 Intent 可使用、可追溯、会随 revision 失效的核心信息组。
|
|
5
|
+
|
|
6
|
+
## 1. 问题
|
|
7
|
+
|
|
8
|
+
LOOM 已经能识别任务需要哪些能力,但“识别能力”不等于“获得能力”。如果 Forge 只根据模型已有知识临时生成一段设计原则,它仍可能做出结构正确、审美普通的结果,并把自洽误当成专业。
|
|
9
|
+
|
|
10
|
+
本设计把能力链拆成四个不同事实:
|
|
11
|
+
|
|
12
|
+
1. Capability Graph:项目为什么需要某项能力。
|
|
13
|
+
2. Search Plan:本轮要用什么问题和关键词去外部寻找。
|
|
14
|
+
3. Expertise Pack:实际打开来源后,哪些规则、工作流、判断门和失败模式可用于本 Intent。
|
|
15
|
+
4. Quality Proof:这些判断是否真的让结果胜过基线。
|
|
16
|
+
|
|
17
|
+
Graph 不保存网站、Skill 名称或固定关键词;Pack 不复制第三方 Skill 或网页正文。
|
|
18
|
+
|
|
19
|
+
## 2. 核心不变量
|
|
20
|
+
|
|
21
|
+
- AI 可以生成检索计划,不能把自己生成的内容登记为外部专业知识。
|
|
22
|
+
- `external_required` 能力必须实际使用 Skill registry、网络、官方文档或研究资料。
|
|
23
|
+
- 搜索结果标题、未打开的摘要、模型记忆和“行业通常如此”都不是来源。
|
|
24
|
+
- 每个 Capability Capsule 必须直接引用至少一个已打开、可回查的外部来源。
|
|
25
|
+
- Pack 绑定 `intent_revision`;Intent 修订后旧 Pack 自动失效。
|
|
26
|
+
- Forge 可以使用 Pack;Keeper 不继承 Forge 的结论,必须重新打开关键来源。
|
|
27
|
+
- 来源化不等于正确。CLI 证明结构与追溯,Keeper 证明来源是否真的支持判断。
|
|
28
|
+
|
|
29
|
+
## 3. 触发模型
|
|
30
|
+
|
|
31
|
+
Capability 节点可选:
|
|
32
|
+
|
|
33
|
+
```json
|
|
34
|
+
{
|
|
35
|
+
"acquisition_mode": "adaptive | external_required | project_only",
|
|
36
|
+
"acquisition_rationale": "project_only 时必填"
|
|
37
|
+
}
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
有效模式按以下顺序计算:
|
|
41
|
+
|
|
42
|
+
1. Graph 显式声明的模式优先。
|
|
43
|
+
2. 未声明时,高影响 capability 自动提升为 `external_required`。
|
|
44
|
+
3. 中低影响 capability 默认为 `adaptive`。
|
|
45
|
+
|
|
46
|
+
`project_only` 只适合未公开内部协议、纯机械迁移等外部知识不会改变做法的任务,必须说明理由。外部交付依赖与只读研究访问是两件事:允许检索资料,不等于允许把外部服务写进产品架构。
|
|
47
|
+
|
|
48
|
+
## 4. 运行流程
|
|
49
|
+
|
|
50
|
+
```text
|
|
51
|
+
Capability Graph
|
|
52
|
+
→ compile acquisition requirement
|
|
53
|
+
→ derive Search Plan from project signals
|
|
54
|
+
→ perform real external retrieval
|
|
55
|
+
→ synthesize Capability Capsules
|
|
56
|
+
→ validate Expertise Pack
|
|
57
|
+
→ Author / Atelier / implementation
|
|
58
|
+
→ independent Keeper source check
|
|
59
|
+
→ passed record binds current Pack
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
搜索词由 Forge 根据以下信号动态派生:
|
|
63
|
+
|
|
64
|
+
- capability question 与 Brief;
|
|
65
|
+
- Intent narrative、quality contract 和 creative scope;
|
|
66
|
+
- 当前媒介、宿主、技术与许可约束;
|
|
67
|
+
- 基线中已经观察到的具体缺口;
|
|
68
|
+
- Authorial Stance 尚未解决的机制问题。
|
|
69
|
+
|
|
70
|
+
关键词属于本轮工作证据,不回写 Graph。这样 LOOM 不会把“网页设计等于某几个灵感站”固化成框架偏见。
|
|
71
|
+
|
|
72
|
+
## 5. Expertise Pack
|
|
73
|
+
|
|
74
|
+
位置:
|
|
75
|
+
|
|
76
|
+
```text
|
|
77
|
+
.loom/vN/10_EXPERTISE_PACKS/<intent-id>.json
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
Pack 包含:
|
|
81
|
+
|
|
82
|
+
- `search_plan`:决策问题、项目信号、派生查询、约束和停止条件;
|
|
83
|
+
- `sources`:类型、权威层级、HTTPS 定位、获取时间、选择理由和已打开证据;
|
|
84
|
+
- `capsules`:专业问题、适用时机、规则、工作流、判断门、失败模式、验证信号和来源引用;
|
|
85
|
+
- `required_capability_refs` 与 `intent_revision`;
|
|
86
|
+
- `status: draft | ready | blocked`。
|
|
87
|
+
|
|
88
|
+
Capability Capsule 是“类似 Skill 的核心信息组”,但它有三个刻意限制:
|
|
89
|
+
|
|
90
|
+
1. 只服务当前 Intent,不假装是通用知识;
|
|
91
|
+
2. 只保存项目化综合,不复制来源内容;
|
|
92
|
+
3. 未经多个真实任务和 Quality Proof 支持,不自动晋升为 Skill 或 Doctrine。
|
|
93
|
+
|
|
94
|
+
## 6. Author 与自我更正
|
|
95
|
+
|
|
96
|
+
外部获取发生在 Author/Atelier 之前。Authorial Stance 必须建立在已经来源化的机制和项目事实之上,而不是用人格、风格词或模型偏好代替研究。
|
|
97
|
+
|
|
98
|
+
自我更正分三层:
|
|
99
|
+
|
|
100
|
+
- Capsule 解释错误、来源不支持规则:修正 Pack,重新验证;如果已 passed,必须由 Keeper 重验。
|
|
101
|
+
- 当前构图、措辞、动效或候选选择失效:写入 Atelier `corrections[]`,递增 `stance_revision`。
|
|
102
|
+
- 出现新的用户结果、约束、风险或能力缺口:提交 Capability Graph proposal,由 Architect 裁决。
|
|
103
|
+
|
|
104
|
+
Author 不能修改 Graph 后继续自证,也不能用一次局部修正把任务长期知识化。
|
|
105
|
+
|
|
106
|
+
## 7. 强门与验证
|
|
107
|
+
|
|
108
|
+
以下入口共同阻止绕过:
|
|
109
|
+
|
|
110
|
+
- `loom guide`:优先引导创建或补齐 Pack;
|
|
111
|
+
- `loom activate forge --intent <id>`:Pack 未 ready 时显示 OPEN 门,只允许勘察、基线和检索;
|
|
112
|
+
- `loom expertise validate <id>`:检查 revision、真实外部来源、直接引用和 Capsule 完整性;
|
|
113
|
+
- `loom verify pass`:强门未闭合时拒绝 passed,并把当前 Pack 的内容摘要绑定到验证记录;
|
|
114
|
+
- `loom intent done`:拒绝未绑定、内容摘要变化或已经过期的 Pack;
|
|
115
|
+
- `loom doctor`:报告缺失、失效和 passed 绑定漂移;
|
|
116
|
+
- Keeper Context Pack:只给出证据入口,不注入 Forge 的 Capsule 结论。
|
|
117
|
+
|
|
118
|
+
## 8. 搜索预算与停止条件
|
|
119
|
+
|
|
120
|
+
LOOM 不规定固定网站数量,也不鼓励无限浏览。每个 Search Plan 必须写停止条件。通常在以下条件同时成立时停止:
|
|
121
|
+
|
|
122
|
+
- 每个 required capability 都有直接来源化 Capsule;
|
|
123
|
+
- 来源足以回答当前决策问题,而不只是提供视觉相似物;
|
|
124
|
+
- 已能写出可执行的判断门、失败模式和验证信号;
|
|
125
|
+
- 新来源只重复已有机制,不再改变候选或验证方法。
|
|
126
|
+
|
|
127
|
+
如果来源互相冲突、关键资料不可访问或许可不清,Pack 应进入 `blocked`,而不是让模型补齐空白。
|
|
128
|
+
|
|
129
|
+
## 9. 与现有系统的去重
|
|
130
|
+
|
|
131
|
+
- Capability Brief 负责“项目问题与获取边界”;Pack 负责“本轮实际获得了什么”。二者不重复。
|
|
132
|
+
- Authorship 负责“基于材料做什么独特选择”;Pack 负责“选择前有哪些可信材料”。二者不重复。
|
|
133
|
+
- Atelier Record 保存候选与修正;Pack 保存外部能力证据。二者不合并。
|
|
134
|
+
- Quality Proof 证明结果提升;Pack 只证明专业判断有来源。来源不能替代结果。
|
|
135
|
+
- Doctrine 保存长期项目判断;Pack 默认短命。未经重复外部结果支持,不进入 Doctrine。
|
|
136
|
+
|
|
137
|
+
## 10. 非目标
|
|
138
|
+
|
|
139
|
+
- 不在 LOOM 仓库内安装、镜像或维护第三方 Skill。
|
|
140
|
+
- 不建立固定网站白名单或 UI 专用关键词表。
|
|
141
|
+
- 不声称只要检索就能突破基础模型的所有智能边界。
|
|
142
|
+
- 不用来源数量、星标或流行度替代任务适配性。
|
|
143
|
+
- 不让 CLI 自动编造 Capsule;CLI 只建模、校验、编译和阻断。
|
package/README.md
CHANGED
|
@@ -15,8 +15,9 @@ LOOM 是一个**哲学驱动的 Agent 质量框架**,核心理念:
|
|
|
15
15
|
LOOM 的核心机制:
|
|
16
16
|
1. **Project Doctrine** 从项目事实中形成长期判断,而不是套用规范模板
|
|
17
17
|
2. **Intent + Contract** 同时定义可靠完成的底线与可选的质量上限
|
|
18
|
-
3. **Expertise Compiler**
|
|
18
|
+
3. **Expertise Compiler** 为当前任务临时组装领域、品味、作者、批评与验证能力
|
|
19
19
|
4. **Quality Arena + Quality Proof** 用机制不同的候选和独立证据支撑质量提升
|
|
20
|
+
5. **Authorship + Atelier** 在真正需要创作判断时形成作者命题、媒介原型与可审计选择
|
|
20
21
|
|
|
21
22
|
---
|
|
22
23
|
|
|
@@ -27,7 +28,10 @@ LOOM 的核心机制:
|
|
|
27
28
|
| **哲学** | 项目的价值观和工程原则——为什么存在、什么不做、冲突时谁优先。由 Weaver 从真实思想体系织造,不是模板填空 |
|
|
28
29
|
| **Intent** | 一个意图单元——不是"做什么"(任务),是"为什么做"(意图)。每个 Intent 有验收契约,Keeper 据此判定实现是否忠实 |
|
|
29
30
|
| **Intent Map** | 所有 Intent 的依赖图(JSON)。Architect 绘制,定义拓扑序和依赖关系 |
|
|
30
|
-
| **
|
|
31
|
+
| **Capability Graph** | 在 Intent 前展开项目问题面、能力缺口、风险和证据;高影响节点必须路由,并回链到 Intent |
|
|
32
|
+
| **Expertise Pack** | Forge 通过真实外部检索为当前 Intent 编译的来源化核心信息组;绑定 revision,不成为永久规则 |
|
|
33
|
+
| **Authorial Stance** | 针对单个 Intent 编译的创作命题、选择、拒绝项、媒介语法和验证视角,不是 Persona 扮演 |
|
|
34
|
+
| **Atelier Path** | 可选创作深路径:冻结基线、形成机制不同候选、比较或保留原版,并把证据写入唯一 Atelier Record |
|
|
31
35
|
| **Quality Arena** | 以基线和机制不同候选进行探索、比较、实现与观察 |
|
|
32
36
|
| **Quality Proof** | Keeper 独立验证完成与质量声明,证据不足时不允许宣称提升 |
|
|
33
37
|
| **Intent Loop** | 选择 → 编译专业能力 → 实现/比较 → 独立证明 → 闭合或回流 |
|
|
@@ -58,9 +62,22 @@ Keeper 验证(基础四维;有质量契约时增加 quality_achievement,
|
|
|
58
62
|
|
|
59
63
|
---
|
|
60
64
|
|
|
61
|
-
## 快速开始
|
|
62
|
-
|
|
63
|
-
###
|
|
65
|
+
## 快速开始
|
|
66
|
+
|
|
67
|
+
### 安装
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
npm install --global @haaaiawd/loom
|
|
71
|
+
loom --version
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
也可以不做全局安装,直接运行:
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
npx @haaaiawd/loom --help
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### 步骤 0:诊断当前阶段
|
|
64
81
|
|
|
65
82
|
```bash
|
|
66
83
|
loom guide
|
|
@@ -119,9 +136,9 @@ loom activate architect
|
|
|
119
136
|
```
|
|
120
137
|
|
|
121
138
|
**输入**:愿景文档 + 哲学文档
|
|
122
|
-
**Architect
|
|
123
|
-
**产出**:`.loom/v1/02_ARCHITECTURE.md` + `.loom/v1/04_INTENT_MAP.json`
|
|
124
|
-
|
|
139
|
+
**Architect 会做什么**:先展开 Capability Graph → 设计系统边界 → 绘制 Intent Map → 定义完成契约、按需的质量契约与专业能力需求
|
|
140
|
+
**产出**:`.loom/v1/07_CAPABILITY_GRAPH.json` + `07_CAPABILITY_BRIEFS/` + `.loom/v1/02_ARCHITECTURE.md` + `.loom/v1/04_INTENT_MAP.json`
|
|
141
|
+
**怎么判断合格**:高影响图谱节点都有路由、Intent 都可回链到图谱,完成契约可观察,质量契约可比较,依赖无环
|
|
125
142
|
**下一步**:进入 Intent Loop
|
|
126
143
|
|
|
127
144
|
### 步骤 5:进入 Intent Loop
|
|
@@ -134,6 +151,10 @@ loom intent update INT-001 --status in_progress
|
|
|
134
151
|
# Forge 编译专业能力并实现
|
|
135
152
|
loom activate forge --intent INT-001
|
|
136
153
|
|
|
154
|
+
# 仅当 Architect 为该 Intent 声明 quality_strategy=atelier
|
|
155
|
+
loom atelier init INT-001
|
|
156
|
+
loom atelier validate INT-001
|
|
157
|
+
|
|
137
158
|
# Keeper 独立形成 Quality Proof
|
|
138
159
|
loom activate keeper --intent INT-001
|
|
139
160
|
loom verify contract INT-001 # 查看验收契约
|
|
@@ -189,7 +210,7 @@ Agent 在用户说"看看进度 / 打开 preview / 看全局"时,先跑 `loom
|
|
|
189
210
|
| `loom preview status` | 检查 `loom-preview.html` 是否存在、是否新鲜 |
|
|
190
211
|
| `loom preview --regen` | 输出提示词,让 Agent 重写 HTML 预览 |
|
|
191
212
|
| `loom preview --stale` | 强行打开过期预览 |
|
|
192
|
-
| `loom help <topic>` |
|
|
213
|
+
| `loom help <topic>` | 分层指南(含 workflow、concepts、loop、capability、atelier、version、patch、doctor、preview) |
|
|
193
214
|
| `loom version list` | 列出所有版本(* 标记当前) |
|
|
194
215
|
| `loom version new` | 创建新版本 + 自动切换(Major 升级) |
|
|
195
216
|
| `loom version use <v>` | 切换当前版本 |
|
|
@@ -205,6 +226,11 @@ Agent 在用户说"看看进度 / 打开 preview / 看全局"时,先跑 `loom
|
|
|
205
226
|
| `loom intent revise <id> --reason <text>` | 创建修订 draft 并报告反向依赖 |
|
|
206
227
|
| `loom intent draft <id>` | 查看 draft |
|
|
207
228
|
| `loom intent finalize <id> [--review <ids> --unaffected <ids>]` | 校验 draft 并原子更新官方 Map/topo_order;修订时必须分类全部下游影响 |
|
|
229
|
+
| `loom capability graph\|frontier\|get\|coverage\|compile` | 查看能力图谱、未路由前沿、覆盖缺口和当前 Intent 的能力编译输入 |
|
|
230
|
+
| `loom capability proposal list\|get\|submit\|decide\|close` | 以 provenance 提交新发现,并由 Architect 裁决和闭合 |
|
|
231
|
+
| `loom asset import\|list\|search\|get\|validate` | 管理带来源、许可、哈希、批准状态与 evidence 回链的本地素材 |
|
|
232
|
+
| `loom expertise init\|get\|validate <id>` | 创建和校验 revision-scoped Search Plan、外部来源与 Capability Capsules |
|
|
233
|
+
| `loom atelier init\|get\|validate <id>` | 为显式 Atelier Intent 创建、读取和校验创作记录 |
|
|
208
234
|
| `loom intent deprecate <id> --reason <text>` | 只读评估当前版本弃用影响;加 `--confirm` 并完整分类依赖方后原子写入 |
|
|
209
235
|
| `loom intent narrative <id>` | Intent 意图叙事 |
|
|
210
236
|
| `loom intent trace <id>` | Intent 完整追溯链(依赖+验证+哲学+叙事) |
|
|
@@ -241,27 +267,34 @@ LOOM/
|
|
|
241
267
|
│ ├── INTENT_LOOP.md Loop 控制流 + Intent Map + Verification 底线
|
|
242
268
|
│ └── PHILOSOPHY_WEAVER.md 哲学织造器规范
|
|
243
269
|
│
|
|
244
|
-
├── dimensions/ 哲学维度库(Weaver 的弹药库)
|
|
245
|
-
│ ├── SEARCH_METHODOLOGY.md 检索方法论(怎么找到优质思想)
|
|
246
|
-
│ ├──
|
|
270
|
+
├── dimensions/ 哲学维度库(Weaver 的弹药库)
|
|
271
|
+
│ ├── SEARCH_METHODOLOGY.md 检索方法论(怎么找到优质思想)
|
|
272
|
+
│ ├── AUTHORSHIP.md Atelier 启用时加载的作者性方法
|
|
273
|
+
│ ├── universal/ 通用层:产品/工程/协作(按需填充)
|
|
247
274
|
│ ├── domain/ 领域层:UX/游戏/后端/AI(按需填充)
|
|
248
275
|
│ └── crosscutting/ 交叉层:性能/安全/心理学/增长(按需填充)
|
|
249
276
|
│
|
|
250
277
|
├── roles/ 角色原型定义
|
|
251
278
|
│ ├── visionary.md 远见者——定义愿景,织造意图叙事
|
|
252
|
-
│ ├── architect.md
|
|
279
|
+
│ ├── architect.md 建筑师——展开图谱,设计系统,绘制 Intent Map
|
|
253
280
|
│ ├── forge.md 锻造师——在哲学约束下自主实现
|
|
254
281
|
│ └── keeper.md 守护者——验证意图忠实度
|
|
255
282
|
│
|
|
256
283
|
├── cli/ CLI 传感器层(Agent 通过 CLI 访问磁盘数据)
|
|
257
|
-
│ ├── bin/loom.js 命令入口
|
|
258
|
-
│ ├── src/ 核心库(intent-map /
|
|
259
|
-
│
|
|
284
|
+
│ ├── bin/loom.js 命令入口
|
|
285
|
+
│ ├── src/ 核心库(intent-map / capability / atelier / verify)
|
|
286
|
+
│ ├── help/ Agent 可直接读取的工作流指南
|
|
287
|
+
│ └── test/ 端到端测试
|
|
260
288
|
│
|
|
261
289
|
└── templates/ 项目级起点骨架
|
|
262
290
|
├── PHILOSOPHY_TEMPLATE.md 哲学文档起点
|
|
263
291
|
├── VISION_TEMPLATE.md 愿景文档起点
|
|
264
|
-
|
|
292
|
+
├── INTENT_MAP_TEMPLATE.json Intent Map 起点
|
|
293
|
+
├── CAPABILITY_GRAPH_TEMPLATE.json Capability Graph 起点
|
|
294
|
+
├── CAPABILITY_BRIEF_TEMPLATE.md Capability Brief 起点
|
|
295
|
+
├── ASSET_LIBRARY_MANIFEST_TEMPLATE.json Asset Library 起点
|
|
296
|
+
├── EXPERTISE_PACK_TEMPLATE.json 外部能力获取记录起点
|
|
297
|
+
└── ATELIER_RECORD_TEMPLATE.json Atelier Record 起点
|
|
265
298
|
```
|
|
266
299
|
|
|
267
300
|
### 文档导航
|
|
@@ -279,8 +312,11 @@ LOOM/
|
|
|
279
312
|
| Forge 做什么 | `roles/forge.md` |
|
|
280
313
|
| Keeper 做什么 | `roles/keeper.md` |
|
|
281
314
|
| 哲学文档长什么样 | `templates/PHILOSOPHY_TEMPLATE.md` |
|
|
282
|
-
| 愿景文档长什么样 | `templates/VISION_TEMPLATE.md` |
|
|
283
|
-
|
|
|
315
|
+
| 愿景文档长什么样 | `templates/VISION_TEMPLATE.md` |
|
|
316
|
+
| Capability Graph 与 Brief 长什么样 | `cli/help/capability.md`、`templates/CAPABILITY_GRAPH_TEMPLATE.json` |
|
|
317
|
+
| 为什么必须外部检索、Expertise Pack 怎么闭合 | `cli/help/expertise.md`、`EXTERNAL_ACQUISITION_DESIGN.md` |
|
|
318
|
+
| Author 与 Atelier 怎么工作 | `cli/help/atelier.md`、`dimensions/AUTHORSHIP.md` |
|
|
319
|
+
| Intent Map 长什么样 | `templates/INTENT_MAP_TEMPLATE.json` |
|
|
284
320
|
| 怎么搜索高质量参考 | `dimensions/SEARCH_METHODOLOGY.md` |
|
|
285
321
|
|
|
286
322
|
---
|
|
@@ -295,8 +331,9 @@ LOOM/
|
|
|
295
331
|
**Agent 生成的**(每个项目跑出来的,厚而灵活):
|
|
296
332
|
- 哲学文档体系(Weaver 决定要几个、多详细)
|
|
297
333
|
- 愿景文档(带意图叙事)
|
|
298
|
-
- 架构文档(根据哲学决定结构)
|
|
299
|
-
-
|
|
334
|
+
- 架构文档(根据哲学决定结构)
|
|
335
|
+
- Capability Graph 与按需生成的 Capability Brief
|
|
336
|
+
- Intent Map(意图依赖图,JSON)
|
|
300
337
|
- 验证契约和验证记录
|
|
301
338
|
|
|
302
339
|
**我们的规范是元规范**——规范"怎么生成规范",不直接规范"规范长什么样"。
|
|
@@ -308,7 +345,7 @@ LOOM/
|
|
|
308
345
|
| 角色 | 原型 | 职责 | 激活时机 |
|
|
309
346
|
|---|---|---|---|
|
|
310
347
|
| **Visionary** 远见者 | 产品联合创始人 | 定义愿景,织造意图叙事 | 项目启动 |
|
|
311
|
-
| **Architect** 建筑师 | 系统建筑师 |
|
|
348
|
+
| **Architect** 建筑师 | 系统建筑师 | 展开 Capability Graph,设计系统,绘制 Intent Map | Visionary 完成后 |
|
|
312
349
|
| **Forge** 锻造师 | 高级工程师 | 在哲学约束下自主实现 | Intent Loop 实现阶段 |
|
|
313
350
|
| **Keeper** 守护者 | 独立验证者(独立激活) | 从磁盘事实验证意图与质量主张 | Intent Loop 验证阶段 |
|
|
314
351
|
|
|
@@ -360,11 +397,13 @@ Agent 在项目中生成的文档结构:
|
|
|
360
397
|
├── 01_VISION.md Visionary 产出(带意图叙事)
|
|
361
398
|
├── 02_ARCHITECTURE.md Architect 产出
|
|
362
399
|
├── 03_DECISIONS/ 架构决策记录
|
|
363
|
-
├── 04_INTENT_MAP.json 意图依赖图(DAG)
|
|
400
|
+
├── 04_INTENT_MAP.json 意图依赖图(DAG)
|
|
364
401
|
├── 05_VERIFICATION.md 每个 Intent 的验证契约
|
|
365
402
|
├── 06_CHANGELOG.json Patch 变更记录(唯一权威来源)
|
|
366
403
|
├── 06_CHANGELOG.md 确定性生成的只读投影
|
|
367
|
-
|
|
404
|
+
├── 07_CAPABILITY_GRAPH.json 问题面、能力缺口、风险、证据与 Intent 回链
|
|
405
|
+
├── 07_CAPABILITY_BRIEFS/ 按需生成的项目化能力 Brief
|
|
406
|
+
└── verifications/ Keeper 的验证记录
|
|
368
407
|
├── INT-001.json
|
|
369
408
|
├── INT-001.md
|
|
370
409
|
└── ...
|
|
@@ -393,11 +432,12 @@ Agent 通过 **CLI 访问** JSON,不直接读文件——省 token、更高效
|
|
|
393
432
|
2. Visionary 定义愿景
|
|
394
433
|
→ 基于哲学写愿景 → 每个意图带意图叙事 → 识别需要的哲学维度
|
|
395
434
|
|
|
396
|
-
3. Architect
|
|
397
|
-
→
|
|
435
|
+
3. Architect 先展开 Capability Graph,再设计系统
|
|
436
|
+
→ 基于愿景检查问题面、能力缺口、风险与证据 → 路由高影响节点 → 绘制 Intent Map → 定义验证契约
|
|
398
437
|
|
|
399
438
|
4. LOOM Quality Engine
|
|
400
|
-
→ Forge 编译 Expertise Pack →
|
|
439
|
+
→ Forge 编译 Expertise Pack → 按需编译 Authorial Stance / 进入 Atelier
|
|
440
|
+
→ Quality Arena 实现/比较 → Keeper 形成 Quality Proof
|
|
401
441
|
→ 循环直到所有 Intent 闭合
|
|
402
442
|
```
|
|
403
443
|
|
|
@@ -407,11 +447,12 @@ Agent 通过 **CLI 访问** JSON,不直接读文件——省 token、更高效
|
|
|
407
447
|
|
|
408
448
|
- [x] `meta/` 元规范(4 个文件)
|
|
409
449
|
- [x] `roles/` 角色原型(4 个角色)
|
|
410
|
-
- [x] `templates/`
|
|
450
|
+
- [x] `templates/` 起点骨架
|
|
411
451
|
- [x] `README.md` 系统总览
|
|
412
452
|
- [x] `dimensions/SEARCH_METHODOLOGY.md` 检索方法论
|
|
413
|
-
- [x] `cli/` CLI 访问层(
|
|
414
|
-
- [
|
|
453
|
+
- [x] `cli/` CLI 访问层(Capability Graph / Proposal / Asset Library / Atelier / Quality Proof)
|
|
454
|
+
- [x] `dimensions/AUTHORSHIP.md` 按需创作方法
|
|
455
|
+
- [ ] 继续通过真实项目校准专业维度与 Atelier 的质量增益
|
|
415
456
|
|
|
416
457
|
---
|
|
417
458
|
|
package/cli/bin/loom.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// loom — LOOM 框架的 CLI 传感器层
|
|
3
3
|
// Agent 通过这个 CLI 访问 Intent Map / 哲学 / 验证记录,不直接读文件。
|
|
4
4
|
|
|
5
|
-
import { argv, cwd, exit } from 'node:process';
|
|
5
|
+
import { argv, cwd, env, exit } from 'node:process';
|
|
6
6
|
import { resolve, join, dirname } from 'node:path';
|
|
7
7
|
import { existsSync, readdirSync, readFileSync } from 'node:fs';
|
|
8
8
|
import { fileURLToPath } from 'node:url';
|
|
@@ -24,6 +24,11 @@ import { generatePreviewPrompt, getPreviewStatus } from '../src/preview.js';
|
|
|
24
24
|
import { getPatch, listPatches, recordPatch, validatePatches } from '../src/patch.js';
|
|
25
25
|
import { addIntentDraft, finalizeIntentDraft, getIntentDraft, reviseIntentDraft } from '../src/intent-draft.js';
|
|
26
26
|
import { resolveIntentRef } from '../src/shared/intent-ref.js';
|
|
27
|
+
import { compileCapabilityInputs, getCapabilityCoverage, getCapabilityFrontier, getCapabilityGraphProjection, getCapabilityNode } from '../src/capability-graph.js';
|
|
28
|
+
import { getAsset, importAsset, listAssets, recoverAssetImportTransaction, searchAssets, validateAssetLibrary } from '../src/asset-library.js';
|
|
29
|
+
import { closeCapabilityProposal, decideCapabilityProposal, getCapabilityProposal, listCapabilityProposals, submitCapabilityProposal } from '../src/capability-proposals.js';
|
|
30
|
+
import { getAtelierRecord, initAtelierRecord, validateAtelierRecord } from '../src/atelier.js';
|
|
31
|
+
import { assertExpertiseReady, getExpertisePack, initExpertisePack, validateExpertisePack } from '../src/expertise-pack.js';
|
|
27
32
|
|
|
28
33
|
// ─── 路径解析 ──────────────────────────────────────────
|
|
29
34
|
// findLoomRoot / findVersionDir / readCurrentPointer 已提取到 shared/paths.js
|
|
@@ -58,15 +63,148 @@ const [cmd, sub, ...rest] = argv.slice(2);
|
|
|
58
63
|
|
|
59
64
|
try {
|
|
60
65
|
switch (cmd) {
|
|
61
|
-
case '--version':
|
|
66
|
+
case '--version':
|
|
62
67
|
case '-v': {
|
|
63
68
|
// 从根 package.json 读版本号(cli/bin -> cli -> LOOM root)
|
|
64
69
|
const pkgPath = resolve(__dirname, '..', '..', 'package.json');
|
|
65
70
|
const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8'));
|
|
66
71
|
console.log(`loom ${pkg.version}`);
|
|
67
|
-
break;
|
|
68
|
-
}
|
|
69
|
-
|
|
72
|
+
break;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
case 'capability': {
|
|
76
|
+
const versionDir = findVersionDir();
|
|
77
|
+
switch (sub) {
|
|
78
|
+
case 'graph':
|
|
79
|
+
output(getCapabilityGraphProjection(versionDir));
|
|
80
|
+
break;
|
|
81
|
+
case 'frontier':
|
|
82
|
+
output(getCapabilityFrontier(versionDir));
|
|
83
|
+
break;
|
|
84
|
+
case 'get': {
|
|
85
|
+
const id = rest[0];
|
|
86
|
+
if (!id) die('用法: loom capability get <node-id>');
|
|
87
|
+
output(getCapabilityNode(versionDir, id));
|
|
88
|
+
break;
|
|
89
|
+
}
|
|
90
|
+
case 'coverage':
|
|
91
|
+
output(getCapabilityCoverage(versionDir));
|
|
92
|
+
break;
|
|
93
|
+
case 'compile': {
|
|
94
|
+
const intentId = rest[0];
|
|
95
|
+
if (!intentId) die('用法: loom capability compile <intent-id>');
|
|
96
|
+
output(compileCapabilityInputs(versionDir, intentId));
|
|
97
|
+
break;
|
|
98
|
+
}
|
|
99
|
+
case 'proposal': {
|
|
100
|
+
const action = rest[0];
|
|
101
|
+
if (action === 'list') output(listCapabilityProposals(versionDir));
|
|
102
|
+
else if (action === 'get') {
|
|
103
|
+
if (!rest[1]) die('用法: loom capability proposal get <CGP-ID>');
|
|
104
|
+
output(getCapabilityProposal(versionDir, rest[1]));
|
|
105
|
+
} else if (action === 'submit') {
|
|
106
|
+
const fileIndex = argv.indexOf('--json-file');
|
|
107
|
+
const path = fileIndex === -1 ? null : argv[fileIndex + 1];
|
|
108
|
+
if (!path) die('用法: loom capability proposal submit --json-file <proposal.json>');
|
|
109
|
+
output(submitCapabilityProposal(versionDir, JSON.parse(readFileSync(path, 'utf-8'))));
|
|
110
|
+
} else if (action === 'decide') {
|
|
111
|
+
const rationaleIndex = argv.indexOf('--rationale');
|
|
112
|
+
if (!rest[1] || !rest[2] || rationaleIndex === -1 || !argv[rationaleIndex + 1]) die('用法: loom capability proposal decide <CGP-ID> <decision> --rationale <text>');
|
|
113
|
+
output(decideCapabilityProposal(versionDir, rest[1], rest[2], argv[rationaleIndex + 1]));
|
|
114
|
+
} else if (action === 'close') {
|
|
115
|
+
const resolutionIndex = argv.indexOf('--resolution-file');
|
|
116
|
+
if (!rest[1] || resolutionIndex === -1 || !argv[resolutionIndex + 1]) die('用法: loom capability proposal close <CGP-ID> --resolution-file <resolution.json>');
|
|
117
|
+
output(closeCapabilityProposal(versionDir, rest[1], JSON.parse(readFileSync(argv[resolutionIndex + 1], 'utf-8'))));
|
|
118
|
+
} else die('用法: loom capability proposal [list|get|submit|decide|close]');
|
|
119
|
+
break;
|
|
120
|
+
}
|
|
121
|
+
default:
|
|
122
|
+
die(`未知 capability 子命令: ${sub}\n用法: loom capability [graph|frontier|get|coverage|compile|proposal]`);
|
|
123
|
+
}
|
|
124
|
+
break;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
case 'asset': {
|
|
128
|
+
const versionDir = findVersionDir();
|
|
129
|
+
switch (sub) {
|
|
130
|
+
case 'import': {
|
|
131
|
+
const filePath = rest[0];
|
|
132
|
+
const option = (name) => {
|
|
133
|
+
const index = argv.indexOf(name);
|
|
134
|
+
return index === -1 ? undefined : argv[index + 1];
|
|
135
|
+
};
|
|
136
|
+
if (!filePath || filePath.startsWith('--')) die('用法: loom asset import <本地文件> --tags <标签,...> --source <来源> --author <作者> --license <许可> --approval approved [--kind image] [--evidence <节点,...>]');
|
|
137
|
+
output(importAsset(versionDir, filePath, {
|
|
138
|
+
tags: option('--tags'), source: option('--source'), author: option('--author'), license: option('--license'),
|
|
139
|
+
approval: option('--approval'), kind: option('--kind'), evidenceRefs: option('--evidence'),
|
|
140
|
+
failureInjection: env.NODE_ENV === 'test' && option('--test-fail-after') === 'manifest' ? 'after_manifest'
|
|
141
|
+
: env.NODE_ENV === 'test' && option('--test-fail-after') === 'crash-manifest' ? 'crash_after_manifest' : undefined,
|
|
142
|
+
}));
|
|
143
|
+
break;
|
|
144
|
+
}
|
|
145
|
+
case 'list': output(listAssets(versionDir)); break;
|
|
146
|
+
case 'search': {
|
|
147
|
+
const query = rest[0];
|
|
148
|
+
if (!query) die('用法: loom asset search <查询>');
|
|
149
|
+
output(searchAssets(versionDir, query));
|
|
150
|
+
break;
|
|
151
|
+
}
|
|
152
|
+
case 'get': {
|
|
153
|
+
const id = rest[0];
|
|
154
|
+
if (!id) die('用法: loom asset get <asset-id>');
|
|
155
|
+
output(getAsset(versionDir, id));
|
|
156
|
+
break;
|
|
157
|
+
}
|
|
158
|
+
case 'validate': {
|
|
159
|
+
const recovery = recoverAssetImportTransaction(versionDir);
|
|
160
|
+
output({ valid: true, assets: Object.keys(validateAssetLibrary(versionDir).assets).length, recovered_transaction: recovery.recovered ? recovery : null });
|
|
161
|
+
break;
|
|
162
|
+
}
|
|
163
|
+
default: die(`未知 asset 子命令: ${sub}\n用法: loom asset [import|list|search|get|validate]`);
|
|
164
|
+
}
|
|
165
|
+
break;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
case 'atelier': {
|
|
169
|
+
const versionDir = findVersionDir();
|
|
170
|
+
const intentId = rest[0];
|
|
171
|
+
if (!intentId) die(`用法: loom atelier ${sub || '<init|get|validate>'} <intent-id>`);
|
|
172
|
+
switch (sub) {
|
|
173
|
+
case 'init':
|
|
174
|
+
output(initAtelierRecord(versionDir, intentId));
|
|
175
|
+
break;
|
|
176
|
+
case 'get':
|
|
177
|
+
output(getAtelierRecord(versionDir, intentId));
|
|
178
|
+
break;
|
|
179
|
+
case 'validate':
|
|
180
|
+
output(validateAtelierRecord(versionDir, intentId));
|
|
181
|
+
break;
|
|
182
|
+
default:
|
|
183
|
+
die(`未知 atelier 子命令: ${sub}\n用法: loom atelier [init|get|validate] <intent-id>`);
|
|
184
|
+
}
|
|
185
|
+
break;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
case 'expertise': {
|
|
189
|
+
const versionDir = findVersionDir();
|
|
190
|
+
const intentId = rest[0];
|
|
191
|
+
if (!intentId) die(`用法: loom expertise ${sub || '<init|get|validate>'} <intent-id>`);
|
|
192
|
+
switch (sub) {
|
|
193
|
+
case 'init':
|
|
194
|
+
output(initExpertisePack(versionDir, intentId));
|
|
195
|
+
break;
|
|
196
|
+
case 'get':
|
|
197
|
+
output(getExpertisePack(versionDir, intentId));
|
|
198
|
+
break;
|
|
199
|
+
case 'validate':
|
|
200
|
+
output(validateExpertisePack(versionDir, intentId));
|
|
201
|
+
break;
|
|
202
|
+
default:
|
|
203
|
+
die(`未知 expertise 子命令: ${sub}\n用法: loom expertise [init|get|validate] <intent-id>`);
|
|
204
|
+
}
|
|
205
|
+
break;
|
|
206
|
+
}
|
|
207
|
+
|
|
70
208
|
case 'intent': {
|
|
71
209
|
const versionDir = findVersionDir();
|
|
72
210
|
switch (sub) {
|
|
@@ -227,7 +365,26 @@ try {
|
|
|
227
365
|
if (!isVerificationCurrent(intent, latest)) {
|
|
228
366
|
die(`${id} 最新 passed 验证不属于当前 Intent revision ${intent.revision ?? 1}。先重新验证。`);
|
|
229
367
|
}
|
|
230
|
-
const
|
|
368
|
+
const expertise = assertExpertiseReady(versionDir, id);
|
|
369
|
+
if (expertise && (latest.expertise?.record_ref !== `10_EXPERTISE_PACKS/${id}.json`
|
|
370
|
+
|| latest.expertise?.intent_revision !== expertise.intent_revision
|
|
371
|
+
|| latest.expertise?.source_count !== expertise.source_count
|
|
372
|
+
|| latest.expertise?.capsule_count !== expertise.capsule_count
|
|
373
|
+
|| latest.expertise?.pack_digest !== expertise.pack_digest)) {
|
|
374
|
+
die(`${id} 最新 passed 未绑定当前 Expertise Pack。请在新的 Keeper task 中重新打开来源并验证。`);
|
|
375
|
+
}
|
|
376
|
+
if (intent.quality_strategy === 'atelier') {
|
|
377
|
+
const atelier = validateAtelierRecord(versionDir, id);
|
|
378
|
+
if (!['selected', 'baseline_retained'].includes(atelier.status)) {
|
|
379
|
+
die(`${id} 的 Atelier Record 尚未完成选择(当前: ${atelier.status})`);
|
|
380
|
+
}
|
|
381
|
+
if (latest.atelier?.record_ref !== `09_ATELIER/${id}.json`
|
|
382
|
+
|| latest.atelier?.stance_revision !== atelier.stance_revision
|
|
383
|
+
|| latest.atelier?.status !== atelier.status) {
|
|
384
|
+
die(`${id} 最新 passed 未绑定当前 Atelier Record 与 stance_revision。请在新的 Keeper task 中重新验证。`);
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
const currentStatus = intent.status;
|
|
231
388
|
if (currentStatus === 'completed') {
|
|
232
389
|
console.log(`${id} 已经是 completed,无需操作`);
|
|
233
390
|
break;
|
|
@@ -796,7 +953,19 @@ To Human:
|
|
|
796
953
|
loom patch list 列出当前版本的 Patch
|
|
797
954
|
loom patch get <id> 返回指定 Patch
|
|
798
955
|
loom patch validate 校验 Patch ledger 和 Markdown 投影
|
|
799
|
-
|
|
956
|
+
|
|
957
|
+
loom capability graph 输出 Capability Graph 的 Mermaid 投影与摘要
|
|
958
|
+
loom capability frontier 列出尚未路由的高影响节点
|
|
959
|
+
loom capability get <id> 返回节点、关系、Brief 与 Intent 回链
|
|
960
|
+
loom capability coverage 检查图谱覆盖、Brief 和 Intent 回链
|
|
961
|
+
loom capability compile <id> 只读显示会进入该 Intent 的能力输入
|
|
962
|
+
loom expertise init <id> 创建当前 Intent 的外部能力获取记录
|
|
963
|
+
loom expertise get <id> 返回并校验当前 Expertise Pack
|
|
964
|
+
loom expertise validate <id> 校验检索、来源、Capsule 与 revision
|
|
965
|
+
loom atelier init <id> 为 atelier Intent 创建唯一创作记录
|
|
966
|
+
loom atelier get <id> 返回并校验当前 Atelier Record
|
|
967
|
+
loom atelier validate <id> 校验 Record、revision、候选与证据引用
|
|
968
|
+
|
|
800
969
|
loom intent next 返回下一个可执行 Intent
|
|
801
970
|
loom intent add --title <text> [--depends-on <ids>] 创建新增 draft
|
|
802
971
|
loom intent revise <id> --reason <text> 创建修订 draft 并报告反向依赖
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# Asset Library Protocol
|
|
2
|
+
|
|
3
|
+
Asset Library is the versioned, local-first source of truth for project materials. It stores asset bytes under `.loom/vN/08_ASSET_LIBRARY/files/` and metadata in `manifest.json`. A remote URL, successful download, or HTTP 200 is never proof that an asset is renderable in the target host.
|
|
4
|
+
|
|
5
|
+
## Import
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
loom asset import ./approved-image.png \
|
|
9
|
+
--kind image \
|
|
10
|
+
--tags "庆祝,表情,项目名" \
|
|
11
|
+
--source "用户自有素材包" \
|
|
12
|
+
--author "作者或权利人" \
|
|
13
|
+
--license "授权说明或许可证" \
|
|
14
|
+
--approval approved
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Import copies an explicitly named ordinary local file, computes SHA-256, derives a stable `ASSET-...` ID, and rejects symbolic links, destination/path escape, duplicate bytes, missing provenance, and unapproved assets. It does not fetch remote material.
|
|
18
|
+
|
|
19
|
+
## Recoverable import transaction
|
|
20
|
+
|
|
21
|
+
An evidence-linked import changes three files: the copied bytes, `manifest.json`, and `07_CAPABILITY_GRAPH.json`. Filesystems do not provide one atomic operation across those files, so Loom does not claim that they do. It first prevalidates the complete candidate, then writes same-directory temporary files and a recovery journal (flushed where the filesystem supports it). If an import errors, Loom rolls back to the recorded pre-import state; if the process is interrupted, the next `loom asset validate`, import, or library read recovers the journal before using the library. `loom asset validate` reports a recovered transaction in its JSON output.
|
|
22
|
+
|
|
23
|
+
## Discover and verify
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
loom asset list
|
|
27
|
+
loom asset search 表情
|
|
28
|
+
loom asset get ASSET-<hash-prefix>
|
|
29
|
+
loom asset validate
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Tags are Unicode strings, so Chinese search works without a separate tokenizer for the small local library. Search returns only active `approval: approved` assets; `asset list` remains the audit view. Only approved assets may be used by Forge.
|
|
33
|
+
|
|
34
|
+
## Evidence links
|
|
35
|
+
|
|
36
|
+
When importing with `--evidence`, Loom validates the complete prospective manifest and Graph first, then writes both the asset's `evidence_refs` and the evidence node's `asset_refs` as one recoverable transaction. `loom asset validate` checks this reciprocal link plus hashes and provenance. This records bytes and traceability; Keeper must still check the real target host renders the result.
|