diff --git a/cloud/skills/software-engineering/SKILL.md b/cloud/skills/software-engineering/SKILL.md index e792d00..9a0e418 100644 --- a/cloud/skills/software-engineering/SKILL.md +++ b/cloud/skills/software-engineering/SKILL.md @@ -175,7 +175,7 @@ G4 分阶段不是“慢”,是止损:web 先行验证核心链路和契约 |----|------|----------|--------------| | G0 | 接单选型冻结 | 客户端清单、目标用户、核心能力、MVP 范围、路线(真原生 / 跨平台壳 + Web 核心)都已由用户确认;**且 agent 类产品必须同时确认执行模型、权限边界、审批模型**(见下);**且仓库冻结项已确认:仓库是新建还是已有、GitHub owner/repo、默认分支、可见性** | 不开任何开发线程,继续问 | | G0.5 | 建仓完成 | 新产品已建仓且首 commit 已落默认分支(首 commit 只含仓库骨架,不含业务代码);已有仓库已核对 owner/repo、默认分支、可见性与 PRD 一致 | G1 不开始,先建仓或先改 PRD | -| G1 | PRD 冻结 | PRD 按 `templates/artifacts/prd-outline.md` 写完,用户故事有验收标准,不做清单已写明;**agent 类产品必须有能力边界、失败故事、成本故事三节** | 回产品线程改,不进入设计 | +| G1 | PRD 冻结 | PRD 按产品经理附录章节所列大纲写完,用户故事有验收标准,不做清单已写明;**agent 类产品必须有能力边界、失败故事、成本故事三节** | 回产品线程改,不进入设计 | | G2 | 契约冻结 | API 契约、数据模型、agent 协议、错误码、鉴权方式已定稿,版本号为 v1;**且必须有任务状态机、错误 taxonomy、技术栈表、每端能力矩阵四份冻结物** | 客户端线程不准开工 | | G3 | 共享核心完成 | 共享类型、API SDK、鉴权与同步逻辑可被客户端引用,有单测;**且有可跑的 mock 服务和契约测试** | 客户端线程等共享线程,不自己各写一套 | | G3.5 | 可行性 spike 通过 | 核心链路在真实(或最接近真实的)环境里跑通:以 agent 工具为例,任务能创建、能跑出进度、能取消、能回结果;跑不通的原因已定位到模型、沙箱、后端三者之一 | 不进入 G4,先修核心链路或缩 MVP,不扩端摊成本 | @@ -320,7 +320,7 @@ G8 在 G7 之后,派生迭代线程(附录 10-iteration)。G8 的完成 ## 接单选型:协调员第一件事是问,不是写代码 用户只说“做一款 agent 工具”时,协调员必须先问清下面这些,再建项目。 -问卷模板在 `templates/artifacts/intake-questions.md`。最关键的六问: +最关键的六问: 1. 目标用户是谁,agent 工具最核心的一到三个能力是什么? 2. 需要哪些客户端?v0.5 默认只问 web(React、多视口自适应): @@ -601,7 +601,6 @@ tests/ # QA 线程专属,含跨端一致性用例 - 未编译 / 未验证的 QA 口径要写死:iOS / Android 原生后置占位 不进 QA 通过表;Mac 在 Linux 主机上编不出来时,QA 结论写 “代码评审 + Web 核心验证”,不写“构建通过”,不写“已发布”。 -- 验收清单模板在 `templates/artifacts/acceptance-checklist.md`。 验收人是用户,协调员只负责把清单和 web 演示产物准备好, 不能代替用户勾选通过。验收和发布为 web 单端: web 演示可真跑;iOS / Android 原生只留后置占位,不进本轮发布; @@ -627,10 +626,6 @@ tests/ # QA 线程专属,含跨端一致性用例 较经济的模型,具体以项目实际可用模型和配额为准; 配额将满时先停新线程,不先透支再解释。 -> 临时版(v2 provisional,待用户确认后才算定):本节源自首轮草稿 -> `code-to10-skill/v05-QA-viewport-rewrite-DRAFT.md` 的视口版 QA 全链路, -> 插在“失败、续跑与成本”末尾;原文的跨端版仍属 #244 停下点, -> 本临时版不替用户定 B4 的最终措辞,改动清单对照表见草稿原文。 ## QA 全链路(视口版):测试环节跑通各个和所有业务链路 @@ -1443,7 +1438,7 @@ G8 的交付物是 v1.1 交接清单终版与下一轮 G0-G6 输入冻结清单 ## 产出 -按 `templates/artifacts/prd-outline.md` 写一份 PRD,至少包含: +按下面大纲写一份 PRD,至少包含: 1. 目标用户和核心场景(不超过 3 个核心能力)。 2. 用户故事,每个故事都有可检验的验收标准(能做什么、做到什么程度算通过)。 @@ -1490,7 +1485,7 @@ G8 的交付物是 v1.1 交接清单终版与下一轮 G0-G6 输入冻结清单 3. 数据模型:核心实体、字段、关系、同步冲突时以哪端为准。 4. Agent 协议:如果产品含 agent 能力,写清任务创建、执行、状态、取消、 超时、失败重试的协议,不要让各客户端自己发明一套。 - 协议模板见 `templates/artifacts/` 下的 agent 任务契约模板。 + (Agent 协议、状态机、错误 taxonomy 的要素见本章第 4、5、6 项。) 5. 任务状态机:至少包含创建、排队、运行中、等审批、已完成、已取消、失败、超时, 每个状态的进入条件、退出条件、可执行操作都要写清。 6. 错误 taxonomy:至少区分模型失败、工具失败、用户取消、超时、权限拒绝、配额超限, @@ -1753,7 +1748,7 @@ iOS / Android 原生后置占位不进 QA 通过表,标注“未编译 / 未 ## 协调员准备 -1. 按 `templates/artifacts/acceptance-checklist.md` 生成本项目的验收清单, +1. 按 PRD 验收标准生成本项目的验收清单, 每一项对应 PRD 里的一条验收标准,不额外加、不悄悄删。 2. 为 web 单端准备一份演示产物:怎么启动、测哪个核心流程、 已知问题是什么、哪些平台未编译验证。web 演示可真跑; diff --git a/cloud/tests/test_skill_transplant_prep.py b/cloud/tests/test_skill_transplant_prep.py index c8ca005..e9d485c 100644 --- a/cloud/tests/test_skill_transplant_prep.py +++ b/cloud/tests/test_skill_transplant_prep.py @@ -10,8 +10,8 @@ What this pins (see TRANSPLANT-PREP-244.md next to the skill): - check-transplanted passes on those drafts and fails when an artifact reference survives or a preserved marker is dropped; - apply fails loudly when a required anchor is missing; -- the real pack in this tree (v0.2 + #244 line) still carries exactly - the six known templates/artifacts/ reference lines, so the +- the real pack in this tree carries zero templates/artifacts/ + reference lines after the user-signed v5 deletion, so the decision-B inventory cannot drift silently. Fixture texts are built from the script's own fragment constants, so @@ -278,10 +278,12 @@ class TransplantPrepTestCase(unittest.TestCase): capture_output=True, text=True) self.assertNotEqual(check.returncode, 0) - def test_real_pack_artifact_inventory_is_six_lines(self): + def test_real_pack_artifact_inventory_is_zero_after_signed_deletion(self): + # v5 用户定稿(2026-11-02):§4 的 6 处引用经用户签字删除, + # 本测试由“钉住 6 处”改为“钉住 0 处”,防止删除后悄悄回潮。 text = SKILL_MD.read_text(encoding="utf-8") refs = [l for l in text.split("\n") if "templates/artifacts" in l] - self.assertEqual(len(refs), 6, refs) + self.assertEqual(len(refs), 0, refs) self.assertIn("## 独立审计与自动推回", text) # 集成基底章节表:审计章在 v0.5 表里编号为 11-auditor #(00–08 + 09-ops + 10-iteration + 11-auditor), diff --git a/cloud/workers.py b/cloud/workers.py index b17a1cc..6dc1782 100644 --- a/cloud/workers.py +++ b/cloud/workers.py @@ -443,13 +443,11 @@ def _default_kill(pid): def _default_audit(db_path, action, detail): """默认审计:user_id=system、project_id="",经统一审计口写。 - 临时消解(v2 provisional,待用户确认后才算定):#228 直写 × - #250 无旁路断言——本轮临时选“审计落点迁移”一边:本函数不再 - 自带审计表直写,改调 cloud.auth 的统一审计口(该口写 legacy - 审计行 + 防篡改账本链条目同一对,落点只增链条目、不丢旧行)。 - 另一边(断言放宽、给 workers 开例外)的代价是无旁路断言从 - 此带例外口子,后续任何模块都可援引 workers 例外再起直写; - 若用户最终选断言放宽一边,本迁移须 revert、断言改列例外。 + 已确认(v5 用户定稿 2026-11-02):#228 直写 × #250 无旁路断言—— + 定稿选“审计落点迁移”一边:本函数不再自带审计表直写,改调 + cloud.auth 的统一审计口(该口写 legacy 审计行 + 防篡改账本链 + 条目同一对,落点只增链条目、不丢旧行)。另一边(断言放宽、 + 给 workers 开例外)未选。 写失败抛给调用方:reap 的杀前审计失败时不杀 (fail-closed),杀后审计失败时只记 audit_after=False。 统一审计口在函数内 import:workers 与 auth 同属控制面, diff --git a/deploy/verify-multiuser.py b/deploy/verify-multiuser.py index 69a6b42..bed66e8 100755 --- a/deploy/verify-multiuser.py +++ b/deploy/verify-multiuser.py @@ -184,12 +184,9 @@ def main(): finally: conn.close() if len(created_task_ids) >= 1: - # 临时消解(v2 provisional,待用户确认后才算定):#240 硬门禁 × - # #263 验证脚本——本轮临时选“验证脚本补门禁证据”一边, - # 门禁默认 hard 一字不动。另一边(门禁给验证场景开口子) - # 的代价是硬门禁出现调用方可走的例外路径,fail-closed - # 语义即被开口;若用户最终选开口子一边,本处证据须随 - # 门禁语义重定,不可两边同时要。 + # 已确认(v5 用户定稿 2026-11-02):#240 硬门禁 × #263 验证 + # 脚本——定稿选“验证脚本补门禁证据”一边,门禁默认 hard + # 一字不动。另一边(门禁给验证场景开口子)未选。 # 证据说明(合成任务的真实值,不是编造的通过凭证): # 合成任务未跑模型、未改任何仓库文件,故 files_changed # 为空清单;owned_dir 沿用既定测试口径的拥有目录写法, diff --git a/host.py b/host.py index 9527e48..fce2260 100644 --- a/host.py +++ b/host.py @@ -1422,12 +1422,9 @@ VERIFY_COMMAND_ALLOWLIST = frozenset({ # “白名单不是沙箱”)、cd/export/time(shell 内建,改 cwd/环境, # 请用 VAR=val cmd 形态或 host 自身的 cwd)。 # -# 临时消解(v2 provisional,待用户确认后才算定):#256 白名单 × -# #263 旧 shell 语义碰撞——本轮临时选“白名单扩围”一边,见下 -# _VERIFY_SHELL_BUILTINS。另一边(旧测试按新语义更新:管道改 -# grep、exit 3 改 python3 -c sys.exit)的代价是丢掉“任意退出码 -# + 管道过滤器”这组旧 shell 语义的直接证据,且改的是 #263 已 -# 定测试的期望;若用户最终选旧测试更新一边,本处扩围须 revert。 +# 已确认(v5 用户定稿 2026-11-02):#256 白名单 × #263 旧 shell +# 语义碰撞——定稿选“白名单扩围”一边,见下 _VERIFY_SHELL_BUILTINS。 +# 另一边(旧测试按新语义更新)未选。 _VERIFY_DENIED_RC = 126 # 仅有的白名单内建命令:exit。它不是外部程序(simple 路走 # shell=False 会因找不到可执行文件而抛错),只能走 shell 路;