fix(adapters) namespace workspace skill per agent so uploads carry the right identity - #571
Conversation
…e right identity Agents sharing a working directory all wrote the SAME skill file (.claude/skills/openagents-workspace.md), whose curl commands embed the writing agent's upload identity — whichever agent wrote last stamped its name into every other agent's file uploads, so files one agent created were attributed to another in the workspace Files list. A resumed Claude session that had once read a wrongly-stamped skill kept the wrong identity in context indefinitely. Chat replies were never affected — the adapter posts those itself under its own name — which is why the mismatch only showed up on files. Skill files and frontmatter names are now per-agent (openagents-workspace-<agent>), mirroring what OpenClaw already did, with system-prompt references following suit and the legacy shared-name file deleted on write. Names satisfy the Agent Skills rules (lowercase kebab-case, max 64 chars); lossy normalization or truncation appends a stable short hash of the raw name so distinct agents (My_Agent vs my-agent) can never converge on one skill, while already-valid names stay readable. The remaining theoretical collision (a verbatim name equal to another's stem-plus-hash output, ~2^-32 or requires editing daemon.yaml which already grants full access) is documented as an accepted tradeoff. Cursor has no system-prompt flag and previously learned its identity ONLY from whichever coexisting skill it happened to open — every spawn now prepends a header pinning the agent name and the exact skill to follow. OpenClaw migration removes the pre-normalization raw-name skill dir, guarded by a safe-charset check, a skills-root containment check (agent names are unvalidated, so the raw name must not let the join escape before a recursive delete), and an ownership proof read from the stored SKILL.md (quote-delimited exact identity match) — covering path traversal and the Windows/macOS case-alias where agent Foo's legacy path IS agent foo's live dir. When ownership cannot be proven the dir is left in place. Adds 19 tests — per-agent naming and identity across all four builders, spec compliance for hostile names, collision resistance, determinism, coexisting cursor skills, the pinned cursor header, claude legacy-file cleanup, and openclaw migration (rename, case-alias regression, unprovable ownership, traversal). OpenClaw tests sandbox the state dir at prototype level so construction never touches a real ~/.openclaw.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
zomux
left a comment
There was a problem hiding this comment.
Reviewed in depth. Fixes a real identity-misattribution bug (agents sharing a working dir clobbered one shared skill file → uploads stamped with the last writer's identity). Per-agent skill naming with a sha256 suffix on lossy/truncated normalization prevents distinct names converging (documented 2^-32 limitation is acceptable). Security-sensitive file deletions are well-guarded: Claude legacy cleanup uses a constant filename (no traversal); the OpenClaw recursive rmSync is gated by legacy!=current + safe charset + direct-child containment + an ownership proof read from the stored SKILL.md (defends case-insensitive FS aliasing). Traced the agentName='..' edge — resolves to a harmless single-segment dir, not a traversal escape. 19 tests cover naming/identity across all four builders, hostile names, collision resistance, cursor coexistence, and the OpenClaw migration incl. path traversal + case-alias + unprovable-ownership. Full suite 715/715. LGTM.
Problem
Agents configured with the same working directory all wrote the SAME workspace skill file (
.claude/skills/openagents-workspace.md), whose curl commands embed the writing agent's upload identity (source=openagents:<agent>). Whichever agent wrote last stamped its name into every other agent's file uploads — files generated by one agent showed up in the workspace Files list attributed to another (e.g. a doc produced by qiyue-bot listed as uploaded by cherie-bot). A resumed Claude session that had once read a wrongly-stamped skill kept the wrong curl identity in its context indefinitely, so the misattribution persisted even when the other agent was idle.Chat replies were never affected — the adapter posts those itself under its own name — which is why the mismatch only ever showed up on files.
Fix
openagents-workspace-<agent>), mirroring what the OpenClaw adapter already did. System-prompt references follow the per-agent name, and the legacy shared-name file is deleted on write so a stale copy with another agent's identity can never be read again. (claude, cursor, opencode; openclaw switched to the shared helper)My_Agentvsmy-agent) can never converge on one skill. Already-valid names stay readable with no hash suffix.Foo's legacy path being agentfoo's live dir).Known accepted limitation
The naming encoding is not closed — a verbatim legal name can in principle equal another name's
<stem>-<hash8>output. Triggering it takes a ~2^-32 accident or editing daemon.yaml, which already grants direct access to every skill file and token. Hashing every name would close the gap but was rejected in favor of readable skill names; documented inworkspaceSkillName.Tests
19 new tests in
test/workspace-prompt.test.js: per-agent naming and identity embedding across all four builders, spec compliance for hostile names, collision resistance, determinism, coexisting cursor skills keeping separate identities, the pinned cursor identity header, claude legacy-file cleanup, and openclaw migration (rename, case-alias regression, unprovable ownership, path traversal). OpenClaw tests sandbox the state dir at prototype level so construction never touches a real~/.openclaw.Full suite 715/715 passing.