Skip to content

Add /design-review --build, an opt-in loop that checks and fixes new UI while you build it - #4142

Merged
capy-ai[bot] merged 22 commits into
mainfrom
design-review-build-loop
Nov 8, 2026
Merged

capy-ai[bot] merged 22 commits into
mainfrom
design-review-build-loop

Conversation

@garrytan

@garrytan garrytan commented Nov 7, 2026 •

Copy link
Copy Markdown
Owner

/design-review --build is 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.

{
  "schema_version": 1,
  "pr": 4142,
  "head": "a0c948ccf53b78641f8b5bd3d3afde2542b79d66",
  "version": "1.98.0.0",
  "base": "main",
  "gate": {
    "test": {
      "pass": 1637,
      "fail": 0,
      "skip": 0
    }
  },
  "ci_carried": [
    {
      "lane": "test",
      "run": 42436674801,
      "attempt": 1,
      "tree": "ea3a0d5064fdf8e4564e0c1cb78122a3993ccec3"
    }
  ],
  "session_kind": "unattended",
  "head_tree": "ea3a0d5064fdf8e4564e0c1cb78122a3993ccec3",
  "product_patch_id": "7a7044af50f8787fb0d26680420a5ebf667e34cb",
  "gstack_version": "1.98.0.0",
  "review_depth": {
    "depth": "full",
    "class": "gate",
    "runtime_lines": 899,
    "rules": "c6a079fdf812f479",
    "base": "aa46032f2be715cba570af61d6a059a2853fba7d",
    "registry": "aa46032f2be715cba570af61d6a059a2853fba7d",
    "gate_scan": {
      "tagged": 2,
      "head": "a0c948ccf53b78641f8b5bd3d3afde2542b79d66"
    },
    "reasons": [
      "gate-class",
      "risk:security",
      "runtime=899"
    ],
    "risk": [
      "security"
    ],
    "mode": "panel"
  },
  "pregate": "requires-remote cleared @ea3a0d5064fd (8 checks, current for a0c948ccf53b)",
  "requires_remote": [
    "free-tests.yml/macos-named-regressions: https://github.com/garrytan/gstack/actions/runs/42436674801/attempts/1",
    "windows-smoke.yml/windows-smoke: https://github.com/garrytan/gstack/actions/runs/42436108189/attempts/1",
    "pregate.json/remote_gate: remote-gate tree=ea3a0d5064fd tests=36301 skipped=105 runs=42436674801/1 profiles=ci-reuse/free-tests heads=a0c948ccf53b verified=2026-11-08T02:10:56.025Z"
  ],
  "issues": {
    "fixes": [],
    "refs": [],
    "flakes": []
  },
  "docs": {
    "status": "updated",
    "scope": "README.md, CLAUDE.md, AGENTS.md and docs/ (design-review-build-loop branch, base aa46032f2be7)"
  },
  "review_loop": {
    "passes": 2,
    "blocking_found": 3,
    "deferred": 1,
    "noted": 16,
    "fixed": 8,
    "scope": "frozen",
    "fix_checks": 3,
    "rounds": 5,
    "ledgers_read": 8,
    "unbound": 3,
    "dispatches": {
      "specialist": 8,
      "red-team": 2
    }
  },
  "ruled_notes": [
    {
      "finding": "s11/adversarial-native#2",
      "head": "c8febec5dd1205371b29d537363c13313dfdf239",
      "by": "Captain GStack Minder (GSTA-36), 2026-11-08",
      "reason": "fail-closed: gitignored churn under a touched folder gives a false TREE_CHANGED; symlinked files skipped; relSafe accepts '.'",
      "at": "2026-11-08T01:37:02.575Z",
      "approval": "a-ea95909de441"
    },
    {
      "finding": "s11/adversarial-native#4",
      "head": "c8febec5dd1205371b29d537363c13313dfdf239",
      "by": "Captain GStack Minder (GSTA-36), 2026-11-08",
      "reason": "fail-closed: bypass() and ws proxies are not modeled; the live-proxy guard covers plain HTTP paths",
      "at": "2026-11-08T01:37:02.718Z",
      "approval": "a-d1930465db4c"
    },
    {
      "finding": "s11/adversarial-native#5",
      "head": "c8febec5dd1205371b29d537363c13313dfdf239",
      "by": "Captain GStack Minder (GSTA-36), 2026-11-08",
      "reason": "fail-closed: default state dir not ownership-checked; a non-JSON line throws; stop leaves unhandled.jsonl",
      "at": "2026-11-08T01:37:02.838Z",
      "approval": "a-3f1cd492f34b"
    },
    {
      "finding": "s11/adversarial-native#6",
      "head": "c8febec5dd1205371b29d537363c13313dfdf239",
      "by": "Captain GStack Minder (GSTA-36), 2026-11-08",
      "reason": "fail-closed: RECEIPT_VERSION not bumped, so an older receipt reads INVENTORY_CHANGED",
      "at": "2026-11-08T01:37:02.954Z",
      "approval": "a-f5da4431db4f"
    },
    {
      "finding": "s11/adversarial-native#7",
      "head": "c8febec5dd1205371b29d537363c13313dfdf239",
      "by": "Captain GStack Minder (GSTA-36), 2026-11-08",
      "reason": "fail-closed: an https loopback URL maps to port 80 for the default state dir",
      "at": "2026-11-08T01:37:03.098Z",
      "approval": "a-9be1859c8537"
    },
    {
      "finding": "fc3/fix-check#2",
      "head": "1ca0129cee37e994bcc5dc03511ad06e855095fe",
      "by": "Captain GStack Minder (GSTA-36), 2026-11-08",
      "reason": "pre-existing: with --preview, a second plugin preview without a stateDir stays unrecorded",
      "at": "2026-11-08T01:37:03.250Z",
      "approval": "a-63b61744a759"
    },
    {
      "finding": "fc3/targeted#1",
      "head": "1ca0129cee37e994bcc5dc03511ad06e855095fe",
      "by": "Captain GStack Minder (GSTA-36), 2026-11-08",
      "reason": "pre-existing residual: when the probe fails, a stopped custom --state preview is unread without --preview",
      "at": "2026-11-08T01:37:03.368Z",
      "approval": "a-7ae3ad78cfb5"
    },
    {
      "finding": "fc3/targeted#2",
      "head": "1ca0129cee37e994bcc5dc03511ad06e855095fe",
      "by": "Captain GStack Minder (GSTA-36), 2026-11-08",
      "reason": "pre-existing: a waived receipt does not bind the waiver file hash and check() does not recheck it",
      "at": "2026-11-08T01:37:03.498Z",
      "approval": "a-3f922714e345"
    }
  ],
  "review_targeted": {
    "classes": [
      "gate"
    ],
    "rules": "8811fd300bf305f0",
    "brief_sha": "7f92a0d0a8319c3c0e076fb3b1a4689c45120b2be2c14dfc7d4cb03aafa9d6a5",
    "product_patch_id": "7a7044af50f8787fb0d26680420a5ebf667e34cb",
    "status": "done",
    "findings": 3,
    "raised_by": "targeted"
  },
  "design": {
    "mode": "static",
    "reason": "no preview declared"
  }
}

