xuym-codex-collab 0.4.2 → 0.4.4

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.
@@ -57,7 +57,46 @@
57
57
  },
58
58
  "admin_dispatch": {
59
59
  "type": "boolean"
60
+ },
61
+ "review_context": {
62
+ "type": "array",
63
+ "maxItems": 100,
64
+ "items": {
65
+ "type": "object",
66
+ "additionalProperties": false,
67
+ "required": [
68
+ "task_id",
69
+ "expected_seq",
70
+ "title",
71
+ "commit",
72
+ "stage"
73
+ ],
74
+ "properties": {
75
+ "task_id": {
76
+ "type": "string",
77
+ "pattern": "^T-[A-Z0-9-]{1,62}$"
78
+ },
79
+ "expected_seq": {
80
+ "type": "integer",
81
+ "minimum": 1
82
+ },
83
+ "title": {
84
+ "type": "string",
85
+ "minLength": 1,
86
+ "maxLength": 200,
87
+ "pattern": "\\S"
88
+ },
89
+ "commit": {
90
+ "type": "string",
91
+ "pattern": "^[a-f0-9]{40}$"
92
+ },
93
+ "stage": {
94
+ "type": "integer",
95
+ "minimum": 0
96
+ }
97
+ }
98
+ }
60
99
  }
61
100
  },
62
- "$comment": "Runtime also verifies the repo and target against the pinned team, a deterministic request ID derived from target_agent and message_key, and authorization by the bot owner, an enrolled team member, or an explicitly allowed administrator. The original group request is shared in Git; private Codex transcripts, bindings and credentials stay local."
101
+ "$comment": "Runtime also verifies the repo and target against the pinned team, a deterministic request ID derived from target_agent and message_key, and authorization by the bot owner, an enrolled team member, or an explicitly allowed administrator. The original group request is shared in Git; private Codex transcripts, bindings and credentials stay local. Optional review_context freezes pending tasks, sequences and code commits when the authenticated owner message arrives. Natural review interpretation cannot replace this context with a newer version. All peers must support these records before enabling natural reviews."
63
102
  }
@@ -64,7 +64,26 @@
64
64
  "signature": {
65
65
  "type": "string",
66
66
  "minLength": 1
67
+ },
68
+ "invitation_replacement": {
69
+ "type": "object",
70
+ "additionalProperties": false,
71
+ "required": [
72
+ "old_invite_id",
73
+ "new_invite_id"
74
+ ],
75
+ "properties": {
76
+ "old_invite_id": {
77
+ "type": "string",
78
+ "pattern": "^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$"
79
+ },
80
+ "new_invite_id": {
81
+ "type": "string",
82
+ "pattern": "^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$"
83
+ }
84
+ },
85
+ "description": "Administrator replaces an unconsumed invitation. Old invitation and enrollment requests become invalid; team policy remains identical."
67
86
  }
68
87
  },
69
- "$comment": "Runtime verifies pinned root hash, contiguous version and parent chain, canonical team_hash, previous-admin signature, immutable existing identities and local anti-rollback checkpoint."
88
+ "$comment": "Runtime verifies pinned root hash, contiguous version and parent chain, canonical team_hash, previous-admin signature, immutable existing identities and local anti-rollback checkpoint. Invitation replacement must keep the team hash unchanged, cannot accompany enrollment, and cannot revoke an approved invitation or reuse a replacement ID. Clients lacking this field fail closed and must upgrade."
70
89
  }
@@ -6,7 +6,7 @@ import { readPeerConfig } from '../../apps/peer/runtime.mjs';
6
6
  import { git } from '../../packages/peer/store.mjs';
7
7
  import { bindingPrompt } from './setup-desktop-project.mjs';
8
8
  const root = fileURLToPath(new URL('../../', import.meta.url));
9
- const legacyHashes = new Set(['6e4d1ea6a644fb3078c541e40bcc9e8bf5069462994152f3ec2fc3aa5fedd5fa', 'f98ad425e2ea3c8ab6fb86febef7d9cb288029ef55bea6937dda6de8b467fece']);
9
+ const legacyHashes = new Set(['46543ca4fe00836f0ae0d7d7c12ea2756c9ab0220f01d29c391d608c5e405c53', '6e4d1ea6a644fb3078c541e40bcc9e8bf5069462994152f3ec2fc3aa5fedd5fa', 'f98ad425e2ea3c8ab6fb86febef7d9cb288029ef55bea6937dda6de8b467fece']);
10
10
  const hash = (value) => createHash('sha256').update(value).digest('hex');
11
11
  const inside = (parent, child) => { const path = relative(parent, child); return !path || path !== '..' && !path.startsWith('../') && !isAbsolute(path); };
