forgedock 1.0.17 → 1.0.19
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/README.md +34 -1
- package/bin/cross-publish.mjs +344 -0
- package/bin/forgedock.mjs +229 -17
- package/commands/autopilot.md +77 -0
- package/commands/design-bench.md +176 -0
- package/commands/design-render-critique-loop.md +103 -0
- package/commands/design.md +259 -0
- package/commands/issue.md +7 -3
- package/commands/orchestrate.md +121 -0
- package/commands/{resume.md → pipeline-resume.md} +4 -4
- package/commands/{status.md → pipeline-status.md} +1 -1
- package/commands/qa-sweep.md +37 -2
- package/commands/quality-gate.md +57 -0
- package/commands/review-pr-staging.md +158 -2
- package/commands/test-gate.md +929 -0
- package/commands/work-on/build/implement.md +5 -3
- package/commands/work-on.md +53 -3
- package/docs/CI.md +177 -0
- package/docs/FORGE-PROTOCOL.md +324 -0
- package/docs/articles/b-vs-c-baseline.md +210 -0
- package/docs/articles/full-abc-benchmark.md +205 -0
- package/docs/articles/selective-spec-loading-token-savings.md +140 -0
- package/docs/design/abc-benchmark.md +195 -0
- package/docs/design/design-architect-rationale.md +123 -0
- package/docs/design/design-memory.md +61 -0
- package/docs/design/design-spec-schema.md +248 -0
- package/docs/design/design-system-lint.md +150 -0
- package/docs/design/divergent-generation.md +106 -0
- package/docs/design/effects-appropriateness.md +133 -0
- package/docs/design/fixtures/briefs/README.md +47 -0
- package/docs/design/fixtures/briefs/cadence.md +39 -0
- package/docs/design/fixtures/briefs/plume.md +39 -0
- package/docs/design/fixtures/briefs/slipstream.md +39 -0
- package/docs/design/fixtures/briefs/tender.md +39 -0
- package/docs/design/fixtures/briefs/voltage.md +39 -0
- package/docs/design/fixtures/runs/b-vs-c-baseline/cadence/arm-b/run-1.html +364 -0
- package/docs/design/fixtures/runs/b-vs-c-baseline/cadence/arm-b/run-2.html +420 -0
- package/docs/design/fixtures/runs/b-vs-c-baseline/cadence/arm-b/run-3.html +506 -0
- package/docs/design/fixtures/runs/b-vs-c-baseline/plume/arm-b/run-1.html +611 -0
- package/docs/design/fixtures/runs/b-vs-c-baseline/plume/arm-b/run-2.html +594 -0
- package/docs/design/fixtures/runs/b-vs-c-baseline/plume/arm-b/run-3.html +817 -0
- package/docs/design/fixtures/runs/b-vs-c-baseline/runs.json +175 -0
- package/docs/design/fixtures/runs/b-vs-c-baseline/scorecard.json +138 -0
- package/docs/design/fixtures/runs/b-vs-c-baseline/slipstream/arm-b/run-1.html +373 -0
- package/docs/design/fixtures/runs/b-vs-c-baseline/slipstream/arm-b/run-2.html +398 -0
- package/docs/design/fixtures/runs/b-vs-c-baseline/slipstream/arm-b/run-3.html +595 -0
- package/docs/design/fixtures/runs/b-vs-c-baseline/tender/arm-b/run-1.html +531 -0
- package/docs/design/fixtures/runs/b-vs-c-baseline/tender/arm-b/run-2.html +565 -0
- package/docs/design/fixtures/runs/b-vs-c-baseline/tender/arm-b/run-3.html +674 -0
- package/docs/design/fixtures/runs/b-vs-c-baseline/voltage/arm-b/run-1.html +388 -0
- package/docs/design/fixtures/runs/b-vs-c-baseline/voltage/arm-b/run-2.html +463 -0
- package/docs/design/fixtures/runs/b-vs-c-baseline/voltage/arm-b/run-3.html +568 -0
- package/docs/design/fixtures/runs/full-abc/cadence/arm-a/run-1.html +562 -0
- package/docs/design/fixtures/runs/full-abc/cadence/arm-a/run-2.html +618 -0
- package/docs/design/fixtures/runs/full-abc/cadence/arm-a/run-3.html +618 -0
- package/docs/design/fixtures/runs/full-abc/cadence/arm-b/run-1.html +364 -0
- package/docs/design/fixtures/runs/full-abc/cadence/arm-b/run-2.html +420 -0
- package/docs/design/fixtures/runs/full-abc/cadence/arm-b/run-3.html +506 -0
- package/docs/design/fixtures/runs/full-abc/plume/arm-a/run-1.html +527 -0
- package/docs/design/fixtures/runs/full-abc/plume/arm-a/run-2.html +445 -0
- package/docs/design/fixtures/runs/full-abc/plume/arm-a/run-3.html +483 -0
- package/docs/design/fixtures/runs/full-abc/plume/arm-b/run-1.html +611 -0
- package/docs/design/fixtures/runs/full-abc/plume/arm-b/run-2.html +594 -0
- package/docs/design/fixtures/runs/full-abc/plume/arm-b/run-3.html +817 -0
- package/docs/design/fixtures/runs/full-abc/runs.json +190 -0
- package/docs/design/fixtures/runs/full-abc/scorecard.json +144 -0
- package/docs/design/fixtures/runs/full-abc/slipstream/arm-a/run-1.html +496 -0
- package/docs/design/fixtures/runs/full-abc/slipstream/arm-a/run-2.html +447 -0
- package/docs/design/fixtures/runs/full-abc/slipstream/arm-a/run-3.html +564 -0
- package/docs/design/fixtures/runs/full-abc/slipstream/arm-b/run-1.html +373 -0
- package/docs/design/fixtures/runs/full-abc/slipstream/arm-b/run-2.html +398 -0
- package/docs/design/fixtures/runs/full-abc/slipstream/arm-b/run-3.html +595 -0
- package/docs/design/fixtures/runs/full-abc/tender/arm-a/run-1.html +622 -0
- package/docs/design/fixtures/runs/full-abc/tender/arm-a/run-2.html +475 -0
- package/docs/design/fixtures/runs/full-abc/tender/arm-a/run-3.html +660 -0
- package/docs/design/fixtures/runs/full-abc/tender/arm-b/run-1.html +531 -0
- package/docs/design/fixtures/runs/full-abc/tender/arm-b/run-2.html +565 -0
- package/docs/design/fixtures/runs/full-abc/tender/arm-b/run-3.html +674 -0
- package/docs/design/fixtures/runs/full-abc/voltage/arm-a/run-1.html +525 -0
- package/docs/design/fixtures/runs/full-abc/voltage/arm-a/run-2.html +446 -0
- package/docs/design/fixtures/runs/full-abc/voltage/arm-a/run-3.html +463 -0
- package/docs/design/fixtures/runs/full-abc/voltage/arm-b/run-1.html +388 -0
- package/docs/design/fixtures/runs/full-abc/voltage/arm-b/run-2.html +463 -0
- package/docs/design/fixtures/runs/full-abc/voltage/arm-b/run-3.html +568 -0
- package/docs/design/fixtures/runs/full-abc-opus/cadence/arm-a/run-1.html +1068 -0
- package/docs/design/fixtures/runs/full-abc-opus/cadence/arm-a/run-2.html +1423 -0
- package/docs/design/fixtures/runs/full-abc-opus/cadence/arm-a/run-3.html +1245 -0
- package/docs/design/fixtures/runs/full-abc-opus/cadence/arm-b/run-1.html +305 -0
- package/docs/design/fixtures/runs/full-abc-opus/cadence/arm-b/run-2.html +327 -0
- package/docs/design/fixtures/runs/full-abc-opus/cadence/arm-b/run-3.html +428 -0
- package/docs/design/fixtures/runs/full-abc-opus/plume/arm-a/run-1.html +1270 -0
- package/docs/design/fixtures/runs/full-abc-opus/plume/arm-a/run-2.html +1172 -0
- package/docs/design/fixtures/runs/full-abc-opus/plume/arm-a/run-3.html +1532 -0
- package/docs/design/fixtures/runs/full-abc-opus/plume/arm-b/run-1.html +315 -0
- package/docs/design/fixtures/runs/full-abc-opus/plume/arm-b/run-2.html +342 -0
- package/docs/design/fixtures/runs/full-abc-opus/plume/arm-b/run-3.html +353 -0
- package/docs/design/fixtures/runs/full-abc-opus/runs.json +190 -0
- package/docs/design/fixtures/runs/full-abc-opus/scorecard.json +144 -0
- package/docs/design/fixtures/runs/full-abc-opus/slipstream/arm-a/run-1.html +345 -0
- package/docs/design/fixtures/runs/full-abc-opus/slipstream/arm-a/run-2.html +396 -0
- package/docs/design/fixtures/runs/full-abc-opus/slipstream/arm-a/run-3.html +502 -0
- package/docs/design/fixtures/runs/full-abc-opus/slipstream/arm-b/run-1.html +408 -0
- package/docs/design/fixtures/runs/full-abc-opus/slipstream/arm-b/run-2.html +446 -0
- package/docs/design/fixtures/runs/full-abc-opus/slipstream/arm-b/run-3.html +496 -0
- package/docs/design/fixtures/runs/full-abc-opus/tender/arm-a/run-1.html +813 -0
- package/docs/design/fixtures/runs/full-abc-opus/tender/arm-a/run-2.html +711 -0
- package/docs/design/fixtures/runs/full-abc-opus/tender/arm-a/run-3.html +721 -0
- package/docs/design/fixtures/runs/full-abc-opus/tender/arm-b/run-1.html +280 -0
- package/docs/design/fixtures/runs/full-abc-opus/tender/arm-b/run-2.html +291 -0
- package/docs/design/fixtures/runs/full-abc-opus/tender/arm-b/run-3.html +366 -0
- package/docs/design/fixtures/runs/full-abc-opus/voltage/arm-a/run-1.html +1010 -0
- package/docs/design/fixtures/runs/full-abc-opus/voltage/arm-a/run-2.html +836 -0
- package/docs/design/fixtures/runs/full-abc-opus/voltage/arm-a/run-3.html +930 -0
- package/docs/design/fixtures/runs/full-abc-opus/voltage/arm-b/run-1.html +407 -0
- package/docs/design/fixtures/runs/full-abc-opus/voltage/arm-b/run-2.html +396 -0
- package/docs/design/fixtures/runs/full-abc-opus/voltage/arm-b/run-3.html +529 -0
- package/docs/design/foundations/brutalist.css +294 -0
- package/docs/design/foundations/editorial.css +300 -0
- package/docs/design/foundations/minimal-luxury.css +295 -0
- package/docs/design/foundations/technical.css +293 -0
- package/docs/design/foundations/warm-photo.css +299 -0
- package/docs/design/reference-corpus.md +1726 -0
- package/docs/design/render-critique-loop.md +57 -0
- package/docs/spec-graph-schema.md +397 -0
- package/package.json +1 -1
- package/scripts/bench-scorecard.mjs +239 -0
- package/scripts/build-spec-graph.mjs +509 -0
- package/scripts/check-native-conflicts.sh +200 -0
- package/scripts/classify-lane.sh +0 -7
- package/scripts/design-system-lint.mjs +993 -0
- package/scripts/graph-query.sh +486 -0
- package/scripts/transition-label.sh +10 -2
- package/scripts/validate-spec-graph.sh +423 -0
- package/templates/workflows/forgedock-review.yml +96 -0
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
# Design-System Linter — `scripts/design-system-lint.mjs`
|
|
2
|
+
|
|
3
|
+
> **Status:** Committed — the deterministic anti-slop gate for the UI Taste Harness (milestone #13, issue #884).
|
|
4
|
+
> Consumes the [`FORGE:DESIGN_SPEC` schema](design-spec-schema.md) (#881); enforces the machine-checkable
|
|
5
|
+
> negatives from the [reference corpus](reference-corpus.md) (#880); invoked by the
|
|
6
|
+
> render → critique loop (#882) and/or quality-gate.
|
|
7
|
+
> Extended: `checkFoundationUsage` check for per-archetype CSS foundation class usage (#1048).
|
|
8
|
+
|
|
9
|
+
## Purpose
|
|
10
|
+
|
|
11
|
+
The positive, deterministic floor of the harness. It **hard-fails** generated landing-page output that
|
|
12
|
+
violates the committed design system, rather than hoping prose prevents regression to generic AI defaults.
|
|
13
|
+
|
|
14
|
+
> Don't let the LLM "reason its way" back to generic defaults — **constrain it out of them deterministically**.
|
|
15
|
+
> Prose is a suggestion; a failing lint is a constraint. This raises the floor and never lets it regress,
|
|
16
|
+
> regardless of model variance. (Same philosophy as the #639 fix.)
|
|
17
|
+
|
|
18
|
+
The linter and the vision critic (#882) check the rendered output against the **same** committed intent
|
|
19
|
+
(the `FORGE:DESIGN_SPEC`). The linter owns the **deterministic** negatives; the critic owns the perceptual ones.
|
|
20
|
+
|
|
21
|
+
## Scope — what the linter owns
|
|
22
|
+
|
|
23
|
+
The [corpus](reference-corpus.md) tags each negative with its check surface. The linter implements exactly the
|
|
24
|
+
deterministic ones; the rest are left to the vision critic.
|
|
25
|
+
|
|
26
|
+
| Negative | Check | Default severity | Surface |
|
|
27
|
+
|---|---|---|---|
|
|
28
|
+
| **N1** | Purple/blue gradient hero on a white/near-white background | BLOCKING when spec opts in | `checkHeroGradient` |
|
|
29
|
+
| **N2** | Inter / system-default typeface at default weights as the display/body face | BLOCKING (typography is core taste) | `checkTypography` |
|
|
30
|
+
| **N4** | Exactly three identical feature cards (structural pattern only) | WARNING — icon judgement is the critic's | `checkRepeatedCards` |
|
|
31
|
+
| **N5** | A single radius applied to everything, or off-scale radii | BLOCKING when a multi-token `radius.scale` exists | `checkRadius` |
|
|
32
|
+
| **N6** | Default Tailwind palette (slate/gray/zinc/neutral/indigo/violet) used as the brand color | BLOCKING when `no-default-tailwind-palette` is set | `checkPalette` |
|
|
33
|
+
| **N7** | The boilerplate skeleton: hero → 3-cards → testimonial → CTA, in that order | BLOCKING when `layout_grammar.sections` exists | `checkSectionSkeleton` |
|
|
34
|
+
| **N24** | Static product mock: `product_mock.type` is committed (not `"none"`) but the rendered hero has a `.product-window` or `.mock-*` element with no `animation`, `transition`, or JS `addEventListener` present <!-- Added: forge#1045 --> | BLOCKING when `product_mock.type` is set and not `"none"` | `checkProductMock` |
|
|
35
|
+
| **N25** | Truncated narrative: `scroll_narrative` is committed in spec but the rendered page has ≤1 below-fold section (`<section>` or `<div role="region">` elements outside the first/hero section) <!-- Added: forge#1046 — spec only; .mjs implementation follows --> | BLOCKING when `scroll_narrative.section_count_min` is set | `checkScrollNarrative` |
|
|
36
|
+
| **N26** | Missing social proof: `scroll_narrative.social_proof_section` is committed (not `"none"`) but no element with class `section-social-proof`, `social-proof`, or `[data-section="social-proof"]` is present <!-- Added: forge#1046 — spec only; .mjs implementation follows --> | BLOCKING when `scroll_narrative.social_proof_section` is set and not `"none"` | `checkSocialProof` |
|
|
37
|
+
| **N27** | Single CTA: `scroll_narrative.cta_placements_min` is ≥ 2 but the rendered page has fewer than 2 elements matching `.btn-primary`, `.cta-button`, `[data-cta]`, or `<a>` with class containing `cta` <!-- Added: forge#1046 — spec only; .mjs implementation follows --> | BLOCKING when `scroll_narrative.cta_placements_min` ≥ 2 | `checkCTACount` |
|
|
38
|
+
| — | Foundation class usage: a foundation CSS file was injected (Stage 3, #1048) but none of `.btn`, `.card`, `.badge`, `.input` appear in the generated HTML — generator replaced foundation classes with Tailwind equivalents <!-- Added: forge#1048 --> | WARNING when `meta.archetype` maps to a known foundation file | `checkFoundationUsage` |
|
|
39
|
+
| — | Off-scale spacing (padding/margin/gap not on `spacing.scale`) | WARNING | `checkSpacing` |
|
|
40
|
+
| — | Contrast: `color.foreground` vs `color.background` below `acceptance.a11y.contrast_min` | BLOCKING when a contrast floor is declared | `checkContrast` |
|
|
41
|
+
|
|
42
|
+
**Opt-in trigger for N24**: `product_mock.type` present in spec and not `"none"`. When `product_mock.type: "none"`,
|
|
43
|
+
N24 is skipped entirely — the architect deliberately opted out of a mock, and no check is needed.
|
|
44
|
+
|
|
45
|
+
**Opt-in trigger for N25**: `scroll_narrative.section_count_min` present in spec. The check counts `<section>`
|
|
46
|
+
(and `<div role="region">`) elements in the rendered HTML; when the count is below `section_count_min`, the check
|
|
47
|
+
blocks. When `scroll_narrative` is absent from the spec, N25 is skipped.
|
|
48
|
+
|
|
49
|
+
**Opt-in trigger for N26**: `scroll_narrative.social_proof_section` present in spec and not `"none"`. Checks for
|
|
50
|
+
social proof element presence using class-name patterns (`section-social-proof`, `social-proof`) and
|
|
51
|
+
`[data-section="social-proof"]` attribute. When `social_proof_section: "none"`, the architect deliberately opted
|
|
52
|
+
out and N26 is skipped.
|
|
53
|
+
|
|
54
|
+
**Opt-in trigger for N27**: `scroll_narrative.cta_placements_min` ≥ 2. Counts CTA elements using class-name
|
|
55
|
+
patterns (`.btn-primary`, `.cta-button`, `[data-cta]`, and `<a>` elements with class containing `cta`). When
|
|
56
|
+
`cta_placements_min` is absent or < 2, N27 is skipped.
|
|
57
|
+
|
|
58
|
+
**Out of scope** (vision-critic-owned, #882): N3 (everything centered), N8 (stock illustration / generic 3D),
|
|
59
|
+
N9 (glassmorphism overuse), N10 (no visual hierarchy), N11 (abstract copy / no product shown),
|
|
60
|
+
N12 (decorative effects that serve nothing), N24 perceptual quality (whether the 2 interactions feel right — the critic
|
|
61
|
+
judges that; the linter only checks that interaction signals are present at all), N25/N26/N27 narrative quality
|
|
62
|
+
(whether the section content is compelling — the critic judges that; the linter only checks structural presence).
|
|
63
|
+
These require perceptual judgement and are not deterministically checkable.
|
|
64
|
+
N12 / effect justification specifically is governed by the [effects-appropriateness doctrine](effects-appropriateness.md) (#885)
|
|
65
|
+
and judged by the vision critic (#882) against the per-section `justification`; the perf gate (#875) owns the hard `budget`. The linter stays out.
|
|
66
|
+
|
|
67
|
+
## Spec-driven gating
|
|
68
|
+
|
|
69
|
+
Which checks **block** (vs. merely warn) is driven by the spec, not hardcoded — so the same linter serves any
|
|
70
|
+
archetype. A check escalates to `BLOCKING` when the spec opts in via:
|
|
71
|
+
|
|
72
|
+
- `color.rules` — e.g. `"no-default-tailwind-palette"` (gates N6/N1), `"contrast>=4.5"` (gates contrast).
|
|
73
|
+
- `negatives[]` — e.g. `"N6"`, `"N7"` (raw IDs, `{ "id": "N6" }` objects, or descriptive strings are all accepted).
|
|
74
|
+
- Presence of the relevant token field — a multi-entry `radius.scale` opts N5 in; `layout_grammar.sections` opts N7 in;
|
|
75
|
+
a committed non-default `typography.display_family` opts N2 in; `acceptance.a11y.contrast_min` opts contrast in;
|
|
76
|
+
`product_mock.type` set to any value other than `"none"` opts N24 in;
|
|
77
|
+
`scroll_narrative.section_count_min` present opts N25 in;
|
|
78
|
+
`scroll_narrative.social_proof_section` set to any value other than `"none"` opts N26 in;
|
|
79
|
+
`scroll_narrative.cta_placements_min` ≥ 2 opts N27 in;
|
|
80
|
+
`meta.archetype` matching a known foundation archetype opts `checkFoundationUsage` in (WARNING only — see #1048). <!-- Added: forge#1048 -->
|
|
81
|
+
|
|
82
|
+
`--strict` forces **every** deterministic check to block regardless of spec opt-in.
|
|
83
|
+
|
|
84
|
+
## Usage
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
node scripts/design-system-lint.mjs --spec <spec.json> --html <page.html> [options]
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
| Option | Meaning |
|
|
91
|
+
|---|---|
|
|
92
|
+
| `--spec <path>` | The `FORGE:DESIGN_SPEC` JSON (required) |
|
|
93
|
+
| `--html <path>` | The generated HTML to lint (required, unless `--selftest`) |
|
|
94
|
+
| `--css <path>` | Optional separate CSS file (inline `<style>` and `style="…"` are always read) |
|
|
95
|
+
| `--baseline` | Report findings but always exit `0` (survey existing slop, never fail the build) |
|
|
96
|
+
| `--strict` | Every deterministic check blocks, even without spec opt-in |
|
|
97
|
+
| `--json` | Emit findings as JSON on stdout (for the #882 critique loop to consume) |
|
|
98
|
+
| `--selftest` | Run internal self-checks (contrast math, palette table) and exit |
|
|
99
|
+
| `--help` | Show usage |
|
|
100
|
+
|
|
101
|
+
### Output
|
|
102
|
+
|
|
103
|
+
Plain mode prints one finding per line with the established severity prefixes, then a summary:
|
|
104
|
+
|
|
105
|
+
```
|
|
106
|
+
BLOCKING: [N6] Committed color accent=#4f46e5 is a default Tailwind palette value — not a brand color.
|
|
107
|
+
WARNING: [SPACING] Off-scale spacing value(s): 17px — not on spacing.scale [4, 8, 12, 16, 24, 32, 48, 64, 96].
|
|
108
|
+
OK: [N1] No purple/blue-gradient-on-white hero detected.
|
|
109
|
+
|
|
110
|
+
=== Summary ===
|
|
111
|
+
Checks run: 13
|
|
112
|
+
Blocking: 11
|
|
113
|
+
Warnings: 1
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
`--json` emits `{ blocking, warnings, baseline, findings: [{ severity, negative, message }] }`.
|
|
117
|
+
|
|
118
|
+
### Exit codes
|
|
119
|
+
|
|
120
|
+
Matches the scripts-layer convention (`scripts/verify-env-vars.sh`):
|
|
121
|
+
|
|
122
|
+
| Code | Meaning |
|
|
123
|
+
|---|---|
|
|
124
|
+
| `0` | Pass — no blocking findings |
|
|
125
|
+
| `1` | Blocking findings present |
|
|
126
|
+
| `2` | Warnings only (or bad invocation) |
|
|
127
|
+
|
|
128
|
+
`--baseline` always exits `0`.
|
|
129
|
+
|
|
130
|
+
## Integration
|
|
131
|
+
|
|
132
|
+
- **Render → critique loop (#882):** call the linter with `--json` on the generated HTML before the vision pass.
|
|
133
|
+
Blocking findings short-circuit the iteration (the page is regenerated against the spec) without spending a
|
|
134
|
+
vision-critique turn. The linter is deterministic and dependency-free, so it is cheap to run every iteration.
|
|
135
|
+
- **quality-gate:** invoke as a sibling scripts-layer check (like `scripts/verify-*.sh`) and key off the exit code.
|
|
136
|
+
Use `--baseline` for a non-failing survey, or default mode to hard-gate.
|
|
137
|
+
|
|
138
|
+
## Design notes
|
|
139
|
+
|
|
140
|
+
- **Zero runtime dependencies** — Node built-ins only (`node:fs`), matching `scripts/gen-logo.mjs`. HTML/CSS is
|
|
141
|
+
scanned with tolerant regex (attribute order, quote style, and whitespace are accommodated); no jsdom/cheerio.
|
|
142
|
+
- **Injection-safe** — inputs are read as data and never interpolated into a shell; there is no `eval`/`exec`
|
|
143
|
+
(avoids the class of review-findings #73 / #335).
|
|
144
|
+
- **Deterministic** — no network, no randomness, stable finding order. The contrast check uses the standard WCAG
|
|
145
|
+
relative-luminance formula (self-tested: `#000`/`#fff` = 21:1).
|
|
146
|
+
- **Parser limitations** — being regex-based, the linter reads inline `<style>` blocks and `style="…"` attributes
|
|
147
|
+
plus Tailwind utility classes; it does not resolve an external Tailwind build's computed colors. Ambiguous cases
|
|
148
|
+
(e.g. a committed font that cannot be confirmed in the output) are reported as `WARNING`, not `BLOCKING`, to avoid
|
|
149
|
+
false hard-fails. For computed/rendered-pixel checks (e.g. N8–N12), defer to the vision critic with a real render
|
|
150
|
+
(Playwright, #875).
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
# Divergent generation + archetype sampling + taste-judge selection
|
|
2
|
+
|
|
3
|
+
> **Status**: committed foundation doc for the UI Taste Harness (#883).
|
|
4
|
+
> The variance lever: how the harness produces *different* good pages instead of mode-collapsing to one.
|
|
5
|
+
> Consumes: [reference-corpus](reference-corpus.md) archetypes (#880), the [design-architect rationale](design-architect-rationale.md) (#886).
|
|
6
|
+
> Produces: a `FORGE:DESIGN_CANDIDATES` set whose winner hands off into [`FORGE:DESIGN_SPEC`](design-spec-schema.md) (#881).
|
|
7
|
+
> Judge is independent from the render → vision-critique loop (#882) and the [ABC benchmark judge](abc-benchmark.md) (#878) — anti-Goodhart.
|
|
8
|
+
> Part of #877.
|
|
9
|
+
|
|
10
|
+
## Purpose
|
|
11
|
+
|
|
12
|
+
Two failure modes bracket AI UI generation. **Mode collapse**: "make it beautiful" yields the same gradient-hero
|
|
13
|
+
template every time — zero variance. **Incoherent blending**: averaging archetypes ("a bit editorial, a bit
|
|
14
|
+
brutalist") yields mush — variance without taste. This doc defines the lever that sits between them: **commit to one
|
|
15
|
+
archetype, then diverge *within* it across N distinct directions, and let an independent taste-judge pick the winner.**
|
|
16
|
+
|
|
17
|
+
Variance between runs comes from *which archetype + which direction* is chosen — never from blending. Coherence within
|
|
18
|
+
a run comes from committing and not drifting.
|
|
19
|
+
|
|
20
|
+
## Step 1 — Archetype sampling (commit, never blend)
|
|
21
|
+
|
|
22
|
+
From the design-blind brief + the architect rationale (#886), select **exactly one** archetype from the five committed
|
|
23
|
+
in [reference-corpus](reference-corpus.md) (#880). The ids are fixed tokens — they must match exactly, because the
|
|
24
|
+
selected id is written into `meta.archetype` in the [spec](design-spec-schema.md):
|
|
25
|
+
|
|
26
|
+
| `archetype` id | When it fits |
|
|
27
|
+
|---|---|
|
|
28
|
+
| `editorial-typographic` | considered, magazine, type-led products; content-forward |
|
|
29
|
+
| `technical-dense` | dashboards, compute, infra; capable, data-forward |
|
|
30
|
+
| `minimal-luxury` | premium, lots of air; restraint as the message |
|
|
31
|
+
| `bold-brutalist` | opinionated, high-contrast; a stance |
|
|
32
|
+
| `warm-photographic` | human, approachable; image/people-led |
|
|
33
|
+
|
|
34
|
+
**Selection rule** (from the corpus): pick the one appropriate to *product nature* + *audience* inferred from the
|
|
35
|
+
brief, then **commit**. No blending, no averaging, no "60% A / 40% B". The variance lever is the *choice between*
|
|
36
|
+
archetypes across runs and the divergent directions below — not a blend within a run.
|
|
37
|
+
|
|
38
|
+
## Step 2 — Divergent generation (N distinct directions)
|
|
39
|
+
|
|
40
|
+
Within the committed archetype, generate **N distinct directions** (default N=3). Each direction is a genuinely
|
|
41
|
+
different interpretation of the *same* archetype + rationale — different layout grammar, different signature move,
|
|
42
|
+
different typographic instantiation — not N near-duplicates with a hue shift. Divergence is structural, not cosmetic.
|
|
43
|
+
|
|
44
|
+
Each direction carries:
|
|
45
|
+
- a one-line concept (the interpretation),
|
|
46
|
+
- its **signature move** (from the rationale's diary — the non-obvious idea that makes it *this* page),
|
|
47
|
+
- the salient token/grammar choices that distinguish it from its siblings.
|
|
48
|
+
|
|
49
|
+
Sampling within one archetype keeps every direction coherent; requiring *structural* difference keeps them genuinely
|
|
50
|
+
divergent. If two directions collapse to the same signature move, one is rejected and re-rolled — duplicate directions
|
|
51
|
+
defeat the lever.
|
|
52
|
+
|
|
53
|
+
## Step 3 — Taste-judge score + select
|
|
54
|
+
|
|
55
|
+
An **independent taste-judge** scores the N directions and selects one winner. The judge:
|
|
56
|
+
- scores each direction on a small taste rubric (hierarchy/intent, signature-move strength, archetype fit, restraint),
|
|
57
|
+
- rejects any that trip the corpus negatives or duplicate a sibling,
|
|
58
|
+
- selects the highest-scoring surviving direction; ties break toward the stronger signature move.
|
|
59
|
+
|
|
60
|
+
### Judge independence (anti-Goodhart) — non-negotiable
|
|
61
|
+
|
|
62
|
+
This taste-judge is **distinct** from both:
|
|
63
|
+
- the **render → vision-critique loop** (#882), which judges a *rendered* page against its committed spec, and
|
|
64
|
+
- the **ABC benchmark judge** (#878), which scores arms blind against arm C for evaluation.
|
|
65
|
+
|
|
66
|
+
Reusing either as the selection judge would let the harness optimize directly against its own evaluator — the textbook
|
|
67
|
+
Goodhart failure. The selection judge scores *candidate directions* (pre-render intent); the critic scores *rendered
|
|
68
|
+
output*; the benchmark scores *finished arms*. Three separate judges, three separate jobs.
|
|
69
|
+
|
|
70
|
+
## Step 4 — Hand-off to DESIGN_SPEC
|
|
71
|
+
|
|
72
|
+
The winning direction is what gets fully specified: it hands off into [`FORGE:DESIGN_SPEC`](design-spec-schema.md)
|
|
73
|
+
(#881) — `meta.archetype` = the committed id, `layout_grammar`/`signature` = the winning direction. The losing
|
|
74
|
+
directions are retained in the `FORGE:DESIGN_CANDIDATES` annotation (below) so the choice is auditable and so
|
|
75
|
+
[design-memory](design-memory.md) (#887) can later diverge from past winners.
|
|
76
|
+
|
|
77
|
+
## The `FORGE:DESIGN_CANDIDATES` annotation
|
|
78
|
+
|
|
79
|
+
Registered in [FORGE-PROTOCOL](../FORGE-PROTOCOL.md). Posted at the divergent-generation step, between the rationale
|
|
80
|
+
and the spec. It records the committed archetype, the N directions, and the judge's selection + scores — so the
|
|
81
|
+
variance decision is a first-class, machine-queryable artifact, not a hidden roll.
|
|
82
|
+
|
|
83
|
+
```markdown
|
|
84
|
+
<!-- FORGE:DESIGN_CANDIDATES -->
|
|
85
|
+
## Design Candidates — {product}
|
|
86
|
+
|
|
87
|
+
**Archetype (committed):** {one of the 5 corpus ids}
|
|
88
|
+
**Directions:**
|
|
89
|
+
1. {concept} — signature: {move} — {distinguishing grammar/tokens}
|
|
90
|
+
2. {concept} — signature: {move} — {…}
|
|
91
|
+
3. {concept} — signature: {move} — {…}
|
|
92
|
+
**Judge scores:** 1) {score} 2) {score} 3) {score}
|
|
93
|
+
**Selected:** #{n} — because {reason}
|
|
94
|
+
|
|
95
|
+
→ Winner produces DESIGN_SPEC: {link}
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
## Acceptance (worked expectation)
|
|
99
|
+
|
|
100
|
+
On the seed set, the same brief produces a *committed archetype* and visibly different *directions*:
|
|
101
|
+
- **Voltage** (`technical-dense`): directions differ on whether the signature move is a scaling-compute visualization,
|
|
102
|
+
a code-first hero, or a benchmark-grid — same archetype, three structures.
|
|
103
|
+
- **Plume** (`minimal-luxury` / `editorial-typographic`): directions differ on keyboard-motif vs cycle-timeline vs
|
|
104
|
+
pure-type hierarchy — all restrained, all coherent.
|
|
105
|
+
|
|
106
|
+
Variance shows up as *which archetype + which direction wins*, across runs — never as a blend within a run.
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
# Effects-appropriateness layer
|
|
2
|
+
|
|
3
|
+
> **Status**: committed foundation doc for the UI Taste Harness (#885).
|
|
4
|
+
> Consumes: [reference-corpus](reference-corpus.md) effect-usage patterns (#880),
|
|
5
|
+
> [design-spec-schema](design-spec-schema.md) `effects_plan` slot (#881).
|
|
6
|
+
> Enforced by: the perf gate (#875, hard/objective) and the vision critique loop (#882, perceptual — N12).
|
|
7
|
+
> Stays out of: the deterministic [linter](design-system-lint.md) (#884) — effect justification is not deterministically checkable.
|
|
8
|
+
> Authored to be consumed by: the [design-architect rationale](design-architect-rationale.md) (#886) and [design-memory](design-memory.md) (#887) phases.
|
|
9
|
+
> Part of #877.
|
|
10
|
+
|
|
11
|
+
## Purpose
|
|
12
|
+
|
|
13
|
+
The schema (#881) gives every page an `effects_plan` — a slot for *which* heavy techniques run *where*, at *what*
|
|
14
|
+
intensity, with a *budget* and a *never* list. The slot is a placeholder. This doc is the **reasoning doctrine that
|
|
15
|
+
fills it**: how the harness decides, **from the design-blind brief alone**, when a heavy effect earns its cost and
|
|
16
|
+
when restraint is the more confident choice.
|
|
17
|
+
|
|
18
|
+
The thesis: AI UI mode-collapses toward gratuitous motion because "make it impressive" has no cost model. The fix is
|
|
19
|
+
to treat every effect as a spend that must be *justified against the content it serves and the budget it consumes* —
|
|
20
|
+
and to make the default **restraint**, with effects added only on evidence, never by reflex.
|
|
21
|
+
|
|
22
|
+
## The core asymmetry
|
|
23
|
+
|
|
24
|
+
Not all effects reward the same posture. This is the single most important rule in this doc:
|
|
25
|
+
|
|
26
|
+
> **Compositional contrast rewards *more* intention. 3D/WebGL, parallax, and multi-layer depth reward *restraint*.**
|
|
27
|
+
|
|
28
|
+
Flattening this into "less is always more" loses the doctrine. Low contrast is itself a slop tell (flat, equal-weight,
|
|
29
|
+
nothing directs the eye — see N12's sibling failures). Deliberate contrast is almost always correct. The *decorative*
|
|
30
|
+
effects (depth, motion, 3D) are the ones that must earn their place against a hard cost.
|
|
31
|
+
|
|
32
|
+
## Effect taxonomy + appropriateness/cost
|
|
33
|
+
|
|
34
|
+
Derived from the corpus effect-usage table (#880); this layer formalizes the `Earns its place when…` / `Slop when…`
|
|
35
|
+
columns into authoring rules with an explicit cost axis.
|
|
36
|
+
|
|
37
|
+
| Effect | Posture | Earns its place when… | Slop when… | Primary cost |
|
|
38
|
+
|---|---|---|---|---|
|
|
39
|
+
| **Compositional contrast** | *more* intention | almost always — direct the eye, establish hierarchy | flat, equal-weight, everything the same size/color | ~none (CSS) |
|
|
40
|
+
| **Multi-layer depth** (glass / grain / gradient) | restraint | one hero backdrop; foreground/background separation that aids reading | over-glass, muddy contrast, applied everywhere | contrast/a11y risk; minor paint |
|
|
41
|
+
| **Parallax / scroll-driven** | restraint | a single progressive-capability reveal where depth *is* the message | on every section; jank/CLS; fights readability | INP/CLS; JS |
|
|
42
|
+
| **3D / WebGL** | strong restraint | the product is spatial/visual; exactly one premium hero centerpiece with a fallback | bolted onto non-visual B2B; wrecks LCP; no reduced-motion/no-WebGL fallback | LCP + JS-kb (largest) |
|
|
43
|
+
|
|
44
|
+
## The 6 decision inputs
|
|
45
|
+
|
|
46
|
+
The architect/rationale phase (#886) infers all six from the brief alone, then writes them into `effects_plan`:
|
|
47
|
+
|
|
48
|
+
1. **Product nature** — is the product itself *spatial/visual* (renders, maps, 3D, creative tooling), *technical/data*
|
|
49
|
+
(compute, dashboards, infra), or *text/workflow* (trackers, docs, email)? Spatial → a heavy hero may be earned;
|
|
50
|
+
text/workflow → near-zero decorative.
|
|
51
|
+
2. **Archetype** — the committed archetype carries an **effects posture** prior (#880): `bold-brutalist` →
|
|
52
|
+
"sharp, near-zero decorative"; `technical-dense` → "code/data motion welcome"; `minimal-luxury` →
|
|
53
|
+
"restrained micro-motion"; `editorial-typographic` → "minimal, type-led"; `warm-photographic` → "image-driven, soft motion".
|
|
54
|
+
3. **Section job** — what is *this* section for? A hero may carry one centerpiece; a pricing table or feature grid
|
|
55
|
+
carries none. Effect intensity is assigned **per section**, not per page.
|
|
56
|
+
4. **Audience expectation** — engineers who "read the code sample closely" reward technical credibility and are
|
|
57
|
+
*repelled* by gratuitous motion; a consumer/creative audience tolerates more spectacle.
|
|
58
|
+
5. **Measurable perf budget** (#875) — LCP / CLS / INP / JS-kb ceilings. This is the **hard gate**: an effect that
|
|
59
|
+
blows the budget is rejected regardless of how good it looks.
|
|
60
|
+
6. **Accessibility** — `prefers-reduced-motion` must be honored; depth must not destroy contrast; every WebGL/3D
|
|
61
|
+
centerpiece needs a static fallback. A11y failures are not negotiable against aesthetics.
|
|
62
|
+
|
|
63
|
+
## Mapping decision inputs → `effects_plan`
|
|
64
|
+
|
|
65
|
+
The fields mirror [design-spec-schema](design-spec-schema.md) exactly:
|
|
66
|
+
|
|
67
|
+
`effects_plan { per_section[{ section, effect, intensity, justification }], budget{ lcp_ms, max_js_kb }, never[] }`
|
|
68
|
+
|
|
69
|
+
- **`per_section[].effect` / `.intensity`** — from inputs 1–4. Default `intensity: none`. Raise it only when product
|
|
70
|
+
nature + archetype + section job *agree* that the effect serves the content. Each step up in intensity needs a
|
|
71
|
+
stronger justification.
|
|
72
|
+
- **`per_section[].justification`** — one sentence stating *what content the effect serves*. "Looks premium" is not a
|
|
73
|
+
justification; "the spatial product *is* the demo, shown once in the hero" is. The critic (#882) reads this field
|
|
74
|
+
and judges whether the rendered effect actually delivered on it (N12).
|
|
75
|
+
- **`budget{ lcp_ms, max_js_kb }`** — from input 5. The hard ceiling. The perf gate (#875) measures the rendered arm
|
|
76
|
+
against it; over-budget = fail, no aesthetic override.
|
|
77
|
+
- **`never[]`** — from inputs 2 + 6. Per-archetype prohibitions (e.g. `bold-brutalist` → `never: [parallax, glass]`)
|
|
78
|
+
and universal a11y rules (`never: [motion-without-reduced-motion-fallback]`).
|
|
79
|
+
|
|
80
|
+
## Enforcement split
|
|
81
|
+
|
|
82
|
+
Three mechanisms, deliberately non-overlapping — no single check owns the whole problem:
|
|
83
|
+
|
|
84
|
+
| Mechanism | Owns | Nature |
|
|
85
|
+
|---|---|---|
|
|
86
|
+
| **Perf gate** (#875) | `budget` — did the effect stay within LCP/CLS/INP/JS-kb? | **Hard, objective.** Earned its *ms*. Blocking. |
|
|
87
|
+
| **Vision critic** (#882) | N12 — did each effect *serve the content* it claimed to? | **Perceptual.** Earned its *place*. Finding. |
|
|
88
|
+
| **Deterministic linter** (#884) | nothing here | Effects are explicitly **out of scope** — not deterministically checkable. |
|
|
89
|
+
|
|
90
|
+
The perf gate answers "could the user afford it?"; the critic answers "was it worth it?". An effect must pass **both**:
|
|
91
|
+
within budget *and* serving the content. Within budget but gratuitous → critic N12 finding. Justified but over budget →
|
|
92
|
+
perf-gate fail. The linter stays out because perceptual judgement can't be reduced to a regex without false hard-fails
|
|
93
|
+
(consistent with `design-system-lint.md`'s N8–N12 out-of-scope list).
|
|
94
|
+
|
|
95
|
+
## Worked inferences (seed set)
|
|
96
|
+
|
|
97
|
+
Demonstrating that the doctrine produces **visibly different effect intensity from the briefs alone** — the acceptance
|
|
98
|
+
criterion. Each is derived purely from the design-blind brief; no visual direction is given.
|
|
99
|
+
|
|
100
|
+
### Voltage — serverless compute / GPUs for ML engineers
|
|
101
|
+
- **Product nature**: technical/data (compute), with a *credible* spatial story (containers scaling zero→thousands).
|
|
102
|
+
- **Audience**: engineers who read the code sample closely → reward technical credibility, repelled by spectacle.
|
|
103
|
+
- **Inference**: `technical-dense` archetype; **one restrained** technical hero visualization (subtle scaling/compute
|
|
104
|
+
motion that *is* the product story), `intensity: subtle`. Code sample is the real hero. No parallax, no glass.
|
|
105
|
+
- `effects_plan`: hero → `effect: technical-motion, intensity: subtle, justification: "the zero→N scaling IS the product, shown once"`;
|
|
106
|
+
all other sections → `none`. `never: [parallax, decorative-3d]`. Tight JS budget (audience will notice bloat).
|
|
107
|
+
|
|
108
|
+
### Plume — fast, keyboard-driven issue tracker for software teams
|
|
109
|
+
- **Product nature**: text/workflow. Speed and focus are the message.
|
|
110
|
+
- **Audience**: craft-focused technical teams who find heavy tools heavy → motion that slows them is *anti-product*.
|
|
111
|
+
- **Inference**: `minimal-luxury` / `editorial-typographic`; **near-zero motion**. The product's own speed is the
|
|
112
|
+
argument; any decorative effect contradicts it. Contrast and typography do all the work.
|
|
113
|
+
- `effects_plan`: every section → `intensity: none`; `never: [parallax, 3d, glass]`. Restraint *is* the design.
|
|
114
|
+
|
|
115
|
+
### Slipstream — git-connected deploy platform / global edge
|
|
116
|
+
- **Product nature**: technical/infra; "confidence and restraint" stated explicitly in the brief.
|
|
117
|
+
- **Audience**: frontend/full-stack devs; serious, opinionated platform.
|
|
118
|
+
- **Inference**: restrained, typographic-technical. At most **one** subtle scroll reveal for the push→production flow
|
|
119
|
+
(depth *is* part of that narrative), `intensity: subtle`; everything else `none`. Restraint as the move.
|
|
120
|
+
- `effects_plan`: hero/flow → `effect: scroll-reveal, intensity: subtle, justification: "push→prod is a sequence; one reveal shows it"`;
|
|
121
|
+
rest → `none`. `never: [decorative-3d, glass]`.
|
|
122
|
+
|
|
123
|
+
**Differential**: Voltage gets one subtle *technical* hero motion; Plume gets *zero*; Slipstream gets one subtle
|
|
124
|
+
*scroll reveal* — three visibly different intensities, inferred from product nature + audience alone. None reaches for
|
|
125
|
+
3D/WebGL, because none is a spatial/visual product. That restraint is the doctrine working.
|
|
126
|
+
|
|
127
|
+
## Authoring checklist (for the rationale phase, #886)
|
|
128
|
+
|
|
129
|
+
- [ ] Default every section to `intensity: none`; raise only on agreement of inputs 1–4.
|
|
130
|
+
- [ ] Every non-`none` entry carries a content-serving `justification` (not "looks premium").
|
|
131
|
+
- [ ] `budget` set from #875 ceilings; `never[]` set from archetype posture + a11y.
|
|
132
|
+
- [ ] Reduced-motion + WebGL/3D fallback covered in `never[]` or per-section notes.
|
|
133
|
+
- [ ] Contrast treated as *expected*, not optional; low contrast flagged as a tell.
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# Seed Briefs — Fixtures
|
|
2
|
+
|
|
3
|
+
> Reproducible fixtures for the [ABC benchmark](../../abc-benchmark.md) (#878, milestone #13).
|
|
4
|
+
> Each brief is **design-blind** (describes only what the product *does*) and uses an **anonymized**
|
|
5
|
+
> product name. These are the fixed inputs re-run as the harness evolves.
|
|
6
|
+
|
|
7
|
+
## What a brief is
|
|
8
|
+
|
|
9
|
+
A brief is the single input shared by all three arms (A = ForgeDock `/design`, B = raw one-shot model,
|
|
10
|
+
C = the real reference). It is derived from a real reference page by **stripping every visual cue** —
|
|
11
|
+
no colors, no typefaces, no layout, no "make it like X" — and keeping only a factual description of what
|
|
12
|
+
the product does, who it is for, and what the page must communicate.
|
|
13
|
+
|
|
14
|
+
## Anonymization is load-bearing — do not leak the real brand
|
|
15
|
+
|
|
16
|
+
Each brief maps to a real reference page (arm C), but the brief **must never name the real product or brand**.
|
|
17
|
+
|
|
18
|
+
A real brand name lets the generation model recall that brand's actual page from training. That measures
|
|
19
|
+
**brand recall, not taste**, and it unfairly inflates arm B (the raw model would reproduce a page it has
|
|
20
|
+
memorized). Treat any real-brand reference inside a brief file as a fixture bug.
|
|
21
|
+
|
|
22
|
+
The mapping below is kept in this README — **separate from the brief files** — so the generator, which is only
|
|
23
|
+
ever handed a single `*.md` brief, never sees which real page it is being compared against.
|
|
24
|
+
|
|
25
|
+
## Brief → reference (C) mapping
|
|
26
|
+
|
|
27
|
+
| Anonymized brief | Real reference (arm C) | Archetype it exemplifies | Category |
|
|
28
|
+
|------------------|------------------------|--------------------------|----------|
|
|
29
|
+
| **Cadence** | resend.com | Clean / warm-minimal | Email API / developer tooling |
|
|
30
|
+
| **Tender** | stripe.com | Polished / enterprise-dev | Payments API |
|
|
31
|
+
| **Slipstream**| vercel.com | Stark monochrome / brutalist-minimal | Deploy platform |
|
|
32
|
+
| **Voltage** | modal.com | Technical / playful | Serverless compute |
|
|
33
|
+
| **Plume** | linear.app | Refined minimal / dark technical-luxury | Issue tracking |
|
|
34
|
+
|
|
35
|
+
The references and archetypes are drawn from the [reference corpus](../../reference-corpus.md) (#880). The
|
|
36
|
+
mapping is an internal record for scoring and the C-as-calibration check — it is **not** part of the brief
|
|
37
|
+
input handed to any arm.
|
|
38
|
+
|
|
39
|
+
## Adding a brief
|
|
40
|
+
|
|
41
|
+
1. Pick a corpus reference (#880) not already represented, or one that adds a distinct archetype.
|
|
42
|
+
2. Strip it to a design-blind, factual product description. Remove every visual cue.
|
|
43
|
+
3. Choose an **anonymized** product name (no resemblance to the real brand).
|
|
44
|
+
4. Save as `fixtures/briefs/<name>.md` following the structure of the existing briefs.
|
|
45
|
+
5. Add the `<name> → real reference` row to the mapping table above.
|
|
46
|
+
6. Keep n high enough: the benchmark runs 3–5 generations per arm across 3–5 products — adding a sixth brief
|
|
47
|
+
is fine, but never run fewer than three.
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# Brief — Cadence
|
|
2
|
+
|
|
3
|
+
> Design-blind seed brief. Describes only what the product does. No visual direction.
|
|
4
|
+
> Anonymized name — do not infer or reproduce any real brand.
|
|
5
|
+
|
|
6
|
+
## Product
|
|
7
|
+
|
|
8
|
+
**Cadence** is an email-sending API for developers and product teams. It lets engineers send
|
|
9
|
+
transactional and marketing email from their applications with a few lines of code, and gives
|
|
10
|
+
non-engineers a way to write, manage, and schedule those emails without touching the codebase.
|
|
11
|
+
|
|
12
|
+
## Who it's for
|
|
13
|
+
|
|
14
|
+
Developers integrating email into a product, plus the marketing and product people on the same team
|
|
15
|
+
who own the content of those emails.
|
|
16
|
+
|
|
17
|
+
## What it does
|
|
18
|
+
|
|
19
|
+
- A simple REST API and SDKs to send email from application code.
|
|
20
|
+
- Deliverability tooling: domain authentication, suppression handling, and bounce/complaint tracking.
|
|
21
|
+
- A way to author emails as reusable templates, including from React-style components.
|
|
22
|
+
- Analytics on opens, clicks, deliveries, and bounces.
|
|
23
|
+
- A test/preview mode so teams can see an email before it ships.
|
|
24
|
+
|
|
25
|
+
## What the landing page must communicate
|
|
26
|
+
|
|
27
|
+
- That sending email from code is genuinely simple here (show, don't claim).
|
|
28
|
+
- That deliverability is handled — the hard, invisible part of email is taken care of.
|
|
29
|
+
- That both engineers and content owners have a place in the workflow.
|
|
30
|
+
- Credibility: this is production infrastructure, not a toy.
|
|
31
|
+
|
|
32
|
+
## Primary call to action
|
|
33
|
+
|
|
34
|
+
Get started / sign up with an API key.
|
|
35
|
+
|
|
36
|
+
## Constraints
|
|
37
|
+
|
|
38
|
+
- Honest, concrete copy about what the product does — no vague promises.
|
|
39
|
+
- The page should read as current, well-resourced SaaS for a technical audience.
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# Brief — Plume
|
|
2
|
+
|
|
3
|
+
> Design-blind seed brief. Describes only what the product does. No visual direction.
|
|
4
|
+
> Anonymized name — do not infer or reproduce any real brand.
|
|
5
|
+
|
|
6
|
+
## Product
|
|
7
|
+
|
|
8
|
+
**Plume** is an issue tracking and project management tool for software teams. It is built to be fast and
|
|
9
|
+
keyboard-driven, and it organizes work into issues, cycles, and projects so a team can plan, prioritize,
|
|
10
|
+
and ship without ceremony.
|
|
11
|
+
|
|
12
|
+
## Who it's for
|
|
13
|
+
|
|
14
|
+
Software engineering teams and the product and design people who plan alongside them — small, fast-moving
|
|
15
|
+
teams that find traditional project tools heavy.
|
|
16
|
+
|
|
17
|
+
## What it does
|
|
18
|
+
|
|
19
|
+
- Issues with statuses, priorities, labels, and assignees, navigable almost entirely by keyboard.
|
|
20
|
+
- Cycles (time-boxed sprints) and longer-running projects to organize work.
|
|
21
|
+
- Roadmap and progress views so leads can see where things stand.
|
|
22
|
+
- Tight integrations with code hosting so issues track real development.
|
|
23
|
+
- A fast, responsive interface that stays out of the way.
|
|
24
|
+
|
|
25
|
+
## What the landing page must communicate
|
|
26
|
+
|
|
27
|
+
- Speed and focus: the tool is fast and respects the user's attention.
|
|
28
|
+
- It is opinionated and designed for teams who care about craft.
|
|
29
|
+
- Planning and shipping live in one place, without bureaucracy.
|
|
30
|
+
- A premium, considered product for discerning technical teams.
|
|
31
|
+
|
|
32
|
+
## Primary call to action
|
|
33
|
+
|
|
34
|
+
Get started / sign up.
|
|
35
|
+
|
|
36
|
+
## Constraints
|
|
37
|
+
|
|
38
|
+
- Crisp, confident copy; minimal and precise.
|
|
39
|
+
- Reads as a refined, premium, well-funded product for technical teams.
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# Brief — Slipstream
|
|
2
|
+
|
|
3
|
+
> Design-blind seed brief. Describes only what the product does. No visual direction.
|
|
4
|
+
> Anonymized name — do not infer or reproduce any real brand.
|
|
5
|
+
|
|
6
|
+
## Product
|
|
7
|
+
|
|
8
|
+
**Slipstream** is a platform for building and deploying web applications. Developers connect a git
|
|
9
|
+
repository and every push is built and deployed automatically to a global edge network, with preview
|
|
10
|
+
environments for each change and zero server management.
|
|
11
|
+
|
|
12
|
+
## Who it's for
|
|
13
|
+
|
|
14
|
+
Frontend and full-stack developers and the teams shipping web apps who want to deploy without operating
|
|
15
|
+
infrastructure.
|
|
16
|
+
|
|
17
|
+
## What it does
|
|
18
|
+
|
|
19
|
+
- Git-connected deploys: push to a branch, get a live URL.
|
|
20
|
+
- Preview deployments for every pull request, so changes can be reviewed running, not just as a diff.
|
|
21
|
+
- A global edge network and CDN so apps are fast everywhere by default.
|
|
22
|
+
- Serverless and edge functions for backend logic without managing servers.
|
|
23
|
+
- Collaboration features so a whole team can see and comment on deploys.
|
|
24
|
+
|
|
25
|
+
## What the landing page must communicate
|
|
26
|
+
|
|
27
|
+
- Speed and immediacy: from push to production is effortless and fast.
|
|
28
|
+
- Zero infrastructure burden — no servers, no ops.
|
|
29
|
+
- It is the obvious home for modern frontend frameworks.
|
|
30
|
+
- Confidence and restraint: this is a serious, opinionated platform.
|
|
31
|
+
|
|
32
|
+
## Primary call to action
|
|
33
|
+
|
|
34
|
+
Deploy now / start for free.
|
|
35
|
+
|
|
36
|
+
## Constraints
|
|
37
|
+
|
|
38
|
+
- Concrete and direct copy; let the capability speak.
|
|
39
|
+
- Reads as a stark, confident, well-funded developer platform.
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# Brief — Tender
|
|
2
|
+
|
|
3
|
+
> Design-blind seed brief. Describes only what the product does. No visual direction.
|
|
4
|
+
> Anonymized name — do not infer or reproduce any real brand.
|
|
5
|
+
|
|
6
|
+
## Product
|
|
7
|
+
|
|
8
|
+
**Tender** is a payments platform and API for internet businesses. It lets companies accept payments,
|
|
9
|
+
send payouts, and run subscription billing through a single integration, and handles the regulatory and
|
|
10
|
+
financial plumbing — fraud screening, currency conversion, compliance — on their behalf.
|
|
11
|
+
|
|
12
|
+
## Who it's for
|
|
13
|
+
|
|
14
|
+
Engineers building checkout, billing, or marketplace flows, plus finance and operations teams at the
|
|
15
|
+
companies that run on top of those flows.
|
|
16
|
+
|
|
17
|
+
## What it does
|
|
18
|
+
|
|
19
|
+
- A unified API to accept cards and local payment methods across many countries and currencies.
|
|
20
|
+
- Subscription and usage-based billing with proration and invoicing.
|
|
21
|
+
- Payouts and money movement for marketplaces and platforms.
|
|
22
|
+
- Fraud detection and risk scoring built in.
|
|
23
|
+
- A dashboard for finance teams to see revenue, disputes, and payouts.
|
|
24
|
+
|
|
25
|
+
## What the landing page must communicate
|
|
26
|
+
|
|
27
|
+
- Breadth and reliability: this handles serious money at scale, globally.
|
|
28
|
+
- Developer-first: integration is clean and well-documented.
|
|
29
|
+
- Trust and compliance are handled — the regulated, scary parts are someone else's problem now.
|
|
30
|
+
- It serves both the engineers who integrate and the finance teams who reconcile.
|
|
31
|
+
|
|
32
|
+
## Primary call to action
|
|
33
|
+
|
|
34
|
+
Start integrating / view the docs.
|
|
35
|
+
|
|
36
|
+
## Constraints
|
|
37
|
+
|
|
38
|
+
- Enterprise-credible but not stuffy; concrete about capabilities.
|
|
39
|
+
- Reads as a high-stakes, well-funded developer platform.
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# Brief — Voltage
|
|
2
|
+
|
|
3
|
+
> Design-blind seed brief. Describes only what the product does. No visual direction.
|
|
4
|
+
> Anonymized name — do not infer or reproduce any real brand.
|
|
5
|
+
|
|
6
|
+
## Product
|
|
7
|
+
|
|
8
|
+
**Voltage** is a serverless platform for running compute-heavy and AI workloads. Developers write
|
|
9
|
+
ordinary Python, attach the resources they need — including GPUs — and Voltage runs it in the cloud on
|
|
10
|
+
demand, scaling from zero to thousands of containers and back without provisioning anything.
|
|
11
|
+
|
|
12
|
+
## Who it's for
|
|
13
|
+
|
|
14
|
+
Machine-learning engineers, data scientists, and backend developers who need heavy or bursty compute
|
|
15
|
+
(model inference, batch jobs, training) but do not want to manage clusters.
|
|
16
|
+
|
|
17
|
+
## What it does
|
|
18
|
+
|
|
19
|
+
- Run Python functions in the cloud by adding a decorator — no Dockerfiles or YAML required.
|
|
20
|
+
- On-demand GPUs and large CPU/memory, billed only while running.
|
|
21
|
+
- Scale to thousands of parallel containers and back to zero automatically.
|
|
22
|
+
- Schedule jobs, serve inference endpoints, and run long batch pipelines.
|
|
23
|
+
- Fast cold starts and a local-feeling developer loop.
|
|
24
|
+
|
|
25
|
+
## What the landing page must communicate
|
|
26
|
+
|
|
27
|
+
- Power made simple: serious compute, but the developer experience feels like writing local code.
|
|
28
|
+
- Pay-for-what-you-use economics — idle costs nothing.
|
|
29
|
+
- It is built for the AI/ML era specifically.
|
|
30
|
+
- Technical credibility: the audience is engineers who will read the code sample closely.
|
|
31
|
+
|
|
32
|
+
## Primary call to action
|
|
33
|
+
|
|
34
|
+
Run your first function / get started.
|
|
35
|
+
|
|
36
|
+
## Constraints
|
|
37
|
+
|
|
38
|
+
- Technical, code-forward copy; show a real usage example in spirit.
|
|
39
|
+
- Reads as a capable, modern, well-funded compute platform.
|