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
96 changes: 48 additions & 48 deletions docs/product/current-state.md
Original file line number Diff line number Diff line change
@@ -1,70 +1,70 @@
# Plainweave Current State Checkpoint: 2026-06-28 (PDR-015; prior PDR-013, PDR-014) · (commit recorded below)
# Plainweave Current State Checkpoint: 2026-06-28 (PDR-016; prior PDR-015) · (commit recorded below)

## The bet right now

**Harden + build out, under the soft-launch / RC posture** (owner-stated: Plainweave is
published but has no users yet, so iteration is cheap). The active theme is
**production-readiness hardening**: PDR-014 retired 3 of the 5 named blockers; PDR-015 this
session closed the peer-facts MCP/CLI parity gap and added cross-member regression coverage.
The carried **coverage-completeness** frontier remains the genuine north-star mover but is
owner-gated / sibling-paced. Metric: production-readiness (surface parity + regression);
north-star (completeness) unchanged.
**production-readiness hardening**. This session hardened the ratified operator web UI
(PDR-013) — two WCAG AA a11y fixes — and **delivered the full 1.2 line to `origin/main`**
(owner-directed). Metric: production-readiness (surface parity + regression + a11y guardrails);
north-star (coverage completeness) unchanged — owner-/sibling-gated.

## In flight

- **Release `1.2.0`** — `release/1.2.0` branch is cut (CHANGELOG still `[Unreleased]`); the
version question (refold 1.1.0 vs ship 1.2.0) is effectively **resolved to 1.2.0**.
Remaining: finalize the CHANGELOG version/date, and the PyPI publish (held, owner-gated).
- **Peer-facts CLI parity — DELIVERED + merged to `main`** (PDR-015):
`plainweave wardline-peer-facts` / `requirements-enrichment` reuse `PlainweaveMcpSurface`;
`make ci` green (378 tests, 91.14% cov); `wardline scan` clean. Lacuna's tour gained
`plainweave+wardline` / `plainweave+warpline` cells (sibling repo, Lacuna PDR-0015) —
**two clean-checkout prerequisites remain owner-side** (see escalations).
- **Operator web UX overhaul — landed concurrently** (`main`: `9f00ae0`, `4c12d7f` — UI/a11y
overhaul, site-kit tokens, design review). NOT a decision of this session and has **no PDR
from this vantage**; recommend its own `/product-checkpoint` so its rationale + reversal
trigger are recorded.
- **Release `1.2.0`** — `origin/main` now carries the entire 1.2 line (peer-facts CLI parity
PDR-015 + the operator web UX/a11y overhaul PDR-016 + design-review docs). The version
decision is **1.2.0** (owner-reaffirmed this session: "still as 1.2"). Remaining: finalize
the CHANGELOG version/date and reconcile the `release/1.2.0` branch (it predates these merges
and now lags `main`), then the **PyPI publish (held, owner-gated)**.
- **Operator web UI UX + a11y overhaul — DELIVERED to `main` + now carries a PDR** (PDR-016):
site-kit tokens + this session's two a11y review fixes (visited-primary contrast restored to
AA; toast auto-dismiss moved to `base.html` so it fires on every page). Closes the
"web overhaul needs a PDR" gap PDR-015 flagged.
- **Peer-facts CLI parity — DELIVERED, now on `origin/main`** (PDR-015):
`plainweave wardline-peer-facts` / `requirements-enrichment`; `make ci` green (378 tests,
91.14% cov); `wardline scan` clean.
- **Peer-facts sibling wiring** — 3 owner-gated handoff prompts (`docs/handoffs/`) not yet
dispatched: Warpline consumer, Wardline scan-identity metadata, Warpline interface-lock
item-schema ratification.
- **Lacuna tour** — two clean-checkout prerequisites remain (sibling repo, Lacuna PDR-0015):
the packaging bug below blocks `uv tool install`, and `docs/tour.md` needs a clean-tree
regen (a `legis govern` leg byte-locks tree-cleanliness; concurrent dirt left it `[WARN]`).
- **Deferred perf/hint** (unchanged, acceptable at pre-alpha scale): `plainweave-706d80dc8e`,
`plainweave-3edcd19943` (P3); semantic-similarity hint `plainweave-02376962ab` (PDR-003).

