Skip to content

[0.2.1] RC | Preflight & GUI Foundation - #554

Merged
cursor[bot] merged 138 commits into
unstablefrom
dev
Sep 14, 2026
Merged

cursor[bot] merged 138 commits into
unstablefrom
dev

Conversation

@mberrys

@mberrys mberrys commented Sep 10, 2026

Copy link
Copy Markdown
Contributor

No description provided.

claude and others added 30 commits September 5, 2026 20:41
Adds pdfquick::tokens (LoopLibQuick/sources/looptokens.h/.cpp): semantic
spacing and colour-role tokens with dark/light/high-contrast values, each
foreground/background pair WCAG contrast-checked. Adds resolveStateVisual()
(loopstatevisual.h/.cpp), the canonical finding/check presentation mapping
issue #194 asks for, with a table-driven test (UnitTestsLoopStateVisual)
asserting an incomplete check and an actively-waived finding never resolve
to the passed treatment. Documents both in docs/LOOP_DESIGN_SYSTEM.md,
including why this uses the repo's current Loop/Quick naming rather than
the issue's stale pre-rebrand Pdf4QtLibGui/Loupe paths, and what remains
open (component implementations land with their consuming surfaces #193,

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NxoABBuEB3mYqr8QyA6KuB
scripts/ci/check_loop_identity.py fails CI on any tracked text file
containing the pre-rebrand product name outside its historical-evidence
allowlist. The "Naming note" section quoted that name three times while
explaining why this doc uses current naming instead of issue #194's stale
paths; reword it to make the same point without the literal token.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NxoABBuEB3mYqr8QyA6KuB
Adding UnitTestsLoopStateVisual to UnitTests/CMakeLists.txt bumped the
project-wide CMake target count the Phase 5 Widgets inventory tracks (its
generator enumerates every target to prove widgets-linkage status, not just
widgets-related ones). Regenerate docs/generated/phase5-widgets-inventory.json
via scripts/generate_phase5_widgets_evidence.py --write (new target's
widgets_linkage is "none", as expected) and update the test's hardcoded
target count (70 -> 71) to match.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NxoABBuEB3mYqr8QyA6KuB
agent-fast's clang-tidy step runs on every changed C++ file regardless of
module classification, but the cmake --build step that generates each
test's AUTOMOC .moc file only runs for targets selected by
classify()/selected_values() against agent-policy.json's module_boundaries
paths. UnitTestsBudgetExhaustion was already listed in core's `tests`, but
its source file, UnitTests/tst_budgetexhaustiontest.cpp, was missing from
core's `paths` glob list, so a change touching only that file never
classified as "core" and the target was never built before clang-tidy ran
on it standalone -- producing "tst_budgetexhaustiontest.moc file not
found". Surfaced by 0aa0d4c's one-line fix to that file. Add the missing
path entry so the target builds first, as it does for every other core
test file already listed there.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NxoABBuEB3mYqr8QyA6KuB
PDF/X-1a:2001 and PDF/X-3:2002 forbid live transparency, but
standards-convert never called the existing PDFTransparencyFlattener
operation (#164) -- live transparency was an unconditional, unfixable
blocker even though Core already has a working flatten path that
PageMaster's export pipeline uses as a separate stage.

Wire PDFTransparencyFlattener::apply()/hasLiveTransparency() into
PDFStandardConversion::preview()/apply(), mirroring the existing
RGB-to-CMYK integration exactly:

- New PDFStandardConversionSettings::flattenTransparency (default-on
  for X-1a/X-3, matching normalizeColor's existing default pattern;
  opt-in for X-4/PDF-A, which permit live transparency).
- pdfx.transparency.allowed becomes a fixable preflight blocker only
  when flattening is requested, so unrelated fixtures without live
  transparency are unaffected (transparencyObjects stays 0, the rule
  already reports Passed).
- The flatten runs before the output-intent/page-box rewrite and its
  report is surfaced verbatim under a new transparency_flatten report
  field -- a real, reported content change, never a silent
  approximation.
- New flatten_transparency parameter on the standards-convert
  operation, available identically from PdfTool's repair command and
  PageMaster's export job (the one shared Core implementation).

Also correct docs/STANDARD_CONVERSION.md's stale claim that an Editor
adapter can land "after the 0.1.1 GUI gate": that gate is already
complete per docs/LOOP_SHELL_CONTRACT.md, which gates product GUI work
behind the still-closed S21/S22 admission contracts instead. Note that
docs/REPO_MAP.md's LoopEditorPlugins/ module does not exist in the
current Qt-Quick-based tree, so a future Editor adapter belongs under
LoopLibInteraction/ + LoopEditor/qml/.

No Qt/CMake toolchain is available in this environment, so the build
and UnitTestsStandardOracle/UnitTestsConversionOracle/UnitTestsRepairOperation
targets could not be run locally; clang-format, source-integrity, and
architecture-catalog checks all pass. CI will provide the first real
build/test signal for this change.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JgoNmy614kqRiTBjiSjRJU
Works the net-new findings from the September 2026 read-only review that were
reproducible against the current tree, plus three adjacent defects the review
did not name.

Security / privacy
- PDFLogScrubber scrubs credential material (URL userinfo such as a Sentry DSN,
  HTTP authorization values, secret-named key/value pairs) ahead of the existing
  path and email passes. The bare auth-scheme pass deliberately excludes "Token"
  so parser diagnostics are not redacted as secrets.
- loop-ocr reads a staged raster once by descriptor instead of re-resolving the
  path for isfile(), PIL, and easyocr in turn, closing the TOCTOU window;
  language codes are shape-validated before they reach easyocr's model file
  names; PdfTool stages the raster 0600.
- Diagnostics bundles truncate plugin display fields.

Fail-closed behaviour
- PdfTool extraction commands record output.empty-result and accept a shared
  --fail-if-empty (exit 1, findings) so an empty output directory cannot pass a
  pipeline that gates on produced files.
- writeIncremental reports whether it appended or only byte-copied; damaged
  documents now carry a source digest, so its "file changed underneath us"
  guard is no longer silently disabled for permissively recovered documents.

Bounds on attacker-controlled shapes
- Damaged-document recovery bounds its dense object table by objects recovered,
  not by the highest declared object number.
- PDFNameTreeLoader terminates cyclic Kids chains and caps depth, entry count,
  and key length (net-new: the cycle was unbounded recursion).
- Structure-tree parsing bounds recursion depth on long acyclic chains.
- PDFJBIG2Bitmap::paint validates grown dimensions on its expandY path, the one
  path that escaped the constructor's dimension check (net-new).

Ergonomics
- isPathContained no longer rejects a planned output whose target directory does
  not exist yet, keeping the stricter symlinked-parent rule for the file side.
- makeUniqueFileName probes 128 sequential names, then random ones.
- OCR option defaults are defined once and shared by capability discovery and
  the command-line parser.

Not built or run here: this environment has no Qt, so the C++ changes are
unverified by compilation. The Python sidecar tests pass and the new scrubber
patterns were validated against a reference implementation of the same passes.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FDJQDFR5ctoKDJbp7LG4GS
Whole-file clang-format across LoopLibCore/PdfTool/UnitTests sources to clear format drift flagged by agent-fast. Add moc-generated autogen include dirs to UnitTests target so Qt meta-object headers resolve. Map agent-policy tidy gates to the three active test suites.
Add canonical milestone text for 0.2.1 (patch on the 0.2.0 line), register
GitHub milestone 17 in the sync manifest, and update living-sequence
references across milestone docs and the 0.5.0–0.10.0 roadmap extension.

Co-authored-by: michael berry <mberrys@users.noreply.github.com>
Replace legacy product tokens in milestone issue summaries, rename the
budget-exhaustion corpus schema kind to loop, and fix workflow
working-directory typos left from the Loupe-to-Loop rebrand.

Co-authored-by: michael berry <mberrys@users.noreply.github.com>
Manual .moc includes are generated at build time, so clang-tidy cannot
analyze those sources during agent-fast. Exclude them from tidy while
keeping format checks.

Co-authored-by: michael berry <mberrys@users.noreply.github.com>
…#144)

Add pdf::PDFBlockingThreadGuard, a runtime thread-affinity check a blocking
service adapter opens with so it refuses to run on the registered
interactive (canvas) thread instead of silently stalling pointer and frame
handling. Wire it into PreflightEngine::run(), the one blocking
implementation already reached through PDFJobScheduler, and register
EditorHost's owning thread as the interactive thread at construction.

Add PDFJobKind to PDFJobTraceEvent so job traces identify async work by
type, and document the interactive-thread boundary (what pointer/frame
callbacks may do directly vs. what must go through a submitted job) in
docs/JOB_SCHEDULER.md.

Wiring an actual UI trigger for interactive preflight runs, and correlating
PDFJobTraceEvent timing against InteractionTraceRecorder's slow-frame
attribution, remain open follow-up work for #144.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Xnr9TZYfGr1nMgBeh16CSb
Add pdfinteraction::evaluateTraceContracts() and its TraceContract/TracePhase
enums (LoopLibInteraction/sources/interactiontracecontract.h/.cpp): the
fixed-order pass/fail evaluator issue #146 AC7 asks for. Given an ordered
QList<TraceContractCheck>, it returns the first unsatisfied contract and the
phase responsible, matching scripts/ci/check_interaction_traces.py's
CONTRACTS/PHASES tuples and docs/schemas/interaction-trace-report.schema.json
exactly, so a future harness that supplies the nine checks in order gets AC7
for free. phaseForStage() is docs/INTERACTION_CONTRACT.md's TraceStage-to-phase
attribution table given a type.

The evaluator takes an already-assembled checklist rather than an
InteractionTraceRecorder or a live replay, so it is fully testable with
synthetic checks -- no InteractionController, no scheduler, no hit-test
dispatch -- and is covered by the new UnitTestsInteractionTraceContract target.

The prior gh-146 work (scenario/report schemas, the nine-scenario corpus, and
check_interaction_traces.py) validates the corpus as data but has no test
binary to produce a run; this evaluator is the piece that decides a run's
verdict once one exists. Replaying a scenario through InteractionController,
applying its cost model, and assembling a full report run remain open, as
UnitTestsInteractionTraces/UnitTestsInteractionTracesPresent in
docs/INTERACTION_CONTRACT.md's two-lanes table.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Xnr9TZYfGr1nMgBeh16CSb
…readGuard

docs/generated/phase5-widgets-inventory.json went stale when
UnitTestsBlockingThreadGuard landed (issue #144 commit): it's a target
directly in UnitTests/CMakeLists.txt, which
scripts/generate_phase5_widgets_evidence.py scans, but the catalog was never
regenerated for it. CI's policy job caught the drift --
test_verify_phase5_widgets_contract.py's crlf-currency check and its
hardcoded target count (70) both went red against the actual count (71).

Regenerate via scripts/generate_phase5_widgets_evidence.py --write and bump
the test's hardcoded count to match.

(scripts/generate-architecture-catalogs.py's separate architecture-catalog.json
was already regenerated for this target in the #144 commit; this is the
sibling widgets-surface catalog that step didn't cover.)

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Xnr9TZYfGr1nMgBeh16CSb
Rename leftover working-directory: loupe to loop in reusable Linux and
Windows workflows so agent-fast/build can run generate_corpus.py --check.

Rename schema_kind from loupe-processing-budget-exhaustion-corpus to
loop-processing-budget-exhaustion-corpus in the corpus generator, test,
and manifest so check_loop_identity passes.

Co-authored-by: michael berry <mberrys@users.noreply.github.com>
Co-authored-by: michael berry <mberrys@users.noreply.github.com>
Co-authored-by: michael berry <mberrys@users.noreply.github.com>
The agent-fast build proof never built the blocking-thread-guard test
target because it was absent from the core module's test list, so its
AUTOMOC .moc file was never generated and clang-tidy failed on
tst_blockingthreadguardtest.cpp. Registering the target lets
check-change.py build it (and generate the moc) before static analysis.
Defer MSI removal until after LGPL relink evidence is collected and normalize usr\bin install layout in run_qt_relink_test.ps1.

Co-authored-by: Cursor <cursoragent@cursor.com>
Route GitHub Actions context through env vars, add Dependabot cooldown, and validate GitHub API slugs before urllib requests. PDF-standard MD5 usage in pdfsecurityhandler.cpp is intentionally unchanged.

Co-authored-by: Cursor <cursoragent@cursor.com>
…ues (#194)

Continue PR #525 on current origin/dev. Shared pdfquick::tokens cover
spacing, typography, focus geometry, and colour roles; resolveStateVisual()
is the canonical finding/check mapping. Incomplete and waived states never
resolve as passed, and each state carries a unique icon plus accessible name.

Co-authored-by: michael berry <mberrys@users.noreply.github.com>
Co-authored-by: michael berry <mberrys@users.noreply.github.com>
Qt::red against white is only ~4.0:1. Use the light-theme fill (#B91C1C) so
a destructive button label still meets WCAG text contrast in high contrast.

Co-authored-by: michael berry <mberrys@users.noreply.github.com>
Drop restated enum notes, unused includes, and CMake/doc padding. Mapping
invariants stay in tests and LOOP_DESIGN_SYSTEM.md.

Co-authored-by: michael berry <mberrys@users.noreply.github.com>
Keep both UnitTests/tst_jbig2decodertest.cpp (PR 519) and
UnitTests/tst_lifecycletest.cpp (dev) in the core module boundary paths.

Co-authored-by: michael berry <mberrys@users.noreply.github.com>
Keep 0.2.1 in the living release train while adopting dev's consolidated
0.5.0-0.8.0 planned-train wording and retired-title note.

Co-authored-by: michael berry <mberrys@users.noreply.github.com>
mberrys and others added 16 commits September 13, 2026 10:59
…tract

UnitTestsDocumentSearch::searchReportsIncompleteWhenOperationBudgetExhausted
asserted that a budget-exhausted search is still admitted. dev's
QuickDocumentModelTest::exhaustedSearchReturnsAnIncompleteResult asserts the
opposite, and pdf::searchDocumentText returns before it evaluates admission when
the budget stops the search, so this branch's expectation is the one that has to
move. The slot keeps what this branch added: the machine-readable budgetExceeded
flag, the not-completed assertion, and the empty-match assertion.
findingNavigationMovesCanvasToTheFindingPage asserts that selecting a finding
moves the canvas to its page, but the check never sized the viewport. With no
viewport size placedPageRect() has no valid rect, so the page cannot be revealed
and currentPage() stays -1 whatever the navigation code does. Every sibling
check in this file calls setViewportGeometry(); this one did not.

The check has been red since it was added in 11d0dea, whose agent-fast never
built the quick targets: the LoopLibCore compile error in that commit failed the
lane before the tests could run, so this row was never exercised.

Reproduced and verified locally against the open PR branches' merge, which carry
the same check: 13 passed / 1 failed before, 13 passed / 0 failed after. The
product navigation code is unchanged.
The twelve overprint render fixtures were built with every page box equal, so
they had no bleed at all and loop-default.json's 9pt check failed them: the
corpus rows that preflight them could never pass, which is why they sat behind
"pending": true with no snapshot.

The trim box is now inset 10pt, which gives BleedBox (still unset, falling back
to MediaBox) a 10pt margin over the trim. Nothing else moves: the media box and
every mark keep their coordinates, so the committed render baselines still hold
and no mark gains or loses coverage.

Verified locally against the corpus harness and the render suite:
- UnitTestsPreflightCorpus: 11 of the 12 overprint rows now report
  pass=true/exit 0 (all twelve failed the bleed check before).
- UnitTestsOverprintRender: 15 passed / 0 failed with the committed 128x128
  baselines unchanged.

overprint-multiply-on still reports "Overprint with Multiply blend mode uses a
fallback; only Normal is exact" (exit 8, verdict incomplete), so its row stays
unresolved: that is the renderer's fidelity classification in
pdftransparencyrenderer.cpp, not a fixture defect.

The regenerated fixtures carry 0.2.0-alpha in their producer header while the
other twenty-odd fixtures still carry 0.1.0; regenerating the whole set is a
separate, cosmetic pass.
With the fixtures carrying real bleed, eleven of the twelve overprint rows
preflight as the manifest says they should (pass=true, no findings), so their
"pending" flags come off and their reports are pinned as snapshots. The suite
therefore stops failing on rows that were only waiting for the fixture fix.

Rows still unresolved, and why, so the next pass does not have to rediscover it:
- overprint-multiply-on: the renderer reports its Multiply blend as an
  approximate fallback (exit 8, verdict incomplete), so its recorded pass=true
  does not hold yet. Fixture is fine; the gap is the fidelity classification.
- malformed-not-pdf: the harness requires data.report, which an unreadable input
  never produces, so an input-error row needs its own comparison mode.
- thin-parts-fill, ai-art-* (4), transparency-* (6): no fixture exists. The
  generator has no builder for any of these names.

Verified locally against the corpus harness: 90 passed / 26 failed rows, down
from 68 / 48; the 26 are exactly those three groups.
Remove const from compressed QByteArray and qMove it into PDFStream
constructor, matching the pattern used elsewhere in pdfrgbtocmykfixup.cpp.

Co-authored-by: michael berry <mberrys@users.noreply.github.com>
…ation (#566)

<!-- CURSOR_AGENT_PR_BODY_BEGIN -->
## Summary

Closes the 0.2.1 release-gate gaps for GitHub #520 and #241.

### #520 — fresh processing budget per search

- `searchDocumentText()` now allocates an operation-scoped
`PDFProcessingBudget` instead of reusing the session budget whose
elapsed timer starts at session construction.
- Budget exhaustion is surfaced as
`PDFDocumentSearchResult::complete=false` / `budgetExceeded=true`;
`QuickDocumentModel::search()` returns `false` without letting
`PDFBudgetExceededException` escape to QML.
- Adds `UnitTestsDocumentSearch` regression coverage and
`scripts/ci/check_search_budget_gate.py`.

### #241 — independent validation release gate

- Adds `scripts/ci/check_independent_validation_gate.py` to keep the
oracle lane reviewable: conversion triad manifests,
`run_independent_validators.py`, `UnitTestsStandardOracle` /
`UnitTestsConversionOracle`, and self-certification source markers.
- Wires both guards into `ci.yml` `source_integrity` and
`scripts/agent/check-change.py`.

## Verification

- `python3 scripts/ci/check_search_budget_gate.py` — pass
- `python3 scripts/ci/check_independent_validation_gate.py` — pass
- `ctest -R '^UnitTestsDocumentSearch$'` — pass
- `python3 scripts/agent/check-change.py --base origin/dev` — focused
tests 34/34 pass; clang-tidy exits non-zero on touched TUs due to
pre-existing `'utility' file not found` diagnostic in this environment
(not introduced by this diff)

## Plan

See coordinator plan:
`/cursor/stores/self/internal/issue-520-241-release-gates-plan.md`

Fixes #520
Refs #241
<!-- CURSOR_AGENT_PR_BODY_END -->

<div><a
href="https://cursor.com/agents/bc-414bc936-d3b7-509a-86c5-5bf256827962?cursor_ref=pr_footer&cursor_cta=open_in_web"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://cursor.com/assets/images/open-in-web-dark.png"><source
media="(prefers-color-scheme: light)"
srcset="https://cursor.com/assets/images/open-in-web-light.png"><img
alt="Open in Web" width="114" height="28"
src="https://cursor.com/assets/images/open-in-web-dark.png"></picture></a>&nbsp;<a
href="https://cursor.com/background-agent?bcId=bc-414bc936-d3b7-509a-86c5-5bf256827962&cursor_ref=pr_footer&cursor_cta=open_in_cursor"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://cursor.com/assets/images/open-in-cursor-dark.png"><source
media="(prefers-color-scheme: light)"
srcset="https://cursor.com/assets/images/open-in-cursor-light.png"><img
alt="Open in Cursor" width="131" height="28"
src="https://cursor.com/assets/images/open-in-cursor-dark.png"></picture></a>&nbsp;</div>

<!-- codesmith:footer -->
---
<a
href="https://app.blacksmith.sh/studio-berry/codesmith/loop/pr/566"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-dark-v2.svg"><source
media="(prefers-color-scheme: light)"
srcset="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-light-v2.svg"><img
alt="View with [code]smith"
src="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-dark-v2.svg"></picture></a>
<a
href="https://backend.blacksmith.sh/track/enable-autofix?expires=1791864821&installation_model_id=435800&pr_number=566&repository=studio-berry%2Floop&return_to=https%3A%2F%2Fgithub.com%2Fstudio-berry%2Floop%2Fpull%2F566&signature=bec110427aa6391d5e2b976b65459615377aef9982e2758dcf197848e81d2552"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-dark.svg"><source
media="(prefers-color-scheme: light)"
srcset="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-light.svg"><img
alt="Autofix with [code]smith"
src="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-dark.svg"></picture></a>
<sup>Need help on this PR? Tag <code>@codesmith-bot</code> with what you
need. Autofix is disabled.</sup>

<!-- codesmith:autofix:disabled -->
<!-- /codesmith:footer -->
- Add transparency, ai-art, and thin-parts-fill PDF fixtures
- Unpend malformed-not-pdf and overprint-multiply-on manifest rows
- Generate thin-parts-fill via LoopGenerateFixtures
- Handle PdfTool input-error envelopes in corpus runner
- Add/update golden snapshots for promoted fixtures

Co-authored-by: michael berry <mberrys@users.noreply.github.com>
- Add transparency, ai-art, and thin-parts-fill PDF fixtures
- Unpend malformed-not-pdf and overprint-multiply-on manifest rows
- Generate thin-parts-fill via LoopGenerateFixtures
- Handle PdfTool input-error envelopes in corpus runner
- Add/update golden snapshots for promoted fixtures
@mberrys
mberrys removed this pull request from stack #567 September 13, 2026 21:22
mberrys and others added 9 commits September 13, 2026 14:23
Co-authored-by: michael berry <mberrys@users.noreply.github.com>
#196)

- Wire canvas overlay clicks through selectFinding for full navigation
- Add selectNextFinding/selectPreviousFinding with Alt+Up/Down shortcuts
- Invalidate FindingCanvasNavigator on revision sync
- Sync PreflightPane list highlight to selectedFindingId
- Populate evidenceTargets from finding bbox in navigation requests
- Add shell keyboard and inspector dispatch tests for finding navigation

Co-authored-by: michael berry <mberrys@users.noreply.github.com>
Move adjacent-finding selection into PreflightFindingsModel so EditorHost
does not aggregate finding counts. Enable Alt+Up/Down shortcuts from Core
preflightStateName and mirror Main.qml in the accessibility smoke target.

Co-authored-by: michael berry <mberrys@users.noreply.github.com>
<!-- CURSOR_AGENT_PR_BODY_BEGIN -->
Closes the documentation scope of GitHub #235 / Linear MB-463 for the
**0.2.1** architecture-truth gate.

PR #255 (2026-08-10) introduced ADR verification headers, generated
architecture catalogs, and the `Documentation truth` CI workflow. This
follow-up re-verifies that narrative against **current `dev`** at
`e65cdd19` after DocumentContext revision authority (#236) and
subsequent preflight/session work.

## Changes

- **ADR-001** — align with revision-keyed caches, optional
`PDFDocumentContext`, admission modes, byte-bounded eviction, and
factory API
- **ADR-002** — add `thin-parts`, graph-backed checks, and pointers to
generated check catalogs
- **All ADRs** — refresh `Last-verified` to `2026-09-13 @ e65cdd1…`
- **`docs/adr/README.md`** — new ADR index with status table and catalog
regeneration instructions
- **`docs/architecture-source-of-truth.md`** — cross-link revision
authority and `preflight-check-catalog.json`
- **`docs/REPO_MAP.md`** — link ADR index in layout table
- **`loop-preflight/README.md`** — clarify v2 examples vs v3 engine
output

## Verification

- `python3 scripts/generate-architecture-catalogs.py --check` — pass
- `python3 scripts/agent/check-change.py --base origin/dev` — pass
(includes mapped preflight focused tests)

No protected contract or schema changes.

Refs #235
<!-- CURSOR_AGENT_PR_BODY_END -->

<div><a
href="https://cursor.com/agents/bc-f35ce71d-cccd-5600-a2ca-25dac77ee16d?cursor_ref=pr_footer&cursor_cta=open_in_web"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://cursor.com/assets/images/open-in-web-dark.png"><source
media="(prefers-color-scheme: light)"
srcset="https://cursor.com/assets/images/open-in-web-light.png"><img
alt="Open in Web" width="114" height="28"
src="https://cursor.com/assets/images/open-in-web-dark.png"></picture></a>&nbsp;<a
href="https://cursor.com/background-agent?bcId=bc-f35ce71d-cccd-5600-a2ca-25dac77ee16d&cursor_ref=pr_footer&cursor_cta=open_in_cursor"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://cursor.com/assets/images/open-in-cursor-dark.png"><source
media="(prefers-color-scheme: light)"
srcset="https://cursor.com/assets/images/open-in-cursor-light.png"><img
alt="Open in Cursor" width="131" height="28"
src="https://cursor.com/assets/images/open-in-cursor-dark.png"></picture></a>&nbsp;</div>

<!-- codesmith:footer -->
---
<a
href="https://app.blacksmith.sh/studio-berry/codesmith/loop/pr/565"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-dark-v2.svg"><source
media="(prefers-color-scheme: light)"
srcset="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-light-v2.svg"><img
alt="View with [code]smith"
src="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-dark-v2.svg"></picture></a>
<a
href="https://backend.blacksmith.sh/track/enable-autofix?expires=1791864553&installation_model_id=435800&pr_number=565&repository=studio-berry%2Floop&return_to=https%3A%2F%2Fgithub.com%2Fstudio-berry%2Floop%2Fpull%2F565&signature=a50e96230032f93f6325b2a26bec45140ef068785ea2a39a5697946431046be1"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-dark.svg"><source
media="(prefers-color-scheme: light)"
srcset="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-light.svg"><img
alt="Autofix with [code]smith"
src="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-dark.svg"></picture></a>
<sup>Need help on this PR? Tag <code>@codesmith-bot</code> with what you
need. Autofix is disabled.</sup>

<!-- codesmith:autofix:disabled -->
<!-- /codesmith:footer -->
## Summary

Implements the Qt Quick operator loop across shell information
architecture, first-class revision-bound preflight, report-backed
Prepress Inspector, finding-to-canvas navigation, and bounded GUI/E2E
verification.

## Issue linkage

- Related to #193
- Related to #195
- Related to #127
- Related to #196
- Related to #170

## Verification

- Focused CTest: 9/9 passed.
- Product operator-loop: 8/8 passed.
- Quick accessibility smoke: 3/3 passed on native and software paths.
- Repository gate: source, architecture, policy, preflight-truth,
mirror-parity, formatting, builds, clang-tidy, and 29/29 policy-selected
tests passed with the configured environment.

No issues are auto-closed by this PR.

<!-- codesmith:footer -->
---
<a
href="https://app.blacksmith.sh/studio-berry/codesmith/loop/pr/564"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-dark-v2.svg"><source
media="(prefers-color-scheme: light)"
srcset="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-light-v2.svg"><img
alt="View with [code]smith"
src="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-dark-v2.svg"></picture></a>
<a
href="https://backend.blacksmith.sh/track/enable-autofix?expires=1791862718&installation_model_id=435800&pr_number=564&repository=studio-berry%2Floop&return_to=https%3A%2F%2Fgithub.com%2Fstudio-berry%2Floop%2Fpull%2F564&signature=07ad839c084425c0ba71236010ce4f16fdbad9e5842e8c5e44fe3acc388b79b9"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-dark.svg"><source
media="(prefers-color-scheme: light)"
srcset="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-light.svg"><img
alt="Autofix with [code]smith"
src="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-dark.svg"></picture></a>
<sup>Need help on this PR? Tag <code>@codesmith-bot</code> with what you
need. Autofix is disabled.</sup>

<!-- codesmith:autofix:disabled -->
<!-- /codesmith:footer -->
Fix whitespace alignment in the nested ternary that maps preflight
verdict states to exit codes. Unblocks agent-fast on dev and RC PR #554.

Co-authored-by: michael berry <mberrys@users.noreply.github.com>
<!-- CURSOR_AGENT_PR_BODY_BEGIN -->
## What changed

Agent-fast on `dev` failed with `-Wclang-format-violations` on lines
298–299 of `UnitTests/tst_preflightcorpus.cpp` (nested ternary
whitespace). This PR applies clang-format to that file only, unblocking
RC PR #554.

## Proof

- [x] `clang-format --dry-run --Werror
UnitTests/tst_preflightcorpus.cpp` passes locally
- [x] One `changes/cursor-fix-preflightcorpus-format-6547.md` fragment
added
- [ ] Changed behaviour has a test that fails without the change — N/A
(format-only)
- [ ] Protected-path or contract change — none

## Internal logic (touched behavior-bearing code)

Format-only change; no logic touched.

Anti-slop summary: Whitespace alignment only; no comments or logic
changed.

## Security and rollback

- [x] No security impact
- Rollback: revert this commit

## Docs

- [x] none needed — format-only fix

## Self-review (BSP-002 §4.3)

- [x] Reviewed diff; format-only whitespace in ternary chain
<!-- CURSOR_AGENT_PR_BODY_END -->

<div><a
href="https://cursor.com/agents/bc-ecb73197-e4af-511c-8e56-122ec4c8b371?cursor_ref=pr_footer&cursor_cta=open_in_web"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://cursor.com/assets/images/open-in-web-dark.png"><source
media="(prefers-color-scheme: light)"
srcset="https://cursor.com/assets/images/open-in-web-light.png"><img
alt="Open in Web" width="114" height="28"
src="https://cursor.com/assets/images/open-in-web-dark.png"></picture></a>&nbsp;<a
href="https://cursor.com/background-agent?bcId=bc-ecb73197-e4af-511c-8e56-122ec4c8b371&cursor_ref=pr_footer&cursor_cta=open_in_cursor"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://cursor.com/assets/images/open-in-cursor-dark.png"><source
media="(prefers-color-scheme: light)"
srcset="https://cursor.com/assets/images/open-in-cursor-light.png"><img
alt="Open in Cursor" width="131" height="28"
src="https://cursor.com/assets/images/open-in-cursor-dark.png"></picture></a>&nbsp;</div>

<!-- codesmith:footer -->
---
<a
href="https://app.blacksmith.sh/studio-berry/codesmith/loop/pr/571"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-dark-v2.svg"><source
media="(prefers-color-scheme: light)"
srcset="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-light-v2.svg"><img
alt="View with [code]smith"
src="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-dark-v2.svg"></picture></a>
<a
href="https://backend.blacksmith.sh/track/enable-autofix?expires=1791933972&installation_model_id=435800&pr_number=571&repository=studio-berry%2Floop&return_to=https%3A%2F%2Fgithub.com%2Fstudio-berry%2Floop%2Fpull%2F571&signature=0fa64747af7a597566091c8ef76c5067c90f5578b7788d889b0fa4e6b5d1c284"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-dark.svg"><source
media="(prefers-color-scheme: light)"
srcset="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-light.svg"><img
alt="Autofix with [code]smith"
src="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-dark.svg"></picture></a>
<sup>Need help on this PR? Tag <code>@codesmith-bot</code> with what you
need. Autofix is disabled.</sup>

<!-- codesmith:autofix:disabled -->
<!-- /codesmith:footer -->
@cursor
cursor Bot merged commit d2e9ce9 into unstable Sep 14, 2026
26 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment