Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
e51e043
fix(posture): read_floor fails closed on a chain-integrity break
tachyon-beep Jun 26, 2026
eb28e4b
test(posture): pin the recomputed-chain forgery as a documented residual
tachyon-beep Jun 26, 2026
84efd82
site: member-specific deconfliction-not-security disclaimer + Charter…
tachyon-beep Jun 26, 2026
304326e
fix(protected): add ProtectedGate.transaction() that advances the anchor
tachyon-beep Jun 26, 2026
6de6fa3
test(protected): pin the raw-batch anchor-advance residual
tachyon-beep Jun 26, 2026
79b4008
test(protected): drop dead import, fix misplaced truncate comment
tachyon-beep Jun 26, 2026
57614ec
feat(warpline): replace HttpWarplineClient with WarplineMcpClient ove…
tachyon-beep Jun 26, 2026
ddfd893
feat(warpline): add StdioMcpInvoke + live-capture DoD gate (Task 2)
tachyon-beep Jun 26, 2026
56a7ec9
feat(warpline): rewire mcp.py to WARPLINE_MCP_CMD + thread repo arg +…
tachyon-beep Jun 26, 2026
0ddb1b5
test(warpline): live-capture real MCP envelopes into golden; non-circ…
tachyon-beep Jun 26, 2026
566790d
test(warpline): harden advisory-boundary/conformance fakes with real-…
tachyon-beep Jun 26, 2026
951150e
ci(coverage): add warpline_preflight coverage floor at 88%
tachyon-beep Jun 26, 2026
075edd0
test(warpline): live-capture reverify session + explicit text=False +…
tachyon-beep Jun 26, 2026
8336847
product: accept governance-honesty bet (2/3 closed, north-star 3->1);…
tachyon-beep Jun 26, 2026
d1dc506
docs(changelog): record the 1.3.0 security/federation fixes + correct…
tachyon-beep Jun 26, 2026
6d6fa3c
Merge origin/main (release/1.3.0 PR #20) into the fixed 1.3.0 line
tachyon-beep Jun 26, 2026
0c07512
docs(plan): governance_read.v1 per-SEI read plan (rev 2, post-review)…
tachyon-beep Jun 27, 2026
00029fc
freeze governance_read.v1 contract (schema + warpline prompt + tests)
tachyon-beep Jun 27, 2026
be9c49f
feat(service): add read_governance_for_sei, gate wrapper, unavailable…
tachyon-beep Jun 27, 2026
031606f
feat(mcp): add governance_read MCP tool (governance_read.v1 clearance…
tachyon-beep Jun 27, 2026
4464c18
feat(api): add GET /governance/sei/{sei:path}/governance-read HTTP route
tachyon-beep Jun 27, 2026
317be80
fix(tests): remove unused SignoffGate import from governance_read rou…
tachyon-beep Jun 27, 2026
a98d147
feat(cli): add legis governance-read <sei> subcommand (Task 5)
tachyon-beep Jun 27, 2026
3ca4985
test(cli): remove unused pytest import in governance_read cli test
tachyon-beep Jun 27, 2026
5330ff8
fix(cli): normalize governance-read tamper stderr to "audit integrity…
tachyon-beep Jun 27, 2026
3f39798
test(guardrails): pin read_governance_for_sei* to advisory-boundary s…
tachyon-beep Jun 27, 2026
422eb54
test(contract): add cross-transport schema agreement tests for govern…
tachyon-beep Jun 27, 2026
aec654b
docs(contract): correct warpline prompt's schema-mirror wording (stru…
tachyon-beep Jun 27, 2026
395d7fc
fix(release): sync __version__ to 1.3.0 (pyproject + CHANGELOG alread…
tachyon-beep Jun 27, 2026
27f12da
legis: consume Plainweave's preflight-facts producer as an ADVISORY s…
tachyon-beep Jun 27, 2026
ee043c9
product: governance_read.v1 federation seam (legis-side done, integra…
tachyon-beep Jun 27, 2026
cee8526
docs(changelog): fold governance_read.v1 + Plainweave consumer into 1…
tachyon-beep Jun 27, 2026
93fd73b
fix(doctor): strip literal [operator] from operator-key message strings
tachyon-beep Jun 27, 2026
7c1d8e5
docs(changelog): record the legis doctor [operator] double-tag fix in…
tachyon-beep Jun 28, 2026
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
102 changes: 93 additions & 9 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,83 @@ versions per [PEP 440](https://peps.python.org/pep-0440/) /

_Post-1.0.0 work lands here; legis versions independently from the Weft 1.0 launch on._

## [1.3.0] — 2026-06-26

Suite-standard dot-dir hygiene, plus the legis-resident halves of six cross-repo
Weft seam conformance oracles.
## [1.3.0] — 2026-06-28

Suite-standard dot-dir hygiene and the legis-resident halves of six cross-repo
Weft seam conformance oracles; three security/federation fixes (two
governance-honesty hardenings on the posture and protected-cell audit paths, and
a rebuild of the Warpline advisory-preflight seam onto Warpline's real MCP wire);
and two new federation read surfaces — `governance_read.v1` (the per-SEI
governance read legis now **publishes** for Warpline) and a Plainweave
advisory-preflight **consumer**.

### Security

- **Posture `read_floor()` fails closed on a chain-integrity break
(legis-476ab6f125).** The hot routing read now gates on the keyless
`verify_integrity()` chain re-hash before returning the floor, so a
raw-DB-written/forged ledger tail can no longer silently set the routing floor:
an unverifiable chain resolves to `None` → the fail-closed `structured`
default, never the tampered floor. A recomputed-keyless-chain forgery remains
the conceded raw-file-write residual (README "Known security limitations"),
pinned by a characterization test rather than implied-closed.
- **Protected-cell batches advance the HeadAnchor (legis-0c310712a7).**
`ProtectedGate` gains a `transaction()` context manager — a parity mirror of
`SignoffGate.transaction()` — that advances the out-of-band HeadAnchor after a
batched protected append commits, so a later tail-truncation back to a stale
anchor is detectable. Preventive/parity hardening: production wires no anchor
and no caller batches protected appends today.

### Changed — Warpline advisory preflight rebuilt onto the real MCP wire

- **`warpline_preflight_get` now speaks Warpline's actual surface
(legis-a53d92507d).** The prior client issued `GET /api/impact-radius` against
an HTTP server Warpline never served. It is replaced by a stdlib stdio JSON-RPC
client (`WarplineMcpClient` + `StdioMcpInvoke`, no new dependency) that consumes
Warpline's **extant** `warpline_impact_radius_get` / `warpline_reverify_worklist_get`
MCP tools with a `rev_range`, parses the real `warpline.impact_radius.v1` /
`warpline.reverify_worklist.v1` envelope, and verifies the
`meta.local_only` / `peer_side_effects` invariant (GV-LG-3), failing closed on
every fault. Config moves from `WARPLINE_API_URL` to `WARPLINE_MCP_CMD`. The
advisory boundary is unchanged: governance verdicts stay byte-identical with or
without Warpline, and any failure degrades to a discriminated `unavailable`.
This **reverses** the earlier "Warpline must ship a flat HTTP producer" framing
— legis conforms to Warpline's frozen envelope (hub SEAM 4 §4A / GV-LG-3);
Warpline builds nothing.

### Added — federation read surfaces: `governance_read.v1` (producer) + Plainweave (consumer)

- **`governance_read.v1` — legis publishes a per-SEI governance read for Warpline
(PDR-0007).** A new surface on CLI (`legis governance-read <sei>`), MCP
(`governance_read` tool) and HTTP (`GET /governance/sei/{sei:path}/governance-read`),
returning the frozen `governance_read.v1` envelope (contract committed at
`contracts/governance_read.v1.schema.json`). It is a pure projection of the
forge-proof per-SEI attestation read (`read_sei_attestations`) into a
**cleared-only** posture-record shape (`operator_override` → `protected_override`,
`signoff_cleared` → `operator_signoff`), so Warpline's
`reverify_worklist(include_federation=True)` can enrich its worklist with legis
governance facts. Fail-closed throughout: an unverifiable trail resolves to a
discriminated `status: "unavailable"` (never a silent `records: []`); a tampered
trail fails loud on all three transports (HTTP 500 / MCP `AUDIT_INTEGRITY_FAILURE`
/ CLI nonzero); `records: []` under `checked` is honest absence of clearance,
never "ungoverned" or "unknown SEI" (legis is an SEI consumer, never the
authority). Advisory-only — Warpline echoes it as `enrichment.governance` and
never gates on it (GV-LG-1). The discriminated-union schema and the CLI
chain-integrity guard are both **mutation-proven** against false-greens. This
ships the producer half of the obligation the 1.3.0 conformance note flagged as
unwired; Warpline's consumer (`LegisClient.governance_for_sei`) is the remaining
integration.

- **Plainweave preflight — advisory consumer (PDR-0008).** legis gains a read-only
`plainweave_preflight_get` consumer of Plainweave's
`weft.plainweave.preflight_facts.v1` producer (its first sibling consumer),
mirroring the Warpline advisory-preflight read exactly: injectable
`PlainweaveMcpClient` + `StdioMcpInvoke`, every fault fails closed →
`unavailable`, GV-LG-3 validated against Plainweave's real `authority_boundary`
shape, configured via `PLAINWEAVE_MCP_CMD` (default unconfigured →
`unavailable`). Enrich-only; governance verdicts stay byte-identical with or
without Plainweave. The conformance oracle drives a constructed golden (live
end-to-end capture is a flagged follow-up).

### Added

Expand Down Expand Up @@ -42,11 +115,22 @@ Weft seam conformance oracles.
the default suite) plus a skip-clean Layer-2 source recheck: SEI
(loomweave→legis), git-renames (legis→loomweave), signoff-binding
(legis→filigree), loomweave-HMAC-wire (legis→loomweave, live-gated), the
warpline preflight read (legis consumer), and the per-SEI `attestation_get`
read (legis producer). Two outstanding peer obligations are recorded rather
than papered over — warpline ships no flat HTTP producer for the preflight
shape, and warpline's `LegisClient.governance_for_sei` is unwired — with the
Layer-2 rechecks armed to fire when each peer lands its half.
warpline preflight read (legis consumer — now driving Warpline's real
`warpline.impact_radius.v1` / `warpline.reverify_worklist.v1` MCP envelope; see
*Changed* above), and the per-SEI `attestation_get` read (legis producer). The
peer obligation this note previously flagged as unwired — the per-SEI governance
read Warpline needs — is now **shipped on legis's side** as `governance_read.v1`
(see *Added* above, with its own frozen-golden oracle); Warpline's consumer
(`LegisClient.governance_for_sei`) is the remaining integration half, tracked for
the live handshake.

### Fixed

- **`legis doctor` no longer double-prints the `[operator]` audience tag.** Five
operator-key check messages baked a literal `[operator]` into the message text
while the renderer also appends the audience tag, so the lines read
`… [operator] [operator]`. The literals are stripped; the renderer remains the
single owner of the tag.

## [1.2.0] — 2026-06-25

Expand Down
91 changes: 91 additions & 0 deletions contracts/governance_read.v1.schema.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://weft.dev/contracts/governance_read.v1.schema.json",
"title": "legis governance_read.v1",
"description": "Per-SEI VERIFIED GOVERNANCE CLEARANCE facts produced by legis (the governance authority) and consumed advisorily by siblings (e.g. warpline reverify enrichment). v1 reports verified clearances ONLY (operator overrides + cleared structured/protected sign-offs). 'records: []' under status 'checked' = no verified clearance for this SEI on legis's verified trail -- NOT 'ungoverned', and NOT 'unknown SEI' (legis is an SEI consumer, never the SEI authority; it cannot distinguish unknown-from-ungoverned). status 'unavailable' = legis could not produce a signature-verifiable answer (no protected gate / verifier / key); consumers MUST treat it as 'unavailable', NEVER as 'absent'. A TAMPERED trail does not reach this envelope at all -- it fails loud as a transport-level integrity error (MCP AUDIT_INTEGRITY_FAILURE / HTTP 5xx / CLI nonzero exit).",
"type": "object",
"required": ["status", "sei", "records"],
"additionalProperties": false,
"properties": {
"status": {
"description": "Envelope state. 'checked' = the verified trail was read (records may be empty = honest absence of clearance). 'unavailable' = could not produce a signature-verifiable answer.",
"enum": ["checked", "unavailable"]
},
"sei": {
"description": "The SEI queried, echoed verbatim. Opaque; never parsed.",
"type": "string",
"minLength": 1
},
"records": {
"description": "Verified governance clearance records keyed on this SEI. Empty under 'checked' = honest absence. Always [] under 'unavailable'.",
"type": "array",
"items": { "$ref": "#/$defs/clearance_record" }
},
"unavailable": {
"description": "Present ONLY under status 'unavailable' (and required there): why legis could not produce a verifiable answer. Non-empty.",
"type": "array",
"minItems": 1,
"items": {
"type": "object",
"required": ["reason"],
"additionalProperties": false,
"properties": { "reason": { "type": "string", "minLength": 1 } }
}
}
},
"allOf": [
{
"if": { "properties": { "status": { "const": "unavailable" } }, "required": ["status"] },
"then": {
"required": ["unavailable"],
"properties": { "records": { "maxItems": 0 } }
}
},
{
"if": { "properties": { "status": { "const": "checked" } }, "required": ["status"] },
"then": { "not": { "required": ["unavailable"] } }
}
],
"$defs": {
"clearance_record": {
"type": "object",
"required": ["sei", "disposition", "posture", "authority", "as_of", "reasons", "content_hash"],
"additionalProperties": false,
"properties": {
"sei": {
"description": "The SEI this clearance is keyed on (== the SIGNED entity_key.value; identity-stable).",
"type": "string",
"minLength": 1
},
"disposition": {
"description": "Record-level governance disposition. NOT the envelope 'status', NOT a consumer's 'enrichment.governance'. v1 closed enum = {'cleared'}: every record is a verified human clearance. (Future dispositions arrive in governance_read.v2 -- v1 is never mutated.)",
"enum": ["cleared"]
},
"posture": {
"description": "The PROVABLE clearance mechanism. legis does NOT claim the enforcement cell for a sign-off (it cannot prove structured-vs-protected for a cleared sign-off) -- it reports the mechanism it can prove. 'protected_override' = a protected operator-override verdict; 'operator_signoff' = an operator-cleared sign-off.",
"enum": ["protected_override", "operator_signoff"]
},
"authority": {
"description": "Clearing-authority class. v1: both clearance kinds are operator-cleared.",
"enum": ["operator"]
},
"as_of": {
"description": "Timestamp from the SIGNED recorded_at of the clearance record (RFC3339 UTC; '+00:00' and 'Z' both valid). A clearance whose recorded_at is absent or non-RFC3339 is OMITTED by the producer (asymmetric-error rule) -- it never ships as null.",
"type": "string",
"format": "date-time"
},
"reasons": {
"description": "Closed-vocab codes naming the clearance kind (what happened). Never free prose. Distinct axis from 'posture' (the provable mechanism / how); v1 correlates them 1:1 by construction, but v2 may carry additional reason codes without changing posture.",
"type": "array",
"minItems": 1,
"items": { "enum": ["operator_override", "signoff_cleared"] }
},
"content_hash": {
"description": "The SIGNED Loomweave content hash binding the clearance to the governed content (non-empty).",
"type": "string",
"minLength": 1
}
}
}
}
}
Loading
Loading