Skip to content

Release 1.2.0: federation consumers + project_status binding probe#3

Open
tachyon-beep wants to merge 37 commits into
mainfrom
release/1.2.0
Open

Release 1.2.0: federation consumers + project_status binding probe#3
tachyon-beep wants to merge 37 commits into
mainfrom
release/1.2.0

Conversation

@tachyon-beep

Copy link
Copy Markdown
Contributor

Release 1.2.0 line → main

Consolidates the release/1.2.0 branch (all local work is merged here) for review into main. 35 commits; package version 1.2.0.

Headline work

  • project_status read-only store-binding probe (warpline.project_status.v1) — this branch's newest addition. A read-only MCP tool (warpline_project_status_get / project_status) that reports whether THIS build can read and serve the snapshot store for a repo (data.binding_ok), reading schema_version from inside the store — never directory existence — so a stale-but-running warpline that can't read its .weft/warpline store at a compatible schema is caught (the loomweave-incident failure class). It is the first genuinely read-only tool (writes_local_state=false, mutates_paths=[]): an absent store reports absent without creating a DB, warpline.db is left byte-for-byte unchanged, and the not-bound cases (store_absent / store_unreadable / schema_ahead) all give binding_ok=false + schema_version=null.
  • Federation consumers (1.2.0 line): D1 impact_completeness self-assessment on reverify_worklist.v1; the Rung-2 wardline-attest-2 risk-as-verification consumer; and the capability-gated legis governance_read.v1 consumer wired into reverify --include_federation.

Lacuna harness handoff (project_status)

warpline wraps every tool in CORE_OUTPUT_SCHEMA, so the probe reads facts under data:

  • structuredContent.data.binding_ok — the verdict
  • structuredContent.data.store.schema_version — assert is not null (the non-tautological store-read signal)
  • data.resolved_root, data.store_status (ok|store_absent|store_unreadable|schema_ahead), warnings[0]

How it was verified

  • TDD + an adversarial multi-lens review (5 lenses → per-finding verification): zero contract violations; all 11 follow-up findings (MEDIUM/LOW/NIT) addressed, incl. an honesty-wording fix and 10 added regression-guard tests.
  • Gate green on the merge result: 506 passed / 1 skipped, mypy --strict clean, ruff clean, wardline scan . --fail-on ERROR exit 0.
  • The installed .mcp.json uv-tool binary was rebuilt and confirmed to expose + serve the new tool live (binding_ok=true, schema_version=4).

🤖 Generated with Claude Code

tachyon-beep and others added 30 commits June 24, 2026 21:02
Package fully renamed charter->plainweave. Updates live member-facing refs:
the federation value-add audit (incl. plainweave_* tool names), consumer
tickets, vision authority split, federation.md, README/index, the
advisory-not-gating concept, PRD-0001, metrics guardrail, and the sibling-import
guard (FORBIDDEN_IMPORT_ROOTS) + consumer-ticket test. Leaves generic 'on-charter',
the draft-charter skill, historical plan docs, and the evidence-entangled sibling
guards (member-diff path + source-grounding) untouched -- those need a baseline
refresh / re-grounding against the real plainweave repo, tracked separately.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…cessor

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Revert the always-on top-version verification guard added to _run_migrations
(and its _top_version_objects_present helper + _TOP_VERSION_OBJECTS_VERSION
constant) as out-of-scope migration-runner hardening. The in-scope v4 block in
_schema_presence_floor is retained. Rewrite test_presence_floor_recovers_dropped_table
to exercise the real user_version==0 reconcile path (meta claims v4, table dropped,
v2/v3 intact -> floor to v3, re-run v4), mirroring the established v3-style test.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ndetermined branch

Fix module docstring purity claim to list all three imports
(collections.abc + typing + warpline.listing.reason).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
… code

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Extends test_stale_first_is_secondary_to_an_explicit_sort with a third
entity Z (depth=0, stale) alongside X (depth=0, fresh) and Y (depth=1,
stale). The new assertion (c) verifies that within the same depth bucket
the stale item precedes the fresh one — the gap left unexercised by the
previous two-item layout.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Also relax dogfood real-member parity check from strict path equality to
subset check (warpline_paths ⊆ baseline_paths): warpline only tracks code
entities, not Makefile/README/docs, so the strict == was a false failure
when the selected lacuna commit happened to touch non-entity files.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…+ error symmetry)

Fix 1 (latent crash): list_change_events_for_key_ids built IN-clause
placeholders from raw key_ids but bound sorted(set(key_ids)), raising
sqlite3.ProgrammingError on any duplicate key_id. Derive both from
unique_ids = sorted(set(key_ids)). Regression test added (RED→GREEN).

Fix 2 (doc): _schema_presence_floor docstring referenced v(N>3); after
the v4 migration it should read v(N>4).

Fix 3 (truth-table): lock the precedence that a mixed covers() result on
the latest change (one event None, another True) yields fresh — a positive
cover wins once any True exists.

Fix 4 (error symmetry): empty/blank commit in verify_record now raises
MissingRequiredFieldError(rejected_field="commit") rather than flowing
through resolve_commit("") → BadRevisionError. Present-but-unresolvable
refs still raise BadRevisionError. Test added (RED→GREEN); existing
bad-ref test confirmed GREEN.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… order

Replace _latest_covering_event (picks by verified_at recency) with
_tightest_covering_event (picks the covering event minimising commits_between
to latest_change). When gate records arrive out of git-ancestry order the
old helper overstated commits_behind; the new one always reflects the
most-advanced proof on record. State classification, reason triples, and
fresh/unverified/unavailable paths are unchanged.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…apture

The `client is None` branch of `capture_edge_snapshot` unconditionally
UPSERTed completeness=SKIPPED and DELETEd edges for the (repo, commit,
loomweave) key across two non-atomic commits. For a commit that already
held a FULL/DELTA row this downgraded a real edge graph to a 0-edge
SKIPPED row — the R3 data-loss class the atomic capture path prevents,
but which the absent-client case never reached (warpline-d7d04243b2).

Fix (the ticket's preferred, enrich-only/fail-closed option):
- store: add get_edge_snapshot(repo_id, commit_sha, source) — exact-key
  lookup (latest_snapshot is repo-latest-by-id, the wrong key).
- snapshot: when a prior FULL/DELTA exists, preserve it untouched and
  return recapture_skipped=True against it (regardless of staleness — a
  stale FULL is still a real graph; the read path downgrades stale
  completeness itself). With no usable prior, write SKIPPED via the
  single-transaction capture_snapshot_atomic(edges=[]), retiring the old
  two-commit UPSERT+DELETE write.
- commands: append a PRESERVED warning. The envelope is then the honest
  triple — completeness=FULL/DELTA (real graph) + sei=unavailable (peer
  down) + warning (not refreshed) — mirroring the if_stale_after
  short-circuit (edges=0, entities=0, already_current).

test_gv_lw_3 realized "loomweave absent -> SKIPPED" as a recapture at
the SAME commit holding the FULL, i.e. it asserted the downgrade —
contradicting GV-LW-6 (preserve prior, never a degraded/0-edge row). The
frozen manifest assert text never said "absent at a commit holding a
FULL", so it stays literally true; only the test's incidental same-commit
realization moves to a no-prior commit (c2). Manifest JSON untouched; the
vector set stays frozen at 19. The preserve invariant is locked by GV-LW-6
plus new unit/CLI tests (full-preserve, delta-preserve, no-prior-atomic,
and a CLI PRESERVED-warning test); the old test that pinned the bug is
inverted, and present-client edge-replace stays covered by
test_capture_snapshot_atomic_replaces_edges.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… + ENVELOPE_KEYS

build_envelope always emits the top-level enrichment_reasons key
(envelope.py:97), but the static contract fixtures and ENVELOPE_KEYS
omitted it, and _assert_frozen_envelope's subset check (ENVELOPE_KEYS
<= set(fixture)) silently tolerated the absence — so the static
reference envelopes no longer matched the runtime the hub consumes.

- Add enrichment_reasons to ENVELOPE_KEYS.
- Add the faithful runtime block to both mcp-response fixtures: the
  reserved-but-honest requirements 'disabled' triple on both, plus the
  sei 'clean' triple on changed (its enrichment.sei is 'present', and
  change_list attaches sei_reason); reverify carries requirements only
  (it passes no enrichment_reasons to build_envelope).
