docs: slice 1 strings for copy review; AGENTS.md notes
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2 files changed,
+114
−0
AGENTS.md+9 −0docs/superpowers/copy/2026-09-08-slice-1-strings.md+105 −0
CI passed — run details
diff --git a/AGENTS.md b/AGENTS.md| index 2f1e946..6bd07ef 100644 |
| --- a/AGENTS.md |
| +++ b/AGENTS.md |
| @@ -19,6 +19,15 @@ mechanically. |
| takes that one screen over, by existence. |
| - `gen/` — generated when manifests are used; never edit. Regenerate |
| with `rastrillo generate`. |
| +- `internal/meet/seal/` — the app's only encryption surface. A title |
| + is sealed by the store and opened by the store; no handler holds a |
| + plaintext title it did not get from `store.title`. An outsider's |
| + address is stored only as a keyed fingerprint. |
| +- `internal/meet/store.go` — every database access. `standing.go` is |
| + the entry authority (spec §2.3), computed per request, never stored. |
| +- Sign-in: `auth.go` is Docs' shape with the pending-join exception of |
| + spec §3.2 and Slides' same-answer wrapper. Every answer from |
| + `POST /signin` is `303 /signin?sent=1`. |
| ## Rules the family holds hard |
diff --git a/docs/superpowers/copy/2026-09-08-slice-1-strings.md b/docs/superpowers/copy/2026-09-08-slice-1-strings.md| new file mode 100644 |
| index 0000000..b5c2373 |
| --- /dev/null |
| +++ b/docs/superpowers/copy/2026-09-08-slice-1-strings.md |
| @@ -0,0 +1,105 @@ |
| +# Slice 1 copy list |
| + |
| +Drafts, pending copy review per spec §10; the review is one sitting |
| +for the slice before merge. |
| + |
| +## Sign in (`/signin`) |
| + |
| +| String | Where | |
| +| --- | --- | |
| +| Sign in | `templates/signin.html`, `title` block | |
| +| Sign in to Meet | `templates/signin.html`, `content` block, page-header Title | |
| +| If that address can sign in here, a link is on its way. Open it on this device to continue. | `templates/signin.html`, `content` block, sent notice | |
| +| Email address | `templates/signin.html`, `content` block, field Label | |
| +| Send me a sign-in link | `templates/signin.html`, `content` block, submit button | |
| +| That does not look like an email address. | `auth.go`, `signin` (`err=address`) | |
| +| Too many sign-in attempts just now. Wait a few minutes and try again. | `auth.go`, `signin` (`err=rate`) | |
| +| That sign-in link has expired. Ask for a new one. | `auth.go`, `signin` (`err=expired`) | |
| +| Sign-in did not work. Try again. | `auth.go`, `signin` (default `err`) | |
| + |
| +## Welcome (`/welcome`) |
| + |
| +| String | Where | |
| +| --- | --- | |
| +| Signed in | `templates/welcome.html`, `title` block | |
| +| You're signed in | `templates/welcome.html`, `content` block, page-header Title | |
| +| You're signed in as {{.Email}}. This team's Meet has no meetings for you. If someone sent you a meeting link, open it again now. | `templates/welcome.html`, `content` block | |
| +| Sign out | `templates/welcome.html`, `content` block, submit button | |
| + |
| +## Meetings list (`/`) |
| + |
| +| String | Where | |
| +| --- | --- | |
| +| Meetings | `templates/index.html`, `title` block and page-header Title | |
| +| New meeting | `templates/index.html`, `content` block, `h2` | |
| +| Title | `templates/index.html`, `content` block, field Label | |
| +| Starts (%s), or leave blank to start now | `templates/index.html`, `content` block, field Label (`%s` is the instance zone, e.g. "Europe/Dublin") | |
| +| Enter the start as a date and time, or leave it blank to start now. | `handlers_meetings.go`, `parseStart` | |
| +| Give the meeting a title. | `handlers_meetings.go`, `createMeeting` | |
| +| Keep the title under 200 characters. | `handlers_meetings.go`, `createMeeting` | |
| +| Create meeting | `templates/index.html`, `content` block, submit button | |
| +| Upcoming | `templates/index.html`, `content` block, `h2` | |
| +| No meetings yet. Make one above and share its link. | `templates/index.html`, `content` block, empty-state Body | |
| +| Starts {{.Starts}} | `templates/index.html`, `content` block, upcoming row (when the meeting has a start time) | |
| +| Starts now | `templates/index.html`, `content` block, upcoming row (when the meeting has no start time) | |
| +| · no live link | `templates/index.html`, `content` block, upcoming row (when the meeting's link was revoked and not replaced) | |
| +| Replace the link | `templates/index.html`, `content` block, upcoming row action link | |
| +| End | `templates/index.html`, `content` block, upcoming row action link | |
| +| Ended meetings ({{len .Ended}}) | `templates/index.html`, `content` block, `details summary` | |
| +| Ended | `templates/index.html`, `content` block, ended row | |
| + |
| +## Link shown once (`/meetings`, `/meetings/{sqid}/links`) |
| + |
| +| String | Where | |
| +| --- | --- | |
| +| Your meeting link | `templates/link_once.html`, `title` block | |
| +| Meetings | `templates/link_once.html`, `content` block, back-nav Label | |
| +| {{.Title}} | `templates/link_once.html`, `content` block, page-header Title (the meeting's own title) | |
| +| Starts {{.Starts}}. | `templates/link_once.html`, `content` block (when the meeting has a start time) | |
| +| The old link has stopped working. | `templates/link_once.html`, `content` block (only when the link was replaced) | |
| +| This is the only time this link is shown. Copy it now and send it to the people you are meeting. | `templates/link_once.html`, `content` block | |
| +| Meeting link | `templates/link_once.html`, `content` block, link input aria-label | |
| +| Go to the meeting | `templates/link_once.html`, `content` block, link button | |
| + |
| +## Confirm: replace the link (`/meetings/{sqid}/links/replace`) |
| + |
| +| String | Where | |
| +| --- | --- | |
| +| Replace the link? | `handlers_meetings.go`, `confirmReplaceLink` (rendered as `title` block and page-header Title via `templates/confirm.html`) | |
| +| Meetings | `templates/confirm.html`, `content` block, back-nav Label | |
| +| Everyone holding the current link for "{{title}}" will get a not-found page. You will see the new link once. | `handlers_meetings.go`, `confirmReplaceLink` (rendered as the confirm Body) | |
| +| Replace the link | `handlers_meetings.go`, `confirmReplaceLink` (confirm-form Label) | |
| +| Cancel | `templates/confirm.html`, `content` block, confirm-form CancelLabel | |
| + |
| +## Confirm: end the meeting (`/meetings/{sqid}/end` GET) |
| + |
| +| String | Where | |
| +| --- | --- | |
| +| End the meeting? | `handlers_meetings.go`, `confirmEnd` (rendered as `title` block and page-header Title via `templates/confirm.html`) | |
| +| Meetings | `templates/confirm.html`, `content` block, back-nav Label | |
| +| "{{title}}" will close for everyone and its link will stop working. | `handlers_meetings.go`, `confirmEnd` (rendered as the confirm Body) | |
| +| End the meeting | `handlers_meetings.go`, `confirmEnd` (confirm-form Label) | |
| +| Cancel | `templates/confirm.html`, `content` block, confirm-form CancelLabel | |
| + |
| +## Holding page (`/m/{sqid}/join`) |
| + |
| +| String | Where | |
| +| --- | --- | |
| +| {{.Title}} | `templates/join.html`, `title` block and page-header Title (the meeting's own title) | |
| +| Meetings | `templates/join.html`, `content` block, back-nav Label (members only) | |
| +| Starts {{.Starts}}. | `templates/join.html`, `content` block (when the meeting has a start time) | |
| +| You are {{.Name}}, joining as a {{.Standing}}. | `templates/join.html`, `content` block (`{{.Standing}}` is "member" or "guest", from `standing.go`, `Standing.String`) | |
| +| This team's Meet has no relay yet. Calls usually connect only between people on the same network. | `templates/join.html`, `content` block (the floor notice; shown only when no relay is configured) | |
| +| The call itself is the next slice of this app. When it lands, this page will show your camera preview, device pickers and a join button, and needs JavaScript for that part only; everything else here works without it. | `templates/join.html`, `content` block | |
| +| End the meeting | `templates/join.html`, `content` block, member-only link | |
| + |
| +## Error page (`/errors`, and any handler's `ErrorPage`) |
| + |
| +`templates/errors.html` now renders rastrillo's shared `error-page` |
| +partial (`{{template "error-page" dict "Status" .Status "Ref" .Ref}}`). |
| +The status, body sentence, and link labels it renders are rastrillo's |
| +copy, not Meet's, so they are not listed here. |
| + |
| +| String | Where | |
| +| --- | --- | |
| +| Something went wrong | `templates/errors.html`, `title` block (the browser tab title; the partial does not override it) | |