agent-trellis 0.14.1 → 0.15.1

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 (60) hide show
  1. package/dist/adapters/claude-code.js +4 -3
  2. package/dist/adapters/codex.js +4 -3
  3. package/dist/adapters/kimi-code.js +4 -3
  4. package/dist/adapters/kiro.js +5 -4
  5. package/dist/adapters/pi.js +4 -3
  6. package/dist/adapters/zcode.d.ts +12 -1
  7. package/dist/adapters/zcode.js +7 -6
  8. package/dist/cli.js +52 -37
  9. package/dist/commands/doctor.d.ts +9 -1
  10. package/dist/commands/doctor.js +43 -6
  11. package/dist/commands/init.d.ts +6 -0
  12. package/dist/commands/init.js +24 -0
  13. package/dist/commands/mcp.d.ts +69 -3
  14. package/dist/commands/mcp.js +255 -56
  15. package/dist/commands/mcpGateway.js +3 -3
  16. package/dist/commands/migrate.d.ts +12 -0
  17. package/dist/commands/migrate.js +8 -4
  18. package/dist/commands/migrateWorkspace.d.ts +40 -0
  19. package/dist/commands/migrateWorkspace.js +197 -0
  20. package/dist/commands/rollback.js +65 -35
  21. package/dist/commands/skill.d.ts +14 -0
  22. package/dist/commands/skill.js +71 -0
  23. package/dist/commands/sync.d.ts +16 -1
  24. package/dist/commands/sync.js +48 -15
  25. package/dist/core/adapter.d.ts +14 -0
  26. package/dist/core/canonical.d.ts +20 -34
  27. package/dist/core/canonical.js +18 -92
  28. package/dist/core/mcpServerDef.d.ts +39 -0
  29. package/dist/core/mcpServerDef.js +93 -0
  30. package/dist/core/types.d.ts +39 -4
  31. package/dist/lib/cliArgs.d.ts +17 -0
  32. package/dist/lib/cliArgs.js +36 -0
  33. package/dist/lib/mcpMigrateRead.d.ts +25 -0
  34. package/dist/lib/mcpMigrateRead.js +9 -2
  35. package/dist/lib/scopeSelection.d.ts +1 -1
  36. package/dist/lib/scopeSelection.js +4 -3
  37. package/dist/lib/skillProvider.js +18 -5
  38. package/dist/lib/workspace.d.ts +39 -0
  39. package/dist/lib/workspace.js +158 -0
  40. package/dist/lib/workspaceConfig.d.ts +51 -0
  41. package/dist/lib/workspaceConfig.js +117 -0
  42. package/dist/lib/workspaceDoctor.d.ts +44 -0
  43. package/dist/lib/workspaceDoctor.js +94 -0
  44. package/dist/lib/workspaceFiles.d.ts +38 -0
  45. package/dist/lib/workspaceFiles.js +264 -0
  46. package/dist/lib/workspaceMcp.d.ts +57 -0
  47. package/dist/lib/workspaceMcp.js +277 -0
  48. package/dist/lib/workspaceMerge.d.ts +37 -0
  49. package/dist/lib/workspaceMerge.js +98 -0
  50. package/dist/lib/workspaceMigrate.d.ts +118 -0
  51. package/dist/lib/workspaceMigrate.js +423 -0
  52. package/dist/pi-bridge/bundle.js +258 -96
  53. package/docs/architecture.md +111 -49
  54. package/docs/getting-started.md +86 -14
  55. package/docs/mcp-oauth-matrix.md +12 -1
  56. package/docs/overview.zh-CN.md +17 -0
  57. package/docs/research.md +28 -6
  58. package/docs/roadmap.md +17 -5
  59. package/package.json +1 -1
  60. package/docs/implementation-plan.md +0 -341
@@ -10,8 +10,8 @@ required reading for that.
10
10
 
11
11
  ```
12
12
  ┌─────────────────────────────────────────────────────────┐
13
- │ Trellis canonical source (~/.trellis — global only, see │
14
- │ "Global vs. workspace scope" below) │
13
+ │ Trellis canonical source (~/.trellis global + <repo>/.agents, │
14
+ │ see "Global vs. workspace scope" below) │
15
15
  │ instructions · skills · agents · mcp/servers.yaml · │
16
16
  │ memories · secrets policy │
17
17
  └───────────────┬─────────────────────────────────────────┘
@@ -19,8 +19,8 @@ required reading for that.
19
19
  ┌───────┼────────┬─────────────┬──────────────┐
20
20
  ▼ ▼ ▼ ▼
21
21
  Claude Code Codex Kiro pi Kimi Code ZCode
22
- (symlink adapter) (incremental (symlink adapter) (bridge
23
- TOML writer) extension)
22
+ (symlink adapter) (incremental (symlink adapter) (native
23
+ TOML writer) mcp.json)
24
24
  ```
25
25
 
26
26
  Trellis owns exactly one thing: **the canonical source, and the generators
@@ -56,19 +56,77 @@ Aligned to the `.agents Protocol` draft, extended where the draft is silent:
56
56
 
57
57
  ## Global vs. workspace scope
58
58
 
