@haaaiawd/loom 1.2.2 → 1.3.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/cli/src/guide.js CHANGED
@@ -11,6 +11,7 @@ import { listCapabilityProposals } from './capability-proposals.js';
11
11
  import { isAutoOn, getAutoMode, writeHeartbeat, needsHumanReview } from './auto.js';
12
12
  import { doctor } from './diagnostics.js';
13
13
  import { getExpertisePackState } from './expertise-pack.js';
14
+ import { validateAtlas } from './atlas.js';
14
15
 
15
16
  /**
16
17
  * 检测文件是否还是模板(未填充真实内容)。
@@ -268,20 +269,25 @@ function diagnoseStage(cwd, loomRoot, auto) {
268
269
  stage_num: 3.1,
269
270
  details: { version: current, coverage: coverage.summary },
270
271
  auto,
271
- next_action: '补齐 Capability Graph 的路由、可观察验证入口与 Intent 回链',
272
+ next_action: '补齐 Capability Graph 的透镜审视、路由、可观察验证入口与 Intent 回链',
272
273
  next_command: 'loom activate architect',
273
- message: `当前版本 ${current}:Capability Graph 尚未闭合(高影响前沿 ${coverage.summary.high_unrouted}、路由缺口 ${coverage.summary.routing_gaps}、不可观察 outcome ${coverage.summary.high_outcomes_without_observable_evidence}、未映射 Intent ${coverage.summary.unmapped_intents})。先由 Architect 补图谱,再继续设计 Intent。`,
274
+ message: `当前版本 ${current}:Capability Graph 尚未闭合(透镜契约缺口 ${coverage.summary.lens_contract_gaps || 0}、能力领域缺口 ${coverage.summary.capability_domain_gaps || 0}、高影响前沿 ${coverage.summary.high_unrouted}、路由缺口 ${coverage.summary.routing_gaps}、不可观察 outcome ${coverage.summary.high_outcomes_without_observable_evidence}、未映射 Intent ${coverage.summary.unmapped_intents})。先由 Architect 补图谱,再继续设计 Intent。`,
274
275
  };
275
276
  }
276
277
  } catch (error) {
278
+ const impactGateError = /impact_assessment|impact 必须为 high|外部获取门禁/.test(error.message);
277
279
  return {
278
280
  stage: 'capability_graph_incomplete',
279
281
  stage_num: 3.1,
280
282
  details: { version: current, error: error.message },
281
283
  auto,
282
- next_action: '修复 Capability Graph',
284
+ next_action: impactGateError
285
+ ? '先完成每个 capability 的 Impact Gate,再决定哪些必须外部获取'
286
+ : '修复 Capability Graph',
283
287
  next_command: 'loom activate architect',
284
- message: `Capability Graph 无法通过校验: ${error.message}`,
288
+ message: impactGateError
289
+ ? `Capability Graph 的 Impact Gate 尚未通过:${error.message} 先由 Architect 判断影响的用户结果、错判代价与外部知识是否会改变决定,不能靠降级 impact 继续。`
290
+ : `Capability Graph 无法通过校验: ${error.message}`,
285
291
  };
286
292
  }
287
293
  }
@@ -317,8 +323,43 @@ function diagnoseStage(cwd, loomRoot, auto) {
317
323
  };
318
324
  }
319
325
 
320
- const allIntents = Object.values(intents);
321
- const counts = {
326
+ const allIntents = Object.values(intents);
327
+ const incompleteDesignDocuments = ['02_ARCHITECTURE.md', '05_VERIFICATION.md']
328
+ .filter((filename) => isTemplate(join(versionDir, filename)));
329
+ if (incompleteDesignDocuments.length) {
330
+ return {
331
+ stage: 'need_architecture',
332
+ stage_num: 3.5,
333
+ details: { version: current, incomplete_documents: incompleteDesignDocuments },
334
+ auto,
335
+ next_action: '完成当前版本的系统架构与验证契约文档',
336
+ next_command: 'loom activate architect',
337
+ message: `当前版本 ${current} 的 Intent Map 已存在,但 ${incompleteDesignDocuments.join('、')} 仍缺失或是模板。Architect 必须先把系统边界与完成契约落到真实文档,再进入 Intent Loop。`,
338
+ };
339
+ }
340
+ const documentIntegrityIssues = doctor(versionDir, join(versionDir, 'verifications'), philosophyDir).issues
341
+ .filter((issue) => [
342
+ 'project_document_missing',
343
+ 'project_document_template',
344
+ 'orphan_philosophy_ref',
345
+ 'orphan_philosophy_anchor',
346
+ 'intent_narrative_invalid',
347
+ 'intent_contract_invalid',
348
+ 'capability_impact_gate_missing',
349
+ ].includes(issue.type));
350
+ if (documentIntegrityIssues.length) {
351
+ const issueTypes = [...new Set(documentIntegrityIssues.map((issue) => issue.type))];
352
+ return {
353
+ stage: 'document_integrity_incomplete',
354
+ stage_num: 3.6,
355
+ details: { version: current, issue_types: issueTypes },
356
+ auto,
357
+ next_action: '修复 LOOM 文档引用与结构完整性,再进入 Intent Loop',
358
+ next_command: 'loom activate architect',
359
+ message: `当前版本 ${current} 的 LOOM 文档完整性尚未通过(${issueTypes.join('、')})。先让 Architect 修复真实文档、章节引用或 Impact Gate;不要带着断开的叙事/契约进入 Intent Loop。`,
360
+ };
361
+ }
362
+ const counts = {
322
363
  pending: allIntents.filter((i) => i.status === 'pending').length,
323
364
  in_progress: allIntents.filter((i) => i.status === 'in_progress').length,
324
365
  completed: allIntents.filter((i) => i.status === 'completed').length,
@@ -346,6 +387,18 @@ function diagnoseStage(cwd, loomRoot, auto) {
346
387
 
347
388
  // 状态 6: 全部 completed
348
389
  if (counts.completed === total && total > 0) {
390
+ const atlas = validateAtlas(join(versionDir, '..', '..'), versionDir);
391
+ if (!atlas.valid) {
392
+ return {
393
+ stage: 'need_decision_atlas',
394
+ stage_num: 5.8,
395
+ details: { version: current, atlas_errors: atlas.errors },
396
+ auto,
397
+ next_action: '生成并校验当前版本的决策图谱交付物',
398
+ next_command: 'loom atlas --regen',
399
+ message: `当前版本 ${current} 的 Intent 已全部完成,但决策图谱尚未交付。它只说明当前架构与决策结构,不展示项目进度;生成 loom-atlas.html 后运行 loom atlas validate。`,
400
+ };
401
+ }
349
402
  const health = doctor(versionDir, join(versionDir, 'verifications'), philosophyDir);
350
403
  const blocking = health.issues.filter((issue) => issue.severity === 'fatal' || issue.severity === 'high');
351
404
  if (blocking.length) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@haaaiawd/loom",
3
- "version": "1.2.2",
3
+ "version": "1.3.1",
4
4
  "description": "LOOM — 哲学驱动开发框架。Agent 通过 CLI 访问 Intent Map / 哲学 / 验证记录,不直接读文件",
5
5
  "type": "module",
6
6
  "bin": {
@@ -27,27 +27,33 @@
27
27
  ## Operating Principles
28
28
 
29
29
  1. 一个 Intent 产生可观察的完整结果,能独立验证,并可在一次受控工作周期内完成。
30
- 2. 在创建正式 Intent Map 前,先用 Capability Graph 检查适用的用户旅程、体验、系统、资产、横切质量和风险;每个透镜必须展开、覆盖或明确排除。
31
- 3. Graph 不是任务列表:未知与调研留在 Graph;只有边界清楚、可独立验证的结果才进入 Intent Map
32
- 4. 高影响 capability 默认进入外部获取强门并创建短小的 Capability Brief;只有证据表明按任务自适应更合适时才显式写 `acquisition_mode: adaptive`,纯内部机械任务可写带理由的 `project_only`。Graph 不保存网站、Skill 或关键词,不为低价值叶子制造文档。
33
- 5. 每个 Intent 必须回链至少一个 Graph 节点;每个高影响 Graph 节点必须有明确路由。
34
- 6. 只引入当前目标确实需要的边界和抽象;不为想象中的扩展性提前付费。
35
- 7. `acceptance` 是完成契约:包含功能承诺、关键失败边界和防御承诺。
36
- 8. Intent 会写入、重组、迁移、同步或覆盖既有用户/系统状态,设 `continuity_required: true`;在同一份 acceptance 写明哪些旧价值不得消失,以及一条“旧状态 操作 新状态”的验收序列。删除、替换和清空必须显式授权,不能由“更新”一词暗示。
37
- 9. `quality_contract` 是可选质量契约:只在结果需要高于功能正确性时声明。
38
- 10. 声明相对提升时,质量契约写清修改前基线、可感知或可测量的质量主张、
30
+ 2. 在创建正式 Intent Map 前,先完成 Graph 的 `lens_contract`。它不是把 UI、UX、后端、AI 写成一排部门标签,而是强制审视六个方向:用户旅程、交互与可访问性、视觉与信息表达、内容与沟通、系统与数据、横切质量与风险。每项都必须连接具体节点,或以项目事实说明为何不适用;不能静默略过。
31
+ 3. 再从项目事实派生 `capability_domains`:这是会改变方案或验证方法的专业领域,例如 UI/UX、3D 建模、光影与材质、网络安全、行为心理学、生物学、供应链或法律。不要维护一个万能学科目录,也不要因为名称听起来高级就加入领域。每个领域必须说明“它现在要回答的专业问题”和“为什么它会改变本项目的决定”,并连接到至少一个具体 capability
32
+ 4. 透镜是检查方向,能力领域是专业知识来源,Capability 才是可交付的能力边界。不要创建 `CAP-UI`、`CAP-UX` 或“做好视觉”这类空节点;改写成用户可观察、可取舍、可验证的能力,例如“让错误状态、恢复入口与键盘路径保持可理解”“让三维光影传达空间尺度”“让长报告的证据层级在窄屏上仍可扫读”。一个具体 capability 可以同时服务多个 outcome,也可以回链多个专业领域、被多个透镜引用。
33
+ 5. Graph 必须出现真实关系,不要把它排成 `一个 Outcome → 一个 Capability → 一个 Intent` 的整齐队列。至少检查:一个 concern 是否约束多个能力、一个 capability 是否支撑多个结果、风险/证据是否横切不同 Intent;若不存在,要写出基于项目事实的理由。
34
+ 6. Graph 不是任务列表:未知与调研留在 Graph;只有边界清楚、可独立验证的结果才进入 Intent Map。
35
+ 7. 在写 Intent 之前,对每个具体 capability 先完成 **Impact Gate**。写出 `impact_assessment`:它影响的用户结果、错判/省略的代价(`low` / `material` / `hard_to_reverse`)、外部知识会不会改变决定,以及理由。若代价不可逆,或外部知识会改变设计/验证判断,`impact` 必须为 `high`;不得把它标成 medium/low 来省掉调研。
36
+ 8. Architect 不能独自确认这项判断。创建一个新的 Agent thread / 子代理,运行 `loom activate impact-reviewer`,让它逐项给出独立的 `impact_review`。它可以上调任何被低估的节点;Graph schema 1.3 还要求 high capability 至少占全部具体 capability 的 30%(向上取整,至少一个)。这是防止用大量“普通节点”稀释关键问题的底线,不是用标签凑数。
37
+ 9. 将每个 high capability 视为一个**主动探索候选**,而不只是“等 Forge 想起来再搜索”的标签。其 Brief 要说清:哪一个专业判断仍未知、哪些项目事实决定检索方向、什么发现会改变设计/验收、以及没有可靠资料时应如何降级或回流。若中低影响节点的外部知识仍可能改变方案,宁可上调为 high;不为满足比例制造无关节点,也不把网址、Skill 名称或关键词写进 Graph。
38
+ 10. Graph schema 1.3 中,高影响 capability 必须进入外部获取强门:`acquisition_mode` 只能为 `external_required`(或省略并使用默认值),并创建短小的 Capability Brief。`adaptive` 与 `project_only` 只属于经 Impact Gate 明确不需要外部来源的较低影响能力。Graph 不保存网站、Skill 或关键词,不为低价值叶子制造文档。
39
+ 11. 每个 Intent 必须回链至少一个 Graph 节点;每个高影响 Graph 节点必须有明确路由。
40
+ 12. 只引入当前目标确实需要的边界和抽象;不为想象中的扩展性提前付费。
41
+ 13. `acceptance` 是完成契约:包含功能承诺、关键失败边界和防御承诺。
42
+ 14. 若 Intent 会写入、重组、迁移、同步或覆盖既有用户/系统状态,设 `continuity_required: true`;在同一份 acceptance 写明哪些旧价值不得消失,以及一条“旧状态 → 操作 → 新状态”的验收序列。删除、替换和清空必须显式授权,不能由“更新”一词暗示。
43
+ 15. `quality_contract` 是可选质量契约:只在结果需要高于功能正确性时声明。
44
+ 16. 声明相对提升时,质量契约写清修改前基线、可感知或可测量的质量主张、
39
45
  最小有意义差异与证据方式。
40
- 11. `capability_needs` 是兼容摘要;新项目优先通过 Capability Graph 和 Brief 声明下游需要补齐的专业领域,不假装能力已经加载。
41
- 12. `creative_scope` 说明 Forge 可以大胆改变什么、必须保持什么。
42
- 13. 每个高影响 `outcome` 必须用 `validated_by` 连接到一个 `evidence` 节点。该节点必须写出 `verification.method`、`target`、`procedure`、`pass_criteria` 和 `artifact`,并回链负责把证据真正产出的 Intent。`artifact` 必须是当前版本 `verifications/` 或 `08_ASSET_LIBRARY/files/` 中实际存在的文件。`target` 是结果实际被接收、呈现或消费的位置:用户界面、目标宿主、外部系统、交付物或人工验收现场。不能用“接口返回成功”“URL 可访问”替代目标宿主中的可观察结果。
43
- 14. 对每个重要 Intent 做简短 Pre-Mortem:最可能出现什么“表面完成”,并将其转成
46
+ 17. `capability_needs` 是兼容摘要;新项目优先通过 Capability Graph 和 Brief 声明下游需要补齐的专业领域,不假装能力已经加载。
47
+ 18. `creative_scope` 说明 Forge 可以大胆改变什么、必须保持什么。
48
+ 19. 每个高影响 `outcome` 必须用 `validated_by` 连接到一个 `evidence` 节点。该节点必须写出 `verification.method`、`target`、`procedure`、`pass_criteria` 和 `artifact`,并回链负责把证据真正产出的 Intent。设计阶段的 `artifact` 是计划中的本地证据路径;负责它的 Intent 一旦 completed,该文件必须实际存在于当前版本 `verifications/` 或 `08_ASSET_LIBRARY/files/`。`target` 是结果实际被接收、呈现或消费的位置:用户界面、目标宿主、外部系统、交付物或人工验收现场。不能用“接口返回成功”“URL 可访问”替代目标宿主中的可观察结果。
49
+ 20. 对每个重要 Intent 做简短 Pre-Mortem:最可能出现什么“表面完成”,并将其转成
44
50
  acceptance 或 verification_method。当 narrative 的核心现象可能被一个更容易实现、但
45
51
  语义不同的代理替换时,写 `semantic_guard`:明确哪种替代不算完成,以及 Keeper 应
46
52
  使用什么反例验证它。它不把 Intent 切成技术碎片,只防止“看似相近”偷换用户结果。
47
- 15. 新要求、论文/资料发现、Keeper 或 Forge 发现先进入 `07_GRAPH_PROPOSALS/`,带来源、观察证据和候选类型。Architect 明确判定它已被覆盖、需要改 Graph、生成/修订 Intent、改变 acceptance,还是 Minor/Major;不得把候选静默写入正式 Graph。
48
- 16. 当项目使用素材时,`08_ASSET_LIBRARY/manifest.json` 是唯一可用素材与来源/作者/许可/哈希的真相源。只允许已批准、可验证的本地资产进入交付;若资产构成结果证据,让 evidence 节点与资产记录双向回链。
49
- 17. `quality_strategy` 缺失等价于 `adaptive`。只有结果确实需要作者命题、媒介原型和独立候选比较时才设为 `atelier`,且必须同时声明 `quality_contract` 与 `creative_scope`。
50
- 18. Author 产生的局部构图、措辞、动效或候选修正留在 Atelier Record;只有新的用户结果、约束、能力缺口、风险或项目证据才进入 Graph proposal。Author 不得裁决自己的 proposal。
53
+ 21. 新要求、论文/资料发现、Keeper 或 Forge 发现先进入 `07_GRAPH_PROPOSALS/`,带来源、观察证据和候选类型。Architect 明确判定它已被覆盖、需要改 Graph、生成/修订 Intent、改变 acceptance,还是 Minor/Major;不得把候选静默写入正式 Graph。
54
+ 22. 当项目使用素材时,`08_ASSET_LIBRARY/manifest.json` 是唯一可用素材与来源/作者/许可/哈希的真相源。只允许已批准、可验证的本地资产进入交付;若资产构成结果证据,让 evidence 节点与资产记录双向回链。
55
+ 23. `quality_strategy` 缺失等价于 `adaptive`。只有结果确实需要作者命题、媒介原型和独立候选比较时才设为 `atelier`,且必须同时声明 `quality_contract` 与 `creative_scope`。
56
+ 24. Author 产生的局部构图、措辞、动效或候选修正留在 Atelier Record;只有新的用户结果、约束、能力缺口、风险或项目证据才进入 Graph proposal。Author 不得裁决自己的 proposal。
51
57
 
52
58
  ## Output Contract
53
59
 
package/roles/forge.md CHANGED
@@ -46,9 +46,7 @@ medium grammar、surprise budget、anti-fixation 与 verification lens。人格
46
46
  名号和风格形容词不能替代这些决策。
47
47
 
48
48
  Context Pack 中出现 Skill 名称只代表可发现。若 External Acquisition Gate 为 OPEN,
49
- 先从 Capability question、项目事实、媒介约束与已观察缺口派生 Search Plan,并实际使用
50
- find skill、网络、官方文档或研究资料。模型自行生成的常识、未打开的搜索摘要和只有标题的
51
- 结果不能成为来源。
49
+ 把每个 `external_required` capability 当作一项主动探索,不要只为“完成检索”随手找一页泛泛资料。先从 Capability question、项目事实、媒介约束与已观察缺口派生 Search Plan,并实际使用 find skill、网络、官方文档或研究资料;随后追问“这条资料让哪一个设计、实现或验证决定不同了”。优先补齐会决定用户体验、风险边界或质量上限的节点;若首个来源过于通用、彼此冲突或无法落入具体决策,继续换通道或回流,而不是把模型常识包装成结论。模型自行生成的常识、未打开的搜索摘要和只有标题的结果不能成为来源。
52
50
 
53
51
  required Pack 写入 `.loom/vN/10_EXPERTISE_PACKS/<intent-id>.json`,只保存来源定位和
54
52
  项目化 Capability Capsules,不复制第三方内容。每个 Capsule 必须直接引用已打开的外部
@@ -0,0 +1,37 @@
1
+ # Impact Reviewer — 独立影响审查契约
2
+
3
+ ## Mission
4
+
5
+ 只判断 Capability Graph 中每一项具体 capability 是否被低估,以及外部知识是否会实质改变设计或验证。你不是 Architect 的润色器,也不替 Forge 实现。
6
+
7
+ ## Independence
8
+
9
+ 你必须在新的 Agent thread / 子代理中运行。不要继承 Architect 的结论为前提;先从 Vision、非目标、用户结果、失败后果和 Graph 关系自行判断。若无法获得独立上下文,不得写入 `impact_review.reviewer_mode: "independent_agent_thread"`,应交给 human 或另开线程。
10
+
11
+ ## Procedure
12
+
13
+ 1. 逐项审查所有 `kind: capability` 节点,而不是只挑 Architect 已标 high 的节点。
14
+ 2. 对每项给出 `recommended_impact`、`external_acquisition_required` 和简短理由。问:错误会伤到什么用户结果?它能否在之后低成本补救?外部研究、规范、真实案例或专业方法会不会改变设计/验收?
15
+ 3. 不确定时宁可上调为 high 并要求外部获取;不要以“通常做法”“看起来简单”降低等级。尤其检查那些名字像基础实现、实际上会决定用户尊严、可访问性、信任、长期可逆性或体验气质的节点。
16
+ 4. 核对至少 30% 的 capability 被标为 high(向上取整,至少一个)。这是一条反稀释底线,不是把所有节点都标 high 的借口。
17
+ 5. 将结论写入 Graph 根级 `impact_review`。只有 review 与节点 `impact`、`acquisition_mode` 一致,Graph 才能通过;若你上调了节点,交回 Architect 更新图谱和 Brief,再由你复审。不要替 Forge 伪造来源:你只判定“这件事值得主动探索”,实际搜索和来源化记录留给 Expertise Pack。
18
+
19
+ ## Output Shape
20
+
21
+ ```json
22
+ {
23
+ "impact_review": {
24
+ "reviewer_mode": "independent_agent_thread",
25
+ "assessments": [
26
+ {
27
+ "capability_id": "CAP-EXAMPLE",
28
+ "recommended_impact": "high",
29
+ "external_acquisition_required": true,
30
+ "rationale": "外部无障碍规范会改变交互和验收,误判会让用户失去完成路径。"
31
+ }
32
+ ]
33
+ }
34
+ }
35
+ ```
36
+
37
+ 不要创建 Intent、Capability Brief、实现或验证记录;你的结论只是进入它们之前的独立门禁。
@@ -0,0 +1,104 @@
1
+ <!doctype html>
2
+ <html lang="zh-CN">
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1">
6
+ <meta name="loom-atlas-source-digest" content="{{SOURCE_DIGEST}}">
7
+ <title>LOOM 决策图谱</title>
8
+ <style>
9
+ :root { --ink:#f2ecdf; --panel:#fbf7ef; --panel-2:#e9dfce; --paper:#24201c; --muted:#746b60; --line:rgba(48,38,28,.22); --acid:#a42a2a; --danger:#b95b3f; }
10
+ * { box-sizing:border-box; } html { background:var(--ink); } body { height:100dvh; min-height:100dvh; margin:0; overflow:hidden; background:var(--ink); color:var(--paper); font:500 16px/1.45 ui-sans-serif,system-ui,"Microsoft YaHei",sans-serif; }
11
+ button { font:inherit; } button:focus-visible { outline:2px solid var(--acid); outline-offset:3px; }
12
+ .atlas-shell { height:100dvh; min-height:100dvh; display:grid; grid-template-rows:auto minmax(0,1fr) auto; }
13
+ .atlas-topbar { position:relative; z-index:2; display:flex; justify-content:space-between; gap:1rem; padding:1.05rem clamp(1rem,3vw,3.5rem); border-top:5px solid var(--acid); border-bottom:1px solid var(--line); }
14
+ .atlas-title { margin:0; color:var(--paper); font-family:Georgia,"Songti SC",STSong,serif; font-size:1rem; font-weight:700; letter-spacing:.05em; } .atlas-title span { color:var(--acid); }
15
+ .atlas-views { display:flex; gap:.4rem; } .atlas-views button, .atlas-control, .atlas-chapter-nav button { appearance:none; border:0; background:transparent; color:var(--muted); cursor:pointer; }
16
+ .atlas-views button { padding:.35rem .55rem; border-bottom:1px solid transparent; } .atlas-views button[aria-pressed="true"] { color:var(--paper); border-color:var(--acid); }
17
+ .atlas-stage { position:relative; min-width:0; min-height:0; overflow:hidden; } .atlas-track { width:500%; height:100%; min-height:0; display:flex; transform:translate3d(0,0,0); transition:transform .68s cubic-bezier(.2,.75,.2,1); }
18
+ .atlas-slide { width:20%; min-height:calc(100dvh - 132px); display:grid; grid-template-columns:minmax(0,1.1fr) minmax(280px,.9fr); align-items:start; gap:clamp(2rem,6vw,7rem); padding:clamp(2.25rem,5vw,5.25rem) clamp(2rem,7vw,7rem); overflow:auto; }
19
+ .atlas-copy { max-width:42rem; } .atlas-copy p { max-width:38rem; color:var(--muted); } .atlas-kicker { margin:0 0 1.25rem; color:var(--acid) !important; font-size:.78rem; letter-spacing:.08em; text-transform:uppercase; }
20
+ h1, h2 { max-width:13ch; margin:0; font-family:Georgia,"Songti SC",STSong,serif; font-size:clamp(2.8rem,4.3vw,4.5rem); line-height:1; letter-spacing:-.045em; } h2 { font-size:clamp(2.35rem,3.7vw,3.8rem); }
21
+ .atlas-ledger { display:grid; grid-template-columns:repeat(3,minmax(0,1fr)); gap:0; margin:1.75rem 0 0; border-top:2px solid var(--paper); border-bottom:1px solid var(--line); } .atlas-ledger div { min-height:5.2rem; padding:1rem .8rem 1rem 0; border-right:1px solid var(--line); } .atlas-ledger div + div { padding-left:.8rem; } .atlas-ledger div:last-child { border-right:0; } .atlas-ledger dt { color:var(--acid); font-size:.72rem; font-weight:700; letter-spacing:.06em; } .atlas-ledger dd { margin:.5rem 0 0; color:var(--paper); font-size:.88rem; line-height:1.35; }
22
+ .atlas-visual { position:relative; min-height:min(55vw,34rem); display:grid; align-content:center; gap:.8rem; } .atlas-visual svg { width:min(100%,36rem); height:auto; overflow:visible; }
23
+ .atlas-visual text { fill:var(--paper); font:500 13px ui-sans-serif,system-ui,sans-serif; } .atlas-visual .muted { fill:var(--muted); } .atlas-visual .accent { fill:var(--acid); } .atlas-visual .line { stroke:var(--line); } .atlas-visual .active-line { stroke:var(--acid); } .atlas-visual path.line, .atlas-visual path.active-line { fill:none; }
24
+ .atlas-note { margin-top:1.1rem; color:var(--muted); font-size:.85rem; } .atlas-note code { color:var(--paper); } .atlas-diagram-note { max-width:36rem; color:var(--muted); font-size:.82rem; } .atlas-diagram-note b { color:var(--paper); font-weight:500; }
25
+ .atlas-controls { position:relative; z-index:2; display:grid; grid-template-columns:1fr auto 1fr; align-items:center; gap:.8rem; padding:1rem clamp(1rem,3vw,3.5rem); border-top:1px solid var(--line); }
26
+ .atlas-control { display:inline-flex; align-items:center; gap:.65rem; width:max-content; padding:.4rem 0; color:var(--paper); } .atlas-control:last-child { justify-self:end; } .atlas-control b { color:var(--acid); font-size:1.25rem; font-weight:400; }
27
+ #atlas-position { color:var(--muted); font-variant-numeric:tabular-nums; font-size:.78rem; letter-spacing:.08em; }
28
+ .atlas-chapter-nav { position:absolute; z-index:3; inset:auto 0 4.7rem; display:flex; justify-content:center; gap:.45rem; pointer-events:none; } .atlas-chapter-nav button { width:.55rem; height:.55rem; padding:0; border:1px solid var(--muted); border-radius:50%; pointer-events:auto; }
29
+ .atlas-chapter-nav button[aria-current="true"] { border-color:var(--acid); background:var(--acid); }
30
+ .atlas-map-stage { display:none; align-content:center; gap:clamp(1.5rem,4vw,4rem); padding:clamp(1.5rem,5vw,5rem); overflow:auto; }
31
+ .atlas-map-heading { display:flex; justify-content:space-between; align-items:end; gap:2rem; } .atlas-map-heading h2 { max-width:14ch; } .atlas-map-heading p { max-width:34rem; margin:0; color:var(--muted); }
32
+ #atlas-audit-map { display:grid; grid-template-columns:minmax(0,1.65fr) minmax(15rem,.7fr); gap:1rem; align-items:stretch; } .atlas-map-canvas { min-height:22rem; border:1px solid var(--line); background:var(--panel); } .atlas-map-canvas svg { display:block; width:100%; height:100%; min-height:22rem; }
33
+ .atlas-map-canvas .edge { fill:none; stroke:var(--muted); stroke-width:1.25; } .atlas-map-canvas .node { fill:var(--panel-2); stroke:var(--muted); stroke-width:1.2; cursor:pointer; } .atlas-map-canvas .node:hover, .atlas-map-canvas .node:focus { stroke:var(--acid); } .atlas-map-canvas .node.active { fill:var(--acid); } .atlas-map-canvas .node-text { fill:var(--paper); font-size:12px; pointer-events:none; } .atlas-map-canvas .node.active + text { fill:var(--ink); }
34
+ .atlas-inspector { display:flex; flex-direction:column; justify-content:space-between; gap:2rem; padding:1.35rem; border:1px solid var(--line); background:var(--panel-2); } .atlas-inspector h3 { margin:0; font-family:Georgia,"Songti SC",STSong,serif; font-size:1.35rem; } .atlas-inspector p { color:var(--muted); } .atlas-source { margin:0; color:var(--acid) !important; font:12px/1.45 ui-monospace,SFMono-Regular,monospace; overflow-wrap:anywhere; }
35
+ [data-atlas-mode="map"] { overflow:auto; } [data-atlas-mode="map"] .atlas-stage, [data-atlas-mode="map"] .atlas-controls, [data-atlas-mode="map"] .atlas-chapter-nav { display:none; } [data-atlas-mode="map"] .atlas-map-stage { display:grid; }
36
+ @media (max-width:760px) { .atlas-slide { min-height:0; height:100%; grid-template-columns:1fr; grid-template-rows:auto minmax(16rem,1fr); align-content:start; gap:1.2rem; padding:2rem 1.25rem 3rem; overflow-y:auto; } .atlas-visual { min-height:15rem; } .atlas-copy p { font-size:.94rem; } .atlas-ledger { grid-template-columns:repeat(3,minmax(0,1fr)); } .atlas-ledger dd { font-size:.76rem; } .atlas-ledger dt { font-size:.65rem; } .atlas-visual text { font-size:16px; } .atlas-map-canvas .node-text { font-size:22px; } h1, h2 { max-width:12ch; } .atlas-topbar { padding:1rem 1.25rem; } .atlas-title { align-self:center; } .atlas-views button { font-size:.82rem; } .atlas-controls { padding:.85rem 1.25rem; } #atlas-audit-map { grid-template-columns:1fr; } .atlas-map-heading { display:block; } .atlas-map-heading p { margin-top:1rem; } }
37
+ @media (prefers-reduced-motion:reduce) { .atlas-track { transition:none; } }
38
+ </style>
39
+ </head>
40
+ <body data-atlas-experience="deck-map-v1" data-atlas-mode="deck">
41
+ <div class="atlas-shell">
42
+ <header class="atlas-topbar">
43
+ <p class="atlas-title">LOOM <span>Decision Atlas</span></p>
44
+ <div class="atlas-views" aria-label="阅读方式">
45
+ <button type="button" data-atlas-view="deck" aria-pressed="true">放映</button>
46
+ <button type="button" data-atlas-view="map" aria-pressed="false">审查地图</button>
47
+ </div>
48
+ </header>
49
+
50
+ <main class="atlas-stage" aria-label="Atlas 放映">
51
+ <div class="atlas-track" id="atlas-track">
52
+ <section class="atlas-slide" id="atlas-origin" data-atlas-slide aria-label="起点">
53
+ <div class="atlas-copy" data-atlas-example>
54
+ <p class="atlas-kicker">从一个承诺开始</p><h1>为什么要这样做?</h1>
55
+ <p>在这里把原则、北极星与非目标收成一个可被质疑的起点。不要逐段复述文档,让每条取舍都看得见。</p>
56
+ <dl class="atlas-ledger"><div><dt>要守住</dt><dd>北极星承诺</dd></div><div><dt>明确不做</dt><dd>非目标边界</dd></div><div><dt>可被挑战</dt><dd>取舍理由</dd></div></dl>
57
+ <p class="atlas-note">来源 <code>00_PHILOSOPHY/*</code></p>
58
+ </div>
59
+ <div class="atlas-visual" data-atlas-example><svg viewBox="0 0 520 400" role="img" aria-labelledby="origin-title origin-desc"><title id="origin-title">原则与非目标的取舍构图</title><desc id="origin-desc">中心北极星被原则支撑,非目标位于边缘以示明确排除。</desc><circle cx="260" cy="200" r="145" fill="none" class="line"/><circle cx="260" cy="200" r="76" fill="none" class="active-line"/><path d="M260 50V350M110 200H410" class="line"/><circle cx="260" cy="200" r="24" fill="var(--acid)"/><text x="260" y="206" text-anchor="middle" fill="var(--ink)">北极星</text><text x="260" y="28" text-anchor="middle" class="accent">原则</text><text x="438" y="204" class="muted">非目标</text><text x="260" y="372" text-anchor="middle" class="muted">可质疑的取舍</text></svg><p class="atlas-diagram-note"><b>读图:</b>中心不是结论,外围才是判断成立的边界。</p></div>
60
+ </section>
61
+ <section class="atlas-slide" id="atlas-structure" data-atlas-slide aria-label="结构">
62
+ <div class="atlas-copy" data-atlas-example><p class="atlas-kicker">把承诺落成结构</p><h2>系统如何不背叛它?</h2><p>用架构边界与 Intent 依赖代替长文说明。每层只回答一件事:它保护了什么,它依赖什么。</p><dl class="atlas-ledger"><div><dt>上层</dt><dd>用户可感知边界</dd></div><div><dt>中层</dt><dd>系统与数据约束</dd></div><div><dt>下层</dt><dd>可验证交付</dd></div></dl><p class="atlas-note">来源 <code>01_VISION.md · 02_ARCHITECTURE.md · 04_INTENT_MAP.json</code></p></div>
63
+ <div class="atlas-visual" data-atlas-example><svg viewBox="0 0 520 400" role="img" aria-labelledby="structure-title structure-desc"><title id="structure-title">架构层与 Intent 依赖</title><desc id="structure-desc">三层架构通过一条意图依赖线连接。</desc><rect x="88" y="72" width="344" height="64" rx="2" fill="var(--panel-2)" class="line"/><rect x="118" y="166" width="284" height="64" rx="2" fill="var(--panel)" class="line"/><rect x="148" y="260" width="224" height="64" rx="2" fill="var(--panel-2)" class="active-line"/><text x="112" y="111">体验与接口边界</text><text x="142" y="205">系统与数据边界</text><text x="172" y="299">可验证的交付</text><path d="M260 136V166M260 230V260" class="active-line"/><circle cx="260" cy="150" r="6" fill="var(--acid)"/><circle cx="260" cy="245" r="6" fill="var(--acid)"/><text x="445" y="151" class="accent">Intent</text></svg><p class="atlas-diagram-note"><b>读图:</b>亮线代表从体验承诺到可验证交付的追溯路径。</p></div>
64
+ </section>
65
+ <section class="atlas-slide" id="atlas-capabilities" data-atlas-slide aria-label="能力">
66
+ <div class="atlas-copy" data-atlas-example><p class="atlas-kicker">能力不是装饰</p><h2>为结果配置真实专长。</h2><p>把 Outcome、Concern、Capability、专业领域与证据连成一张图。点击一个节点时,应能看到它具体服务哪条承诺。</p><dl class="atlas-ledger"><div><dt>结果</dt><dd>用户最终获得什么</dd></div><div><dt>能力</dt><dd>需要解决什么问题</dd></div><div><dt>证据</dt><dd>如何确认它成立</dd></div></dl><p class="atlas-note">来源 <code>07_CAPABILITY_GRAPH.json · 07_CAPABILITY_BRIEFS/*</code></p></div>
67
+ <div class="atlas-visual" data-atlas-example><svg viewBox="0 0 520 400" role="img" aria-labelledby="capability-title capability-desc"><title id="capability-title">能力链关系图</title><desc id="capability-desc">结果、关注点、能力和专业领域形成一条可追溯能力链。</desc><path d="M86 200H202M316 200H434M260 94V306" class="active-line"/><circle cx="72" cy="200" r="48" fill="var(--panel-2)" class="line"/><circle cx="260" cy="94" r="38" fill="var(--panel)" class="line"/><circle cx="260" cy="200" r="58" fill="var(--acid)"/><circle cx="260" cy="306" r="38" fill="var(--panel)" class="line"/><circle cx="448" cy="200" r="48" fill="var(--panel-2)" class="line"/><text x="72" y="205" text-anchor="middle">结果</text><text x="260" y="99" text-anchor="middle" class="muted">关注点</text><text x="260" y="205" text-anchor="middle" fill="var(--ink)">能力</text><text x="260" y="311" text-anchor="middle" class="muted">领域</text><text x="448" y="205" text-anchor="middle">证据</text></svg><p class="atlas-diagram-note"><b>读图:</b>不是所有专业名词都值得上图,只有能连回结果的能力才留下。</p></div>
68
+ </section>
69
+ <section class="atlas-slide" id="atlas-decisions" data-atlas-slide aria-label="决策">
70
+ <div class="atlas-copy" data-atlas-example><p class="atlas-kicker">不是唯一正确</p><h2>每个选择都保留代价。</h2><p>把 ADR 处理成分叉,而不是胜利清单。读者应该能一眼看到选择什么、没有选择什么,以及依据来自哪里。</p><dl class="atlas-ledger"><div><dt>问题</dt><dd>必须作出的取舍</dd></div><div><dt>选择</dt><dd>被采纳的方向</dd></div><div><dt>代价</dt><dd>仍需承担的后果</dd></div></dl><p class="atlas-note">来源 <code>03_DECISIONS/*</code></p></div>
71
+ <div class="atlas-visual" data-atlas-example><svg viewBox="0 0 520 400" role="img" aria-labelledby="decision-title decision-desc"><title id="decision-title">决策分叉与取舍</title><desc id="decision-desc">一个问题分出两种方案,选定路径以亮色表达,另一条保留其代价。</desc><path d="M72 200H214M214 200L420 92M214 200L420 308" class="line"/><path d="M72 200H214L420 92" class="active-line" stroke-width="3"/><circle cx="72" cy="200" r="34" fill="var(--panel-2)" class="line"/><circle cx="214" cy="200" r="26" fill="var(--acid)"/><circle cx="420" cy="92" r="42" fill="var(--panel-2)" class="active-line"/><circle cx="420" cy="308" r="42" fill="var(--panel)" class="line"/><text x="72" y="205" text-anchor="middle">问题</text><text x="214" y="205" text-anchor="middle" fill="var(--ink)">取舍</text><text x="420" y="97" text-anchor="middle">选择</text><text x="420" y="313" text-anchor="middle" class="muted">舍弃</text></svg><p class="atlas-diagram-note"><b>读图:</b>暗线不是被隐藏的失败,它是这条选择真实的成本。</p></div>
72
+ </section>
73
+ <section class="atlas-slide" id="atlas-review" data-atlas-slide aria-label="审查">
74
+ <div class="atlas-copy" data-atlas-example><p class="atlas-kicker">把缺口留在光下</p><h2>哪里仍然不够好?</h2><p>这里不宣告完成。它只留下结构上的断线、待确认项和能返回原始资料的入口,供下一次判断使用。</p><dl class="atlas-ledger"><div><dt>断线</dt><dd>需要补回的关系</dd></div><div><dt>待确认</dt><dd>尚无依据的判断</dd></div><div><dt>回到资料</dt><dd>每项都有来源</dd></div></dl><p class="atlas-note">来源 <code>Atlas structural_review · source_refs</code></p></div>
75
+ <div class="atlas-visual" data-atlas-example><svg viewBox="0 0 520 400" role="img" aria-labelledby="review-title review-desc"><title id="review-title">结构性缺口审查</title><desc id="review-desc">完整链路和断开的链路并置,提醒审查者回到来源资料。</desc><path d="M72 200H168M224 200H304M360 200H448" class="active-line"/><path d="M168 200H224M304 200H360" stroke="var(--danger)" stroke-width="2" stroke-dasharray="7 8"/><circle cx="72" cy="200" r="28" fill="var(--panel-2)" class="line"/><circle cx="196" cy="200" r="28" fill="var(--panel-2)" stroke="var(--danger)" stroke-width="2"/><circle cx="332" cy="200" r="28" fill="var(--panel-2)" stroke="var(--danger)" stroke-width="2"/><circle cx="448" cy="200" r="28" fill="var(--panel-2)" class="line"/><text x="72" y="205" text-anchor="middle">目标</text><text x="196" y="205" text-anchor="middle">?</text><text x="332" y="205" text-anchor="middle">?</text><text x="448" y="205" text-anchor="middle">证据</text></svg><p class="atlas-diagram-note"><b>读图:</b>断线是待查路径,不是完成率,也不替人下结论。</p></div>
76
+ </section>
77
+ </div>
78
+ </main>
79
+
80
+ <section class="atlas-map-stage" aria-label="Atlas 审查地图">
81
+ <div class="atlas-map-heading"><div><p class="atlas-kicker">从关系开始审查</p><h2>一条链,还是一团雾?</h2></div><p>这里应从 Atlas Model 生成可点击节点。选择节点后,检查台只展示必要解释、连接对象和来源,不重复整篇文档。</p></div>
82
+ <div id="atlas-audit-map">
83
+ <div class="atlas-map-canvas" data-atlas-example><svg viewBox="0 0 760 430" role="img" aria-labelledby="map-title map-desc"><title id="map-title">目标到验证设计的审查链</title><desc id="map-desc">从目标、能力、专业领域、Intent 到验证设计的一条可点击关系链。</desc><path class="edge" d="M126 215H258M350 215H454M546 215H652"/><g data-atlas-node="目标" role="button" tabindex="0"><rect class="node active" x="30" y="170" width="96" height="90" rx="2"/><text class="node-text" x="78" y="220" text-anchor="middle">目标</text></g><g data-atlas-node="能力" role="button" tabindex="0"><rect class="node" x="258" y="170" width="92" height="90" rx="2"/><text class="node-text" x="304" y="220" text-anchor="middle">能力</text></g><g data-atlas-node="领域" role="button" tabindex="0"><rect class="node" x="454" y="170" width="92" height="90" rx="2"/><text class="node-text" x="500" y="220" text-anchor="middle">领域</text></g><g data-atlas-node="Intent" role="button" tabindex="0"><rect class="node" x="652" y="170" width="78" height="90" rx="2"/><text class="node-text" x="691" y="220" text-anchor="middle">Intent</text></g><path class="edge" d="M691 260V350H304V260"/><text class="node-text" x="496" y="380" text-anchor="middle">验证设计</text></svg></div>
84
+ <aside class="atlas-inspector" aria-live="polite"><div><p class="atlas-kicker">检查台</p><h3 id="atlas-inspector-title">目标</h3><p id="atlas-inspector-copy">选择一个节点,查看它在当前决策结构中的作用与连接。</p></div><p class="atlas-source" id="atlas-inspector-source">source_refs: Atlas Model</p></aside>
85
+ </div>
86
+ </section>
87
+
88
+ <nav class="atlas-chapter-nav" aria-label="章节定位"><button type="button" data-atlas-jump="0" aria-current="true" aria-label="起点"></button><button type="button" data-atlas-jump="1" aria-current="false" aria-label="结构"></button><button type="button" data-atlas-jump="2" aria-current="false" aria-label="能力"></button><button type="button" data-atlas-jump="3" aria-current="false" aria-label="决策"></button><button type="button" data-atlas-jump="4" aria-current="false" aria-label="审查"></button></nav>
89
+ <footer class="atlas-controls"><button type="button" class="atlas-control" data-atlas-control="previous"><b>←</b> 上一章</button><span id="atlas-position" aria-live="polite">起点 1 / 5</span><button type="button" class="atlas-control" data-atlas-control="next">下一章 <b>→</b></button></footer>
90
+ </div>
91
+ <script>
92
+ (() => {
93
+ const root = document.body; const track = document.getElementById('atlas-track'); const slides = [...document.querySelectorAll('[data-atlas-slide]')]; const jumps = [...document.querySelectorAll('[data-atlas-jump]')]; const position = document.getElementById('atlas-position'); const names = ['起点', '结构', '能力', '决策', '审查']; let current = 0; let touchStart = null;
94
+ const go = (index) => { current = Math.max(0, Math.min(slides.length - 1, index)); track.style.transform = `translate3d(${-current * 20}%,0,0)`; jumps.forEach((button, i) => button.setAttribute('aria-current', String(i === current))); position.textContent = `${names[current]} ${current + 1} / ${slides.length}`; };
95
+ document.querySelector('[data-atlas-control="previous"]').addEventListener('click', () => go(current - 1)); document.querySelector('[data-atlas-control="next"]').addEventListener('click', () => go(current + 1)); jumps.forEach((button) => button.addEventListener('click', () => go(Number(button.dataset.atlasJump))));
96
+ document.querySelectorAll('[data-atlas-view]').forEach((button) => button.addEventListener('click', () => { const mode = button.dataset.atlasView; root.dataset.atlasMode = mode; document.querySelectorAll('[data-atlas-view]').forEach((view) => view.setAttribute('aria-pressed', String(view === button))); }));
97
+ window.addEventListener('keydown', (event) => { if (root.dataset.atlasMode !== 'deck' || /INPUT|TEXTAREA|SELECT/.test(document.activeElement.tagName)) return; if (event.key === 'ArrowLeft') go(current - 1); if (event.key === 'ArrowRight') go(current + 1); });
98
+ track.addEventListener('touchstart', (event) => { touchStart = event.changedTouches[0].clientX; }, { passive:true }); track.addEventListener('touchend', (event) => { if (touchStart === null) return; const distance = event.changedTouches[0].clientX - touchStart; if (Math.abs(distance) > 44) go(current + (distance < 0 ? 1 : -1)); touchStart = null; }, { passive:true });
99
+ const nodeDetails = { 目标:['目标','它定义这张图最终要守住的用户结果。','source_refs: capability_graph.outcomes'], 能力:['能力','它是为结果解决具体问题的可观察专长。','source_refs: capability_graph.capabilities'], 领域:['领域','它标出需要引入的专业知识,而不是贴标签。','source_refs: capability_domains'], Intent:['Intent','它把能力落成可实现、可验证的产品承诺。','source_refs: intent_structure'] };
100
+ document.querySelectorAll('[data-atlas-node]').forEach((node) => { const inspect = () => { const [title, copy, source] = nodeDetails[node.dataset.atlasNode]; document.getElementById('atlas-inspector-title').textContent = title; document.getElementById('atlas-inspector-copy').textContent = copy; document.getElementById('atlas-inspector-source').textContent = source; document.querySelectorAll('[data-atlas-node] .node').forEach((shape) => shape.classList.remove('active')); node.querySelector('.node').classList.add('active'); }; node.addEventListener('click', inspect); node.addEventListener('keydown', (event) => { if (event.key === 'Enter' || event.key === ' ') { event.preventDefault(); inspect(); } }); });
101
+ })();
102
+ </script>
103
+ </body>
104
+ </html>
@@ -22,6 +22,7 @@
22
22
  - 需要回答的专业决策问题:
23
23
  - 可用的检索通道、工具、项目事实或人类输入(不在 Brief 写死网站和关键词):
24
24
  - Forge 应依据哪些项目信号派生本轮查询:
25
+ - 哪一种发现会改变当前设计、实现或验证决定:
25
26
  - 不可用时的降级或回流:
26
27
 
27
28
  ## 产出与验证入口
@@ -0,0 +1,188 @@
1
+ {
2
+ "_meta": {
3
+ "_description": "示例:一张能力边界图不是按部门分类,也不是 Intent 的镜像。它先完成透镜审视,再用关系表达共享能力、约束、风险与证据。替换为自己的项目事实,不要复制节点标题。",
4
+ "_version": "1.2",
5
+ "_loom_version": "v1",
6
+ "_generated_by": "architect-example"
7
+ },
8
+ "lens_contract": {
9
+ "selection_basis": "这是一个帮助用户审视复杂选择的对话式产品;交互状态、视觉阅读、论断措辞、证据数据和信任风险都会直接影响结果。",
10
+ "lenses": [
11
+ {
12
+ "id": "journey",
13
+ "title": "用户旅程",
14
+ "question": "用户从开始到离开,是否能完成有意义的完整路径?",
15
+ "status": "applicable",
16
+ "node_refs": ["OUTCOME-REVISABLE-CHOICE", "CAP-STATEFUL-GUIDANCE"]
17
+ },
18
+ {
19
+ "id": "interaction_accessibility",
20
+ "title": "交互与可访问性",
21
+ "question": "状态、反馈、失败恢复和不同使用条件是否真实可用?",
22
+ "status": "applicable",
23
+ "node_refs": ["CAP-STATEFUL-GUIDANCE", "EVIDENCE-END-TO-END-USE"]
24
+ },
25
+ {
26
+ "id": "visual_editorial",
27
+ "title": "视觉与信息表达",
28
+ "question": "视觉语言、层级、版式与资产是否帮助用户理解并形成该产品的气质?",
29
+ "status": "applicable",
30
+ "node_refs": ["CAP-EVIDENCE-READABILITY", "EVIDENCE-END-TO-END-USE"]
31
+ },
32
+ {
33
+ "id": "content_communication",
34
+ "title": "内容与沟通",
35
+ "question": "文案、信息呈现或对话是否准确、可理解且符合产品立场?",
36
+ "status": "applicable",
37
+ "node_refs": ["CAP-CONDITIONAL-INSIGHT", "RISK-OVERCLAIM"]
38
+ },
39
+ {
40
+ "id": "system_data",
41
+ "title": "系统与数据",
42
+ "question": "数据、模型、集成、权限与运行边界是否支撑而非伤害用户结果?",
43
+ "status": "applicable",
44
+ "node_refs": ["CONCERN-USER-OWNERSHIP", "CAP-STATEFUL-GUIDANCE"]
45
+ },
46
+ {
47
+ "id": "quality_risk",
48
+ "title": "横切质量与风险",
49
+ "question": "可靠性、隐私、安全、性能、素材来源与独立验证是否被处理?",
50
+ "status": "applicable",
51
+ "node_refs": ["RISK-OVERCLAIM", "EVIDENCE-END-TO-END-USE"]
52
+ }
53
+ ]
54
+ },
55
+ "capability_domains": [
56
+ {
57
+ "id": "DOMAIN-INTERACTION-DESIGN",
58
+ "title": "Interaction Design / UX",
59
+ "question": "怎样让状态、错误、恢复与退出在真实交互中可理解且可操作?",
60
+ "why_now": "入口和恢复并非视觉润色;它决定用户能否保有会话主导权。",
61
+ "node_refs": ["CAP-STATEFUL-GUIDANCE", "CAP-EVIDENCE-READABILITY"]
62
+ },
63
+ {
64
+ "id": "DOMAIN-EDITORIAL-INFORMATION-DESIGN",
65
+ "title": "Editorial & Information Design",
66
+ "question": "怎样让事实、推断和待验证问题在有限屏幕内保持可分辨的阅读层级?",
67
+ "why_now": "报告若只显得有权威而不能被扫读,会直接放大过度断言风险。",
68
+ "node_refs": ["CAP-EVIDENCE-READABILITY", "CAP-CONDITIONAL-INSIGHT"]
69
+ },
70
+ {
71
+ "id": "DOMAIN-APPLIED-EPISTEMICS",
72
+ "title": "Applied Epistemics / Responsible AI Communication",
73
+ "question": "怎样在给出有用洞察时保留条件、证据来源、反例与用户修正权?",
74
+ "why_now": "这里的措辞和推断结构会决定产品是在帮助用户判断,还是冒充裁决者。",
75
+ "node_refs": ["CAP-CONDITIONAL-INSIGHT"]
76
+ }
77
+ ],
78
+ "nodes": {
79
+ "OUTCOME-REVISABLE-CHOICE": {
80
+ "id": "OUTCOME-REVISABLE-CHOICE",
81
+ "kind": "outcome",
82
+ "title": "用户带着可修订的选择假设离开,而不是被系统替他下结论",
83
+ "status": "covered",
84
+ "impact": "high",
85
+ "route": "intent",
86
+ "intent_refs": ["INT-002", "INT-003"],
87
+ "relationships": [
88
+ { "type": "refines", "target": "CONCERN-USER-OWNERSHIP" },
89
+ { "type": "requires", "target": "CAP-STATEFUL-GUIDANCE" },
90
+ { "type": "requires", "target": "CAP-CONDITIONAL-INSIGHT" },
91
+ { "type": "requires", "target": "CAP-EVIDENCE-READABILITY" },
92
+ { "type": "risks", "target": "RISK-OVERCLAIM" },
93
+ { "type": "validated_by", "target": "EVIDENCE-END-TO-END-USE" }
94
+ ]
95
+ },
96
+ "CONCERN-USER-OWNERSHIP": {
97
+ "id": "CONCERN-USER-OWNERSHIP",
98
+ "kind": "concern",
99
+ "title": "用户始终理解系统现在知道什么、能暂停或修正什么",
100
+ "status": "covered",
101
+ "impact": "high",
102
+ "route": "intent",
103
+ "intent_refs": ["INT-001", "INT-002"],
104
+ "relationships": [
105
+ { "type": "constrains", "target": "CAP-STATEFUL-GUIDANCE" },
106
+ { "type": "constrains", "target": "CAP-CONDITIONAL-INSIGHT" }
107
+ ]
108
+ },
109
+ "CAP-STATEFUL-GUIDANCE": {
110
+ "id": "CAP-STATEFUL-GUIDANCE",
111
+ "kind": "capability",
112
+ "title": "让会话状态、失败恢复与暂停入口保持可理解",
113
+ "status": "researched",
114
+ "impact": "high",
115
+ "route": "brief",
116
+ "intent_refs": ["INT-001", "INT-002"],
117
+ "domain_refs": ["DOMAIN-INTERACTION-DESIGN"],
118
+ "acquisition_mode": "external_required",
119
+ "brief_ref": "07_CAPABILITY_BRIEFS/CAP-STATEFUL-GUIDANCE.md",
120
+ "question": "用户是否能看见当前状态、理解下一步,并在中断后安全恢复或退出?",
121
+ "relationships": [
122
+ { "type": "requires", "target": "CAP-EVIDENCE-READABILITY" },
123
+ { "type": "risks", "target": "RISK-OVERCLAIM" }
124
+ ]
125
+ },
126
+ "CAP-CONDITIONAL-INSIGHT": {
127
+ "id": "CAP-CONDITIONAL-INSIGHT",
128
+ "kind": "capability",
129
+ "title": "把洞察表达为带证据、条件与反例的可修订假设",
130
+ "status": "researched",
131
+ "impact": "high",
132
+ "route": "brief",
133
+ "intent_refs": ["INT-002", "INT-003"],
134
+ "domain_refs": ["DOMAIN-EDITORIAL-INFORMATION-DESIGN", "DOMAIN-APPLIED-EPISTEMICS"],
135
+ "acquisition_mode": "external_required",
136
+ "brief_ref": "07_CAPABILITY_BRIEFS/CAP-CONDITIONAL-INSIGHT.md",
137
+ "question": "系统能否给出具体洞察而不越权成为命运裁决者?",
138
+ "relationships": [
139
+ { "type": "requires", "target": "CAP-EVIDENCE-READABILITY" },
140
+ { "type": "risks", "target": "RISK-OVERCLAIM" }
141
+ ]
142
+ },
143
+ "CAP-EVIDENCE-READABILITY": {
144
+ "id": "CAP-EVIDENCE-READABILITY",
145
+ "kind": "capability",
146
+ "title": "让证据、推断与待验证问题在报告中可扫读且不被视觉淹没",
147
+ "status": "researched",
148
+ "impact": "high",
149
+ "route": "brief",
150
+ "intent_refs": ["INT-002", "INT-003"],
151
+ "domain_refs": ["DOMAIN-INTERACTION-DESIGN", "DOMAIN-EDITORIAL-INFORMATION-DESIGN"],
152
+ "acquisition_mode": "external_required",
153
+ "brief_ref": "07_CAPABILITY_BRIEFS/CAP-EVIDENCE-READABILITY.md",
154
+ "question": "窄屏和长文本中,用户能否分清事实、推断和下一步,而不是只看到漂亮结论?",
155
+ "relationships": []
156
+ },
157
+ "RISK-OVERCLAIM": {
158
+ "id": "RISK-OVERCLAIM",
159
+ "kind": "risk",
160
+ "title": "流畅、权威的表达掩盖了证据不足,诱导用户把假设当成定论",
161
+ "status": "covered",
162
+ "impact": "high",
163
+ "route": "intent",
164
+ "intent_refs": ["INT-002", "INT-003"],
165
+ "relationships": [
166
+ { "type": "validated_by", "target": "EVIDENCE-END-TO-END-USE" }
167
+ ]
168
+ },
169
+ "EVIDENCE-END-TO-END-USE": {
170
+ "id": "EVIDENCE-END-TO-END-USE",
171
+ "kind": "evidence",
172
+ "title": "独立使用者在真实阅读与中断恢复路径中区分证据、推断与可操作的下一步",
173
+ "status": "covered",
174
+ "impact": "high",
175
+ "route": "intent",
176
+ "intent_refs": ["INT-003"],
177
+ "verification": {
178
+ "method": "independent_human_review",
179
+ "target": "窄屏和桌面端的真实报告与会话恢复界面",
180
+ "procedure": "让未参与实现者完成一次中断、恢复、阅读报告并追问一个结论来源的任务。",
181
+ "pass_criteria": "使用者能指出至少一项证据、一项条件化推断与一个修正入口;恢复过程没有丢失已确认状态。",
182
+ "artifact": "verifications/INT-003-end-to-end-use.md"
183
+ },
184
+ "relationships": []
185
+ }
186
+ },
187
+ "constraints": []
188
+ }