Release 1.3.0 — federation read surfaces (governance_read.v1 + Plainweave) + the 1.3.0 line#21
Release 1.3.0 — federation read surfaces (governance_read.v1 + Plainweave) + the 1.3.0 line#21tachyon-beep wants to merge 34 commits into
Conversation
read_floor() now gates on verify_integrity() before returning the floor, so a raw-DB-written/forged tail record that breaks the keyless hash chain can no longer silently set the routing floor (it maps to the fail-closed structured default). Cryptographic operator_sig verification stays the operator-side doctor check (KEY_RESET-acknowledgment path only); a recomputed-chain forgery remains the conceded raw-file-write residual (README.md:137). Retires test_read_floor_uses_tail_read's 'must not call read_all' premise (the integrity gate supersedes it) and corrects the now-false module docstring. Closes the load-bearing half of legis-476ab6f125 (PRD-0005 criterion 1). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
read_floor's keyless integrity gate cannot detect a file-write attacker who recomputes the keyless chain; on a non-rekeyed ledger that is caught by neither the hot read nor doctor (doctor's operator_sig check is the KEY_RESET-ack path only). It is the conceded raw-file-write residual (README.md:137). This characterization test makes the limit visible in the suite so it is never implied-closed. 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>
A protected record appended inside a batch defers its HeadAnchor advance (the mid-batch head read is forbidden, Q-M5) and, unlike SignoffGate, had no transaction owner to re-advance it after commit — so a batched protected append could leave the anchor at the pre-batch head and a later tail-truncation would go undetected. Add ProtectedGate.transaction(), a verbatim mirror of SignoffGate.transaction(), as that owner. Closes legis-0c310712a7 (PRD-0005 criterion 2). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
A protected append inside a raw store.transaction() (bypassing gate.transaction()) leaves the anchor stale — the supported safe path is gate.transaction(). This characterization test makes the parity limit visible so it is never implied-closed. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Final-review cleanups (M1 unused Verdict import; M2 rank-5 comment landed inside the _truncate_to docstring). No logic change. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…r injectable invoke seam Rewrites the warpline preflight client from an HTTP layer to a lightweight MCP-envelope consumer. Deletes HttpWarplineClient and all urllib/http.client/ ipaddress helpers; adds WarplineMcpClient with an injectable Invoke seam for offline testing. Validates schema, ok, meta (isinstance guard closes GV-LG-3 non-dict escape), local_only, peer_side_effects, and data.completeness — every contract fault fails closed to WarplineError. Envelope is passed through verbatim (bare-object MCP output schema makes pass-through lossless). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Adds StdioMcpInvoke — the production Invoke: a one-shot stdio JSON-RPC call to warpline-mcp. shell=False + list argv; text=False byte-bounded stdout; empty-argv rejected; entire post-spawn parse wrapped so every fault (spawn, timeout, non-JSON, scalar result, isError, oversize) → WarplineError (fail closed). Adds _read_jsonrpc_result for line-by-line id-matched response scanning. Adds test_stdio_invoke.py (11 tests: fake server round-trip, live transcript replay DoD gate, 5 fault parametrize, missing binary, empty argv, timeout, oversize). Live-capture gate (warpline-mcp 1.2.0): exits on stdin-EOF (rc=0), no interleaved I/O required, protocolVersion 2025-03-26, structuredContent dict returned — subprocess.run one-shot confirmed safe. notifications/initialized → id:null error, correctly ignored (id != 2). Fixture warpline-mcp-live-session.jsonl is the verbatim 3-line capture. Concern flagged (not fixed): warpline_impact_radius_get requires a "repo" arg that WarplineMcpClient._call does not yet supply. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… fix cross-task import breaks Replace WARPLINE_API_URL/HttpWarplineClient with WARPLINE_MCP_CMD/WarplineMcpClient in build_runtime; supply repo=str(project_root()) from the established cwd-anchored resolver. Add required repo: str param to WarplineMcpClient.__init__ and thread it into _call arguments (live capture proved warpline_impact_radius_get/-reverify_worklist_get require "repo"; without it JSON-RPC -32602 kills the seam). Update all 9 test_client.py construction sites to pass repo="/tmp/r" and tighten the argument-shape assertion. Fix the three test_server.py tests that referenced the deleted HttpWarplineClient and WARPLINE_API_URL. After this commit: mypy src/legis is clean, pytest collects 1285 tests with only test_warpline_preflight_oracle.py failing (Task 4's scope). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ular oracle; reverse producer obligation Replace the hand-rolled flat golden with real warpline.impact_radius.v1 / warpline.reverify_worklist.v1 envelopes live-captured from warpline-mcp 1.2.0 (legis repo, HEAD~1..HEAD, 2026-06-27). Add machine-readable provenance marker (_provenance.source = "live-captured") with a CI-visible test that fails if "pending-live-capture" is committed without the escape env var. Rewrite the oracle: deleted HttpWarplineClient/_decode_json_response imports removed; all assertions now flow the golden through WarplineMcpClient._call (schema/ok/meta/completeness validation is real), asserting HARDCODED literals (schema=="warpline.impact_radius.v1", completeness=="NO_SNAPSHOT", affected==[], meta.local_only==True, etc.) — never a re-parse of the golden. Layer-2 recheck repointed from the obsolete REST path to the MCP contract fixture path. PROVENANCE.md: delete the "WARPLINE PRODUCER-SIDE OBLIGATION" block; record legis as consumer of warpline's extant envelope per SEAM 4 §4A + GV-LG-3. Re-pin GOLDEN_BLOB_SHA = 777b858. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…shaped envelopes + GV-LG-3 positive test
Replace all flat {affected/entries, count} warpline fakes with envelopes carrying
schema/ok/data.completeness/meta so the advisory payload (hostile values in
data.affected/data.items), not a contract violation, is what's proven inert.
test_warpline_advisory_boundary.py:
- _HostileWarpline now returns real-shaped envelopes with GV-LG-3-valid meta
(local_only:true, peer_side_effects:[]) and hostile advisory payload (SEI="EVERYTHING").
- Add guard in byte-identity test: assert hostile side reached status=="checked"
(side assertion, outside the compared blobs) so vacuous unavailable==unavailable
cannot silently pass the test.
- Add test_gv_lg_3_invalid_meta_peer_side_effects_yields_unavailable: routes
through WarplineMcpClient with peer_side_effects=["some-peer"] and asserts
the end-to-end result is status=="unavailable".
- Structural boundary test (lines 143-174, derived from _TOOL_HANDLERS) preserved unchanged.
test_output_schema_conformance.py:
- _FakeWarpline returns real-shaped envelopes with valid meta (the old flat stubs
would have been refused → unavailable, silently flipping status to unavailable
and making the checked assertion vacuous).
test_server.py + test_preflight.py:
- All remaining flat warpline fakes updated to real-shaped envelopes;
assertions updated to match (pass-through semantics preserved).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Measured coverage is 91.9% (79/86 statements covered in client.py). Floor set at 88% to lock in the gain from the MCP-client rewrite while leaving headroom for incidental churn. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… content-fallback test IMPORTANT #1: add warpline-mcp-reverify-session.jsonl — three-line JSON-RPC transcript of a real warpline_reverify_worklist_get call (warpline-mcp 1.2.0, 2026-06-27, legis repo, HEAD~1..HEAD). Adds test_replays_a_REAL_reverify_session that echoes these bytes through StdioMcpInvoke and asserts schema/completeness/ items from the capture. Golden's reverify_worklist was already byte-identical to the freshly captured structuredContent; GOLDEN_BLOB_SHA unchanged. Updates PROVENANCE.md to document both halves are now live-captured with committed transcripts. MINOR (b): make text=False explicit in StdioMcpInvoke's subprocess.run call (was implicit via the absence of text=True; explicit kwarg prevents a future refactor from silently switching to char mode). MINOR (c): add test_content_text_fallback_parse — exercises the content[0].text parse path in StdioMcpInvoke when structuredContent is absent from the result. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… ship warpline preflight MCP-envelope fix; PDR-0005, PDR-0006 - PDR-0005: accept legis-476ab6f125 + legis-0c310712a7 against PRD-0005 (north-star 3->1; legis-0186c23a2c remains) - PDR-0006: warpline preflight conforms to warpline's extant MCP envelope (transport=MCP, owner-confirmed); producer-obligation reversed; reverify kept droppable pending wardline - refresh metrics.md (north-star 1; advisory-boundary re-proven; live-Loomweave gate -> skip-not-fail; coverage 92.25%), roadmap.md (Now 2/3 done), current-state.md - includes the 3 codebase-validated implementation plans + review history Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… the warpline producer-obligation framing Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…; sync uv.lock to 1.3.0 Plan for the warpline→legis governance read seam, revised against the 7-agent ultracode review (CHANGES_REQUESTED → all 8 must-fixes folded in). Contract artifacts (schema + warpline prompt) staged uncommitted for the build's Task 1. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Commits the FROZEN governance_read.v1 contract: the discriminated-union JSON schema (contracts/governance_read.v1.schema.json), the warpline hand-off prompt (docs/contracts/warpline-governance-read.v1-prompt.md), and the pinning test suite (tests/contract/test_governance_read_v1_schema.py). Tests cover 3 positives, 3 discriminator-negatives, 8 constraint-negatives, 1 format test (with load-bearing rfc3339-validator assertion), and 1 drift guard (structural equality of prompt's embedded schema block vs committed file, stripping non-validating descriptions only). Adds jsonschema[format] to the dev group so Draft202012Validator format_checker enforces the RFC3339 date-time constraint on as_of. .v1 is a ONE-WAY DOOR — any change to validation logic requires .v2. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… helper Adds the per-SEI governance-clearance projection (`read_governance_for_sei`), the CLI/batch verified-gate wrapper (`read_governance_for_sei_gate` — mirrors `evaluate_override_rate_gate` so both verify halves are mandatory), and the shared unavailable-envelope helper (`governance_read_unavailable`) to `service/governance.py`. Exports all three from `service/__init__.py`. Includes `_POSTURE_BY_KIND` and `_is_rfc3339`; unknown-kind / bad-as_of records are omitted (asymmetric-error), not fabricated. TDD red→green: 10 tests in `tests/service/test_governance_read.py`, mypy clean. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… projection) Adds the `governance_read` MCP tool that exposes per-SEI verified governance clearances as the `governance_read.v1` envelope, completing the warpline seam for advisory governance enrichment. Key properties: - BOTH-objects fail-closed pre-gate (mirrors attestation_get): gates on BOTH runtime.protected_gate AND runtime.trail_verifier; missing either -> status:"unavailable" (discriminated), never silent checked/[]. - Handler calls read_governance_for_sei(_governance_trail_records(runtime)) which runs BOTH verify_integrity (chain) AND TrailVerifier.verify (sigs) via the verified_records path; tampered trail -> AUDIT_INTEGRITY_FAILURE. - outputSchema built via _one_of over the v1 clearance_record fields (sei/disposition/posture/authority/as_of/reasons/content_hash), NOT attestation_get's fields. - Registered in _AGENT_TOOLS, tool_definitions(), and _TOOL_HANDLERS. Tests: - tests/mcp/test_governance_read_tool.py: handler tests (checked/unavailable/ tamper) incl. BOTH-objects gate on each missing half. - tests/mcp/test_output_schema_conformance.py: two explicit variant cases (checked + unavailable) validate against the declared _one_of outputSchema. - tests/conformance/test_governance_read_oracle.py: FROZEN GOLDEN mirroring test_warpline_attestation_oracle.py; byte-pinned blob SHA + LIVE==FROZEN value assert (not schema.validate); both clearance kinds pinned; content_hash cross-check confirms same records as the attestation golden. - tests/conformance/fixtures/legis-governance-read.golden.json: committed golden (blob SHA 898fd1a). - tests/mcp/test_server.py: update hard-coded tool list to include governance_read. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Exposes the governance_read.v1 per-SEI clearance read on the HTTP adapter
(Task 4). The route gates on BOTH protected_gate and trail_verifier (fail-closed
pre-gate identical to the MCP tool); verified_governance_records() runs both
chain and signature checks, mapping tamper to HTTP 500. Missing either object
yields a discriminated status:unavailable envelope, never a silent checked/[].
{sei:path} captures slash-bearing SEIs correctly.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…te test Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Exposes per-SEI verified governance clearances (governance_read.v1) at the CLI boundary. Both verification halves are mandatory per Constraint 1: verify_integrity() (hash-chain/seq-contiguity/delete-reorder defence) runs FIRST, then read_governance_for_sei_gate (signature half via the service layer). Omitting either half is a false-green — test_cli_governance_read_chain_tamper_exits_nonzero is RED without verify_integrity() and GREEN with it (mutation-verified). Fail-closed: no LEGIS_HMAC_KEY → unavailable; missing DB → unavailable; chain tamper → exit 1 + "audit integrity" stderr; signature tamper (key mismatch) → exit 1. No bare except. No --json flag (output is always JSON). No duplicate governance logic in the adapter — all decisions flow through service/governance.py. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…" contract
All tamper paths (chain gap AND signature mismatch) now emit the "audit
integrity" substring on stderr, matching the established contract used by
`service/governance.py:verified_records`, `mcp.py`, and the chain-tamper
path already in the same CLI helper. Fixes case (d) in the test, which
previously asserted "verification failed" (a substring only of the service
gate's AuditIntegrityError message, not the contract marker).
Change: `_governance_read` except block now prints
`"Error: audit integrity: {exc}"` instead of `"Error: {exc}"`, so the
"audit integrity" substring is present regardless of which verification
half raised. Test case (d) assertion updated from `"verification failed"`
to `"audit integrity"`.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…tructural check Adds read_governance_for_sei, read_governance_for_sei_gate, and governance_read_unavailable to the explicit warpline-free symbol list in test_runtime_warpline_referenced_in_no_verdict_path_function, so any future accidental warpline reference in these service functions is caught immediately. Full CI-equivalent sweep passes: coverage 92.39%/all per- package floors hold; ruff/mypy clean; SEI oracle, policy-boundary-check, governance-gate all green. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ance_read.v1 Adds three test_cross_transport_* tests to the contract freeze file, each capturing a REAL output from one transport adapter (MCP golden / HTTP TestClient / CLI main()) and validating it against the committed frozen contracts/governance_read.v1.schema.json with the rfc3339 format checker wired. Satisfies Task 6 DoD item: one captured output per transport validates against the frozen v1 schema. All 19 contract tests pass; per-package coverage floors and all CI gates remain green. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ctural, not byte) The embedded schema block is an abridged structural mirror — every validating keyword is identical to the canonical contracts/governance_read.v1.schema.json (legis CI asserts it), but description annotations live only in the canonical file. Prior "byte-equal" wording was inaccurate. Prose-only; the drift guard test is unchanged and still green. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…y at 1.3.0) src/legis/__init__.py carried a stale __version__ = "1.2.0" from the 1.3.0-prep that bumped pyproject.toml and CHANGELOG but not the constant, so `legis --version` reported 1.2.0 on the 1.3.0 line. Surfaced when deploying the local-main build for the warpline governance_read handshake. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ibling
Lands Plainweave in Legis's API: a read-only consumer of Plainweave's only
implemented producer, plainweave_preflight_facts_get / envelope
weft.plainweave.preflight_facts.v1 (ADR-006), which had no sibling consumer
and had never been exercised end-to-end.
Mirrors the existing warpline advisory-preflight read EXACTLY:
- legis/plainweave_preflight/client.py — injectable PlainweaveMcpClient +
StdioMcpInvoke; every contract fault fails CLOSED -> PlainweaveError. The
GV-LG-3 boundary is validated against Plainweave's real envelope shape
(data.authority_boundary.{local_only, live_peer_calls, governance_verdicts}
+ mandatory data.freshness/facts), since Plainweave's meta carries no
local_only/peer_side_effects (those are warpline's).
- service/preflight.read_plainweave_preflight — discriminated checked/unavailable
SIBLING of read_warpline_preflight; None/fault -> unavailable with a reason,
NEVER INTERNAL_ERROR, NEVER an empty-as-clean.
- mcp.py — plainweave_preflight_get tool next to warpline_preflight_get (separate
advisory sibling, not merged); runtime.plainweave wired from PLAINWEAVE_MCP_CMD,
default None -> unavailable; governance unaffected when absent/unconfigured.
ADVISORY ONLY, enrich-only: this read never changes a Legis policy/governance
decision. Tests pin it: a byte-identity test proves a hostile Plainweave client
cannot perturb a real verdict; a structural test proves no verdict-path function
references runtime.plainweave; a GV-LG-3 test refuses any producer claiming
governance_verdicts; the honest-degrade path (absent -> unavailable; ok:false
error envelope -> unavailable) is pinned.
Conformance oracle drives legis's real parser over a frozen golden built from the
producer contract (CONSTRUCTED, not live-captured — the hub session's MCP wiring
misroutes Plainweave; live end-to-end capture is a flagged follow-up in a
legis-rooted session). Gates green: ruff, mypy, pytest (1377 passed),
per-package coverage floors (plainweave_preflight 96.6%), sei oracle,
policy-boundary-check.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…tion pending) + record Plainweave consumer; PDR-0007, PDR-0008 Checkpoint 2026-06-28. PDR-0007 (build governance_read.v1, cleared-only per-SEI read legis publishes for warpline, owner-directed) and PDR-0008 (record the parallel session's Plainweave advisory consumer under federation-read doctrine). North-star unchanged at 1 (federation work is seam-quality, not P2 findings). Escalation: the push/publish release decision for the now-substantial unpushed local main (G1 + Plainweave + 1.3.0 line) remains owner-gated. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
….3.0 Records the two federation read surfaces added since the 1.3.0 section was written (PDR-0007 governance_read.v1 producer; PDR-0008 Plainweave advisory consumer) and updates the conformance note: the per-SEI governance read Warpline needs is now shipped on legis's producer side. Owner-directed: fold into 1.3.0. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: cee85267e0
ℹ️ 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".
| if not argv: | ||
| raise WarplineError("WARPLINE_MCP_CMD is blank") | ||
| from legis.config import project_root | ||
| warpline = WarplineMcpClient(invoke=StdioMcpInvoke(command=argv), repo=str(project_root())) |
There was a problem hiding this comment.
Use the configured source root for Warpline
When the MCP server is launched from outside the target repo and LEGIS_SOURCE_ROOT points at the checkout (the same setting used for runtime.source_root and the other git/source tools), this constructs the Warpline client with project_root(), which is just the process cwd. warpline_preflight_get will then send Warpline a repo for the wrong checkout and return advisory impact/worklist data for that directory instead of the configured repository; build this from the same source root used later on the runtime.
Useful? React with 👍 / 👎.
| raise WarplineError(f"{tool} envelope meta is {type(meta).__name__}, expected an object") | ||
| if meta.get("local_only") is not True: | ||
| raise WarplineError(f"{tool} meta.local_only is not true: {meta.get('local_only')!r}") | ||
| if meta.get("peer_side_effects"): |
There was a problem hiding this comment.
Require explicit no-side-effect metadata
When Warpline omits meta.peer_side_effects or returns it as null/false, this truthiness check accepts the envelope as checked, even though the GV-LG-3 boundary only proves safety when the producer explicitly says there were no peer side effects. A malformed boundary envelope should degrade through read_warpline_preflight to unavailable, not be passed through as advisory data; require the exact valid empty value before accepting it.
Useful? React with 👍 / 👎.
| proc = subprocess.run(self._command, input=stdin, capture_output=True, | ||
| timeout=self._timeout, shell=False, check=False, text=False) |
There was a problem hiding this comment.
Fail closed on non-zero MCP subprocess exits
If the configured warpline-mcp command writes a valid id=2 result and then exits non-zero, for example because a wrapper or the server crashes during shutdown, this check=False path has no later returncode guard and will still return structuredContent as a successful checked advisory result. The transport contract treats non-zero exit as a fault that should become WarplineError/unavailable, so check proc.returncode before accepting any parsed envelope.
Useful? React with 👍 / 👎.
The renderer (render_text) appends an audience tag ("[operator]",
"[auto-fixable]", "[fixed]") to every check line. Five operator-key
check messages in doctor.py already ended with a literal " [operator]",
causing the renderer to emit "[operator] [operator]" double-tags.
Remove the trailing " [operator]" from the four message strings in
check_posture_key_reset and check_operator_key_accessible; the renderer
continues to own the audience tag on every check line.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… 1.3.0 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 7c1d8e5c34
ℹ️ 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".
| if isinstance(sc, dict): | ||
| return sc |
There was a problem hiding this comment.
Fail closed on failed Plainweave subprocess exits
If PLAINWEAVE_MCP_CMD points to a wrapper/server that emits a valid id=2 structuredContent result and then exits non-zero (for example, a crash or failed cleanup during shutdown), this branch returns the envelope as successful checked advisory facts because proc.returncode is only included in later error strings and is never checked. That treats a failed MCP transport as success; check the return code before accepting structuredContent/content so read_plainweave_preflight degrades to unavailable.
Useful? React with 👍 / 👎.
| if not argv: | ||
| raise PlainweaveError("PLAINWEAVE_MCP_CMD is blank") | ||
| from legis.config import project_root | ||
| plainweave = PlainweaveMcpClient(invoke=PlainweaveStdioMcpInvoke(command=argv), repo=str(project_root())) |
There was a problem hiding this comment.
Run Plainweave from the configured source root
When the MCP server is launched outside the target checkout with LEGIS_SOURCE_ROOT pointing at the repo, this still starts the Plainweave client with an invoker that inherits the process cwd; the repo=str(project_root()) value here is just cwd and is not sent by PlainweaveMcpClient anyway. Because the Plainweave producer roots itself from the launched command's working directory, plainweave_preflight_get can return facts for the wrong project instead of the configured source root; pass the configured source root through as the subprocess cwd (or equivalent) when wiring this client.
Useful? React with 👍 / 👎.
| datetime.fromisoformat(value.replace("Z", "+00:00")) | ||
| return True |
There was a problem hiding this comment.
Reject non-RFC3339 governance timestamps
For signed records whose recorded_at is date-only or lacks an offset, datetime.fromisoformat still succeeds, so governance_read.v1 emits that value as as_of even though the frozen contract declares format: date-time and the docstring says malformed timestamps are omitted. A legacy/imported or test-injected signed clearance with recorded_at: "2026-06-02" or "2026-06-02T12:00:00" will therefore produce a checked envelope that fails the published schema instead of being safely omitted.
Useful? React with 👍 / 👎.
| f"{tool} authority_boundary.governance_verdicts is not false: " | ||
| f"{boundary.get('governance_verdicts')!r}" | ||
| ) | ||
| if "freshness" not in data or "facts" not in data: # degraded -> unavailable, not bare empty 'checked' |
There was a problem hiding this comment.
Validate Plainweave fact field types
This only checks that freshness and facts keys are present, so a malformed success envelope such as {"freshness": null, "facts": "not-a-list"} still returns status: "checked" and is passed through to callers as advisory facts. Since the Plainweave consumer contract says payload shape mismatches must degrade to unavailable, require the expected types (at least string freshness and array facts) before accepting the envelope.
Useful? React with 👍 / 👎.
Release 1.3.0 — the unpushed federation/security line + two new federation read surfaces
Folds the complete unpushed
maindelta (31 commits) into the 1.3.0 release.pyproject+__version__are both at1.3.0;CHANGELOG.md [1.3.0]is updated to match.Headline — new federation read surfaces
governance_read.v1— legis publishes a per-SEI governance read for Warpline (PDR-0007). New surface on CLI (legis governance-read <sei>), MCP (governance_readtool) and HTTP (GET /governance/sei/{sei:path}/governance-read), returning the frozengovernance_read.v1envelope (contract:contracts/governance_read.v1.schema.json). A pure projection of the forge-proof per-SEI attestation read into a cleared-only posture shape (operator_override→protected_override,signoff_cleared→operator_signoff), so Warpline'sreverify_worklist(include_federation=True)can enrich advisorily. Fail-closed throughout: unverifiable trail → discriminatedstatus:"unavailable"(never silent[]); tampered trail fails loud on all three transports (HTTP 500 / MCPAUDIT_INTEGRITY_FAILURE/ CLI nonzero);records:[]undercheckedis honest absence of clearance, never "ungoverned"/"unknown SEI". Advisory-only — Warpline echoesenrichment.governanceand never gates (GV-LG-1). Ships the producer half the prior 1.3.0 conformance note flagged as unwired.Plainweave preflight — advisory consumer (PDR-0008). First sibling consumer of Plainweave's
weft.plainweave.preflight_facts.v1; mirrors the Warpline advisory-preflight read (PlainweaveMcpClient+StdioMcpInvoke, fail-closed →unavailable, GV-LG-3 validated,PLAINWEAVE_MCP_CMD). Enrich-only; verdicts byte-identical with/without Plainweave.Also in 1.3.0 (already on the line)
read_floor()fails closed on a chain-integrity break (legis-476ab6f125); protected-cell batches advance the HeadAnchor (legis-0c310712a7).WARPLINE_API_URL→WARPLINE_MCP_CMD(legis-a53d92507d)..weft/legis/.gitignoreat install; the legis-resident halves of six cross-repo Weft seam conformance oracles.Verification (local, CI-equivalent)
pytest: 1378 passed, 9 skipped ·mypy: clean (80 files) ·ruff: cleanwarpline_preflight95.3, newplainweave_preflight)governance_read.v1was hardened by a 7-agent review (a Critical CLI false-green caught + fixed) and the CLI chain-integrity guard is mutation-proven (neuteringverify_integrity()reproduces the false-green; the regression test catches it).Notes for the reviewer / merger
LegisGovernanceClient.governance_for_sei(thegovernance_read.v1consumer); Plainweave's oracle golden is constructed, with live e2e capture a flagged follow-up.v1.3.0triggersrelease.yml→ PyPI (tag must equal pyproject1.3.0✓; the live-Loomweave conformance gate is skip-not-fail absentLOOMWEAVE_URL).outputSchemalooser than the frozen contract — Minor).🤖 Generated with Claude Code