59
- **Global only, for now.** Trellis manages `~/.trellis` — one canonical
60
- source per machine, applied to that machine's six supported agents. It does not yet
61
- read or merge a project-local `.trellis/` in a specific repo.
59
+ Two layers, both canonical: `~/.trellis` per machine (global) and
60
+ `<repo>/.agents/` per project (workspace). A repo opts in by containing
61
+ `.agents/`; `trellis sync` discovers the nearest ancestor `.agents/`
62
+ walking up from the cwd (`findWorkspaceRoot` in `src/lib/workspace.ts` —
63
+ `~/` itself is never picked up as a workspace root) and merges the two
64
+ layers. Outside any workspace the plan is byte-identical to the old
65
+ global-only behavior; `--global-only` opts out explicitly.
62
66
 
63
- The `.agents Protocol` draft (see `research.md`) describes a two-layer
64
- merge — global defaults, workspace overrides on top, closest wins. That
65
- model is a reasonable target eventually, but it's explicitly **out of
66
- scope until a later phase**: it adds real complexity (merge precedence,
67
- per-project drift, a second place secrets policy has to be checked) that
68
- isn't justified before the single-layer global case is solid. Don't build
69
- workspace resolution ahead of that decision — if you find yourself adding
70
- a `root?: string` parameter or precedence logic to `loadCanonicalSource`,
71
- that's scope creep against this section, not a natural extension.
67
+ ```
68
+ .agents/
69
+ ├── config.json # { "version": 1, mcp.servers } — the same
70
+ │ # snake_case schema and validator as
71
+ │ # mcp/servers.yaml; one schema, one validator
72
+ ├── AGENTS.md # workspace instructions
73
+ ├── skills/<name>/SKILL.md
74
+ └── .trellis-rendered.json # Trellis's ownership manifest — committable;
75
+ # what a fresh clone re-attaches through
76
+ ```
77
+
78
+ Merge semantics (`src/lib/workspaceMerge.ts`): workspace wins by ID for
79
+ MCP servers and skills; `enabled: false` tombstones a global entry for
80
+ this project only; instructions are not content-merged (a workspace
81
+ `AGENTS.md` stands on its own layer). Provenance and the
82
+ shadowed/tombstoned lists ride on the canonical source so `trellis
83
+ doctor` can attribute every entry to its layer.
84
+
85
+ Delivery is layer-preserving — Trellis never re-renders global content
86
+ into project files. Global entries go to the agents' user-level paths as
87
+ before; workspace entries go to project-level native paths (`.mcp.json`,
88
+ `.codex/config.toml`, `.kiro/settings/mcp.json`, `.pi/mcp.json`,
89
+ `.kimi-code/mcp.json`, `zcode.json`/`.zcode/config.json`). The agents
90
+ then layer natively: five of six resolve project-over-user; zcode
91
+ resolves same-name MCP conflicts user-first, so a shadowing workspace
92
+ server gets an explicit sync warning instead of a silent no-op. Skills
93
+ are *copied* (not symlinked — rendered artifacts must be committable and
94
+ work without symlink support) into `.claude/skills/` and `.kiro/skills/`
95
+ with digest-based drift detection, while Codex/pi/Kimi read
96
+ `.agents/skills/` natively. Instructions render as marker-headed copies:
97
+ root `AGENTS.md` for Codex/pi/Kimi and `.kiro/steering/
98
+ trellis-workspace.md` for Kiro; Claude's `CLAUDE.md` is never written
99
+ (v1 limitation — `migrate --workspace` is the path for absorbing a
100
+ hand-written one).
101
+
102
+ Two invariants make the workspace layer safe to commit:
103
+
104
+ - **No secrets in the repo.** Workspace `config.json` rejects
105
+ credential-shaped literals at load (the same `reject_patterns` as the
106
+ global secrets policy) and accepts only `${VAR}` references; rendered
107
+ artifacts likewise carry references, never resolved values. Secret
108
+ values live in the machine-local store (`secrets.policy.yaml`'s
109
+ `env_file`) and are re-established per machine —
110
+ `migrate --workspace` extracts any literal it finds in a hand-written
111
+ project file into that store (and flags git-tracked plaintext with a
112
+ rotation advisory).
113
+ - **Ownership travels with the repo.** `.agents/.trellis-rendered.json`
114
+ records what Trellis rendered per agent per server; an entry present
115
+ in an agent's file but absent from the manifest is user-authored and
116
+ never overwritten. Because the manifest is committed, a fresh clone —
117
+ or a copied directory — re-attaches cleanly instead of
118
+ conflict-guarding on its own committed artifacts.
119
+
120
+ `trellis sync --check` computes the identical plan with zero writes and
121
+ exits non-zero on drift — the CI freshness gate for committed artifacts.
122
+ Existing hand-written project config is adopted with
123
+ `trellis migrate --workspace`: it scans all six agents' project-level
124
+ paths plus the root `AGENTS.md`, classifies every find (create /
125
+ already-managed / identical-to-global / skip-local / skip-unsupported /
126
+ conflict / extract-secret), refuses the whole run on unresolved
127
+ conflicts, then imports and re-renders inside a single backup session so
128
+ one `trellis rollback` restores originals and removes generated
129
+ `.agents/` content.
72
130
 
73
131
  ## Private / agent-specific capabilities
74
132
 
