abelien-harness 0.4.0 → 0.5.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/.env.example +3 -0
- package/package.json +1 -1
- package/skills/abelien-hardware/SKILL.md +7 -2
- package/skills/abelien-hardware/domain.json +3 -3
- package/skills/abelien-hardware/references/search-index-format.md +10 -0
- package/skills/abelien-hardware/references/search-index-release.md +4 -2
- package/skills/abelien-hardware/references/web-evidence-contract.md +2 -2
- package/skills/abelien-hardware/scripts/electrical.mjs +125 -0
- package/skills/abelien-hardware/scripts/finalize-selection.mjs +5 -1
- package/skills/abelien-hardware/scripts/provider-chain-contract.mjs +10 -6
- package/skills/abelien-hardware/scripts/search-index-release.mjs +30 -17
- package/skills/abelien-hardware/scripts/tos-wiki-search.mjs +4 -2
- package/skills/abelien-hardware/scripts/volc-web-search.mjs +6 -1
- package/skills/abelien-hardware/scripts/web-common.mjs +4 -1
- package/skills/abelien-hardware/scripts/web-provider-chain.mjs +8 -2
- package/skills/abelien-hardware/scripts/web-search-plan.mjs +16 -1
- package/skills/abelien-hardware/scripts/web-search.mjs +4 -2
- package/skills/abelien-hardware-selection/SKILL.md +1 -1
- package/skills/abelien-hardware-selection/domain.json +2 -2
- package/skills/abelien-hardware-selection/references/selection-service-contract.md +20 -1
- package/skills/abelien-hardware-selection/scripts/select.mjs +26 -7
- package/skills/abelien-workspace/domain.json +1 -1
- package/skills/abelien-workspace/references/hardware-journey-orchestration.md +1 -1
- package/skills/abelien-workspace/workflows/definitions/0852e4949f5a6246880c1a26bf5ccaa42f8cda06b960e7c7ce234a0a176878f9.json +229 -0
- package/skills/abelien-workspace/workflows/definitions/7c69ea0d51099b1ae947f08b056ea67f5cad6b40ae8bcb00efb496fa5b9d5ed3.json +149 -0
- package/skills/abelien-workspace/workflows/definitions/9b5c65ad03fdecc0148931a7677cfa684a3fb04ab2738d6f7a1086a2c79ac86c.json +149 -0
- package/skills/abelien-workspace/workflows/definitions/c1b5c6c653f0c4761d51efee923aafbbeea05512e7f35c60f7f7d36ec49fc1d1.json +229 -0
- package/skills/abelien-workspace/workflows/definitions/e391e14c14cb39408a0a9e226ed54ffab7a36badea305ae4a3eafbac8124fc02.json +175 -0
- package/skills/abelien-workspace/workflows/definitions/fd8ce7074e2044985778446e93153864940bb9465471c1c71c41328cefff70bf.json +175 -0
- package/skills/abelien-workspace/workflows/user-journey-hardware-algorithm.json +3 -3
- package/skills/abelien-workspace/workflows/user-journey-hardware-candidates.json +3 -3
- package/skills/abelien-workspace/workflows/user-journey-hardware.json +3 -3
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "abelien-hardware-selection",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "本地硬件选型:真实 TOS 召回、Agent 证据判断与受信资源校验;不是数据库兼容性求解器",
|
|
5
5
|
"resources": ["hardware-selection"],
|
|
6
6
|
"requires": ["abelien-harness", "abelien-hardware"],
|
|
7
7
|
"capabilities": {
|
|
8
8
|
"hardware.select": {
|
|
9
|
-
"description": "回读同需求的真实召回资源,验证 Agent
|
|
9
|
+
"description": "回读同需求的真实召回资源,验证 Agent 选择的型号、数量、逐约束引用与兼容评估(电源与接口可由可信电气数据确定性判定,结构/散热/软件只提示),保存选型、可选尺寸占用摘要与兼容报告;未知不通过门禁",
|
|
10
10
|
"adapter": {
|
|
11
11
|
"type": "module",
|
|
12
12
|
"path": "scripts/select.mjs",
|
|
@@ -20,7 +20,7 @@ proposal 包含 status=verified|needs_confirmation、plan_mode=assemble_new|adap
|
|
|
20
20
|
- quantity 显式给出且等于槽位数量,不默认补 1;每槽位最多一个型号。
|
|
21
21
|
- selection_reason 非空;wiki_evidence 为完整 Wiki 中至少 8 字符的原文引用数组,不是 ID、ETag 或自由改写摘要。
|
|
22
22
|
- constraint_checks 逐项包含 constraint_id、status=verified|unknown|incompatible、reason、evidence:[{component_id,quote}]。ID 覆盖 function、slot:<hard_constraints 的键>、limit:<每项 hard limit.id>。缺关键证据仍 unknown。
|
|
23
|
-
-
|
|
23
|
+
- 多型号须为 power、interfaces 提供 compatibility_checks(dimension/status/reason/evidence,每个所选型号都有原文证据),除非可信电气数据已确定性通过;mechanical、thermal、software 可选填写,只作提示。见下文“电气兼容与兼容报告”。
|
|
24
24
|
|
|
25
25
|
constraint_checks 非数组、ID 重复或不属于当前槽位时仍以 VALIDATION 拒绝。error.message 列明 slot_id、expected(当前槽位的 function / slot 键与全局 hard limit ID)、received(完整原顺序,非数组为 null)、unexpected(去重、首次出现顺序)与 duplicate(去重、首次重复顺序),供既有 Web 预检 issues 原样反馈并修正。其他槽位具有某个 hard_constraints 键,不使它成为当前槽位的有效 ID;例如 desk-sensor 的 slot:no-stand 不能用于缺少该键的 weather-display。只缺少某项检查仍走 CONSTRAINT_UNVERIFIED、needs_confirmation,不因诊断改为结构拒绝;Wiki 归属、incompatible 和门禁语义不变。
|
|
26
26
|
|
|
@@ -66,3 +66,22 @@ limits 可附 envelope;严格形状与来源规则见 [索引尺寸契约](../
|
|
|
66
66
|
每个型号额外携带可信候选 title 派生的 name、dimensions_mm、dimension_basis、dimension_geometry、dimension_source 和 dimension_check;interfaces 只在候选存在时透传。bom_item_id 为 `selection-line-<24hex>`,以 slot_id/component_id 派生的稳定选型行身份,不冒称数据库 BOM 主键,不使用模型提供的 ID。
|
|
67
67
|
|
|
68
68
|
有 envelope 时输出增加可选 occupancy:advisory=true、method、estimated_volume_mm3、unknown_lines、containers(limit_id/cavity_volume_mm3/ratio)。只统计 selected_models 的实际数量,按 bom_item_id 去重,不再次加入 coverage_ledger 的整机内部覆盖。它是包围体积估算,非装箱证明;unknown 基础的占位尺寸不计入体积,仅保留 unknown_lines;全未知时不输出容器密度。部分未知时体积/比例只含已知或显式估算行,不代表整体密度。浮点溢出/下溢等不可表示的几何量保持 unknown,无法表示的体积或比例省略,不序列化 NaN/Infinity;没有隐含硬阈值。工具函数只在调用方显式提供 occupancy_warning_ratio 策略时给 warning,默认没有告警阈值。接入方须接受这一可选加法,但不得将 occupancy 或 ratio 作为通过/拒绝权威。
|
|
69
|
+
|
|
70
|
+
## 电气兼容与兼容报告
|
|
71
|
+
|
|
72
|
+
多型号选型由 `electrical.mjs` 按星形拓扑做确定性电气检查:选中的唯一主控(`compute-control/controller-board|controller-module`)为中心,`power-energy` 件给主控供电,主控电压轨与已选电源给外设供电,外设所需总线由主控提供。没有主控或主控不止一个时拓扑记为 not_star,全部未知。
|
|
73
|
+
|
|
74
|
+
只有 `electrical.basis` 为 measured / datasheet、且通过 `electrical_source` 源绑定的记录能给出确定结论:
|
|
75
|
+
|
|
76
|
+
| 结果 | 含义 | 门禁 |
|
|
77
|
+
| --- | --- | --- |
|
|
78
|
+
| pass | 全部相关件可信且规则全部通过 | power / interfaces 视为已验证,不再要求逐件原文引用 |
|
|
79
|
+
| fail | 总线类型缺失或数量不足(I2C / SPI / CAN 是共享总线,主控有即可;UART / USB / I2S / PWM / GPIO / ADC 按数量累加) | finalize 与 select 以 VALIDATION 拒绝,须替换一侧 |
|
|
80
|
+
| gap | 可信数据下没有电压轨落在外设或主控的输入范围内 | 记 `ELECTRICAL_SUPPLY_GAP`,返回 needs_confirmation;须补电源或稳压件,不拒绝外设 |
|
|
81
|
+
| risk | 电压只部分重叠、连接器不同、逻辑电平不同且未选电平转换件 | 不确定性判定,回到原文引用路径 |
|
|
82
|
+
| unknown | 数据缺失、未源绑定或非星形 | 回到原文引用路径 |
|
|
83
|
+
|
|
84
|
+
mechanical、thermal、software 只作提示,不进入 unknowns,也不阻止 verified;结构可行性由尺寸粗筛和 CAD 检查负责。任何维度只要模型明确给出 status=incompatible,都记 `COMPATIBILITY_INCOMPATIBLE` 并阻塞。
|
|
85
|
+
|
|
86
|
+
多型号时输出增加可选根字段 `compatibility_report`:`method`、`dimensions`(每维 gate=deterministic|evidence|unverified|advisory、model_status、model_verified,power / interfaces 另有 electrical 结论)和 `electrical`(拓扑、主控与逐条检查)。它是选型依据的说明,不代表实测或制造可行;接入方须显式接收这一可选字段。所选型号原样携带候选的 `electrical` 与 `electrical_source`,不采用模型自填。
|
|
87
|
+
|
|
@@ -3,6 +3,7 @@ import { evaluateDimensions, validateRequirementEnvelopes } from "../../abelien-
|
|
|
3
3
|
import { createHash } from "node:crypto";
|
|
4
4
|
import { mergeHardwareWeb } from "../../abelien-hardware/scripts/web-merge.mjs";
|
|
5
5
|
import { finalizeHardwareSelection } from "../../abelien-hardware/scripts/finalize-selection.mjs";
|
|
6
|
+
import { evaluateElectrical } from "../../abelien-hardware/scripts/electrical.mjs";
|
|
6
7
|
import { canonical, digest, selectionRequestDigest, validateSelectionSlots } from "../../abelien-hardware/scripts/selection-request.mjs";
|
|
7
8
|
const record = value => value && typeof value === "object" && !Array.isArray(value);
|
|
8
9
|
const text = value => typeof value === "string" && value.trim().length > 0;
|
|
@@ -101,12 +102,29 @@ export async function selectHardware({ input, readResource, readBlob }) {
|
|
|
101
102
|
if (recall.retrieval_mode !== "category_index" || recall.unknowns?.length) add("RECALL_INCOMPLETE", { details: recall.unknowns ?? [] });
|
|
102
103
|
const compatibility = proposal.compatibility_checks ?? [];
|
|
103
104
|
if (!Array.isArray(compatibility)) invalid("compatibility_checks must be an array");
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
105
|
+
// Power/interfaces: trusted deterministic pass, or quoted model evidence. Mechanical/thermal/software are advisory
|
|
106
|
+
// (size screening and CAD own mechanical fit); an explicit model "incompatible" still blocks every dimension.
|
|
107
|
+
let compatibilityReport;
|
|
108
|
+
if (models.size > 1) {
|
|
109
|
+
const electrical = evaluateElectrical(normalized.selected_models);
|
|
110
|
+
if (electrical.checks.some(check => check.status === "fail")) invalid("selected components are electrically incompatible");
|
|
111
|
+
const gaps = electrical.checks.filter(check => check.status === "gap");
|
|
112
|
+
if (gaps.length) add("ELECTRICAL_SUPPLY_GAP", { checks: gaps });
|
|
113
|
+
const dimensions = {};
|
|
114
|
+
for (const dimension of ["power", "interfaces", "mechanical", "thermal", "software"]) {
|
|
115
|
+
const checks = compatibility.filter(item => item?.dimension === dimension);
|
|
116
|
+
const modelVerified = checks.length === 1 && checks[0].status === "verified" && text(checks[0].reason)
|
|
117
|
+
&& validQuotes(checks[0].evidence, candidates)
|
|
118
|
+
&& candidates.every(candidate => checks[0].evidence.some(item => item.component_id === candidate.component_id));
|
|
119
|
+
const deterministic = electrical.dimensions[dimension];
|
|
120
|
+
const gate = ["mechanical", "thermal", "software"].includes(dimension) ? "advisory"
|
|
121
|
+
: deterministic === "pass" ? "deterministic" : modelVerified ? "evidence" : "unverified";
|
|
122
|
+
if (gate === "unverified") add("COMPATIBILITY_UNVERIFIED", { dimension, assessments: checks, electrical: deterministic });
|
|
123
|
+
if (checks.some(item => item?.status === "incompatible")) add("COMPATIBILITY_INCOMPATIBLE", { dimension, assessments: checks });
|
|
124
|
+
dimensions[dimension] = { gate, model_status: checks.length === 1 ? String(checks[0].status) : checks.length ? "ambiguous" : "missing",
|
|
125
|
+
model_verified: modelVerified, ...(deterministic !== undefined ? { electrical: deterministic } : {}) };
|
|
126
|
+
}
|
|
127
|
+
compatibilityReport = { method: "compatibility-gate-v1", dimensions, electrical };
|
|
110
128
|
}
|
|
111
129
|
const coverage = slots.map(slot => ({ slot_id: slot.slot_id, requested_quantity: slot.quantity,
|
|
112
130
|
selected_quantity: models.get(slot.slot_id)?.quantity ?? 0,
|
|
@@ -123,6 +141,7 @@ export async function selectHardware({ input, readResource, readBlob }) {
|
|
|
123
141
|
await checkMergedSource();
|
|
124
142
|
const hash = digest({ input, source_digest: digest(source.body) });
|
|
125
143
|
return { ...normalized, id: `selection-${hash.slice(0, 16)}`, revision: `r-${hash.slice(0, 12)}`,
|
|
126
|
-
status, coverage_ledger: coverage, remaining_slots: remaining, unknowns
|
|
144
|
+
status, coverage_ledger: coverage, remaining_slots: remaining, unknowns,
|
|
145
|
+
...(compatibilityReport ? { compatibility_report: compatibilityReport } : {}) };
|
|
127
146
|
}
|
|
128
147
|
export const run = selectHardware;
|
|
@@ -26,4 +26,4 @@ All three new hardware definitions now share `review-hardware-candidates` -> `ha
|
|
|
26
26
|
|
|
27
27
|
Prismer Parse pending holds the original search-hardware-web cursor as awaiting_external; no extract/merge/select runs. The controlled {runId} host resumes the same frozen args/resource with `workflow resume`; task progress uses fixed original-task GET, received synchronous POST results are reused and only undispatched original-plan operations may first POST. Unknown paid effects/failed terminal runs cannot restart. Running SIGKILL snapshots require same-ID latest-checkpoint/source/plan/fence-owner verification; see the hardware evidence architecture for exact fields.
|
|
28
28
|
|
|
29
|
-
|
|
29
|
+
Prismer is temporarily off by default (P2-05.02): the chain saves unsent prismer_disabled markers, searches Volc directly with an English query and Count ≤ 5, and reads sources over public HTTPS (PDF/image sources stay unavailable). When the trusted host enables it, the Prismer-first chain permits one Volc search only after saved definitive primary denial/successful empty query/unsent missing Key. Source denial permits safe direct HTML/plaintext, not a Parse substitute. Saved denial/fallback receipt SIGKILL windows recover in the same run/resource; only original unstarted fallback/source work may first dispatch, and unknown effects remain closed. The v2 host uses the declared pure recovery guard against the trusted original step snapshot; see the architecture.
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "user-journey-hardware-algorithm",
|
|
3
|
+
"domain": "abelien-workspace",
|
|
4
|
+
"executionProtocol": "pinned-result-v1",
|
|
5
|
+
"description": "Library recall, suitability review, fixed Prismer-first/Volc evidence for unresolved slots, source-bound merge, then the same formal hardware.select and gate",
|
|
6
|
+
"input": {
|
|
7
|
+
"required": [
|
|
8
|
+
"requirements",
|
|
9
|
+
"reactions"
|
|
10
|
+
]
|
|
11
|
+
},
|
|
12
|
+
"steps": [
|
|
13
|
+
{
|
|
14
|
+
"id": "record-requirements",
|
|
15
|
+
"executor": "cli",
|
|
16
|
+
"action": "resource.put",
|
|
17
|
+
"args": {
|
|
18
|
+
"kind": "draft",
|
|
19
|
+
"id": "hardware-algorithm-d-{{hash}}",
|
|
20
|
+
"body": {
|
|
21
|
+
"requirements": "{{input.requirements}}",
|
|
22
|
+
"reactions": "{{input.reactions}}"
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
"id": "classify-hardware",
|
|
28
|
+
"executor": "agent",
|
|
29
|
+
"instruction": "需求已澄清;requirements 是 clarify 的 Requirements:context 为落点与场景,reaction[] 为全部触发→反应,limits[] 每项带 strength。按全部 reaction 推导功能槽位与数量,strength=hard 的 limits 进 hard_constraints,preference 只作排序提示;缺 reaction 或只有品类标签时停止并说明。读取同级 abelien-hardware-selection/SKILL.md,并用其 scripts/load-guide.mjs 依次按需加载 entry、命中的 level1、命中的 level2、contract;仅提交功能槽位、数量、受控三级路径和需求硬约束,不提交型号或猜测数据库事实。回复 {\"slots\":[...]};若需求不足或路径不确定,停止并说明,不能伪造槽位。",
|
|
30
|
+
"replySchema": {
|
|
31
|
+
"slots": "array"
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
"id": "search-hardware-wikis",
|
|
36
|
+
"executor": "cli",
|
|
37
|
+
"action": "capability.run",
|
|
38
|
+
"args": {
|
|
39
|
+
"capability": "hardware.search",
|
|
40
|
+
"input": {
|
|
41
|
+
"operation": "search",
|
|
42
|
+
"query": "{{input.requirements}}",
|
|
43
|
+
"requirements": "{{input.requirements}}",
|
|
44
|
+
"slots": "{{steps.classify-hardware.result.slots}}",
|
|
45
|
+
"policy": {
|
|
46
|
+
"prefer_system_candidates": true,
|
|
47
|
+
"top_k_per_slot": 8,
|
|
48
|
+
"include_content": true
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
"id": "hardware-knowledge-recalled",
|
|
55
|
+
"executor": "cli",
|
|
56
|
+
"action": "machine.send",
|
|
57
|
+
"args": {
|
|
58
|
+
"machine": "hardware-recall",
|
|
59
|
+
"event": "confirmRecall",
|
|
60
|
+
"instance": "{{steps.search-hardware-wikis.resource.id}}"
|
|
61
|
+
}
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
"id": "review-hardware-candidates",
|
|
65
|
+
"executor": "agent",
|
|
66
|
+
"instruction": "Read the complete library candidates and original requirements/slots. Review suitability against function and every hard constraint. Reply {\"unresolved_slots\":[{\"slot_id\":\"original slot\",\"reason\":\"no candidates or specific reasons all candidates are unsuitable\",\"query\":\"official model search targeting function/category/key hard constraints\",\"count\":10}]}. Every zero-candidate slot requires supplemental search. All unsuitable candidates also require search. Preserve rechargeable built-in battery, wireless charging, and all other original requirements; do not ask the user to drop a requirement because the catalog is empty. unresolved_slots contains only slots that need search. Omit suitable library slots entirely; never add placeholder rows with an empty query or count=0. Return [] when all slots are suitable. Before committing this review, the trusted host validates the full original requirements, slots and recall with validate-web-search-plan.mjs; a VALIDATION reply preserves this pause so the same run can be corrected. Count is optional and a positive integer; Prismer search.topK and return.topK are explicit. Do not apply undocumented Prismer query/result limits or truncate requirements. The trusted fixed Prismer-first policy permits Volc only after a saved definitive denial, successful empty query or unsent missing Key; Volc alone checks its official 1-100 character Query and Count 1-50 at dispatch. Unknown dispatched effects never authorize fallback or a new invocation. Do not supply URLs, credentials, commands or providers. System reuse is optional: poor matches must not force complex whole systems. Concept visuals and the original requirements come first.",
|
|
67
|
+
"replySchema": {
|
|
68
|
+
"unresolved_slots": "array"
|
|
69
|
+
}
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
"id": "search-hardware-web",
|
|
73
|
+
"executor": "cli",
|
|
74
|
+
"action": "capability.run",
|
|
75
|
+
"args": {
|
|
76
|
+
"capability": "hardware.web-search",
|
|
77
|
+
"input": {
|
|
78
|
+
"requirements": "{{input.requirements}}",
|
|
79
|
+
"slots": "{{steps.classify-hardware.result.slots}}",
|
|
80
|
+
"recall_id": "{{steps.search-hardware-wikis.resource.id}}",
|
|
81
|
+
"unresolved_slots": "{{steps.review-hardware-candidates.result.unresolved_slots}}"
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
"id": "extract-web-hardware",
|
|
87
|
+
"executor": "agent",
|
|
88
|
+
"instruction": "When pages contain blob_ref, use resource get <evidenceResourceId> --page <pageId> to read each required full original page; never copy page bodies into replies. Read the persisted hardware-web-evidence pages from search-hardware-web in full. Search Content/snippets/provider official labels are not complete official pages or proof of authority. Extract only manufacturer pages; uncertain source authority remains unknown and third-party mirrors are not official merely because their URL contains a manufacturer domain. Reply {\"candidates\":[{\"slot_id\":\"original slot\",\"page_id\":\"persisted page ID\",\"manufacturer\":\"exact manufacturer\",\"manufacturer_quote\":\"at least 8 source characters\",\"model\":\"exact model\",\"model_quote\":\"at least 8 source characters\",\"parts\":[{\"name\":\"physical part name\",\"name_quote\":\"exact source quote\",\"shape\":\"box|cylinder|sphere|unknown\",\"shape_quote\":\"exact source quote\",\"dimensions_mm\":{\"length\":20,\"width\":12,\"height\":3},\"dimension_quotes\":{\"length\":\"exact quote identifying this part, axis, numeric value and unit\",\"width\":\"exact quote\",\"height\":\"exact quote\"}}]}]}. Quotes must include the exact part/name/shape they support. Each physical part has separate dimensions; cylinders use diameter/height, spheres use diameter. Unknown dimensions are omitted, never invented or defaulted. Conflicting versions and unknown multi-part overall dimensions remain unknown; do not combine contradictory versions. Do not submit page bodies, official/verified/CAD_available/source/geometry claims. Missing reliable pages or no network means candidates empty. This is envelope_only, not true component CAD or engineering verification. For an attributed tuple such as Back Panel: 48mm x 32mm x 0.5mm, add dimensions_quote with the entire exact source string and dimension_axes:[\"length\",\"width\",\"height\"] in original order; dimensions_mm must map each original value/unit to that explicitly declared axis. Preserve alternate imperial tuples in the quote; never use their values as mm or borrow another part's measurements. A 2-value tuple leaves height unknown. A box inferred from dimensions is only an envelope expression: actual part shape and orientation remain unknown. dimension_quotes may be empty for this tuple mode. Never invent coil thickness or total assembly dimensions.",
|
|
89
|
+
"replySchema": {
|
|
90
|
+
"candidates": "array"
|
|
91
|
+
}
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
"id": "merge-hardware-web",
|
|
95
|
+
"executor": "cli",
|
|
96
|
+
"action": "capability.run",
|
|
97
|
+
"args": {
|
|
98
|
+
"capability": "hardware.web-merge",
|
|
99
|
+
"input": {
|
|
100
|
+
"requirements": "{{input.requirements}}",
|
|
101
|
+
"slots": "{{steps.classify-hardware.result.slots}}",
|
|
102
|
+
"recall_id": "{{steps.search-hardware-wikis.resource.id}}",
|
|
103
|
+
"evidence_id": "{{steps.search-hardware-web.resource.id}}",
|
|
104
|
+
"candidates": "{{steps.extract-web-hardware.result.candidates}}"
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
"id": "select-hardware-from-wikis",
|
|
110
|
+
"executor": "agent",
|
|
111
|
+
"instruction": "先读 abelien-hardware-selection/references/selection-service-contract.md 与真实候选的完整 Wiki。每槽位选择一个真实 component_id,显式 quantity 等于槽位 quantity;manufacturer/model 取候选,selection_reason 非空,wiki_evidence 为至少 8 字符的 Wiki 原文引用数组。selected_models 每项需 constraint_checks,覆盖 function、slot:<hard_constraints 的键>、limit:<每项 hard limit.id>;每项包含 constraint_id、status=verified|unknown|incompatible、reason、evidence:[{component_id,quote}]。多型号另给 compatibility_checks:power、interfaces 两维须包含 status、reason、每个型号的原文 evidence,可信电气数据确定性通过时以 compatibility_report 为准;mechanical、thermal、software 只作提示,可选填写,但填 incompatible 仍阻塞。证据不足填 unknown,不可编造。status=verified|needs_confirmation,plan_mode=assemble_new|adapt_system,其余数组 selected_models/coverage_ledger/remaining_slots/unknowns/replacement_plan 必填。先比较整机,但整机继承缺 manifest 必须待确认,不凭文案抵扣数量。verified 只表示 Wiki 证据判断通过,不是独立工程兼容求解或实测,不代表采用。 Read only merge-hardware-web candidates for the final choice. Preserve structured limits.envelope and source strength; dimension metadata/name/selection-line identity are supplied by the trusted finalizer, never invented. Incompatible dimension candidates require replacement; only decision_required (user hard limit, measured/datasheet size, no axis-aligned fit) returns needs_confirmation, other risk/unknown stays advisory and risk candidates rank last. Electrically incompatible candidates (trusted data: missing bus type or count) require replacing one side; ELECTRICAL_SUPPLY_GAP means add a power or regulator part. all_indexed_candidates_rejected is scoped to this indexed category; occupancy is advisory and clear is only coarse single-part screening. Whole-system reuse is optional; a poor match never forces a complex baseline. External IDs are external:<hash>, with source authority and engineering unknowns; envelopes are not component CAD and cannot grant adoption or delivery.",
|
|
112
|
+
"replySchema": {
|
|
113
|
+
"status": "verified|needs_confirmation",
|
|
114
|
+
"plan_mode": "adapt_system|assemble_new",
|
|
115
|
+
"selected_models": "array",
|
|
116
|
+
"coverage_ledger": "array",
|
|
117
|
+
"remaining_slots": "array",
|
|
118
|
+
"unknowns": "array",
|
|
119
|
+
"replacement_plan": "array",
|
|
120
|
+
"compatibility_checks": "array"
|
|
121
|
+
}
|
|
122
|
+
},
|
|
123
|
+
{
|
|
124
|
+
"id": "select-hardware",
|
|
125
|
+
"executor": "cli",
|
|
126
|
+
"action": "capability.run",
|
|
127
|
+
"args": {
|
|
128
|
+
"capability": "hardware.select",
|
|
129
|
+
"input": {
|
|
130
|
+
"requirements": "{{input.requirements}}",
|
|
131
|
+
"slots": "{{steps.classify-hardware.result.slots}}",
|
|
132
|
+
"recall_id": "{{steps.merge-hardware-web.resource.id}}",
|
|
133
|
+
"selection_proposal": "{{steps.select-hardware-from-wikis.result}}"
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
},
|
|
137
|
+
{
|
|
138
|
+
"id": "record-hardware-selection",
|
|
139
|
+
"executor": "cli",
|
|
140
|
+
"action": "resource.update",
|
|
141
|
+
"args": {
|
|
142
|
+
"id": "{{steps.record-requirements.resource.id}}",
|
|
143
|
+
"bodyPatch": {
|
|
144
|
+
"hardwareSelectionId": "{{steps.select-hardware.resource.id}}",
|
|
145
|
+
"hardwareSelectionStatus": "{{steps.select-hardware.result.status}}",
|
|
146
|
+
"hardwareSelectionRevision": "{{steps.select-hardware.result.revision}}",
|
|
147
|
+
"hardwarePlanMode": "{{steps.select-hardware.result.plan_mode}}"
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
},
|
|
151
|
+
{
|
|
152
|
+
"id": "hardware-selected",
|
|
153
|
+
"executor": "cli",
|
|
154
|
+
"action": "machine.send",
|
|
155
|
+
"args": {
|
|
156
|
+
"machine": "hardware-selection",
|
|
157
|
+
"event": "confirmSelection",
|
|
158
|
+
"instance": "{{steps.record-requirements.resource.id}}"
|
|
159
|
+
},
|
|
160
|
+
"completeWhen": {
|
|
161
|
+
"path": "steps.hardware-selected.result.to",
|
|
162
|
+
"equals": "selected_pending_confirmation"
|
|
163
|
+
},
|
|
164
|
+
"completionResult": {
|
|
165
|
+
"selectionId": "{{steps.select-hardware.resource.id}}",
|
|
166
|
+
"selectionStatus": "{{steps.select-hardware.result.status}}",
|
|
167
|
+
"selectionRevision": "{{steps.select-hardware.result.revision}}"
|
|
168
|
+
}
|
|
169
|
+
},
|
|
170
|
+
{
|
|
171
|
+
"id": "research-algorithms",
|
|
172
|
+
"executor": "agent",
|
|
173
|
+
"instruction": "硬件选型已完成。读取同级 abelien-algorithm/SKILL.md 和 references/research-policy.md,并从 context-json 的 select-hardware.resource 读取准确厂商、型号、能力和 Wiki 证据。针对 input.reactions 先检索硬件厂商官方资料,再检索算法或模型官方资料与 Hugging Face;端侧不满足且用户允许联网时才比较成熟云服务。选择每个 reaction 的最合适实现并回复 {\"bindings\":[...],\"candidates\":[...],\"sources\":[...],\"unavailable_sources\":[...],\"unknowns\":[...],\"blocking_unknowns\":[...]};来源必须回读,binding 必须明确 edge、cloud 或 hybrid。",
|
|
174
|
+
"replySchema": {
|
|
175
|
+
"bindings": "array",
|
|
176
|
+
"candidates": "array",
|
|
177
|
+
"sources": "array",
|
|
178
|
+
"unavailable_sources": "array",
|
|
179
|
+
"unknowns": "array",
|
|
180
|
+
"blocking_unknowns": "array"
|
|
181
|
+
}
|
|
182
|
+
},
|
|
183
|
+
{
|
|
184
|
+
"id": "select-algorithms",
|
|
185
|
+
"executor": "cli",
|
|
186
|
+
"action": "capability.run",
|
|
187
|
+
"args": {
|
|
188
|
+
"capability": "algorithm.finalize",
|
|
189
|
+
"input": {
|
|
190
|
+
"operation": "select",
|
|
191
|
+
"hardware_selection_id": "{{steps.select-hardware.resource.id}}",
|
|
192
|
+
"hardware_selection_revision": "{{steps.select-hardware.result.revision}}",
|
|
193
|
+
"requirements": "{{input.requirements}}",
|
|
194
|
+
"reactions": "{{input.reactions}}",
|
|
195
|
+
"research": "{{steps.research-algorithms.result}}"
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
},
|
|
199
|
+
{
|
|
200
|
+
"id": "algorithm-selected",
|
|
201
|
+
"executor": "cli",
|
|
202
|
+
"action": "machine.send",
|
|
203
|
+
"args": {
|
|
204
|
+
"machine": "algorithm-selection",
|
|
205
|
+
"event": "confirmSelection",
|
|
206
|
+
"instance": "{{steps.select-algorithms.resource.id}}"
|
|
207
|
+
}
|
|
208
|
+
},
|
|
209
|
+
{
|
|
210
|
+
"id": "record-algorithm-selection",
|
|
211
|
+
"executor": "cli",
|
|
212
|
+
"action": "resource.update",
|
|
213
|
+
"args": {
|
|
214
|
+
"id": "{{steps.record-requirements.resource.id}}",
|
|
215
|
+
"bodyPatch": {
|
|
216
|
+
"algorithmSelectionId": "{{steps.select-algorithms.resource.id}}",
|
|
217
|
+
"algorithmSelectionStatus": "{{steps.select-algorithms.result.status}}",
|
|
218
|
+
"algorithmSelectionRevision": "{{steps.select-algorithms.result.revision}}"
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
],
|
|
223
|
+
"result": {
|
|
224
|
+
"selectionId": "{{steps.select-hardware.resource.id}}",
|
|
225
|
+
"selectionStatus": "{{steps.select-hardware.result.status}}",
|
|
226
|
+
"selectionRevision": "{{steps.select-hardware.result.revision}}"
|
|
227
|
+
},
|
|
228
|
+
"legacyResume": "read_only"
|
|
229
|
+
}
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "user-journey-hardware-candidates",
|
|
3
|
+
"domain": "abelien-workspace",
|
|
4
|
+
"description": "Library recall, suitability review, fixed Prismer-first/Volc evidence for unresolved slots, source-bound merge, then candidate proposal",
|
|
5
|
+
"input": {
|
|
6
|
+
"required": [
|
|
7
|
+
"requirements"
|
|
8
|
+
]
|
|
9
|
+
},
|
|
10
|
+
"steps": [
|
|
11
|
+
{
|
|
12
|
+
"id": "record-requirements",
|
|
13
|
+
"executor": "cli",
|
|
14
|
+
"action": "resource.put",
|
|
15
|
+
"args": {
|
|
16
|
+
"kind": "draft",
|
|
17
|
+
"id": "hardware-candidates-d-{{hash}}",
|
|
18
|
+
"body": {
|
|
19
|
+
"requirements": "{{input.requirements}}"
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
"id": "classify-hardware",
|
|
25
|
+
"executor": "agent",
|
|
26
|
+
"instruction": "需求已澄清;requirements 是 clarify 交回的 Requirements:context 为落点与场景,reaction[] 为全部触发→反应,limits[] 每项带 strength。按全部 reaction 推导功能槽位与数量,strength=hard 的 limits 进 hard_constraints,preference 只作排序提示;缺 reaction 或只有品类标签时停止并说明。读取同级 abelien-hardware/SKILL.md,并用其 scripts/load-guide.mjs 依次按需加载 entry、命中的 level1、命中的 level2、contract;只提交功能槽位、数量、受控三级路径和本次硬约束。回复 {\"slots\":[...]},不要提交型号。",
|
|
27
|
+
"replySchema": {
|
|
28
|
+
"slots": "array"
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
"id": "search-hardware-wikis",
|
|
33
|
+
"executor": "cli",
|
|
34
|
+
"action": "capability.run",
|
|
35
|
+
"args": {
|
|
36
|
+
"capability": "hardware.search",
|
|
37
|
+
"input": {
|
|
38
|
+
"operation": "search",
|
|
39
|
+
"query": "{{input.requirements}}",
|
|
40
|
+
"requirements": "{{input.requirements}}",
|
|
41
|
+
"slots": "{{steps.classify-hardware.result.slots}}",
|
|
42
|
+
"policy": {
|
|
43
|
+
"prefer_system_candidates": true,
|
|
44
|
+
"top_k_per_slot": 8,
|
|
45
|
+
"include_content": true
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
"id": "hardware-knowledge-recalled",
|
|
52
|
+
"executor": "cli",
|
|
53
|
+
"action": "machine.send",
|
|
54
|
+
"args": {
|
|
55
|
+
"machine": "hardware-recall",
|
|
56
|
+
"event": "confirmRecall",
|
|
57
|
+
"instance": "{{steps.search-hardware-wikis.resource.id}}"
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
"id": "review-hardware-candidates",
|
|
62
|
+
"executor": "agent",
|
|
63
|
+
"instruction": "Read the complete library candidates and original requirements/slots. Review suitability against function and every hard constraint. Reply {\"unresolved_slots\":[{\"slot_id\":\"original slot\",\"reason\":\"no candidates or specific reasons all candidates are unsuitable\",\"query\":\"official model search targeting function/category/key hard constraints\",\"count\":10}]}. Every zero-candidate slot requires supplemental search. All unsuitable candidates also require search. Preserve rechargeable built-in battery, wireless charging, and all other original requirements; do not ask the user to drop a requirement because the catalog is empty. unresolved_slots contains only slots that need search. Omit suitable library slots entirely; never add placeholder rows with an empty query or count=0. Return [] when all slots are suitable. Before committing this review, the trusted host validates the full original requirements, slots and recall with validate-web-search-plan.mjs; a VALIDATION reply preserves this pause so the same run can be corrected. Count is optional and a positive integer; Prismer search.topK and return.topK are explicit. Do not apply undocumented Prismer query/result limits or truncate requirements. The trusted fixed Prismer-first policy permits Volc only after a saved definitive denial, successful empty query or unsent missing Key; Volc alone checks its official 1-100 character Query and Count 1-50 at dispatch. Unknown dispatched effects never authorize fallback or a new invocation. Do not supply URLs, credentials, commands or providers. System reuse is optional: poor matches must not force complex whole systems. Concept visuals and the original requirements come first.",
|
|
64
|
+
"replySchema": {
|
|
65
|
+
"unresolved_slots": "array"
|
|
66
|
+
}
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
"id": "search-hardware-web",
|
|
70
|
+
"executor": "cli",
|
|
71
|
+
"action": "capability.run",
|
|
72
|
+
"args": {
|
|
73
|
+
"capability": "hardware.web-search",
|
|
74
|
+
"input": {
|
|
75
|
+
"requirements": "{{input.requirements}}",
|
|
76
|
+
"slots": "{{steps.classify-hardware.result.slots}}",
|
|
77
|
+
"recall_id": "{{steps.search-hardware-wikis.resource.id}}",
|
|
78
|
+
"unresolved_slots": "{{steps.review-hardware-candidates.result.unresolved_slots}}"
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
"id": "extract-web-hardware",
|
|
84
|
+
"executor": "agent",
|
|
85
|
+
"instruction": "Read the persisted hardware-web-evidence pages from search-hardware-web in full. Search Content/snippets/provider official labels are not complete official pages or proof of authority. Extract only manufacturer pages; uncertain source authority remains unknown and third-party mirrors are not official merely because their URL contains a manufacturer domain. Reply {\"candidates\":[{\"slot_id\":\"original slot\",\"page_id\":\"persisted page ID\",\"manufacturer\":\"exact manufacturer\",\"manufacturer_quote\":\"at least 8 source characters\",\"model\":\"exact model\",\"model_quote\":\"at least 8 source characters\",\"parts\":[{\"name\":\"physical part name\",\"name_quote\":\"exact source quote\",\"shape\":\"box|cylinder|sphere|unknown\",\"shape_quote\":\"exact source quote\",\"dimensions_mm\":{\"length\":20,\"width\":12,\"height\":3},\"dimension_quotes\":{\"length\":\"exact quote identifying this part, axis, numeric value and unit\",\"width\":\"exact quote\",\"height\":\"exact quote\"}}]}]}. Quotes must include the exact part/name/shape they support. Each physical part has separate dimensions; cylinders use diameter/height, spheres use diameter. Unknown dimensions are omitted, never invented or defaulted. Conflicting versions and unknown multi-part overall dimensions remain unknown; do not combine contradictory versions. Do not submit page bodies, official/verified/CAD_available/source/geometry claims. Missing reliable pages or no network means candidates empty. This is envelope_only, not true component CAD or engineering verification. For an attributed tuple such as Back Panel: 48mm x 32mm x 0.5mm, add dimensions_quote with the entire exact source string and dimension_axes:[\"length\",\"width\",\"height\"] in original order; dimensions_mm must map each original value/unit to that explicitly declared axis. Preserve alternate imperial tuples in the quote; never use their values as mm or borrow another part's measurements. A 2-value tuple leaves height unknown. A box inferred from dimensions is only an envelope expression: actual part shape and orientation remain unknown. dimension_quotes may be empty for this tuple mode. Never invent coil thickness or total assembly dimensions.",
|
|
86
|
+
"replySchema": {
|
|
87
|
+
"candidates": "array"
|
|
88
|
+
}
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
"id": "merge-hardware-web",
|
|
92
|
+
"executor": "cli",
|
|
93
|
+
"action": "capability.run",
|
|
94
|
+
"args": {
|
|
95
|
+
"capability": "hardware.web-merge",
|
|
96
|
+
"input": {
|
|
97
|
+
"requirements": "{{input.requirements}}",
|
|
98
|
+
"slots": "{{steps.classify-hardware.result.slots}}",
|
|
99
|
+
"recall_id": "{{steps.search-hardware-wikis.resource.id}}",
|
|
100
|
+
"evidence_id": "{{steps.search-hardware-web.resource.id}}",
|
|
101
|
+
"candidates": "{{steps.extract-web-hardware.result.candidates}}"
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
},
|
|
105
|
+
{
|
|
106
|
+
"id": "select-hardware-from-wikis",
|
|
107
|
+
"executor": "agent",
|
|
108
|
+
"instruction": "读取 context-json 中 merge-hardware-web 的候选和完整 Wiki;按用户硬约束、功能覆盖与整机覆盖先提出可复用整机候选,再为剩余槽位选择零部件,并检查接口、供电、机械、热和软件依赖。只选择候选中的 component_id,不按 draft、selection_gate 或 CAD 状态过滤。召回结果里 unmatched_slots 列出的槽位一个候选都没有:这些槽位必须逐条写进 remaining_slots,status 只能是 needs_confirmation——finalize 会拒绝把无候选槽位静默丢掉的「完整」提案。回复 {\"status\":\"proposed|needs_confirmation\",\"plan_mode\":\"adapt_system|assemble_new\",\"selected_models\":[...],\"coverage_ledger\":[...],\"remaining_slots\":[...],\"unknowns\":[...],\"replacement_plan\":[...]},每个型号带 slot_id、component_id(候选中的真实值)、manufacturer、model、quantity(1–128 的整数,本槽位实际要用几个,缺失或非整数会被 finalize 拒绝)、selection_reason(字符串)和 wiki_evidence(非空字符串数组,逐条引用该候选完整 Wiki 中支持此选择的原文要点);coverage_ledger、remaining_slots、unknowns、replacement_plan 均为数组,没有内容时给空数组。 提案不具有正式选型权限;不能提交 hardware-selected 或据此开始算法选型,须另走 hardware.select。 Read only merge-hardware-web candidates for the final choice. Preserve structured limits.envelope and source strength; dimension metadata/name/selection-line identity are supplied by the trusted finalizer, never invented. Incompatible dimension candidates require replacement; only decision_required (user hard limit, measured/datasheet size, no axis-aligned fit) returns needs_confirmation, other risk/unknown stays advisory and risk candidates rank last. Electrically incompatible candidates (trusted data: missing bus type or count) require replacing one side; ELECTRICAL_SUPPLY_GAP means add a power or regulator part. all_indexed_candidates_rejected is scoped to this indexed category; occupancy is advisory and clear is only coarse single-part screening. Whole-system reuse is optional; a poor match never forces a complex baseline. External IDs are external:<hash>, with source authority and engineering unknowns; envelopes are not component CAD and cannot grant adoption or delivery.",
|
|
109
|
+
"replySchema": {
|
|
110
|
+
"status": "proposed|needs_confirmation",
|
|
111
|
+
"plan_mode": "adapt_system|assemble_new",
|
|
112
|
+
"selected_models": "array",
|
|
113
|
+
"coverage_ledger": "array",
|
|
114
|
+
"remaining_slots": "array",
|
|
115
|
+
"unknowns": "array",
|
|
116
|
+
"replacement_plan": "array"
|
|
117
|
+
}
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
"id": "finalize-hardware-proposal",
|
|
121
|
+
"executor": "cli",
|
|
122
|
+
"action": "capability.run",
|
|
123
|
+
"args": {
|
|
124
|
+
"capability": "hardware.finalize",
|
|
125
|
+
"input": {
|
|
126
|
+
"operation": "create",
|
|
127
|
+
"planning_mode": "auto",
|
|
128
|
+
"requirements": "{{input.requirements}}",
|
|
129
|
+
"slots": "{{steps.classify-hardware.result.slots}}",
|
|
130
|
+
"knowledge_recall": "{{steps.merge-hardware-web.resource.body}}",
|
|
131
|
+
"selection_proposal": "{{steps.select-hardware-from-wikis.result}}"
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
},
|
|
135
|
+
{
|
|
136
|
+
"id": "record-hardware-proposal",
|
|
137
|
+
"executor": "cli",
|
|
138
|
+
"action": "resource.update",
|
|
139
|
+
"args": {
|
|
140
|
+
"id": "{{steps.record-requirements.resource.id}}",
|
|
141
|
+
"bodyPatch": {
|
|
142
|
+
"hardwareProposalId": "{{steps.finalize-hardware-proposal.resource.id}}",
|
|
143
|
+
"hardwareProposalStatus": "{{steps.finalize-hardware-proposal.result.status}}",
|
|
144
|
+
"hardwareProposalRevision": "{{steps.finalize-hardware-proposal.result.revision}}"
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
]
|
|
149
|
+
}
|