website-build-skill 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (109) hide show
  1. package/.claude-plugin/marketplace.json +12 -0
  2. package/.claude-plugin/plugin.json +10 -0
  3. package/AGENTS.md +19 -0
  4. package/CHANGELOG.md +42 -0
  5. package/CLAUDE.md +16 -0
  6. package/CODE_OF_CONDUCT.md +127 -0
  7. package/CONTRIBUTING.md +49 -0
  8. package/LICENSE +21 -0
  9. package/MAINTAINERS.md +12 -0
  10. package/README.md +148 -0
  11. package/RELEASING.md +133 -0
  12. package/REPO_SETTINGS.md +91 -0
  13. package/SECURITY.md +28 -0
  14. package/adapters/agents-md.md +26 -0
  15. package/adapters/antigravity.md +68 -0
  16. package/adapters/chatgpt-project.md +57 -0
  17. package/adapters/claude-code.md +25 -0
  18. package/adapters/claude-desktop.md +33 -0
  19. package/adapters/codex.md +21 -0
  20. package/adapters/custom-gpt.md +57 -0
  21. package/adapters/grok.md +100 -0
  22. package/adapters/hermes.md +49 -0
  23. package/adapters/team.yaml +42 -0
  24. package/adapters/zero-install.md +17 -0
  25. package/bin/website-build-skill.mjs +6 -0
  26. package/docs/COMPATIBILITY.md +34 -0
  27. package/docs/EVALUATION.md +109 -0
  28. package/docs/INSTALLER.md +73 -0
  29. package/docs/LIBRARY-CHECK.md +95 -0
  30. package/docs/METHOD.md +32 -0
  31. package/docs/PROVENANCE.md +36 -0
  32. package/docs/TIPS.md +18 -0
  33. package/docs/bundles/checklists.md +414 -0
  34. package/docs/bundles/method.md +1398 -0
  35. package/docs/bundles/playbooks.md +1566 -0
  36. package/docs/bundles/prompts.md +987 -0
  37. package/docs/bundles/team.md +1781 -0
  38. package/docs/evaluation/host-trial.md +95 -0
  39. package/docs/evaluation/receipt-template.json +18 -0
  40. package/docs/evidence/audit-baseline.json +61 -0
  41. package/docs/evidence/content-review.json +141 -0
  42. package/docs/evidence/floor.json +345 -0
  43. package/docs/evidence/library-check.json +164 -0
  44. package/docs/evidence/local-checks.json +156 -0
  45. package/llms.txt +74 -0
  46. package/package.json +68 -0
  47. package/skills/website-build-skill/SKILL.md +124 -0
  48. package/skills/website-build-skill/archive/graphics-design-original.md +70 -0
  49. package/skills/website-build-skill/checklists/accessibility.md +38 -0
  50. package/skills/website-build-skill/checklists/brand-and-mockups.md +43 -0
  51. package/skills/website-build-skill/checklists/build.md +39 -0
  52. package/skills/website-build-skill/checklists/performance-seo.md +40 -0
  53. package/skills/website-build-skill/checklists/research.md +91 -0
  54. package/skills/website-build-skill/checklists/security.md +38 -0
  55. package/skills/website-build-skill/checklists/ship.md +59 -0
  56. package/skills/website-build-skill/examples/audit-cases.md +66 -0
  57. package/skills/website-build-skill/examples/fictional-studio-brief.md +73 -0
  58. package/skills/website-build-skill/examples/fictional-studio-handoff.md +98 -0
  59. package/skills/website-build-skill/manifest.json +1474 -0
  60. package/skills/website-build-skill/playbooks/accessibility.md +91 -0
  61. package/skills/website-build-skill/playbooks/choose-stack.md +69 -0
  62. package/skills/website-build-skill/playbooks/data-and-templates.md +89 -0
  63. package/skills/website-build-skill/playbooks/deploy-and-operate.md +87 -0
  64. package/skills/website-build-skill/playbooks/embed-facades.md +59 -0
  65. package/skills/website-build-skill/playbooks/image-pipeline.md +73 -0
  66. package/skills/website-build-skill/playbooks/performance-budgets.md +76 -0
  67. package/skills/website-build-skill/playbooks/research-and-memory.md +398 -0
  68. package/skills/website-build-skill/playbooks/security-headers.md +132 -0
  69. package/skills/website-build-skill/playbooks/self-hosted-fonts.md +62 -0
  70. package/skills/website-build-skill/playbooks/structured-data-and-llms.md +84 -0
  71. package/skills/website-build-skill/prompts/00-start.md +94 -0
  72. package/skills/website-build-skill/prompts/01-website-deep-research.md +233 -0
  73. package/skills/website-build-skill/prompts/03-extract-brand-kit.md +46 -0
  74. package/skills/website-build-skill/prompts/04-three-mockups.md +44 -0
  75. package/skills/website-build-skill/prompts/05-stack-and-build.md +46 -0
  76. package/skills/website-build-skill/prompts/06-site-audit.md +39 -0
  77. package/skills/website-build-skill/prompts/07-accessibility-contrast.md +38 -0
  78. package/skills/website-build-skill/prompts/08-seo-aeo.md +72 -0
  79. package/skills/website-build-skill/prompts/09-security-headers.md +40 -0
  80. package/skills/website-build-skill/prompts/10-adversarial-pre-ship.md +44 -0
  81. package/skills/website-build-skill/prompts/11-ship-and-verify.md +44 -0
  82. package/skills/website-build-skill/prompts/12-web-design-team.md +141 -0
  83. package/skills/website-build-skill/references/stacks/framework.md +76 -0
  84. package/skills/website-build-skill/references/stacks/scripted-static.md +76 -0
  85. package/skills/website-build-skill/references/stacks/static-html.md +72 -0
  86. package/skills/website-build-skill/roles/builder.md +139 -0
  87. package/skills/website-build-skill/roles/coordinator.md +132 -0
  88. package/skills/website-build-skill/roles/designer.md +125 -0
  89. package/skills/website-build-skill/roles/graphics.md +126 -0
  90. package/skills/website-build-skill/roles/optimizer.md +129 -0
  91. package/skills/website-build-skill/roles/researcher.md +202 -0
  92. package/skills/website-build-skill/roles/reviewer.md +139 -0
  93. package/skills/website-build-skill/templates/audit-brief.md +63 -0
  94. package/skills/website-build-skill/templates/brand.md +53 -0
  95. package/skills/website-build-skill/templates/brief.md +51 -0
  96. package/skills/website-build-skill/templates/evidence.md +100 -0
  97. package/skills/website-build-skill/templates/handoff.yaml +23 -0
  98. package/skills/website-build-skill/templates/install-choice.txt +28 -0
  99. package/skills/website-build-skill/templates/site-operations.md +71 -0
  100. package/skills/website-build-skill/templates/status.md +47 -0
  101. package/skills/website-build-skill/templates/tokens.json +72 -0
  102. package/src/agents.mjs +7 -0
  103. package/src/bundle.mjs +106 -0
  104. package/src/catalog.mjs +12 -0
  105. package/src/choice.mjs +6 -0
  106. package/src/cli.mjs +96 -0
  107. package/src/install.mjs +344 -0
  108. package/src/library-check.mjs +106 -0
  109. package/src/validate.mjs +351 -0