@@ -163,17 +221,19 @@ populates `~/.pi/agent/skills` on its own. (This corrects an earlier,
163
221
  pre-P0 assumption that pi needed "no adapter" for skills/instructions;
164
222
  that was written before pi's actual global discovery directory was
165
223
  confirmed, when it wasn't yet known whether canonical skills would ever
166
- reach it without one.) MCP is the one place pi is genuinely different: it
167
- needs a real bridge either way, but which shape depends on `mcp.hub`:
168
- without it, the bridge extension opens N `@modelcontextprotocol/sdk` stdio
169
- clients (one per server) and registers each one's tools through pi's
170
- `registerTool` API; with `mcp.hub` set, it opens exactly one HTTP client to
171
- the hub instead — meaningfully less code and one fewer class of failure
172
- (N processes to keep alive vs. one connection). This is the one piece of
173
- the project that is an agent runtime extension, not a config generator,
174
- regardless of hub mode.
175
-
176
- The pi bridge symlink follows the currently executing Trellis installation.
224
+ reach it without one.) MCP on pi ≥ 1.1.0 is native: the adapter merges
225
+ entries into `~/.pi/agent/mcp.json` — a `trellis mcp-gateway --agent pi`
226
+ stdio entry under gateway mode (or `mcp-runtime` under runtime delivery),
227
+ a single hub-URL entry under hub mode, direct entries otherwise — with
228
+ agent-owned OAuth servers written as bare `{url}` entries that
229
+ `pi mcp login` authorizes (an optional canonical `auth.client_name`
230
+ renders as `oauth.clientName` for providers that gate dynamic client
231
+ registration by name, e.g. Figma). On pi < 1.1.0 the legacy bridge
232
+ extension (`src/pi-bridge/`, symlinked into `~/.pi/agent/extensions/`) is
233
+ still planned instead; it is deprecated and scheduled for removal.
234
+
235
+ The legacy bridge symlink follows the currently executing Trellis
236
+ installation.
177
237
  When switching from a checkout to a global package (or between installation
178
238
  roots), sync can repair an outside-root link only if its target ends in
179
239
  `dist/pi-bridge/bundle.js` and its bytes match the current bridge bundle.
@@ -211,12 +271,14 @@ to the code writing one entry that points at it.
211
271
  - Every adapter writes ONE entry instead of N. This is most of the value:
212
272
  adding a new backend server means editing wherever the hub's own config
213
273
  lives (this project doesn't prescribe that either) and never touching
214
- any of the five agents' configs or restarting them, if the hub supports
274
+ any of the six agents' configs or restarting them, if the hub supports
215
275
  live reload (mcp-hub does, via SSE).
216
276
  - The collision check against `known_host_injected` (docs/research.md
217
277
  §"Codex — three hard constraints") shrinks to checking one name instead
218
278
  of N, since there's nothing else locally defined to collide with.
219
- - pi's bridge (P4) becomes one HTTP client instead of N stdio clients.
279
+ - pi gets one hub-URL entry in its native mcp.json instead of N direct
280
+ entries (pre-1.1.0: the legacy bridge opens one HTTP client instead of N
281
+ stdio clients).
220
282
 
221
283
  **What doesn't change:** the boundary with mirasim (docs/research.md §3)
222
284
  is unaffected — `mcp.hub`, self-hosted or not, only ever carries the
@@ -253,11 +315,11 @@ there (not silently dropped) while still reaching every other agent.
253
315
 
254
316
  **Real OAuth** (browser redirect, short-lived access token, refresh
255
317
  token) was, for most of this project's life, deliberately not built:
256
- all three native-config agents already have their own working flow —
318
+ all the native-config agents already have their own working flow —
257
319
  Claude Code's `claude mcp add --client-id/--client-secret/--callback-port`,
258
320
  Codex's `codex mcp login`/`logout` pair, Kiro's `oauth`/`oauthScopes`
259
- fields — and pi, whose bridge is Trellis's own code, simply couldn't
260
- reach such a server at all.
321
+ fields, pi's `pi mcp login` (native since pi 1.1.0; the legacy bridge
322
+ could not reach such a server at all).
261
323
 
262
324
  Gateway mode does not automatically take ownership of OAuth servers. Mark a
263
325
  server explicitly with `auth: oauth` (or `trellis mcp set <name> --auth oauth`)
@@ -400,7 +462,7 @@ Trellis MCP Runtime
400
462
  │ ├─ SkillProvider (read/search canonical skills)
401
463
  │ ├─ RuntimeMemoryProvider
402
464
  │ │ └─ CanonicalMemoryProvider (read-only canonical Markdown)
403
- │ └─ StatusProvider (future read-only diagnostics)
465
+ │ └─ StatusProvider (read-only diagnostics)
404
466
  └─ UpstreamProvider
405
467
  └─ existing GatewayBackend / future RemoteBackend
