feat(design-consultation): font procedure, role-scoped overused list, color strategies

The proposal section stops handing out a font menu. "Choosing faces: a
procedure, not a menu" names the subject's world, shortlists per role,
strikes the overused list for that role, verifies availability in-session,
and states the loading strategy. {{OVERUSED_FONTS}} renders the role-scoped
lists from lib/design-catalog.ts: overused as display (the detector's
overused-font set plus the training-data defaults), fine as body/UI on an
Operate or Read surface, mono for data and code, banned in any role, and a
short verified-free list with its verification date. Color approaches become
Restrained / Committed / Full palette / Drenched. The anti-convergence
directive drops light-vs-dark as a dial (it comes from the use scene) and the
three-looks calibration sits under Your Design Knowledge. The slop list is
{{DESIGN_SLOP_BULLETS}}: prose from the catalog, no rule ids, polish-level
tells omitted.

design-html's "Never include (AI slop blacklist)" list keeps its literal
(carve guard) and each line now carries a trailing <!-- id --> naming a
catalog entry, pinned by test/design-catalog.test.ts so the last surviving
duplicate is derived-by-test. Both resolvers are registered and listed in
ARCHITECTURE.md. No carve-guard or budget re-baseline needed.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
Garry Tan
2026-09-08 15:45:58 +00:00
co-authored by Claude Fable 5.1
parent 9825bfdbb7
commit 71505f8374
9 changed files with 156 additions and 78 deletions
+22 -1
View File
@@ -1,6 +1,6 @@
import { type TemplateContext, toShellPath } from './types';
import { AI_SLOP_BLACKLIST, OPENAI_HARD_REJECTIONS, OPENAI_LITMUS_CHECKS, CODEX_WEB_SEARCH_FLAG, CC_BACKGROUND_DEFAULT_SINCE } from './constants';
import { DESIGN_SLOP_CATALOG, OVERUSED_FONTS_DISPLAY, selectCatalog, catalogEntry } from '../../lib/design-catalog';
import { DESIGN_SLOP_CATALOG, OVERUSED_FONTS_DISPLAY, BANNED_FONTS, FONTS_BODY_UI_OK, FONTS_MONO_OK, FONTS_VERIFIED_FREE, selectCatalog, catalogEntry, renderCatalog } from '../../lib/design-catalog';
export function generateDesignReviewLite(ctx: TemplateContext): string {
const litmusList = OPENAI_LITMUS_CHECKS.map((item, i) => `${i + 1}. ${item}`).join(' ');
@@ -808,6 +808,27 @@ ${ctx.paths.binDir}/gstack-review-log '{"skill":"design-outside-voices","timesta
Replace STATUS with "clean" or "issues_found", SOURCE with "codex+subagent", "codex-only", "subagent-only", or "unavailable".`;
}
// ─── Overused fonts (role-scoped) + slop bullets for the proposal skills ───
// The font procedure and the role-scoped lists are derived from
// pbakaus/impeccable reference/new-work.md (Apache-2.0), rewritten. See NOTICE.md.
export function generateOverusedFonts(_ctx: TemplateContext): string {
const free = FONTS_VERIFIED_FREE;
return `**Overused as display** (never the display voice on a Persuade or Experience surface; the detector flags several as \`overused-font\`): ${OVERUSED_FONTS_DISPLAY.join(', ')}.
**Fine as body/UI on an Operate or Read surface when the proposal says so:** ${FONTS_BODY_UI_OK.join(', ')}. **Mono for data and code:** ${FONTS_MONO_OK.join(', ')}.
**Banned in any role:** ${BANNED_FONTS.join(', ')}.
**Freely available faces on no default list** (verified ${free.verified}; re-verify in-session before naming one): ${free.fontshare.join(', ')} (Fontshare); ${free.googleFonts.join(', ')} (Google Fonts). Short on purpose. A long list of "good" fonts is how the last convergence happened.
User asks for a listed face by name: comply, state the tradeoff once.`;
}
/** Prose-only slop bullets for the proposal skills: no ids, polish-level tells omitted. */
export function generateDesignSlopBullets(_ctx: TemplateContext): string {
return renderCatalog({ kind: 'slop', style: 'bullets', omitImpact: ['polish'] });
}
// ─── Design Hard Rules (OpenAI framework + gstack slop catalog) ───
// Modes (Persuade/Operate/Read/Experience), the craft-floor reflexes, and the
// three-looks calibration are derived from pbakaus/impeccable reference/craft-floor.md
+3 -1
View File
@@ -19,7 +19,7 @@ import type { TemplateContext, ResolverFn } from './types';
// Domain modules
import { generatePreamble } from './preamble';
import { generateTestFailureTriage } from './preamble';
import { generateDesignMethodology, generateDesignHardRules, generateDesignOutsideVoices, generateDesignReviewLite, generateDesignSketch, generateDesignSetup, generateDesignMockup, generateDesignShotgunLoop, generateTasteProfile, generateUXPrinciples } from './design';
import { generateDesignMethodology, generateDesignHardRules, generateDesignOutsideVoices, generateDesignReviewLite, generateDesignSketch, generateDesignSetup, generateDesignMockup, generateDesignShotgunLoop, generateTasteProfile, generateUXPrinciples, generateOverusedFonts, generateDesignSlopBullets } from './design';
import { generateTestBootstrap, generateTestCoverageAuditPlan, generateTestCoverageAuditShip } from './testing';
import { generateReviewDashboard, generatePlanFileReviewReport, generateExitPlanModeGate, generateAntiShortcutClause, generateSpecReviewLoop, generateBenefitsFrom, generateCodexSecondOpinion, generateAdversarialStep, generateCodexPlanReview, generateCodexDocReview, generatePlanCompletionAuditShip, generatePlanCompletionAuditReview, generatePlanVerificationExec, generateScopeDrift, generateCrossReviewDedup } from './review';
import { generateSlugEval, generateSlugSetup, generateBaseBranchDetect, generateDeployBootstrap, generateQAMethodology, generateCoAuthorTrailer, generateChangelogWorkflow, generateCodexWebSearchFlag, generateSetupCommand } from './utility';
@@ -59,6 +59,8 @@ export const RESOLVERS: Record<string, ResolverFn> = {
QA_METHODOLOGY: generateQAMethodology,
DESIGN_METHODOLOGY: generateDesignMethodology,
DESIGN_HARD_RULES: generateDesignHardRules,
OVERUSED_FONTS: generateOverusedFonts,
DESIGN_SLOP_BULLETS: generateDesignSlopBullets,
UX_PRINCIPLES: generateUXPrinciples,
DESIGN_OUTSIDE_VOICES: generateDesignOutsideVoices,
DESIGN_REVIEW_LITE: generateDesignReviewLite,