@@ -0,0 +1,398 @@
1
+ # Research and memory
2
+
3
+ Establish the engagement date, build the evidence library, then release work.
4
+
5
+ ## ASK DATE rule
6
+
7
+ - Meaning: ASK DATE is the date the user makes the request, fixed at engagement start. Research must reflect what is available as of that date, with later checks explicitly dated inside the same engagement. It is never the model's training cutoff, a hardcoded prompt year, or the last library's date.
8
+ - First action: establish it before research or intake questions. Never ask the user what the date is, in any phrasing. Never infer it from the model's own knowledge. An environment-supplied date and a remembered date may feel alike to the model; only external provenance counts.
9
+ - Ownership: Researcher alone records it once in `site-work/research/library/scope.md`. A later role reads that record instead of independently resetting it. Installing a skill is not the start of a website request.
10
+
11
+ **Date-source ladder.** Try in this order and stop establishing the date at the
12
+ first successful rung. Record failed/unavailable earlier rungs and the successful
13
+ rung's raw evidence. Capturing the first HTTP header remains a cross-check after
14
+ an earlier rung succeeds; it does not restart the ladder or a later day's engagement.
15
+
16
+ 1. **Host environment (`host-environment`).** Use a current date explicitly injected by the host into this request/session. Record the exact supplied value and its host-context location. A date the model believes it remembers, an old saved session's date, or a date typed by the user is not host evidence. Preserve any supplied timezone; do not invent a time of day when only a date is supplied.
17
+ 2. **System clock (`system-clock`).** Through an available command runner, execute `date -u '+%Y-%m-%dT%H:%M:%SZ'`. Expected output is one UTC line shaped `YYYY-MM-DDTHH:MM:SSZ`; take its `YYYY-MM-DD` part as the date and preserve the whole output. On a Windows-only runner, use `powershell -NoProfile -Command "[DateTime]::UtcNow.ToString('yyyy-MM-ddTHH:mm:ssZ')"` with the same output shape. Unsupported or failed execution advances the ladder, never invents output.
18
+ 3. **HTTP response (`http-date`).** Capture the raw `Date` response header on the first URL fetch of this run, including requested URL, final URL, status, raw header and any cache/Age evidence. Its expected HTTP-date shape is `Day, DD Mon YYYY HH:MM:SS GMT`. Parse that server-supplied value and normalize to UTC. Where command execution is available, `curl --silent --show-error --dump-header - --output /dev/null '<source-url>'` shows response headers; retain only date provenance fields, never cookies or credentials. A fetch API that hides headers cannot satisfy this rung; missing, malformed or demonstrably stale cached headers advance it. Do not claim every fetch tool exposes a usable header or fabricate one from page content.
19
+ 4. **Filesystem (`filesystem-mtime`).** If writing and metadata reading are available but command execution is not, write a new scratch file at `site-work/research/library/.ask-date-probe` and read its modification timestamp through the file tool. Record the exact raw mtime, timezone/precision, relative path and fresh-write result; derive the date from that timestamp. Reusing an old file's mtime does not count. If metadata cannot be read, advance the ladder. Remove only this owned scratch file if supported; it is never deployed or published.
20
+ 5. **Derived floor (`derived-floor`).** If none of the earlier rungs is available, take the most recent credible publication/update date actually visible in sources opened this run. Record `ASK DATE: derived-floor <date>` with source URLs, observed date text and why it is credible. Collect only the minimum source evidence needed to establish this rung before the full research pass. Future scheduled dates, snippets, model knowledge and guessed dates are not observations. This is a lower bound, not proof of the actual day: research is current at least to that date, and currency beyond it is unproven. Every output opens with `Research as of derived-floor <date>; currency beyond this floor is unproven.` Every gate repeats that qualification; never silently promote it to an exact date. As more credible source dates are opened during initial establishment, take the latest before finalizing the one scope record; retain the candidate trail.
21
+ 6. **Nothing available (`unavailable`, never a successful date rung).** No host date, command execution, usable URL fetch or filesystem means no current research capability either. Write or return `query-plan.md` and `unresolved-claims.md`, state the tool limit, and record the research gate BLOCKED. If URLs can be opened but no credible publication date or earlier rung can be obtained, date provenance is still BLOCKED. A missing date is not a separate softer exception, and cannot be solved by asking the user.
22
+
23
+ **Cross-check, and never let a fetched source move the date.** A first-fetch HTTP Date
24
+ comes from a server you do not control, and the first source of a run can be chosen by
25
+ whatever you were pointed at. Treat it as evidence, never as authority.
26
+
27
+ - **A local rung wins.** When a host date or a system clock is available, it sets ASK DATE.
28
+ A disagreeing HTTP Date is recorded as a discrepancy with both values; it does not
29
+ become the chosen rung and does not change ASK DATE.
30
+ - **A fetched date later than the local clock is rejected.** No source knows the future.
31
+ Record it as `rejected: future http-date`, keep the local rung, and treat that source as
32
+ unreliable for dating anything else it says.
33
+ - **A fetched date earlier than the local clock** is usually a cached or proxied response.
34
+ Record it, keep the local rung, and prefer a direct fetch for anything date-sensitive.
35
+ - **Only when rungs 1 and 2 are both unavailable** can `http-date` be the chosen rung, and
36
+ then it needs corroboration: a second HTTP Date from an independent host, agreeing within
37
+ 24 hours. Without that second source, do not adopt it; fall through to `derived-floor`
38
+ and carry its qualification.
39
+ - **A clock error is established, not assumed.** Two independent fetched sources agreeing
40
+ with each other and disagreeing with the local clock by more than 24 hours is the only
41
+ evidence that promotes a correction, and the correction is an explicit recorded decision
42
+ that invalidates dependent receipts. Never a silent reset, and never averaged.
43
+ - Normal passage of days in an engagement is not a conflicting start timestamp.
44
+
45
+ **Why this rule is shaped this way.** Preferring the server unconditionally lets a single
46
+ attacker-controlled page set ASK DATE into the future, after which every genuine access date
47
+ looks stale and the research gate blocks the engagement. A source supplies evidence about
48
+ itself; it never supplies authority over your own state.
49
+
50
+ **Record once in scope.md.** Required date fields, before other scope assumptions:
51
+
52
+ ```text
53
+ ASK DATE: <YYYY-MM-DD | derived-floor YYYY-MM-DD>
54
+ ASK DATE rung: <host-environment | system-clock | http-date | filesystem-mtime | derived-floor>
55
+ ASK DATE evidence: <exact host value/location, command/output, header/URL, mtime, or source-date observations>
56
+ ASK DATE precision: <exact date | derived floor>
57
+ ASK DATE timezone: <supplied zone | UTC | unspecified by source>
58
+ ASK DATE attempts: <unavailable earlier rungs and reasons>
59
+ ASK DATE cross-check: <both raw values and disposition | not available with reason>
60
+ Engagement: <stable request identifier; start preserved across sessions>
61
+ ```
62
+
63
+ - Validity: require a real calendar date and raw evidence matching the allowed rung. No missing date or rung, no assumed date, no `assumed`, `from memory`, or `user-supplied` rung. Model confidence and user confirmation cannot replace the ladder.
64
+ - Source discipline: training memory is never research. A claim without a source URL and access date is a failure however confidently stated. Keep the existing search, opened-source, disagreement, evidence/inference, and unresolved-claim standards alongside this rule.
65
+ - Two dates: each claim has `published: <source publication or update date | unknown>` (label which when known) and `accessed: <actual access date>`, plus URL and supporting passage/revision. The publication date is the source's fact; the access date is when the agent opened it. Unknown publication dates stay `published: unknown`. Do not infer them from content, URL, copyright footer or HTTP Date.
66
+ - Current access: `accessed` must be ASK DATE or later inside the same engagement, backed by a source-opening receipt. A date after the actual observation is fabrication. Preserve timezone/date precision and link the session/tool result; merely typing a recent date is not access evidence.
67
+ - Derived-floor access: where the ladder proves only a floor, record `accessed: derived-floor <date>` with the actual source-opening event/sequence and `exact access date: unavailable`. Compare known lower bounds without claiming a precise wall-clock date. All such outputs and gate records retain the floor qualifier. A time-sensitive decision needing a proven exact day stays BLOCKED until that evidence exists; the qualified mode never claims exact-day currency. Other claims may pass the qualified gate with fresh source-opening evidence, all checks satisfied, and the floor limitation in the receipt.
68
+ - Coverage: each applicable domain needs at least one actually opened, access-dated source and claim mapping; record its publication/update date or unknown separately. NOT APPLICABLE needs a project-specific reason. A bare URL, empty file or unresolved actionable claim does not meet coverage.
69
+ - Opener: every library Markdown file, including scope, ledgers and domain checklists, starts with `Research as of <ASK DATE>`. The value is the exact stored ASK DATE, including the derived-floor qualification when applicable. Later access dates belong to claims, not a rewritten engagement start. YAML handoffs carry the date, rung, precision and gate qualification in their check evidence and limitations.
70
+
71
+ **Freshness windows relative to ASK DATE.** These are the repo's conservative
72
+ reuse defaults and triggers, not vendor promises that a fact cannot change. For a
73
+ newly checked domain, the first due date is ASK DATE plus the window; a later actual
74
+ check advances the next due date from that check. Store both the concrete due date
75
+ and its offset from ASK DATE using date tooling. At or beyond expiry, recheck before
76
+ reliance. A shorter known vendor change date or relevant version release wins.
77
+ Same-day means that within one engagement, reuse the receipt when reliance falls
78
+ on the same UTC calendar date as its `fetched_at`. Fetch again when reliance falls
79
+ on a later calendar day or a change trigger fires, even within the same day. It
80
+ does not grant 24 hours from a late check. In derived-floor mode, re-open fast-domain sources in the current work
81
+ session and recheck them at every resumed session because elapsed days cannot be
82
+ proved. This can satisfy only a visibly qualified lower-bound gate; it never proves
83
+ same-calendar-day currency. A decision explicitly requiring that proof stays BLOCKED.
84
+
85
+ | Domain | Freshness window relative to ASK DATE | Why this window and what triggers an earlier recheck |
86
+ | --- | --- | --- |
87
+ | 1. Reference codebases and real implementations | 30 days for pattern comparisons; verify revision and maintenance status at first reuse. | Structural lessons outlast releases, but a moving branch may change the inspected implementation. New revision, license or security advisory triggers a recheck. |
88
+ | 2. Stacks and frameworks | 7 days for landscape comparisons; same-day check for selected versions, APIs, deprecations and support. | Framework releases and exact API contracts can change within a build; confirm the current supported version before coding against it. |
89
+ | 3. Design | 365 days for typography, colour theory, gestalt and grids; 90 days for awards, trends and anti-trends. | Fundamentals decay slowly; examples and trends need a fresher view. Award selection always covers the last two to three years relative to ASK DATE. |
90
+ | 4. Graphics skills | Same-day check for tool capabilities, pricing, commercial rights per tier and destination specs; 90 days for export craft. | Product tiers, safe zones and rights can change without changing a tool's name; stable compression principles need less repetition. |
91
+ | 5. UI and UX | 180 days for tested interaction principles; 30 days for browser/device interaction behavior. | Task and recovery principles persist; platform behavior changes. A new input mode, audience or observed usability failure triggers a recheck. |
92
+ | 6. Accessibility | 365 days for fundamentals; current-version check at first reliance and after 30 days. | Age alone does not invalidate contrast or keyboard principles. Confirm the current standard release, target level and relevant errata as of ASK DATE, and again before applying any newly discovered release. |
93
+ | 7. Performance | 30 days for measurement strategy; same-day check for CWV thresholds, metric definitions and selected tooling. | Loading principles are durable, while current metric semantics and measurement tools can change; distinguish field evidence from lab results. |
94
+ | 8. SEO | 7 days for general documented behavior; same-day check for search features, schema eligibility and indexing interfaces. | A supported feature can retire or change independently of basic crawlability; platform announcements trigger immediate recheck. |
95
+ | 9. AEO and AI citation | Same-day check for crawler policies, citation behavior, search behavior and proposal adoption. | Consumer behavior and documentation change quickly and evidence is incomplete; a prior observation never proves present citation behavior. |
96
+ | 10. Security | 7 days for the threat landscape; same-day check for advisories, host header/CSP syntax and scanner criteria. | Structural escaping remains useful, but new exposure or configuration behavior can invalidate a safe-looking baseline. Surface changes trigger immediate review. |
97
+ | 11. Hosting, deploy and DNS | Same-day check for platform capabilities, plan prices/restrictions, header syntax and deploy configuration; 90 days for DNS fundamentals. | Commercial limits and deployment contracts change quickly; name-resolution principles change slowly. Recheck the actual target before release. |
98
+ | 12. Measurement | 30 days for setup and interpretation guidance; same-day check for selected event APIs, consent settings and receiving-property behavior. | Statistical caveats persist; vendor interfaces and active configuration do not. Changed instrumentation or property triggers verification. |
99
+ | 13. Legal, kept light | Same-day check for exact font/stock/AI tool licenses and intended-use rights; 30 days for background guidance. | Rights attach to a particular asset, version and tier; a previously allowed use is not evidence for a new use. Changed terms or jurisdiction triggers review. |
100
+
101
+ - Versioned standards: identify the authoritative current release as of ASK DATE and at each scheduled refresh; record release/version, target level, source and applicability. An old but still-current standard is not stale merely because its publication is old. A new relevant release triggers review before reuse even inside a nominal window.
102
+ - Staleness artifact: generate this full table into `staleness.md`, add all applicable claims, original accesses, last revalidations, window/expiry, trigger, reason, owner and dependent receipts. Name the earliest-expiring applicable domain (all ties), its window, and concrete recheck date with the ASK DATE-relative expression. Same-day domains are due before use that day. Do not average domain windows or let a slow domain hide a fast subclaim.
103
+
104
+ **Prior-library revalidation pass.** A library from another engagement is stale
105
+ until this pass completes against the new ASK DATE, even if it contains useful work.
106
+
107
+ 1. Read the previous scope ASK DATE and every per-claim access date first. Preserve them as history before recording the new engagement's date evidence. Start the new research gate BLOCKED; an old PASS does not transfer.
108
+ 2. Map every potentially relied-on claim to its domain window and the current brief. Compare the original/last genuine check with the new ASK DATE using date tooling; inspect change triggers and current version status.
109
+ 3. For elapsed windows or changed scope/version, reopen authoritative sources and fully recheck the claim. For a claim still inside its window, allow a lighter confirmation of the original source, version and applicability instead of repeating the entire research sweep. It still needs a real source open during this engagement to earn a current `accessed` date; a desk review alone cannot meet the acted-on claim gate.
110
+ 4. List every reused claim in `staleness.md` with claim ID, `original accessed`, original scope date, window, decision (`rechecked`, `reused within window`, `superseded`, or `blocked`), reason, supporting current source-opening receipt and revalidation date. Update its current `accessed` only after that source opening. Historical dates remain visible as history, never passed off as current evidence.
111
+ 5. Finish all domain dispositions and relied-on claims, then rewrite library opening lines to the new ASK DATE and evaluate the gate. A new scope record may be established first with BLOCKED status; it cannot certify the untouched old library. Files containing unresolved material label it clearly and no dependent decision is released by a stamp alone.
112
+ 6. Without web access, retain the old evidence as historical, produce `query-plan.md` and `unresolved-claims.md`, and keep the gate BLOCKED. An existing library does not waive current-source access or staleness checks.
113
+
114
+ **Downstream top-ups and multi-day engagements.** Every role follows the same
115
+ rule, starting with the library scope record. Its `top-up.md` records each claim's
116
+ source date, URL, actual current-engagement access and any original access plus
117
+ revalidation decision. Reviewer returns those fields in its read-only packet.
118
+ Training-memory claims and unrevalidated prior-run dates fail identically for all
119
+ roles. Send canonical corrections to Researcher and pause affected decisions.
120
+ ASK DATE remains the engagement start across days and sessions. Record later checks
121
+ with their own access dates, do not restamp the start. If a fast domain's window
122
+ elapses, recheck before its facts are relied on again, including before release.
123
+ Invalidate dependent gate receipts until the refresh evidence is accepted.
124
+
125
+ **No search, no current-research pass.** Without live web access, produce or return
126
+ `query-plan.md` and `unresolved-claims.md`, state the limitation, and leave the gate
127
+ BLOCKED whether the library is absent, old, or freshly stamped. Training knowledge,
128
+ user-supplied dates and a list of intended queries cannot satisfy the gate. A
129
+ research packet can be useful without being complete; never label it PASSED.
130
+
131
+ **Failure modes.** Record stale reuse, restamping without revalidation, missing
132
+ or invented date provenance, asking the user for a date, confident undated claims,
133
+ invented publication dates, unqualified derived floors, expired multi-day claims,
134
+ and capability-free passes as findings. Their tell is missing or contradictory
135
+ scope/source-opening/revalidation evidence, not the prose's apparent confidence.
136
+
137
+
138
+ ## Build research that someone can apply
139
+
140
+ Question: which facts change this site's design, implementation, or release?
141
+
142
+ - Standards: search dated claims, open each cited source, and preserve source and access dates separately.
143
+ - Areas: execute every numbered domain in prompts/01-website-deep-research.md.
144
+ - Depth: examine actual repository files at an identified revision, not only project descriptions.
145
+ - Interpretation: turn each brief word into a testable visual decision and an alternative.
146
+ - Evaluation: compare evidence of user task completion separately from aesthetic preference.
147
+ - Extraction: separate observed values, inferred roles, approved rules, and unresolved conflicts.
148
+ - Save: write the library and propose durable memory as two separate destinations.
149
+ - Close: report surprising findings with claim IDs, then request only still-missing design inputs.
150
+ - Order: Researcher is agent one; no downstream role starts until its disk library passes.
151
+
152
+ ## Write a claim ledger
153
+
154
+ Use templates/evidence.md for each claim that could change a decision.
155
+ Record claim ID, domain, statement, URL, source date and kind, actual access event,
156
+ supporting passage or repository revision, applicability, confidence, and dependents.
157
+ A search result is a discovery lead. Open its source before recording it as evidence.
158
+ Label evidence, inference, proposed default, measurement, and UNVERIFIED separately.
159
+ A proposed default can guide a draft only when no blocked external claim supports it.
160
+
161
+ Use this exact table header in `sources.md`; keep applicability and evidence kind
162
+ in the per-claim record. Escape literal pipes in table cells with a backslash.
163
+
164
+ ```text
165
+ | Claim ID | Domain | Statement | URL | Published | Accessed | Status | Dependents |
166
+ | --- | --- | --- | --- | --- | --- | --- | --- |
167
+ ```
168
+
169
+ Use stable `CLAIM-` IDs containing only letters, digits, underscores and hyphens.
170
+ Status is `OPENED` only with a receipt, otherwise `UNVERIFIED`. A `Verified` label
171
+ without a receipt fails the gate; it cannot stand in for proof of a fetch.
172
+
173
+ **Fetch receipts.** At fetch time, write one receipt per cited claim's opened
174
+ source to `research/library/receipts/<CLAIM-ID>.md`, relative to `site-work/`.
175
+ Never reconstruct receipts later or mark a claim OPENED from memory or a search
176
+ snippet. Search results are discovery leads; the page itself must be fetched.
177
+ The receipt starts with the library's dated opener, followed by these plain fields:
178
+
179
+ ```text
180
+ url: <exact URL in the claim row>
181
+ fetched_at: <UTC timestamp from the environment, YYYY-MM-DDTHH:MM:SSZ>
182
+ tool: <fetch tool actually used>
183
+ result: <HTTP status or actual tool outcome>
184
+ published: <date copied verbatim from the excerpt, or unknown>
185
+ excerpt: |
186
+ <verbatim supporting page passage of at least 80 characters>
187
+ ```
188
+
189
+ Indent each excerpt line by two spaces. Include quoted page date text in the
190
+ excerpt when claiming a publication/update date; otherwise use `unknown`. The
191
+ row's Published value must match the receipt's published value exactly. Optional
192
+ milliseconds in fetched_at use three digits before Z. If the environment cannot
193
+ supply a UTC timestamp, leave that claim UNVERIFIED; never invent precision.
194
+ An existing qualified ASK DATE does not authorize a fabricated fetch timestamp.
195
+
196
+ **Check before reliance.** Run `website-build-skill check-library <root>/site-work`
197
+ when a shell exists. From a repository checkout the equivalent is
198
+ `node bin/website-build-skill.mjs check-library <site-work-dir>`. Save the exact
199
+ command, exit code and output with the research gate evidence. Exit 0 means
200
+ receipt consistency, not proof that a passage is true or supports a decision;
201
+ exit 2 reports problems, one per line. The checker lists UNVERIFIED rows even
202
+ when it exits 0. Any acted-on UNVERIFIED claim keeps research acceptance BLOCKED.
203
+ Without a shell, Reviewer records the same five checks in
204
+ checklists/research.md by hand. Independent AD09 re-fetching remains required.
205
+
206
+ Example: a provider's paid-tier export right needs the exact tier's current terms,
207
+ the asset's origin, intended use, a source-opening receipt, and required notices.
208
+ A review of the provider's image quality cannot establish any of those rights.
209
+
210
+ When sources disagree, record both claim IDs, dates, scopes, and the affected decision.
211
+ Do not average incompatible claims or pick the most convenient answer.
212
+ Prefer the authoritative source for the exact version or tier, and record why.
213
+ If evidence cannot settle a material conflict, block that decision with a next action.
214
+
215
+ ## Choose where the work is saved
216
+
217
+ Read outputRoot and optional outputStorage from the install receipt before the first write.
218
+ Reuse that choice without asking again. If it is absent, ask the human using
219
+ templates/install-choice.txt: an Obsidian vault folder, local folder, Notion export, or
220
+ another local destination. An explicitly accepted default uses the website project folder;
221
+ a missing answer is not consent. Researcher records the root and any export target in
222
+ site-work/research/library/scope.md beside ASK DATE. Every project path, including
223
+ site-work/, resolves inside that root. Later roles read this record instead of choosing again.
224
+
225
+ An Obsidian vault and a plain folder both work directly, because the library is Markdown on disk.
226
+ Notion is an export destination, never the working copy: the research gate, the prior-library pass
227
+ and every role read their own files back by path, and a page in a workspace API cannot serve that
228
+ read-back. Keep the working copy on disk and export the finished library, recording the export the
229
+ same way as any other save, with status and read-back. Announce that split when Notion is chosen,
230
+ and record which destination holds the authoritative copy.
231
+
232
+ Confirm the root is writable by writing `<root>/site-work/research/library/scope.md`
233
+ and reading it back before the sweep begins.
234
+
235
+ ## Produce the complete library
236
+
237
+ All paths below belong to the user's authorized project, never the installed skill.
238
+ They resolve inside the workspace root the human chose; site-work/ is a name under it, not a fixed location.
239
+ Researcher owns the library and its revisioned research receipts.
240
+ Library Markdown, including each domain checklist, uses the mandatory dated opener.
241
+
242
+ ```text
243
+ site-work/
244
+ research/
245
+ library/ Researcher-owned canonical library.
246
+ README.md Dated index, headline findings, role reading map.
247
+ scope.md ASK DATE, ladder rung/raw evidence, workspace root, request, tools, applicability.
248
+ coverage.md Thirteen domains, files, checklist and source coverage.
249
+ 01-codebases-and-stacks.md Domains 1 and 2; code reads and current stacks.
250
+ 02-design-and-experience.md Domains 3 and 5; design and UI/UX.
251
+ 03-graphics-and-rights.md Domains 4 and 13; graphics and light legal.
252
+ 04-accessibility-and-performance.md Domains 6 and 7; standards and measurement.
253
+ 05-search-and-answers.md Domains 8 and 9; SEO and AEO.
254
+ 06-security-and-delivery.md Domains 10 and 11; threats, hosts, deploy, DNS.
255
+ 07-measurement-and-operations.md Domain 12; analytics and operational follow-through.
256
+ sources.md Claim IDs, opened URLs, source/access dates, scope.
257
+ receipts/
258
+ <CLAIM-ID>.md Per-claim page fetch fields and verbatim supporting excerpt.
259
+ disagreements.md Conflicting sources, affected decisions, dispositions.
260
+ query-plan.md Search questions and missing-source actions.
261
+ unresolved-claims.md UNVERIFIED claims and blocked downstream decisions.
262
+ how-to-read-a-brand-kit.md Evidence into checkable design decisions.
263
+ website-qa-checklist.md Cross-domain blocker-first index of applied checks.
264
+ surprises.md Short findings and implications for the user.
265
+ staleness.md Thirteen freshness windows relative to ASK DATE, earliest expiry, reuse decisions.
266
+ learning.md Opened evidence, learned rules, applied checklist IDs.
267
+ recipes.md Commands that actually ran, with tool version and what they produced.
268
+ memory-proposal.md Durable rules and location, not a completed save.
269
+ memory-receipt.md Save status, destination, read-back or pending action.
270
+ checklists/
271
+ 01-codebases.md Inspected source, license, complexity, reuse.
272
+ 02-stacks.md Version/API evidence and justified dependencies.
273
+ 03-design.md Brand interpretation, tokens, three directions.
274
+ 04-graphics.md Per-tier rights, sizes, safe zones, inspected exports.
275
+ 05-ui-ux.md Task journeys, state coverage, mobile recovery.
276
+ 06-accessibility.md Computed contrast and manual assistive-tech checks.
277
+ 07-performance.md Field/lab distinction and repeatable budgets.
278
+ 08-seo.md Crawl, canonical, schema, linking, sitemap.
279
+ 09-aeo.md Quotable answers, entities, crawler evidence.
280
+ 10-security.md Input/secret boundaries, host CSP, adverse cases.
281
+ 11-hosting.md Preview, DNS, HTTPS, rollback, plan restrictions.
282
+ 12-measurement.md Receiving-property proof and interpretation limits.
283
+ 13-legal.md Font, stock, AI imagery, trademark evidence.
284
+ coordinator/ Coordinator top-ups, flags, learning and QA receipts.
285
+ designer/ Designer top-ups, flags, learning and QA receipts.
286
+ graphics/ Graphics top-ups, flags, learning and QA receipts.
287
+ builder/ Builder top-ups, flags, learning and QA receipts.
288
+ optimizer/ Optimizer top-ups, flags, learning and QA receipts.
289
+ handoffs/
290
+ researcher/ Versioned research gate receipts to Coordinator.
291
+ review/ Coordinator captures read-only Reviewer returns.
292
+ <revision>/ Findings, research packet, handoff, capture envelope.
293
+ MEMORY.md Coordinator's consolidated durable-memory proposal.
294
+ ```
295
+
296
+ - Coverage: map all thirteen domains to grouped files, source claims, checks, and downstream owners.
297
+ - Exclusions: survey every domain; justify any project-specific NOT APPLICABLE check.
298
+ - Checklists: each domain check names criterion, method, expected evidence, claim IDs, owner, status, and exclusion reason.
299
+ - Blockers: website-qa-checklist.md collects unresolved critical checks before quality scoring.
300
+ - Learning: reopen written files and record which rules change the handoff.
301
+ - Recipes: when a command works, paste it into recipes.md with the tool and version it ran on,
302
+ the input it took, and the output it produced. A later role runs the recorded command instead
303
+ of re-deriving flags. A recipe is a record of one run, not a guarantee for a different version:
304
+ re-check it against the installed tool before relying on it, exactly as with any example command.
305
+ - Read-back: verify the saved revision and links before issuing a research receipt.
306
+ - Privacy: keep runtime research, source assets, and private scope out of deployment output.
307
+
308
+ ## Learn, ingest, then top up
309
+
310
+ Every downstream role starts with its WHAT YOU MUST LEARN filenames.
311
+ Read the actual library, its current revision, and the applicable domain checklists.
312
+ Record opened files, learned rules, changed assumptions, and applied check IDs in learning.md.
313
+ Top up only remaining questions in that role's domain using current source openings.
314
+ Read library/recipes.md before deriving an image, font, or build command, and append any
315
+ command you got working, with its tool version and result, in the same pass.
316
+ Write README.md, sources.md, top-up.md, flags.md, learning.md, applied-checklists.md,
317
+ memory-proposal.md, and memory-receipt.md in the role's owned research directory.
318
+ Reviewer returns these bodies read-only for unchanged Coordinator capture.
319
+
320
+ Send wrong or stale canonical claims to Researcher by claim ID, dated counterevidence,
321
+ affected decisions, and paused receipts. Only Researcher revises the shared library.
322
+ A new brief, host, tier, dependency, brand decision, or source correction invalidates
323
+ all affected downstream receipts until the relevant checks run again.
324
+
325
+ In SOLO, read the same full role bodies and do the same research and learning.
326
+ Write and reopen a self-handoff at every boundary using templates/handoff.yaml.
327
+ Name in framing_reset which prior assumption or design attachment you release.
328
+ Keep approved requirements; do not treat your previous suggestion as a user decision.
329
+
330
+ ## Save durable rules separately
331
+
332
+ Keep volatile versions, prices, rights, and platform behavior in the dated library.
333
+ Propose durable rules such as computed contrast, three mockups, evidence-backed claims,
334
+ smallest justified stack, source-safe rendering, and different-family review.
335
+ Record the library location and refresh procedure so a later session can find it.
336
+
337
+ Use supported memory or project instructions only within existing authorization.
338
+ Record status as saved, declined, unsupported, or pending, with the exact destination.
339
+ For saved, record the operation receipt and read back the persisted content.
340
+ If save or read-back fails, record the failure and keep the proposal available.
341
+ Session context and an agent saying it learned something are not durable storage.
342
+ Coordinator may consolidate proposals into site-work/MEMORY.md without changing
343
+ another role's receipt or upgrading a pending save into a success.
344
+
345
+ ## Continue without durable memory
346
+
347
+ Return a reattachment packet containing the brief, capability limits, library revision,
348
+ claim/source ledger, staleness schedule, approvals, stage status, and latest handoffs.
349
+ Include complete named bodies when the receiver cannot open file paths.
350
+ Tell the user which project mechanism can save the packet and which files to reattach.
351
+ Reopen the received files at the next session and run the prior-library or resumed-session
352
+ freshness procedure as appropriate. Missing disk persistence still blocks research.
353
+ Optional memory being unsupported does not invalidate a verified disk library.
354
+
355
+ ## Missing-capability table
356
+
357
+ | Missing capability | Still works | Cannot honestly complete | Recovery artifact |
358
+ | --- | --- | --- | --- |
359
+ | Web search | Request clarification, supplied-source review, query planning. | Current-to-ASK-DATE research or revalidation, including a prior library; gate stays BLOCKED. | `query-plan.md`, `unresolved-claims.md`, and BLOCKED receipt. |
360
+ | URL retrieval | Pasted/uploaded core method. | Raw-URL bootstrap and unopened-source citations. | Self-contained bundles from the human. |
361
+ | File writing | Draft prompts, specifications, named file bodies. | Saved disk research or a claimed local install. | Downloadable files or copyable labeled blocks. |
362
+ | Persistent memory | Current-session workflow and project documents. | Automatic durable memory across future sessions. | `MEMORY.md` proposal plus explicit save/reattach steps. |
363
+ | Image generation/viewing | Brief and wireframe planning. | Three inspected visual mockups and visual approval. | Designer handoff with required assets and criteria. |
364
+ | Code execution/browser | Draft implementation and test plan. | Measured contrast, functional tests, lab scores, live QA. | Commands and exact expected evidence for a capable runner. |
365
+ | Separate workers | Sequential SOLO jobs, role learning, and saved self-handoffs. | A claimed TEAM or concurrent worker independence. | SOLO capability receipt and role-boundary packets. |
366
+ | Independent model family | Internal critique and review packet. | Independent adversarial gate. | AUDIT_BRIEF plus immutable artifact for another family. |
367
+ | Deploy access | Reviewable local/preview artifact where available. | Production release and live verification. | Operations doc and authorized operator handoff. |
368
+
369
+
370
+ Capability gaps accumulate. One working tool cannot stand in for another.
371
+ A URL reader is not a browser, image inspector, response-header reader, or calculator.
372
+ An installed role definition is not a worker, tool permission, or different model family.
373
+ Actual host loading, orchestration, isolation, memory, and deployment support are
374
+ UNVERIFIED until tested in that session. Record the probe and result separately.
375
+
376
+ ## Verify and hand off
377
+
378
+ Apply checklists/research.md AD01 through AD08, then R01 through R06.
379
+ Save the producer receipt and have Coordinator reopen its artifacts before acceptance.
380
+ Independent AD09 runs later, before shipment, rather than blocking agent one's start.
381
+ Every receipt names the library revision, scope provenance, relied-on claims,
382
+ source-opening evidence, earliest expiry, next owner, and unresolved limitations.
383
+ All applicable checks must pass; a persuasive summary does not replace the evidence.
384
+
385
+ ## Failure modes
386
+
387
+ - Decorative research: no claim-to-decision map or usable domain checklist.
388
+ - False persistence: a proposal or inaccessible filename is called a saved library.
389
+ - Scope drift: a downstream role quietly selects a new tier or host without research.
390
+ - Stale handoff: a changed claim leaves dependent PASS receipts untouched.
391
+ - False independence: another persona in the same family approves its own work.
392
+
393
+ ## Source and verification status
394
+
395
+ This playbook defines the method's evidence policy, not a claim about a live platform.
396
+ Source URLs and access events are recorded at runtime using templates/evidence.md.
397
+ External facts not opened and checked in the engagement remain UNVERIFIED.
398
+ Never report a measured, saved, installed, or deployed result without evidence.
@@ -0,0 +1,132 @@
1
+ # Tailor headers to the real response
2
+
3
+ Date rule: [establish ASK DATE and revalidate claims](research-and-memory.md#ask-date-rule).
4
+ Source status: external facts and example commands are UNVERIFIED until checked for the chosen version and engagement.
5
+ Record opened URLs, source dates or unknown, actual access dates, and supporting evidence.
6
+
7
+ Question: which restrictions fit the site's actual host, resources, and endpoints?
8
+
9
+ ## Inventory before configuring
10
+
11
+ List every script, stylesheet, image, font, media source, frame, connection, and form target.
12
+ Record exact origins, inline blocks, required permissions, and the user task each serves.
13
+ Remove unused resources before adding allowances.
14
+ Map normal HTML, redirects, errors, static assets, proxies, and function responses separately.
15
+ Verify HTTPS readiness and recovery before enabling long-lived HSTS.
16
+
17
+ ## Review the starter assumptions
18
+
19
+ These starters assume HTTPS, self-hosted resources, no inline scripts or styles,
20
+ no third-party frames or APIs, and no need for another site to frame this site.
21
+ They are UNVERIFIED configuration proposals, not deployed or scanned examples.
22
+ Keep existing redirects, rewrites, and unrelated settings while merging the rules.
23
+ The supplied HSTS preset is max-age=63072000; verify the chosen policy and readiness.
24
+ Never add includeSubDomains without an HTTPS inventory of every affected subdomain.
25
+ Never enable preload as incidental cleanup; it needs a separate explicit decision.
26
+
27
+ ## Select the static host format
28
+
29
+ ### Vercel static deployment
30
+
31
+ Merge this proposal into vercel.json, then inspect actual response coverage.
32
+
33
+ ```json
34
+ {
35
+ "headers": [{
36
+ "source": "/(.*)",
37
+ "headers": [
38
+ {"key": "Content-Security-Policy", "value": "default-src 'self'; script-src 'self'; style-src 'self'; img-src 'self' data:; font-src 'self'; connect-src 'self'; media-src 'self'; frame-src 'none'; object-src 'none'; base-uri 'self'; form-action 'self'; frame-ancestors 'none'; upgrade-insecure-requests"},
39
+ {"key": "Strict-Transport-Security", "value": "max-age=63072000"},
40
+ {"key": "X-Content-Type-Options", "value": "nosniff"},
41
+ {"key": "X-Frame-Options", "value": "DENY"},
42
+ {"key": "Referrer-Policy", "value": "strict-origin-when-cross-origin"},
43
+ {"key": "Permissions-Policy", "value": "camera=(), microphone=(), geolocation=()"}
44
+ ]
45
+ }]
46
+ }
47
+ ```
48
+
49
+ Starting source: https://vercel.com/docs/project-configuration
50
+ Current syntax, matching, and response coverage require source opening and a host test.
51
+
52
+ ### Cloudflare Pages static output
53
+
54
+ Place this proposal in the deployed static directory as _headers.
55
+
56
+ ```text
57
+ /*
58
+ Content-Security-Policy: default-src 'self'; script-src 'self'; style-src 'self'; img-src 'self' data:; font-src 'self'; connect-src 'self'; media-src 'self'; frame-src 'none'; object-src 'none'; base-uri 'self'; form-action 'self'; frame-ancestors 'none'; upgrade-insecure-requests
59
+ Strict-Transport-Security: max-age=63072000
60
+ X-Content-Type-Options: nosniff
61
+ X-Frame-Options: DENY
62
+ Referrer-Policy: strict-origin-when-cross-origin
63
+ Permissions-Policy: camera=(), microphone=(), geolocation=()
64
+ ```
65
+
66
+ Starting source: https://developers.cloudflare.com/pages/configuration/headers/
67
+ Verify the current documented exclusion of function responses; set and test their
68
+ headers in the response path rather than assuming this static file covers them.
69
+
70
+ ### Netlify static output
71
+
72
+ Place this proposal in the publish directory as _headers.
73
+
74
+ ```text
75
+ /*
76
+ Content-Security-Policy: default-src 'self'; script-src 'self'; style-src 'self'; img-src 'self' data:; font-src 'self'; connect-src 'self'; media-src 'self'; frame-src 'none'; object-src 'none'; base-uri 'self'; form-action 'self'; frame-ancestors 'none'; upgrade-insecure-requests
77
+ Strict-Transport-Security: max-age=63072000
78
+ X-Content-Type-Options: nosniff
79
+ X-Frame-Options: DENY
80
+ Referrer-Policy: strict-origin-when-cross-origin
81
+ Permissions-Policy: camera=(), microphone=(), geolocation=()
82
+ ```
83
+
84
+ Starting source: https://docs.netlify.com/manage/routing/headers/
85
+ Verify current behavior for proxies, functions, and edge functions separately.
86
+ Static rules alone cannot be treated as proof of headers on every response class.
87
+
88
+ ## Adapt CSP to actual resources
89
+
90
+ Add reviewed exact frame-src origins for authorized embeds and connect-src origins for APIs.
91
+ Retain object-src 'none', a reviewed base-uri, form-action, and framing policy.
92
+ Avoid wildcard script origins and production unsafe-eval.
93
+ Self-host fonts and use local-poster embed facades to keep the resource graph small.
94
+
95
+ Static inline blocks need hashes of their exact served bytes when a hash policy is chosen.
96
+ Regenerate hashes when bytes change and test the final artifact, including line endings.
97
+ A nonce design needs unpredictable per-response values shared by the header and allowed blocks.
98
+ Do not reuse a fixed nonce in static output or publish cached nonce-bearing HTML blindly.
99
+ Do not copy a strict static CSP onto a framework and assume hydration still works.
100
+ Read the selected framework's current CSP guidance and inspect emitted scripts.
101
+ Safe JSON serialization remains required even when CSP is enforced.
102
+
103
+ ## Verify the policy, then the journey
104
+
105
+ Use an actual GET response and preserve status, redirect chain, relevant headers, and URL.
106
+ Avoid relying on HEAD alone when the host handles it differently.
107
+ Check normal HTML, redirect responses and destinations, errors, assets, and functions.
108
+ Require exactly one intended enforced CSP per response, with no accidental duplicate policy.
109
+ Report-only CSP helps diagnosis but cannot satisfy the enforced-policy gate.
110
+
111
+ Exercise navigation, forms, fonts, images, authorized players, and payments when applicable.
112
+ Inspect browser violations with production policy active and retain functional evidence.
113
+ Run securityheaders.com against the exact authorized public URL and save its dated result.
114
+ Require A or A+ plus working journeys; a grade alone cannot prove application security.
115
+ If the scanner cannot run, record UNVERIFIED and leave its required gate blocked.
116
+
117
+ ## Record exceptions and recovery
118
+
119
+ Write site-work/qa/security-headers.md with candidate identity, origin inventory,
120
+ config revision, response matrix, browser results, scanner receipt, and remaining failures.
121
+ An exception needs scope, reason, owner, expiry, and evidence; do not silently lower a gate.
122
+ Keep the prior known-working configuration and an authorized rollback procedure.
123
+ New resources or endpoints invalidate affected header checks before release.
124
+ Apply checklists/security.md S01 through S08.
125
+
126
+ ## Failure modes
127
+
128
+ - Duplicate CSP: intersecting policies silently break allowed behavior.
129
+ - Partial coverage: a static header file leaves function errors unprotected.
130
+ - Scanner substitution: an A grade hides broken forms or authorization gaps.
131
+ - Premature HSTS: unready subdomains become inaccessible for returning browsers.
132
+ - Hash drift: minification changes inline bytes after policy generation.
@@ -0,0 +1,62 @@
1
+ # Serve licensed fonts from the site
2
+
3
+ Date rule: [establish ASK DATE and revalidate claims](research-and-memory.md#ask-date-rule).
4
+ Source status: external facts and example commands are UNVERIFIED until checked for the chosen version and engagement.
5
+ Record opened URLs, source dates or unknown, actual access dates, and supporting evidence.
6
+
7
+ Question: how can the chosen type remain legible without a third-party font request?
8
+
9
+ ## Verify the exact rights
10
+
11
+ Identify font family, version, source file, and license text.
12
+ Check web embedding, redistribution, and proposed subsetting separately.
13
+ Preserve required notices with the authorized woff2 files.
14
+ A screenshot or a public font download is not evidence of those rights.
15
+ Unknown rights keep the font out of the release; use an approved fallback for drafts.
16
+
17
+ ## Map type roles to files
18
+
19
+ List body, heading, UI, and emphasis roles with used weights and styles.
20
+ Include only faces the selected design actually needs.
21
+ Test required language glyphs before subsetting; do not remove content's characters.
22
+ Confirm the fallback has usable shapes, metrics, and coverage.
23
+ Do not rely on synthetic weight or style when the approved design needs a real face.
24
+
25
+ ## Define loading behavior
26
+
27
+ ```css
28
+ @font-face {
29
+ font-family: 'Project Sans';
30
+ src: url('/assets/fonts/project-sans-regular.woff2') format('woff2');
31
+ font-weight: 400;
32
+ font-style: normal;
33
+ font-display: swap;
34
+ }
35
+ body { font-family: 'Project Sans', system-ui, sans-serif; }
36
+ ```
37
+
38
+ This is a file naming and loading example, not a supplied or licensed font.
39
+ Choose display behavior for the content and test the fallback-to-loaded transition.
40
+ Use metric overrides only after measuring the actual fallback and loaded face.
41
+ Preload only critical faces with correct type and cross-origin fetch behavior.
42
+ Confirm the preload and CSS reference resolve to the same resource.
43
+
44
+ ## Verify failure and delivery
45
+
46
+ Block font requests and complete the primary journey using fallbacks.
47
+ Inspect all font requests and redirects; keep them on approved first-party origins.
48
+ Use font-src 'self' in the site's tailored CSP and test the enforced response.
49
+ Record layout shift, line wrapping, missing glyphs, and weight/style selection.
50
+ Check long copy and translated content when applicable.
51
+ Apply checklists/performance-seo.md PS03 and checklists/brand-and-mockups.md BM07.
52
+
53
+ ## Failure modes and sources
54
+
55
+ - License mismatch: desktop use is mistaken for web redistribution permission.
56
+ - Hidden external load: imported CSS contacts a font provider.
57
+ - Duplicate transfer: a mismatched preload fetches a face twice.
58
+ - Fragile layout: loaded type hides a broken fallback.
59
+
60
+ Open the font's actual license and current font loading documentation at
61
+ https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face before implementation.
62
+ No third-party font binaries ship with this skill.