demiurge-peitho 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.
- package/CLAUDE.md +84 -0
- package/LICENSE +21 -0
- package/README.md +138 -0
- package/SKILL.md +83 -0
- package/bin/peitho.js +138 -0
- package/docs/HONEST-NUMBERS.md +38 -0
- package/lib/gate.js +132 -0
- package/lib/pipeline.js +77 -0
- package/lib/siblings.js +74 -0
- package/package.json +12 -0
- package/references/assets/ads.md +71 -0
- package/references/assets/business-ideas.md +52 -0
- package/references/assets/cold-outreach.md +52 -0
- package/references/assets/content-calendar.md +54 -0
- package/references/assets/content-kit.md +49 -0
- package/references/assets/hooks.md +63 -0
- package/references/assets/landing-page.md +60 -0
- package/references/assets/long-form-script.md +58 -0
- package/references/assets/newsletter.md +58 -0
- package/references/assets/persuasive-case.md +48 -0
- package/references/assets/pitch-deck.md +67 -0
- package/references/assets/sales-objections.md +64 -0
- package/references/competitor-teardown.md +74 -0
- package/references/offer-pricing.md +81 -0
- package/references/positioning.md +151 -0
- package/references/swot.md +70 -0
package/CLAUDE.md
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# PEITHO companion (guided setup and ongoing help)
|
|
2
|
+
|
|
3
|
+
You are Claude, reading this inside the PEITHO repo or skill folder. You are the setup companion and, after setup, the ongoing guide. One step at a time, plain language, never pressure an optional step.
|
|
4
|
+
|
|
5
|
+
## What PEITHO is (tell them in one line)
|
|
6
|
+
|
|
7
|
+
Every AI tool writes marketing copy. PEITHO refuses to ship a line a competitor could have written, and it will not let a headline exist before the positioning does.
|
|
8
|
+
|
|
9
|
+
## When to reach for it (say this once)
|
|
10
|
+
|
|
11
|
+
- **PEITHO** once something exists and must be sold: positioning, pricing, landing page, launch posts, ads, pitch, cold outreach.
|
|
12
|
+
- **ATHENA** when the question is whether to enter a market or build the thing at all. Positioning is execution; that question is a decision.
|
|
13
|
+
- **ZOILUS** judges the copy as an artifact. PEITHO produces it and never self-approves.
|
|
14
|
+
- **PYRRHO** owns what the numbers say. No conversion claim ships without passing it.
|
|
15
|
+
|
|
16
|
+
## Setup, conversationally
|
|
17
|
+
|
|
18
|
+
1. **Install is one copy.** `SKILL.md`, `lib/`, `bin/` and `references/` into `~/.claude/skills/peitho/`. Show the command for their OS before running it.
|
|
19
|
+
|
|
20
|
+
PowerShell:
|
|
21
|
+
```powershell
|
|
22
|
+
Copy-Item -Recurse . "$env:USERPROFILE\.claude\skills\peitho"
|
|
23
|
+
```
|
|
24
|
+
bash:
|
|
25
|
+
```bash
|
|
26
|
+
cp -r . ~/.claude/skills/peitho
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
2. **Check it landed.** `node bin/peitho.js setup` prints a state-aware readout.
|
|
30
|
+
|
|
31
|
+
3. **Try one thing.** Have them run the line that sells the product:
|
|
32
|
+
```powershell
|
|
33
|
+
node bin/peitho.js line "We help teams work smarter."
|
|
34
|
+
```
|
|
35
|
+
It blocks, names the cliche it matched, and tells them what to do about it.
|
|
36
|
+
|
|
37
|
+
4. **Zero config.** No API key, no account, no service. The gate runs locally with no model call.
|
|
38
|
+
|
|
39
|
+
## The rule that matters most
|
|
40
|
+
|
|
41
|
+
**Positioning before copy.** Do not let them ask you for a headline first. Build the positioning state file (five Dunford components, the angles with their tests, the priced offer), run `peitho check`, and only produce assets when it returns ALLOWED. This is not advice, it is a return value: `canProduceAssets` returns BLOCKED with the reasons named.
|
|
42
|
+
|
|
43
|
+
If they push for copy anyway, tell them plainly: a headline written before the wedge exists is decoration. Then help them build the wedge, which takes ten minutes and is the actual work.
|
|
44
|
+
|
|
45
|
+
## The second rule
|
|
46
|
+
|
|
47
|
+
**PEITHO never grades its own pitch.** When copy is ready, run the ship-gate in order:
|
|
48
|
+
|
|
49
|
+
1. `peitho gate <copy.md>` (blocking findings stop the ship)
|
|
50
|
+
2. ZOILUS copy-critique lens (where a skeptical reader drops off), blind to the maker
|
|
51
|
+
3. VERITAS anti-slop pass
|
|
52
|
+
4. CALLIOPE if the asset has a visual surface. PEITHO writes the words, CALLIOPE designs the frame.
|
|
53
|
+
|
|
54
|
+
If a sibling is missing, say so and continue rather than blocking. Recommend it once, never nag.
|
|
55
|
+
|
|
56
|
+
## The CLI helpers (all zero-LLM)
|
|
57
|
+
|
|
58
|
+
```
|
|
59
|
+
peitho gate <copy.md> the anti-generic gate on a whole page
|
|
60
|
+
peitho line "<one line>" gate a single line
|
|
61
|
+
peitho hype <file|text> scan for hype vocabulary
|
|
62
|
+
peitho check <state.json> may we produce assets yet?
|
|
63
|
+
peitho position <state.json> are all five Dunford components present?
|
|
64
|
+
peitho bets <state.json> does every angle carry a cheapest test?
|
|
65
|
+
peitho setup
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
`position` and `bets` accept either a bare object or a full state file.
|
|
69
|
+
|
|
70
|
+
## Ongoing companion duties (never retire)
|
|
71
|
+
|
|
72
|
+
- When they write a claim about conversion, stop. Route it through PYRRHO before it reaches a page.
|
|
73
|
+
- When the gate flags low specificity, remember it is a heuristic. Read the line yourself. Do not blindly rewrite good copy because a regex was unsure.
|
|
74
|
+
- When the same rejection keeps firing, offer CHIRON: a rejection you keep hitting should become a permanent rule.
|
|
75
|
+
- Honest limit, tell them once: PEITHO proves copy clears a gate. It cannot prove the copy sells more. That is what the cheapest test attached to every angle is for.
|
|
76
|
+
|
|
77
|
+
## Laws you must not break
|
|
78
|
+
|
|
79
|
+
1. Nothing generic. If a line could run unchanged on a competitor's page, it fails.
|
|
80
|
+
2. Positioning before copy. No headline until the wedge exists.
|
|
81
|
+
3. Every angle carries its cheapest test and the metric that decides.
|
|
82
|
+
4. The customer's words, not yours.
|
|
83
|
+
5. Hype omitted. Zero hype vocabulary, zero em dashes, in the product and in anything you write about it. A single em dash here is a self-own.
|
|
84
|
+
6. Never claim a conversion lift without a real test.
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Lee Jun Ying
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
|
|
3
|
+