## Open questions / blocked-on-owner (escalations)

- **Push `main` + finalize `release/1.2.0` + publish.** `main` is well ahead of
`origin/main` and now carries peer-facts CLI parity + the web overhaul. Pushing
`foundryside-dev/plainweave` is outward-facing (needs `tachyon-beep`, `gh auth switch`);
finalizing 1.2.0 + the held PyPI publish are owner calls.
- **Lacuna tour — two clean-checkout prerequisites** (the new cells are correct but not
reproducibly green on a fresh clone until): (1) **install the updated plainweave** —
blocked by a pre-existing wheel-build packaging bug (`force-include` double-adds
`web/static/.gitkeep`), filed as observation **`plainweave-obs-6a7255ffbe`**; (2)
regenerate `docs/tour.md` on a clean tree (a pre-existing `legis govern` leg bakes
tree-cleanliness into the byte-locked doc; concurrent dirt left it `[WARN]`). Both recorded
in Lacuna PDR-0015.
- **Hand off the 3 peer prompts** to the sibling owners (Warpline/Wardline) — owner-gated.
- **Cross-member coverage completeness** (carried, most pressing north-star mover) — Rust
public surface untagged upstream on Loomweave; owner-gated (sibling obligation).
- **Carried:** `vision.md` authority-grant metadata still missing (a vision edit, owner-gated);
publishing a headline north-star number remains owner-gated (PDR-002/009).
- **Finalize `release/1.2.0` + publish to PyPI** — held, owner-gated (publication is an
authority-grant escalation, PDR-002/PDR-012). _(The "push `main`" half of this escalation
was RESOLVED this session — the owner directed the merge to remote `main`.)_
- **Lacuna tour — two clean-checkout prerequisites:** (1) fix the **wheel-build packaging bug**
(`[tool.hatch.build.targets.wheel.force-include]` double-adds `web/static/.gitkeep`),
observation **`plainweave-obs-6a7255ffbe`** (P2), then install plainweave; (2) regenerate
`docs/tour.md` on a clean tree.
- **Hand off the 3 peer prompts** to the sibling owners (Warpline / Wardline) — owner-gated.
- **Cross-member coverage completeness** (carried, the most pressing north-star mover) — the
Rust public surface is untagged upstream on Loomweave; owner-gated (sibling obligation).
- **Carried vision edits (owner-gated):** `vision.md` authority-grant metadata still missing;
"Serves" still does not name human operators (PDR-013); publishing a headline north-star
number remains owner-gated (PDR-002/009).

## Last checkpoint did (this session)

- **Delivered peer-facts CLI parity** (PDR-015, accepted): two CLI subcommands reusing the MCP
surface; folded in two owner-directed sibling-contract fixes (rejected-trace enrichment +
root-aware doctor remediation). `make ci` green (378 tests, 91.14% cov); merged to `main`.
- **Built the Lacuna cross-member tour demos** (Lacuna PDR-0015): `plainweave+wardline`
(full resolved/unseen) + `plainweave+warpline`, each asserting the no-silent-clean invariant.
- **Ran an adversarial multi-lens review** (ultracode workflow): fixed 4 real findings
(temp-dir cleanup, per-conjunct drop-tests, PEP8); rejected 4 false positives. Filed the
packaging-bug observation; recorded the 2 tour prerequisites.
- **Adversarially reviewed two owner-supplied web a11y findings** (did not rubber-stamp —
confirmed CSS specificity, WCAG contrast math, and the htmx confirm-flow trace), then **fixed
both** (`a15adb1`): visited primary links restored to AA contrast; success-toast auto-dismiss
moved to `base.html` so confirm-step flows and the requirement dossier no longer leave it
stuck. 0 false positives.
- **Merged `feat/lacuna-peer-facts-tour-cli-parity` → `origin/main` via PR #5** (owner-directed
push as `tachyon-beep`): brought the web overhaul + docs + peer-facts checkpoint + a11y fixes
to `main`. CI gate green (378 tests, 91.14% cov, 37s); branch deleted.
- **Recorded PDR-016**, closing the web-overhaul-needs-a-PDR gap PDR-015 left open.