- Assert the block in _assert_frozen_envelope, mirroring build_envelope's
  contract (envelope.py:78-88) + reason() (listing.py:43): every dimension
  in the closed vocab, every value a canonical reason_class, non-clean
  carries cause+fix, and requirements is universally 'disabled'.

Test-only hygiene; no src change. Closes warpline-fc09bdeddd.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ueError)

listing.reason() enforced its carrier rule (class-membership, and every
non-clean carrier MUST carry both cause and fix) with bare asserts, which
python -O strips. build_envelope only re-checked reason_class membership,
not cause/fix. So under -O a hollow {reason_class: 'disabled'} triple with
no cause/fix would pass validation and ship -- the exact 'unexplained
absence' the honesty doctrine forbids.

- listing.py: promote both reason() asserts to raised ValueError (keep the
  clean short-circuit). Closes the helper-built-triple hole.
- envelope.py: build_envelope now rejects a non-clean enrichment_reasons
  triple missing cause/fix (clean exempt). Closes the parallel
  hand-built-via-kwarg hole, which bypassed reason() even without -O.
- _enrichment.py: sei_reason() is non-Optional -- raises ValueError on an
  out-of-vocab state instead of returning None.
- commands.py: delete the four now-dead 'assert sei_triple is not None'
  narrowing guards (also -O-strippable); sei_reason's non-Optional return
  makes them redundant. Param kept as str (not Literal) to avoid mypy
  [arg-type] churn at the call sites.

Tests: flip the reason() AssertionError expectations to ValueError; rewrite
the sei_reason None test to expect ValueError; add coverage that
build_envelope rejects a hollow non-clean triple via the enrichment_reasons=
kwarg.

Internal hardening; frozen warpline.<contract>.v1 envelope and the closed
enrichment vocab unchanged. Verified: full suite green (5 known pre-existing
env failures only), python -O proof passes on all paths, mypy unchanged
(1 pre-existing no-any-return), ruff clean. Closes warpline-d88e223731.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…→Plainweave refs

Adds/normalizes the 'not-for-X' Banner naming this member's specific misuse (deconfliction-first, not security/compliance); fixes hardcoded Charter→Plainweave prose. Re-vendored kit; build green.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…econcile workspace to plan/verification-freshness

Execution-only session on the PDR-0006 deferred follow-ups; no product bet
decided/killed/reprioritized, so no new PDR. current-state.md reconciled from the
stale 2026-06-24 (main @ v1.2.0) brief to present reality: branch
plan/verification-freshness, verification-freshness BUILT-but-unreleased (Track B in
CHANGELOG [Unreleased]; reconciliation-debt flag for its missing acceptance PDR), and
the follow-up tracker state. metrics.md gains a 2026-06-26 quality-debt-burndown
reading (honesty guardrail strengthened: weft-reason invariant survives python -O); no
reversal trigger crossed. roadmap.md/vision.md untouched (no horizon or strategy change).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…worklist.v1

Add an honest completeness+staleness self-assessment to
warpline.reverify_worklist.v1 so wardline (and downstream consumers) can tell a
narrowed/partial impact scope from an authoritative one, instead of treating any
worklist as proven-good.

- New additive data.impact_completeness OBJECT carrying BOTH axes in one place:
  staleness (as_of producer timestamp + graph_fresh + graph_ref) and completeness
  (status: complete|partial|unknown + depth_capped + unresolved_count + reasons[]).
  status="complete" ONLY when the impact set is genuinely exhaustive (positively
  fresh FULL graph, no depth cap, zero unresolved); any gap -> partial; no graph
  -> unknown. Never complete on a guess. wardline mirrors this object verbatim
  into producer_completeness.
- The FROZEN raw-snapshot data.completeness STRING enum is unchanged (raw signal
  vs. derived assessment); additive on .v1, no v2 bump.
- New depth_capped signal in blast_radius: a node at the depth horizon with an
  out-edge to an unseen target means the traversal truncated reachable impact.
- Publish the drift-checkable contract at contracts/reverify_worklist.v1.schema.json
  (JSON Schema draft 2020-12); validates real worklist output and rejects malformed
  payloads (bad status/reason, completeness-as-object, missing entity.{locator,sei},
  malformed as_of via an RFC3339 pattern since format is annotation-only).
