Skip to content

feat(projects): an agent can start a project for its owner — projects.manage + create_project / import_project (abilityai/trinity-enterprise#588) - #3339

Merged
vybe merged 2 commits into
devfrom
feature/ent588-agent-projects
Oct 9, 2026
Merged

vybe merged 2 commits into
devfrom
feature/ent588-agent-projects

Conversation

@dolho

@dolho dolho commented Oct 7, 2026

Copy link
Copy Markdown
Contributor

Stacked on #3330 (→ #3236), whose capability seam and Settings panel it extends. This PR retargets to dev as those land. Review the top commit only.

Summary

Re-scope of ent#588 (ruling 2026-09-29, ent#661): on Trinity, /project-init creates the project through the platform. ent#661 planned the agent's right as "a new capability beside skills.manage; changing members or visibility stays person-only". This PR adds that capability.

  • projects.manage joins the closed capability set. It lets an agent start a Workspace project on its owner's behalf: the owner is the creator and first member, the agent is the steward, and the project is members-only. It also lets the agent import one of its own folder projects. Adding people or changing who can see a project is never grantable.
  • Named refusal: project_management_not_permitted, with the ask instruction from feat(agents): the self-change permissions as four admin-only toggles in Agent Settings (abilityai/trinity-enterprise#756) #3330.
  • Settings → Permissions to change itself: a fifth toggle, "Start projects".
  • MCP: create_project and import_project. They are license-blind like the rest of projects.ts, and their descriptions state that the grant is needed and what the owner keeps.

The routes that enforce this and do the create/import are in the enterprise projects module, which checks projects.manage before reading anything (abilityai/trinity-enterprise PR, same issue). The skills that call these tools are in Abilityai/abilities: project-init 1.4, plus the ent#673 task skills.

Merge order

This PR first, then the enterprise PR. Until this is on dev, projects.manage isn't in the closed set, so the enterprise routes refuse every agent. That fails closed.

Test Plan

  • tests/unit/test_ent164_self_change_grants.py: the closed set now includes projects.manage, and its refusal is named and tells the agent how to ask. 113 passed together with test_2996_human_only_routes.py.

  • MCP projects.test.ts, 3 new tests:

    • create_project sends name and goal, and sends the tracker only when one is given;
    • the named refusal comes back as a result, never a throw;
    • import_project forwards only the path and surfaces a second import's 409.

    Including the description-budget and access-wiring guards: 36 passed. tsc is clean.

  • selfChangePermissionsPanel.spec.js: 12 passed. The specs iterate over the capability list, so the fifth toggle is covered.

  • The enterprise-docs guard is clean on the diff.

  • Look at the fifth toggle in Settings, in both themes.

Refs abilityai/trinity-enterprise#588

🤖 Generated with Claude Code

@dolho

dolho commented Oct 7, 2026

Copy link
Copy Markdown
Contributor Author

/review + test run (2026-10-07)

Branch: feature/ent588-agent-projects → feature/ent756-self-change-toggles (stacked on #3330 → #3236). 12 files, +140/−10.
Scope: CLEAN. The capability, its refusal, the toggle, the two MCP tools, docs and tests. The enterprise gitlink is not moved: HEAD keeps b73c65f.
Plan: ent#588's 2026-09-29 re-scope, public half. Done: the capability (ent#661's planned agent right), the named refusal, the MCP tools, the Settings toggle. The enforcement lives in trinity-enterprise#835.

Execution coverage

Changed symbol Executed by Live consumer Verdict
CAPABILITY_PROJECTS_MANAGE in the closed set test_ent164…::test_the_three_capabilities_join_the_closed_set capability_grant_service.set_grant, agent_has_capability, and enterprise#835 _require_projects_manage ✅
_CAPABILITY_REFUSALS["projects.manage"] test_a_non_holder_gets_a_named_refusal…[projects.manage], which also asserts title includes 'projects.manage' enforce_agent_capability ✅
create_project / import_project tools and client methods projects.test.ts, 3 new tests (body shape, named refusal as a result, 409 surfaced) server.ts → createProjectTools ✅
SELF_CHANGE_CAPABILITIES fifth entry selfChangePermissionsPanel.spec.js (iterates over the list) SelfChangePermissionsPanel.vue ✅

Tests (local)

Suite Result
Backend auth and capability suites: ent164, 2996 ×3, 293, 1310 ×2, ent596, 186 454 passed
MCP, full (src/*.test.ts src/tools/*.test.ts) 723 passed, 0 failed; tsc --noEmit clean
Frontend, full vitest 4874 passed, 1 failed. The failure is portalBackgroundAskInboxOnly.spec.js (expected ['open'] to deeply equal ['done','open']), which fails identically on this PR's base branch (#3330), so it predates this PR and is unrelated to it.
Enterprise suite against this tree (trinity-enterprise#835 checked out on it), seeds 12345 and 106 788 passed, 5 skipped, 1 failed. The failure is the known test_500 chat label scan (public #3145; fixed on ent#818/#721, not on that branch's main). All six of #835's tests pass against this PR.
CI All green except: changes "fail 0s" is the benign cancelled duplicate (the ui label and the PR open fired together), and e2e is pending.

Critical findings

None.

Informational findings

[I1] The "Start projects" toggle shows on builds that have no projects module (Confidence: 8/10)
File: src/frontend/src/utils/capabilityGrants.js, SelfChangePermissionsPanel.vue.
The backend lists every capability in the closed set, and the panel renders SELF_CHANGE_CAPABILITIES unconditionally. On an open-source build, or one not licensed for projects, an admin can grant "Start projects", and the grant does nothing because no route uses it. The frontend already gates enterprise surfaces on enterpriseStore.enterpriseFeatures (SystemTeardownPanel.vue:207, the A2A tab).
Suggestion: give the entry requiresFeature: 'projects' and have the panel hide it unless enterpriseFeatures.includes('projects'). The backend grant can stay as it is: an unused capability row is harmless.

[I2] A capability whose only enforcement is in a private module (Confidence: 6/10)
projects.manage sits in the public closed set while the only place it's checked is the enterprise projects module. That's the open-core seam working as designed (the capability is the edition-agnostic primitive), but the docstring and requirements/auth.md should say "enforced by the projects module, when present". That way a reader of the public tree doesn't hunt for an OSS check that doesn't exist.

Summary

🤖 Generated with Claude Code

@vybe
vybe force-pushed the feature/ent756-self-change-toggles branch from 73ea1c0 to 4785b99 Compare October 8, 2026 06:58
@dolho
dolho force-pushed the feature/ent588-agent-projects branch from 08362ff to 2196f9c Compare October 8, 2026 07:12
@dolho

dolho commented Oct 8, 2026

Copy link
Copy Markdown
Contributor Author

Rebased onto the current #3330 head (2196f9cb4). #3330 had been rewritten on top of dev after #3236 squash-merged, so I cherry-picked this PR's single commit onto it. It applied cleanly. The red build was portalBackgroundAskInboxOnly.spec.js, a fixture that aged out of its 7-day window. dev fixed it in #3348, and the rebased base carries that fix. Locally, ent164 + 2996 owner-config give 175 passed, and MCP projects.test.ts gives 19 passed.

trinity-enterprise#835's refusal tests now accept the generic code until this PR lands, so that PR can go green against dev first.

🤖 Generated with Claude Code

@vybe
vybe changed the base branch from feature/ent756-self-change-toggles to dev October 9, 2026 22:45
….manage + create_project / import_project (trinity-enterprise#588)

Re-scope of ent#588 (ruling 2026-09-29, ent#661): on Trinity, /project-init
creates the project through the platform. ent#661 planned the agent right as
"a new capability beside skills.manage; changing members or visibility stays
person-only" — this is that capability, on the #3236 seam:

- db/capability_grants: `projects.manage` joins the closed set — start a
  Workspace project ON BEHALF OF the agent's owner (owner = creator and
  first member, agent = steward, members-only) and import one of the
  agent's OWN folder projects. People and visibility are never grantable.
- dependencies: its named refusal (`project_management_not_permitted`)
  with the ask instruction.
- Settings → Permissions to change itself: a fifth toggle, "Start projects".
- MCP: `create_project` and `import_project` (license-blind, like the rest
  of projects.ts), each saying the grant is needed and what the owner keeps.

The enforcement and the create/import themselves are in the enterprise
projects module (abilityai/trinity-enterprise, same issue), which checks
projects.manage before any read. Until this lands on dev the enterprise
routes refuse every agent — the capability is not in the closed set — so
the merge order is this PR, then the enterprise PR.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@vybe
vybe force-pushed the feature/ent588-agent-projects branch from 2196f9c to 085f6f6 Compare October 9, 2026 22:46
@vybe

vybe commented Oct 9, 2026

Copy link
Copy Markdown
Contributor

merge-train (2026-10-09): base PR #3330 (feature/ent756-self-change-toggles) was squash-merged to dev on 2026-10-08, so this PR was retargeted to dev and its single commit was rebased onto origin/dev with git rebase --onto (force-pushed 2196f9c → 085f6f6). The diff against dev is line-for-line identical to the previous diff against the ent756 branch (12 files, +140/−10). Mechanical, no content change.

…ts.manage (ent#588) — mechanical, per the merge-train note on the PR
@vybe

vybe commented Oct 9, 2026

Copy link
Copy Markdown
Contributor

merge-train (2026-10-10): pushed one mechanical commit fixing the three stale "four" lines the validation flagged (routers/agent_config.py docstring, requirements/auth.md grant-surface and Settings-surface lines) → "five" / adds projects to the toggle list. No behaviour change.

@vybe vybe left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

merge-train: batch validated on train/20261009-2324-b (#3504)

@vybe
vybe merged commit 9e21584 into dev Oct 9, 2026
29 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ui PR touches the frontend UI — triggers Playwright e2e tests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants