Filed by motir run MOTIR-3500 (parent-run, guard #4) on 2026-08-25. The plan defect is already corrected — the plan cmt9b9y3p001ei4ph9145oz38 proposes the missing prerequisite and re-scopes MOTIR-3501, which is blocked. This card is the telemetry.
MOTIR-3501 specified, in its own words:
read the org's workspaces through a repository count/list method (a read that guards a write, so it takes the
tx) … when there is exactly one, create thatWorkspaceMembership… viaworkspaceMembershipRepository.create(..., tx)— same transaction
Both operations were folded into organizationsService.addMember's existing withOrgContext transaction. That transaction binds app.user_id + app.organization_id and no app.workspace_id — and under row-level security neither operation does what the card assumed. Measured against real Postgres on origin/main @ d32892bd:
TRUE org workspace count = 2
SEEN under withOrgContext(founder) = 1
INSERT under org ctx -> DriverAdapterError: new row violates row-level security policy
for table "workspace_membership"
The card was written by reading the service, and the service reads correctly. Everything the card cites is real: addMember exists, withOrgContext exists, workspaceRepository has a tx-taking count and list, workspaceMembershipRepository.create takes a tx. The policies that refuse the work are in prisma/migrations/, a directory the card never opens, and RLS is invisible at the call site by design.
The write half fails loudly and would have been caught in the first minute of building. The read half is the expensive one: it returns a plausible wrong number rather than an error. workspace's RLS answers "which workspaces may this user SEE?"; the card's predicate asks "how many does this ORG have?". Substituting the first for the second returns 1 where the truth is 2, which is indistinguishable from a small org — so the count-1 arm would fire in a two-workspace org whose inviting admin belongs to one of them, creating exactly the membership the card's own AC 3 forbids.
And AC 3's test would have passed anyway. The re-pointed fixture it describes creates both workspaces from one owner, which puts the actor in both, so the actor-scoped read returns 2 and the arm correctly does not fire — for the wrong reason. The card ships green with the defect in it. (The re-scope now pins the fixture: the acting admin must be in exactly one of the two.)
MOTIR-3500's premise is that organization-tier.md §5 and §6 were never reconciled at count = 1. Neither clause ever says whose count. §6's "count ≥ 2" reads as the organization's; the shipped gate ShellTierNav.tsx:103 counts listUserWorkspaces(session.user.id) filtered to the active org — the viewer's. They coincide exactly when the viewer belongs to every workspace in the org, which is the founder case, which is why nobody noticed.
Both answers are right in their own place and only one is right in each: the membership arm must read the org (whether an invitee is stranded cannot depend on their inviter's memberships) and the disclosure arm must read the viewer (a door nobody can walk through should not be drawn). MOTIR-3501 AC 5 now requires the amendment to say so.
The gap was already written down — lib/repositories/githubRepoRepository.ts:285-305 says "'the org's workspaces' IS NOT READABLE FROM A BACKGROUND PATH … Widening workspace's RLS instead would be a cross-tenant access change, which is not this card's to make." It sits in a comment explaining a workaround, where nothing planning MOTIR-3501 would ever read it.
plan-rules/core.md gate 2 (preconditions verified against shipped reality) covers does this symbol exist. Both symbols existed. What no gate asks is does the security context this card folds its work into ADMIT that work — a question whose answer lives one layer below every file the card cites.
plan-rules/core.md gate 2 gains a limb — or a sibling gate is added — requiring that a card which places a write, or a read that guards one, inside an existing transaction / security context names the policy or binding that admits it, verified against the migration rather than the call site.cmt9b9y3p001ei4ph9145oz38 — the correction awaiting approvalmotir-meta/prompts/plan-rules/core.md gate 2 — where the limb landsmotir-core lib/organizations/context.ts, lib/workspaces/context.ts:209, lib/repositories/githubRepoRepository.ts:285-305motir-core prisma/migrations/20260810001000_tenant_root_insert_policies/migration.sql:110, 20260527134009_add_workspace_rls/migration.sqlRepo: the fix is a rule change in motir-meta (prompts/plan-rules/core.md). No criterion names a path in another repository — the motir-core refs above are evidence, not deliverables.