Skip to content

test(persona): read src/ authored metadata for retired persona names (#1003) - #1278

Merged
os-warren merged 1 commit into
mainfrom
claude/issue-1003-persona-scan-scope
Aug 24, 2026
Merged

os-warren merged 1 commit into
mainfrom
claude/issue-1003-persona-scan-scope

Conversation

@os-warren

Copy link
Copy Markdown
Collaborator

Part of #1003. The card's own decision points 1 and 3 are not settled here — see "What is still the maintainer's call" below.

The measurement came first, and it is the reason this is safe to land

The card was dispatched as a count, not a rule, because building the rule first risks shipping a gate red on an unknown number of src/ strings — and a gate nobody can turn green gets disabled. So the scan was run as a throwaway before any rule existed, on origin/main @ 903079a5:

Strings in the resolved stack 20,578 across 19 surfaces
Under the card-named four (title/label/description/help) 6,292
Persona-vocabulary hits 0
Hits including the bare word Copilot 0
Source-text grep over all 166 src/**/*.ts 0 persona matches

Zero genuine hits and zero false positives. The #802-shaped trap does not apply, so the gate lands green on the day it lands — a ratchet, not a backlog.

The only copilot text anywhere in src/ is two comment lines in src/pages/home.page.ts, both explaining why the card must not name sales_copilot. That is the load-bearing detail behind the design below.

What the gate reads

test/persona-copy.test.ts walks the resolved stack (objectstack.config.ts after every src/ module registers), not the source text. Two consequences, both measured:

  • Comments are structurally excluded. They are the one legitimate place in src/ to name a retired persona, and they already exist. A source-text grep would flag those two lines and need a HISTORICAL-style whitelist to excuse them; reading the resolved stack means there is nothing to excuse, so this rule ships with no exemption map. An exemption list with no members is a standing licence granted to nobody.
  • Every string is checked, not a key allow-list. The card named title/label/description/help; measured, those four miss 510 further strings that also reach a screen — successMessage (161), pluralLabel (90), subject (77), subtitle (26), helpText (15) and others. A key allow-list is a hole that grows silently every time someone authors a new component prop. Checking all 20,578 costs 29ms.

Vocabulary: shared, not re-typed

PERSONAS and normalise moved verbatim out of test/docs-drift.test.ts into test/helpers/persona-vocabulary.ts; both rules now import them. A second hand-written copy would drift, and the two would then disagree silently — each reporting its surface clean in spellings the other had already widened.

The surfaces differ only in what each adds: the bare word Copilot is a src/ term (PR #1002 neutralised it in interface copy) and never a docs term (#611 keeps AI Copilot as a section name). That split is why the shared base stops at the persona pairs.

Byte budget (#1196) — headroom returned, not spent

test/docs-drift.test.ts was at 100,429 / 102,400 bytes. Moving the vocabulary out takes it to 99,746 — 683 bytes returned. pnpm hygiene reports ✓ no source file over 100KB.

Reverse verification (on committed work, at 6ea57709)

Predicted direction: green from the start, unlike the docs rule which was red on 29 pages before #612's rewrite. Ablation injected two personas into real authored strings, proved on disk in both directions (injected present, original absent) before the run, with a trap … EXIT INT TERM restore:

pages[5].regions[3].components[0].properties.title: Sales Copilot, Copilot
translations[0].zh-CN.pages.sales_home_page.components.ai_briefing.title: 销售 Copilot, Copilot

RED as predicted, at an English page prop and a zh-CN locale-pack string — the second proving the CJK spellings are genuinely enforced, since 销售/服务/銷售/服務 are authored only in the translation bundles. Restore verified byte-identical (git status --porcelain empty), then GREEN: 4/4.

Because "0 found" and "the detector stopped matching" read identically, the rule carries three vacuity guards of its own: the stack is non-trivial, the walk reaches the locale packs, and a positive probe proves every one of the seven spellings still matches.

Verification

Run at 6ea57709, the commit this PR head points at:

  • npx vitest run — 124 files / 2892 passed, 1 skipped, exit 0
  • pnpm typecheck — exit 0
  • pnpm hygiene — ✓ source hygiene clean, incl. ✓ no source file over 100KB
  • pnpm hygiene:tokens — ✓ source token ratchet clean (measures src/, which this diff does not touch)

Declared narrowing: pnpm validate, pnpm lint and pnpm build were not run locally. The diff touches four files — .changeset/, test/docs-drift.test.ts, test/helpers/persona-vocabulary.ts, test/persona-copy.test.ts — and no src/ or objectstack.config.ts file, which is the entire input those three gates read. CI runs them regardless.

Timing budget: the new suite adds ~36ms of test time (heaviest assertion 29ms) against vitest's 5000ms default. It imports the stack rather than walking content/docs, so it does not lengthen the docs walk.

What is still the maintainer's call

This PR does not close the card, because two of its three stated decision points are wording rulings, not code:

  1. Bare Copilot — adopted here as a src/-only term, following the line PR Home page still ships a card titled "Ask the Sales Copilot" — a retired persona in live UI metadata, outside every docs guard's scan surface #1002 already landed and documented. Flipping it is one array entry (UI_ONLY); the measurement is 0 either way, so nothing turns red on either choice.
  2. Exemption mechanism — answered by measurement: none needed, because the stack route excludes comments. Recorded rather than ruled.
  3. Two personas vs a general retired-word vocabulary — left as-is. Generalising means someone maintains the list; not taken unilaterally.

Generated by Claude Code

@vercel

vercel Bot commented Aug 24, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
hotcrm Ignored Ignored Aug 24, 2026 4:31am

Request Review

@github-actions github-actions Bot added the ci/cd CI plumbing and the verification pipeline label Aug 24, 2026
@os-warren
os-warren marked this pull request as ready for review August 24, 2026 04:36
@os-warren
os-warren added this pull request to the merge queue Aug 24, 2026
Merged via the queue into main with commit 2a3eac6 Aug 24, 2026
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ci/cd CI plumbing and the verification pipeline

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants