@haaaiawd/loom 1.2.1 → 1.2.2

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 CHANGED
@@ -1,5 +1,14 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.2.2 — 2026-07-31
4
+
5
+ ### Fixed
6
+
7
+ - `guide` 只输出下一步命令、Context Pack 提示与完成校验,不再展示文件输入/输出清单;当下一步是角色激活时,由该命令装配 Context Pack。
8
+ - `activate weaver` 直接注入检索方法与哲学维度目录;`activate architect` 在无 Intent 的设计阶段直接注入愿景、当前 Capability Graph、Intent Map 与未闭合 proposal。
9
+ - Capability Graph 未闭合或 proposal 待裁决时,`guide` 重新指向可推进工作的 Architect Context Pack,而不是重复运行只读检查。
10
+ - `loom intent next` 返回开始该 Intent 和获取 Forge Context Pack 的明确后续命令。
11
+
3
12
  ## 1.2.1 — 2026-07-31
4
13
 
5
14
  ### Fixed
package/README.md CHANGED
@@ -87,6 +87,9 @@ loom guide --dry-run # 只读诊断,不写 heartbeat
87
87
  guide 检测项目当前在哪个阶段,输出"你在阶段 X,下一步做 Y"。
88
88
  Agent 每完成一步都跑 guide 确认下一步。
89
89
  如果只是审计或探测,不希望产生任何状态写入,用 `loom guide --dry-run`。
90
+
91
+ 当 `guide` 的下一步是 `loom activate <role>` 时,先运行这条命令:它会把该阶段需要的
92
+ 规范与版本化输入编译为 Context Pack。`guide` 只负责导航,不输出待阅读文件清单。
90
93
 
91
94
  ### AUTO 模式
92
95
 
package/cli/bin/loom.js CHANGED
@@ -274,9 +274,19 @@ try {
274
274
  }));
275
275
  break;
276
276
  }
277
- case 'next':
278
- output(getNextIntent(versionDir) ?? '没有可执行的 Intent');
279
- break;
277
+ case 'next':
278
+ {
279
+ const next = getNextIntent(versionDir);
280
+ output(next ? {
281
+ ...next,
282
+ suggested_flow: {
283
+ start: `loom intent update ${next.id} --status in_progress`,
284
+ forge_context: `loom activate forge --intent ${next.id}`,
285
+ note: '先显式开始 Intent,再由 activate 命令装配该 Intent 的叙事、契约、图谱路由与专业输入。',
286
+ },
287
+ } : '没有可执行的 Intent');
288
+ }
289
+ break;
280
290
  case 'status': {
281
291
  const s = getStatus(versionDir);
282
292
  const fmt = (ids) => ids.map((id) => s.titles[id] ? `${id}(${s.titles[id]})` : id).join(', ') || '-';
@@ -518,7 +528,7 @@ try {
518
528
  const icon = issue.severity === 'high' ? '⚠' : '·';
519
529
  console.log(` ${icon} [${issue.severity}] ${issue.msg}`);
520
530
  }
521
- console.log('\n参见 meta/PHILOSOPHY_WEAVER.md + dimensions/SEARCH_METHODOLOGY.md。');
531
+ console.log('\n下一步: 运行 loom activate weaver;命令会重新输出哲学阶段所需的 Context Pack。');
522
532
  exit(1);
523
533
  }
524
534
  break;
@@ -738,7 +748,7 @@ try {
738
748
  console.log(` → 修复: ${issue.fix_hint}`);
739
749
  }
740
750
  }
741
- console.log(`\n参见 meta/PHILOSOPHY_WEAVER.md + dimensions/SEARCH_METHODOLOGY.md。`);
751
+ console.log('\n下一步: 运行 loom guide;它会根据当前状态给出可执行动作与所需 Context Pack。');
742
752
  }
743
753
  break;
744
754
  }
@@ -788,17 +798,12 @@ try {
788
798
  };
