fix: auto-discover KNOWN_AGENTS for resource injection during pull - #394
fix: auto-discover KNOWN_AGENTS for resource injection during pull#394jeff-r2026 wants to merge 7 commits into
Conversation
|
建议把这个问题提升为更明确的产品模型:不再由 建议的职责划分:
当前 PR 的 auto-discovery 方向符合这个目标,但实现上建议补齐几个边界:
建议增加以下回归测试:
这样可以彻底解决“新增 Agent 需要更新团队配置”的问题,同时避免把路径猜测和双向同步安全边界混在一起。 |
|
复查最新提交 [P1] pull 的 tombstone 清理仍会删除自动发现目录中的个人 Skill
本地复现:
也就是说,直接调用 另外还有两个 auto-discovery 功能遗漏:
建议在合并前至少修复 tombstone 删除问题,并为“自动发现目录中存在同名个人 Skill”加入回归测试。 |
The pull flow (skills, rules, agents, builtin resources) only iterated over tools explicitly listed in teamai.yaml toolPaths via scopedToolPaths(). Tools like tclaude/tcodex that are registered in KNOWN_AGENTS and installed on disk (.tclaude/ exists) were silently skipped — seedProjectAgentRoot() created their root directory, but pullItem() never wrote resources into it. Add effectiveToolPaths() that merges scopedToolPaths() with auto-discovered KNOWN_AGENTS entries whose install root exists on disk. Convention-based paths (skills, rules, agents, claudemd) are derived from the agent's skillsPath. Use this in all pull/sync call sites so any installed tool receives team resources without requiring explicit teamai.yaml config. Also add tclaude and tcodex to SELF_MODE_AGENT_CHOICES so they are detected during `teamai init` in single-repo mode. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…anaged tools Address PR review feedback: 1. Replace convention-based path derivation (deriveToolPaths) with a lookup into DEFAULT_TOOL_PATHS — a verified per-tool registry extracted from the schema defaults. Agents without a registry entry (e.g. gemini) receive only their skills path; rules/agents/claudemd are never guessed. 2. Restrict push (scanLocalForPush) and remove (removeItem) to scopedToolPaths() — only team-managed tools. This prevents personal skills in auto-discovered tool dirs from being silently uploaded, and ensures remove only deletes resources teamai has management records for. 3. Pull and sync paths (pullItem, pullAllRules, builtin-*) continue using effectiveToolPaths() so installed tools receive team resources. 4. Add regression tests covering: auto-discovery with verified paths, skills-only fallback for unregistered agents, custom path override precedence, disabledAgents, codebuddy CODEBUDDY.md preservation, and scopedToolPaths isolation. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ull path Address second round of PR review: 1. [P1] Tombstone cleanup and stale-skill cleanup in pull.ts now use scopedToolPaths() instead of effectiveToolPaths(). A personal skill in an auto-discovered dir (e.g. ~/.gemini/skills/private-skill) that shares a name with a tombstoned team skill is no longer deleted. Same fix applied to stale-rule cleanup in rules.ts. 2. OpenCode user-scope detection: effectiveToolPaths() now resolves the install-detection root from userScope paths when in user scope, so ~/.config/opencode is correctly detected (not just ~/.opencode). userScope path overrides are also applied to the returned paths. 3. AgentsHandler.pullItem() and pullLegacyMd() now use effectiveToolPaths() so auto-discovered tools (e.g. tclaude) receive team agent definitions. 4. Added regression tests for OpenCode user-scope auto-discovery. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
bd9bc73 to
c63b293
Compare
|
本地 review 确认两个 P1 数据损失问题,建议修复后再合并。 审查版本: 1. [P1] 角色清理会删除未被团队管理的个人技能复现条件与步骤:
实际结果:整个个人 原因: 2. [P1] 自动发现后的首次同步会直接覆盖同名个人技能位置:src/resources/skills.ts:442–472 复现条件与步骤:
实际结果:个人文件被团队版本覆盖,正文变为 原因:自动发现将 Gemini 纳入写入目标,随后 验证情况
|
Address PR review P1 data-loss findings on effectiveToolPaths() pull: 1. [P1] Role cleanup (cleanupInactiveNamespaceSkills in pull.ts) iterated effectiveToolPaths(), so a personal skill in an auto-discovered dir (e.g. ~/.gemini/skills/private-ops) sharing a name with an inactive team namespace was deleted. Restrict it to scopedToolPaths(), matching the tombstone/stale cleanup scoping already applied — deletion only touches team-managed tools. 2. [P1] First-time takeover (SkillsHandler.pullItem in skills.ts) used copyDir(overwrite) unconditionally, clobbering a personal same-named skill in an auto-discovered dir. Skip the write when the tool is only auto-discovered (not in scopedToolPaths) and the destination already exists; team-managed tools still overwrite as before. pull into installed tools still uses effectiveToolPaths(), so tclaude etc. keep receiving team resources. Added regression tests for both data-loss scenarios in pull-tombstone.test.ts. Note: rules/agents pullItem have the analogous overwrite pattern; left for a follow-up per reviewer scoping. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
已针对本轮 review 的两个 P1 数据丢失问题修复,并 rebase 到最新 修复P1-1 角色清理删除个人技能( P1-2 首次接管覆盖个人技能( 验证
待跟进
|
|
复查最新提交 1. [P1] 个人 rules 仍会被自动同步覆盖位置:src/resources/rules.ts:168–195 此次防覆盖逻辑只加到了 skills,rules 仍直接写入自动发现的工具目录。 真实 CLI 复现:
结果:个人文件被覆盖为 建议:将个人资源冲突保护覆盖到 rules;首次遇到未归属 TeamAI 的同名文件时保留文件并给出可见提示。也建议检查 agents 的对应写入路径是否需要相同保护。 2. [P2] “目标存在就跳过”会阻断团队技能后续更新位置:src/resources/skills.ts:469–473 真实 CLI 复现:
结果:Claude 正常更新为 建议:区分“预先存在的个人资源”和“由 TeamAI 部署的资源”,不能仅用目录是否存在来判断。可以在本地状态中记录部署目标及上次同步内容摘要:未记录的同名资源保留并提示;已记录且未被本地修改的资源允许更新;存在本地修改时保留并提示冲突。后续删除也应以实际部署归属为依据。 建议补充的回归测试
验证情况:最新版本 |
…gents + updates) Address round-2 review on the auto-discovery personal-resource protection: 1. [P1] Extend the personal-resource guard from skills to RULES and AGENTS (both the YAML-render and legacy-md agent paths). Previously only skills were protected; a personal ~/.<tool>/rules/<name> could still be overwritten on pull. 2. [P2] The prior skills guard skipped ANY pre-existing destination, which permanently blocked team UPDATES to a resource teamai itself deployed into an auto-discovered dir (2nd pull after a team edit never landed). Content comparison cannot fix this: after a team update the local copy is the old team version, indistinguishable by content from a personal resource. So track ownership instead. Add state.autoDiscoveredManaged (keys <tool>:<type>:<name>) recording what teamai deployed into auto-discovered tool dirs, plus a small helper module (auto-discovered-ownership.ts). pullItem rule for non-scoped tools: - destination absent OR key tracked -> write (and record ownership) - destination present but untracked -> preserve personal resource + warn Team-managed tools (scopedToolPaths) are unaffected and always overwrite. State is loaded/saved lazily (only when a non-scoped tool is involved), load-modify-save like the coAuthorManaged reconciler. Regression tests: personal skill/rule preserved; teamai-deployed skill in an auto-discovered dir still receives team updates on a later pull. Note: gemini has no rules path in DEFAULT_TOOL_PATHS (skills-only auto- discovery), so the rules guard is exercised via tclaude, not gemini. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
已修复本轮的两个问题(head 方案修正:从「内容比对」改为「归属记录」上一版我曾考虑用「本地内容 vs 团队源」比对来判断是否可覆盖。这个思路是错的,回归测试直接证伪了它:团队更新后,自动发现目录里的本地副本是旧的团队版,它既不等于新团队源、也和「个人资源」在内容上无法区分——单凭内容判不出「这是不是 teamai 部署的」。所以采用你最初建议的归属记录方案。 修复[P2] 已部署资源后续更新被阻断 —— 新增
团队管理的工具(scopedToolPaths)行为不变,始终覆盖。state 仅在涉及非 scoped 工具时惰性 load/save,采用 load-modify-save,与 [P1] rules / agents 同类覆盖 —— 把上述保护从 skills 扩展到 rules 和 agents(agents 覆盖 YAML 渲染路径和 legacy 新增 helper 模块 验证
一个说明
|
|
复查 [P1] Cursor 旧格式清理绕过个人文件保护位置: 复现步骤:
实际结果:个人 原因: 建议:对于自动发现的工具目录,旧格式清理也必须验证被删除文件本身的归属。不能仅因 验证:最新版本构建成功, |
…ursor dir Round-3 review P1: the old-layout `.md` cleanup after writing a cursor `.mdc` rule ran unconditionally. In an auto-discovered (non-team-managed) cursor-family dir, a personal `safety.md` with no `safety.mdc` was deleted on pull — the ownership check gated the `.mdc` write target, not the `.md` that actually got removed. Only delete the same-named `.md` for team-managed tools (scopedToolPaths). In an auto-discovered dir the `.md` may be a personal file, so it is never removed there. Added a regression test (personal .md, no .mdc, cursor auto-discovered → .md preserved after pull). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
已修复该 Cursor 修复[P1] Cursor 旧格式清理绕过个人文件保护 —— 根因如你所述:写 改法:那句删旧 await writeFile(dest, teamRuleToCursorMdc(raw));
// 只有团队管理的工具才清理旧布局遗留的 .md;
// 自动发现目录里的同名 .md 可能是个人文件,不删。
if (scopedKeys.has(tool)) {
await remove(path.join(destDir, `${item.name}.md`));
}验证
顺带确认: |
Round-4 review — extend the auto-discovered ownership record to the two remaining paths that bypassed it: 1. [P1] Built-in skill deployment (builtin-skills.ts) copied with overwrite:true and no ownership check, so a personal same-named skill in an auto-discovered dir (e.g. .tclaude/skills/team-wiki-codebase) was clobbered. Now: in a non-team-managed tool dir, only overwrite a skill teamai deployed itself (tracked); an untracked pre-existing skill is preserved with a warning. Record ownership on deploy. (No localConfig = reporting-only path keeps legacy behavior; state is scope-bound.) 2. [P2] Tombstone cleanup (pull.ts step 3) only iterated scopedToolPaths, so a resource teamai deployed into an auto-discovered dir was never withdrawn when the team recalled it — a tombstoned (possibly dangerous) skill lingered in e.g. .tclaude and could still be loaded. Now, for auto-discovered tools, also remove tombstoned resources that teamai deployed (tracked in the ownership record) and drop them from the record. Untracked same-named personal files are still never deleted. Add unmarkAutoDiscovered/isAutoDiscoveredTracked helpers. Regression tests: personal built-in-named skill preserved; withdrawn teamai-deployed skill removed from the auto-discovered dir on tombstone; personal same-named skill NOT removed on tombstone. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
已修复本轮两个问题(head 修复[P1] 内置 skill 无提示覆盖个人文件 —— 内置 skill 部署( [P2] 撤回的资源残留在自动发现目录(安全) —— tombstone 清理( helper 补充 验证
关于这几轮 review这个 PR 的核心不变量是「自动发现的工具目录必须尊重个人资源(不删/不覆盖),但 teamai 自己部署的要能更新/撤回」。前几轮我是被逐个路径地指出问题、逐个修的。这轮我已把所有读/写/删自动发现目录的路径梳理了一遍(普通 pullItem、rules |
Summary
pullItem()in skills/rules/agents handlers only iteratedscopedToolPaths()(=teamai.yamltoolPaths), missing tools liketclaude/tcodexthat are inKNOWN_AGENTSand installed on diskeffectiveToolPaths()intypes.tsthat mergesscopedToolPaths()with auto-discoveredKNOWN_AGENTSentries whose install root (e.g..tclaude/) existseffectiveToolPaths()tclaudeandtcodextoSELF_MODE_AGENT_CHOICESforteamai initsingle-repo mode detectionTest plan
npx tsc --noEmitpasses (no new type errors)npx vitest run— all previously-passing tests still pass, updated 3 test files for new SELF_MODE_AGENT_CHOICES sizemkdir -p /root/gpu/.tclaude && teamai pull --force→ skills/rules injected into.tclaude/skills/and.tclaude/rules/🤖 Generated with Claude Code