Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 51 additions & 0 deletions .agents/inbox/2026-10-28-browser-evidence-needs-files.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# Browser evidence must exist as files before report collection

2026-10-28, PR #224. Independent review comment4404454674 verified that
`runPlaywrightSequence` ignores attachments without a path. The new priority
journeys used `info.attach({body})`; the actual Playwright JSON normalizer retained
body/no path, and the real adapter probe returned a passing case with zero
attachments and zero errors. The517742c2,000-item stage completed successfully
in CI40742884920 at18:22:57UTC, but this did not establish retained priority
accounting evidence. Preserve that distinction and the earlier report.

Cause: producer-side inline attachments did not meet the existing unified
collector's file-path contract. A green browser assertion alone does not prove
that another machine can inspect its measurements or screenshots.

Corrective rule: write JSON via `info.outputPath` and `writeFile`, save screenshots
to output paths, then attach by `path`. Required evidence must survive the actual
unified report and uploaded archive, not only Playwright's in-memory report.
Do not weaken owned-path checks or silently call missing evidence accepted.

The corrected1440px headed priority journey passed in13.09s with one worker and
zero retries. Its actual JSON report lists file attachments for
`priority-accounting.json` (3193 bytes) and `priority-fallback.png` (61545 bytes),
and both files exist. Retained local report: `priority-artifacts6.json` in the
owned resolution evidence directory. The2,000-item case now writes and attaches
`two-thousand-priority.json` by the same existing pattern; it is not rerun locally
under the workstation resource constraint.

Limits: this is a correction to the new test producers, not a claim that all
legacy inline attachments are collected. Final exact-source CI must execute the
large case and independently verify its retained counts, screenshots, artifact
paths and source fingerprint. No runtime or policy behavior changed.

Independent inspection of the materialized 9b8409c image found a second evidence
gap: the screenshot showed an almost empty canvas after reload/inspection, even
though canonical fallback IDs were correct. The test now waits for camera
readiness, frames the owned pair, and requires its actual painted stroke and
visible “Depends On +1” label. It uses the shared symbol oracle, including useful
visible titles, minimum text/wire weight, and label/card/wire clearance.

The first strengthened run (`priority-artifacts7`) rejected a painted horizontal
SVG path because Playwright's area-based visibility predicate sees zero height.
The replacement checks ancestor visibility, actual stroke/opacity/length and
viewport intersection. The next run (`priority-artifacts8`) correctly rejected
the 390px scene: its horizontal endpoint titles were both off-screen. The phone
fixture now positions the same owned Gateway/Worker pair vertically before the
API baseline is recorded. No assertion or source-position invariant was relaxed.
Both desktop 1440 and phone 390 journeys passed in 25.17s in
`priority-artifacts9`, with actual geometry JSON, PNG and accounting files. The
phone image shows both endpoint titles and the fallback connection; the desktop
image shows four cards. All failed reports/images remain retained. This remains
a test/evidence correction; no product defect was established by these failures.
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
# Refresh every subscribed edge query after deleting a relationship

On 2026-10-28, inspecting the actual `priority-typography10` desktop/phone
JSON exposed a count mismatch after the intentional BLOCKS deletion: canonical
API data and the graph dock had four relationships, while the graph-selector
header still read `4 nodes, 5 connections`. Existing cache/count lessons did
not cover this query-variable mismatch.

The stronger desktop assertion failed before the fix:

```text
priority-count11: 0 passed, 1 failed, 20.15 seconds, zero retries
Expected: 4 nodes, 4 connections
Received: 4 nodes, 5 connections
Timeout: 5000ms (14 reads of the unchanged header)
```

The failed report, screenshot and trace remain in the owned evidence directory.
The exercised command was the existing `relationship-priority.spec.ts` with
`--grep 1440 --headed --workers=1 --retries=0`, using only owned graph fixtures.

Cause: the selector observes `GET_EDGES` with a source-graph filter; the graph
observes the same document with source-or-target filtering. The relationship editor had no mutation refetch configuration and its parent
callback refreshed only the renderer’s variables. Apollo stores those root lists
separately, so normalized entity updates alone did not remove the stale ID from
the selector's list. The selector does not poll.

The correction supplies `GET_EDGES` itself to the mutation's `refetchQueries`,
on the editor’s explicit Delete action, so Apollo refreshes matching observed
queries using their own variables. The
installed `QueryManager.getObservableQueries` implementation was inspected to
verify document matching. The editor awaits those refetches before reporting completion. Its separate
flip workflow is unchanged; no graph membership, priority policy or persisted
position changes.

Corrective rule: when deleting records represented by independently filtered
query lists, refresh the subscribed lists or explicitly update each affected
cache field. Test the user-facing count as well as the canvas and server state.
Do not add polling merely to hide a mutation invalidation gap.

The desktop/phone priority journey now requires the header to change from five
to four connections after the one authorized deletion, alongside original-ID
fallback, rendered text/wire geometry, no extra mutations and unchanged nodes.
Final committed-source CI and independent review remain required. This is a
deletion-path correction, not proof of every other mutation or cross-client
refresh path.

An initial local attempt changed the graph canvas mutation instead of the
editor’s actual Delete action. `priority-count12` still failed the desktop header
assertion; that attempted source change was reverted. Its phone case separately
failed an earlier keyboard-return assertion before deletion; that report and
trace are retained for independent review. A passing subsequent count test alone
does not explain or erase that separate failure.

With the correction on the actual editor action, `priority-count13` passed both
complete desktop/phone journeys in 25.22 seconds, zero retries. The retained
final typography samples now show `4 nodes, 4 connections`; all original API,
priority, focus and geometry assertions also passed.

Independent review traced the separate count12 focus failure to stale label
clearance after the relationship panel closes. Its deterministic failing-before
regression and correction are in [the priority context lesson](2026-10-28-priority-controls-must-preserve-context.md).
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
# Verify emitted typography after refreshing a long-running preview

On 2026-10-28, the owned GraphDone headed preview still displayed some small
text after the readability change. Searching the symptom index and existing
readable-symbol, dependency-parser and preview lessons found no matching
configuration-refresh incident.

The preview and reviewed source had identical `packages/web/tailwind.config.js`
bytes (SHA256 `ab33c1897cd34ea18ff04cd6ef644558b59254dcaeb6120225eef4951e8f3ff8`).
Nevertheless, reading the actual browser CSS rules before restart returned:

```text
.text-xs { font-size: 0.75rem; line-height: 1rem; }
.font-normal { font-weight: 400; }
```

The document root was 16px. Visible graph counts, connection status and sidebar
labels consequently measured 12px. The long-running Vite process had received
source updates; source-file identity did not establish emitted-style identity.
Only the owned Vite process was stopped and restarted from its web package with
the same loopback API proxy. Reloading the same headed browser then returned:

```text
.text-xs { font-size: 0.875rem; line-height: 1.25rem; }
.font-medium { font-weight: 600; }
.font-normal { font-weight: 500; }
```