## Next session, start here

**Owner calls on the release + push escalations** (finalize 1.2.0 + the held publish + push
`main`), then close the two Lacuna-tour prerequisites (fix the packaging bug → install
plainweave → clean-tree `make tour`). Also: **checkpoint the concurrent web UX overhaul** so
it carries a PDR. Then continue **harden + build** (remaining blockers: Loomweave-owned
identity resolution, Legis fact emission, Filigree contract tests) or pivot to
coverage-completeness if the owner wants product movement.
**Owner calls on the release escalation** finalize the `1.2.0` CHANGELOG version/date,
reconcile/retire the `release/1.2.0` branch against `main`, then the held PyPI publish. Then
close the two **Lacuna-tour prerequisites** (fix the packaging bug → install plainweave →
clean-tree `make tour`). Then continue **harden + build** (remaining production blockers:
Loomweave-owned identity resolution, Legis fact emission, Filigree contract tests) or pivot to
**coverage-completeness** if the owner wants north-star movement.
72 changes: 72 additions & 0 deletions docs/product/decisions/PDR-016-web-ux-a11y-overhaul-delivered.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
# PDR-016: Operator web UI UX + a11y overhaul hardened and delivered to main

Date: 2026-06-28 Status: accepted Author: agent (product checkpoint; a11y review + merge driven this session) Owner sign-off: EXPLICIT (owner supplied the two a11y review findings to evaluate, then directed "commit these and merge back to remote main … still as 1.2, we haven't published it yet")
Related: PDR-013 (operator web UI ratified as a standing bet — this hardens it, it is not a new bet), PDR-015 (the concurrent 1.2 line this rode in on), PDR-002 / PDR-012 (publication owner-gated — the held PyPI publish)

## Context

PDR-013 ratified the operator web UI as a standing product bet. Since then a **UX +
a11y overhaul** (commit `9f00ae0`: site-kit design-token adoption, contrast / focus-ring /
target-size fixes) and its design-review docs (`4c12d7f`) landed on the
`feat/lacuna-peer-facts-tour-cli-parity` branch carrying **no PDR**. PDR-015's checkpoint
flagged this explicitly as a decision-without-provenance gap and asked the next checkpoint
to record the overhaul with a rationale + reversal trigger. This checkpoint does that, and
folds in this session's a11y review-fix work and the delivery to `main`.

## Options considered

1. The two owner-supplied a11y review findings — **adversarially verify** before fixing vs
accept-as-given. Verified (CSS specificity math, WCAG contrast computation, the htmx
confirm-flow trace); both confirmed real, **0 false positives**.
2. Toast-dismiss fix scope — reorder within `review.html` (fixes the 3 review-page
confirm flows only) vs **move to `base.html`** (covers every page, including the
requirement dossier, which loads no page script of its own). Chose `base.html`.
3. Recording — **record the overhaul** as accepted hardening (close the PDR-015 gap) vs
leave it unrecorded.
4. Release posture — publish 1.2 now vs **hold**. Owner explicitly held publish.

## The call

- **Both a11y findings accepted and fixed** (`a15adb1`):
- *Visited primary anchors:* the global `a:visited` rule (specificity 0,1,1) outspecified
`.btn--primary` (0,1,0), flipping the "New requirement" link's text to `--link` on the
brass fill (~1.7:1 — a WCAG AA failure) once visited. Re-asserted `--text-on-accent` for
anchor primaries at higher specificity. Plain `<button>` primaries are unaffected (no
`:visited` state).
- *Stuck success toast:* the auto-dismiss timer lived inside `review.html`'s `.qi-actions`
focus guard, so the confirm-step queue flows (drifted-accept, reject, draft-approve) and
the requirement dossier left the toast on screen indefinitely. Moved the dismiss to
`base.html` so it fires on any page when `#toast` is filled; `review.html` keeps only its
focus management.
- **The operator web UI UX + a11y overhaul (`9f00ae0`) is recorded here as accepted
hardening of the PDR-013 bet** — not a new bet, no roadmap horizon change.
- **The whole branch merged to `origin/main` via PR #5** (owner-directed push): web overhaul
+ design-review docs + peer-facts CLI-parity checkpoint (PDR-015) + these a11y fixes. This
**resolves the standing "push `main`" escalation** carried since PDR-013.
- **1.2 stays unreleased.** No separate CHANGELOG entry for the a11y fixes (consistent with
the overhaul carrying none); CHANGELOG version/date finalization + the PyPI publish remain
owner-gated.

