linguistics — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited linguistics (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
Treat every name or visible string as a small language artifact. Its form carries a contract: morphology makes the artifact parseable, semantics fixes what it means, pragmatics fits the situation, and register fits the audience.
This skill replaces taste-based naming and copy decisions with repeatable linguistic checks. It prevents weak contracts such as generic handlers, unqualified polysemous identifiers, utility-file dumping grounds, agent-register UI copy, blame-heavy errors, and culturally narrow language that does not translate cleanly.
Distinct from naming-conventions, which owns artifact-specific casing and deterministic convention policy. Distinct from refactor, which owns behavior-preserving rename mechanics across call sites. Distinct from information-architecture, which owns document, navigation, and content-structure findability. Distinct from microcopy, which owns specialized UI-text pattern catalogs. Distinct from writing-humanizer, which owns prose polish, AI-tell removal, and rhythm repair. Linguistics in software is grammar for the interface between people and systems: the syntax of a name or sentence should make the intended meaning easy to recover without hidden context. The common mistake is treating naming and wording as personal preference. Ambiguous words, weak compounds, blame-heavy error text, and wrong register create predictable comprehension failures; agreement inside one team does not make the language portable or clear.
Linguistic analysis patterns for software work — the rules that govern how names, labels, error messages, and copy are formed. Covers (1) morphology: casing conventions per artifact kind, compound-word head-first ordering, abbreviation decision tree, verb-noun naming patterns; (2) polysemy resolution: identifying ambiguous identifiers in a codebase and qualifying them with their domain (e.g., provider → fulfillmentProvider / authProvider / paymentProvider); (3) register selection: choosing the right tone, vocabulary, and sentence structure for end-users, agents, and developers; (4) error-message linguistics: the three-part What → Why → What-to-do structure with blame-free framing, specificity rules, and actionability; and (5) cross-cultural linguistic awareness: the linguistic facts (number structure, currency notation, grammatical gender, script direction) that shape internationalization decisions. Provides the linguistic rationale for these choices — not the casing convention itself, not document/navigation structure, not specialized UI microcopy pattern catalogs, not final prose polish, not canonical term definition, and not i18n implementation.
Language in software is architecture. A function named handleContinue can do anything from persisting form state to advancing a wizard — it carries a weak contract outside its local component. A function named transformPaymentEvent is much harder to misunderstand. An error message that says "Error 500" transfers zero information; one that says "Order sync paused — your API key may have expired. Open Settings → Integrations to reconnect." transfers a complete causal chain plus an action. The same word can carry different meanings in different parts of the same codebase, and without disambiguation every reader must infer the meaning from surrounding context — that inference has a cost, and sometimes a failure mode.
Three linguistic laws follow:
The linguistic goal is to make meaning unambiguous at the point of contact — in the name itself, the message itself, the label itself — not in a glossary entry the reader has to look up.
| Trigger | Use this skill? | Route |
|---|---|---|
| Choosing the meaning-bearing words in an identifier, label, error, or agent-facing sentence | Yes | Apply morphology, polysemy, register, and blame-free language checks here. |
| Choosing kebab-case vs camelCase vs snake_case or project-wide artifact naming convention | No | Use naming-conventions; return here only for semantic ambiguity or abbreviation judgment. |
| Renaming a symbol across call sites or preserving behavior through a structural rename | No | Use refactor; this skill may supply the target name but not the mechanics. |
| Structuring docs, navigation, page hierarchy, sitemap, or content grouping | No | Use information-architecture; this skill only audits wording inside the structure. |
| Choosing a specialized button, empty-state, tooltip, dialog, or toast text pattern | Usually no | Use microcopy; return here for register, blame, ambiguity, or cross-cultural language concerns. |
| Removing AI tells, improving prose rhythm, or polishing a release note/PR/doc paragraph | No | Use writing-humanizer; return here when the question is linguistic correctness rather than prose finish. |
| Implementing locale-aware number/date/currency/plural behavior | No | Use the project i18n tooling and platform docs; this skill explains the language risk, not the implementation. |
Morphology is the study of word form — how words are built from parts. In code, the "words" are identifiers, and the "morphology rules" are casing conventions, compounding strategies, and abbreviation policies.
| Convention | Typical Use | Linguistic Reason |
|---|---|---|
camelCase | Variables, function names in many languages | Each morpheme boundary is marked by capitalization; reads as one compound word |
PascalCase | Types, classes, components | Same compound logic, but signals "noun/thing" rather than "action/value" |
kebab-case | File names, CSS classes, URL paths | Human-readable in filesystem and URL contexts where case is often flattened |
snake_case | Database columns, Python identifiers | Separator makes each morpheme explicit; SQL is case-insensitive so underscores are the only safe delimiter |
SCREAMING_SNAKE | Constants, enums, environment variables | All-caps signals immutability; snake separators keep it readable |
Rule: match the convention to the artifact-kind context, never cross-pollinate. orderCount in TypeScript, order_count in SQL, order-count in CSS. They are the same concept expressed in three linguistic registers. The casing decision itself belongs to naming-conventions; this skill explains why each convention fits its context.
Compound words carry more semantic load than simple words. The order of morphemes matters.
Head-first vs. modifier-first:
In English technical compounds, the modifier comes first and the head (the main concept) comes last. The head tells you what kind of thing it is; the modifier qualifies it.
| Compound | Head | Modifier | Reads as |
|---|---|---|---|
shippingCost | cost | shipping | "a cost, specifically for shipping" |
orderCount | count | order | "a count, specifically of orders" |
fulfillmentProvider | provider | fulfillment | "a provider, specifically for fulfillment" |
Anti-pattern: reversing the order (costShipping, countOrders) breaks English morphology and makes names harder to scan. The mind expects the head at the end.
Disambiguation through compounding:
When a simple word is ambiguous, compound it with its domain qualifier:
| Ambiguous | Qualified | Domain |
|---|---|---|
shipping | shippingCostCents | Outbound cost paid by the seller |
shipping | shippingChargedCents | Amount charged to the customer |
provider | fulfillmentProvider | Fulfillment partner |
provider | authProvider | Authentication identity provider |
provider | paymentProvider | Payment processor |
cost | productionCostCents | Production / fulfillment cost |
cost | subscriptionCost | Plan pricing |
cost | tokenCostUsd | Inference / API cost |
Rule: if a word has more than one meaning anywhere in the codebase, compound it with its domain qualifier. The unqualified form is banned in typed code.
Abbreviations save characters but cost comprehension. Use this decision tree:
Is this abbreviation universally understood by every reader?
├── Yes → Allow (examples: URL, API, DB, ID, HTML, CSS, JSON, HTTP, SKU)
└── No → Is the full form longer than 25 characters?
├── No → Use the full form
└── Yes → Is the abbreviation used in 10+ places?
├── No → Use the full form, consider renaming the concept
└── Yes → Define the abbreviation in the project glossary, then allow itAlways acceptable: id, url, api, db, html, css, json, http, sku, ui, ux, pii, gdpr.
Never acceptable: mgr (manager), proc (process or procedure?), calc (just write calculate), btn (button), val (validate or value?), auth without qualifier (authentication or authorization?), temp (temporary or temperature?), util (a red flag — see anti-patterns).
Functions describe actions (verbs). Variables describe things (nouns). Mixing the patterns creates naming smells.
Function naming — verb-first:
| Verb | When to use | Example |
|---|---|---|
get | Retrieval from a source, may be async | getOrders, getOrderById |
fetch | Specifically async network call | fetchExternalOrders |
load | Load into memory/state from a slower source | loadDashboardData |
validate | Check correctness, return boolean or throw | validateWebhookPayload |
parse | Convert raw input into typed output | parseConnectionString |
transform | Convert one structured form to another | transformPaymentEvent |
convert | Change units or formats, same semantic content | convertCentsToDisplayAmount |
calculate | Derive a computed value | calculateNetMargin |
create | Instantiate and persist | createPlatformConnection |
update | Modify existing entity | updateOrderStatus |
delete / remove | Destructive operations | deleteAccount, removeLineItem |
handle | Entry point for events/webhooks (and nothing else) | handleIncomingWebhook |
process | Multi-step pipeline execution | processVerifiedWebhook |
extract | Pull a subset from a larger structure | extractOrderPii |
format | Produce a display string | formatCurrencyDisplay |
build | Assemble a complex object | buildCanonicalOrder |
Anti-pattern: using handle for everything in server-side or utility code. handleSync tells you the entry point. It does not tell you whether it validates, transforms, persists, or retries. Name the operation, not the trigger.
Exception — UI event handlers: in component files (e.g., React .tsx), handle* is the established convention for DOM event callbacks (handleSubmit, handleChange, handleClose). These are scoped to the component and the "event being handled" is self-evident from the UI context. The anti-pattern label applies to backend / service / utility functions where the operation ambiguity is real.
Variable naming — noun-first:
| Pattern | Example | Why | |
|---|---|---|---|
Boolean: is + adjective | isValid, isActive, isReconciled | Reads as a question in conditions: if (isValid) | |
Boolean: has + noun | hasConnection, hasFinancialData | "Does X have Y?" — confirms presence | |
Boolean: can + verb | canExportOrders, canEditPricing | Permission check — "is X allowed to do Y?" | |
Count: noun + Count | orderCount, lineItemCount | Disambiguates from the collection | |
| Collection: plural noun | orders, lineItems, errors | Plural form signals collection; no List, Array, Set suffix | |
| Nullability | Express via the type system, not the name | Use `T | null, not *OrNull` suffixes |
| Currency-as-integer | noun + Cents (or unit suffix) | Mandatory for any financial integer; never store money as a float |
Polysemy is when one word carries multiple meanings. In natural language, surrounding context resolves the ambiguity automatically. In code and documentation, context is often missing — and the resolution cost falls on every reader.
These words are commonly polysemous in software. The unqualified form should not appear in typed code; always use the qualified form.
| Ambiguous term | Context A | Context B | Context C | Qualified forms |
|---|---|---|---|---|
| margin | Finance: profit as % of revenue | CSS: spacing property | Domain-typical range (industry-specific) | marginPercent (finance), CSS property (leave as-is in stylesheet) |
| shipping | Cost paid by the seller to a carrier | Amount charged to the customer on invoice | The carrier itself | shippingCostCents, shippingChargedCents, carrierName |
| provider | Fulfillment partner | Authentication identity provider | Payment processor | fulfillmentProvider, authProvider, paymentProvider |
| cost | Production / fulfillment cost | Subscription plan pricing | Inference / API token spend | productionCostCents, subscriptionPriceCents, tokenCostUsd |
| sync | Data import from an external platform | URL ↔ UI state coordination | Inter-process / inter-agent coordination | platformSync, stateSync, agentSync |
| channel | Sales platform | Alert delivery medium | Chat-platform channel | salesChannel, alertChannel, chatChannel |
| source | Data origin (which platform) | Source code file | Content source | dataSource, sourceFile, contentSource |
| status | Order status (pending / shipped) | Fulfillment status (in production) | Task status (in progress / done) | orderStatus, fulfillmentStatus, taskStatus |
| connection | Platform integration (a third-party connected) | Database connection pool | WebSocket connection | platformConnection, dbConnection, wsConnection |
| confidence | Data completeness score (0–100) | Statistical probability | Colloquial certainty | dataConfidenceScore, keep confidence in statistical contexts |
When you encounter an ambiguous term:
Code naming rule: the qualified form goes into the identifier. No fallback to context inference.
// Wrong — "shipping" is ambiguous
const shipping = order.shipping_cost + order.shipping_charged;
// Right — each concept is named precisely
const shippingCostCents = order.shipping_cost_cents; // seller pays this
const shippingChargedCents = order.shipping_charged_cents; // customer pays thisDocumentation rule: the first occurrence of an ambiguous term in any doc must be qualified. Subsequent occurrences may use the short form only if the surrounding context is unambiguous.
Register is the level of formality and technicality appropriate for a given audience and context. The same fact requires different register for an end-user, an agent, and a developer. Writing in the wrong register is a communication failure even when the content is accurate.
| Audience | Context | Register | Character | Example |
|---|---|---|---|---|
| End-user | UI copy, tooltips, empty states, error messages | Warm, plain, action-oriented | A knowledgeable friend who respects the user's time and intelligence | "Connect your fulfillment partner to see your real production cost per order." |
| End-user | Onboarding | Confident, step-by-step, time-honest | A setup guide written by someone who has done this a hundred times | "Step 2 of 5: Link your storefront. Takes about 2 minutes." |
| Agent | Skill / capability files | Dense, precise, reference-heavy | A technical spec from a colleague who assumes domain knowledge | "Use fulfillmentProvider, never unqualified provider. Three distinct meanings exist." |
| Agent | Structured logs | Diagnostic, no hedging | A structured log entry | [WEBHOOK_FAILED] order_id=12345 reason=hmac_mismatch retry=true |
| Developer | Code comments | Concise, rationale-focused, explains why | A note from the author who knows the reader is technical | // Using the org-scoped query — must stay tenant-scoped (ABC-123) |
| Developer | Architecture decision records | Formal, decision-focused, versioned | An architectural decision record | "Decision: use COALESCE(EXCLUDED.col, existing.col) to prevent null overwrites on upsert." |
| Developer | PR descriptions | Technical, factual, testable | A clear brief for a code reviewer | "Adds HMAC verification to platform webhooks. Test: curl the endpoint without the signature header — expect 401." |
The end-user register has the tightest constraints because it directly affects user trust and conversion.
Vocabulary:
canonical, reconciliation (say "matched" instead), backfill (say "importing past data").Sentence structure:
Tone:
Agent-facing docs prioritize density and parsability over warmth.
Structure:
Vocabulary:
src/lib/payment/processor.ts), not "the payment processor".cardComponent.tsx line 42" not "this is the pattern used".Developer-facing content (code comments, ADRs, PR descriptions) lives closer to the code and prioritizes rationale.
Code comments:
// must use the tenant-scoped query — raw query() leaks across tenants (ABC-123) not // using tenant-scoped query here.// COALESCE prevents null overwrite on re-webhook — partner has a 30-day deletion window.(ABC-123) in comments that address a known bug or decision.PR descriptions:
Implementation details for currency formatting, date locale rules, and number systems belong to a separate i18n skill. This section covers only the linguistic awareness that shapes those decisions: different languages have fundamentally different number structures, grammatical gender, and script directions.
Key linguistic facts that affect i18n decisions:
1,234.56); many European locales reverse them (1.234,56). This is not a formatting preference — it changes how numbers are read. A developer writing number logic must know the linguistic reason for the locale parameter, not just its mechanical effect.$ signals USD to a US reader; € signals EUR. Bare numbers without currency symbols are linguistically incomplete — they transfer a quantity but not a unit. Always qualify with the currency code or symbol.When the maintainer is bilingual, all code-facing surfaces must be in the project's chosen language:
| Domain | Rule | Reason |
|---|---|---|
| Code identifiers | Project language only | Global readability; future contributors may not read the operator's native language |
| UI copy | Audience language only | The product speaks the audience's language |
| Internal docs (skill files, ADRs) | Project language only | Agent-readable docs must be in a single language |
| Commit messages | Project language only | Conventional-commit type/scope terms are typically English |
| Code comments | Project language only | Agents and developers across regions read these |
| Personal notes (private) | Operator's native language acceptable | Private communication between operator and operator-only tools |
| Business term references | Qualify if a non-project-language term is used | Proper nouns (carrier names, regulatory terms) are acceptable as borrowed words |
Anti-pattern: business concepts from the operator's native language slipping into code as abbreviations. If a word in the operator's language collides with a different meaning in the project language, the abbreviation is unsafe even when the operator finds it natural.
Error messages are the most linguistically precise text in any software product. They arrive at the worst moment for the reader (something went wrong) and must deliver maximum information in minimum words.
Every error message must answer three questions in order:
| Pattern | Example |
|---|---|
| What → Why → What to do | "Order sync paused — your API key expired. Open Settings → Integrations to reconnect." |
| What → What to do (cause unknown) | "Couldn't load your orders. Try refreshing. If this continues, check your storefront connection." |
| What (system message, no user action) | "Webhook received but could not be verified. The payload was rejected." |
| Blame-assigning (wrong) | Blame-free (right) | Why |
|---|---|---|
| "You entered the wrong API key." | "We couldn't verify your API key." | Passive construction removes blame; "verify" names the operation |
| "Invalid input." | "This field requires a number between 1 and 100." | Describe what's needed, not what was wrong |
| "You haven't connected the fulfillment partner yet." | "Connect your fulfillment partner to see your production cost." | Positive framing — lead with the outcome |
| "Your sync failed." | "Sync paused — we'll retry automatically in 5 minutes." | "Your sync failing" reads as the user's fault; "sync paused" is a system state |
Rule: never use "you" in a negative construction. "You haven't…", "You entered…", "Your connection failed…" all assign blame. Reframe to a system state or a missing action.
| Too vague | Specific | Why |
|---|---|---|
| "Something went wrong." | "Order sync failed — the API returned a 429 (rate limit). Retrying in 60 seconds." | Names the operation, the error code, and the recovery |
| "Error loading data." | "Couldn't load orders for the last 30 days. Your storefront connection may have expired." | Names the data type, time range, and probable cause |
| "Action failed." | "Couldn't archive order #1247 — it's currently in fulfillment." | Names the order, the operation, and the blocking state |
Include the entity name when the error involves a specific record, connection, or resource. order #1247 beats "an order"; your store "my-shop" beats "your store".
Every error that requires user action must end with a specific next step:
| Error type | Actionable ending |
|---|---|
| Connection expired | "Open Settings → Integrations to reconnect." |
| Missing source data | "Connect your fulfillment partner to see your production cost." |
| Sync paused | "We'll retry in 5 minutes. Or reconnect now in Settings → Integrations." |
| Rate limit hit | "We're retrying automatically. No action needed." |
| Unknown error | "Refresh the page, or check your connection in Settings." |
Never end with a bare error. If the error is purely informational (system log, agent message), mark it explicitly as informational so the reader knows no action is needed.
| Anti-pattern | Example | Why it fails | Correct pattern |
|---|---|---|---|
| Generic verb names | handleContinue(), handleRefresh(), handleExport() in non-UI code | Carries too little semantic load once you leave the local UI context | Name the operation and its subject: transformPaymentEvent(), validateWebhookPayload() |
| Unqualified polysemous terms | provider, shipping, cost, margin in typed code | Ambiguous — requires context to resolve | Always compound with domain: fulfillmentProvider, shippingCostCents, productionCostCents, marginPercent |
| Register mismatch | "COGS null — display —" in an end-user tooltip | Agent register in an end-user context | "Cost data not yet available for this order." |
| Blame-assigning errors | "You haven't connected your storefront yet." | Assigns blame; creates friction | "Connect your storefront to start tracking revenue." |
| Abbreviation overload | calcMgrSvcUtil() | Three unrecognized abbreviations; zero parsability | calculateManagedServiceUtilization() (or rename the concept) |
| False precision in i18n | $${(cents / 100).toFixed(2)} | Hardcoded USD symbol, no locale, bypasses any shared formatter | Use the project's currency formatter or Intl.NumberFormat(...) |
| Vague error messages | "Error 500. Please try again." | Names neither the operation nor the cause | "Sync failed. We'll retry automatically — check Settings if this persists." |
| Implicit null = zero | Display $0.00 when the cost field is null | Null means unknown; zero means confirmed zero. $0.00 cost implies 100% margin | Display — or "Cost unknown" when null |
| Utility file names | utils.ts, helpers.ts, misc.ts | Non-names that aggregate unrelated functionality | Name by domain: orderCalculations.ts, webhookValidation.ts, currencyFormatting.ts |
Before committing code, writing documentation, or shipping UI copy, run through this checklist.
LINGUISTICS NAMING CHECK
========================
[ ] Every function is verb-first with a specific subject (not handle/do/process/get alone in non-UI code)
[ ] Every variable is noun-first with qualifiers for counts, booleans, and financial values
[ ] No unqualified polysemous terms in typed code: provider, shipping, cost, margin, sync, channel, source, status
[ ] Financial values end in Cents (or specify currency in the name) and are stored as integers
[ ] Abbreviations are universally understood or defined in the project glossary
[ ] File names describe what the file does, not which workflow it belongs to
[ ] No utils.ts, helpers.ts, misc.ts — name by domainLINGUISTICS COPY CHECK
======================
[ ] Error messages follow What → Why → What to do structure
[ ] No blame-assigning language ("you entered", "you haven't", "your error")
[ ] Specific entity names included when a specific record/connection is involved
[ ] Every error that requires action has a specific next step
[ ] Register matches the audience (end-user: warm + plain; agent: dense + precise; developer: rationale-focused)
[ ] No agent-register terms in end-user copy (canonical, reconciliation, backfill, orchestration)
[ ] Financial terms match the project glossary definitionsLINGUISTICS I18N CHECK
======================
[ ] All code identifiers are in the project's chosen language
[ ] No business concepts from the operator's native language slipping into code abbreviations
[ ] UI copy targets the audience's language and conventions, not the operator's
[ ] Null financial values display as — or "unknown", never as $0.00 (null ≠ zero)
[ ] Currency symbol or code is always present — bare numbers without units are linguistically incomplete
[ ] Implementation details (Intl.NumberFormat, date locale, plural handling) are deferred to project i18n tooling or platform docs| Instead, use | Why |
|---|---|
naming-conventions | Deciding artifact casing or deterministic convention policy such as kebab-case, camelCase, snake_case, boolean prefixes, or env-var casing. Linguistics owns meaning, ambiguity, morphology rationale, and register. |
refactor | Renaming a thing across many call sites or restructuring code without behavior change. Refactor owns the mechanics; linguistics can supply the target wording. |
information-architecture | Choosing docs architecture, navigation, page hierarchy, sitemap shape, or content grouping. IA owns structure; linguistics owns wording inside a structure. |
microcopy | Selecting specialized UI text patterns for buttons, empty states, tooltips, dialogs, or toasts. Microcopy owns the pattern catalog; linguistics verifies ambiguity, register, and blame-free wording. |
writing-humanizer | Polishing prose, removing AI tells, varying rhythm, or making a draft sound less robotic while preserving truth. |
code-review | Judging a specific PR or change for correctness, security, tests, or maintainability. Code review may call this skill for naming/copy findings. |
| A glossary or domain-modeling source | Defining the canonical meaning of a domain term. Linguistics applies definitions consistently in names and copy; it does not establish the domain ontology. |
| Project i18n tooling or locale docs | Implementing Intl.NumberFormat, date pickers, ICU plurals, string extraction, bidirectional layout, or locale fallback. Linguistics explains the language risk behind those decisions. |
<!-- skill-graph-context:start (generated — do not edit by hand) -->
Classification
knowledge-organizationtruefoundations/languagenaming-conventions), call-site-wide renames (use refactor), docs/navigation structure (use information-architecture), specialized UI text pattern catalogs (use microcopy), or final prose humanization (use writing-humanizer).When to use
Not for
Related skills
code-review, naming-conventions, writing-humanizerprompt-craft, intent-recognition, semantics, writing-humanizer, microcopy, code-review, naming-conventions, refactor, information-architectureConcept
Grounding
universalhttps://developers.google.com/style/voice, https://developers.google.com/style/tone, https://developers.google.com/style/translation, https://learn.microsoft.com/en-us/windows/apps/design/style/writing-style, https://learn.microsoft.com/en-us/windows/win32/debug/error-message-guidelines, https://www.w3.org/TR/WCAG22/, https://www.nngroup.com/articles/ten-usability-heuristics/, https://www.nngroup.com/articles/hostile-error-messages/Keywords
linguistic precision, software linguistics, identifier morphology, polysemy resolution, register selection, audience register, blame-free error wording, compound-word ordering, abbreviation policy, semantic naming<!-- skill-graph-context:end -->
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.