diff --git a/.task/fix-svc-test-port-governance-final.md b/.task/fix-svc-test-port-governance-final.md new file mode 100644 index 00000000..c8935b71 --- /dev/null +++ b/.task/fix-svc-test-port-governance-final.md @@ -0,0 +1,92 @@ +# fix/svc-test-port-governance-final 任务卡 + +任务主记录:;状态:进行中;owner:weichen + +- 权威仓:ssh://git@192.168.3.2:2222/weichen/Agent-System-Dev.git;目标分支:main;R0(initial_base_sha)= 955a32de2bb49171348bad5f566cce935df19212 +- 工作区:/home/weichen/projects/Agent-System-Dev-wt-fix-svc-test-port-governance-final(worktree);分支:fix/svc-test-port-governance-final +- 分支类型:standalone;root_target:main;immediate_target:main;accepting_requirements:false +- 需求分流:verdict=NEW;selected_initiative=无;requirement_sha256=04cbe9df900a03163aeadb42fd22e5a86ddeced179901b50ac0f4642ce7f6881;triage_receipt=/tmp/pg3-triage.json;receipt_sha256=aca390790027841efaefe2082123780b1ec8d775f9ca0be80262a80f7121bde9 + +- 授权与交付终点:<本次允许的动作与终点;未授权事项写明> +- 交付模式: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 | +|---|---|---|---| +| 启动 | 955a32de2bb49171348bad5f566cce935df19212 | 955a32de2bb49171348bad5f566cce935df19212 | 2026-10-22T08:55:33Z | + +## 证据(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-22T08:54:47.013779+00:00", + "command": "make precheck", + "exit_code": 0, + "cwd": "/home/weichen/projects/Agent-System-Dev", + "before_head": "955a32de2bb49171348bad5f566cce935df19212", + "after_head": "955a32de2bb49171348bad5f566cce935df19212", + "branch": "main", + "target_branch": "main", + "target_head": "955a32de2bb49171348bad5f566cce935df19212", + "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=955a32de2b", + "[remote] origin/main=955a32de2b ahead=0 behind=0", + "[tree] clean submodules_drift=0 uninit=0", + "[worktrees] linked=5", + "[recycle] merged un-recycled branches: feature/container-storage-plan", + "[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] 955a32de2b(完整:955a32de2bb49171348bad5f566cce935df19212)", + "[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": "b63c0d5c11be0292024cc972eee78fbcef7349381ee3bdecb432815b903373e6", + "receipt_sha256": "3ee914c56ff0e9cf2a4d11db1ec0a2e6c74cf745cceb7eff1cefd2f9d938ee89", + "receipt_path": "/home/weichen/.cache/agent-system-dev/evidence/3ee914c56ff0e9cf2a4d11db1ec0a2e6c74cf745cceb7eff1cefd2f9d938ee89.json" +} +``` diff --git a/tests/test_svc.py b/tests/test_svc.py index da2e34df..e11433fe 100644 --- a/tests/test_svc.py +++ b/tests/test_svc.py @@ -296,12 +296,14 @@ class SvcDbRecoveryTests(unittest.TestCase): # ---- 1. 存量 exec= DSN:连续启动两次均恢复,进程参数无秘密 ---- def test_legacy_exec_dsn_survives_consecutive_restarts(self): - self.register_pg("pg1", 18890, password="legacy-pw-1") - dsn = "postgresql://agent:legacy-pw-1@127.0.0.1:18890/agent" + pg_port = free_test_port() + self.register_pg("pg1", pg_port, password="legacy-pw-1") + dsn = "postgresql://agent:legacy-pw-1@127.0.0.1:%d/agent" % pg_port d = self.runtime("dev") - self.seed_agent("dev", 18791, - "--addr 127.0.0.1:18791 --data %s --plugins %s --auth auto --dsn %s" - % (d / "data", d / "plugins", dsn)) + port = free_test_port() + self.seed_agent("dev", port, + "--addr 127.0.0.1:%d --data %s --plugins %s --auth auto --dsn %s" + % (port, d / "data", d / "plugins", dsn)) for _ in range(2): self.clear_serve_record() self.svc("dev", "restart") @@ -322,12 +324,14 @@ class SvcDbRecoveryTests(unittest.TestCase): # ---- 2. 仅 dbref:裸 restart 与重新部署均保留绑定 ---- def test_dbref_binding_survives_bare_restart_and_redeploy(self): - self.register_pg("pg1", 18891, password="bind-pw-2") - dsn = "postgresql://agent:bind-pw-2@127.0.0.1:18891/agent" + pg_port = free_test_port() + self.register_pg("pg1", pg_port, password="bind-pw-2") + dsn = "postgresql://agent:bind-pw-2@127.0.0.1:%d/agent" % pg_port d = self.runtime("dev") - self.seed_agent("dev", 18792, - "--addr 127.0.0.1:18792 --data %s --plugins %s --auth auto" - % (d / "data", d / "plugins"), + port = free_test_port() + self.seed_agent("dev", port, + "--addr 127.0.0.1:%d --data %s --plugins %s --auth auto" + % (port, d / "data", d / "plugins"), extra_rows=[("dbref", "pg1/agent"), ("db", "pg")]) self.clear_serve_record() self.svc("dev", "restart") @@ -413,9 +417,10 @@ class SvcDbRecoveryTests(unittest.TestCase): def test_refusals_keep_registration_without_sqlite_fallback(self): d = self.runtime("a1") - self.seed_agent("a1", 18796, - "--addr 127.0.0.1:18796 --data %s --plugins %s --auth auto" - % (d / "data", d / "plugins"), + port = free_test_port() + self.seed_agent("a1", port, + "--addr 127.0.0.1:%d --data %s --plugins %s --auth auto" + % (port, d / "data", d / "plugins"), extra_rows=[("dbref", "pgmissing/agent"), ("db", "pg")]) self.clear_serve_record() result = self.svc("a1", "restart", check=False) @@ -425,33 +430,41 @@ class SvcDbRecoveryTests(unittest.TestCase): self.assertEqual(self.kv("a1", "dbref"), "pgmissing/agent") # 可恢复配置保留 # 实例登记不全(缺 password)→ 拒启。 - self.register_pg("pginc", 18895, complete=False) + self.register_pg("pginc", free_test_port(), complete=False) d = self.runtime("a2") - self.seed_agent("a2", 18797, - "--addr 127.0.0.1:18797 --data %s --plugins %s --auth auto" - % (d / "data", d / "plugins"), + port = free_test_port() + self.seed_agent("a2", port, + "--addr 127.0.0.1:%d --data %s --plugins %s --auth auto" + % (port, d / "data", d / "plugins"), extra_rows=[("dbref", "pginc/agent"), ("db", "pg")]) result = self.svc("a2", "restart", check=False) self.assertNotEqual(result.returncode, 0) self.assertIn("拒绝", result.stdout) # dbref 与 dsn= 指向不同库 → 配置冲突拒启。 - self.register_pg("pg1", 18896, password="clash-pw") + pg_port = free_test_port() + self.register_pg("pg1", pg_port, password="clash-pw") + other_pg_port = free_test_port() + while other_pg_port == pg_port: + other_pg_port = free_test_port() d = self.runtime("a3") - self.seed_agent("a3", 18798, - "--addr 127.0.0.1:18798 --data %s --plugins %s --auth auto" - % (d / "data", d / "plugins"), + port = free_test_port() + self.seed_agent("a3", port, + "--addr 127.0.0.1:%d --data %s --plugins %s --auth auto" + % (port, d / "data", d / "plugins"), extra_rows=[("dbref", "pg1/agent"), ("db", "pg"), - ("dsn", "postgresql://u:p@127.0.0.1:18999/otherdb")]) + ("dsn", "postgresql://u:p@127.0.0.1:%d/otherdb" + % other_pg_port)]) result = self.svc("a3", "restart", check=False) self.assertNotEqual(result.returncode, 0) self.assertIn("拒绝", result.stdout) # db=pg 但无可恢复 DSN → 拒启。 d = self.runtime("a4") - self.seed_agent("a4", 18799, - "--addr 127.0.0.1:18799 --data %s --plugins %s --auth auto" - % (d / "data", d / "plugins"), + port = free_test_port() + self.seed_agent("a4", port, + "--addr 127.0.0.1:%d --data %s --plugins %s --auth auto" + % (port, d / "data", d / "plugins"), extra_rows=[("db", "pg")]) result = self.svc("a4", "restart", check=False) self.assertNotEqual(result.returncode, 0)