Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
195 commits
Select commit Hold shift + click to select a range
a80862e
refactor(entries): let a namespaced entry reader declare its own layo…
SaulMoro Sep 28, 2026
2f20e47
refactor(models): share the team values path and stdin reader with a …
SaulMoro Sep 28, 2026
cb34fd3
merge: ticket 01 (#879)
SaulMoro Sep 28, 2026
19ab741
merge: ticket 02 (#879)
SaulMoro Sep 28, 2026
111c182
feat(env): declare team secrets in env/secrets.yaml and show their st…
SaulMoro Sep 28, 2026
7c6048f
merge: ticket 03 (#879)
SaulMoro Sep 28, 2026
d814632
feat(env): declare a team secret with env add --secret (#879)
SaulMoro Sep 28, 2026
9166b4e
feat(mcp): keep the entry an earlier pull wrote when a declared secre…
SaulMoro Sep 28, 2026
6d163cc
merge: ticket 05 (#879)
SaulMoro Sep 28, 2026
a5faa12
merge: ticket 10 (#879)
SaulMoro Sep 28, 2026
c979fb0
feat(env): keep a member's value for a team secret and resolve it in …
SaulMoro Sep 28, 2026
ca57663
docs(env): document team secret values, storage and MCP resolution (#…
SaulMoro Sep 28, 2026
65c5b93
feat(env): set one value for a team secret for every team on the mach…
SaulMoro Sep 28, 2026
1acbadd
docs(env): document the machine value for team secrets (#879)
SaulMoro Sep 28, 2026
4c46e29
merge: ticket 04 (#879)
SaulMoro Sep 28, 2026
ab34ab2
feat(mcp): keep project MCP configs with resolved values out of git (…
SaulMoro Sep 28, 2026
2ebf051
merge: ticket 07 (#879)
SaulMoro Sep 28, 2026
4a06dc5
feat(env): name a missing team secret and the command that sets it (#…
SaulMoro Sep 28, 2026
79c93ca
docs(env): document the missing-secret advisory in pull, doctor and t…
SaulMoro Sep 28, 2026
371b6d4
fix(uninstall): count the .git/info/exclude block in the removal plan…
SaulMoro Sep 28, 2026
551a78a
merge: ticket 06 (#879)
SaulMoro Sep 28, 2026
c894d0c
feat(env): run a command with the directory's team env and secrets vi…
SaulMoro Sep 28, 2026
2bcad5a
docs(env): document env exec, what the command can reach and the ANTH…
SaulMoro Sep 28, 2026
23bebdd
merge: ticket 08 (#879)
SaulMoro Sep 28, 2026
2e15c3f
fix(tests): isolate Claude config dir from model tests
SaulMoro Sep 28, 2026
4f549b0
fix(env): warn when env add --secret updates a declaration an unknown…
SaulMoro Sep 28, 2026
ae763fb
feat(env): tell agents at session start which team secrets exist and …
SaulMoro Sep 28, 2026
b7a1a8f
docs(env): teach agents to use team secrets through env exec and leav…
SaulMoro Sep 28, 2026
ba1137a
feat(env): resolve plain env variables in one order, with a member ov…
SaulMoro Sep 28, 2026
a9d5d65
docs(env): document the variable order and the member override (#879)
SaulMoro Sep 28, 2026
31ce8d5
merge: ticket 09 (#879)
SaulMoro Sep 28, 2026
7e903ce
merge: ticket 11 (#879)
SaulMoro Sep 28, 2026
ec29e34
fix(mcp): keep the exclude block until every MCP config is clean (#882)
SaulMoro Sep 28, 2026
f710333
fix(env): discount an old env.sh export in every later command (#879)
SaulMoro Sep 28, 2026
dba5374
fix(uninstall): remove the exclude block only once its files are prov…
SaulMoro Sep 28, 2026
336a3b0
fix(mcp): protect every project MCP config holding a resolved value (…
SaulMoro Sep 28, 2026
8377bcb
refactor(env): resolve a scope's env once per command (#879)
SaulMoro Sep 28, 2026
b72b639
fix(mcp): mcp list reports a broken secrets.yaml and exits 1 (#879)
SaulMoro Sep 28, 2026
7cdc408
fix(env): env commands outside a scope say so and exit 1 (#879)
SaulMoro Sep 28, 2026
9a921aa
fix(env): env exec refuses a command without -- before it (#879)
SaulMoro Sep 28, 2026
ef71eb9
feat(doctor): check that the member's secret values can be read (#879)
SaulMoro Sep 28, 2026
801da67
fix(env): name the unset variable a --from-env secret reads (#879)
SaulMoro Sep 28, 2026
8211ba9
test(mcp): env unset keeps the entry, still owned, until a new value …
SaulMoro Sep 28, 2026
2aa4b59
refactor(env): expected env set/remove failures as values, one wordin…
SaulMoro Sep 28, 2026
7b2fcdd
refactor(entries): EntryFailure always carries its layout (#879)
SaulMoro Sep 28, 2026
4b3e57c
refactor(doctor): name entry resolution checks with their layout (#879)
SaulMoro Sep 28, 2026
7f5a649
refactor(secrets): report an unparsable value store by path only (#879)
SaulMoro Sep 28, 2026
376ece1
test(secrets): typed fixtures instead of casts in the new tests (#879)
SaulMoro Sep 28, 2026
95f975d
docs(env): env set takes variables, listings show sources, exec needs…
SaulMoro Sep 28, 2026
e33c1a0
fix(env): refuse env set/unset/list when the project config can't be …
SaulMoro Sep 28, 2026
98e9ffa
fix(env-exec): exit 128 + signal for a command killed by SIGPIPE or S…
SaulMoro Sep 28, 2026
b010a93
fix(env-exec): don't send the command a second SIGINT on Ctrl-C (#879)
SaulMoro Sep 28, 2026
eb156cc
docs(env): exec signal handling and env set on an unreadable project …
SaulMoro Sep 28, 2026
0abdc1e
fix(mcp): judge MCP configs by disk and manifest, not current config …
SaulMoro Sep 28, 2026
b7d5fa6
merge: origin/main into feat/875-team-secrets
SaulMoro Sep 28, 2026
d3cf8da
fix(env): the env commands and env exec load config through --dry-run…
SaulMoro Sep 28, 2026
197c667
fix(secrets): name the team values file by the repo identity hash alo…
SaulMoro Sep 28, 2026
f9d227d
fix(env): keep a __proto__ env key through the store, MCP and env exe…
SaulMoro Sep 28, 2026
d166946
fix(env): env list loads config with --dry-run always (#879)
SaulMoro Sep 28, 2026
0b7ab1e
revert: drop the #890 cherry-pick from this branch
SaulMoro Sep 28, 2026
1791a71
fix(env): env exec applies no team env while the declarations fail (#…
SaulMoro Sep 28, 2026
aa3057f
fix(fs): create the atomic-write temp file with the target mode (#879)
SaulMoro Sep 28, 2026
9680c83
fix(env): env set --dry-run previews without asking for the value (#879)
SaulMoro Sep 28, 2026
b2cd191
fix(env): serialize env set and env unset on the values file (#879)
SaulMoro Sep 28, 2026
9c4d3f9
fix(env): keep a secret's stored value from becoming a variable overr…
SaulMoro Sep 28, 2026
5bc97e9
fix(mcp): write an MCP config that holds a resolved value 0600 (#879)
SaulMoro Sep 28, 2026
a73133a
fix(mcp): create the Codex config temp file 0600 (#879)
SaulMoro Sep 28, 2026
89f8cdb
docs(env): say env exec ignores a SIGINT or SIGQUIT sent to teamai al…
SaulMoro Sep 28, 2026
9c1c4f0
fix(mcp): tighten an unchanged config that holds a resolved value to …
SaulMoro Sep 28, 2026
684b44a
fix(env): mark what each env.sh exported so a value from one no scan …
SaulMoro Sep 28, 2026
e8fe491
fix(env): pass on a SIGINT or SIGQUIT sent to env exec outside the te…
SaulMoro Sep 28, 2026
a47f8b0
fix(env): keep marking what an env.sh exported before a rewrite dropp…
SaulMoro Sep 28, 2026
9a254ea
docs(env): say a SIGINT sent to a foreground env exec alone is not pa…
SaulMoro Sep 28, 2026
3947a8e
fix(secrets): name the team values file by the configured team repo U…
SaulMoro Sep 28, 2026
3e1478f
fix(env): remove what a teamai env.sh exported from env exec while th…
SaulMoro Sep 28, 2026
bde17ab
merge: #882 (PR #886) — keep project MCP configs with resolved tokens…
SaulMoro Sep 28, 2026
3678005
fix(mcp): never write a declared secret into a project MCP config git…
SaulMoro Sep 28, 2026
5a4dd3c
fix(env): leave no duplicate declaration of a key env add --secret or…
SaulMoro Sep 28, 2026
a971d82
test: keep the real normalizeRepoUrlForCompare in utils/git mocks the…
SaulMoro Sep 28, 2026
d3e2e4e
fix(env): keep the port in the URL that names a team's secrets file (…
SaulMoro Sep 28, 2026
d8da567
fix(mcp): skip the .git/info/exclude write while another command hold…
SaulMoro Sep 28, 2026
b1a7973
fix(uninstall): keep an exclude entry unless its MCP config is proven…
SaulMoro Sep 28, 2026
2cf842d
merge: #882 (PR #886) — keep the exclude block without proof, skip un…
SaulMoro Sep 28, 2026
66af56a
fix(env): keep http and https team repos in separate secrets files (#…
SaulMoro Sep 29, 2026
43513d9
fix(env): strip teamai env.sh exports in env exec when the project co…
SaulMoro Sep 29, 2026
38a8fb2
fix(mcp): exclude a project MCP config from git before writing a reso…
SaulMoro Sep 29, 2026
71c27e7
fix(mcp): report a server withheld from a file git would commit in mc…
SaulMoro Sep 29, 2026
0d9f7fa
merge: #882 (PR #886) — exclude before writing a resolved value
SaulMoro Sep 29, 2026
ce2706b
fix(secrets): keep the ssh user in a team's values-file identity (#879)
SaulMoro Sep 29, 2026
c6888da
fix(env): overlay and remove env exec keys case-insensitively on Wind…
SaulMoro Sep 29, 2026
a9f0836
fix(mcp): report a tracked file on a dry run and a withheld server al…
SaulMoro Sep 29, 2026
c4a9160
fix(mcp): name a tracked MCP config before an unwritable .git/info/ex…
SaulMoro Sep 29, 2026
683a36a
fix(mcp): take a project MCP config's exclude line back out once it h…
SaulMoro Sep 29, 2026
86a0aef
fix(secrets): tell an scp path in the ssh user's home from an ssh:// …
SaulMoro Sep 29, 2026
ae6d4a6
fix(mcp): judge a project MCP config by the manifest as it stood befo…
SaulMoro Sep 29, 2026
389635e
fix(mcp): log a rolled-back exclude line at debug level (#882)
SaulMoro Sep 29, 2026
2f39c37
merge: #882 (PR #886) — exclusion lifecycle, tracked first, backport
SaulMoro Sep 29, 2026
06f3b8d
fix(mcp): keep a shared exclude line while another worktree's config …
SaulMoro Sep 29, 2026
e290adb
merge: #882 (PR #886) — keep a shared exclusion while another worktre…
SaulMoro Sep 29, 2026
7810e52
test(mcp): build the other worktree from the real temp path so the te…
SaulMoro Sep 29, 2026
fbd6301
merge: #882 (PR #886) — realpath the other worktree in its test
SaulMoro Sep 29, 2026
16ca43b
fix(env): strip teamai env.sh exports from env exec with no config or…
SaulMoro Sep 29, 2026
2b6e82a
fix(secrets): name a team's values file by the full SHA-256 digest (#…
SaulMoro Sep 29, 2026
fbb7abd
fix(env): name the env.sh provenance marker by the full SHA-256 of it…
SaulMoro Sep 29, 2026
c58846c
Merge remote-tracking branch 'origin/main' into feat/882-mcp-git-exclude
SaulMoro Sep 29, 2026
ffa3d25
Merge remote-tracking branch 'origin/main' into feat/875-ci-loop-10
SaulMoro Sep 29, 2026
e527f37
test(push): push publishes the secrets.yaml env add --secret leaves (…
SaulMoro Sep 29, 2026
e5331ff
fix(uninstall): list no worktrees for a project root that no longer e…
SaulMoro Sep 29, 2026
29d965b
fix(secrets): keep the URL query and fragment in a team's values file…
SaulMoro Sep 29, 2026
b040124
fix(mcp): treat an empty, unparsable or tool-less managed-mcp.json as…
SaulMoro Sep 29, 2026
46f0e52
fix(env): compare exported, recorded and marked keys case-insensitive…
SaulMoro Sep 29, 2026
f15191a
fix(uninstall): list no worktrees for a project root that no longer e…
SaulMoro Sep 29, 2026
5783dc6
fix(mcp): keep the exclude line of a config this pull wrote when a la…
SaulMoro Sep 29, 2026
d045b59
fix(mcp): read a check-ignore error as unsafe unless ls-files proves …
SaulMoro Sep 29, 2026
b9529d1
fix(mcp): report withheld only for targets delivery would write the s…
SaulMoro Sep 29, 2026
34bb7c1
docs(mcp): describe the .git/info/exclude block in the setup skill an…
SaulMoro Sep 29, 2026
1392f78
merge: #882 (PR #886) — rollback after a write, check-ignore errors, …
SaulMoro Sep 29, 2026
875c7cf
fix(mcp): keep the exclude line of an entry a pull wrote with a resol…
SaulMoro Sep 29, 2026
7cd4841
fix(mcp): judge a nested repository's linked worktree config by its s…
SaulMoro Sep 29, 2026
a6cfbee
feat(mcp): record the project MCP configs a pull wrote a resolved val…
SaulMoro Sep 29, 2026
4339efb
fix(mcp): keep protecting a config a pull wrote under a toolPaths map…
SaulMoro Sep 29, 2026
5c46d8a
fix(mcp): keep a config's exclude line past the pull that rebuilt its…
SaulMoro Sep 29, 2026
c43085b
test(mcp): pin today's exclude rules for a missing, corrupt or locked…
SaulMoro Sep 29, 2026
23a00df
docs(mcp): describe managed-mcp-files.json and the configs it keeps p…
SaulMoro Sep 29, 2026
0ec4246
refactor(mcp): keep the #882 record edits off the lines #880 changes …
SaulMoro Sep 29, 2026
72799f5
Merge remote-tracking branch 'origin/main' into feat/882-mcp-git-exclude
SaulMoro Sep 29, 2026
d797f94
Merge branch 'feat/882-mcp-git-exclude' into feat/875-team-secrets
SaulMoro Sep 29, 2026
38025a6
test(mcp): keep excluding a config whose entry a pull kept for a miss…
SaulMoro Sep 29, 2026
53c4216
fix(mcp): protect a config an older teamai wrote under a mapping an e…
SaulMoro Sep 29, 2026
a466fd5
fix(mcp): keep a rebuilt record from persisting without its note of t…
SaulMoro Sep 29, 2026
a933c22
fix(mcp): take back a managed-mcp-files.json record for a config the …
SaulMoro Sep 29, 2026
df98441
docs(mcp): describe the teamai.yaml history read, the unnoted rebuilt…
SaulMoro Sep 29, 2026
ecb3009
refactor(mcp): keep the r3 edits off the lines #880 changes (#882)
SaulMoro Sep 29, 2026
16007ae
fix(mcp): also protect a config an older teamai wrote under a built-i…
SaulMoro Sep 29, 2026
2a219f6
Merge branch 'feat/882-mcp-git-exclude' into feat/875-team-secrets
SaulMoro Sep 29, 2026
0cc3fd5
fix(mcp): replace a symlinked Codex config instead of writing into th…
SaulMoro Sep 29, 2026
a76b40e
fix(env): drop what a teamai env.sh exported from env exec when env.y…
SaulMoro Sep 29, 2026
ce43f6e
fix(env): on Windows, match a declared secret to an env.yaml variable…
SaulMoro Sep 29, 2026
c252a0e
fix(mcp): judge a project MCP config under a symlinked directory wher…
SaulMoro Sep 29, 2026
5152b74
docs(mcp): describe how a config under a symlinked directory is kept …
SaulMoro Sep 29, 2026
d19a6d6
refactor(mcp): keep realFilePath next to existingAncestor, without an…
SaulMoro Sep 29, 2026
7d2463f
Merge branch 'feat/882-mcp-git-exclude' into feat/875-team-secrets
SaulMoro Sep 29, 2026
02dbd75
refactor(mcp): key each worktree's targets with realFilePath, the one…
SaulMoro Sep 29, 2026
0c8d2dc
fix(mcp): judge a config under an earlier teamai.yaml mapping as a re…
SaulMoro Sep 29, 2026
a30f56d
fix(mcp): have doctor check the configs earlier teamai.yaml mappings …
SaulMoro Sep 29, 2026
5d9df20
docs(mcp): describe how a config under an earlier teamai.yaml mapping…
SaulMoro Sep 29, 2026
bf28224
Merge remote-tracking branch 'origin/main' into feat/882-mcp-git-exclude
SaulMoro Sep 29, 2026
df1970a
Merge branch 'feat/882-mcp-git-exclude' into feat/875-team-secrets
SaulMoro Sep 29, 2026
5696b36
fix(mcp): record a config under an earlier teamai.yaml mapping that g…
SaulMoro Sep 29, 2026
fbed13d
fix(mcp): keep judging a recorded config for a tool the team moved wh…
SaulMoro Sep 29, 2026
16c1938
docs(mcp): describe the tracked config an earlier mapping reached, an…
SaulMoro Sep 29, 2026
fc807e0
fix(mcp): find a config an older teamai wrote under an earlier mappin…
SaulMoro Sep 29, 2026
c4d39c1
docs(mcp): describe the history read's configs another tool maps toda…
SaulMoro Sep 29, 2026
e46c8a0
Merge remote-tracking branch 'origin/main' into feat/882-mcp-git-exclude
SaulMoro Sep 29, 2026
df4440a
Merge branch 'feat/882-mcp-git-exclude' into feat/875-team-secrets
SaulMoro Sep 29, 2026
3bea844
fix(mcp): prove a shared config clean only while every tool that wrot…
SaulMoro Sep 29, 2026
a274539
Merge branch 'feat/882-mcp-git-exclude' into feat/875-team-secrets
SaulMoro Sep 29, 2026
f3a1fc3
fix(env): on Windows, set and unset a key under the name the scope de…
SaulMoro Sep 29, 2026
3d718b8
fix(mcp): judge a built-in location no mapping reaches today as an ea…
SaulMoro Sep 29, 2026
da0c8f8
docs(mcp): describe the built-in location of a moved or dropped tool,…
SaulMoro Sep 29, 2026
b988bd2
Merge branch 'feat/882-mcp-git-exclude' into feat/875-team-secrets
SaulMoro Sep 29, 2026
86e2baf
fix(env): on Windows, match a secret's declaration and stored value i…
SaulMoro Sep 29, 2026
32fa951
fix(mcp): name the ignore rule that re-includes a config teamai just …
SaulMoro Sep 29, 2026
cd69dad
fix(mcp): judge a moved tool's built-in location another tool maps fo…
SaulMoro Sep 29, 2026
978ecec
docs(mcp): describe the no-manifest rule, a moved tool's built-in loc…
SaulMoro Sep 29, 2026
9fb467c
Merge remote-tracking branch 'origin/main' into feat/882-mcp-git-exclude
SaulMoro Sep 29, 2026
173c7b3
Merge branch 'feat/882-mcp-git-exclude' into feat/875-team-secrets
SaulMoro Sep 29, 2026
7f75588
fix(env): key a team's values by its repo URL when the configured rem…
SaulMoro Sep 29, 2026
6b98a26
fix(env): on Windows, recognise a secret's env.yaml value under anoth…
SaulMoro Sep 29, 2026
d522707
fix(mcp): on Windows, keep an inherited value under another case of a…
SaulMoro Sep 29, 2026
047e77f
fix(env): on Windows, replace and remove every stored entry under ano…
SaulMoro Sep 29, 2026
0f6db9e
fix(mcp): keep a tool's record as it was when its config does not par…
SaulMoro Sep 29, 2026
6b177e8
fix(mcp): mark the records a pull with no managed-mcp.json writes as …
SaulMoro Sep 29, 2026
95ee768
fix(mcp): have doctor judge a record marked unnoted like a missing ma…
SaulMoro Sep 29, 2026
f8688bd
Merge branch 'feat/882-mcp-git-exclude' into feat/875-team-secrets
SaulMoro Sep 29, 2026
a915ed1
fix(mcp): judge a config tools of different formats share in each of …
SaulMoro Sep 29, 2026
c544a38
fix(mcp): note the servers no record claims in the file of a tool who…
SaulMoro Sep 29, 2026
dfe1a74
fix(mcp): take back a tool managed-mcp-files.json recorded before a w…
SaulMoro Sep 29, 2026
d051823
Merge branch 'feat/882-mcp-git-exclude' into feat/875-team-secrets
SaulMoro Sep 29, 2026
549bcab
fix(mcp): treat an installed tool's missing record as lost at every p…
SaulMoro Sep 29, 2026
f9941e2
Merge branch 'feat/882-mcp-git-exclude' into feat/875-team-secrets
SaulMoro Sep 29, 2026
58dd2b5
fix(mcp): tighten to 0600 every project config the protection pass ke…
SaulMoro Sep 29, 2026
0881085
fix(mcp): on Windows, fill a placeholder from the variable of the sam…
SaulMoro Sep 29, 2026
9ba907c
fix(mcp): note the unclaimed servers under every format of a shared c…
SaulMoro Sep 29, 2026
f466dd0
Merge branch 'feat/882-mcp-git-exclude' into feat/875-team-secrets
SaulMoro Sep 29, 2026
6e5f659
fix(mcp): count an uninstalled tool's missing record when no installe…
SaulMoro Sep 29, 2026
ee33d5f
fix(mcp): on Windows, match a placeholder to its secret in any case i…
SaulMoro Sep 29, 2026
83b7d12
Merge branch 'feat/882-mcp-git-exclude' into feat/875-team-secrets
SaulMoro Sep 29, 2026
00169ad
fix(mcp): scope a shared config's claims to the tools reading the sam…
SaulMoro Sep 29, 2026
e3eb882
Merge remote-tracking branch 'origin/main' into feat/882-mcp-git-exclude
SaulMoro Sep 29, 2026
49d9207
fix(env): keep a file:// repo's .git suffix in its values file identi…
SaulMoro Sep 29, 2026
4378d5e
fix(env): on Windows, update and remove an env.yaml variable typed in…
SaulMoro Sep 29, 2026
23ecd4b
Merge branch 'feat/882-mcp-git-exclude' into feat/875-team-secrets
SaulMoro Sep 29, 2026
2033b5b
fix(mcp): keep suspect an uninstalled tool managed-mcp-files.json lis…
SaulMoro Sep 29, 2026
fa4c3d9
Merge branch 'feat/882-mcp-git-exclude' into feat/875-team-secrets
SaulMoro Sep 29, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 31 additions & 2 deletions docs/designs/data-directory-layout.md
Original file line number Diff line number Diff line change
Expand Up @@ -439,6 +439,9 @@ every checkout, so that is where they live now:
├── reports-wt/ (the side-branch locks sit beside them)
├── pending-learnings/ pendingLearningsDir → <dataHome>/pending-learnings
└── workspaces/<managedMcpWorkspaceId(root)>/
├── managed-mcp.json managedMcpManifestPath, one per checkout
├── managed-mcp-files.json resolvedMcpFilesPath: project MCP configs teamai may have written a resolved ${VAR} to, and whether
│ the paths earlier teamai.yaml revisions mapped were read; one of those git tracks is marked tracked (#882)
└── search-index.json getProjectSearchIndexPath, one per checkout
<checkout>/.teamai/ one per checkout: committed knowledge, knowledge-wt/
```
Expand Down Expand Up @@ -655,8 +658,8 @@ the other repository, and `recall` rebuilds a missing index. `uninstall` lists,
how many unpublished learnings each queue in the data home holds, set-aside ones
included, so the member can publish or copy them first.

Every checkout keeps its `workspaces/<id>/` (search index, managed MCP,
resource cache) in the shared data home. A full `pull` removes those of
Every checkout keeps its `workspaces/<id>/` (search index, managed MCP and
the MCP configs it wrote a resolved value to, resource cache) in the shared data home. A full `pull` removes those of
checkouts `git worktree list` no longer shows; the fast path does not list
worktrees.

Expand Down Expand Up @@ -905,3 +908,29 @@ user finds partitions safe to `rm -rf` by hand.
`teamai migrate` / `gc` / `--revert` commands; cross-project shared team-repo clone.
Downgrade to an older teamai after
P1 migration is not supported (`.teamai.bak/` is the manual rollback path).

## Team secret values (#875)

A member's values for their teams' declared secrets live in `~/.teamai/secrets/`,
a class-A2 (machine-level) directory: `teams/<hash>.json`, one file per
team repo, named by the full SHA-256 hex digest (64 characters, never shortened) of the team repo URL in `~/.teamai/config.yaml` (never
`teamai.yaml`'s `repo:`), without the team name, so renaming `team:` keeps the values;
the hash covers the URL's scheme (the ssh forms count as one; https and http are two),
ssh user, host, non-default port and path (an scp-style path not starting with `/` or `~`
is in the user's home, as `ssh://host/~/path`; `ssh://host/path` is from the root), so an
scp path in the home and the `ssh://` path from the root, two ssh users' repos on one host, two
repos on one host with different ports, or repos behind http and https, get different files,
and `machine.json`, the values set with `teamai env set --global` for every team.
Every scope that uses the same team, and every worktree of it, reads the same file.
Each entry records whether it is a secret's value or the member's value for an
`env.yaml` variable (`kind`), so one is never used as the other.
It never goes to a partition or to `<dataHome>`, which in single-repo mode is inside
the business repo, and it is not `~/.teamai/env`, which is already the user scope's
env backup file. Files are written atomically with mode `0600`. Uninstalling a
project scope removes only its partition, so the values stay; uninstalling the user
scope removes `~/.teamai` and them with it. See [Team secrets](team-secrets.md#storage).

Beside each scope's `env.sh`, in `<dataHome>`, `env.sh.exports.json` records what
that `env.sh` has exported: per key, a SHA-256 of `KEY=VALUE` for the last 20
values, never a value, mode `0600`. It is machine data like `env.sh` and is
removed with it. See [Team secrets](team-secrets.md#resolution).
3 changes: 2 additions & 1 deletion docs/designs/management-backend.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,8 @@ plane accepts identity-bound events with separate retention and write permission
| `skills/` | SkillsHandler, namespaces and marketplace metadata | Resource bundles with immutable files, dependencies and generated marketplace views |
| `rules/` | RulesHandler and enforced-rule selection | Versioned rules with separately enforced policy constraints |
| `docs/` | DocsHandler and indexed documentation | Versioned documents, authorized materialization and recall indexing |
| `env/env.yaml` | EnvHandler, local overrides and environment injection | Non-secret templates plus secret references; secret resolution has separate authorization |
| `env/env.yaml` | EnvHandler, local overrides and environment injection; values in plaintext | Non-secret templates plus secret references; secret resolution has separate authorization |
| `env/secrets.yaml` | Secret declarations with no value ([team secrets](team-secrets.md)); v1 resolves each member's value on their machine | Secret references; the encrypted secret service below stays future work |
| `agents/` | AgentsHandler and tool-format conversion | Versioned agent definitions rendered through the existing tool adapters |
| `hooks/hooks.yaml` | HooksHandler plus hook reconciliation; no general per-item push | Reviewed declarative hooks, client consent and typed validation |
| `mcp/mcp.yaml` | McpHandler plus MCP reconciliation; direct YAML editing for contributions | Reviewed server definitions, transport policy and secret references |
Expand Down
3 changes: 2 additions & 1 deletion docs/designs/management-backend.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@
| `skills/` | SkillsHandler、命名空间及 marketplace 元数据 | 不可变文件和依赖组成的资源包,派生 marketplace 视图 |
| `rules/` | RulesHandler 及强制规则选择 | 版本化规则,并单独执行强制策略约束 |
| `docs/` | DocsHandler 及文档索引 | 版本化文档、授权物化及召回索引 |
| `env/env.yaml` | EnvHandler、本地覆盖和环境注入 | 非密钥模板及密钥引用,解析密钥时单独授权 |
| `env/env.yaml` | EnvHandler、本地覆盖和环境注入;值为明文 | 非密钥模板及密钥引用,解析密钥时单独授权 |
| `env/secrets.yaml` | 只声明、不含值的密钥([团队密钥](team-secrets.zh-CN.md));v1 在每个成员的机器上解析其值 | 密钥引用;下文的加密密钥服务仍属未来工作 |
| `agents/` | AgentsHandler 及工具格式转换 | 版本化 agent 定义,复用现有工具适配器渲染 |
| `hooks/hooks.yaml` | HooksHandler 及 hook 协调,不支持通用逐项 push | 可审核的声明式 hooks、客户端同意及类型验证 |
| `mcp/mcp.yaml` | McpHandler 及 MCP 协调,贡献通过直接编辑 YAML 完成 | 可审核的服务定义、transport 策略及密钥引用 |
Expand Down
2 changes: 2 additions & 0 deletions docs/designs/model-profiles.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ Model profiles let a team publish one gateway catalog that every supported agent

A key is either stored or referenced as an environment variable; it is never accepted as a command-line argument. `0600` is not encryption. The team-key file name is a hash of the repository identity; the sanitized `teamai.yaml` team name plays no part in it, so renaming the team never orphans the keys. When no repository identity exists at all (no usable remote, URL, or `repo:` claim), the name hashes the team slug with the path instead — there is nothing repository-shaped to key on, and the slug keeps differently named teams that share a checkout path apart. While the hash-only file does not exist yet, a legacy `<slug>-<hash>.json` from an older version is read where it lies — nothing is renamed — and the next save writes the hash-only name. A legacy file under a repository-bound digest (a URL, a URL-shaped `repo:` claim or remote) carries its host in the identity, so it is read by digest alone; a legacy file under a **provider-ambiguous** digest (a path-shaped `repo:` claim, a provider-relative remote, a bare alias, or no repository identity) names no single repository — the old name scheme never encoded the provider, so two providers' same-named teams hash the same file, and the slug cannot prove ownership across providers. Such a file is never read by a silent rule: the CLI surfaces it once and the user explicitly adopts the exact `<slug>-<hash>` identity for this checkout, after which the read happens and the next save migrates the keys to the provider-qualified hash-only name. Non-interactive and `--dry-run` runs never adopt: they report the file and leave it unread. Switch records under a provider-ambiguous identity are never claimed either — the old name never encoded the provider, so no slug (not even this checkout's exact slug) proves ownership: a GitHub and a GitCode team both named `Alpha` on the bare claim `acme/widgets` share the identical `alpha-<digest>` form. No machine-global record is ever used as proof, because a store shared by every checkout on the machine would equally belong to a foreign team; the explicit adoption of the values file re-establishes this team's presence, and its switched agents are re-recorded by the next `models switch` under the provider-qualified identity. Repository-bound switch records still match by digest alone. The identity is recorded with each `team:` switch so `pull` only re-applies the current team's profiles. Inside it, each key is stored under `team:<id>@<origin>`; see [Namespaces and key binding](#namespaces-and-key-binding).

Model profile keys are not [team secrets](team-secrets.md): `teamai env set` does not configure them, `env/secrets.yaml` cannot declare one, and the two stores share code, not files.

## Catalog and protocols

```yaml
Expand Down
2 changes: 2 additions & 0 deletions docs/designs/model-profiles.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@

密钥要么保存在本地,要么引用环境变量,不接受命令行参数传入。`0600` 并非加密。团队密钥文件名只是仓库身份的哈希,`teamai.yaml` 中的团队名不参与其中,因此重命名团队不会导致密钥失效。当完全不存在仓库身份(可用的 remote、URL 或 `repo:` claim 都没有)时,文件名改为哈希团队 slug 与路径的组合——此时没有任何仓库形态的信息可以依赖,靠 slug 区分共享同一检出路径、名字不同的团队;旧版本遗留的 `<团队名>-<哈希>.json` 会在纯哈希文件尚不存在时被原位读取,不做任何改名,下一次保存才会写入纯哈希文件名。在 provider 可确定的 digest(URL 或 URL 形态的 `repo:` claim/remote)下写出的遗留文件,identity 自带主机,直接按 digest 读取;在 **provider 不明确** 的 digest(形如 `owner/repo` 的 `repo:` claim、provider 相对的 remote、裸 alias,或没有仓库身份)下写出的遗留文件既不指向唯一仓库——旧命名从未编码 provider,两个 provider 的同名团队会哈希出同一个文件,slug 无法在 provider 之间证明归属。这类文件绝不按静默规则读取:CLI 会展示一次,由用户显式确认采用这个确切的 `<团队名>-<哈希>` identity 后才读取,随后下一次保存会把密钥迁移到 provider 限定的纯哈希文件名下。非交互与 `--dry-run` 运行一律不采用:只报告该文件并保持不读。provider 不明确 identity 下的 switch 记录同样绝不采用——旧命名从未编码 provider,任何 slug(即使与本 checkout 完全相同的 slug)都无法证明归属:GitHub 与 GitCode 上都叫 `Alpha`、裸 claim 同为 `acme/widgets` 的两支团队会共享完全相同的 `alpha-<digest>` 形式。绝不把任何机器级记录当作归属证明,因为同一机器上被各 checkout 共享的记录对别的团队同样成立;只有对遗留 values 文件的显式采用才能重新确立本团队的存在,其已切换的 agent 随后通过下一次 `models switch` 以 provider 限定的 identity 重新记录。provider 可确切的 switch 记录仍按 digest 直接匹配。每次切换 `team:` 配置时也会记录这个身份,`pull` 只会重新应用当前团队的配置。文件内每个密钥保存在 `team:<id>@<origin>` 下,见 [Namespace 与密钥绑定](#namespace-与密钥绑定)。

模型配置的密钥不是[团队密钥](team-secrets.zh-CN.md):`teamai env set` 不配置它们,`env/secrets.yaml` 也不能声明它们,两者只共享代码、不共享文件。

## 目录与协议

```yaml
Expand Down
12 changes: 8 additions & 4 deletions docs/designs/multi-project-management.md
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,7 @@ directory's projects list under `resources.<type>`.
| Type | `resources:` key | Replaced by name | Two active namespaces, one name |
|---|---|---|---|
| env | `env` | variable `key` | conflict |
| secrets (`env/<ns>/secrets.yaml`, [#875](team-secrets.md)) | `env` | secret `key` | conflict |
| hooks | `hooks` | hook `id` | conflict |
| mcp | `mcp` | server `name` (`command`, `args`, `env` and `tools:` together) | conflict |
| models | `models` | profile `id` | conflict |
Expand All @@ -266,7 +267,8 @@ active, the next pull delivers the root item again and removes items that only
the namespace had; for env, hooks and MCP that happens on an `Already synced`
pull too, and `env.sh` is regenerated from the resolved set even when
`env/env.yaml` is missing or declares nothing. MCP `${VAR}` lookup reads the same
resolved env set.
resolved env set, with the member's value for this team (`teamai env set KEY`)
first; the environment no longer overrides a team variable ([Team secrets](team-secrets.md#variables)).

Skills keep one difference: in role/project mode the root `skills/` stays the tag
catalog and is not delivered by default. A root skill that arrives through a
Expand Down Expand Up @@ -320,13 +322,14 @@ copy is not a duplicate: each copy that passes the role filter is delivered, as
| Type | Effect of a failure |
|---|---|
| env | `env.sh` and the shell profile keep what they had |
| secrets | the declared secrets are not resolved, and `env.sh`, the env backup and the MCP servers keep what they had; `teamai env list` and `teamai doctor` fail naming the file |
| hooks | installed team hooks and the managed-hooks record stay as they are. The built-in hooks are still installed in each tool that misses one (a tool with all of them is not rewritten), so a first install gets the session-start pull that heals it: with the root file's `builtin:` overrides whenever `hooks/hooks.yaml` parses (a broken namespace file or a clash does not hide them), and when the root file itself does not parse, with their defaults and only in a tool that has no teamai hook yet. `teamai init` and bootstrap say the team hooks were not installed; `teamai hooks inject` exits 1 |
| mcp | no tool's MCP config changes |
| models | no switched agent is updated; `teamai models` commands fail with the same message; `teamai push` refuses any invalid models file, active or not |
| skills, agents | that type is neither installed nor swept; the other types and the search index still sync |
| rules, claudemd, docs, learnings | no conflict case |

For env, hooks, MCP and models the warning is also written to
For env, secrets, hooks, MCP and models the warning is also written to
`~/.teamai/debug.log`, so a silent session-start pull leaves a trace. This
replaces two earlier behaviours: an invalid hooks or MCP file reconciled to the
empty set and removed every managed entry, and a skills or agents collision
Expand Down Expand Up @@ -450,8 +453,9 @@ a root one is written to its namespace file, never to the root. The agents
source order is active namespace, then this machine's placement record, then the
shared root; in role/project mode a same-stem root file no longer withdraws the
placement record (legacy mode still does). The skills push scan uses role ∪
project namespaces, and `push` picks up a change to any `env/<ns>/env.yaml`.
`teamai env add|remove` take `--role` / `--project`. `teamai remove mcp <name>`
project namespaces, and `push` picks up a change to any `env/<ns>/env.yaml` or `env/<ns>/secrets.yaml`.
`teamai env add|remove` take `--role` / `--project`, and `--secret` for that namespace's `secrets.yaml`.
`teamai remove mcp <name>`
removes from the root file when it defines the name, otherwise from the one
namespace file that does, and asks for `--role` / `--project` only when several
namespace files and not the root define it, and removes nothing by a bare name
Expand Down
Loading
Loading