- Consumer-side risk-as-verification gate (completeness_risk): an absent or
  non-complete assessment degrades to risk=unavailable with an explicit reason
  (completeness_not_declared / completeness_partial); never clean.

Coordination with wardline (deviations from the original D1 prompt, both from
mid-flight reconciliation): the field is data.impact_completeness (data.completeness
was already frozen as a string); data.generated_at is NOT emitted (it never existed)
- the producer timestamp is folded into impact_completeness.as_of so one object
declares completeness AND staleness.

End-to-end verified through the real MCP handler and CLI surfaces (not just the
internal command), confirming no response projection strips the field. jsonschema
added as a dev-only dep (runtime deps stay empty).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…tion)

Close the verification_source_absent gap D1 left open: warpline can now read a
change as proven-good, sourced from wardline's attestation rather than minting a
clean verdict of its own.

- New pure consumer _attest.worklist_risk: layered on D1's completeness gate, a
  COMPLETE worklist whose every affected entity is attested clean at its CURRENT
  body reads risk="proven" (reason_code attested_clean). Mechanical (commit,
  content_hash) equality per SEI against the wardline-attest-2 boundaries
  (verdict=="clean", not dirty, commit pins). All-or-nothing.
- Echo of wardline's authority, NOT a warpline clean: the HMAC signature is not
  verified by warpline (it does not hold the shared key), so every proven verdict
  carries authority="wardline" + signature_verified=false + the mechanical basis.
- Honesty edges all degrade to unavailable with an explicit machine reason: no
  bundle (verification_source_absent), non-attest-2 schema, dirty tree, null /
  mismatched commit, sei_source unavailable, null sei/content_hash, non-clean
  verdict, any unmatched affected entity (attestation_incomplete).
- loomweave.resolve_content_hash_for_locator: the entity-body content_hash from
  the SAME entity_resolve round trip warpline already makes for the SEI. Verified
  byte-identical to wardline's bundle value across loomweave's MCP entity_resolve
  and HTTP /api/v1/identity/sei surfaces (the empirical make-or-break: without
  hash parity the seam would be a dead match-nothing path).

Verified end-to-end against live loomweave: a complete worklist + a matching
attest-2 bundle reads proven-good; a content_hash drift degrades to
attestation_incomplete.

Scope note: the consumer logic + loomweave hash retrieval are implemented and
tested. A CLI/MCP entrypoint that ingests a pushed --attest-bundle and a
worklist-level wiring are the next increment. Env caveats: the installed wardline
CLI emits wardline-attest-1 (the consumer correctly rejects non-attest-2), and
warpline's own boundary-free source cannot itself produce a populated bundle.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Close the verification_source_absent gap in ACTUAL OPERATION, not just as a pure
function: warpline reverify now ingests a pushed wardline-attest-2 bundle and
emits its risk-as-verification posture on every worklist.

- `warpline reverify --attest-bundle <file>` (CLI) and the `attest_bundle` MCP
  arg (advertised + consumed) read the PUSHED, UNTRUSTED bundle JSON and pass it
  to reverify_worklist.
- data.risk_verification is now emitted on EVERY worklist (additive .v1): with no
  bundle a complete worklist honestly reads verification_source_absent; with a
  matching bundle whose every affected entity is attested clean at its current
  body it reads proven-good (echo of wardline, HMAC unverified).
- The per-SEI current content_hash is sourced from the SAME loomweave
  entity_resolve round trip warpline already makes for the SEI
  (_attest_content_hashes; fail-soft + read-only — an unreachable loomweave
  yields no hashes, so entities are honestly unmatched, never faked-good). Only
  paid when a bundle is supplied.
- The verdict describes the FULL filtered+sorted worklist (pre-page, like
  verification_summary), deduped/order-preserving across affected SEIs.
- contracts/reverify_worklist.v1.schema.json documents risk_verification
  (optional/lenient — wardline's vendored fixtures needn't carry warpline's
  consumer-side posture). Contract fixture + golden envelope updated.

Verified through the real CLI binary and the MCP handler: a pushed --attest-bundle
moves a complete worklist's verdict off verification_source_absent (consumed), and
the live demo confirms proven-good for an entity loomweave can resolve.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…he page

