Repository navigation
Add /design-review --build, an opt-in loop that checks and fixes new UI while you build it - #4142
Merged
Merged
Conversation
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
…ose API call went unanswered is never reported finished Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
…every paid test Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
…d fixes UI while you build it Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
… rules, skills guide and design-html Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
…ine and pointer Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
A real run of /design-review --build turned up four problems: - Each bash block runs in a fresh shell, so later blocks lost $RUN and the helper path, and the first block never set the project slug or state root. Blocks now stand alone and later ones use the printed run path. - The lint command it printed was a bare name that is not on PATH; it now prints the full path to the bundled lint. - gstack's own browser can only save screenshots under /tmp, so the section says to save where the browser can write and copy the file into place. - The --build pointer sat before the design hard rules, which every section must follow; it now comes right after them. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
|
😎 This pull request was merged. |
…le changes Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
…at are not the preview A missing fixture route that was fixed before the final pass no longer blocks the receipt, an API call that arrived with no scenario now does, preflight only promises fixtures-only mutations when every page carries the preview script, and a bad path escape or a fixture with a bad status no longer stops the preview. Review-Finding: p1/specialist-batched#1 reader=state-machines Review-Finding: p1/specialist-batched#2 reader=security Review-Finding: p1/red-team#1 reader=red-team Review-Finding: p1/red-team#2 reader=red-team Review-Finding: p1/red-team#4 reader=red-team Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
…y trust a page the preview actually serves Any API call the preview could not answer during a run now keeps the receipt incomplete, and its fix line says to add the route, restart the preview and start again from preflight. Preflight checks every local page whatever hosts were granted, asks the preview's own probe route instead of looking for a marker in the HTML, and treats a redirect as not the preview. The Vite plugin now applies to the dev server only, so built pages never carry the preview script. Review-Finding: p2v/outside-voice#3 reader=outside-voice Review-Finding: p2/red-team#1 reader=red-team Review-Finding: p2v/outside-voice#1 reader=outside-voice Review-Finding: p2v/outside-voice#2 reader=outside-voice Review-Loop-Exception: a-0aec1d2672bd Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
6 tasks done
…check in the changelog Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
Run the slug helper through the shared script launcher, move the preview server tests into the design build test that imports the product code, let the single-source check skip generated host copies, write the build-loop commands without free-text placeholders (trimmed so the skill stays under its size cap), and add the build routing line to the onboarding fixture. Review-Loop-Exception: a-b2e2abe1c646 Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
… requests the preview log records Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
…runs clean The receipt now reads waivers from the lint's grade, hashes every file in a touched folder, refuses an inventory that changed after verify-start, and finds the preview's record of unanswered calls in its default state folder. The preview answers a path the app's own dev proxy would forward with a recorded 501, and refuses a state folder that is a symlink or another user's. Review-Finding: p1/red-team#1 reader=red-team Review-Finding: p1/red-team#2 reader=red-team Review-Finding: p1/red-team#3 reader=red-team Review-Finding: p1/red-team#4 reader=red-team Review-Finding: p1/specialist-batched#1 reader=testing Review-Finding: p1/specialist-batched#2 reader=security Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
…, and say the preview does not stop proxied WebSocket upgrades Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
…@ from slipping past the design build checks An empty server.proxy key now gets the recorded 501 too. The preview's probe names its state directory, so the receipt reads a --state or --port 0 preview's record without --preview, and a preview that keeps no record makes the run incomplete. Text redaction drops userinfo up to the last @ and redacts percent-encoded secret parameter names. Review-Finding: s11/outside-voice#1 reader=outside-voice Review-Finding: s11/targeted#1 reader=targeted Review-Finding: s11/adversarial-native#3 reader=adversarial-native Review-Finding: s11/targeted#2 reader=targeted Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
…scan does not read it as a real login Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
… preview still answers The receipt now reads the union of --preview, the state directory each answering preview names, and the default gstack-preview-<port> directory for every loopback state origin that did not answer the probe. servedStates reports which origin each answer came from. Review-Finding: fc3/fix-check#1 reader=fix-check Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
…n the project structure guide Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
/design-review --buildis a new, opt-in mode for UI you are still building. It lints and screenshots each state of a local preview, fixes what it finds in up to three rounds, then prints one line saying whether the section came out clean. It serves the README's "a designer who catches AI slop" during Build, before review, using the app-section check that landed in #4138.What changed
/design-review --buildis a new opt-in mode for UI you are still building. It lists the states your change can show, then lints and screenshots each one at 1440 and 375 wide. It fixes what fails for up to three rounds, then runs one read-only pass and prints a singleDESIGN_BUILD: <clean|waived|open|unrendered|incomplete|stale>line. It never commits, stashes or resets your edits, and it asks nothing when unattended.gstack-design-build(preflight, plan, admit, verify-start, receipt, check) decides that line in code. It reads the lint's JSON verdict, never its exit code. A skipped render, a state measured at only some sizes, a missing screenshot, evidence older than the final pass, an edited tree, or an API call the preview could not answer can never print clean. The receipt is a private file tied to the exact tree it measured, so a later edit makescheckreport it stale.design-review/templates/preview-fixtures.mjs) serves the app on 127.0.0.1 with canned API answers, one scenario per state (?as=<scenario>). Any API call without a fixture, including one a dev-server proxy would have sent to a real backend, gets a recorded 501. The receipt reads that record from--preview, from the state directory each running preview names when probed, and from the default per-port directory of any loopback origin where no preview answers. A running preview that keeps no record makes the run incomplete. See docs/howto-preview-a-frontend.md.@, and percent-encoded secret parameter names are now redacted.Why
qm#3186 shipped crowded two-line rows, help copy flush under a list, and a status note as loud as the name beside it. Screenshots alone didn't catch them, and the page lint's 697 findings missed all three. #4138 made those defects measurable, and this PR checks them while the UI is being built, with a receipt that cannot call a run clean when the preview missed an API call.
Blast radius
The audit modes of /design-review are unchanged: normal runs load 312 more bytes (the routing line, pointer, index row and description clause), and the build section loads only with
--build. Nothing is added to /ship, review or merge tooling; the new bin, library and template are reached only from the build section, which the free suite exercises end to end (test/design-build-e2e.test.ts, script ran in CI).Approvals
Approved: yes (record r-83626008d2c8). The full approval record stays private: this repository is public or its visibility is unknown.
Plan: approved (record r-848ebcf7abd8)
Plan check: approved (record r-848ebcf7abd8)
Internal references
GST-1741 PR 2 (gate-2 tasks T2, T3, T5, T7, T8, T12, T14, T17, T18, T21, T22, T26, T29, T31, T36, T37, T38). Size-cap grant a-4c506af03994 (design-review skeleton 85,182, ratio 1.357); freeze ruling a-87876e6fa8ce.
Summary
The build loop, its receipt CLI and the fixture preview landed earlier on this branch. This /ship run hardened the receipt and preview through three review rounds and three owner-granted fix-checks. The receipt now reads waived findings from the lint's grade, hashes touched folders file by file, and binds the inventory to verify-start. The preview answers a dev-proxy path with a recorded 501, including a catch-all
''proxy key, and refuses a symlinked or foreign state directory. The receipt reads every record a running or stopped preview kept, and redaction covers@in passwords and percent-encoded secret keys. Every fix has a failing-first test.Test Coverage
Coverage: deterministic (each of the 11 changed runtime files has a changed test that names it; no audit reader ran).
Tests ran: test 1637 (test files, carried from CI run 42436674801/1 at tree ea3a0d5064fd)
Pre-Landing Review
Three full rounds and three granted fix-checks. Round 1 (p1) found 6 findings, all fixed in 6e18171. Round 2 (p2) found 3 informational notes. Step 11 (adversarial-native, outside voice openai/gpt-6.1-sol, targeted) found 9: the 3 fail-open ones were fixed in 4a9937f under grant a-fbbb1ea56993, and the 5 fail-closed ones are owner-ruled notes. Fix-check fc3 found a regression in that fix, fixed in b97d7f6 under grant a-92203e18dcaf, and fix-check fc4 found only notes. The final fix-check (fc5) read c8febec..a0c948c as one link under grant a-731edab77b39, made no edits, and found only notes.
REVIEW_LOOP: passes=2 blocking_found=3 deferred=1 noted=16 fixed=8 scope=frozen unbound=3 ledgers_read=8 fix_checks=3 dispatches=10
Ruled note: s11/adversarial-native#2 at c8febec ruled by Captain GStack Minder (GSTA-36), 2026-11-08 at 2026-11-08T01:37:02.575Z: fail-closed: gitignored churn under a touched folder gives a false TREE_CHANGED; symlinked files skipped; relSafe accepts '.' (approval a-ea95909de441)
Ruled note: s11/adversarial-native#4 at c8febec ruled by Captain GStack Minder (GSTA-36), 2026-11-08 at 2026-11-08T01:37:02.718Z: fail-closed: bypass() and ws proxies are not modeled; the live-proxy guard covers plain HTTP paths (approval a-d1930465db4c)
Ruled note: s11/adversarial-native#5 at c8febec ruled by Captain GStack Minder (GSTA-36), 2026-11-08 at 2026-11-08T01:37:02.838Z: fail-closed: default state dir not ownership-checked; a non-JSON line throws; stop leaves unhandled.jsonl (approval a-3f1cd492f34b)
Ruled note: s11/adversarial-native#6 at c8febec ruled by Captain GStack Minder (GSTA-36), 2026-11-08 at 2026-11-08T01:37:02.954Z: fail-closed: RECEIPT_VERSION not bumped, so an older receipt reads INVENTORY_CHANGED (approval a-f5da4431db4f)
Ruled note: s11/adversarial-native#7 at c8febec ruled by Captain GStack Minder (GSTA-36), 2026-11-08 at 2026-11-08T01:37:03.098Z: fail-closed: an https loopback URL maps to port 80 for the default state dir (approval a-9be1859c8537)
Ruled note: fc3/fix-check#2 at 1ca0129 ruled by Captain GStack Minder (GSTA-36), 2026-11-08 at 2026-11-08T01:37:03.250Z: pre-existing: with --preview, a second plugin preview without a stateDir stays unrecorded (approval a-63b61744a759)
Ruled note: fc3/targeted#1 at 1ca0129 ruled by Captain GStack Minder (GSTA-36), 2026-11-08 at 2026-11-08T01:37:03.368Z: pre-existing residual: when the probe fails, a stopped custom --state preview is unread without --preview (approval a-7ae3ad78cfb5)
Ruled note: fc3/targeted#2 at 1ca0129 ruled by Captain GStack Minder (GSTA-36), 2026-11-08 at 2026-11-08T01:37:03.498Z: pre-existing: a waived receipt does not bind the waiver file hash and check() does not recheck it (approval a-3f922714e345)
Gate edits: none detected (14 listed, 3 read; patterns: RH-1,RH-3,RH-4,RH-12,RH-13,RH-14,RH-15,RH-16; unlisted idioms: none)
Outside review: openai/gpt-6.1-sol completed at c8febec (1 finding, fixed).
Review notes
These findings ship unfixed, as listed notes (all INFORMATIONAL):
--previewrun incomplete.receiptcan printwaivedwithout--waivers, andchecknever rehashes the waiver file (the owner-ruled fc3/targeted#2 covers the rehash).treeIdentityignores untracked files that are not listed intouched.stateDirthrough unresolved, so the receipt can look for the record relative to the wrong directory.PREVIEW_UNRECORDEDis skipped whenever--previewis given, even for a second origin it cannot cover.stateDir.Exploratory QA
Functional QA smoke at dddb2bf: 11 captures, verdict pass. Later commits were checked by their failing-first tests, not a new QA run.
Design Review
No rendered /design-review runs inside /ship. The end-to-end run of this mode on the qm#3186 fixture is described in Why.
Eval Results
Evals not run inside /ship: the selector's pr profile was full-fallback (113 behavioral probes, 0 judges), so the ready step's
--screenand the train census run them.Review bot comments
No review bot comments.
Issues
Refs fc3/fix-check#1
Refs p1/red-team#1
Refs p1/red-team#2
Refs p1/red-team#3
Refs p1/red-team#4
Refs p1/specialist-batched#1
Refs p1/specialist-batched#2
Refs p2/red-team#1
Refs p2v/outside-voice#1
Refs p2v/outside-voice#2
Refs p2v/outside-voice#3
Refs s11/adversarial-native#3
Refs s11/outside-voice#1
Refs s11/targeted#1
Refs s11/targeted#2
TODOS
No TODO items completed in this PR.
Documentation
Status: updated: one factual fix, no blockers.
Audited scope: the design-review-build-loop branch (base aa46032, head b97d7f6; 32 committed files) plus the unstaged docs/PROJECT_STRUCTURE.md, covering README.md, CLAUDE.md, AGENTS.md, docs/howto-preview-a-frontend.md, docs/skills.md, docs/design-lint.md, gstack/llms.txt, capy/skill/gstack/lane-card.md, and the design-review and design-html templates, checked against bin/gstack-design-build and bin/gstack-skill-start.
Documentation health:
admitto the gstack-design-build subcommand list)Coverage debt:
/design-review --buildandgstack-design-buildhave reference and how-to coverage (docs/skills.md, docs/howto-preview-a-frontend.md); there is no tutorial-style walkthrough (common gap). The internal--out-rootflag is undocumented. No architecture diagram drift: the diff touches no diagram entities.Test plan
Agent notes
GST-1741 PR 2 (gate-2 tasks T2, T3, T5, T7, T8, T12, T14, T17, T18, T21, T22, T26, T29, T31, T36, T37, T38). Size-cap grant a-4c506af03994 (design-review skeleton 85,182, ratio 1.357); freeze ruling a-87876e6fa8ce. Review-loop grants on this /ship run: a-fbbb1ea56993, a-92203e18dcaf, a-731edab77b39. /ship run ship-20261108T004917-340fcb (GSTA-406).