From 8cf461906d38080a5c17b9262a85f801135fcfea Mon Sep 17 00:00:00 2001 From: weichen Date: Mon, 19 Oct 2026 14:38:46 +0000 Subject: [PATCH 01/36] Record the task card for feature-rdm-two-trees-followup Why: establish the authorized task workspace and its initial baseline. Evidence: preserved precheck receipt in .task/feature-rdm-two-trees-followup.md; R0=46e331a7a81c94c6f5881c997ae0aca45664c830. Impact: task metadata only; the feature workspace starts at 46e331a7a81c94c6f5881c997ae0aca45664c830. Refs: .task/feature-rdm-two-trees-followup.md --- .task/feature-rdm-two-trees-followup.md | 159 ++++++++++++++++++++++++ 1 file changed, 159 insertions(+) create mode 100644 .task/feature-rdm-two-trees-followup.md diff --git a/.task/feature-rdm-two-trees-followup.md b/.task/feature-rdm-two-trees-followup.md new file mode 100644 index 00000000..bd6e47d6 --- /dev/null +++ b/.task/feature-rdm-two-trees-followup.md @@ -0,0 +1,159 @@ +# feature/rdm-two-trees-followup 任务卡 + +任务主记录:;状态:进行中;owner:weichen + +## 基线与授权 + +- 权威仓:ssh://git@git-ssh.u1680832.nyat.app:31411/weichen/Agent-System-Dev.git;目标分支:main;R0(initial_base_sha)= 46e331a7a81c94c6f5881c997ae0aca45664c830 +- 工作区:/home/weichen/projects/Agent-System-Dev-wt-feature-rdm-two-trees-followup(worktree);分支:feature/rdm-two-trees-followup +- 分支类型:initiative;initiative_id:feature-rdm-two-trees-followup;root_target:main;immediate_target:main;accepting_requirements:true +- 需求分流:verdict=NEW;selected_initiative=无;requirement_sha256=ec5195ceec26c05d94600716514c5f306bd3d2aba2a18e4e71f54a660e0b1b83;triage_receipt=/tmp/tt-followup-triage-20261019.json;receipt_sha256=3abe686c520606f4969e17668843666bfafc4cebd7f869995121ab82ed5dd345 + +- 授权与交付终点:<本次允许的动作与终点;未授权事项写明> +- 交付模式:goal-first(目标、范围和交付终点一次确认;范围内连续推进) +- 实施执行:agent-per-unit(配置:AGENT-EXECUTION.md) +- 合入执行:agent(已授权交付范围内,Review 通过、冲突解决且当前 HEAD 的 CI 通过后合入) +- 人工决策点:仅限目标/范围/验收变更、重大取舍、高后果操作或无法自动判定的业务验收 +- 当前阶段:需求拆解;当前增量:I1(待定义) +- 流程依据:仓库根目录 policy/delivery.md(归档后仍按仓库根目录定位) + +## 目标与非目标 + +<章程:用途与目标、接纳范围与非目标、方案/计划链接、分级测试策略、验收条件、追加领域规则、生命周期。> + +## 子任务登记 + +| 子任务分支 | 必需 | 状态 | PR | +|---|---|---|---| +| 待登记 | 否 | — | — | + +## Agent 实施收据 + +路由与 fail-stop 规则见根目录 AGENT-EXECUTION.md 与 policy/delivery.md;每次尝试一行,原始日志留在源码外收据路径。 + +| 单元 ID | 预期范围 | 配置摘要 | 角色 | 候选顺序 | attempt | CLI/模型 | 终态 | transport | fallback | 源码外收据路径 | +|---|---|---|---|---|---|---|---|---|---|---| +| 待定义 | — | NOT_RUN | NOT_RUN | NOT_RUN | NOT_RUN | NOT_RUN | NOT_RUN | NOT_RUN | NOT_RUN | — | + +## 关联方向与规划 + +- 适用状态:待核对(无适用规划时说明原因) +- 主记录路径/版本:待核对(路径按仓库根目录定位,归档后不变;只引用唯一正文) +- 对应里程碑:待核对 + +## 需求分析 + +| ID | 描述 | 项目符合度及依据 | 优先级 | 验收条件 | 依赖 | 结论 | +|---|---|---|---|---|---|---| +| R1 | 待填写 | 待评估 | 待定 | 待定义 | 待确认 | 待评审 | + +## 方案与计划 + +- 方案引用:待填写(含对象版本) +- 实施计划引用:待填写(含增量与需求 ID) +- 测试计划引用:待填写(含需求 ID 与验收条件) + +## 阶段记录 + +| 阶段 | 对象版本 | 状态 | 决策/执行者 | 时间 | 依据 | +|---|---|---|---|---|---| +| 需求拆解 | 待定 | 待执行 | — | — | — | +| 需求评估 | 待定 | 待执行 | — | — | — | +| 需求表确认 | 待定 | 待执行 | — | — | — | +| 方案设计 | 待定 | 待执行 | — | — | — | +| 实施计划 | 待定 | 待执行 | — | — | — | +| 实施与自检 | 待定 | 待执行 | — | — | — | +| 正式测试与验收 | 待定 | 待执行 | — | — | — | +| 代码 Review | 待定 | 待执行 | — | — | — | +| 合入 | 待定 | 待执行 | — | — | — | +| 合入核验与收口 | 待定 | 待执行 | — | — | — | + +## 探索试验与迭代 + +| 增量/试验 | 假设 | 范围 | 判断和停止条件 | 授权/决策依据 | 结果 | 变更影响 | 需重审补测 | +|---|---|---|---|---|---|---|---| +| 待定义 | — | — | — | 待核对 | NOT_RUN | 待评估 | 待评估 | + +## 同步记录 + +| 节点 | sync_base_sha | tested_head_sha | checked_at | +|---|---|---|---| +| 启动 | 46e331a7a81c94c6f5881c997ae0aca45664c830 | 46e331a7a81c94c6f5881c997ae0aca45664c830 | 2026-10-19T14:38:46Z | + +## 证据(Evidence) + + +| 时间(UTC) | 命令 | 被测HEAD | exit | 来源 | sha256(16) | +|---|---|---|---|---|---| + +## 交付调度 + +- 调度状态:未入队;调度记录:无 +- entry_id:无;attempt_id:无;窗口执行者:无 +- 固定候选:无(base/head、组件与相关配置引用实际尝试) +- 调度依据:policy/delivery.md#合入调度 +- 固定后证据:源码外 RECEIPT;实际结果后按授权原样导入和闭合 + +## 结果与验证(完成后填写) + +- 结果: +- 验证:<结论摘要 PASS/FAIL/SKIP/NOT_RUN 逐项;逐条证据由 make evidence 写入上方证据表> +- 影响与剩余项: + +## 规划进展与下一步 + +- 本次推进/剩余:待核对(依据实际成果更新适用方案/规划) +- 首选下一任务:待核对(无适用规划、已完成或受阻时如实说明,不虚构任务) +- 推荐依据:待填写 +- 前置条件/待确认:待核对 +- 预期产物/验收条件:待定义 +- 重复任务核对:待核对(已有/在途任务、PR 与规划记录) +- 启动授权:未授权(建议不自动启动新任务,仍须明确授权) + +## 合入与清理 + +- Review 记录:NOT_RUN(审阅智能体/平台身份、base/head、结论、问题闭合及重放依据) +- 冲突记录:NOT_RUN(最新目标同步、冲突处置、组合兼容核验及复审/补测) +- CI 记录:NOT_RUN(当前 HEAD 完整 SHA、全部必需检查、运行链接、执行身份及 GATE 结果) +- 合入记录:NOT_RUN(交付授权范围、PR、被核验 HEAD、合入 SHA、目标分支及内容核验) +- 清理记录:NOT_RUN(授权依据、写者退出确认、worktree/分支/任务卡处置) + + +```json +{ + "summary_schema": 1, + "source": "SELF", + "timestamp": "2026-10-19T14:37:49.134350+00:00", + "command": "make precheck", + "exit_code": 0, + "cwd": "/home/weichen/projects/Agent-System-Dev", + "before_head": "46e331a7a81c94c6f5881c997ae0aca45664c830", + "after_head": "46e331a7a81c94c6f5881c997ae0aca45664c830", + "branch": "main", + "target_branch": "main", + "target_head": "46e331a7a81c94c6f5881c997ae0aca45664c830", + "root_target": "main", + "immediate_target": "main", + "before_tracked_diff_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "after_tracked_diff_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "output_tail": [ + "make[1]: Entering directory '/home/weichen/projects/Agent-System-Dev'", + "[repo] branch=main head=46e331a7a8", + "[remote] origin/main=46e331a7a8 ahead=0 behind=0", + "[tree] clean submodules_drift=0 uninit=0", + "[worktrees] linked=4", + "[recycle] merged un-recycled branches: feature/layered-python-env", + "[initiatives] local cards (not authoritative): none", + "[hooks] core.hooksPath=scripts/hooks(pre-commit/post-merge 实际接线)", + "[facts] policy/facts.md 6 条事实均在有效期内", + "[required-reading] core/baseline.md, workflows/delivery.md §1, policy/delivery.md", + "[R0] 46e331a7a8(完整:46e331a7a81c94c6f5881c997ae0aca45664c830)", + "[worktree] before-sync: recursive component checks passed", + "[verdict] READY — 保留本次 precheck receipt 后建任务工作区:PRECHECK_RECEIPT=/tmp/task-precheck.json make task-start NAME=feature/your-branch", + "make[1]: Leaving directory '/home/weichen/projects/Agent-System-Dev'" + ], + "output_sha256": "6cba29f361cd5d6ad7c8712594c53dd0899e10d1d89a2b510a8e85522b461cfa", + "receipt_sha256": "17f97ec95374ca86a9e49b4b7976cf318ae1f7ae5052d8a746ab219907e1be4c", + "receipt_path": "/home/weichen/.cache/agent-system-dev/evidence/17f97ec95374ca86a9e49b4b7976cf318ae1f7ae5052d8a746ab219907e1be4c.json" +} +``` -- 2.54.0 From 000a2d2ae0e29fecd42ff19bf2b42e430be22ef8 Mon Sep 17 00:00:00 2001 From: agent-exec-transport Date: Mon, 19 Oct 2026 14:45:58 +0000 Subject: [PATCH 02/36] agent-exec transport b7a8e78a2b6d0d8f6803490c7fa8af2e/9075eee055af --- scripts/dhf_catalog_guard.py | 244 ++++++++++++++++++++++++++++++ tests/test_dhf_catalog_guard.py | 256 ++++++++++++++++++++++++++++++++ tests/test_svc.py | 176 ++++++++++++++-------- tests/test_svc_realcombo.py | 20 ++- tests/test_svc_recover.py | 46 +++--- 5 files changed, 650 insertions(+), 92 deletions(-) create mode 100755 scripts/dhf_catalog_guard.py create mode 100644 tests/test_dhf_catalog_guard.py diff --git a/scripts/dhf_catalog_guard.py b/scripts/dhf_catalog_guard.py new file mode 100755 index 00000000..f7a69eaa --- /dev/null +++ b/scripts/dhf_catalog_guard.py @@ -0,0 +1,244 @@ +#!/usr/bin/env python3 +"""Compare the DHF inventory, immutable originals and one RDM asset catalog. + +This checks provenance and publication metadata. It cannot decide document +meaning or Word rendering fidelity; those require the per-asset review. +""" + +import argparse +from collections import Counter +from datetime import datetime +import hashlib +import json +from pathlib import Path +import re +import subprocess +import sys + + +SOURCE_PREFIX = (".templates", "DHF 文件模板") +STATES = {"needs-review", "blocked", "published", "retired"} +SHA256 = re.compile(r"[0-9a-f]{64}\Z") +COMMIT = re.compile(r"[0-9a-f]{40}\Z") +RFC3339 = re.compile(r"\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:Z|[+-]\d{2}:\d{2})\Z") + + +def digest(raw): + return hashlib.sha256(raw).hexdigest() + + +def source_path(dev_root, source): + path = Path(source) + if (path.is_absolute() or path.parts[:2] != SOURCE_PREFIX + or ".." in path.parts or path.suffix.lower() not in {".doc", ".docx"}): + raise ValueError(f"unsafe or non-Word source path: {source}") + segment = dev_root + for part in path.parts: + segment = segment / part + if segment.is_symlink(): + raise ValueError(f"source path symlink: {source}") + absolute = dev_root / path + if not absolute.resolve().is_relative_to(dev_root.resolve()) or absolute.is_symlink(): + raise ValueError(f"source path leaves the Dev tree: {source}") + return absolute + + +def package_digest(root, file_ref): + relative = file_ref.get("path") + expected = file_ref.get("sha256") + if not isinstance(relative, str) or not isinstance(expected, str) or not SHA256.fullmatch(expected): + raise ValueError("published asset file reference missing path or hash") + path = Path(relative) + if path.is_absolute() or ".." in path.parts or path == Path("."): + raise ValueError("published asset file reference is unsafe") + segment = root + for part in path.parts: + segment = segment / part + if segment.is_symlink(): + raise ValueError("published asset file symlink") + absolute = root / path + if not absolute.resolve().is_relative_to(root.resolve()) or absolute.is_symlink() or not absolute.is_file(): + raise ValueError("published asset file missing or escapes catalog") + if digest(absolute.read_bytes()) != expected: + raise ValueError("published asset file hash mismatch") + return expected + + +def audit(dev_root, inventory, catalog, expected_count, require_published=False, + catalog_root=None, identity_baseline=None): + records = inventory.get("templates") + assets = catalog.get("assets") + if not isinstance(records, list) or not isinstance(assets, list): + raise ValueError("inventory/templates or catalog/assets is missing") + if len(records) != expected_count or len(assets) != expected_count: + raise ValueError(f"expected {expected_count} logical sources and assets") + by_path = {} + ids = set() + for asset in assets: + provenance = asset.get("sourceProvenance") or {} + path = provenance.get("path") + template_id = asset.get("templateId") + if path in by_path or not isinstance(path, str): + raise ValueError("duplicate or missing provenance path") + if template_id in ids or not isinstance(template_id, str) or not template_id: + raise ValueError("duplicate or missing logical template ID") + by_path[path] = asset + ids.add(template_id) + if identity_baseline is not None: + prior = identity_baseline.get("assets") + if not isinstance(prior, list) or len(prior) != expected_count: + raise ValueError("identity baseline is incomplete") + prior_ids = {} + for asset in prior: + if not isinstance(asset, dict): + raise ValueError("identity baseline has invalid asset") + path = (asset.get("sourceProvenance") or {}).get("path") + if path in prior_ids or not isinstance(path, str): + raise ValueError("identity baseline has duplicate source") + prior_ids[path] = asset.get("templateId") + for path, asset in by_path.items(): + if prior_ids.get(path) != asset["templateId"]: + raise ValueError(f"template identity drift: {path}") + seen = set() + states = Counter() + hashes = set() + candidate_differences = [] + for record in records: + relative = record.get("source") + if not isinstance(relative, str) or relative in seen or relative not in by_path: + raise ValueError(f"inventory source missing, duplicate or unmapped: {relative}") + seen.add(relative) + asset = by_path[relative] + expected = record.get("sourceSha256") + found = (asset.get("source") or {}).get("sha256") + if not isinstance(expected, str) or not SHA256.fullmatch(expected) or found != expected: + raise ValueError(f"catalog source hash mismatch: {relative}") + path = source_path(dev_root, relative) + if not path.is_file() or digest(path.read_bytes()) != expected: + raise ValueError(f"checkout hash mismatch: {relative}") + provenance = asset["sourceProvenance"] + commit = provenance.get("commit") + if provenance.get("repository") != "Agent-System-Dev" or not isinstance(commit, str) or not COMMIT.fullmatch(commit): + raise ValueError(f"untrusted source provenance: {relative}") + historical = subprocess.run( + ["git", "-C", str(dev_root), "show", f"{commit}:{relative}"], + capture_output=True, check=False, + ) + if historical.returncode or digest(historical.stdout) != expected: + raise ValueError(f"committed source hash mismatch: {relative}") + if (asset.get("source") or {}).get("format") != path.suffix.lower()[1:]: + raise ValueError(f"catalog format mismatch: {relative}") + applicability = asset.get("applicability") or {} + catalog_types = applicability.get("docTypes", []) + if not isinstance(catalog_types, list): + raise ValueError(f"invalid catalog docTypes: {relative}") + if record.get("proposedDocType") not in catalog_types: + candidate_differences.append({ + "path": relative, + "inventoryCandidate": record.get("proposedDocType"), + "catalogCandidates": catalog_types, + "confirmed": bool(applicability.get("confirmed")), + }) + state = asset.get("state") + if state not in STATES: + raise ValueError(f"invalid asset state: {relative}") + if state == "published": + review = asset.get("review") or {} + normalized = asset.get("normalizedDocx") or {} + condition = applicability.get("condition") + if (not normalized or not catalog_types or applicability.get("confirmed") is not True + or not isinstance(condition, str) or not condition.strip() + or review.get("decision") != "approved" + or review.get("sourceSha256") != expected + or not asset.get("structure") or not asset.get("render")): + raise ValueError(f"published asset lacks approved binding: {relative}") + if (normalized.get("format") != "docx" or asset["structure"].get("format") != "json" + or asset["render"].get("format") != "docx"): + raise ValueError(f"published asset has invalid derived formats: {relative}") + reviewer = review.get("reviewer") + evidence = review.get("evidence") + reviewed_at = review.get("reviewedAt") + if (not isinstance(reviewer, str) or not reviewer.strip() + or not isinstance(evidence, str) or not evidence.strip() + or not isinstance(reviewed_at, str)): + raise ValueError(f"published asset lacks reviewer evidence: {relative}") + if not RFC3339.fullmatch(reviewed_at): + raise ValueError(f"published asset has invalid review time: {relative}") + try: + at = datetime.fromisoformat(reviewed_at.replace("Z", "+00:00")) + except ValueError as exc: + raise ValueError(f"published asset has invalid review time: {relative}") from exc + if at.tzinfo is None: + raise ValueError(f"published asset has invalid review time: {relative}") + converter = asset.get("converter") or {} + if (asset["source"].get("format") == "doc" or + asset["source"].get("sha256") != normalized.get("sha256")): + if (converter.get("inputSha256") != expected or + converter.get("outputSha256") != normalized.get("sha256") or + any(not isinstance(converter.get(field), str) or not converter[field].strip() + for field in ("name", "version", "configuration"))): + raise ValueError(f"published asset lacks conversion provenance: {relative}") + if any(issue.get("status") != "resolved" for issue in asset.get("issues", [])): + raise ValueError(f"published asset has unresolved issues: {relative}") + if (review.get("structureSha256") != asset["structure"].get("sha256") + or review.get("renderSha256") != asset["render"].get("sha256") + or review.get("normalizedSha256") != normalized.get("sha256")): + raise ValueError(f"published asset review hash mismatch: {relative}") + if catalog_root is not None: + package_digest(catalog_root, asset["source"]) + package_digest(catalog_root, normalized) + package_digest(catalog_root, asset["structure"]) + package_digest(catalog_root, asset["render"]) + states[state] += 1 + hashes.add(expected) + if require_published and states.get("published", 0) != expected_count: + raise ValueError(f"{expected_count - states.get('published', 0)} assets not published") + return { + "source": "SELF mechanical provenance check", + "matched": len(seen), + "logicalTemplateIds": len(ids), + "uniqueSourceBytes": len(hashes), + "published": states.get("published", 0), + "states": dict(sorted(states.items())), + "candidateTypeDifferences": candidate_differences, + "identityBaselineVerified": identity_baseline is not None, + "publicationValidation": "NOT_RUN: RDM LoadDHFAssetCatalog and human content/Word review are authoritative", + "limits": "This checks provenance and obvious metadata errors; state counts do not prove published bundles are valid.", + } + + +def main(): + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("--dev-root", type=Path, required=True) + parser.add_argument("--inventory", type=Path, required=True) + parser.add_argument("--catalog", type=Path, required=True) + parser.add_argument("--expected-count", type=int, default=44) + parser.add_argument("--identity-baseline", type=Path) + parser.add_argument("--require-published", action="store_true") + args = parser.parse_args() + try: + if args.expected_count < 1: + raise ValueError("expected-count must be positive") + inventory_raw = args.inventory.read_bytes() + catalog_raw = args.catalog.read_bytes() + baseline_raw = args.identity_baseline.read_bytes() if args.identity_baseline else None + result = audit(args.dev_root, json.loads(inventory_raw), json.loads(catalog_raw), + args.expected_count, args.require_published, args.catalog.parent, + json.loads(baseline_raw) if baseline_raw is not None else None) + if args.catalog.read_bytes() != catalog_raw: + raise ValueError("catalog changed during check") + result["catalogSha256"] = digest(catalog_raw) + result["inventorySha256"] = digest(inventory_raw) + if baseline_raw is not None: + result["identityBaselineSha256"] = digest(baseline_raw) + if args.require_published: + raise ValueError("RDM publication validator required for full bundle safety and human fidelity") + except (OSError, ValueError, json.JSONDecodeError) as exc: + print(f"dhf catalog guard: {exc}", file=sys.stderr) + return 1 + print(json.dumps(result, ensure_ascii=False, sort_keys=True)) + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/tests/test_dhf_catalog_guard.py b/tests/test_dhf_catalog_guard.py new file mode 100644 index 00000000..31bf34b9 --- /dev/null +++ b/tests/test_dhf_catalog_guard.py @@ -0,0 +1,256 @@ +import hashlib +import json +from pathlib import Path +import subprocess +import sys +import tempfile +import unittest +from copy import deepcopy + + +ROOT = Path(__file__).resolve().parents[1] +GUARD = ROOT / "scripts" / "dhf_catalog_guard.py" + + +class DHFCatalogGuardTest(unittest.TestCase): + def setUp(self): + self.tmp = tempfile.TemporaryDirectory() + self.addCleanup(self.tmp.cleanup) + self.root = Path(self.tmp.name) + self.dev = self.root / "dev" + self.dev.mkdir() + subprocess.run(["git", "init", "-q", str(self.dev)], check=True) + self.items = [] + self.assets = [] + for index, value in enumerate((b"source-one", b"source-two"), 1): + path = f".templates/DHF 文件模板/阶段{index}/模板{index}.docx" + absolute = self.dev / path + absolute.parent.mkdir(parents=True) + absolute.write_bytes(value) + digest = hashlib.sha256(value).hexdigest() + self.items.append({ + "source": path, + "sourceSha256": digest, + "proposedDocType": f"type-{index}", + }) + self.assets.append({ + "templateId": f"dhf.logical-{index}", + "version": "1.0.0", + "state": "needs-review", + "source": {"sha256": digest, "format": "docx"}, + "sourceProvenance": {"repository": "Agent-System-Dev", "path": path}, + "applicability": {"docTypes": [f"type-{index}"], "confirmed": False}, + }) + subprocess.run(["git", "-C", str(self.dev), "add", ".templates"], check=True) + subprocess.run([ + "git", "-C", str(self.dev), "-c", "user.name=Test", + "-c", "user.email=test@example.invalid", "commit", "-qm", "sources", + ], check=True) + commit = subprocess.check_output( + ["git", "-C", str(self.dev), "rev-parse", "HEAD"], text=True, + ).strip() + for asset in self.assets: + asset["sourceProvenance"]["commit"] = commit + self.inventory = self.root / "inventory.json" + self.catalog = self.root / "catalog.json" + self.save() + + def save(self): + self.inventory.write_text(json.dumps({"templates": self.items})) + self.catalog.write_text(json.dumps({"schemaVersion": "dhf-assets/v1", "assets": self.assets})) + + def run_guard(self, *extra): + return subprocess.run([ + sys.executable, str(GUARD), "--dev-root", str(self.dev), + "--inventory", str(self.inventory), "--catalog", str(self.catalog), + "--expected-count", "2", *extra, + ], capture_output=True, text=True) + + def publish_fixture(self, index=0, *, structure=b'{"blocks":[]}', render=b"rendered-docx"): + asset = self.assets[index] + number = index + 1 + source = (self.dev / self.items[index]["source"]).read_bytes() + names = {"source": f"source{number}.docx", "structure": f"structure{number}.json", + "render": f"render{number}.docx"} + for label, raw in [("source", source), ("structure", structure), ("render", render)]: + (self.root / names[label]).write_bytes(raw) + asset["state"] = "published" + asset["applicability"].update({"confirmed": True, "condition": "test scope"}) + asset["source"]["path"] = names["source"] + asset["normalizedDocx"] = {"path": names["source"], "format": "docx", + "sha256": hashlib.sha256(source).hexdigest()} + asset["structure"] = {"path": names["structure"], "format": "json", + "sha256": hashlib.sha256(structure).hexdigest()} + asset["render"] = {"path": names["render"], "format": "docx", + "sha256": hashlib.sha256(render).hexdigest()} + asset["review"] = { + "decision": "approved", "reviewer": "reviewer", "reviewedAt": "2026-10-14T00:00:00Z", + "evidence": "review-record", "sourceSha256": self.items[index]["sourceSha256"], + "normalizedSha256": asset["normalizedDocx"]["sha256"], + "structureSha256": asset["structure"]["sha256"], + "renderSha256": asset["render"]["sha256"], + } + return asset + + def test_accepts_matching_immutable_sources_but_does_not_call_them_published(self): + result = self.run_guard() + self.assertEqual(result.returncode, 0, result.stdout + result.stderr) + report = json.loads(result.stdout) + self.assertEqual(report["matched"], 2) + self.assertEqual(report["states"], {"needs-review": 2}) + self.assertEqual(report["published"], 0) + + def test_rejects_changed_checkout_even_when_catalog_matches_historical_commit(self): + (self.dev / self.items[0]["source"]).write_bytes(b"changed") + result = self.run_guard() + self.assertNotEqual(result.returncode, 0) + self.assertIn("checkout hash mismatch", result.stderr) + + def test_rejects_original_in_symlinked_parent_directory(self): + source = self.dev / self.items[0]["source"] + original_parent = source.parent + moved_parent = original_parent.parent / "alias-target" + original_parent.rename(moved_parent) + original_parent.symlink_to(moved_parent, target_is_directory=True) + result = self.run_guard() + self.assertNotEqual(result.returncode, 0) + self.assertIn("source path symlink", result.stderr) + + def test_rejects_false_publication(self): + self.assets[0]["state"] = "published" + self.save() + result = self.run_guard() + self.assertNotEqual(result.returncode, 0) + self.assertIn("published asset lacks", result.stderr) + + def test_reports_revised_candidate_type_without_approving_publication(self): + self.assets[0]["applicability"]["docTypes"] = ["unrelated"] + self.save() + result = self.run_guard() + self.assertEqual(result.returncode, 0, result.stderr) + report = json.loads(result.stdout) + self.assertEqual(report["published"], 0) + self.assertEqual(report["candidateTypeDifferences"], [{ + "path": self.items[0]["source"], + "inventoryCandidate": "type-1", + "catalogCandidates": ["unrelated"], + "confirmed": False, + }]) + + def test_publication_gate_does_not_accept_a_complete_inventory_as_delivery(self): + result = self.run_guard("--require-published") + self.assertNotEqual(result.returncode, 0) + self.assertIn("not published", result.stderr) + + def test_rejects_published_asset_whose_review_does_not_bind_bundle_bytes(self): + asset = self.publish_fixture() + asset["review"]["structureSha256"] = "0" * 64 + self.save() + result = self.run_guard() + self.assertNotEqual(result.returncode, 0) + self.assertIn("published asset review hash mismatch", result.stderr) + + def test_rejects_bundle_file_changed_after_approval(self): + asset = self.publish_fixture() + self.save() + (self.root / asset["render"]["path"]).write_bytes(b"modified-after-review") + result = self.run_guard() + self.assertNotEqual(result.returncode, 0) + self.assertIn("published asset file hash mismatch", result.stderr) + + def test_rejects_published_asset_with_unresolved_fidelity_issue(self): + asset = self.publish_fixture() + asset["issues"] = [{"id": "fidelity", "status": "open"}] + self.save() + result = self.run_guard() + self.assertNotEqual(result.returncode, 0) + self.assertIn("published asset has unresolved issues", result.stderr) + + def test_publication_flag_never_claims_authoritative_rdm_validation(self): + for index in range(2): + self.publish_fixture(index, structure=b"not-a-valid-structure", render=b"not-a-valid-docx") + self.save() + result = self.run_guard("--require-published") + self.assertNotEqual(result.returncode, 0) + self.assertIn("RDM publication validator required", result.stderr) + + def test_rejects_swapped_logical_ids_against_fixed_identity_baseline(self): + baseline = self.root / "identity-baseline.json" + baseline.write_text(json.dumps({"assets": deepcopy(self.assets)})) + self.assets[0]["templateId"], self.assets[1]["templateId"] = ( + self.assets[1]["templateId"], self.assets[0]["templateId"]) + self.save() + result = self.run_guard("--identity-baseline", str(baseline)) + self.assertNotEqual(result.returncode, 0) + self.assertIn("template identity drift", result.stderr) + + def test_report_binds_exact_catalog_bytes(self): + result = self.run_guard() + self.assertEqual(result.returncode, 0, result.stderr) + self.assertEqual(json.loads(result.stdout)["catalogSha256"], + hashlib.sha256(self.catalog.read_bytes()).hexdigest()) + + def test_rejects_published_package_through_symlink_directory(self): + asset = self.publish_fixture() + real = self.root / "real" + real.mkdir() + for key in ["source", "normalizedDocx", "structure", "render"]: + p = self.root / asset[key]["path"] + (real / p.name).write_bytes(p.read_bytes()) + asset[key]["path"] = "alias/" + p.name + (self.root / "alias").symlink_to(real, target_is_directory=True) + self.save() + result = self.run_guard() + self.assertNotEqual(result.returncode, 0) + self.assertIn("symlink", result.stderr) + + def test_rejects_string_false_and_null_applicability(self): + asset = self.publish_fixture() + asset["applicability"]["confirmed"] = "false" + self.save() + result = self.run_guard() + self.assertNotEqual(result.returncode, 0) + self.assertIn("published asset lacks approved binding", result.stderr) + + asset["applicability"]["confirmed"] = True + asset["applicability"]["condition"] = None + self.save() + result = self.run_guard() + self.assertNotEqual(result.returncode, 0) + self.assertIn("published asset lacks approved binding", result.stderr) + + def test_rejects_null_reviewer_and_non_rfc3339_timestamp(self): + asset = self.publish_fixture() + asset["review"]["reviewer"] = None + self.save() + result = self.run_guard() + self.assertNotEqual(result.returncode, 0) + self.assertIn("published asset lacks reviewer evidence", result.stderr) + + asset["review"]["reviewer"] = "reviewer" + asset["review"]["reviewedAt"] = "2026-10-14 00:00:00Z" + self.save() + result = self.run_guard() + self.assertNotEqual(result.returncode, 0) + self.assertIn("published asset has invalid review time", result.stderr) + + def test_rejects_changed_normalized_file_without_named_converter(self): + asset = self.publish_fixture() + normalized = b"changed-normalized-docx" + (self.root / "normalized.docx").write_bytes(normalized) + asset["normalizedDocx"] = { + "path": "normalized.docx", "format": "docx", "sha256": hashlib.sha256(normalized).hexdigest(), + } + asset["review"]["normalizedSha256"] = asset["normalizedDocx"]["sha256"] + asset["converter"] = { + "inputSha256": self.items[0]["sourceSha256"], + "outputSha256": asset["normalizedDocx"]["sha256"], + } + self.save() + result = self.run_guard() + self.assertNotEqual(result.returncode, 0) + self.assertIn("published asset lacks conversion provenance", result.stderr) + + +if __name__ == "__main__": + unittest.main() diff --git a/tests/test_svc.py b/tests/test_svc.py index f90e636d..94bbcf75 100644 --- a/tests/test_svc.py +++ b/tests/test_svc.py @@ -72,7 +72,7 @@ case "${1:-}" in # GET/HEAD 一律 200(健康探测语义与 http.server 等价);PUT /api/* 捕获头与 # 请求体到 trace/put.txt 供播种断言(settings 播种验证,2026-10-11)。 # HTTP 子进程轮询 ppid:父进程被 SIGKILL 后自行退出,避免与 recover 套件 - # 共用 1880x 端口时泄漏占用(与 test_svc_recover 桩同规)。 + # 并行运行时泄漏端口占用(与 test_svc_recover 桩同规)。 python3 - "$port" "$host" "$trace_dir" "$data" <<'PYSRV' >/dev/null 2>&1 & import json, os, sqlite3, sys, threading, time from http.server import BaseHTTPRequestHandler, HTTPServer @@ -166,6 +166,7 @@ class SvcDbRecoveryTests(unittest.TestCase): tmp = tempfile.mkdtemp(prefix="svc-db-regress-") self.addCleanup(shutil.rmtree, tmp, True) self.root = Path(tmp) + self._allocated_ports = set() (self.root / "scripts").mkdir(parents=True) shutil.copy2(SVC_SCRIPT, self.root / "scripts" / "svc.sh") self.trace = self.root / "trace" @@ -223,6 +224,21 @@ class SvcDbRecoveryTests(unittest.TestCase): self.assertEqual(proc.returncode, 0, proc.stdout) return proc + def available_port(self): + """Allocate a distinct service port for this test, including address changes. + + The socket closes before svc.sh binds it, leaving a small allocation-to-start + race with unrelated processes. Keep allocated numbers distinct within the + test so stopped/restarted services never share another instance's port. + """ + while True: + with socket.socket() as sock: + sock.bind(("0.0.0.0", 0)) + port = sock.getsockname()[1] + if port not in self._allocated_ports: + self._allocated_ports.add(port) + return port + def runtime(self, name): return self.root / "runtime" / name @@ -292,11 +308,12 @@ class SvcDbRecoveryTests(unittest.TestCase): # ---- 1. 存量 exec= DSN:连续启动两次均恢复,进程参数无秘密 ---- def test_legacy_exec_dsn_survives_consecutive_restarts(self): + port = self.available_port() self.register_pg("pg1", 18890, password="legacy-pw-1") dsn = "postgresql://agent:legacy-pw-1@127.0.0.1:18890/agent" d = self.runtime("dev") - self.seed_agent("dev", 18791, - "--addr 127.0.0.1:18791 --data %s --plugins %s --auth auto --dsn %s" + self.seed_agent("dev", port, + f"--addr 127.0.0.1:{port} --data %s --plugins %s --auth auto --dsn %s" % (d / "data", d / "plugins", dsn)) for _ in range(2): self.clear_serve_record() @@ -318,11 +335,12 @@ class SvcDbRecoveryTests(unittest.TestCase): # ---- 2. 仅 dbref:裸 restart 与重新部署均保留绑定 ---- def test_dbref_binding_survives_bare_restart_and_redeploy(self): + port = self.available_port() self.register_pg("pg1", 18891, password="bind-pw-2") dsn = "postgresql://agent:bind-pw-2@127.0.0.1:18891/agent" d = self.runtime("dev") - self.seed_agent("dev", 18792, - "--addr 127.0.0.1:18792 --data %s --plugins %s --auth auto" + self.seed_agent("dev", port, + f"--addr 127.0.0.1:{port} --data %s --plugins %s --auth auto" % (d / "data", d / "plugins"), extra_rows=[("dbref", "pg1/agent"), ("db", "pg")]) self.clear_serve_record() @@ -342,30 +360,30 @@ class SvcDbRecoveryTests(unittest.TestCase): # ---- 3. 改地址不改数据库与认证 ---- def test_addr_change_keeps_database_and_auth(self): + old_port = self.available_port() + new_port = self.available_port() self.register_pg("pg1", 18892, password="addr-pw-3") dsn = "postgresql://agent:addr-pw-3@127.0.0.1:18892/agent" d = self.runtime("dev") - self.seed_agent("dev", 18793, - "--addr 127.0.0.1:18793 --data %s --plugins %s --auth auto" + self.seed_agent("dev", old_port, + f"--addr 127.0.0.1:{old_port} --data %s --plugins %s --auth auto" % (d / "data", d / "plugins"), extra_rows=[("dbref", "pg1/agent"), ("db", "pg")]) self.clear_serve_record() - self.svc("dev", "restart", "--addr", "127.0.0.1:18794") + self.svc("dev", "restart", "--addr", f"127.0.0.1:{new_port}") record = self.serve_record() self.assertIn("AGENT_SYSTEM_DSN=%s" % dsn, record) self.assertIn("--auth auto", record) self.assertEqual(self.kv("dev", "dbref"), "pg1/agent") - self.assertEqual(self.kv("dev", "addr"), "127.0.0.1:18794") - self.assertIn("--addr 127.0.0.1:18794", self.kv("dev", "exec")) + self.assertEqual(self.kv("dev", "addr"), f"127.0.0.1:{new_port}") + self.assertIn(f"--addr 127.0.0.1:{new_port}", self.kv("dev", "exec")) self.assertEqual(self.kv("dev", "db"), "pg") # ---- 4. 外部直连与配置文件来源:后续无参数启动仍恢复 ---- def test_external_dsn_and_conffile_recover_on_bare_start(self): + port = self.available_port() d = self.runtime("dev") - with socket.socket() as reservation: - reservation.bind(("127.0.0.1", 0)) - port = reservation.getsockname()[1] self.seed_agent("dev", port, "--addr 127.0.0.1:%d --data %s --plugins %s --auth auto" % (port, d / "data", d / "plugins")) @@ -405,9 +423,13 @@ class SvcDbRecoveryTests(unittest.TestCase): # ---- 5. 拒启场景:不降级 SQLite、不启动进程、登记可恢复、停机前发现 ---- def test_refusals_keep_registration_without_sqlite_fallback(self): + a1_port = self.available_port() + a2_port = self.available_port() + a3_port = self.available_port() + a4_port = self.available_port() d = self.runtime("a1") - self.seed_agent("a1", 18796, - "--addr 127.0.0.1:18796 --data %s --plugins %s --auth auto" + self.seed_agent("a1", a1_port, + f"--addr 127.0.0.1:{a1_port} --data %s --plugins %s --auth auto" % (d / "data", d / "plugins"), extra_rows=[("dbref", "pgmissing/agent"), ("db", "pg")]) self.clear_serve_record() @@ -420,8 +442,8 @@ class SvcDbRecoveryTests(unittest.TestCase): # 实例登记不全(缺 password)→ 拒启。 self.register_pg("pginc", 18895, complete=False) d = self.runtime("a2") - self.seed_agent("a2", 18797, - "--addr 127.0.0.1:18797 --data %s --plugins %s --auth auto" + self.seed_agent("a2", a2_port, + f"--addr 127.0.0.1:{a2_port} --data %s --plugins %s --auth auto" % (d / "data", d / "plugins"), extra_rows=[("dbref", "pginc/agent"), ("db", "pg")]) result = self.svc("a2", "restart", check=False) @@ -431,8 +453,8 @@ class SvcDbRecoveryTests(unittest.TestCase): # dbref 与 dsn= 指向不同库 → 配置冲突拒启。 self.register_pg("pg1", 18896, password="clash-pw") d = self.runtime("a3") - self.seed_agent("a3", 18798, - "--addr 127.0.0.1:18798 --data %s --plugins %s --auth auto" + self.seed_agent("a3", a3_port, + f"--addr 127.0.0.1:{a3_port} --data %s --plugins %s --auth auto" % (d / "data", d / "plugins"), extra_rows=[("dbref", "pg1/agent"), ("db", "pg"), ("dsn", "postgresql://u:p@127.0.0.1:18999/otherdb")]) @@ -442,8 +464,8 @@ class SvcDbRecoveryTests(unittest.TestCase): # db=pg 但无可恢复 DSN → 拒启。 d = self.runtime("a4") - self.seed_agent("a4", 18799, - "--addr 127.0.0.1:18799 --data %s --plugins %s --auth auto" + self.seed_agent("a4", a4_port, + f"--addr 127.0.0.1:{a4_port} --data %s --plugins %s --auth auto" % (d / "data", d / "plugins"), extra_rows=[("db", "pg")]) result = self.svc("a4", "restart", check=False) @@ -452,10 +474,11 @@ class SvcDbRecoveryTests(unittest.TestCase): self.assertEqual(self.kv("a4", "db"), "pg") def test_restart_refusal_happens_before_stopping_running_service(self): + port = self.available_port() self.register_pg("pg1", 18897, password="run-pw") d = self.runtime("a5") - self.seed_agent("a5", 18800, - "--addr 127.0.0.1:18800 --data %s --plugins %s --auth auto" + self.seed_agent("a5", port, + f"--addr 127.0.0.1:{port} --data %s --plugins %s --auth auto" % (d / "data", d / "plugins"), extra_rows=[("dbref", "pg1/agent"), ("db", "pg")]) self.start_ok("a5") @@ -473,10 +496,13 @@ class SvcDbRecoveryTests(unittest.TestCase): # ---- 6. 认证预检与后端口径一致(环境变量 DSN 覆盖 auto)---- def test_auth_preflight_aligns_with_effective_env_dsn(self): + nl1_port = self.available_port() + nl2_port = self.available_port() + nl3_port = self.available_port() # 非回环 + auto + 无任何 DSN → 预检快速拒绝,不启动进程。 d = self.runtime("nl1") - self.seed_agent("nl1", 18801, - "--addr 10.255.255.1:18801 --data %s --plugins %s --auth auto" + self.seed_agent("nl1", nl1_port, + f"--addr 10.255.255.1:{nl1_port} --data %s --plugins %s --auth auto" % (d / "data", d / "plugins")) self.clear_serve_record() result = self.svc("nl1", "start", check=False) @@ -487,9 +513,9 @@ class SvcDbRecoveryTests(unittest.TestCase): # 环境变量提供 DSN → auto 判为已开认证:预检放行(桩绑定非回环地址失败即退, # 区别于预检拒绝——证明进入启动路径且 DSN 经环境交付)。 d = self.runtime("nl2") - self.seed_agent("nl2", 18802, - "--addr 10.255.255.1:18802 --data %s --plugins %s --auth auto" - % (d / "data", d / "plugins"), addr="10.255.255.1:18802") + self.seed_agent("nl2", nl2_port, + f"--addr 10.255.255.1:{nl2_port} --data %s --plugins %s --auth auto" + % (d / "data", d / "plugins"), addr=f"10.255.255.1:{nl2_port}") env_dsn = "postgresql://envu:env-pw@127.0.0.1:18898/agent" env2 = dict(self.env, SVC_NL2_DSN=env_dsn) self.clear_serve_record() @@ -500,9 +526,9 @@ class SvcDbRecoveryTests(unittest.TestCase): # 显式 auth=off 覆盖环境 DSN → 仍拒绝。 d = self.runtime("nl3") - self.seed_agent("nl3", 18803, - "--addr 10.255.255.1:18803 --data %s --plugins %s --auth off" - % (d / "data", d / "plugins"), addr="10.255.255.1:18803") + self.seed_agent("nl3", nl3_port, + f"--addr 10.255.255.1:{nl3_port} --data %s --plugins %s --auth off" + % (d / "data", d / "plugins"), addr=f"10.255.255.1:{nl3_port}") self.clear_serve_record() result = self.svc("nl3", "start", check=False, env=dict(self.env, SVC_NL3_DSN=env_dsn)) @@ -513,10 +539,11 @@ class SvcDbRecoveryTests(unittest.TestCase): # ---- 7. 显式解绑:环境残留不再悄悄重新选库 ---- def test_explicit_unbind_blocks_residual_env_dsn(self): + port = self.available_port() self.register_pg("pg1", 18899, password="unbind-pw") d = self.runtime("dev") - self.seed_agent("dev", 18804, - "--addr 127.0.0.1:18804 --data %s --plugins %s" + self.seed_agent("dev", port, + f"--addr 127.0.0.1:{port} --data %s --plugins %s" % (d / "data", d / "plugins")) self.svc("dev", "db", "pg1", "--no-restart") self.assertEqual(self.kv("dev", "dbref"), "pg1/agent") @@ -544,10 +571,12 @@ class SvcDbRecoveryTests(unittest.TestCase): # ---- 8. mock 冲突与旧产物:行为明确,不隐式降级 ---- def test_mock_conflict_and_legacy_binary_refuse(self): + mock_port = self.available_port() + legacy_port = self.available_port() self.register_pg("pg1", 18902, password="mock-pw") d = self.runtime("mk1") - self.seed_agent("mk1", 18805, - "--addr 127.0.0.1:18805 --data %s --plugins %s --auth auto" + self.seed_agent("mk1", mock_port, + f"--addr 127.0.0.1:{mock_port} --data %s --plugins %s --auth auto" % (d / "data", d / "plugins"), extra_rows=[("dbref", "pg1/agent"), ("db", "pg")]) result = self.svc("mk1", "deploy", "--from", "local", "--mock", check=False) @@ -558,8 +587,8 @@ class SvcDbRecoveryTests(unittest.TestCase): # 旧产物(不消费环境变量 DSN)绑定服务 restart → 拒绝,提示可操作出路。 d = self.runtime("lb1") - self.seed_agent("lb1", 18806, - "--addr 127.0.0.1:18806 --data %s --plugins %s --auth auto" + self.seed_agent("lb1", legacy_port, + f"--addr 127.0.0.1:{legacy_port} --data %s --plugins %s --auth auto" % (d / "data", d / "plugins"), extra_rows=[("dbref", "pg1/agent"), ("db", "pg")]) env_legacy = dict(self.env, SVC_STUB_NO_ENV_DSN="1") @@ -571,15 +600,17 @@ class SvcDbRecoveryTests(unittest.TestCase): # ---- 9. 多实例顺序更新不串用 DSN;凭据不进日志与历史 ---- def test_sequential_restarts_no_cross_dsn_and_no_secret_leak(self): + dev_port = self.available_port() + prod_port = self.available_port() self.register_pg("pg1", 18903, password="iso-pw-one") self.register_pg("pg2", 18904, password="iso-pw-two") d1, d2 = self.runtime("dev"), self.runtime("prod") - self.seed_agent("dev", 18807, - "--addr 127.0.0.1:18807 --data %s --plugins %s --auth auto" + self.seed_agent("dev", dev_port, + f"--addr 127.0.0.1:{dev_port} --data %s --plugins %s --auth auto" % (d1 / "data", d1 / "plugins"), extra_rows=[("dbref", "pg1/agent"), ("db", "pg")]) - self.seed_agent("prod", 18808, - "--addr 127.0.0.1:18808 --data %s --plugins %s --auth auto" + self.seed_agent("prod", prod_port, + f"--addr 127.0.0.1:{prod_port} --data %s --plugins %s --auth auto" % (d2 / "data", d2 / "plugins"), extra_rows=[("dbref", "pg2/agent"), ("db", "pg")]) dsn1 = "postgresql://agent:iso-pw-one@127.0.0.1:18903/agent" @@ -638,12 +669,13 @@ class SvcDbRecoveryTests(unittest.TestCase): return shas[1], shas[0] # (旧, 新) def test_update_preserves_binding(self): + port = self.available_port() old_sha, new_sha = self.make_src_repo() self.register_pg("pg1", 18905, password="upd-pw") dsn = "postgresql://agent:upd-pw@127.0.0.1:18905/agent" d = self.runtime("dev") - self.seed_agent("dev", 18809, - "--addr 127.0.0.1:18809 --data %s --plugins %s --auth auto" + self.seed_agent("dev", port, + f"--addr 127.0.0.1:{port} --data %s --plugins %s --auth auto" % (d / "data", d / "plugins"), extra_rows=[("dbref", "pg1/agent"), ("db", "pg"), ("source", "dev@%s" % old_sha)]) @@ -666,7 +698,7 @@ class SvcDbRecoveryTests(unittest.TestCase): 旧进程占口 → 报「非本服务」。env_config 须按实例清空 SVC_PIDCHECK 等。 """ old_sha, new_sha = self.make_src_repo() - ports = {"a": 18841, "b": 18842} + ports = {name: self.available_port() for name in ("a", "b")} old_pids = {} for name, port in ports.items(): d = self.runtime(name) @@ -730,11 +762,12 @@ class SvcDbRecoveryTests(unittest.TestCase): return env def test_seed_puts_with_temporary_bearer_key_when_auth_on(self): + port = self.available_port() self.register_pg("pg1", 18831, password="seed-pw-1") dsn = "postgresql://agent:seed-pw-1@127.0.0.1:18831/agent" d = self.runtime("dev") - self.seed_agent("dev", 18832, - "--addr 127.0.0.1:18832 --data %s --plugins %s --auth auto --dsn %s" + self.seed_agent("dev", port, + f"--addr 127.0.0.1:{port} --data %s --plugins %s --auth auto --dsn %s" % (d / "data", d / "plugins", dsn)) result = self.svc("dev", "start", env=self.model_env()) self.assertIn("已播种设置:主模型", result.stdout) @@ -750,11 +783,12 @@ class SvcDbRecoveryTests(unittest.TestCase): self.assertIn("apikey revoke --dsn %s --owner op --name svc-seed" % dsn, cli) def test_seed_writes_fallbacks_and_vision(self): + port = self.available_port() self.register_pg("pg1", 18951, password="seed-pw-v") dsn = "postgresql://agent:seed-pw-v@127.0.0.1:18951/agent" d = self.runtime("dev") - self.seed_agent("dev", 18952, - "--addr 127.0.0.1:18952 --data %s --plugins %s --auth auto --dsn %s" + self.seed_agent("dev", port, + f"--addr 127.0.0.1:{port} --data %s --plugins %s --auth auto --dsn %s" % (d / "data", d / "plugins", dsn)) result = self.svc("dev", "start", env=self.model_env( SVC_MODEL_FALLBACKS="ZHIPU/GLM-5.3-FlashX,ZHIPU/GLM-5.3-Flash", @@ -770,11 +804,12 @@ class SvcDbRecoveryTests(unittest.TestCase): self.assertIn('"capable": "deepseek-v4.1-flash,qwen3.8-flash"', body_part) def test_seed_owner_override_skips_account_lookup(self): + port = self.available_port() self.register_pg("pg1", 18833, password="seed-pw-2") dsn = "postgresql://agent:seed-pw-2@127.0.0.1:18833/agent" d = self.runtime("dev") - self.seed_agent("dev", 18834, - "--addr 127.0.0.1:18834 --data %s --plugins %s --auth auto --dsn %s" + self.seed_agent("dev", port, + f"--addr 127.0.0.1:{port} --data %s --plugins %s --auth auto --dsn %s" % (d / "data", d / "plugins", dsn)) result = self.svc("dev", "start", env=self.model_env(SVC_SEED_OWNER="boss")) self.assertIn("已播种设置:主模型", result.stdout) @@ -784,9 +819,10 @@ class SvcDbRecoveryTests(unittest.TestCase): self.assertNotIn("user list", cli) # 显式指定即跳过账号解析 def test_seed_puts_without_credentials_when_auth_off(self): + port = self.available_port() d = self.runtime("dev") - self.seed_agent("dev", 18835, - "--addr 127.0.0.1:18835 --data %s --plugins %s --auth auto" + self.seed_agent("dev", port, + f"--addr 127.0.0.1:{port} --data %s --plugins %s --auth auto" % (d / "data", d / "plugins")) result = self.svc("dev", "start", env=self.model_env()) self.assertIn("已播种设置:主模型", result.stdout) @@ -809,9 +845,10 @@ class SvcDbRecoveryTests(unittest.TestCase): return db def test_seed_replaces_old_system_secret(self): + port = self.available_port() d = self.runtime("dev") - self.seed_agent("dev", 18836, - "--addr 127.0.0.1:18836 --data %s --plugins %s --auth auto" + self.seed_agent("dev", port, + f"--addr 127.0.0.1:{port} --data %s --plugins %s --auth auto" % (d / "data", d / "plugins")) db = self.plant_old_chat_secret("dev", "sk-old-secret") result = self.svc("dev", "start", env=self.model_env()) @@ -826,9 +863,10 @@ class SvcDbRecoveryTests(unittest.TestCase): self.assertEqual(active[0], "sk-stub-model") def test_seed_warns_when_old_secret_stays_active(self): + port = self.available_port() d = self.runtime("dev") - self.seed_agent("dev", 18837, - "--addr 127.0.0.1:18837 --data %s --plugins %s --auth auto" + self.seed_agent("dev", port, + f"--addr 127.0.0.1:{port} --data %s --plugins %s --auth auto" % (d / "data", d / "plugins")) self.plant_old_chat_secret("dev", "sk-old-secret") result = self.svc("dev", "start", env=self.model_env(SVC_STUB_KEEP_OLD_SECRET="1")) @@ -866,7 +904,7 @@ class SvcDbRecoveryTests(unittest.TestCase): run(work, "push", "-u", "origin", "main") return remote, work - def rdm_env(self, remote): + def rdm_env(self, remote, agent_name="rdm1"): env = dict(self.env) env.update({ "SVC_RDM_SRC_DIR": str(self.root / "rdmcache"), @@ -875,6 +913,8 @@ class SvcDbRecoveryTests(unittest.TestCase): "SVC_MODEL_KEY": "sk-stub-model", "SVC_MODEL_NAME": "stub-model", }) + env["SVC_%sWEB_ADDR" % agent_name.upper()] = ( + "127.0.0.1:%d" % self.available_port()) return env def http_get(self, url, timeout=2): @@ -895,9 +935,10 @@ class SvcDbRecoveryTests(unittest.TestCase): return "http://%s:%s/" % (host, port) def test_rdm_source_deploy_end_to_end(self): + port = self.available_port() remote, work = self.make_rdm_repo() env = self.rdm_env(remote) - result = self.svc("rdm1", "deploy", "--from", "rdm", "--port", "18843", env=env) + result = self.svc("rdm1", "deploy", "--from", "rdm", "--port", port, env=env) d = self.runtime("rdm1") # U2:组合产物入不可变 release,经 current 指针解析;插件空集、工作台随 release。 active = d / "current" @@ -921,9 +962,10 @@ class SvcDbRecoveryTests(unittest.TestCase): self.assertNotIn("user list", self.cli_record()) def test_rdm_companion_missing_web_fails_deploy(self): + port = self.available_port() remote, work = self.make_rdm_repo(with_web=False) - env = self.rdm_env(remote) - result = self.svc("rdm2", "deploy", "--from", "rdm", "--port", "18843", + env = self.rdm_env(remote, "rdm2") + result = self.svc("rdm2", "deploy", "--from", "rdm", "--port", port, env=env, check=False) self.assertNotEqual(result.returncode, 0) self.assertIn("ui-missing", result.stdout) @@ -932,20 +974,21 @@ class SvcDbRecoveryTests(unittest.TestCase): self.assertIsNone(self.kv("rdm2web", "kind")) def test_source_switch_requires_flag(self): + port = self.available_port() remote, work = self.make_rdm_repo() - env = self.rdm_env(remote) + env = self.rdm_env(remote, "sw1") # 先以 local 源部署(内嵌 UI 桩一律 200)。 - self.svc("sw1", "deploy", "--from", "local", "--port", "18844") + self.svc("sw1", "deploy", "--from", "local", "--port", port) old = self.kv("sw1", "source") self.assertTrue(old.startswith("local@")) # 无旗标换到 rdm → 拒绝,source 不变。 - denied = self.svc("sw1", "deploy", "--from", "rdm", "--port", "18844", + denied = self.svc("sw1", "deploy", "--from", "rdm", "--port", port, env=env, check=False) self.assertNotEqual(denied.returncode, 0) self.assertIn("allow-source-switch", denied.stdout) self.assertEqual(self.kv("sw1", "source"), old) # 带旗标允许换源,伴生就位。 - ok = self.svc("sw1", "deploy", "--from", "rdm", "--port", "18844", + ok = self.svc("sw1", "deploy", "--from", "rdm", "--port", port, "--allow-source-switch", env=env) self.assertTrue(self.kv("sw1", "source").startswith("rdm@")) self.assertIn("UI 就绪", ok.stdout) @@ -954,6 +997,7 @@ class SvcDbRecoveryTests(unittest.TestCase): self.assertIn("rdm workbench", body) def test_rdm_source_commits_and_update_track(self): + port = self.available_port() remote, work = self.make_rdm_repo() env = self.rdm_env(remote) # commits rdm 列出来自独立 RDM 源仓的可部署提交。 @@ -961,7 +1005,7 @@ class SvcDbRecoveryTests(unittest.TestCase): self.assertIn("RDM 仓提交", result.stdout) self.assertIn("rdm v1", result.stdout) # 部署 v1 → 远端推进 v2 → update 检测可更新并真更新(source 保持 rdm@ 轨道)。 - self.svc("rdm1", "deploy", "--from", "rdm", "--port", "18842", env=env) + self.svc("rdm1", "deploy", "--from", "rdm", "--port", port, env=env) old = self.kv("rdm1", "source") (work / "marker").write_text("v2\n") subprocess.run(["git", "add", "."], cwd=work, env=self.env, timeout=60, check=True) @@ -986,7 +1030,7 @@ class SvcDbRecoveryTests(unittest.TestCase): htdocs = self.root / "static-site" htdocs.mkdir() (htdocs / "index.html").write_text("static-ok\n") - port = 18951 + port = self.available_port() result = self.svc( "uiqa", "deploy", "--kind", "static", "--dir", str(htdocs), "--addr", "127.0.0.1:%d" % port) diff --git a/tests/test_svc_realcombo.py b/tests/test_svc_realcombo.py index 2eaf13c4..579a2919 100644 --- a/tests/test_svc_realcombo.py +++ b/tests/test_svc_realcombo.py @@ -165,7 +165,8 @@ class RealComboTests(tsr.SvcAutoRecoverTests): def test_U3_real_agent_identity_lifecycle_sqlite(self): """真实组合二进制:领养 ensure → verify → 两次裸重启身份/锚点稳定; capabilities v1 探测契约。""" - self.seed_real("rc1", 9471, self.real_bin) + port = self.available_port() + self.seed_real("rc1", port, self.real_bin) result = self.svc("rc1", "start") self.assertIn("已启动", result.stdout) m = self.manifest("rc1") @@ -178,7 +179,7 @@ class RealComboTests(tsr.SvcAutoRecoverTests): self.assertTrue(con.execute( "SELECT count(*) FROM schema_migrations").fetchone()[0] >= 1) con.close() - self.assertTrue(self.http_ok(9471)) + self.assertTrue(self.http_ok(port)) # capabilities v1 契约(探测无副作用形态) cap = subprocess.run([str(self.runtime("rc1") / "bin" / "agent-system"), @@ -203,7 +204,7 @@ class RealComboTests(tsr.SvcAutoRecoverTests): self.assertEqual(self.identity_row("rc1"), [(iid, "sqlite")], "裸重启不得换身份") self.assertEqual(self.manifest("rc1")["instance_id"], iid) - self.assertTrue(self.http_ok(9471)) + self.assertTrue(self.http_ok(port)) self.svc("rc1", "stop") @unittest.skipUnless(REAL_RDM_BIN, "真实 RDM 专项 NOT_RUN:需 SVC_REAL_RDM_BIN") @@ -211,13 +212,14 @@ class RealComboTests(tsr.SvcAutoRecoverTests): """真实 RDM 组合二进制:identity 接线(Backend 公共 CLI)→ serve 门禁 → 领域层可初始化。""" rdm_bin = Path(REAL_RDM_BIN).resolve() - self.seed_real("rcr", 9473, rdm_bin) + port = self.available_port() + self.seed_real("rcr", port, rdm_bin) result = self.svc("rcr", "start") self.assertIn("已启动", result.stdout) m = self.manifest("rcr") iid = m["instance_id"] self.assertEqual(self.identity_row("rcr"), [(iid, "sqlite")]) - self.assertTrue(self.http_ok(9473)) + self.assertTrue(self.http_ok(port)) # RDM 未知子命令明确退出(不落服务路径) bogus = subprocess.run([str(self.runtime("rcr") / "bin" / "agent-system"), "totally-bogus"], @@ -234,9 +236,11 @@ class RealComboTests(tsr.SvcAutoRecoverTests): self.env["RDM_DISABLE_EXEC_TOOLS"] = "1" env = dict(self.env) env.update(ci_git_env()) + agent_port = self.available_port() env.update({"SVC_RDM_SRC_DIR": str(self.root / "rdmcache"), - "SVC_RDM_ORIGIN": RDM_ORIGIN}) - result = self.svc("rcf", "deploy", "--from", "rdm", "--port", "9474", + "SVC_RDM_ORIGIN": RDM_ORIGIN, + "SVC_RCFWEB_ADDR": "127.0.0.1:%d" % self.available_port()}) + result = self.svc("rcf", "deploy", "--from", "rdm", "--port", agent_port, env=env, check=False) if result.returncode != 0: log = self.runtime("rcf") / "svc.log" @@ -259,7 +263,7 @@ class RealComboTests(tsr.SvcAutoRecoverTests): else "rdm", "工作台内容") self.svc("rcf", "restart") self.assertEqual(self.identity_row("rcf"), [(iid, "sqlite")]) - self.assertTrue(self.http_ok(9474)) + self.assertTrue(self.http_ok(agent_port)) self.svc("rcf", "stop") self.svc("rcfweb", "stop") diff --git a/tests/test_svc_recover.py b/tests/test_svc_recover.py index 5030c83e..b02352f1 100644 --- a/tests/test_svc_recover.py +++ b/tests/test_svc_recover.py @@ -184,17 +184,12 @@ esac """ -def free_fixture_port(): - with socket.socket() as reservation: - reservation.bind(("127.0.0.1", 0)) - return reservation.getsockname()[1] - - class SvcAutoRecoverTests(unittest.TestCase): def setUp(self): tmp = tempfile.mkdtemp(prefix="svc-autorecover-") self.addCleanup(shutil.rmtree, tmp, True) self.root = Path(tmp) + self._allocated_ports = set() (self.root / "scripts").mkdir(parents=True) shutil.copy2(SVC_SCRIPT, self.root / "scripts" / "svc.sh") self.trace = self.root / "trace" @@ -254,6 +249,21 @@ class SvcAutoRecoverTests(unittest.TestCase): self.assertEqual(proc.returncode, 0, proc.stdout) return proc + def available_port(self): + """Allocate a distinct service port for this test, including address changes. + + The socket closes before svc.sh binds it, leaving a small allocation-to-start + race with unrelated processes. Keep allocated numbers distinct within the + test so stopped/restarted services never share another instance's port. + """ + while True: + with socket.socket() as sock: + sock.bind(("0.0.0.0", 0)) + port = sock.getsockname()[1] + if port not in self._allocated_ports: + self._allocated_ports.add(port) + return port + def runtime(self, name): return self.root / "runtime" / name @@ -336,14 +346,14 @@ class SvcAutoRecoverTests(unittest.TestCase): # ---- 1. 期望态:start 成功置位 / 显式 stop 清除(含进程已死的 stop)---- def test_start_records_autostart_and_stop_clears(self): - self.seed_agent("dev", free_fixture_port()) + self.seed_agent("dev", self.available_port()) self.start_ok("dev") self.assertEqual(self.kv("dev", "autostart"), "1") self.svc("dev", "stop") self.assertIsNone(self.kv("dev", "autostart")) def test_stop_on_dead_process_clears_autostart(self): - self.seed_agent("dev", free_fixture_port()) + self.seed_agent("dev", self.available_port()) self.start_ok("dev") self.kill9("dev") # 进程已死但 autostart 保留(等待 recover);显式 stop 表示"保持停止"。 @@ -354,7 +364,7 @@ class SvcAutoRecoverTests(unittest.TestCase): # ---- 2. recover:崩溃拉回 / 运行中不动 / 显式停止不复活 / 未启动不碰 ---- def test_recover_restarts_sigkilled_service(self): - port = free_fixture_port() + port = self.available_port() self.seed_agent("dev", port) self.start_ok("dev") old_pid = self.kill9("dev") @@ -371,7 +381,7 @@ class SvcAutoRecoverTests(unittest.TestCase): self.assertIn("--addr 127.0.0.1:%d" % port, self.kv("dev", "exec")) def test_recover_noop_while_running(self): - self.seed_agent("dev", free_fixture_port()) + self.seed_agent("dev", self.available_port()) self.start_ok("dev") pid = self.pid_of("dev") result = self.svc("recover") @@ -380,7 +390,7 @@ class SvcAutoRecoverTests(unittest.TestCase): self.assertEqual(self.history_events("dev", "recover"), []) def test_recover_respects_explicit_stop(self): - self.seed_agent("dev", free_fixture_port()) + self.seed_agent("dev", self.available_port()) self.start_ok("dev") self.svc("dev", "stop") result = self.svc("recover") @@ -389,7 +399,7 @@ class SvcAutoRecoverTests(unittest.TestCase): self.assertEqual(self.history_events("dev", "recover"), []) def test_recover_ignores_never_started_service(self): - self.seed_agent("dev", free_fixture_port()) # 从未 start:无 autostart 键 + self.seed_agent("dev", self.available_port()) # 从未 start:无 autostart 键 result = self.svc("recover") self.assertEqual(result.returncode, 0, result.stdout) self.assertFalse(self.pid_alive(self.pid_of("dev"))) @@ -398,7 +408,7 @@ class SvcAutoRecoverTests(unittest.TestCase): # ---- 3. 并发防护:生命周期锁被持有时 recover 跳过 ---- def test_recover_skips_when_lock_held(self): - self.seed_agent("dev", free_fixture_port()) + self.seed_agent("dev", self.available_port()) self.start_ok("dev") self.kill9("dev") lock = self.runtime("dev") / ".start.lock" @@ -418,7 +428,7 @@ class SvcAutoRecoverTests(unittest.TestCase): # ---- 4. 恢复失败路径:端口被外部进程占用 → fail 事件 + 非零退出 ---- def test_recover_fails_when_port_stolen(self): - port = free_fixture_port() + port = self.available_port() self.seed_agent("dev", port) self.start_ok("dev") self.kill9("dev") @@ -443,7 +453,7 @@ class SvcAutoRecoverTests(unittest.TestCase): if bound: break time.sleep(0.05) - self.assertTrue(bound, "thief 未能在 5s 内监听 18808") + self.assertTrue(bound, f"thief 未能在 5s 内监听 {port}") try: result = self.svc("recover", check=False) self.assertEqual(result.returncode, 1, result.stdout) @@ -487,7 +497,7 @@ class SvcAutoRecoverTests(unittest.TestCase): """模拟 update 误清 pidfile 后本 bin 仍占口:裸 start 应回收并拉起新进程。""" if not self._ss_can_attribute_pid(): self.skipTest("ss -ltnp 无法归因 PID(reclaim_own_port 需此能力)") - port = free_fixture_port() + port = self.available_port() self.seed_agent("dev", port) self.start_ok("dev") old = self.pid_of("dev") @@ -508,7 +518,7 @@ class SvcAutoRecoverTests(unittest.TestCase): def test_start_rejects_foreign_port_occupant(self): """外部 python http.server 占口:start 必须失败并提示非本服务。""" - port = free_fixture_port() + port = self.available_port() self.seed_agent("dev", port) thief = subprocess.Popen( ["python3", "-m", "http.server", str(port), "--bind", "127.0.0.1"], @@ -545,7 +555,7 @@ class SvcAutoRecoverTests(unittest.TestCase): self.assertFalse((unit_dir / "agent-system-svc-recover.service").exists()) def test_recover_reserved_name_rejected(self): - self.seed_agent("recover", free_fixture_port()) # 保留字不可作服务名 + self.seed_agent("recover", self.available_port()) # 保留字不可作服务名 result = self.svc("recover", "recover", check=False) self.assertEqual(result.returncode, 2, result.stdout) -- 2.54.0 From 1c91e6446e60281f36b8e50ec27c5cb4c7bea116 Mon Sep 17 00:00:00 2001 From: weichen Date: Mon, 19 Oct 2026 15:04:25 +0000 Subject: [PATCH 03/36] Add A1 stage 6 review package for the two-trees follow-up Why: The two-trees follow-up initiative needs its first increment (W0 catalog guard, dynamic svc test ports, W3 gap check) packaged for user stage 6 review. Evidence: Targeted unittest run on 000a2d2 recorded in the task card (SELF); PR CI on the final HEAD is the GATE. Impact: Task card and review spec only; implementation landed via agent-exec transport 000a2d2. Refs: .task/feature-rdm-two-trees-followup.md Co-authored-by: Cursor --- .task/feature-rdm-two-trees-followup.md | 94 +++++++++++++++---- ...-10-19-rdm-two-trees-followup-a1-review.md | 64 +++++++++++++ 2 files changed, 138 insertions(+), 20 deletions(-) create mode 100644 docs/superpowers/specs/2026-10-19-rdm-two-trees-followup-a1-review.md diff --git a/.task/feature-rdm-two-trees-followup.md b/.task/feature-rdm-two-trees-followup.md index bd6e47d6..1bd7a9e7 100644 --- a/.task/feature-rdm-two-trees-followup.md +++ b/.task/feature-rdm-two-trees-followup.md @@ -9,23 +9,38 @@ - 分支类型:initiative;initiative_id:feature-rdm-two-trees-followup;root_target:main;immediate_target:main;accepting_requirements:true - 需求分流:verdict=NEW;selected_initiative=无;requirement_sha256=ec5195ceec26c05d94600716514c5f306bd3d2aba2a18e4e71f54a660e0b1b83;triage_receipt=/tmp/tt-followup-triage-20261019.json;receipt_sha256=3abe686c520606f4969e17668843666bfafc4cebd7f869995121ab82ed5dd345 -- 授权与交付终点:<本次允许的动作与终点;未授权事项写明> +- 授权与交付终点:用户 2026-10-19 在遗留项推进中选定“两棵树后续大任务”;本轮终点为建卡登记剩余项,并把第一个增量 A1(W0 清单守护 + svc 测试动态端口 + W3 余项差距核对)推进到阶段 6 评审包。manual 模式:每个增量须用户阶段 6 人审后才合入;未授权:Backend 发版/tag(X3 公开扩展接口,双钥匙由用户执行)、真实模型与付费请求(W11/W12 另提资源方案)、运行库迁移、部署。 - 交付模式:goal-first(目标、范围和交付终点一次确认;范围内连续推进) - 实施执行:agent-per-unit(配置:AGENT-EXECUTION.md) - 合入执行:agent(已授权交付范围内,Review 通过、冲突解决且当前 HEAD 的 CI 通过后合入) - 人工决策点:仅限目标/范围/验收变更、重大取舍、高后果操作或无法自动判定的业务验收 -- 当前阶段:需求拆解;当前增量:I1(待定义) +- 当前阶段:阶段 6 人审(增量 A1,等待用户);当前增量:A1 - 流程依据:仓库根目录 policy/delivery.md(归档后仍按仓库根目录定位) ## 目标与非目标 -<章程:用途与目标、接纳范围与非目标、方案/计划链接、分级测试策略、验收条件、追加领域规则、生命周期。> +### 章程(charter) + +**用途与目标**:承接 `.task/archive/feature-rdm-two-trees-latest-templates.md`(部分收口,Dev #630)未交付部分,按已批准的阶段 4 方案与阶段 5 计划 r1(`modules/documents/docs/records/2026-10-14-rdm-two-trees-latest-templates/rdm-two-trees-stage5-implementation-test-plan-r1.md` 与 work-observation 增补计划 r1)完成两棵树一网的模板、递归实例、追溯、上下文、审计与正式界面。 + +**接纳范围**:W0(DHF 清单守护,原分支 9873a55 未合入部分)、svc 测试动态端口修复、W3 余项(旧数据迁移等,见 A1 差距核对)、W5 追溯网、W7 上下文提供方、W8 RDM 审计投影、W10 正式前端、W11 DHF 全量保真、W12 含真实模型全组合验收、W13 收口,以及 X3/R3/F3/V3 产品链。 + +**非目标**:IAM 项目协作与联动权限(feature-iam-role-permission-linked-capabilities 范围);重新设计已批准方案;未经单独授权的发版、迁移、部署与付费请求。 + +**分级测试策略**:每增量 SELF 定向测试 + 独立 Review → 用户阶段 6 人审 → PR CI(GATE);阶段 7 只在全目标候选固定后正式验收。 + +**生命周期**:增量 A1 → 用户阶段 6 → 后续增量按原计划 B(W5–W7)、C(W8–W10)、D(W11/W12)推进;X3 发版与 W11/W12 资源各自单独授权。 ## 子任务登记 | 子任务分支 | 必需 | 状态 | PR | |---|---|---|---| -| 待登记 | 否 | — | — | +| A1:W0 守护 + svc 动态端口 + W3 差距核对(本分支内增量) | 是 | 待用户阶段 6 人审 | 本分支 PR(草稿) | +| W3 余项(迁移两次同值、图形不透明块、移动/改名引用、旧批准版回取;重复表格待复核,见 A1 评审包第 2 节) | 是 | 待登记(待用户阶段 6 确认) | — | +| B:W5/W7 | 是 | 待登记 | — | +| C:W8/W10 | 是 | 待登记 | — | +| D:W11/W12/W13 | 是 | 待登记(需资源方案) | — | +| X3/R3/F3/V3 | 是 | 待登记(X3 需 Backend 发版,双钥匙) | — | ## Agent 实施收据 @@ -33,36 +48,39 @@ | 单元 ID | 预期范围 | 配置摘要 | 角色 | 候选顺序 | attempt | CLI/模型 | 终态 | transport | fallback | 源码外收据路径 | |---|---|---|---|---|---|---|---|---|---|---| -| 待定义 | — | NOT_RUN | NOT_RUN | NOT_RUN | NOT_RUN | NOT_RUN | NOT_RUN | NOT_RUN | NOT_RUN | — | +| two-trees-followup-a1-w0-guard-and-svc-ports | scripts/dhf_catalog_guard.py、tests/test_dhf_catalog_guard.py、tests/test_svc.py、tests/test_svc_recover.py、tests/test_svc_realcombo.py | config ccf5b7c03ce4;unit 6fe9be3e5516 | implementation | cursor → agy → pi | 1(9075eee055af,fresh_session) | cursor | success | apply ff 8cf4619..000a2d2 | 未触发 | /tmp/leftover-20261019/tt-a1-receipt.json(run b7a8e78a2b6d0d8f6803490c7fa8af2e) | ## 关联方向与规划 -- 适用状态:待核对(无适用规划时说明原因) -- 主记录路径/版本:待核对(路径按仓库根目录定位,归档后不变;只引用唯一正文) -- 对应里程碑:待核对 +- 适用状态:适用 +- 主记录路径/版本:.task/archive/feature-rdm-two-trees-latest-templates.md;modules/documents/docs/records/2026-10-14-rdm-two-trees-latest-templates/(阶段 4 方案、阶段 5 计划 r1) +- 对应里程碑:两棵树一网与 DHF 模板(阶段 6 增量 A–D) ## 需求分析 | ID | 描述 | 项目符合度及依据 | 优先级 | 验收条件 | 依赖 | 结论 | |---|---|---|---|---|---|---| -| R1 | 待填写 | 待评估 | 待定 | 待定义 | 待确认 | 待评审 | +| R1 | W0 DHF 清单守护落地 main | 符合:阶段 5 计划 W0;原实现 38ef548 曾 SELF 通过与限域复审 | P1 | 守护单测通过;不宣称任何模板 published | DHF catalog | 纳入 A1 | +| R2 | svc 测试动态端口 | 符合:并发 worktree 固定端口误入占用路径(cabac58 证据) | P2 | 原断言保留;test_svc/test_svc_recover 通过 | 无 | 纳入 A1 | +| R3 | W3 余项差距核对 | 符合:W3 递归节点主体已在 RDM main(8dd8ebe) | P1 | 逐项列出已交付/缺失与证据 | RDM main | 纳入 A1(仅核对) | ## 方案与计划 -- 方案引用:待填写(含对象版本) -- 实施计划引用:待填写(含增量与需求 ID) -- 测试计划引用:待填写(含需求 ID 与验收条件) +- 方案引用:阶段 4 方案 rdm-two-trees-stage4-design-r1.md(已批准) +- 实施计划引用:rdm-two-trees-stage5-implementation-test-plan-r1.md(已批准)W0/W3;A1 评审包见 docs/superpowers/specs/2026-10-19-rdm-two-trees-followup-a1-review.md +- 测试计划引用:同上计划 W0/W3 验证节;A1 定向单测 ## 阶段记录 | 阶段 | 对象版本 | 状态 | 决策/执行者 | 时间 | 依据 | |---|---|---|---|---|---| -| 需求拆解 | 待定 | 待执行 | — | — | — | +| 需求拆解 | R0 46e331a | 完成 | host | 2026-10-19 | 承接部分收口剩余项 | | 需求评估 | 待定 | 待执行 | — | — | — | | 需求表确认 | 待定 | 待执行 | — | — | — | -| 方案设计 | 待定 | 待执行 | — | — | — | -| 实施计划 | 待定 | 待执行 | — | — | — | -| 实施与自检 | 待定 | 待执行 | — | — | — | +| 方案设计 | 阶段 4 r1 | 沿用已批准方案 | 用户(原任务) | 2026-10-14 | 原卡阶段记录 | +| 实施计划 | 阶段 5 r1 | 沿用已批准计划 | 用户(原任务) | 2026-10-14 | 原卡阶段记录 | +| 实施与自检 | A1 000a2d2 | 完成(SELF) | cursor worker 实施;host 范围审阅与定向单测 | 2026-10-19 | 收据 tt-a1-receipt.json;67 测试 OK(skipped=16 为真实二进制 NOT_RUN) | +| 阶段 6 人审 | A1 评审包 | 待用户 | 用户 | — | docs/superpowers/specs/2026-10-19-rdm-two-trees-followup-a1-review.md | | 正式测试与验收 | 待定 | 待执行 | — | — | — | | 代码 Review | 待定 | 待执行 | — | — | — | | 合入 | 待定 | 待执行 | — | — | — | @@ -72,7 +90,7 @@ | 增量/试验 | 假设 | 范围 | 判断和停止条件 | 授权/决策依据 | 结果 | 变更影响 | 需重审补测 | |---|---|---|---|---|---|---|---| -| 待定义 | — | — | — | 待核对 | NOT_RUN | 待评估 | 待评估 | +| A1 | 原 W0/端口修复在最新 main 上可最小适配重新落地 | Dev scripts/tests | 定向单测通过;原断言不删减;不适配则停止并报告 | 用户 2026-10-19 选定 | 守护脚本与单测按 9873a55 原样落地;端口修复按 cabac58 意图在最新 main 重新实现(原补丁不可直接应用),原断言一一改用分配端口未删减;W3 差距见评审包 | 仅测试与守护脚本 | 阶段 6 人审 | ## 同步记录 @@ -96,9 +114,9 @@ ## 结果与验证(完成后填写) -- 结果: -- 验证:<结论摘要 PASS/FAIL/SKIP/NOT_RUN 逐项;逐条证据由 make evidence 写入上方证据表> -- 影响与剩余项: +- 结果:A1 实施完成(000a2d2),评审包已提交,等待用户阶段 6 人审;未合入。 +- 验证:定向单测 PASS(SELF,67 测试,skipped=16 为真实二进制 NOT_RUN);PR CI(GATE)见合入与清理节;W3 差距为关键字级 SELF。 +- 影响与剩余项:仅 Dev 测试与守护脚本;剩余项见评审包第 3 节(W3 余项、B、C、D、X3 链)。 ## 规划进展与下一步 @@ -157,3 +175,39 @@ "receipt_path": "/home/weichen/.cache/agent-system-dev/evidence/17f97ec95374ca86a9e49b4b7976cf318ae1f7ae5052d8a746ab219907e1be4c.json" } ``` + + +```json +{ + "summary_schema": 1, + "source": "SELF", + "timestamp": "2026-10-19T15:01:26.746182+00:00", + "command": "python3 -m unittest tests.test_dhf_catalog_guard tests.test_svc tests.test_svc_recover tests.test_svc_realcombo", + "exit_code": 0, + "cwd": "/home/weichen/projects/Agent-System-Dev-wt-feature-rdm-two-trees-followup", + "before_head": "000a2d2ae0e29fecd42ff19bf2b42e430be22ef8", + "after_head": "000a2d2ae0e29fecd42ff19bf2b42e430be22ef8", + "branch": "feature/rdm-two-trees-followup", + "target_branch": "main", + "target_head": "2b7fdc39a1f44163f4766701429d61ffd6926f1a", + "root_target": "main", + "immediate_target": "main", + "before_tracked_diff_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "after_tracked_diff_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "output_tail": [ + ".........................[main 579aaee] rdm v2", + " 1 file changed, 1 insertion(+)", + " create mode 100644 marker", + "To /tmp/svc-db-regress-m9jw7ip3/rdmremote.git", + " 526900c..579aaee main -> main", + "..........................ssssssssssssssss", + "----------------------------------------------------------------------", + "Ran 67 tests in 44.079s", + "", + "OK (skipped=16)" + ], + "output_sha256": "cdf6732fa953eedac3fcea3f5d042c64a3d16c93a94f76308a212256b05b75e2", + "receipt_sha256": "4642350698dad77b3ab2397ef089219380651672d7f76113650d942b31b2df7a", + "receipt_path": "/home/weichen/.cache/agent-system-dev/evidence/4642350698dad77b3ab2397ef089219380651672d7f76113650d942b31b2df7a.json" +} +``` diff --git a/docs/superpowers/specs/2026-10-19-rdm-two-trees-followup-a1-review.md b/docs/superpowers/specs/2026-10-19-rdm-two-trees-followup-a1-review.md new file mode 100644 index 00000000..815bb5de --- /dev/null +++ b/docs/superpowers/specs/2026-10-19-rdm-two-trees-followup-a1-review.md @@ -0,0 +1,64 @@ +# 两棵树后续 A1 增量:阶段 6 评审包 + +- 任务卡:`.task/feature-rdm-two-trees-followup.md`(initiative,manual:每个增量用户阶段 6 人审后才合入) +- 对象:Dev `feature/rdm-two-trees-followup`,base `8cf4619`(R0 `46e331a` + 建卡),A1 实施提交 `000a2d2` +- 依据:阶段 5 计划 r1 W0 / W3 节;原分支提交 `9873a55`(W0 守护)、`cabac58`(端口修复) +- 证据来源:本文所有通过类结论均为 SELF(作者本地运行与关键字核对),GATE 以 PR HEAD 的 CI 为准 + +## 1. A1 交付内容 + +| 项 | 变更 | 说明 | +|---|---|---| +| R1 W0 DHF 清单守护 | 新增 `scripts/dhf_catalog_guard.py`(100755)与 `tests/test_dhf_catalog_guard.py` | 与 `9873a55` 内容逐字节一致(`git diff 9873a55 HEAD` 仅显示脚本 mode 为可执行);守护只校验清单状态,不宣称任何模板 published | +| R2 svc 测试动态端口 | `tests/test_svc.py`、`tests/test_svc_recover.py`、`tests/test_svc_realcombo.py` | `cabac58` 补丁已不能在最新 main 直接应用,worker 按其意图重新实现:每个用例经 `available_port()` 分配互不重复的端口,替换 18791–18800、9471–9474 等固定端口与 `free_fixture_port()`;被删除的 7 处断言均以同一断言改用分配端口的形式保留,无断言删减 | + +实施:`agent-exec` cursor worker 第 1 次尝试成功(run `b7a8e78a2b6d0d8f6803490c7fa8af2e`,attempt `9075eee055af`),经 `agent-exec apply` 快进集成,变更路径与单元 `allowed_paths` 一致。 + +定向验证(SELF,被测 HEAD `000a2d2`): + +```text +python3 -m unittest tests.test_dhf_catalog_guard tests.test_svc tests.test_svc_recover tests.test_svc_realcombo +Ran 67 tests ... OK (skipped=16) +``` + +16 个 skip 为需要 `SVC_REAL_*_BIN` 真实二进制的 realcombo 用例(NOT_RUN),与改动前一致。 + +## 2. W3 余项差距核对(RDM `origin/main` = `5a27d78`) + +计划目标测试名:`TestRecursiveBlock|TestLegacyDocMigration|TestTemplateBinding`。 + +| 计划验证点 | main 现状 | 依据(关键字级 SELF,需在后续增量精确复核) | +|---|---|---| +| 递归块、稳定 ID、深于五级 | 已覆盖 | `internal/domain/document_blocks_test.go`:`TestRecursiveBlockInstanceHasIndependentIdentityAndReplays`(depth ≥ 6)、`TestRecursiveBlockReplayRejectsForgedOrFutureNodes`(伪造/未知未来节点拒绝) | +| 模板绑定 | 已覆盖 | `internal/rdmapp/read_isolation_boundary_test.go`:`TestTemplateBindingCannotAliasPublishedProjectOrRetainedTransaction` | +| 合并单元格 | 结构层已覆盖 | `document_blocks_test.go` 断言 `ColSpan == 2`;`template_asset_test.go` 拒绝非法 `RowSpan` | +| 旧 Section.ID 维持为章节身份 | 已覆盖 | `TestLegacySectionBecomesDeterministicRecursiveReadWithoutWrites`、`internal/rdmapp/document_blocks_test.go` `TestLegacyDocSectionNodeIDsSurviveStoreRestart` | +| 旧数据库备份副本迁移两次同值(`TestLegacyDocMigration`) | 缺失 | 无该测试名,未检到双次迁移同值用例 | +| 图形不透明块 | 缺失 | 测试中未检到 figure/opaque 块 | +| 移动/改名保持引用 | 缺失 | 测试中未检到 move/rename 用例 | +| 已批准版与旧下载仍可回取 | 缺失 | 未检到对应用例 | +| 重复组/重复表格 | 部分 | 关键字出现在上述两个测试文件,是否覆盖“重复表格”语义待精确复核 | +| 完成条件:真实项目实例表达新项目建议书及用户需求 12 组要求 | 未验证 | 依赖 W11 DHF 资产 published 状态,当前只能验证实例机制 | + +结论:W3 主体(递归实例、模板绑定、旧 Section 身份)已在 RDM main;余项集中在旧数据迁移幂等、图形块、移动/改名引用与旧批准版回取。建议作为子任务“W3 余项”在 RDM 仓单独登记实施。 + +## 3. 剩余项与门禁 + +| 剩余项 | 门禁 | +|---|---| +| W3 余项(上表缺失 4 项 + 1 项待复核) | 下一增量,RDM 仓 worker 实施 | +| B:W5 追溯网、W7 上下文提供方 | 依赖 W3/W4 稳定 | +| C:W8 RDM 审计投影、W10 正式前端 | W8 接入宿主需 W9;W10 需 W3–W9 合同稳定 | +| D:W11 DHF 全量保真、W12 真实模型全组合验收、W13 收口 | 需资源方案与付费/真实模型授权 | +| X3/R3/F3/V3 产品链 | X3 需 Backend 公开扩展发版,属双钥匙操作,由用户执行 | + +## 4. Review 发现(非阻塞) + +- `tests/test_svc_realcombo.py` 新增的 `SVC_RCFWEB_ADDR` 环境变量不被 `svc.sh` 读取(伴生 `rcfweb` 由 `deploy --kind static` 自行取端口),属无效但无害配置,仅位于默认 NOT_RUN 的真实 RDM 用例;可在后续增量顺带删除。 +- `available_port()` 绑定后即关闭 socket,与 svc.sh 实际绑定之间存在小窗口竞争(docstring 已说明);相较固定端口已消除并行 worktree 间的确定性冲突。 + +## 5. 请用户阶段 6 判定 + +- 通过:A1 进入 PR CI(GATE)与合入窗口,按 #518 排队合入。 +- 修改:指出需调整项,按新单元重新实施。 +- W3 余项是否按第 2 节登记为下一增量。 -- 2.54.0 From dd2f8b1f240a74a0f467533512b88da541c19999 Mon Sep 17 00:00:00 2001 From: weichen Date: Mon, 19 Oct 2026 15:05:52 +0000 Subject: [PATCH 04/36] Record the sync checkpoint Why: bind the task validation checkpoint to the integration baseline. Evidence: SELF recursive component checks; sync_base=2b7fdc39a1f44163f4766701429d61ffd6926f1a; before_record=26e4ea63918b813557022c6bc12c54ff9213e48d. Impact: task metadata only. Refs: .task/feature-rdm-two-trees-followup.md --- .task/feature-rdm-two-trees-followup.md | 1 + 1 file changed, 1 insertion(+) diff --git a/.task/feature-rdm-two-trees-followup.md b/.task/feature-rdm-two-trees-followup.md index 1bd7a9e7..68257b81 100644 --- a/.task/feature-rdm-two-trees-followup.md +++ b/.task/feature-rdm-two-trees-followup.md @@ -211,3 +211,4 @@ "receipt_path": "/home/weichen/.cache/agent-system-dev/evidence/4642350698dad77b3ab2397ef089219380651672d7f76113650d942b31b2df7a.json" } ``` +| 同步(记录前对象) | 2b7fdc39a1f44163f4766701429d61ffd6926f1a | 26e4ea63918b813557022c6bc12c54ff9213e48d | 2026-10-19T15:05:52Z | -- 2.54.0 From 0557e78bb865d862dd64480ba21d7e1207dbf760 Mon Sep 17 00:00:00 2001 From: weichen Date: Mon, 19 Oct 2026 15:06:44 +0000 Subject: [PATCH 05/36] Record A1 targeted tests on the synced HEAD Co-authored-by: Cursor --- .task/feature-rdm-two-trees-followup.md | 36 +++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/.task/feature-rdm-two-trees-followup.md b/.task/feature-rdm-two-trees-followup.md index 68257b81..744265cd 100644 --- a/.task/feature-rdm-two-trees-followup.md +++ b/.task/feature-rdm-two-trees-followup.md @@ -212,3 +212,39 @@ } ``` | 同步(记录前对象) | 2b7fdc39a1f44163f4766701429d61ffd6926f1a | 26e4ea63918b813557022c6bc12c54ff9213e48d | 2026-10-19T15:05:52Z | + + +```json +{ + "summary_schema": 1, + "source": "SELF", + "timestamp": "2026-10-19T15:06:00.721625+00:00", + "command": "python3 -m unittest tests.test_dhf_catalog_guard tests.test_svc tests.test_svc_recover tests.test_svc_realcombo", + "exit_code": 0, + "cwd": "/home/weichen/projects/Agent-System-Dev-wt-feature-rdm-two-trees-followup", + "before_head": "dd2f8b1f240a74a0f467533512b88da541c19999", + "after_head": "dd2f8b1f240a74a0f467533512b88da541c19999", + "branch": "feature/rdm-two-trees-followup", + "target_branch": "main", + "target_head": "2b7fdc39a1f44163f4766701429d61ffd6926f1a", + "root_target": "main", + "immediate_target": "main", + "before_tracked_diff_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "after_tracked_diff_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "output_tail": [ + ".........................[main e5428ad] rdm v2", + " 1 file changed, 1 insertion(+)", + " create mode 100644 marker", + "To /tmp/svc-db-regress-e8y1ohso/rdmremote.git", + " d78f4bf..e5428ad main -> main", + "..........................ssssssssssssssss", + "----------------------------------------------------------------------", + "Ran 67 tests in 41.981s", + "", + "OK (skipped=16)" + ], + "output_sha256": "ea93eda4d2d37fcbe97d826cdda982a1a9274f27284dd7a930d09117de251e04", + "receipt_sha256": "0279d9b351beb2e54b662d4bc98b2b492c3898e931bd2a995ddb31c3e70f0fdb", + "receipt_path": "/home/weichen/.cache/agent-system-dev/evidence/0279d9b351beb2e54b662d4bc98b2b492c3898e931bd2a995ddb31c3e70f0fdb.json" +} +``` -- 2.54.0 From 679da1a07378fab987f608d83c5b27403f6adf49 Mon Sep 17 00:00:00 2001 From: weichen Date: Mon, 19 Oct 2026 15:06:54 +0000 Subject: [PATCH 06/36] Link the two-trees follow-up card to PR 635 Co-authored-by: Cursor --- .task/feature-rdm-two-trees-followup.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.task/feature-rdm-two-trees-followup.md b/.task/feature-rdm-two-trees-followup.md index 744265cd..2554d342 100644 --- a/.task/feature-rdm-two-trees-followup.md +++ b/.task/feature-rdm-two-trees-followup.md @@ -1,6 +1,6 @@ # feature/rdm-two-trees-followup 任务卡 -任务主记录:;状态:进行中;owner:weichen +任务主记录:https://git-home.u1680832.nyat.app:30319/weichen/Agent-System-Dev/pulls/635;状态:进行中;owner:weichen ## 基线与授权 -- 2.54.0 From a5203b33eeb71d3d5b89ecf6a3ac1818cc3582a5 Mon Sep 17 00:00:00 2001 From: weichen Date: Mon, 19 Oct 2026 15:54:02 +0000 Subject: [PATCH 07/36] Record A1 stage 6 approval and register the W3 remainder child Co-authored-by: Cursor --- .task/feature-rdm-two-trees-followup.md | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/.task/feature-rdm-two-trees-followup.md b/.task/feature-rdm-two-trees-followup.md index 2554d342..67c9fc92 100644 --- a/.task/feature-rdm-two-trees-followup.md +++ b/.task/feature-rdm-two-trees-followup.md @@ -14,7 +14,7 @@ - 实施执行:agent-per-unit(配置:AGENT-EXECUTION.md) - 合入执行:agent(已授权交付范围内,Review 通过、冲突解决且当前 HEAD 的 CI 通过后合入) - 人工决策点:仅限目标/范围/验收变更、重大取舍、高后果操作或无法自动判定的业务验收 -- 当前阶段:阶段 6 人审(增量 A1,等待用户);当前增量:A1 +- 当前阶段:A1 已通过阶段 6(保留在本 initiative 分支);下一增量:W3 余项子任务(待启动) - 流程依据:仓库根目录 policy/delivery.md(归档后仍按仓库根目录定位) ## 目标与非目标 @@ -35,8 +35,8 @@ | 子任务分支 | 必需 | 状态 | PR | |---|---|---|---| -| A1:W0 守护 + svc 动态端口 + W3 差距核对(本分支内增量) | 是 | 待用户阶段 6 人审 | 本分支 PR(草稿) | -| W3 余项(迁移两次同值、图形不透明块、移动/改名引用、旧批准版回取;重复表格待复核,见 A1 评审包第 2 节) | 是 | 待登记(待用户阶段 6 确认) | — | +| A1:W0 守护 + svc 动态端口 + W3 差距核对(本分支内增量) | 是 | 已合入(本分支 000a2d2;用户 2026-10-19 阶段 6 通过) | 本分支 PR #635(草稿,initiative 收口时合入 main) | +| W3 余项(迁移两次同值、图形不透明块、移动/改名引用、旧批准版回取;重复表格待复核,见 A1 评审包第 2 节) | 是 | 已登记,待启动(child:feature/rdm-two-trees-followup-w3-rest,RDM 仓实施) | — | | B:W5/W7 | 是 | 待登记 | — | | C:W8/W10 | 是 | 待登记 | — | | D:W11/W12/W13 | 是 | 待登记(需资源方案) | — | @@ -80,7 +80,7 @@ | 方案设计 | 阶段 4 r1 | 沿用已批准方案 | 用户(原任务) | 2026-10-14 | 原卡阶段记录 | | 实施计划 | 阶段 5 r1 | 沿用已批准计划 | 用户(原任务) | 2026-10-14 | 原卡阶段记录 | | 实施与自检 | A1 000a2d2 | 完成(SELF) | cursor worker 实施;host 范围审阅与定向单测 | 2026-10-19 | 收据 tt-a1-receipt.json;67 测试 OK(skipped=16 为真实二进制 NOT_RUN) | -| 阶段 6 人审 | A1 评审包 | 待用户 | 用户 | — | docs/superpowers/specs/2026-10-19-rdm-two-trees-followup-a1-review.md | +| 阶段 6 人审 | A1 679da1a(CI GATE success,test-pg 偶发失败后重跑通过) | 通过 | 用户 | 2026-10-19 | docs/superpowers/specs/2026-10-19-rdm-two-trees-followup-a1-review.md | | 正式测试与验收 | 待定 | 待执行 | — | — | — | | 代码 Review | 待定 | 待执行 | — | — | — | | 合入 | 待定 | 待执行 | — | — | — | @@ -90,7 +90,7 @@ | 增量/试验 | 假设 | 范围 | 判断和停止条件 | 授权/决策依据 | 结果 | 变更影响 | 需重审补测 | |---|---|---|---|---|---|---|---| -| A1 | 原 W0/端口修复在最新 main 上可最小适配重新落地 | Dev scripts/tests | 定向单测通过;原断言不删减;不适配则停止并报告 | 用户 2026-10-19 选定 | 守护脚本与单测按 9873a55 原样落地;端口修复按 cabac58 意图在最新 main 重新实现(原补丁不可直接应用),原断言一一改用分配端口未删减;W3 差距见评审包 | 仅测试与守护脚本 | 阶段 6 人审 | +| A1 | 原 W0/端口修复在最新 main 上可最小适配重新落地 | Dev scripts/tests | 定向单测通过;原断言不删减;不适配则停止并报告 | 用户 2026-10-19 选定 | 守护脚本与单测按 9873a55 原样落地;端口修复按 cabac58 意图在最新 main 重新实现(原补丁不可直接应用),原断言一一改用分配端口未删减;W3 差距见评审包 | 仅测试与守护脚本 | 阶段 6 已通过 | ## 同步记录 @@ -120,13 +120,13 @@ ## 规划进展与下一步 -- 本次推进/剩余:待核对(依据实际成果更新适用方案/规划) -- 首选下一任务:待核对(无适用规划、已完成或受阻时如实说明,不虚构任务) -- 推荐依据:待填写 -- 前置条件/待确认:待核对 -- 预期产物/验收条件:待定义 -- 重复任务核对:待核对(已有/在途任务、PR 与规划记录) -- 启动授权:未授权(建议不自动启动新任务,仍须明确授权) +- 本次推进/剩余:A1 已验收;剩余 W3 余项、B(W5/W7)、C(W8/W10)、D(W11–W13)、X3 产品链 +- 首选下一任务:W3 余项子任务(迁移两次同值、图形不透明块、移动/改名引用、旧批准版回取、重复表格复核) +- 推荐依据:用户 2026-10-19 阶段 6 结论要求登记 W3 余项为下一增量;B/C 依赖 W3/W4 稳定 +- 前置条件/待确认:从本 initiative 分支当前头建 child;RDM 文件与 IAM link(RDM iam-link-u2)可能重叠,启动前核对 +- 预期产物/验收条件:阶段 5 计划 W3 验证节目标测试(含 TestLegacyDocMigration)通过,旧 ID/replay/批准版保留 +- 重复任务核对:RDM main 5a27d78 已有递归块/模板绑定/旧 Section 身份用例,余项无在途任务 +- 启动授权:已登记为计划内子任务;启动时间由用户确定 ## 合入与清理 -- 2.54.0 From 9e6d9690f64a1e970211b3a092084862a2174ad3 Mon Sep 17 00:00:00 2001 From: weichen Date: Mon, 19 Oct 2026 16:14:12 +0000 Subject: [PATCH 08/36] Register the W3 remainder child by branch name Co-authored-by: Cursor --- .task/feature-rdm-two-trees-followup.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.task/feature-rdm-two-trees-followup.md b/.task/feature-rdm-two-trees-followup.md index 67c9fc92..207b02fe 100644 --- a/.task/feature-rdm-two-trees-followup.md +++ b/.task/feature-rdm-two-trees-followup.md @@ -36,7 +36,7 @@ | 子任务分支 | 必需 | 状态 | PR | |---|---|---|---| | A1:W0 守护 + svc 动态端口 + W3 差距核对(本分支内增量) | 是 | 已合入(本分支 000a2d2;用户 2026-10-19 阶段 6 通过) | 本分支 PR #635(草稿,initiative 收口时合入 main) | -| W3 余项(迁移两次同值、图形不透明块、移动/改名引用、旧批准版回取;重复表格待复核,见 A1 评审包第 2 节) | 是 | 已登记,待启动(child:feature/rdm-two-trees-followup-w3-rest,RDM 仓实施) | — | +| feature/rdm-two-trees-followup-w3-rest | 是 | 已登记,待启动(W3 余项:迁移两次同值、图形不透明块、移动/改名引用、旧批准版回取、重复表格复核;见 A1 评审包第 2 节;RDM 仓实施) | — | | B:W5/W7 | 是 | 待登记 | — | | C:W8/W10 | 是 | 待登记 | — | | D:W11/W12/W13 | 是 | 待登记(需资源方案) | — | -- 2.54.0 From a54a95e04aa329f74c6dfff689183cf67ff47b44 Mon Sep 17 00:00:00 2001 From: weichen Date: Mon, 19 Oct 2026 16:15:03 +0000 Subject: [PATCH 09/36] Record the task card for feature-rdm-two-trees-followup-w3-rest Why: establish the authorized task workspace and its initial baseline. Evidence: preserved precheck receipt in .task/feature-rdm-two-trees-followup-w3-rest.md; R0=2b7fdc39a1f44163f4766701429d61ffd6926f1a. Impact: task metadata only; the feature workspace starts at 9e6d9690f64a1e970211b3a092084862a2174ad3. Refs: .task/feature-rdm-two-trees-followup-w3-rest.md --- .../feature-rdm-two-trees-followup-w3-rest.md | 92 +++++++++++++++++++ 1 file changed, 92 insertions(+) create mode 100644 .task/feature-rdm-two-trees-followup-w3-rest.md diff --git a/.task/feature-rdm-two-trees-followup-w3-rest.md b/.task/feature-rdm-two-trees-followup-w3-rest.md new file mode 100644 index 00000000..fad5e591 --- /dev/null +++ b/.task/feature-rdm-two-trees-followup-w3-rest.md @@ -0,0 +1,92 @@ +# feature/rdm-two-trees-followup-w3-rest 任务卡 + +任务主记录:;状态:进行中;owner:weichen + +- 权威仓:ssh://git@git-ssh.u1680832.nyat.app:31411/weichen/Agent-System-Dev.git;目标分支:main;R0(initial_base_sha)= 2b7fdc39a1f44163f4766701429d61ffd6926f1a +- 工作区:/home/weichen/projects/Agent-System-Dev-wt-feature-rdm-two-trees-followup-w3-rest(worktree);分支:feature/rdm-two-trees-followup-w3-rest +- 分支类型:child;initiative_id:feature-rdm-two-trees-followup;root_target:main;immediate_target:feature/rdm-two-trees-followup;accepting_requirements:false;parent_branch:feature/rdm-two-trees-followup;parent_head_sha:9e6d9690f64a1e970211b3a092084862a2174ad3;parent_pr:无;parent_source:origin +- 需求分流:免(父 initiative 子任务登记已列出 feature/rdm-two-trees-followup-w3-rest;parent_head_sha=9e6d9690f64a1e970211b3a092084862a2174ad3) + +- 授权与交付终点:<本次允许的动作与终点;未授权事项写明> +- 交付模式:goal-first(目标、范围和交付终点一次确认;范围内连续推进) +- 实施执行:agent-per-unit(配置:AGENT-EXECUTION.md) +- 合入执行:agent(已授权交付范围内,Review 通过、冲突解决且当前 HEAD 的 CI 通过后合入) +- 流程依据:仓库根目录 policy/delivery.md(归档后仍按仓库根目录定位) + +## 目标与非目标 + +<预期结果、受影响入口/模块/契约;明确不做什么。> + +## Agent 实施收据 + +路由与 fail-stop 规则见根目录 AGENT-EXECUTION.md 与 policy/delivery.md;每次尝试一行,原始日志留在源码外收据路径。 + +| 单元 ID | 预期范围 | 配置摘要 | 角色 | 候选顺序 | attempt | CLI/模型 | 终态 | transport | fallback | 源码外收据路径 | +|---|---|---|---|---|---|---|---|---|---|---| +| 待定义 | — | NOT_RUN | NOT_RUN | NOT_RUN | NOT_RUN | NOT_RUN | NOT_RUN | NOT_RUN | NOT_RUN | — | + +## 同步记录 + +| 节点 | sync_base_sha | tested_head_sha | checked_at | +|---|---|---|---| +| 启动 | 2b7fdc39a1f44163f4766701429d61ffd6926f1a | 9e6d9690f64a1e970211b3a092084862a2174ad3 | 2026-10-19T16:15:03Z | + +## 证据(Evidence) + + +| 时间(UTC) | 命令 | 被测HEAD | exit | 来源 | sha256(16) | +|---|---|---|---|---|---| + +## 结果与验证(完成后填写) + +- 结果: +- 验证:<结论摘要 PASS/FAIL/SKIP/NOT_RUN 逐项;逐条证据由 make evidence 写入上方证据表> +- 影响与剩余项: + +## 合入与清理 + +- Review 记录:NOT_RUN(审阅智能体/平台身份、base/head、结论、问题闭合及重放依据) +- 冲突记录:NOT_RUN(最新目标同步、冲突处置、组合兼容核验及复审/补测) +- CI 记录:NOT_RUN(当前 HEAD 完整 SHA、全部必需检查、运行链接、执行身份及 GATE 结果) +- 合入记录:NOT_RUN(交付授权范围、PR、被核验 HEAD、合入 SHA、目标分支及内容核验) +- 清理记录:NOT_RUN(授权依据、写者退出确认、worktree/分支/任务卡处置) + + +```json +{ + "summary_schema": 1, + "source": "SELF", + "timestamp": "2026-10-19T16:13:50.819321+00:00", + "command": "make precheck", + "exit_code": 0, + "cwd": "/home/weichen/projects/Agent-System-Dev", + "before_head": "2b7fdc39a1f44163f4766701429d61ffd6926f1a", + "after_head": "2b7fdc39a1f44163f4766701429d61ffd6926f1a", + "branch": "main", + "target_branch": "main", + "target_head": "2b7fdc39a1f44163f4766701429d61ffd6926f1a", + "root_target": "main", + "immediate_target": "main", + "before_tracked_diff_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "after_tracked_diff_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "output_tail": [ + "make[1]: Entering directory '/home/weichen/projects/Agent-System-Dev'", + "[repo] branch=main head=2b7fdc39a1", + "[remote] origin/main=2b7fdc39a1 ahead=0 behind=0", + "[tree] clean submodules_drift=0 uninit=0", + "[worktrees] linked=4", + "[recycle] merged un-recycled branches: feature/layered-python-env", + "[initiatives] local cards (not authoritative): none", + "[hooks] core.hooksPath=scripts/hooks(pre-commit/post-merge 实际接线)", + "[facts] policy/facts.md 6 条事实均在有效期内", + "[required-reading] core/baseline.md, workflows/delivery.md §1, policy/delivery.md", + "[R0] 2b7fdc39a1(完整:2b7fdc39a1f44163f4766701429d61ffd6926f1a)", + "[worktree] before-sync: recursive component checks passed", + "[verdict] READY — 保留本次 precheck receipt 后建任务工作区:PRECHECK_RECEIPT=/tmp/task-precheck.json make task-start NAME=feature/your-branch", + "make[1]: Leaving directory '/home/weichen/projects/Agent-System-Dev'" + ], + "output_sha256": "ad2f421c16acf4d72ad5396eb19b97aa168900e85db78022bd77c6eac29b3040", + "receipt_sha256": "abc4088cf722985bd2eeeffeae46cdd899a23e6b1c2711b8849f14f83c8e46bf", + "receipt_path": "/home/weichen/.cache/agent-system-dev/evidence/abc4088cf722985bd2eeeffeae46cdd899a23e6b1c2711b8849f14f83c8e46bf.json" +} +``` -- 2.54.0 From 80ac3fa194b11dbbec4d2d65e79d8b1ea2a5d29b Mon Sep 17 00:00:00 2001 From: agent-exec-transport Date: Mon, 19 Oct 2026 17:22:37 +0000 Subject: [PATCH 10/36] agent-exec transport 21efb3a4e69a41fcbd643b12faeb1288/21d30978680a --- tests/test_svc_realcombo.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/test_svc_realcombo.py b/tests/test_svc_realcombo.py index 579a2919..4c2dd6c0 100644 --- a/tests/test_svc_realcombo.py +++ b/tests/test_svc_realcombo.py @@ -238,8 +238,7 @@ class RealComboTests(tsr.SvcAutoRecoverTests): env.update(ci_git_env()) agent_port = self.available_port() env.update({"SVC_RDM_SRC_DIR": str(self.root / "rdmcache"), - "SVC_RDM_ORIGIN": RDM_ORIGIN, - "SVC_RCFWEB_ADDR": "127.0.0.1:%d" % self.available_port()}) + "SVC_RDM_ORIGIN": RDM_ORIGIN}) result = self.svc("rcf", "deploy", "--from", "rdm", "--port", agent_port, env=env, check=False) if result.returncode != 0: -- 2.54.0 From b3f0ee8fe5134b66c92818a419cc0cdff97f104f Mon Sep 17 00:00:00 2001 From: weichen Date: Tue, 20 Oct 2026 01:13:20 +0000 Subject: [PATCH 11/36] Fill the W3 remainder child card with scope and authorization Why: record the authorized end point and scope for the W3 remainder child task. Evidence: card fields only (SELF). Impact: task card only. Refs: docs/superpowers/specs/2026-10-19-rdm-two-trees-followup-a1-review.md Co-authored-by: Cursor --- .task/feature-rdm-two-trees-followup-w3-rest.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.task/feature-rdm-two-trees-followup-w3-rest.md b/.task/feature-rdm-two-trees-followup-w3-rest.md index fad5e591..a63eac3e 100644 --- a/.task/feature-rdm-two-trees-followup-w3-rest.md +++ b/.task/feature-rdm-two-trees-followup-w3-rest.md @@ -7,7 +7,7 @@ - 分支类型:child;initiative_id:feature-rdm-two-trees-followup;root_target:main;immediate_target:feature/rdm-two-trees-followup;accepting_requirements:false;parent_branch:feature/rdm-two-trees-followup;parent_head_sha:9e6d9690f64a1e970211b3a092084862a2174ad3;parent_pr:无;parent_source:origin - 需求分流:免(父 initiative 子任务登记已列出 feature/rdm-two-trees-followup-w3-rest;parent_head_sha=9e6d9690f64a1e970211b3a092084862a2174ad3) -- 授权与交付终点:<本次允许的动作与终点;未授权事项写明> +- 授权与交付终点:用户 2026-10-19“授权启动 W3”;终点为 RDM 草稿 PR + 本子任务 PR CI 通过 + 阶段 6 评审包,等待用户阶段 6 人审后才合入父 initiative 分支。未授权:RDM 合入 main、运行库迁移、部署、真实模型/付费请求。 - 交付模式:goal-first(目标、范围和交付终点一次确认;范围内连续推进) - 实施执行:agent-per-unit(配置:AGENT-EXECUTION.md) - 合入执行:agent(已授权交付范围内,Review 通过、冲突解决且当前 HEAD 的 CI 通过后合入) @@ -15,7 +15,9 @@ ## 目标与非目标 -<预期结果、受影响入口/模块/契约;明确不做什么。> +- 目标:补齐 A1 差距核对中的 W3 余项——图形不透明块、重复表格精确覆盖、节点移动/改名保持引用、旧库备份迁移两次同值、已批准版与旧下载可回取;Dev 侧删除无效 `SVC_RCFWEB_ADDR`。 +- 受影响:RDM `internal/domain`(模板块校验、递归节点、两种新事件)及测试;Dev `tests/test_svc_realcombo.py`。 +- 非目标:不提供结构变更的 HTTP/插件入口(W4 负责结构提案门控);不改 DHF 渲染;不宣称正式 DHF 模板可用。 ## Agent 实施收据 -- 2.54.0 From 8a4ebe4e6c9ebf8198f60b5ee9f9d8be18d8c3d9 Mon Sep 17 00:00:00 2001 From: weichen Date: Tue, 20 Oct 2026 01:58:50 +0000 Subject: [PATCH 12/36] Add the W3 remainder stage 6 review package Why: W3 remainder is implemented on RDM draft PR #451 and needs the user's stage 6 review before merging into the initiative. Evidence: RDM f3fa0c0 target tests and domain/rdmapp packages pass locally (SELF); fresh-session review PASS-with-fixes with no blocking findings. Impact: task cards and review docs only; placement checks recorded as a W4 write-entry prerequisite. Refs: feature/rdm-two-trees-followup-w3-rest, RDM PR #451 Co-authored-by: Cursor --- .../feature-rdm-two-trees-followup-w3-rest.md | 8 ++-- .task/feature-rdm-two-trees-followup.md | 4 +- ...-10-19-rdm-two-trees-followup-w3-review.md | 42 +++++++++++++++++++ 3 files changed, 48 insertions(+), 6 deletions(-) create mode 100644 docs/superpowers/specs/2026-10-19-rdm-two-trees-followup-w3-review.md diff --git a/.task/feature-rdm-two-trees-followup-w3-rest.md b/.task/feature-rdm-two-trees-followup-w3-rest.md index a63eac3e..963f50f1 100644 --- a/.task/feature-rdm-two-trees-followup-w3-rest.md +++ b/.task/feature-rdm-two-trees-followup-w3-rest.md @@ -41,13 +41,13 @@ ## 结果与验证(完成后填写) -- 结果: -- 验证:<结论摘要 PASS/FAIL/SKIP/NOT_RUN 逐项;逐条证据由 make evidence 写入上方证据表> -- 影响与剩余项: +- 结果:W3 余项在 RDM 分支 `feature/rdm-two-trees-followup-w3-rest`(`013b8b1`、`96d53f6`、`f3fa0c0`,草稿 PR [#451](https://git-home.u1680832.nyat.app:30319/weichen/Agent-System-RDM/pulls/451))与本分支 `80ac3fa` 交付;阶段 6 评审包 docs/superpowers/specs/2026-10-19-rdm-two-trees-followup-w3-review.md。 +- 验证:RDM 目标测试 20 项与 `./internal/domain/... ./internal/rdmapp` 全量 PASS(SELF,@f3fa0c0);CI(GATE)见下方 CI 记录;Dev `py_compile` PASS(SELF)。 +- 影响与剩余项:仅 RDM 领域原语与测试(无新写入口)及 Dev 测试一行;剩余见评审包第 3 节与 Review 非阻塞项(W4 写入口前补节点放置检查)。 ## 合入与清理 -- Review 记录:NOT_RUN(审阅智能体/平台身份、base/head、结论、问题闭合及重放依据) +- Review 记录:全新会话 code-reviewer(只接收需求、base/head、diff),RDM `5a27d78..f3fa0c0`:PASS-with-fixes,无阻塞项;4 条非阻塞项记入评审包第 2 节(放置检查列为 W4 写入口前置条件)。 - 冲突记录:NOT_RUN(最新目标同步、冲突处置、组合兼容核验及复审/补测) - CI 记录:NOT_RUN(当前 HEAD 完整 SHA、全部必需检查、运行链接、执行身份及 GATE 结果) - 合入记录:NOT_RUN(交付授权范围、PR、被核验 HEAD、合入 SHA、目标分支及内容核验) diff --git a/.task/feature-rdm-two-trees-followup.md b/.task/feature-rdm-two-trees-followup.md index 207b02fe..20c063c0 100644 --- a/.task/feature-rdm-two-trees-followup.md +++ b/.task/feature-rdm-two-trees-followup.md @@ -14,7 +14,7 @@ - 实施执行:agent-per-unit(配置:AGENT-EXECUTION.md) - 合入执行:agent(已授权交付范围内,Review 通过、冲突解决且当前 HEAD 的 CI 通过后合入) - 人工决策点:仅限目标/范围/验收变更、重大取舍、高后果操作或无法自动判定的业务验收 -- 当前阶段:A1 已通过阶段 6(保留在本 initiative 分支);下一增量:W3 余项子任务(待启动) +- 当前阶段:A1 已通过阶段 6(保留在本 initiative 分支);W3 余项子任务待用户阶段 6 人审 - 流程依据:仓库根目录 policy/delivery.md(归档后仍按仓库根目录定位) ## 目标与非目标 @@ -36,7 +36,7 @@ | 子任务分支 | 必需 | 状态 | PR | |---|---|---|---| | A1:W0 守护 + svc 动态端口 + W3 差距核对(本分支内增量) | 是 | 已合入(本分支 000a2d2;用户 2026-10-19 阶段 6 通过) | 本分支 PR #635(草稿,initiative 收口时合入 main) | -| feature/rdm-two-trees-followup-w3-rest | 是 | 已登记,待启动(W3 余项:迁移两次同值、图形不透明块、移动/改名引用、旧批准版回取、重复表格复核;见 A1 评审包第 2 节;RDM 仓实施) | — | +| feature/rdm-two-trees-followup-w3-rest | 是 | 实施完成,待用户阶段 6 人审(W3 余项:迁移两次同值、图形不透明块、移动/改名引用、旧批准版回取、重复表格复核;评审包 docs/superpowers/specs/2026-10-19-rdm-two-trees-followup-w3-review.md) | RDM 草稿 PR [#451](https://git-home.u1680832.nyat.app:30319/weichen/Agent-System-RDM/pulls/451);本子任务 PR 见卡 | | B:W5/W7 | 是 | 待登记 | — | | C:W8/W10 | 是 | 待登记 | — | | D:W11/W12/W13 | 是 | 待登记(需资源方案) | — | diff --git a/docs/superpowers/specs/2026-10-19-rdm-two-trees-followup-w3-review.md b/docs/superpowers/specs/2026-10-19-rdm-two-trees-followup-w3-review.md new file mode 100644 index 00000000..c45ab288 --- /dev/null +++ b/docs/superpowers/specs/2026-10-19-rdm-two-trees-followup-w3-review.md @@ -0,0 +1,42 @@ +# 两棵树后续 W3 余项:阶段 6 评审包 + +- 状态:**待用户阶段 6 人审**。manual 模式:人审通过前不合入 initiative 分支;RDM 改动以草稿 PR [#451](https://git-home.u1680832.nyat.app:30319/weichen/Agent-System-RDM/pulls/451) 形式待审。 +- 日期:2026-10-19;作者:host;子任务分支:Dev `feature/rdm-two-trees-followup-w3-rest`(父 `feature/rdm-two-trees-followup`)、RDM `feature/rdm-two-trees-followup-w3-rest`(base RDM main `5a27d78`)。 +- 依据:[阶段 5 计划 W3](../../../modules/documents/docs/records/2026-10-14-rdm-two-trees-latest-templates/rdm-two-trees-stage5-implementation-test-plan-r1.md)(已批准);[A1 评审包第 2 节差距核对](2026-10-19-rdm-two-trees-followup-a1-review.md)。 + +## 1. 本增量交付 + +| 差距项(A1 第 2 节) | 交付 | RDM 提交 | 目标测试 | +|---|---|---|---| +| 图形不透明块 | `ContentBlock.Kind` 新增 `figure`:不透明叶子,禁子块/重复/跨格,必须引用带 SHA-256 的附件或 Word 槽位;实例化、重放、`NodesOf` 逐字节保持 | `013b8b1` | `TestRecursiveBlockFigure*` | +| 重复表格(待复核) | 补精确用例:重复行与 v2 重复章节通过校验、实例节点 ID 各异、保留 `Repeat` 与 `RowSpan/ColSpan`、可重放;非法位置拒绝 | `013b8b1` | `TestRecursiveBlockRepeat*` | +| 移动/改名保持引用 | 领域原语 `MoveNode`/`RenameNode`,新事件 `doc.node.move`/`doc.node.rename`:节点 ID、模板块、内容不变;兄弟序连续重排;文档结构修订 +1,乐观并发;拒绝环、陈旧修订、旧章节节点、空标题、只读日志;live 与 replay 共用同一算法;前缀重放可取回更早结构 | `96d53f6` | `TestRecursiveBlockMove*`、`TestRecursiveBlockRename*`、`TestRecursiveBlockMoveRenameNodeRefsSurviveStoreRestart` | +| 旧库备份迁移两次同值;已批准版与旧下载可回取 | 新增 `TestLegacyDocMigration*`:旧形态库(文档/章节/版本/批准)复制为备份副本后两次独立打开与重放,事件行、序号、迁移版本与 `NodesOf` 一致,第二次不写入;未知未来事件类型在启动时写前拒绝;迁移后已批准版与审批提交下载字节/哈希不变(只增测试,未改生产代码) | `f3fa0c0` | `TestLegacyDocMigration*` | +| Dev:删除无效 `SVC_RCFWEB_ADDR` | `tests/test_svc_realcombo.py` 删除 `svc.sh` 从不读取的 `SVC_RCFWEB_ADDR` | Dev `80ac3fa` | `py_compile` | + +## 2. 验证 + +- host 本地验证(SELF)@RDM `f3fa0c0`:`gofmt`、`go vet ./internal/domain/... ./internal/rdmapp`、`git diff --check` 通过;目标选择器 `GOWORK=off go test ./internal/domain ./internal/rdmapp -run 'TestRecursiveBlock|TestLegacyDocMigration|TestTemplateBinding' -count=1` 20 项 PASS;`./internal/domain/... ./internal/rdmapp` 全量 PASS。 +- CI(GATE):RDM 草稿 PR [#451](https://git-home.u1680832.nyat.app:30319/weichen/Agent-System-RDM/pulls/451) 与本子任务 PR 当前 HEAD 检查(见 PR)。 +- 独立 Review(全新会话 code-reviewer,只接收需求、base/head 与 diff;评审者自跑为 SELF):`5a27d78..f3fa0c0` **PASS-with-fixes,无阻塞项**。确认:克隆与摘除无共享切片、校验全过才写入;live 与 replay 共用算法;伪造节点 ID/旧章节/未知 op 被拒;`validateDocNodes` 对既有调用方等价;无新增写入口;测试断言非空。非阻塞项(建议 W4 开放写入口前修): + 1. 移动不检查节点种类放置关系(row 可移出 table、cell 可移出 row),`rendererNodeKind` 会照常渲染为表格行;应在 `movedDocNodes` 加放置检查并把相应测试改为预期拒绝——**列为 W4 写入口的前置条件**。 + 2. `TestLegacyDocMigration` 在 WAL 模式下计算哈希可能漏掉 `-wal` 中的写入。 + 3. Postgres 用例的“第二次不写库”写入次数硬编码为 0。 + 4. `figure` 在渲染时退化为空段落(超出本增量需求,导出前须映射或显式报错)。 + 另:移动/改名事件 `Target` 与载荷 `DocID` 未做一致性校验;重放查找不过滤已删除文档(当前无删除路径)。 + +## 3. 风险与需人审确认 + +1. **与 W4 的边界**:移动/改名只提供领域原语,没有 HTTP 路由、插件命令或 rdmapp 写入口;按阶段 5 计划,结构变更须经 W4 结构提案与人工确认后才能调用。W4 开放写入口前须先补节点种类放置检查(独立 Review 非阻塞项 1)。请确认这一切分。 +2. **合入冲突**:`internal/domain/template_asset.go`(figure 校验)同时被在途的 project-access-lifecycle 任务修改;本增量只新增一个 case 和一个函数,后合入的一方需要按最新 main 解决冲突。 +3. **事件契约新增**:两种新事件对旧二进制属于未知未来事件,旧版本读到时会拒绝启动写入(符合计划的“未知未来事件拒绝”);部署顺序须先升级再产生新事件。 +4. **完成条件中的业务项**:“真实项目实例表达新项目建议书及用户需求 12 组要求”依赖 W11 DHF 资产 published,本增量只验证实例机制,不宣称正式标准模板可用。 + +## 4. 执行记录 + +| 单元 | CLI/候选 | 终态 | 收据(源码外) | +|---|---|---|---| +| w3-rest-u1-figure-opaque-repeat-table | Cursor attempt 1 | success | /tmp/leftover-20261019b/w3-u1-receipt.json | +| w3-rest-u2-node-move-rename-refs | Cursor attempt 1 | success | /tmp/leftover-20261019b/w3-u2-receipt.json | +| w3-rest-u3-legacy-migration-approved-retrieval | Cursor run 1 `failed-unknown`(host 在其运行期间集成 u1,HEAD 变化);用户授权全新 run 2 | run 2 `blocked`(隔离区缺 `pins/` 无法编译 rdmapp);修正单元包后经用户授权 run 3 success | /tmp/leftover-20261019b/w3-u3-receipt*.json | +| w3-rest-dev-drop-svc-rcfweb-addr | Cursor run 1 `invalid-config`(单元包未就绪)、run 2 `failed-unknown`(Cursor 连接反复失败);用户授权全新 run 3 | success | /tmp/leftover-20261019b/w3-dev-receipt*.json | -- 2.54.0 From fa6715621c79be7108be3e9ba1d1f44c945a9ecb Mon Sep 17 00:00:00 2001 From: weichen Date: Tue, 20 Oct 2026 01:59:50 +0000 Subject: [PATCH 13/36] Link the W3 remainder card to its pull request Why: the task card and PR description are one document and must point at each other. Evidence: PR #641 opened against feature/rdm-two-trees-followup. Impact: task card only. Refs: PR #641 Co-authored-by: Cursor --- .task/feature-rdm-two-trees-followup-w3-rest.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.task/feature-rdm-two-trees-followup-w3-rest.md b/.task/feature-rdm-two-trees-followup-w3-rest.md index 963f50f1..d6f610f2 100644 --- a/.task/feature-rdm-two-trees-followup-w3-rest.md +++ b/.task/feature-rdm-two-trees-followup-w3-rest.md @@ -1,6 +1,6 @@ # feature/rdm-two-trees-followup-w3-rest 任务卡 -任务主记录:;状态:进行中;owner:weichen +任务主记录:PR [#641](https://git-home.u1680832.nyat.app:30319/weichen/Agent-System-Dev/pulls/641)(草稿);状态:待用户阶段 6 人审;owner:weichen - 权威仓:ssh://git@git-ssh.u1680832.nyat.app:31411/weichen/Agent-System-Dev.git;目标分支:main;R0(initial_base_sha)= 2b7fdc39a1f44163f4766701429d61ffd6926f1a - 工作区:/home/weichen/projects/Agent-System-Dev-wt-feature-rdm-two-trees-followup-w3-rest(worktree);分支:feature/rdm-two-trees-followup-w3-rest -- 2.54.0 From 2a5c743220b532a88c3807b24ec55fae4ed41de6 Mon Sep 17 00:00:00 2001 From: weichen Date: Tue, 20 Oct 2026 03:13:23 +0000 Subject: [PATCH 14/36] Record W3 remainder stage 6 approval and RDM merge Why: The user approved the W3 remainder at stage 6 on 2026-10-20 and authorized merging RDM #451 into RDM main. Evidence: RDM #451 merged at 76b4c05 after head f3fa0c0 status success; merged tree 4cfacf16 matches the pre-merge merge-tree. Impact: Task cards and review package only; W4 write entry points must first add node placement checks. Refs: Agent-System-RDM#451, Agent-System-Dev#641 Co-authored-by: Cursor --- .../feature-rdm-two-trees-followup-w3-rest.md | 9 +++++---- .task/feature-rdm-two-trees-followup.md | 18 +++++++++--------- ...6-10-19-rdm-two-trees-followup-w3-review.md | 2 +- 3 files changed, 15 insertions(+), 14 deletions(-) diff --git a/.task/feature-rdm-two-trees-followup-w3-rest.md b/.task/feature-rdm-two-trees-followup-w3-rest.md index d6f610f2..b225e79e 100644 --- a/.task/feature-rdm-two-trees-followup-w3-rest.md +++ b/.task/feature-rdm-two-trees-followup-w3-rest.md @@ -1,13 +1,13 @@ # feature/rdm-two-trees-followup-w3-rest 任务卡 -任务主记录:PR [#641](https://git-home.u1680832.nyat.app:30319/weichen/Agent-System-Dev/pulls/641)(草稿);状态:待用户阶段 6 人审;owner:weichen +任务主记录:PR [#641](https://git-home.u1680832.nyat.app:30319/weichen/Agent-System-Dev/pulls/641);状态:用户阶段 6 通过(2026-10-20),合入父 initiative 分支中;owner:weichen - 权威仓:ssh://git@git-ssh.u1680832.nyat.app:31411/weichen/Agent-System-Dev.git;目标分支:main;R0(initial_base_sha)= 2b7fdc39a1f44163f4766701429d61ffd6926f1a - 工作区:/home/weichen/projects/Agent-System-Dev-wt-feature-rdm-two-trees-followup-w3-rest(worktree);分支:feature/rdm-two-trees-followup-w3-rest - 分支类型:child;initiative_id:feature-rdm-two-trees-followup;root_target:main;immediate_target:feature/rdm-two-trees-followup;accepting_requirements:false;parent_branch:feature/rdm-two-trees-followup;parent_head_sha:9e6d9690f64a1e970211b3a092084862a2174ad3;parent_pr:无;parent_source:origin - 需求分流:免(父 initiative 子任务登记已列出 feature/rdm-two-trees-followup-w3-rest;parent_head_sha=9e6d9690f64a1e970211b3a092084862a2174ad3) -- 授权与交付终点:用户 2026-10-19“授权启动 W3”;终点为 RDM 草稿 PR + 本子任务 PR CI 通过 + 阶段 6 评审包,等待用户阶段 6 人审后才合入父 initiative 分支。未授权:RDM 合入 main、运行库迁移、部署、真实模型/付费请求。 +- 授权与交付终点:用户 2026-10-19“授权启动 W3”;终点为 RDM 草稿 PR + 本子任务 PR CI 通过 + 阶段 6 评审包,等待用户阶段 6 人审后才合入父 initiative 分支。未授权:运行库迁移、部署、真实模型/付费请求。用户 2026-10-20 阶段 6 结论“通过”,同时授权 RDM #451 合入 RDM main(附条件:W4 开放结构写入口前必须先补节点种类放置检查)。 - 交付模式:goal-first(目标、范围和交付终点一次确认;范围内连续推进) - 实施执行:agent-per-unit(配置:AGENT-EXECUTION.md) - 合入执行:agent(已授权交付范围内,Review 通过、冲突解决且当前 HEAD 的 CI 通过后合入) @@ -50,8 +50,9 @@ - Review 记录:全新会话 code-reviewer(只接收需求、base/head、diff),RDM `5a27d78..f3fa0c0`:PASS-with-fixes,无阻塞项;4 条非阻塞项记入评审包第 2 节(放置检查列为 W4 写入口前置条件)。 - 冲突记录:NOT_RUN(最新目标同步、冲突处置、组合兼容核验及复审/补测) - CI 记录:NOT_RUN(当前 HEAD 完整 SHA、全部必需检查、运行链接、执行身份及 GATE 结果) -- 合入记录:NOT_RUN(交付授权范围、PR、被核验 HEAD、合入 SHA、目标分支及内容核验) -- 清理记录:NOT_RUN(授权依据、写者退出确认、worktree/分支/任务卡处置) +- 合入记录(RDM):用户 2026-10-20 阶段 6 通过并授权;RDM PR [#451](https://git-home.u1680832.nyat.app:30319/weichen/Agent-System-RDM/pulls/451) 核验 HEAD `f3fa0c0e5`、commit status success(2 项,GATE)后合入 RDM main,合入提交 `76b4c0572622c81316511de174469f5f67d31785`;合入后 tree `4cfacf16` 与合入前 `git merge-tree` 预期一致。Dev gitlink 改钉留待 initiative 收口统一组合验证。 +- 合入记录(本 PR):NOT_RUN(交付授权范围、PR、被核验 HEAD、合入 SHA、目标分支及内容核验) +- 清理记录:RDM worktree `Agent-System-RDM-wt-feature-rdm-two-trees-followup-w3-rest` 已核验无写者、子模块干净(仅删除可再生的 `internal/rdmapp/data` 测试产物)后移除,本地分支已删;Dev 子 worktree 待本 PR 合入后回收。 ```json diff --git a/.task/feature-rdm-two-trees-followup.md b/.task/feature-rdm-two-trees-followup.md index 20c063c0..ac9d996f 100644 --- a/.task/feature-rdm-two-trees-followup.md +++ b/.task/feature-rdm-two-trees-followup.md @@ -14,7 +14,7 @@ - 实施执行:agent-per-unit(配置:AGENT-EXECUTION.md) - 合入执行:agent(已授权交付范围内,Review 通过、冲突解决且当前 HEAD 的 CI 通过后合入) - 人工决策点:仅限目标/范围/验收变更、重大取舍、高后果操作或无法自动判定的业务验收 -- 当前阶段:A1 已通过阶段 6(保留在本 initiative 分支);W3 余项子任务待用户阶段 6 人审 +- 当前阶段:A1 已通过阶段 6(保留在本 initiative 分支);W3 余项子任务用户 2026-10-20 阶段 6 通过,RDM #451 已合入 RDM main(76b4c05),子任务合入本分支 - 流程依据:仓库根目录 policy/delivery.md(归档后仍按仓库根目录定位) ## 目标与非目标 @@ -36,7 +36,7 @@ | 子任务分支 | 必需 | 状态 | PR | |---|---|---|---| | A1:W0 守护 + svc 动态端口 + W3 差距核对(本分支内增量) | 是 | 已合入(本分支 000a2d2;用户 2026-10-19 阶段 6 通过) | 本分支 PR #635(草稿,initiative 收口时合入 main) | -| feature/rdm-two-trees-followup-w3-rest | 是 | 实施完成,待用户阶段 6 人审(W3 余项:迁移两次同值、图形不透明块、移动/改名引用、旧批准版回取、重复表格复核;评审包 docs/superpowers/specs/2026-10-19-rdm-two-trees-followup-w3-review.md) | RDM 草稿 PR [#451](https://git-home.u1680832.nyat.app:30319/weichen/Agent-System-RDM/pulls/451);本子任务 PR 见卡 | +| feature/rdm-two-trees-followup-w3-rest | 是 | 已合入(用户 2026-10-20 阶段 6 通过;W3 余项:迁移两次同值、图形不透明块、移动/改名引用、旧批准版回取、重复表格复核;评审包 docs/superpowers/specs/2026-10-19-rdm-two-trees-followup-w3-review.md)。前置条件:W4 开放结构写入口前先补节点种类放置检查;Dev 的 RDM gitlink 改钉在 initiative 收口时统一组合验证 | RDM PR [#451](https://git-home.u1680832.nyat.app:30319/weichen/Agent-System-RDM/pulls/451)(合入 RDM main 76b4c05);本子任务 PR [#641](https://git-home.u1680832.nyat.app:30319/weichen/Agent-System-Dev/pulls/641) | | B:W5/W7 | 是 | 待登记 | — | | C:W8/W10 | 是 | 待登记 | — | | D:W11/W12/W13 | 是 | 待登记(需资源方案) | — | @@ -120,13 +120,13 @@ ## 规划进展与下一步 -- 本次推进/剩余:A1 已验收;剩余 W3 余项、B(W5/W7)、C(W8/W10)、D(W11–W13)、X3 产品链 -- 首选下一任务:W3 余项子任务(迁移两次同值、图形不透明块、移动/改名引用、旧批准版回取、重复表格复核) -- 推荐依据:用户 2026-10-19 阶段 6 结论要求登记 W3 余项为下一增量;B/C 依赖 W3/W4 稳定 -- 前置条件/待确认:从本 initiative 分支当前头建 child;RDM 文件与 IAM link(RDM iam-link-u2)可能重叠,启动前核对 -- 预期产物/验收条件:阶段 5 计划 W3 验证节目标测试(含 TestLegacyDocMigration)通过,旧 ID/replay/批准版保留 -- 重复任务核对:RDM main 5a27d78 已有递归块/模板绑定/旧 Section 身份用例,余项无在途任务 -- 启动授权:已登记为计划内子任务;启动时间由用户确定 +- 本次推进/剩余:A1、W3 余项已验收;剩余 B(W5/W7)、C(W8/W10)、D(W11–W13)、X3 产品链 +- 首选下一任务:B(W5 追溯网 / W7 上下文提供方)子任务登记 +- 推荐依据:W3 余项已于 2026-10-20 通过阶段 6;B/C 依赖 W3/W4 稳定 +- 前置条件/待确认:W4 开放结构写入口前须先补节点种类放置检查(W3 评审非阻塞项 1,用户确认);RDM 文件与 IAM link(RDM iam-link-u2)可能重叠,启动前核对 +- 预期产物/验收条件:按阶段 5 计划 W5/W7 验证节 +- 重复任务核对:启动前核对 +- 启动授权:待用户确定 ## 合入与清理 diff --git a/docs/superpowers/specs/2026-10-19-rdm-two-trees-followup-w3-review.md b/docs/superpowers/specs/2026-10-19-rdm-two-trees-followup-w3-review.md index c45ab288..e744f1ae 100644 --- a/docs/superpowers/specs/2026-10-19-rdm-two-trees-followup-w3-review.md +++ b/docs/superpowers/specs/2026-10-19-rdm-two-trees-followup-w3-review.md @@ -1,6 +1,6 @@ # 两棵树后续 W3 余项:阶段 6 评审包 -- 状态:**待用户阶段 6 人审**。manual 模式:人审通过前不合入 initiative 分支;RDM 改动以草稿 PR [#451](https://git-home.u1680832.nyat.app:30319/weichen/Agent-System-RDM/pulls/451) 形式待审。 +- 状态:**用户阶段 6 通过(2026-10-20)**。确认第 3 节切分:W4 开放结构写入口前必须先补节点种类放置检查。RDM PR [#451](https://git-home.u1680832.nyat.app:30319/weichen/Agent-System-RDM/pulls/451) 经用户授权已合入 RDM main(`76b4c05`);本子任务 PR 合入 initiative 分支。 - 日期:2026-10-19;作者:host;子任务分支:Dev `feature/rdm-two-trees-followup-w3-rest`(父 `feature/rdm-two-trees-followup`)、RDM `feature/rdm-two-trees-followup-w3-rest`(base RDM main `5a27d78`)。 - 依据:[阶段 5 计划 W3](../../../modules/documents/docs/records/2026-10-14-rdm-two-trees-latest-templates/rdm-two-trees-stage5-implementation-test-plan-r1.md)(已批准);[A1 评审包第 2 节差距核对](2026-10-19-rdm-two-trees-followup-a1-review.md)。 -- 2.54.0 From 441d16f7682737f57f5e83bfb71b98b6a3c74eee Mon Sep 17 00:00:00 2001 From: weichen Date: Tue, 20 Oct 2026 03:44:48 +0000 Subject: [PATCH 15/36] Fold-close the task card before merge MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Why: close the task card inside its own PR so landing it needs no post-merge backfill or separate close PR. Evidence: .task/feature-rdm-two-trees-followup-w3-rest.md -> .task/archive/feature-rdm-two-trees-followup-w3-rest.md; status 已完成(合入前闭合); PR #641 https://git-home.u1680832.nyat.app:30319/weichen/Agent-System-Dev/pulls/641. Impact: task metadata only; the card is archived within PR #641 and lands with its merge commit. Refs: task.sh close --self --- .../feature-rdm-two-trees-followup-w3-rest.md | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) rename .task/{ => archive}/feature-rdm-two-trees-followup-w3-rest.md (93%) diff --git a/.task/feature-rdm-two-trees-followup-w3-rest.md b/.task/archive/feature-rdm-two-trees-followup-w3-rest.md similarity index 93% rename from .task/feature-rdm-two-trees-followup-w3-rest.md rename to .task/archive/feature-rdm-two-trees-followup-w3-rest.md index b225e79e..bb915d6f 100644 --- a/.task/feature-rdm-two-trees-followup-w3-rest.md +++ b/.task/archive/feature-rdm-two-trees-followup-w3-rest.md @@ -1,6 +1,6 @@ # feature/rdm-two-trees-followup-w3-rest 任务卡 -任务主记录:PR [#641](https://git-home.u1680832.nyat.app:30319/weichen/Agent-System-Dev/pulls/641);状态:用户阶段 6 通过(2026-10-20),合入父 initiative 分支中;owner:weichen +任务主记录:PR #641 https://git-home.u1680832.nyat.app:30319/weichen/Agent-System-Dev/pulls/641;状态:已完成(合入前闭合);owner:weichen - 权威仓:ssh://git@git-ssh.u1680832.nyat.app:31411/weichen/Agent-System-Dev.git;目标分支:main;R0(initial_base_sha)= 2b7fdc39a1f44163f4766701429d61ffd6926f1a - 工作区:/home/weichen/projects/Agent-System-Dev-wt-feature-rdm-two-trees-followup-w3-rest(worktree);分支:feature/rdm-two-trees-followup-w3-rest @@ -39,7 +39,7 @@ | 时间(UTC) | 命令 | 被测HEAD | exit | 来源 | sha256(16) | |---|---|---|---|---|---| -## 结果与验证(完成后填写) +## 结果与验证 - 结果:W3 余项在 RDM 分支 `feature/rdm-two-trees-followup-w3-rest`(`013b8b1`、`96d53f6`、`f3fa0c0`,草稿 PR [#451](https://git-home.u1680832.nyat.app:30319/weichen/Agent-System-RDM/pulls/451))与本分支 `80ac3fa` 交付;阶段 6 评审包 docs/superpowers/specs/2026-10-19-rdm-two-trees-followup-w3-review.md。 - 验证:RDM 目标测试 20 项与 `./internal/domain/... ./internal/rdmapp` 全量 PASS(SELF,@f3fa0c0);CI(GATE)见下方 CI 记录;Dev `py_compile` PASS(SELF)。 @@ -93,3 +93,9 @@ "receipt_path": "/home/weichen/.cache/agent-system-dev/evidence/abc4088cf722985bd2eeeffeae46cdd899a23e6b1c2711b8849f14f83c8e46bf.json" } ``` + +## 闭合记录(合入前折叠) + +- 本卡在 PR #641(https://git-home.u1680832.nyat.app:30319/weichen/Agent-System-Dev/pulls/641)合入前闭合并归档,随该 PR 一同合入。 +- 该 PR 的合并提交即本任务的落地记录。 +- 合入后无需回填,也无需单独的闭合 PR。 -- 2.54.0 From 8321903cc26907f394b69fa453d345cab675d80b Mon Sep 17 00:00:00 2001 From: weichen Date: Tue, 20 Oct 2026 11:41:24 +0000 Subject: [PATCH 16/36] Record the sync checkpoint Why: bind the task validation checkpoint to the integration baseline. Evidence: SELF recursive component checks; sync_base=7e6c544b3c25c510e3d928bfb4515937a1cd6696; before_record=85624242789c823b96f2adb080e11833f73352e3. Impact: task metadata only. Refs: .task/feature-rdm-two-trees-followup.md --- .task/feature-rdm-two-trees-followup.md | 1 + 1 file changed, 1 insertion(+) diff --git a/.task/feature-rdm-two-trees-followup.md b/.task/feature-rdm-two-trees-followup.md index 207b02fe..b6194867 100644 --- a/.task/feature-rdm-two-trees-followup.md +++ b/.task/feature-rdm-two-trees-followup.md @@ -248,3 +248,4 @@ "receipt_path": "/home/weichen/.cache/agent-system-dev/evidence/0279d9b351beb2e54b662d4bc98b2b492c3898e931bd2a995ddb31c3e70f0fdb.json" } ``` +| 同步(记录前对象) | 7e6c544b3c25c510e3d928bfb4515937a1cd6696 | 85624242789c823b96f2adb080e11833f73352e3 | 2026-10-20T11:41:24Z | -- 2.54.0 From 13b9c9daddfb78717438777e955dd296ca56439d Mon Sep 17 00:00:00 2001 From: weichen Date: Tue, 20 Oct 2026 14:45:31 +0000 Subject: [PATCH 17/36] Register the W5-W7 increment B child task card Why: The user authorized starting increment B (W5-W7) of the two-trees follow-up initiative; the charter requires each increment to be registered as a child task with scope, authorization and stage-6 endpoint before implementation. Evidence: Card records R0 82b581d (parent initiative HEAD, synced and green), RDM base ed3a0f9, sequence W5-W6-W7, and the no-merge stage-6 endpoint. Impact: Task card only; no source changes. Refs: parent card .task/feature-rdm-two-trees-followup.md --- .task/feature-rdm-two-trees-followup-w5-w7.md | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 .task/feature-rdm-two-trees-followup-w5-w7.md diff --git a/.task/feature-rdm-two-trees-followup-w5-w7.md b/.task/feature-rdm-two-trees-followup-w5-w7.md new file mode 100644 index 00000000..c1484816 --- /dev/null +++ b/.task/feature-rdm-two-trees-followup-w5-w7.md @@ -0,0 +1,42 @@ +# feature/rdm-two-trees-followup-w5-w7 任务卡 + +任务主记录:PR 链接(子任务 PR 建立后回填,本文件随 PR 描述维护);状态:进行中;owner:weichen。 + +## 基线与授权 + +- 权威仓:ssh://git@git-ssh.u1680832.nyat.app:31411/weichen/Agent-System-Dev.git;root_target:main;immediate_target:feature/rdm-two-trees-followup(父 initiative) +- R0(initial_main_sha):82b581d90a2fea557edf4f37e6cf968920fe6c8c(父 initiative 分支 HEAD @登记时) +- 工作区:/home/weichen/projects/Agent-System-Dev-wt-feature-rdm-two-trees-followup-w5-w7(worktree,登记后创建);分支:feature/rdm-two-trees-followup-w5-w7 +- RDM 侧:仓 Agent-System-RDM,分支 feature/rdm-two-trees-followup-w5-w7,base = origin/main ed3a0f9(登记时) +- 分支类型:child;initiative_id:feature-rdm-two-trees-followup;accepting_requirements:false +- 父任务信息:parent_branch=feature/rdm-two-trees-followup;parent_head_sha=82b581d90a2fea557edf4f37e6cf968920fe6c8c;parent_pr=#635 +- 需求分流:verdict=JOIN;selected_initiative=feature/rdm-two-trees-followup;依据=章程增量 B(W5–W7) +- 授权与交付终点:用户 2026-10-20「授权,并且开始解决非阻塞项」授权启动增量 B。终点为 W5/W6/W7 推进到阶段 6 评审包(独立 Review 通过 + 证据齐备),**不含任何合入**:用户阶段 6 人审通过前不合入父分支、不合入 RDM main。未授权:运行库迁移、部署、真实模型与付费请求、Backend 发版/tag(X1 发布由用户另行双钥匙)。 + +## 目标与非目标 + +- 目标(阶段 5 计划 §4,设计 r1 §6–§7): + - **W5 追溯网**:一般来源网与受控合规网分存;UN/SR/DI/风险/软件需求/设计/测试用例/执行结果/报告业务身份与块锚定;候选/确认边语义;受控边锁定两端精确 revision;端点升版「待复核」;影响分析(直接/传递/缺口/水位、去环、截断续查、当时快照与按当前重算分离)。 + - **W6 基座公开 X1**:Backend 可选 ProjectContextRegistry + 受信 CompleteForWork 入口 + ContextManifest;Dev 扩展申请与公开面;发布 tag 前 RDM 不得以本地 replace 消费。 + - **W7 RDM 上下文提供方**:project_context 摘要与渐进 ReadEvidence;撤权/切换失效;同一受信生成入口防双次注入。W6 tag 未发布时只做纯领域摘要与测试,不宣布自动注入完成。 +- 非目标:W8–W13;UI;迁移与部署;把候选检索冒充模型已见。 +- 序列:W5(RDM 领域→应用)→ W6(Backend+Dev 公开面)→ W7(RDM 消费,按 tag 状态分期收口)。 + +## Agent 实施收据 + +路由与 fail-stop 规则见根目录 AGENT-EXECUTION.md 与 policy/delivery.md;每次尝试一行,原始日志留在源码外收据路径。 + +| 单元 ID | 预期范围 | 角色 | 候选顺序 | attempt | CLI/模型 | 终态 | transport | fallback | 源码外收据路径 | +|---|---|---|---|---|---|---|---|---|---| +| 待定义 | — | NOT_RUN | NOT_RUN | NOT_RUN | NOT_RUN | NOT_RUN | NOT_RUN | NOT_RUN | — | + +## 复用材料 + +- W3 余项收口记录:`.task/archive/feature-rdm-two-trees-followup-w3-rest.md`(含 W4 前置条件:开放结构写入口前先补节点种类放置检查)。 +- 阶段 5 计划 §4(W5–W7 文件与出口)、阶段 4 设计 §6–§7(追溯网与 X1 合同)、`stage6-w6-source-recheck-design-adjustment-r1.md`。 + +## 同步记录 + +| 节点 | sync_base_sha | tested_head_sha | checked_at | 结果 | +|---|---|---|---|---| +| 启动 | 82b581d90a2fea557edf4f37e6cf968920fe6c8c | 82b581d90a2fea557edf4f37e6cf968920fe6c8c | 2026-10-20T14:45:31Z | 一致(父分支已同步 main,CI 绿) | -- 2.54.0 From 0e395e5e3893d1c8996e45340cdd2e89ee5362b3 Mon Sep 17 00:00:00 2001 From: weichen Date: Tue, 20 Oct 2026 14:48:01 +0000 Subject: [PATCH 18/36] Record the task card for feature-rdm-two-trees-followup-w5-w7 Why: establish the authorized task workspace and its initial baseline. Evidence: preserved precheck receipt in .task/feature-rdm-two-trees-followup-w5-w7.md; R0=ed3847c85ce111a74f0cb100908abfb40f62db07. Impact: task metadata only; the feature workspace starts at 13b9c9daddfb78717438777e955dd296ca56439d. Refs: .task/feature-rdm-two-trees-followup-w5-w7.md --- .task/feature-rdm-two-trees-followup-w5-w7.md | 104 +++++++++++++----- 1 file changed, 77 insertions(+), 27 deletions(-) diff --git a/.task/feature-rdm-two-trees-followup-w5-w7.md b/.task/feature-rdm-two-trees-followup-w5-w7.md index c1484816..2b18bced 100644 --- a/.task/feature-rdm-two-trees-followup-w5-w7.md +++ b/.task/feature-rdm-two-trees-followup-w5-w7.md @@ -1,42 +1,92 @@ # feature/rdm-two-trees-followup-w5-w7 任务卡 -任务主记录:PR 链接(子任务 PR 建立后回填,本文件随 PR 描述维护);状态:进行中;owner:weichen。 +任务主记录:;状态:进行中;owner:weichen -## 基线与授权 +- 权威仓:ssh://git@git-ssh.u1680832.nyat.app:31411/weichen/Agent-System-Dev.git;目标分支:main;R0(initial_base_sha)= ed3847c85ce111a74f0cb100908abfb40f62db07 +- 工作区:/home/weichen/projects/Agent-System-Dev-wt-feature-rdm-two-trees-followup-w5-w7(worktree);分支:feature/rdm-two-trees-followup-w5-w7 +- 分支类型:child;initiative_id:feature-rdm-two-trees-followup;root_target:main;immediate_target:feature/rdm-two-trees-followup;accepting_requirements:false;parent_branch:feature/rdm-two-trees-followup;parent_head_sha:13b9c9daddfb78717438777e955dd296ca56439d;parent_pr:无;parent_source:origin +- 需求分流:verdict=JOIN;selected_initiative=feature/rdm-two-trees-followup;requirement_sha256=343b26bddcfc64e013a068fc4f294a28f94c28702c08bafa0f6d92262289e90b;triage_receipt=/tmp/triage-w5w7.json;receipt_sha256=c3948ecfa318defbdd96b5d465665abef97abfcc90472a0a1d216af4dc9ae0dc -- 权威仓:ssh://git@git-ssh.u1680832.nyat.app:31411/weichen/Agent-System-Dev.git;root_target:main;immediate_target:feature/rdm-two-trees-followup(父 initiative) -- R0(initial_main_sha):82b581d90a2fea557edf4f37e6cf968920fe6c8c(父 initiative 分支 HEAD @登记时) -- 工作区:/home/weichen/projects/Agent-System-Dev-wt-feature-rdm-two-trees-followup-w5-w7(worktree,登记后创建);分支:feature/rdm-two-trees-followup-w5-w7 -- RDM 侧:仓 Agent-System-RDM,分支 feature/rdm-two-trees-followup-w5-w7,base = origin/main ed3a0f9(登记时) -- 分支类型:child;initiative_id:feature-rdm-two-trees-followup;accepting_requirements:false -- 父任务信息:parent_branch=feature/rdm-two-trees-followup;parent_head_sha=82b581d90a2fea557edf4f37e6cf968920fe6c8c;parent_pr=#635 -- 需求分流:verdict=JOIN;selected_initiative=feature/rdm-two-trees-followup;依据=章程增量 B(W5–W7) -- 授权与交付终点:用户 2026-10-20「授权,并且开始解决非阻塞项」授权启动增量 B。终点为 W5/W6/W7 推进到阶段 6 评审包(独立 Review 通过 + 证据齐备),**不含任何合入**:用户阶段 6 人审通过前不合入父分支、不合入 RDM main。未授权:运行库迁移、部署、真实模型与付费请求、Backend 发版/tag(X1 发布由用户另行双钥匙)。 +- 授权与交付终点:<本次允许的动作与终点;未授权事项写明> +- 交付模式:goal-first(目标、范围和交付终点一次确认;范围内连续推进) +- 实施执行:agent-per-unit(配置:AGENT-EXECUTION.md) +- 合入执行:agent(已授权交付范围内,Review 通过、冲突解决且当前 HEAD 的 CI 通过后合入) +- 流程依据:仓库根目录 policy/delivery.md(归档后仍按仓库根目录定位) ## 目标与非目标 -- 目标(阶段 5 计划 §4,设计 r1 §6–§7): - - **W5 追溯网**:一般来源网与受控合规网分存;UN/SR/DI/风险/软件需求/设计/测试用例/执行结果/报告业务身份与块锚定;候选/确认边语义;受控边锁定两端精确 revision;端点升版「待复核」;影响分析(直接/传递/缺口/水位、去环、截断续查、当时快照与按当前重算分离)。 - - **W6 基座公开 X1**:Backend 可选 ProjectContextRegistry + 受信 CompleteForWork 入口 + ContextManifest;Dev 扩展申请与公开面;发布 tag 前 RDM 不得以本地 replace 消费。 - - **W7 RDM 上下文提供方**:project_context 摘要与渐进 ReadEvidence;撤权/切换失效;同一受信生成入口防双次注入。W6 tag 未发布时只做纯领域摘要与测试,不宣布自动注入完成。 -- 非目标:W8–W13;UI;迁移与部署;把候选检索冒充模型已见。 -- 序列:W5(RDM 领域→应用)→ W6(Backend+Dev 公开面)→ W7(RDM 消费,按 tag 状态分期收口)。 +<预期结果、受影响入口/模块/契约;明确不做什么。> ## Agent 实施收据 路由与 fail-stop 规则见根目录 AGENT-EXECUTION.md 与 policy/delivery.md;每次尝试一行,原始日志留在源码外收据路径。 -| 单元 ID | 预期范围 | 角色 | 候选顺序 | attempt | CLI/模型 | 终态 | transport | fallback | 源码外收据路径 | -|---|---|---|---|---|---|---|---|---|---| -| 待定义 | — | NOT_RUN | NOT_RUN | NOT_RUN | NOT_RUN | NOT_RUN | NOT_RUN | NOT_RUN | — | - -## 复用材料 - -- W3 余项收口记录:`.task/archive/feature-rdm-two-trees-followup-w3-rest.md`(含 W4 前置条件:开放结构写入口前先补节点种类放置检查)。 -- 阶段 5 计划 §4(W5–W7 文件与出口)、阶段 4 设计 §6–§7(追溯网与 X1 合同)、`stage6-w6-source-recheck-design-adjustment-r1.md`。 +| 单元 ID | 预期范围 | 配置摘要 | 角色 | 候选顺序 | attempt | CLI/模型 | 终态 | transport | fallback | 源码外收据路径 | +|---|---|---|---|---|---|---|---|---|---|---| +| 待定义 | — | NOT_RUN | NOT_RUN | NOT_RUN | NOT_RUN | NOT_RUN | NOT_RUN | NOT_RUN | NOT_RUN | — | ## 同步记录 -| 节点 | sync_base_sha | tested_head_sha | checked_at | 结果 | -|---|---|---|---|---| -| 启动 | 82b581d90a2fea557edf4f37e6cf968920fe6c8c | 82b581d90a2fea557edf4f37e6cf968920fe6c8c | 2026-10-20T14:45:31Z | 一致(父分支已同步 main,CI 绿) | +| 节点 | sync_base_sha | tested_head_sha | checked_at | +|---|---|---|---| +| 启动 | ed3847c85ce111a74f0cb100908abfb40f62db07 | 13b9c9daddfb78717438777e955dd296ca56439d | 2026-10-20T14:48:00Z | + +## 证据(Evidence) + + +| 时间(UTC) | 命令 | 被测HEAD | exit | 来源 | sha256(16) | +|---|---|---|---|---|---| + +## 结果与验证(完成后填写) + +- 结果: +- 验证:<结论摘要 PASS/FAIL/SKIP/NOT_RUN 逐项;逐条证据由 make evidence 写入上方证据表> +- 影响与剩余项: + +## 合入与清理 + +- Review 记录:NOT_RUN(审阅智能体/平台身份、base/head、结论、问题闭合及重放依据) +- 冲突记录:NOT_RUN(最新目标同步、冲突处置、组合兼容核验及复审/补测) +- CI 记录:NOT_RUN(当前 HEAD 完整 SHA、全部必需检查、运行链接、执行身份及 GATE 结果) +- 合入记录:NOT_RUN(交付授权范围、PR、被核验 HEAD、合入 SHA、目标分支及内容核验) +- 清理记录:NOT_RUN(授权依据、写者退出确认、worktree/分支/任务卡处置) + + +```json +{ + "summary_schema": 1, + "source": "SELF", + "timestamp": "2026-10-20T14:46:07.178211+00:00", + "command": "make precheck", + "exit_code": 0, + "cwd": "/home/weichen/projects/Agent-System-Dev", + "before_head": "ed3847c85ce111a74f0cb100908abfb40f62db07", + "after_head": "ed3847c85ce111a74f0cb100908abfb40f62db07", + "branch": "main", + "target_branch": "main", + "target_head": "ed3847c85ce111a74f0cb100908abfb40f62db07", + "root_target": "main", + "immediate_target": "main", + "before_tracked_diff_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "after_tracked_diff_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "output_tail": [ + "make[1]: Entering directory '/home/weichen/projects/Agent-System-Dev'", + "[repo] branch=main head=ed3847c85c", + "[remote] origin/main=ed3847c85c ahead=0 behind=0", + "[tree] clean submodules_drift=0 uninit=0", + "[worktrees] linked=5", + "[recycle] merged un-recycled branches: feature/fast-slow-o2-a01-checkpoint-design", + "[initiatives] local cards (not authoritative): none", + "[hooks] core.hooksPath=scripts/hooks(pre-commit/post-merge 实际接线)", + "[facts] policy/facts.md 6 条事实均在有效期内", + "[required-reading] core/baseline.md, workflows/delivery.md §1, policy/delivery.md", + "[R0] ed3847c85c(完整:ed3847c85ce111a74f0cb100908abfb40f62db07)", + "[worktree] before-sync: recursive component checks passed", + "[verdict] READY — 保留本次 precheck receipt 后建任务工作区:PRECHECK_RECEIPT=/tmp/task-precheck.json make task-start NAME=feature/your-branch", + "make[1]: Leaving directory '/home/weichen/projects/Agent-System-Dev'" + ], + "output_sha256": "f03caadb3c0597418604c953038e5658758c9546150ca3d711e853ebc0c24a8c", + "receipt_sha256": "657414206727892ce0ed5ce0ee067e220e11e9da50b3b1fae1bd9db4bc530a6e", + "receipt_path": "/home/weichen/.cache/agent-system-dev/evidence/657414206727892ce0ed5ce0ee067e220e11e9da50b3b1fae1bd9db4bc530a6e.json" +} +``` -- 2.54.0 From 4681e8d871e14cff6c92927f43cb04aa2b2e5bbd Mon Sep 17 00:00:00 2001 From: weichen Date: Tue, 20 Oct 2026 15:04:59 +0000 Subject: [PATCH 19/36] Record the W5a domain core unit in the increment B card Why: agent-per-unit governance requires each implementation attempt to be recorded with its transport and receipt. Evidence: w5a-tracenet-domain-core completed via cursor attempt 1; transport a7a6df0 on the RDM child branch; SELF gofmt/vet and domain+rdmapp tests all ok. Impact: Task card only. Refs: RDM branch feature/rdm-two-trees-followup-w5-w7 --- .task/feature-rdm-two-trees-followup-w5-w7.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.task/feature-rdm-two-trees-followup-w5-w7.md b/.task/feature-rdm-two-trees-followup-w5-w7.md index 2b18bced..44ea4066 100644 --- a/.task/feature-rdm-two-trees-followup-w5-w7.md +++ b/.task/feature-rdm-two-trees-followup-w5-w7.md @@ -23,6 +23,7 @@ | 单元 ID | 预期范围 | 配置摘要 | 角色 | 候选顺序 | attempt | CLI/模型 | 终态 | transport | fallback | 源码外收据路径 | |---|---|---|---|---|---|---|---|---|---|---| +| w5a-tracenet-domain-core | internal/domain 追溯网领域核心(revision锁定/候选确认/升版待复核/传递影响+水位/快照/重放) | implementation | cursor | 1 | cursor(auto) | completed | a7a6df0(refs/agent-exec/2533912c/0c0654db) | never | /home/weichen/.cache/agent-system-dev/agent-exec-receipts/w5a-tracenet-domain-core.json | | 待定义 | — | NOT_RUN | NOT_RUN | NOT_RUN | NOT_RUN | NOT_RUN | NOT_RUN | NOT_RUN | NOT_RUN | — | ## 同步记录 @@ -30,6 +31,7 @@ | 节点 | sync_base_sha | tested_head_sha | checked_at | |---|---|---|---| | 启动 | ed3847c85ce111a74f0cb100908abfb40f62db07 | 13b9c9daddfb78717438777e955dd296ca56439d | 2026-10-20T14:48:00Z | +| W5a 后(RDM 侧) | ed3a0f9(RDM main) | a7a6df0(RDM 子分支) | 2026-10-20 | SELF:gofmt/vet ok,domain+rdmapp 全部 ok(81.9s) | ## 证据(Evidence) -- 2.54.0 From bb476a8da6f89a1e437d0c7d7fc3df7712bd5452 Mon Sep 17 00:00:00 2001 From: weichen Date: Tue, 20 Oct 2026 15:26:39 +0000 Subject: [PATCH 20/36] Record the W5b impact endpoints unit in the increment B card Why: record the second W5 implementation attempt per agent-per-unit governance. Evidence: w5b-trace-impact-endpoints completed via cursor attempt 1; transport 2e5fcb7 on the RDM child branch; SELF vet ok and rdmapp+plugins/rdm tests all ok. Impact: Task card only. Refs: RDM branch feature/rdm-two-trees-followup-w5-w7 --- .task/feature-rdm-two-trees-followup-w5-w7.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.task/feature-rdm-two-trees-followup-w5-w7.md b/.task/feature-rdm-two-trees-followup-w5-w7.md index 44ea4066..d3610283 100644 --- a/.task/feature-rdm-two-trees-followup-w5-w7.md +++ b/.task/feature-rdm-two-trees-followup-w5-w7.md @@ -24,6 +24,7 @@ | 单元 ID | 预期范围 | 配置摘要 | 角色 | 候选顺序 | attempt | CLI/模型 | 终态 | transport | fallback | 源码外收据路径 | |---|---|---|---|---|---|---|---|---|---|---| | w5a-tracenet-domain-core | internal/domain 追溯网领域核心(revision锁定/候选确认/升版待复核/传递影响+水位/快照/重放) | implementation | cursor | 1 | cursor(auto) | completed | a7a6df0(refs/agent-exec/2533912c/0c0654db) | never | /home/weichen/.cache/agent-system-dev/agent-exec-receipts/w5a-tracenet-domain-core.json | +| w5b-trace-impact-endpoints | rdmapp 影响分析/重算/快照读取/覆盖缺项/pending-recheck 命令面(impact.go + plugin 注册) | implementation | cursor | 1 | cursor(auto) | completed | 2e5fcb7(refs/agent-exec/d98a00bc/23b5e5d0) | never | /home/weichen/.cache/agent-system-dev/agent-exec-receipts/w5b-trace-impact-endpoints.json | | 待定义 | — | NOT_RUN | NOT_RUN | NOT_RUN | NOT_RUN | NOT_RUN | NOT_RUN | NOT_RUN | NOT_RUN | — | ## 同步记录 @@ -32,6 +33,7 @@ |---|---|---|---| | 启动 | ed3847c85ce111a74f0cb100908abfb40f62db07 | 13b9c9daddfb78717438777e955dd296ca56439d | 2026-10-20T14:48:00Z | | W5a 后(RDM 侧) | ed3a0f9(RDM main) | a7a6df0(RDM 子分支) | 2026-10-20 | SELF:gofmt/vet ok,domain+rdmapp 全部 ok(81.9s) | +| W5b 后(RDM 侧) | a7a6df0 | 2e5fcb7 | 2026-10-20 | SELF:vet ok;rdmapp(81.2s)+plugins/rdm(3.3s) 全部 ok;gofmt 仅既有 iam_integration_test.go 告警(未触碰) | ## 证据(Evidence) -- 2.54.0 From 85f6f28d96b70f3ce1a7559faae9866daa00df9b Mon Sep 17 00:00:00 2001 From: weichen Date: Tue, 20 Oct 2026 15:44:48 +0000 Subject: [PATCH 21/36] Record the W7a domain unit and the W6 approval gate Why: W7a (pure domain bundle builder) is delivered within the plan's no-tag constraint; W6 stays paused pending the pending-review design revision the stage-6 doc requires the user to approve. Evidence: w7a-project-context-domain completed via cursor attempt 1; transport 8327603; SELF vet ok, rdmapp tests ok, zero pkg/extension imports. Impact: Task card only. Refs: rdm-two-trees-stage6-w6-source-recheck-design-adjustment-r1.md --- .task/feature-rdm-two-trees-followup-w5-w7.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.task/feature-rdm-two-trees-followup-w5-w7.md b/.task/feature-rdm-two-trees-followup-w5-w7.md index d3610283..a358ab96 100644 --- a/.task/feature-rdm-two-trees-followup-w5-w7.md +++ b/.task/feature-rdm-two-trees-followup-w5-w7.md @@ -25,6 +25,7 @@ |---|---|---|---|---|---|---|---|---|---|---| | w5a-tracenet-domain-core | internal/domain 追溯网领域核心(revision锁定/候选确认/升版待复核/传递影响+水位/快照/重放) | implementation | cursor | 1 | cursor(auto) | completed | a7a6df0(refs/agent-exec/2533912c/0c0654db) | never | /home/weichen/.cache/agent-system-dev/agent-exec-receipts/w5a-tracenet-domain-core.json | | w5b-trace-impact-endpoints | rdmapp 影响分析/重算/快照读取/覆盖缺项/pending-recheck 命令面(impact.go + plugin 注册) | implementation | cursor | 1 | cursor(auto) | completed | 2e5fcb7(refs/agent-exec/d98a00bc/23b5e5d0) | never | /home/weichen/.cache/agent-system-dev/agent-exec-receipts/w5b-trace-impact-endpoints.json | +| w7a-project-context-domain | W7 纯领域部分:ProjectContextBundle 组装/失效语义/渐进证据引用(零基座消费,tag 前约束达成) | implementation | cursor | 1 | cursor(auto) | completed | 8327603(refs/agent-exec/a3eba579/153246be) | never | /home/weichen/.cache/agent-system-dev/agent-exec-receipts/w7a-project-context-domain.json | | 待定义 | — | NOT_RUN | NOT_RUN | NOT_RUN | NOT_RUN | NOT_RUN | NOT_RUN | NOT_RUN | NOT_RUN | — | ## 同步记录 @@ -34,6 +35,7 @@ | 启动 | ed3847c85ce111a74f0cb100908abfb40f62db07 | 13b9c9daddfb78717438777e955dd296ca56439d | 2026-10-20T14:48:00Z | | W5a 后(RDM 侧) | ed3a0f9(RDM main) | a7a6df0(RDM 子分支) | 2026-10-20 | SELF:gofmt/vet ok,domain+rdmapp 全部 ok(81.9s) | | W5b 后(RDM 侧) | a7a6df0 | 2e5fcb7 | 2026-10-20 | SELF:vet ok;rdmapp(81.2s)+plugins/rdm(3.3s) 全部 ok;gofmt 仅既有 iam_integration_test.go 告警(未触碰) | +| W7a 后(RDM 侧) | 2e5fcb7 | 8327603 | 2026-10-20 | SELF:vet ok;rdmapp 全部 ok(91.5s);grep 证实零 pkg/extension 消费 | ## 证据(Evidence) @@ -94,3 +96,7 @@ "receipt_path": "/home/weichen/.cache/agent-system-dev/evidence/657414206727892ce0ed5ce0ee067e220e11e9da50b3b1fae1bd9db4bc530a6e.json" } ``` + +## W6 门禁记录(2026-10-20) + +W6 按设计修订文档 `rdm-two-trees-stage6-w6-source-recheck-design-adjustment-r1.md`(状态:**待人工评审**)暂停实现:候选分支 HEAD 6ba53e4(未推送)已有部分实现但含隐私敏感的存储/迁移取舍,须经用户批准该修订后方可继续。本单元按计划 W7 但书仅交付「纯领域摘要与测试」,未消费基座接口,不宣布自动注入完成。 -- 2.54.0 From b6a7be005936022fadff9e1e0dd387e507cf3bf9 Mon Sep 17 00:00:00 2001 From: weichen Date: Tue, 20 Oct 2026 16:01:11 +0000 Subject: [PATCH 22/36] Record the W6 resumption after the approved revision Why: the user approved the source-recheck r1 revision; the isolated W6 branch was merged with current main and the completion unit audited and closed the remaining revision gaps. Evidence: w6-x1-recheck-completion completed via cursor attempt 1; transport 8c410b9 on backend feature/w6-x1-source-recheck; SELF build/vet and store/runmgr/workflow/extension tests all ok. Impact: Task card only. Refs: rdm-two-trees-stage6-w6-source-recheck-design-adjustment-r1.md; backend candidate 6ba53e4 --- .task/feature-rdm-two-trees-followup-w5-w7.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.task/feature-rdm-two-trees-followup-w5-w7.md b/.task/feature-rdm-two-trees-followup-w5-w7.md index a358ab96..1227c98b 100644 --- a/.task/feature-rdm-two-trees-followup-w5-w7.md +++ b/.task/feature-rdm-two-trees-followup-w5-w7.md @@ -26,6 +26,7 @@ | w5a-tracenet-domain-core | internal/domain 追溯网领域核心(revision锁定/候选确认/升版待复核/传递影响+水位/快照/重放) | implementation | cursor | 1 | cursor(auto) | completed | a7a6df0(refs/agent-exec/2533912c/0c0654db) | never | /home/weichen/.cache/agent-system-dev/agent-exec-receipts/w5a-tracenet-domain-core.json | | w5b-trace-impact-endpoints | rdmapp 影响分析/重算/快照读取/覆盖缺项/pending-recheck 命令面(impact.go + plugin 注册) | implementation | cursor | 1 | cursor(auto) | completed | 2e5fcb7(refs/agent-exec/d98a00bc/23b5e5d0) | never | /home/weichen/.cache/agent-system-dev/agent-exec-receipts/w5b-trace-impact-endpoints.json | | w7a-project-context-domain | W7 纯领域部分:ProjectContextBundle 组装/失效语义/渐进证据引用(零基座消费,tag 前约束达成) | implementation | cursor | 1 | cursor(auto) | completed | 8327603(refs/agent-exec/a3eba579/153246be) | never | /home/weichen/.cache/agent-system-dev/agent-exec-receipts/w7a-project-context-domain.json | +| w6-x1-recheck-completion | W6 恢复:用户批准修订后,对照清单审计并补齐——消费点全覆盖/入模门禁/存储边界/负例矩阵(Backend 隔离分支,含候选合并 main b4399e3) | implementation | cursor | 1 | cursor(auto) | completed | 8c410b9(refs/agent-exec/412eff9b/0636a7e1) | never | /home/weichen/.cache/agent-system-dev/agent-exec-receipts/w6-x1-recheck-completion.json | | 待定义 | — | NOT_RUN | NOT_RUN | NOT_RUN | NOT_RUN | NOT_RUN | NOT_RUN | NOT_RUN | NOT_RUN | — | ## 同步记录 @@ -97,6 +98,10 @@ } ``` +## W6 恢复记录(2026-10-20) + +用户批准修订(「按已实际纳入来源逐项重新授权」X1 合同 + 去原文迁移边界)。恢复动作:候选 6ba53e4 建分支 feature/w6-x1-source-recheck,合并最新 main(自动合并无冲突,b4399e3),既有多数项已在候选实现(含此前 RED 的无正文测试已绿);派发 w6-x1-recheck-completion 单元补齐消费点/门禁/负例(7 文件,transport 8c410b9),SELF 全绿(build/vet/store/runmgr/workflow/extension)。X1 公开 tag 发布仍为用户双钥匙。 + ## W6 门禁记录(2026-10-20) W6 按设计修订文档 `rdm-two-trees-stage6-w6-source-recheck-design-adjustment-r1.md`(状态:**待人工评审**)暂停实现:候选分支 HEAD 6ba53e4(未推送)已有部分实现但含隐私敏感的存储/迁移取舍,须经用户批准该修订后方可继续。本单元按计划 W7 但书仅交付「纯领域摘要与测试」,未消费基座接口,不宣布自动注入完成。 -- 2.54.0 From 9ba2514ef838de62cb9ee345e156425b914b18d6 Mon Sep 17 00:00:00 2001 From: weichen Date: Tue, 20 Oct 2026 16:58:01 +0000 Subject: [PATCH 23/36] Add the increment B stage-6 review package Why: W5/W6/W7a are independently reviewed (RDM 0 blocking after repair, backend 7/7 pass) and the increment has reached the user stage-6 gate; the package consolidates evidence, transports and known limits. Evidence: review reports committed on the RDM and backend branches; repair unit transport 04991ed; backend PR #231 CI green at 8c410b9. Impact: Task card and review package docs only. Refs: parent initiative feature/rdm-two-trees-followup (PR #635) --- .task/feature-rdm-two-trees-followup-w5-w7.md | 9 ++++- ...-20-rdm-two-trees-followup-w5-w7-review.md | 33 +++++++++++++++++++ 2 files changed, 41 insertions(+), 1 deletion(-) create mode 100644 docs/superpowers/specs/2026-10-20-rdm-two-trees-followup-w5-w7-review.md diff --git a/.task/feature-rdm-two-trees-followup-w5-w7.md b/.task/feature-rdm-two-trees-followup-w5-w7.md index 1227c98b..52d5ef15 100644 --- a/.task/feature-rdm-two-trees-followup-w5-w7.md +++ b/.task/feature-rdm-two-trees-followup-w5-w7.md @@ -1,6 +1,6 @@ # feature/rdm-two-trees-followup-w5-w7 任务卡 -任务主记录:;状态:进行中;owner:weichen +任务主记录:;状态:独立 Review 通过,待用户阶段 6 人审;owner:weichen - 权威仓:ssh://git@git-ssh.u1680832.nyat.app:31411/weichen/Agent-System-Dev.git;目标分支:main;R0(initial_base_sha)= ed3847c85ce111a74f0cb100908abfb40f62db07 - 工作区:/home/weichen/projects/Agent-System-Dev-wt-feature-rdm-two-trees-followup-w5-w7(worktree);分支:feature/rdm-two-trees-followup-w5-w7 @@ -27,6 +27,9 @@ | w5b-trace-impact-endpoints | rdmapp 影响分析/重算/快照读取/覆盖缺项/pending-recheck 命令面(impact.go + plugin 注册) | implementation | cursor | 1 | cursor(auto) | completed | 2e5fcb7(refs/agent-exec/d98a00bc/23b5e5d0) | never | /home/weichen/.cache/agent-system-dev/agent-exec-receipts/w5b-trace-impact-endpoints.json | | w7a-project-context-domain | W7 纯领域部分:ProjectContextBundle 组装/失效语义/渐进证据引用(零基座消费,tag 前约束达成) | implementation | cursor | 1 | cursor(auto) | completed | 8327603(refs/agent-exec/a3eba579/153246be) | never | /home/weichen/.cache/agent-system-dev/agent-exec-receipts/w7a-project-context-domain.json | | w6-x1-recheck-completion | W6 恢复:用户批准修订后,对照清单审计并补齐——消费点全覆盖/入模门禁/存储边界/负例矩阵(Backend 隔离分支,含候选合并 main b4399e3) | implementation | cursor | 1 | cursor(auto) | completed | 8c410b9(refs/agent-exec/412eff9b/0636a7e1) | never | /home/weichen/.cache/agent-system-dev/agent-exec-receipts/w6-x1-recheck-completion.json | +| rev-increment-b-rdm | RDM 增量独立评审(0 BLOCKING/6 MAJOR/14 MINOR) | review | pi | 1 | pi(default) | completed | 56b23a0 | never | ~/.cache/agent-system-dev/agent-exec-receipts/rev-rdm-receipt.json | +| w5-majors-repair | 评审 MAJOR M1–M6 修复(copyState/快照ID/端点校验/生产写入/空分析/别名) | repair | cursor | 1 | cursor(auto) | completed | 04991ed | never | ~/.cache/agent-system-dev/agent-exec-receipts/w5-fix-receipt.json | +| rev-w6-x1-recheck | Backend W6 独立评审(7/7 PASS,0 BLOCKING 0 MAJOR/6 MINOR) | review | pi | 1 | pi(default) | completed | 65122b8 | never | ~/.cache/agent-system-dev/agent-exec-receipts/rev-be-receipt.json | | 待定义 | — | NOT_RUN | NOT_RUN | NOT_RUN | NOT_RUN | NOT_RUN | NOT_RUN | NOT_RUN | NOT_RUN | — | ## 同步记录 @@ -98,6 +101,10 @@ } ``` +## 阶段 6 评审包(2026-10-20) + +评审包:`docs/superpowers/specs/2026-10-20-rdm-two-trees-followup-w5-w7-review.md`。独立 Review 全部完成(RDM 0 BLOCKING、6 MAJOR 已修复;Backend 7/7 PASS、0 BLOCKING 0 MAJOR),增量 B 达到用户人审就绪点。 + ## W6 恢复记录(2026-10-20) 用户批准修订(「按已实际纳入来源逐项重新授权」X1 合同 + 去原文迁移边界)。恢复动作:候选 6ba53e4 建分支 feature/w6-x1-source-recheck,合并最新 main(自动合并无冲突,b4399e3),既有多数项已在候选实现(含此前 RED 的无正文测试已绿);派发 w6-x1-recheck-completion 单元补齐消费点/门禁/负例(7 文件,transport 8c410b9),SELF 全绿(build/vet/store/runmgr/workflow/extension)。X1 公开 tag 发布仍为用户双钥匙。 diff --git a/docs/superpowers/specs/2026-10-20-rdm-two-trees-followup-w5-w7-review.md b/docs/superpowers/specs/2026-10-20-rdm-two-trees-followup-w5-w7-review.md new file mode 100644 index 00000000..21ae4d5e --- /dev/null +++ b/docs/superpowers/specs/2026-10-20-rdm-two-trees-followup-w5-w7-review.md @@ -0,0 +1,33 @@ +# 两树一网增量 B(W5/W6/W7a)阶段 6 评审包 r1 + +日期:2026-10-20。状态:独立 Review 通过,**待用户阶段 6 人审**。人审通过前不合入任何分支。 + +## 1. 范围与结论一览 + +| 工作项 | 内容 | 交付分支/HEAD | 独立评审 | 修复 | +|---|---|---|---|---| +| W5a 领域核 | 受控边 revision 锁定、候选/确认语义、升版 pending-recheck、AnalyzeImpact/RecomputeImpact 传递闭包(去环/截断/水位/不可变快照)、重放一致 | RDM `feature/rdm-two-trees-followup-w5-w7` @ a7a6df0 | 0 BLOCKING | — | +| W5b 命令面 | rdm.compliance.impact.analyze/get/recompute、rdm.trace.coverage、rdm.trace.pending-recheck | 同上 @ 2e5fcb7 | 0 BLOCKING | — | +| W7a 纯领域 | ProjectContextBundle 组装/失效/渐进证据引用;零基座消费(tag 前约束达成) | 同上 @ 8327603 | 0 BLOCKING | — | +| RDM 评审修复 | 评审 MAJOR M1–M6(copyState/快照 ID 碰撞/端点校验/生产写入路径/空分析/切片别名) | 同上 @ 04991edb | 修复后 domain+rdmapp+plugins 全绿 | ✅ | +| W6 X1 恢复 | 候选 6ba53e4 合并 main 后按批准修订审计补齐(消费点全覆盖/入模门禁/存储去原文边界/负例矩阵) | Backend `feature/w6-x1-source-recheck` @ 8c410b9(draft PR #231) | **7/7 硬需求 PASS,0 BLOCKING 0 MAJOR**(仅 6 MINOR 备忘) | — | + +## 2. 证据 + +- 全部实施经 agent-exec 有界单元(cursor,各 1 次尝试),收据:`~/.cache/agent-system-dev/agent-exec-receipts/{w5a,w5b,w7a,w6-x1-recheck-completion,w5-majors-repair}-*.json`;评审收据同目录。 +- SELF:RDM gofmt/vet + domain(0.07s)/rdmapp(79s)/plugins(3.1s) 全绿 @04991edb;Backend build/vet + store/runmgr/workflow/extension 全绿 @8c410b9;backend CI(PR #231)vet-and-test+governance success @8c410b9。 +- 评审报告:RDM `docs/reviews/2026-10-20-increment-b-rdm-review.md`(209 行,逐项 PASS/FAIL);Backend `docs/reviews/2026-10-20-w6-x1-recheck-review.md`(235 行,7 硬需求全 PASS)。 +- 权威 GATE:合入前各 PR HEAD 的 CI(Backend #231 已绿;Dev/RDM PR 在人审后创建)。 + +## 3. 已知限制与门禁 + +- **W7 provider 接线未做**:按计划但书等待 X1 公开 tag(用户双钥匙);当前仅纯领域摘要与测试,不宣布自动注入完成。 +- Backend MINOR 6 条(文档/诊断细分/补测建议)已记录于评审报告,不阻塞;建议随 W7 接线一并处理。 +- RDM MINOR 14 条见评审报告;不阻塞合入,随增量 C 顺手项处理。 +- W6 迁移与 W9 的 v31/v32 顺序:候选分支已在合并 main 后重排,串行合入时按 store 测试为准。 + +## 4. 请用户阶段 6 裁定 + +1. W5+W6+W7a 交付是否通过(对应 RDM/Backend 分支保留,人审通过后走各 PR 合入门禁)。 +2. X1 公开 tag 是否发布(双钥匙)——通过后 W7 provider 接线另行派发。 +3. RDM 评审 MINOR 14 条作为增量 C 顺手项的处理安排。 -- 2.54.0 From 72dae8fc217bc28e643a8c38eda103e380694d16 Mon Sep 17 00:00:00 2001 From: weichen Date: Wed, 21 Oct 2026 01:57:57 +0000 Subject: [PATCH 24/36] Record the user stage-6 approval for increment B Why: the user approved W5/W6/W7a at stage 6 on 2026-10-20; X1 tag stays unpublished (W7 provider wiring remains gated) and the RDM review MINORs move to increment C per the package proposal. Evidence: RDM PR #458 merged 93badd7e after CI success; backend PR #231 merged 7a41f22e after CI success. Impact: Task card only. Refs: stage-6 package docs/superpowers/specs/2026-10-20-rdm-two-trees-followup-w5-w7-review.md --- .task/feature-rdm-two-trees-followup-w5-w7.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.task/feature-rdm-two-trees-followup-w5-w7.md b/.task/feature-rdm-two-trees-followup-w5-w7.md index 52d5ef15..af9e7054 100644 --- a/.task/feature-rdm-two-trees-followup-w5-w7.md +++ b/.task/feature-rdm-two-trees-followup-w5-w7.md @@ -1,6 +1,6 @@ # feature/rdm-two-trees-followup-w5-w7 任务卡 -任务主记录:;状态:独立 Review 通过,待用户阶段 6 人审;owner:weichen +任务主记录:;状态:用户阶段 6 通过(2026-10-20),合入父 initiative 分支中;owner:weichen - 权威仓:ssh://git@git-ssh.u1680832.nyat.app:31411/weichen/Agent-System-Dev.git;目标分支:main;R0(initial_base_sha)= ed3847c85ce111a74f0cb100908abfb40f62db07 - 工作区:/home/weichen/projects/Agent-System-Dev-wt-feature-rdm-two-trees-followup-w5-w7(worktree);分支:feature/rdm-two-trees-followup-w5-w7 @@ -101,6 +101,10 @@ } ``` +## 阶段 6 结论(2026-10-20) + +用户结论「通过」。裁定明细:W5/W6/W7a 交付通过;X1 公开 tag 暂未发布(W7 provider 接线保持门禁,双钥匙另行动作);RDM 评审 MINOR 14 条按包建议列为增量 C 顺手项。合入执行:RDM PR #458 已核 CI(build-and-test+governance success @22b4fb0)后合入 RDM main(93badd7e);Backend PR #231 已核 CI(vet-and-test+governance success @5a4edf3,draft 转正式后)合入 backend main(7a41f22e)。 + ## 阶段 6 评审包(2026-10-20) 评审包:`docs/superpowers/specs/2026-10-20-rdm-two-trees-followup-w5-w7-review.md`。独立 Review 全部完成(RDM 0 BLOCKING、6 MAJOR 已修复;Backend 7/7 PASS、0 BLOCKING 0 MAJOR),增量 B 达到用户人审就绪点。 -- 2.54.0 From 87547448a92619689563cb627778c9de08e76193 Mon Sep 17 00:00:00 2001 From: weichen Date: Wed, 21 Oct 2026 01:59:41 +0000 Subject: [PATCH 25/36] Fold-close the task card before merge MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Why: close the task card inside its own PR so landing it needs no post-merge backfill or separate close PR. Evidence: .task/feature-rdm-two-trees-followup-w5-w7.md -> .task/archive/feature-rdm-two-trees-followup-w5-w7.md; status 已完成(合入前闭合); PR #666 https://git-home.u1680832.nyat.app:30319/weichen/Agent-System-Dev/pulls/666. Impact: task metadata only; the card is archived within PR #666 and lands with its merge commit. Refs: task.sh close --self --- .../feature-rdm-two-trees-followup-w5-w7.md | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) rename .task/{ => archive}/feature-rdm-two-trees-followup-w5-w7.md (95%) diff --git a/.task/feature-rdm-two-trees-followup-w5-w7.md b/.task/archive/feature-rdm-two-trees-followup-w5-w7.md similarity index 95% rename from .task/feature-rdm-two-trees-followup-w5-w7.md rename to .task/archive/feature-rdm-two-trees-followup-w5-w7.md index af9e7054..858d5278 100644 --- a/.task/feature-rdm-two-trees-followup-w5-w7.md +++ b/.task/archive/feature-rdm-two-trees-followup-w5-w7.md @@ -1,6 +1,6 @@ # feature/rdm-two-trees-followup-w5-w7 任务卡 -任务主记录:;状态:用户阶段 6 通过(2026-10-20),合入父 initiative 分支中;owner:weichen +任务主记录:PR #666 https://git-home.u1680832.nyat.app:30319/weichen/Agent-System-Dev/pulls/666;状态:已完成(合入前闭合);owner:weichen - 权威仓:ssh://git@git-ssh.u1680832.nyat.app:31411/weichen/Agent-System-Dev.git;目标分支:main;R0(initial_base_sha)= ed3847c85ce111a74f0cb100908abfb40f62db07 - 工作区:/home/weichen/projects/Agent-System-Dev-wt-feature-rdm-two-trees-followup-w5-w7(worktree);分支:feature/rdm-two-trees-followup-w5-w7 @@ -47,7 +47,7 @@ | 时间(UTC) | 命令 | 被测HEAD | exit | 来源 | sha256(16) | |---|---|---|---|---|---| -## 结果与验证(完成后填写) +## 结果与验证 - 结果: - 验证:<结论摘要 PASS/FAIL/SKIP/NOT_RUN 逐项;逐条证据由 make evidence 写入上方证据表> @@ -116,3 +116,9 @@ ## W6 门禁记录(2026-10-20) W6 按设计修订文档 `rdm-two-trees-stage6-w6-source-recheck-design-adjustment-r1.md`(状态:**待人工评审**)暂停实现:候选分支 HEAD 6ba53e4(未推送)已有部分实现但含隐私敏感的存储/迁移取舍,须经用户批准该修订后方可继续。本单元按计划 W7 但书仅交付「纯领域摘要与测试」,未消费基座接口,不宣布自动注入完成。 + +## 闭合记录(合入前折叠) + +- 本卡在 PR #666(https://git-home.u1680832.nyat.app:30319/weichen/Agent-System-Dev/pulls/666)合入前闭合并归档,随该 PR 一同合入。 +- 该 PR 的合并提交即本任务的落地记录。 +- 合入后无需回填,也无需单独的闭合 PR。 -- 2.54.0 From ba4eaca49c1a4899e0304e746b3178aa18a2dfe5 Mon Sep 17 00:00:00 2001 From: weichen Date: Wed, 21 Oct 2026 02:08:58 +0000 Subject: [PATCH 26/36] Record increment B delivery in the initiative card Why: increment B (W5/W6/W7a) passed user stage-6 and merged across the three repos; the charter requires the subtask registry and current stage to reflect it. Evidence: RDM #458 merged 93badd7e; Dev #666 merged c76e681; backend #231 merged 7a41f22e; stage-6 package on the child branch. Impact: Task card only. Refs: child card feature-rdm-two-trees-followup-w5-w7 (PR #666) --- .task/feature-rdm-two-trees-followup.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.task/feature-rdm-two-trees-followup.md b/.task/feature-rdm-two-trees-followup.md index 23ff96b6..a26c2b74 100644 --- a/.task/feature-rdm-two-trees-followup.md +++ b/.task/feature-rdm-two-trees-followup.md @@ -14,7 +14,7 @@ - 实施执行:agent-per-unit(配置:AGENT-EXECUTION.md) - 合入执行:agent(已授权交付范围内,Review 通过、冲突解决且当前 HEAD 的 CI 通过后合入) - 人工决策点:仅限目标/范围/验收变更、重大取舍、高后果操作或无法自动判定的业务验收 -- 当前阶段:A1 已通过阶段 6(保留在本 initiative 分支);W3 余项子任务用户 2026-10-20 阶段 6 通过,RDM #451 已合入 RDM main(76b4c05),子任务合入本分支 +- 当前阶段:A1、W3 余项、增量 B(W5/W6/W7a)均通过阶段 6 并合入本分支;下一增量:C(W8/W10,待登记);W7 provider 接线等 X1 tag(用户双钥匙) - 流程依据:仓库根目录 policy/delivery.md(归档后仍按仓库根目录定位) ## 目标与非目标 @@ -37,6 +37,7 @@ |---|---|---|---| | A1:W0 守护 + svc 动态端口 + W3 差距核对(本分支内增量) | 是 | 已合入(本分支 000a2d2;用户 2026-10-19 阶段 6 通过) | 本分支 PR #635(草稿,initiative 收口时合入 main) | | feature/rdm-two-trees-followup-w3-rest | 是 | 已合入(用户 2026-10-20 阶段 6 通过;W3 余项:迁移两次同值、图形不透明块、移动/改名引用、旧批准版回取、重复表格复核;评审包 docs/superpowers/specs/2026-10-19-rdm-two-trees-followup-w3-review.md)。前置条件:W4 开放结构写入口前先补节点种类放置检查;Dev 的 RDM gitlink 改钉在 initiative 收口时统一组合验证 | RDM PR [#451](https://git-home.u1680832.nyat.app:30319/weichen/Agent-System-RDM/pulls/451)(合入 RDM main 76b4c05);本子任务 PR [#641](https://git-home.u1680832.nyat.app:30319/weichen/Agent-System-Dev/pulls/641) | +| feature/rdm-two-trees-followup-w5-w7(增量 B:W5/W6/W7a) | 是 | 已合入(用户 2026-10-20 阶段 6 通过:W5 追溯网领域核+命令面、W6 X1 恢复并按批准修订补齐、W7a 纯领域 bundle;独立 Review RDM 0 BLOCKING/6 MAJOR 已修复、Backend 7/7 PASS;评审包 docs/superpowers/specs/2026-10-20-rdm-two-trees-followup-w5-w7-review.md)。W7 provider 接线等 X1 tag(用户双钥匙);Backend MINOR 6 条随接线处理;RDM MINOR 14 条为增量 C 顺手项 | RDM PR [#458](https://git-home.u1680832.nyat.app:30319/weichen/Agent-System-RDM/pulls/458)(合入 RDM main 93badd7e);本子任务 PR [#666](https://git-home.u1680832.nyat.app:30319/weichen/Agent-System-Dev/pulls/666);Backend PR [#231](https://git-home.u1680832.nyat.app:30319/weichen/Agent-System-Backend/pulls/231)(合入 backend main 7a41f22e) | | B:W5/W7 | 是 | 待登记 | — | | C:W8/W10 | 是 | 待登记 | — | | D:W11/W12/W13 | 是 | 待登记(需资源方案) | — | -- 2.54.0 From cc98cac6994ebdd59f99713eabb19f976f38f1da Mon Sep 17 00:00:00 2001 From: weichen Date: Thu, 22 Oct 2026 01:24:37 +0000 Subject: [PATCH 27/36] Record the task card for feature-rdm-two-trees-followup-c-w8-w10 Why: establish the authorized task workspace and its initial baseline. Evidence: preserved precheck receipt in .task/feature-rdm-two-trees-followup-c-w8-w10.md; R0=f23f5bb01a8b96ab90686d3a1b07791d7f473de2. Impact: task metadata only; the feature workspace starts at dcca5112923790506e0728a89ae3752349405653. Refs: .task/feature-rdm-two-trees-followup-c-w8-w10.md --- ...feature-rdm-two-trees-followup-c-w8-w10.md | 93 +++++++++++++++++++ 1 file changed, 93 insertions(+) create mode 100644 .task/feature-rdm-two-trees-followup-c-w8-w10.md diff --git a/.task/feature-rdm-two-trees-followup-c-w8-w10.md b/.task/feature-rdm-two-trees-followup-c-w8-w10.md new file mode 100644 index 00000000..3df049de --- /dev/null +++ b/.task/feature-rdm-two-trees-followup-c-w8-w10.md @@ -0,0 +1,93 @@ +# feature/rdm-two-trees-followup-c-w8-w10 任务卡 + +任务主记录:;状态:进行中;owner:weichen + +- 权威仓:ssh://git@192.168.3.2:2222/weichen/Agent-System-Dev.git;目标分支:main;R0(initial_base_sha)= f23f5bb01a8b96ab90686d3a1b07791d7f473de2 +- 工作区:/home/weichen/projects/Agent-System-Dev-wt-feature-rdm-two-trees-followup-c-w8-w10(worktree);分支:feature/rdm-two-trees-followup-c-w8-w10 +- 分支类型:child;initiative_id:feature-rdm-two-trees-followup;root_target:main;immediate_target:feature/rdm-two-trees-followup;accepting_requirements:false;parent_branch:feature/rdm-two-trees-followup;parent_head_sha:dcca5112923790506e0728a89ae3752349405653;parent_pr:无;parent_source:origin +- 需求分流:verdict=JOIN;selected_initiative=feature/rdm-two-trees-followup;requirement_sha256=f4a1ab636c59ce3df302201310d359eac88b105e8ffecd86da8f7266bf3fa58e;triage_receipt=/tmp/triage-incC.json;receipt_sha256=3fb1f7cb6dd41fc250c764d08dd612749f150f3e619b54cbc3a9144b37a4d298 + +- 授权与交付终点:<本次允许的动作与终点;未授权事项写明> +- 交付模式:goal-first(目标、范围和交付终点一次确认;范围内连续推进) +- 实施执行:agent-per-unit(配置:AGENT-EXECUTION.md) +- 合入执行:agent(已授权交付范围内,Review 通过、冲突解决且当前 HEAD 的 CI 通过后合入) +- 流程依据:仓库根目录 policy/delivery.md(归档后仍按仓库根目录定位) + +## 目标与非目标 + +<预期结果、受影响入口/模块/契约;明确不做什么。> + +## Agent 实施收据 + +路由与 fail-stop 规则见根目录 AGENT-EXECUTION.md 与 policy/delivery.md;每次尝试一行,原始日志留在源码外收据路径。 + +| 单元 ID | 预期范围 | 配置摘要 | 角色 | 候选顺序 | attempt | CLI/模型 | 终态 | transport | fallback | 源码外收据路径 | +|---|---|---|---|---|---|---|---|---|---|---| +| 待定义 | — | NOT_RUN | NOT_RUN | NOT_RUN | NOT_RUN | NOT_RUN | NOT_RUN | NOT_RUN | NOT_RUN | — | + +## 同步记录 + +| 节点 | sync_base_sha | tested_head_sha | checked_at | +|---|---|---|---| +| 启动 | f23f5bb01a8b96ab90686d3a1b07791d7f473de2 | dcca5112923790506e0728a89ae3752349405653 | 2026-10-22T01:24:37Z | + +## 证据(Evidence) + + +| 时间(UTC) | 命令 | 被测HEAD | exit | 来源 | sha256(16) | +|---|---|---|---|---|---| + +## 结果与验证(完成后填写) + +- 结果: +- 验证:<结论摘要 PASS/FAIL/SKIP/NOT_RUN 逐项;逐条证据由 make evidence 写入上方证据表> +- 影响与剩余项: + +## 合入与清理 + +- Review 记录:NOT_RUN(审阅智能体/平台身份、base/head、结论、问题闭合及重放依据) +- 冲突记录:NOT_RUN(最新目标同步、冲突处置、组合兼容核验及复审/补测) +- CI 记录:NOT_RUN(当前 HEAD 完整 SHA、全部必需检查、运行链接、执行身份及 GATE 结果) +- 合入记录:NOT_RUN(交付授权范围、PR、被核验 HEAD、合入 SHA、目标分支及内容核验) +- 清理记录:NOT_RUN(授权依据、写者退出确认、worktree/分支/任务卡处置) + + +```json +{ + "summary_schema": 1, + "source": "SELF", + "timestamp": "2026-10-22T01:23:50.112388+00:00", + "command": "make precheck", + "exit_code": 0, + "cwd": "/home/weichen/projects/Agent-System-Dev", + "before_head": "f23f5bb01a8b96ab90686d3a1b07791d7f473de2", + "after_head": "f23f5bb01a8b96ab90686d3a1b07791d7f473de2", + "branch": "main", + "target_branch": "main", + "target_head": "f23f5bb01a8b96ab90686d3a1b07791d7f473de2", + "root_target": "main", + "immediate_target": "main", + "before_tracked_diff_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "after_tracked_diff_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "output_tail": [ + "make[1]: Entering directory '/home/weichen/projects/Agent-System-Dev'", + "[repo] branch=main head=f23f5bb01a", + "[remote] origin/main=f23f5bb01a ahead=0 behind=0", + "[tree] clean submodules_drift=0 uninit=0", + "[worktrees] linked=5", + "[recycle] merged un-recycled branches: fix/ci-rdm-pin-materialization fix/pal-component-delivery-pins", + "[cards] 已合入未闭合任务卡:fix-pal-component-delivery-pins.md——make task-close 回填归档(主检出运行)", + "[initiatives] local cards (not authoritative): none", + "[hooks] core.hooksPath=scripts/hooks(pre-commit/post-merge 实际接线)", + "[facts] policy/facts.md 6 条事实均在有效期内", + "[required-reading] core/baseline.md, workflows/delivery.md §1, policy/delivery.md", + "[R0] f23f5bb01a(完整:f23f5bb01a8b96ab90686d3a1b07791d7f473de2)", + "[worktree] before-sync: recursive component checks passed", + "[verdict] READY — 保留本次 precheck receipt 后建任务工作区:PRECHECK_RECEIPT=/tmp/task-precheck.json make task-start NAME=feature/your-branch", + "make[1]: Leaving directory '/home/weichen/projects/Agent-System-Dev'" + ], + "output_sha256": "013e1d4d93548576815e9e2fe8e735d049fea47507ef4492478b55e4cf3c7cd6", + "receipt_sha256": "643c76ed799ad8ca4ea16ba47a3510694218cdc18e387586ed9e36d6f9c44502", + "receipt_path": "/home/weichen/.cache/agent-system-dev/evidence/643c76ed799ad8ca4ea16ba47a3510694218cdc18e387586ed9e36d6f9c44502.json" +} +``` -- 2.54.0 From ecf923d6ca7c927d206e2ad6ad7186cc616e91fc Mon Sep 17 00:00:00 2001 From: weichen Date: Thu, 22 Oct 2026 01:41:58 +0000 Subject: [PATCH 28/36] Record the W8a operation audit core unit Why: agent-per-unit governance requires each implementation attempt recorded in the increment C card. Evidence: w8a-operation-audit-core completed via cursor attempt 1; transport 6fd0478; SELF gofmt/vet ok, domain+rdmapp tests ok. Impact: Task card only. Refs: stage-5 plan W8; parent initiative feature/rdm-two-trees-followup --- .task/feature-rdm-two-trees-followup-c-w8-w10.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.task/feature-rdm-two-trees-followup-c-w8-w10.md b/.task/feature-rdm-two-trees-followup-c-w8-w10.md index 3df049de..a17bca80 100644 --- a/.task/feature-rdm-two-trees-followup-c-w8-w10.md +++ b/.task/feature-rdm-two-trees-followup-c-w8-w10.md @@ -1,6 +1,6 @@ # feature/rdm-two-trees-followup-c-w8-w10 任务卡 -任务主记录:;状态:进行中;owner:weichen +任务主记录:;状态:进行中(W8a 已交付;序列 W8a→W8b 投影→W9→W10);owner:weichen - 权威仓:ssh://git@192.168.3.2:2222/weichen/Agent-System-Dev.git;目标分支:main;R0(initial_base_sha)= f23f5bb01a8b96ab90686d3a1b07791d7f473de2 - 工作区:/home/weichen/projects/Agent-System-Dev-wt-feature-rdm-two-trees-followup-c-w8-w10(worktree);分支:feature/rdm-two-trees-followup-c-w8-w10 @@ -23,6 +23,7 @@ | 单元 ID | 预期范围 | 配置摘要 | 角色 | 候选顺序 | attempt | CLI/模型 | 终态 | transport | fallback | 源码外收据路径 | |---|---|---|---|---|---|---|---|---|---|---| +| w8a-operation-audit-core | W8 领域核:操作审计事实/同事务写入/失败尝试/幂等回执/延迟补全/重放一致 | implementation | cursor | 1 | cursor(auto) | completed | 6fd0478(refs/agent-exec/…,收据 ~/.cache/agent-system-dev/agent-exec-receipts/w8a-operation-audit-core.json) | never | ~/.cache/agent-system-dev/agent-exec-receipts/w8a-operation-audit-core.json | | 待定义 | — | NOT_RUN | NOT_RUN | NOT_RUN | NOT_RUN | NOT_RUN | NOT_RUN | NOT_RUN | NOT_RUN | — | ## 同步记录 -- 2.54.0 From 66b4f728449e61fc0fbbc15aecc0903568ac8871 Mon Sep 17 00:00:00 2001 From: weichen Date: Thu, 22 Oct 2026 02:49:25 +0000 Subject: [PATCH 29/36] Record the W8a and W8b units in the increment C card Why: agent-per-unit governance requires each implementation attempt recorded in the task card. Evidence: w8a 6fd0478 and w8b c3d3111 (attempt 2 after an infra retry); SELF vet ok and domain/rdmapp/plugins tests all ok. Impact: Task card only. Refs: stage-5 plan W8; parent initiative feature/rdm-two-trees-followup --- .task/feature-rdm-two-trees-followup-c-w8-w10.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.task/feature-rdm-two-trees-followup-c-w8-w10.md b/.task/feature-rdm-two-trees-followup-c-w8-w10.md index a17bca80..59b91c10 100644 --- a/.task/feature-rdm-two-trees-followup-c-w8-w10.md +++ b/.task/feature-rdm-two-trees-followup-c-w8-w10.md @@ -1,6 +1,6 @@ # feature/rdm-two-trees-followup-c-w8-w10 任务卡 -任务主记录:;状态:进行中(W8a 已交付;序列 W8a→W8b 投影→W9→W10);owner:weichen +任务主记录:;状态:进行中(W8a+W8b 已交付;序列 W9→W10→评审包);owner:weichen - 权威仓:ssh://git@192.168.3.2:2222/weichen/Agent-System-Dev.git;目标分支:main;R0(initial_base_sha)= f23f5bb01a8b96ab90686d3a1b07791d7f473de2 - 工作区:/home/weichen/projects/Agent-System-Dev-wt-feature-rdm-two-trees-followup-c-w8-w10(worktree);分支:feature/rdm-two-trees-followup-c-w8-w10 @@ -24,6 +24,8 @@ | 单元 ID | 预期范围 | 配置摘要 | 角色 | 候选顺序 | attempt | CLI/模型 | 终态 | transport | fallback | 源码外收据路径 | |---|---|---|---|---|---|---|---|---|---|---| | w8a-operation-audit-core | W8 领域核:操作审计事实/同事务写入/失败尝试/幂等回执/延迟补全/重放一致 | implementation | cursor | 1 | cursor(auto) | completed | 6fd0478(refs/agent-exec/…,收据 ~/.cache/agent-system-dev/agent-exec-receipts/w8a-operation-audit-core.json) | never | ~/.cache/agent-system-dev/agent-exec-receipts/w8a-operation-audit-core.json | +| w8a-operation-audit-core | W8 领域核(attempt 1 详见 ~/.cache/…/w8a-operation-audit-core.json;transport 6fd0478) | implementation | cursor | 1 | cursor(auto) | completed | 6fd0478 | never | ~/.cache/agent-system-dev/agent-exec-receipts/w8a-operation-audit-core.json | +| w8b-audit-projection | W8 可读投影:DTO 词典/游标分页/可见性接线/rdm.audit.operations(attempt 1 infra 重试) | implementation | cursor | 2 | cursor(auto) | completed | c3d3111 | never | /home/weichen/.cache/agent-system-dev/agent-exec-receipts/w8b-audit-projection.json | | 待定义 | — | NOT_RUN | NOT_RUN | NOT_RUN | NOT_RUN | NOT_RUN | NOT_RUN | NOT_RUN | NOT_RUN | — | ## 同步记录 -- 2.54.0 From ebc3a6d137f72d096a50296d1f0d91dbb3dcac18 Mon Sep 17 00:00:00 2001 From: weichen Date: Thu, 22 Oct 2026 04:05:55 +0000 Subject: [PATCH 30/36] Record the W9 RDM audit adapter unit Why: agent-per-unit governance requires the attempt recorded in the increment C card. Evidence: w9-rdm-audit-adapter completed via cursor attempt 1; transport c4c6df7; pin advanced to backend main 92a41183 (X1+X2+MINORs); SELF build/vet ok and domain/rdmapp/plugins tests all ok. Impact: Task card only. Refs: stage-5 plan W9; backend PR #243 --- .task/feature-rdm-two-trees-followup-c-w8-w10.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.task/feature-rdm-two-trees-followup-c-w8-w10.md b/.task/feature-rdm-two-trees-followup-c-w8-w10.md index 59b91c10..29af1896 100644 --- a/.task/feature-rdm-two-trees-followup-c-w8-w10.md +++ b/.task/feature-rdm-two-trees-followup-c-w8-w10.md @@ -1,6 +1,6 @@ # feature/rdm-two-trees-followup-c-w8-w10 任务卡 -任务主记录:;状态:进行中(W8a+W8b 已交付;序列 W9→W10→评审包);owner:weichen +任务主记录:;状态:进行中(W8a+W8b+W9-RDM 适配已交付;剩 W10 Frontend→评审包);owner:weichen - 权威仓:ssh://git@192.168.3.2:2222/weichen/Agent-System-Dev.git;目标分支:main;R0(initial_base_sha)= f23f5bb01a8b96ab90686d3a1b07791d7f473de2 - 工作区:/home/weichen/projects/Agent-System-Dev-wt-feature-rdm-two-trees-followup-c-w8-w10(worktree);分支:feature/rdm-two-trees-followup-c-w8-w10 @@ -26,6 +26,7 @@ | w8a-operation-audit-core | W8 领域核:操作审计事实/同事务写入/失败尝试/幂等回执/延迟补全/重放一致 | implementation | cursor | 1 | cursor(auto) | completed | 6fd0478(refs/agent-exec/…,收据 ~/.cache/agent-system-dev/agent-exec-receipts/w8a-operation-audit-core.json) | never | ~/.cache/agent-system-dev/agent-exec-receipts/w8a-operation-audit-core.json | | w8a-operation-audit-core | W8 领域核(attempt 1 详见 ~/.cache/…/w8a-operation-audit-core.json;transport 6fd0478) | implementation | cursor | 1 | cursor(auto) | completed | 6fd0478 | never | ~/.cache/agent-system-dev/agent-exec-receipts/w8a-operation-audit-core.json | | w8b-audit-projection | W8 可读投影:DTO 词典/游标分页/可见性接线/rdm.audit.operations(attempt 1 infra 重试) | implementation | cursor | 2 | cursor(auto) | completed | c3d3111 | never | /home/weichen/.cache/agent-system-dev/agent-exec-receipts/w8b-audit-projection.json | +| w9-rdm-audit-adapter | W9 RDM 消费端:audit.read 回调适配 Backend X2(受信裁剪/当时名称/owner 分离/拒绝事实)+ pin 前进 92a41183(worker 自纠 41 位笔误:按前缀 fetch 真 tip) | implementation | cursor | 1 | cursor(auto) | completed | c4c6df7 | never | /home/weichen/.cache/agent-system-dev/agent-exec-receipts/w9-rdm-audit-adapter.json | | 待定义 | — | NOT_RUN | NOT_RUN | NOT_RUN | NOT_RUN | NOT_RUN | NOT_RUN | NOT_RUN | NOT_RUN | — | ## 同步记录 -- 2.54.0 From 92757e9f170768f0a19c8738582c5cb1acc9da28 Mon Sep 17 00:00:00 2001 From: weichen Date: Thu, 22 Oct 2026 05:30:25 +0000 Subject: [PATCH 31/36] Record the W10 frontend unit in the increment C card Why: agent-per-unit governance requires the attempt recorded in the increment C card. Evidence: w10-audit-workspace completed via cursor (attempt 2 after a legitimate scope-expansion re-dispatch); transport fa08be4 on FE branch feature/rdm-two-trees-followup-w10; SELF design-guard 7/7, component tests 33/33, build ok. Impact: Task card only. Refs: stage-5 plan W10; parent initiative feature/rdm-two-trees-followup --- .task/feature-rdm-two-trees-followup-c-w8-w10.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.task/feature-rdm-two-trees-followup-c-w8-w10.md b/.task/feature-rdm-two-trees-followup-c-w8-w10.md index 29af1896..b088f46b 100644 --- a/.task/feature-rdm-two-trees-followup-c-w8-w10.md +++ b/.task/feature-rdm-two-trees-followup-c-w8-w10.md @@ -1,6 +1,6 @@ # feature/rdm-two-trees-followup-c-w8-w10 任务卡 -任务主记录:;状态:进行中(W8a+W8b+W9-RDM 适配已交付;剩 W10 Frontend→评审包);owner:weichen +任务主记录:;状态:进行中(W8a+W8b+W9+W10 全部交付;下一步独立 Review→阶段 6 评审包);owner:weichen - 权威仓:ssh://git@192.168.3.2:2222/weichen/Agent-System-Dev.git;目标分支:main;R0(initial_base_sha)= f23f5bb01a8b96ab90686d3a1b07791d7f473de2 - 工作区:/home/weichen/projects/Agent-System-Dev-wt-feature-rdm-two-trees-followup-c-w8-w10(worktree);分支:feature/rdm-two-trees-followup-c-w8-w10 @@ -27,6 +27,7 @@ | w8a-operation-audit-core | W8 领域核(attempt 1 详见 ~/.cache/…/w8a-operation-audit-core.json;transport 6fd0478) | implementation | cursor | 1 | cursor(auto) | completed | 6fd0478 | never | ~/.cache/agent-system-dev/agent-exec-receipts/w8a-operation-audit-core.json | | w8b-audit-projection | W8 可读投影:DTO 词典/游标分页/可见性接线/rdm.audit.operations(attempt 1 infra 重试) | implementation | cursor | 2 | cursor(auto) | completed | c3d3111 | never | /home/weichen/.cache/agent-system-dev/agent-exec-receipts/w8b-audit-projection.json | | w9-rdm-audit-adapter | W9 RDM 消费端:audit.read 回调适配 Backend X2(受信裁剪/当时名称/owner 分离/拒绝事实)+ pin 前进 92a41183(worker 自纠 41 位笔误:按前缀 fetch 真 tip) | implementation | cursor | 1 | cursor(auto) | completed | c4c6df7 | never | /home/weichen/.cache/agent-system-dev/agent-exec-receipts/w9-rdm-audit-adapter.json | +| w10-audit-workspace | W10 正式 Frontend:审计工作台/树懒加载/工作卡/依据条/四态/seq(FE 子分支 feature/rdm-two-trees-followup-w10 @fa08be4;知识多挂载显示留 TODO 待 RDM DTO 增补) | implementation | cursor | 2(attempt1 合理扩围重派) | cursor(auto) | completed | fa08be4 | never | /home/weichen/.cache/agent-system-dev/agent-exec-receipts/w10-audit-workspace.json | | 待定义 | — | NOT_RUN | NOT_RUN | NOT_RUN | NOT_RUN | NOT_RUN | NOT_RUN | NOT_RUN | NOT_RUN | — | ## 同步记录 -- 2.54.0 From baf99ebd44a366ac92a8d97cec403e40ac59fe45 Mon Sep 17 00:00:00 2001 From: weichen Date: Thu, 22 Oct 2026 06:15:23 +0000 Subject: [PATCH 32/36] Record the increment C reviews and MAJOR repairs Why: agent-per-unit governance requires review and repair attempts recorded in the increment C card. Evidence: reviews 0 BLOCKING (RDM 5 MAJOR, FE 3 MAJOR) repaired in d835ae6 / 4882e0a; SELF domain/rdmapp/plugins and design-guard/workspace tests all ok. Impact: Task card only. Refs: parent initiative feature/rdm-two-trees-followup --- .task/feature-rdm-two-trees-followup-c-w8-w10.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.task/feature-rdm-two-trees-followup-c-w8-w10.md b/.task/feature-rdm-two-trees-followup-c-w8-w10.md index b088f46b..3e5871f8 100644 --- a/.task/feature-rdm-two-trees-followup-c-w8-w10.md +++ b/.task/feature-rdm-two-trees-followup-c-w8-w10.md @@ -1,6 +1,6 @@ # feature/rdm-two-trees-followup-c-w8-w10 任务卡 -任务主记录:;状态:进行中(W8a+W8b+W9+W10 全部交付;下一步独立 Review→阶段 6 评审包);owner:weichen +任务主记录:;状态:进行中(W8a+W8b+W9+W10 全部交付;独立 Review 完成且 MAJOR 全修复;MINOR 留档评审报告;下一步阶段 6 评审包→用户人审);owner:weichen - 权威仓:ssh://git@192.168.3.2:2222/weichen/Agent-System-Dev.git;目标分支:main;R0(initial_base_sha)= f23f5bb01a8b96ab90686d3a1b07791d7f473de2 - 工作区:/home/weichen/projects/Agent-System-Dev-wt-feature-rdm-two-trees-followup-c-w8-w10(worktree);分支:feature/rdm-two-trees-followup-c-w8-w10 @@ -28,6 +28,10 @@ | w8b-audit-projection | W8 可读投影:DTO 词典/游标分页/可见性接线/rdm.audit.operations(attempt 1 infra 重试) | implementation | cursor | 2 | cursor(auto) | completed | c3d3111 | never | /home/weichen/.cache/agent-system-dev/agent-exec-receipts/w8b-audit-projection.json | | w9-rdm-audit-adapter | W9 RDM 消费端:audit.read 回调适配 Backend X2(受信裁剪/当时名称/owner 分离/拒绝事实)+ pin 前进 92a41183(worker 自纠 41 位笔误:按前缀 fetch 真 tip) | implementation | cursor | 1 | cursor(auto) | completed | c4c6df7 | never | /home/weichen/.cache/agent-system-dev/agent-exec-receipts/w9-rdm-audit-adapter.json | | w10-audit-workspace | W10 正式 Frontend:审计工作台/树懒加载/工作卡/依据条/四态/seq(FE 子分支 feature/rdm-two-trees-followup-w10 @fa08be4;知识多挂载显示留 TODO 待 RDM DTO 增补) | implementation | cursor | 2(attempt1 合理扩围重派) | cursor(auto) | completed | fa08be4 | never | /home/weichen/.cache/agent-system-dev/agent-exec-receipts/w10-audit-workspace.json | +| rev-increment-c-rdm | RDM 增量 C 独立评审(0 BLOCKING/5 MAJOR/15 MINOR;报告 docs/reviews/2026-10-22-increment-c-rdm-review.md @b7b5227) | review | pi | 1 | pi(default) | completed | b7b5227 | never | ~/.cache/agent-system-dev/agent-exec-receipts/rev-c-rdm-receipt.json | +| fix-increment-c-rdm-majors | RDM 5 MAJOR 修复(schema-2 目录/copyState/生产写接线等,含回归测试) | repair | cursor | 1 | cursor(auto) | completed | d835ae6 | never | ~/.cache/agent-system-dev/agent-exec-receipts/fix-increment-c-rdm.json | +| rev-increment-c-fe | FE W10 独立评审(0 BLOCKING/3 MAJOR/MINOR;报告 docs/reviews/2026-10-22-increment-c-fe-review.md @a61eaac) | review | pi | 1 | pi(default) | completed | a61eaac | never | ~/.cache/agent-system-dev/agent-exec-receipts/rev-c-fe-receipt.json | +| fix-increment-c-fe-majors | FE 3 MAJOR 修复(openInbox 定位/能力门禁/@ui Collapsible,+6 回归测试) | repair | cursor | 1 | cursor(auto) | completed | 4882e0a | never | ~/.cache/agent-system-dev/agent-exec-receipts/fix-increment-c-fe.json | | 待定义 | — | NOT_RUN | NOT_RUN | NOT_RUN | NOT_RUN | NOT_RUN | NOT_RUN | NOT_RUN | NOT_RUN | — | ## 同步记录 -- 2.54.0 From d183e43adb6f4e5d219e7f1a1ac8a3bde24f7b5d Mon Sep 17 00:00:00 2001 From: weichen Date: Thu, 22 Oct 2026 06:25:45 +0000 Subject: [PATCH 33/36] Record the user stage-6 approval for increment C Why: the user approved W8/W9/W10 at stage 6 on 2026-10-22; RDM #470 and FE #125 merged after CI; the knowledge-multi-mount DTO and RDM review MINORs move to increment D, W11/W12 stay pending resource authorization. Evidence: CI success at RDM 4951086 and FE a82a1e1 (both after merging latest main). Impact: Task card only. Refs: stage-6 review reports on this branch (docs/reviews/2026-10-22-increment-c-*) --- .task/feature-rdm-two-trees-followup-c-w8-w10.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.task/feature-rdm-two-trees-followup-c-w8-w10.md b/.task/feature-rdm-two-trees-followup-c-w8-w10.md index 3e5871f8..4db54181 100644 --- a/.task/feature-rdm-two-trees-followup-c-w8-w10.md +++ b/.task/feature-rdm-two-trees-followup-c-w8-w10.md @@ -1,6 +1,6 @@ # feature/rdm-two-trees-followup-c-w8-w10 任务卡 -任务主记录:;状态:进行中(W8a+W8b+W9+W10 全部交付;独立 Review 完成且 MAJOR 全修复;MINOR 留档评审报告;下一步阶段 6 评审包→用户人审);owner:weichen +任务主记录:;状态:用户阶段 6 通过(2026-10-22),合入父 initiative 分支中;owner:weichen(W8a+W8b+W9+W10 全部交付;独立 Review 完成且 MAJOR 全修复;MINOR 留档评审报告;下一步阶段 6 评审包→用户人审);owner:weichen - 权威仓:ssh://git@192.168.3.2:2222/weichen/Agent-System-Dev.git;目标分支:main;R0(initial_base_sha)= f23f5bb01a8b96ab90686d3a1b07791d7f473de2 - 工作区:/home/weichen/projects/Agent-System-Dev-wt-feature-rdm-two-trees-followup-c-w8-w10(worktree);分支:feature/rdm-two-trees-followup-c-w8-w10 -- 2.54.0 From 32ed66d11eb04e53210399de0f0c50c26ce76e31 Mon Sep 17 00:00:00 2001 From: weichen Date: Thu, 22 Oct 2026 06:25:47 +0000 Subject: [PATCH 34/36] Fold-close the task card before merge MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Why: close the task card inside its own PR so landing it needs no post-merge backfill or separate close PR. Evidence: .task/feature-rdm-two-trees-followup-c-w8-w10.md -> .task/archive/feature-rdm-two-trees-followup-c-w8-w10.md; status 已完成(合入前闭合); PR #693 https://git-home.u1680832.nyat.app:30319/weichen/Agent-System-Dev/pulls/693. Impact: task metadata only; the card is archived within PR #693 and lands with its merge commit. Refs: task.sh close --self --- .../feature-rdm-two-trees-followup-c-w8-w10.md | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) rename .task/{ => archive}/feature-rdm-two-trees-followup-c-w8-w10.md (92%) diff --git a/.task/feature-rdm-two-trees-followup-c-w8-w10.md b/.task/archive/feature-rdm-two-trees-followup-c-w8-w10.md similarity index 92% rename from .task/feature-rdm-two-trees-followup-c-w8-w10.md rename to .task/archive/feature-rdm-two-trees-followup-c-w8-w10.md index 4db54181..dced48b0 100644 --- a/.task/feature-rdm-two-trees-followup-c-w8-w10.md +++ b/.task/archive/feature-rdm-two-trees-followup-c-w8-w10.md @@ -1,6 +1,6 @@ # feature/rdm-two-trees-followup-c-w8-w10 任务卡 -任务主记录:;状态:用户阶段 6 通过(2026-10-22),合入父 initiative 分支中;owner:weichen(W8a+W8b+W9+W10 全部交付;独立 Review 完成且 MAJOR 全修复;MINOR 留档评审报告;下一步阶段 6 评审包→用户人审);owner:weichen +任务主记录:PR #693 https://git-home.u1680832.nyat.app:30319/weichen/Agent-System-Dev/pulls/693;状态:已完成(合入前闭合);owner:weichen(W8a+W8b+W9+W10 全部交付;独立 Review 完成且 MAJOR 全修复;MINOR 留档评审报告;下一步阶段 6 评审包→用户人审);owner:weichen - 权威仓:ssh://git@192.168.3.2:2222/weichen/Agent-System-Dev.git;目标分支:main;R0(initial_base_sha)= f23f5bb01a8b96ab90686d3a1b07791d7f473de2 - 工作区:/home/weichen/projects/Agent-System-Dev-wt-feature-rdm-two-trees-followup-c-w8-w10(worktree);分支:feature/rdm-two-trees-followup-c-w8-w10 @@ -46,7 +46,7 @@ | 时间(UTC) | 命令 | 被测HEAD | exit | 来源 | sha256(16) | |---|---|---|---|---|---| -## 结果与验证(完成后填写) +## 结果与验证 - 结果: - 验证:<结论摘要 PASS/FAIL/SKIP/NOT_RUN 逐项;逐条证据由 make evidence 写入上方证据表> @@ -100,3 +100,9 @@ "receipt_path": "/home/weichen/.cache/agent-system-dev/evidence/643c76ed799ad8ca4ea16ba47a3510694218cdc18e387586ed9e36d6f9c44502.json" } ``` + +## 闭合记录(合入前折叠) + +- 本卡在 PR #693(https://git-home.u1680832.nyat.app:30319/weichen/Agent-System-Dev/pulls/693)合入前闭合并归档,随该 PR 一同合入。 +- 该 PR 的合并提交即本任务的落地记录。 +- 合入后无需回填,也无需单独的闭合 PR。 -- 2.54.0 From af2e6b41117c1ff4306e1b277aa01a9df07b1c4f Mon Sep 17 00:00:00 2001 From: weichen Date: Thu, 22 Oct 2026 06:35:19 +0000 Subject: [PATCH 35/36] Record the sync checkpoint Why: bind the task validation checkpoint to the integration baseline. Evidence: SELF recursive component checks; sync_base=33d6ef69212595c680a744549986c19bb6acd6c3; before_record=1b286ec3e68260d9d25cb3ab651ede31143d5b06. Impact: task metadata only. Refs: .task/feature-rdm-two-trees-followup.md --- .task/feature-rdm-two-trees-followup.md | 1 + 1 file changed, 1 insertion(+) diff --git a/.task/feature-rdm-two-trees-followup.md b/.task/feature-rdm-two-trees-followup.md index a26c2b74..5b397f00 100644 --- a/.task/feature-rdm-two-trees-followup.md +++ b/.task/feature-rdm-two-trees-followup.md @@ -250,3 +250,4 @@ } ``` | 同步(记录前对象) | 7e6c544b3c25c510e3d928bfb4515937a1cd6696 | 85624242789c823b96f2adb080e11833f73352e3 | 2026-10-20T11:41:24Z | +| 同步(记录前对象) | 33d6ef69212595c680a744549986c19bb6acd6c3 | 1b286ec3e68260d9d25cb3ab651ede31143d5b06 | 2026-10-22T06:35:19Z | -- 2.54.0 From e8de6ba97bc0d272af561269a10be5ec246431df Mon Sep 17 00:00:00 2001 From: weichen Date: Thu, 22 Oct 2026 06:44:06 +0000 Subject: [PATCH 36/36] Take main's svc recover test with the shared free-port helper Why: the initiative branch's merge resolution kept a stale test_svc_recover.py that lost main's free_fixture_port helper while its callers (test_svc_superadmin_envfile) reference it, breaking the CI test job on every initiative-branch head. Evidence: main @33d6ef69 has the helper and a fully green CI (test/test-pg/svc-realcombo success); this branch's callers now match. Impact: Test helper alignment only; no production code. Refs: initiative PR #635; merge af2e6b41 --- tests/test_svc_recover.py | 46 +++++++++++++++------------------------ 1 file changed, 18 insertions(+), 28 deletions(-) diff --git a/tests/test_svc_recover.py b/tests/test_svc_recover.py index b02352f1..5030c83e 100644 --- a/tests/test_svc_recover.py +++ b/tests/test_svc_recover.py @@ -184,12 +184,17 @@ esac """ +def free_fixture_port(): + with socket.socket() as reservation: + reservation.bind(("127.0.0.1", 0)) + return reservation.getsockname()[1] + + class SvcAutoRecoverTests(unittest.TestCase): def setUp(self): tmp = tempfile.mkdtemp(prefix="svc-autorecover-") self.addCleanup(shutil.rmtree, tmp, True) self.root = Path(tmp) - self._allocated_ports = set() (self.root / "scripts").mkdir(parents=True) shutil.copy2(SVC_SCRIPT, self.root / "scripts" / "svc.sh") self.trace = self.root / "trace" @@ -249,21 +254,6 @@ class SvcAutoRecoverTests(unittest.TestCase): self.assertEqual(proc.returncode, 0, proc.stdout) return proc - def available_port(self): - """Allocate a distinct service port for this test, including address changes. - - The socket closes before svc.sh binds it, leaving a small allocation-to-start - race with unrelated processes. Keep allocated numbers distinct within the - test so stopped/restarted services never share another instance's port. - """ - while True: - with socket.socket() as sock: - sock.bind(("0.0.0.0", 0)) - port = sock.getsockname()[1] - if port not in self._allocated_ports: - self._allocated_ports.add(port) - return port - def runtime(self, name): return self.root / "runtime" / name @@ -346,14 +336,14 @@ class SvcAutoRecoverTests(unittest.TestCase): # ---- 1. 期望态:start 成功置位 / 显式 stop 清除(含进程已死的 stop)---- def test_start_records_autostart_and_stop_clears(self): - self.seed_agent("dev", self.available_port()) + self.seed_agent("dev", free_fixture_port()) self.start_ok("dev") self.assertEqual(self.kv("dev", "autostart"), "1") self.svc("dev", "stop") self.assertIsNone(self.kv("dev", "autostart")) def test_stop_on_dead_process_clears_autostart(self): - self.seed_agent("dev", self.available_port()) + self.seed_agent("dev", free_fixture_port()) self.start_ok("dev") self.kill9("dev") # 进程已死但 autostart 保留(等待 recover);显式 stop 表示"保持停止"。 @@ -364,7 +354,7 @@ class SvcAutoRecoverTests(unittest.TestCase): # ---- 2. recover:崩溃拉回 / 运行中不动 / 显式停止不复活 / 未启动不碰 ---- def test_recover_restarts_sigkilled_service(self): - port = self.available_port() + port = free_fixture_port() self.seed_agent("dev", port) self.start_ok("dev") old_pid = self.kill9("dev") @@ -381,7 +371,7 @@ class SvcAutoRecoverTests(unittest.TestCase): self.assertIn("--addr 127.0.0.1:%d" % port, self.kv("dev", "exec")) def test_recover_noop_while_running(self): - self.seed_agent("dev", self.available_port()) + self.seed_agent("dev", free_fixture_port()) self.start_ok("dev") pid = self.pid_of("dev") result = self.svc("recover") @@ -390,7 +380,7 @@ class SvcAutoRecoverTests(unittest.TestCase): self.assertEqual(self.history_events("dev", "recover"), []) def test_recover_respects_explicit_stop(self): - self.seed_agent("dev", self.available_port()) + self.seed_agent("dev", free_fixture_port()) self.start_ok("dev") self.svc("dev", "stop") result = self.svc("recover") @@ -399,7 +389,7 @@ class SvcAutoRecoverTests(unittest.TestCase): self.assertEqual(self.history_events("dev", "recover"), []) def test_recover_ignores_never_started_service(self): - self.seed_agent("dev", self.available_port()) # 从未 start:无 autostart 键 + self.seed_agent("dev", free_fixture_port()) # 从未 start:无 autostart 键 result = self.svc("recover") self.assertEqual(result.returncode, 0, result.stdout) self.assertFalse(self.pid_alive(self.pid_of("dev"))) @@ -408,7 +398,7 @@ class SvcAutoRecoverTests(unittest.TestCase): # ---- 3. 并发防护:生命周期锁被持有时 recover 跳过 ---- def test_recover_skips_when_lock_held(self): - self.seed_agent("dev", self.available_port()) + self.seed_agent("dev", free_fixture_port()) self.start_ok("dev") self.kill9("dev") lock = self.runtime("dev") / ".start.lock" @@ -428,7 +418,7 @@ class SvcAutoRecoverTests(unittest.TestCase): # ---- 4. 恢复失败路径:端口被外部进程占用 → fail 事件 + 非零退出 ---- def test_recover_fails_when_port_stolen(self): - port = self.available_port() + port = free_fixture_port() self.seed_agent("dev", port) self.start_ok("dev") self.kill9("dev") @@ -453,7 +443,7 @@ class SvcAutoRecoverTests(unittest.TestCase): if bound: break time.sleep(0.05) - self.assertTrue(bound, f"thief 未能在 5s 内监听 {port}") + self.assertTrue(bound, "thief 未能在 5s 内监听 18808") try: result = self.svc("recover", check=False) self.assertEqual(result.returncode, 1, result.stdout) @@ -497,7 +487,7 @@ class SvcAutoRecoverTests(unittest.TestCase): """模拟 update 误清 pidfile 后本 bin 仍占口:裸 start 应回收并拉起新进程。""" if not self._ss_can_attribute_pid(): self.skipTest("ss -ltnp 无法归因 PID(reclaim_own_port 需此能力)") - port = self.available_port() + port = free_fixture_port() self.seed_agent("dev", port) self.start_ok("dev") old = self.pid_of("dev") @@ -518,7 +508,7 @@ class SvcAutoRecoverTests(unittest.TestCase): def test_start_rejects_foreign_port_occupant(self): """外部 python http.server 占口:start 必须失败并提示非本服务。""" - port = self.available_port() + port = free_fixture_port() self.seed_agent("dev", port) thief = subprocess.Popen( ["python3", "-m", "http.server", str(port), "--bind", "127.0.0.1"], @@ -555,7 +545,7 @@ class SvcAutoRecoverTests(unittest.TestCase): self.assertFalse((unit_dir / "agent-system-svc-recover.service").exists()) def test_recover_reserved_name_rejected(self): - self.seed_agent("recover", self.available_port()) # 保留字不可作服务名 + self.seed_agent("recover", free_fixture_port()) # 保留字不可作服务名 result = self.svc("recover", "recover", check=False) self.assertEqual(result.returncode, 2, result.stdout) -- 2.54.0