Merge branch 'main' of amadan.net/oficina/meet
Slice 6's docs landed while mid-call device switching was in the gates. Documentation only — no Go, no client, no templates — so the binary already on edge (9434395) is behaviourally identical to one built from this merge, and is left serving rather than redeployed: every deploy restarts the instance and drops live calls.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
6 files changed,
+962
−45
AGENTS.md+24 −5PRODUCT.md+269 −0README.md+175 −0docs/superpowers/plans/2026-09-14-meet-slice-6-deploy.md+157 −0docs/superpowers/reviews/2026-09-14-slice-6-record.md+209 −0docs/superpowers/specs/2026-09-07-meet-design.md+128 −40
CI passed — run details
diff --git a/AGENTS.md b/AGENTS.md| index 3bc2096..a163561 100644 |
| --- a/AGENTS.md |
| +++ b/AGENTS.md |
| @@ -50,11 +50,13 @@ mechanically. |
| a rename is indistinguishable from a drop plus an add. |
| - Money is integer cents. A float never touches a value a person will |
| be held to. |
| -- Screens work with JavaScript disabled, with one exception: browser |
| +- Screens work with JavaScript disabled, with two exceptions: browser |
| media participation (the holding screen's camera preview and join |
| - button, and the call itself in the room) needs script; both pages |
| - render their title, standing, floor notice and navigation without it. |
| - Destructive actions get their own confirm-page URL. |
| + button, and the call itself in the room), and, once a call exists, |
| + the room's chat panel and its admission queue's Admit controls; both |
| + pages still render their title, standing, floor notice and |
| + navigation without script. Destructive actions get their own |
| + confirm-page URL. |
| - The gate is `make ci` (vet + gofmt + tests) — the same definition |
| CI runs. Run it before every push. `CGO_ENABLED=0` throughout: the |
| stack is cgo-free by design. |
| @@ -81,9 +83,26 @@ the golden deployment target, not a requirement: `./app -addr :8080` |
| serves anywhere. `GET /healthz` and `GET /api/version` are answered |
| by the framework, outside app middleware. |
| +## Deploying |
| + |
| +`make release VERSION=<sha>` builds and stamps the artifact; `carlos |
| +deploy --app meet --account oficina --channel edge --version <sha> |
| +--target linux-arm64 releases/meet-linux-arm64` ships and promotes it, |
| +waiting until `/api/version` serves it — but only once `carlos apps |
| +build-probe --app meet --account oficina /api/version` has been run |
| +for the app (set on the flagship app since 2026-09-09); a new app or |
| +account needs that first, or the wait watches `X-Carlos-Version` |
| +instead, which can report the version adopted before the process has |
| +actually changed. A migration applied under an earlier filename fails |
| +at boot; otherwise migrations never re-run. Every deploy, and every |
| +relay config change, restarts the instance and drops live calls — no |
| +drain exists. The wait can time out before |
| +hand-over — check `/api/version` before retrying. See the README's |
| +Deploying section for the canary recipe. |
| + |
| ## UX conventions (seeded from profile: considered) |
| -Accessible by construction, progressively enhanced, and never dependent on JavaScript to be usable, with the one exception named above: browser media participation, on the holding screen and in the room. |
| +Accessible by construction, progressively enhanced, and never dependent on JavaScript to be usable, with the exceptions named above: browser media participation, on the holding screen and in the room, and, once a call exists, the room's chat panel and admission controls. |
| These are rastrillo's own conventions, and the profile is named for what it does rather than after anyone else's work. For wider reading on interface quality, impeccable.style, the WAI-ARIA Authoring Practices and Inclusive Components are all worth your time — none of them is endorsed by, or authoritative for, this framework. |
diff --git a/PRODUCT.md b/PRODUCT.md| new file mode 100644 |
| index 0000000..871ef8e |
| --- /dev/null |
| +++ b/PRODUCT.md |
| @@ -0,0 +1,269 @@ |
| +# Product |
| + |
| +<!-- impeccable:product-schema 1 --> |
| + |
| +> **How this file was written.** Written unattended, on the same |
| +> instruction that produced `oficina/docs`' `PRODUCT.md`: every fact |
| +> below comes from repository evidence, not an interview — |
| +> `docs/superpowers/specs/2026-09-07-meet-design.md` (revision 9, plus |
| +> the 2026-09-10 and 2026-09-12 amendments), `AGENTS.md`, the slice |
| +> records under `docs/superpowers/reviews/`, `native/README.md`, and the |
| +> shipped code in `internal/meet/` on branch `slice/6-deploy`, main |
| +> `9225ec2`. Facts are cited to a spec section or a file. A reading |
| +> rather than a citation is marked **[inferred — confirm]** and should |
| +> be corrected, not trusted. A bare "ruling N" is the Meet spec's §1; a |
| +> doctrine ruling is always written "suite ruling N". |
| + |
| +## Platform |
| + |
| +Web, plus native Mac and iPhone/iPad clients over the same server |
| +contracts (spec §8.4's 2026-09-14 amendment, `native/README.md`). |
| + |
| +## Users |
| + |
| +**Primary: a member of one team**, making and joining that team's video |
| +calls. The instance boundary is the team — one instance per team |
| +(preamble; suite ruling 1, 5, §0.2), the "lone shape" until a suite home |
| +exists (§7.1). **Secondary: an outside guest**, admitted with a real |
| +identity, never as an anonymous URL holder: every participant signs in, |
| +and a meeting link gives an outsider a **guest grant**, never a way in |
| +without a name (ruling 1; suite ruling 15); a guest waits until an |
| +admitted member lets them in (ruling 9, §3.3). |
| + |
| +Access is a magic link gated by `MEET_ALLOWED_ADDRESSES` |
| +(`internal/meet/config.go`), with optional Home sign-in when an operator |
| +sets all four `MEET_HOME_*` settings (§7.1.1) — Home only *links* an |
| +existing member after independent local sign-in; it never creates a |
| +person or grants membership. Unlike Docs' §8.1, the spec states no |
| +passkey ruling of its own. **[inferred — confirm]** the team is assumed |
| +small enough that an address allowlist is appropriate; the spec states |
| +no target size. |
| + |
| +## Product Purpose |
| + |
| +Meet is **video calling for one Oficina team**: a member makes a |
| +meeting, sends one link, and the people who follow it set up camera and |
| +microphone, wait to be let in if not on the team, and talk (preamble). |
| +"The instance carries the pages, the sign-in, the signalling and the |
| +in-call chat, and never a frame of media" (§0.1) — falsifiable: publish |
| +the SQLite file, its WAL, and every log line, and the worst anyone |
| +learns is the shape of the team's meetings and who minted what, never a |
| +title, chat text, or signalling payload, enforced by a WAL-grep test and |
| +a captured-logger test, not merely asserted (§0.1). |
| + |
| +## Positioning |
| + |
| +1. **The claim is made per process, not once** (§0.1): Meet's own |
| + process never touches a media packet; the platform TURN relay |
| + forwards encrypted DTLS-SRTP it cannot read; a future platform SFU |
| + decrypts to forward and gets its own spec revision when it ships |
| + (§5.7). |
| +2. **No relay of its own, by ruling** (suite ruling 6, §5.2): present |
| + `CARLOS_RELAY` mints ICE credentials per call; absent means host |
| + candidates only, stated before the join button (§5.5). |
| +3. **Two authorities, not one, for a room.** *Standing* (§2.3, computed |
| + per request, never stored) decides who may **enter**; a |
| + *participation* (§2.4, hub state) decides who may **continue** — an |
| + admitted guest keeps talking past its grant's expiry while a member |
| + who loses standing is dropped at once (ruling 14). |
| + |
| +## Operating Context |
| + |
| +- **One Go binary per instance**, `CGO_ENABLED=0`, deployed on CARLOS as |
| + a **unit route** (§7.3). Native Apple bindings under `native/` are the |
| + one place cgo is used, isolated in `native/go.mod` (`AGENTS.md`). |
| +- **Routes today** (`internal/meet/app.go`): `GET /`, `POST /meetings`; |
| + `GET /j/{token}` (outside the session group); the holding screen and |
| + room; signalling (`stream`, `signal`, `ice`); `POST /m/{sqid}/share` |
| + (2026-09-12); five destructive confirmation pairs (remove, takeover, |
| + replace invitation, end meeting, revoke agent); Settings and agent |
| + tokens; sign-in including optional Home routes; native handoff |
| + endpoints; a bearer-only `/api/v1/*` group (`api.go`) outside CSRF and |
| + the session group. `GET /healthz`/`GET /api/version` answer from |
| + rastrillo itself, outside app middleware. |
| +- **Scriptless, with browser media participation as the exception, and |
| + two script-only parts inside a live room.** Reaching a camera and |
| + another browser needs script; so, once a call exists, do the chat |
| + panel (`partials/chat.html` renders it `hidden` until script un-hides |
| + it) and the admission queue's Admit controls (`room.js`). Every other |
| + screen — the list, creating a meeting, a link shown once, every |
| + confirm page, sign-in, `/welcome`, the agent token page, the Share |
| + page and the Home account-link screens (§7.1.1), and the |
| + server-rendered parts of the holding screen and room — works with |
| + scripts off (§9; `AGENTS.md`'s UX line carries the media exception; |
| + full list below). |
| +- **Nothing stored beyond a meeting's bones.** Rooms, peers, admission, |
| + chat and presence live in an in-process hub and die with the process |
| + (§2.2); a restart drops every live call (§4.5). Stored: `persons`, |
| + `meetings` (sealed title, `internal/meet/seal/`), `meeting_links` |
| + (hash-indexed plus a sealed copy for sharing since 2026-09-12), |
| + `pending_joins` (a keyed address fingerprint, never plaintext), |
| + `guest_grants`, `agents` (a member's minted principal; the token |
| + itself is never stored, only its SHA-256) (models.go; §2.1). |
| + |
| +## Capabilities and Constraints |
| + |
| +**Shipped:** meeting creation and listing; a link shown once, replaced |
| +or shared via `POST /m/{sqid}/share`; sign-in with the pending-join |
| +exception admitting an outsider only while holding a live link (ruling |
| +12, §3.2); optional Home account-linking (§7.1.1); the holding screen |
| +and a P2P mesh room capped at four with perfect negotiation, resume, and |
| +a replay ring (§4); relay-minted ICE credentials renewed before deadline |
| +(§5.2, §5.3); ephemeral chat and screen share (§6, §5.4); a bearer-token |
| +drive surface for agents re-checking operator membership on every |
| +request (§8, §15.17); native Mac and iPhone/iPad apps sharing the Go |
| +protocol core (`native/README.md`). |
| + |
| +**Deliberately not built yet** (§11, as amended): see "What is |
| +deliberately not here" below for the full, cited list. |
| + |
| +**Binding technical constraints:** |
| + |
| +- **Media never touches Meet's own process** (§0.1); no handler accepts |
| + a media packet. **`scope.Owned`, no bound request body**: every |
| + user-owned query goes through it, reads and writes alike; a row that |
| + isn't yours 404s, never 403s (`AGENTS.md`). |
| +- **Standing is computed, never cached** — every request, every |
| + 15-second hub tick (§2.3, §2.4). A shipped migration is never edited. |
| + The agent API's rate limit keys on the resolved agent, not the client |
| + address, deliberately (§15.17; see below). |
| +- **`CGO_ENABLED=0 make ci` is the server's cgo-free gate.** Two |
| + things run under `CGO_ENABLED=1` and never ship: `make race`, for |
| + any change to `internal/meet/hub` or the stream, and `make |
| + native-test`'s own `meetcore` race sub-step. The native Mac and |
| + iPhone/iPad apps are the one place real cgo does ship — `MeetBridge` |
| + is a binary target `MeetKit` links (`native/apple/Package.swift`, |
| + `native/scripts/build-mac.sh`) — while every server release stays |
| + `CGO_ENABLED=0` (`AGENTS.md`). **`make browser`** needs UDP, which |
| + the Claude Code bash sandbox blocks (`AGENTS.md`). |
| + |
| +## Brand Commitments |
| + |
| +- **Name:** Meet, `amadan.net/oficina/meet`, first served at |
| + `meet.oficina.works` (preamble; ruling 2 chose `oficina/meet` over |
| + `oficina/conferencia`). Built beside Docs, Calendar, Slides and the |
| + suite doctrine, consuming a decision made there rather than restating |
| + it (preamble, §0.2). |
| +- **The theme is Estilo's**, adopted at whatever Estilo holds when each |
| + slice lands. As recorded on 2026-09-14 (`git ls-remote --tags` |
| + against `oficina/estilo`, empty at that check), no tag exists; |
| + consumed at a pseudo-version, already adopted by the Home integration |
| + on main. **[inferred — confirm]** the exact commit at any later date. |
| +- **The chat panel is Meet's contribution to Estilo** — "one |
| + self-contained template partial and one script file so a second app |
| + can adopt it," the suite's first chat, built to be taken (§6). |
| +- **Voice: [inferred — confirm].** Copy review was waived for this |
| + documentation round (steering on `oficina/suite` discussion 5), so |
| + shipped strings were not checked against a review record. |
| + |
| +## Evidence on Hand |
| + |
| +- **Spec:** revision 9 plus the 2026-09-10 and 2026-09-12 amendments, |
| + 2100+ lines, six rounds of Codex review (§14). **Plans:** |
| + `docs/superpowers/plans/`, one programme (slices 2–6) plus a plan per |
| + slice. **Slice records:** `docs/superpowers/reviews/`, one per slice |
| + 2–5 (room, relay, chat/screen-share, drive surface), each an index |
| + into the spec's own §15 rulings for that slice. |
| +- **Native:** `native/README.md`, `native/DESIGN.md`, |
| + `native/VERIFICATION.md` — build, gates, stated acceptance limits (no |
| + real-device pass claimed for camera permissions, audio-device |
| + switching, sleep/wake, or Home passkeys). |
| +- **What does not exist and must not be invented:** customers, |
| + testimonials, benchmarks, pricing, usage numbers, launch date, press, |
| + or a production promotion from this slice — edge |
| + (`meet.oficina.works`) is promoted by hand by Paul, separately from |
| + documentation (slice 6 plan, "What slice 6 was"). The acknowledgements |
| + page and the Estilo theme pin are the other two slice-6 items with a |
| + disposition rather than a delivery; spec §15.18 is the record for all |
| + three. |
| + |
| +## Product Principles |
| + |
| +1. **State the degradation rather than let it be discovered.** The |
| + no-relay floor says calls usually connect only on the same network |
| + (§5.5); §0.3 states what the privacy claim excludes (signalling in |
| + flight, a replay ring of up to 32 messages for 30 seconds, a link as |
| + a bearer); the mail-budget residue is written down, not claimed away |
| + (§3.2). |
| +2. **A verification that cannot distinguish "no" from "I can't see it" |
| + is not a verification.** The §0.1 claim is enforced by grepping raw |
| + SQLite bytes and the WAL and capturing the logger during a real call; |
| + `make browser` asserts a received track by `ontrack` and frame count, |
| + never a label (§13). |
| +3. **Two authorities are named because one would be wrong in some |
| + direction** (§2.3–§2.4, ruling 14): a single authority either drops |
| + an admitted guest at the grant's two-hour mark or lets an expired |
| + grant re-enter. |
| +4. **A contract is written for the next client, not the current one.** |
| + Signalling, `/ice` and the meeting API are contracts a native client |
| + could speak (ruling 15, §8.4); the native apps are that ruling paying |
| + off. |
| +5. **Actors are `person:<id>` or `agent:<id>`, never fabricated** |
| + (§7.2, doctrine ruling 9). |
| + |
| +## Accessibility & Inclusion |
| + |
| +`AGENTS.md`'s vendored UI conventions apply: labelled fields with one |
| +error envelope, destructive actions on their own confirm-page URL and |
| +never a modal (`ui/confirm-form` — §3.1, §3.5, §4.2), state shown with a |
| +text label and not colour alone, and empty states that say what the |
| +screen is for. |
| + |
| +**The scriptless floor is the accessibility constraint this app adds |
| +beyond that shared list.** Reaching a camera and another browser needs |
| +script, and so, once a call exists, do the room's chat panel and its |
| +admission-queue Admit controls; nothing else does. With scripts off |
| +the holding screen's join button becomes one paragraph saying a call |
| +needs JavaScript and everything else on the page works without it |
| +(§3.3); the room does the same (§3.4). |
| + |
| +No target locale count or WCAG conformance level is stated in the Meet |
| +spec or `AGENTS.md`. **[inferred — confirm]**: Docs states "WCAG 2.2 AA, |
| +no exemptions" for itself; nothing here says the same target binds Meet, |
| +and this file does not assume it does. |
| + |
| +## What is deliberately not here |
| + |
| +- **Scriptless media, chat and admission** — the exceptions to the |
| + scriptless floor: reaching a camera and another browser needs script, |
| + and so, once a call exists, do the room's chat panel and its |
| + admission-queue Admit controls; every other screen, including the |
| + server-rendered parts of the holding screen and the room, works with |
| + scripts off (spec §9; `AGENTS.md`'s UX-conventions line carries the |
| + media exception in the same words). |
| +- **No STUN or TURN server of Meet's own.** ICE servers come from the |
| + platform relay, present or not at all — never a server Meet names |
| + itself (suite ruling 6, §5.2, §5.5). |
| +- **No SFU, and the room is capped at four admitted peers** — not a |
| + claimed product limit, the mesh's own (ruling 5), lifted only when a |
| + platform SFU that decrypts to forward ships, in its own spec revision, |
| + not a quiet cap change (§5.7, §0.3, §11 "rooms above four"). |
| +- **No client-address limiter on the drive surface.** The agent API's |
| + per-agent rate limit (one request a second sustained, burst 60) keys |
| + on the resolved agent, not the client address: behind the platform's |
| + relay socket every request can share one address, and an |
| + address-keyed limiter would let one flood take out every real agent |
| + at once (§15.17). |
| +- **No passkeys ruling of its own.** Unlike Docs §8.1, the spec states |
| + no instance-local-passkey decision. **[inferred — confirm]**. |
| +- **Chat is never stored.** A `chat` message fans out to admitted peers |
| + and renders client-side; not replayed to a peer who joins or resumes |
| + later, gone with the tab (ruling 8, §6). |
| +- **No recurring meetings, Calendar integration, recording, attendance |
| + records, reactions, dial-in, captions, multi-host signalling, |
| + push-to-talk, or virtual backgrounds, and no way to deny a knock** — a |
| + guest who isn't admitted simply waits or leaves (§11). |
| +- **No native client sign-in method of its own** — a native client |
| + authenticates through the same Home/local sign-in the browser uses, |
| + handed off through a five-minute, one-use authorization; no separate |
| + bearer or token scheme for native apps (§8.4's 2026-09-14 amendment, |
| + `native/README.md`). |
| + **No attendance claim, ever**: §0.3 says Meet does not record who was |
| + in a call or for how long; an earlier revision implied one and the |
| + spec dropped the implication rather than building the model. |
| + |
| +--- |
| + |
| +*See also:* the design spec, `README.md`, `AGENTS.md`, and the slice |
| +records under `docs/superpowers/reviews/`. |
| + |
diff --git a/README.md b/README.md| new file mode 100644 |
| index 0000000..53753fb |
| --- /dev/null |
| +++ b/README.md |
| @@ -0,0 +1,175 @@ |
| +# Meet |
| + |
| +Meet is video calling for one team. A member makes a meeting, now or |
| +for later, and sends one link; anyone who follows it sets up their |
| +camera and microphone on a holding screen, waits to be let in if they |
| +are not on the team, and talks in a room of up to four, with chat |
| +beside the call and a screen to share. An agent can also create, |
| +list, relink and end meetings over an API. Every screen works with |
| +JavaScript disabled except browser media participation — the camera |
| +preview and join button on the holding screen, and the call itself in |
| +the room — and, once a call exists, the room's two other script-only |
| +parts: the chat panel and the live admission queue with its Admit |
| +controls. Both pages still render their title, start time, standing, |
| +floor notice, the paragraph that says what needs script, and a |
| +member's navigation with scripts off (spec §9). |
| + |
| +ICE servers come from the CARLOS platform relay, delivered as |
| +`CARLOS_RELAY` and minted fresh for each call at `GET /m/{sqid}/ice`; |
| +Meet names no STUN or TURN server of its own (suite ruling 6). With no |
| +relay configured, calls are direct only: two browsers connect when ICE |
| +can find a working path straight between them, which the holding |
| +screen states plainly above the join button: "This team's Meet has no |
| +relay yet. Calls usually connect only between people on the same |
| +network." Enabling or changing the relay restarts the instance. When |
| +the relay is in the path it forwards DTLS-SRTP packets encrypted |
| +between the browsers, so it carries bytes it cannot read; Meet's own |
| +process never receives a media packet at all. With the relay on, a |
| +call that still fails says "could not connect, even through the |
| +relay" and offers retry; it does not diagnose the network. One known |
| +cause is a network that allows only TCP 443, because the relay's TLS |
| +listener is deferred by the platform — a possibility, not a verdict |
| +(spec §0.1, §5.2, §5.5, §5.6, §7.3, §15.13). |
| + |
| +## Sign-in |
| + |
| +Sign-in is a magic link to an address on the team's allowlist |
| +(`MEET_ALLOWED_ADDRESSES`). Following a meeting link gives an outsider |
| +a guest grant at sign-in — never a way into a room without a name — |
| +and the allowlist otherwise gates sign-in exactly as it does for a |
| +member (spec §3, §7.1). An operator can also enable Home sign-in with |
| +all four of `MEET_HOME_ISSUER`, `MEET_HOME_CONSUMER_ID`, |
| +`MEET_HOME_KEYS_BASE64` and `MEET_HOME_DEK_BASE64` — never a partial |
| +set — which links an existing member after a fresh, independent local |
| +sign-in and explicit confirmation; it never creates a person or grants |
| +membership on its own (spec §7.1.1). Because a member's address can be |
| +rate-limited on purpose and gets a different answer from an unknown |
| +one, whether a given address is on the team is not a secret the |
| +sign-in form can keep; that residue is stated rather than claimed away |
| +(spec §3.2). |
| + |
| +## The room |
| + |
| +The room is a peer-to-peer mesh of up to four admitted participants, |
| +negotiated with the W3C perfect-negotiation pattern over an SSE stream |
| +and a POST signal per peer. A guest waits in a queue until an admitted |
| +member lets them in; removing a participant and ending a meeting each |
| +go through their own confirm page — there is no in-room control that |
| +skips one (spec §3.5). A member can retrieve the current invitation |
| +again from the holding screen or the room with Share (`POST |
| +/m/{sqid}/share`). On a meeting whose only link predates the |
| +2026-09-12 sharing update, the first Share mints a new recoverable |
| +invitation alongside the old, still-valid one rather than opening it; |
| +every Share after that retrieves the same recoverable one. Replacing a |
| +link revokes every live one. Chat is fanned out live to admitted peers |
| +and never stored (spec §6). Screen share adds a second tile per sharer |
| +(spec §5.4). The room lives in one process's memory, so every deploy |
| +drops every live call (spec §15.11). |
| + |
| +## Agents |
| + |
| +A member mints an agent's bearer token from Settings; it is shown once |
| +and the row after it keeps only its hash. The token works on |
| +`/api/v1` only — never a cookie there, and never a bearer on an HTML |
| +route — for five operations: list meetings, create one, replace its |
| +link, end it, and read one meeting's detail. It cannot join a call |
| +(spec §8). An agent's reach is re-derived from its operator's current |
| +standing on every request, so an operator who leaves the team takes |
| +their agent's reach with them at once, with no separate revocation |
| +step. Requests are limited per agent to one a second sustained, with a |
| +burst of 60 (spec §8, §15.17). |
| + |
| +## Native apps |
| + |
| +The SwiftUI Mac and iPhone apps use this same server and a shared Go |
| +core (`meetcore/`, `protocol/`); there are no embedded webviews. Build |
| +the Mac app with `make native-mac`. See `native/README.md` and |
| +`native/ios/README.md` for setup, native sign-in and the native gates. |
| + |
| +## Building and gates |
| + |
| +`CGO_ENABLED=0 make ci` (vet, gofmt, tests, migration check) is the |
| +one gate a runner and a push share; `ci` itself does not set the |
| +variable, so the runner and every push must. Three things ship or run |
| +under `CGO_ENABLED=1`, each isolated from the server: `make race` |
| +builds a server test binary, never a release, for any change to |
| +`internal/meet/hub` or the signalling stream; `make native-test`'s own |
| +`meetcore` race sub-step does the same for the shared Go core; and the |
| +native Mac and iPhone/iPad bindings under `native/` bridge Go to |
| +Objective-C with real cgo, isolated in `native/go.mod` and built with |
| +`make native-mac`. `make browser` drives a real call across two real |
| +Chromium contexts, 31 scenarios in about nine minutes; it needs the |
| +Claude Code bash sandbox off, because the sandbox blocks UDP and every |
| +call then fails with `frames` stuck at 0. `make release VERSION=<sha>` |
| +stamps that version into `/api/version`, so a deploy can be checked |
| +against what it is meant to be running. |
| + |
| +## Deploying |
| + |
| +Meet deploys as a CARLOS unit route. Build the artifact first — `make |
| +release VERSION=<sha>` produces `releases/meet-linux-arm64`, stamped |
| +with the version `/api/version` will report (`strings -a |
| +releases/meet-linux-arm64 | grep -cx <sha>` confirms the stamp) — then |
| +deploy it: `carlos deploy --app meet --account oficina --channel edge |
| +--version <sha> --target linux-arm64 releases/meet-linux-arm64`, |
| +which waits until `/api/version` reports it — but only once a build |
| +probe is configured for the app: `carlos apps build-probe --app meet |
| +--account oficina /api/version`, set on the flagship app since |
| +2026-09-09. A new app or account needs that command run once before |
| +the wait means anything; without it `carlos deploy` watches |
| +`X-Carlos-Version` instead, which can report the new version adopted |
| +before the running process has actually changed. `--account` is a |
| +global flag; `carlos ship` uploads only, while `carlos deploy` is ship, |
| +promote and wait (its own help text). Building for your own |
| +architecture and shipping that uploads fine and fails to exec on the |
| +instance. |
| + |
| +These are the settings a deploy needs (`config.go`, `standing.go`). |
| +Five refuse startup when empty outside `-env development`: |
| +`MEET_ORIGIN` (the external origin, scheme included); |
| +`MEET_INSTANCE_KEY`; `MEET_DEK` (base64 of exactly 32 decoded bytes, |
| +not 32 base64 characters); `MEET_ALLOWED_ADDRESSES` (comma-separated, |
| +non-empty — this is the team); and mail, `MEET_SMTP_*` or the |
| +platform's `CARLOS_SMTP_*`. Two are optional, each with its own |
| +default rather than a refusal: `MEET_ZONE` (an IANA zone, defaulting |
| +to UTC when unset) and `CARLOS_RELAY` (empty means no relay, §5.5 — |
| +only a *malformed* value refuses startup), delivered by `carlos relay |
| +enable --app meet` rather than set by hand. Secrets — |
| +`MEET_INSTANCE_KEY`, `MEET_DEK` and `MEET_SMTP_PASS` — go through |
| +`carlos secrets`; the rest go through `carlos env`. Mail reads |
| +`MEET_SMTP_*` with `CARLOS_SMTP_*` as a per-variable fallback; the |
| +platform supplies a sender too |
| +(`CARLOS_SMTP_FROM`), which `MEET_SMTP_FROM` can optionally override, |
| +so `carlos email enable` alone is enough to send mail. `carlos relay |
| +enable --app meet` turns on the platform relay. Every deploy, and |
| +every relay change, restarts the instance and drops every live call — |
| +no drain exists, so deploy outside meeting hours. Migrations apply |
| +once each at boot (`msg=migrate` in the log) and are never re-run; a |
| +database that already applied a migration file under an earlier name |
| +fails at boot rather than silently diverging. The deploy wait can time |
| +out before the hand-over while the instance then serves the new |
| +version a minute later — check `/api/version` before retrying. |
| + |
| +Canary a build on its own host: `carlos canary --app meet --name |
| +slice2` composed `slice2.meet.bds.oncarlos.com`, and the console |
| +refused it ("invalid host, an instance host is one DNS label followed |
| +by .bds.oncarlos.com") — as recorded on 2026-09-10 in platform |
| +discussion #124, open as of that record. The recipe actually used: |
| +`carlos instances create --app meet --account oficina --host |
| +slice2-meet.bds.oncarlos.com --channel canary/slice2 --environment |
| +slice2`. The `slice2` environment bundle must already exist, created |
| +separately, carrying `MEET_ORIGIN` for the canary host; without it |
| +sign-in refuses on the canary while GETs look healthy. Then `carlos |
| +deploy --account oficina --app meet --channel canary/slice2 --host |
| +slice2-meet.bds.oncarlos.com --version <sha> |
| +releases/meet-linux-arm64`. |
| + |
| +## Where things are written down |
| + |
| +The design lives in `docs/superpowers/specs/2026-09-07-meet-design.md`, |
| +the slice plans in `docs/superpowers/plans/`, and each slice's review |
| +in `docs/superpowers/reviews/`. `PRODUCT.md` covers what Meet is for |
| +and what it deliberately leaves out; `AGENTS.md` covers the |
| +conventions the code is held to. Spec §15.18 is the disposition of |
| +record for what slice 6 delivered, deferred (the acknowledgements |
| +page) and declined (the Estilo theme pin, the production promotion). |
diff --git a/docs/superpowers/plans/2026-09-14-meet-slice-6-deploy.md b/docs/superpowers/plans/2026-09-14-meet-slice-6-deploy.md| new file mode 100644 |
| index 0000000..dbbce1a |
| --- /dev/null |
| +++ b/docs/superpowers/plans/2026-09-14-meet-slice-6-deploy.md |
| @@ -0,0 +1,157 @@ |
| +# Meet Slice 6: Deploy Docs Implementation Plan |
| + |
| +> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. |
| + |
| +**Goal:** Close the Meet programme (spec §12 item 6) with the documents a deployed app owes: README, PRODUCT.md, the *Consumed suite rulings* commit for suite Appendix A.6, AGENTS.md's final notes, and the slice record, each true of main as it is on 2026-09-14. |
| + |
| +**Architecture:** Documentation only. Nothing under `internal/`, `native/`, `meetcore/` or `protocol/` changes. Every sentence about behaviour is checked against the code on main `9225ec2` before it is written, and cites the spec section or file it comes from. Items of the programme's slice 6 that other sessions have already delivered or are delivering are recorded as such, not redone. |
| + |
| +**Tech Stack:** Markdown; the spec at `docs/superpowers/specs/2026-09-07-meet-design.md` (revision 9 plus the 2026-09-10 and 2026-09-12 amendments on main); the suite sharing doctrine at `oficina/suite` `docs/superpowers/specs/2026-09-05-suite-sharing-doctrine.md` revision 8, main `1ac4323`. |
| + |
| +**Spec:** `docs/superpowers/specs/2026-09-07-meet-design.md` §7.3, §9, §10, §11, §12 item 6, §0.2. Programme: `docs/superpowers/plans/2026-09-09-meet-slices-2-6-programme.md` (slice 6 line and §5). |
| + |
| +## Global Constraints |
| + |
| +- Branch `slice/6-deploy` from main `9225ec2`; docs only; `make ci` stays green (it is unaffected by Markdown, run it once at the end). |
| +- No user-facing app string changes. Copy review is waived for this round by Paul's steering on `oficina/suite` discussion 5 ("copy review is explicitly waived for this entire massive round"); README and PRODUCT.md prose is catalogued in the record, not reviewed. |
| +- Every claim about behaviour is verified against the code on `9225ec2` (not against memory of earlier slices) and cites its source. A claim that cannot be verified is not written. |
| +- The README's first paragraph carries the scriptless-floor sentence (spec §9: browser media participation needs script, everything else works with scripts off) and the second paragraph is the relay paragraph (spec §5.2, §5.5: ICE servers come from the platform relay through `CARLOS_RELAY`, Meet names no STUN or TURN server of its own; with no relay, calls are direct only). |
| +- Nothing here restates a suite ruling; §0.2 names rulings by number (doctrine Appendix A intro: "delete the restatement, name the ruling"). |
| + |
| +## What slice 6 was, and what it is now |
| + |
| +The programme (2026-09-09) listed for slice 6: PRODUCT.md, the README with the floor and relay paragraphs first, AGENTS.md's final notes, the acknowledgements page, the *Consumed suite rulings* commit for suite Appendix A.6, the Estilo theme pin if a tagged release exists, and the production promotion with its notification. Since slice 5 shipped (a283c53, 2026-09-11) other sessions landed on main: Home sign-in (`7.1.1`, `internal/meet/home.go`), the shared Estilo day theme and brand (`f9cb47f`, `34fc367`; `amadan.net/oficina/estilo.git` as an indirect pseudo-version), the invitation `Share` route (`POST /m/{sqid}/share`, 2026-09-12 amendment), and the native Mac, iPhone and iPad apps (`native/`, `meetcore/`, `protocol/`, tag `v0.1.0` at `9225ec2`). Therefore: |
| + |
| +| Programme item | Disposition in this slice | |
| +|---|---| |
| +| PRODUCT.md | Task 2, here. | |
| +| README with floor and relay paragraphs first | Task 1, here. | |
| +| AGENTS.md final notes | Task 1, here (deploy and gate notes only; the file already carries the native and sharing notes added on main). | |
| +| Acknowledgements page | **Not built here.** `oficina/meet` discussion 10, branch `feat-open-source-credits` (`117b6e4`, `bbc126e`): a shared Estilo credits page with a runtime dependency inventory, Fable-approved, verified live on the overnight canary, not yet merged to main. Slice 6 records it and defers to it; building a second one would be the duplication the programme forbids. | |
| +| Estilo theme pin if a tagged release exists | **No tag exists** (`git ls-remote --tags` on `oficina/estilo` is empty on 2026-09-14). The theme is nevertheless already adopted on main at a pseudo-version by the Home integration. Recorded in §15.18; not changed. | |
| +| Consumed suite rulings commit | Task 3, here: §0.2 refreshed against doctrine main `1ac4323` (still revision 8) and against what main now consumes (Home hand-off, the Share amendment), in one commit titled so Appendix A.6 can point at it. | |
| +| Production promotion with its notification | **No deploy from this slice.** The change is documentation; edge (`meet.oficina.works`) is being promoted by hand by Paul (`651cff2` on 2026-09-12) with other sessions' work queued behind live checks (discussion 14). A docs-only redeploy would drop live calls for nothing. The notification posted on discussion 3 says so in those words; a queued promotion is never announced as live (programme §5). | |
| + |
| +--- |
| + |
| +### Task 1: README.md and AGENTS.md's final notes |
| + |
| +**Files:** |
| +- Create: `README.md` |
| +- Modify: `AGENTS.md` (append a short "Deploying" section after "Serving"; do not touch existing lines) |
| + |
| +**Interfaces:** |
| +- Consumes: spec §3.3/§3.4 (the floor sentence on the holding page and room: find the exact shipped sentence in `internal/meet/templates/join.html` and `room.html`), §5.2/§5.5 (relay), §7.1.1 (Home), §7.3 (deploy), §8 (agents), `native/README.md`, `Makefile` targets, `cmd/meet/main.go` (env vars), `internal/meet/config.go` (which are refused when empty outside development). |
| +- Produces: the README that PRODUCT.md (Task 2) and the record (Task 4) link to. |
| + |
| +- [ ] **Step 1: Verify each fact you will state** by reading the file it comes from on this branch. Keep a list of `claim → file:line` for the report. |
| + |
| +- [ ] **Step 2: Write `README.md`** with this shape (the paragraphs in this order; write them as prose, not as this outline): |
| + |
| +```markdown |
| +# Meet |
| + |
| +<Paragraph 1: what Meet is (video calls for one team: create or schedule a |
| +meeting, share a link, a holding screen, a room of up to four, chat, screen |
| +share, an agent API), and the floor sentence: every screen works with |
| +JavaScript disabled except browser media participation, the camera preview |
| +and join button on the holding screen and the call itself in the room; both |
| +pages render their title, standing, floor notice and navigation without |
| +script (spec §9).> |
| + |
| +<Paragraph 2: the relay. ICE servers come from the CARLOS platform relay, |
| +delivered as CARLOS_RELAY and minted per call at GET /m/{sqid}/ice; Meet |
| +names no STUN or TURN server of its own (suite ruling 6); with no relay |
| +configured, calls are direct only and the holding screen says so. Enabling |
| +or rotating the relay restarts the instance (spec §5.2, §5.5, §15.13).> |
| + |
| +## Sign-in |
| +<magic link to an allowlisted address (MEET_ALLOWED_ADDRESSES); a meeting |
| +link gives an outsider a guest grant at sign-in, never a way in without a |
| +name; optional Home sign-in with the four MEET_HOME_* settings, all or |
| +none (spec §7.1.1).> |
| + |
| +## The room |
| +<P2P mesh of up to four, perfect negotiation, SSE stream + POST signal, |
| +waiting queue for guests, removal and takeover through confirm pages, |
| +chat fanned out and never stored, screen share as a second tile; every |
| +deploy drops live calls because the hub is in-process (spec §4, §5, §6).> |
| + |
| +## Agents |
| +<Settings mints a token shown once; bearer-only /api/v1 (list, create, |
| +replace links, end, get); reach re-derived per request; 60/min per agent; |
| +spec §8 and §15.17.> |
| + |
| +## Native apps |
| +<one paragraph pointing at native/README.md and native/ios/README.md; |
| +make native-mac; same server and shared Go core; no embedded webviews.> |
| + |
| +## Building and gates |
| +<make ci (CGO_ENABLED=0), make race (the cgo exception, tests only), |
| +make browser (real Chromium, 31+ scenarios, about nine minutes, must run |
| +with the Claude Code bash sandbox off: UDP is blocked inside it), make |
| +native-test; make release VERSION=<sha> stamps /api/version.> |
| + |
| +## Deploying |
| +<unit route on CARLOS; carlos deploy --app meet --account oficina with the |
| +build probe on /api/version; secrets MEET_INSTANCE_KEY, MEET_DEK (32 base64 |
| +bytes), mail via MEET_SMTP_* with CARLOS_SMTP_* as fallback; env |
| +MEET_ORIGIN, MEET_ALLOWED_ADDRESSES, MEET_ZONE; carlos relay enable --app |
| +meet; migrations apply at boot once each (log line msg=migrate); every |
| +deploy restarts the instance and drops live calls, so deploy outside |
| +meeting hours; the canary recipe (carlos instances create + carlos deploy |
| +--channel) because carlos canary forms a two-label host, platform #124.> |
| + |
| +## Where things are written down |
| +<spec, programme plan, the slice records under docs/superpowers/reviews/, |
| +PRODUCT.md, AGENTS.md.> |
| +``` |
| + |
| +- [ ] **Step 3: Append to `AGENTS.md`**, after the "Serving" section, a "Deploying" section of at most eight lines: unit route; `carlos deploy` with the probe; migrations at boot, never re-run (already in the rules; say only that a database which applied a differently named migration file fails at boot); every deploy and every relay config change restarts the instance and drops live calls; the `carlos deploy` wait can time out before the hand-over, check `/api/version` before retrying; the canary recipe. No other change to AGENTS.md. |
| + |
| +- [ ] **Step 4: Check** `grep -c '' README.md` is under 140 lines, no sentence claims something you did not verify, no suite ruling is paraphrased where a number will do. |
| + |
| +- [ ] **Step 5:** Do not commit. Report the claim list. |
| + |
| +### Task 2: PRODUCT.md |
| + |
| +**Files:** |
| +- Create: `PRODUCT.md` |
| + |
| +**Interfaces:** |
| +- Consumes: `oficina/docs` `PRODUCT.md` as the shape (impeccable product schema 1: Platform, Users, Product Purpose, Positioning, Operating Context, Capabilities and Constraints, Brand Commitments, Evidence on Hand, Product Principles, Accessibility & Inclusion), the spec's §1 (goals), §9 (the floor), §11 (deliberately not built), §13 (gates), the slice records. |
| +- Produces: the section "What is deliberately not here" that spec §9 says slice 6 records the scriptless exception in. |
| + |
| +- [ ] **Step 1: Read** `/home/paulca/amadan.net/oficina/docs/PRODUCT.md` in full for the shape and the disclaimer header (written unattended; facts cited to spec or code; readings marked **[inferred — confirm]**). |
| + |
| +- [ ] **Step 2: Write `PRODUCT.md`** in that shape, for Meet, citing spec sections and files. It must contain a section **"What is deliberately not here"** listing: the scriptless-floor exception (browser media participation, spec §9); no reactions, dial-in, captions, multi-host signalling, recordings (§11, as amended on main); no STUN/TURN of Meet's own (ruling 6); no passkeys at the instance (as Docs); no SFU (roadmap 4b later); no client-address limiter on the API (§15.17); chat never stored; the room capped at four. Mark inferred readings. Under 240 lines. |
| + |
| +- [ ] **Step 3:** Do not commit. Report the claim list. |
| + |
| +### Task 3: The *Consumed suite rulings* commit and §15.18 |
| + |
| +**Files:** |
| +- Modify: `docs/superpowers/specs/2026-09-07-meet-design.md` (§0.2; §12 item 6; a new §15.18) |
| + |
| +**Interfaces:** |
| +- Consumes: doctrine main `1ac4323` revision 8 (`/home/paulca/amadan.net/oficina/suite/docs/superpowers/specs/2026-09-05-suite-sharing-doctrine.md`, verified current by `git ls-remote` on 2026-09-14), Appendix A's intro (name the ruling, delete the restatement), spec §7.1.1 and the 2026-09-12 sharing amendment on main, `internal/meet/home.go`, `internal/meet/api.go`. |
| +- Produces: the commit suite Appendix A.6 will cite (its hash goes on suite discussion 5 in Task 4). |
| + |
| +- [ ] **Step 1: Refresh §0.2.** Keep the table's shape. Confirm the doctrine citation (revision 8 at 1ac4323, still main on 2026-09-14). Update the row for rulings 4 and 12: the home now mints assertions and Meet consumes them through `home/connect` (§7.1.1) while the allowlist remains the membership authority; the row must name the rulings and §7.1.1, not restate them. Add a row for ruling 16 as amended by the 2026-09-12 sharing update (invitation tokens are hash-indexed with a sealed copy for members' repeat sharing; agent credentials remain hash-only and shown once). Keep "Also consumed" current (discussion 4; the media roadmap; the relay spec, now live). Do not paraphrase any ruling. |
| + |
| +- [ ] **Step 2: §12 item 6:** annotate as delivered on 2026-09-14 with the disposition table from this plan's "What slice 6 was" section in one sentence per item. |
| + |
| +- [ ] **Step 3: Add §15.18** "§12 item 6 — what slice 6 delivered, deferred and declined": the README and PRODUCT.md; the acknowledgements page deferred to discussion 10's branch; the Estilo pin (no tag exists; adopted at a pseudo-version by the Home integration on main; the programme's condition is recorded as unmet and the adoption as done by another route); no deploy from a docs-only slice, edge hand-managed at 651cff2. |
| + |
| +- [ ] **Step 4:** Do not commit. Report the exact lines changed. |
| + |
| +### Task 4: Record, reviews, merge, notification |
| + |
| +**Files:** |
| +- Create: `docs/superpowers/reviews/2026-09-14-slice-6-record.md` |
| + |
| +- [ ] **Step 1:** Commit Tasks 1 to 3 as three commits (README+AGENTS; PRODUCT.md; "Consumed suite rulings: §0.2 against doctrine 1ac4323 rev 8, §15.18"). |
| +- [ ] **Step 2:** Whole-branch review (Opus): every claim in the three documents checked against the code on the branch; findings W6-n. |
| +- [ ] **Step 3:** Codex round(s) until accept. |
| +- [ ] **Step 4:** Record in the shape of the slice 5 record: rulings, dispositions, carried items (the acknowledgements page, the Estilo tag, the production promotion, the credits inventory freshness gate that discussion 10 adds), the copy catalogue note, the gates (`make ci` on the head; the browser gate is not run: no page or client changed). |
| +- [ ] **Step 5:** `make ci`, push, remote CI, fast-forward main, the notification on `oficina/meet` discussion 3 and the checkpoint on `oficina/suite` discussion 5 naming the §0.2 commit for Appendix A.6, close the slice discussion, hub tasks Done, memory. |
diff --git a/docs/superpowers/reviews/2026-09-14-slice-6-record.md b/docs/superpowers/reviews/2026-09-14-slice-6-record.md| new file mode 100644 |
| index 0000000..85f8a03 |
| --- /dev/null |
| +++ b/docs/superpowers/reviews/2026-09-14-slice-6-record.md |
| @@ -0,0 +1,209 @@ |
| +# Meet slice 6 — the record |
| + |
| +Branch `slice/6-deploy`, `9225ec2..HEAD` (this commit; started on main |
| +`9225ec2`, tag `v0.1.0`). Spec: `docs/superpowers/specs/2026-09-07-meet-design.md`, |
| +revision 9 (§15.18 carries this slice's dispositions). Plan: |
| +`docs/superpowers/plans/2026-09-14-meet-slice-6-deploy.md`. |
| + |
| +Slice 6 is the programme's closing slice (spec §12 item 6) and is |
| +documentation only: `README.md`, `PRODUCT.md`, a Deploying section in |
| +`AGENTS.md`, the *Consumed suite rulings* commit (`fa875c7`, the hash |
| +suite Appendix A.6 points at) and the spec amendments that commit and |
| +the review made. No file under `internal/`, `cmd/`, `native/`, |
| +`meetcore/` or `protocol/` changed. The ledger is |
| +`.superpowers/sdd/2026-09-14-meet-slice-6-deploy/` (gitignored; this |
| +file is its substance). |
| + |
| +--- |
| + |
| +## 1. Rulings and decisions |
| + |
| +- **The slice was re-scoped against main as it is on 2026-09-14, not |
| + as the programme imagined it on 2026-09-09.** Between slice 5 |
| + (`a283c53`, 2026-09-11) and this slice, other sessions landed Home |
| + sign-in (§7.1.1), the shared Estilo day theme and brand, the |
| + invitation `Share` route (the 2026-09-12 amendment), and the native |
| + Mac, iPhone and iPad apps. The plan's "What slice 6 was, and what it |
| + is now" table is the disposition of each programme item; §12 item 6 |
| + and §15.18 restate it in the spec. |
| +- **The acknowledgements page is not built here.** `oficina/meet` |
| + discussion 10, branch `feat-open-source-credits` (`117b6e4`, |
| + `bbc126e`), carries a shared Estilo credits page with a runtime |
| + dependency inventory and its freshness gate, Fable-approved and |
| + verified live on the overnight canary. Building a second one would |
| + be the duplication the programme forbids. |
| +- **The Estilo theme pin.** The programme's condition was a tagged |
| + release; `git ls-remote --tags` on `oficina/estilo` is empty on |
| + 2026-09-14. The theme is nevertheless adopted on main at an indirect |
| + pseudo-version (`go.mod`), brought in by the Home integration. |
| + Recorded as: condition unmet, adoption done by another route, |
| + nothing changed here. |
| +- **No deploy from this slice.** The change is documentation, |
| + checkable from this diff. As observed on 2026-09-14 from `carlos |
| + channels` and `oficina/meet` discussions 11 and 14, edge |
| + (`meet.oficina.works`) was being promoted by hand by Paul (`651cff2` |
| + on 2026-09-12), with discussion 14's web UI work queued behind a |
| + live check — state as of that observation, not asserted as current |
| + here. A redeploy would drop live calls for nothing; a queued |
| + promotion is never announced as live (programme §5). The domain was |
| + attached before this slice. |
| +- **Copy review is waived** for this round by Paul's steering on |
| + `oficina/suite` discussion 5. README and PRODUCT.md prose is |
| + catalogued here (§3) rather than reviewed. |
| +- **Writers did not commit.** Three writers worked concurrently in one |
| + worktree on disjoint files; the controller committed each set. The |
| + index is the shared resource, not the files. |
| +- **Every behavioural claim is verified against the code on the |
| + branch and cites its source.** The whole-branch review's finding was |
| + that the writers verified the documents against the code but not the |
| + code's documents against the documents: four spec sentences on main |
| + asserted things about "the README" that the README, once it existed, |
| + did not say (§0.1/§5.6's encryption sentence, §5.5's TCP-443 cause |
| + and "first paragraph", §3.2's residue). All four now hold, and the |
| + fix wave swept every spec sentence naming README, AGENTS.md or |
| + PRODUCT.md (twelve remaining, all true). |
| +- **The two meanings of "floor".** §5.5's floor is "no relay"; §9's is |
| + the scriptless floor. §12 item 6 now says which goes where (the |
| + scriptless sentence in the README's first paragraph, the relay |
| + paragraph carrying §5.5's sentence second); §15.18 notes the two |
| + senses. |
| +- **Platform facts stated from this project's own deploys**, not from |
| + the platform source: `carlos canary` composed a host the console |
| + refused (platform discussion 124, open); the recipe used is |
| + `carlos instances create --host <name>-meet.bds.oncarlos.com |
| + --channel canary/<name> --environment <name>` then `carlos deploy |
| + --channel …`, with the environment bundle mandatory because a canary |
| + without one serves `MEET_ORIGIN` for the main host and refuses |
| + sign-in while GETs look healthy. The release command is `carlos |
| + deploy --app meet --account oficina --channel edge --version <sha> |
| + --target linux-arm64 releases/meet-linux-arm64` after `make release |
| + VERSION=<sha>`; the deploy wait can time out before the hand-over |
| + while the instance serves the new version a minute later. |
| +- **Ruling 16** stays cited as on the doctrine's |
| + `worktree-worktree-token-at-rest` branch, not doctrine main (whose |
| + rulings run 1 to 15 at `1ac4323`, revision 8, confirmed current by |
| + `ls-remote` on 2026-09-14), as amended by the 2026-09-12 sharing |
| + update for invitation tokens; agent credentials remain hash-only and |
| + shown once. |
| + |
| +--- |
| + |
| +## 2. Per-task review dispositions |
| + |
| +Three writing tasks (Sonnet) in parallel, then one whole-branch review |
| +(Opus) and one fix wave, then Codex rounds. |
| + |
| +- **Task 1, README and AGENTS.md** (`93f1c2e`): 106 lines, the two |
| + paragraphs first. Flagged and acted on: spec §11 still listed a |
| + native client as not built (`aa9b227`). Flagged and initially left, |
| + then closed by the review: §5.5's "first paragraph" cross-reference; |
| + `MEET_SMTP_PASS` as a secret. |
| +- **Task 2, PRODUCT.md** (`e684b97`): impeccable product schema 1 in |
| + `oficina/docs`' shape with the unattended-writing disclaimer; "What |
| + is deliberately not here" carries the scriptless exception spec §9 |
| + asked for. |
| +- **Task 3, the consumed-rulings commit** (`fa875c7`): §0.2's 4/12 row |
| + consumes the home's assertions through §7.1.1 with the allowlist as |
| + membership authority; a ruling-16 row as amended; §12 item 6 |
| + annotated; §15.18 added. Revision line left at 9, following what |
| + §15.13 to §15.17 did. |
| +- **Whole-branch review** (`e684b97`): verdict **merge with named |
| + fixes**, W6-1 to W6-15, all applied in `bf3b86b` and `c22cae7` |
| + (reflow), plus the handoff's spec sweep, the two-floors |
| + disambiguation, §15.11's stale "until slice 3, or until a drain |
| + exists" (no drain exists; every deploy drops live calls) and |
| + `token_sealed` added to §2.1's `meeting_links` columns. Roughly |
| + sixty behavioural claims were traced to file and line and found |
| + correct; the fifteen findings were the remainder. |
| + |
| +**Codex round 1** (independent, static, scope `9225ec2..c22cae7`): |
| +verdict **request changes** — thirteen findings, S6-1 through S6-13. |
| +All applied in one commit (`.superpowers/sdd/2026-09-14-meet-slice-6-deploy/fix-wave-report.md`, |
| +round-1 section): |
| + |
| +- **S6-1 — P2, deployment settings undocumented. Fixed:** README's Deploying section enumerates every required setting and which refuse startup outside `-env development`. |
| +- **S6-2 — P2, the deploy-wait guarantee had an unstated prerequisite. Fixed:** README and AGENTS.md now state the `carlos apps build-probe` prerequisite and the `X-Carlos-Version` fallback it stands in for. |
| +- **S6-3 — P2, the scriptless exception was narrower than shipped. Fixed, then completed in Codex round 2 (S6-16):** README, PRODUCT.md and spec §9 name the chat panel and the live admission controls as script-gated too, alongside browser media participation; AGENTS.md's two matching lines, left behind in round 1, were widened the same way, so §9's "the binding file and the code agree" holds again; §15.18 notes both. |
| +- **S6-4 — P2, the cgo claims didn't match the Makefile. Fixed, then corrected again in Codex round 2 (S6-14):** README and PRODUCT.md say `CGO_ENABLED=0 make ci` and name `make race` and `make native-test`'s `meetcore` sub-step as the two `CGO_ENABLED=1` cases that never ship; the native Mac and iPhone/iPad apps are named separately as the one place real cgo does ship (`MeetBridge`, linked by `MeetKit`), while server releases stay cgo-free. |
| +- **S6-5 — P2, the SMTP fallback description was backwards. Fixed:** README now says the platform supplies `CARLOS_SMTP_FROM` too, which `MEET_SMTP_FROM` optionally overrides. |
| +- **S6-6 — P2, suite restatements remained under §0.2. Fixed, then completed in Codex round 2 (S6-15):** rows 3, 6, 9 and 15 cite section and ruling number only; the discussion-4 paragraph does too; the §5.2 paragraph, shortened but not emptied in round 1, is now the bare citation "Doctrine §5.2 is also relied on, for §2."; PRODUCT.md's actor sentence likewise; ruling 16's off-main provenance kept as before. |
| +- **S6-7 — P2, PRODUCT.md cited a section that denies native clients shipped. Fixed:** spec §8.4 gained a 2026-09-14 amendment recording the shipped milestone (`v0.1.0` at `9225ec2`) and the browser-approval handoff (`86ed9f3`); PRODUCT.md's two native-client citations now point at that amendment. |
| +- **S6-8 — P2, the shipped same-network sentence was missing from the README. Fixed:** the relay paragraph now quotes `join.html`'s floor sentence verbatim. |
| +- **S6-9 — P2, the route inventory undercounted confirmation pairs. Fixed:** PRODUCT.md now says "five destructive confirmation pairs"; spec §9 now says "every confirm page (five)". |
| +- **S6-10 — P3, Share's legacy behavior was omitted. Fixed:** README now distinguishes a legacy meeting's first Share (mints a new recoverable invitation alongside the old one) from every retrieval after. |
| +- **S6-11 — P3, "60 requests a minute" obscured the permitted burst. Fixed:** README and PRODUCT.md now say "one request a second sustained, with a burst of 60". |
| +- **S6-12 — P2, the canary creation command relied on undocumented app/account defaults. Fixed:** README's `instances create` now carries `--app meet --account oficina` and states the named environment bundle must already exist, created separately. |
| +- **S6-13 — P3, disposition coverage and external-state attribution were incomplete. Fixed, then completed in Codex round 2 (S6-17):** README and PRODUCT.md link to spec §15.18 as the disposition of record; the platform-124, no-Estilo-tag and credits-branch-canary claims are attributed to dated records. Round 1 left the production-promotion state itself (edge's served commit, the queued work) asserted as current fact in §15.18 and this record's own §3; both now attribute it to what `carlos channels` and `oficina/meet` discussions 11 and 14 showed on 2026-09-14, keeping "this slice changes documentation only" as the one claim checkable from the repository. |
| + |
| +**Codex round 2** (independent, static, scope `2a6eee4`): verdict |
| +**request changes** — four findings, S6-14 through S6-17, against |
| +round 1's own fixes; the other twelve confirmed fixed as claimed |
| +(table in the round's own report). All four applied in one commit |
| +(`.superpowers/sdd/2026-09-14-meet-slice-6-deploy/fix-wave-report.md`, |
| +round-2 section): |
| + |
| +- **S6-14 — P2, PRODUCT.md still claimed the native cgo bridge never ships. Fixed:** "three things run under `CGO_ENABLED=1`, none of them shipped" is now two — `make race` and `make native-test`'s `meetcore` sub-step, both test-only — with the native Mac and iPhone/iPad apps named separately as the one place real cgo does ship (`MeetBridge`, a `native/apple/Package.swift` binary target `MeetKit` links, built by `native/scripts/build-mac.sh`), while server releases stay `CGO_ENABLED=0`. This record's own S6-4 line is corrected to match. |
| +- **S6-15 — P2, the guest-grant sentence was shortened, not removed. Fixed:** "Doctrine §5.2 is also relied on, for §2: a guest grant is stored, not asked for" drops its second clause — still a paraphrase of doctrine §5.2's grant authority — leaving the bare citation "Doctrine §5.2 is also relied on, for §2." |
| +- **S6-16 — P2, the widened scriptless exception left `AGENTS.md` behind. Fixed:** `AGENTS.md`'s two scriptless lines (the "Screens work with JavaScript disabled" rule and the UX-conventions sentence) now name the chat panel and admission controls alongside browser media participation, matching §9, README and PRODUCT.md; §9's own "the binding file and the code agree" is corrected to say when each half landed; §15.18 records the correction. |
| +- **S6-17 — P3, production state was asserted as current rather than attributed. Fixed:** §15.18's production-promotion bullet and this record's own §1 and §3 now attribute edge's served commit and the queued web UI work to what `carlos channels` and `oficina/meet` discussions 11 and 14 showed on 2026-09-14, rather than presenting it as established from this repository; "this slice changes documentation only" stays stated as fact, since the diff itself proves it. |
| + |
| +**Codex round 3** (independent, static, scope `cd02a59`): verdict |
| +**accept** — S6-14 to S6-17 closed, no new finding, "fit to merge as |
| +documentation of the code on this branch". Three rounds in all: 13, 4, |
| +0 findings. |
| + |
| +--- |
| + |
| +## 3. Carried items, and where they go |
| + |
| +- **The acknowledgements page.** Discussion 10's branch |
| + `feat-open-source-credits`, not yet on main. **Destination: that |
| + branch's owner**; when it merges, the README's "Where things are |
| + written down" section should gain the credits page's path (one |
| + line). |
| +- **The Estilo theme tag.** No tagged release exists; the pseudo-version |
| + pin stays until one does. **Destination: oficina/estilo.** |
| +- **The production promotion of main's head.** As observed on |
| + 2026-09-14 from `carlos channels` and `oficina/meet` discussions 11 |
| + and 14, edge was serving `651cff2` with discussion 14's web UI work |
| + queued behind it — state as of that observation, not asserted as |
| + current here. Main is at `9225ec2` plus this slice, checkable from |
| + this repository: `9225ec2` changed native code only, and this slice |
| + changes documents only. **Destination: Paul**, who promotes by hand. |
| +- **Unauthenticated flood control on `/api/v1`** (from slice 5). |
| + **Destination: carlos/platform**, unchanged. |
| +- **Platform discussion 124** (`carlos canary` and the one-label host). |
| + Open. The README carries the recipe that works. **Destination: |
| + carlos/platform.** |
| +- **Spec §9's "four confirm pages" is five** (remove, takeover, |
| + replace-link, end, revoke-agent). **Resolved in Codex round 1 |
| + (S6-9):** §9 now says "every confirm page (five)" and PRODUCT.md |
| + says "five destructive confirmation pairs". |
| +- **Copy catalogue** (copy review waived): the README's and |
| + PRODUCT.md's prose are the new user-facing text this slice adds; |
| + neither is an app string. Nothing in `internal/meet/templates` |
| + changed. |
| +- **The ledger's process note.** A writer's flag should become a task, |
| + not a paragraph: two of the three task reports flagged the right |
| + problems (W6-3, W6-6) in their "not corrected" sections and the |
| + controller took them as recorded rather than as work. |
| + |
| +--- |
| + |
| +## 4. Deploying this slice |
| + |
| +Nothing to deploy. No binary, migration, template, client or |
| +configuration changed. When main is next promoted, the README's |
| +Deploying section is the recipe, and the `carlos deploy` wait note in |
| +§1 applies. |
| + |
| +--- |
| + |
| +## 5. The gates, and how to run them |
| + |
| +| Gate | Command | This slice | |
| +|---|---|---| |
| +| CI | `CGO_ENABLED=0 make ci` | Green on every commit of the branch; remote CI passed on `e684b97` and `c22cae7`. Markdown cannot fail it; it is run so the branch's head is known green. | |
| +| Race | `make race` | Not run: no change under `internal/meet/hub` or the stream. | |
| +| Browser | `make browser` (sandbox off) | Not run: no page, template or client file changed. The last run on a shipping head is slice 5's, 31 of 31 on `4f896c2`. | |
| +| Native | `make native-test` | Not run: nothing under `native/`, `meetcore/` or `protocol/` changed. | |
diff --git a/docs/superpowers/specs/2026-09-07-meet-design.md b/docs/superpowers/specs/2026-09-07-meet-design.md| index f4a7dba..8eae61f 100644 |
| --- a/docs/superpowers/specs/2026-09-07-meet-design.md |
| +++ b/docs/superpowers/specs/2026-09-07-meet-design.md |
| @@ -89,20 +89,17 @@ This app cites the suite sharing doctrine (`oficina/suite`, |
| | Ruling | Used for | |
| |---|---| |
| | 1, 5 | One instance per team; the first deploy is the **lone shape** (§7.1). | |
| -| 3 | Authorization is asked per request and never cached. Standing (member, guest, neither) is derived at each request and re-derived on every hub tick (§2.3). | |
| -| 4, 12 | Identity and roster belong to the home. Until the home mints assertions, the lone instance keeps its own allowlist exactly as Docs and Slides do. | |
| -| 6 | No product-wide egress. Meet never names a STUN or TURN server of its own; ICE servers come from the platform (§5.2) or there are none (§5.5). | |
| -| 9 | Every write names its real actor: a member, a guest who signed in, or an agent (§8). | |
| -| 15 | Three rungs plus a read-only link. A meeting link is a capability to obtain a **guest grant at sign-in**, the `granted` rung, and never a way into a room without a name (§3). Ruled for Meet on `oficina/suite` discussion 3, Paul, 2026-09-06. | |
| -| 16 | A link token is stored hashed and shown once (§3.1). Ruling 16 is on the doctrine's `worktree-worktree-token-at-rest` branch (suite discussion 2), not yet on main; Meet adopts it now so it never has the Docs defect that produced it. | |
| - |
| -Doctrine §5.2 is also relied on: a guest grant held by the instance is |
| -authoritative for that grant, which is why §2 stores it and does not |
| -ask anyone. |
| - |
| -Also consumed: `oficina/suite` discussion 4 (agents as their own |
| -principal, on behalf of a person, bound to the operator's reach and no |
| -more) for the drive surface (§8); the CARLOS media roadmap |
| +| 3 | §2.3: standing (member, guest, neither) is derived at each request and re-derived on every hub tick. | |
| +| 4, 12 | The home now mints assertions; Meet consumes them through `home/connect`'s bridge, resolving to the existing person and re-checking membership on every request, while the allowlist remains the membership authority throughout (§7.1.1). | |
| +| 6 | §5.2, §5.5: Meet never names a STUN or TURN server of its own; ICE servers come from the platform, or there are none. | |
| +| 9 | §8: a member, a guest who signed in, or an agent. | |
| +| 15 | §3: a meeting link is a capability to obtain a **guest grant at sign-in**, the `granted` rung, and never a way into a room without a name. Ruled for Meet on `oficina/suite` discussion 3, Paul, 2026-09-06. | |
| +| 16 | The token at rest (§3.1), as amended by the 2026-09-12 sharing update at the top of this file: invitation tokens are hash-indexed with a sealed copy so a member can share the current one again; agent credentials stay hash-only and shown once (§15.17). Ruling 16 is on the doctrine's `worktree-worktree-token-at-rest` branch (suite discussion 2), not on main on 2026-09-14; Meet adopts it early so it never has the Docs defect that produced it. | |
| + |
| +Doctrine §5.2 is also relied on, for §2. |
| + |
| +Also consumed: `oficina/suite` discussion 4, for the drive surface |
| +(§8); the CARLOS media roadmap |
| (`carlos/platform`, |
| `docs/superpowers/specs/2026-09-07-media-platform-roadmap-design.md`, |
| merged at 8291cb2) and the stage 4a relay spec |
| @@ -171,9 +168,12 @@ that the subject is an address, not an id. Standing is not a column |
| its links answer 404 exactly as a revoked one does. |
| **`meeting_links`** — `id`, `meeting_id`, `token_hash` (SHA-256 of the |
| -token, ruling 16), `created_by`, `created_at`, `revoked_at`. One meeting |
| -may hold several links so a revoked one can be replaced. The token is |
| -returned once, in the response that minted it, and never again. |
| +token, ruling 16), `token_sealed` (nullable; added by the 2026-09-12 |
| +sharing amendment, top of file, so a member can retrieve a current |
| +invitation again), `created_by`, `created_at`, `revoked_at`. One |
| +meeting may hold several links so a revoked one can be replaced. The |
| +token is returned once, in the response that minted it, and again on |
| +demand through `POST /m/{sqid}/share` once a sealed copy exists. |
| **`pending_joins`** — `id`, `meeting_id`, `link_id` (the |
| `meeting_links` row the browser followed), `address_fingerprint` (keyed |
| @@ -823,9 +823,10 @@ is usually true on a permissive local network, usually false across the |
| internet, and false on a local network with client isolation. The |
| pre-join screen says, above the button: "This team's Meet has no relay |
| yet. Calls usually connect only between people on the same network." |
| -The README's first paragraph says the same. An operator enables the |
| -platform relay with `carlos relay enable --app meet`, after which this |
| -paragraph no longer applies to that instance. |
| +The README's second paragraph, the one that introduces the relay, says |
| +the same; its first paragraph carries the scriptless floor (§9). An |
| +operator enables the platform relay with `carlos relay enable --app |
| +meet`, after which this paragraph no longer applies to that instance. |
| With `CARLOS_RELAY` present, a failed connection's tile says "could not |
| connect, even through the relay" and offers retry. It does not diagnose |
| @@ -974,6 +975,19 @@ A thin adapter over §8.2, deferred until a consumer asks by name. |
| ### 8.4 Native clients |
| +**2026-09-14 amendment.** The SwiftUI Mac, iPhone and iPad apps this |
| +section specifies shipped on `main` (`native/`, `meetcore/`, |
| +`protocol/`, tag `v0.1.0` at `9225ec2`), closing the authentication gap |
| +the bullets below name with a browser-approval hand-off |
| +(`native/README.md`): a five-minute, one-use authorization bound to a |
| +proof secret held only by the app; approving in the browser creates an |
| +ordinary framework session, no cookie copied and no new bearer type |
| +introduced. The production handoff endpoints were deployed in |
| +`86ed9f3`. This supersedes the closing paragraph's "version one does |
| +not ship a native client" below; the rest of this section, written |
| +before that milestone, otherwise stands as the contract the shipped |
| +apps speak. |
| + |
| Ruling 15: a native app is the next client after the browser, and |
| nothing in Meet's server contracts may assume the browser. Concretely, |
| in version one: |
| @@ -1000,19 +1014,25 @@ until an OpenAPI document earns its place. |
| ## 9. The scriptless floor |
| -The exception is **browser media participation** and nothing wider: |
| -reaching a camera and another browser needs script. Every other screen |
| -works with scripts off, including the meeting list, creating a meeting, |
| -seeing and copying a link, all four confirm pages, sign-in and |
| -continuation, the `/welcome` page, the agent token page, and the server-rendered |
| -parts of the holding screen and the room (§3.3, §3.4): title, start |
| -time, standing, floor sentence, the paragraph that says what needs |
| -script, and navigation to everything that does not. |
| - |
| -`AGENTS.md`'s line "screens work with JavaScript disabled" gains, in |
| -slice 2, the one exception in those words, so the binding file and the |
| -code agree from the commit that introduces the exception. `PRODUCT.md` |
| -records it in "what is deliberately not here" in slice 6. |
| +The exception is **browser media participation**: reaching a camera |
| +and another browser needs script. Inside a room that exists, script |
| +also gates the chat panel (`chat.html`'s whole panel is rendered |
| +`hidden` until script un-hides it, because a Send button with no |
| +script behind it would be a lie, §6, §10) and the admission queue's |
| +Admit controls (`room.js`), since neither can do anything before a |
| +call does. Every other screen works with scripts off, including the |
| +meeting list, creating a meeting, seeing and copying a link, every |
| +confirm page (five), sign-in and continuation, the `/welcome` page, |
| +the agent token page, and the server-rendered parts of the holding |
| +screen and the room (§3.3, §3.4): title, start time, standing, floor |
| +sentence, the paragraph that says what needs script, and navigation to |
| +everything that does not. |
| + |
| +`AGENTS.md`'s line "screens work with JavaScript disabled" gained, in |
| +slice 2, the one exception in those words; on 2026-09-14, alongside |
| +this section's own widening, it gained the other two (§15.18), so the |
| +binding file and the code agree again. `PRODUCT.md` records it in |
| +"what is deliberately not here" in slice 6. |
| Hand-written static JavaScript, no bundler, no npm, in three files: |
| `devices.js` (the holding screen), `room.js` (signalling, resume and |
| @@ -1040,8 +1060,7 @@ are drafts for that review, not approved copy. |
| Recurring meetings. Calendar integration. Recording. Attendance |
| records. A relay of Meet's own. Rooms above four. Persisted chat. |
| Reactions. Dial-in. Captions. Multi-host signalling. |
| -Push-to-talk. Virtual backgrounds. A native client and its sign-in |
| -(§8.4). Denying a knock (a guest who is not |
| +Push-to-talk. Virtual backgrounds. Denying a knock (a guest who is not |
| admitted simply waits or leaves). Each is named so the next session |
| does not rediscover it. |
| @@ -1082,9 +1101,22 @@ own gates from §13; nothing is deferred to the deploy slice. |
| 5. **Drive surface.** `agents`, the five operations, the per-request |
| reach check, the badge. |
| 6. **Deploy.** Domain, secrets, canary, `PRODUCT.md`, the README with |
| - the floor sentence in its first paragraph and the relay paragraph, |
| - and the `Consumed suite rulings` commit that suite Appendix A.6 will |
| - point at. |
| + the scriptless-floor sentence (§9) in its first paragraph and the |
| + relay paragraph, carrying §5.5's no-relay sentence, second, and the |
| + `Consumed suite rulings` commit that suite Appendix A.6 will point |
| + at. |
| + |
| + **Delivered 2026-09-14 (§15.18).** The README, with the floor and |
| + relay paragraphs first, was written. `PRODUCT.md` was written. |
| + AGENTS.md's deploy notes were appended. This is the `Consumed suite |
| + rulings` commit, refreshing §0.2 against doctrine main `1ac4323` |
| + revision 8. The acknowledgements page is deferred to `oficina/meet` |
| + discussion 10's branch `feat-open-source-credits`, not duplicated |
| + here. The Estilo theme pin did not happen, because no tagged release |
| + exists; the theme is nonetheless already adopted on main at a |
| + pseudo-version through the Home integration. No production |
| + promotion happened, because this slice is documentation only; edge |
| + stays hand-managed by Paul. |
| --- |
| @@ -1482,8 +1514,9 @@ they were otherwise recorded only in an untracked ledger: |
| not solved). Slice 2 is the first release where that has a |
| user-visible cost: **every deploy drops every live call.** Members |
| rejoin automatically; guests go back to waiting and must be admitted |
| - again. Deploys should avoid meeting hours until slice 3, or until a |
| - drain exists. |
| + again. No drain exists, and slice 3 shipping did not change that: |
| + every deploy still drops every live call, so deploying during |
| + meeting hours means exactly that. |
| ### 15.12 §2.5 — the last row corrected: standing is not consulted *for a guest* |
| @@ -2130,3 +2163,58 @@ truncated before the `~` — the badge's icon needs no separate |
| every icon "sits beside its own visible text label") is already |
| satisfied by the badge's own word, alongside AGENTS.md's own line — |
| "State — never colour alone — always a text label too." |
| + |
| +### 15.18 §12 item 6 — what slice 6 delivered, deferred and declined |
| + |
| +Slice 6 is documentation only: nothing under `internal/`, `native/`, |
| +`meetcore/` or `protocol/` changed. Against the programme's slice 6 |
| +line (`docs/superpowers/plans/2026-09-09-meet-slices-2-6-programme.md` |
| +§5) and this spec's own §12 item 6: |
| + |
| +The word "floor" names two different things in this spec: §5.5's "The |
| +floor" is the no-relay condition, and §9's "The scriptless floor" is |
| +the JavaScript exception; item 6's bullet above now names each rather |
| +than leaving the bare word to carry both. |
| + |
| +§9's exception was also corrected here, on Codex round 1: browser |
| +media participation was never the only script-gated part of a room — |
| +the live admission controls have needed script since slice 2 and the |
| +chat panel since slice 4 — and §9, the README and `PRODUCT.md` now say |
| +so rather than "and nothing wider." Codex round 2 found the binding |
| +file left behind: `AGENTS.md` still named only the media exception, so |
| +§9's own "the binding file and the code agree" was false again the |
| +moment §9 widened. `AGENTS.md`'s two scriptless lines were widened to |
| +match on 2026-09-14, in the same commit. |
| + |
| +- **Delivered.** `README.md`, with the scriptless floor sentence and |
| + the relay paragraph first. `PRODUCT.md`. `AGENTS.md`'s deploy notes. |
| + §0.2 above, refreshed against doctrine main `1ac4323`, still |
| + revision 8 on 2026-09-14 — this is the `Consumed suite rulings` |
| + commit suite Appendix A.6 will point at. The domain was already |
| + attached outside this slice — `meet.oficina.works` serves the |
| + flagship instance (§7.3's `carlos domains attach`) — so item 6's |
| + domain row needed nothing from slice 6. |
| +- **Deferred, not duplicated.** The acknowledgements page lives on |
| + `oficina/meet` discussion 10, branch `feat-open-source-credits` |
| + (`117b6e4`, `bbc126e`): a shared Estilo credits page with a runtime |
| + dependency inventory. As recorded on that branch's own review, it is |
| + Fable-approved and was verified live on the overnight canary, not |
| + yet merged to main — not independently reverified here. Building a |
| + second one here would be the duplication the programme forbids. |
| +- **Declined: the Estilo theme pin.** The programme's condition for |
| + pinning was a tagged release; `git ls-remote --tags` against |
| + `oficina/estilo` is empty on 2026-09-14, so no tag exists and no pin |
| + was made. The theme is adopted on main anyway, at a pseudo-version |
| + (`amadan.net/oficina/estilo.git`), by the Home integration |
| + (`f9cb47f`, `34fc367`) — the programme's condition is recorded here |
| + as unmet, and the adoption as done by another route, not as the |
| + condition having been met after all. |
| +- **Declined: the production promotion.** A docs-only slice has |
| + nothing to promote that changes behaviour, and a redeploy would drop |
| + every live call for no reason (§15.11). As observed on 2026-09-14 |
| + from `carlos channels` and `oficina/meet` discussions 11 and 14, |
| + `meet.oficina.works` was being promoted by hand by Paul (`651cff2`, |
| + 2026-09-12) with other sessions' work queued behind live checks — |
| + state as of that observation, not asserted as current here. This |
| + slice does not touch that queue or announce a deploy of its own, |
| + which is checkable from this diff alone. |