Skip to content
cccskills
FreePublished on GitHub

interface-text

Rules for every string rendered inside the app, plus the sweep that removes in-app prose. Use when writing or changing a label, hint, description, tooltip, empty state or KPI tile in a .tsx file, or when running Pattern Patrol P14 or asked to find or fix long UI text.

The English summary is being prepared. Showing the original description.

See how to install

Files included (6)

  • SKILL.md11.2 KB
  • confirm.md2.8 KB
  • discover.md5.0 KB
  • evals.md7.0 KB
  • fix.md7.7 KB
  • review.md5.0 KB

SKILL.md (original)

Review the instructions the agent will receive before you install.

<!-- SYNCED COPY — do not edit here. Canonical: common-docs/skills/interface-text/SKILL.md This file is distributed to every consuming repo by common-docs/meta/scripts/sync_skills.py. Edit the canonical, run the sync, and commit each repo. Edits made here are overwritten and lost. -->

interface-text — in-app text is layout

<!-- rules:stamp -->

Rules from common-docs/policies/interface-text-is-layout.md — edit there, never here (python3 common-docs/meta/scripts/one_home.py --write).

  1. Labels, not prose. A screen is label → value → action; the label carries the meaning (Batch savings (7d)). If a number needs a paragraph, rename it; if it still needs a definition, one sentence in a tooltip. No page or section descriptions on dashboard and functionality pages: a title is not followed by a sentence. Moving one into a help icon is a fix, never a regression, and lost taglines are not damage. AI-written descriptions are worse than none ("Choose which channels each notice reaches you on…"). Only promotional pages may carry one.
  2. A dashboard is numbers, lists and tables. Per signal: title, number, share, a compact table of top rows; no "meaning" text, threshold sentences or hints under tiles. One big table first, drill-downs beneath it or on click, never scattered panels each with its own story. A broken dashboard is fixed surgically, keeping what worked (the window picker, the dimensions, the drill); never rip data out to undo a mistake. A tooltip on an icon is the ceiling for explanation; the explanation lives in FEATURE.md, not on the screen.
  3. Tooltips always, sentences never. Every label, icon button, abbreviation or number a newcomer might not understand gets a tooltip (InfoHint); a complex thing gets a help popover (FieldHelp; settings rows use helpText). Never a native title= (phones cannot open it).
  4. Every slot has a budget, and the component enforces it (budgets). A primitive renders secondary text on one line (truncate / line-clamp-1) with the full definition in its tooltip slot; components/official/kpi/KpiTile.tsx is the model. A primitive that lets secondary text grow is the defect, not the long string; choosing a hand-rolled component because the shared one "cuts off long hints" is this rule broken twice.
  5. Text sets the size of its row and its column, and siblings match. Before adding text, look at the row and the column it lives in. Repeated components fill the same visible slots at similar length (within about 1.5x) and the same grammatical shape, or none do; one tile with a hint among five without is a defect. A tooltip states only what the code or data contract proves, never an invented definition.
  6. Identifiers never render. A key, variable name, slug, kind or tool name (normal_text) shows as the thing's label, else through the one humanizer (humanizeIdentifier / displayLabel, @ai-matrx/kit/text-case); raw only where the person types or uses it, as a monospace token. Guard: pnpm check:raw-identifiers.
  7. Copy is adult and concise. Never repeat a name the app header already shows; a panel header is one compact row of controls; no subtitle that explains the obvious or describes the agent. When one instance is found, sweep its siblings. In a focused mode (the docked chat) the main app sidebar is not a column: it collapses behind one icon that opens it on click (UI shell style guide).
  8. Human-written text is protected. An AI judge falls for what made the junk and deletes the few texts a person wrote. Any judgment sweep over user-facing text protects human-authored strings mechanically (git authorship, an approved keep list), gives Arman a click-through review (page link, before → after, keep / revert / note), and turns his answers into documented patterns the skill teaches. Every scheduled sweep honors the keep list.
  9. A person's own content may carry emoji and anything other companies allow: page, callout and workspace icons, text, reactions. The no-emoji rule covers our own chrome (labels, buttons, empty states), which stays Lucide-only.
  10. You see it rendered before it is done. Agents write a string into source, where 190 characters look like one line. Interface text is done only after it has been seen rendered at desktop and narrow widths (reality is the referee) and pnpm check:interface-text --changed (matrx-frontend) has been run on the diff.
<!-- rules:stamp-end -->

Doctrine (read once): common-docs/policies/interface-text-is-layout.md.

You are writing interface text, not prose. Every string the app renders sits in a slot owned by a component, has a character budget, and has siblings that must match. The screen is not where you explain, justify, or prove anything — that is what the commit message, the code comment and FEATURE.md are for.

The card — apply to every string you write or touch

  1. Who is this sentence for? If it helps someone reading the diff — a formula, a function or table name, where the number comes from, what changed, what is not built yet, which other page agrees with it — it is author-facing. Put it in a code comment or the commit. It never renders.
  2. Label first, tooltip always. Make the label carry the meaning (Batch savings (7d)). Then give every label, icon button, abbreviation or number a newcomer might not understand a one-sentence tooltip: title= on KpiTile, components/official/InfoHint everywhere else (hover, keyboard and touch — a native title= attribute is unreachable on phones). A complex thing gets a help popover (FieldHelp from @ai-matrx/design-system/controls; a Field's string help and a settings row's helpText already render one). When you delete prose, ask what a newcomer loses and move that into a tooltip — never just delete (Arman, 2026-10-10: "our changes need to push for ALWAYS tooltips").
  3. Fit the slot. Secondary text ≤ 60 chars, one line, never two sentences. Tooltip ≤ 140, one sentence. Placeholder ≤ 60, an example value. Dialog description / empty / error state ≤ 140, at most two sentences: what happened, what to do. No sentence under a page or section title — ever.
  4. Look at the row and the column. Your text sets the height of every tile in its row and the width of every cell in its column. Fill a visible slot on all siblings, at similar length and in the same shape, or on none. Tooltips are hidden and per need — never add one to a sibling just to match.
  5. Use the primitive that enforces the budget. components/official/kpi/KpiTile + KpiGrid for KPI rows (one-line hint, title tooltip). If the official primitive "cuts off" your text, your text is too long — shorten it; never hand-roll a component to escape the limit. A local component that renders unbounded secondary text is itself a finding.
  6. A tooltip states only what you verified in the code or the data contract. Cannot prove the definition ("since midnight", "today's budget")? Write no tooltip — a wrong definition is worse than none.
  7. Honesty is state, not prose. Unmeasured → — with the reason in the tooltip. Partial feature → the Coming Soon registry. Never "not yet reported by the backend", never "Backfill brings this up to 100%".
  8. Text has three colors — never a fainter one. Content and actions text-foreground; labels, meta, menu group labels, placeholders text-muted-foreground; a disabled control text-disabled-foreground (its disabled prop paints it). Never /60, opacity-* on text, or text-gray-*: a label must look different from the action it names, in light AND dark (the 2026-10-14 "gray on gray on gray" menu). Table: the style guide's Color section.
  9. See it rendered, then check it. In matrx-frontend run pnpm check:interface-text --changed before committing; any other repo: node ../matrx-frontend/scripts/interface-text/check-interface-text.mjs --root=. --changed. Every NOVEL line on your diff is fixed before commit.

Rationalizations

From the 2026-09-30 baseline runs (evals.md) — each one produced a defect.

Excuse (verbatim)Reality
"the shared tile cuts off long hints"That is the budget working. Shorten the text; keep the primitive.
"swapping only this row would make one page look two ways… should be its own change"Adopt the primitive for the whole page in this change; it is a few lines.
"the rule that every number names its window and item count"The label (7d) names the window; a count fits a 60-char hint. A sentence is not required.
"Both are a screen lying." → adds a sentenceHonesty is — + tooltip, a badge, or a registry entry.
"in the same words the Platform Spend 'Saved by batching' headline uses"Consistency means the same label, not the same paragraph copied to two pages.
(with the skill) tooltips added to all six tiles "so the row matches" — two invented "since midnight" / "today's budget"Parity is for visible slots. An unverified definition is fabrication; leave the tooltip out.

