[multi-team P3a-1] Scope the AI autonomy accessor to the window's team - #15443
Conversation
|
This PR was generated with Warp. Comment |
There was a problem hiding this comment.
Overview
P3a-1 scopes the AI autonomy accessor to the window's team, keeping AiAutonomySettings as the effective-policy shape and lowering the team shape into it rather than pushing EnforceableSetting/SplitListSetting through ~25 call sites. The architecture was verified independently against both the server merge and the client conversion and is sound; the defects found are going back to the author. One question below needs your call rather than a fix.
Concerns
app/src/workspaces/user_workspaces.rs:1067-1090— the new accessor spans every workspace where the old one read only the current one, and its two halves disagree about scope.is_ai_autonomy_allowedreadcurrent_workspace();all_teams_allow_ai_autonomyiteratesself.workspaces.iter().flat_map(|w| w.teams.iter()), so a team in a different workspace configuring nothing can now switch autonomy off for a user whose current workspace's team did configure it — a real behaviour change for multi-workspace members, which the PR body says does not exist and the tests do not cover. Meanwhiletier_allows_autonomystill readscurrent_workspace()alone, so entitlement is workspace-local while policy is global. The all-workspaces shape does mirrorteams_allow_codebase_context, which the contract names as the reference, so it may be deliberate — but for a safety gate the two halves should agree, and which way they agree is your call.- Related, smaller:
has_any_team()(user_workspaces.rs:1039-1044) also spans all workspaces whileteam_from_scope→team_from_uid(:362-365) searches only the current one. So a user whose current workspace has no teams but who belongs to a team elsewhere never gets the workspace-layer fallback, even though for that workspace the settings genuinely are team-neutral. Worth settling on the same axis as the above. - Summary-level: the empty-allowlist hazard is reachable today, not only on a future data migration. Because the server merges allowlists by intersection, two admin layers with disjoint allowlists yield
values: []with both entry lists non-empty; the lowering reads that as "no override", and an allowlist is deny-by-default, so it becomes maximally permissive. Being fixed in this PR — flagged here only because the PR body currently states the opposite, and because it turns outStringListSettingInfo.isConfiguredalready exists on the wire for exactly this purpose but the client's vendored schema copy is stale.
Verdict
Checks: build pass, tests pass (104/104 local, 9/9 new), CI green except MacOS pending, visual proof n/a
Found: 0 critical, 4 important, 2 suggestions — the scope question above is yours; the rest are with the author.
affe17b to
883bdb8
Compare
d2c4855 to
7dd67ff
Compare
f6d01df to
1acd835
Compare
Migrate the AI autonomy settings accessor and the autonomy-allowed gate off ambient workspace state, and reconcile the workspace and team settings shapes so that call sites keep consuming one policy type. `AiAutonomySettings` becomes the effective-policy shape both admin layers lower into, with a `From<&TeamAiAutonomySettings>` conversion. The team wire shape's `EnforceableSetting` / `SplitListSetting` structure records which admin layer contributed a value, which is an admin-UI concern rather than policy, so it does not survive the conversion. `ai_autonomy_settings_for_scope` reads the scope's team, treats a scope with no team as governed by no policy rather than substituting another team's, and falls back to the workspace layer only for a user with no teams at all. `is_ai_autonomy_allowed` becomes `all_teams_allow_ai_autonomy`: its only consumer has no window anywhere in its call chain, so it reads across every team, conservatively. The tier policy stays workspace-level, being billing entitlement. Onboarding's autonomy-enforcement flag now resolves from the root view's handle and refreshes on `WindowTeamChanged`, which it previously ignored. Applying onboarding choices captures a scope for the write.
Also drops the remaining P0 dead-code markers on TeamScope, TeamContext, team_context and new_for_test, each of which now has a real call site.
…ompile, and a non-discriminating test The "the team wire shape cannot express an enforced-empty list" premise was wrong. Allowlists merge by intersection server-side (util.IntersectLists), so two admin layers with disjoint allowlists produce empty `values` while both entry lists are populated. Reading only `values` treated that as no override, which is the permissive answer to a deny-by-default setting and is reachable by configuration today. SplitListSetting::is_configured now consults all three lists. One case remains indistinguishable and needs the server's isConfigured. all_teams_allow_ai_autonomy lowered the whole team shape to ask six is_some() questions, compiling every org regex on a render and per-action path only to discard it, and turning one malformed org regex into a report_error! per frame. TeamAiAutonomySettings::configures_any_policy answers without lowering, and a test locks the two implementations together. The merged-values test used disjoint layers, where `values` and the layers concatenated are the same list, so it could not detect the violation it existed to catch. The layers now overlap. Also: match UserWorkspacesEvent exhaustively per AGENTS.md rather than with a wildcard, and refresh on TeamsChanged and CurrentWorkspaceChanged, which are more common staleness than the window switch.
The lowered check ignores three fields, not two. computer_use is the likeliest of them to drift: the lowering carries it into AiAutonomySettings, so it reads as an omission from the check rather than a field the check has no view of. Adding it to autonomy_allowed_by_policy previously left every test passing. Also drops caller descriptions from the two new doc comments, per AGENTS.md.
Co-Authored-By: Warp <agent@warp.dev>
Co-Authored-By: Warp <agent@warp.dev>
1acd835 to
2027abe
Compare
2027abe to
ec85be0
Compare
…indow's team Squashed for rebase onto master post-#15443. See PR description for the full account of the rework.
…indow's team Squashed for rebase onto master post-#15443. See PR description for the full account of the rework.


crux of pr is making ai_autonomy_settings & is_ai_autonomy_allowed require a team scope...
lots of threading through is then required: view context/handle -> exchange for team context -> feed into ai autonomy settings