@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/cli/src/guide.js
CHANGED
|
@@ -6,8 +6,11 @@ import { existsSync, readFileSync, readdirSync, statSync } from 'node:fs';
|
|
|
6
6
|
import { join } from 'node:path';
|
|
7
7
|
import { readCurrentPointer } from './version.js';
|
|
8
8
|
import { loadIntentMap } from './intent-map.js';
|
|
9
|
+
import { getCapabilityCoverage } from './capability-graph.js';
|
|
10
|
+
import { listCapabilityProposals } from './capability-proposals.js';
|
|
9
11
|
import { isAutoOn, getAutoMode, writeHeartbeat, needsHumanReview } from './auto.js';
|
|
10
12
|
import { doctor } from './diagnostics.js';
|
|
13
|
+
import { getExpertisePackState } from './expertise-pack.js';
|
|
11
14
|
|
|
12
15
|
/**
|
|
13
16
|
* 检测文件是否还是模板(未填充真实内容)。
|
|
@@ -70,11 +73,26 @@ export function guideProject(projectDir, options = {}) {
|
|
|
70
73
|
outputs: [`.loom/${current}/01_VISION.md`],
|
|
71
74
|
verify_command: 'loom guide',
|
|
72
75
|
},
|
|
73
|
-
need_architecture: {
|
|
74
|
-
inputs: ['roles/architect.md', `.loom/${current}/01_VISION.md`],
|
|
75
|
-
outputs: [`.loom/${current}/02_ARCHITECTURE.md`, `.loom/${current}/04_INTENT_MAP.json`],
|
|
76
|
-
verify_command: 'loom doctor',
|
|
77
|
-
},
|
|
76
|
+
need_architecture: {
|
|
77
|
+
inputs: ['roles/architect.md', `.loom/${current}/01_VISION.md`],
|
|
78
|
+
outputs: [`.loom/${current}/02_ARCHITECTURE.md`, `.loom/${current}/04_INTENT_MAP.json`],
|
|
79
|
+
verify_command: 'loom doctor',
|
|
80
|
+
},
|
|
81
|
+
need_capability_graph: {
|
|
82
|
+
inputs: ['roles/architect.md', `.loom/${current}/01_VISION.md`],
|
|
83
|
+
outputs: [`.loom/${current}/07_CAPABILITY_GRAPH.json`, `.loom/${current}/07_CAPABILITY_BRIEFS/`],
|
|
84
|
+
verify_command: 'loom capability coverage',
|
|
85
|
+
},
|
|
86
|
+
capability_graph_incomplete: {
|
|
87
|
+
inputs: ['roles/architect.md', `.loom/${current}/07_CAPABILITY_GRAPH.json`, `.loom/${current}/04_INTENT_MAP.json`],
|
|
88
|
+
outputs: [`.loom/${current}/07_CAPABILITY_GRAPH.json`, `.loom/${current}/07_CAPABILITY_BRIEFS/`],
|
|
89
|
+
verify_command: 'loom capability coverage',
|
|
90
|
+
},
|
|
91
|
+
capability_graph_proposals_pending: {
|
|
92
|
+
inputs: ['roles/architect.md', `.loom/${current}/07_GRAPH_PROPOSALS/`, `.loom/${current}/07_CAPABILITY_GRAPH.json`],
|
|
93
|
+
outputs: [`.loom/${current}/07_GRAPH_PROPOSALS/`, `.loom/${current}/07_CAPABILITY_GRAPH.json`, `.loom/${current}/04_INTENT_MAP.json`],
|
|
94
|
+
verify_command: 'loom capability proposal list',
|
|
95
|
+
},
|
|
78
96
|
intent_map_broken: {
|
|
79
97
|
inputs: [`.loom/${current}/04_INTENT_MAP.json`],
|
|
80
98
|
outputs: [`.loom/${current}/04_INTENT_MAP.json`],
|
|
@@ -169,8 +187,9 @@ function diagnoseStage(cwd, loomRoot, auto) {
|
|
|
169
187
|
|
|
170
188
|
const versionDir = join(loomRoot, current);
|
|
171
189
|
const philosophyDir = join(versionDir, '00_PHILOSOPHY');
|
|
172
|
-
const visionPath = join(versionDir, '01_VISION.md');
|
|
173
|
-
const intentMapPath = join(versionDir, '04_INTENT_MAP.json');
|
|
190
|
+
const visionPath = join(versionDir, '01_VISION.md');
|
|
191
|
+
const intentMapPath = join(versionDir, '04_INTENT_MAP.json');
|
|
192
|
+
const capabilityGraphPath = join(versionDir, '07_CAPABILITY_GRAPH.json');
|
|
174
193
|
|
|
175
194
|
// 状态 1: 哲学未织造
|
|
176
195
|
const philosophyFile = join(philosophyDir, 'PRODUCT_PHILOSOPHY.md');
|
|
@@ -199,16 +218,77 @@ function diagnoseStage(cwd, loomRoot, auto) {
|
|
|
199
218
|
};
|
|
200
219
|
}
|
|
201
220
|
|
|
202
|
-
// 状态 3:
|
|
203
|
-
if (isTemplate(
|
|
204
|
-
return {
|
|
205
|
-
stage: '
|
|
206
|
-
stage_num: 3,
|
|
207
|
-
details: { version: current },
|
|
208
|
-
auto,
|
|
209
|
-
next_action: '
|
|
210
|
-
next_command: 'loom activate architect',
|
|
211
|
-
message: `当前版本 ${current}
|
|
221
|
+
// 状态 3: 愿景已定义,先展开项目问题面与能力缺口,再承诺 Intent。
|
|
222
|
+
if (existsSync(capabilityGraphPath) && isTemplate(capabilityGraphPath)) {
|
|
223
|
+
return {
|
|
224
|
+
stage: 'need_capability_graph',
|
|
225
|
+
stage_num: 3,
|
|
226
|
+
details: { version: current },
|
|
227
|
+
auto,
|
|
228
|
+
next_action: '展开 Capability Graph,路由高影响问题与能力缺口',
|
|
229
|
+
next_command: 'loom activate architect',
|
|
230
|
+
message: `当前版本 ${current}:愿景已定义,但 Capability Graph 还是模板。Architect 必须先判断哪些体验、系统、资产、风险与能力适用,再创建正式 Intent。`,
|
|
231
|
+
};
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
// 图谱一旦存在,就不能把不完整路由悄悄跨过去。旧项目缺少该文件仍保留兼容路径。
|
|
235
|
+
if (existsSync(capabilityGraphPath)) {
|
|
236
|
+
try {
|
|
237
|
+
const pendingProposals = listCapabilityProposals(versionDir, { unresolvedOnly: true });
|
|
238
|
+
if (pendingProposals.length) {
|
|
239
|
+
return {
|
|
240
|
+
stage: 'capability_graph_proposals_pending',
|
|
241
|
+
stage_num: 3,
|
|
242
|
+
details: { version: current, proposals: pendingProposals.map((proposal) => proposal.id) },
|
|
243
|
+
auto,
|
|
244
|
+
next_action: '审计新信息对 Capability Graph、Intent 和契约的影响',
|
|
245
|
+
next_command: 'loom capability proposal list',
|
|
246
|
+
message: `当前版本 ${current} 有 ${pendingProposals.length} 个未闭合的 Capability Graph proposal。它们是新要求、研究或实现发现,不得由 Forge 静默变成当前 Intent 范围。`,
|
|
247
|
+
};
|
|
248
|
+
}
|
|
249
|
+
} catch (error) {
|
|
250
|
+
return {
|
|
251
|
+
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',
|
|
253
|
+
message: `Capability Graph proposal 无法审计: ${error.message}`,
|
|
254
|
+
};
|
|
255
|
+
}
|
|
256
|
+
try {
|
|
257
|
+
const coverage = getCapabilityCoverage(versionDir);
|
|
258
|
+
if (!coverage.summary.ready) {
|
|
259
|
+
return {
|
|
260
|
+
stage: 'capability_graph_incomplete',
|
|
261
|
+
stage_num: 3.1,
|
|
262
|
+
details: { version: current, coverage: coverage.summary },
|
|
263
|
+
auto,
|
|
264
|
+
next_action: '补齐 Capability Graph 的路由、可观察验证入口与 Intent 回链',
|
|
265
|
+
next_command: 'loom capability coverage',
|
|
266
|
+
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
|
+
};
|
|
268
|
+
}
|
|
269
|
+
} catch (error) {
|
|
270
|
+
return {
|
|
271
|
+
stage: 'capability_graph_incomplete',
|
|
272
|
+
stage_num: 3.1,
|
|
273
|
+
details: { version: current, error: error.message },
|
|
274
|
+
auto,
|
|
275
|
+
next_action: '修复 Capability Graph',
|
|
276
|
+
next_command: 'loom capability coverage',
|
|
277
|
+
message: `Capability Graph 无法通过校验: ${error.message}`,
|
|
278
|
+
};
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
// 状态 3.5: 图谱已建立,Intent Map 未设计。
|
|
283
|
+
if (isTemplate(intentMapPath)) {
|
|
284
|
+
return {
|
|
285
|
+
stage: 'need_architecture',
|
|
286
|
+
stage_num: 3.5,
|
|
287
|
+
details: { version: current },
|
|
288
|
+
auto,
|
|
289
|
+
next_action: '从 Capability Graph 编译系统架构 + Intent Map',
|
|
290
|
+
next_command: 'loom activate architect',
|
|
291
|
+
message: `当前版本 ${current}:Capability Graph 已建立,Intent Map 还是模板。Architect 需要将已路由的问题面编译为系统架构与可闭合 Intent。`,
|
|
212
292
|
};
|
|
213
293
|
}
|
|
214
294
|
|
|
@@ -291,10 +371,57 @@ function diagnoseStage(cwd, loomRoot, auto) {
|
|
|
291
371
|
};
|
|
292
372
|
}
|
|
293
373
|
|
|
294
|
-
// 状态 5: 有 in_progress
|
|
295
|
-
if (counts.in_progress > 0) {
|
|
296
|
-
const inProgressIds = allIntents.filter((i) => i.status === 'in_progress').map((i) => i.id);
|
|
297
|
-
|
|
374
|
+
// 状态 5: 有 in_progress
|
|
375
|
+
if (counts.in_progress > 0) {
|
|
376
|
+
const inProgressIds = allIntents.filter((i) => i.status === 'in_progress').map((i) => i.id);
|
|
377
|
+
const expertiseOpen = allIntents
|
|
378
|
+
.filter((intent) => intent.status === 'in_progress')
|
|
379
|
+
.map((intent) => ({ intent, state: getExpertisePackState(versionDir, intent.id) }))
|
|
380
|
+
.find(({ state }) => state.required && !state.ready);
|
|
381
|
+
if (expertiseOpen) {
|
|
382
|
+
const missing = expertiseOpen.state.reason === 'missing';
|
|
383
|
+
const blocked = expertiseOpen.state.reason?.startsWith('blocked:');
|
|
384
|
+
return {
|
|
385
|
+
stage: 'in_loop',
|
|
386
|
+
stage_num: 5,
|
|
387
|
+
details: {
|
|
388
|
+
version: current,
|
|
389
|
+
counts,
|
|
390
|
+
in_progress_ids: inProgressIds,
|
|
391
|
+
expertise_intent: expertiseOpen.intent.id,
|
|
392
|
+
expertise_reason: expertiseOpen.state.reason,
|
|
393
|
+
},
|
|
394
|
+
auto,
|
|
395
|
+
next_action: missing
|
|
396
|
+
? '创建搜索计划并执行外部能力获取'
|
|
397
|
+
: blocked
|
|
398
|
+
? '解决 Expertise Pack 记录的外部获取阻塞'
|
|
399
|
+
: '补齐来源化 Expertise Pack',
|
|
400
|
+
next_command: missing
|
|
401
|
+
? `loom expertise init ${expertiseOpen.intent.id}`
|
|
402
|
+
: blocked
|
|
403
|
+
? `loom expertise get ${expertiseOpen.intent.id}`
|
|
404
|
+
: `loom expertise validate ${expertiseOpen.intent.id}`,
|
|
405
|
+
message: blocked
|
|
406
|
+
? `${expertiseOpen.intent.id} 的外部能力获取已明确 blocked:${expertiseOpen.state.reason.slice('blocked: '.length)}。满足 Pack 中的 recovery_condition 后再继续;不能让模型补齐空白。`
|
|
407
|
+
: `${expertiseOpen.intent.id} 需要外部能力获取。先由任务信号派生搜索词,实际使用 find skill、网络搜索、官方文档或研究资料,再把可回查来源编译为 Capability Capsules;模型临时生成内容不能代替来源。`,
|
|
408
|
+
};
|
|
409
|
+
}
|
|
410
|
+
const atelierWithoutRecord = allIntents.find((intent) => intent.status === 'in_progress'
|
|
411
|
+
&& intent.quality_strategy === 'atelier'
|
|
412
|
+
&& !existsSync(join(versionDir, '09_ATELIER', `${intent.id}.json`)));
|
|
413
|
+
if (atelierWithoutRecord) {
|
|
414
|
+
return {
|
|
415
|
+
stage: 'in_loop',
|
|
416
|
+
stage_num: 5,
|
|
417
|
+
details: { version: current, counts, in_progress_ids: inProgressIds, atelier_intent: atelierWithoutRecord.id },
|
|
418
|
+
auto,
|
|
419
|
+
next_action: '创建 Atelier Record 并冻结基线',
|
|
420
|
+
next_command: `loom atelier init ${atelierWithoutRecord.id}`,
|
|
421
|
+
message: `${atelierWithoutRecord.id} 已进入 Atelier Path,但还没有唯一创作记录。先创建 Record,再按 Forge Context Pack 形成 Authorial Stance。`,
|
|
422
|
+
};
|
|
423
|
+
}
|
|
424
|
+
return {
|
|
298
425
|
stage: 'in_loop',
|
|
299
426
|
stage_num: 5,
|
|
300
427
|
details: { version: current, counts, in_progress_ids: inProgressIds },
|
package/cli/src/init.js
CHANGED
|
@@ -46,9 +46,13 @@ export function createVersionStructure(projectDir, version, parentVersion = null
|
|
|
46
46
|
'.loom',
|
|
47
47
|
`.loom/${v}`,
|
|
48
48
|
`.loom/${v}/00_PHILOSOPHY`,
|
|
49
|
-
`.loom/${v}/verifications`,
|
|
50
|
-
`.loom/${v}/03_DECISIONS`,
|
|
51
|
-
|
|
49
|
+
`.loom/${v}/verifications`,
|
|
50
|
+
`.loom/${v}/03_DECISIONS`,
|
|
51
|
+
`.loom/${v}/07_CAPABILITY_BRIEFS`,
|
|
52
|
+
`.loom/${v}/07_GRAPH_PROPOSALS`,
|
|
53
|
+
`.loom/${v}/08_ASSET_LIBRARY/files`,
|
|
54
|
+
`.loom/${v}/10_EXPERTISE_PACKS`,
|
|
55
|
+
];
|
|
52
56
|
|
|
53
57
|
for (const d of dirs) {
|
|
54
58
|
const path = join(cwd, d);
|
|
@@ -63,7 +67,9 @@ export function createVersionStructure(projectDir, version, parentVersion = null
|
|
|
63
67
|
const templates = [
|
|
64
68
|
['templates/INTENT_MAP_TEMPLATE.json', `.loom/${v}/04_INTENT_MAP.json`],
|
|
65
69
|
['templates/PHILOSOPHY_TEMPLATE.md', `.loom/${v}/00_PHILOSOPHY/PRODUCT_PHILOSOPHY.md`],
|
|
66
|
-
['templates/VISION_TEMPLATE.md', `.loom/${v}/01_VISION.md`],
|
|
70
|
+
['templates/VISION_TEMPLATE.md', `.loom/${v}/01_VISION.md`],
|
|
71
|
+
['templates/CAPABILITY_GRAPH_TEMPLATE.json', `.loom/${v}/07_CAPABILITY_GRAPH.json`],
|
|
72
|
+
['templates/ASSET_LIBRARY_MANIFEST_TEMPLATE.json', `.loom/${v}/08_ASSET_LIBRARY/manifest.json`],
|
|
67
73
|
];
|
|
68
74
|
|
|
69
75
|
// 02_ARCHITECTURE.md 和 05_VERIFICATION.md 没有"填空模板"——
|
|
@@ -114,7 +120,7 @@ export function createVersionStructure(projectDir, version, parentVersion = null
|
|
|
114
120
|
skipped.push(dst);
|
|
115
121
|
} else if (existsSync(srcPath)) {
|
|
116
122
|
copyFileSync(srcPath, dstPath);
|
|
117
|
-
if (dst.endsWith('04_INTENT_MAP.json')) {
|
|
123
|
+
if (dst.endsWith('04_INTENT_MAP.json') || dst.endsWith('07_CAPABILITY_GRAPH.json') || dst.endsWith('08_ASSET_LIBRARY/manifest.json')) {
|
|
118
124
|
const map = JSON.parse(readFileSync(dstPath, 'utf-8'));
|
|
119
125
|
map._meta._loom_version = v;
|
|
120
126
|
map._meta._parent_version = parentVersion;
|
package/cli/src/intent-map.js
CHANGED
|
@@ -174,6 +174,17 @@ function validateLifecycle(data, id, lifecycle, errors) {
|
|
|
174
174
|
|
|
175
175
|
function validateOptionalIntentFields(id, intent, errors) {
|
|
176
176
|
const prefix = `intents["${id}"]`;
|
|
177
|
+
const qualityStrategy = intent.quality_strategy ?? 'adaptive';
|
|
178
|
+
|
|
179
|
+
if (!['adaptive', 'atelier'].includes(qualityStrategy)) {
|
|
180
|
+
errors.push(`${prefix}.quality_strategy 非法: ${JSON.stringify(qualityStrategy)} (合法: adaptive|atelier)`);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
if ('proposal_refs' in intent) {
|
|
184
|
+
if (!Array.isArray(intent.proposal_refs) || intent.proposal_refs.some((ref) => typeof ref !== 'string' || !ref.trim())) {
|
|
185
|
+
errors.push(`${prefix}.proposal_refs 必须是非空 proposal ID 字符串数组`);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
177
188
|
|
|
178
189
|
if ('continuity_required' in intent && typeof intent.continuity_required !== 'boolean') {
|
|
179
190
|
errors.push(`${prefix}.continuity_required 必须是布尔值;仅在本 Intent 会变更既有用户或系统状态且必须证明未误伤旧状态时设为 true`);
|
|
@@ -210,6 +221,15 @@ function validateOptionalIntentFields(id, intent, errors) {
|
|
|
210
221
|
errors.push(`${prefix}.creative_scope 必须说明可以改变什么、必须保持什么`);
|
|
211
222
|
}
|
|
212
223
|
}
|
|
224
|
+
|
|
225
|
+
if (qualityStrategy === 'atelier') {
|
|
226
|
+
if (typeof intent.quality_contract !== 'string' || intent.quality_contract.trim().length < 10) {
|
|
227
|
+
errors.push(`${prefix}.quality_strategy=atelier 必须声明有效 quality_contract`);
|
|
228
|
+
}
|
|
229
|
+
if (typeof intent.creative_scope !== 'string' || intent.creative_scope.trim().length < 10) {
|
|
230
|
+
errors.push(`${prefix}.quality_strategy=atelier 必须声明有效 creative_scope`);
|
|
231
|
+
}
|
|
232
|
+
}
|
|
213
233
|
}
|
|
214
234
|
|
|
215
235
|
function validateLineage(data, id, lineage, errors) {
|
package/cli/src/verify.js
CHANGED
|
@@ -7,6 +7,8 @@ import { extractMdSection, readJsonFile } from './shared/md-utils.js';
|
|
|
7
7
|
import { getIntent, getEffectiveVerificationEpoch, hasLegacyIntentRevision } from './intent-map.js';
|
|
8
8
|
import { formatIntentRef, resolveIntentRef } from './shared/intent-ref.js';
|
|
9
9
|
import { resolveQualityProofReference } from './shared/proof-reference.js';
|
|
10
|
+
import { validateAtelierRecord } from './atelier.js';
|
|
11
|
+
import { assertExpertiseReady } from './expertise-pack.js';
|
|
10
12
|
|
|
11
13
|
/** 合法判定结果 */
|
|
12
14
|
const VALID_VERDICTS = ['passed', 'deviated', 'blocked', 'pending_human'];
|
|
@@ -44,6 +46,8 @@ function getRequiredDimensions(intent) {
|
|
|
44
46
|
*/
|
|
45
47
|
export function writeVerification(versionDir, verificationsDir, record) {
|
|
46
48
|
const errors = [];
|
|
49
|
+
let atelierEvidence = null;
|
|
50
|
+
let expertiseEvidence = null;
|
|
47
51
|
if (!record.intent_id) errors.push('缺少 intent_id');
|
|
48
52
|
if (!record.verdict || !VALID_VERDICTS.includes(record.verdict)) {
|
|
49
53
|
errors.push(`verdict 非法: "${record.verdict}" (合法: ${VALID_VERDICTS.join('|')})`);
|
|
@@ -102,6 +106,23 @@ export function writeVerification(versionDir, verificationsDir, record) {
|
|
|
102
106
|
errors.push(error.message);
|
|
103
107
|
}
|
|
104
108
|
}
|
|
109
|
+
if (record.verdict === 'passed' && intent) {
|
|
110
|
+
try {
|
|
111
|
+
expertiseEvidence = assertExpertiseReady(versionDir, record.intent_id);
|
|
112
|
+
} catch (error) {
|
|
113
|
+
errors.push(`passed 前必须闭合外部能力获取强门: ${error.message}`);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
if (intent?.quality_strategy === 'atelier' && record.verdict === 'passed') {
|
|
117
|
+
try {
|
|
118
|
+
atelierEvidence = validateAtelierRecord(versionDir, record.intent_id);
|
|
119
|
+
if (!['selected', 'baseline_retained'].includes(atelierEvidence.status)) {
|
|
120
|
+
errors.push(`quality_strategy=atelier 通过前,Atelier Record 必须是 selected 或 baseline_retained(当前: ${atelierEvidence.status})`);
|
|
121
|
+
}
|
|
122
|
+
} catch (error) {
|
|
123
|
+
errors.push(`quality_strategy=atelier 通过前必须有当前且合法的 Atelier Record: ${error.message}`);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
105
126
|
if (errors.length > 0) {
|
|
106
127
|
throw new Error(`验证记录校验失败:\n - ${errors.join('\n - ')}`);
|
|
107
128
|
}
|
|
@@ -144,7 +165,20 @@ export function writeVerification(versionDir, verificationsDir, record) {
|
|
|
144
165
|
verdict: record.verdict,
|
|
145
166
|
timestamp: record.timestamp,
|
|
146
167
|
summary: record.summary,
|
|
147
|
-
dimensions: record.dimensions,
|
|
168
|
+
dimensions: record.dimensions,
|
|
169
|
+
atelier: atelierEvidence ? {
|
|
170
|
+
record_ref: `09_ATELIER/${record.intent_id}.json`,
|
|
171
|
+
stance_revision: atelierEvidence.stance_revision,
|
|
172
|
+
status: atelierEvidence.status,
|
|
173
|
+
} : undefined,
|
|
174
|
+
expertise: expertiseEvidence ? {
|
|
175
|
+
record_ref: `10_EXPERTISE_PACKS/${record.intent_id}.json`,
|
|
176
|
+
intent_revision: expertiseEvidence.intent_revision,
|
|
177
|
+
required_node_ids: expertiseEvidence.required_node_ids,
|
|
178
|
+
source_count: expertiseEvidence.source_count,
|
|
179
|
+
capsule_count: expertiseEvidence.capsule_count,
|
|
180
|
+
pack_digest: expertiseEvidence.pack_digest,
|
|
181
|
+
} : undefined,
|
|
148
182
|
reproduction_command: record.reproduction_command,
|
|
149
183
|
deviation_detail: record.deviation_detail,
|
|
150
184
|
reset_suggested: record.reset_suggested,
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# Authorship — Identity Compiler 与 Atelier Method
|
|
2
|
+
|
|
3
|
+
本维度只在 `quality_strategy=atelier` 时加载。目标不是扮演某位大师,而是迫使本次创作
|
|
4
|
+
形成可反驳的命题、明确的选择与可观察的作品差异。
|
|
5
|
+
|
|
6
|
+
## Identity Compiler
|
|
7
|
+
|
|
8
|
+
先读取当前 Intent、Doctrine anchors、Capability Graph / Brief、quality contract、
|
|
9
|
+
creative scope、真实媒介约束与参考机制,再形成 Authorial Stance:
|
|
10
|
+
|
|
11
|
+
1. `creative_thesis`:作品要让用户以什么不同方式理解或感受问题。
|
|
12
|
+
2. `gaze`:这次优先看见什么。
|
|
13
|
+
3. `tension`:哪两个价值必须同时成立。
|
|
14
|
+
4. `signature_bet`:主张、实现机制与主要代价。
|
|
15
|
+
5. `refusals`:拒绝哪些安全但平庸的默认解。
|
|
16
|
+
6. `medium_grammar`:构图、节奏、动效、材质、语言或声音如何承载命题。
|
|
17
|
+
7. `surprise_budget`:允许陌生到什么程度,哪些边界不可牺牲。
|
|
18
|
+
8. `anti_fixation`:至少一个主动打破首个构想的约束。
|
|
19
|
+
9. `verification_lens`:不看阐述时,怎样从作品与用户行为判断命题成立。
|
|
20
|
+
|
|
21
|
+
如果这些内容不会改变任何构图、交互、资产、语言或验证动作,Stance 无效。
|
|
22
|
+
|
|
23
|
+
## Atelier
|
|
24
|
+
|
|
25
|
+
1. 在修改前冻结真实基线。
|
|
26
|
+
2. 定义至少两个会改变用户体验机制的差异轴。
|
|
27
|
+
3. 独立产生媒介原型;换色、换皮、同义改写不算不同候选。
|
|
28
|
+
4. 每个候选先过 Reliability Floor,再进入质量比较。
|
|
29
|
+
5. 交换顺序或隐藏来源进行比较;没有候选胜过基线时保留基线。
|
|
30
|
+
6. 完整实现胜出机制,观察真实宿主并修正。
|
|
31
|
+
|
|
32
|
+
唯一记录位于 `.loom/vN/09_ATELIER/<intent-id>.json`。每个候选必须绑定
|
|
33
|
+
`stance_revision`;Stance 改变后,旧候选要重新资格检查或归档。
|
|
34
|
+
|
|
35
|
+
## Correction Triage
|
|
36
|
+
|
|
37
|
+
- 当前命题、机制、媒介语法或候选选择失效:写 `corrections[]`,递增
|
|
38
|
+
`stance_revision`。
|
|
39
|
+
- 新用户结果、约束、能力缺口、风险或项目证据:提交带 provenance 的 Capability Graph
|
|
40
|
+
proposal,由 Architect 裁决。
|
|
41
|
+
- Intent、契约或 Doctrine 错误:按 LOOM reflow 回到对应上层。
|
|
42
|
+
- 多个任务经 Quality Proof 重复验证的方法:作为 learning candidate,人工晋升为 Skill;
|
|
43
|
+
只有跨 Intent 的长期创作判断才考虑 Creative Lineage。
|
|
44
|
+
|
|
45
|
+
Author 不能修改 Graph、Intent 或验收标准,也不能裁决自己的 proposal。
|
package/meta/INTENT_LOOP.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
Intent Loop 将一个产品意图变成可验证结果,并在证据不足时回流到真正负责的层。
|
|
4
4
|
|
|
5
5
|
```text
|
|
6
|
-
Doctrine → Intent → Contract
|
|
6
|
+
Doctrine → Intent narrative → Capability Graph → Contract
|
|
7
7
|
→ Expertise Compiler → Quality Arena → Quality Proof
|
|
8
8
|
→ Close or Reflow
|
|
9
9
|
```
|
|
@@ -14,8 +14,8 @@ Doctrine → Intent → Contract
|
|
|
14
14
|
|---|---|
|
|
15
15
|
| 长期价值、卓越标准、反模式 | Weaver |
|
|
16
16
|
| 产品目标、非目标、Intent narrative | Visionary |
|
|
17
|
-
|
|
|
18
|
-
| Expertise Pack
|
|
17
|
+
| Capability Graph、系统边界、Intent DAG、完成/质量契约 | Architect |
|
|
18
|
+
| Expertise Pack、Authorial Stance、Atelier 候选、实现、自测 | Forge |
|
|
19
19
|
| 独立判定、Quality Proof | Keeper |
|
|
20
20
|
|
|
21
21
|
Keeper 不修改契约;Forge 不以实现困难改写 Intent;Visionary 不写 acceptance;Weaver 不拆实施模块。
|
|
@@ -38,11 +38,22 @@ Keeper 不修改契约;Forge 不以实现困难改写 Intent;Visionary 不
|
|
|
38
38
|
- `quality_contract`:相对基线可观察的质量主张与最小有意义差异。
|
|
39
39
|
- `capability_needs`:任务需要的专业认知、工具或审美能力。
|
|
40
40
|
- `creative_scope`:允许探索与不得改变的边界。
|
|
41
|
+
- `quality_strategy`:`adaptive | atelier`,缺失等价于 `adaptive`;Atelier 只用于明确需要作者命题、媒介原型与独立候选比较的结果。
|
|
41
42
|
- `verification_method`:可复现验证方法。
|
|
42
43
|
|
|
43
44
|
`acceptance` 是 Reliability Floor;`quality_contract` 是 Distinctive Ceiling。二者不能合并成一串模糊
|
|
44
45
|
“高质量要求”,否则完成与卓越都无法诚实判定。
|
|
45
46
|
|
|
47
|
+
### 2.1 Capability Graph Gate
|
|
48
|
+
|
|
49
|
+
Capability Graph 在 Vision 与 Intent Map 之间展开:`outcome`、`concern`、`capability`、`risk`、`evidence` 节点及其关系。它不是执行 DAG;未知、调研和分叉留在 Graph,只有边界清楚、可独立验收的结果才进入 Intent。
|
|
50
|
+
|
|
51
|
+
- 所有高影响节点必须路由为 `expand`、`brief`、`intent`、`defer`、`exclude` 或 `covered_by`,不能停留在 `open`。
|
|
52
|
+
- 每个高影响 `outcome` 必须以 `validated_by` 连接到一个有验证计划的 `evidence` 节点。该计划至少声明:结果在何处被观察(`target`)、怎么复现(`procedure`)、什么算通过(`pass_criteria`)、留下什么证据(`artifact`)和由哪个 Intent 产出它。`artifact` 必须是当前版本内 `verifications/` 或 `08_ASSET_LIBRARY/files/` 下真实存在的普通文件;接口可用、文件存在于版本外或 URL 可访问都不能替代目标宿主、用户界面、外部接收方或交付物中的实际可观察结果。
|
|
53
|
+
- 每个当前 Intent 必须由至少一个 Graph 节点的 `intent_refs` 回链;Graph 是这份关联的唯一真相源,避免双写漂移。
|
|
54
|
+
- 需要专业方法、外部知识、研究或即将进入当前 Intent 的能力节点,才使用 `.loom/vN/07_CAPABILITY_BRIEFS/<node-id>.md` 写项目化 Brief。
|
|
55
|
+
- `loom capability coverage` 是 Architect 完成图谱后的门;`loom capability compile <id>` 是 Forge 的只读编译入口。Forge 发现新的缺口必须回流 Architect,不能把猜测静默变成实现范围。
|
|
56
|
+
|
|
46
57
|
## 3. 状态与 revision
|
|
47
58
|
|
|
48
59
|
状态:
|
|
@@ -68,7 +79,7 @@ completed → needs_review → in_progress
|
|
|
68
79
|
3. Hard Invariants
|
|
69
80
|
4. Success Contracts
|
|
70
81
|
5. Project Judgment
|
|
71
|
-
6. Expertise Inputs
|
|
82
|
+
6. Expertise Inputs(含当前 Intent 编译得到的 Capability Graph 节点与 Brief)
|
|
72
83
|
7. Working Facts
|
|
73
84
|
8. Role Contract / Output / Reflow / Stop
|
|
74
85
|
|
|
@@ -83,6 +94,7 @@ loom intent update <id> --status in_progress
|
|
|
83
94
|
```
|
|
84
95
|
|
|
85
96
|
只选择 pending、所有依赖 completed、未弃用的 Intent。一次 Forge 作用域只包含一个当前 Intent。
|
|
97
|
+
进入选择前,Graph coverage 必须没有未路由的高影响节点、无计划能力节点和未映射 Intent。
|
|
86
98
|
|
|
87
99
|
## 6. Expertise Compiler
|
|
88
100
|
|
|
@@ -90,10 +102,41 @@ Forge 在实现前形成临时 Expertise Pack:
|
|
|
90
102
|
|
|
91
103
|
- **Domain**:领域机制、失败边界和项目事实。
|
|
92
104
|
- **Taste**:什么区分普通、可靠和出众。
|
|
105
|
+
- **Author**:这次提出什么可反驳的创作命题,选择什么并拒绝什么。
|
|
93
106
|
- **Critic**:最可能出现的平庸方案、自我欺骗与反例。
|
|
94
107
|
- **Verifier**:如何观察、比较和复现。
|
|
95
108
|
|
|
96
|
-
|
|
109
|
+
这五项是认知功能,不是必须创建五个角色或五份文档。
|
|
110
|
+
|
|
111
|
+
Capability Graph 先提供当前 Intent 相关的项目事实、风险、约束和 Capability Brief;Expertise Compiler 再按 Brief 的获取计划加载真实技能、工具或资料。它不把整张图或历史会话当成当前任务上下文。
|
|
112
|
+
|
|
113
|
+
当 capability 显式为 `external_required`,或高影响 capability 未显式豁免时,External
|
|
114
|
+
Acquisition Gate 启用。Forge 只能自行生成 Search Plan,必须实际使用 find skill、
|
|
115
|
+
网络、官方文档或研究资料获取内容,再把可回查来源与项目化 Capability Capsules 写入
|
|
116
|
+
`.loom/vN/10_EXPERTISE_PACKS/<intent-id>.json`。Graph 不保存固定站点、Skill 或关键词。
|
|
117
|
+
模型记忆、未打开的搜索摘要和自生成原则不能替代来源。Pack 绑定 Intent revision;Keeper
|
|
118
|
+
不继承 Capsule 结论,而是重新打开关键来源并在 passed 记录中绑定当前 Pack。
|
|
119
|
+
|
|
120
|
+
`quality_strategy=atelier` 时运行 Identity Compiler:将项目判断编译为可执行的 Authorial
|
|
121
|
+
Stance,而不是模仿名人的 Persona。Forge 在 `.loom/vN/09_ATELIER/<intent-id>.json`
|
|
122
|
+
保存唯一 Atelier Record;普通 Intent 不创建该文件。
|
|
123
|
+
|
|
124
|
+
### 2.2 Graph Change Proposal Gate
|
|
125
|
+
|
|
126
|
+
新用户要求是 `outcome` 或 `constraint` 候选;论文、资料与运行发现是带 provenance 的 `capability`、`risk` 或 `evidence` 候选。它们先写入 `.loom/vN/07_GRAPH_PROPOSALS/CGP-*.json`,必须记录来源、观察时间、具体证据、为什么现在需要处理。Proposal 不是正式 Graph,Forge/Keeper 不得借它静默扩大当前 Intent。
|
|
127
|
+
|
|
128
|
+
Architect 必须把每个 proposal 判定为:已覆盖、Graph 更新、Intent 变更、acceptance 变更、Minor、Major 或拒绝;关闭时必须提交与决策相符的结构化 resolution,CLI 会从决策时磁盘基线验证 Graph / Intent / acceptance / 决策记录的真实变化或现有有效覆盖,不能以任意 implementation_ref 文本关闭。`constraint` 若决定为 Graph 更新,必须进入正式 Graph 的 `constraints` 字段并回链受影响节点。`covered_by` 必须显式指向另一个已覆盖、非 `covered_by` 路由的节点,并同时保留同目标的关系。`loom guide` 与 `loom doctor` 对未闭合 proposal 回流 Architect。
|
|
129
|
+
|
|
130
|
+
Author 的自我更正不得绕过该门:局部命题、机制、媒介语法或候选选择变化写入 Atelier
|
|
131
|
+
Record `corrections[]` 并递增 `stance_revision`;只有新的用户结果、约束、能力缺口、风险
|
|
132
|
+
或项目证据才提交 Graph proposal。Architect 裁决并修订磁盘真相源后,Capability compile
|
|
133
|
+
把新输入交回 Author。Author 不得裁决自己的 proposal,也不得修改考纲后自证通过。
|
|
134
|
+
|
|
135
|
+
### 2.3 Asset Library Protocol
|
|
136
|
+
|
|
137
|
+
若项目使用图片、音频、视频、模型或其他交付素材,`.loom/vN/08_ASSET_LIBRARY/manifest.json` 与同目录 `files/` 是版本化的一等真相源。每条资产必须有内容派生稳定 ID、kind、中文/其他标签、来源/作者/许可、SHA-256、库内相对路径、status 与 approval。`loom asset import` 只接受明确的本地普通文件、复制后校验哈希,并拒绝路径逃逸、重复字节和未批准/缺少许可元数据。
|
|
138
|
+
|
|
139
|
+
素材字节能下载不等于素材可呈现;远程 URL 不是呈现证据。资产若用于 Capability Graph 的 evidence,资产 `evidence_refs` 与 evidence 节点 `asset_refs` 必须双向一致,Keeper 仍需在目标宿主验证实际呈现。
|
|
97
140
|
|
|
98
141
|
技能、工具和资料必须经历:
|
|
99
142
|
|
|
@@ -123,6 +166,16 @@ Discover → Load → Translate → Use
|
|
|
123
166
|
|
|
124
167
|
候选不强制落盘,不设置固定数量。没有候选胜过基线时,保留原方案或回流契约。
|
|
125
168
|
|
|
169
|
+
### Atelier Path
|
|
170
|
+
|
|
171
|
+
当 `quality_strategy=atelier` 时,Arena 增加明确作者命题与落盘证据:
|
|
172
|
+
|
|
173
|
+
1. 编译 Authorial Stance 并冻结修改前基线。
|
|
174
|
+
2. 定义质量差异轴,独立形成机制不同的媒介原型。
|
|
175
|
+
3. 候选先过 Reliability Floor,再匿名比较或保留基线。
|
|
176
|
+
4. 每个候选绑定 `stance_revision`;Stance 改变后重新资格检查或归档旧候选。
|
|
177
|
+
5. 选择证据、主要代价和 corrections 写入唯一 Atelier Record,再进入完整实现。
|
|
178
|
+
|
|
126
179
|
## 8. Independent Quality Proof
|
|
127
180
|
|
|
128
181
|
Keeper 在独立任务中只加载当前 revision、真实产物、契约、Doctrine 和必要验证工具。不要加载 Forge 的
|
|
@@ -210,6 +263,7 @@ Codex 的 goal/status 用于驱动循环与恢复工作,不是替代上述证
|
|
|
210
263
|
| 长期价值或质量观缺失 | Weaver |
|
|
211
264
|
| 产品目标、非目标或 narrative 错误 | Visionary |
|
|
212
265
|
| 系统边界、依赖、契约不可成立 | Architect |
|
|
266
|
+
| 图谱分支遗漏、能力缺口或高影响节点未路由 | Architect 更新 Capability Graph |
|
|
213
267
|
| 专业能力、候选或实现不足 | Forge |
|
|
214
268
|
| 证据不足、验证偏差或需人类感知 | Keeper |
|
|
215
269
|
|
package/meta/ROLE_ACTIVATION.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
角色是决策权边界,不是人格表演。LOOM 的执行链是:
|
|
4
4
|
|
|
5
5
|
```text
|
|
6
|
-
Doctrine → Intent → Contract → Expertise Compiler
|
|
6
|
+
Doctrine → Intent narrative → Capability Graph → Contract → Expertise Compiler
|
|
7
7
|
→ Quality Arena → Quality Proof → Reflow
|
|
8
8
|
```
|
|
9
9
|
|
|
@@ -18,11 +18,11 @@ Doctrine → Intent → Contract → Expertise Compiler
|
|
|
18
18
|
3. Hard Invariants:BASELINE 摘要与命中的项目底线。
|
|
19
19
|
4. Success Contracts:acceptance、按需的 continuity_required / quality_contract、verification_method;其中状态守恒规则仍只写在 acceptance。
|
|
20
20
|
5. Project Judgment:相关 Doctrine anchors 与决策记录。
|
|
21
|
-
6. Expertise Inputs
|
|
21
|
+
6. Expertise Inputs:当前 Intent 编译得到的 Capability Graph 节点与 Brief、`capability_needs`、`quality_strategy`、可发现的 Skill / 工具 / 资产入口和获取边界;仅当 `quality_strategy=atelier` 时注入 Authorship Method 与 Atelier Record 要求。
|
|
22
22
|
7. Working Facts:相关架构、代码、资产、基线和产物路径。
|
|
23
23
|
8. Output / Reflow / Stop:交付、证据、回流与停止条件。
|
|
24
24
|
|
|
25
|
-
Context Pack 编译器只选择事实和能力入口。Expertise Compiler 在角色激活后检查真实环境,
|
|
25
|
+
Context Pack 编译器只选择事实和能力入口。Capability Graph 保留项目问题面、能力缺口、风险、证据与 Intent 回链;它不是任务列表,只有当前 Intent 关联的节点和 Brief 会进入 Context Pack。Expertise Compiler 在角色激活后检查真实环境,
|
|
26
26
|
再形成 Expertise Pack;看见 Skill 名称不等于已经加载能力。
|
|
27
27
|
|
|
28
28
|
Context Pack 不会清除 Agent 既有记忆。发生冲突时,以 system、developer 和用户指令
|
|
@@ -42,14 +42,18 @@ Context Pack 不会清除 Agent 既有记忆。发生冲突时,以 system、de
|
|
|
42
42
|
|
|
43
43
|
### Architect
|
|
44
44
|
|
|
45
|
-
-
|
|
46
|
-
-
|
|
45
|
+
- 拥有 Capability Graph、系统边界、Intent DAG、公共契约、质量契约和验证入口。
|
|
46
|
+
- 先路由高影响图谱节点并保证每个 Intent 回链,再声明 capability_needs 与 creative_scope。
|
|
47
47
|
- 不实现,也不给出通过结论。
|
|
48
48
|
|
|
49
49
|
### Forge
|
|
50
50
|
|
|
51
51
|
- 为当前 Intent 编译 Expertise Pack,运行 Quality Arena 并完成实现和自测。
|
|
52
52
|
- 可以做必要局部设计、错误处理和可逆探索。
|
|
53
|
+
- `quality_strategy=atelier` 时增加 Author 认知职能:用 Identity Compiler 形成可反驳的
|
|
54
|
+
Authorial Stance,并将基线、候选、修正和选择写入唯一 Atelier Record。
|
|
55
|
+
- 局部创作假设更正只递增 `stance_revision`;结构性新发现提交 Capability Graph proposal,
|
|
56
|
+
由 Architect 裁决后再经 Capability compile 进入下一版 Stance。
|
|
53
57
|
- 不改变上层目标、公共契约或架构边界。
|
|
54
58
|
|
|
55
59
|
### Keeper
|
|
@@ -62,7 +66,13 @@ Context Pack 不会清除 Agent 既有记忆。发生冲突时,以 system、de
|
|
|
62
66
|
### Expertise Compiler
|
|
63
67
|
|
|
64
68
|
按任务组合项目事实、Skill、工具、资产、参考、质量机制、失败模型与验证手段,输出临时
|
|
65
|
-
Expertise Pack。Domain、Taste、Critic、Verifier 是按需认知职能,不是新增角色。
|
|
69
|
+
Expertise Pack。Domain、Taste、Author、Critic、Verifier 是按需认知职能,不是新增角色。
|
|
70
|
+
Author 只在需要形成创作命题时启用,不是常驻 Persona。
|
|
71
|
+
|
|
72
|
+
未显式豁免的高影响专业能力会让 Context Pack 先打开 External Acquisition Gate:Forge
|
|
73
|
+
从项目事实派生查询并实际检索,将来源化 Capability Capsules 写入当前
|
|
74
|
+
Intent revision 的 `10_EXPERTISE_PACKS`;门闭合后才注入 Author/Atelier。Keeper 只接收
|
|
75
|
+
Pack 的证据入口和计数,必须独立重开关键来源,不继承 Forge 的综合结论。
|
|
66
76
|
|
|
67
77
|
### Quality Arena
|
|
68
78
|
|
|
@@ -79,6 +89,7 @@ Reliability Floor,质量契约是 Distinctive Ceiling。没有候选胜过基
|
|
|
79
89
|
|
|
80
90
|
- 实现错误、遗漏或局部质量不足 → Forge。
|
|
81
91
|
- acceptance、verification_method、依赖或架构错误 → Architect。
|
|
92
|
+
- 项目问题面遗漏、能力缺口或图谱回链缺失 → Architect 更新 Capability Graph。
|
|
82
93
|
- 目标、非目标或 narrative 错误 → Visionary。
|
|
83
94
|
- 长期项目原则持续失效 → Weaver / 新版本。
|
|
84
95
|
- 缺少外部授权或主观裁决 → 人类。
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@haaaiawd/loom",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"description": "LOOM — 哲学驱动开发框架。Agent 通过 CLI 访问 Intent Map / 哲学 / 验证记录,不直接读文件",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -12,10 +12,16 @@
|
|
|
12
12
|
"cli/help",
|
|
13
13
|
"meta",
|
|
14
14
|
"roles",
|
|
15
|
-
"templates",
|
|
16
|
-
"dimensions",
|
|
17
|
-
"README.md"
|
|
18
|
-
|
|
15
|
+
"templates",
|
|
16
|
+
"dimensions",
|
|
17
|
+
"README.md",
|
|
18
|
+
"CHANGELOG.md",
|
|
19
|
+
"EXTERNAL_ACQUISITION_DESIGN.md"
|
|
20
|
+
],
|
|
21
|
+
"publishConfig": {
|
|
22
|
+
"access": "public",
|
|
23
|
+
"registry": "https://registry.npmjs.org/"
|
|
24
|
+
},
|
|
19
25
|
"engines": {
|
|
20
26
|
"node": ">=18"
|
|
21
27
|
},
|