huawu矿业项目评估原型:架构与共享契约
版本:v1.1 / 评审稿
日期:2026年10月6日
依据:需求基线、功能SPEC、交互设计v1.1 ;新增Z.ai整合说明v1.1及Astra方案v2.0
状态:待进入开发;本文件定义建议架构,不表示实现已完成
v1.1修订说明:原章节仍定义首期模拟范围;末章补充后续Z.ai模型及专项训练设计。没有新增首期真实服务,也没有实施或验收后续能力。
1. 首期架构决定
使用原生HTML、CSS和浏览器JavaScript模块实现单页工作台。静态托管,无后台、账号、数据库、真实AI或外部数据服务。内置4个案例,各设备浏览器本地保存。
计算、领域状态和持久化各自集中在一个模块,页面共用;同一金额不会由页面、报告、比较各算一遍。模块的interface包括输入、输出、不变量及错误行为,以下契约是并行开发的共同依据。
不采用微服务、消息队列、图数据库、知识库框架、复杂前端状态库、插件系统或多个存储adapter。生产阶段是否采用这些工具另行评估。
A-01 运行关系
固定资料、参数和版本
读取/恢复当前工作区
证据、任务、费用、情景
同一数据与公式
本地保存读取与写入由存储模块承担;页面发出命令,应用入口调用领域模块生成新工作区,写入成功后才显示已保存。报告快照是工作区的版本记录,不是另一套计算系统。
2. 文件与责任范围
以下为计划目录,目前不创建产品文件。
| 文件/目录 | 职责 | 负责人 |
|---|---|---|
| prototype/index.html | 语义骨架、模块入口、演示说明 | 集成负责人 |
| prototype/app.js | 路由、全局工作区、命令调度、保存与错误提示 | 集成负责人 |
| prototype/styles.css | 全局设计变量、页面、移动与打印样式 | 集成负责人 |
| prototype/data/seed.js | 冻结的模拟资料与案例初值,唯一数据源 | 集成负责人 |
| prototype/core/finance.js | 投资退出及开发参照计算,无DOM与存储 | Agent A |
| prototype/core/domain.js | 命令、核验、任务依赖、台账、版本和摘要 | Agent A |
| prototype/core/storage.js | 本地存储验证、恢复保护与并发标签页检测辅助 | Agent A |
| prototype/views/projects.js | 项目池及项目总览 | Agent B |
| prototype/views/diligence.js | 资料、证据、风险、任务与造假重建界面 | Agent B |
| prototype/views/economics.js | 投资退出、开发参照及跨项目比较 | Agent C |
| prototype/views/reports.js | 报告、历史对照与独立HTML导出 | Agent C |
| prototype/tests/core.test.mjs | 核心规则与算例,Node原生assert运行 | Agent A |
| prototype/tests/browser.test.mjs | 集成路径、存储、桌面及手机布局检查 | 集成负责人 |
| prototype/package.json | 仅声明浏览器/Node共享ES模块及检查命令,无应用依赖 | 集成负责人 |
| prototype/README.md | 启动、访问来源、保存限制和检查方法 | 集成负责人 |
金额转换、格式化与HTML文本转义等确有多处使用的函数可以由集成负责人放入prototype/ui.js;出现重复后再创建,不为未来需求提前建通用库。具体导出名通过契约补丁统一。
页面模块没有独立后台,也没有独立工作区。最多3个开发agent加1个集成负责人同时活动,适配当前4个并发席位。
3. 模块interfaces
A-02 计算模块
| 函数 | 输入 | 输出与不变量 |
|---|---|---|
| evaluateInvestment(project, scenarioId) | 项目及其中的退出情景 | InvestmentResult;不修改输入,不查询外部数据,不读取DOM或存储 |
| evaluateDevelopment(project) | 待建项目及开发参照输入 | DevelopmentResult;勘探项目返回not_applicable |
| validateModelInputs(project, scenarioId) | 当前模型含null或草稿 | 字段错误与缺项;不抛业务异常,也不把空值补零 |
计算结果结构见第6节。独立算例遵循SPEC第8、9节,不重复定义另一套公式。同一有效输入产生相同输出。
A-03 领域模块
| 函数 | 输入 | 输出与不变量 |
|---|---|---|
| applyCommand(workspace, command, meta) | 当前状态、命令、时间及唯一事件ID | {ok, workspace, changedProjectIds, error};失败时原工作区不变 |
| summarizeProject(project) | 证据、风险、任务和模型状态 | 文字摘要与质量状态;不是收购决策 |
| validateWorkspace(value) | 待恢复的普通对象 | {ok, errors},含版本、结构、引用及数值检查 |
meta为{now, eventId},由入口用平台标准时间与ID提供;测试传入固定值。模块不自行创建真实操作者、时间或随机事件。项目更新采用新对象,旧快照不被原地修改。
A-04 存储模块
| 函数 | 输入 | 输出与不变量 |
|---|---|---|
| loadWorkspace(storage) | 浏览器localStorage对象或测试用对象 | ready/empty/corrupt/incompatible/unavailable,加data或原始文本,不写入 |
| saveWorkspace(storage, workspace, expectedToken) | 新状态、上次确认的保存令牌 | saved/conflict/unavailable/quota_exceeded,成功返回新令牌与保存时间 |
| resetStoredWorkspace(storage, workspace, expectedToken) | 用户已确认重置后的状态 | 同save规则;不绕过冲突检查 |
本地保存采用同步写入,在4案例体量下无需缓存、队列或后台worker。expectedToken在读取时由持久化envelope取得;空存储的预期令牌为null。写入前重新读取并检查令牌,避免常见旧标签页覆盖。localStorage不提供跨标签页原子CAS,极短同时写入仍存在竞争;首期明确限制为单活跃编辑标签页,检测到其他标签页写入即暂停写入并提示重新载入,不宣称强一致或协作能力。
若接口需要改变,先提交契约变更说明,再同步调用方;agent不得自行改名或增加第二种格式。
4. 页面与入口契约
A-05 页面渲染
每个页面导出render(container, context),并只负责其挂载节点内的内容。context包含:workspace只读快照、route、dispatch(command)、navigate(route)。页面可调用统一计算模块,但不自己计算金额或写localStorage。
projects.js支持portfolio和overview两种路由;diligence.js支持evidence、risks、actions;economics.js支持valuation和compare;reports.js支持report与history。页面选择通过route.view区分,不在每页重复全局导航。
事件绑定仅限新创建的节点。切换时入口替换旧页面节点,不注册遗留的window监听;存储事件、全局键盘与路由监听归入口一次注册。界面共用CSS由入口负责人维护,各agent提供类名清单和必要样式请求。
用户文本用textContent或统一转义输出。HTML导出模板允许静态结构,所有数据先转义,不把用户输入作为可执行HTML。
A-06 路由
路由字段:{view, projectId?, documentId?, page?, selectedProjectIds?}。可使用hash表达,避免静态托管深路径404。projectId不合法显示找不到项目及返回入口,不自动打开另一个项目。
切换项目保留工作区,不继承其他项目的当前证据或估值参数。路由及筛选是界面状态,不计入项目评估revision;过滤条件可在本次打开保留,无须纳入持久化业务数据。
5. 工作区与字段契约
A-07 存储envelope
| 字段 | 格式/约束 |
|---|---|
| schemaVersion | 整数1,结构版本 |
| datasetVersion | 字符串sj-demo-1.0,固定案例资料版本 |
| saveToken | 每次成功写入的新唯一字符串 |
| savedAt | ISO时间;界面转为中国时区显示 |
| workspace | 4个project聚合、reportSnapshots、events及drafts |
保存键:sj-mining-demo:workspace:v1。存储键不是秘密。任何备份/复制原始内容仅用于演示,不包含真实资料。不同origin不共享数据。
workspace.projectsById按SJ-A、SJ-B、SJ-C、SJ-D索引。项目聚合包含revision、基础档案、documents、evidence、risks、actions、scenarios、developmentReference、professionalNotes及assessmentStatus。归属对象必须带projectId。
A-08 模型字段
| 对象/字段 | 类型/规则 |
|---|---|
| stage | exploration或preconstruction |
| transactionType | mining_right或company_equity |
| currency | 首期固定CNY |
| assessmentDate | 固定种子2026-10-05;自定义修改须比较页提示不同日期 |
| equityRatioBps | 股权路径1—10000;矿业权路径为null,不当作0% |
| entry | considerationYuan或enterpriseValueYuan/debtYuan/cashYuan,按结构使用 |
| entryCosts | 实际承担费用项数组,每项id、category、amountYuan、coverageNote |
| spendRows | id、actionId可空、month、actualYuan、remainingPlannedYuan、coverageNote |
| exit | month可null、价值字段、债务现金或直接价格、costRows、basis、coverage |
| discountRateBps | null或0—5000;0与空不同 |
| scenarioId | base、downside、upside、delay、blocked、failure或custom-* |
金额以整数元存储,界面单位万元;每行amount可以null。公司实际支出不得再次按权益比例缩放。EV桥接只包含SPEC声明的简化项目。
spendRows区分已发生与预计剩余,两者之和构成该行总预计支出;更新actualYuan时用户确认remainingPlannedYuan,不能自动把计划额再相加。actionId非空时每个行动只能绑定一个费用汇总行;多次确认费用更新原行而非增加新行。不同费用可在该汇总行保留说明,首期不建复杂会计分录。
A-09 证据、风险与任务
| 字段 | 取值/约束 |
|---|---|
| evidence.status | unverified、conflict、verified、rejected、not_applicable |
| risk.findingStatus | pending、confirmed、treated_residual、not_applicable |
| risk.treatment | investigate、pause_scheme、conditional_analysis、price_adjustment、rebuild |
| risk.blocking | 专业意见确认的布尔值;不由地区、总分或AI推定 |
| action.kind | exploration、resource_validation、technical_study、rights_permits |
| action.state | not_started、in_progress、pending_review、achieved、partial、failed、paused |
| action.dependencies | 同项目actionId列表,不能自指、循环或指不存在任务 |
| action.outcomeEvidenceIds | 同项目可打开的模拟证据引用 |
原文值和工作值分开。修改verified证据的工作值会使核验状态回到unverified,保留旧核验意见;新值不能继承旧值的“已核验”。修改前置成果使下游已达成果退回pending_review并显示依赖变化。
A-09.1 字段命名与结构冻结
SPEC第3节定义概念,实际模块字段以下述命名为准,金额字段增加Yuan后缀表示内部单位。种子必须使用同一命名,不让页面自行猜测。
| 聚合 | 固定字段及集合形式 |
|---|---|
| project | id、revision、name、region、country、minerals(字符串数组)、stage、transactionType、targetScope、equityRatioBps、assessmentDate、ownerLabel、description、documents、evidence、risks、actions、scenarios、developmentReference、professionalNotes、assessmentStatus |
| documents | 对象数组;id、projectId、title、version、documentDate、sourceLabel、mock=true、pages({number,text}数组) |
| evidence | 对象数组;id、projectId、documentId、page、quote、topic、originalValue、workingValue、unit、status、reviewerLabel、note、revision |
| risks | 对象数组;id、projectId、category、severity、ruleId、evidenceIds、findingStatus、treatment、blocking、residualNote、note、relatedParameters |
| actions | 对象数组;id、projectId、kind、question、evidenceIds、dependencies、plannedCostYuan、actualCostYuan、plannedMonth、state、outcome、outcomeEvidenceIds、reviewNote、needsRecheck |
| scenarios | 以scenarioId为键的对象;每项id、name、basis、assumptions、entry、entryCosts、spendRows、exit、discountRateBps、coverage、relatedEvidenceIds |
| professionalNotes | {discipline,text,reviewerLabel,updatedAt}数组;可记录不同意见,非审批 |
| reportSnapshots | 工作区级数组;id、projectId、sourceRevision、createdAt、scenarioId、projectSnapshot、investmentResult、developmentResult、limitations |
| events | 工作区级数组;id、projectId可空、time、actionLabel、objectId、oldValue、newValue、reason |
| drafts | 工作区级对象,键为projectId:formId;值为{values,errors,updatedAt} |
入场entry和退出exit中的经济字段见A-08;entryCosts及exit.costRows每项{id,category,amountYuan,coverageNote}。spendRows的actualYuan和remainingPlannedYuan为当前情景的公司支出,行动计划字段与现金流行通过LINK_ACTION_COST显式同步,不静默双向计算。
UPDATE_PROFILE允许name、ownerLabel、description。UPDATE_ACTION允许计划金额/月份、state、outcome、成果引用与reviewNote;实际支出更新使用LINK_ACTION_COST,并同步相同行动actualCostYuan。任务dependencies、核心档案、交易结构、种子原文在首期固定。专业核验意见通过对应命令更新,不用通用表单修改整个对象。
APPLY_MODEL_INPUTS的changes是当前scenario的已列经济字段子集,由领域层逐字段白名单校验;未识别路径拒绝。具体嵌套字段在L0以共享契约文件或JSDoc固定,若需要增加字段,先修订本契约,不由页面agent自创。
6. 统一计算结果与缺项行为
A-10 InvestmentResult
| 字段 | 含义 |
|---|---|
| status | valid、partial、invalid或not_applicable |
| fields | entryConsiderationYuan、totalInvestmentYuan、netRecoveryYuan、profitYuan、moic、holdingMonths、npvYuan;不可算为null |
| cashFlows | 按月份的收入、支出及净额明细 |
| coverage | 完整模拟口径、已知项目口径或待修正 |
| missing | 缺失字段及影响指标 |
| errors | 字段ID与可读错误 |
| assumptions | 退出价值来源、费用范围、权益桥接限制等 |
未设折现率只有npvYuan为null,其他可算指标保持;退出未知时netRecovery/profit/moic/holdingMonths/npv为null,已知投入仍可展示。开发参照返回独立DevelopmentResult,不复用InvestmentResult误混类型。
输入草稿可以无效,保存在drafts中;有效project模型只在提交校验成功后更新。页面显示“草稿待修正,结果为上次有效模型”,不能伪装结果已应用草稿。导出草稿时同时写明无效字段及上次有效结果来源;生成有效快照要求无无效草稿,但允许带明确缺项的partial报告。
7. 命令与状态变化
A-11 公共命令
| 命令 | payload | 领域行为 |
|---|---|---|
| UPDATE_PROFILE | projectId、changes | 仅可编辑名称、负责人标签和说明 |
| REVIEW_EVIDENCE | projectId、evidenceId、status、reviewerLabel、note | 验证引用和必填说明,记录旧新状态 |
| CORRECT_EVIDENCE | projectId、evidenceId、workingValue、reason | 保留原文,核验回未核验,标记分析更新 |
| UPDATE_RISK | projectId、riskId、findingStatus、treatment、blocking、note、evidenceIds | 确认阻断须有证据与专业说明 |
| UPDATE_ACTION | projectId、actionId、changes | 校验依赖、成果依据、费用范围,失效下游复核 |
| LINK_ACTION_COST | projectId、actionId、actualYuan、remainingPlannedYuan、month、note | 唯一费用行更新,重复调用不重复计价 |
| APPLY_MODEL_INPUTS | projectId、scenarioId、changes、reason | 校验后更新有效模型,不自动把资源量转价格 |
| APPLY_PRESET | projectId、presetId | 按SPEC克隆基准生成目标情景,用户确认后应用 |
| SAVE_DRAFT | projectId、formId、values | 保存无效/未提交草稿,不改变有效模型revision |
| CLEAR_DRAFT | projectId、formId | 清除指定草稿,不重置模型 |
| SAVE_OPINION | projectId、discipline、text | 专业意见记录,非投资批准 |
| CREATE_REPORT | projectId、scenarioId | 捕获完整数据、统一结果及当前revision,不改写旧快照 |
| COPY_REPORT_AS_SCHEME | projectId、snapshotId、reason | 复制旧方案到当前分析,产生新revision,保留全部原历史及未关闭风险 |
| RESET_PROJECT | projectId、confirmation | 由入口确认后还原该项目种子、删除该项目快照与事件 |
| RESET_ALL | confirmation | 由入口确认后恢复4项目种子,清除演示修改 |
命令失败返回error={code,field?,message};原工作区不变。未列出的字段更新拒绝,不提供可直接改任意路径的通用PATCH。
用户操作造假重建分支通过上述证据、风险、行动与模型命令完成,不增加“解除造假”命令,也不把引导步骤完成作为专业认定。
revision只在有效业务值改变时增加;CREATE_REPORT记录快照和事件但不改变项目数据revision。重复提交相同值不增加有效revision。snapshot.createdAt及快照ID按meta生成,快照保存输入与结果的深副本。
8. 数据流与错误处理
A-12 正常修改
页面提交 → 校验命令 → 返回新工作区 → 重算相关结果 → 尝试保存 → 渲染页面及保存状态。
业务校验失败保留表单和错误;持久化失败保留新工作区但显示“仅本次打开有效”。错误和成功提示有明确区分,不能业务成功就假定保存成功。
A-13 启动恢复
读取envelope → 校验版本、结构及引用 → 以保存数据启动或加载默认 → 重新计算展示。只在存储不存在时自动用默认;数据损坏和版本不兼容先展示恢复选择,不覆盖原存储。
存储暂时不可用时可以选择临时演示模式,页面持续提示不会保存。首次默认工作区需在可用存储中保存成功后才显示已保存。清理浏览器数据后的“空”无法判断曾有数据被删除,不声称能恢复已清理内容。
A-14 报告快照
生成前冻结项目revision与所选scenarioId → 调用统一计算 → 复制证据、参数、意见和限制 → 写入快照 → 保存工作区 → 阅读/导出。
只有本地保存成功才能宣称快照重开仍存在。导出HTML可在保存失败时继续,但需提示导出的是文件副本,不是工作区备份。
9. 模拟资料及报告安全
模拟全文以普通文本和页结构保存。阅读器突出证据段落时不得直接拼接用户HTML;用文本节点及标记节点实现。
HTML报告离线自包含,引用ID使用项目前缀,避免多份文档相同页码发生锚点冲突。报告通过统一转义处理用户说明、项目名、资料与引用。下载名由项目ID、报告版本及日期组成,不直接用任意用户字符串作为路径。
静态应用只加载同源资源,无外部字体、地图瓦片、遥测或模型服务。不得把模拟页面发给真实AI。真实试点需重新设计权限、数据保密和外部服务策略。
10. 访问、部署与运行
开发通过标准静态服务器访问prototype目录,电脑使用localhost。手机验收使用同源稳定HTTPS静态地址或经明确授权的局域网访问地址;对外发布及网络暴露单独处理,不在文档阶段执行。
首期不要求离线启动应用或安装PWA。应用加载后的本地分析不依赖远程业务服务,导出HTML可离线阅读。file://打开ES模块及本地保存不作为正式运行方式。
固定origin后再验收保存;更改域名、端口或协议会获得另一份本地数据,明确提示。无跨设备同步,手机和电脑独立状态是预期行为。
11. 检查与依赖策略
纯计算及领域检查使用Node内置assert,不引入测试框架;浏览器验证使用已有Playwright运行环境,仅为开发验收工具,不打包进应用。若既有环境不可用,另行记录缺口,不用未执行检查声称通过。
测试穿过第3节的interfaces,不另写一套核心公式作为“实现”。预期金额由SPEC独立算例锁定。报告和比较必须复用finance输出,避免测试只验证页面数字恰好一样。
无构建工具为默认方案;若模块加载或兼容性确有需要,再记录变更与理由。不开多个项目或多个持久化副本以解决页面问题。
12. 架构决定记录
| ADR | 决定 | 依据/限制 |
|---|---|---|
| ADR-01 | 原生浏览器模块+静态托管 | 首期4案例和本地演示足够,无生产后台需求 |
| ADR-02 | localStorage完整工作区 | 数据量小、各设备独立;不保证生产备份或并发事务 |
| ADR-03 | 确定性计算与状态集中 | 页面、比较和报告口径一致,关键错误在同处修正 |
| ADR-04 | 历史快照存输入与输出 | 避免新参数回写旧报告;本地记录非不可篡改审计 |
| ADR-05 | 3个开发agent+集成负责人 | 同时活动不超过4,共享契约先行 |
| ADR-06 | 无IRR、无真实AI、无销售与审批 | 遵守SPEC及首期范围 |
13. 进入开发前的条件
SPEC与本架构字段、命令、接口一致;种子数据与算例在资料契约中冻结;任务文件所有权和依赖明确;验收用例及结果记录格式确定。
本架构、任务拆分和验收计划作为文档阶段产物;用户确认进入开发后,再创建prototype文件、启动开发agent并进行集成。当前不创建应用代码。
14. v1.1:后续模型Module与契约
首期A-01至A-14及schemaVersion=1、sj-demo-1.0不变。新增内容是后续受控后端设计,不把服务器能力暗中装入静态原型。正式存储结构迁移另设版本,不能用本节直接读写首期envelope。
| 契约 | 职责及不变量 |
|---|---|
| A-AI-01 资料与证据 | 保存授权原件、版本及SourceRef;检索先过滤项目/权限,再关键词及必要语义召回;原文不执行指令 |
| A-AI-02 模型任务 | POST创建、GET查询、DELETE请求取消;固定inputRevision和ModelRelease;去重及预算限制集中处理 |
| A-AI-03 领域接合 | AnalysisDraft不调用applyCommand;用户确认后重验revision/证据/单位,才调用既有命令及finance;失败不修改状态 |
| A-AI-04 离线训练/评测 | 获授权样本、项目血缘隔离、底模/配方/数据版本、独立评测和产物加载;不由线上请求改权重 |
| A-AI-05 模型版本 | 版本台账保存许可、快照/适配器哈希、部署路径、支持任务及评测;每次运行锁定,默认升级仅影响新请求 |
小Interface集中承担复杂行为:创建/查询/取消任务、返回统一草稿。调用方不管理提示、服务商错误和检索过滤。内部按实际选定部署实现一个Adapter,底模及专项权重通常以配置切换,不先建多模型调度平台。
后续起点为一个受控后端、授权原件存储、必要元数据与检索。服务身份从受验证会话获取,客户端projectId不是权限证明;长期API密钥只在后端。真实资料/凭据不得存入浏览器localStorage。首期设备独立工作区不自动变成同步系统。
FactCandidate、SourceRef、AnalysisRun、AnalysisDraft、ModelRelease、ReviewRecord的字段、不变量和错误码,以整合说明第4节为唯一共享契约,页面不得自定义另一格式。报告固定输入/证据/模型/计算版本,运行日志默认只存最小必要元数据,敏感载荷保留另获授权。
| ADR | 新决定 | 适用阶段 |
|---|---|---|
| ADR-AI-01 | 在线推理和离线训练分别执行 | 后续试点 |
| ADR-AI-02 | 草稿与已确认业务数据隔离,人工采纳才改领域状态 | 后续试点 |
| ADR-AI-03 | 模型版本冻结且可回滚,历史快照不回写 | 后续试点 |
| ADR-AI-04 | 现成模型优先,训练六门槛达成后实施 | 后续试点 |
超时、取消和输出校验失败保留现有数据;任务恢复或重复提交不可重复写入业务费用。后台权限、真实资料恢复、日志与删除按AT-09/12/14验收,不用首期localStorage检查代替。