No product source changed. This establishes stale preview styling, consistent
with retained build/configuration state; it does not isolate a specific Vite or
Tailwind cache implementation. A fresh independent exact-source PostCSS compile
also emitted the intended rules in 1.37 seconds, using locked Tailwind 3.4.19,
PostCSS 8.5.28 and autoprefixer 10.4.21. See [the issue evidence](https://github.com/GraphDone/GraphDone-Core/issues/222#issuecomment-6477709156)
and [independent review](https://github.com/GraphDone/GraphDone-Core/pull/223#pullrequestreview-5688035698).

Corrective rule: after copying build or typography configuration into an existing
preview, restart that owned preview and read computed styles from real controls.
Do not stop unrelated services, assume hot reload refreshed configuration, or
equate matching source hashes with matching generated CSS. Keep one headed
browser and bounded serial checks on the shared workstation.

The existing desktop/phone relationship-priority journeys now measure the actual
graph title, graph counts, visible Connections dock and Links control. They require the 14px/500 secondary
baseline, 14px/600 heading and 16px/600 control, reject a deliberate 12px/400
visible counter, restore its original style, and retain named before/negative/after
computed samples in `priority-typography.json` using file-backed attachments.

Limits: these samples do not audit every page or every font. Earlier local SVG
geometry checks remain evidence for their explicit assertions, not for all app
utilities. The preceding CI build passed but did not retain generated CSS bytes;
neither source compilation nor screenshots are retroactive byte-level inspection
of that CSS. The strengthened journey must pass on its final committed source.

The first refreshed-style run, `priority-typography10`, passed both complete
journeys in 25.28 seconds without retries. Actual JSON samples showed 14/600,
14/500 and 16/600 before/after, and the injected counter was 12/400. Inspection
also exposed a stale relationship count; its separate cause and correction are
recorded in [the deletion lesson](2026-10-28-edge-deletion-must-refresh-subscribed-counts.md).

The phone intentionally hides the header count with its existing responsive
CSS. That sample verifies emitted styling and subscribed data, not visible
phone-counter readability. The final test also requires the actual Connections
dock to be visible and readable, records visibility for every named sample, and
applies the 12px/400 negative to that visible dock on phones.

Final focused run `priority-typography16` passed both full journeys in 25.81
seconds with zero retries. Its JSON explicitly distinguishes the hidden phone
header from the visible 14px/500 dock and records the visible negative target.
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# Priority controls must preserve current focus and inspection

2026-10-28, PR #224 / issue #220. Independent review of `5aaf6ec`
reproduced two interaction failures with the actual DOM/handlers:
- Open a “Blocks +2” pair, change Links to All and close the pair browser. The
connected SVG trigger loses its tabindex, so calling focus does nothing and
keyboard focus remains on BODY.
- Click the new Links control on a graph with fewer than40 items. The document
outside-click handler clears the selected item and editing edge; the same
control inside semantic overview is protected by that existing boundary.

Review evidence: PR comments4404185217 and4404202776, summary5687337487.
The initial helper/component suite passed41 cases and routing passed10; those
passes did not cover these transitions.

Corrective rule: after attempting return focus, verify the actual activeElement
and fall back to the visible Browse trigger if the original no longer accepts
focus. Preserve unrelated focus. A presentation control owns its click boundary;
changing detail must not also dismiss the current inspector/editor.

`relationship-priority.spec.ts` now opens a pair, switches to All, keyboard-closes
it and asserts Browse receives focus with an unchanged camera. It also inspects
Gateway, opens the native select by pointer, changes All/Essential by keyboard,
and checks the same inspector/camera remain. Both1440/390 headed journeys passed
in25.0s with one worker and zero retries (`priority-focus5`). Original identity,
API snapshot, explicit winner deletion/fallback and cleanup checks remain.
A preceding local command used the preview as its own copy source, failed the
copy, then executed the old tests; `priority-focus4` is not regression evidence.

Limits: local probes reuse owned dependencies. Full exact-head quality/browser
CI, actual2,000-item priority artifacts, independent correction review and final
dev integration remain required. No claim of full item routing/bus completion.

## Recompute label clearance when the browser panel changes

The `priority-count12` phone journey later failed its initial pair-return focus
assertion before any deletion. Independent trace inspection showed the pair
label was still present by ID but had `display:none`: a delayed label-placement
pass had treated the open relationship panel as an obstacle. Closing the panel
did not invalidate placement, so the now-unobstructed label stayed hidden and
focus correctly fell back to Browse. Review comment4404899816 records the trace
evidence; accepting Browse in this case would hide the layout defect.

A deterministic regression changes All then Essential while the phone panel is
open, verifies the obstructed label is hidden, then presses Escape. On the old
runtime `priority-obstacle14` failed after 16.23 seconds: the label remained hidden
for all 14 reads over the 5-second assertion deadline. Camera/data assertions and
expected focus remain unchanged.

The label-placement layout effect now also depends on `itemRelationshipScope`.
Mounting/unmounting/changing the panel recalculates its actual obstacle footprint
before the existing next-frame focus restoration. This is bounded placement on
a UI transition, not a new per-frame router. The All-level case still falls back
to Browse when the original label intentionally loses its interactive role.

The corrected `priority-obstacle15` run passed both full desktop/phone journeys
in 26.03 seconds with zero retries, including the deterministic hidden-to-visible
transition, original-label keyboard return, accurate post-delete counts and
computed typography negatives. The final priority CI still must validate and
retain these assertions on the published source.
68 changes: 68 additions & 0 deletions .agents/inbox/2026-10-28-trace-fallback-needs-directional-scope.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
# Trace fallback must respect direction and preserve useful screen space

Date:2026-10-28. Core PR224, issue220. Existing guidance on control flow,
readable symbols and priority context was checked first.

## Evidence and cause

Final source377f5a3 passed the small priority and2000-item/5000-edge stages, but
CI40751802514 failed both nested semantic browser cases. Retained review:
https://github.com/GraphDone/GraphDone-Core/pull/224#pullrequestreview-5688631798 .
Desktop incoming Payments selected an original DEPENDS_ON bundle, then wiring
intersected it with the global unordered-pair selection. The opposite-direction
BLOCKS winner removed the only eligible incoming relationship. The phone's
additional Links row reduced the measured overview capacity to one group.
The process-evidence failure is not a third independent failing browser case;
downstream required stages did not run.

The new component regression failed on the unchanged runtime: expected
`['fallback','reverse']`, received `['fallback']`;6 other cases passed.
Command, using an owned dependency fixture:
`vitest run src/components/SemanticGraphOverview.test.tsx --maxWorkers=1 --no-file-parallelism`.
After correction, that suite plus relationshipPriority and semanticTrace passed
19 cases in3.29s. A first command used a nonexistent vitest.config.ts and failed
before tests; it is not behavioral negative evidence.

A first responsive candidate passed both headed nested journeys in67.27s,
zero retries/errors, but its actual390px screenshot showed Zoom to Fit covering
part of the group-count button. That candidate is visually rejected despite
the green tests. The correction retains the reserved right control lane,
uses one line for the phone group/item counts, and reduces spacing without
reducing the14/16/18px typography floors or44px touch targets.

Final focused headed desktop/phone run passed2/2 in51.51s, zero retries,
errors or skipped cases, with the unchanged readable-text negative and strengthened
incoming-direction/control-clearance checks. Actual geometry JSON and PNGs show
two cards and one painted incoming route at both sizes: no card intersections,
unrelated crossings/overlaps, diagonal segments or small text. Partition at the
incoming trace is183 total =1 drawn +132 internal +50 external deferred; the
previously summarized incoming original is now represented in its explicit scope.
Command: `playwright test tests/e2e/graph/nested-semantic-lod.spec.ts
--project=GraphDone-Core/dev-neo4j/chromium --headed --workers=1 --retries=0
--trace=retain-on-failure --reporter=json`, against an owned local API/database.
The superseded67.27s candidate and full CI failures remain retained.

## Corrective rule

An explicit incoming/outgoing trace re-evaluates per-original-pair fallback
among that direction's canonical external relationships, before routing or
paging. Its additional eligible originals are represented while tracing;
other global originals remain accounted for. Exiting restores the global
priority partition. Do not switch the user's level to All, reverse originals,
or use the strongest group-level bundle to suppress other member pairs.

Maintain exact partitions for drawn, deferred, summarized, internal and pending
records. A component regression covers the opposite blocker, incoming fallback,
a lower-tier independent member pair, All, direction changes, exit and unchanged
input. The existing actual browser regression continues to require two useful
cards, a painted incoming dependency, readable text, clear routes and no writes.
It additionally checks top controls do not cover one another. Inspect screenshots;
a geometry oracle that checks only routes cannot establish control clearance.

## Limits

These changes concern group traces and controls, not arbitrary item obstacle
routing or larger browser capacity. Smaller screens can still honestly defer
content when finite space cannot fit two cards. A focused owned-fixture run is
not a clean-install/full-CI acceptance substitute. Earlier failures remain in
GitHub artifacts and final exact-source plus post-dev evidence is still required.
Loading
Loading