What changed

  • /design-review --build is 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 single DESIGN_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 makes check report it stale.
  • A preview template (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.
  • Safer URL redaction in the design lint. URLs that do not parse, token values that hold punctuation, passwords that contain @, and percent-encoded secret parameter names are now redacted.
  • Adoption. One recommendation line each in the lane card, docs/skills.md, the CLAUDE.md routing block and /design-html's last step. The mode stays opt-in.

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):

  • p2/specialist-batched#1: the default state directory fallback is not ownership-checked, and a non-JSON line in unhandled.jsonl throws.
  • p2/red-team#1: the preview does not stop proxied WebSocket upgrades (documented in the how-to).
  • p2/red-team#2: a leftover unhandled.jsonl from an earlier run can make a later run incomplete.
  • fc4/fix-check#1 (fails closed): a stale default record from an older preview on the same port can make a --preview run incomplete.
  • fc4/targeted#1: receipt can print waived without --waivers, and check never rehashes the waiver file (the owner-ruled fc3/targeted#2 covers the rehash).
  • fc4/targeted#2 and fc5/targeted#1: treeIdentity ignores untracked files that are not listed in touched.
  • fc5/fix-check#1: the Vite plugin passes a relative stateDir through unresolved, so the receipt can look for the record relative to the wrong directory.
  • fc5/fix-check#2 (fails closed): same as fc4/fix-check#1.
  • fc5/fix-check#3: PREVIEW_UNRECORDED is skipped whenever --preview is given, even for a second origin it cannot cover.
  • fc5/fix-check#4: the template's usage comment still shows the plugin without stateDir.
  • fc5/targeted#2: the receipt matches lint coverage by state name and viewport, not by URL.
  • fc5/targeted#3: screenshot freshness is the file's mtime, so a copied older shot passes as fresh.

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 --screen and 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:

  • README.md: current (Preview a frontend row links the new how-to)
  • docs/howto-preview-a-frontend.md: current (all six gstack-design-build subcommands documented)
  • docs/skills.md: current (/design-review --build paragraph)
  • docs/design-lint.md: current (URL redaction note)
  • docs/PROJECT_STRUCTURE.md: updated (added admit to the gstack-design-build subcommand list)
  • gstack/llms.txt: current
  • capy/skill/gstack/lane-card.md: current
  • CLAUDE.md: current; its Skill routing section does not mirror the new injected 'Building UI' rule, left for the parent to decide

Coverage debt: /design-review --build and gstack-design-build have 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-root flag is undocumented. No architecture diagram drift: the diff touches no diagram entities.

Test plan

  • bun run test: carried from CI free-tests run 42436674801/1 at tree ea3a0d5064fd (1637 test files, exit 0); macOS named regressions and Windows smoke passed at the same head.
  • Focused: test/design-build.test.ts, test/design-build-e2e.test.ts and test/design-lint-app-contract.test.ts ran 59 tests with no failures at a0c948c.
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).

Open in Capy

garrytan and others added 8 commits November 7, 2026 19:56
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>
@trunk-io

trunk-io Bot commented Nov 7, 2026 •

Copy link
Copy Markdown

😎 This pull request was merged.

garrytan and others added 3 commits November 7, 2026 20:47
…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>
garrytan and others added 3 commits November 7, 2026 21:25
…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>
@capy-ai
capy-ai Bot marked this pull request as draft November 8, 2026 00:31
garrytan and others added 8 commits November 8, 2026 00:34
… 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>
@capy-ai
capy-ai Bot marked this pull request as ready for review November 8, 2026 02:16
@capy-ai
capy-ai Bot merged commit 118207f into main Nov 8, 2026
72 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant