Skip to content
MCP ThesaurusMCP Thesaurus

Audit Swiftui Macos Nativeness

CommunityGood70/100Claim

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.

SourceWebsiteDocs1

What can you do with Audit Swiftui Macos Nativeness?


name: audit-swiftui-macos-nativeness description: Audit macOS SwiftUI macos nativeness 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 macOS Nativeness

AUDIT-ONLY Β· macOS-only Β· SwiftUI-only Β· META-AUDIT (score + route, never fix). Run this on a finished or in-progress macOS SwiftUI project to answer one question: "how much does this read like an iPad app dropped into a window?" It emits a 0-100 nativeness score and a prioritized punch-list where every smell is routed to the owner skill that fixes it β€” this skill itself never writes a code fix. Findings are written to disk in the toolkit's unified schema with fix_mode: flag-only; the run index is a kind: nativeness-dashboard.

The Mac is pointer-driven, not touch: it has a cursor, a right mouse button, a Tab-key focus ring, a resizable window, a sortable data grid, a main menu, and a Settings scene. iOS has none of these, so an iOS-trained model emits code that compiles and looks plausible but is missing the entire Mac affordance vocabulary. That gap is what this skill measures.

Boundary / seam note (stay in lane)

This is a router, not a repairer. Every finding here carries a cross_ref to the owner skill; the owner skill holds the βŒβ†’βœ… fix, the floor, and the auto-fix. Do not restate or apply those fixes.

  • Pointer/gesture affordances (onHover, contextMenu, pointerStyle, onContinuousHover, touch-only swipe idioms) β†’ audit-swiftui-pointer-gestures.
  • Control density, formStyle, focusable/@FocusState, help, control styles β†’ audit-swiftui-controls-forms.
  • List-where-Table, content-frame window sizing, controlSize sizing axis β†’ audit-swiftui-layout-and-tables.
  • Scene-level sizing (defaultSize/windowResizability), Settings/MenuBarExtra scenes β†’ audit-swiftui-scenes-windows.
  • Push-stack-as-shell, navigationBarTitle, toolbar placements β†’ audit-swiftui-navigation-toolbars.
  • Menu actions faked as buttons, .commands / CommandMenu β†’ audit-swiftui-menus-commands.
  • Glass chrome is audit-swiftui-liquid-glass's; VoiceOver labels are audit-swiftui-accessibility's β€” this skill notes the seam and routes, never owns it.

Seam ownership + the exact cross_ref targets are in <swiftui-plugin-root>/references/_shared/cross-ref-graph.md (the macos-nativeness row) β€” read it, never restate it.

The one rule

A smell is the absence of a Mac affordance, not the presence of a bad one. Most tells here are "this interactive view has no .onHover", "this Form has no .formStyle(.grouped)", "this app has no Settings {} scene". Grep/ast-grep locate candidate sites; the absence judgment is yours after READ. Never score a smell you have not confirmed by reading the view in full.

Smell index (nat-01 … nat-15)

id Β· one-line tell Β· severity Β· routed owner skill Β· reference. Severities: warning (compiles but non-native), advisory (judgment / density). There are no hard-fails β€” nothing here breaks the build; it breaks the feel. fix_mode is flag-only for every row (this skill routes, never fixes).

id One-line tell (the iPad-in-a-window smell) Sev Route β†’ owner skill Reference
nat-01 custom interactive row/card with no .onHover (no pointer affordance) warn pointer-gestures smell-catalog.md
nat-02 icon-only Button/segment with no .help tooltip warn controls-forms smell-catalog.md
nat-03 custom focus-taking view with no .focusable() / @FocusState (Tab skips it) warn controls-forms smell-catalog.md
nat-04 row/item view with actions but no right-click .contextMenu warn pointer-gestures smell-catalog.md
nat-05 draggable / divider / clickable view with no .pointerStyle cursor adv pointer-gestures smell-catalog.md
nat-06 Form with no .formStyle(.grouped) (macOS default is ungrouped) warn controls-forms smell-catalog.md
nat-07 default control density β€” no .listStyle/.controlSize/.pickerStyle(.menu) (reads oversized) adv controls-forms smell-catalog.md
nat-08 single-column List of structured rows where a sortable Table belongs warn layout-and-tables smell-catalog.md
nat-09 WindowGroup/Window content with no min/ideal/max .frame warn layout-and-tables smell-catalog.md
nat-10 scene with no .defaultSize / .windowResizability warn scenes-windows smell-catalog.md
nat-11 NavigationStack / deprecated NavigationView as the top-level shell (push stack, not a Mac sidebar) warn navigation-toolbars smell-catalog.md
nat-12 navigationBarTitle / navigationBarTitleDisplayMode / navigationBar*/topBar* placements warn navigation-toolbars smell-catalog.md
nat-13 menu actions faked as in-window buttons; no .commands {} main-menu warn menus-commands smell-catalog.md
nat-14 no Settings {} scene / no MenuBarExtra (menu-bar app faked with NSStatusItem) warn menus-commands / scenes-windows smell-catalog.md
nat-15 .swipeActions / swipe-to-delete as the only way to act on a row (touch idiom) adv pointer-gestures smell-catalog.md

The 0-100 score is computed from the confirmed smell set by category weight β€” the rubric, the dashboard layout, and the punch-list ordering are in references/nativeness-scoring.md. The route table

  • how to emit cross_ref + the route-not-fix discipline are in references/routing-map.md.

The real API, at a glance

These are the Mac affordances whose absence is the smell β€” all real on the floors below (the reconciled values live in <swiftui-plugin-root>/references/_shared/floors-master.md; never restated here): onHover (macOS 10.15+), help(_:) (11+), focusable(_:) (12+, not 10.15), contextMenu (10.15+), controlSize (10.15+), formStyle (13.0+), Table (12+), pointerStyle(_:) (15+), onContinuousHover (14+), defaultSize/windowResizability (13+), NavigationSplitView (13+), Settings/SettingsLink (11/14), MenuBarExtra (13+), commands/CommandMenu. The canonical shape of each is fetched live from swiftui-ctx in VERIFY/FIX β€” never hand-assert a signature. The deprecated/iOS-only names you flag (route them) are navigationBarTitle, navigationBarTitleDisplayMode, navigationBarLeading/Trailing, topBarLeading/Trailing (the last two are unavailable on macOS β†’ owner skill confirms the compile error), and NavigationView.

Grounded βœ… affordance (the canonical shape, from real code)

The ## Correct block of a finding shows the owner's route + the swiftui-ctx consensus affordance shape backed by a real macOS-26 example β€” never a hand-written snippet. Worked for nat-01 (onHover), verified live (swiftui-ctx lookup onHover --json β†’ consensus { } at 96%, introduced_macos 10.15; swiftui-ctx file ex_ffa067d89d --smart for the enclosing view):

// βœ… The Mac affordance whose ABSENCE is nat-01 β€” the 96%-consensus closure shape.
// Real macOS-26 site (sindresorhus/Gifski, β˜…8409), an icon Button that highlights on hover:
Button("Toggle Trimmer", systemImage: "chevron.compact.down", action: action)
    .labelStyle(.iconOnly)
    .background(Capsule().fill(.white.opacity(isHovered ? 0.2 : 0.05)))
    .onHover { isHovered = $0 }     // ← the missing piece a custom interactive view needs

