@domandigital/craft 0.22.0 → 0.23.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.
- package/CHANGELOG.md +12 -0
- package/CHARACTER.md +138 -5
- package/COPY.md +35 -9
- package/PRINCIPLES.md +9 -0
- package/README.md +6 -0
- package/design-review.schema.json +156 -0
- package/dist/{audit-LQ2TDISV.js → audit-CRTC7JSF.js} +3 -3
- package/dist/audit.cjs +365 -15
- package/dist/audit.js +365 -15
- package/dist/{chunk-DE2ZAV4G.js → chunk-3LCBLDAO.js} +171 -3
- package/dist/{chunk-6PZG4MJS.js → chunk-3LHIKF5L.js} +5 -5
- package/dist/{chunk-G47ZCBD5.js → chunk-4NON4PVK.js} +2 -2
- package/dist/{chunk-6DRBFDWT.js → chunk-A7KUKNX6.js} +1 -1
- package/dist/{chunk-OVWVKMPS.js → chunk-KGEJ2TGT.js} +14 -14
- package/dist/{chunk-ONA73THJ.js → chunk-KIBDFRHT.js} +195 -13
- package/dist/{chunk-ZS7PQNJU.js → chunk-OTQQTXXK.js} +4 -4
- package/dist/{chunk-RBQCGDQQ.js → chunk-Y2LGYHJ5.js} +5 -5
- package/dist/{cli-R2HBESHI.js → cli-E2CFVIGZ.js} +5 -5
- package/dist/{cli-SZ4SZLUN.js → cli-HWGSNSDD.js} +4 -4
- package/dist/{cli-7DL4BKA7.js → cli-IYRJZWMN.js} +6 -6
- package/dist/{cli-YNIJOEJK.js → cli-RHU3MAZY.js} +3 -3
- package/dist/{cli-AM4FLXGM.js → cli-ROVZDHVR.js} +5 -5
- package/dist/{cli-T7A3BU5J.js → cli-TPV2EIIN.js} +9 -9
- package/dist/{cli-WZA5IXSR.js → cli-X3RZE4GM.js} +6 -6
- package/dist/{cli-7QL26YPR.js → cli-YRRBBU27.js} +1 -1
- package/dist/cli.js +3 -3
- package/dist/index.cjs +368 -15
- package/dist/index.d.cts +49 -3
- package/dist/index.d.ts +49 -3
- package/dist/index.js +367 -15
- package/dist/{viewports-cli-F7KJIVZL.js → viewports-cli-EAUVLHFJ.js} +3 -3
- package/package.json +1 -1
- package/word-lists.json +11 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# @domandigital/craft
|
|
2
2
|
|
|
3
|
+
## 0.23.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 6890c34: <!-- copy-ok: names the shapes the release starts catching --> Contrastive negation catches the shapes a 92EL report passed the gate with (DOM-1358, catalogue 2026.10.7). **This tightens the gate:** `not-just-but`, which blocks, now covers the parallel gerund ("renting Microsoft's services, not running servers") as well as the parallel participle; its 45 estate hits were read first and every one in shipped copy is the real template. A new review-tier tell, `trailing-contrast`, reports the softer forms COPY.md had left to the read-through: a noun after ", not" closing a sentence ("Edge matters for game servers, not registration"), "not a legal one", and a gerund "instead of" a gerund ("renting computing instead of owning it"). It never blocks, because a genuine disclaimer has the same shape, and it stays quiet where `not-just-but` already reports. Plain negation is untouched: "It is not tested at national scale", "not yet automated", "Nothing is copied by hand". A second new review-tier tell, `parallel-pair`, reports verbless parallel pairs, the staccato triplet's two-part cousin: "One form, seven workflows", "Same site, same £8,000.", "Pay per user, per month", and a verbless list used as a tagline ("Service account, match-day reminders, analytics."). A plain list of names, a sentence with a verb, a subtitle and a numeric result line pass. It never blocks, because a short slide label is often fine.
|
|
8
|
+
|
|
9
|
+
## 0.22.1
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- 68f65c3: <!-- copy-ok: names the phrases the release starts catching --> craft learns from Eunice Ordor's design and copy reviews (catalogue 2026.10.5). Her 73-note review of the new Doman Digital site is the first record in a reviewer corpus (`reviews/` in the repository; the schema test keeps each record to `design-review.schema.json`), and CHARACTER.md writes up the principles it teaches. `design-review.schema.json` gains optional fields for a reviewer's own record: `reviewer`, `date`, `source` and `rulings` on the review, and `source`, `verdict`, `founderRuling`, `principle` and `tells` on a note; `REVIEW_VERDICTS` is exported. Two new review-tier tells: `hero-cta-pair` (source and rendered) reports two buttons side by side in a hero, found in 140 of 140 null-build heroes, and `confession-line` reports copy that scopes a business by what it has not done or will not do ("What this is and is not", "we have not yet built", "our experience so far is one practice"). `plain-english`, already blocking, now covers the whole family the founder banned on 20 October 2026: bare "plainly" and "in plain terms/language/words", with licence text ("plainly marked") let through. `review-phrase` adds "plain" as a self-description ("a plain recommendation").
|
|
14
|
+
|
|
3
15
|
## 0.22.0
|
|
4
16
|
|
|
5
17
|
### Minor Changes
|
package/CHARACTER.md
CHANGED
|
@@ -632,6 +632,135 @@ back as `change`, ask for what is `hold`, find out what is `gather-evidence`,
|
|
|
632
632
|
and leave what is `no-change`. When a note names something that was not
|
|
633
633
|
inspected, look before you act on it.
|
|
634
634
|
|
|
635
|
+
### Eunice's review of the DD site, 2026-10-19
|
|
636
|
+
|
|
637
|
+
Eunice Ordor reviewed the preview of Doman Digital's own new site on Pastel
|
|
638
|
+
(canvas 986559) on 18 and 19 October 2026: 73 comments across the home,
|
|
639
|
+
services, work, Sensphere case, clinics, who-we-help, process, pricing, plans
|
|
640
|
+
and contact pages. The whole review is kept, note by note, in
|
|
641
|
+
[`reviews/eunice-ordor/2026-10-19-dd-site.json`](https://github.com/Doman-Digital/dd-packages/blob/main/packages/craft/reviews/eunice-ordor/2026-10-19-dd-site.json)
|
|
642
|
+
in the repository:
|
|
643
|
+
her words as she wrote them, what she proposed, what was done with it, the
|
|
644
|
+
founder's ruling where one was needed, and the principle each note teaches. The
|
|
645
|
+
founder went through it on 20 October 2026. As in "Where it came from" above,
|
|
646
|
+
four things are kept apart.
|
|
647
|
+
|
|
648
|
+
#### What she saw
|
|
649
|
+
|
|
650
|
+
Twelve notes are praise, and they are a record of what to keep: the structure
|
|
651
|
+
and type, the four routes in, the who-we-help page ("a site that reads as a van
|
|
652
|
+
roof"), the Chair and Blade case, the six-step process and the responsibility
|
|
653
|
+
matrix. The rest name problems. These matter beyond this one site:
|
|
654
|
+
|
|
655
|
+
- Two equal buttons in the hero (#5), and again on the process page (#36).
|
|
656
|
+
- Confession lines: "What this is and is not", "We have not yet built and
|
|
657
|
+
run...", "Our clinic experience so far is one practice" (#8, #13), and a
|
|
658
|
+
defensive caveat under the clinic questions (#10).
|
|
659
|
+
- Summary pages that send the reader elsewhere for the substance: services
|
|
660
|
+
cards that are a line of nouns and a link (#66 to #69), a homepage case card
|
|
661
|
+
with none of the case's proof (#19), a pricing page that charges £95 and £165
|
|
662
|
+
a month and never says what either buys (#40, #48), and a /work page where
|
|
663
|
+
nothing says we still run any of it (#57).
|
|
664
|
+
- Every /work line states the problem and leaves the result on another page
|
|
665
|
+
(#56).
|
|
666
|
+
- Tiers that make the same promise at two volumes, so the extra £1,000 reads as
|
|
667
|
+
better writing (#39).
|
|
668
|
+
- A price that looks steep until the maths is shown: £165 a month is £95 of
|
|
669
|
+
care and £70 of website (#43).
|
|
670
|
+
- Closed lists where the work is open: the hero sub-line and route 3 narrowed
|
|
671
|
+
to bookings and enquiries (#2, #6, #25).
|
|
672
|
+
- A page that contradicts itself: the Sensphere form said both that enquiries
|
|
673
|
+
reach the inbox and that details stay out of one (#15), and a process step
|
|
674
|
+
said "paid" for a product that had been retired (#22).
|
|
675
|
+
- On a phone, the hero image crops badly (#55).
|
|
676
|
+
|
|
677
|
+
#### What she proposed
|
|
678
|
+
|
|
679
|
+
Specific wording for most notes, and three larger changes: a hero slideshow of
|
|
680
|
+
client systems (#3), a call to action after several sections (#50, #51, #70),
|
|
681
|
+
and a social media card (#72). Her diagnoses were nearly all right. Her wording
|
|
682
|
+
often used the patterns COPY.md blocks. Four of her comments blocked at
|
|
683
|
+
<!-- copy-ok: quoting the reviewer's draft line -->
|
|
684
|
+
catalogue 2026.10.4 ("No licence, no lock-in" in #42 is one), and eight do once
|
|
685
|
+
the plain-English family is widened.
|
|
686
|
+
|
|
687
|
+
#### The founder's rulings, 20 October 2026
|
|
688
|
+
|
|
689
|
+
- One button in the hero and on each closing section.
|
|
690
|
+
- On a phone the first screen is ours: the headline, the sub-line and one
|
|
691
|
+
button. Another client's brand never opens it. The slideshow is declined
|
|
692
|
+
(#3).
|
|
693
|
+
- No confession lines, no "what we are not", and nobody declined in advance.
|
|
694
|
+
It is an open shop: be honest by being precise, keep it open-ended, and stop
|
|
695
|
+
being absolute.
|
|
696
|
+
<!-- copy-ok: naming the banned adverb -->
|
|
697
|
+
- The adverb "plainly" and its kin are banned, with "plain English".
|
|
698
|
+
- Cut "Our clinic experience so far is one practice" (#8). On the clinics page
|
|
699
|
+
keep "Built and run by us", and describe what Sensphere is: a growing
|
|
700
|
+
practice whose clinicians work remotely (#13).
|
|
701
|
+
- A testimonial (#9) is reworded only once its author approves the new words.
|
|
702
|
+
- Held for their own decisions: e-commerce as a sector (#27), a clinic
|
|
703
|
+
subscription with its own price (#49), response times (#54) and social media
|
|
704
|
+
(#72). Verqan stays off /work (#59). Quarterly packs are declined for the
|
|
705
|
+
site (#53).
|
|
706
|
+
|
|
707
|
+
#### The principles
|
|
708
|
+
|
|
709
|
+
Each id is what a note's `principle` field names in the record.
|
|
710
|
+
|
|
711
|
+
- `open-shop`: precise, never confessional or absolute. Scope is shown by
|
|
712
|
+
exact claims ("the portal we run for Sensphere"), and a contractual fact is
|
|
713
|
+
said as what the buyer gets. `confession-line` reports the shapes for
|
|
714
|
+
review.
|
|
715
|
+
- `summary-pages-carry-substance`: a page that summarises carries a sentence
|
|
716
|
+
of what happens, so nobody has to click away to learn what we do.
|
|
717
|
+
- `problem-then-result`: every case line ends on the result, from the proof
|
|
718
|
+
ledger, or on a description of what now happens.
|
|
719
|
+
- `one-hero-cta`: one button in the hero and on each closing section, with the
|
|
720
|
+
second route as a text link. `hero-cta-pair` reports the pair.
|
|
721
|
+
- `text-links-not-cta-bands`: where a section needs a next step, a text link
|
|
722
|
+
at its end answers "what next", and the page keeps one closing button.
|
|
723
|
+
`cta-band-stock` already reports the band.
|
|
724
|
+
- `tiers-by-what-the-site-carries`: each tier names a different business need
|
|
725
|
+
(one service and a form; several services, comparison and booking), never a
|
|
726
|
+
bigger version of the same promise.
|
|
727
|
+
- `show-the-price-maths`: where a price looks steep, show the split that makes
|
|
728
|
+
it fair (£95 of care plus £70 of website), and put the commercial model where
|
|
729
|
+
the buyer reads.
|
|
730
|
+
- `lists-as-pattern-examples-invitation`: name the pattern, give examples, then
|
|
731
|
+
invite the case we have not met. A closed list of four reads as a menu.
|
|
732
|
+
- `first-phone-screen-is-ours`: the first screen on a phone is the business's
|
|
733
|
+
own headline, line and button. A client's brand, however good the work, comes
|
|
734
|
+
after it and is framed as our work.
|
|
735
|
+
- `no-self-contradiction`: read a page against itself before it ships. Two
|
|
736
|
+
lines that disagree cost more trust than either line earns.
|
|
737
|
+
- `the-work-continues`: the site sells a relationship that carries on, so a
|
|
738
|
+
case, a step or a summary says what we still run.
|
|
739
|
+
|
|
740
|
+
#### The counter-lesson
|
|
741
|
+
|
|
742
|
+
Her diagnoses beat Claude's defaults. Claude's first pass on this review would
|
|
743
|
+
have kept the "What this is and is not" sentence, the two hero buttons, the
|
|
744
|
+
noun-list service cards and three proof numbers in a row. Each is a default
|
|
745
|
+
craft names (`confession-line`, `hero-cta-pair`, the summary-card pattern,
|
|
746
|
+
`stats-row`). Where the question is "does this read as decided and generous to
|
|
747
|
+
the buyer", she was right. Where it is "is it true, and is it allowed", the
|
|
748
|
+
proof ledger and the house rules held: she asked for promises that are not
|
|
749
|
+
live yet (#53, #54, #72), and her replacement wording goes through copy-check
|
|
750
|
+
like anyone's. A reviewer's diagnosis is taken on its merits; her
|
|
751
|
+
words are copy, and copy is checked.
|
|
752
|
+
|
|
753
|
+
#### Feeding later reviews in
|
|
754
|
+
|
|
755
|
+
Every later review, hers or another reviewer's, goes through the
|
|
756
|
+
`reviewer-intake` skill in claude-kit: pull the canvas, keep each note whole,
|
|
757
|
+
classify it, check its facts against the proof ledger, brand facts and Linear,
|
|
758
|
+
write the record under `reviews/<reviewer>/`, and propose tells or fixtures for
|
|
759
|
+
what recurs. `src/__tests__/reviews.test.ts` holds each record to the schema
|
|
760
|
+
and to this file, and fires every tell a note taught on the words it flagged.
|
|
761
|
+
See [reviews/README.md](https://github.com/Doman-Digital/dd-packages/blob/main/packages/craft/reviews/README.md);
|
|
762
|
+
the corpus stays in the repository and is left out of the npm package.
|
|
763
|
+
|
|
635
764
|
## Declaring an exception
|
|
636
765
|
|
|
637
766
|
Doman Digital's own brand is violet. A hue rule with no way to say so flags the
|
|
@@ -1341,7 +1470,7 @@ Generated from the package. Run `pnpm --filter @domandigital/craft run docs`
|
|
|
1341
1470
|
after changing an entry; a test fails until you do.
|
|
1342
1471
|
|
|
1343
1472
|
<!-- craft:catalogue:start -->
|
|
1344
|
-
Catalogue version `2026.10.
|
|
1473
|
+
Catalogue version `2026.10.7`, 76 tells.
|
|
1345
1474
|
|
|
1346
1475
|
| Id | Gen | Surface | Severity | Tell | Why it is a default |
|
|
1347
1476
|
| --- | --- | --- | --- | --- | --- |
|
|
@@ -1360,6 +1489,7 @@ Catalogue version `2026.10.4`, 72 tells.
|
|
|
1360
1489
|
| `cream-palette` | 2 | source + rendered | warn | Cream ground | Once white-and-violet was named, models moved to a warm off-white: parchment, linen, oat. It reads as 'tasteful' in the same way everywhere. |
|
|
1361
1490
|
| `italic-serif-display` | 2 | source + rendered | warn | Italic serif display | A serif heading with one italic word ('Beauty, reimagined') is the second wave's signature move. |
|
|
1362
1491
|
| `hero-eyebrow-chip` | 2 | source + rendered | warn | Eyebrow chip above the hero | A small bordered pill ('New · Now booking') above the headline is in almost every generated hero. |
|
|
1492
|
+
| `hero-cta-pair` | 1 | source + rendered | warn | Two buttons in the hero | A filled button beside an outline or ghost one ('Get a free quote' / 'See our plans') is in 140 of 140 heroes Claude builds for a brief. Two equal asks make the visitor choose before they know anything, and say nobody decided what the page is for. |
|
|
1363
1493
|
| `icon-tile-stack` | 2 | source | warn | Icon in a tinted tile | A library icon in a soft rounded square, stacked above a heading, is the stock card header. |
|
|
1364
1494
|
| `bento-grid` | 2 | source | warn | Bento grid | Mixed-size tiles in a grid became the default 'features' layout of the second wave. |
|
|
1365
1495
|
| `radial-spotlight-glow` | 2 | source + rendered | warn | Radial glow | A soft blurred blob or radial spotlight behind the hero is atmosphere without a subject. |
|
|
@@ -1371,22 +1501,25 @@ Catalogue version `2026.10.4`, 72 tells.
|
|
|
1371
1501
|
| `stock-phrase` | 1 | copy | warn | Stock phrase | Phrases every generated services page uses. They fill space where a fact should be. |
|
|
1372
1502
|
| `ai-phrase` | 1 | copy | warn | AI phrase | Let's dive in, here's the thing, at its core, seamless, rest assured: the phrase list of the house copy rules. A reader has seen each one in a thousand generated pages. |
|
|
1373
1503
|
| `plainer-word` | 1 | copy | warn | A plainer word exists | Empower, leverage, harness, delve: each stands in for a plainer verb, and the swap is a reliable sign nobody chose the word. |
|
|
1374
|
-
| `plain-english` | 2 | copy | warn | 'Plain English' | Told to avoid jargon, a model announces that it is avoiding jargon
|
|
1504
|
+
| `plain-english` | 2 | copy | warn | 'Plain English' | Told to avoid jargon, a model announces that it is avoiding jargon: 'in plain English', 'stated plainly', 'we'll tell you plainly', 'in plain terms'. The founder bans the whole family (20 October 2026); a reader takes it as filler. |
|
|
1375
1505
|
| `buzzword` | 1 | copy | warn | Buzzword | Cutting-edge, world-class, reach out, turnkey: corporate filler older than any model, and still the first thing a model writes about a business it knows nothing about. |
|
|
1376
1506
|
| `negative-reassurance` | 1 | copy | warn | Negative reassurance | 'No hidden fees', 'no surprises', 'never locked in' reassure by naming the fear, and plant it in a reader who did not have it. |
|
|
1377
1507
|
| `vague-word` | 1 | copy | warn | Vague word | Innovative, scalable, end-to-end, solutions: each can be true, and each is used where the writer had nothing specific to say. |
|
|
1378
|
-
| `review-phrase` | 1 | copy | warn | Review-tier phrase | Truly, genuinely, clear, ultimately, 'the single most', 'bar none': normal English once, and a tell when they stack. The house rules keep them for review, never blocking. |
|
|
1508
|
+
| `review-phrase` | 1 | copy | warn | Review-tier phrase | Truly, genuinely, clear, ultimately, 'a plain recommendation', 'the single most', 'bar none': normal English once, and a tell when they stack. The house rules keep them for review, never blocking. |
|
|
1379
1509
|
| `sales-tagline` | 1 | copy | warn | Sales tagline | 'So your budget goes where it counts', 'Real results', 'pages that convert': advert lines that sound like a pitch and say nothing a reader can check. |
|
|
1380
1510
|
| `outcome-promise` | 1 | copy | warn | Outcome promise | 'We'll turn that into enquiries', 'once the first areas are working', 'competitors you can outdo': a hoped-for result written as if it were delivered. Rankings and enquiries depend on things nobody controls. |
|
|
1381
1511
|
| `matey-register` | 2 | copy | warn | Matey register | 'Alright Dave,', 'no worries, we'll get you sorted', 'Quick one:', 'have look at': a put-on, over-familiar British voice, with the small words clipped out. A model asked to sound British writes it; the UK is broad, and a client reads it as cringe and a little rude. |
|
|
1512
|
+
| `confession-line` | 2 | copy | warn | Confession line | 'What this is and is not', 'we have not yet built', 'our experience so far is one practice', 'what we would and wouldn't take on': a model scopes a business by confessing its limits. It reads as small print, and it turns a buyer away before they make contact. |
|
|
1382
1513
|
| `hollow-imperative` | 1 | copy | warn | Hollow imperative | 'Discover', 'Experience', 'Transform your' as the opening verb of a heading or button is a call to action with nothing in it. |
|
|
1383
1514
|
| `rhetorical-opener` | 1 | copy | warn | Rhetorical question opener | 'Looking for...?', 'Tired of...?', 'Ready to...?' opens with the model guessing at the reader instead of telling them something. |
|
|
1384
1515
|
| `em-dash` | 2 | copy | warn | Em dash | Generated copy leans on the em dash to join clauses. House copy does not use it. |
|
|
1385
1516
|
| `emoji` | 1 | copy | warn | Emoji in copy | A sparkle or a rocket beside a heading is decoration a model adds to seem friendly. It dates the page and reads as a social post. |
|
|
1386
|
-
| `not-just-but` | 2 | copy | warn | Contrastive negation | 'It's not just a haircut, it's an experience', 'dispatched from here, not shipped in': the contrast-and-reveal template is the most recognisable construction in generated copy. |
|
|
1517
|
+
| `not-just-but` | 2 | copy | warn | Contrastive negation | 'It's not just a haircut, it's an experience', 'dispatched from here, not shipped in': the contrast-and-reveal template (correctio, antithesis: see COPY.md) is the most recognisable construction in generated copy. |
|
|
1518
|
+
| `trailing-contrast` | 2 | copy | warn | Trailing contrast | 'Edge matters for game servers, not registration', 'the league's own threshold, not a legal one', 'renting computing instead of owning it': the contrast template (correctio, antithesis: see COPY.md) in its softer forms. A genuine disclaimer has the same shape, so a person decides. |
|
|
1387
1519
|
| `no-x-no-y` | 2 | copy | warn | 'No X, no Y' list | 'No obligation, no spam.' Defining the business by what it is not, itemised, is the same template as contrastive negation. |
|
|
1388
1520
|
| `no-x-badge` | 2 | copy | warn | 'No X' badge | 'No catch.', 'NO JARGON GUIDE': a short standalone 'No X' reads as a slapped-on kicker, and worse when the same one is reused across pieces. |
|
|
1389
|
-
| `staccato-triplet` | 2 | copy | warn | Staccato triplet | Three fragments in a row ('Fast. Friendly. Local.' or 'No fuss. No jargon. Just results.') is the second wave's favourite rhythm. |
|
|
1521
|
+
| `staccato-triplet` | 2 | copy | warn | Staccato triplet | Three fragments in a row ('Fast. Friendly. Local.' or 'No fuss. No jargon. Just results.') (a tricolon in asyndeton: see COPY.md) is the second wave's favourite rhythm. |
|
|
1522
|
+
| `parallel-pair` | 2 | copy | warn | Verbless parallel pair | 'One form, seven workflows', 'Same site, same £8,000': two matched fragments with no verb (isocolon, often with anaphora or asyndeton: see COPY.md), the staccato triplet's two-part cousin. It sounds decided and says less than a sentence would. |
|
|
1390
1523
|
| `where-x-meets-y` | 2 | copy | warn | 'Where X meets Y' | 'Where luxury meets comfort' is a tagline shape that fits every business and so describes none. |
|
|
1391
1524
|
| `chatbot-residue` | 1 | copy | warn | Chatbot residue | 'Certainly! Here's a revised version', 'as an AI language model', a citeturn0search0 token, a link tracked utm_source=chatgpt.com: text that exists only because a chat reply was pasted whole. This is evidence, not style. |
|
|
1392
1525
|
| `stock-email-line` | 1 | copy | warn | Stock email line | 'I hope this email finds you well', 'let me know if you have any questions', 'don't hesitate to contact us': the opener and closer of a form email. A client reads past them, and a model drafting an email writes them every time. |
|
package/COPY.md
CHANGED
|
@@ -38,7 +38,10 @@ A single hit fails the check. These are not judgment calls.
|
|
|
38
38
|
- "less about X, more about Y"
|
|
39
39
|
- parallel participle: "shipped from here, not imported from Seoul". Both
|
|
40
40
|
sides must be real participles, so "cosmetics, not medicines" (a plain
|
|
41
|
-
factual contrast) passes
|
|
41
|
+
factual contrast) passes here and is left to `trailing-contrast`.
|
|
42
|
+
- parallel gerund: "renting Microsoft's services, not running servers",
|
|
43
|
+
"delivering services, not managing bookings". "Something" and "nothing"
|
|
44
|
+
are not gerunds.
|
|
42
45
|
- **A "No X" claim as the whole string.** "NO JARGON GUIDE", "No catch." A
|
|
43
46
|
short standalone "No X" reads as a slapped-on badge. Empty-state and error
|
|
44
47
|
text is exempt ("No results found", "No bookings yet"), as is anything under
|
|
@@ -57,7 +60,8 @@ A single hit fails the check. These are not judgment calls.
|
|
|
57
60
|
`in today's rapidly evolving…`, `increasingly digital`,
|
|
58
61
|
`whether you're a X or a Y`, `seamless(ly)`, `unlock your…`,
|
|
59
62
|
`meaningful impact`, `foster collaboration`, `empower`, `leverage`,
|
|
60
|
-
`harness`, `delve`, `a comprehensive guide to`, `plain English
|
|
63
|
+
`harness`, `delve`, `a comprehensive guide to`, `plain English`,
|
|
64
|
+
`plainly`, `in plain terms`, `in plain language`.
|
|
61
65
|
|
|
62
66
|
Also blocking: `in the event that`, `at no additional cost to you`, `rest
|
|
63
67
|
assured`, `it is worth noting that`, `when it comes to`, `we've got you
|
|
@@ -78,7 +82,12 @@ exists. Name the mechanism: "Your team can publish without us", not "we
|
|
|
78
82
|
empower your team".
|
|
79
83
|
|
|
80
84
|
`plain English` has one house replacement: **"properly explained"**.
|
|
81
|
-
"Explained plainly" swaps a synonym and keeps the tell
|
|
85
|
+
"Explained plainly" swaps a synonym and keeps the tell, and so do "stated
|
|
86
|
+
plainly", "we'll tell you plainly" and "in plain terms": the whole family
|
|
87
|
+
blocks (founder, 20 October 2026). Drop the adverb and say the thing. Licence
|
|
88
|
+
text ("must be plainly marked") is let through. `plain` and `clear` describing
|
|
89
|
+
the copy itself ("a plain recommendation", "clear pricing") are review tier,
|
|
90
|
+
in `review-phrase`: say what the reader actually gets.
|
|
82
91
|
|
|
83
92
|
## Review tier
|
|
84
93
|
|
|
@@ -87,9 +96,11 @@ person reading decides which instance earns its place.
|
|
|
87
96
|
|
|
88
97
|
| Tell | What it catches |
|
|
89
98
|
| --- | --- |
|
|
90
|
-
| `review-phrase` | truly, genuinely, deeply, ultimately, clear and clearly ("a clear next step", "clear pricing": say what the reader actually gets), great question, absolutely, one-size-fits-all, and superlative over-claiming: "the single most", "by far the most", "hands down the", "arguably the best", "bar none" |
|
|
99
|
+
| `review-phrase` | truly, genuinely, deeply, ultimately, clear and clearly ("a clear next step", "clear pricing": say what the reader actually gets), plain as a self-description ("plain answers", "a plain recommendation"), great question, absolutely, one-size-fits-all, and superlative over-claiming: "the single most", "by far the most", "hands down the", "arguably the best", "bar none" |
|
|
91
100
|
| `sales-tagline` | advert lines that say nothing a reader can check: "so your budget goes where it counts", "real results", "results that matter", "work harder for you", "pages that convert" |
|
|
92
101
|
| `matey-register` | the put-on British voice: "Alright Dave,", "cheers mate", "no worries", "we'll get you sorted", "proper good", "give me a shout", "chuffed", "Right then,"; and clipped speech that drops the small words: "have look at", "give it go", "Quick one:", "built you a site". Write plain, complete British English |
|
|
102
|
+
| `confession-line` | scoping the business by what it has not done, will not do or is not: "What this is and is not", "we have not yet built", "our clinic experience so far is one practice", "what we would and wouldn't take on", "who we don't work with". It's an open shop: be honest by being precise ("the portal we run for Sensphere") and keep the door open. Contractual facts (eligibility, who runs what) stay, said as what the buyer gets |
|
|
103
|
+
| `trailing-contrast` | the softer contrast template: a noun or phrase after ", not" closing a sentence ("Edge matters for game servers, not registration"), "not a legal one", and "renting computing instead of owning it". A genuine disclaimer has the same shape ("general information, not a recommendation"), so it is reported, never blocked. Say the positive claim; keep the contrast only where the reader would otherwise assume the other thing |
|
|
93
104
|
| `outcome-promise` | a hoped-for result written as delivered: "we'll turn that into enquiries", "once the first areas are working", "competitors you can outdo", "exactly what convinces", "guaranteed rankings", "you'll get more". Promise the work; measure and report the results |
|
|
94
105
|
| `ai-vocabulary` | tapestry, testament, realm, elevate, nestled, meticulous, unparalleled, moreover; and underscore, showcasing, pivotal, measured 10 to 14 times over-used in post-2022 text |
|
|
95
106
|
| `stock-email-line` | the form-email opener and closer: "I hope this email finds you well", "hope you're having a great week", "let me know if you have any questions", "don't hesitate to contact us". Start with the reason for writing; end with the next step and who to ask |
|
|
@@ -97,6 +108,7 @@ person reading decides which instance earns its place.
|
|
|
97
108
|
| `hollow-imperative` | Discover, Experience, Transform, Elevate as the opening verb of a heading or button |
|
|
98
109
|
| `rhetorical-opener` | "Looking for...?", "Tired of...?", "Ready to...?" |
|
|
99
110
|
| `staccato-triplet` | "Fast. Friendly. Local." |
|
|
111
|
+
| `parallel-pair` | the staccato triplet's two-part cousin, two matched fragments with no verb: "One form, seven workflows", "Same site, same £8,000.", "Pay per user, per month", and a verbless list used as a tagline ("Service account, match-day reminders, analytics."). A plain list of names ("Forms, SharePoint, Outlook and Teams") and a sentence with a verb pass. Write the sentence the pair stands for; a short slide label can stay once a person has read it |
|
|
100
112
|
| `where-x-meets-y` | "Where luxury meets comfort" |
|
|
101
113
|
| `ing-tail` | "..., ensuring peace of mind", "..., highlighting our commitment": significance claimed, no mechanism |
|
|
102
114
|
| `vague-attribution` | "studies show", "experts agree", "it is widely known": a claim credited to nobody |
|
|
@@ -109,6 +121,23 @@ person reading decides which instance earns its place.
|
|
|
109
121
|
| `placeholder` | "[Insert client name]", lorem ipsum, `TODO_PLACEHOLDER`. Fine in a draft commit; **zero in anything delivered** |
|
|
110
122
|
| `generic-hero-claim` | on the home page (a root route file, a top-level `index.html`, or a hero or home component), a literal `<h1>` and the paragraph under it that name no place, person, number, price or job: "Quality you can trust", "Your vision, our expertise". One trade noun is not enough ("quality plumbing"); two are ("boiler and radiator repairs"). Also read on the rendered first screen by `craft audit` |
|
|
111
123
|
|
|
124
|
+
### The figures these tells name
|
|
125
|
+
|
|
126
|
+
Several tells are classical figures of speech used as a template. Before
|
|
127
|
+
ruling on a finding you are unsure of, read the definition at the source:
|
|
128
|
+
the figure is the shape, and a line is a hit only when it has the shape.
|
|
129
|
+
Silva Rhetoricae (Brigham Young University) is the reference; Wikipedia
|
|
130
|
+
gives more examples.
|
|
131
|
+
|
|
132
|
+
| Figure | What it is | Tells | Sources |
|
|
133
|
+
| --- | --- | --- | --- |
|
|
134
|
+
| Correctio | defining a thing by saying what it is not, before or after naming it: "dispatched from here, not shipped in" | `not-just-but`, `trailing-contrast` | [Silva](http://rhetoric.byu.edu/Figures/C/correctio.htm) |
|
|
135
|
+
| Antithesis | contrasting words or ideas set side by side, often in parallel structure: "renting services, not running servers" | `not-just-but`, `trailing-contrast` | [Silva](http://rhetoric.byu.edu/Figures/A/antithesis.htm), [Wikipedia](https://en.wikipedia.org/wiki/Antithesis) |
|
|
136
|
+
| Isocolon | a series of elements with the same structure and length: "One form, seven workflows" | `parallel-pair` | [Silva](http://rhetoric.byu.edu/Figures/I/isocolon.htm), [Wikipedia](https://en.wikipedia.org/wiki/Isocolon) |
|
|
137
|
+
| Anaphora | the same word or words opening each of successive phrases: "Same site, same £8,000" | `parallel-pair`, `no-x-no-y` | [Silva](http://rhetoric.byu.edu/Figures/A/anaphora.htm), [Wikipedia](https://en.wikipedia.org/wiki/Anaphora_(rhetoric)) |
|
|
138
|
+
| Asyndeton | leaving out the conjunctions between items: "Service account, match-day reminders, analytics." | `parallel-pair`, `staccato-triplet` | [Silva](http://rhetoric.byu.edu/Figures/A/asyndeton.htm), [Wikipedia](https://en.wikipedia.org/wiki/Asyndeton) |
|
|
139
|
+
| Tricolon | three parallel elements of the same length in a row: "Fast. Friendly. Local." | `staccato-triplet` | [Silva](http://rhetoric.byu.edu/Figures/T/tricolon.htm), [Wikipedia](https://en.wikipedia.org/wiki/Tricolon) |
|
|
140
|
+
|
|
112
141
|
### Style is not evidence
|
|
113
142
|
|
|
114
143
|
Most tells here are house style: they make copy generic, whoever wrote it. The
|
|
@@ -119,12 +148,9 @@ was pasted. Report findings as an editorial diagnosis ("three benefit claims
|
|
|
119
148
|
lack a mechanism; two stock phrases recur"), never as a score or an
|
|
120
149
|
accusation.
|
|
121
150
|
|
|
122
|
-
|
|
123
|
-
|
|
151
|
+
One more review pattern no regex can separate from honest English, so it is
|
|
152
|
+
for the read-through only:
|
|
124
153
|
|
|
125
|
-
- **Trailing contrastive negation**: "Real Square data, not a vanity metric."
|
|
126
|
-
The same shape is how a genuine disclaimer is written ("general information,
|
|
127
|
-
not a recommendation").
|
|
128
154
|
- **Abstract noun triads** with no concrete referent: "clarity, consistency,
|
|
129
155
|
confidence".
|
|
130
156
|
|
package/PRINCIPLES.md
CHANGED
|
@@ -129,3 +129,12 @@ a stakeholder's observation, the visitor problem under it, the proposed fix and
|
|
|
129
129
|
the evidence are judged apart, and the smallest change that answers the problem
|
|
130
130
|
wins. "The existing design is already appropriate" is a result. See
|
|
131
131
|
[Reviewing a proposed change](./CHARACTER.md#reviewing-a-proposed-change).
|
|
132
|
+
|
|
133
|
+
Her review of Doman Digital's own new site (18 and 19 October 2026, 73 notes)
|
|
134
|
+
is kept whole in the reviewer corpus, with the founder's rulings of 20 October,
|
|
135
|
+
and it adds eleven principles and two tells. The main ones: an open shop is honest
|
|
136
|
+
by being precise, never by confessing what it has not done; a summary page
|
|
137
|
+
carries the substance; a case line ends on its result; a hero has one button;
|
|
138
|
+
and the first screen on a phone belongs to the business. Every later review of
|
|
139
|
+
hers feeds craft the same way. See
|
|
140
|
+
[Eunice's review of the DD site](./CHARACTER.md#eunices-review-of-the-dd-site-2026-10-19).
|
package/README.md
CHANGED
|
@@ -121,6 +121,12 @@ no change is needed. Evidence only reported by an audit or a stakeholder cannot
|
|
|
121
121
|
make a problem observed, and a width nobody looked at stays unknown. See
|
|
122
122
|
[Reviewing a proposed change](./CHARACTER.md#reviewing-a-proposed-change).
|
|
123
123
|
|
|
124
|
+
A reviewer's own review is kept whole in the same shape, in the repository's
|
|
125
|
+
reviewer corpus (`packages/craft/reviews/`, left out of the npm package), with
|
|
126
|
+
what was done with each note and the principle it teaches. Eunice Ordor's
|
|
127
|
+
review of the DD site is the first. See
|
|
128
|
+
[Eunice's review of the DD site](./CHARACTER.md#eunices-review-of-the-dd-site-2026-10-19).
|
|
129
|
+
|
|
124
130
|
`--snapshot` accepts saved files and preview or production URLs. Drift fails
|
|
125
131
|
with `--strict`; declared estate comparisons stay advisory. Version 1 files
|
|
126
132
|
still validate with a warning. See [CHARACTER.md](./CHARACTER.md) for the full
|
|
@@ -20,6 +20,67 @@
|
|
|
20
20
|
"type": "string",
|
|
21
21
|
"minLength": 1
|
|
22
22
|
},
|
|
23
|
+
"reviewer": {
|
|
24
|
+
"type": "string",
|
|
25
|
+
"minLength": 1,
|
|
26
|
+
"description": "The person whose review this is, when the file is their record. Each note's raisedBy still says who raised it."
|
|
27
|
+
},
|
|
28
|
+
"date": {
|
|
29
|
+
"type": "string",
|
|
30
|
+
"pattern": "^\\d{4}-\\d{2}-\\d{2}$",
|
|
31
|
+
"description": "The day the review was given."
|
|
32
|
+
},
|
|
33
|
+
"source": {
|
|
34
|
+
"type": "object",
|
|
35
|
+
"description": "Where the review came from, when it is a reviewer's own record (a reviewer corpus under reviews/).",
|
|
36
|
+
"required": [
|
|
37
|
+
"tool"
|
|
38
|
+
],
|
|
39
|
+
"properties": {
|
|
40
|
+
"tool": {
|
|
41
|
+
"type": "string",
|
|
42
|
+
"minLength": 1,
|
|
43
|
+
"description": "pastel, a document, a call, an email."
|
|
44
|
+
},
|
|
45
|
+
"canvas": {
|
|
46
|
+
"type": [
|
|
47
|
+
"integer",
|
|
48
|
+
"string"
|
|
49
|
+
]
|
|
50
|
+
},
|
|
51
|
+
"link": {
|
|
52
|
+
"type": "string"
|
|
53
|
+
},
|
|
54
|
+
"comments": {
|
|
55
|
+
"type": "integer",
|
|
56
|
+
"minimum": 0
|
|
57
|
+
},
|
|
58
|
+
"from": {
|
|
59
|
+
"type": "string"
|
|
60
|
+
},
|
|
61
|
+
"to": {
|
|
62
|
+
"type": "string"
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
},
|
|
66
|
+
"rulings": {
|
|
67
|
+
"type": "object",
|
|
68
|
+
"description": "Who made the final calls recorded in each note's founderRuling, and when.",
|
|
69
|
+
"required": [
|
|
70
|
+
"by",
|
|
71
|
+
"date"
|
|
72
|
+
],
|
|
73
|
+
"properties": {
|
|
74
|
+
"by": {
|
|
75
|
+
"type": "string",
|
|
76
|
+
"minLength": 1
|
|
77
|
+
},
|
|
78
|
+
"date": {
|
|
79
|
+
"type": "string",
|
|
80
|
+
"pattern": "^\\d{4}-\\d{2}-\\d{2}$"
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
},
|
|
23
84
|
"notes": {
|
|
24
85
|
"type": "array",
|
|
25
86
|
"items": {
|
|
@@ -414,6 +475,101 @@
|
|
|
414
475
|
}
|
|
415
476
|
}
|
|
416
477
|
}
|
|
478
|
+
},
|
|
479
|
+
"source": {
|
|
480
|
+
"type": "object",
|
|
481
|
+
"description": "Where the note was left: the tool, and the reference that finds it again.",
|
|
482
|
+
"required": [
|
|
483
|
+
"tool"
|
|
484
|
+
],
|
|
485
|
+
"properties": {
|
|
486
|
+
"tool": {
|
|
487
|
+
"type": "string",
|
|
488
|
+
"minLength": 1
|
|
489
|
+
},
|
|
490
|
+
"canvas": {
|
|
491
|
+
"type": [
|
|
492
|
+
"integer",
|
|
493
|
+
"string"
|
|
494
|
+
]
|
|
495
|
+
},
|
|
496
|
+
"comment": {
|
|
497
|
+
"type": [
|
|
498
|
+
"integer",
|
|
499
|
+
"string"
|
|
500
|
+
],
|
|
501
|
+
"description": "The comment's number as the reviewer sees it."
|
|
502
|
+
},
|
|
503
|
+
"commentId": {
|
|
504
|
+
"type": [
|
|
505
|
+
"integer",
|
|
506
|
+
"string"
|
|
507
|
+
]
|
|
508
|
+
},
|
|
509
|
+
"url": {
|
|
510
|
+
"type": "string",
|
|
511
|
+
"description": "The page the note was left on."
|
|
512
|
+
},
|
|
513
|
+
"at": {
|
|
514
|
+
"type": "string",
|
|
515
|
+
"description": "When it was left, ISO 8601."
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
},
|
|
519
|
+
"verdict": {
|
|
520
|
+
"enum": [
|
|
521
|
+
"praise",
|
|
522
|
+
"take",
|
|
523
|
+
"take-reworded",
|
|
524
|
+
"partly",
|
|
525
|
+
"decline",
|
|
526
|
+
"founder-decision",
|
|
527
|
+
"known"
|
|
528
|
+
],
|
|
529
|
+
"description": "What was done with the note. take-reworded: the diagnosis is taken and the suggested wording rewritten (it is copy-checked like any other). partly: the aim is taken, by a smaller or different change. known: already tracked, no change here."
|
|
530
|
+
},
|
|
531
|
+
"founderRuling": {
|
|
532
|
+
"type": "object",
|
|
533
|
+
"required": [
|
|
534
|
+
"date",
|
|
535
|
+
"ruling"
|
|
536
|
+
],
|
|
537
|
+
"properties": {
|
|
538
|
+
"date": {
|
|
539
|
+
"type": "string",
|
|
540
|
+
"pattern": "^\\d{4}-\\d{2}-\\d{2}$"
|
|
541
|
+
},
|
|
542
|
+
"ruling": {
|
|
543
|
+
"type": "string",
|
|
544
|
+
"minLength": 1
|
|
545
|
+
}
|
|
546
|
+
},
|
|
547
|
+
"description": "The founder's call where the note needed one, stated as the decision and nothing more."
|
|
548
|
+
},
|
|
549
|
+
"principle": {
|
|
550
|
+
"type": "string",
|
|
551
|
+
"pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*$",
|
|
552
|
+
"description": "The id of the principle the note teaches, as written up in CHARACTER.md."
|
|
553
|
+
},
|
|
554
|
+
"tells": {
|
|
555
|
+
"type": "array",
|
|
556
|
+
"description": "Craft tells the note informed. With text, the words that tell must fire on.",
|
|
557
|
+
"items": {
|
|
558
|
+
"type": "object",
|
|
559
|
+
"required": [
|
|
560
|
+
"id"
|
|
561
|
+
],
|
|
562
|
+
"properties": {
|
|
563
|
+
"id": {
|
|
564
|
+
"type": "string",
|
|
565
|
+
"pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*$"
|
|
566
|
+
},
|
|
567
|
+
"text": {
|
|
568
|
+
"type": "string",
|
|
569
|
+
"minLength": 1
|
|
570
|
+
}
|
|
571
|
+
}
|
|
572
|
+
}
|
|
417
573
|
}
|
|
418
574
|
}
|
|
419
575
|
}
|
|
@@ -9,10 +9,10 @@ import {
|
|
|
9
9
|
snapshotPage,
|
|
10
10
|
snapshotUrl,
|
|
11
11
|
snapshotUrls
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-A7KUKNX6.js";
|
|
13
13
|
import "./chunk-JYNXGCYZ.js";
|
|
14
|
-
import "./chunk-
|
|
15
|
-
import "./chunk-
|
|
14
|
+
import "./chunk-3LCBLDAO.js";
|
|
15
|
+
import "./chunk-KIBDFRHT.js";
|
|
16
16
|
import "./chunk-QYBAVU3P.js";
|
|
17
17
|
export {
|
|
18
18
|
PROVENANCE_BUDGET_MS,
|