`make ci` green at merge: ruff + mypy `--strict`, **378 tests, 91.14% coverage**; CI gate
passed (37s).

## Rationale

The a11y fixes **restore a WCAG AA guardrail** (interactive-control contrast) on a ratified
human-facing surface — the no-silent-degradation discipline applied to the UI. Verifying the
findings before acting kept a plausible-but-wrong review from driving a change; the
discipline is the point even though both findings held. `base.html` for the toast is the
structurally complete fix. Recording the overhaul closes the PDR-015 provenance gap. The push
was outward-facing but **owner-directed in-session**, so it is authorized — explicitly
distinguished by the owner from publication, which was held.

## Reversal trigger

- If a future a11y audit (axe / WCAG AA) on the operator UI flags a new contrast / focus /
target-size failure, or the visited-link / toast-dismiss fixes regress under a later change,
reopen as a UI-hardening item (tie to the interactive-control-contrast guardrail in
`metrics.md`).
- The standing PDR-013 trigger still governs the bet itself: if the operator web UI attracts
no operator use within a window once real users exist, reopen as kill / shrink.
- Publication stays gated: reconsidering the held 1.2 publish is an owner call (PDR-002 /
PDR-012), not reversed here.
19 changes: 19 additions & 0 deletions docs/product/metrics.md
Original file line number Diff line number Diff line change
Expand Up @@ -160,3 +160,22 @@ covered→present, orphan→absent, identity-gap→`unavailable`-never-`absent`,
absent-`.wardline/`→`unavailable`-never-clean, out-of-scope→`indeterminate`-never-resolved).
No reversal trigger fired. (Out-of-scope item filed: a pre-existing wheel-build packaging bug
blocks `uv tool install` — observation `plainweave-obs-6a7255ffbe`.)

### 2026-06-28 — Operator web UI a11y hardening + 1.2 line delivered to main (PDR-016)

Hardening reading, NOT a north-star reading. Two operator-UI a11y review findings
(owner-supplied) were **adversarially verified, then fixed**: (1) visited primary anchors
regained `--text-on-accent` — the "New requirement" link was ~1.7:1 (a WCAG AA failure) once
visited, because the global `a:visited` rule (0,1,1) outspecified `.btn--primary` (0,1,0);
(2) the success toast now auto-dismisses on **every** page — the dismiss timer was gated
behind `review.html`'s `.qi-actions` handler, so the confirm-step queue flows and the
requirement dossier left it stuck. `make ci` green: **378 tests, 91.14% coverage** (unchanged
from PDR-015 — the changes are CSS / template / JS, no Python coverage delta); CI gate passed
(37s). The full `feat/lacuna-peer-facts-tour-cli-parity` line (web overhaul `9f00ae0` +
design-review docs + peer-facts CLI parity + these fixes) merged to **`origin/main`** via PR #5
— owner-directed (resolves the standing "push `main`" escalation).

Guardrails — all intact: web writes remain human-attributed; advisory, no release verdict; the
a11y fix *restores* a contrast guardrail rather than tripping one. No reversal trigger fired.
Publication held by owner ("we haven't published it yet") — the PyPI publish + the CHANGELOG
version/date finalization remain owner-gated.
10 changes: 9 additions & 1 deletion src/plainweave/service.py
Original file line number Diff line number Diff line change
Expand Up @@ -2485,7 +2485,15 @@ def _enrich_loomweave_trace(self, link: TraceLink) -> TraceLink:
if lookup is None:
return link
try:
current = self._loomweave_adapter().resolve_identity(lookup)
# Read-path enrichment is reached from tools that advertise
# ``local_only: True`` / ``live_peer_calls: False`` (trace_link_list,
# the requirement dossier, verification status). Resolve from the
# local Loomweave catalog ONLY — never the HTTP-capable
# ``resolve_identity`` — so the advertised authority boundary stays
# true even when a Loomweave endpoint is configured (RED-2,
# weft-d5091cba12). Write-time normalization (``_normalize_trace_refs``)
# is a separate, non-local_only path and keeps live resolution.
current = self._loomweave_adapter().resolve_identity_local(lookup)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve live accept results on mutation responses

