From f5e759530b66ea2f6208d3baa61cef191e052d24 Mon Sep 17 00:00:00 2001 From: Remon Panman <228601219+Tradebaas@users.noreply.github.com> Date: Fri, 7 Aug 2026 22:30:42 +0200 Subject: [PATCH 1/2] refactor(docs): the two documents the method reads sit where it looks The design method resolves its context from the project root, .agents/context/ and docs/, reads no configuration for it, and offers no way to point it elsewhere that is not configuration. From inside docs/design/ it resolved nothing: designPath null on a repo whose design system is filled, which would have opened every design session by calling our own document a documentation gap. The design system moves up one directory to docs/DESIGN.md and the product record sits beside it at docs/PRODUCT.md. Both now resolve, with platform web, measured with the loader itself rather than argued from the source. docs/design/ keeps VOICE.md and the reference material, which the method never reads. The product record points where the brief already owns the fact: stack, users and purpose are one line each at docs/product/BRIEF.md. What it holds itself is what the brief never carried, the platform, the three surfaces this project actually renders, the brand commitments, the evidence on hand, and the absences nobody may fabricate. Read against the brief line by line, two sentences that had drifted into restating it were cut back to the interface fact underneath them. A fresh copy gets the design system and no product record at all: begin deletes Groundwork's own and the method's init writes that project's in the same place. DESIGN.md now says in its own header that sections 1 and 2 are input and section 3 is written from the built world after the finish review. maintain refreshes the method as the one dependency that is in no manifest, and the refresh was run rather than assumed: on an up-to-date install it reports the version and changes nothing. Decision 0020 gained the option underneath the whole choice, writing a deeper in-house method, rejected because the missing halves were an owner-facing decision round and a mechanical detector, which together are a product rather than a skill; a tier table against decision 0015; and where the two documents live. Over the whole spec the most expensive tier shrank, AGENTS.md 126 lines before and 125 after. The move added no dead path: the links gate's unresolved list is identical before and after, 71 either way. The archived baseline spec keeps the old name, which is what the file was called then. The retired path is in the denylist, scoped so this spec's own record can still name it. Traces-to: SC-8 --- .agents/skills/begin/SKILL.md | 4 + .agents/skills/design/SKILL.md | 24 +++-- .agents/skills/maintain/SKILL.md | 8 +- AGENTS.md | 2 +- checks/cockpit-page.mjs | 2 +- checks/config.json | 1 + docs/{design => }/DESIGN.md | 14 ++- docs/PRODUCT.md | 93 +++++++++++++++++++ docs/README.md | 3 +- ...replaces-the-in-house-frontend-rulebook.md | 40 ++++++++ .../design/reference/ui-library-showcase.html | 2 +- docs/specs/011-design-on-impeccable/plan.md | 2 +- docs/specs/011-design-on-impeccable/spec.md | 2 +- .../06-artifact-ownership-and-record.md | 56 +++++++++-- docs/state/DEBT.md | 2 +- 15 files changed, 228 insertions(+), 27 deletions(-) rename docs/{design => }/DESIGN.md (86%) create mode 100644 docs/PRODUCT.md diff --git a/.agents/skills/begin/SKILL.md b/.agents/skills/begin/SKILL.md index 8d9da8d..8044ff4 100644 --- a/.agents/skills/begin/SKILL.md +++ b/.agents/skills/begin/SKILL.md @@ -31,6 +31,10 @@ went wrong or needs the owner's action; a list of deleted template files is nois the record of what the framework itself had already shipped. Counted against this project they would report someone else's work as done here. Put the blank brief back (`cp docs/product/TEMPLATE-BRIEF.md docs/product/BRIEF.md`) and delete the baseline folder. +- `docs/PRODUCT.md` is Groundwork's own record of the surfaces this framework renders, which the + design method would read as this project's product truth. Delete it: the method's own init writes + this project's, in the same place, from what the interview below already captured. + `docs/DESIGN.md` stays: sections 1 and 2 ship with Groundwork and are input to that method. - `docs/operations/deploy.md` holds Groundwork's own release route, which would read as this project's if it stayed. Put the blank runbook back (`cp docs/operations/TEMPLATE-DEPLOY.md docs/operations/deploy.md`). `deliver` fills it at first diff --git a/.agents/skills/design/SKILL.md b/.agents/skills/design/SKILL.md index 2dbd046..be0d163 100644 --- a/.agents/skills/design/SKILL.md +++ b/.agents/skills/design/SKILL.md @@ -11,11 +11,18 @@ the top of `node checks/check.mjs` says whether this project has it, and which r is the Groundwork side of that seam. It carries what is genuinely ours, hands it over as binding input, and holds open the three points where the owner decides. -`docs/design/DESIGN.md` sections 1 and 2 and `docs/design/VOICE.md` carry the durable principles -and the owner's standing defaults. DESIGN.md **section 3 is not written here**: it is recorded from -the world that was actually built, after the finish review (step 4). A rulebook written before the +`docs/DESIGN.md` sections 1 and 2 and `docs/design/VOICE.md` carry the durable principles and the +owner's standing defaults. DESIGN.md **section 3 is not written here**: it is recorded from the +world that was actually built, after the finish review (step 4). A rulebook written before the build gets defended against reality instead of describing it. +**Where the two documents live.** The method reads `docs/DESIGN.md` and writes its product record +to `docs/PRODUCT.md`, because `docs/` is one of the directories it searches by itself. Neither +path is configured anywhere, and neither moves. The product record holds what +`docs/product/BRIEF.md` does not own (platform, stack, brand commitments, evidence on hand, +accessibility needs) and points at the brief for scope, users and purpose: a fact that stands in +both files is a fact that will disagree with itself later. + No design method installed (a project that started without an interface, a failed install recorded in STATE.md)? Install it first. Everything below assumes it is there. @@ -73,11 +80,12 @@ Then hand the method its input, once, and let it run: - **Product truth it must not ask twice for.** `docs/product/BRIEF.md` and `docs/product/CONTEXT.md` already hold the users, the purpose, the positioning, the constraints and the domain terms, captured by `begin` in the owner's own words. The method's `init` step - writes its own product record: give it those two files as the source, play the extracted answers - back for a one-line confirmation each, and let it interview only for what it genuinely adds and - Groundwork never captured: platform (web, iOS, Android, adaptive), brand commitments, the - evidence actually on hand, and accessibility needs beyond the floor. An owner who has just sat - through `begin`'s interview answers nothing here twice. + writes `docs/PRODUCT.md` from that: give it those two files as the source, play the extracted + answers back for a one-line confirmation each, and let it interview only for what it genuinely + adds and Groundwork never captured: platform (web, iOS, Android, adaptive), brand commitments, + the evidence actually on hand, and accessibility needs beyond the floor. What the brief already + owns is pointed at from the record, never copied into it. An owner who has just sat through + `begin`'s interview answers nothing here twice. - **The binding design input.** DESIGN.md section 1 (the ten principles) is a floor: a direction may build any world it likes on top of it, and may not break it. Section 2 (the owner's standing taste) is the pinned seed, and the method honors a pinned brief. The owner may replace section 2 diff --git a/.agents/skills/maintain/SKILL.md b/.agents/skills/maintain/SKILL.md index 92db38d..cfb01b9 100644 --- a/.agents/skills/maintain/SKILL.md +++ b/.agents/skills/maintain/SKILL.md @@ -28,7 +28,13 @@ First maintenance session: confirm the minimum exists, or create it and record i solutions and store apps, plugins and custom code registered in the instance, and the vendor's own release and deprecation notices. Those last ones move on the vendor's schedule rather than yours, which is what makes a platform go stale while every project file sits - untouched. + untouched. The installed design method is a dependency too, and the only one that is not in a + manifest: re-run `node checks/design-method.mjs --install` to take its current release (it + reports the installed version and changes nothing when that is already the newest), read the + version back from the enforcement line at the top of `node checks/check.mjs`, and note it in + STATE.md when it moved. Read the release notes for a rule that was dropped: decision 0020 + credits rules to that method, and one that disappears upstream comes back into a Groundwork + file rather than being forked there. 3. **Debt harvest**: `grep -rn "defer:" --exclude-dir=.git .` → reconcile with DEBT.md. Flag markers whose upgrade trigger has fired, and `no-trigger` markers (those rot silently). Paying debt is a proposed, owner-approved task like any other. diff --git a/AGENTS.md b/AGENTS.md index 9e58378..238c292 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -81,7 +81,7 @@ Read enough to know the root cause, then fix the cause once, not the symptom eve | System map (architecture) | `docs/product/ARCHITECTURE.md` (made by `architect`) | | Architecture & other decisions | `docs/decisions/` | | Code standards (per stack) | `docs/standards/` | -| Design system (visual) | `docs/design/DESIGN.md` | +| Design system (visual), and the product record beside it | `docs/DESIGN.md` and `docs/PRODUCT.md`: the two files the design method reads from `docs/` with no configuration | | Voice & content system | `docs/design/VOICE.md` | | EU/NL compliance: this project's register | `docs/compliance/REGISTER.md` (regimes: `docs/compliance/COMPLIANCE.md`) | | Operational runbooks | `docs/operations/` | diff --git a/checks/cockpit-page.mjs b/checks/cockpit-page.mjs index 53c9b55..6da1907 100644 --- a/checks/cockpit-page.mjs +++ b/checks/cockpit-page.mjs @@ -122,7 +122,7 @@ export function formatSize(bytes) { // defer: the few token values below are copied from the explainer (index.html) instead of read // from a token file. ceiling: a third surface, or the owner moving the accent, makes the copies -// drift. upgrade-when: this project's own token section in docs/design/DESIGN.md is filled. +// drift. upgrade-when: this project's own token section in docs/DESIGN.md is filled. const STYLE = `:root{color-scheme:dark light; --bg:#0a0b0b;--surface:rgba(255,255,255,.025);--line:rgba(255,255,255,.08); --ink:#f2f3f1;--ink2:#c3c6c0;--muted:#8f938a;--accent:#3fae9f;--tint:#3fae9f17; diff --git a/checks/config.json b/checks/config.json index 9d44b8a..418bf97 100644 --- a/checks/config.json +++ b/checks/config.json @@ -19,6 +19,7 @@ { "pattern": "definitions cover language|no implementation detail in this file", "why": "retired glossary rule; a CONTEXT.md entry may now settle how a term is measured (which period, which basis, who counts) and stops at the threshold value and the branching, which belong in a spec where a test can execute them (decision 0019)" }, { "pattern": "\\btaste dials\\b|VARIANCE ?/ ?MOTION ?/ ?DENSITY", "why": "retired taste-skill machinery; a page is no longer configured by three numeric knobs set before the owner sees anything. The installed design method commits a direction contract, a color strategy and one authored motion instead (decision 0020)" }, { "pattern": "leonxlnx/taste-skill", "why": "retired upstream pointer; the frontend rulebook this repo adapted from it is gone and the installed design method owns that ground now (decision 0020 supersedes 0012)" }, + { "pattern": "docs/design/DESIGN\\.md", "why": "retired path; the design system is docs/DESIGN.md since 2026-08-07, beside docs/PRODUCT.md, because that is where the installed design method reads both without configuration (decision 0020). docs/design/ still owns VOICE.md and reference/", "exclude": ["docs/specs/011-design-on-impeccable/"] }, { "pattern": "skill `taste`|\\.agents/skills/taste", "why": "retired skill; taste was removed on 2026-08-07 and nothing may point at it again. What each of its rules became is the table in decision 0020", "exclude": ["docs/specs/011-design-on-impeccable/"] } ], "styleBans": [ diff --git a/docs/design/DESIGN.md b/docs/DESIGN.md similarity index 86% rename from docs/design/DESIGN.md rename to docs/DESIGN.md index 3a48e2d..1891169 100644 --- a/docs/design/DESIGN.md +++ b/docs/DESIGN.md @@ -1,7 +1,14 @@ # DESIGN: the design system - + ## 1. Principles: why things look right @@ -54,7 +61,8 @@ with dark ink `#222228`, a proven starting pair, re-derive per brand). Flat card borders, soft-but-adult radius (12-16px containers). Confirm this direction per project with the `design` skill; deviate only on the owner's say-so. -## 3. Tokens: THIS PROJECT +## 3. Tokens: THIS PROJECT - **UI foundation:** TBD + + + +## Platform + +web + +## Stack + +`docs/product/BRIEF.md` owns it, under Product ("Target & stack"). Nothing here restates it. + +## Users + +`docs/product/BRIEF.md` owns them, under Users: one individual at the wheel, in four named +situations. The reader of the surfaces below is that person, before they have decided to adopt +anything. + +## Product Purpose + +`docs/product/BRIEF.md` owns it: the one sentence, the cost of doing nothing, and the success +criteria the owner reads on a date. + +## Operating Context + +Three surfaces exist, and they are the whole interface this project has: + +- **The explainer** (`index.html`). It is the front door: someone deciding whether to adopt reads + it in a browser, once, before they type anything, and just as often from disk as from the web. + One tracked file, no build step, no framework, no network at render time, self-hosted fonts, + inline SVG icons. It is the file the detector gate runs on. +- **The cockpit** (`node checks/progress.mjs --serve`), a local stand that renders what is done + and what is left. It is generated by `checks/cockpit-page.mjs` on demand, never published, and + read by the owner of a project rather than by a visitor. +- **The gates' own output** (`node checks/check.mjs` and the suites beside it), read in a terminal + or in a CI log. `design-guard` section 3 owns how that output has to read. + +Everything else this framework produces is Markdown, read by an agent or by a human in an editor. + +## Capabilities and Constraints + +`docs/product/BRIEF.md` owns the capability list (SC-1 to SC-12) and the project-wide constraints. +What binds an interface here, and is stated nowhere else: + +- The explainer stays one self-contained file that renders from disk. A build step, a framework + or a CDN would each break the way it is actually opened, and the page argues for this framework + by being what it describes. +- Its content stays readable with JavaScript off. Motion is progressive enhancement, never the + thing that reveals the text. +- The cockpit is rendered by a check script, so its styling lives in that script. That copy of the + page's colors is the one piece of known debt on this surface: `docs/state/DEBT.md`, DEBT-001. + +## Brand Commitments + +- `docs/DESIGN.md` sections 1 and 2 are binding: the ten principles as a floor, and the owner's + standing direction as the pinned seed. A direction round may build on them and may not break + them. +- The wordmark is the text "Groundwork" in the display face. No logo exists, and none is to be + invented. +- Type: Josefin Sans for display, Inter for body, both self-hosted as variable woff2. The + explainer's face picker swaps the display face only. +- Icons: Lucide (ISC), descended from Feather (MIT), inlined as SVG. Never emoji as UI icons. + +## Evidence on Hand + +- Real and quotable: the published explainer, the changelog and the tagged releases, the gate + output on any commit, and the evidence drill in `docs/operations/evidence-drill.md`. +- Absent, and not to be fabricated: adopters, testimonials, case studies, usage numbers, + benchmarks, screenshots of anyone else's project. The success-criteria table in + `docs/product/BRIEF.md` is where the real numbers are read, on the dates it names. + +## Product Principles + +The durable principles are already owned: `AGENTS.md` for how the work is governed, +`docs/DESIGN.md` section 1 for how an interface may look, `docs/design/VOICE.md` for how it reads. +A third list here would be the drift those files exist to prevent. + +## Accessibility & Inclusion + +The floor is `docs/DESIGN.md` principle 8, with `docs/compliance/COMPLIANCE.md` behind it (WCAG +2.1 AA, visible focus, semantics before ARIA), plus principle 7: whatever a direction authors +collapses to static under a reduced-motion preference, with the content still readable. No need +beyond that floor has been established for this audience, and the explainer is the surface where +it is measured. diff --git a/docs/README.md b/docs/README.md index a6d2434..af118c3 100644 --- a/docs/README.md +++ b/docs/README.md @@ -8,6 +8,8 @@ domain, updated when the domain changes; **ARCHIVE** = frozen, never cite as cur | File | Tier | What it owns | |---|---|---| | `README.md` | LIVE | This manifest | +| `DESIGN.md` | REF | Design system: principles, the owner's standing direction, this project's tokens. In `docs/` because the design method reads it there without configuration | +| `PRODUCT.md` | REF | Product record for the design method: platform, brand commitments, evidence on hand, accessibility. Points at `product/BRIEF.md` for scope, users and purpose. Written by the method's own init; absent until then, and `begin` removes Groundwork's own | | `state/STATE.md` | LIVE | Live state, session handoff, the single "what's next" | | `state/DEBT.md` | LIVE | Technical debt ledger (with `defer:` site markers) | | `state/TEMPLATE-DEBT.md` | REF | Blank debt ledger; `begin` puts it in place of Groundwork's own | @@ -26,7 +28,6 @@ domain, updated when the domain changes; **ARCHIVE** = frozen, never cite as cur | `decisions/[0-9]*.md` ◆ | REF | Decision records, numbered (Groundwork's own ship with the framework) | | `standards/GLOBAL.md` | REF | Universal code standards, stack-independent | | `standards/*.md` ◆ | REF | Per-stack standards, generated by the `stack` skill | -| `design/DESIGN.md` | REF | Design system: principles, tokens, quality rules | | `design/reference/**` ◆ | REF | Brand assets, screenshots, design references | | `design/VOICE.md` | REF | Voice & content system: how the product reads | | `compliance/REGISTER.md` | LIVE | This project's register: which regimes apply, status and evidence per obligation | diff --git a/docs/decisions/0020-the-design-method-replaces-the-in-house-frontend-rulebook.md b/docs/decisions/0020-the-design-method-replaces-the-in-house-frontend-rulebook.md index d7aec6e..9cdfdb4 100644 --- a/docs/decisions/0020-the-design-method-replaces-the-in-house-frontend-rulebook.md +++ b/docs/decisions/0020-the-design-method-replaces-the-in-house-frontend-rulebook.md @@ -22,6 +22,16 @@ one place. The owner chose retirement over coexistence on 2026-08-05. 3. **Keep `taste` as the house overlay on top of the method:** an overlay is a patch on somebody else's file by another name, and it re-creates the update cost the per-project install exists to avoid (spec 011's settled decisions). +4. **Write a deeper in-house method instead of installing one:** rejected, and this is the choice + underneath the other three. What was missing was never a longer list of rules; it was the two + things a list cannot buy. The owner had to be asked before the look was decided rather than + after, and something had to measure a rendered page mechanically. Building that here means a + direction round with a browser decision page, rendered compositions, a reviewer that never saw + the build thread, and a detector with dozens of rules that stays current as the machine default + look moves. That is a product, not a skill, and it would compete for the same sessions as the + framework itself. Installing it costs an upstream dependency and buys the whole apparatus at + its current release. Groundwork's own claim, use what exists before you write it, applies to + Groundwork. ## Where each retired rule went @@ -47,6 +57,36 @@ close. The method decides the same things in the open and further down: a commit contract, a color strategy chosen at page scale, and motion authored once as the form's own. A numeric knob beside that contract would be a second, weaker answer to a question already settled. +## What it costs, and where that is paid + +Decision 0015 says every addition names its tier. Measured over the whole of spec 011: + +| Tier | What landed | Standing cost | +|---|---|---| +| 1 Artifact | This record, `docs/PRODUCT.md`, and the tracked `.impeccable/config.json` with its waivers and their reasons | Read once, by whoever needs it | +| 2 Template | None added. `docs/DESIGN.md` keeps the role it had, and the method's own init writes the product record, so no blank one is carried here | Nothing until filled | +| 3 On-demand skill | The installed payload, loaded only in a design session, and declared third-party so no gate measures its prose. The registry went from 21 skills to 20: `taste` left and the payload is not listed | Tokens in a design session only | +| 4 Gate | The detector as a CI job, and the second half of `stack-gates` that proves the job actually runs it. The registry still names 22 gates | CI seconds, outside the model's context | +| 5 Per-action rule | `begin` gained an install step and one cleanup line, `design` routes to the method and holds three decision points, `maintain`'s dependency round refreshes it, `stack` wires the detector. `design-guard` got shorter by more than the others gained | Only when that action runs | +| 6 AGENTS.md | Net minus one line: the `taste` row is gone and the design row now names both documents the method reads. 126 lines before this spec, 125 after | Every session, on every model | + +The bill lands where 0015 says it should: the expensive tier shrank, and what grew is an artifact, +a gate and a handful of per-action lines inside skills that only fire in a design session. + +## Where the two documents live + +The method resolves its context from the project root, `.agents/context/`, then `docs/`, and it +reads no configuration for that. So the design system moved up one directory to `docs/DESIGN.md` +and the product record it writes sits beside it at `docs/PRODUCT.md`. `docs/design/` keeps VOICE.md +and the reference material, which the method does not read. The old design path is in the denylist, +and the two rows in the AGENTS.md map name the new one so nobody searches for it. + +The product record holds what `docs/product/BRIEF.md` does not own (platform, brand commitments, +evidence on hand, accessibility needs) and points at the brief for scope, users and purpose. A +fresh copy gets the design system with sections 1 and 2 filled and no product record at all: +`begin` deletes Groundwork's own, and the method's init writes that project's from what `begin` +already captured. + ## Decision & consequences `taste` is gone from `.agents/skills/`, from the AGENTS.md table, from DESIGN.md principle 10, from diff --git a/docs/design/reference/ui-library-showcase.html b/docs/design/reference/ui-library-showcase.html index d5c2555..05824c5 100644 --- a/docs/design/reference/ui-library-showcase.html +++ b/docs/design/reference/ui-library-showcase.html @@ -451,7 +451,7 @@
design skill, after the stack is chosen. The stack constrains the menu (most libraries below target React; other stacks have their own equivalents, which the stack skill researches live).docs/decisions/ naming the foundation and why; the token mapping in docs/design/DESIGN.md section 3; the theme file in code as the SSOT.docs/decisions/ naming the foundation and why; the token mapping in docs/DESIGN.md section 3; the theme file in code as the SSOT.