The 8-step audit workflow (execute verbatim)

  1. ORIENT. tree / find the SwiftUI sources. Read the deployment target (project.pbxproj MACOSX_DEPLOYMENT_TARGET or Package.swift platforms:) β€” it bounds which affordances are even available to expect (pointerStyle only β‰₯15, onContinuousHover only β‰₯14). Find the @main App scene body: it anchors nat-09/10/11/13/14.
  2. LOCATE. Run the shared hybrid lint runner: bash <swiftui-plugin-root>/scripts/swiftui-lint.sh --skill audit-swiftui-macos-nativeness --dir <sources> --json /tmp/nat.json --sarif /tmp/nat.sarif. It runs this skill's tier-1 grep tells (lint/grep-tells.tsv) + tier-2 ast-grep structural rules (lint/ast-grep/*.yml β€” icon-button-no-help, stack-as-shell), a per-file parse probe, and emits unified JSON + SARIF. Read parse_warnings β€” a file that didn't fully parse must be READ by hand. The runner only LOCATES candidate sites; presence-of-an-idiom or presence-of-an-interactive -view is never itself a finding. Engine + rule format: <swiftui-plugin-root>/references/_shared/lint-architecture.md.
  3. READ. Open every located file in full. The smell is an absence (no .onHover, no .formStyle, no Settings scene) β€” invisible to grep, decidable only by reading the whole view + the App body. Build a per-view inventory: each interactive view + which Mac affordances it carries and which it lacks.
  4. DETECT. Apply the index. A smell counts only at 100% certainty that the affordance is truly absent and the floor supports it (e.g. don't flag missing pointerStyle under a macOS-14 floor). Assign each its category for scoring.
  5. VERIFY. For any affordance whose existence/shape/floor you are < ~100% sure of, run both evidence sources. (a) Practice β€” bash <swiftui-plugin-root>/scripts/swiftui-ctx lookup <api> --json: read its consensus (the canonical shape), introduced_macos, recommended permalink, and co_occurs_with; for a deprecation route (nat-11/12) also swiftui-ctx deprecated <api>. A lookup exit 3 means the symbol you expected is not real. (b) Spec β€” confirm the floor via Sosumi: curl -sSL https://sosumi.ai/<apple-path> per references/source-directory.md and <swiftui-plugin-root>/references/_shared/sosumi-reference.md (never WebFetch developer.apple.com). Cross-check introduced_macos against floors-master.md. The CLI contract is <swiftui-plugin-root>/references/_shared/swiftui-ctx-reference.md. Deeper corpus evidence (benchmark the score): anchor the 0-100 to the real-Mac-app baseline β€” bash <swiftui-plugin-root>/scripts/swiftui-ctx stats --json (.result.modern_stack) + bash <swiftui-plugin-root>/scripts/swiftui-ctx insights modern-stack --json (.result.data = modern_stack_adoption_pct) + bash <swiftui-plugin-root>/scripts/swiftui-ctx rankings most_modern_stack --json. Over 1,857 shipping repos, adoption is @Observable 23.4%, NavigationStack/SplitView 41%, Settings scene 30.1%, MenuBarExtra 21.6% β€” phrase findings as "real apps adopt X at N%; this app M%", and use rankings most_modern_stack (e.g. 0xCUB3/wBlock, 205 unique APIs) as the top-decile exemplar.
  6. SCORE + REPORT. Compute the 0-100 nativeness score (references/nativeness-scoring.md). Write each confirmed smell as a finding (output contract below), one per file, with its cross_ref to the owner skill. Write the run's _index.md as the nativeness dashboard (kind: nativeness-dashboard): the score, the per-category breakdown, and the prioritized punch-list.
  7. ROUTE (this skill's "FIX"). This skill is fix_mode: flag-only for every smell β€” it applies no code change. The ## Correct of each finding is not a fix here; it is (a) a one-line "run <owner-skill> to fix this" route, and (b) the swiftui-ctx consensus shape as the canonical βœ… affordance, backed by a real macOS-26 example fetched with bash <swiftui-plugin-root>/scripts/swiftui-ctx file <recommended.id> --smart whose GitHub permalink goes in ## Source. The fix-safety protocol (<swiftui-plugin-root>/references/_shared/fix-safety-protocol.md) still governs: since nothing is fix_mode: auto, no commit is made by this skill β€” it hands off.
  8. DOUBLE-CHECK. Re-confirm each finding's cross_ref names a valid sibling slug (per cross-ref-graph.md) and the routed owner actually owns that fix (no double-ownership). Re-confirm every floor citation still resolves. Recompute the score from the final finding set so the dashboard total equals the sum of its parts.

Confidence gating (load-bearing)

Score a smell only at 100% certainty the affordance is absent and in-floor. Anything less goes to VERIFY (step 5) first. This skill never auto-fixes (fix_mode: flag-only everywhere) β€” it routes.

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:

  • Findings: swiftui-audits/macos-nativeness/<context>/NN-slug.md (one per file, zero-padded, ordered).
  • Run index: swiftui-audits/macos-nativeness/_index.md with kind: nativeness-dashboard (the score + category breakdown + prioritized punch-list β€” layout in references/nativeness-scoring.md).
  • domain: macos-nativeness. fix_mode: flag-only on every finding. Every finding carries a cross_ref to its owner skill (status: open, never fixed by this skill). availability reads from floors-master.md. source is an Apple URL via Sosumi or verify against Xcode 26 SDK.

Starter <context> folders (file here when…):

<context> File a smell here when…
pointer-affordances/ missing onHover/contextMenu/pointerStyle, or a touch-only swipe idiom (nat-01, nat-04, nat-05, nat-15)
control-density-forms/ missing help/focusable, ungrouped Form, or iOS control density (nat-02, nat-03, nat-06, nat-07)
data-grid-windows/ a List-where-Table, or content-frame/scene window sizing is absent (nat-08, nat-09, nat-10)
navigation-shell/ a push stack used as the shell, or stale navigationBar* API (nat-11, nat-12)
menus-scenes/ menu actions faked as buttons, or a missing Settings/MenuBarExtra scene (nat-13, nat-14)

New-folder rule: if a smell does not fit an existing context folder, create a new lowercase-hyphen folder under swiftui-audits/macos-nativeness/ and note it in the run's _index.md. Prefer an existing folder when the fit is reasonable; two runs over the same code produce structurally identical trees.

Reference routing

File Open when
references/smell-catalog.md the per-smell depth β€” the iPad-in-a-window tell, why AI emits it, the absence-detection method (nat-01 … nat-15)
references/nativeness-scoring.md step SCORE+REPORT β€” the 0-100 rubric, category weights, the nativeness-dashboard layout, punch-list ordering
references/routing-map.md step ROUTE β€” smell β†’ owner-skill table, how to emit cross_ref, the route-not-fix discipline
references/source-directory.md step VERIFY β€” the Apple/WWDC source map fetched via Sosumi
lint/grep-tells.tsv + lint/ast-grep/*.yml (nat-02-icon-button-no-help.yml, nat-11-stack-as-shell.yml) step LOCATE β€” this skill's declarative rule set fed to the shared runner (tier-1 grep + tier-2 structural); 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 value (the reconciled truth)
<swiftui-plugin-root>/references/_shared/macos-arm-gating.md the macOS-arm gating rule when an affordance needs a floor gate
<swiftui-plugin-root>/references/_shared/hallucination-blacklist.md the canonical invented-name list
<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 β€” here only the no-auto-fix / hand-off clause)
<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 affordance shape + permalink (steps 5 VERIFY Β· 7 ROUTE)
<swiftui-plugin-root>/references/_shared/cross-ref-graph.md the macos-nativeness seam row + every cross_ref target (this skill's whole output is routes)

Detection accelerator

bash <swiftui-plugin-root>/scripts/swiftui-lint.sh --skill audit-swiftui-macos-nativeness --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 β€” the stale-API and touch-idiom presence tells + the interactive-primitive locators nat-01…nat-15) + tier-2 ast-grep structural rules (lint/ast-grep/*.yml β€” nat-02 icon-button-no-help co-occurrence-absence, nat-11 push-stack nested directly in WindowGroup) that grep cannot express. Most nat- tells are absence of an affordance*, which neither grep nor ast-grep can decide β€” the runner only locates candidate sites; the absence judgment is the LLM's after READ (step 3). It runs a per-file parse probe, emits unified JSON + SARIF, exits 0 (no hard-fail rules β€” nativeness breaks feel, not the build), and degrades to grep-only with a notice if ast-grep is unreachable. The thin scripts/nativeness-lint.sh is a pointer to this runner. Engine + rule-file format + JSON/SARIF shape: <swiftui-plugin-root>/references/_shared/lint-architecture.md.