From f6184ed1945f4e69b421b7a693822631cef4a282 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 9 Sep 2026 03:10:39 +0000 Subject: [PATCH] docs(agents): name the shared container's one heavy-verify lock MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit objectui agents already serialise heavy verification through scripts/pm/os-verify-lock.sh in the sibling objectstack checkout — three worktrees were measured reaching for it by absolute path at the same time — but nothing in this repository's own documentation names the path, so every agent rediscovers it. Adds one bullet to the multi-agent working-discipline section, beside the existing rules about shared state that worktree isolation does not cover (the stash stack, the four per-worktree ref namespaces, the shared scratchpad). It gives the absolute path, when to reach for it, and why this repository must NOT grow a copy of the script: the serialised resource is the container, which both repositories share, so a per-repo lock would let one objectui agent and one objectstack agent run heavy suites simultaneously while each believed it held the lock. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01HxLw5aKDPR5RJgyUR7Exkd --- AGENTS.md | 1 + 1 file changed, 1 insertion(+) diff --git a/AGENTS.md b/AGENTS.md index 797b680757..57921a442d 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -286,6 +286,7 @@ AGENTS.md 的「只跑受影响的包」指的是**用上面的路径过滤缩 2. **次选纪律:确实需要临时文件时,文件名一律带卡号/分支号前缀**(该目录里既有的 `3309-pr.md` 就是这个惯例),**且用完即删**;写完要用之前先读回一遍,确认拿到的还是自己那份。 两条不是并列的两个建议:前缀与删除要求每个作者每一次都记得,记性会衰减,而衰减是静默的(见上:撞车不报错);`git commit -F -` 那种形式让撞车**不可能发生**,不依赖任何人的记性。所以能用形式解决的,就别退回到纪律。这一族目前**没有钩子**兜底(上面 worktree 与 stash 两条各有一个 PreToolUse 钩子),因此这条规则的全部效力就在于你选哪种形式。 +- **重验证先经那把锁 —— 它住在兄弟检出 `../objectstack` 里,本仓没有这个脚本。** 任何**重验证**(全量 `vitest run`、计时测量、整仓 build 或整套 suite)开跑之前先经 `/home/user/objectstack/scripts/pm/os-verify-lock.sh` 串行化,写法 `bash /home/user/objectstack/scripts/pm/os-verify-lock.sh -c '<命令>'`。⛔ **绝不在本仓复制一份**:被序列化的资源是**容器**,本仓和 `../objectstack` 共用同一个 —— 两份 per-repo 的锁只会让一个 objectui agent 和一个 objectstack agent **同时**跑重套件、而各自都以为自己持有锁,比不加锁更糟。⚠️ 而这把锁**只排除其他已加锁的运行**:`--status` 打印的持有者和队列里只有**走了这个入口**的那些运行,**空队列不等于空箱** —— 一个没加锁就跑 `turbo build` 的 agent 对它完全不可见,却照样落进你的计时测量里。 - **一个任务一个 feature 分支 + 一个 PR**;**绝不**把任务改动直接提交到 `main`。 - **绝不 `git push --force`/`--force-with-lease`,绝不推 `main`**(会覆盖并行 agent 的工作;`main` 共享,一律走 PR)。**禁令不按「这条分支是不是只有我一个人用」分档**:那个判断评估错的时候没有任何症状,而错掉的代价正是本节要防的那类静默丢工作 —— 所以它一律绝对,单人 feature 分支同样不例外。**要把自己的分支同步到当前 `main`,合规路线是 merge,不是 rebase**:`git fetch origin && git merge origin/main`,解完冲突照常 push。代价只是一个 merge commit —— 本仓 PR 一律 `--squash` 入队合并,它不会留到 `main` 上;换来的是任何一次 push 都不重写已经推上去的历史。**「要同步分支」从来不是 force-push 的理由**,别用 `git rebase origin/main` + `--force-with-lease` 去「把历史弄干净」。(入队合并本身并不要求你同步 —— 队列会在当前 `main` 上重建,见下面「不必为了合并去 rebase 其他在途分支」那条;主动同步的价值在于提前撞出别人刚落地的破坏。) - **能 push 分支,却删不掉远端 ref —— 而且失败之后 git 打印的是一张成功回执。** 实测(objectui#6756,同一会话里两个 agent 独立撞到、签名相同):任何删除 ref 的 push 都被 agent proxy 以 `error: RPC failed; HTTP 403` 拒绝,且没有旁路 —— GitHub MCP 工具面只有 `create_branch`、**没有对应的 delete**,容器内也没有 `gh` CLI。⚠️ 要命的是紧接其后的最后一行:`Everything up-to-date` —— 只看输出尾部、或把「最后一行非空」当成功的调用方,会把**被拒绝的删除读成已完成的删除**。⇒ 代价不是「不整洁」,而是**认领信号被污染**:同一张卡改名重开留下的孤儿分支,在席位平时读的任何界面上都看不见(不在卡上、不在 PR 列表、不在任何队列视图),只有按卡号做前缀 glob 才现形 —— `git ls-remote --heads origin 'refs/heads/claude/issue--*'`;实测一次险些被读成「另一个席位在并行做同一张卡」,而那正是认领纪律要防的唯一一件事。**以下四点未测,别当结论用**:403 出自代理策略 / token scope / 分支保护中的哪一层、其他席位或环境是否删得掉、tag 是否同样受限、仓内还有多少陈旧 `claude/*` 分支。⛔ 本条只记录能力缺口,**不**授权任何分支清理、普查或生命周期策略 —— 那是维护者的决定。