design-playbook 0.11.1 → 0.13.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/README.md +20 -1
- package/codex/AGENTS.md +70 -0
- package/codex/install_skills.py +69 -0
- package/commands/doctor.md +15 -0
- package/commands/run-status.md +21 -0
- package/design_playbook.py +20 -0
- package/examples/README.md +11 -0
- package/examples/craft-detectors/composition-contrast.md +16 -0
- package/examples/craft-detectors/existing-brand-contrast.md +22 -0
- package/examples/craft-detectors/landing-product-contrast.md +12 -0
- package/examples/craft-detectors/saas-dashboard.md +29 -0
- package/examples/ops-list-spec.md +44 -0
- package/examples/point-back-findings.md +29 -0
- package/examples/reference-intake/README.md +11 -0
- package/examples/reference-intake/product-analogy/contract.md +53 -0
- package/examples/reference-intake/product-analogy/manifest.json +15 -0
- package/examples/reference-intake/screenshot/assets/README.md +1 -0
- package/examples/reference-intake/screenshot/contract.md +55 -0
- package/examples/reference-intake/screenshot/manifest.json +15 -0
- package/examples/reference-intake/url/contract.md +55 -0
- package/examples/reference-intake/url/manifest.json +15 -0
- package/examples/settings-decision-report.md +26 -0
- package/mcp/evidence/capture_contract.py +268 -0
- package/mcp/evidence/capture_runtime.py +505 -0
- package/mcp/evidence/containment.py +164 -0
- package/mcp/evidence/ledger_syntax.py +131 -0
- package/mcp/evidence/server.py +28 -398
- package/mcp/evidence/test_capture_contract.py +355 -0
- package/mcp/evidence/test_containment.py +581 -0
- package/mcp/evidence/test_ledger_syntax.py +252 -0
- package/mcp/evidence/test_server_stdio.py +331 -393
- package/mcp/preview/compatibility.py +158 -0
- package/mcp/preview/control.css +78 -15
- package/mcp/preview/control.html +15 -2
- package/mcp/preview/control.js +208 -65
- package/mcp/preview/control.py +19 -13
- package/mcp/preview/i18n.py +16 -6
- package/mcp/preview/integrity.py +362 -0
- package/mcp/preview/{browser.py → review_session.py} +61 -15
- package/mcp/preview/server.py +14 -9
- package/mcp/preview/test_browser_control.py +225 -176
- package/mcp/preview/test_integrity.py +208 -0
- package/mcp/preview/test_server_stdio.py +10 -449
- package/mcp/preview/test_transaction.py +23 -18
- package/mcp/preview/test_versions.py +77 -24
- package/mcp/preview/test_versions_freeze.py +176 -0
- package/mcp/preview/transaction.py +32 -56
- package/mcp/preview/util.py +1 -21
- package/mcp/preview/versions.py +78 -132
- package/mcp/test_transport.py +6 -2
- package/package.json +5 -1
- package/scripts/__init__.py +0 -0
- package/scripts/_diagnostics.py +94 -0
- package/scripts/contract_v1.py +443 -0
- package/scripts/doctor.py +142 -0
- package/scripts/g1_spec.py +81 -0
- package/scripts/g2_g4_pointback.py +310 -0
- package/scripts/g5_preview.py +265 -0
- package/scripts/g6_evidence.py +252 -0
- package/scripts/g6_records.py +56 -0
- package/scripts/g6_warnings.py +104 -0
- package/scripts/g7_contract_drift.py +236 -0
- package/scripts/run_facts.py +212 -0
- package/scripts/run_status.py +311 -0
- package/scripts/stages.py +90 -0
- package/scripts/test_verdict_syntax.py +239 -0
- package/scripts/validate_run.py +302 -0
- package/scripts/verdict_syntax.py +96 -0
- package/skills/craft-guard/SKILL.md +3 -1
- package/skills/design-playbook/SKILL.md +10 -13
- package/skills/design-playbook/references/first-run.md +33 -0
- package/skills/design-playbook/references/load-map.md +8 -0
- package/skills/design-playbook/references/observe-ops.md +10 -0
- package/skills/design-playbook/references/preview-ops.md +11 -0
- package/skills/ui-evaluator/SKILL.md +5 -1
- package/skills/ui-evaluator/references/a11y-tree.md +31 -0
- package/skills/ui-evaluator/references/repair.md +20 -0
- package/skills/ux-spec/SKILL.md +10 -2
- package/mcp/preview/test_anchor_v2.py +0 -69
package/README.md
CHANGED
|
@@ -135,9 +135,28 @@ The Design I/O run is a **declared, host-neutral contract** over plain-Markdown
|
|
|
135
135
|
|
|
136
136
|
Run artifacts land under `.scratch/<run>/` (`design-baseline/`, `plan.md`, `preview/`, `evidence/manifest.jsonl`, `point-back.md`); see the orchestrator skill for what lands when. That is where to look — and manually intervene — when a run stalls.
|
|
137
137
|
|
|
138
|
+
### Stuck / resume
|
|
139
|
+
|
|
140
|
+
```text
|
|
141
|
+
python <pkg>/scripts/run_status.py .scratch/<run> # text phases + next action
|
|
142
|
+
python <pkg>/scripts/run_status.py .scratch/<run> --json # machine-readable
|
|
143
|
+
python <pkg>/scripts/run_status.py --list # newest runs under .scratch/
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
The status command reuses the packaged validator’s G5 confirm rules. It is part of the installed package — not monorepo-only tooling.
|
|
147
|
+
|
|
148
|
+
### Doctor
|
|
149
|
+
|
|
150
|
+
```text
|
|
151
|
+
python <pkg>/scripts/doctor.py
|
|
152
|
+
python <pkg>/scripts/doctor.py --json
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
One packaged diagnosis for interpreter, package surface, optional Playwright, and run-root configuration. Distinguishes `ok` / `degraded` / `broken` with repair actions.
|
|
156
|
+
|
|
138
157
|
**Bundled MCP (v0.3+):** Preview (`mcp/preview/`) and Evidence (`mcp/evidence/`) runtimes ship inside this package and are registered by `.mcp.json` (`${CLAUDE_PLUGIN_ROOT}`). Sibling monorepo dirs remain compatibility launchers/docs. The orchestrator still **probes** MCP `tools/list` and skips `preview*` / `observe*` when tools are absent. Evidence provider writes artifacts only — never the manifest. **`DESIGN_PLAYBOOK_RUN_ROOT`:** default `"."` in `.mcp.json` is the **MCP process cwd**, not the chat workspace — for a host-app dogfood, set an **absolute** path to `.scratch/<run>/` (see [`mcp/evidence/README.md`](mcp/evidence/README.md)). Capture responses include `written_path` (absolute) so mis-rooted writes are visible without a filesystem search.
|
|
139
158
|
|
|
140
|
-
What is **deterministically enforced** today:
|
|
159
|
+
What is **deterministically enforced** today: repository install/structure CI checks and the run-artifact shape (`scripts/validate_run.py` — L1–L6 present; every top-level L6 item ordered `Given -> When -> Then`; one non-empty four-field evidence ledger row per `L6.<n>` with allowed results; four non-empty finding fields with non-empty source; exactly one explicit `## Verdict` of `Pass` or `Recirculate`; Pass requires every evidence result to be `pass` and exactly one issue-linked `0 blocking` closure per blocking finding; exit 0/`RUN OK`, exit 1/`RUN INVALID`, exit 2/`RUN ERROR`; regression-tested by `tests/test_validate_run.py`, which also validates the showcase artifacts directly; **G5** is a *conditional* preview-confirm gate — enforced only when preview artifacts exist / `--preview-dir` is used; **G6** is a *conditional* evidence-binding gate — enforced only when a ledger `observed` references an `evidence/` artifact / `--evidence-dir` is used; opt-in **strict mode** via `--require-preview` / `--require-evidence` / `--strict`). The `observe*` step probes MCP tool `execute_capture_plan` and is skipped when absent. Everything else in the pipeline is agent-executed craft judgment, not a machine gate.
|
|
141
160
|
|
|
142
161
|
## Codex
|
|
143
162
|
|
package/codex/AGENTS.md
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# design-playbook for Codex
|
|
2
|
+
|
|
3
|
+
## Install (path of record)
|
|
4
|
+
|
|
5
|
+
Marketplace catalog lives at the **repo root** (same GitHub repo as Claude Code).
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
# published
|
|
9
|
+
codex plugin marketplace add Bandersnatch0x/design-playbook
|
|
10
|
+
codex plugin add design-playbook@design-playbook
|
|
11
|
+
|
|
12
|
+
# local monorepo (dev)
|
|
13
|
+
codex plugin marketplace add <abs-path-to-repo-root>
|
|
14
|
+
codex plugin add design-playbook@design-playbook
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Verify:
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
codex plugin list -m design-playbook --available --json
|
|
21
|
+
# expect: design-playbook@design-playbook, enabled=true after add
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Codex-native manifest: `packages/design-playbook/.codex-plugin/plugin.json`
|
|
25
|
+
Codex MCP (relative paths, no `CLAUDE_PLUGIN_ROOT`): `.codex-plugin/mcp.json`
|
|
26
|
+
Skills: `packages/design-playbook/skills/*`
|
|
27
|
+
|
|
28
|
+
## Fallback: skills-only install
|
|
29
|
+
|
|
30
|
+
If you only want skills under `~/.codex/skills` (no plugin marketplace):
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
# from repo root — copies/symlinks skill trees into ~/.codex/skills
|
|
34
|
+
python packages/design-playbook/codex/install_skills.py --force
|
|
35
|
+
# or @-reference a single skill:
|
|
36
|
+
# @packages/design-playbook/skills/design-playbook/SKILL.md
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Manual MCP (only if not using `codex plugin add`):
|
|
40
|
+
|
|
41
|
+
```toml
|
|
42
|
+
# ~/.codex/config.toml
|
|
43
|
+
[mcp_servers.design-playbook-preview]
|
|
44
|
+
command = "python"
|
|
45
|
+
args = ["<abs>/packages/design-playbook/mcp/preview/server.py"]
|
|
46
|
+
|
|
47
|
+
[mcp_servers.design-playbook-evidence]
|
|
48
|
+
command = "python"
|
|
49
|
+
args = ["<abs>/packages/design-playbook/mcp/evidence/server.py"]
|
|
50
|
+
# evidence also needs: pip install playwright && playwright install chromium
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Load order
|
|
54
|
+
|
|
55
|
+
1. `skills/design-playbook/SKILL.md`
|
|
56
|
+
2. Standard order: `design-baseline?` → `ux-spec` → `ui-picker` → `fill` → `craft-guard` → `ui-evaluator`.
|
|
57
|
+
|
|
58
|
+
Native desktop order: `ux-spec` → `native-craft` → `ui-picker` → `fill` → `craft-guard` → `ui-evaluator`.
|
|
59
|
+
|
|
60
|
+
Conditional entry `reference-intake?` (screenshot/URL/design/product analogy, ADR-0011) runs **before** `ux-spec?` when reference materials are present — fixed orchestrator order, not reorderable. Run `native-craft` only for an explicit native-desktop/native-feel target. Web and mobile Web skip `native-craft`; if the platform is unclear, ask before choosing the order. The orchestrator owns the decision gate, render-surface seam handoff, and fail-closed behavior.
|
|
61
|
+
|
|
62
|
+
Conditional entry `design-baseline?` (ADR-0012) runs before `reference-intake?` for UI builds/fixes in repositories with meaningful existing first-party UI. Existing-product Fill requires a valid existing baseline, an accepted generated baseline, or an explicit user waiver.
|
|
63
|
+
|
|
64
|
+
Mirror the orchestrator's skip narration (SKILL.md Steps preamble): when a step is skipped, output one line — step name + reason + how to enable, with the gate label when one applies, e.g. `-> preview*: adapter absent, skipped (G5 not triggered; enable via packages/design-playbook/mcp/preview/ or host MCP)`.
|
|
65
|
+
|
|
66
|
+
## Compose
|
|
67
|
+
|
|
68
|
+
- Style DB → ui-ux-pro-max
|
|
69
|
+
- Visual risk → frontend-design
|
|
70
|
+
- Pipeline + acceptance → design-playbook
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Cross-platform Codex skill installer for design-playbook.
|
|
3
|
+
|
|
4
|
+
Creates (or refreshes) symlinks under ``~/.codex/skills/<name>`` pointing at
|
|
5
|
+
this package's ``skills/*`` directories. Falls back to directory copy when
|
|
6
|
+
symlinks are unavailable (common on Windows without Developer Mode).
|
|
7
|
+
"""
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
import argparse
|
|
11
|
+
import os
|
|
12
|
+
import shutil
|
|
13
|
+
import sys
|
|
14
|
+
from pathlib import Path
|
|
15
|
+
|
|
16
|
+
PACKAGE = Path(__file__).resolve().parents[1]
|
|
17
|
+
SKILLS_SRC = PACKAGE / "skills"
|
|
18
|
+
DEFAULT_DEST = Path.home() / ".codex" / "skills"
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def install_one(src: Path, dest: Path, *, force: bool) -> str:
|
|
22
|
+
if not src.is_dir():
|
|
23
|
+
return f"skip {src.name}: source missing"
|
|
24
|
+
if dest.exists() or dest.is_symlink():
|
|
25
|
+
if not force:
|
|
26
|
+
return f"skip {src.name}: {dest} exists (pass --force)"
|
|
27
|
+
if dest.is_symlink() or dest.is_file():
|
|
28
|
+
dest.unlink()
|
|
29
|
+
else:
|
|
30
|
+
shutil.rmtree(dest)
|
|
31
|
+
dest.parent.mkdir(parents=True, exist_ok=True)
|
|
32
|
+
try:
|
|
33
|
+
os.symlink(src, dest, target_is_directory=True)
|
|
34
|
+
return f"link {src.name} -> {dest}"
|
|
35
|
+
except OSError:
|
|
36
|
+
shutil.copytree(src, dest)
|
|
37
|
+
return f"copy {src.name} -> {dest}"
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def main(argv: list[str] | None = None) -> int:
|
|
41
|
+
parser = argparse.ArgumentParser(description="Install design-playbook skills for Codex")
|
|
42
|
+
parser.add_argument(
|
|
43
|
+
"--dest",
|
|
44
|
+
type=Path,
|
|
45
|
+
default=DEFAULT_DEST,
|
|
46
|
+
help=f"skills directory (default: {DEFAULT_DEST})",
|
|
47
|
+
)
|
|
48
|
+
parser.add_argument(
|
|
49
|
+
"--force",
|
|
50
|
+
action="store_true",
|
|
51
|
+
help="replace existing skill directories/links",
|
|
52
|
+
)
|
|
53
|
+
args = parser.parse_args(argv)
|
|
54
|
+
|
|
55
|
+
if not SKILLS_SRC.is_dir():
|
|
56
|
+
print(f"skills source missing: {SKILLS_SRC}", file=sys.stderr)
|
|
57
|
+
return 2
|
|
58
|
+
|
|
59
|
+
print(f"source: {SKILLS_SRC}")
|
|
60
|
+
print(f"dest: {args.dest}")
|
|
61
|
+
for skill in sorted(p for p in SKILLS_SRC.iterdir() if p.is_dir()):
|
|
62
|
+
print(" ", install_one(skill, args.dest / skill.name, force=args.force))
|
|
63
|
+
print("done. Load design-playbook via Codex skills or @ references.")
|
|
64
|
+
print("MCP: see packages/design-playbook/codex/AGENTS.md")
|
|
65
|
+
return 0
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
if __name__ == "__main__":
|
|
69
|
+
sys.exit(main())
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Diagnose installed design-playbook capability and repairs
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# doctor
|
|
6
|
+
|
|
7
|
+
One packaged diagnosis entry for install/runtime capability.
|
|
8
|
+
|
|
9
|
+
```text
|
|
10
|
+
python <plugin>/scripts/doctor.py
|
|
11
|
+
python <plugin>/scripts/doctor.py --json
|
|
12
|
+
python <plugin>/scripts/doctor.py --run-root .scratch/<run>
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
Reports `ok` / `degraded` / `broken`. Failed checks include a concrete repair. Optional adapters (Playwright, run-root env) degrade rather than hard-fail the install.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Report Design I/O run phase, blocker, and next resume action
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# run-status
|
|
6
|
+
|
|
7
|
+
Inspect a stopped Design I/O run without reconstructing state from scratch files by hand.
|
|
8
|
+
|
|
9
|
+
## Usage
|
|
10
|
+
|
|
11
|
+
```text
|
|
12
|
+
python <plugin>/scripts/run_status.py [.scratch/<run>] [--json] [--list] [--scratch <dir>]
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
- Omit the run path to pick the newest directory under `--scratch` (default `.scratch/`).
|
|
16
|
+
- `--json` emits machine-readable stages + `next` action.
|
|
17
|
+
- `--list` only lists discovered runs.
|
|
18
|
+
|
|
19
|
+
## Done when
|
|
20
|
+
|
|
21
|
+
The command names completed stage markers, any active blocker (preview floor, baseline gate, recirculate verdict), and the single next valid resume action. It reuses `validate_run` judgments for G5 confirm validity rather than inventing a second state machine.
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"""Namespace alias: absolute ``design_playbook.*`` imports inside this plugin.
|
|
2
|
+
|
|
3
|
+
The plugin directory is ``design-playbook`` (hyphen), so Python's import
|
|
4
|
+
system cannot load it under the identifier ``design_playbook`` — FileFinder
|
|
5
|
+
matches directory names literally. This module aliases the package root onto
|
|
6
|
+
``design_playbook.__path__`` so that, once the one bootstrap (ADR-0022) puts
|
|
7
|
+
the package root on ``sys.path``, absolute imports such as
|
|
8
|
+
``design_playbook.mcp.preview.integrity`` and
|
|
9
|
+
``design_playbook.scripts.stages`` resolve to the real ``mcp/`` and
|
|
10
|
+
``scripts/`` trees below.
|
|
11
|
+
|
|
12
|
+
The alias also keeps the import seam namespaced: a bare ``mcp.*`` import
|
|
13
|
+
would collide with the PyPI ``mcp`` SDK when the host has it installed.
|
|
14
|
+
"""
|
|
15
|
+
from __future__ import annotations
|
|
16
|
+
|
|
17
|
+
from pathlib import Path
|
|
18
|
+
|
|
19
|
+
__path__ = [str(Path(__file__).resolve().parent)]
|
|
20
|
+
__all__: list[str] = []
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# examples
|
|
2
|
+
|
|
3
|
+
Self-authored samples for onboarding and dogfood. **Not** ports of any upstream playbook.
|
|
4
|
+
|
|
5
|
+
| File | Use |
|
|
6
|
+
| --- | --- |
|
|
7
|
+
| [ops-list-spec.md](ops-list-spec.md) | Minimal six-layer spec (ops delivery log) |
|
|
8
|
+
| [settings-decision-report.md](settings-decision-report.md) | ui-picker decision report before code |
|
|
9
|
+
| [point-back-findings.md](point-back-findings.md) | evaluator output shape + recirculate |
|
|
10
|
+
|
|
11
|
+
Agent-loaded SSOT remains `../skills/*/references/*`. These files are human-facing packs you can paste into a session.
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# Composition detector contrast cases
|
|
2
|
+
|
|
3
|
+
Authored worked cases for CRAFT-01 through CRAFT-05. Each case combines a rendered observation with independent source evidence. `Expected` is advisory detector status, not evaluator severity or verdict.
|
|
4
|
+
|
|
5
|
+
| Case | ID | Expected | Rendered evidence | Source evidence | Exception check | Owner hint | Positive fix |
|
|
6
|
+
| --- | --- | --- | --- | --- | --- | --- | --- |
|
|
7
|
+
| competing-actions-hit | CRAFT-01 | hit | Header exposes Create, Import, and Export with equal filled emphasis | All three actions use primary Button variant | Spec names Create as main task; no equal-choice exception | craft | Keep Create primary and group Import/Export as secondary actions |
|
|
8
|
+
| equal-choice-clear | CRAFT-01 | clear | Two plan options receive equal weight in a deliberate comparison | Shared selectable-card primitive applies same selected affordance | Spec requires neutral side-by-side choice before Continue | craft | - |
|
|
9
|
+
| queue-card-wall-hit | CRAFT-02 | hit | Twelve equal cards make status and owner hard to compare | Queue records map directly to Card wrappers | Records are operational rows, not independent browse objects | template | Replace card wall with table/list and stable comparison columns |
|
|
10
|
+
| card-collection-clear | CRAFT-02 | clear | Gallery cards represent independent templates with image, owner, and open action | TemplateCard owns preview and item-level interaction | Browsable independent objects fit card semantics | template | - |
|
|
11
|
+
| nested-panels-hit | CRAFT-03 | hit | Page section floats as a shadowed card containing three more bordered cards | Card wraps section and nested Cards provide spacing only | No modal, tool, or repeated-item semantics justify frames | template | Flatten section, group with spacing/dividers, retain frame only for tool |
|
|
12
|
+
| drawer-tool-clear | CRAFT-03 | clear | Unframed page contains one bounded detail drawer | Drawer primitive owns focus and dismiss behavior; no nested Card | Detail drawer is a genuine framed tool | components | - |
|
|
13
|
+
| blue-everywhere-hit | CRAFT-04 | hit | Canvas, surfaces, actions, charts, and state badges use blue variants | Single blue ramp fills surface, action, success, and selected roles | No verified monochrome baseline or semantic role separation | design | Restore neutral surfaces and assign distinct semantic state roles |
|
|
14
|
+
| semantic-color-clear | CRAFT-04 | clear | Neutral surfaces dominate; cyan marks selection, amber warning, red failure | Tokens map each semantic role independently | Brand accent remains selective and states stay distinguishable | design | - |
|
|
15
|
+
| pill-everything-hit | CRAFT-05 | hit | Tabs, buttons, fields, filters, and section labels all use pill silhouettes | Global radius-full token applies across unrelated controls | No baseline or semantic grouping justifies uniform pill geometry | components | Restore control-specific shapes and reserve pills for compact tags |
|
|
16
|
+
| status-pill-clear | CRAFT-05 | clear | Compact pills appear only for status and removable filter chips | Badge and Chip primitives use pill shape; buttons use restrained radius | Shape communicates status/grouping and is not page-wide | components | - |
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# Existing-brand baseline contrast
|
|
2
|
+
|
|
3
|
+
## Verified baseline exception
|
|
4
|
+
|
|
5
|
+
- Detector: CRAFT-05
|
|
6
|
+
- Generic signal: product uses pill geometry across navigation and compact actions.
|
|
7
|
+
- Rendered evidence: pill silhouette is consistent, sparse, readable, and does not obscure control state.
|
|
8
|
+
- Source evidence: confirmed project radius token and shared primitives apply the geometry consistently.
|
|
9
|
+
- Verified baseline: project `DESIGN.md` explicitly names capsule geometry as a first-party brand convention; binding status is `ready`.
|
|
10
|
+
- Baseline disposition: clear
|
|
11
|
+
- Reason: verified project choice wins generic detector taste.
|
|
12
|
+
|
|
13
|
+
## Override boundary
|
|
14
|
+
|
|
15
|
+
- Detector: CRAFT-07
|
|
16
|
+
- Generic signal: dangerous account deletion is represented by an unlabeled trash icon.
|
|
17
|
+
- Rendered evidence: destructive action has no text, consequence, or confirmation cue.
|
|
18
|
+
- Source evidence: IconButton invokes deletion directly without confirmation Dialog.
|
|
19
|
+
- Verified baseline: project uses icon-only toolbars.
|
|
20
|
+
- Override disposition: hit
|
|
21
|
+
- Reason: safety, usability, and explicit dangerous-action declarations override baseline consistency.
|
|
22
|
+
- Positive fix: retain baseline icon treatment for ordinary tools, but use explicit destructive text and confirmation for account deletion.
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# Landing and product detector contrast cases
|
|
2
|
+
|
|
3
|
+
Authored worked cases for CRAFT-06 through CRAFT-08. Each result is advisory and leaves declaration mapping, severity, and verdict to `ui-evaluator`.
|
|
4
|
+
|
|
5
|
+
| Case | ID | Expected | Rendered evidence | Source evidence | Exception check | Owner hint | Positive fix |
|
|
6
|
+
| --- | --- | --- | --- | --- | --- | --- | --- |
|
|
7
|
+
| dashboard-display-type-hit | CRAFT-06 | hit | Compact metrics panel uses 72px heading that crowds values below | Panel heading references display-hero token | Surface is an operational panel, not a literal hero | design | Use panel title role and preserve hierarchy through grouping and weight |
|
|
8
|
+
| product-hero-clear | CRAFT-06 | clear | Product name leads first viewport while next section remains visible | H1 uses display token within bounded responsive hero | Literal product hero warrants display scale and text fits target viewports | design | - |
|
|
9
|
+
| verbose-toolbar-hit | CRAFT-07 | hit | Toolbar repeats Undo, Redo, Save, Zoom in, and Zoom out as wide text pills | Generic Button renders familiar tool actions despite icon library availability | Actions are familiar and low-risk; accessible icon labels are possible | components | Use icon buttons with accessible names and tooltips; keep text for ambiguous commands |
|
|
10
|
+
| destructive-text-clear | CRAFT-07 | clear | Delete workspace remains an explicit text action with consequence copy | Destructive Button opens confirmation Dialog | High-risk action benefits from explicit language | components | - |
|
|
11
|
+
| looping-decoration-hit | CRAFT-08 | hit | CTA badge bounces continuously without state change | Infinite keyframes animate translateY and ignore reduced-motion | No game or immersive intent is declared | craft | Remove loop and use short transform/opacity feedback only for a named state change |
|
|
12
|
+
| state-transition-clear | CRAFT-08 | clear | Saved indicator fades in after persistence and stays stable | 160ms opacity transition follows saved state and reduced-motion disables it | Motion explains persistence completion | craft | - |
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# SaaS dashboard detector contrast
|
|
2
|
+
|
|
3
|
+
Worked fixture for detector protocol validation. Rendered and source descriptions are independent authored observations, not validator-generated expectations.
|
|
4
|
+
|
|
5
|
+
## Input
|
|
6
|
+
|
|
7
|
+
- Rendered surface: desktop operations dashboard at 1440 x 900.
|
|
8
|
+
- Source surface: React page using shared Button, Table, Card, Badge, and motion tokens.
|
|
9
|
+
- Baseline: none.
|
|
10
|
+
|
|
11
|
+
## Detector ledger
|
|
12
|
+
|
|
13
|
+
| ID | Status | Rendered evidence | Source evidence | Exception check | Positive fix |
|
|
14
|
+
| --- | --- | --- | --- | --- | --- |
|
|
15
|
+
| CRAFT-01 | hit | Header has three equally filled primary actions | Three Button instances use `variant="primary"` | No equal-choice flow in spec | Keep Create run primary; move Import and Export to secondary/menu actions |
|
|
16
|
+
| CRAFT-02 | hit | Twelve equal cards hide queue comparison | Queue records map directly to Card wrappers | Records are comparable operational rows, not independent browse objects | Use a table/list with stable columns and one framed detail tool |
|
|
17
|
+
| CRAFT-03 | clear | Page bands are unframed; detail drawer alone is framed | Card is not nested and Drawer owns detail | Drawer is a genuine framed tool | - |
|
|
18
|
+
| CRAFT-04 | clear | Neutral surfaces carry most area; amber and red have named state roles | Semantic tokens map warning and failure independently | No monochrome exception needed | - |
|
|
19
|
+
| CRAFT-05 | clear | Pills appear only for status badges | Badge uses pill radius; buttons and inputs use control-specific shape | Status grouping warrants compact pill | - |
|
|
20
|
+
| CRAFT-06 | clear | Panel headings fit dense dashboard hierarchy | Display type token is absent inside panels | No hero context claimed | - |
|
|
21
|
+
| CRAFT-07 | clear | Refresh and close use named icon buttons; destructive action keeps text | IconButton has accessible labels and destructive Button remains explicit | High-risk action needs text | - |
|
|
22
|
+
| CRAFT-08 | blocked | Static capture cannot prove transition purpose or reduced-motion behavior | Motion source was not included in review input | No exception can be checked without source | Provide motion source and interaction trace before complete craft Pass |
|
|
23
|
+
|
|
24
|
+
## Expected contract observations
|
|
25
|
+
|
|
26
|
+
- All eight stable IDs appear exactly once.
|
|
27
|
+
- Ledger contains `hit`, `clear`, and `blocked`.
|
|
28
|
+
- Hit rows carry rendered evidence, source evidence, exception check, and positive fix.
|
|
29
|
+
- No row assigns declaration source, severity, or verdict.
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# Ops delivery log — sample spec.md
|
|
2
|
+
|
|
3
|
+
Illustrative only. Replace domain terms for your product.
|
|
4
|
+
|
|
5
|
+
## L1 定位与意图
|
|
6
|
+
|
|
7
|
+
- 一句话定义:查看某端点的 webhook 投递记录,并对失败项触发重试。
|
|
8
|
+
- 目标用户:集成开发者。
|
|
9
|
+
- 场景:日常排查投递失败;批量重试一段窗口内的失败。
|
|
10
|
+
- 非目标:不在此配置端点密钥;不做全站日志检索。
|
|
11
|
+
- 行为边界:重试 = 询问后;删除投递记录 = 永不(本页)。
|
|
12
|
+
|
|
13
|
+
## L2 信息架构
|
|
14
|
+
|
|
15
|
+
- 顶栏:端点选择、时间范围、状态筛选。
|
|
16
|
+
- 主区:投递列表(状态、HTTP、耗时、时间、操作)。
|
|
17
|
+
- 侧/展开:单次请求/响应摘要(默认脱敏)。
|
|
18
|
+
- 批量条:选中失败项后的重试入口。
|
|
19
|
+
|
|
20
|
+
## L3 核心链路
|
|
21
|
+
|
|
22
|
+
- pending → delivered
|
|
23
|
+
- pending → failed → retry → pending
|
|
24
|
+
- failed → ignore(仅隐藏于默认筛选,不删数据)
|
|
25
|
+
|
|
26
|
+
## L4 组件功能细节
|
|
27
|
+
|
|
28
|
+
- 状态 Badge:pending / delivered / failed。
|
|
29
|
+
- 行操作:查看详情、重试(loading / disabled / error)。
|
|
30
|
+
- 批量重试:二次确认后并行触发,逐行回写结果。
|
|
31
|
+
|
|
32
|
+
## L5 边界条件
|
|
33
|
+
|
|
34
|
+
- 空态:该端点暂无投递;说明如何触发一次测试投递。
|
|
35
|
+
- 加载:表结构骨架,不塌布局。
|
|
36
|
+
- 错误:列表拉取失败 → 原因 + 重试;单条重试失败 → 行内错误 + 可再试。
|
|
37
|
+
- 权限:只读角色禁用重试,并说明所需权限。
|
|
38
|
+
|
|
39
|
+
## L6 验收标准
|
|
40
|
+
|
|
41
|
+
- Given 一条 failed,When 打开详情,Then 可见状态码/错误摘要且敏感字段脱敏。
|
|
42
|
+
- Given 一条 failed,When 重试成功,Then 行转为 pending 且可刷新到 delivered。
|
|
43
|
+
- Given 无数据,Then 非白屏空态。
|
|
44
|
+
- Given 只读用户,Then 无法触发重试且有原因。
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# Sample point-back findings + recirculate
|
|
2
|
+
|
|
3
|
+
Illustrative `ui-evaluator` output. Every issue names a declaration.
|
|
4
|
+
|
|
5
|
+
```text
|
|
6
|
+
issue: update payment has no confirm step
|
|
7
|
+
source: domain
|
|
8
|
+
fix: Dialog with consequence copy before submit
|
|
9
|
+
severity: high
|
|
10
|
+
|
|
11
|
+
issue: full card number rendered in form summary
|
|
12
|
+
source: domain
|
|
13
|
+
fix: mask to last-4; explicit reveal only if product allows
|
|
14
|
+
severity: high
|
|
15
|
+
|
|
16
|
+
issue: empty invoice table is a blank white region
|
|
17
|
+
source: spec
|
|
18
|
+
fix: empty state copy + CTA to billing history help
|
|
19
|
+
severity: med
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Recirculate (blocking)
|
|
23
|
+
|
|
24
|
+
1. Open owning declaration (`domain` / `spec` / …).
|
|
25
|
+
2. Patch only that layer.
|
|
26
|
+
3. Resume pipeline from the step that consumes it (fill or craft).
|
|
27
|
+
4. Re-run evaluator → **Done when** zero high/blocking remain (or each remaining item is explicitly accepted by the user).
|
|
28
|
+
|
|
29
|
+
Do not whole-page restyle to “clear” blocking findings.
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# reference-intake examples
|
|
2
|
+
|
|
3
|
+
Three minimal fixtures for ADR-0011. They are **shape samples**, not live run artifacts.
|
|
4
|
+
|
|
5
|
+
| Fixture | Source kind | Shows |
|
|
6
|
+
| --- | --- | --- |
|
|
7
|
+
| `screenshot/` | local image | evidence + file sha256 inventory |
|
|
8
|
+
| `url/` | absolute URL | structure notes without shipping third-party chrome |
|
|
9
|
+
| `product-analogy/` | named product taste | Keep/Change/Do not copy without a file |
|
|
10
|
+
|
|
11
|
+
Real runs write the same filenames under `.scratch/<run>/reference/`.
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# Reference contract — product-analogy fixture
|
|
2
|
+
|
|
3
|
+
## Source summary
|
|
4
|
+
|
|
5
|
+
- Ask (one line): Agent ops dashboard that feels as scannable as Linear's issue list, but for our agent runs.
|
|
6
|
+
- Sources (ids matching `manifest.json`): src-1 (product analogy)
|
|
7
|
+
- Captured at (ISO-8601; may match `manifest.json` top-level `captured_at`): 2026-07-22T10:10:00+08:00
|
|
8
|
+
|
|
9
|
+
## Evidence (observed)
|
|
10
|
+
|
|
11
|
+
- User provided no screenshot; only the product name "Linear" as a taste anchor.
|
|
12
|
+
- Requested qualities in chat: scannable rows, keyboard-friendly, low decoration.
|
|
13
|
+
|
|
14
|
+
## Inferred (labeled)
|
|
15
|
+
|
|
16
|
+
- Prefer tight row height and muted meta columns | confidence: medium | why: common Linear-list reading of "scannable"
|
|
17
|
+
- Avoid kanban as default | confidence: medium | why: user said list, not board
|
|
18
|
+
|
|
19
|
+
## Keep
|
|
20
|
+
|
|
21
|
+
- Scannable list semantics: identity column + sparse meta + quiet density
|
|
22
|
+
|
|
23
|
+
## Change
|
|
24
|
+
|
|
25
|
+
- Domain objects are agent runs, not issues; columns and empty states follow our L2 duties
|
|
26
|
+
- Keyboard map must match our app, not Linear shortcuts
|
|
27
|
+
|
|
28
|
+
## Do not copy
|
|
29
|
+
|
|
30
|
+
- Linear wordmark, issue ID format, and any trademarked product chrome
|
|
31
|
+
- Distinctive empty-state illustration or onboarding checklist copy
|
|
32
|
+
|
|
33
|
+
## Functional constraints for ux-spec
|
|
34
|
+
|
|
35
|
+
- Goal / scene hints: operator scans agent runs and opens one run detail
|
|
36
|
+
- States or edges implied: empty fleet, filtered-empty, run failure badge
|
|
37
|
+
- Non-goals implied by Do not copy: not a Linear clone; no issue-tracker information architecture
|
|
38
|
+
- always / ask / never hints: always show run state chip; ask before bulk cancel; never use Linear keyboard map as default
|
|
39
|
+
|
|
40
|
+
## Visual cues for ui-picker
|
|
41
|
+
|
|
42
|
+
- Density: console-tight
|
|
43
|
+
- Scene class hints: list / agent-admin
|
|
44
|
+
- Region weight / hierarchy: main = run table; side optional filters; status = run state chip
|
|
45
|
+
- Explicit exclusions: marketing hero, board/kanban default
|
|
46
|
+
|
|
47
|
+
## License / brand risks
|
|
48
|
+
|
|
49
|
+
- Product analogy only. Do not download or embed Linear brand assets. If a later screenshot is added, re-run reference-intake and tighten Do not copy.
|
|
50
|
+
|
|
51
|
+
## Unresolved questions
|
|
52
|
+
|
|
53
|
+
- Which columns are mandatory for v0 agent-run list?
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schema": "design-playbook.reference.manifest/v1",
|
|
3
|
+
"run_id": "fixture-product-analogy",
|
|
4
|
+
"captured_at": "2026-07-22T10:10:00+08:00",
|
|
5
|
+
"tool": "reference-intake",
|
|
6
|
+
"sources": [
|
|
7
|
+
{
|
|
8
|
+
"id": "src-1",
|
|
9
|
+
"kind": "product_analogy",
|
|
10
|
+
"locator": "Linear (product analogy; no asset)",
|
|
11
|
+
"sha256": null,
|
|
12
|
+
"note": "taste anchor only"
|
|
13
|
+
}
|
|
14
|
+
]
|
|
15
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Fixture placeholder. Real runs store the referenced screenshot bytes here.
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# Reference contract — screenshot fixture
|
|
2
|
+
|
|
3
|
+
## Source summary
|
|
4
|
+
|
|
5
|
+
- Ask (one line): Rebuild the ops alert list so empty/error states match this screenshot's information hierarchy, without copying brand chrome.
|
|
6
|
+
- Sources (ids matching `manifest.json`): src-1 (local screenshot)
|
|
7
|
+
- Captured at (ISO-8601; may match `manifest.json` top-level `captured_at`): 2026-07-22T10:00:00+08:00
|
|
8
|
+
|
|
9
|
+
## Evidence (observed)
|
|
10
|
+
|
|
11
|
+
- Dense console list: primary column is alert title; secondary meta is severity + time.
|
|
12
|
+
- Empty state is a centered panel with one primary action, not a blank table body only.
|
|
13
|
+
- Severity uses a compact status chip left of the title, not a colored full-row background.
|
|
14
|
+
|
|
15
|
+
## Inferred (labeled)
|
|
16
|
+
|
|
17
|
+
- Operators scan severity before title | confidence: medium | why: chip is left-aligned in the first 80px of each row
|
|
18
|
+
- Empty-state action creates a new alert rule | confidence: low | why: button label not fully legible in the crop
|
|
19
|
+
|
|
20
|
+
## Keep
|
|
21
|
+
|
|
22
|
+
- Severity-before-title scan order
|
|
23
|
+
- Empty state with a single primary recovery action
|
|
24
|
+
|
|
25
|
+
## Change
|
|
26
|
+
|
|
27
|
+
- Replace third-party product name and iconography with our product voice
|
|
28
|
+
- Map severity chip to our status role tokens, not the reference palette
|
|
29
|
+
|
|
30
|
+
## Do not copy
|
|
31
|
+
|
|
32
|
+
- Product logo, wordmark, and distinctive empty-state illustration
|
|
33
|
+
- Exact marketing microcopy on the primary button
|
|
34
|
+
|
|
35
|
+
## Functional constraints for ux-spec
|
|
36
|
+
|
|
37
|
+
- Goal / scene hints: operator can triage alerts and recover from empty/error
|
|
38
|
+
- States or edges implied: default list, empty, error reload
|
|
39
|
+
- Non-goals implied by Do not copy: do not reproduce vendor branding or illustration system
|
|
40
|
+
- always / ask / never hints: always show empty recovery action; ask before bulk-dismiss; never auto-delete alerts
|
|
41
|
+
|
|
42
|
+
## Visual cues for ui-picker
|
|
43
|
+
|
|
44
|
+
- Density: console-tight
|
|
45
|
+
- Scene class hints: list
|
|
46
|
+
- Region weight / hierarchy: main = table; action = top-right primary; status = per-row chip
|
|
47
|
+
- Explicit exclusions: no marketing hero, no full-row severity paint
|
|
48
|
+
|
|
49
|
+
## License / brand risks
|
|
50
|
+
|
|
51
|
+
- Screenshot appears to be a third-party product UI; treat as unlicensed reference only. Do not ship cropped brand assets into Fill or public demos.
|
|
52
|
+
|
|
53
|
+
## Unresolved questions
|
|
54
|
+
|
|
55
|
+
- Exact empty-state button label is illegible in the crop; confirm with product owner
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schema": "design-playbook.reference.manifest/v1",
|
|
3
|
+
"run_id": "fixture-screenshot",
|
|
4
|
+
"captured_at": "2026-07-22T10:00:00+08:00",
|
|
5
|
+
"tool": "reference-intake",
|
|
6
|
+
"sources": [
|
|
7
|
+
{
|
|
8
|
+
"id": "src-1",
|
|
9
|
+
"kind": "screenshot",
|
|
10
|
+
"locator": "assets/ops-alert-list.png",
|
|
11
|
+
"sha256": "0000000000000000000000000000000000000000000000000000000000000000",
|
|
12
|
+
"note": "fixture placeholder hash; real runs must hash the file"
|
|
13
|
+
}
|
|
14
|
+
]
|
|
15
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# Reference contract — URL fixture
|
|
2
|
+
|
|
3
|
+
## Source summary
|
|
4
|
+
|
|
5
|
+
- Ask (one line): Settings page for notification channels; use the linked docs site IA as reference, not as a skin.
|
|
6
|
+
- Sources (ids matching `manifest.json`): src-1 (URL)
|
|
7
|
+
- Captured at (ISO-8601; may match `manifest.json` top-level `captured_at`): 2026-07-22T10:05:00+08:00
|
|
8
|
+
|
|
9
|
+
## Evidence (observed)
|
|
10
|
+
|
|
11
|
+
- Left nav groups settings into Account / Notifications / Integrations.
|
|
12
|
+
- Notifications page uses a definition-list of channels with a trailing toggle, not a multi-column form grid.
|
|
13
|
+
- Destructive actions stay outside the per-channel row.
|
|
14
|
+
|
|
15
|
+
## Inferred (labeled)
|
|
16
|
+
|
|
17
|
+
- Toggle is optimistic with toast rollback | confidence: low | why: network behavior not visible from static docs page
|
|
18
|
+
- Integrations is out of scope for this ask | confidence: high | why: user named notifications only
|
|
19
|
+
|
|
20
|
+
## Keep
|
|
21
|
+
|
|
22
|
+
- Grouped left nav with a single active section highlight
|
|
23
|
+
- Channel rows as label + short description + trailing control
|
|
24
|
+
|
|
25
|
+
## Change
|
|
26
|
+
|
|
27
|
+
- Replace docs-site content width with our app shell widths
|
|
28
|
+
- Use our settings template regions instead of docs sidebar chrome
|
|
29
|
+
|
|
30
|
+
## Do not copy
|
|
31
|
+
|
|
32
|
+
- Vendor site logo, docs search widget, and marketing CTA footer
|
|
33
|
+
- Exact section titles that are product-trademark phrases
|
|
34
|
+
|
|
35
|
+
## Functional constraints for ux-spec
|
|
36
|
+
|
|
37
|
+
- Goal / scene hints: user enables/disables notification channels and understands delivery target
|
|
38
|
+
- States or edges implied: loading channel list, save error, permission denied
|
|
39
|
+
- Non-goals implied by Do not copy: no docs search, no marketing footer, no integrations subtree in this run
|
|
40
|
+
- always / ask / never hints: always show channel delivery target; ask before disabling the last channel; never bury destructive actions in the row
|
|
41
|
+
|
|
42
|
+
## Visual cues for ui-picker
|
|
43
|
+
|
|
44
|
+
- Density: console-tight
|
|
45
|
+
- Scene class hints: settings
|
|
46
|
+
- Region weight / hierarchy: side = section nav; main = channel list; action = page-level save if required
|
|
47
|
+
- Explicit exclusions: docs-site header/footer patterns
|
|
48
|
+
|
|
49
|
+
## License / brand risks
|
|
50
|
+
|
|
51
|
+
- Public marketing/docs URL is third-party. Capture only structure notes; do not mirror proprietary illustration or trademarked slogans into Fill.
|
|
52
|
+
|
|
53
|
+
## Unresolved questions
|
|
54
|
+
|
|
55
|
+
- none
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schema": "design-playbook.reference.manifest/v1",
|
|
3
|
+
"run_id": "fixture-url",
|
|
4
|
+
"captured_at": "2026-07-22T10:05:00+08:00",
|
|
5
|
+
"tool": "reference-intake",
|
|
6
|
+
"sources": [
|
|
7
|
+
{
|
|
8
|
+
"id": "src-1",
|
|
9
|
+
"kind": "url",
|
|
10
|
+
"locator": "https://example.com/docs/settings/notifications",
|
|
11
|
+
"sha256": null,
|
|
12
|
+
"note": "example.com placeholder for fixture shape only"
|
|
13
|
+
}
|
|
14
|
+
]
|
|
15
|
+
}
|