diff --git a/docs/design/ai-slop-tells.md b/docs/design/ai-slop-tells.md index 2aa51becf..a7c0ab57b 100644 --- a/docs/design/ai-slop-tells.md +++ b/docs/design/ai-slop-tells.md @@ -57,8 +57,7 @@ listed again. line, so it excuses one literal, never the rest of the file. *Exception:* keyboard notation (`⌘↵`), the reply-aim `↳`, the DM pair `↔`; user content (the reaction picker); the parser for the kernel's `🤝` DM - event; masked-token bullets; `↵` in the marketing demo. Dated 2026-11-03: - `activity.decision.ruled`, left to the Activity redesign owner. + event; masked-token bullets; `↵` in the marketing demo. 7. **A sparkle "AI" icon.** It is the category's cliché, and it names the technology rather than the act. *Check:* no `AutoAwesome`, `AutoFixHigh`, `Sparkle(s)` or `✨` in v2 @@ -101,9 +100,9 @@ any live app surface. It found one chromatic glow, the logo key, which is drawn. | 3 | Frosted glass | `landing/v2-landing.css:87` | the marketing sticky header only | acceptable | guard | | 4 | Gradients | 30+ key rules | all d215 a/b key pairs; 4 named masks, track and hatch | acceptable | guard | | 5 | Glow | `v2.css` `.v2-rail__brand-icon`, `primitives.css` `.v2p-b-c` | artboard values (`d215/index.html:167`, `:226`) | acceptable | guard | -| 5 | Focus halo | `v2.css` `.v2-activity__compose:focus-within` | hard-coded `rgba(29,63,209,.10)` 4px, not `--v2-focus-ring`; on the dark ground it is all but invisible (`rgb(138,162,255)` 4px ring with the token, measured on a local build) | real | proposal for the Activity/Artifacts redesign owner | +| 5 | Focus halo | `v2.css` `.v2-activity__compose:focus-within` | hard-coded `rgba(29,63,209,.10)` 4px, not `--v2-focus-ring`; on the dark ground it is all but invisible (`rgb(138,162,255)` 4px ring with the token, measured on a local build) | real | fixed by the Activity build: the open composer's ring is `var(--v2-focus-ring)` (`components/V2ActivityPage.css`) | | 6 | Glyph icons | `en`/`zh-CN`: `inviteModal.connectOwnAgent`, `adminUsers.registered.analyticsLink`, `adminAnalytics.userAdminLink` (`→`), `approvalCard.approved` (`✓`) | strings | real | glyphs dropped from the copy | -| 6 | Glyph icons | `activity.decision.ruled` (`✓ {{by}} ruled`), shown on Activity and the thread decision card | string | real | proposal for the Activity/Artifacts redesign owner; allowlisted by name and date in the guard | +| 6 | Glyph icons | `activity.decision.ruled` (`✓ {{by}} ruled`), shown on Activity and the thread decision card | string | real | fixed by the Activity build: the `✓` left both locales and the guard's allowlist | | 6 | Glyph icons | `V2PodBoard.tsx` Follow `✓`, `V2LangSwitch.tsx` `✓`, `V2FirstRunHero.tsx` `↗`, `V2Lightbox.tsx` `←`/`→`, `V2SettingsFrame.tsx` `✎` | JSX text | real | SVG glyphs from `icons/glyphs.tsx` (two chevrons added) | | 6 | Close and chevron glyphs | `×` on the close buttons in `V2Lightbox`, `V2PodBoard` (focus editor and new task, both with no accessible name), `V2Composer` (reply aim), `V2InviteModal`, `V2CatchUpStrip` and `V2AvatarCropDialog`; `›` in `V2SettingsFrame` | JSX text | real | `ShellGlyph` `close` (added) and `chevron-right`; the two board buttons gained `aria-label` from `common.close` | | 6 | Emoji | `V2MessageRow.tsx` reply quote | quoted uploads rendered as `📎 name` | real | an `aria-hidden` SVG file glyph before the name | @@ -129,11 +128,9 @@ floors burn-down allowlist under a heading dated 2026-11-03, not fixed here. ### Proposals for the Activity/Artifacts redesign owner -- `.v2-activity__compose:focus-within` should use `var(--v2-focus-ring)`. The - hard-coded 10% cobalt halo barely shows in dark mode. -- Drop the `✓` from `activity.decision.ruled` (en and zh-CN), and the - allowlist entry in `v2-slop-tells.test.ts` with it. -- The Class A note on "Needs you" below. +- Done for Activity (the d215 build): the composer ring is the token, the `✓` + left `activity.decision.ruled`, and "Needs you" is one hairline-split list + (the Class A note below). ### Proposals for UX Lead (Class A, not made here) diff --git a/docs/design/artboards/d215/README.md b/docs/design/artboards/d215/README.md index 4612c051f..1f11e902f 100644 --- a/docs/design/artboards/d215/README.md +++ b/docs/design/artboards/d215/README.md @@ -6,7 +6,7 @@ The spec for D215 (artboard v2). Open `index.html` in a browser. The toggle at t - A second block under agent settings draws the states of that page (policy and machine, identity edit, connector grants, runtime with the model and effort selects, own API key) at 1440 and 390. The runtime and key frames follow V2RuntimeControls and V2AgentProviderKey, including the stored-model refusal and the key-save error. Those frames carry `data-state`, so `measure_after.js` skips them and `targets.json` does not move. - Two state-only surfaces: `task-record` (the task record page, loaded and not-available, under the reply trace) and `handoff` (the OAuth and Discord return pages, `data-state` working, done, error, on the auth card). Every frame carries `data-state`, so the scorer skips them and `targets.json` does not move. - A block under Settings draws the free-plan Plan row and the administrator-only Administration group (`data-state="admin-free"`, 1440 and 390, also skipped by the scorer). -- Under Activity and under Artifacts, a block redraws each page in the picked language (`#s-activity-signal`, `#s-artifacts-signal`): busy and day zero at 1440 and 390, built only from the seven picked surfaces' blocks. Sam approved them on 11-03. The frames carry `data-state="signal"`, so the scorer skips them until each page's build PR makes them the scored frames; the frames above them stay as the record of the live page until then. +- Under Activity and under Artifacts, a block redraws each page in the picked language (`#s-activity-signal`, `#s-artifacts-signal`): busy and day zero at 1440 and 390, built only from the seven picked surfaces' blocks. Activity's build scores its four frames (no `data-state`) and retired the traced `#s-activity` section. Artifacts' frames still carry `data-state="signal"`, so the scorer skips them until its build lands. - The theme switch (sun / moon, D224) sits in the rail above the avatar at 1440. At 390 there is no rail, so the same switch rides the Pods top bar, left of Search. It is a two-item segment: the item for the theme in effect is the white key. - `before/` holds prod captures from 2026-10-31, blurred so they show layout and density only. - `targets.json` holds the helper-word and scroll targets per frame. `cap/measure_after.js` writes it from `index.html`. @@ -15,14 +15,14 @@ The spec for D215 (artboard v2). Open `index.html` in a browser. The toggle at t ## Where each frame came from -Passing the prod check means a page matches its frame. It means the page matches the style Sam picked only when the frame came from his pick. Every frame is in one of four groups. Only the first two have scored frames, and prod scores are reported per group, never as one total. +Passing the prod check means a page matches its frame. It means the page matches the style Sam picked only when the frame came from his pick. Every frame is in one of four groups. A group's frames are scored only where the table says so, and prod scores are reported per group, never as one total. | Group | Frames | Source | |---|---|---| | **From Sam's pick** | sidebar, chat, board, agent-memory, agent-settings, settings, connectors | The seven surfaces picked on 10-31 (#3059). Later edits: the theme switch (#3175) and the open thread (#3178). #3288 (the 390 agent-settings and settings frames, brought up to the shipped pages) and #3289 (memory notes drawn as the API holds them) moved those frames toward the live page, so read them with that in mind. | | **Drawn after the pick** | dm, byo, byo-handoff, connect, team, firstrun-\*, signin, signup, signup-sent, verify-email, forgot-password, reset-password, cli-authorize, invite, invite-required, profile, agent-profile, run-trace-after, chat-trace, chat-agents-away, and the agent-settings and settings state blocks | New drawings in the picked language, from 11-01 on. Sam has not reviewed them as a set. | -| **Approved by Sam, 11-03** | activity-\*, artifacts-\* with `data-state="signal"`; task-record-\*; handoff-\* | Sam saw each one live-beside-proposed and answered "Build as drawn" for all four pages. Activity and Artifacts are built only from the picked surfaces' blocks. The scorer still skips these frames (they carry `data-state`). Each page's build PR makes its approved frame the scored one and retires the frame it replaces. | -| **Drawn from live, being retired** | activity-\*, artifacts-\* without `data-state` | Traced from the live pages with small fixes (#3316, #3318). The scorer skips them (`SKIPPED` in `cap/measure_after.js`). Scoring a page against them would only show it has not drifted from itself. The Activity and Artifacts build PRs remove them. The two before frames, `run-trace-before` and `chat-trace-before`, draw the old pages and are never a target. | +| **Approved by Sam, 11-03** | activity-busy, activity-dayzero (`#s-activity-signal`, scored since the Activity build); artifacts-\* with `data-state="signal"`; task-record-\*; handoff-\* | Sam saw each one live-beside-proposed and answered "Build as drawn" for all four pages. Activity and Artifacts are built only from the picked surfaces' blocks. The scorer still skips these frames (they carry `data-state`). Each page's build PR makes its approved frame the scored one and retires the frame it replaces. | +| **Drawn from live, being retired** | artifacts-\* without `data-state` | Traced from the live page with small fixes (#3318). The scorer skips them (`SKIPPED` in `cap/measure_after.js`); scoring a page against them would only show it has not drifted from itself. The Artifacts build PR removes them; the Activity build removed its traced frames. The two before frames, `run-trace-before` and `chat-trace-before`, draw the old pages and are never a target. | ## Rules for D215 PRs diff --git a/docs/design/artboards/d215/cap/measure_after.js b/docs/design/artboards/d215/cap/measure_after.js index 25d9ec07c..85d4f75e7 100644 --- a/docs/design/artboards/d215/cap/measure_after.js +++ b/docs/design/artboards/d215/cap/measure_after.js @@ -29,14 +29,13 @@ const SURFACES = [ 'settings', 'agent-settings', 'agent-memory', 'board', 'connectors', 'chat', 'sidebar', 'byo', 'byo-handoff', 'firstrun-welcome', 'firstrun-waiting', 'firstrun-connected', 'firstrun-error', 'connect', 'team', 'chat-agents-away', 'chat-trace', 'run-trace-after', 'profile', 'firstrun-welcome-nohost', + // Activity: the frames Sam approved 11-03 ("Build as drawn"), built in V2ActivityPage. + 'activity-busy', 'activity-dayzero', ]; // Base frames (no data-state) that are drawn but deliberately not scored. Each needs a reason. const SKIPPED = { - // Activity and Artifacts are being redesigned in another session; targets taken now would pin - // frames that are about to change. Score them once that redesign lands. - 'activity-busy': 'redesign in progress elsewhere', - 'activity-dayzero': 'redesign in progress elsewhere', - 'activity-dayzero-pending': 'redesign in progress elsewhere', + // Artifacts is being redesigned in another session; targets taken now would pin frames that + // are about to change. Score them once that redesign lands. 'artifacts-busy': 'redesign in progress elsewhere', 'artifacts-dayzero': 'redesign in progress elsewhere', // Drawings of the old page beside their "after" frames (390 only). They are what the fix moves @@ -48,7 +47,8 @@ const SKIPPED = { // a real key. The first-run dialog is a latch-gated overlay, and the Scout welcome only exists in a // brand-new pod. chat-agents-away and chat-trace need a pod in that exact state, run-trace-after a // run id and profile a person id, none of which prod() takes yet, so they are artboard-only for now. -const PROD_SURFACES = ['settings', 'agent-settings', 'agent-memory', 'board', 'connectors', 'chat', 'sidebar', 'byo', 'connect', 'team']; +// activity-dayzero needs an account with no asks and no agents, so only the busy page is checked. +const PROD_SURFACES = ['settings', 'agent-settings', 'agent-memory', 'board', 'connectors', 'chat', 'sidebar', 'byo', 'connect', 'team', 'activity-busy']; const VIEWPORTS = ['1440', '390']; const EXPECTED = SURFACES.flatMap(s => VIEWPORTS.map(v => `${s}-${v}`)); @@ -221,6 +221,7 @@ async function prod(only) { ['byo', () => '/v2/agents/byo'], ['connect', () => '/v2/connect'], ['team', () => '/v2/agents'], + ['activity-busy', () => '/v2/activity'], ['chat', () => `/v2/pods/${pod}`], ['sidebar', vp => (vp === '1440' ? `/v2/pods/${side}` : '/v2'), { list390: SIDEBAR_390 }], ]; diff --git a/docs/design/artboards/d215/cap/measure_after.test.js b/docs/design/artboards/d215/cap/measure_after.test.js index 8da521996..8090d4229 100644 --- a/docs/design/artboards/d215/cap/measure_after.test.js +++ b/docs/design/artboards/d215/cap/measure_after.test.js @@ -29,7 +29,7 @@ test('--only with an unknown surface throws', () => { test('the committed targets.json passes its own validation', () => { const t = JSON.parse(fs.readFileSync(path.join(__dirname, '..', 'targets.json'), 'utf8')); - assert.strictEqual(Object.keys(t).length, 40); + assert.strictEqual(Object.keys(t).length, 44); validateTargets(t); }); @@ -39,7 +39,7 @@ test('an empty or partial measurement is refused', () => { const partial = { ...t }; delete partial['board-390']; assert.throws(() => validateTargets(partial), /missing board-390/); assert.throws(() => validateTargets({ ...t, 'chat-1440': { helperWords: NaN, innerRatio: 2 } }), /invalid chat-1440/); - assert.strictEqual(EXPECTED.length, 40); + assert.strictEqual(EXPECTED.length, 44); }); test('a frame the scorer does not know is named, with the way to fix it', () => { diff --git a/docs/design/artboards/d215/index.html b/docs/design/artboards/d215/index.html index eb954c040..3c9a2fc54 100644 --- a/docs/design/artboards/d215/index.html +++ b/docs/design/artboards/d215/index.html @@ -1282,7 +1282,7 @@
Say hello in the pod where it lives. If it doesn't answer, @mention it.
Slack or Telegram — the agent answers where your team already talks.
Say hello in the pod where it lives. If it doesn't answer, @mention it.
Slack or Telegram — the agent answers where your team already talks.
| Day zero · Today | Drawn. One pod, only Scout: 2 steps, current key Open My Workspace, both sections empty. |
| Step copy | "Say something to it" no longer claims an @mention is needed: Scout answers a plain hello in My Workspace (walk 11-02). The line now reads "Say hello in the pod where it lives. If it doesn't answer, @mention it." |
| Day zero · 7 days | Drawn at 390. Moved forward reads "Nothing moved in the last 7 days." |
| Get started · checking | Drawn beside the loaded card, at the height of the two-step day-zero card. A one- or three-step result shifts by one row when it lands, and an empty result removes the card. Reserved only when hasEverHadAttention === false, the queue is 0 and the scope is All pods. |
| Busy | Drawn. One decision (Recommended under the first option), one approval, two mentions, two pod groups. |
| No agent yet (step 1) | Not drawn. The composer stays hidden and Hire an agent is the current key; same card, three rows. |
| Reply open, ruled, Other… | Not drawn. The editor takes the full card width, as prod does. |
| Loading, error, count unavailable | Not drawn. They keep prod's spinner, __error and Retry. |
Say hello in the pod where it lives. If it doesn't answer, @mention it.
Slack or Telegram — the agent answers where your team already talks.
Say hello in the pod where it lives. If it doesn't answer, @mention it.
Slack or Telegram — the agent answers where your team already talks.