789
799
  console.log(`模式: ${modeDesc[result.auto_mode] || result.auto_mode}`);
790
800
  console.log(`\n${result.message}`);
791
- console.log(`\n下一步: ${result.next_action}`);
792
- console.log(` → ${result.next_command}`);
793
- if (result.inputs && result.inputs.length > 0) {
794
- console.log(`\n需要读取:`);
795
- for (const f of result.inputs) console.log(` - ${f}`);
796
- }
797
- if (result.outputs && result.outputs.length > 0) {
798
- console.log(`\n需要产出:`);
799
- for (const f of result.outputs) console.log(` - ${f}`);
800
- }
801
- if (result.verify_command) {
801
+ console.log(`\n下一步: ${result.next_action}`);
802
+ console.log(` → ${result.next_command}`);
803
+ if (result.input_delivery === 'context_pack') {
804
+ console.log('\n上下文: 直接运行这条命令;它会输出当前阶段所需的 Context Pack。');
805
+ }
806
+ if (result.verify_command) {
802
807
  console.log(`\n完成后校验: ${result.verify_command}`);
803
808
  }
804
809
  if (result.auto_mode === 'manual' && result.stage_num > 0 && result.stage_num < 6) {
@@ -9,6 +9,9 @@ loom context
9
9
 
10
10
  只读探测使用 `loom guide --dry-run`。
11
11
 
12
+ 若 `guide` 指向 `loom activate <role>`,直接运行该命令。它会输出已经装配的 Context Pack;
13
+ `guide` 只负责给出当前动作,不要求 Agent 逐个寻找文件。
14
+
12
15
  ## 1. Doctrine — Weaver
13
16
 
14
17
  ```bash
@@ -1,7 +1,7 @@
1
1
  // activate — compile a role- and intent-scoped Context Pack.
2
2
 
3
- import { readFileSync, existsSync } from 'node:fs';
4
- import { join } from 'node:path';
3
+ import { readFileSync, existsSync, readdirSync } from 'node:fs';
4
+ import { join, relative } from 'node:path';
5
5
  import { getLoomRoot } from './shared/paths.js';
6
6
  import { getIntent, getNarrative } from './intent-map.js';
7
7
  import { getIntentDraft } from './intent-draft.js';
@@ -11,6 +11,7 @@ import { extractMdSection } from './shared/md-utils.js';
11
11
  import { compileCapabilityInputs } from './capability-graph.js';
12
12
  import { getAtelierRecord } from './atelier.js';
13
13
  import { formatExpertisePackForPrompt, getExpertisePack, getExpertisePackState } from './expertise-pack.js';
14
+ import { listCapabilityProposals } from './capability-proposals.js';
14
15
 
15
16
  const VALID_ROLES = ['weaver', 'visionary', 'architect', 'forge', 'keeper'];
16
17
 
@@ -354,6 +355,92 @@ function compileWorkingFacts(versionDir, objective) {
354
355
  return refs.join('\n');
355
356
  }
356
357
 
358
+ function readStageFile(path, label) {
359
+ if (!existsSync(path)) return `> ${label} 当前不存在;不要猜测其内容。按角色契约创建或回流。`;
360
+ return readFileSync(path, 'utf-8').trim();
361
+ }
362
+
363
+ function listMarkdownFiles(root, current = root) {
364
+ if (!existsSync(current)) return [];
365
+ return readdirSync(current, { withFileTypes: true })
366
+ .sort((a, b) => a.name.localeCompare(b.name))
367
+ .flatMap((entry) => {
368
+ const path = join(current, entry.name);
369
+ if (entry.isDirectory()) return listMarkdownFiles(root, path);
370
+ return entry.isFile() && entry.name.endsWith('.md')
371
+ ? [relative(root, path).replaceAll('\\', '/')]
372
+ : [];
373
+ });
374
+ }
375
+
376
+ /**
377
+ * Compile the stage inputs that used to be merely named by `loom guide`.
378
+ * These are intentionally separate from Working Facts: they are the source
379
+ * material for a role's immediate decision, not a request to hunt for paths.
380
+ */
381
+ function compileStageInputs(role, versionDir, objective) {
382
+ if (role === 'weaver') {
383
+ const dimensionsRoot = join(getLoomRoot(), 'dimensions');
384
+ const catalog = listMarkdownFiles(dimensionsRoot)
385
+ .filter((path) => path !== 'SEARCH_METHODOLOGY.md')
386
+ .map((path) => `- dimensions/${path}`);
387
+ return [
388
+ '本节由 `loom activate weaver` 直接装配。不要为了取得这些输入而搜索 CLI 安装目录。',
389
+ '',
390
+ '### Search Methodology',
391
+ '',
392
+ readStageFile(join(dimensionsRoot, 'SEARCH_METHODOLOGY.md'), 'SEARCH_METHODOLOGY.md'),
393
+ '',
394
+ '### Available Dimension Catalog',
395
+ '',
396
+ catalog.length
397
+ ? `${catalog.join('\n')}\n\n只打开会实质改变当前项目原则或取舍的维度;目录本身不是要求逐个阅读。`
398
+ : '> 当前没有可用的 dimensions 文档。',
399
+ ].join('\n');
400
+ }
401
+
402
+ if (role === 'architect' && versionDir && !objective.intent && !objective.draft) {
403
+ let proposals = [];
404
+ let proposalsError = null;
405
+ try {
406
+ proposals = listCapabilityProposals(versionDir, { unresolvedOnly: true });
407
+ } catch (error) {
408
+ proposalsError = error.message;
409
+ }
410
+ return [
411
+ '本节由 `loom activate architect` 直接装配。以下是当前设计决策所需的版本化输入,不要先手动查找路径。',
412
+ '',
413
+ '### Vision Input (01_VISION.md)',
414
+ '',
415
+ readStageFile(join(versionDir, '01_VISION.md'), '01_VISION.md'),
416
+ '',
417
+ '### Capability Graph Input (07_CAPABILITY_GRAPH.json)',
418
+ '',
419
+ readStageFile(join(versionDir, '07_CAPABILITY_GRAPH.json'), '07_CAPABILITY_GRAPH.json'),
420
+ '',
421
+ '### Intent Map Input (04_INTENT_MAP.json)',
422
+ '',
423
+ readStageFile(join(versionDir, '04_INTENT_MAP.json'), '04_INTENT_MAP.json'),
424
+ '',
425
+ '### Open Capability Graph Proposals',
426
+ '',
427
+ proposalsError
428
+ ? `> Proposal 记录无法读取:${proposalsError}。先修复这份记录,不要猜测其状态。`
429
+ : proposals.length
430
+ ? `\`\`\`json\n${JSON.stringify(proposals, null, 2)}\n\`\`\``
431
+ : '无。',
432
+ ].join('\n');
433
+ }
434
+
435
+ if (role === 'visionary') {
436
+ return '产品哲学与决策准则已在上方 Project Judgment 中装配;不要重新搜索 `.loom` 目录。';
437
+ }
438
+ if (role === 'forge' || role === 'keeper') {
439
+ return '当前 Intent 的叙事、契约、图谱路由与已就绪的 Expertise 输入已在上方装配;只有产物本身需要按 Working Facts 检查。';
440
+ }
441
+ return '当前角色没有额外的阶段输入。';
442
+ }
443
+
357
444
  /**
358
445
  * Compile a role-scoped Context Pack.
359
446
  * @param {string} role
@@ -377,9 +464,10 @@ export function activateRole(role, versionDir, intentId = null) {
377
464
  section('3. Hard Invariants', compileInvariants(role, versionDir)),
378
465
  section('4. Success Contracts', compileContracts(role, versionDir, objective)),
379
466
  section('5. Project Judgment', compileProjectJudgment(role, versionDir, objective)),
380
- section('6. Expertise Inputs', compileExpertiseInputs(role, versionDir, objective)),
381
- section('7. Working Facts', compileWorkingFacts(versionDir, objective)),
382
- section('8. Role Contract / Output / Reflow / Stop', readRole(role)),
467
+ section('6. Stage Inputs (command-assembled)', compileStageInputs(role, versionDir, objective)),
468
+ section('7. Expertise Inputs', compileExpertiseInputs(role, versionDir, objective)),
469
+ section('8. Working Facts', compileWorkingFacts(versionDir, objective)),
470
+ section('9. Role Contract / Output / Reflow / Stop', readRole(role)),
383
471
  ];
384
472
  return `${parts.join('\n\n---\n\n')}\n`;
385
473
  }
package/cli/src/guide.js CHANGED
@@ -63,35 +63,41 @@ export function guideProject(projectDir, options = {}) {
63
63
  outputs: ['.loom/v1/'],
64
64
  verify_command: 'loom guide',
65
65
  },
66
- need_philosophy: {
66
+ need_philosophy: {
67
67
  inputs: ['meta/PHILOSOPHY_WEAVER.md', 'meta/BASELINE.md', 'dimensions/SEARCH_METHODOLOGY.md'],
68
- outputs: [`.loom/${current}/00_PHILOSOPHY/PRODUCT_PHILOSOPHY.md`, `.loom/${current}/00_PHILOSOPHY/ENGINEERING_CREED.md`, `.loom/${current}/00_PHILOSOPHY/DECISION_RUBRIC.md`],
69
- verify_command: 'loom philosophy check',
70
- },
71
- need_vision: {
72
- inputs: ['roles/visionary.md', `.loom/${current}/00_PHILOSOPHY/`],
73
- outputs: [`.loom/${current}/01_VISION.md`],
74
- verify_command: 'loom guide',
75
- },
68
+ outputs: [`.loom/${current}/00_PHILOSOPHY/PRODUCT_PHILOSOPHY.md`, `.loom/${current}/00_PHILOSOPHY/ENGINEERING_CREED.md`, `.loom/${current}/00_PHILOSOPHY/DECISION_RUBRIC.md`],
69
+ verify_command: 'loom philosophy check',
70
+ input_delivery: 'context_pack',
71
+ },
72
+ need_vision: {
73
+ inputs: ['roles/visionary.md', `.loom/${current}/00_PHILOSOPHY/`],
74
+ outputs: [`.loom/${current}/01_VISION.md`],
75
+ verify_command: 'loom guide',
76
+ input_delivery: 'context_pack',
77
+ },
76
78
  need_architecture: {
77
79
  inputs: ['roles/architect.md', `.loom/${current}/01_VISION.md`],
78
80
  outputs: [`.loom/${current}/02_ARCHITECTURE.md`, `.loom/${current}/04_INTENT_MAP.json`],
79
81
  verify_command: 'loom doctor',
82
+ input_delivery: 'context_pack',
80
83
  },
81
84
  need_capability_graph: {
82
85
  inputs: ['roles/architect.md', `.loom/${current}/01_VISION.md`],
83
86
  outputs: [`.loom/${current}/07_CAPABILITY_GRAPH.json`, `.loom/${current}/07_CAPABILITY_BRIEFS/`],
84
87
  verify_command: 'loom capability coverage',
88
+ input_delivery: 'context_pack',
85
89
  },
86
90
  capability_graph_incomplete: {
87
91
  inputs: ['roles/architect.md', `.loom/${current}/07_CAPABILITY_GRAPH.json`, `.loom/${current}/04_INTENT_MAP.json`],
88
92
  outputs: [`.loom/${current}/07_CAPABILITY_GRAPH.json`, `.loom/${current}/07_CAPABILITY_BRIEFS/`],
89
93
  verify_command: 'loom capability coverage',
94
+ input_delivery: 'context_pack',
90
95
  },
91
96
  capability_graph_proposals_pending: {
92
97
  inputs: ['roles/architect.md', `.loom/${current}/07_GRAPH_PROPOSALS/`, `.loom/${current}/07_CAPABILITY_GRAPH.json`],
93
98
  outputs: [`.loom/${current}/07_GRAPH_PROPOSALS/`, `.loom/${current}/07_CAPABILITY_GRAPH.json`, `.loom/${current}/04_INTENT_MAP.json`],
94
99
  verify_command: 'loom capability proposal list',
100
+ input_delivery: 'context_pack',
95
101
  },
96
102
  intent_map_broken: {
97
103
  inputs: [`.loom/${current}/04_INTENT_MAP.json`],
@@ -120,9 +126,10 @@ export function guideProject(projectDir, options = {}) {
120
126
  },
121
127
  };
122
128
  const meta = stageMeta[result.stage] || {};
123
- result.inputs = meta.inputs || [];
124
- result.outputs = meta.outputs || [];
125
- result.verify_command = meta.verify_command || null;
129
+ result.inputs = meta.inputs || [];
130
+ result.outputs = meta.outputs || [];
131
+ result.verify_command = meta.verify_command || null;
132
+ result.input_delivery = meta.input_delivery || null;
126
133
  // 统一后处理:写心跳 + 加 AUTO 提示词 + 判断是否需要人类 review
127
134
  if (existsSync(loomRoot) && !options.dryRun) {
128
135
  try {
@@ -242,14 +249,14 @@ function diagnoseStage(cwd, loomRoot, auto) {
242
249
  details: { version: current, proposals: pendingProposals.map((proposal) => proposal.id) },
243
250
  auto,
244
251
  next_action: '审计新信息对 Capability Graph、Intent 和契约的影响',
245
- next_command: 'loom capability proposal list',
252
+ next_command: 'loom activate architect',
246
253
  message: `当前版本 ${current} 有 ${pendingProposals.length} 个未闭合的 Capability Graph proposal。它们是新要求、研究或实现发现,不得由 Forge 静默变成当前 Intent 范围。`,
247
254
  };
248
255
  }
249
256
  } catch (error) {
250
257
  return {
251
258
  stage: 'capability_graph_proposals_pending', stage_num: 3, details: { version: current, error: error.message }, auto,
252
- next_action: '修复 Capability Graph proposal', next_command: 'loom capability proposal list',
259
+ next_action: '修复 Capability Graph proposal', next_command: 'loom activate architect',
253
260
  message: `Capability Graph proposal 无法审计: ${error.message}`,
254
261
  };
255
262
  }
@@ -262,7 +269,7 @@ function diagnoseStage(cwd, loomRoot, auto) {
262
269
  details: { version: current, coverage: coverage.summary },
263
270
  auto,
264
271
  next_action: '补齐 Capability Graph 的路由、可观察验证入口与 Intent 回链',
265
- next_command: 'loom capability coverage',
272
+ next_command: 'loom activate architect',
266
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。`,
267
274
  };
268
275
  }
@@ -273,7 +280,7 @@ function diagnoseStage(cwd, loomRoot, auto) {
273
280
  details: { version: current, error: error.message },
274
281
  auto,
275
282
  next_action: '修复 Capability Graph',
276
- next_command: 'loom capability coverage',
283
+ next_command: 'loom activate architect',
277
284
  message: `Capability Graph 无法通过校验: ${error.message}`,
278
285
  };
279
286
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@haaaiawd/loom",
3
- "version": "1.2.1",
3
+ "version": "1.2.2",
4
4
  "description": "LOOM — 哲学驱动开发框架。Agent 通过 CLI 访问 Intent Map / 哲学 / 验证记录,不直接读文件",
5
5
  "type": "module",
6
6
  "bin": {