|
|
4
|
+
|
|
5
|
+
# PEITHO: Positioning Earned, Instinct Tested, Hype Omitted
|
|
6
|
+
|
|
7
|
+
*Every AI tool writes you marketing copy. PEITHO refuses to ship a line a competitor could have written.*
|
|
8
|
+
|
|
9
|
+
[](LICENSE)
|
|
10
|
+
[](package.json)
|
|
11
|
+
[](benchmarks/run.js)
|
|
12
|
+
|
|
13
|
+
</div>
|
|
14
|
+
|
|
15
|
+
**Every AI tool writes you marketing copy. PEITHO refuses to ship a line a competitor could have written.**
|
|
16
|
+
|
|
17
|
+
> I am Peitho. Persuasion was my domain. I never mistook it for volume.
|
|
18
|
+
|
|
19
|
+
*Positioning Earned, Instinct Tested, Hype Omitted.*
|
|
20
|
+
|
|
21
|
+
Copy generators are a commodity. Every model writes a passable landing page. That is not the hard part, and it never was. The hard part is refusing the line that sounds fine and means nothing. I do that mechanically, and I do not let you write a headline before you know why anyone should choose you.
|
|
22
|
+
|
|
23
|
+
## Before and after
|
|
24
|
+
|
|
25
|
+
**Your AI, asked for a landing page:**
|
|
26
|
+
|
|
27
|
+
> We help teams work smarter.
|
|
28
|
+
|
|
29
|
+
**PEITHO, handed the same line:**
|
|
30
|
+
|
|
31
|
+
```
|
|
32
|
+
$ peitho line "We help teams work smarter."
|
|
33
|
+
|
|
34
|
+
[blocking] generic-anywhere: cliche: matches \bwe help (?:teams|companies|businesses|people)\b
|
|
35
|
+
fix: Rewrite until the line could only belong to this offer.
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
It never reaches a page. Neither does an em dash, neither does `unleash`, and neither does a headline written before the positioning exists.
|
|
39
|
+
|
|
40
|
+
## The proof, not the promise
|
|
41
|
+
|
|
42
|
+
I was tested against the thing I claim to beat. Same product, same brief. One landing page written by a single-shot "write me a landing page" prompt. One written through my pipeline: position, offer, assets, gate.
|
|
43
|
+
|
|
44
|
+
Two independent critics scored both. Neither knew how either page was made. They were shown the pages **in opposite orders** to control for position bias.
|
|
45
|
+
|
|
46
|
+
| | one-shot | PEITHO pipeline |
|
|
47
|
+
|---|---|---|
|
|
48
|
+
| Critic 1 (control first) | 6/10 | **8/10** |
|
|
49
|
+
| Critic 2 (pipeline first) | 6/10 | **8/10** |
|
|
50
|
+
| Deterministic gate | 7 blocking findings, 10 em dashes | **passed clean** |
|
|
51
|
+
| Chosen by | | **both critics** |
|
|
52
|
+
|
|
53
|
+
**The honest caveat:** one of the two critics still passed the one-shot page, weakly, calling it "a strong 40-line page wearing a 114-line page." So "the one-shot fails" held for one critic of two, not both. The pipeline won on every measure taken. It did not annihilate the control, and I will not tell you it did.
|
|
54
|
+
|
|
55
|
+
## The five laws
|
|
56
|
+
|
|
57
|
+
1. **Nothing generic.** If a line could run unchanged on a competitor's page, it fails. Checked against a cliche corpus and a specificity test, not against my feelings.
|
|
58
|
+
2. **Positioning before copy.** No hooks, no headlines, no ads until the wedge exists. `peitho check` returns BLOCKED until all five positioning components are present, every angle carries a test, and the offer is priced.
|
|
59
|
+
3. **Every angle carries its cheapest test.** Name the two angles you would bet budget on, how to test each this week, and the metric that decides. An untested angle is a guess wearing a suit.
|
|
60
|
+
4. **The customer's words, not yours.** Lead with the outcome they want, in their language. Features are not benefits.
|
|
61
|
+
5. **Hype omitted.** Zero hype vocabulary. Zero em dashes. Checked, not trusted.
|
|
62
|
+
|
|
63
|
+
And one structural law: **I never grade my own pitch.** The ship-gate hands the copy to ZOILUS (where does a skeptical reader drop off) and VERITAS (anti-slop). A seller marking its own homework is how generic copy ships.
|
|
64
|
+
|
|
65
|
+
And the reader-side counterpart: **the zero-context test.** Copy is judged as the coldest reader, someone who has seen none of the strategy, the roadmap, or this conversation. If that reader cannot understand the line and act on it, the line does not ship, however good it sounds to the room that wrote it.
|
|
66
|
+
|
|
67
|
+
## A gate that knows what it does not know
|
|
68
|
+
|
|
69
|
+
The gate separates two things on purpose:
|
|
70
|
+
|
|
71
|
+
- **Blocking**: a demonstrable cliche, hype vocabulary, an em dash. Provable. Stops the ship.
|
|
72
|
+
- **Flag**: low specificity. A heuristic. It warns, it does not block.
|
|
73
|
+
|
|
74
|
+
Because a rule that blocks real copy on a guess is worse than the generic line it was hunting. The test suite pins this: `It never sees who wrote the code.` flags but does not block, while `We help companies save time and money.` blocks.
|
|
75
|
+
|
|
76
|
+
## Install for your agent
|
|
77
|
+
|
|
78
|
+
> **From npm:** `npm install -g demiurge-peitho`, then `peitho setup` — or `npx demiurge-peitho gate <copy.md>` with no install. (Skill copy uses the source clone below.)
|
|
79
|
+
|
|
80
|
+
PowerShell:
|
|
81
|
+
```powershell
|
|
82
|
+
git clone https://github.com/eragonlonelyboy-lab/peitho; cd peitho; node bin/peitho.js setup
|
|
83
|
+
```
|
|
84
|
+
bash:
|
|
85
|
+
```bash
|
|
86
|
+
git clone https://github.com/eragonlonelyboy-lab/peitho && cd peitho && node bin/peitho.js setup
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
Copy the folder into `~/.claude/skills/peitho/` and invoke with `/peitho`. Zero config. The CLI is the deterministic half:
|
|
90
|
+
|
|
91
|
+
```
|
|
92
|
+
peitho gate <copy.md> the anti-generic gate on a whole page
|
|
93
|
+
peitho line "<one line>" gate a single line
|
|
94
|
+
peitho hype <file> scan for hype vocabulary
|
|
95
|
+
peitho check <state.json> may we produce assets yet?
|
|
96
|
+
peitho position <state.json> are all five Dunford components present?
|
|
97
|
+
peitho bets <state.json> does every angle carry a cheapest test?
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
## Not for you if
|
|
101
|
+
|
|
102
|
+
- You want copy fast and you do not care whether anyone could tell it apart from your competitor's.
|
|
103
|
+
- You want a tool that tells you the copy will convert. It cannot, and it says so.
|
|
104
|
+
- You want to skip positioning. `peitho check` will not let you, and that is the product.
|
|
105
|
+
|
|
106
|
+
## FAQ
|
|
107
|
+
|
|
108
|
+
**"So it is a copywriter."**
|
|
109
|
+
No. Every model is a copywriter. I am the thing that refuses what the copywriter produced.
|
|
110
|
+
|
|
111
|
+
**"Can you prove your copy sells more?"**
|
|
112
|
+
No, and be suspicious of anyone who says they can without a real test. I can prove copy clears a gate. Claiming a conversion lift without running the experiment is precisely what I exist to prevent. Before any numeric claim ships, it passes PYRRHO.
|
|
113
|
+
|
|
114
|
+
**"Your cliche list will go stale."**
|
|
115
|
+
It will. Language moves and a finite corpus lags it. See [HONEST-NUMBERS](docs/HONEST-NUMBERS.md), where I list what I miss.
|
|
116
|
+
|
|
117
|
+
**"Why can't I write the headline first?"**
|
|
118
|
+
Because a headline written before the wedge is decoration. `peitho check` returns BLOCKED and names what is missing. It is a return value, not advice.
|
|
119
|
+
|
|
120
|
+
## The family
|
|
121
|
+
|
|
122
|
+
**ATHENA** decides whether to enter the market. **PEITHO** executes the go-to-market once the decision is made. **ZOILUS** judges the copy as an artifact. **VERITAS** cleans the prose. **CALLIOPE** designs the frame, I write the words, in that order. **PYRRHO** owns what the numbers say, so no conversion claim ships without passing it.
|
|
123
|
+
|
|
124
|
+
**HORKOS** proves the campaign shipped. **MONETA** budgets the loop. **CHIRON** turns a repeated rejection into a rule.
|
|
125
|
+
|
|
126
|
+
The working standard the whole house runs on is public too: [ARETE](https://github.com/eragonlonelyboy-lab/arete), five discipline gates any model can run. PEITHO's zero-context test is its reporting gate, applied to a landing page.
|
|
127
|
+
|
|
128
|
+
## Verify me
|
|
129
|
+
|
|
130
|
+
```bash
|
|
131
|
+
node benchmarks/run.js # 27/27
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
If PEITHO stops one borrowed line from reaching your landing page, star it. If it does not, do not.
|
|
135
|
+
|
|
136
|
+
MIT. Copyright (c) 2026 Lee Jun Ying. Built by Eragon Lee.
|
|
137
|
+
|
|
138
|
+
*Named for Peitho, Greek goddess of persuasion and charming speech.*
|
package/SKILL.md
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: peitho
|
|
3
|
+
description: The go-to-market god. Use PEITHO to position, price, and sell anything you have built: the wedge, the offer, the landing page, the launch post, the ads, the pitch, the cold outreach. It refuses to write a headline before the positioning exists, rejects any line a competitor could have written unchanged, and makes every angle carry the cheapest test that would settle it. Trigger on "position this", "write the landing page", "how do I launch this", "price this", "/peitho". Not for deciding WHETHER to enter a market (that is ATHENA), and it never grades its own pitch (that is ZOILUS).
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# PEITHO: the go-to-market god
|
|
7
|
+
|
|
8
|
+
> Peitho, goddess of persuasion and charming speech. Persuasion was her domain; she never mistook it for volume.
|
|
9
|
+
|
|
10
|
+
**Every AI tool writes you marketing copy. PEITHO refuses to ship a line a competitor could have written.**
|
|
11
|
+
|
|
12
|
+
Copy generators are a commodity. Every model writes a passable landing page. PEITHO's value is not the copy, it is the discipline around the copy: positioning before words, a gate that rejects the generic, and a cheapest test attached to every claim you intend to bet on.
|
|
13
|
+
|
|
14
|
+
## When to use / when not
|
|
15
|
+
|
|
16
|
+
- **Use PEITHO** once something exists and must be sold: positioning, pricing, landing page, launch posts, ads, pitch decks, cold outreach, content.
|
|
17
|
+
- **Not for deciding whether** to enter a market, build the thing, or pursue a strategy. That is **ATHENA** (wisdom of a decision). Positioning is execution.
|
|
18
|
+
- **PEITHO never grades its own pitch.** The ship-gate delegates to **ZOILUS** (copy-critique: where does a skeptical reader drop off) and **VERITAS** (anti-slop). A seller marking its own homework is how generic copy ships.
|
|
19
|
+
|
|
20
|
+
## The five laws (non-negotiable)
|
|
21
|
+
|
|
22
|
+
**Zero-context handoff test.** Before a sales or launch asset ships, give only the artifact, offer facts and target reader to a fresh reviewer. It must identify the audience, promise, proof, action and major caveat without access to the maker's reasoning. If it cannot, the handoff failed even when the original team agrees with the copy.
|
|
23
|
+
|
|
24
|
+
1. **Nothing generic.** If a line could run unchanged on a competitor's page, it fails. `peitho gate` enforces this mechanically: cliche corpus, plus a specificity test (no number, no proper noun, no quoted term means the line could name any product).
|
|
25
|
+
2. **Positioning before copy.** No hooks, no headlines, no ads until the wedge exists. `peitho check` refuses to let the assets stage run until all five Dunford components are present, every angle carries a test, and the offer is priced.
|
|
26
|
+
3. **Every angle carries its cheapest test.** Name the two angles you would bet real budget on and how to test each this week, plus the metric that decides. An untested angle is a guess wearing a suit.
|
|
27
|
+
4. **The customer's words, not yours.** Lead with the outcome the customer wants, in their language. Features are not benefits.
|
|
28
|
+
5. **Hype omitted.** Zero hype vocabulary, zero em dashes. Checked, not trusted.
|
|
29
|
+
|
|
30
|
+
## The lifecycle
|
|
31
|
+
|
|
32
|
+
**Mode 0 - WHAT TO SELL** (optional, upstream). Venture ideas matched to real skills, budget and time, each with a buyer, a first-ten-customers plan, unit economics, and the one risk to test cheaply this month.
|
|
33
|
+
|
|
34
|
+
**Mode 1 - POSITION** (nothing else runs first). Load the reference, do not work from memory.
|
|
35
|
+
- **Dunford positioning** (`references/positioning.md`): the five components, and the statement template `For [segment] who [need], [offer] is the [category] that [key benefit], unlike [alternative], because [proof].` Plus three differentiated messaging hooks and the "where your positioning is weak" note.
|
|
36
|
+
- **Seven angles** (`references/positioning.md`), one per named psychological driver: status, fear of missing out, identity, ease, speed, belonging, transformation. Then the two you would bet budget on and a cheap test for each this week.
|
|
37
|
+
- **Competitor teardown** (`references/competitor-teardown.md`): six sections, label anything speculative, name the one thing of theirs you should NOT copy because it only works at their scale, end with "The wedge:" and one sentence.
|
|
38
|
+
- **SWOT** (`references/swot.md`): 3 to 4 points per quadrant, internal and external split, two cross-pairs (Strength x Opportunity, Weakness x Threat), end with "This month:".
|
|
39
|
+
- **Output:** positioning statement, the wedge line, two bets, their tests. Validate with `peitho position` and `peitho bets`.
|
|
40
|
+
|
|
41
|
+
**Mode 2 - OFFER** (`references/offer-pricing.md`). Score the offer out of 10 on clarity, desirability and believability, each with the reason and what would raise it. Surface the **five** objections most likely to kill the sale, not three. Give the price verdict (too high, too low, or mismatched) with a better-fitting model, three ways to make it a no-brainer, and end with "The tightened offer:" and one sentence. **Output:** offer, price, guarantee, five objections with answers.
|
|
42
|
+
|
|
43
|
+
**Mode 3 - ASSETS** (only once `peitho check` says ALLOWED). **Each asset has a reference file carrying its section structure, named taxonomies, constraints and quality bar. Load it. Do not write the asset from memory.**
|
|
44
|
+
|
|
45
|
+
| Asset | Reference | The structure it must not lose |
|
|
46
|
+
|---|---|---|
|
|
47
|
+
| Landing page | `references/assets/landing-page.md` | 11 labelled sections, grade 6 reading level |
|
|
48
|
+
| Hooks | `references/assets/hooks.md` | 10 hooks, one per named angle, ranked top 3 |
|
|
49
|
+
| Ads | `references/assets/ads.md` | 8 variations, one per named angle, which two to test and the deciding metric |
|
|
50
|
+
| Pitch deck | `references/assets/pitch-deck.md` | 10 slides in order, 3 parts each |
|
|
51
|
+
| Cold outreach | `references/assets/cold-outreach.md` | 3 versions under 90 words, plus the 4-day follow-up |
|
|
52
|
+
| Sales objections | `references/assets/sales-objections.md` | **seven** objections including the unspoken ones, 4 parts each |
|
|
53
|
+
| Content calendar | `references/assets/content-calendar.md` | 30 days across 4 journey stages, 80/20 value ratio |
|
|
54
|
+
| Content kit | `references/assets/content-kit.md` | 6 sections, every quote findable word for word |
|
|
55
|
+
| Long-form script | `references/assets/long-form-script.md` | 5-second hook, re-hook, open loops, pattern interrupt |
|
|
56
|
+
| Newsletter | `references/assets/newsletter.md` | subject plus 2 alternatives, preview text, one idea only |
|
|
57
|
+
| Persuasive case | `references/assets/persuasive-case.md` | 5 parts, `[ADD SOURCE]` rather than an invented source |
|
|
58
|
+
| Business ideas (Mode 0) | `references/assets/business-ideas.md` | 7 ideas, 6-part format, ranked top 3 by fit |
|
|
59
|
+
|
|
60
|
+
Every reference also carries that prompt's **intake questions**. Ask them before producing. An asset written before its intake is answered is decoration.
|
|
61
|
+
|
|
62
|
+
**Mode 4 - GATE** (before anything ships).
|
|
63
|
+
1. `peitho gate <copy>`, the anti-generic gate. Blocking findings stop the ship.
|
|
64
|
+
2. **ZOILUS copy-critique lens**, where a skeptical, time-poor reader drops off; the dead weight; the one highest-leverage fix. Blind to the maker.
|
|
65
|
+
3. **VERITAS**, anti-slop pass, voice preserved.
|
|
66
|
+
4. **CALLIOPE** if the asset has a visual surface. PEITHO writes the words, CALLIOPE designs the frame, in that order.
|
|
67
|
+
|
|
68
|
+
Fail the gate, rewrite, re-run. Budget-capped, like every Demiurge loop.
|
|
69
|
+
|
|
70
|
+
## Boundaries (do not blur the pantheon)
|
|
71
|
+
|
|
72
|
+
- **ATHENA** decides. PEITHO executes go-to-market once the decision is made.
|
|
73
|
+
- **ZOILUS** judges the copy as an artifact. PEITHO produces it and never self-approves.
|
|
74
|
+
- **VERITAS** owns prose hygiene. PEITHO composes with it, never reimplements it.
|
|
75
|
+
- **CALLIOPE** owns the visual. PEITHO owns the words.
|
|
76
|
+
- **PYRRHO** owns what the numbers say. If PEITHO wants to claim a result, PYRRHO decides whether the data carries it. No conversion-lift claim ships without passing PYRRHO.
|
|
77
|
+
- **HORKOS** proves it shipped. **MONETA** budgets. **CHIRON** turns a repeated rejection into a rule.
|
|
78
|
+
|
|
79
|
+
## Honest limit
|
|
80
|
+
PEITHO can prove its copy clears a gate. It cannot prove the copy sells more. Anyone claiming a numeric conversion lift without a real test is doing exactly what this god exists to prevent. See `docs/HONEST-NUMBERS.md`.
|
|
81
|
+
|
|
82
|
+
## Sibling recommendation
|
|
83
|
+
On setup, detect installed siblings and recommend only the missing natural pairs: ZOILUS (the copy gate), VERITAS (anti-slop), CALLIOPE (the visual half), PYRRHO (before any numeric claim).
|
package/bin/peitho.js
ADDED
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
// peitho, the go-to-market god. Deterministic CLI half (zero-LLM): the
|
|
4
|
+
// anti-generic gate, the positioning-before-copy check, the every-angle-has-a-test
|
|
5
|
+
// check. The persuasion is skill-driven (SKILL.md); this is what refuses to ship.
|
|
6
|
+
const fs = require('fs');
|
|
7
|
+
const { gateCopy, gateLine, scanHype } = require('../lib/gate');
|
|
8
|
+
const { canProduceAssets, validatePositioning, validateAngles, screenIdeas } = require('../lib/pipeline');
|
|
9
|
+
const siblings = require('../lib/siblings');
|
|
10
|
+
const pkg = require('../package.json');
|
|
11
|
+
|
|
12
|
+
const args = process.argv.slice(2);
|
|
13
|
+
const cmd = args[0];
|
|
14
|
+
const out = (s) => process.stdout.write(s + '\n');
|
|
15
|
+
const readJson = (f) => JSON.parse(fs.readFileSync(f, 'utf8'));
|
|
16
|
+
|
|
17
|
+
switch (cmd) {
|
|
18
|
+
case '--version': case '-v': out(`peitho ${pkg.version}`); break;
|
|
19
|
+
|
|
20
|
+
case 'gate': {
|
|
21
|
+
const file = args[1];
|
|
22
|
+
if (!file || !fs.existsSync(file)) { out('usage: peitho gate <copy.md>'); process.exit(1); }
|
|
23
|
+
const r = gateCopy(fs.readFileSync(file, 'utf8'));
|
|
24
|
+
if (r.pass) { out('PASS: no generic lines, no hype, no em dashes.'); break; }
|
|
25
|
+
out(`FAIL: ${r.blocking} blocking finding(s).\n`);
|
|
26
|
+
for (const l of r.perLine) {
|
|
27
|
+
out(` line ${l.line}: ${l.text}`);
|
|
28
|
+
for (const f of l.findings) out(` [${f.severity}] ${f.id}: ${f.summary}\n fix: ${f.fix}`);
|
|
29
|
+
}
|
|
30
|
+
process.exit(1);
|
|
31
|
+
break;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
case 'line': {
|
|
35
|
+
const line = args.slice(1).join(' ');
|
|
36
|
+
if (!line) { out('usage: peitho line "<one line of copy>"'); process.exit(1); }
|
|
37
|
+
const r = gateLine(line);
|
|
38
|
+
if (r.pass) { out('PASS'); break; }
|
|
39
|
+
for (const f of r.findings) out(`[${f.severity}] ${f.id}: ${f.summary}\n fix: ${f.fix}`);
|
|
40
|
+
process.exit(1);
|
|
41
|
+
break;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
case 'hype': {
|
|
45
|
+
const file = args[1];
|
|
46
|
+
const text = file && fs.existsSync(file) ? fs.readFileSync(file, 'utf8') : args.slice(1).join(' ');
|
|
47
|
+
const hits = scanHype(text);
|
|
48
|
+
out(hits.length ? 'hype words: ' + hits.join(', ') : 'no hype words.');
|
|
49
|
+
process.exit(hits.length ? 1 : 0);
|
|
50
|
+
break;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
case 'check': {
|
|
54
|
+
// peitho check state.json -> may we produce assets yet?
|
|
55
|
+
const file = args[1];
|
|
56
|
+
if (!file || !fs.existsSync(file)) { out('usage: peitho check <state.json>'); process.exit(1); }
|
|
57
|
+
const r = canProduceAssets(readJson(file));
|
|
58
|
+
if (r.allowed) { out('ALLOWED: positioning locked, every angle carries a test, offer priced. Assets may be produced.'); break; }
|
|
59
|
+
out('BLOCKED: you do not get a headline yet.');
|
|
60
|
+
for (const b of r.blockers) out(' - ' + b);
|
|
61
|
+
process.exit(1);
|
|
62
|
+
break;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
case 'position': {
|
|
66
|
+
const file = args[1];
|
|
67
|
+
if (!file || !fs.existsSync(file)) { out('usage: peitho position <positioning.json | state.json>'); process.exit(1); }
|
|
68
|
+
const doc = readJson(file);
|
|
69
|
+
const r = validatePositioning(doc && doc.positioning ? doc.positioning : doc); // accept a full state file too
|
|
70
|
+
out(r.ok ? 'OK: all five positioning components present.' : 'INCOMPLETE: missing ' + r.missing.join(', '));
|
|
71
|
+
process.exit(r.ok ? 0 : 1);
|
|
72
|
+
break;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
case 'bets': {
|
|
76
|
+
const file = args[1];
|
|
77
|
+
if (!file || !fs.existsSync(file)) { out('usage: peitho bets <angles.json | state.json>'); process.exit(1); }
|
|
78
|
+
const doc = readJson(file);
|
|
79
|
+
const r = validateAngles(Array.isArray(doc) ? doc : (doc && doc.angles)); // accept a full state file too
|
|
80
|
+
out(r.ok ? `OK: ${r.count} angle(s), every one carries a test and a metric.` : `FAIL: angles without a cheapest test: ${r.untested.join(', ')}`);
|
|
81
|
+
process.exit(r.ok ? 0 : 1);
|
|
82
|
+
break;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
case 'ideas': {
|
|
86
|
+
const file = args[1];
|
|
87
|
+
if (!file || !fs.existsSync(file)) { out('usage: peitho ideas <ideas.json> (Mode 0: what to sell)'); process.exit(1); }
|
|
88
|
+
const doc = readJson(file);
|
|
89
|
+
const r = screenIdeas(Array.isArray(doc) ? doc : (doc && doc.ideas));
|
|
90
|
+
if (r.ok) { out(`OK: ${r.count} idea(s), each with a buyer, a first-ten plan, unit economics and a cheap risk test.`); break; }
|
|
91
|
+
out('INCOMPLETE: an idea without a buyer, unit economics and a cheap risk test is a daydream.');
|
|
92
|
+
for (const i of r.incomplete) out(` - ${i.name}: missing ${i.missing.join(', ')}`);
|
|
93
|
+
process.exit(1);
|
|
94
|
+
break;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
case 'siblings': {
|
|
98
|
+
const s = siblings.detect();
|
|
99
|
+
out('installed: ' + (s.installed.join(', ') || 'none'));
|
|
100
|
+
const rec = siblings.recommend(s.installed);
|
|
101
|
+
out('recommended (missing ship-gate pairs): ' + (rec.map((r) => r.name).join(', ') || 'none, the gate is complete'));
|
|
102
|
+
for (const r of rec) out(` - ${r.name}: ${r.why}`);
|
|
103
|
+
break;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
case 'gate-route': {
|
|
107
|
+
const stage = args[1];
|
|
108
|
+
if (!stage) { out('usage: peitho gate-route <copy-critique|anti-slop|visual|numeric-claim>'); break; }
|
|
109
|
+
out(`${stage} -> ${siblings.routeGate(stage)}`);
|
|
110
|
+
break;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
case 'setup': {
|
|
114
|
+
out('PEITHO setup check');
|
|
115
|
+
out('------------------');
|
|
116
|
+
out(` SKILL.md : ${fs.existsSync(__dirname + '/../SKILL.md') ? 'yes' : 'MISSING'}`);
|
|
117
|
+
out('');
|
|
118
|
+
out('PEITHO is skill-first: invoke it with /peitho or "position and launch this".');
|
|
119
|
+
out('This CLI is the deterministic half: the anti-generic gate and the positioning-before-copy law.');
|
|
120
|
+
out('PEITHO writes. ZOILUS judges the copy. VERITAS cleans it. CALLIOPE designs the frame.');
|
|
121
|
+
out('It never grades its own pitch.');
|
|
122
|
+
break;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
default:
|
|
126
|
+
out(`peitho ${pkg.version}, positioning earned, instinct tested, hype omitted`);
|
|
127
|
+
out('');
|
|
128
|
+
out(' peitho gate <copy.md> the anti-generic gate on a whole page');
|
|
129
|
+
out(' peitho line "<one line>" gate a single line');
|
|
130
|
+
out(' peitho hype <file|text> scan for hype vocabulary');
|
|
131
|
+
out(' peitho check <state.json> may we produce assets yet? (positioning first)');
|
|
132
|
+
out(' peitho position <p.json> are all five Dunford components present?');
|
|
133
|
+
out(' peitho bets <angles.json> does every angle carry a cheapest test?');
|
|
134
|
+
out(' peitho ideas <ideas.json> Mode 0: does each idea carry a buyer and a cheap risk test?');
|
|
135
|
+
out(' peitho siblings detect installed Demiurge gods');
|
|
136
|
+
out(' peitho gate-route <stage> which god owns this ship-gate stage');
|
|
137
|
+
out(' peitho setup');
|
|
138
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# HONEST-NUMBERS
|
|
2
|
+
|
|
3
|
+
Every claim PEITHO makes about itself, and every one it cannot make. A product whose first law is "nothing generic" does not get to sell itself with a generic claim.
|
|
4
|
+
|
|
5
|
+
## What is checkable
|
|
6
|
+
|
|
7
|
+
`node benchmarks/run.js` runs 27 deterministic tests, no model involved. They prove:
|
|
8
|
+
|
|
9
|
+
- **The gate rejects the demonstrably borrowed.** `We help teams work smarter.` blocks on the cliche corpus. `Unleash your revolutionary workflow.` blocks on hype vocabulary. Any em dash blocks.
|
|
10
|
+
- **The gate does not reject the specific.** `PEITHO refuses to ship a line a competitor could have written.` passes. `Reviews 145 prompts and rejects 35 of them.` passes. An ALL-CAPS brand token counts as specificity even at the start of a line.
|
|
11
|
+
- **Positioning before copy is a return value.** `canProduceAssets` returns BLOCKED, with the reasons named, until all five Dunford components exist, every angle carries a test and a metric, and the offer has a price and its killing objections. A headline cannot be produced from positioning alone.
|
|
12
|
+
- **An angle without a cheapest test is rejected**, and zero angles does not quietly count as "all angles tested."
|
|
13
|
+
|
|
14
|
+
## The blind A/B, with its caveat
|
|
15
|
+
|
|
16
|
+
PEITHO's pipeline was tested against a single-shot "write me a landing page" prompt on the same product with the same brief. Two independent critics scored both pages against the ZOILUS copy-critique rubric. Neither knew how either page was produced, and they were shown the pages in opposite orders to control for position bias.
|
|
17
|
+
|
|
18
|
+
Both critics scored the pipeline page 8/10 and the one-shot 6/10. Both chose the pipeline page. The deterministic gate found 7 blocking findings and 10 em dashes in the one-shot; the pipeline page passed clean.
|
|
19
|
+
|
|
20
|
+
**The caveat, stated plainly:** one of the two critics still passed the one-shot page, weakly. The intended criterion was "the one-shot does not pass." That held for one critic of two. The pipeline won on every measure taken. It did not annihilate the control.
|
|
21
|
+
|
|
22
|
+
Two critics is not a study. It is one honest test, run once, reported with its limits.
|
|
23
|
+
|
|
24
|
+
## What is NOT checkable
|
|
25
|
+
|
|
26
|
+
**PEITHO cannot prove the copy converts.** It proves copy clears a gate. Conversion is an empirical question about your market, and answering it requires running the test PEITHO tells you to run. Any tool claiming a conversion lift without that test is doing exactly what this one exists to prevent. Before any numeric claim ships, it passes PYRRHO.
|
|
27
|
+
|
|
28
|
+
**The low-specificity check is a heuristic.** It flags rather than blocks, deliberately, because a rule that blocks real copy on a guess is worse than the generic line it was hunting. It will miss a thoroughly generic line dressed in a proper noun, and it will flag a good short sentence that happens to carry no number or name.
|
|
29
|
+
|
|
30
|
+
**The cliche corpus is finite and will lag language.** Today's fresh phrasing is next year's entry. The corpus is plain markdown in `lib/gate.js`; when a new cliche escapes it, add it. Absence from the corpus is not proof a line is original.
|
|
31
|
+
|
|
32
|
+
**Taste is not fully checkable.** The gate catches the provable failures. Whether the copy is actually persuasive, whether the wedge is the right wedge, whether a reader cares: those are judgments. That is why the ship-gate delegates to ZOILUS and VERITAS rather than pretending its own taste is oracle.
|
|
33
|
+
|
|
34
|
+
**Positioning validation is structural, not semantic.** `peitho position` confirms all five Dunford components are present. It cannot confirm they are true, or that your claimed unique attribute is actually unique. It checks that you did the work, not that the work was right.
|
|
35
|
+
|
|
36
|
+
## What it costs
|
|
37
|
+
|
|
38
|
+
Nothing to run the gate. It is a skill and a zero-LLM CLI; the corpus checks and the pipeline validation run locally with no model call. The writing is done by whatever agent invoked the skill, and the ship-gate calls ZOILUS and VERITAS, each of which costs whatever they cost.
|
package/lib/gate.js
ADDED
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
// gate.js, the anti-generic gate.
|
|
3
|
+
// Law 1: if a line could run unchanged on a competitor's page, it fails.
|
|
4
|
+
// Law 5: hype omitted, zero em dashes. Both are checkable, so we check them
|
|
5
|
+
// rather than trusting a model to feel bad about writing "unleash".
|
|
6
|
+
|
|
7
|
+
const HYPE = [
|
|
8
|
+
'unleash', 'game-changer', 'game changer', 'game-changing', 'revolutionary', 'revolutionize',
|
|
9
|
+
'elevate', 'seamless', 'seamlessly', 'cutting-edge', 'state-of-the-art', 'best-in-class',
|
|
10
|
+
'next level', 'next-level', 'supercharge', 'turbocharge', 'delve', 'harness the power',
|
|
11
|
+
'empower', 'synergy', 'paradigm shift', 'disruptive', 'world-changing', 'transformative',
|
|
12
|
+
'work smarter', 'take it to the next level', 'unlock the power', 'navigate the landscape',
|
|
13
|
+
'in today’s world', 'in today\'s world', 'robust solution', 'holistic solution',
|
|
14
|
+
];
|
|
15
|
+
|
|
16
|
+
// Lines that could belong to any company in any industry.
|
|
17
|
+
const CLICHE = [
|
|
18
|
+
/\bwe help (?:teams|companies|businesses|people)\b/i,
|
|
19
|
+
/\bwork smarter\b/i,
|
|
20
|
+
/\bsave time and money\b/i,
|
|
21
|
+
/\bbuilt for (?:the )?modern\b/i,
|
|
22
|
+
/\bthe future of\b/i,
|
|
23
|
+
/\ball[- ]in[- ]one (?:platform|solution)\b/i,
|
|
24
|
+
/\bpowerful(?:ly)? (?:simple|easy)\b/i,
|
|
25
|
+
/\bdesigned to help you\b/i,
|
|
26
|
+
/\btake your \w+ to the next level\b/i,
|
|
27
|
+
/\bmade simple\b/i,
|
|
28
|
+
];
|
|
29
|
+
|
|
30
|
+
// CHI-R001: spell the banned characters as escapes so this lint never matches
|
|
31
|
+
// itself, and so a bulk "strip the em dashes" pass cannot silently rewrite the
|
|
32
|
+
// detector into one that flags ordinary hyphens. (It did, once. Hence the rule.)
|
|
33
|
+
const EM_DASH = /[\u2014\u2013]/;
|
|
34
|
+
|
|
35
|
+
// An inline code span is a quoted token, not shipped prose. Naming the word you
|
|
36
|
+
// ban is not using it. Strip `like this` before judging a line, or the gate
|
|
37
|
+
// flags your own documentation. Same family as CHI-R001: a lint must never match
|
|
38
|
+
// the act of describing what it forbids.
|
|
39
|
+
function stripInlineCode(text) {
|
|
40
|
+
return String(text || '').replace(/`[^`]*`/g, ' ');
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function scanHype(text) {
|
|
44
|
+
const t = stripInlineCode(text).toLowerCase();
|
|
45
|
+
return HYPE.filter((h) => t.includes(h.toLowerCase()));
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function hasEmDash(text) { return EM_DASH.test(String(text || '')); }
|
|
49
|
+
|
|
50
|
+
// Specificity signals: a digit, a quoted term, an ALL-CAPS brand token anywhere
|
|
51
|
+
// (PEITHO, ZOILUS), or a capitalised word past the first (which would otherwise
|
|
52
|
+
// just be the sentence-initial capital).
|
|
53
|
+
function hasSpecificity(s) {
|
|
54
|
+
if (/\d/.test(s)) return true;
|
|
55
|
+
if (/["“].+?["”]/.test(s)) return true;
|
|
56
|
+
const words = s.split(/\s+/);
|
|
57
|
+
if (words.some((w) => /^[A-Z]{2,}[A-Z0-9]*[.,!?]?$/.test(w))) return true; // ALL-CAPS brand
|
|
58
|
+
return words.slice(1).some((w) => /^[A-Z][a-zA-Z]{2,}/.test(w));
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// Two distinct failures, deliberately weighted differently:
|
|
62
|
+
// cliche -> demonstrable, blocking. The line is provably borrowed.
|
|
63
|
+
// low specificity -> a heuristic, so it flags rather than blocks. A rule that
|
|
64
|
+
// blocks real copy on a guess is worse than the generic line it was hunting.
|
|
65
|
+
function genericAnywhere(line) {
|
|
66
|
+
const raw = String(line || '').trim();
|
|
67
|
+
if (!raw) return { generic: false, blocking: false, reasons: [] };
|
|
68
|
+
const s = stripInlineCode(raw).trim(); // a named example is not a shipped claim
|
|
69
|
+
if (!s) return { generic: false, blocking: false, reasons: [] };
|
|
70
|
+
const reasons = [];
|
|
71
|
+
let blocking = false;
|
|
72
|
+
|
|
73
|
+
for (const re of CLICHE) {
|
|
74
|
+
if (re.test(s)) { reasons.push(`cliche: matches ${re.source}`); blocking = true; }
|
|
75
|
+
}
|
|
76
|
+
if (!hasSpecificity(s)) {
|
|
77
|
+
reasons.push('low specificity: no number, no proper noun, no quoted term. Check that this line could only belong to this offer.');
|
|
78
|
+
}
|
|
79
|
+
return { generic: reasons.length > 0, blocking, reasons };
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// Gate a single line. pass = zero BLOCKING findings (flags are advisory).
|
|
83
|
+
function gateLine(line) {
|
|
84
|
+
const findings = [];
|
|
85
|
+
const hype = scanHype(line);
|
|
86
|
+
if (hype.length) findings.push({ severity: 'blocking', id: 'hype-vocabulary', summary: `Hype words present: ${hype.join(', ')}`, fix: 'Say the specific thing instead.' });
|
|
87
|
+
if (hasEmDash(line)) findings.push({ severity: 'blocking', id: 'em-dash', summary: 'Em or en dash present.', fix: 'Use a comma, a period, or a colon.' });
|
|
88
|
+
const g = genericAnywhere(line);
|
|
89
|
+
if (g.blocking) {
|
|
90
|
+
findings.push({ severity: 'blocking', id: 'generic-anywhere', summary: g.reasons.filter((r) => r.startsWith('cliche')).join(' | '), fix: 'Rewrite until the line could only belong to this offer.' });
|
|
91
|
+
} else if (g.generic) {
|
|
92
|
+
findings.push({ severity: 'major', id: 'low-specificity', summary: g.reasons.join(' | '), fix: 'Add the number, the name, or the concrete noun that makes this yours.' });
|
|
93
|
+
}
|
|
94
|
+
const blocking = findings.filter((f) => f.severity === 'blocking').length;
|
|
95
|
+
return { pass: blocking === 0, blocking, findings };
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// Gate a whole block of copy, line by line. Structure and quoted material are
|
|
99
|
+
// not claims you are shipping, so they are exempt: blank lines, headings, rules,
|
|
100
|
+
// fenced code, and blockquotes. A blockquote is usually the bad example you are
|
|
101
|
+
// holding up to mock, and gating it would flag your own before-and-after.
|
|
102
|
+
function gateCopy(text) {
|
|
103
|
+
const lines = String(text || '').split('\n');
|
|
104
|
+
const perLine = [];
|
|
105
|
+
let inFence = false;
|
|
106
|
+
lines.forEach((raw, i) => {
|
|
107
|
+
const line = raw.trim();
|
|
108
|
+
if (/^(```|~~~)/.test(line)) { inFence = !inFence; return; }
|
|
109
|
+
if (inFence) return;
|
|
110
|
+
if (!line || /^#{1,6}\s/.test(line) || /^[-*_]{3,}$/.test(line) || /^>/.test(line)) return;
|
|
111
|
+
const r = gateLine(line);
|
|
112
|
+
if (r.findings.length) perLine.push({ line: i + 1, text: line, findings: r.findings });
|
|
113
|
+
});
|
|
114
|
+
const blocking = perLine.reduce((n, l) => n + l.findings.filter((f) => f.severity === 'blocking').length, 0);
|
|
115
|
+
const flags = perLine.reduce((n, l) => n + l.findings.filter((f) => f.severity === 'major').length, 0);
|
|
116
|
+
return { pass: blocking === 0, blocking, flags, perLine };
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// The fresh reviewer supplies only what they can recover from the artifact.
|
|
120
|
+
// This gate compares that zero-context readback with the offer owner's facts;
|
|
121
|
+
// agreement inside the producing session is deliberately irrelevant.
|
|
122
|
+
function zeroContextHandoff(expected = {}, observed = {}) {
|
|
123
|
+
const fields = ['audience', 'promise', 'proof', 'action', 'caveat'];
|
|
124
|
+
const missing = fields.filter((k) => !String(observed[k] || '').trim());
|
|
125
|
+
const mismatched = fields.filter((k) => {
|
|
126
|
+
if (!String(observed[k] || '').trim() || !String(expected[k] || '').trim()) return false;
|
|
127
|
+
return String(observed[k]).trim().toLowerCase() !== String(expected[k]).trim().toLowerCase();
|
|
128
|
+
});
|
|
129
|
+
return { pass: missing.length === 0 && mismatched.length === 0, missing, mismatched };
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
module.exports = { gateLine, gateCopy, zeroContextHandoff, scanHype, hasEmDash, genericAnywhere, HYPE, CLICHE };
|