406
468
  ```
@@ -542,26 +604,26 @@ development, not in CI, not for a "quick manual check." A bug in an adapter
542
604
  that patches TOML in place is exactly the kind of thing that corrupts a
543
605
  real config file if it's tested against one.
544
606
 
545
- **Exception: pi.** This rule protects real state a person depends on — the
546
- other three agents' adapters patch that state in place (symlinks over real
547
- directories, in-place TOML/JSON edits). pi's adapter never does: skills/
548
- instructions are the same symlink-or-noop regardless of machine, and the
549
- MCP bridge (P4) is a single already-symlinked extension file that reads a
550
- separate, Trellis-owned `servers.yaml` rather than writing into anything pi
551
- itself depends on. A temporary, narrowly-scoped `~/.trellis/mcp/servers.yaml`
552
- (deleted afterward) plus a real `pi -p` run therefore carries none of the
553
- corruption risk this section exists to prevent, and it's the only way to
554
- observe pi's actual extension-loading behavior on *this* installed pi/jiti
555
- version — `docker/pi-sandbox.Dockerfile` verifies the same jiti-tolerance in
556
- general (P4's own acceptance criteria), but doesn't stand in for a
557
- spot-check against a specific real installation. Real-machine verification
558
- of pi specifically is therefore permitted, not a hard-rule violation — the
559
- other three agents are not exempted.
607
+ **Exception: pi (bridge era, kept as history).** This rule protects real
608
+ state a person depends on — the other agents' adapters patch that state in
609
+ place (symlinks over real directories, in-place TOML/JSON edits). In the
610
+ bridge era pi's adapter never did: skills/instructions were the same
611
+ symlink-or-noop regardless of machine, and the MCP bridge (P4) was a
612
+ single already-symlinked extension file that read a separate,
613
+ Trellis-owned `servers.yaml` rather than writing into anything pi itself
614
+ depended on, so a temporary, narrowly-scoped `~/.trellis/mcp/servers.yaml`
615
+ plus a real `pi -p` run carried none of the corruption risk this section
616
+ exists to prevent. Since pi 1.1.0 the adapter merges
617
+ `~/.pi/agent/mcp.json` in place like every other adapter, so **this
618
+ exception no longer applies to MCP config** — real-machine pi verification
619
+ (the v0.14.0 managed migration, for example) follows the standard
620
+ discipline: backup, dry-run, then a scoped apply. The paragraph is kept
621
+ because the bridge extension still exists as the pre-1.1.0 fallback.
560
622
 
561
623
  Verification happens against an isolated environment instead: a scratch
562
624
  `$HOME` (or a container with one mounted) populated with synthetic
563
625
  per-agent config that looks like the real thing but is expendable — created
564
- fresh, asserted against, thrown away. `docs/implementation-plan.md`'s P1
626
+ fresh, asserted against, thrown away. `docs/archive/implementation-plan.md`'s P1
565
627
  acceptance criteria already describes this shape ("point at a scratch
566
628
  `$HOME`... run `trellis sync skills`... confirm zero findings"); this
567
629
  section exists to make it a project-wide rule that every later phase's
@@ -496,8 +496,8 @@ Trellis resolves `CODEX_HOME` when set, otherwise `~/.codex`, and reads only
496
496
  the Memory directory. `AGENTS.md`, `session_index.jsonl`, sessions,
497
497
  credentials, and plugin state are never treated as memory.
498
498
 
499
- **MCP servers** (claude-code, kiro, codex — not pi, which has no static
500
- MCP config to read at all) migrate the same way, into
499
+ **MCP servers** (claude-code, kiro, codex, kimi-code, zcode — not pi, whose
500
+ mcp.json migrate-in is not implemented) migrate the same way, into
501
501
  `~/.trellis/mcp/servers.yaml`:
502
502
 
503
503
  ```