This helper is also used by _transition_trace() after accept_trace_link(): that path deliberately calls the HTTP-capable _normalize_trace_refs(), writes the live Loomweave snapshot, and then returns _trace_from_row(). When WEFT_LOOMWEAVE_URL is configured but the local Loomweave catalog is missing or behind the remote SEI data, this local-only re-resolution replaces the freshly accepted response with freshness="unknown"/identity_unsupported (or stale) even though the row was just accepted with a current live snapshot; the CLI/web accept response can therefore report a degraded trace immediately after a successful live-resolution mutation.

Useful? React with 👍 / 👎.

except LoomweaveIdentityError as exc:
return self._trace_with_degraded_snapshot(link, exc)
snapshot = current.to_dict()
Expand Down
43 changes: 43 additions & 0 deletions tests/state/test_trace_links.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from tests.loomweave_test_utils import seed_loomweave_catalog

from plainweave.errors import ErrorCode, PlainweaveError
from plainweave.loomweave_adapter import LoomweaveAdapter
from plainweave.models import TraceRef
from plainweave.service import PlainweaveService
from plainweave.store import connect, migrate
Expand Down Expand Up @@ -256,3 +257,45 @@ def test_read_time_orphaned_loomweave_identity_returns_degraded_trace_without_de
assert any(item["code"] == "identity_orphaned" for item in returned.target_snapshot["degraded"])
with connect(service.db_path) as connection:
assert connection.execute("select count(*) from trace_links").fetchone()[0] == 1


def test_read_path_honors_local_only_boundary_when_loomweave_endpoint_configured(
tmp_path: Path, monkeypatch: pytest.MonkeyPatch
) -> None:
"""RED-2 (weft-d5091cba12): Plainweave's trace read tools advertise
``local_only: True`` / ``live_peer_calls: False``. With a Loomweave HTTP
endpoint CONFIGURED, the read-time enrich path (``trace_for`` ->
``_enrich_loomweave_trace``, which backs ``plainweave_trace_link_list`` and
the dossier) must resolve identity from the local catalog only and make NO
live peer call — otherwise the advertised boundary is a lie."""
service = service_for(tmp_path)
approved = approved_requirement_ref(service)
seed = seed_loomweave_catalog(tmp_path)
# Create the accepted link BEFORE an endpoint is configured: write-time
# normalization is a separate (non-local_only) path and is not what we test.
link = service.create_trace_link(
TraceRef("loomweave_entity", seed["public_locator"]),
"satisfies",
TraceRef("requirement_version", approved),
actor="human:john",
authority="accepted",
)

# Now a Loomweave HTTP endpoint IS configured, and ANY live peer call made
# from the read path must fail the test instead of reaching the wire.
monkeypatch.setenv("WEFT_LOOMWEAVE_URL", "http://127.0.0.1:9")

def fail_http(*_args: object, **_kwargs: object) -> dict[str, object]:
raise AssertionError("advertised local_only read path must not make a live peer call")

monkeypatch.setattr(LoomweaveAdapter, "_http_json", fail_http)
# Guard the guard: the endpoint really is configured, so a route to HTTP
# would happen if the read path used the HTTP-capable resolver.
assert LoomweaveAdapter(tmp_path).http_url == "http://127.0.0.1:9"

returned = service.trace_for()[0]

assert returned.id == link.id
assert returned.target_snapshot["sei"] == seed["public_sei"]
assert returned.target_snapshot["content_hash"] == "hash-public-v1"
assert returned.freshness == "current"
Loading
Loading