Repository navigation
[feat] Let teamai push --shared place a new resource at the shared root when roles/projects exist #1314
Description
Problem
A team that declares manifest/roles.yaml (or manifest/projects.yaml) can no longer publish a new team-wide resource at the shared root with teamai push.
namespaceCandidates() only returns { kind: 'shared-root' } when the candidate list is empty. Once roles exist:
- non-interactive push fails with
Pass --role <ns> to name one; - the interactive prompt only lists role namespaces, with no shared-root choice;
--role <ns>must now name a declared namespace (post-feat(push): support all namespaced resource types #1234), so there is no opt-out.
This makes push disagree with pull: pull deliberately delivers root resources to everyone (#911, #1007), so the shared root is a first-class destination for pull but unreachable for push.
Concrete scenario
Team repo layout:
manifest/roles.yamldeclaresbe,fe,client,qa- team-wide skills live at the root:
skills/popo-im/,skills/km-ask/,skills/eagle-log-search/(tag-filtered viatags.yaml) - role-specific skills live under
skills/be/(the Java audit suite)
Publishing a new team-wide skill (jira-assistant, a JIRA CLI assistant that is not backend-specific):
$ teamai push --skill <path>
✖ Several skills namespaces could take new skills (be, fe, client, qa), and there is no terminal to ask on. Pass --role <ns> to name one.
$ teamai push --skill <path> --role be
✔ pushed to skills/be/jira-assistant
The only way to reach the intended location was a manual git mv skills/be/jira-assistant skills/jira-assistant, a commit and a push. That works, but it bypasses push's placement bookkeeping (the placement record / pending-push state), so later edits of the local copy cannot be pushed back to the root path by teamai push, and nothing in the CLI hints this is the supported workflow.
Proposed solution
Add an explicit opt-in destination flag:
teamai push --skill <path> --shared # also accept --root
- Places the resource at the resource root:
skills/<name>/,rules/<name>.md,agents/<name>.yaml, etc. - Mutually exclusive with
--role/--project(exit 2 with a clear message if combined). - Also offer "shared root (all roles)" as an explicit choice in the interactive namespace prompt, keeping the current default selection unchanged.
- Record the placement the same way [feat] Make all distributed resources pushable with project and role namespaces #1101 records namespaced placements, so a later edit of the root copy targets the root path again.
This keeps the "missing or ambiguous mappings fail instead of falling back to the shared root" rule intact: reaching the root becomes an explicit request, not a fallback.
Acceptance criteria
teamai push --skill <path> --sharedwritesskills/<name>/...to the push branch even whenmanifest/roles.yamldeclares namespaces.--sharedcombined with--roleor--projectexits 2 with a message naming the conflict.- The interactive namespace prompt includes the shared root as a selectable option; the default stays the previous behavior.
- A subsequent edit of the delivered root copy is pushed back to the same root path (placement record), matching [feat] Make all distributed resources pushable with project and role namespaces #1101 behavior.
teamai review --branchdoes not flag intentionally shared-root items as undeclared namespaces.- Unit coverage in
push-namespaces/push-role, plus an E2E case with a roles manifest and a new root skill.
Environment
- teamai-cli 0.27.0 (latest published), macOS,
provider: git - team repo with
manifest/roles.yamlandtags.yaml
Activity