@@ -821,6 +821,69 @@ automatically, so `trellis rollback` can undo the whole run later — see
821
821
  [`trellis rollback`](#trellis-rollback--undoing-a-syncmcp-synconboard-run)
822
822
  below.
823
823
 
824
+ ## Workspace scope — per-project config in the repo
825
+
826
+ Everything above manages `~/.trellis`, one canonical source per machine.
827
+ A project can carry its own layer in the repo itself, under `.agents/` —
828
+ committable by design, shared with every teammate and agent that checks
829
+ it out:
830
+
831
+ ```
832
+ $ cd your-repo
833
+ $ trellis init --workspace # scaffold .agents/ (fill-missing-only)
834
+ ```
835
+
836
+ ```
837
+ .agents/
838
+ ├── config.json # { "version": 1, mcp.servers } — same schema
839
+ │ # as ~/.trellis/mcp/servers.yaml
840
+ ├── AGENTS.md # workspace instructions
841
+ ├── skills/<name>/SKILL.md
842
+ └── .trellis-rendered.json # Trellis's ownership manifest — commit it too
843
+ ```
844
+
845
+ Edit those files directly, or use the CLI with `--workspace`
846
+ (`trellis mcp add <name> --workspace`, `trellis skill add <name> --from ... --workspace`).
847
+ Then, from anywhere inside the repo:
848
+
849
+ ```
850
+ $ trellis sync # global layer + workspace layer together
851
+ $ trellis sync --global-only # global only, even inside a workspace
852
+ ```
853
+
854
+ The workspace layer wins on ID conflicts with the global one (and
855
+ `enabled: false` in `config.json` tombstones a global server for this
856
+ project). Rendered artifacts — `.mcp.json`, `.codex/config.toml`,
857
+ `.pi/mcp.json`, skill copies under `.claude/skills/`, the marker-headed
858
+ root `AGENTS.md`, … — are meant to be **committed** alongside `.agents/`.
859
+ They contain only `${VAR}` references, never secret values, and
860
+ `.agents/config.json` itself refuses credential-shaped literals at load;
861
+ actual values live in each machine's local secret store and are
862
+ re-established per machine. CI keeps the committed artifacts honest:
863
+
864
+ ```
865
+ $ trellis sync --check # zero writes; exit 1 naming any stale file
866
+ ```
867
+
868
+ Already have hand-written project config (a `.mcp.json`, a
869
+ `.codex/config.toml`, a root `AGENTS.md`)? Absorb it instead of
870
+ rewriting by hand:
871
+
872
+ ```
873
+ $ trellis migrate --workspace --dry-run # preview the classified plan
874
+ $ trellis migrate --workspace # import + re-render, one
875
+ # backup session — `trellis
876
+ # rollback` undoes the whole thing
877
+ ```
878
+
879
+ The scanner inventories all six agents' project-level paths, skips
880
+ `*.local.*` files unread, extracts plaintext secrets into the global
881
+ secret store as `${VAR}` references (with a rotation advisory when the
882
+ literal was git-tracked), and refuses the run on unresolved conflicts —
883
+ pick a side with `--choose name=agentId`, or import an
884
+ identical-to-global entry as an intentional shadow with
885
+ `--dedup override`.
886
+
824
887
  ## `trellis mcp sync`
825
888
 
826
889
  Distributes `~/.trellis/mcp/servers.yaml` to every **managed** agent's
@@ -915,9 +978,13 @@ stay direct while ordinary remote servers remain shared through the gateway.
915
978
 
916
979
  ### `trellis mcp auth <server-name>`
917
980
 
918
- For a remote (`http`/`sse`) server marked `auth: oauth`, native Agents should
919
- use their own login command. Pi's direct bridge path can be authorized once
920
- through Trellis:
981
+ Authorization ownership is explicit per server (the full model is
982
+ [`mcp-authorization-ownership.md`](mcp-authorization-ownership.md)):
983
+ **agent-owned** OAuth servers (plain `auth: oauth`) are authorized by the
984
+ Agent's own login command — `claude mcp` / `codex mcp login` /
985
+ `pi mcp login <name>` — and Trellis never touches their tokens. **Trellis-owned**
986
+ servers (`auth: { kind: oauth, owner: trellis }`) connect through the
987
+ gateway/runtime on a credential Trellis holds, authorized once through:
921
988
 
922
989
  ```
923
990
  $ trellis mcp auth notion-remote
@@ -929,17 +996,19 @@ This opens your browser, completes the flow, and stores the result 0600
929
996
  under `~/.trellis/mcp/oauth/` — never in `servers.yaml`, so canonical
930
997
  stays safe to read, diff, and commit.
931
998
 
932
- Run it once per server when Pi's direct bridge owns the OAuth connection.
933
- After that the bridge refreshes the token silently whenever it expires; it
934
- never opens a browser and never prompts, because it is spawned by an agent
935
- with no terminal attached. Re-running
999
+ Run it once per Trellis-owned server. After that the gateway refreshes the
1000
+ token silently whenever it expires; it never opens a browser and never
1001
+ prompts, because it is spawned by an agent with no terminal attached.
1002
+ Re-running
936
1003
  this command when the stored token is still valid does nothing (`--force`
937
1004
  overrides); when it has expired but is renewable, it refreshes without a
938
- browser.
1005
+ browser. `trellis mcp renew` does the same non-interactively for every
1006
+ Trellis-owned server that can be renewed without a browser.
939
1007
 
940
- If a Pi direct OAuth server has no stored credential, the bridge skips that
941
- one server and keeps serving every other — it does not fail to start. Native
942
- Agents report the same direct entry as requiring their own authorization.
1008
+ If a Trellis-owned OAuth server has no stored credential, the gateway skips
1009
+ that one server and keeps serving every other — it does not fail to start.
1010
+ Agent-owned servers in the same route are unaffected: the Agent's own client
1011
+ reports them as requiring its own authorization.
943
1012
 
944
1013
  An Agent can call the read-only `trellis.mcp.status` Runtime tool to explain
945
1014
  this partial state to the user. It reports unavailable or authorization-
@@ -1083,7 +1152,10 @@ $ trellis doctor
1083
1152
  ```
1084
1153
 
1085
1154
  Read-only. Scans all six agents' current state and reports drift —
1086
- mismatched skill content across agents, wrong-case skill files, and (with
1155
+ mismatched skill content across agents, wrong-case skill files, OAuth
1156
+ credential health for Trellis-owned servers (the same read-only
1157
+ classification as `trellis mcp renew` and the `trellis.mcp.status` Runtime
1158
+ tool, so the three never disagree), and (with
1087
1159
  `--probe-mcp`) whether each configured MCP server actually handshakes.
1088
1160
  Safe to run any time; nothing here writes anything.
1089
1161
 
@@ -41,7 +41,18 @@ per-provider list, is what Trellis commits to.
41
41
  | Notion | DCR-open | `client_id` from DCR | Same | Medium |
42
42
  | Linear | DCR-open | `client_id` from DCR | Same | Medium |
43
43
  | Cloudflare | DCR-open | `client_id` from DCR | Same | Medium |
44
- | Figma | Allowlist | Provider-published `client_id`, supplied by the user | Registration refused with `unauthorized_client` — observed directly, and the reason this change exists | High |
44
+ | Figma | DCR gated by client_name | `client_id` from DCR, issued only when the self-asserted `client_name` is on Figma's beta allowlist | Registration with an unknown name (e.g. `pi`, `Trellis`) refused with a bare 403; `Claude Code` succeeds — observed directly 2026-10-11 (oauth-client-name) | High |
45
+
46
+ **Figma, updated.** The row above supersedes an earlier classification of
47
+ Figma as plain Allowlist ("no self-service path"). What Figma actually gates
48
+ is the `client_name` a client asserts at registration, not possession of a
49
+ pre-issued `client_id`: the same registration endpoint answers 403 for
50
+ `pi`/`Trellis` and 200 for an allowlisted name, independent of User-Agent.
51
+ The working path is therefore agent-owned auth plus a declared canonical
52
+ `auth.client_name` (rendered into the agent's own registration, e.g. pi's
53
+ `oauth.clientName`). Trellis-hosted DCR hardcodes `client_name: "Trellis"`
54
+ (`src/lib/oauth/flow.ts`) and would be refused for Figma until Trellis's own
55
+ name is allowlisted or the field is wired through there too.
45
56
 
46
57
  **On confidence.** "High" means the behavior was observed directly against the
47
58
  live provider and the failure (or success) is reproducible from this
@@ -71,6 +71,22 @@ Trellis Runtime / Gateway
71
71
  └── MCP Runtime ────── Kimi Code / ZCode / 其他 Runtime-first Agent
72
72
  ```
73
73
 
74
+ ### 所有权边界(Ownership boundary)
75
+
76
+ - `~/.trellis/` 是 canonical source 和策略边界。
77
+ - 各 Agent 的原生目录是投影,不是独立的事实源。
78
+ - Gateway/Runtime 负责连接路由和 Provider 暴露,不接管 Agent 的私有会话。
79
+ - 凭证不进入 canonical YAML,在运行时解析。
80
+ - Runtime Provider 将 Memory、MCP 输出和任务记录视为不可信上下文。
81
+
82
+ ## 投递模式(Delivery modes)
83
+
84
+ | 模式 | 含义 | 典型场景 |
85
+ |---|---|---|
86
+ | `native` | 将能力投影到 Agent 的原生配置 | 最大化原生兼容性 |
87
+ | `mcp` | 通过 Runtime MCP 边界消费 Trellis 能力 | Kimi Code 等 Runtime-first Agent |
88
+ | `both` | 过渡期同时保留 native 和 Runtime 投递 | 兼容性迁移 |
89
+
74
90
  ## 与相似产品的关系
75
91
 
76
92
  | 产品/类别 | 主要解决的问题 | Trellis 的区别 |
@@ -79,6 +95,7 @@ Trellis Runtime / Gateway
79
95
  | [MCP Router](https://github.com/mcp-router/mcp-router) | 桌面 MCP 管理、Workspace、Provider 和日志 | 可作为 Trellis 的导入源或上游;Trellis 自己维护 canonical MCP 状态 |
80
96
  | [MetaMCP](https://github.com/metatool-ai/metamcp) / [mcp-hub](https://github.com/ravitemer/mcp-hub) | MCP 聚合和统一入口 | Trellis 额外负责不同 Agent 的 native 适配、生命周期和安全同步 |
81
97
  | [OpenViking](https://github.com/volcengine/OpenViking) | Memory、资源和 Skill 的上下文数据库 | Trellis 可将其接入 Memory/Context Provider,作为底层上下文服务 |
98
+ | Agent 编排平台 | 启动 worker、调度任务、协调执行 | Trellis 目前只提供持久化任务交接记录和租约,不隐式远程执行 Agent;执行层是明确的未来方向 |
82
99
 
83
100
  ## 术语约定
84
101
 
package/docs/research.md CHANGED
@@ -3,6 +3,13 @@
3
3
  Surveyed 2026-09-11. This is why Trellis is a thin orchestration layer, not a
4
4
  from-scratch rebuild of anything below.
5
5
 
6
+ > **Currency note (2026-10-11, doc governance):** this is a research/history
7
+ > document — sections are dated snapshots of what was true when surveyed, and
8
+ > some "decided not to build" / "future direction" passages have since been
9
+ > implemented (gateway/runtime, skills-over-MCP, pi native MCP). Where a
10
+ > section conflicts with [`architecture.md`](architecture.md), architecture.md
11
+ > is current. Inline markers flag the known-superseded spots.
12
+
6
13
  ## Rules / skills sync (crowded — don't rebuild)
7
14
 
8
15
  | Project | Covers | Kiro | pi | MCP | Memory | Secrets |
@@ -50,7 +57,11 @@ specifies).
50
57
  | [mcp-router](https://github.com/mcp-router/mcp-router) | — | Desktop app + CLI, Sustainable Use License | Already deployed in this environment; token-based, has a GUI. **First-hand incident**: its `MCPR_TOKEN` existed in three different values across `secrets.env`/`config.toml`/`kiro/mcp.json` simultaneously, one silently invalid — see below |
51
58
 
52
59
  Decision: Trellis still does not implement aggregation/routing logic
53
- itself. It generates native MCP config for each agent directly — that's
60
+ itself. *(Superseded 2026-10: gateway mode and the Trellis MCP Runtime now
61
+ do exactly this in-process — see architecture.md "Gateway mode" and the
62
+ BuiltinRegistry/UpstreamProvider diagram; the hub-mode support described
63
+ below remains as the external-endpoint option.)* It generates native MCP
64
+ config for each agent directly — that's
54
65
  what actually needed solving, since none of the above touch Kiro/pi/Codex's
55
66
  TOML format. But it now natively *supports* routing every agent through a
56
67
  single external endpoint instead of N direct definitions ("hub mode," see
@@ -68,6 +79,10 @@ before hub mode existed as a documented option.
68
79
 
69
80
  ### MCP Runtime / built-in capability direction — confirmed architecture
70
81
 
82
+ *(Implemented: SkillProvider, RuntimeMemoryProvider and StatusProvider ship
83
+ in v0.12–v0.14 exactly in this shape — this section is the pre-implementation
84
+ confirmation, kept as the design's origin.)*
85
+
71
86
  The next abstraction is broader than a skill-only MCP server. MCP defines
72
87
  tools, resources, and prompts with different control models, so a Trellis
73
88
  runtime should host a registry of providers rather than make every new
@@ -93,6 +108,11 @@ scripts by default.
93
108
 
94
109
  ### Local Claude Code / pi dogfood — 2026-09-18
95
110
 
111
+ *(Bridge-era snapshot: "the packaged MCP bridge" below refers to the pi
112
+ bridge extension, retired as the default delivery by pi 1.1.0 native MCP in
113
+ v0.14.0. The findings about tool-surface size and route granularity are
114
+ still valid.)*
115
+
96
116
  After an external, credential-minimized host snapshot, the managed set was
97
117
  narrowed from all four agents to Claude Code and pi through `trellis manage
98
118
  set`. Hashes of Codex and Kiro's relevant native state were identical before
@@ -245,12 +265,14 @@ Reverse-engineered directly from the installed binary
245
265
  not supported"` — that era is why the bridge extension below exists.
246
266
  - pi's capability surface is **extensions**: JS modules loaded via
247
267
  `--extension`/discovery, with a real API (`createExtension`,
248
- `registerTool`). Giving pi access to the same MCP servers every other agent
249
- uses means writing a bridge extension that spins up
268
+ `registerTool`). *(Superseded as the default path: since pi 1.1.0, Trellis
269
+ writes pi's native `mcp.json` directly — trellis-pi-native-mcp-migration,
270
+ v0.14.0. The bridge extension remains only as the pre-1.1.0 fallback and
271
+ is scheduled for removal.)* Giving pi access to the same MCP servers
272
+ every other agent uses meant writing a bridge extension that spins up
250
273
  `@modelcontextprotocol/sdk` stdio clients from `mcp.json` and registers
251
- their tools through this API. This is the one adapter in Trellis that is
252
- genuine code, not config templating — see
253
- [`src/adapters/pi/`](../src/adapters/pi).
274
+ their tools through this API — the one adapter in Trellis that is genuine
275
+ code, not config templating.
254
276
 
255
277
  ## Cross-machine / cloud sharing — surveyed 2026-09-15, future direction confirmed
256
278
 
package/docs/roadmap.md CHANGED
@@ -1,10 +1,13 @@
1
1
  # Roadmap
2
2
 
3
+ *Current release: v0.14.1 (2026-10-11). This file tracks phase-level scope;
4
+ per-release detail lives in [`releases/`](releases/).*
5
+
3
6
  Each phase must ship with a `trellis doctor` check that verifies its own
4
7
  claim — no phase is "done" on the strength of a config file existing, only
5
8
  on the strength of a passing verification against the real running agent.
6
9
 
7
- See [`implementation-plan.md`](implementation-plan.md) for P1–P4 broken down
10
+ See [`archive/implementation-plan.md`](archive/implementation-plan.md) for P1–P4 broken down
8
11
  to file/function level.
9
12
 
10
13
  **P0 is done and archived** (`openspec/changes/archive/2026-09-12-trellis-doctor-p0/`;
@@ -21,7 +24,7 @@ had a much larger blast radius than "read-only" should mean.
21
24
 
22
25
  This is the format every later phase uses: one `openspec/changes/<phase>/`
23
26
  directory per phase, `openspec new change <name>` → tasks implemented →
24
- `openspec archive <name>`. `implementation-plan.md`'s P0/P1 sections are
27
+ `openspec archive <name>`. `archive/implementation-plan.md`'s P0/P1 sections are
25
28
  kept only as historical notes; don't edit them further.
26
29
 
27
30
  **P1 is done and archived** (`openspec/changes/archive/2026-09-12-trellis-sync-p1/`;
@@ -933,7 +936,7 @@ tests passing.
933
936
  | P1 | ✅ `trellis sync skills` / `trellis sync instructions` — symlink-based distribution to Claude Code, Codex, Kiro, and pi | P0 |
934
937
  | P2 | ✅ `trellis mcp sync` — incremental, in-place adapters for Claude Code (JSON merge), Codex (TOML section patch), Kiro (JSON merge); collision check against known host-injected server names | P1 |
935
938
  | P3 | ✅ `trellis secrets audit` — scans every adapter's output for literal credential patterns and unexpected env var names, fails non-zero on any hit | P2 |
936
- | P4 | ✅ pi bridge extension — MCP tool registration via `registerTool`, sourced from the same `mcp/servers.yaml` | P2 |
939
+ | P4 | ✅ pi bridge extension — MCP tool registration via `registerTool`, sourced from the same `mcp/servers.yaml`. **Superseded as the default by v0.14.0** (pi ≥ 1.1.0 native MCP, trellis-pi-native-mcp-migration): the bridge is now the pre-1.1.0 fallback only, and `src/pi-bridge/` is scheduled for removal one release later | P2 |
937
940
  | P5 | ✅ `@trellis/sdk` — read-only API over the canonical source, for third-party agents to consume without depending on the CLI | P1–P4 stable |
938
941
  | P6 | ✅ Memory: document and wire the `server-memory` default; write the mem0/OpenMemory upgrade guide | P2 |
939
942
  | P7 | ✅ Secrets/env management: shared `resolveSecretEnv` + `secrets.policy.yaml`'s `env_file`, pi bridge stops reading raw ambient env, `secrets audit` gains a `missing-env-value` check | P3, P4 |
@@ -957,9 +960,18 @@ tests passing.
957
960
 
958
961
  | P25 | ✅ Onboard prompt TUI: replaces Trellis's hand-written raw-mode picker and ANSI redraw logic with `@clack/prompts`, preserving non-TTY fallbacks, `--json`, stream-injected tests, stderr-only interactive chrome, and compact agent summaries that show counts instead of enumerating skills. Full-screen TUI runtimes remain out of scope; onboarding stays visible in terminal scrollback | P22 |
959
962
  | P26 | ✅ Fine-grained capability selection: item-level skill/MCP/memory selection from a serializable selection file or searchable TUI, per-agent MCP route overrides with direct/gateway/hub precedence, selected-memory sync without implicit native-memory import, and explicit unsupported-reader diagnostics | P17, P21, P22, P25 |
960
- | P27 | 🚧 Trellis MCP Runtime phase 1 ✅: one provider registry and agent-facing MCP edge; SkillProvider and the read-only CanonicalMemoryProvider expose scoped progressive-disclosure tools/resources, runtime delivery supports native/mcp/both per agent, selected upstream tools mount through the existing GatewayBackend, and doctor checks runtime drift. Remaining: upstream resource/prompt backend, real pi/Kiro model smoke, and real Claude model smoke (Claude remains intentionally deferred) | P21, P25, P26 |
961
- | P28 | 🚧 Kimi Code Runtime-first adapter: Kimi is recognized as a managed Agent, receives one deferred `trellis` Runtime entry in `~/.kimi-code/mcp.json`, and `trellis kimi` isolates native Skill discovery for Runtime-only delivery. The Runtime Skill is available through SkillProvider; remaining: real Kimi model-session smoke and upstream resource/prompt consumption | P27 |
963
+ | P27 | 🚧 Trellis MCP Runtime phase 1 ✅: one provider registry and agent-facing MCP edge; SkillProvider and the read-only CanonicalMemoryProvider expose scoped progressive-disclosure tools/resources, runtime delivery supports native/mcp/both per agent, selected upstream tools mount through the existing GatewayBackend, upstream **resources** ship (v0.12.0), and doctor checks runtime drift. Remaining: upstream **prompts** backend, real pi/Kiro model smoke, and real Claude model smoke (Claude remains intentionally deferred) | P21, P25, P26 |
964
+ | P28 | 🚧 Kimi Code Runtime-first adapter: Kimi is recognized as a managed Agent, receives one deferred `trellis` Runtime entry in `~/.kimi-code/mcp.json`, and `trellis kimi` isolates native Skill discovery for Runtime-only delivery. The Runtime Skill is available through SkillProvider; upstream resources ship (v0.12.0). Remaining: real Kimi model-session smoke and upstream prompt consumption | P27 |
962
965
  | P29 | ✅ ZCode Runtime-first adapter: `zcode` is a managed Agent with profile-aware static configuration (`~/.zcode/cli/config.json` for official profiles and `setting.json` for the local community CLI), a single owned Runtime MCP entry, scoped-Skill isolation, safe instruction/MCP migration, doctor/onboarding coverage, and public-CLI chat/delegation parsing for ZCode's `response`/`sessionId` stream envelope. Desktop-private runtime paths are never process-host entry points. | P27, P28 |
966
+ | P30 | ✅ Workspace scope: a second canonical layer in the repo itself, `<repo>/.agents/` (`config.json` reusing `servers.yaml`'s exact snake_case schema + validator, `AGENTS.md`, `skills/`), discovered by walking up from the cwd (`~/` never counts) and merged workspace-wins-by-ID with `enabled: false` tombstones. Delivery is layer-preserving — global content never re-renders into project files; workspace entries go to all six agents' project-level native paths, with skills *copied* (digest-drift-detected) for Claude/Kiro, native `.agents/skills/` reads for Codex/pi/Kimi, marker-headed root `AGENTS.md` for Codex/pi/Kimi + Kiro steering, and a zcode reverse-precedence warning (its MCP resolves user-first). Committable by design: `config.json` refuses credential-shaped literals at load, rendered artifacts carry only `${VAR}` references, and the committed `.agents/.trellis-rendered.json` ownership manifest is what lets a fresh clone or copied directory re-attach instead of conflict-guarding on its own artifacts. CLI: `init --workspace`, `sync` auto-include with `--check` as the CI freshness gate and `--global-only` as the escape hatch, `mcp add`/`skill add --workspace`, and `migrate --workspace` — a six-path scanner + seven-way classifier (create / already-managed / identical-to-global / skip-local / skip-unsupported / conflict / extract-secret) that refuses wholesale on unresolved conflicts, extracts plaintext secrets into the global store (git-tracked literals get a rotation advisory), seeds manifest ownership so the cascade render adopts rather than conflicts, and runs inside one backup session so a single `rollback` restores every original | P2, P24 |
967
+
968
+ **Shipped since P29 without a phase number** (detail in `docs/releases/`):
969
+ v0.13.0 — OAuth credential operability (`trellis mcp renew`, doctor OAuth
970
+ health, honest credential status in `trellis.mcp.status`, browser callback
971
+ page). v0.14.0 — pi native MCP delivery (pi ≥ 1.1.0 `mcp.json` writes,
972
+ bridge retirement in the same sync; supersedes P4's default path).
973
+ v0.14.1 — canonical `auth.client_name` for providers that gate OAuth dynamic
974
+ client registration by client name (Figma).
963
975
 
964
976
  **Cross-machine / cloud sharing — confirmed future direction, not yet
965
977
  scoped as a phase.** Surveyed 2026-09-15 (`docs/research.md`'s "Cross-
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agent-trellis",
3
- "version": "0.14.1",
3
+ "version": "0.15.1",
4
4
  "description": "A unified Code Agent Runtime for Skills, MCP, Memory, and shared instructions across Claude Code, Codex, Kiro, pi, Kimi Code, and ZCode.",
5
5
  "license": "MIT",
6
6
  "author": "Paul Leo",