NOASSERTIONupdated 1mo ago
Let be the absolute plugin directory two levels above this SKILL.md. Resolve that path before running commands or opening shared references. When these instructions say swiftui-ctx, invoke /scripts/swiftui-ctx; do not assume the command is on PATH.
Audit Swiftui Typography Text 能做什么?
name: audit-swiftui-typography-text description: Audit macOS SwiftUI typography text for correctness, current APIs, and production conventions. Use for that domain or as part of a full audit.
Bundled resource root
Let <swiftui-plugin-root> be the absolute plugin directory two levels above this SKILL.md. Resolve that path before running commands or opening shared references. When these instructions say swiftui-ctx, invoke <swiftui-plugin-root>/scripts/swiftui-ctx; do not assume the command is on PATH.
Audit SwiftUI Typography & Text
AUDIT-ONLY · macOS-only · SwiftUI-only. Run this on a finished or in-progress macOS SwiftUI
project to detect — and where certain, fix — every way text and type go wrong on a macOS 26 (Tahoe)
target: deprecated Text + Text concatenation, malformed AttributedString, hardcoded font sizes that
defeat Dynamic Type, lineLimit(N) that jumps layout, the design-only Font.system overload, mis-gated
TextRenderer, hand-rolled label rows that should be LabeledContent, jiggling numerics missing
monospacedDigit(), and invented type APIs. Findings are written to disk in the toolkit's unified schema;
certain mechanical defects are fixed under the fix-safety protocol. This is never a from-scratch text-UI
generator.
Several of this domain's deprecations close at macOS 26.0 / 26.5 (after most training data), so AI
frequently emits the now-deprecated Text + Text and design-only Font.system. Be suspicious wherever AI
composed styled text.
Boundary / seam note (stay in lane)
- The
Text + Text/Font.system(_:design:)deprecation flag is owned byaudit-swiftui-api-currency; this skill owns the positiveAttributedString/ interpolation /system(_:design:weight:)craft. Emitcross_ref: api-currencyon these findings; do not double-own the flag. - String externalization,
String(localized:), and the AttributedString localization facet belong toaudit-swiftui-localization— file the catalog implication there; this skill owns rendering. - Dynamic Type as an accessibility requirement is cross-linked to
audit-swiftui-accessibility; this skill detects the hardcoded-size mechanics, a11y owns the trait-level audit. Emitcross_ref: accessibility. - AppKit
NSTextView/NSAttributedStringrich-text bridging is out of scope — note it in one line and point to the futureaudit-appkit-interopskill.
Domain rules
- Compose, don't concatenate.
Text + Textis deprecated at macOS 26.0; build styled runs withAttributedString(AttributeContainer) or string interpolation into oneText. - Size through the type system, never literals. Use a semantic text style (
.system(.body)) or@ScaledMetricso Dynamic Type scales it;.font(.system(size: 14))freezes the layout. - Reserve space you'll need.
.lineLimit(N, reservesSpace: true)keeps the frame stable; bare.lineLimit(N)jumps when content arrives. - Stop the digits from dancing. Live-updating numerics (timers, counters, prices) need
.monospacedDigit()or a monospaced-digit font; otherwise each frame re-flows.
Defect index (txt-01 … txt-09)
id · tell · severity · fix · open reference. Severities: hard-fail (never-correct / invented),
warning (compiles but non-native / deprecated), advisory (judgment / craft). auto = mechanical
single-answer fix; flag = show the ✅, dev applies.
| id | One-line tell | Sev | Fix | Reference |
|---|---|---|---|---|
| txt-01 | Text(…) + Text(…) concatenation (deprecated macOS 26.0) |
warning | flag | text-composition-and-attributed.md |
| txt-02 | Font.system(_:design:) design-only overload (deprecated 26.5 → add weight:) |
warning | auto | fonts-and-dynamic-type.md |
| txt-03 | .font(.system(size: N)) hardcoded size — defeats Dynamic Type |
advisory | flag | fonts-and-dynamic-type.md |
| txt-04 | .lineLimit(N) integer without reservesSpace: → layout jump |
advisory | flag | text-layout-and-rendering.md |
| txt-05 | AttributedString(…) built wrong (String concat / no AttributeContainer) |
warning | flag | text-composition-and-attributed.md |
| txt-06 | .textRenderer(_:) (macOS 15) / TextRenderer (macOS 14) mis-gated |
warning | flag | text-layout-and-rendering.md |
| txt-07 | hand-rolled HStack { Text; Spacer(); Text } label row → LabeledContent |
advisory | flag | text-layout-and-rendering.md |
| txt-08 | live numeric Text (.formatted()/format:) missing .monospacedDigit() |
advisory | flag | fonts-and-dynamic-type.md |
| txt-09 | invented type API: .fontSize(, .textStyle(, Text(styled:), .attributedText(, .font(size: |
hard-fail | flag | text-composition-and-attributed.md |
Currency seam: txt-01 and txt-02 carry cross_ref: api-currency (currency flags the deprecation;
typography owns the craft). txt-03 carries cross_ref: accessibility (Dynamic Type).
The real API, at a glance
Real (exist on macOS 26): AttributedString + AttributeContainer, Text string interpolation,
Font.system(_:design:weight:), @ScaledMetric(relativeTo:), lineLimit(_:reservesSpace:) (macOS 13+),
TextRenderer (protocol, macOS 14+) + textRenderer(_:) (modifier, macOS 15+), LabeledContent (macOS 13+),
monospacedDigit(), Text(_:format:). Font.system(_:design:) (no weight:) still resolves but is
deprecated at macOS 26.5 → system(_:design:weight:); Text("a") + Text("b") is deprecated at 26.0.
Invented (never exist): .fontSize(_:), .textStyle(_:), Text(styled:), .attributedText(_:),
.font(size:) (the real spelling is .font(.system(size:))). Confirm any uncertain name via
swiftui-ctx lookup <api> (exit 3 = no shipping Mac app uses it) + the canonical invented-name list in
<swiftui-plugin-root>/references/_shared/hallucination-blacklist.md — read, never restate.
Floor values are the reconciled truth in
<swiftui-plugin-root>/references/_shared/floors-master.md — read, never restate the table here.
Grounded ✅ correct shape (real shipping code, not a placeholder)
The ✅ examples in this skill are the swiftui-ctx consensus shape backed by a permalinked Mac app, not
hand-written snippets. The canonical txt-08 fix (a live numeric Text that must not jiggle) — verified via
swiftui-ctx lookup monospacedDigit --json (consensus () at 100%, introduced_macos 10.15) and
swiftui-ctx file ex_59de3fab78 --smart:
// ✅ live numeric Text — .monospacedDigit() stops per-frame re-flow (sindresorhus/Gifski, macOS 26)
Text(progress.formatted(.percent.precision(.fractionLength(0))))
.font(.system(size: 30, weight: .bold, design: .rounded)) // current overload carries weight: (txt-02 ✅)
.monospacedDigit() // txt-08 ✅
- Source (real GitHub permalink): https://github.com/sindresorhus/Gifski/blob/7f873856e2acd8b52e6681dee3aec31e6cab23e4/Gifski/Utilities.swift#L5210
- Spec (Sosumi
doc:): doc: https://sosumi.ai/documentation/swiftui/view/monospaceddigit
Reproduce the grounding for any other defect: swiftui-ctx lookup <api> --json → read consensus +
recommended → swiftui-ctx file <recommended.id> --smart → put that consensus shape in ## Correct and its
permalink + Sosumi doc: in ## Source (step 7 FIX).
The 8-step audit workflow (execute verbatim)
- ORIENT.
tree/findthe SwiftUI sources. Read the deployment target (project.pbxprojMACOSX_DEPLOYMENT_TARGET, orPackage.swiftplatforms:). It is load-bearing: txt-06 mis-gating fires only when the floor is below the symbol's introduction, and the txt-01/02 deprecations are advisory below their close (26.0 / 26.5) but become live-warning at/after it. Record it. - LOCATE. Run the shared hybrid lint runner:
bash <swiftui-plugin-root>/scripts/swiftui-lint.sh --skill audit-swiftui-typography-text --dir <sources> --json /tmp/txt.json --sarif /tmp/txt.sarif. It runs this skill's tier-1 grep tells (lint/grep-tells.tsv) + the tier-2 structural ast-grep rule (lint/ast-grep/*.yml— the multi-lineText + Textgrep can't express), a per-file parse probe, and emits unified JSON + SARIF. Read itsparse_warnings— a flagged file did not fully parse, so a structural miss can't masquerade as clean; READ those by hand. The runner only LOCATES. Engine + rule-file format + degradation:<swiftui-plugin-root>/references/_shared/lint-architecture.md. - READ. Open every located file in full — never pattern-match-and-patch blind. Whether a numeric
Textupdates live, whether alineLimitframe matters, and whether anHStackis really a label row are invisible to grep. Build a per-file inventory: each text site + its composition shape + its sizing + its layout reservation. - DETECT. Apply the index. Assign each candidate a confidence; report a finding only at 100%
certainty (an invented name, a literal
Text + Text, a bare integerlineLimit). - VERIFY. For anything ≤ ~70% confidence (a symbol you're unsure exists, a floor you can't place, a
deprecation you can't date), run both evidence sources. (a) Practice —
bash <swiftui-plugin-root>/scripts/swiftui-ctx lookup <api> --json(andbash <swiftui-plugin-root>/scripts/swiftui-ctx deprecated <api>for txt-01/02): read itsconsensus(the canonical shape),deprecated+replacement,recommendedpermalink,introduced_macos, andco_occurs_with; alookupexit 3 (not-found, with a did-you-meansuggestion) corroborates a txt-09 hallucination — no shipping Mac app uses the symbol. (b) Spec — confirm via Sosumi:curl -sSL https://sosumi.ai/<apple-path>usingreferences/source-directory.mdfor the path and<swiftui-plugin-root>/references/_shared/sosumi-reference.mdfor the protocol (neverWebFetchdeveloper.apple.com). Cross-checkintroduced_macosagainstfloors-master.mdand the Sosumidoc:floor. The CLI contract is<swiftui-plugin-root>/references/_shared/swiftui-ctx-reference.md. Promote with the citation or discard. - REPORT. Write each confirmed finding (output contract below). One finding per file, zero-padded,
ordered. Write the run's
_index.md. - FIX. Apply corrections under the fix-safety protocol
(
<swiftui-plugin-root>/references/_shared/fix-safety-protocol.md): clean-tree gate, findings-first, onlyfix_mode: auto(txt-02 — appendweight: .regular), one conventional commit per finding citing itsrule_id, never weaken a check. The ✅ "Correct" is not a hand-written snippet — it is the swiftui-ctx consensus shape put in## Correct, backed by a real macOS example fetched withbash <swiftui-plugin-root>/scripts/swiftui-ctx file <recommended.id> --smartwhose GitHub permalink (plus the Sosumidoc:) goes in## Source. Leaveflag-onlyfindingsopenwith that ✅. - DOUBLE-CHECK. Re-grep each fixed file to confirm the tell no longer matches; record the evidence in
## Fix applied?. Re-confirm every citation still resolves. If a fix introduced a new tell (e.g. anAttributedStringyou wrote now needs a gate), loop that file back to DETECT.
Confidence gating (load-bearing)
Report a finding only at 100% certainty. Anything ≤ ~70% goes to VERIFY (step 5) before it can become a
finding — never emit a speculative finding. Auto-fix only the mechanical set (txt-02); everything else is
fix_mode: flag-only.
Output contract
Inherits the toolkit's unified contract (full schema + body sections + frontmatter keys:
<swiftui-plugin-root>/references/_shared/finding-schema.md — do not restate it). Specialized for this
domain:
- Findings:
swiftui-audits/typography-text/<context>/NN-slug.md(one finding per file, zero-padded, ordered). Per-run index:swiftui-audits/typography-text/_index.md. domain: typography-text. Frontmatter is the canonical schema;fix_modeisautofor txt-02, elseflag-only.availabilityreads fromfloors-master.md.sourceis an Apple URL + access date (fetched via Sosumi) orverify against Xcode 26 SDK. Emitcross_reffor txt-01/02 (api-currency) and txt-03 (accessibility).
Starter <context> folders (file here when…):
<context> |
File a finding here when… |
|---|---|
text-composition/ |
text is concatenated, an AttributedString is malformed, or an invented type API appears (txt-01, txt-05, txt-09) |
fonts-dynamic-type/ |
the design-only Font.system, a hardcoded size, or jiggling numerics (txt-02, txt-03, txt-08) |
text-layout-rendering/ |
lineLimit reservation, a mis-gated TextRenderer, or a hand-rolled label row (txt-04, txt-06, txt-07) |
New-folder rule: if a finding does not fit any existing context folder, create a new one under
swiftui-audits/typography-text/ with a lowercase-hyphen slug naming the sub-category, and note it in the
run's _index.md. Prefer an existing folder when the fit is reasonable; consistency across runs is a hard
requirement. Two runs over the same code produce structurally identical trees.
Reference routing
| File | Open when |
|---|---|
references/text-composition-and-attributed.md |
composition, AttributedString craft, the Text + Text rewrite, invented type names (txt-01/05/09) |
references/fonts-and-dynamic-type.md |
the design-only Font.system, sizing via text styles / @ScaledMetric, monospaced digits (txt-02/03/08) |
references/text-layout-and-rendering.md |
lineLimit reservation, TextRenderer/textRenderer floors + gating, LabeledContent (txt-04/06/07) |
references/source-directory.md |
step VERIFY — the Apple/WWDC/practitioner source map fetched via Sosumi |
lint/grep-tells.tsv + lint/ast-grep/*.yml |
step LOCATE — this skill's declarative lint rule set fed to the shared runner (tier-1 grep tells + the tier-2 structural Text + Text rule); edit here to tune detection |
Shared toolkit references (point in, never restate):
| Shared file | For |
|---|---|
<swiftui-plugin-root>/references/_shared/floors-master.md |
every floor/availability/deprecation value (the reconciled truth) |
<swiftui-plugin-root>/references/_shared/hallucination-blacklist.md |
the canonical invented-name list (txt-09) |
<swiftui-plugin-root>/references/_shared/macos-arm-gating.md |
the macOS-arm gating rule (txt-06 wrong-arm) |
<swiftui-plugin-root>/references/_shared/finding-schema.md |
the unified finding schema + frontmatter keys |
<swiftui-plugin-root>/references/_shared/fix-safety-protocol.md |
the fix-safety protocol (step 7) |
<swiftui-plugin-root>/references/_shared/sosumi-reference.md |
the Apple-doc spec fetch protocol (step 5 VERIFY) |
<swiftui-plugin-root>/references/_shared/swiftui-ctx-reference.md |
the practice-corpus CLI contract — lookup/deprecated/file --smart for the consensus shape + permalinked example (steps 5 VERIFY · 7 FIX) |
<swiftui-plugin-root>/references/_shared/cross-ref-graph.md |
seam ownership + cross_ref targets (api-currency, localization, accessibility) |
Detection accelerator
bash <swiftui-plugin-root>/scripts/swiftui-lint.sh --skill audit-swiftui-typography-text --dir <files-or-dir> [--json out.json] [--sarif out.sarif] — the toolkit's one shared hybrid lint engine, fed this skill's
declarative rules: tier-1 grep tells (lint/grep-tells.tsv, txt-01…txt-09) + a tier-2 ast-grep
structural rule (lint/ast-grep/txt-01-text-concat.yml — multi-line Text + Text concatenation grep can't
express). It runs a per-file parse probe (surfaces "did not fully parse"), emits unified JSON + SARIF,
exits 2 on any hard-fail (txt-09) for a CI gate, and degrades to grep-only with a notice if ast-grep
is unreachable (npx --package @ast-grep/cli ast-grep; faster: brew install ast-grep). It only LOCATES —
always READ each hit in full before reporting (step 3). The legacy scripts/typography-lint.sh is a thin
pointer to this runner. Engine + rule-file format + JSON/SARIF shape + safety rails:
<swiftui-plugin-root>/references/_shared/lint-architecture.md.
安装
把 Audit Swiftui Typography Text 添加到你的客户端。选择你正在使用的那个。
npx skills add yigitkonur/plugin-swiftuiInstalls every skill in the repository, then prompts for which to keep.
/plugin marketplace add yigitkonur/plugin-swiftuiAdds the repository as a plugin marketplace; install individual plugins with `/plugin install`.
git clone https://github.com/yigitkonur/plugin-swiftui
cp -r plugins/swiftui/skills/audit-swiftui-typography-text ~/.claude/skills/A skill is a plain directory. Copy it into `.claude/skills/` in a project or in your home directory.
评分
75 / 100
良好