@nelsonlongxiang/dsh-open-a2a-net 0.6.28 → 0.6.30

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. package/README.md +87 -14
  2. package/README_zh.md +83 -7
  3. package/assets/nexusDist/assets/index-C_x3iAth.js +9 -0
  4. package/assets/nexusDist/assets/index-Dz8N80tI.css +1 -0
  5. package/assets/nexusDist/index.html +2 -2
  6. package/cli/a2a.mjs +0 -0
  7. package/cordis.patch.yml +21 -21
  8. package/lib/canvas-store.js +21 -1
  9. package/lib/client.js +64 -64
  10. package/lib/client.js.map +1 -1
  11. package/lib/faces/admin.js +755 -0
  12. package/lib/faces/canvas-notify.js +138 -0
  13. package/lib/faces/wire.js +669 -0
  14. package/lib/flood-guard.js +106 -0
  15. package/lib/index.js +200 -1392
  16. package/lib/recursion-guard.js +78 -0
  17. package/lib/runtime.js +1 -0
  18. package/lib/skill/SKILL.md +35 -9
  19. package/lib/skill/references/cli.md +24 -7
  20. package/lib/skill/references/collaboration.md +355 -0
  21. package/lib/skill/references/discovery.md +5 -2
  22. package/lib/skill/references/pitfalls.md +2 -1
  23. package/lib/skill/references/routing.md +18 -8
  24. package/lib/skill/references/setup.md +152 -0
  25. package/lib/task-ledger.js +40 -4
  26. package/lib/types/canvas-store.d.ts +10 -1
  27. package/lib/types/faces/admin.d.ts +133 -0
  28. package/lib/types/faces/canvas-notify.d.ts +74 -0
  29. package/lib/types/faces/wire.d.ts +171 -0
  30. package/lib/types/flood-guard.d.ts +29 -0
  31. package/lib/types/index.d.ts +11 -3
  32. package/lib/types/recursion-guard.d.ts +56 -0
  33. package/lib/types/runtime.d.ts +35 -0
  34. package/lib/types/task-ledger.d.ts +15 -1
  35. package/nexus-stage/package-lock.json +2262 -2262
  36. package/nexus-stage/src/canvas-ops.ts +175 -175
  37. package/nexus-stage/src/canvas-wire.ts +156 -156
  38. package/nexus-stage/src/edges.ts +72 -72
  39. package/nexus-stage/src/federation-overlay.ts +103 -103
  40. package/nexus-stage/src/federation.ts +240 -240
  41. package/nexus-stage/src/layout-doc.ts +143 -143
  42. package/nexus-stage/src/layout-wire.ts +158 -158
  43. package/nexus-stage/src/main.ts +5 -1
  44. package/nexus-stage/src/planning-card-text.ts +73 -0
  45. package/nexus-stage/src/planning-edges.ts +26 -0
  46. package/nexus-stage/src/planning-fit.ts +45 -0
  47. package/nexus-stage/src/planning-legend.ts +38 -0
  48. package/nexus-stage/src/planning-mirror.ts +31 -0
  49. package/nexus-stage/src/planning-overlap.ts +159 -0
  50. package/nexus-stage/src/planning-relayout.ts +121 -0
  51. package/nexus-stage/src/planning-search.ts +168 -0
  52. package/nexus-stage/src/planning-types.ts +1 -0
  53. package/nexus-stage/src/planning-undo.ts +68 -0
  54. package/nexus-stage/src/planning-view.ts +120 -121
  55. package/nexus-stage/src/planning.css +41 -8
  56. package/nexus-stage/src/seat.ts +35 -35
  57. package/nexus-stage/src/stage-name.ts +13 -13
  58. package/nexus-stage/src/tokens.ts +31 -31
  59. package/nexus-stage/src/viewport.ts +24 -1
  60. package/nexus-stage/src/wb-chat.ts +20 -6
  61. package/nexus-stage/src/wb-ledger.ts +20 -7
  62. package/nexus-stage/src/wb-names.ts +43 -0
  63. package/nexus-stage/src/workbench.css +8 -2
  64. package/nexus-stage/src/workbench.ts +55 -17
  65. package/nexus-stage/src/world.ts +13 -21
  66. package/package.json +216 -214
  67. package/assets/nexusDist/assets/index-1niOBYxp.js +0 -5
  68. package/assets/nexusDist/assets/index-uQf7NwjF.css +0 -1
  69. package/nexus-stage/scripts/__pycache__/mockhost.cpython-312.pyc +0 -0
@@ -0,0 +1,78 @@
1
+ /**
2
+ * Recursion guard (#60, first step: the hop budget) per
3
+ * docs/protocol/recursion-guard.md. State rides the payload: the origin
4
+ * mints the envelope with a full budget, every forwarded leg decrements,
5
+ * and a zero-budget arrival is refused with a STRUCTURED budget-exhausted
6
+ * error — silent swallowing is forbidden. The visited set (protocol §4.3)
7
+ * is the SECOND step and is deliberately absent here.
8
+ *
9
+ * Wire form: the X-A2A-Guard header carries a base64 JSON payload
10
+ * { visitToken, hopBudget, deadlineAt? }. An ABSENT header means a
11
+ * non-forwarding origin: the receiver grants the default one-shot budget
12
+ * and records guardMode 'default' (protocol §6 — old peers are
13
+ * constrained, not broken). Parse cost is O(1) for the budget path.
14
+ * @module @nelsonlongxiang/dsh-open-a2a-net/recursion-guard
15
+ */
16
+ export const DEFAULT_HOP_BUDGET = 4;
17
+ /** Wire code for a zero-budget arrival (cluster-C registry, after -32006). */
18
+ export const WIRE_ERROR_BUDGET_EXHAUSTED = -32007;
19
+ /**
20
+ * Ingress check: parse the header, validate the budget, fail closed. A
21
+ * malformed payload falls back to the default budget (a guard that cannot
22
+ * be evaluated must not reject honest first-hop traffic; the budget bound
23
+ * still applies). hopBudget <= 0 on arrival ⇒ budget-exhausted.
24
+ */
25
+ export function checkGuardAtIngress(header) {
26
+ if (header === undefined || header === '') {
27
+ return { kind: 'ok', guard: { visitToken: '', hopBudget: DEFAULT_HOP_BUDGET }, mode: 'default' };
28
+ }
29
+ let parsed;
30
+ try {
31
+ parsed = JSON.parse(Buffer.from(header, 'base64').toString('utf8'));
32
+ }
33
+ catch {
34
+ return { kind: 'ok', guard: { visitToken: '', hopBudget: DEFAULT_HOP_BUDGET }, mode: 'default' };
35
+ }
36
+ const hopBudget = parsed?.hopBudget;
37
+ if (typeof hopBudget !== 'number' || !Number.isInteger(hopBudget)) {
38
+ return { kind: 'ok', guard: { visitToken: '', hopBudget: DEFAULT_HOP_BUDGET }, mode: 'default' };
39
+ }
40
+ if (hopBudget <= 0)
41
+ return { kind: 'budget-exhausted' };
42
+ const visitToken = typeof parsed.visitToken === 'string'
43
+ ? String(parsed.visitToken)
44
+ : '';
45
+ const deadlineRaw = parsed.deadlineAt;
46
+ return {
47
+ kind: 'ok',
48
+ guard: { visitToken, hopBudget, ...(typeof deadlineRaw === 'number' ? { deadlineAt: deadlineRaw } : {}) },
49
+ mode: 'explicit',
50
+ };
51
+ }
52
+ /** Mint the outbound guard for a first-hop dispatch (full budget at origin). */
53
+ export function mintGuard() {
54
+ return {
55
+ visitToken: Array.from({ length: 16 }, () => Math.floor(Math.random() * 16).toString(16)).join(''),
56
+ hopBudget: DEFAULT_HOP_BUDGET,
57
+ };
58
+ }
59
+ /** Serialize for the X-A2A-Guard header. */
60
+ export function guardHeader(guard) {
61
+ return Buffer.from(JSON.stringify(guard), 'utf8').toString('base64');
62
+ }
63
+ /**
64
+ * The ingress refusal path (gh#60): budget-exhausted answers the structured
65
+ * error, records the receiptless ledger row, and reports true (the caller
66
+ * returns). The whole response lives here so the ingress seam stays ONE
67
+ * line (the index.ts ratchet pays-as-it-goes: no net line growth).
68
+ */
69
+ export function refuseIfBudgetExhausted(req, res, team, caller, taskId, ledger) {
70
+ const verdict = checkGuardAtIngress(req.headers['x-a2a-guard']);
71
+ if (verdict.kind !== 'budget-exhausted')
72
+ return false;
73
+ ledger.trackReceiptless(taskId, team, caller === '' ? 'unknown' : caller, undefined, 'budget-exhausted at ingress (hopBudget=0)');
74
+ const payload = JSON.stringify({ error: 'budget-exhausted: the hop budget is spent (recursion-guard #60) — this delivery traversed its full forwarding allowance and is refused at ingress', code: WIRE_ERROR_BUDGET_EXHAUSTED, team, task_status: 'TASK_STATE_FAILED' });
75
+ res.writeHead(200, { 'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(payload) });
76
+ res.end(payload);
77
+ return true;
78
+ }
package/lib/runtime.js ADDED
@@ -0,0 +1 @@
1
+ export {};
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: a2a-network
3
- description: Use when a task needs cross-session or cross-node collaboration over the DSH A2A network — joining and teaming, routing work to remote teams and agents, reconciling receipts and the task ledger, and reading the A2A workbench (/__dsh_a2a_nexus/). Covers admission rules, the receipt contract, and the failure shapes that look like bugs but are contract semantics.
3
+ description: Use when a task needs cross-session or cross-node collaboration over the DSH A2A network — setting it up (install, config, apiKey, peers, canvas links for one host, two peers, or hosts that cannot reach each other), joining and teaming, routing work to remote teams and agents, reconciling receipts and the task ledger, and reading the A2A workbench (/__dsh_a2a_nexus/). Covers admission rules, the receipt contract, and the failure shapes that look like bugs but are contract semantics.
4
4
  ---
5
5
 
6
6
  # DSH A2A Network
@@ -27,6 +27,20 @@ surface on every node.
27
27
  deposited on ONE home host for up to 4h, with a mailbox instead of a
28
28
  wakeable session. See [cli.md](references/cli.md).
29
29
 
30
+ ## Setting up
31
+
32
+ Start with [setup.md](references/setup.md). It is a checked path for three
33
+ network shapes:
34
+ - **one host**: install, join the sessions, give them a shared team;
35
+ - **two hosts that reach each other**: one shared `apiKey`, `announce` plus
36
+ peers seeded both ways, and a canvas team naming both handles;
37
+ - **hosts that cannot reach each other**: host forwarding is not shipped
38
+ yet (#57), so tunnel or delegate per hop.
39
+
40
+ The owner does the gestures (install, config, join, allowlist, canvas). The
41
+ agent prepares the exact config and verifies each step with `a2a_whoami`,
42
+ `a2a_probe`, `a2a_teams` and one round with a receipt.
43
+
30
44
  ## Routing (a2a_route)
31
45
 
32
46
  ```text
@@ -36,10 +50,15 @@ a2a_route { team: "<zone>/<id8 or canvas name>", message, context_id?, async? }
36
50
  - `async: true` delivers without waiting (`delivered:true` + task id); the
37
51
  target routes a receipt — a message starting `[A2A receipt] task <id>` —
38
52
  back to your team.
39
- - Sync (default) waits for the round's final answer. If the 15s transport
40
- budget fires first, the result is **-32005 DELIVERED-UNSETTLED**: the
41
- delivery landed and the peer keeps executing. **Never re-dispatch blindly**
42
- — reconcile via the task id (the receipt or `a2a_teams` coordinates) instead.
53
+ - Sync (default) waits for the round's final answer. A target on this host
54
+ gets up to 180s; past that the tool answers the delivered shape
55
+ (`TASK_STATE_DELIVERED`) and the receipt contract carries the rest. A
56
+ remote peer's delivery rides a 15s transport budget; if it fires first, the
57
+ result is **-32005 DELIVERED-UNSETTLED**: the delivery landed and the peer
58
+ keeps executing. Either way, **never re-dispatch blindly** — reconcile via
59
+ the task id (the receipt, `a2a_status` activity, or `a2a_tasks`) instead.
60
+ - Model tools cannot route to the bare process team (`<zone>` alone, the
61
+ host's own mailbox): target a session handle or a canvas team.
43
62
  - `context_id` from a previous reply continues that conversation.
44
63
 
45
64
  ## Membership rules
@@ -55,10 +74,15 @@ a2a_route { team: "<zone>/<id8 or canvas name>", message, context_id?, async? }
55
74
 
56
75
  ## Reading the state
57
76
 
58
- `__dsh_a2a/state` (per node) carries `sessions` (live/joined), `sessionTeams`,
59
- `remote` (peer session rows with `origin` = node label + LAN IP and `via` =
60
- the peer URL), `activity` (routing ring), `tasks` (the ledger: pending /
61
- stale / archived). The A2A workbench (`/__dsh_a2a_nexus/`, merged responsive
77
+ `__dsh_a2a/state` (per node, key-gated like every control route) carries
78
+ `sessions` (live/joined, with their teams), `canvas` (canvas teams; remote
79
+ members show `remote: true`), `remote` (peer session rows with `origin` =
80
+ node label + LAN IP and `via` = the peer URL), `activity` (routing ring),
81
+ and the ledger: `tasks` (pending, each with `settleable`),
82
+ `tasksStaleCount`, `tasksDead`, and `archived` (newest 64 settled rows, each
83
+ with `outcome`, `endedBy` and `late`) plus `archivedCount` /
84
+ `archivedSplit`. `sessionTeams` is a card field, not a state field. The A2A
85
+ workbench (`/__dsh_a2a_nexus/`, merged responsive
62
86
  shell since 0.6.2 — the 2D planning board is the stage, directory / ledger /
63
87
  activity / plan ride a collapsible rail, narrow screens get a drawer)
64
88
  renders the same data for humans.
@@ -82,8 +106,10 @@ renders the same data for humans.
82
106
 
83
107
  ## Details
84
108
 
109
+ - [setup.md](references/setup.md) — setup and checks: one host, two peers, beyond direct peers
85
110
  - [routing.md](references/routing.md) — receipts, idempotency, ledger anatomy
86
111
  - [discovery.md](references/discovery.md) — cards, peer boundary model, invisibility
87
112
  - [membership.md](references/membership.md) — join/leave, allowlist, canvas teams
88
113
  - [pitfalls.md](references/pitfalls.md) — operational pitfalls observed in production
89
114
  - [cli.md](references/cli.md) — the `a2a-net` CLI: deposit, mailbox, inbox hooks, limits
115
+ - [collaboration.md](references/collaboration.md) — collaboration norm (Chinese): single-seat first, decide-then-report, release tiers, stuck gates, credentials, receipts
@@ -24,7 +24,10 @@ ten model tools.
24
24
 
25
25
  - `a2a-net publish` deposits the signed CLI card on the home host
26
26
  (`/__dsh_a2a/cli-deposit`, a control route: key-gated like every write).
27
- The deposit lives at most 4h, then deregisters; publish again to return.
27
+ The deposit lives at most 4h. An expired deposit is no longer routable and
28
+ its card is no longer served, but it stays in the host's directory as an
29
+ OFFLINE row (gh#47; the newest 16 are kept) so canvas refs to it never
30
+ dangle silently. Publish again (same handle, same key) to come back.
28
31
  - While deposited, the host serves the card at
29
32
  `<home>/a2a/cli/<handle>/.well-known/agent-card.json` and lists the handle
30
33
  in its directory as "cli — deposited identity (no wake; mailbox)".
@@ -36,8 +39,14 @@ ten model tools.
36
39
 
37
40
  ## Sending
38
41
 
39
- - `a2a-net route <team> <message…>` delivers an async round with a signed
40
- OriginClaim envelope to the HOME host's `/a2a/direct`.
42
+ - `a2a-net route <team> <message…>` delivers a round with a signed
43
+ OriginClaim envelope to the HOME host's `/a2a/direct`. It is async by
44
+ default: the receipt comes back to `a2a-net inbox`.
45
+ - `--sync` waits for the target's reply and prints it:
46
+ `reply from <team> · task <id> · context <ctx>` followed by the reply text.
47
+ When the round has not settled (status other than completed) a warning
48
+ goes to stderr: reconcile by task id before re-sending.
49
+ - `--context ID` continues that conversation (sends it as `context_id`).
41
50
  - Direct delivery does not relay: only teams on the home host are reachable.
42
51
  A team on another host answers "No live DSH session node accepts team".
43
52
  - Admission: a deposited handle is a node fact of its home host (N3). It
@@ -45,8 +54,8 @@ ten model tools.
45
54
  - `a2a-net report <message…>` is a one-way report to the host's process team.
46
55
  - A message that starts with `-` goes after `--`. Flag values never become
47
56
  part of the message.
48
- - Output is one line (`delivered → <team> · task <id> · <receipt>`); `--json`
49
- prints the raw reply.
57
+ - Async output is one line (`delivered → <team> · task <id> · <receipt>`);
58
+ `--json` prints the raw reply.
50
59
 
51
60
  ## Receiving: the mailbox
52
61
 
@@ -71,8 +80,16 @@ ten model tools.
71
80
  ## Reading the host
72
81
 
73
82
  `whoami`, `teams [query]`, `status`, `tasks`, `probe` read the home host's
74
- state face (key-gated on a keyed host). `teams`, `tasks` and `probe` take
75
- `--json`.
83
+ state face (key-gated on a keyed host). `--json` prints raw rows for
84
+ `teams`, `tasks`, `probe`, `route`, `report`, `inbox` and `skills`.
85
+
86
+ ## Local commands
87
+
88
+ - `a2a-net skills [name] [--root DIR] [--json]` lists the skills under the
89
+ local skill directory (default `~/.agents/skills`), or prints one by name.
90
+ It has no model-tool counterpart.
91
+ - `a2a-net tools` prints the CLI ↔ model-tool alignment table; `help` the
92
+ usage.
76
93
 
77
94
  ## Exit codes
78
95
 
@@ -0,0 +1,355 @@
1
+ # A2A 协作规范
2
+
3
+ > 版本 v1.13,2026-10-30。本文自成一体:各节点照本文执行,不需要、也不引用任何只在某台机器上才有的文件或工件。A2A 协作的规则以本文为准;更新时整份替换旧版。修订记录见文末。
4
+
5
+ **一句话:自己能做完的就自己做完;要别人做的,一次说清、异步发出,然后接着干别的。**
6
+
7
+ **限制只认三处:第 4 节先授权的五类、项目写明的红线、派活方给的完成标准。坐席不自己加门禁,也不自己抬高完成标准。能拍板的人明确说了“做”,就做。**
8
+
9
+ ## 1. 职责不是坐席
10
+
11
+ - 开发、评审、监督、运维是四种职责。小项目一个坐席担全部。
12
+ - 只有两种情况才拆出独立坐席:要并行,或要独立评审(见第 7 节高档)。
13
+ - 总工只裁跨项目接口和资源冲突,不重开项目内已经放行的事;发现问题开修复单交回项目。
14
+ - 监督被叫到才介入(冲突、阻塞、跨项目)。巡查只读、出看板,不派单、不催办。
15
+
16
+ ## 2. 什么时候发 A2A
17
+
18
+ 只有两种理由可以转派,消息里必须写明是哪一种:
19
+
20
+ | 理由 | 例子 |
21
+ |---|---|
22
+ | 需独立评审 | 属于第 7 节的高档,且要交给已有的评审方;也可以自己起干净复核,那不算转派 |
23
+ | 并行拆段 | 拆开后各段互不依赖、不改同一批文件 |
24
+
25
+ - 不在这两种里的,自己做。“那是别的仓库”不是转派理由,见下一节。
26
+ - 收到没写理由的转派,可以直接退回,不算失职。
27
+ - 接手的一段自己从头做完,不再转手。
28
+
29
+ ## 3. 写权限放开
30
+
31
+ - 做事的坐席可以直接改任务涉及的任何仓库和宿主,不必转给负责那个仓库的坐席。
32
+ - 改别的仓库时按那个仓库自己的规矩来:它要求分支加 PR,就开分支、提 PR;它允许直改,就直改。
33
+ - 只提交自己改的文件,提交前复核暂存内容;不收编、不暂存、不回退别人在途的改动。
34
+ - 先看一眼目标仓库的在途改动(`git status`、开着的分支和 PR):别人正在改同一批文件,就另开分支,或先和对方说一声,不在同一份文件上并行改。
35
+ - 推分支、提 PR 到项目自己的远端,是正常写入,不算外发。
36
+ - 例外只有两种:属主宣布冻结的仓库(例如 D1 冻结的 ai-native-expert-agents)不写;凭证和密钥不在写权限之内,归第 4 节的“身份、授权与资金”。
37
+
38
+ **不用 git worktree。**
39
+ - 不建、也不进 git worktree:不用 `git worktree add`,不用 agent 的“进入 worktree”功能,新建坐席时不选“在 worktree 里工作”。
40
+ - 改动直接在仓库的主检出里做。低档直接提交;要 PR 的,在主检出里开分支、提交、推送、提 PR,合并后切回主分支,删掉分支。
41
+ - 同一个仓库有几个坐席同时写:先按文件分开,在同一条分支上各提交各的,只提交自己改的文件、提交前复核暂存。不切换别人正在用的分支,不 stash、不 reset 别人的在途改动。确实要两条分支并行,就排队:前一个提交、推送完,后一个再切。
42
+ - 只读地看别的版本:用 `git show <版本>:<路径>`、`git diff`、`gh pr diff`。要某个版本的完整文件树(例如钉版构建),用 `git archive <版本> | tar -x -C <目录>` 导出到可写区(`tmp/`、`work/`)。导出目录不是 worktree,不登记进仓库。
43
+ - 手里已有的 worktree:先把里面的改动提交、推送,再 `git worktree remove <路径>`,最后 `git worktree prune`。正被别处引用的(例如测试钉住的引擎构建),先换成 archive 导出,再移除。
44
+
45
+ ## 4. 决定权:先做后报
46
+
47
+ - 干活时遇到要定的事,自己当场定、当场做,写进交付记录,事后报备。上报不是做事的前置步骤。
48
+ - 只有这五类要先拿到授权再做:
49
+ 1. 外发:发给公司以外的人或系统、对外发帖、对外发版。部署到内网、团队自己用、能回滚的工作台或页面,不算外发,按第 7 节中档自己放;
50
+ 2. 不可逆操作(删除、强推、迁移或写入生产数据);
51
+ 3. 身份、授权与资金;
52
+ 4. 跨项目接口变更(改别人在用的接口约定;只改实现不改约定不算);
53
+ 5. 生产环境的配置变更。
54
+ - 以下四类默认已授权,不用问:
55
+ 1. 本仓验证器全过、不新增依赖时,升降引擎版本;
56
+ 2. 新判据配了能判 FAIL 的反例时,修改本仓判据;
57
+ 3. 验证器报错时,根因在哪个仓库就去哪个仓库修,按那个仓库的规矩提交;
58
+ 4. 开关 issue,合并低档、中档的 PR,不限本仓。
59
+ - **指令含糊时**,按上下文取最可能的解释,先做几种解释里都安全的部分,并在回复里写明“我按某某理解”。只有每种解释都要做先授权五类的事时才问,问时给出选项,不让对方重新组织语言。
60
+ - **能拍板的人明确说了“做”,就做。** 例如持权人回“执行即可”“照这个做”:这就是授权,先授权五类的事也一样。风险最多说一次,和结果写在同一条回复里;不再追问,也不改成让对方自己动手的方案。只有项目写明的红线挡住时才不做,并给出那条红线的出处。
61
+ - 反复出现的同类决定,请属主一次授权、长期有效,写进该仓库 AGENTS 的“常设授权”一节,注明条件和授权日期。
62
+
63
+ ## 5. 上报怎么写
64
+
65
+ 直接发给能拍板的人,不经中转,监督只抄送。
66
+
67
+ ```
68
+ [上报] <项目>/<事项> · 最晚等到 <时间>(不写默认 30 分钟)
69
+ 问题:<一句话>
70
+ 推荐:<方案>
71
+ 不批时的默认动作:<动作>
72
+ 已经做了什么 / 影响范围:<…>
73
+ ```
74
+
75
+ - 五类以外的事:到点没回复,就按推荐方案执行,交付记录里写“到点按默认执行”。
76
+ - 五类事:到点没回复,就停在那一步,先做别的,不硬做。
77
+
78
+ ## 6. 转派怎么写
79
+
80
+ ```
81
+ [转派] <项目>/<事项> · 理由:需独立评审 | 并行拆段
82
+ 要做什么:<…>
83
+ 完成标准:<怎样算做完,最好是能跑的验证>
84
+ 输入:<路径、提交、链接;不贴文件内容>
85
+ 回给:<坐席或团队>
86
+ ```
87
+
88
+ 接收方做完后发一条回执,内容见第 10 节。
89
+
90
+ ## 7. 放行分档
91
+
92
+ 风险档由做事的坐席自己判,写进交付记录。
93
+
94
+ | 档 | 典型 | 谁放行 | 留什么证 |
95
+ |---|---|---|---|
96
+ | 低 | 纯文档、单仓内可回滚的小改、不外发 | 自己放 | 验证通过(有判据时)+提交 SHA |
97
+ | 中 | 改代码行为或配置、跨多个文件 | 自验后自己放,同时异步通知评审 | 低档两项+判据覆盖本次范围 |
98
+ | 高 | 外发发布、不可逆、身份授权资金、跨项目接口、生产数据 | 交付前独立复核(见下,不必是常设评审席)+放行授权 | 判据覆盖范围、验证对象与交付物同一 SHA、约定的平台与环境、验证方独立于执行方、放行授权有记录 |
99
+
100
+ - 中档的评审意见当修复单处理,不阻断已经放行的交付;只有 P0、P1 才回滚。
101
+ - 判低了(本该高档却自放),事后按事故复盘,不为此给所有交付事前加卡。
102
+
103
+ **交付到位才算完成。**
104
+ - 完成指用户在该看的地方看到了正确结果(工作台、报告、看板),不是“数据改好了”。
105
+ - 交付途中自己发现的问题,属于这个任务本身,按这个顺序处理:
106
+ 1. 能修就修:写权限放开,常设授权第 3 条也允许去根因所在的仓库修;修完重验再发。
107
+ 2. 一时修不好,就把出问题的那一段删掉或标明(例如“历史理由,税率已从 3% 调为 1.5%”),其余部分照发。
108
+ 3. 修和标都做不到,才不发,并按第 5 节上报。
109
+ - 不因为“有一段可能误导”就整份不发:把那一段处理掉。
110
+ - 交给别的系统用的文件,目标系统收下、回执通过才算交付到位,放进下载目录不算。提交属于内网、能回滚的,自己提交并读回回执;属于外发的,把提交备成持权人的一步(文件加操作说明),回执回来后由同一个坐席核对。
111
+ - 核对、审计的结论要落成文件,放到决策人干活的地方(同一个目录、工作台或看板),不能只写在回复里。
112
+ - 一轮里能做完的就做完,不在“还差一步”的时候收尾汇报。收尾写“尚未完成”的,只能是先授权五类的事,或被数据门禁卡住的部分。
113
+
114
+ **先做交付物,不做交接包。**
115
+ - 目标交付物(例如一版工作簿、一份报告)能做,就直接做。不先做交接包、索引、汇总这类中间件,交给一个“待定的承接人”:按第 1、2 节,接手这件事的坐席就是承接人。
116
+ - 中间件只在两种情况下做:转派时(第 6 节的两种理由)写转派消息;或者它本身就是交付物的一部分。不给中间件开版本(v4、v5……),也不为它请评审或监督复核。
117
+ - 评审只审交付物,按上面的风险档来。对中间件做的“文件身份核验”不算复核,不发、也不等。
118
+ - 冻结旧版本不挡新版本:冻结的意思是不改旧版,不是不许做新版。做 v7 不动 v6。
119
+ - **空转止损**:连续两轮工作都没让目标交付物往前走(没有新版本、没有新写入、没有新的验证运行),就换做法:要么用现有数据按第 8 节降级交付,先把交付物做出来;要么按第 5 节一次性上报卡在哪、要什么,然后去做别的。
120
+
121
+ **独立复核怎么找。** 独立指复核方没参与做这件事,也没看过执行方的结论和推理;不要求是一个常设的评审席或 A2A 团队。按下面的顺序,由执行坐席自己发起,不算转派:
122
+ 1. **自起干净复核**:临时拉起一个不带本任务上下文的 agent(子 agent 或新坐席),只给它交付物、规则、原始输入和完成标准,不给执行方的结论和推理。让它独立重算或复核,给出 PASS/FAIL 和差异清单。
123
+ 2. **机器复核**:能用判据机器判定的(计算、对账、格式、一致性),用冻结在先的验证器或另一份独立实现重算;结果一致就算独立复核。
124
+ 3. **属主拍板**:前两步做不了或结果有分歧,按第 5 节上报属主(或该域有授权的人),附上候选版、复核记录和差异。属主批准就是放行授权;属主也可以接受风险直接放行,写进交付记录。
125
+
126
+ 找不到常设评审席不是停工理由。只有复核结论 FAIL 才阻断放行。
127
+
128
+ **放行授权从哪来。** 属主事先给过的授权(例如“这个范围内可以写工作台”),在复核通过后就能用来放行高档改动,不必再问一次;交付记录写明授权来源和复核记录。
129
+
130
+ ## 8. 门禁卡住时
131
+
132
+ **先看这道门禁该不该有。** 门禁只认三处来源:
133
+ 1. 第 4 节先授权的五类;
134
+ 2. 项目或仓库写明的红线:写在它的 AGENTS 或 README 里,引用时给出处,说不出出处的不算;
135
+ 3. 派活方给的完成标准。
136
+
137
+ 不在这三处的,不是门禁,坐席不自己设:
138
+ - 完成标准由派活方定。没给的,默认就是第 7 节的“交付到位”:用户在该看的地方看到结果,每个数据字段标明来源和读取时间。
139
+ - 证据要求看用途,不取最高标准。报告、草稿、工作台预览里的字段,标明来源和读取时间就够。记录 ID、哈希、字段字典、逐字段采集时间,只在派活方要求或目标系统的判据要求时才做。
140
+ - 觉得应该多核实一步,就写成“建议补核”放进交付记录,不当门禁,不挡交付。
141
+ - “来源不够权威”不是不用的理由:先用拿得到的来源,标明是哪个;拿到更权威的来源后再更新。
142
+ - 不能直接用的只有两种:找不到任何来源的,和来源互相矛盾、要业务判断的。这两种按下面的三类处理。
143
+
144
+ **写“阻断”之前**
145
+ - 先把拿得到的来源都试一遍,并记下来:页面上看得到的内容、已有的导出和附件、供应商资料、别的系统里的同一条记录。只调了一个接口就说拿不到,不算试过。
146
+ - 接口返回“未登录”“无权限”,就是缺凭证:按第 9 节备好落位命令和只读探测,不写成数据门禁,也不另开一套完成标准。
147
+ - 阻断消息的第一行写已经交付的降级版(路径、提交或链接)。实在一个字段都填不了,交付物就是备好的落位命令和探测脚本,凭证一到就能跑出结果。只有阻断说明、没有交付物的消息不发。
148
+ - 一次阻断只要一件东西:一条命令、一份导出,或一个授权。写清推荐和默认动作,按第 5 节发。不开多项清单让对方逐项满足。
149
+
150
+ 已经确认该有的门禁,分两种,处理方式不同:
151
+
152
+ | 门禁 | 例子 | 怎么办 |
153
+ |---|---|---|
154
+ | 数据门禁:数据真不真 | 候选记录还没经远端回读核实 | 保留:未核实的数据不写进系统的正式字段(账、正式财务数据、对外上架的内容);报告、草稿、预览里照用,标明来源。不因此停交付,按下面的降级交付 |
155
+ | 流程门禁:等谁点头 | 等授权、等评审、等上线许可 | 按第 4 节先做后报;属于先授权五类的,上报的同时先交降级版 |
156
+
157
+ **降级交付**:门禁解不开时,交出能用的最好版本,把限制标在明处,不让整件事停住。
158
+ - 候选数据可以展示、可以下载,但页面、文件名和文件内容都标“候选·待核实”,写明缺哪一步核实;
159
+ - 正式状态、正式字段、正式数据不写,等门禁解开再改;
160
+ - 交付记录写清:降级了什么、缺什么、谁能解、怎么解。
161
+
162
+ **每道门禁都写清三件事**:谁能解;凭什么解(要对方给的那一件东西:一条命令、一份导出或一个授权,不是一张证据清单);解不开时怎么降级。没写清的门禁,执行坐席按降级交付处理,并在交付记录里把这三件事补上。
163
+
164
+ **核对结果不一时,分三类交付**,不把整批都压成“候选”:
165
+ 1. **已核实的**:和来源一致的行,正式交付或提交。
166
+ 2. **能按现行规则消解的**:例如两个价格只能留一个时,留和来源一致的那个;税率按现行规则改。按规则改好,逐行标明用的是哪条规则,可以和第 1 类一起交。
167
+ 3. **要业务判断的**:金额对不上、找不到来源的行,列成待确认清单。每行写文件值、来源值、推荐值和理由,按第 5 节一次性批量上报给该域有授权的人;不批时默认只交前两类,这些行先不交。
168
+
169
+ 机械修复(改格式、去重、补字段)遇到多个取值时,按证据选,不随手挑一个;没有证据可依的,在清单里标出来。
170
+
171
+ **指定的解锁人不存在时**(例如“由评审席复核”,但没有可路由的评审席),不在原地等:按第 7 节“独立复核怎么找”的顺序自己解,最后兜底的是属主。
172
+
173
+ **分块放行**:一份交付里,已经过了门禁的部分先转正式,没过的部分继续标“候选·待核实”,不让一处没核实的数据拖住整份交付。
174
+
175
+ **缺凭证或缺授权**:不自己造凭证,也不绕过门禁。按第 5 节上报给能授权的人,写清要什么(例如“某数据源的只读权限”,或“请在某处跑一次回读命令”),同时先交降级版。拿到授权后,由同一个坐席把剩下的做完。
176
+
177
+ **例子**:财务月度聚合预览里,7–9 月的候选记录还没完成远端回读核实。
178
+ - 旧做法:下载按钮全部禁用,不更新线上工作台,停在离线稿,等别人来解。
179
+ - 新做法:
180
+ 1. 候选包开放下载,文件名和页面都标“候选·待核实(未经远端回读)”;
181
+ 2. 内网工作台的预览页按中档自己发布,同时异步通知评审;
182
+ 3. 正式财务数据不写;
183
+ 4. 上报属主:“财务月度聚合缺远端回读授权。推荐:给本坐席某对象的只读权限。不批时默认:先以候选版运行,正式数据不动。最晚等到明早 10 点。”
184
+ 5. 授权一到,同一个坐席完成回读、去掉“待核实”标记、开放正式下载。
185
+
186
+ **例子二**:定价核算按现行规则重算后,盈亏平衡价应从工作台现值 MXN 82.93 改为 MXN 81.44(售价 MXN 99,净利 MXN 14.665,净利率 14.81313%)。写工作台属于生产数据,是高档,要独立复核,但查不到可路由的评审席;OMS/货盘原始资料和图片审核还没核实。
187
+ - 旧做法:找不到评审席,就不写生产数据、不发正式报告,停在候选版。
188
+ - 新做法:
189
+ 1. 自起干净复核:临时拉起一个不带本任务上下文的子 agent,只给它定价规则、原始输入和候选 JSON 的结果字段,不给推理过程;让它独立重算净利、净利率和盈亏平衡价。
190
+ 2. 结果一致:凭属主事先给的授权,把工作台盈亏平衡价改为 MXN 81.44;交付记录写明复核方、两边的结果、提交 SHA 和授权来源。结果不一致:列出差异,按第 5 节上报属主,工作台保持 82.93。
191
+ 3. 分块放行:报告里定价核算这一块转正式;OMS/货盘原始资料和图片审核这两块继续标“候选·待核实”,各自等自己的数据门禁。
192
+ 4. 自起复核只要一轮工作的时间,不要为了等常设评审席停工。
193
+
194
+ **例子四**:例子二做完后,生产定价已修好,复核 PASS,审计也留了痕;但报告生成器把终审理由里旧的税率 3% 原文带进了报告,和现行的 1.5% 并列。
195
+ - 旧做法:发现可能误导,就不发布正式报告,收尾写“正式报告发布仍待解决”。
196
+ - 新做法:
197
+ 1. 修生成器:终审理由按现行规则(税率 1.5%)重新生成;或者把旧理由标成“历史理由,税率已从 3% 调为 1.5%”。同时加一条判据:报告里出现的税率必须等于现行规则,防止再犯。
198
+ 2. 重新生成待发布包,用判据和浏览器复核通过后,按中档发布到市场工作台(内网、能回滚),同时异步通知评审。
199
+ 3. 分块:定价这一块是正式的;规格、文本事实、类目绑定、图片审核继续标“候选·待核实”,等 OMS/货盘的数据门禁。
200
+ 4. 收尾汇报写:报告已发布(版本、链接、提交 SHA),生成器已修(提交),剩下的只有被数据门禁卡住的那几块。
201
+
202
+ **例子五**:系统退回了一份报价文件,856 行都报“单价和含税单价只需填一个”。核对来源记录:567 行能对应到精确的 SKU 和供应商报价,其中 118 行两种价格都一致、273 行只有一种一致、176 行两种都不一致;另有 289 行找不到来源;还有 420 行税率和来源不一致。
203
+ - 旧做法:每行清掉一个价格字段,交一份 856 行的修正版放进下载目录;核对结论只写在回复里,金额和税率留给“数据门禁”。
204
+ - 新做法:
205
+ 1. 按证据挑字段:只有一种价格和来源一致的行,留一致的那个;两种都不一致或找不到来源的,先留原值,在待确认清单里标出。逐行记下按哪条规则选的。
206
+ 2. 分三份文件,都放进同一个下载目录,各写 SHA-256:
207
+ - 可提交版:价格和税率都和来源一致、或已按现行规则消解的行;
208
+ - 待确认清单:金额对不上、找不到来源、税率不一致的行,每行列文件值、来源值、推荐值、理由;
209
+ - 全量对照版:只修了格式,文件名标“仅修格式·金额未核实”,只作对照,不提交。
210
+ 3. 一次性上报采购域有授权的人:“待确认 N 行,推荐按来源值和现行税率改;不批时默认只提交可提交版,其余行暂不提交;最晚等到某时。”
211
+ 4. 交付到位:提交可提交版。系统在内网、能回滚,就自己提交并读回回执;属于外发,就备成持权人的一步,回执回来后由同一个坐席核对。
212
+ 5. 收尾写清:提交了多少行、回执结果如何、待确认多少行、在等谁、最晚到几点。
213
+
214
+ **例子八**:坐席要补一个 SKU 的规格字段:品牌、型号、接口、包装清单、颜色、尺寸、重量。OMS 接口 `POST /oms/sku/list` 匿名调用,返回 HTTP 200、`code=200000`、`message=账号未登录`、`data=null`;主站页面上也抓不到它认为“权威”的行。坐席写了一张阻断卡,然后停下:
215
+ - 解锁人写的是属主或 OMS 账号持权人,要“一次性只读授权或脱敏正式导出”;
216
+ - 完成标准列了六项:经前端调用核实型号与 SKU 的对应,并拿到来源记录 ID、更新时间和字段字典;官方原图或货盘原始附件带 SHA-256 和测量时间;每个字段带来源引用、哈希和采集时间;七个字段逐项对源;报告逐字段标 OMS 来源;只放行待定字段。
217
+
218
+ 问题在于:六项完成标准是坐席自己加的,任务里没有;“主站页面不权威”也是坐席自己设的限。真正缺的只有一样,OMS 的只读凭证。
219
+ - 新做法:
220
+ 1. 完成标准回到任务本身:七个规格字段填上,每个字段标明来源和读取时间。记录 ID、哈希、字段字典、测量时间都不当门禁,有就带上,没有就写进“建议补核”。
221
+ 2. 先用拿得到的来源填:主站商品页上显示的、货盘附件和已有导出里的、供应商规格书里的、别的系统里同一 SKU 的记录。两个来源一致的算已核实;只有一个来源的照填,标“单一来源:某某”;来源矛盾的列进待确认清单,写出两个值和推荐值。
222
+ 3. OMS 未登录是缺凭证,按第 9 节办:写好 OMS 只读账号的落位命令(隐藏输入,写进本机密钥库)和只读探测。凭证一到,探测就调 `/oms/sku/list`,逐字段对比 OMS 的值和已填的值,更新来源标注。
223
+ 4. 报告现在就交:定价这一块照旧是正式的;规格这一块带着来源标注交出去;图片先用现有的货盘附件,标明来源。
224
+ 5. 一次上报,只要一件东西:“推荐:在本机运行 `<落位命令>`,放一个 OMS 只读账号。不批时默认:规格按现有来源交付,标‘未经 OMS 核对’。最晚等到某时。”消息第一行写已交付报告的路径。
225
+ 6. 凭证到位后,同一个坐席跑探测、更新标注;和 OMS 有出入的字段,按上面的三类处理。
226
+
227
+ ## 9. 凭证与密钥
228
+
229
+ - 凭证不留在 agent 这边:坐席不索要、不保存、不复述、不转发明文密码、密钥和令牌。
230
+ - 要长期用的凭证,落位的路径由坐席备好,持权人只做“输入一次”这一步:
231
+ - 给出一条持权人在本机直接运行的命令,隐藏输入,写进本机密钥库(例如 macOS 钥匙串)或仓库之外、权限 600 的配置文件;
232
+ - 需要给 GitHub Actions 用的,给出 `gh secret set <名字> -R <仓库>`,由持权人运行,按提示输入;
233
+ - 读取凭证的代码和配置由坐席写好、提交,只引用密钥库里的名字,不含值。
234
+ - GitHub Secrets 只给 Actions 用;部署机上的服务读本机密钥库。两边要用就各落一次。
235
+ - **持权人自己把凭证交给坐席,就用它把事做完。** 持权人在对话里贴出凭证,又说了要做什么(“上传到这里”“执行即可”),或者手上的任务明显就要用它,这就是第 4 节要的授权。坐席照做,守住四条:
236
+ 1. 只用于这一件事,做完不再用;
237
+ 2. 经环境变量或标准输入交给执行的进程,不放进命令参数,不写进脚本、配置、日志、提交、A2A 消息和回复;做完清掉;
238
+ 3. 结果出来后,在同一条回复里用一句话提醒轮换;以后还要用,附上落位命令;
239
+ 4. 不以“凭证已经暴露”“连接没加密”为由不做:暴露已经发生,不做也降不了风险,只会让活停下。这类风险在交付记录里写一句(例如“经 HTTP 明文传输,建议改 HTTPS”),不当门禁。
240
+ - 凭证出现在聊天里、但和手上的事都无关时:不用、不复述;用一句话提醒轮换,给出落位命令。
241
+ - 凭证到位后的检查(能否登录、是不是最小只读权限、需要的字段在不在)由坐席自己用只读探测完成,结果写进交付记录,不要求持权人逐项确认。探测发现要改生产系统的结构或权限(例如给 Odoo 加字段),属于先授权五类,按第 5 节上报。
242
+ - 平台规定必须由人点的动作(例如 PR 要非作者批准):坐席不绕过,也不把它当停工理由。把它准备成持权人的一步——给出链接或一条现成的命令(例如 `gh pr review <号> --approve`),然后先做别的。
243
+
244
+ **例子三**:持权人在聊天里贴出了 Odoo 地址、库名、服务账号和密码,随后说“使用 gh”。
245
+ - 旧做法:拒绝使用密码,列出三项待确认,停下;接着问“使用 gh”是指什么。
246
+ - 新做法:
247
+ 1. 持权人贴出密码,就是让坐席用它:现在就用这份密码跑只读探测,检查能否登录、是否只读、“账号类型”字段的技术名和取值。密码经环境变量传给探测进程,不写进文件。字段不存在,就上报“要在生产 Odoo 加字段”,等授权。
248
+ 2. 地址、库名、账号名不是秘密,直接写进连接配置并提交;长期连接时,读密码的代码只引用密钥库里的名字。
249
+ 3. 探测结果出来后,一句话提醒轮换,附上轮换后的落位命令(隐藏输入,写进本机密钥库)。
250
+ 4. “使用 gh”有两种理解:一是处理 PR,就用 gh 查 PR 状态,把需要批准的 PR 链接和 `gh pr review --approve` 命令交给持权人;二是放进 GitHub Secrets,就给出 `gh secret set` 命令,由持权人运行。两种都安全,就都备好,并写明“两种都已备好,你挑一个执行”。
251
+
252
+ **例子九**:持权人要把两份候选 Excel 上传到内网的临时交付通道(一个 HTTP 的 WebDAV 地址),在聊天里一并给了账号和密码。
253
+ - 旧做法:坐席拒用贴出的密码,写好上传脚本,让持权人轮换密码后自己运行。持权人回“执行即可”,坐席又以“HTTP 明文传输凭证”为由再拒一次。两轮下来,文件没上传。
254
+ - 新做法:
255
+ 1. 持权人给了凭证、说了上传,这就是授权。用这份凭证上传两份候选 Excel:密码经环境变量传给上传脚本,不写进脚本和日志。
256
+ 2. 上传后从 WebDAV 读回,比对 SHA-256,一致才算交付到位。
257
+ 3. 回复第一行报结果:两份文件在通道上的路径,读回的 SHA-256 是否一致。
258
+ 4. 第二行一句话:“密码出现在聊天里,又经 HTTP 明文传过,用完请轮换;以后常用,在本机运行 `<落位命令>`。”
259
+ 5. 最后写剩下没做的:正式工作台提交、还缺的原始资料,各自在等谁。
260
+
261
+ ## 10. 消息与回执
262
+
263
+ - 长任务一律异步发送(`async: true`),发完接着干别的,不干等。
264
+ - 回执是终态:不对回执再回执。收到别人的回执(包括评审、监督的复核回执)不回复,也不确认收到。
265
+ - 回执写四件事:做了什么;结果(提交、产物路径);证据属于哪一层(实测、转述、文档、推断);没做完什么。
266
+ - 引用已有证据时给出处:提交 SHA、报告编号、测试命令和结果,不写“继续有效”这类没法查的话。
267
+ - 同步等待超时(-32005)不等于确认送达:先按 task id 对账,确认没送达再重派,不盲目重发。
268
+ - 一条消息说完一件事。文件不走 A2A 消息:给路径、提交或链接。确实要传文件,走独立通道;过渡期单个 task 最多分 16 片。
269
+ - 未加入网络的坐席既看不到别人,也收不到消息;要协作先加入。身份只认 A2A 成员关系。
270
+ - 坐席名统一用「<项目>--<职责>」。
271
+
272
+ **收到规范或规则更新时**
273
+ - 不回“收到”,也不复述规则。规范更新不是任务,不需要回执。
274
+ - 直接拿新规范把手上在途的事重新过一遍:原来卡住、现在规范允许的,马上去做;需要人点的,按第 9 节备成持权人的一步。
275
+ - 回复只报变化:哪件事因为哪一条规范现在能往前走了、做了什么、结果如何。手上没有受影响的事,就不回。
276
+ - 项目或仓库自己的红线(例如“DSH 源码只读”)优先于这份通用规范。但只在它挡住某个具体动作时才提:写明挡住了什么、改用什么办法,不预先罗列。
277
+ - 通用规范解不开的门禁(例如平台规定的非作者审批),不要只说“不会被自动解除”:按第 8 节写清谁能解、凭什么解、怎么降级,并把要人点的那一步备好。
278
+
279
+ **例子六**:坐席收到 v1.8 后回复“收到,后续按 v1.8 执行”,逐条复述了五条规则,说明已有公钥、修复和测试证据“继续有效”,又说 #267、#268 的非作者审批和同源 P1 安全门“不会被通用规范自动解除”,然后停下。
280
+ - 新做法:不回“收到”,直接用 v1.8 过一遍手上的 #267、#268:
281
+ 1. **非作者审批**:备成持权人的一步——“#267、#268 等你批准”,附上两个 PR 的链接,或 `gh pr review 267 --approve`、`gh pr review 268 --approve`,然后先做别的。
282
+ 2. **同源 P1 安全门**:根因在工作台市场的代码里,写权限放开,自己修,补上测试并重验。一时修不好,就按第 8 节写清谁能解、凭什么、怎么降级。
283
+ 3. **DSH 源码只读**:只有某一步要改 DSH 源码时才提,并写明改用插件还是配置。
284
+ 4. 回复只报结果:哪个 PR 现在只差批准(附链接);P1 修了没有(提交 SHA、测试命令和结果);还卡在哪、谁能解。
285
+
286
+ **例子七**:一个进销存调查,目标是 M4-v7 工作簿和正式验证运行。坐席把“候选资料交接包”做到了 v5,核验交接包引用的 12 份文件大小和 SHA 都对;评审核验交接包,监督再复核“静默”,坐席又回复“收到监督复核结果”。三轮都只确认了交接包本身没问题,M4-v7 一步没动,“具名承接人未定”,这件事用掉了 1300 多万 token。
287
+ - 新做法:
288
+ 1. 这个坐席就是 M4-v7 的承接人,不等别人来“具名承接”,也不再做交接包 v6。
289
+ 2. 直接建 M4-v7:v6 冻结不动,v7 另起一份。数据按第 8 节分三类放:
290
+ - 已核实,写进 v7:8 月四家承运商 8462 件;9 月数量匹配的 40 项 SKU;具备资格的 47 个 D14 金额来源。
291
+ - 列进待确认清单:派格 826 件(只在台账里有,单列,不并入、不当成零);9 月 13 项差异;4 项找不到对应明细的 M4 记录;14 项 OPEN。
292
+ 3. 缺的 8、9 月签收和月末在途原始数据,按第 5 节一次性上报给能提供数据的人:“推荐给某某原始导出;不批时默认 v7 先按‘签收与在途缺数据’的降级版交付;最晚等到某时。”
293
+ 4. 跑正式验证运行,把 v7 放到 SOP 规定的位置,让人在那里能看到。v7 要作为正式财务报表交付,属于高档:按第 7 节自起干净复核,凭属主事先的授权放行。
294
+ 5. 评审和监督只看 v7。收到他们的回执不回复。
295
+
296
+ ## 11. 定时任务与轮询
297
+
298
+ - 默认不开定时轮询,需要时手动跑一次。
299
+ - 确实要定时:从一天一到两次起步;同一项检查只开一个;结果写进看板或台账,结论变了才发消息。
300
+ - 轮询里不派单、不开 issue 催办、不以属主账号对外发帖。
301
+
302
+ ## 12. 留痕
303
+
304
+ - 交付记录写:风险档、提交 SHA(改了几个仓库就写几个)、验证结论、到点按默认执行了哪些决定。
305
+ - 引用证据时标明是哪一层。只有自己实测过的才能写成“现状”,转述和文档写成“据某某”。
306
+ - 缺证即未证实:说自己做过的事(跑过测试、提交过、发布过),没有痕迹的不算做完,也不断言“没做”;要么补证,要么按未完成处理,写明缺什么证据。这一条管工作记录,不管业务数据:业务数据按第 8 节标来源,不因为缺哈希、缺记录 ID 就不用。
307
+
308
+ ## 13. 每周看五个数
309
+
310
+ - 每件工作的转派次数:能单体完成的应为 0;
311
+ - 上报从发出到得到答复的时长;
312
+ - 一次放行率:放行后没被修复单打回的比例;
313
+ - 定时轮询任务占全部任务的比例;
314
+ - 只产出中间件或阻断说明、没让交付物往前走的轮次,以及它们用掉的 token。
315
+
316
+ ## 发消息前自检
317
+
318
+ - [ ] 我自己能做完吗?能就别发。
319
+ - [ ] 要改别的仓库?自己去改,按那个仓库的规矩提交,不转派。
320
+ - [ ] 想开 worktree?不开:在主检出里做;只读看旧版本用 git show 或 git archive。
321
+ - [ ] 属于先授权的五类吗?不是就先做后报。
322
+ - [ ] 被门禁卡住了?先看它在不在先授权五类、项目写明的红线、派活方的完成标准里,不在就不是门禁。在的话,先交标明限制的降级版,再上报,只要一件东西。
323
+ - [ ] 要写完成标准或证据要求?派活方没要的不加;报告里的字段标明来源和读取时间就够。
324
+ - [ ] 能拍板的人已经说了“做”?那就做,风险写一句,不再问。
325
+ - [ ] 要用凭证?持权人交给我的,用它把指明的事做完,不落盘、不复述,做完提醒轮换;要长期用的,给持权人一条落位命令。
326
+ - [ ] 指令含糊?按最可能的意思先做安全的部分,写明自己怎么理解的。
327
+ - [ ] 发现交付途中的问题?能修就修,修不好就删掉或标明那一段,再把其余部分发出去。
328
+ - [ ] 准备收尾了?用户在该看的地方能看到结果了吗?交给别的系统的文件,回执通过了吗?没有就接着做。
329
+ - [ ] 核对结果有好有坏?分成已核实、按规则消解、要业务判断三类交付,别整批都标“候选”。
330
+ - [ ] 要独立复核但找不到评审席?自己起一个干净复核,或用验证器重算;都不行再找属主。
331
+ - [ ] 写清理由、完成标准和截止时间了吗?
332
+ - [ ] 带的是路径和提交,而不是文件内容吗?
333
+ - [ ] 是异步发出的吗?
334
+ - [ ] 刚收到规范更新?不回“收到”,直接用它推进手上的事,只报变化。
335
+ - [ ] 准备做交接包、索引或汇总?能直接做交付物就先做交付物;连续两轮交付物没动,就换做法。
336
+ - [ ] 收到的是别人的回执?不回复。
337
+
338
+ ## 修订记录
339
+
340
+ | 版本 | 改动 |
341
+ |---|---|
342
+ | v1 | 首版 |
343
+ | v1.1 | 写权限放开 |
344
+ | v1.2 | 门禁卡住时降级交付 |
345
+ | v1.3 | 独立复核不必等常设评审席 |
346
+ | v1.4 | 执行单位改为坐席 |
347
+ | v1.5 | 凭证与密钥;指令含糊时怎么办 |
348
+ | v1.6 | 交付到位才算完成 |
349
+ | v1.7 | 核对结果不一时分三类交付 |
350
+ | v1.8 | 不用 git worktree |
351
+ | v1.9 | 收到规范更新直接用在手头的事上 |
352
+ | v1.10 | 先做交付物、空转止损、收到回执不回复 |
353
+ | v1.11 | 去掉对本机设计工件的引用,本文自成一体,A2A 协作规则以本文为准 |
354
+ | v1.12 | 门禁只认三处来源,坐席不自设门禁、不加码完成标准;证据要求看用途;阻断消息先写已交付的降级版,一次只要一件东西 |
355
+ | v1.13 | 能拍板的人明确说“做”就做;持权人交给坐席的凭证用于指明的那件事,不以已暴露、未加密为由拒做;改写例子三,加例子九 |
@@ -10,8 +10,11 @@ capability flags) plus unsigned serve-fresh fields.
10
10
  - The full card goes only to a caller that presents an OriginClaim envelope
11
11
  (`X-A2A-Caller` / `-Url` / `-Ts` / `-Sig`, signed with the caller's card
12
12
  key) AND that this host links: the same origin (self-fetch), one of its
13
- joined session handles, or an exact canvas remote member ref the operator
14
- added (#18, #19 D1). Proving a key is not a link.
13
+ joined session handles, an exact canvas remote member ref the operator
14
+ added (#18, #19 D1), or bilateral seeding — this host's `peers` config
15
+ names the caller's origin AND the caller's card lists this host's origin
16
+ among its peers (both operators made the gesture). Proving a key is not a
17
+ link.
15
18
  - Peers poll cards and aggregate the `sessionTeams` they are entitled to into
16
19
  their `remote` rows — this is how the planning canvas shows other nodes.
17
20
 
@@ -24,7 +24,8 @@
24
24
  the host that receives it; a team on another host answers "No live DSH
25
25
  session node accepts team". `a2a_route` resolves peers and forwards;
26
26
  direct callers (the CLI included) must target their home host's teams.
27
- - A sync route's 15s transport budget is shorter than most model turns. For
27
+ - A sync route to a remote peer rides a 15s transport budget (a target on
28
+ this host gets 180s) — both are shorter than many model turns. For
28
29
  anything that runs long, prefer `async: true` and the receipt contract.
29
30
 
30
31
  ## Names and prefixes