12
12
  async function plainPath(base, path) {
@@ -11,7 +11,7 @@ export function bindingPrompt(agentId, repo) {
11
11
  return `使用 $team-collab-desktop,启用当前项目的团队协作,将 ${agentId} 机器人绑定到当前对话。项目:${repo}`;
12
12
  }
13
13
  export function detailedBindingPrompt(agentId, repo) {
14
- return `请把当前已有 Codex 对话设为 ${agentId} 的企微协作执行对话,不要新建独立执行线程。\n项目:${repo}\n读取 ${join(repo, '.agents/skills/team-collab-desktop/SKILL.md')}。\n1. 用本项目 MCP 的 get_identity 确认身份是 ${agentId},execution_mode 是 desktop_poll;若不匹配,停止并提示重新加载 MCP。\n2. 获取当前真实对话 ID:优先使用已提供的应用上下文,或当前终端 CODEX_THREAD_ID(如果存在);不可猜 ID 或读取/修改应用数据库。没有可用 ID 时请让我复制当前对话 ID/链接。\n3. 调用 bind_desktop_thread 绑定当前真实对话,然后用应用 automation_update 工具在当前已有对话创建一个 heartbeat:每分钟检查(仅当工具接受该周期;否则说明限制),不要创建 cron、新对话或后台 SDK。先查现有 automation,避免重复;不要修改无关 automation 或 CC Switch。\n4. heartbeat 的保存提示词必须包含 ${agentId}、当前真实 thread_id 和该 skill 路径;每次 get_identity → poll_desktop_task。job=null 且 requests 为空 时保持安静;有任务就只在本对话和返回的隔离 worktree 执行本阶段,主动续租、测试、明确提交,然后 finish_desktop_task;失败时按 skill 处理。requests 非空时按 Skill 理解群消息,调用 resolve_desktop_request 创建任务、追问或回答;使用 team_context 的现有路由、能力与默认分工,不能猜测不存在的同事。解决后再次 poll 开始工作。自然语言“通过/完成”不能代替人工审核命令。复用或更新当前对话已有的协作 heartbeat,避免重复创建。禁止启动 SDK/CLI 代替当前对话。仅新任务、结果、失败或需我操作时通知。\n5. 创建完成后立即调用一次 poll_desktop_task 验证,无任务应正常返回,不要创建测试任务。告诉我绑定身份、对话 ID 和 heartbeat 状态;若工具不可用明确说明未启用自动轮询。\n`;
14
+ return `请把当前已有 Codex 对话设为 ${agentId} 的企微协作执行对话,不要新建独立执行线程。\n项目:${repo}\n读取 ${join(repo, '.agents/skills/team-collab-desktop/SKILL.md')}。\n1. 用本项目 MCP 的 get_identity 确认身份是 ${agentId},execution_mode 是 desktop_poll;若不匹配,停止并提示重新加载 MCP。\n2. 获取当前真实对话 ID:优先使用已提供的应用上下文,或当前终端 CODEX_THREAD_ID(如果存在);不可猜 ID 或读取/修改应用数据库。没有可用 ID 时请让我复制当前对话 ID/链接。\n3. 调用 bind_desktop_thread 绑定当前真实对话,然后用应用 automation_update 工具在当前已有对话创建一个 heartbeat:每分钟检查(仅当工具接受该周期;否则说明限制),不要创建 cron、新对话或后台 SDK。先查现有 automation,避免重复;不要修改无关 automation 或 CC Switch。\n4. heartbeat 的保存提示词必须包含 ${agentId}、当前真实 thread_id 和该 skill 路径;每次 get_identity → poll_desktop_task。job=null 且 requests 为空 时保持安静;有任务就只在本对话和返回的隔离 worktree 执行本阶段,主动续租、测试、明确提交,然后 finish_desktop_task;失败时按 skill 处理。requests 非空时按 Skill 理解群消息,调用 resolve_desktop_request 创建任务、转达明确的真人审核、追问或回答;使用 team_context 的现有路由、能力与默认分工,不能猜测不存在的同事。解决后再次 poll 开始工作。真人自然语言审核仅能通过 request.review_context 中的固定版本转达;多任务、语义不清或版本变化时先追问,不得自行批准、完成或合并。复用或更新当前对话已有的协作 heartbeat,避免重复创建。禁止启动 SDK/CLI 代替当前对话。仅新任务、结果、失败或需我操作时通知。\n5. 创建完成后立即调用一次 poll_desktop_task 验证,无任务应正常返回,不要创建测试任务。告诉我绑定身份、对话 ID 和 heartbeat 状态;若工具不可用明确说明未启用自动轮询。\n`;
15
15
  }
16
16
 
17
17
  // An explicit project attachment: preserve unrelated TOML settings, keep a local