feat(design-review,plan-design-review): craft audit carved on every host, Persuade plan checks, craft tells as catalog entries (GSTA-92 phase 2)

Size pins and caps raised to measured sizes only: design-review (13 hosts), plan-design-review (12), design-consultation (9), design-consultation maxSizeRatio, and the new design-review parity guard. Garry 2026-10-25 "Do it" (GSTA-92).

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
This commit is contained in:
garrytanandcapy-ai[bot] committed 2026-10-25 23:01:53 +00:00
1 parent 98316193c6
commit f9d825bee6
23 files changed
+511 -75

No files matched your search

+31
View File
@@ -0,0 +1,31 @@
/**
* Craft resolvers shared by /design-review's craft audit and /plan-design-review.
*
* {{DESIGN_CRAFT_RULE:<lead>}} renders one paragraph of design-html's craft
* section verbatim, found by its bold lead (`**Ship floor.**`), with the
* bullets under it, so the audit holds a page to the rules /design-html builds
* it to and the two cannot drift. A renamed lead fails generation.
*
* {{DESIGN_PERSUADE_CHECKS}} is the five conversion checks, phrased to hold for
* a built page and for a plan of one. Adapted from Elaya's landing-page-design
* and redesign-skill (MIT); see NOTICE.md.
*/
import * as fs from 'fs';
import * as path from 'path';
import type { ResolverFn } from './types';
const CRAFT_SECTION = path.resolve(import.meta.dir, '../../design-html/sections/craft.md.tmpl');
export const DESIGN_CRAFT_RULE: ResolverFn = (_ctx, args) => {
const lead = args?.join(':');
if (!lead) throw new Error('{{DESIGN_CRAFT_RULE:<lead>}} requires the bold lead of a craft paragraph');
const paragraph = fs.readFileSync(CRAFT_SECTION, 'utf-8').split(/\n{2,}/).find(p => p.startsWith(`**${lead}`));
if (!paragraph) throw new Error(`{{DESIGN_CRAFT_RULE:${lead}}}: no paragraph starting "**${lead}" in design-html/sections/craft.md.tmpl`);
return paragraph.trimEnd();
};
export const DESIGN_PERSUADE_CHECKS: ResolverFn = () => `1. **One primary action**, named; nothing competes with it above the fold, and the closing CTA repeats it.
2. **Named objections**: the visitor's top objections, each answered where it arises (FAQ of real questions, comparison, guarantee).
3. **Proof beside each claim**: a supplied customer, quote or figure next to the claim it supports, never a metric row; an unsupported claim is cut or marked \`[Needs proof: …]\`.
4. **A risk reversal** the business really offers (free plan, trial, no card, cancel anytime, refund); never an invented one.
5. **An index/noindex decision**: an ad-only or time-bound page is \`noindex\`; an indexed one has a real title and description, and its FAQ ships as FAQPage JSON-LD.`;
+3
View File
@@ -39,6 +39,7 @@ import { generateDxFramework, generateDxErrorCompact, generateDxErrorItems } fro
import { generateGBrainContextLoad, generateGBrainSaveResults, generateBrainPreflight, generateBrainCacheRefresh, generateBrainWriteBack } from './gbrain';
import { generateTasksSectionEmit, generateTasksSectionAggregate } from './tasks-section';
import { SECTION, SECTION_INDEX } from './sections';
import { DESIGN_CRAFT_RULE, DESIGN_PERSUADE_CHECKS } from './design-craft';
import { generateRedactInvocationBlock } from './redact-doc';
import { generateFreeTextFile } from './free-text-file';
import { FOREGROUND_DISPATCH_NOTE, codexSelect } from './constants';
@@ -109,6 +110,8 @@ export const RESOLVERS: Record<string, ResolverFn> = {
DESIGN_DETECTOR: generateDesignDetector,
DESIGN_MD_CHECK: generateDesignMdCheck,
DESIGN_SLOP_BULLETS: generateDesignSlopBullets,
DESIGN_CRAFT_RULE,
DESIGN_PERSUADE_CHECKS,
UX_PRINCIPLES: generateUXPrinciples,
DESIGN_OUTSIDE_VOICES: generateDesignOutsideVoices,
DESIGN_REVIEW_LITE: generateDesignReviewLite,
+1 -1
View File
@@ -27,7 +27,7 @@ export const QA_ASSET_BLOCKER = 'If missing or unreadable, report a QA setup blo
/** Skills carved on every host: QA (portable assets) and those whose external
* render would exceed SKILL_BYTE_CEILING inlined (C4, #2777). */
const CARVED_ON_EVERY_HOST = ['qa', 'qa-only', 'ship', 'plan-ceo-review', 'office-hours'];
const CARVED_ON_EVERY_HOST = ['qa', 'qa-only', 'ship', 'plan-ceo-review', 'office-hours', 'design-review'];
/** Hosts read at most this many UTF-8 bytes of one SKILL.md (~40K tokens). */
export const SKILL_BYTE_CEILING = 160_000;