Red flags — stop and re-read the card

  • You are about to paste words from your commit message, FEATURE.md or a code comment into JSX.
  • Your string contains a dot-separated or snake_case name, a backtick, "backend", "server", or "not yet".
  • One sibling gets a hint and the others do not.
  • You are writing a second sentence in a hint or description.
  • You are choosing a local component over components/official/* because of text length.
  • You are writing a tooltip definition you did not read in the code or the data contract.
  • You are making text fainter with /NN, opacity-* or a hand-picked gray, or hand-styling a menu group label.

The sweep — Discover → Review → Fix → Confirm (Pattern Patrol P14)

Each phase is its own agent. Read only the file for the phase you were given:

PhaseLaneRead
Discover — build units for a slice, classify each, propose the exact fix; the validator must passquick with sonnet (haiku mapped rules to verdicts without reading and cut rewrites mid-sentence — 2026-09-30)discover.md
Review — accept or correct the classifications, find primitive-level fixes, batch the work, pick what goes to Armanstandard (opus — judgment over the classifications)review.md
Fix — apply a reviewed batch in its filesquick (sonnet) for mechanical batches, standard otherwisefix.md
Confirm — independent check of a fixed batchstandard (sonnet), never the fixerconfirm.md

The proof record and regression scenario for this skill is evals.md; the next editor reruns it.

Reviews

No reviews yet. Tell others what you thought.

Comments

No login needed. Share how it worked for you, ask a question, or note where it did not run.

No comments yet. Be the first to write one.

Comments are published right away. Do not include personal information such as email addresses or phone numbers. Up to 2 URLs.

0 / 1,000 characters

This form is protected by reCAPTCHA, and the Google Privacy Policy and Terms of Service apply.

More skills from this repository

Admin debug system wiring for the floating AdminIndicator's live debug data and Copy Full Context. Use when adding debug visibility to a route or feature, wiring useDebugContext or the debug panel, capturing console errors, or enabling the copy-context workflow for a page.

The English summary is being prepared. Showing the original description.

armanisadeghi/ai-matrx3Updated Oct 20, 2026

Compact two-icon Copy / Copy-for-AI controls (components/agent-copy). Use when adding copy buttons to a row, card, list, or record; merging duplicate Copy/JSON/AI controls; continuing the copy rollout; or writing a Copy-for-AI payload. NOT for markdown content actions (use rich-document-actions).

The English summary is being prepared. Showing the original description.

armanisadeghi/ai-matrx3Updated Oct 20, 2026

Disclosing a surface's existing fixed AI jobs in the shell's top Agents menu. Use when a page, panel, overlay, or window already runs a mandate behind a button, assist, automatic action, or mode; when the agent-disclosure guard names a file; or during a surface check.

The English summary is being prepared. Showing the original description.

armanisadeghi/ai-matrx3Updated Oct 20, 2026

The watch-fix-rerun method for making an existing platform agent or automated process efficient and correct: baseline its ledger, run one unit yourself, fix the class behind every wasted call, rerun, record. Use when asked to improve, optimize, watch, or 'make efficient' an agent, a sandbox session, a sync job, or any recurring automated process.

The English summary is being prepared. Showing the original description.

armanisadeghi/ai-matrx3Updated Oct 20, 2026

Redux state for agent execution and firing agent shortcuts. Use when editing features/agents/redux/, building agent UI, creating a conversation, touching assembleRequest or NDJSON stream state, wiring agent-state selectors, adding a per-conversation capability, or triggering a shortcut from a button, menu, or code (useShortcutTrigger, launchAgentExecution).

The English summary is being prepared. Showing the original description.

armanisadeghi/ai-matrx3Updated Oct 20, 2026

The provision for a call site: the exhaustive menu of values that place in the code can realistically produce. Use before creating or fixing a mandate or agent that reasons about more than its own input, when deciding whether an agent can answer at all with what it is sent, or when its output 'looks right' but nobody checked it could be. NOT for building the agent (use create-agent).

The English summary is being prepared. Showing the original description.

armanisadeghi/ai-matrx3Updated Oct 20, 2026

See all skills by armanisadeghi

Report a problem with this skill