Repository navigation
Conversation
WorkBuddy has no project-scoped MCP configuration surface. Its only entry is the machine-level ~/.workbuddy/mcp.json, read and written by UserMcpProvider. That file is shared by every project while an aoci MCP server is bound to one --repo, so writing a fixed "aoci" key would silently repoint another repository's integration. - workbuddy.go merges into ~/.workbuddy/mcp.json and never overwrites a foreign aoci entry: it falls back to aoci-<project>, and reports an error when that key is taken as well - IsWorkBuddyMCPInstalled scans every entry for one bound to this repository, so another repository's aoci never reads as installed here - Detect probes the user-level file; a project-root probe would always miss - init --agent workbuddy writes no repository file, so initAgentCandidatePaths returns nil and .gitignore is left alone - the AGENTS.md managed block is prepended for this host only: WorkBuddy injects roughly the first 8000 characters of AGENTS.md into model context, so a trailing block is never read. Every other host keeps appending - --hooks is intentionally inert here; WorkBuddy exposes no pre-write lifecycle hook surface, and the adapter never pretends it installed one
- agent-integrations.md: new WorkBuddy section covering the machine-level configuration shape, the never-overwrite-foreign-entry rule, the inert --hooks, and the prepended managed block; the shared header now names the machine-level file and states why it is the exception to the commit rule - README (en/zh-CN): host lists, prerequisites, host tables, configuration file inventories and the command samples - troubleshooting.md: stale-entry list, the "tools appear in unrelated projects" section (WorkBuddy is the host where scoping cannot be achieved by moving a file), and the .gitignore boundary - CHANGELOG: Unreleased entry
|
I went through this properly, and it's not going into rc18. The design is right; a few things need fixing first, one of them before anyone runs the tests on Windows. The blocker: workbuddy_test.go only sets HOME. On Windows os.UserHomeDir reads USERPROFILE, so the tests write into the real %USERPROFILE%.workbuddy\mcp.json, and two of them overwrite it with Things I reproduced: a file containing Two docs points before it lands. The en-US AGENTS block is about 15,600 characters, so with the 8,000-character window you measured it gets cut in half even when it's first, and a repo already initialised for Claude or Codex keeps its block at the end. Please also put the WorkBuddy version you measured in the docs; right now the README lists it next to hosts we validate ourselves. Smaller: the UI page hard-codes its integration keys, so the new key never renders; "byte-for-byte intact" isn't true after MarshalIndent, "semantically intact" is; the HOME-missing message should mention USERPROFILE on Windows. Fix those and I'll land it on the 0.2.0 line under your name. |
Design discussion: #98
What changes and why
WorkBuddy was not a recognised host. Three concrete consequences:
init --agent workbuddyfailed closed,doctorhad no row for it, and — most consequential —the managed
AGENTS.mdblock is appended at the end of the file, whileWorkBuddy injects only the first few thousand characters of that file into model
context. A trailing block is therefore never read there, so the single written
instruction telling a model to load
aoci_rulesandaoci_overviewbeforestarting work is structurally unreachable on that host.
WorkBuddy is also structurally different from every existing host: it has no
project-scoped MCP surface. Its only entry is the machine-level
~/.workbuddy/mcp.json(read and written byUserMcpProvider);./.mcp.jsonisonly consulted when a plugin declares it. That file is shared by every project
on the machine while an aoci server is bound to one
--repo, so copying theClaude implementation would make
initfor repository B silently repointrepository A's server.
This change adds the host with that constraint respected rather than worked
around: merge into the machine-level file, never overwrite an entry that belongs
to another repository, write nothing into the repository, keep
--hooksinertinstead of emulated, and prepend the managed block for this host alone.
Affected public contracts
--json形状spec/public/合同文本或机器词表(internal/machinecontract)The nine MCP tool names, their schemas and the binary name are untouched.
The CLI change is
init --agentacceptingworkbuddy, plus a newdoctorrow and a newintegrationskey in the read-only UI snapshot.spec/public/is deliberately untouched: it specifies host capability,interaction and delivery contracts and does not enumerate hosts, so no public
contract text changes. All user-visible strings live in the Locale assets, and
both
en-USandzh-CNgain the same keys.Compatibility:
--agent allkeeps its existing claude/codex/cursor set. That setmeans "install project-level host configuration", and silently widening it would
change what
alldoes for every existing user. An older binary that meets aworkbuddykey in~/.workbuddy/mcp.jsonbehaves exactly as it does today — itignores unknown keys in a file it does not manage.
Verification
make fastmake fullpython3 scripts/blackbox/mcp_conformance.pypython3 scripts/blackbox/mcp_scenarios.pypython3 scripts/blackbox/mcp_lifecycle.pyHOME的临时仓库)+ 变更包的对照实验make fastwas run on macOS. Two environment facts, both pre-existing andunrelated to this change:
/varas a symlink to/private/var, andt.TempDir()returnsa
/var/folders/...path. Roughly 70 tests then fail with原子创建父路径不安全: /varorsafe_inventory_git_boundary_mismatch. WithTMPDIR=/private/tmpall of them pass — includinginternal/cli, the largestpackage, which goes to 0 failures.
internal/fsTestProcessIdentityIsStableAndNonEmptystill fails on macOS:process_identity_unix.gois built for darwin and returnsknown=false, whichthe test asserts against. On Linux the
_linuximplementation reads/proc/<pid>/stat, so CI is unaffected. This package is not touched here.Beyond the gate:
internal/cli, the package with the most surface area:identical failure sets before and after, compared by test name. Comparing
whole lines is useless because every line carries a duration.
internal/hooks/workbuddy_test.gocover idempotence,foreign-entry preservation, scoped-key conflict, broken-JSON refusal, existing
config preservation, the "another repository is not installed here" predicate,
Detect, dispatch throughInstall, key sanitisation, and both blockplacements. A second test pins that the default placement is still the append.
HOME: the entrylands in the user file with the right command and
--repo; the working treekeeps no
.mcp.json,.workbuddy,.claude,.codexoropencode.json; asecond repository receives
aoci-<project>while the first entry staysbyte-for-byte intact;
doctorreports the WorkBuddy row; the managed blocklands on line 1 with existing content preserved; a second run changes nothing.
Operating system impact
The installer only writes a JSON file, and path handling reuses the existing
TplDataforward-slash normalisation, so Windows behaves the same as it does forthe other hosts. The host itself was exercised on macOS only, and the
8000character injection limit quoted in the code comments and docs is a measured
property of that host, not a portable constant.
Migration and recovery
No persisted data changes. The only new persistent state is one additional key in
an existing user-level JSON file, written through the same backup-then-atomic-write
path every other installer uses. Removing that key is the complete rollback.
A note for operators already running an older build: overwrite a running
executable with
rmpluscp, notcpalone. Replacing the bytes under a liveprocess left the new binary failing to start with exit code 137 and no output,
while the same file ran normally from its build directory. The old inode stays
alive for the running process, so delete-then-create is the reliable order.
Cognition
Neither box is ticked, and that is accurate rather than an omission. This
does change managed objects:
workbuddy.gois new, and five Go files plus twoLocale assets changed. The first box stays unticked because the governance loop
is not done: it runs through the MCP tools, which are bound to whichever
repository the host started them for, so a contributor working in two checkouts
cannot complete it for the second one without restarting the host — and this
repository's own
aoci checkdoes not start clean. Raised as an open questionin #98 rather than answered by guess. Happy to add the entries in a follow-up
commit if that is the preferred order.