The risk-as-verification content_hash lookup built its sei->locator map from the
post-apply_page `items`, but affected_seis (and the all-or-nothing proven check)
spans the FULL pre-page set. So any worklist larger than `limit` (default 100), or
trimmed by overflow, could NEVER read proven-good even when the bundle attested
every affected entity — the off-page entities had no locator, hence no
content_hash, hence attestation_incomplete.

Capture the sei->locator map at the same pre-page point as affected_seis and pass
it to _attest_content_hashes. New regression test drives proven through the full
reverify_worklist + build_envelope path with TWO entities at limit=1 (one off
page 1) and asserts matched==affected==2 — which also confirms the wardline-clean
carrier riding inside data.risk_verification leaves the honesty invariant intact.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…erify

Lights up the previously-inert `legis` federation member. `reverify
--include_federation` now consults legis's authoritative governance_read.v1
(verified clearances only — operator override / cleared sign-off) via a real
LegisGovernanceClient over `legis governance-read <SEI> --json`, mirroring the
WardlineDossierClient CLI idiom. The contract is mirrored as the source of truth
at contracts/governance_read.v1.schema.json (legis OWNS it).

Trust boundary held: warpline ECHOES governance advisorily and never gates
(GV-LG-1 — no governance_verdict in output; an adversarial test pins that the
clearance does NOT move verification_summary / risk_verification /
impact_completeness / item order). The clearance content_hash is echoed verbatim,
NOT re-derived against the current body — governance is an echo, not a verdict
(contrast the attest-2 risk-as-verification path).

Honesty: an empty read is `governance: absent` = "no verified clearance," which
deliberately conflates ungoverned, unknown-SEI, and an entity actively BLOCKED
awaiting sign-off — so `absent` is never "ungoverned" (disclosed in the schema
description + the federation reference docs). Wiring is CAPABILITY-GATED: the
client is wired only when the installed legis advertises `governance-read`, so an
unshipped read surface stays honestly `disabled` (capability absent) rather than
a forced `unreachable`, and lights up automatically once legis ships the verb.
The stale disabled `fix`/blocker text (which recruited "wire a LegisClient" —
now done) is updated to recruit installing/upgrading legis.

The governance_read.v1 schema vectors are the contract's canonical samples, not a
live capture: at time of writing the installed legis exposes no governance-read
verb yet. 477 passed, 1 skipped; ruff + mypy clean on changed files.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…reverify

The handler's True-branch (available()=True -> records -> governance: present) was
only exercised through commands.reverify_worklist; this drives it end-to-end
through the MCP handler so the 3-line capability-gated construction has direct
coverage. filigree/wardline degrade independently here — governance is unaffected.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
tachyon-beep and others added 5 commits June 27, 2026 13:07
…iminated union)

legis tightened the contract since the first hand-off: the schema now enforces
the status<->shape discriminated union via allOf — status 'unavailable' REQUIRES
a non-empty `unavailable` reasons array and empty `records` (maxItems:0); status
'checked' MUST NOT carry the `unavailable` key. Plus minItems:1 on reasons and
minLength:1 on each reason string. Backward-compatible (legis never emitted the
now-rejected shapes), so warpline's consumer built against the looser draft is
not broken.

Re-mirrored BYTE-FOR-BYTE from legis's canonical (diff -q == identical) so the
mirror stays a true mirror with no drift. Added consumer-side rejection tests
pinning every arm of the union (checked-carrying-unavailable, unavailable-missing-
reasons, empty reasons, blank reason string, unavailable-carrying-records) so
warpline validates with exactly the tightness legis emits — an 'unavailable' can
never masquerade as a clean empty 'checked'.

483 passed, 1 skipped; ruff + mypy clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…d CLI (drop --json)

Verified warpline against legis's now-shipped adapters (legis commits a98d147
CLI / 4464c18 HTTP / 031606f MCP). One interface drift found and fixed:

legis's CLI is `legis governance-read <SEI>` with output ALWAYS JSON — there is
no `--json` flag (legis src/legis/cli.py:117-125). warpline was passing `--json`
(carried over from the first hand-off, which legis later dropped), which is an
argparse error -> nonzero exit -> the read would have degraded to `unreachable`
forever, even once legis is installed. Removed the flag; pinned the exact argv
(`["legis","governance-read",<sei>]`, no `--json`) with a regression test so the
invocation form can't drift back out of sync.

Everything else is in sync:
- schema: warpline's mirror is BYTE-IDENTICAL to legis's canonical (diff -q).
- shape: legis's REAL conformance golden envelope validates against warpline's
  mirror AND round-trips through the consumer parse path. Vendored that golden
  vector (legis-governance-read.golden.json) as a durable interface-agreement
  guard that fails loud if the emitted/consumed shapes ever diverge.

Still capability-gated: the INSTALLED legis binary is behind source (no
governance-read verb yet), so warpline stays honestly `disabled` until it lands,
then auto-wires. 485 passed, 1 skipped; ruff + mypy clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add `warpline_project_status_get` / `project_status`
(`warpline.project_status.v1`), a read-only store-binding/health probe for the
Weft federation's Lacuna MCP-attachment harness. It reports whether THIS build
can read and serve the snapshot store for a given repo (`data.binding_ok`),
reading `schema_version` FROM INSIDE the store — never mere directory existence —
so a stale-but-running warpline that cannot read its `.weft/warpline` store at a
compatible schema is caught (the loomweave-incident failure class).

It is the first GENUINELY read-only tool: `writes_local_state=false`,
`mutates_paths=[]`. It creates/migrates no snapshot state (an absent store reports
absent — `store_absent` + a capture next-action — without creating a DB), leaves
`warpline.db` byte-for-byte unchanged, and never reaches `WarplineStore.open`'s
mkdir/migrate path. A corrupt store is `store_unreadable`; a store written by a
newer build is `schema_ahead` (all not-bound cases: `binding_ok=false`,
`schema_version=null`). The store is read strictly read-only via `mode=ro`
(chosen over `immutable=1` so the probe always reads the latest committed schema
version; opening a present WAL store may spawn gitignored `-wal`/`-shm`
coordination sidecars, which are not snapshot state).

- store.py: `read_store_binding` read-only reader, `StoreBinding`, shared
  `store_repo_id`, closed `STORE_STATUS_VOCAB`.
- commands.py: `project_status` command (CORE envelope; binding facts under
  `data`), fail-closed vocab guard.
- mcp.py: tool spec + handler + honesty-invariant registrations
  (`_HANDLER_CONSUMES` / `_KNOWN_FASTFOLLOW_DEAD`); `assert_inputschema_consumed`
  stays green.
- mcp_smoke.py: structural binding-probe check.
- Generalized the live tools/list metadata assertion to honestly allow a
  read-only tool (mutates_paths==[]); declared the read-only probe's intentional
  exclusion from the frozen six-tool federation-data-contract inventory.

Tests-first (TDD) + an adversarial multi-lens review (zero contract violations);
21 tests in tests/test_project_status.py pin the three required cases, both arms
of the schema-ahead `max(meta, user_version)` floor, empty-but-serveable and
below-HIGHEST serveability, durable-DB immutability under probing, and repo-scoped
counts. Gate: 506 passed / mypy --strict clean / ruff clean /
`wardline scan --fail-on ERROR` exit 0.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Cut the 1.2.0 release line: D1 impact-completeness, the Rung-2 wardline-attest-2
and legis governance_read.v1 federation consumers, and the read-only
project_status store-binding probe. Gate green on the merge result.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: def6d43cfc

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/warpline/commands.py
for it in items:
entity = it.get("entity", {})
sei = entity.get("sei")
if isinstance(sei, str) and sei and sei not in _seen_seis:

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Treat unkeyed worklist entities as unattested

When a complete worklist contains an affected item whose entity.sei is null, this condition simply skips it, so affected_seis can be empty and worklist_risk() will return risk: "proven" for an empty attest bundle (matched: 0, affected: 0). In repos where SEI resolution was unavailable or an entity has only a locator, that falsely marks a real affected entity as attested instead of degrading to attestation_incomplete; unkeyed affected entities need to be counted as unmatched/blocking for the all-or-nothing verdict.

Useful? React with 👍 / 👎.

Comment thread src/warpline/commands.py
affected_seis: list[str] = []
affected_sei_locators: dict[str, str] = {}
_seen_seis: set[str] = set()
for it in items:

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 Build attestation scope before list filters

This loop derives the all-or-nothing attestation set from items after apply_filters() has already narrowed the list, so a caller can pass a filter such as path_prefix that hides an unattested affected entity and still get risk: "proven" for the remaining subset. Because risk_verification is reported as the change/worklist-level verdict rather than a filtered-view verdict, its scope should be based on the full pre-filter affected set (as already done for pagination) so filters cannot turn a partial attestation into a proven one.

Useful? React with 👍 / 👎.

Comment thread src/warpline/store.py
FROM change_events ce
WHERE ce.repo_id = ?
AND ce.entity_key_id IN ({placeholders})
ORDER BY COALESCE(datetime(ce.changed_at), ce.changed_at), ce.id

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 Order verification changes by commit topology

For entities with multiple changes whose author timestamps are not topologically ordered (common after rebases/amends or hand-set GIT_AUTHOR_DATE), this changed_at ordering can put a descendant change before its parent, while compose_verification_freshness() treats entity_change_commits[-1] as the latest change. In that case a verification recorded at the older commit is reported fresh even though a later descendant change exists; the freshness path needs to determine latest by commit ancestry/commit order rather than author-time ordering.

Useful? React with 👍 / 👎.

Comment thread src/warpline/_attest.py
return {
"schema": bundle.get("schema"),
"commit": payload.get("commit"),
"dirty": bool(payload.get("dirty")),

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 Fail closed when attestation dirty flag is absent

When a supplied wardline-attest-2 payload omits dirty or sets it to null, bool(payload.get("dirty")) normalizes that unknown state to False, so a bundle with no clean-tree pinning signal can pass the bundle-level checks and return risk: "proven" if the boundaries match. Since the dirty flag is the guard that makes the attested commit truthfully pin the source, absence of that field should degrade instead of being treated as clean.

Useful? React with 👍 / 👎.

"required": ["risk", "reason_code", "reason"],
"properties": {
"risk": { "enum": ["proven", "unavailable"] },
"reason_code": { "type": "string" },

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 Constrain risk verification reason codes in schema

The contract description names a closed machine-code vocabulary for risk_verification.reason_code, but the schema accepts any string here, so a typo or producer drift in this new federation field still validates and can reach consumers that switch on those codes. Please encode the same enum used by the producer/tests in the schema so the published contract catches invalid risk-verification states.

Useful? React with 👍 / 👎.

"additionalProperties": true,
"required": [
"completeness",
"impact_completeness",

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 Keep new completeness field optional in v1 schema

Adding impact_completeness to the required list makes the published warpline.reverify_worklist.v1 schema reject pre-D1 v1 worklists, even though the schema description says v1 changes are additive and the consumer path explicitly degrades a missing field to completeness_not_declared. If wardline or another consumer validates pushed v1 payloads before applying that degradation logic, old-but-valid producers now fail validation instead of being handled honestly; leave this field optional in v1 or bump the schema version for the breaking requirement.

Useful? React with 👍 / 👎.

Comment on lines +199 to +201
records = payload.get("records", [])
if not isinstance(records, list):
return []

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 Reject malformed governance-read records

When legis returns status: "checked" but omits records or returns a non-array, this defaults to [] and the federation consult reports a clean, earned-empty governance result. Because governance_read.v1 requires records to be an array, a malformed or truncated response should become LegisGovernanceUnavailable/unreachable; otherwise transport or producer drift is silently converted into governance=absent.

Useful? React with 👍 / 👎.

tachyon-beep and others added 2 commits June 28, 2026 16:57
…rch-analysis reports

Source/test fixes (PDR-0023 honesty + list-ergonomics lineage):

- _attest.py: fail closed on an EMPTY/unkeyed affected set — a complete worklist
  with no SEI-keyed entity (e.g. an install/backfill run while loomweave was
  unavailable) is `attestation_unkeyed`, never a vacuous proven verdict on the
  satisfied-because-empty all-or-nothing loop.
- commands.py (change_list): rebuild the reverify/blast follow-up SEEDS
  (data.changed_refs + next_action arguments) from the FILTERED set, so a
  path_prefix/actor/since filter narrows the advertised next-action scope too —
  not just the visible items.
- commands.py (capture_snapshot): idempotency reflects whether THIS capture was
  skipped/reused (`recapture_skipped`), not whether ANY prior snapshot existed —
  a new row for a different commit is `created`, only the loomweave-absent
  preserve path is honestly `already_current`.
- listing.py (apply_page): reject a non-positive `limit` loudly (else an empty
  window with a self-referential next_cursor loops a cursor-following client) —
  honor the advertised knob or reject it, like every other numeric bound.
- tests: cover each of the above (test_attest, test_honesty_invariant,
  test_list_ergonomics) + a lint cleanup in test_snapshots.

Docs: architecture-analysis reports (00–06) under
docs/arch-analysis-2026-06-28-0728/. The `temp/` scratch subdir is intentionally
left out of version control (it carries developer absolute paths the
test_public_docs_hygiene gate forbids).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The scratch subdir from the 2026-06-28 architecture analysis: the technical-debt
catalog and the two validation catalogs. The lone developer absolute path in
debt-catalog.md (`/home/john/warpline/src/warpline/`) is rewritten repo-relative
(`src/warpline/`) so the test_public_docs_hygiene gate stays green.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 5ef2472f48

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +134 to +139
exhaustive = (
completeness == "FULL"
and graph_fresh
and not depth_capped
and unresolved_count == 0
)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Require unscoped FULL before proving impact complete

When a worklist is backed by a scoped snapshot, this can promote the raw FULL marker to impact_completeness.status == "complete" even though the graph is not exhaustive: capture_edge_snapshot(..., scope_locators=...) only queries the scoped entities and still writes completeness = "FULL" when there are no failures, and reverify's lazy capture passes scoped seed locators for cold stores. In that cold/scoped path an attest bundle can then make risk_verification.risk read proven while downstream entities outside the scoped capture were never considered; carry an unscoped-full signal or mark scoped captures partial before allowing complete.

Useful? React with 👍 / 👎.

Comment on lines +199 to +202
records = payload.get("records", [])
if not isinstance(records, list):
return []
return [r for r in records if isinstance(r, dict)]

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 Reject governance records for a different SEI

If legis governance-read returns a checked envelope for a different top-level sei, or records whose sei does not match the requested one, this returns those records and _consult_legis attaches them to the current locator. In a misrouted or stale producer response, that makes an entity show governance present based on another entity's clearance; fail closed unless the envelope and each returned record are keyed to the requested sei.

Useful? React with 👍 / 👎.

Comment thread src/warpline/commands.py
Comment on lines +1423 to +1426
"verified_at": verified_at,
"actor": actor,
"source": "warpline",
"idempotency": "recorded" if inserted else "already_recorded",

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 Return stored metadata for idempotent verification records

When the same (repo, commit, kind) is recorded again with a different actor or at a later now, the insert is ignored by the unique key but this response is still built from the replayed arguments. The caller receives idempotency: "already_recorded" alongside a verified_at/actor that were never persisted, so audit/logging clients can believe the gate pass happened at the wrong time or by the wrong actor; fetch and report the existing row on idempotent replays.

Useful? React with 👍 / 👎.

Comment thread src/warpline/store.py
Comment on lines +357 to +358
on_disk = max(int(meta_row["value"]), user_version)
if on_disk > HIGHEST_KNOWN_VERSION:

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 Verify schema objects before reporting binding ok

For a store whose markers claim schema v4 but whose verification_events table is missing (for example after a failed or foreign migration), this trusts the marker as long as it is not ahead of the binary and later returns binding_ok: true because the probe only queries change_events and edge_snapshots. Since reverify and verify-record now require verification_events, project_status can say this build can serve a store that will fail on the new verification paths; use the existing schema-object floor/table checks before returning ok.

Useful? React with 👍 / 👎.

Comment thread src/warpline/_attest.py
if isinstance(b, dict):
sei = b.get("sei")
if isinstance(sei, str) and sei:
by_sei[sei] = b

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 Reject duplicate attestation boundaries

Because this map silently overwrites earlier boundaries with the same SEI, a pushed attest bundle can include a non-clean or stale boundary for an affected entity followed by a clean, body-matching duplicate and still get risk: "proven". Since the bundle is explicitly untrusted and its signature is not verified here, duplicate SEI boundaries should fail closed (or require every duplicate to match cleanly) instead of letting array order mask a defect.

Useful? React with 👍 / 👎.

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