diff --git a/docs/internal/MULTITENANT-HANDOFF.md b/docs/internal/MULTITENANT-HANDOFF.md index a4bcfd1..c8701ce 100644 --- a/docs/internal/MULTITENANT-HANDOFF.md +++ b/docs/internal/MULTITENANT-HANDOFF.md @@ -1,5 +1,22 @@ # Multitenant Handoff +## Agent Identity + +| Agent | `user.name` | Platform | Lane | +| ----------------- | ------------------- | -------- | ------------------------------- | +| Operator & zAI | `Operator & zAI` | Linux | Code review, cleanup, push | +| Operator & Codex | `Operator & Codex` | FreeBSD | Tests, build, host provisioning | +| Operator & Claude | `Operator & Claude` | Linux | Code review, edits, push | + +All agents share `user.email = hello@clawdie.si`. +Check attribution: `git log --format='%h %an — %s' -20` + +Each agent must set `user.name` in the repo before committing: + +``` +git config user.name "Operator & " +``` + ## In flight This branch is worked on by more than one agent in parallel. Before @@ -7,7 +24,7 @@ starting a new edit, append a one-line claim here; remove the line in the same commit that closes the work. Keep entries short and concrete so a peer can tell at a glance whether their planned change overlaps. -Format: `- · · · ` +Format: `- · · · ` Working agreement: @@ -88,6 +105,7 @@ Cross-repo: 886 lines now. Working through my own 16-point gap analysis: Bugs fixed: + - `platform.reserved_host_labels` schema field + dedicated section enumerating `[ai, cms, git, web, www, mail]`. Decision 13's Configurable cell now reads "No — `ai` is reserved" instead of @@ -109,6 +127,7 @@ Bugs fixed: `host_label`). Substantial gaps filled: + - New "How tenants reach the code service" section parallel to CMS: operator-only admin in V2, tenants reach via git+SSH/HTTPS. - New `code_admin_exposure` schema field with V2: must be @@ -122,6 +141,7 @@ Substantial gaps filled: `ai.`. Polish: + - Stale claim example removed from the In flight format spec. - New "Naming conventions appendix" with mechanical rules. - Wildcard DNS/TLS sharp-edge note in the cloud worked example. @@ -395,7 +415,7 @@ following cleanup keeps the contract honest and the type tractable. currently hard-coded (`false` and `[]`). Compute them from real signal — at minimum: `readyForAutomaticApply = blockers.length === 0 - && !preflightChecks.some(c => c.status === 'blocked')`. +&& !preflightChecks.some(c => c.status === 'blocked')`. Even when the only contributor today is "live apply path does not exist", deriving the boolean is cheap and prevents the field from silently lying when a real check is added.