From a9f676420c1aa92cfa598c31a22df30ced070890 Mon Sep 17 00:00:00 2001 From: Jerry Xiao Date: Sun, 2 Aug 2026 04:30:41 +0000 Subject: [PATCH 01/33] docs(agents): record contract-parity coverage boundary; anchor core-dump ignores Constrained fields owe their own dedicated test. That convention is already well followed - `lease_seconds_is_bounded_like_the_schema` and its siblings exist because the schema parity test cannot cover them - but it was written down nowhere, so the next person to add a constrained field would reasonably assume parity covers it. `generated_schemas_match_checked_in_schemas` compares only property names, `required`, and `additionalProperties` via `assert_object_parity`. Measured: setting `$defs.change_request.properties.capability_id.type` to `"integer"` in `schemas/experiment.schema.json`, against `capability_id: String` in Rust, leaves all 29 contract tests green. Also replace the unanchored `core` / `core.*` crash-dump ignores. A slash-less pattern matches at any depth and matches directories, so bare `core` would silently untrack a future `src/core/` subsystem and bare `core.*` would swallow a source file such as `api/core.ts`. The replacement anchors to the repo root, negates a root-level `core/` package directory, and covers both per-host dump shapes. Verified: `git check-ignore` reports `core` and `core.node.12345` ignored and `api/core.ts` not ignored; `cargo test --workspace` and `cargo fmt --check` pass. No source or schema file is modified. --- .gitignore | 18 +++++++++++++++--- AGENTS.md | 1 + 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index 0233772..420eefe 100644 --- a/.gitignore +++ b/.gitignore @@ -23,6 +23,18 @@ Thumbs.db .sentrux/cache.bin .sentrux/churn.bin -# Crash dumps must never enter source control. -core -core.* +# Crash artifacts, never repo state. A core dump is a memory image of a process +# that ran holding live credentials, so an automated fix round staging one into a +# public repo is a credential exposure, not bloat. +# Anchored with a leading `/` so these apply at the repo root only: unanchored +# `core` matches at ANY depth and matches directories, so it would silently +# untrack a whole `src/core/` subsystem, and unanchored `core.*` would swallow +# `api/core.ts`. The negation keeps a legitimate root-level `core/` package +# tracked while still ignoring a root-level `core` FILE. +# Two dump shapes are covered because `kernel.core_pattern` is per-host: +# `core` and `core.` (this container uses the bare `core` form), and +# `core..` from the common `core.%e.%p` pattern. +/core +!/core/ +/core.[0-9]* +/core.*.[0-9]* diff --git a/AGENTS.md b/AGENTS.md index d48e094..bb8b512 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -15,6 +15,7 @@ Start with `docs/README.md`. Read `docs/IMPLEMENTATION_PLAN.md`, `docs/ARCHITECT ## Repository rules - Keep shared wire types in `crates/contracts`, and keep `schemas/*.json` in sync with them; the contract tests enforce matching fields and enum strings. +- Give every field that carries a type constraint, a range, or a `deserialize_with` validator its own dedicated test, copying the `*_like_the_schema` tests in `crates/contracts/src/lib.rs`; the schema parity test compares property names, `required`, and `additionalProperties` only, so a mismatched field `type` or a dropped bound otherwise stays green. - Keep provider lifecycle behavior in `crates/provider-sdk`. - Keep the capability registry, policy, broker lifecycle, and experiment journal in `crates/control-plane`. - Keep the local IPC transport, framing, and peer-authentication seams behind traits in `crates/ipc` (Unix domain socket now, Windows named pipe later); the privileged broker in `apps/broker` composes them over the control plane and enforces peer auth, catalog policy, and single-owner-per-knob. The non-`Send` control plane is confined to one worker thread reached through a `Send` handle. From f568904bc1f3fef7ebcf76f40cca1c0791a32745 Mon Sep 17 00:00:00 2001 From: Jerry Xiao Date: Sun, 2 Aug 2026 04:53:13 +0000 Subject: [PATCH 02/33] no-mistakes(review): widen contract-parity rule to both parity helpers --- AGENTS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AGENTS.md b/AGENTS.md index bb8b512..2d64627 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -15,7 +15,7 @@ Start with `docs/README.md`. Read `docs/IMPLEMENTATION_PLAN.md`, `docs/ARCHITECT ## Repository rules - Keep shared wire types in `crates/contracts`, and keep `schemas/*.json` in sync with them; the contract tests enforce matching fields and enum strings. -- Give every field that carries a type constraint, a range, or a `deserialize_with` validator its own dedicated test, copying the `*_like_the_schema` tests in `crates/contracts/src/lib.rs`; the schema parity test compares property names, `required`, and `additionalProperties` only, so a mismatched field `type` or a dropped bound otherwise stays green. +- Give every field that carries a type constraint, a range, or a `deserialize_with` validator its own dedicated test, following the `*_like_the_schema` tests and `change_request_parameters_are_an_object_in_both`; the parity helpers `assert_object_parity` and `assert_same_shape` compare property names, `required`, and `additionalProperties` only, so a mismatched field `type` or a dropped bound otherwise stays green. - Keep provider lifecycle behavior in `crates/provider-sdk`. - Keep the capability registry, policy, broker lifecycle, and experiment journal in `crates/control-plane`. - Keep the local IPC transport, framing, and peer-authentication seams behind traits in `crates/ipc` (Unix domain socket now, Windows named pipe later); the privileged broker in `apps/broker` composes them over the control plane and enforces peer auth, catalog policy, and single-owner-per-knob. The non-`Send` control plane is confined to one worker thread reached through a `Send` handle. From bf2902e69eff2210fe21852764ef13764b96ae87 Mon Sep 17 00:00:00 2001 From: Jerry Xiao Date: Sun, 2 Aug 2026 05:13:24 +0000 Subject: [PATCH 03/33] no-mistakes(document): document parity boundary on both schema parity helpers --- crates/contracts/src/lib.rs | 4 ++++ crates/contracts/src/test_support.rs | 4 +++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/crates/contracts/src/lib.rs b/crates/contracts/src/lib.rs index 6a52f37..4ced807 100644 --- a/crates/contracts/src/lib.rs +++ b/crates/contracts/src/lib.rs @@ -489,6 +489,10 @@ mod tests { } /// Asserts that two object schemas declare the same fields. + /// + /// Property names, the `required` list, and `additionalProperties` are + /// compared; property types and bounds are not, so each of those carries its + /// own dedicated test instead. fn assert_object_parity(label: &str, generated: &Value, checked_in: &Value) { let generated_properties: BTreeSet = generated["properties"] .as_object() diff --git a/crates/contracts/src/test_support.rs b/crates/contracts/src/test_support.rs index cf38242..bcde236 100644 --- a/crates/contracts/src/test_support.rs +++ b/crates/contracts/src/test_support.rs @@ -56,7 +56,9 @@ pub fn serialized_fields(value: impl serde::Serialize) -> BTreeSet { /// Asserts that `generated` and `checked_in` declare the same object shape. /// /// Property names, the `required` list, and `additionalProperties` are compared; -/// a definition that drifts in any of the three fails the calling test. +/// a definition that drifts in any of the three fails the calling test. Property +/// types and bounds are not compared, so each of those carries its own dedicated +/// test instead. pub fn assert_same_shape(generated: &schemars::Schema, checked_in: &Value) { let generated = serde_json::to_value(generated).expect("generated schema should serialize"); assert_eq!(properties(&generated), properties(checked_in)); From 3cd44560d5bc68fe6e589abc7d6f4a70de8a3968 Mon Sep 17 00:00:00 2001 From: Jerry Xiao Date: Sun, 2 Aug 2026 05:18:41 +0000 Subject: [PATCH 04/33] chore(gitignore): match core dumps at any depth, not just repo root --- .gitignore | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/.gitignore b/.gitignore index 420eefe..5b673f3 100644 --- a/.gitignore +++ b/.gitignore @@ -26,15 +26,17 @@ Thumbs.db # Crash artifacts, never repo state. A core dump is a memory image of a process # that ran holding live credentials, so an automated fix round staging one into a # public repo is a credential exposure, not bloat. -# Anchored with a leading `/` so these apply at the repo root only: unanchored -# `core` matches at ANY depth and matches directories, so it would silently -# untrack a whole `src/core/` subsystem, and unanchored `core.*` would swallow -# `api/core.ts`. The negation keeps a legitimate root-level `core/` package -# tracked while still ignoring a root-level `core` FILE. -# Two dump shapes are covered because `kernel.core_pattern` is per-host: +# `**/` matches at any depth because a dump lands in the CRASHING PROCESS's working +# directory, which is not always the repo root: `cargo test` runs each package's +# test binary with cwd at that package root, so a Rust workspace dumps to +# `crates//core`. +# `!**/core/` is what makes the depth safe: without it, `**/core` would also match +# every directory named `core` and silently untrack whole subsystems such as +# `src/core/` or a `crates/core` package. +# Two dump name shapes are covered because `kernel.core_pattern` is per-host: # `core` and `core.` (this container uses the bare `core` form), and # `core..` from the common `core.%e.%p` pattern. -/core -!/core/ -/core.[0-9]* -/core.*.[0-9]* +**/core +!**/core/ +**/core.[0-9]* +**/core.*.[0-9]* From 73755681f378bdb5cb2e94f36efee9de0567fe85 Mon Sep 17 00:00:00 2001 From: Jerry Xiao Date: Sun, 2 Aug 2026 05:51:02 +0000 Subject: [PATCH 05/33] no-mistakes(review): key parity test rule off schema, note capability_id gap --- AGENTS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AGENTS.md b/AGENTS.md index 2d64627..59fc694 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -15,7 +15,7 @@ Start with `docs/README.md`. Read `docs/IMPLEMENTATION_PLAN.md`, `docs/ARCHITECT ## Repository rules - Keep shared wire types in `crates/contracts`, and keep `schemas/*.json` in sync with them; the contract tests enforce matching fields and enum strings. -- Give every field that carries a type constraint, a range, or a `deserialize_with` validator its own dedicated test, following the `*_like_the_schema` tests and `change_request_parameters_are_an_object_in_both`; the parity helpers `assert_object_parity` and `assert_same_shape` compare property names, `required`, and `additionalProperties` only, so a mismatched field `type` or a dropped bound otherwise stays green. +- Give every field whose checked-in schema constrains it beyond `type` (a `minLength`, a `pattern`, a numeric bound) or that carries a `deserialize_with` validator its own dedicated test, following the `*_like_the_schema` tests and `change_request_parameters_are_an_object_in_both`; the parity helpers `assert_object_parity` and `assert_same_shape` compare property names, `required`, and `additionalProperties` only, so a mismatched `type` or a dropped bound otherwise stays green, and `capability_id`'s `minLength` in `schemas/experiment.schema.json` and `pattern` in `schemas/broker-request.schema.json` are a known unguarded gap tracked as follow-up. - Keep provider lifecycle behavior in `crates/provider-sdk`. - Keep the capability registry, policy, broker lifecycle, and experiment journal in `crates/control-plane`. - Keep the local IPC transport, framing, and peer-authentication seams behind traits in `crates/ipc` (Unix domain socket now, Windows named pipe later); the privileged broker in `apps/broker` composes them over the control plane and enforces peer auth, catalog policy, and single-owner-per-knob. The non-`Send` control plane is confined to one worker thread reached through a `Send` handle. From d5e352a521cd0c95fe8ca149a14691cb28e7b7a0 Mon Sep 17 00:00:00 2001 From: Jerry Xiao Date: Sun, 2 Aug 2026 06:08:21 +0000 Subject: [PATCH 06/33] no-mistakes(review): complete unguarded-field list, note lease ceiling drift --- AGENTS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AGENTS.md b/AGENTS.md index 59fc694..141b999 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -15,7 +15,7 @@ Start with `docs/README.md`. Read `docs/IMPLEMENTATION_PLAN.md`, `docs/ARCHITECT ## Repository rules - Keep shared wire types in `crates/contracts`, and keep `schemas/*.json` in sync with them; the contract tests enforce matching fields and enum strings. -- Give every field whose checked-in schema constrains it beyond `type` (a `minLength`, a `pattern`, a numeric bound) or that carries a `deserialize_with` validator its own dedicated test, following the `*_like_the_schema` tests and `change_request_parameters_are_an_object_in_both`; the parity helpers `assert_object_parity` and `assert_same_shape` compare property names, `required`, and `additionalProperties` only, so a mismatched `type` or a dropped bound otherwise stays green, and `capability_id`'s `minLength` in `schemas/experiment.schema.json` and `pattern` in `schemas/broker-request.schema.json` are a known unguarded gap tracked as follow-up. +- Give every field whose checked-in schema constrains it beyond `type` (a `minLength`, a `pattern`, a numeric bound) or that carries a `deserialize_with` validator its own dedicated test, following the `*_like_the_schema` tests and `change_request_parameters_are_an_object_in_both`; the parity helpers `assert_object_parity` and `assert_same_shape` compare property names, `required`, and `additionalProperties` only, so a mismatched `type` or a dropped bound otherwise stays green, six constraints with no Rust-side equivalent are currently unguarded (`capability_id`, `owner`, `capability.id`, `capability.description`, `sidecar.id`, `targets`), and `$defs.ChangeRequest.lease_seconds` in `schemas/broker-request.schema.json` is a live instance missing the `maximum` that `crates/contracts/src/lib.rs:95` and `schemas/experiment.schema.json` both carry, harmless at runtime because `crates/control-plane/src/lib.rs:292` rejects an over-ceiling lease and tracked as follow-up `fpsm-lease-ceiling-parity`. - Keep provider lifecycle behavior in `crates/provider-sdk`. - Keep the capability registry, policy, broker lifecycle, and experiment journal in `crates/control-plane`. - Keep the local IPC transport, framing, and peer-authentication seams behind traits in `crates/ipc` (Unix domain socket now, Windows named pipe later); the privileged broker in `apps/broker` composes them over the control plane and enforces peer auth, catalog policy, and single-owner-per-knob. The non-`Send` control plane is confined to one worker thread reached through a `Send` handle. From 604ae90d6501abae8a4e0910ff2bf5b363fd5ea0 Mon Sep 17 00:00:00 2001 From: Jerry Xiao Date: Sun, 2 Aug 2026 06:31:57 +0000 Subject: [PATCH 07/33] no-mistakes(review): drop gap count, cite symbols, make doc comments normative --- AGENTS.md | 2 +- crates/contracts/src/lib.rs | 4 ++-- crates/contracts/src/test_support.rs | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 141b999..cbfeb9f 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -15,7 +15,7 @@ Start with `docs/README.md`. Read `docs/IMPLEMENTATION_PLAN.md`, `docs/ARCHITECT ## Repository rules - Keep shared wire types in `crates/contracts`, and keep `schemas/*.json` in sync with them; the contract tests enforce matching fields and enum strings. -- Give every field whose checked-in schema constrains it beyond `type` (a `minLength`, a `pattern`, a numeric bound) or that carries a `deserialize_with` validator its own dedicated test, following the `*_like_the_schema` tests and `change_request_parameters_are_an_object_in_both`; the parity helpers `assert_object_parity` and `assert_same_shape` compare property names, `required`, and `additionalProperties` only, so a mismatched `type` or a dropped bound otherwise stays green, six constraints with no Rust-side equivalent are currently unguarded (`capability_id`, `owner`, `capability.id`, `capability.description`, `sidecar.id`, `targets`), and `$defs.ChangeRequest.lease_seconds` in `schemas/broker-request.schema.json` is a live instance missing the `maximum` that `crates/contracts/src/lib.rs:95` and `schemas/experiment.schema.json` both carry, harmless at runtime because `crates/control-plane/src/lib.rs:292` rejects an over-ceiling lease and tracked as follow-up `fpsm-lease-ceiling-parity`. +- Give every field whose checked-in schema constrains it beyond `type` (a `minLength`, a `pattern`, a numeric bound) or that carries a `deserialize_with` validator its own dedicated test, following the `*_like_the_schema` tests and `change_request_parameters_are_an_object_in_both`; the parity helpers `assert_object_parity` and `assert_same_shape` compare property names, `required`, and `additionalProperties` only, so a mismatched `type` or a dropped bound otherwise stays green, several fields carry checked-in schema constraints with no dedicated test (`capability_id` among them), and `$defs.ChangeRequest.lease_seconds` in `schemas/broker-request.schema.json` is a live instance missing the `maximum` that `MAX_LEASE_SECONDS` and `schemas/experiment.schema.json` both carry, harmless at runtime because the control-plane policy check rejects an over-ceiling lease, and tracked as follow-up `fpsm-lease-ceiling-parity`. - Keep provider lifecycle behavior in `crates/provider-sdk`. - Keep the capability registry, policy, broker lifecycle, and experiment journal in `crates/control-plane`. - Keep the local IPC transport, framing, and peer-authentication seams behind traits in `crates/ipc` (Unix domain socket now, Windows named pipe later); the privileged broker in `apps/broker` composes them over the control plane and enforces peer auth, catalog policy, and single-owner-per-knob. The non-`Send` control plane is confined to one worker thread reached through a `Send` handle. diff --git a/crates/contracts/src/lib.rs b/crates/contracts/src/lib.rs index 4ced807..5d7d9cb 100644 --- a/crates/contracts/src/lib.rs +++ b/crates/contracts/src/lib.rs @@ -491,8 +491,8 @@ mod tests { /// Asserts that two object schemas declare the same fields. /// /// Property names, the `required` list, and `additionalProperties` are - /// compared; property types and bounds are not, so each of those carries its - /// own dedicated test instead. + /// compared; property types and bounds are not, so each of those requires + /// its own dedicated test instead. fn assert_object_parity(label: &str, generated: &Value, checked_in: &Value) { let generated_properties: BTreeSet = generated["properties"] .as_object() diff --git a/crates/contracts/src/test_support.rs b/crates/contracts/src/test_support.rs index bcde236..18b3bca 100644 --- a/crates/contracts/src/test_support.rs +++ b/crates/contracts/src/test_support.rs @@ -57,8 +57,8 @@ pub fn serialized_fields(value: impl serde::Serialize) -> BTreeSet { /// /// Property names, the `required` list, and `additionalProperties` are compared; /// a definition that drifts in any of the three fails the calling test. Property -/// types and bounds are not compared, so each of those carries its own dedicated -/// test instead. +/// types and bounds are not compared, so each of those requires its own +/// dedicated test instead. pub fn assert_same_shape(generated: &schemars::Schema, checked_in: &Value) { let generated = serde_json::to_value(generated).expect("generated schema should serialize"); assert_eq!(properties(&generated), properties(checked_in)); From 76ad414a3d0bdd0eaa5c27b1464c6aa0002b2604 Mon Sep 17 00:00:00 2001 From: Jerry Xiao Date: Sun, 2 Aug 2026 06:44:20 +0000 Subject: [PATCH 08/33] no-mistakes(review): attribute parity blind spot to comparison, name hand-rolled sites --- AGENTS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AGENTS.md b/AGENTS.md index cbfeb9f..ec4b842 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -15,7 +15,7 @@ Start with `docs/README.md`. Read `docs/IMPLEMENTATION_PLAN.md`, `docs/ARCHITECT ## Repository rules - Keep shared wire types in `crates/contracts`, and keep `schemas/*.json` in sync with them; the contract tests enforce matching fields and enum strings. -- Give every field whose checked-in schema constrains it beyond `type` (a `minLength`, a `pattern`, a numeric bound) or that carries a `deserialize_with` validator its own dedicated test, following the `*_like_the_schema` tests and `change_request_parameters_are_an_object_in_both`; the parity helpers `assert_object_parity` and `assert_same_shape` compare property names, `required`, and `additionalProperties` only, so a mismatched `type` or a dropped bound otherwise stays green, several fields carry checked-in schema constraints with no dedicated test (`capability_id` among them), and `$defs.ChangeRequest.lease_seconds` in `schemas/broker-request.schema.json` is a live instance missing the `maximum` that `MAX_LEASE_SECONDS` and `schemas/experiment.schema.json` both carry, harmless at runtime because the control-plane policy check rejects an over-ceiling lease, and tracked as follow-up `fpsm-lease-ceiling-parity`. +- Give every field whose checked-in schema constrains it beyond `type` (a `minLength`, a `pattern`, a numeric bound) or that carries a `deserialize_with` validator its own dedicated test, following the `*_like_the_schema` tests and `change_request_parameters_are_an_object_in_both`; schema parity compares property names, `required`, and `additionalProperties` only, whether through the `assert_object_parity` and `assert_same_shape` helpers or hand-rolled inline in `response_variants_match_schema`, `capability_fields_match_capability_schema`, and `manifest_fields_match_sidecar_schema`, so a mismatched `type` or a dropped bound otherwise stays green, several fields carry checked-in schema constraints with no dedicated test (`capability_id` among them), and `$defs.ChangeRequest.lease_seconds` in `schemas/broker-request.schema.json` is a live instance missing the `maximum` that `MAX_LEASE_SECONDS` and `schemas/experiment.schema.json` both carry, harmless at runtime because the control-plane policy check rejects an over-ceiling lease, and tracked as follow-up `fpsm-lease-ceiling-parity`. - Keep provider lifecycle behavior in `crates/provider-sdk`. - Keep the capability registry, policy, broker lifecycle, and experiment journal in `crates/control-plane`. - Keep the local IPC transport, framing, and peer-authentication seams behind traits in `crates/ipc` (Unix domain socket now, Windows named pipe later); the privileged broker in `apps/broker` composes them over the control plane and enforces peer auth, catalog policy, and single-owner-per-knob. The non-`Send` control plane is confined to one worker thread reached through a `Send` handle. From 6f9b530680d3f8f2a4a6d81d46b1c51e5ee16c3f Mon Sep 17 00:00:00 2001 From: Jerry Xiao Date: Sun, 2 Aug 2026 07:01:09 +0000 Subject: [PATCH 09/33] no-mistakes(review): register lease-ceiling follow-up, trim rules bullet to pointer --- AGENTS.md | 2 +- docs/ARCHITECTURE.md | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/AGENTS.md b/AGENTS.md index ec4b842..31f70ab 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -15,7 +15,7 @@ Start with `docs/README.md`. Read `docs/IMPLEMENTATION_PLAN.md`, `docs/ARCHITECT ## Repository rules - Keep shared wire types in `crates/contracts`, and keep `schemas/*.json` in sync with them; the contract tests enforce matching fields and enum strings. -- Give every field whose checked-in schema constrains it beyond `type` (a `minLength`, a `pattern`, a numeric bound) or that carries a `deserialize_with` validator its own dedicated test, following the `*_like_the_schema` tests and `change_request_parameters_are_an_object_in_both`; schema parity compares property names, `required`, and `additionalProperties` only, whether through the `assert_object_parity` and `assert_same_shape` helpers or hand-rolled inline in `response_variants_match_schema`, `capability_fields_match_capability_schema`, and `manifest_fields_match_sidecar_schema`, so a mismatched `type` or a dropped bound otherwise stays green, several fields carry checked-in schema constraints with no dedicated test (`capability_id` among them), and `$defs.ChangeRequest.lease_seconds` in `schemas/broker-request.schema.json` is a live instance missing the `maximum` that `MAX_LEASE_SECONDS` and `schemas/experiment.schema.json` both carry, harmless at runtime because the control-plane policy check rejects an over-ceiling lease, and tracked as follow-up `fpsm-lease-ceiling-parity`. +- Give every field whose checked-in schema constrains it beyond `type` (a `minLength`, a `pattern`, a numeric bound) or that carries a `deserialize_with` validator its own dedicated test, following the `*_like_the_schema` tests and `change_request_parameters_are_an_object_in_both`; schema parity compares property names, `required`, and `additionalProperties` only, whether through `assert_object_parity` and `assert_same_shape` or hand-rolled in `response_variants_match_schema`, `capability_fields_match_capability_schema`, and `manifest_fields_match_sidecar_schema`, so a mismatched `type` or a dropped bound otherwise stays green, and several such fields have no dedicated test yet (`capability_id` among them); known parity drift is tracked in the deferred work list in `docs/ARCHITECTURE.md`. - Keep provider lifecycle behavior in `crates/provider-sdk`. - Keep the capability registry, policy, broker lifecycle, and experiment journal in `crates/control-plane`. - Keep the local IPC transport, framing, and peer-authentication seams behind traits in `crates/ipc` (Unix domain socket now, Windows named pipe later); the privileged broker in `apps/broker` composes them over the control plane and enforces peer auth, catalog policy, and single-owner-per-knob. The non-`Send` control plane is confined to one worker thread reached through a `Send` handle. diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md index aecf74a..01fd706 100644 --- a/docs/ARCHITECTURE.md +++ b/docs/ARCHITECTURE.md @@ -68,6 +68,7 @@ Deploy it under a supervisor that restarts on failure, and let the watchdog own - `fpsm-broker-splitacl`: the real split-privilege ACL, replacing the interim same-uid policy described above, plus journaling the verified peer uid and pid against each lifecycle and authenticating the client-supplied owner label against them. - Client reconnect on `Closed`: the broker closes a connection idle for 30 seconds, and `BrokerClient` holds one long-lived stream with no keepalive or reconnect, so a caller whose requests are further apart than that gets `ClientError::Closed`. Whether the client reconnects transparently, the server distinguishes a healthy idle peer from a stalled one, or callers connect per request is undecided. - `broker-dispatch-unbounded`: neither `BrokerHandle::dispatch` nor `BrokerClient::request` bounds the wait on the single control-plane worker, so a provider that blocks inside `apply` or `verify` stalls every peer rather than failing one. Deferred to the pass that adds graceful shutdown, which has to answer the same question: what a request already in flight is owed when the broker stops serving. +- `fpsm-lease-ceiling-parity`: the missing `maximum` on `$defs.ChangeRequest.lease_seconds` in `schemas/broker-request.schema.json`, which declares only a minimum while `MAX_LEASE_SECONDS` and `schemas/experiment.schema.json` both carry the ceiling, harmless at runtime because the control-plane policy check rejects an over-ceiling lease and so drift in the published contract rather than in enforcement. ### Watchdog From 41fe7a9150a75324d44ec2f7b57a298ca3d90f9a Mon Sep 17 00:00:00 2001 From: Jerry Xiao Date: Sun, 2 Aug 2026 07:15:35 +0000 Subject: [PATCH 10/33] no-mistakes(review): align doc-comment trigger, name gateway ceiling carrier --- crates/contracts/src/lib.rs | 4 +++- crates/contracts/src/test_support.rs | 4 +++- docs/ARCHITECTURE.md | 2 +- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/crates/contracts/src/lib.rs b/crates/contracts/src/lib.rs index 5d7d9cb..30b3913 100644 --- a/crates/contracts/src/lib.rs +++ b/crates/contracts/src/lib.rs @@ -491,7 +491,9 @@ mod tests { /// Asserts that two object schemas declare the same fields. /// /// Property names, the `required` list, and `additionalProperties` are - /// compared; property types and bounds are not, so each of those requires + /// compared; property types and bounds are not, so a field whose checked-in + /// schema constrains it beyond a bare `type` (a `minLength`, a `pattern`, a + /// numeric bound) or that carries a `deserialize_with` validator requires /// its own dedicated test instead. fn assert_object_parity(label: &str, generated: &Value, checked_in: &Value) { let generated_properties: BTreeSet = generated["properties"] diff --git a/crates/contracts/src/test_support.rs b/crates/contracts/src/test_support.rs index 18b3bca..8da1fc8 100644 --- a/crates/contracts/src/test_support.rs +++ b/crates/contracts/src/test_support.rs @@ -57,7 +57,9 @@ pub fn serialized_fields(value: impl serde::Serialize) -> BTreeSet { /// /// Property names, the `required` list, and `additionalProperties` are compared; /// a definition that drifts in any of the three fails the calling test. Property -/// types and bounds are not compared, so each of those requires its own +/// types and bounds are not compared, so a field whose checked-in schema +/// constrains it beyond a bare `type` (a `minLength`, a `pattern`, a numeric +/// bound) or that carries a `deserialize_with` validator requires its own /// dedicated test instead. pub fn assert_same_shape(generated: &schemars::Schema, checked_in: &Value) { let generated = serde_json::to_value(generated).expect("generated schema should serialize"); diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md index 01fd706..10c3cdf 100644 --- a/docs/ARCHITECTURE.md +++ b/docs/ARCHITECTURE.md @@ -68,7 +68,7 @@ Deploy it under a supervisor that restarts on failure, and let the watchdog own - `fpsm-broker-splitacl`: the real split-privilege ACL, replacing the interim same-uid policy described above, plus journaling the verified peer uid and pid against each lifecycle and authenticating the client-supplied owner label against them. - Client reconnect on `Closed`: the broker closes a connection idle for 30 seconds, and `BrokerClient` holds one long-lived stream with no keepalive or reconnect, so a caller whose requests are further apart than that gets `ClientError::Closed`. Whether the client reconnects transparently, the server distinguishes a healthy idle peer from a stalled one, or callers connect per request is undecided. - `broker-dispatch-unbounded`: neither `BrokerHandle::dispatch` nor `BrokerClient::request` bounds the wait on the single control-plane worker, so a provider that blocks inside `apply` or `verify` stalls every peer rather than failing one. Deferred to the pass that adds graceful shutdown, which has to answer the same question: what a request already in flight is owed when the broker stops serving. -- `fpsm-lease-ceiling-parity`: the missing `maximum` on `$defs.ChangeRequest.lease_seconds` in `schemas/broker-request.schema.json`, which declares only a minimum while `MAX_LEASE_SECONDS` and `schemas/experiment.schema.json` both carry the ceiling, harmless at runtime because the control-plane policy check rejects an over-ceiling lease and so drift in the published contract rather than in enforcement. +- `fpsm-lease-ceiling-parity`: the missing `maximum` on `$defs.ChangeRequest.lease_seconds` in `schemas/broker-request.schema.json`, which declares only a minimum while `MAX_LEASE_SECONDS` and `schemas/experiment.schema.json` both carry the ceiling, and the gateway's `tools/list` input schema, which publishes the ceiling as a bare literal that no reference to `MAX_LEASE_SECONDS` and no test binds, so raising `MAX_LEASE_SECONDS` would leave the gateway advertising a stale ceiling with the suite green. The control-plane policy check rejects an over-ceiling lease, so this is drift in the published contract rather than in enforcement. ### Watchdog From 012171b58c231c9dc83f72b8efb9df55366e1ffa Mon Sep 17 00:00:00 2001 From: Jerry Xiao Date: Sun, 2 Aug 2026 07:48:10 +0000 Subject: [PATCH 11/33] no-mistakes(review): register capability_id guard block, unframe gateway ceiling design --- AGENTS.md | 3 ++- crates/contracts/src/lib.rs | 11 +++++++---- crates/contracts/src/test_support.rs | 12 +++++++----- docs/ARCHITECTURE.md | 3 ++- 4 files changed, 18 insertions(+), 11 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 31f70ab..0c0b969 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -15,7 +15,8 @@ Start with `docs/README.md`. Read `docs/IMPLEMENTATION_PLAN.md`, `docs/ARCHITECT ## Repository rules - Keep shared wire types in `crates/contracts`, and keep `schemas/*.json` in sync with them; the contract tests enforce matching fields and enum strings. -- Give every field whose checked-in schema constrains it beyond `type` (a `minLength`, a `pattern`, a numeric bound) or that carries a `deserialize_with` validator its own dedicated test, following the `*_like_the_schema` tests and `change_request_parameters_are_an_object_in_both`; schema parity compares property names, `required`, and `additionalProperties` only, whether through `assert_object_parity` and `assert_same_shape` or hand-rolled in `response_variants_match_schema`, `capability_fields_match_capability_schema`, and `manifest_fields_match_sidecar_schema`, so a mismatched `type` or a dropped bound otherwise stays green, and several such fields have no dedicated test yet (`capability_id` among them); known parity drift is tracked in the deferred work list in `docs/ARCHITECTURE.md`. +- Give every field whose checked-in schema constrains it beyond `type` (a `minLength`, a `pattern`, a numeric bound) or that carries a `deserialize_with` validator its own dedicated test, following the `*_like_the_schema` tests and `change_request_parameters_are_an_object_in_both`. + Schema parity compares property names, `required`, and `additionalProperties` only, whether through `assert_object_parity` and `assert_same_shape` or hand-rolled in `response_variants_match_schema`, `capability_fields_match_capability_schema`, and `manifest_fields_match_sidecar_schema`, so a mismatched `type` or a dropped bound otherwise stays green; not every such field carries its test today, and where writing one is blocked rather than merely pending, as it is for `capability_id`, the block is registered as `fpsm-capid-guard` in the deferred work list in `docs/ARCHITECTURE.md`, beside `fpsm-lease-ceiling-parity` for the published lease ceiling. - Keep provider lifecycle behavior in `crates/provider-sdk`. - Keep the capability registry, policy, broker lifecycle, and experiment journal in `crates/control-plane`. - Keep the local IPC transport, framing, and peer-authentication seams behind traits in `crates/ipc` (Unix domain socket now, Windows named pipe later); the privileged broker in `apps/broker` composes them over the control plane and enforces peer auth, catalog policy, and single-owner-per-knob. The non-`Send` control plane is confined to one worker thread reached through a `Send` handle. diff --git a/crates/contracts/src/lib.rs b/crates/contracts/src/lib.rs index 30b3913..00c841e 100644 --- a/crates/contracts/src/lib.rs +++ b/crates/contracts/src/lib.rs @@ -491,10 +491,13 @@ mod tests { /// Asserts that two object schemas declare the same fields. /// /// Property names, the `required` list, and `additionalProperties` are - /// compared; property types and bounds are not, so a field whose checked-in - /// schema constrains it beyond a bare `type` (a `minLength`, a `pattern`, a - /// numeric bound) or that carries a `deserialize_with` validator requires - /// its own dedicated test instead. + /// compared; neither property types nor bounds are, so a `type` that + /// disagrees passes here just as a dropped bound does. A field whose + /// checked-in schema constrains it beyond a bare `type` (a `minLength`, a + /// `pattern`, a numeric bound) or that carries a `deserialize_with` + /// validator requires its own dedicated test instead. That rule covers the + /// narrower subset, so a field declared with nothing but a `type` stays + /// uncovered by both. fn assert_object_parity(label: &str, generated: &Value, checked_in: &Value) { let generated_properties: BTreeSet = generated["properties"] .as_object() diff --git a/crates/contracts/src/test_support.rs b/crates/contracts/src/test_support.rs index 8da1fc8..2d5fb4c 100644 --- a/crates/contracts/src/test_support.rs +++ b/crates/contracts/src/test_support.rs @@ -56,11 +56,13 @@ pub fn serialized_fields(value: impl serde::Serialize) -> BTreeSet { /// Asserts that `generated` and `checked_in` declare the same object shape. /// /// Property names, the `required` list, and `additionalProperties` are compared; -/// a definition that drifts in any of the three fails the calling test. Property -/// types and bounds are not compared, so a field whose checked-in schema -/// constrains it beyond a bare `type` (a `minLength`, a `pattern`, a numeric -/// bound) or that carries a `deserialize_with` validator requires its own -/// dedicated test instead. +/// a definition that drifts in any of the three fails the calling test. Neither +/// property types nor bounds are compared, so a `type` that disagrees passes +/// here just as a dropped bound does. A field whose checked-in schema constrains +/// it beyond a bare `type` (a `minLength`, a `pattern`, a numeric bound) or that +/// carries a `deserialize_with` validator requires its own dedicated test +/// instead. That rule covers the narrower subset, so a field declared with +/// nothing but a `type` stays uncovered by both. pub fn assert_same_shape(generated: &schemars::Schema, checked_in: &Value) { let generated = serde_json::to_value(generated).expect("generated schema should serialize"); assert_eq!(properties(&generated), properties(checked_in)); diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md index 10c3cdf..1737fc2 100644 --- a/docs/ARCHITECTURE.md +++ b/docs/ARCHITECTURE.md @@ -68,7 +68,8 @@ Deploy it under a supervisor that restarts on failure, and let the watchdog own - `fpsm-broker-splitacl`: the real split-privilege ACL, replacing the interim same-uid policy described above, plus journaling the verified peer uid and pid against each lifecycle and authenticating the client-supplied owner label against them. - Client reconnect on `Closed`: the broker closes a connection idle for 30 seconds, and `BrokerClient` holds one long-lived stream with no keepalive or reconnect, so a caller whose requests are further apart than that gets `ClientError::Closed`. Whether the client reconnects transparently, the server distinguishes a healthy idle peer from a stalled one, or callers connect per request is undecided. - `broker-dispatch-unbounded`: neither `BrokerHandle::dispatch` nor `BrokerClient::request` bounds the wait on the single control-plane worker, so a provider that blocks inside `apply` or `verify` stalls every peer rather than failing one. Deferred to the pass that adds graceful shutdown, which has to answer the same question: what a request already in flight is owed when the broker stops serving. -- `fpsm-lease-ceiling-parity`: the missing `maximum` on `$defs.ChangeRequest.lease_seconds` in `schemas/broker-request.schema.json`, which declares only a minimum while `MAX_LEASE_SECONDS` and `schemas/experiment.schema.json` both carry the ceiling, and the gateway's `tools/list` input schema, which publishes the ceiling as a bare literal that no reference to `MAX_LEASE_SECONDS` and no test binds, so raising `MAX_LEASE_SECONDS` would leave the gateway advertising a stale ceiling with the suite green. The control-plane policy check rejects an over-ceiling lease, so this is drift in the published contract rather than in enforcement. +- `fpsm-lease-ceiling-parity`: the missing `maximum` on `$defs.ChangeRequest.lease_seconds` in `schemas/broker-request.schema.json`, which declares only a minimum while `MAX_LEASE_SECONDS` and `schemas/experiment.schema.json` both carry the ceiling, and the gateway's `tools/list` input schema, which states the ceiling independently as the `MAX_LEASE_SECONDS` doc comment intends but which no test binds to that constant in agreement, so raising `MAX_LEASE_SECONDS` would leave the gateway advertising a stale ceiling with the suite green. The deferred work is the binding test, not a reference from the gateway to the constant. The control-plane policy check rejects an over-ceiling lease, so this is drift in the published contract rather than in enforcement. +- `fpsm-capid-guard`: the dedicated guard `AGENTS.md` requires for a field whose checked-in schema constrains it beyond a bare `type` cannot be written for `ChangeRequest::capability_id` today. The Rust field is a plain `String` with no constraint attribute, so the generated schema carries no constraint to compare against, and its checked-in schemas constrain it differently from each other, a `pattern` in one and a `minLength` in the other. Closing this needs the Rust type to carry the constraint and the disagreeing schemas settled onto one before a guard can be green; it is a prerequisite chain, not a missing test. ### Watchdog From 1aef468a281de548e51081cdda7dbb038bf174fe Mon Sep 17 00:00:00 2001 From: Jerry Xiao Date: Sun, 2 Aug 2026 08:06:46 +0000 Subject: [PATCH 12/33] no-mistakes(review): require parity test to bind every constraining schema --- AGENTS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AGENTS.md b/AGENTS.md index 0c0b969..a680bc2 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -15,7 +15,7 @@ Start with `docs/README.md`. Read `docs/IMPLEMENTATION_PLAN.md`, `docs/ARCHITECT ## Repository rules - Keep shared wire types in `crates/contracts`, and keep `schemas/*.json` in sync with them; the contract tests enforce matching fields and enum strings. -- Give every field whose checked-in schema constrains it beyond `type` (a `minLength`, a `pattern`, a numeric bound) or that carries a `deserialize_with` validator its own dedicated test, following the `*_like_the_schema` tests and `change_request_parameters_are_an_object_in_both`. +- Give every field whose checked-in schema constrains it beyond `type` (a `minLength`, a `pattern`, a numeric bound) or that carries a `deserialize_with` validator its own dedicated test that binds each checked-in schema carrying that constraint, not merely one of them, following the `*_like_the_schema` tests and `change_request_parameters_are_an_object_in_both`. Schema parity compares property names, `required`, and `additionalProperties` only, whether through `assert_object_parity` and `assert_same_shape` or hand-rolled in `response_variants_match_schema`, `capability_fields_match_capability_schema`, and `manifest_fields_match_sidecar_schema`, so a mismatched `type` or a dropped bound otherwise stays green; not every such field carries its test today, and where writing one is blocked rather than merely pending, as it is for `capability_id`, the block is registered as `fpsm-capid-guard` in the deferred work list in `docs/ARCHITECTURE.md`, beside `fpsm-lease-ceiling-parity` for the published lease ceiling. - Keep provider lifecycle behavior in `crates/provider-sdk`. - Keep the capability registry, policy, broker lifecycle, and experiment journal in `crates/control-plane`. From 96aff88dbf111b6cd5e2625092dd173f1f5711e0 Mon Sep 17 00:00:00 2001 From: Jerry Xiao Date: Sun, 2 Aug 2026 08:35:10 +0000 Subject: [PATCH 13/33] no-mistakes(review): clarify parity exemplars, widen capid guard to class --- AGENTS.md | 5 +++-- docs/ARCHITECTURE.md | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index a680bc2..fd3f4c7 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -15,8 +15,9 @@ Start with `docs/README.md`. Read `docs/IMPLEMENTATION_PLAN.md`, `docs/ARCHITECT ## Repository rules - Keep shared wire types in `crates/contracts`, and keep `schemas/*.json` in sync with them; the contract tests enforce matching fields and enum strings. -- Give every field whose checked-in schema constrains it beyond `type` (a `minLength`, a `pattern`, a numeric bound) or that carries a `deserialize_with` validator its own dedicated test that binds each checked-in schema carrying that constraint, not merely one of them, following the `*_like_the_schema` tests and `change_request_parameters_are_an_object_in_both`. - Schema parity compares property names, `required`, and `additionalProperties` only, whether through `assert_object_parity` and `assert_same_shape` or hand-rolled in `response_variants_match_schema`, `capability_fields_match_capability_schema`, and `manifest_fields_match_sidecar_schema`, so a mismatched `type` or a dropped bound otherwise stays green; not every such field carries its test today, and where writing one is blocked rather than merely pending, as it is for `capability_id`, the block is registered as `fpsm-capid-guard` in the deferred work list in `docs/ARCHITECTURE.md`, beside `fpsm-lease-ceiling-parity` for the published lease ceiling. +- Give every field whose checked-in schema constrains it beyond `type` (a `minLength`, a `pattern`, a numeric bound) or that carries a `deserialize_with` validator its own dedicated test that binds each checked-in schema carrying that constraint, not merely one of them; for a `deserialize_with` validator, which no checked-in schema can state, the counterpart to bind is that field's declared `type` in each schema publishing it. + The `*_like_the_schema` tests and `change_request_parameters_are_an_object_in_both` show the shape such a test takes rather than that completeness: `lease_seconds_is_bounded_like_the_schema` binds one publisher of the lease ceiling and not the other, the gap registered as `fpsm-lease-ceiling-parity`. + Schema parity compares property names, `required`, and `additionalProperties` only, whether through `assert_object_parity` and `assert_same_shape` or hand-rolled in `response_variants_match_schema`, `capability_fields_match_capability_schema`, and `manifest_fields_match_sidecar_schema`, so a mismatched `type` or a dropped bound otherwise stays green; not every such field carries its test today, and where writing one is blocked rather than merely pending, as it is for `capability_id`, the block is registered as `fpsm-capid-guard`, beside `fpsm-lease-ceiling-parity` for the published lease ceiling, in the deferred work list in `docs/ARCHITECTURE.md`. - Keep provider lifecycle behavior in `crates/provider-sdk`. - Keep the capability registry, policy, broker lifecycle, and experiment journal in `crates/control-plane`. - Keep the local IPC transport, framing, and peer-authentication seams behind traits in `crates/ipc` (Unix domain socket now, Windows named pipe later); the privileged broker in `apps/broker` composes them over the control plane and enforces peer auth, catalog policy, and single-owner-per-knob. The non-`Send` control plane is confined to one worker thread reached through a `Send` handle. diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md index 1737fc2..b7a980f 100644 --- a/docs/ARCHITECTURE.md +++ b/docs/ARCHITECTURE.md @@ -69,7 +69,7 @@ Deploy it under a supervisor that restarts on failure, and let the watchdog own - Client reconnect on `Closed`: the broker closes a connection idle for 30 seconds, and `BrokerClient` holds one long-lived stream with no keepalive or reconnect, so a caller whose requests are further apart than that gets `ClientError::Closed`. Whether the client reconnects transparently, the server distinguishes a healthy idle peer from a stalled one, or callers connect per request is undecided. - `broker-dispatch-unbounded`: neither `BrokerHandle::dispatch` nor `BrokerClient::request` bounds the wait on the single control-plane worker, so a provider that blocks inside `apply` or `verify` stalls every peer rather than failing one. Deferred to the pass that adds graceful shutdown, which has to answer the same question: what a request already in flight is owed when the broker stops serving. - `fpsm-lease-ceiling-parity`: the missing `maximum` on `$defs.ChangeRequest.lease_seconds` in `schemas/broker-request.schema.json`, which declares only a minimum while `MAX_LEASE_SECONDS` and `schemas/experiment.schema.json` both carry the ceiling, and the gateway's `tools/list` input schema, which states the ceiling independently as the `MAX_LEASE_SECONDS` doc comment intends but which no test binds to that constant in agreement, so raising `MAX_LEASE_SECONDS` would leave the gateway advertising a stale ceiling with the suite green. The deferred work is the binding test, not a reference from the gateway to the constant. The control-plane policy check rejects an over-ceiling lease, so this is drift in the published contract rather than in enforcement. -- `fpsm-capid-guard`: the dedicated guard `AGENTS.md` requires for a field whose checked-in schema constrains it beyond a bare `type` cannot be written for `ChangeRequest::capability_id` today. The Rust field is a plain `String` with no constraint attribute, so the generated schema carries no constraint to compare against, and its checked-in schemas constrain it differently from each other, a `pattern` in one and a `minLength` in the other. Closing this needs the Rust type to carry the constraint and the disagreeing schemas settled onto one before a guard can be green; it is a prerequisite chain, not a missing test. +- `fpsm-capid-guard`: the dedicated guard `AGENTS.md` requires cannot be written today for the class of field whose checked-in schema carries a constraint with no Rust-side counterpart to compare against, because the Rust field is a plain type with no constraint attribute and the generated schema therefore states nothing a guard could bind. `ChangeRequest::capability_id` is the worked example, and it carries a second blocker of its own: its checked-in schemas constrain it differently from each other, a `pattern` in one and a `minLength` in the other. Closing the class needs each such Rust type to carry its constraint, and for `capability_id` the disagreeing schemas settled onto one, before a guard can be green; it is a prerequisite chain, not a missing test. ### Watchdog From 213ca4a57e28faab5e3585e5368fdfc23fac5638 Mon Sep 17 00:00:00 2001 From: Jerry Xiao Date: Sun, 2 Aug 2026 09:02:02 +0000 Subject: [PATCH 14/33] no-mistakes(review): widen ceiling-parity register to class, sync parity doc comments --- AGENTS.md | 4 ++-- crates/contracts/src/lib.rs | 9 ++++++--- crates/contracts/src/test_support.rs | 8 ++++++-- docs/ARCHITECTURE.md | 2 +- 4 files changed, 15 insertions(+), 8 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index fd3f4c7..894a8f4 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -16,8 +16,8 @@ Start with `docs/README.md`. Read `docs/IMPLEMENTATION_PLAN.md`, `docs/ARCHITECT - Keep shared wire types in `crates/contracts`, and keep `schemas/*.json` in sync with them; the contract tests enforce matching fields and enum strings. - Give every field whose checked-in schema constrains it beyond `type` (a `minLength`, a `pattern`, a numeric bound) or that carries a `deserialize_with` validator its own dedicated test that binds each checked-in schema carrying that constraint, not merely one of them; for a `deserialize_with` validator, which no checked-in schema can state, the counterpart to bind is that field's declared `type` in each schema publishing it. - The `*_like_the_schema` tests and `change_request_parameters_are_an_object_in_both` show the shape such a test takes rather than that completeness: `lease_seconds_is_bounded_like_the_schema` binds one publisher of the lease ceiling and not the other, the gap registered as `fpsm-lease-ceiling-parity`. - Schema parity compares property names, `required`, and `additionalProperties` only, whether through `assert_object_parity` and `assert_same_shape` or hand-rolled in `response_variants_match_schema`, `capability_fields_match_capability_schema`, and `manifest_fields_match_sidecar_schema`, so a mismatched `type` or a dropped bound otherwise stays green; not every such field carries its test today, and where writing one is blocked rather than merely pending, as it is for `capability_id`, the block is registered as `fpsm-capid-guard`, beside `fpsm-lease-ceiling-parity` for the published lease ceiling, in the deferred work list in `docs/ARCHITECTURE.md`. + A test binds a schema by opening the checked-in file and asserting the constraint there, as `protocol_version_zero_is_rejected_like_the_schema` and `the_hypothesis_is_bounded_like_the_schema` do, and as `change_request_parameters_are_an_object_in_both` does for a declared `type`; a sibling that only asserts what the Rust type rejects binds nothing and is not the pattern to copy. Those binders show the shape such a test takes rather than that completeness: `lease_seconds_is_bounded_like_the_schema` binds fewer publishers of the lease ceiling than carry it, the class registered as `fpsm-lease-ceiling-parity`. + Schema parity compares property names, `required`, and `additionalProperties` only, whether through `assert_object_parity` and `assert_same_shape` or hand-rolled in `response_variants_match_schema`, `capability_fields_match_capability_schema`, and `manifest_fields_match_sidecar_schema`, so a mismatched `type` or a dropped bound otherwise stays green; not every such field carries its test today, and where writing one is blocked rather than merely pending, as it is for `capability_id`, the block is registered as `fpsm-capid-guard`, beside `fpsm-lease-ceiling-parity` for a test that binds fewer publishers of a constraint than carry it, in the deferred work list in `docs/ARCHITECTURE.md`. - Keep provider lifecycle behavior in `crates/provider-sdk`. - Keep the capability registry, policy, broker lifecycle, and experiment journal in `crates/control-plane`. - Keep the local IPC transport, framing, and peer-authentication seams behind traits in `crates/ipc` (Unix domain socket now, Windows named pipe later); the privileged broker in `apps/broker` composes them over the control plane and enforces peer auth, catalog policy, and single-owner-per-knob. The non-`Send` control plane is confined to one worker thread reached through a `Send` handle. diff --git a/crates/contracts/src/lib.rs b/crates/contracts/src/lib.rs index 00c841e..94c20e1 100644 --- a/crates/contracts/src/lib.rs +++ b/crates/contracts/src/lib.rs @@ -495,9 +495,12 @@ mod tests { /// disagrees passes here just as a dropped bound does. A field whose /// checked-in schema constrains it beyond a bare `type` (a `minLength`, a /// `pattern`, a numeric bound) or that carries a `deserialize_with` - /// validator requires its own dedicated test instead. That rule covers the - /// narrower subset, so a field declared with nothing but a `type` stays - /// uncovered by both. + /// validator requires its own dedicated test instead, one that binds each + /// checked-in schema carrying that constraint rather than merely one of + /// them; for a `deserialize_with` validator, which no checked-in schema can + /// state, the counterpart to bind is that field's declared `type` in each + /// schema publishing it. That rule covers the narrower subset, so a field + /// declared with nothing but a `type` stays uncovered by both. fn assert_object_parity(label: &str, generated: &Value, checked_in: &Value) { let generated_properties: BTreeSet = generated["properties"] .as_object() diff --git a/crates/contracts/src/test_support.rs b/crates/contracts/src/test_support.rs index 2d5fb4c..17b3bf5 100644 --- a/crates/contracts/src/test_support.rs +++ b/crates/contracts/src/test_support.rs @@ -61,8 +61,12 @@ pub fn serialized_fields(value: impl serde::Serialize) -> BTreeSet { /// here just as a dropped bound does. A field whose checked-in schema constrains /// it beyond a bare `type` (a `minLength`, a `pattern`, a numeric bound) or that /// carries a `deserialize_with` validator requires its own dedicated test -/// instead. That rule covers the narrower subset, so a field declared with -/// nothing but a `type` stays uncovered by both. +/// instead, one that binds each checked-in schema carrying that constraint +/// rather than merely one of them; for a `deserialize_with` validator, which no +/// checked-in schema can state, the counterpart to bind is that field's +/// declared `type` in each schema publishing it. That rule covers the narrower +/// subset, so a field declared with nothing but a `type` stays uncovered by +/// both. pub fn assert_same_shape(generated: &schemars::Schema, checked_in: &Value) { let generated = serde_json::to_value(generated).expect("generated schema should serialize"); assert_eq!(properties(&generated), properties(checked_in)); diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md index b7a980f..1df654c 100644 --- a/docs/ARCHITECTURE.md +++ b/docs/ARCHITECTURE.md @@ -68,7 +68,7 @@ Deploy it under a supervisor that restarts on failure, and let the watchdog own - `fpsm-broker-splitacl`: the real split-privilege ACL, replacing the interim same-uid policy described above, plus journaling the verified peer uid and pid against each lifecycle and authenticating the client-supplied owner label against them. - Client reconnect on `Closed`: the broker closes a connection idle for 30 seconds, and `BrokerClient` holds one long-lived stream with no keepalive or reconnect, so a caller whose requests are further apart than that gets `ClientError::Closed`. Whether the client reconnects transparently, the server distinguishes a healthy idle peer from a stalled one, or callers connect per request is undecided. - `broker-dispatch-unbounded`: neither `BrokerHandle::dispatch` nor `BrokerClient::request` bounds the wait on the single control-plane worker, so a provider that blocks inside `apply` or `verify` stalls every peer rather than failing one. Deferred to the pass that adds graceful shutdown, which has to answer the same question: what a request already in flight is owed when the broker stops serving. -- `fpsm-lease-ceiling-parity`: the missing `maximum` on `$defs.ChangeRequest.lease_seconds` in `schemas/broker-request.schema.json`, which declares only a minimum while `MAX_LEASE_SECONDS` and `schemas/experiment.schema.json` both carry the ceiling, and the gateway's `tools/list` input schema, which states the ceiling independently as the `MAX_LEASE_SECONDS` doc comment intends but which no test binds to that constant in agreement, so raising `MAX_LEASE_SECONDS` would leave the gateway advertising a stale ceiling with the suite green. The deferred work is the binding test, not a reference from the gateway to the constant. The control-plane policy check rejects an over-ceiling lease, so this is drift in the published contract rather than in enforcement. +- `fpsm-lease-ceiling-parity`: the class of constraint published by more than one checked-in schema whose dedicated test binds only one of them, leaving the unbound publishers free to drift with the suite green. The lease ceiling is the worked example: `schemas/broker-request.schema.json` declares only a minimum on `$defs.ChangeRequest.lease_seconds` while `MAX_LEASE_SECONDS` and `schemas/experiment.schema.json` both carry the ceiling, `lease_seconds_is_bounded_like_the_schema` binds the experiment schema alone, and the gateway's `tools/list` input schema states the ceiling independently as the `MAX_LEASE_SECONDS` doc comment intends but no test binds it to that constant in agreement, so raising `MAX_LEASE_SECONDS` would leave the gateway advertising a stale ceiling. `ChangeRequest::parameters` is a second instance: `change_request_parameters_are_an_object_in_both` binds the broker request schema and the generated schema, while `schemas/experiment.schema.json` publishes the same field's declared `type` and nothing opens it. The deferred work is the binding tests, not a reference from the gateway to the constant. The control-plane policy check rejects an over-ceiling lease, so the lease half is drift in the published contract rather than in enforcement. - `fpsm-capid-guard`: the dedicated guard `AGENTS.md` requires cannot be written today for the class of field whose checked-in schema carries a constraint with no Rust-side counterpart to compare against, because the Rust field is a plain type with no constraint attribute and the generated schema therefore states nothing a guard could bind. `ChangeRequest::capability_id` is the worked example, and it carries a second blocker of its own: its checked-in schemas constrain it differently from each other, a `pattern` in one and a `minLength` in the other. Closing the class needs each such Rust type to carry its constraint, and for `capability_id` the disagreeing schemas settled onto one, before a guard can be green; it is a prerequisite chain, not a missing test. ### Watchdog From bf91e177dbbe3b48610ed40363f0e5f100f0b0ed Mon Sep 17 00:00:00 2001 From: Jerry Xiao Date: Sun, 2 Aug 2026 09:18:04 +0000 Subject: [PATCH 15/33] no-mistakes(review): split unbound-carrier parity class from lease-ceiling drift entry --- AGENTS.md | 4 ++-- docs/ARCHITECTURE.md | 5 +++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 894a8f4..9992ca6 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -16,8 +16,8 @@ Start with `docs/README.md`. Read `docs/IMPLEMENTATION_PLAN.md`, `docs/ARCHITECT - Keep shared wire types in `crates/contracts`, and keep `schemas/*.json` in sync with them; the contract tests enforce matching fields and enum strings. - Give every field whose checked-in schema constrains it beyond `type` (a `minLength`, a `pattern`, a numeric bound) or that carries a `deserialize_with` validator its own dedicated test that binds each checked-in schema carrying that constraint, not merely one of them; for a `deserialize_with` validator, which no checked-in schema can state, the counterpart to bind is that field's declared `type` in each schema publishing it. - A test binds a schema by opening the checked-in file and asserting the constraint there, as `protocol_version_zero_is_rejected_like_the_schema` and `the_hypothesis_is_bounded_like_the_schema` do, and as `change_request_parameters_are_an_object_in_both` does for a declared `type`; a sibling that only asserts what the Rust type rejects binds nothing and is not the pattern to copy. Those binders show the shape such a test takes rather than that completeness: `lease_seconds_is_bounded_like_the_schema` binds fewer publishers of the lease ceiling than carry it, the class registered as `fpsm-lease-ceiling-parity`. - Schema parity compares property names, `required`, and `additionalProperties` only, whether through `assert_object_parity` and `assert_same_shape` or hand-rolled in `response_variants_match_schema`, `capability_fields_match_capability_schema`, and `manifest_fields_match_sidecar_schema`, so a mismatched `type` or a dropped bound otherwise stays green; not every such field carries its test today, and where writing one is blocked rather than merely pending, as it is for `capability_id`, the block is registered as `fpsm-capid-guard`, beside `fpsm-lease-ceiling-parity` for a test that binds fewer publishers of a constraint than carry it, in the deferred work list in `docs/ARCHITECTURE.md`. + A test binds a schema by opening the checked-in file and asserting the constraint there, as `protocol_version_zero_is_rejected_like_the_schema` and `the_hypothesis_is_bounded_like_the_schema` do, and as `change_request_parameters_are_an_object_in_both` does for a declared `type`; a sibling that only asserts what the Rust type rejects binds nothing and is not the pattern to copy. Those binders show the shape such a test takes rather than that completeness: that last one binds fewer checked-in schemas than carry the declared `type` it asserts, the class registered as `fpsm-unbound-carrier-parity`. + Schema parity compares property names, `required`, and `additionalProperties` only, whether through `assert_object_parity` and `assert_same_shape` or hand-rolled in `response_variants_match_schema`, `capability_fields_match_capability_schema`, and `manifest_fields_match_sidecar_schema`, so a mismatched `type` or a dropped bound otherwise stays green; not every such field carries its test today, and where writing one is blocked rather than merely pending, as it is for `capability_id`, the block is registered as `fpsm-capid-guard`, beside `fpsm-unbound-carrier-parity` for a test that binds fewer checked-in schemas than carry a constraint, in the deferred work list in `docs/ARCHITECTURE.md`. - Keep provider lifecycle behavior in `crates/provider-sdk`. - Keep the capability registry, policy, broker lifecycle, and experiment journal in `crates/control-plane`. - Keep the local IPC transport, framing, and peer-authentication seams behind traits in `crates/ipc` (Unix domain socket now, Windows named pipe later); the privileged broker in `apps/broker` composes them over the control plane and enforces peer auth, catalog policy, and single-owner-per-knob. The non-`Send` control plane is confined to one worker thread reached through a `Send` handle. diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md index 1df654c..5c37b17 100644 --- a/docs/ARCHITECTURE.md +++ b/docs/ARCHITECTURE.md @@ -68,8 +68,9 @@ Deploy it under a supervisor that restarts on failure, and let the watchdog own - `fpsm-broker-splitacl`: the real split-privilege ACL, replacing the interim same-uid policy described above, plus journaling the verified peer uid and pid against each lifecycle and authenticating the client-supplied owner label against them. - Client reconnect on `Closed`: the broker closes a connection idle for 30 seconds, and `BrokerClient` holds one long-lived stream with no keepalive or reconnect, so a caller whose requests are further apart than that gets `ClientError::Closed`. Whether the client reconnects transparently, the server distinguishes a healthy idle peer from a stalled one, or callers connect per request is undecided. - `broker-dispatch-unbounded`: neither `BrokerHandle::dispatch` nor `BrokerClient::request` bounds the wait on the single control-plane worker, so a provider that blocks inside `apply` or `verify` stalls every peer rather than failing one. Deferred to the pass that adds graceful shutdown, which has to answer the same question: what a request already in flight is owed when the broker stops serving. -- `fpsm-lease-ceiling-parity`: the class of constraint published by more than one checked-in schema whose dedicated test binds only one of them, leaving the unbound publishers free to drift with the suite green. The lease ceiling is the worked example: `schemas/broker-request.schema.json` declares only a minimum on `$defs.ChangeRequest.lease_seconds` while `MAX_LEASE_SECONDS` and `schemas/experiment.schema.json` both carry the ceiling, `lease_seconds_is_bounded_like_the_schema` binds the experiment schema alone, and the gateway's `tools/list` input schema states the ceiling independently as the `MAX_LEASE_SECONDS` doc comment intends but no test binds it to that constant in agreement, so raising `MAX_LEASE_SECONDS` would leave the gateway advertising a stale ceiling. `ChangeRequest::parameters` is a second instance: `change_request_parameters_are_an_object_in_both` binds the broker request schema and the generated schema, while `schemas/experiment.schema.json` publishes the same field's declared `type` and nothing opens it. The deferred work is the binding tests, not a reference from the gateway to the constant. The control-plane policy check rejects an over-ceiling lease, so the lease half is drift in the published contract rather than in enforcement. -- `fpsm-capid-guard`: the dedicated guard `AGENTS.md` requires cannot be written today for the class of field whose checked-in schema carries a constraint with no Rust-side counterpart to compare against, because the Rust field is a plain type with no constraint attribute and the generated schema therefore states nothing a guard could bind. `ChangeRequest::capability_id` is the worked example, and it carries a second blocker of its own: its checked-in schemas constrain it differently from each other, a `pattern` in one and a `minLength` in the other. Closing the class needs each such Rust type to carry its constraint, and for `capability_id` the disagreeing schemas settled onto one, before a guard can be green; it is a prerequisite chain, not a missing test. +- `fpsm-lease-ceiling-parity`: the missing `maximum` on `$defs.ChangeRequest.lease_seconds` in `schemas/broker-request.schema.json`, which declares only a minimum while `MAX_LEASE_SECONDS` and `schemas/experiment.schema.json` both carry the ceiling, and the gateway's `tools/list` input schema, which states the ceiling independently as the `MAX_LEASE_SECONDS` doc comment intends but which no test binds to that constant in agreement, so raising `MAX_LEASE_SECONDS` would leave the gateway advertising a stale ceiling with the suite green. The deferred work is the binding test, not a reference from the gateway to the constant. The control-plane policy check rejects an over-ceiling lease, so this is drift in the published contract rather than in enforcement. +- `fpsm-unbound-carrier-parity`: the class of constraint carried by more than one checked-in schema whose dedicated test binds only one of them, leaving the unbound carriers free to drift with the suite green. The lease floor is the worked example: `schemas/broker-request.schema.json` and `schemas/experiment.schema.json` declare the same minimum on `$defs.ChangeRequest.lease_seconds`, and no test binds that minimum in either - `lease_seconds_is_bounded_like_the_schema` asserts only the ceiling, and `lease_seconds_zero_is_rejected` asserts only what the Rust type rejects, which binds nothing. `ChangeRequest::parameters` is a second instance: `change_request_parameters_are_an_object_in_both` binds the broker request schema and the generated schema, while `schemas/experiment.schema.json` publishes the same field's declared `type` and nothing opens it. +- `fpsm-capid-guard`: the dedicated guard `AGENTS.md` requires cannot prove parity today for the class of field whose checked-in schema carries a constraint with no Rust-side counterpart to compare against, because the Rust field is a plain type with no constraint attribute and the generated schema therefore states nothing a guard could hold the checked-in constraint against. A guard that opens the checked-in file and asserts the constraint is writable today, but it pins that file against itself and proves no parity. `ChangeRequest::capability_id` is the worked example, and it carries a second blocker of its own: its checked-in schemas constrain it differently from each other, a `pattern` in one and a `minLength` in the other. Closing the class needs each such Rust type to carry its constraint, and for `capability_id` the disagreeing schemas settled onto one, before a guard can prove parity; it is a prerequisite chain, not a missing test. ### Watchdog From 0fc2955e2c38416db757216e1fdbbad54ab8db5b Mon Sep 17 00:00:00 2001 From: Jerry Xiao Date: Sun, 2 Aug 2026 09:32:54 +0000 Subject: [PATCH 16/33] no-mistakes(review): fix parity register pointers, headline, and stale-ceiling precondition --- AGENTS.md | 2 +- docs/ARCHITECTURE.md | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 9992ca6..fd0c3e8 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -17,7 +17,7 @@ Start with `docs/README.md`. Read `docs/IMPLEMENTATION_PLAN.md`, `docs/ARCHITECT - Keep shared wire types in `crates/contracts`, and keep `schemas/*.json` in sync with them; the contract tests enforce matching fields and enum strings. - Give every field whose checked-in schema constrains it beyond `type` (a `minLength`, a `pattern`, a numeric bound) or that carries a `deserialize_with` validator its own dedicated test that binds each checked-in schema carrying that constraint, not merely one of them; for a `deserialize_with` validator, which no checked-in schema can state, the counterpart to bind is that field's declared `type` in each schema publishing it. A test binds a schema by opening the checked-in file and asserting the constraint there, as `protocol_version_zero_is_rejected_like_the_schema` and `the_hypothesis_is_bounded_like_the_schema` do, and as `change_request_parameters_are_an_object_in_both` does for a declared `type`; a sibling that only asserts what the Rust type rejects binds nothing and is not the pattern to copy. Those binders show the shape such a test takes rather than that completeness: that last one binds fewer checked-in schemas than carry the declared `type` it asserts, the class registered as `fpsm-unbound-carrier-parity`. - Schema parity compares property names, `required`, and `additionalProperties` only, whether through `assert_object_parity` and `assert_same_shape` or hand-rolled in `response_variants_match_schema`, `capability_fields_match_capability_schema`, and `manifest_fields_match_sidecar_schema`, so a mismatched `type` or a dropped bound otherwise stays green; not every such field carries its test today, and where writing one is blocked rather than merely pending, as it is for `capability_id`, the block is registered as `fpsm-capid-guard`, beside `fpsm-unbound-carrier-parity` for a test that binds fewer checked-in schemas than carry a constraint, in the deferred work list in `docs/ARCHITECTURE.md`. + Schema parity compares property names, `required`, and `additionalProperties` only, whether through `assert_object_parity` and `assert_same_shape` or hand-rolled in `response_variants_match_schema`, `capability_fields_match_capability_schema`, and `manifest_fields_match_sidecar_schema`, so a mismatched `type` or a dropped bound otherwise stays green; not every such field carries its test today, and where writing one is blocked rather than merely pending, as it is for `capability_id`, the block is registered as `fpsm-capid-guard`, beside `fpsm-unbound-carrier-parity`, in the deferred work list in `docs/ARCHITECTURE.md`. - Keep provider lifecycle behavior in `crates/provider-sdk`. - Keep the capability registry, policy, broker lifecycle, and experiment journal in `crates/control-plane`. - Keep the local IPC transport, framing, and peer-authentication seams behind traits in `crates/ipc` (Unix domain socket now, Windows named pipe later); the privileged broker in `apps/broker` composes them over the control plane and enforces peer auth, catalog policy, and single-owner-per-knob. The non-`Send` control plane is confined to one worker thread reached through a `Send` handle. diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md index 5c37b17..9b9da89 100644 --- a/docs/ARCHITECTURE.md +++ b/docs/ARCHITECTURE.md @@ -68,8 +68,8 @@ Deploy it under a supervisor that restarts on failure, and let the watchdog own - `fpsm-broker-splitacl`: the real split-privilege ACL, replacing the interim same-uid policy described above, plus journaling the verified peer uid and pid against each lifecycle and authenticating the client-supplied owner label against them. - Client reconnect on `Closed`: the broker closes a connection idle for 30 seconds, and `BrokerClient` holds one long-lived stream with no keepalive or reconnect, so a caller whose requests are further apart than that gets `ClientError::Closed`. Whether the client reconnects transparently, the server distinguishes a healthy idle peer from a stalled one, or callers connect per request is undecided. - `broker-dispatch-unbounded`: neither `BrokerHandle::dispatch` nor `BrokerClient::request` bounds the wait on the single control-plane worker, so a provider that blocks inside `apply` or `verify` stalls every peer rather than failing one. Deferred to the pass that adds graceful shutdown, which has to answer the same question: what a request already in flight is owed when the broker stops serving. -- `fpsm-lease-ceiling-parity`: the missing `maximum` on `$defs.ChangeRequest.lease_seconds` in `schemas/broker-request.schema.json`, which declares only a minimum while `MAX_LEASE_SECONDS` and `schemas/experiment.schema.json` both carry the ceiling, and the gateway's `tools/list` input schema, which states the ceiling independently as the `MAX_LEASE_SECONDS` doc comment intends but which no test binds to that constant in agreement, so raising `MAX_LEASE_SECONDS` would leave the gateway advertising a stale ceiling with the suite green. The deferred work is the binding test, not a reference from the gateway to the constant. The control-plane policy check rejects an over-ceiling lease, so this is drift in the published contract rather than in enforcement. -- `fpsm-unbound-carrier-parity`: the class of constraint carried by more than one checked-in schema whose dedicated test binds only one of them, leaving the unbound carriers free to drift with the suite green. The lease floor is the worked example: `schemas/broker-request.schema.json` and `schemas/experiment.schema.json` declare the same minimum on `$defs.ChangeRequest.lease_seconds`, and no test binds that minimum in either - `lease_seconds_is_bounded_like_the_schema` asserts only the ceiling, and `lease_seconds_zero_is_rejected` asserts only what the Rust type rejects, which binds nothing. `ChangeRequest::parameters` is a second instance: `change_request_parameters_are_an_object_in_both` binds the broker request schema and the generated schema, while `schemas/experiment.schema.json` publishes the same field's declared `type` and nothing opens it. +- `fpsm-lease-ceiling-parity`: the missing `maximum` on `$defs.ChangeRequest.lease_seconds` in `schemas/broker-request.schema.json`, which declares only a minimum while `MAX_LEASE_SECONDS` and the change request lease in `schemas/experiment.schema.json` both carry the ceiling, and the gateway's `tools/list` input schema, which states the ceiling independently as the `MAX_LEASE_SECONDS` doc comment intends but which no test binds to that constant in agreement. Raising `MAX_LEASE_SECONDS` on its own is caught: within `lease_seconds_is_bounded_like_the_schema` the assertion comparing the checked-in experiment literal against the constant fails the moment the constant moves, while the assertion comparing the generated value against that same constant moves with it and stays green. Once the experiment schema has been brought along, nothing is left to fail and the gateway advertises a stale ceiling with the suite green. The deferred work is the binding test, not a reference from the gateway to the constant. The control-plane policy check rejects an over-ceiling lease, so this is drift in the published contract rather than in enforcement. +- `fpsm-unbound-carrier-parity`: the class of constraint carried by more than one checked-in schema whose dedicated test binds fewer of those carriers than carry it, leaving the unbound carriers free to drift with the suite green. The quantifier ranges over each checked-in schema carrying the triggering constraint, read per constraint rather than per field, so one field can be compliant for one of its constraints and not for another, and a carried constraint no test binds at all is inside the class. The lease floor is the worked example: the change request lease declares the same minimum under `$defs.ChangeRequest` in `schemas/broker-request.schema.json` and under `$defs.change_request` in `schemas/experiment.schema.json`, and no test binds that minimum in either - `lease_seconds_is_bounded_like_the_schema` asserts only the ceiling, and `lease_seconds_zero_is_rejected` asserts only what the Rust type rejects, which binds nothing. That same field is compliant for its ceiling, which every checked-in schema carrying it binds. `ChangeRequest::parameters` is a second instance: `change_request_parameters_are_an_object_in_both` binds the broker request schema and the generated schema, while `schemas/experiment.schema.json` publishes the same field's declared `type` and nothing opens it. - `fpsm-capid-guard`: the dedicated guard `AGENTS.md` requires cannot prove parity today for the class of field whose checked-in schema carries a constraint with no Rust-side counterpart to compare against, because the Rust field is a plain type with no constraint attribute and the generated schema therefore states nothing a guard could hold the checked-in constraint against. A guard that opens the checked-in file and asserts the constraint is writable today, but it pins that file against itself and proves no parity. `ChangeRequest::capability_id` is the worked example, and it carries a second blocker of its own: its checked-in schemas constrain it differently from each other, a `pattern` in one and a `minLength` in the other. Closing the class needs each such Rust type to carry its constraint, and for `capability_id` the disagreeing schemas settled onto one, before a guard can prove parity; it is a prerequisite chain, not a missing test. ### Watchdog From 2d18577f968de635d7d474dd30d037f83b815df1 Mon Sep 17 00:00:00 2001 From: Jerry Xiao Date: Sun, 2 Aug 2026 09:57:39 +0000 Subject: [PATCH 17/33] no-mistakes(review): register pending parity class, drop contradicting doc-comment residual --- AGENTS.md | 2 +- crates/contracts/src/lib.rs | 3 +-- crates/contracts/src/test_support.rs | 4 +--- docs/ARCHITECTURE.md | 2 +- 4 files changed, 4 insertions(+), 7 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index fd0c3e8..ca61d34 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -17,7 +17,7 @@ Start with `docs/README.md`. Read `docs/IMPLEMENTATION_PLAN.md`, `docs/ARCHITECT - Keep shared wire types in `crates/contracts`, and keep `schemas/*.json` in sync with them; the contract tests enforce matching fields and enum strings. - Give every field whose checked-in schema constrains it beyond `type` (a `minLength`, a `pattern`, a numeric bound) or that carries a `deserialize_with` validator its own dedicated test that binds each checked-in schema carrying that constraint, not merely one of them; for a `deserialize_with` validator, which no checked-in schema can state, the counterpart to bind is that field's declared `type` in each schema publishing it. A test binds a schema by opening the checked-in file and asserting the constraint there, as `protocol_version_zero_is_rejected_like_the_schema` and `the_hypothesis_is_bounded_like_the_schema` do, and as `change_request_parameters_are_an_object_in_both` does for a declared `type`; a sibling that only asserts what the Rust type rejects binds nothing and is not the pattern to copy. Those binders show the shape such a test takes rather than that completeness: that last one binds fewer checked-in schemas than carry the declared `type` it asserts, the class registered as `fpsm-unbound-carrier-parity`. - Schema parity compares property names, `required`, and `additionalProperties` only, whether through `assert_object_parity` and `assert_same_shape` or hand-rolled in `response_variants_match_schema`, `capability_fields_match_capability_schema`, and `manifest_fields_match_sidecar_schema`, so a mismatched `type` or a dropped bound otherwise stays green; not every such field carries its test today, and where writing one is blocked rather than merely pending, as it is for `capability_id`, the block is registered as `fpsm-capid-guard`, beside `fpsm-unbound-carrier-parity`, in the deferred work list in `docs/ARCHITECTURE.md`. + Schema parity compares property names, `required`, and `additionalProperties` only, whether through `assert_object_parity` and `assert_same_shape` or hand-rolled in `response_variants_match_schema`, `capability_fields_match_capability_schema`, and `manifest_fields_match_sidecar_schema`, so a mismatched `type` or a dropped bound otherwise stays green; not every such field carries its test today, and that gap is registered in the deferred work list in `docs/ARCHITECTURE.md` as `fpsm-capid-guard` where writing the guard is blocked, as it is for `capability_id`, and as `fpsm-unbound-carrier-parity` where it is merely pending. - Keep provider lifecycle behavior in `crates/provider-sdk`. - Keep the capability registry, policy, broker lifecycle, and experiment journal in `crates/control-plane`. - Keep the local IPC transport, framing, and peer-authentication seams behind traits in `crates/ipc` (Unix domain socket now, Windows named pipe later); the privileged broker in `apps/broker` composes them over the control plane and enforces peer auth, catalog policy, and single-owner-per-knob. The non-`Send` control plane is confined to one worker thread reached through a `Send` handle. diff --git a/crates/contracts/src/lib.rs b/crates/contracts/src/lib.rs index 94c20e1..cbccfd5 100644 --- a/crates/contracts/src/lib.rs +++ b/crates/contracts/src/lib.rs @@ -499,8 +499,7 @@ mod tests { /// checked-in schema carrying that constraint rather than merely one of /// them; for a `deserialize_with` validator, which no checked-in schema can /// state, the counterpart to bind is that field's declared `type` in each - /// schema publishing it. That rule covers the narrower subset, so a field - /// declared with nothing but a `type` stays uncovered by both. + /// schema publishing it. fn assert_object_parity(label: &str, generated: &Value, checked_in: &Value) { let generated_properties: BTreeSet = generated["properties"] .as_object() diff --git a/crates/contracts/src/test_support.rs b/crates/contracts/src/test_support.rs index 17b3bf5..8877231 100644 --- a/crates/contracts/src/test_support.rs +++ b/crates/contracts/src/test_support.rs @@ -64,9 +64,7 @@ pub fn serialized_fields(value: impl serde::Serialize) -> BTreeSet { /// instead, one that binds each checked-in schema carrying that constraint /// rather than merely one of them; for a `deserialize_with` validator, which no /// checked-in schema can state, the counterpart to bind is that field's -/// declared `type` in each schema publishing it. That rule covers the narrower -/// subset, so a field declared with nothing but a `type` stays uncovered by -/// both. +/// declared `type` in each schema publishing it. pub fn assert_same_shape(generated: &schemars::Schema, checked_in: &Value) { let generated = serde_json::to_value(generated).expect("generated schema should serialize"); assert_eq!(properties(&generated), properties(checked_in)); diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md index 9b9da89..1dbdf0e 100644 --- a/docs/ARCHITECTURE.md +++ b/docs/ARCHITECTURE.md @@ -69,7 +69,7 @@ Deploy it under a supervisor that restarts on failure, and let the watchdog own - Client reconnect on `Closed`: the broker closes a connection idle for 30 seconds, and `BrokerClient` holds one long-lived stream with no keepalive or reconnect, so a caller whose requests are further apart than that gets `ClientError::Closed`. Whether the client reconnects transparently, the server distinguishes a healthy idle peer from a stalled one, or callers connect per request is undecided. - `broker-dispatch-unbounded`: neither `BrokerHandle::dispatch` nor `BrokerClient::request` bounds the wait on the single control-plane worker, so a provider that blocks inside `apply` or `verify` stalls every peer rather than failing one. Deferred to the pass that adds graceful shutdown, which has to answer the same question: what a request already in flight is owed when the broker stops serving. - `fpsm-lease-ceiling-parity`: the missing `maximum` on `$defs.ChangeRequest.lease_seconds` in `schemas/broker-request.schema.json`, which declares only a minimum while `MAX_LEASE_SECONDS` and the change request lease in `schemas/experiment.schema.json` both carry the ceiling, and the gateway's `tools/list` input schema, which states the ceiling independently as the `MAX_LEASE_SECONDS` doc comment intends but which no test binds to that constant in agreement. Raising `MAX_LEASE_SECONDS` on its own is caught: within `lease_seconds_is_bounded_like_the_schema` the assertion comparing the checked-in experiment literal against the constant fails the moment the constant moves, while the assertion comparing the generated value against that same constant moves with it and stays green. Once the experiment schema has been brought along, nothing is left to fail and the gateway advertises a stale ceiling with the suite green. The deferred work is the binding test, not a reference from the gateway to the constant. The control-plane policy check rejects an over-ceiling lease, so this is drift in the published contract rather than in enforcement. -- `fpsm-unbound-carrier-parity`: the class of constraint carried by more than one checked-in schema whose dedicated test binds fewer of those carriers than carry it, leaving the unbound carriers free to drift with the suite green. The quantifier ranges over each checked-in schema carrying the triggering constraint, read per constraint rather than per field, so one field can be compliant for one of its constraints and not for another, and a carried constraint no test binds at all is inside the class. The lease floor is the worked example: the change request lease declares the same minimum under `$defs.ChangeRequest` in `schemas/broker-request.schema.json` and under `$defs.change_request` in `schemas/experiment.schema.json`, and no test binds that minimum in either - `lease_seconds_is_bounded_like_the_schema` asserts only the ceiling, and `lease_seconds_zero_is_rejected` asserts only what the Rust type rejects, which binds nothing. That same field is compliant for its ceiling, which every checked-in schema carrying it binds. `ChangeRequest::parameters` is a second instance: `change_request_parameters_are_an_object_in_both` binds the broker request schema and the generated schema, while `schemas/experiment.schema.json` publishes the same field's declared `type` and nothing opens it. +- `fpsm-unbound-carrier-parity`: the class of constraint whose dedicated test binds fewer checked-in schemas than carry it, leaving the unbound carriers free to drift with the suite green. The quantifier ranges over each checked-in schema carrying the triggering constraint, read per constraint rather than per field, so one field can be compliant for one of its constraints and not for another, and a carried constraint no test binds at all is inside the class whether a lone schema carries it or several do. What separates this class from `fpsm-capid-guard` is that the Rust field here does carry the counterpart - `schemars` emits the bound on the generated side - so a guard that proves parity is writable today and the work is pending rather than blocked. The lease floor is the worked example: the change request lease declares the same minimum under `$defs.ChangeRequest` in `schemas/broker-request.schema.json` and under `$defs.change_request` in `schemas/experiment.schema.json`, and no test binds that minimum in either - `lease_seconds_is_bounded_like_the_schema` asserts only the ceiling, and `lease_seconds_zero_is_rejected` asserts only what the Rust type rejects, which binds nothing. That same field is compliant for its ceiling, which every checked-in schema carrying it binds. `ChangeRequest::parameters` is a second instance: `change_request_parameters_are_an_object_in_both` binds the broker request schema and the generated schema, while `schemas/experiment.schema.json` publishes the same field's declared `type` and nothing opens it. A lone carrier falls in the same way: `DecisionBounds::min_samples` declares its minimum in `schemas/experiment.schema.json` alone, and `decision_bounds_are_bounded_like_the_schema` skips that keyword while binding the improvement floor and the exclusive minimums beside it out of the same envelope, so the hole is per keyword in a table that demonstrably does floors. - `fpsm-capid-guard`: the dedicated guard `AGENTS.md` requires cannot prove parity today for the class of field whose checked-in schema carries a constraint with no Rust-side counterpart to compare against, because the Rust field is a plain type with no constraint attribute and the generated schema therefore states nothing a guard could hold the checked-in constraint against. A guard that opens the checked-in file and asserts the constraint is writable today, but it pins that file against itself and proves no parity. `ChangeRequest::capability_id` is the worked example, and it carries a second blocker of its own: its checked-in schemas constrain it differently from each other, a `pattern` in one and a `minLength` in the other. Closing the class needs each such Rust type to carry its constraint, and for `capability_id` the disagreeing schemas settled onto one, before a guard can prove parity; it is a prerequisite chain, not a missing test. ### Watchdog From 9018a9fd984e01ab163a0de4a3dbd36f161e4ed5 Mon Sep 17 00:00:00 2001 From: Jerry Xiao Date: Sun, 2 Aug 2026 10:10:10 +0000 Subject: [PATCH 18/33] no-mistakes(review): scope parity counterpart per constraint, unhedge complete binders --- AGENTS.md | 2 +- docs/ARCHITECTURE.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index ca61d34..5e23955 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -16,7 +16,7 @@ Start with `docs/README.md`. Read `docs/IMPLEMENTATION_PLAN.md`, `docs/ARCHITECT - Keep shared wire types in `crates/contracts`, and keep `schemas/*.json` in sync with them; the contract tests enforce matching fields and enum strings. - Give every field whose checked-in schema constrains it beyond `type` (a `minLength`, a `pattern`, a numeric bound) or that carries a `deserialize_with` validator its own dedicated test that binds each checked-in schema carrying that constraint, not merely one of them; for a `deserialize_with` validator, which no checked-in schema can state, the counterpart to bind is that field's declared `type` in each schema publishing it. - A test binds a schema by opening the checked-in file and asserting the constraint there, as `protocol_version_zero_is_rejected_like_the_schema` and `the_hypothesis_is_bounded_like_the_schema` do, and as `change_request_parameters_are_an_object_in_both` does for a declared `type`; a sibling that only asserts what the Rust type rejects binds nothing and is not the pattern to copy. Those binders show the shape such a test takes rather than that completeness: that last one binds fewer checked-in schemas than carry the declared `type` it asserts, the class registered as `fpsm-unbound-carrier-parity`. + A test binds a schema by opening the checked-in file and asserting the constraint there, as `protocol_version_zero_is_rejected_like_the_schema` and `the_hypothesis_is_bounded_like_the_schema` do, and as `change_request_parameters_are_an_object_in_both` does for a declared `type`; a sibling that only asserts what the Rust type rejects binds nothing and is not the pattern to copy. `protocol_version_zero_is_rejected_like_the_schema` and `the_hypothesis_is_bounded_like_the_schema` are also complete for the constraints they assert, each opening the schema that carries it: `schemas/sidecar.schema.json` carries the `protocol_version` minimum alone, and `schemas/experiment.schema.json` the hypothesis length bounds alone. `change_request_parameters_are_an_object_in_both` binds fewer checked-in schemas than carry the declared `type` it asserts, the class registered as `fpsm-unbound-carrier-parity`. Schema parity compares property names, `required`, and `additionalProperties` only, whether through `assert_object_parity` and `assert_same_shape` or hand-rolled in `response_variants_match_schema`, `capability_fields_match_capability_schema`, and `manifest_fields_match_sidecar_schema`, so a mismatched `type` or a dropped bound otherwise stays green; not every such field carries its test today, and that gap is registered in the deferred work list in `docs/ARCHITECTURE.md` as `fpsm-capid-guard` where writing the guard is blocked, as it is for `capability_id`, and as `fpsm-unbound-carrier-parity` where it is merely pending. - Keep provider lifecycle behavior in `crates/provider-sdk`. - Keep the capability registry, policy, broker lifecycle, and experiment journal in `crates/control-plane`. diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md index 1dbdf0e..d88e443 100644 --- a/docs/ARCHITECTURE.md +++ b/docs/ARCHITECTURE.md @@ -69,7 +69,7 @@ Deploy it under a supervisor that restarts on failure, and let the watchdog own - Client reconnect on `Closed`: the broker closes a connection idle for 30 seconds, and `BrokerClient` holds one long-lived stream with no keepalive or reconnect, so a caller whose requests are further apart than that gets `ClientError::Closed`. Whether the client reconnects transparently, the server distinguishes a healthy idle peer from a stalled one, or callers connect per request is undecided. - `broker-dispatch-unbounded`: neither `BrokerHandle::dispatch` nor `BrokerClient::request` bounds the wait on the single control-plane worker, so a provider that blocks inside `apply` or `verify` stalls every peer rather than failing one. Deferred to the pass that adds graceful shutdown, which has to answer the same question: what a request already in flight is owed when the broker stops serving. - `fpsm-lease-ceiling-parity`: the missing `maximum` on `$defs.ChangeRequest.lease_seconds` in `schemas/broker-request.schema.json`, which declares only a minimum while `MAX_LEASE_SECONDS` and the change request lease in `schemas/experiment.schema.json` both carry the ceiling, and the gateway's `tools/list` input schema, which states the ceiling independently as the `MAX_LEASE_SECONDS` doc comment intends but which no test binds to that constant in agreement. Raising `MAX_LEASE_SECONDS` on its own is caught: within `lease_seconds_is_bounded_like_the_schema` the assertion comparing the checked-in experiment literal against the constant fails the moment the constant moves, while the assertion comparing the generated value against that same constant moves with it and stays green. Once the experiment schema has been brought along, nothing is left to fail and the gateway advertises a stale ceiling with the suite green. The deferred work is the binding test, not a reference from the gateway to the constant. The control-plane policy check rejects an over-ceiling lease, so this is drift in the published contract rather than in enforcement. -- `fpsm-unbound-carrier-parity`: the class of constraint whose dedicated test binds fewer checked-in schemas than carry it, leaving the unbound carriers free to drift with the suite green. The quantifier ranges over each checked-in schema carrying the triggering constraint, read per constraint rather than per field, so one field can be compliant for one of its constraints and not for another, and a carried constraint no test binds at all is inside the class whether a lone schema carries it or several do. What separates this class from `fpsm-capid-guard` is that the Rust field here does carry the counterpart - `schemars` emits the bound on the generated side - so a guard that proves parity is writable today and the work is pending rather than blocked. The lease floor is the worked example: the change request lease declares the same minimum under `$defs.ChangeRequest` in `schemas/broker-request.schema.json` and under `$defs.change_request` in `schemas/experiment.schema.json`, and no test binds that minimum in either - `lease_seconds_is_bounded_like_the_schema` asserts only the ceiling, and `lease_seconds_zero_is_rejected` asserts only what the Rust type rejects, which binds nothing. That same field is compliant for its ceiling, which every checked-in schema carrying it binds. `ChangeRequest::parameters` is a second instance: `change_request_parameters_are_an_object_in_both` binds the broker request schema and the generated schema, while `schemas/experiment.schema.json` publishes the same field's declared `type` and nothing opens it. A lone carrier falls in the same way: `DecisionBounds::min_samples` declares its minimum in `schemas/experiment.schema.json` alone, and `decision_bounds_are_bounded_like_the_schema` skips that keyword while binding the improvement floor and the exclusive minimums beside it out of the same envelope, so the hole is per keyword in a table that demonstrably does floors. +- `fpsm-unbound-carrier-parity`: the class of constraint whose dedicated test binds fewer checked-in schemas than carry it, leaving the unbound carriers free to drift with the suite green. The quantifier ranges over each checked-in schema carrying the triggering constraint, read per constraint rather than per field, so one field can be compliant for one of its constraints and not for another, and a carried constraint no test binds at all is inside the class whether a lone schema carries it or several do. What separates this class from `fpsm-capid-guard` is that the Rust field here carries a counterpart for the triggering constraint itself, read per constraint as above: `schemars` emits the minimum for the non-zero lease, and the declared `type` where the attribute names the field a JSON object map. So a guard that proves parity is writable today and the work is pending rather than blocked. A plain `String` also emits a declared `type`, but nothing that a `pattern` or a `minLength` can be held against, which is why `capability_id` stays with the blocked class. The lease floor is the worked example: the change request lease declares the same minimum under `$defs.ChangeRequest` in `schemas/broker-request.schema.json` and under `$defs.change_request` in `schemas/experiment.schema.json`, and no test binds that minimum in either - `lease_seconds_is_bounded_like_the_schema` asserts only the ceiling, and `lease_seconds_zero_is_rejected` asserts only what the Rust type rejects, which binds nothing. That same field is compliant for its ceiling, which every checked-in schema carrying it binds. `ChangeRequest::parameters` is a second instance: `change_request_parameters_are_an_object_in_both` binds the broker request schema and the generated schema, while `schemas/experiment.schema.json` publishes the same field's declared `type` and nothing opens it. A lone carrier falls in the same way: `DecisionBounds::min_samples` declares its minimum in `schemas/experiment.schema.json` alone, and `decision_bounds_are_bounded_like_the_schema` skips that keyword while binding the improvement floor and the exclusive minimums beside it out of the same envelope, so the hole is per keyword in a table that demonstrably does floors. - `fpsm-capid-guard`: the dedicated guard `AGENTS.md` requires cannot prove parity today for the class of field whose checked-in schema carries a constraint with no Rust-side counterpart to compare against, because the Rust field is a plain type with no constraint attribute and the generated schema therefore states nothing a guard could hold the checked-in constraint against. A guard that opens the checked-in file and asserts the constraint is writable today, but it pins that file against itself and proves no parity. `ChangeRequest::capability_id` is the worked example, and it carries a second blocker of its own: its checked-in schemas constrain it differently from each other, a `pattern` in one and a `minLength` in the other. Closing the class needs each such Rust type to carry its constraint, and for `capability_id` the disagreeing schemas settled onto one, before a guard can prove parity; it is a prerequisite chain, not a missing test. ### Watchdog From 5a5750c3dfc73d1adf6ca7dfd2ea8e00ef2e5a4b Mon Sep 17 00:00:00 2001 From: Jerry Xiao Date: Sun, 2 Aug 2026 10:32:06 +0000 Subject: [PATCH 19/33] no-mistakes(review): fix parity binder role, opener claim, doubled symbols --- AGENTS.md | 2 +- docs/ARCHITECTURE.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 5e23955..b4d840b 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -16,7 +16,7 @@ Start with `docs/README.md`. Read `docs/IMPLEMENTATION_PLAN.md`, `docs/ARCHITECT - Keep shared wire types in `crates/contracts`, and keep `schemas/*.json` in sync with them; the contract tests enforce matching fields and enum strings. - Give every field whose checked-in schema constrains it beyond `type` (a `minLength`, a `pattern`, a numeric bound) or that carries a `deserialize_with` validator its own dedicated test that binds each checked-in schema carrying that constraint, not merely one of them; for a `deserialize_with` validator, which no checked-in schema can state, the counterpart to bind is that field's declared `type` in each schema publishing it. - A test binds a schema by opening the checked-in file and asserting the constraint there, as `protocol_version_zero_is_rejected_like_the_schema` and `the_hypothesis_is_bounded_like_the_schema` do, and as `change_request_parameters_are_an_object_in_both` does for a declared `type`; a sibling that only asserts what the Rust type rejects binds nothing and is not the pattern to copy. `protocol_version_zero_is_rejected_like_the_schema` and `the_hypothesis_is_bounded_like_the_schema` are also complete for the constraints they assert, each opening the schema that carries it: `schemas/sidecar.schema.json` carries the `protocol_version` minimum alone, and `schemas/experiment.schema.json` the hypothesis length bounds alone. `change_request_parameters_are_an_object_in_both` binds fewer checked-in schemas than carry the declared `type` it asserts, the class registered as `fpsm-unbound-carrier-parity`. + A test binds a schema by opening the checked-in file and asserting the constraint there; a sibling that only asserts what the Rust type rejects binds nothing and is not the pattern to copy. `protocol_version_zero_is_rejected_like_the_schema` and `the_hypothesis_is_bounded_like_the_schema` bind that way and are also complete for the constraints they assert, each opening the schema that carries it: `schemas/sidecar.schema.json` carries the `protocol_version` minimum alone, and `schemas/experiment.schema.json` the hypothesis length bounds alone. `change_request_parameters_are_an_object_in_both` binds that way for a declared `type`, but does so for fewer checked-in schemas than carry the one it asserts, the class registered as `fpsm-unbound-carrier-parity`. Schema parity compares property names, `required`, and `additionalProperties` only, whether through `assert_object_parity` and `assert_same_shape` or hand-rolled in `response_variants_match_schema`, `capability_fields_match_capability_schema`, and `manifest_fields_match_sidecar_schema`, so a mismatched `type` or a dropped bound otherwise stays green; not every such field carries its test today, and that gap is registered in the deferred work list in `docs/ARCHITECTURE.md` as `fpsm-capid-guard` where writing the guard is blocked, as it is for `capability_id`, and as `fpsm-unbound-carrier-parity` where it is merely pending. - Keep provider lifecycle behavior in `crates/provider-sdk`. - Keep the capability registry, policy, broker lifecycle, and experiment journal in `crates/control-plane`. diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md index d88e443..737dee7 100644 --- a/docs/ARCHITECTURE.md +++ b/docs/ARCHITECTURE.md @@ -69,7 +69,7 @@ Deploy it under a supervisor that restarts on failure, and let the watchdog own - Client reconnect on `Closed`: the broker closes a connection idle for 30 seconds, and `BrokerClient` holds one long-lived stream with no keepalive or reconnect, so a caller whose requests are further apart than that gets `ClientError::Closed`. Whether the client reconnects transparently, the server distinguishes a healthy idle peer from a stalled one, or callers connect per request is undecided. - `broker-dispatch-unbounded`: neither `BrokerHandle::dispatch` nor `BrokerClient::request` bounds the wait on the single control-plane worker, so a provider that blocks inside `apply` or `verify` stalls every peer rather than failing one. Deferred to the pass that adds graceful shutdown, which has to answer the same question: what a request already in flight is owed when the broker stops serving. - `fpsm-lease-ceiling-parity`: the missing `maximum` on `$defs.ChangeRequest.lease_seconds` in `schemas/broker-request.schema.json`, which declares only a minimum while `MAX_LEASE_SECONDS` and the change request lease in `schemas/experiment.schema.json` both carry the ceiling, and the gateway's `tools/list` input schema, which states the ceiling independently as the `MAX_LEASE_SECONDS` doc comment intends but which no test binds to that constant in agreement. Raising `MAX_LEASE_SECONDS` on its own is caught: within `lease_seconds_is_bounded_like_the_schema` the assertion comparing the checked-in experiment literal against the constant fails the moment the constant moves, while the assertion comparing the generated value against that same constant moves with it and stays green. Once the experiment schema has been brought along, nothing is left to fail and the gateway advertises a stale ceiling with the suite green. The deferred work is the binding test, not a reference from the gateway to the constant. The control-plane policy check rejects an over-ceiling lease, so this is drift in the published contract rather than in enforcement. -- `fpsm-unbound-carrier-parity`: the class of constraint whose dedicated test binds fewer checked-in schemas than carry it, leaving the unbound carriers free to drift with the suite green. The quantifier ranges over each checked-in schema carrying the triggering constraint, read per constraint rather than per field, so one field can be compliant for one of its constraints and not for another, and a carried constraint no test binds at all is inside the class whether a lone schema carries it or several do. What separates this class from `fpsm-capid-guard` is that the Rust field here carries a counterpart for the triggering constraint itself, read per constraint as above: `schemars` emits the minimum for the non-zero lease, and the declared `type` where the attribute names the field a JSON object map. So a guard that proves parity is writable today and the work is pending rather than blocked. A plain `String` also emits a declared `type`, but nothing that a `pattern` or a `minLength` can be held against, which is why `capability_id` stays with the blocked class. The lease floor is the worked example: the change request lease declares the same minimum under `$defs.ChangeRequest` in `schemas/broker-request.schema.json` and under `$defs.change_request` in `schemas/experiment.schema.json`, and no test binds that minimum in either - `lease_seconds_is_bounded_like_the_schema` asserts only the ceiling, and `lease_seconds_zero_is_rejected` asserts only what the Rust type rejects, which binds nothing. That same field is compliant for its ceiling, which every checked-in schema carrying it binds. `ChangeRequest::parameters` is a second instance: `change_request_parameters_are_an_object_in_both` binds the broker request schema and the generated schema, while `schemas/experiment.schema.json` publishes the same field's declared `type` and nothing opens it. A lone carrier falls in the same way: `DecisionBounds::min_samples` declares its minimum in `schemas/experiment.schema.json` alone, and `decision_bounds_are_bounded_like_the_schema` skips that keyword while binding the improvement floor and the exclusive minimums beside it out of the same envelope, so the hole is per keyword in a table that demonstrably does floors. +- `fpsm-unbound-carrier-parity`: the class of constraint whose dedicated test binds fewer checked-in schemas than carry it, leaving the unbound carriers free to drift with the suite green. The quantifier ranges over each checked-in schema carrying the triggering constraint, read per constraint rather than per field, so one field can be compliant for one of its constraints and not for another, and a carried constraint no test binds at all is inside the class whether a lone schema carries it or several do. What separates this class from `fpsm-capid-guard` is that the Rust field here carries a counterpart for the triggering constraint itself, read per constraint as above: `schemars` emits the minimum for the non-zero lease, and the declared `type` where the attribute names the field a JSON object map. So a guard that proves parity is writable today and the work is pending rather than blocked. A plain `String` also emits a declared `type`, but nothing that a `pattern` or a `minLength` can be held against, which is why `capability_id` stays with the blocked class. The lease floor is the worked example: the change request lease declares the same minimum under `$defs.ChangeRequest` in `schemas/broker-request.schema.json` and under `$defs.change_request` in `schemas/experiment.schema.json`, and no test binds that minimum in either - `lease_seconds_is_bounded_like_the_schema` asserts only the ceiling, and `lease_seconds_zero_is_rejected` asserts only what the Rust type rejects, which binds nothing. That same field is compliant for its ceiling, which `lease_seconds_is_bounded_like_the_schema` binds in every checked-in schema carrying it. `ChangeRequest::parameters` is a second instance: `change_request_parameters_are_an_object_in_both` binds the broker request schema and the generated schema, while `schemas/experiment.schema.json` publishes the same field's declared `type` and nothing asserts that declared `type` there. A lone carrier falls in the same way: `DecisionBounds::min_samples` declares its minimum in `schemas/experiment.schema.json` alone, and `decision_bounds_are_bounded_like_the_schema` skips that keyword while binding the improvement floor and the exclusive minimums beside it out of the same envelope, so the hole is per keyword in a table that demonstrably does floors. - `fpsm-capid-guard`: the dedicated guard `AGENTS.md` requires cannot prove parity today for the class of field whose checked-in schema carries a constraint with no Rust-side counterpart to compare against, because the Rust field is a plain type with no constraint attribute and the generated schema therefore states nothing a guard could hold the checked-in constraint against. A guard that opens the checked-in file and asserts the constraint is writable today, but it pins that file against itself and proves no parity. `ChangeRequest::capability_id` is the worked example, and it carries a second blocker of its own: its checked-in schemas constrain it differently from each other, a `pattern` in one and a `minLength` in the other. Closing the class needs each such Rust type to carry its constraint, and for `capability_id` the disagreeing schemas settled onto one, before a guard can prove parity; it is a prerequisite chain, not a missing test. ### Watchdog From adff25030e4c23d3ddcafc093db75e902a6bdf77 Mon Sep 17 00:00:00 2001 From: Jerry Xiao Date: Sun, 2 Aug 2026 10:42:38 +0000 Subject: [PATCH 20/33] no-mistakes(review): scope parity quantifier to checked-in schemas, gloss per constraint --- AGENTS.md | 4 ++-- crates/contracts/src/lib.rs | 2 +- crates/contracts/src/test_support.rs | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index b4d840b..865e2de 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -15,9 +15,9 @@ Start with `docs/README.md`. Read `docs/IMPLEMENTATION_PLAN.md`, `docs/ARCHITECT ## Repository rules - Keep shared wire types in `crates/contracts`, and keep `schemas/*.json` in sync with them; the contract tests enforce matching fields and enum strings. -- Give every field whose checked-in schema constrains it beyond `type` (a `minLength`, a `pattern`, a numeric bound) or that carries a `deserialize_with` validator its own dedicated test that binds each checked-in schema carrying that constraint, not merely one of them; for a `deserialize_with` validator, which no checked-in schema can state, the counterpart to bind is that field's declared `type` in each schema publishing it. +- Give every field whose checked-in schema constrains it beyond `type` (a `minLength`, a `pattern`, a numeric bound) or that carries a `deserialize_with` validator its own dedicated test that binds each checked-in schema carrying that constraint, not merely one of them; for a `deserialize_with` validator, which no checked-in schema can state, the counterpart to bind is that field's declared `type` in each checked-in schema publishing it. A test binds a schema by opening the checked-in file and asserting the constraint there; a sibling that only asserts what the Rust type rejects binds nothing and is not the pattern to copy. `protocol_version_zero_is_rejected_like_the_schema` and `the_hypothesis_is_bounded_like_the_schema` bind that way and are also complete for the constraints they assert, each opening the schema that carries it: `schemas/sidecar.schema.json` carries the `protocol_version` minimum alone, and `schemas/experiment.schema.json` the hypothesis length bounds alone. `change_request_parameters_are_an_object_in_both` binds that way for a declared `type`, but does so for fewer checked-in schemas than carry the one it asserts, the class registered as `fpsm-unbound-carrier-parity`. - Schema parity compares property names, `required`, and `additionalProperties` only, whether through `assert_object_parity` and `assert_same_shape` or hand-rolled in `response_variants_match_schema`, `capability_fields_match_capability_schema`, and `manifest_fields_match_sidecar_schema`, so a mismatched `type` or a dropped bound otherwise stays green; not every such field carries its test today, and that gap is registered in the deferred work list in `docs/ARCHITECTURE.md` as `fpsm-capid-guard` where writing the guard is blocked, as it is for `capability_id`, and as `fpsm-unbound-carrier-parity` where it is merely pending. + Schema parity compares property names, `required`, and `additionalProperties` only, whether through `assert_object_parity` and `assert_same_shape` or hand-rolled in `response_variants_match_schema`, `capability_fields_match_capability_schema`, and `manifest_fields_match_sidecar_schema`, so a mismatched `type` or a dropped bound otherwise stays green; not every such constraint is bound today in every checked-in schema carrying it, and that gap is registered in the deferred work list in `docs/ARCHITECTURE.md` as `fpsm-capid-guard` where writing the guard is blocked, as it is for `capability_id`, and as `fpsm-unbound-carrier-parity` where it is merely pending. - Keep provider lifecycle behavior in `crates/provider-sdk`. - Keep the capability registry, policy, broker lifecycle, and experiment journal in `crates/control-plane`. - Keep the local IPC transport, framing, and peer-authentication seams behind traits in `crates/ipc` (Unix domain socket now, Windows named pipe later); the privileged broker in `apps/broker` composes them over the control plane and enforces peer auth, catalog policy, and single-owner-per-knob. The non-`Send` control plane is confined to one worker thread reached through a `Send` handle. diff --git a/crates/contracts/src/lib.rs b/crates/contracts/src/lib.rs index cbccfd5..e3781d9 100644 --- a/crates/contracts/src/lib.rs +++ b/crates/contracts/src/lib.rs @@ -499,7 +499,7 @@ mod tests { /// checked-in schema carrying that constraint rather than merely one of /// them; for a `deserialize_with` validator, which no checked-in schema can /// state, the counterpart to bind is that field's declared `type` in each - /// schema publishing it. + /// checked-in schema publishing it. fn assert_object_parity(label: &str, generated: &Value, checked_in: &Value) { let generated_properties: BTreeSet = generated["properties"] .as_object() diff --git a/crates/contracts/src/test_support.rs b/crates/contracts/src/test_support.rs index 8877231..5bc4d23 100644 --- a/crates/contracts/src/test_support.rs +++ b/crates/contracts/src/test_support.rs @@ -64,7 +64,7 @@ pub fn serialized_fields(value: impl serde::Serialize) -> BTreeSet { /// instead, one that binds each checked-in schema carrying that constraint /// rather than merely one of them; for a `deserialize_with` validator, which no /// checked-in schema can state, the counterpart to bind is that field's -/// declared `type` in each schema publishing it. +/// declared `type` in each checked-in schema publishing it. pub fn assert_same_shape(generated: &schemars::Schema, checked_in: &Value) { let generated = serde_json::to_value(generated).expect("generated schema should serialize"); assert_eq!(properties(&generated), properties(checked_in)); From b735cd2c7efa607c66d1fbd68bf4fd812bc2a30e Mon Sep 17 00:00:00 2001 From: Jerry Xiao Date: Sun, 2 Aug 2026 10:49:21 +0000 Subject: [PATCH 21/33] no-mistakes(review): fix capid-guard pointer verb, parameters binder wording --- AGENTS.md | 2 +- docs/ARCHITECTURE.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 865e2de..9b100d9 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -17,7 +17,7 @@ Start with `docs/README.md`. Read `docs/IMPLEMENTATION_PLAN.md`, `docs/ARCHITECT - Keep shared wire types in `crates/contracts`, and keep `schemas/*.json` in sync with them; the contract tests enforce matching fields and enum strings. - Give every field whose checked-in schema constrains it beyond `type` (a `minLength`, a `pattern`, a numeric bound) or that carries a `deserialize_with` validator its own dedicated test that binds each checked-in schema carrying that constraint, not merely one of them; for a `deserialize_with` validator, which no checked-in schema can state, the counterpart to bind is that field's declared `type` in each checked-in schema publishing it. A test binds a schema by opening the checked-in file and asserting the constraint there; a sibling that only asserts what the Rust type rejects binds nothing and is not the pattern to copy. `protocol_version_zero_is_rejected_like_the_schema` and `the_hypothesis_is_bounded_like_the_schema` bind that way and are also complete for the constraints they assert, each opening the schema that carries it: `schemas/sidecar.schema.json` carries the `protocol_version` minimum alone, and `schemas/experiment.schema.json` the hypothesis length bounds alone. `change_request_parameters_are_an_object_in_both` binds that way for a declared `type`, but does so for fewer checked-in schemas than carry the one it asserts, the class registered as `fpsm-unbound-carrier-parity`. - Schema parity compares property names, `required`, and `additionalProperties` only, whether through `assert_object_parity` and `assert_same_shape` or hand-rolled in `response_variants_match_schema`, `capability_fields_match_capability_schema`, and `manifest_fields_match_sidecar_schema`, so a mismatched `type` or a dropped bound otherwise stays green; not every such constraint is bound today in every checked-in schema carrying it, and that gap is registered in the deferred work list in `docs/ARCHITECTURE.md` as `fpsm-capid-guard` where writing the guard is blocked, as it is for `capability_id`, and as `fpsm-unbound-carrier-parity` where it is merely pending. + Schema parity compares property names, `required`, and `additionalProperties` only, whether through `assert_object_parity` and `assert_same_shape` or hand-rolled in `response_variants_match_schema`, `capability_fields_match_capability_schema`, and `manifest_fields_match_sidecar_schema`, so a mismatched `type` or a dropped bound otherwise stays green; not every such constraint is bound today in every checked-in schema carrying it, and that gap is registered in the deferred work list in `docs/ARCHITECTURE.md` as `fpsm-capid-guard` where writing a guard that proves parity is blocked, as it is for `capability_id`, and as `fpsm-unbound-carrier-parity` where it is merely pending. - Keep provider lifecycle behavior in `crates/provider-sdk`. - Keep the capability registry, policy, broker lifecycle, and experiment journal in `crates/control-plane`. - Keep the local IPC transport, framing, and peer-authentication seams behind traits in `crates/ipc` (Unix domain socket now, Windows named pipe later); the privileged broker in `apps/broker` composes them over the control plane and enforces peer auth, catalog policy, and single-owner-per-knob. The non-`Send` control plane is confined to one worker thread reached through a `Send` handle. diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md index 737dee7..824c53b 100644 --- a/docs/ARCHITECTURE.md +++ b/docs/ARCHITECTURE.md @@ -69,7 +69,7 @@ Deploy it under a supervisor that restarts on failure, and let the watchdog own - Client reconnect on `Closed`: the broker closes a connection idle for 30 seconds, and `BrokerClient` holds one long-lived stream with no keepalive or reconnect, so a caller whose requests are further apart than that gets `ClientError::Closed`. Whether the client reconnects transparently, the server distinguishes a healthy idle peer from a stalled one, or callers connect per request is undecided. - `broker-dispatch-unbounded`: neither `BrokerHandle::dispatch` nor `BrokerClient::request` bounds the wait on the single control-plane worker, so a provider that blocks inside `apply` or `verify` stalls every peer rather than failing one. Deferred to the pass that adds graceful shutdown, which has to answer the same question: what a request already in flight is owed when the broker stops serving. - `fpsm-lease-ceiling-parity`: the missing `maximum` on `$defs.ChangeRequest.lease_seconds` in `schemas/broker-request.schema.json`, which declares only a minimum while `MAX_LEASE_SECONDS` and the change request lease in `schemas/experiment.schema.json` both carry the ceiling, and the gateway's `tools/list` input schema, which states the ceiling independently as the `MAX_LEASE_SECONDS` doc comment intends but which no test binds to that constant in agreement. Raising `MAX_LEASE_SECONDS` on its own is caught: within `lease_seconds_is_bounded_like_the_schema` the assertion comparing the checked-in experiment literal against the constant fails the moment the constant moves, while the assertion comparing the generated value against that same constant moves with it and stays green. Once the experiment schema has been brought along, nothing is left to fail and the gateway advertises a stale ceiling with the suite green. The deferred work is the binding test, not a reference from the gateway to the constant. The control-plane policy check rejects an over-ceiling lease, so this is drift in the published contract rather than in enforcement. -- `fpsm-unbound-carrier-parity`: the class of constraint whose dedicated test binds fewer checked-in schemas than carry it, leaving the unbound carriers free to drift with the suite green. The quantifier ranges over each checked-in schema carrying the triggering constraint, read per constraint rather than per field, so one field can be compliant for one of its constraints and not for another, and a carried constraint no test binds at all is inside the class whether a lone schema carries it or several do. What separates this class from `fpsm-capid-guard` is that the Rust field here carries a counterpart for the triggering constraint itself, read per constraint as above: `schemars` emits the minimum for the non-zero lease, and the declared `type` where the attribute names the field a JSON object map. So a guard that proves parity is writable today and the work is pending rather than blocked. A plain `String` also emits a declared `type`, but nothing that a `pattern` or a `minLength` can be held against, which is why `capability_id` stays with the blocked class. The lease floor is the worked example: the change request lease declares the same minimum under `$defs.ChangeRequest` in `schemas/broker-request.schema.json` and under `$defs.change_request` in `schemas/experiment.schema.json`, and no test binds that minimum in either - `lease_seconds_is_bounded_like_the_schema` asserts only the ceiling, and `lease_seconds_zero_is_rejected` asserts only what the Rust type rejects, which binds nothing. That same field is compliant for its ceiling, which `lease_seconds_is_bounded_like_the_schema` binds in every checked-in schema carrying it. `ChangeRequest::parameters` is a second instance: `change_request_parameters_are_an_object_in_both` binds the broker request schema and the generated schema, while `schemas/experiment.schema.json` publishes the same field's declared `type` and nothing asserts that declared `type` there. A lone carrier falls in the same way: `DecisionBounds::min_samples` declares its minimum in `schemas/experiment.schema.json` alone, and `decision_bounds_are_bounded_like_the_schema` skips that keyword while binding the improvement floor and the exclusive minimums beside it out of the same envelope, so the hole is per keyword in a table that demonstrably does floors. +- `fpsm-unbound-carrier-parity`: the class of constraint whose dedicated test binds fewer checked-in schemas than carry it, leaving the unbound carriers free to drift with the suite green. The quantifier ranges over each checked-in schema carrying the triggering constraint, read per constraint rather than per field, so one field can be compliant for one of its constraints and not for another, and a carried constraint no test binds at all is inside the class whether a lone schema carries it or several do. What separates this class from `fpsm-capid-guard` is that the Rust field here carries a counterpart for the triggering constraint itself, read per constraint as above: `schemars` emits the minimum for the non-zero lease, and the declared `type` where the attribute names the field a JSON object map. So a guard that proves parity is writable today and the work is pending rather than blocked. A plain `String` also emits a declared `type`, but nothing that a `pattern` or a `minLength` can be held against, which is why `capability_id` stays with the blocked class. The lease floor is the worked example: the change request lease declares the same minimum under `$defs.ChangeRequest` in `schemas/broker-request.schema.json` and under `$defs.change_request` in `schemas/experiment.schema.json`, and no test binds that minimum in either - `lease_seconds_is_bounded_like_the_schema` asserts only the ceiling, and `lease_seconds_zero_is_rejected` asserts only what the Rust type rejects, which binds nothing. That same field is compliant for its ceiling, which `lease_seconds_is_bounded_like_the_schema` binds in every checked-in schema carrying it. `ChangeRequest::parameters` is a second instance: `change_request_parameters_are_an_object_in_both` binds the broker request schema, comparing it against the generated schema, while `schemas/experiment.schema.json` publishes the same field's declared `type` and nothing asserts that declared `type` there. A lone carrier falls in the same way: `DecisionBounds::min_samples` declares its minimum in `schemas/experiment.schema.json` alone, and `decision_bounds_are_bounded_like_the_schema` skips that keyword while binding the improvement floor and the exclusive minimums beside it out of the same envelope, so the hole is per keyword in a table that demonstrably does floors. - `fpsm-capid-guard`: the dedicated guard `AGENTS.md` requires cannot prove parity today for the class of field whose checked-in schema carries a constraint with no Rust-side counterpart to compare against, because the Rust field is a plain type with no constraint attribute and the generated schema therefore states nothing a guard could hold the checked-in constraint against. A guard that opens the checked-in file and asserts the constraint is writable today, but it pins that file against itself and proves no parity. `ChangeRequest::capability_id` is the worked example, and it carries a second blocker of its own: its checked-in schemas constrain it differently from each other, a `pattern` in one and a `minLength` in the other. Closing the class needs each such Rust type to carry its constraint, and for `capability_id` the disagreeing schemas settled onto one, before a guard can prove parity; it is a prerequisite chain, not a missing test. ### Watchdog From a9ce485c8c24c1ef9cb50a75a5bd13c218dc8099 Mon Sep 17 00:00:00 2001 From: Jerry Xiao Date: Sun, 2 Aug 2026 11:01:42 +0000 Subject: [PATCH 22/33] no-mistakes(review): read capid-guard class per constraint, not per field --- docs/ARCHITECTURE.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md index 824c53b..de6e90a 100644 --- a/docs/ARCHITECTURE.md +++ b/docs/ARCHITECTURE.md @@ -70,7 +70,7 @@ Deploy it under a supervisor that restarts on failure, and let the watchdog own - `broker-dispatch-unbounded`: neither `BrokerHandle::dispatch` nor `BrokerClient::request` bounds the wait on the single control-plane worker, so a provider that blocks inside `apply` or `verify` stalls every peer rather than failing one. Deferred to the pass that adds graceful shutdown, which has to answer the same question: what a request already in flight is owed when the broker stops serving. - `fpsm-lease-ceiling-parity`: the missing `maximum` on `$defs.ChangeRequest.lease_seconds` in `schemas/broker-request.schema.json`, which declares only a minimum while `MAX_LEASE_SECONDS` and the change request lease in `schemas/experiment.schema.json` both carry the ceiling, and the gateway's `tools/list` input schema, which states the ceiling independently as the `MAX_LEASE_SECONDS` doc comment intends but which no test binds to that constant in agreement. Raising `MAX_LEASE_SECONDS` on its own is caught: within `lease_seconds_is_bounded_like_the_schema` the assertion comparing the checked-in experiment literal against the constant fails the moment the constant moves, while the assertion comparing the generated value against that same constant moves with it and stays green. Once the experiment schema has been brought along, nothing is left to fail and the gateway advertises a stale ceiling with the suite green. The deferred work is the binding test, not a reference from the gateway to the constant. The control-plane policy check rejects an over-ceiling lease, so this is drift in the published contract rather than in enforcement. - `fpsm-unbound-carrier-parity`: the class of constraint whose dedicated test binds fewer checked-in schemas than carry it, leaving the unbound carriers free to drift with the suite green. The quantifier ranges over each checked-in schema carrying the triggering constraint, read per constraint rather than per field, so one field can be compliant for one of its constraints and not for another, and a carried constraint no test binds at all is inside the class whether a lone schema carries it or several do. What separates this class from `fpsm-capid-guard` is that the Rust field here carries a counterpart for the triggering constraint itself, read per constraint as above: `schemars` emits the minimum for the non-zero lease, and the declared `type` where the attribute names the field a JSON object map. So a guard that proves parity is writable today and the work is pending rather than blocked. A plain `String` also emits a declared `type`, but nothing that a `pattern` or a `minLength` can be held against, which is why `capability_id` stays with the blocked class. The lease floor is the worked example: the change request lease declares the same minimum under `$defs.ChangeRequest` in `schemas/broker-request.schema.json` and under `$defs.change_request` in `schemas/experiment.schema.json`, and no test binds that minimum in either - `lease_seconds_is_bounded_like_the_schema` asserts only the ceiling, and `lease_seconds_zero_is_rejected` asserts only what the Rust type rejects, which binds nothing. That same field is compliant for its ceiling, which `lease_seconds_is_bounded_like_the_schema` binds in every checked-in schema carrying it. `ChangeRequest::parameters` is a second instance: `change_request_parameters_are_an_object_in_both` binds the broker request schema, comparing it against the generated schema, while `schemas/experiment.schema.json` publishes the same field's declared `type` and nothing asserts that declared `type` there. A lone carrier falls in the same way: `DecisionBounds::min_samples` declares its minimum in `schemas/experiment.schema.json` alone, and `decision_bounds_are_bounded_like_the_schema` skips that keyword while binding the improvement floor and the exclusive minimums beside it out of the same envelope, so the hole is per keyword in a table that demonstrably does floors. -- `fpsm-capid-guard`: the dedicated guard `AGENTS.md` requires cannot prove parity today for the class of field whose checked-in schema carries a constraint with no Rust-side counterpart to compare against, because the Rust field is a plain type with no constraint attribute and the generated schema therefore states nothing a guard could hold the checked-in constraint against. A guard that opens the checked-in file and asserts the constraint is writable today, but it pins that file against itself and proves no parity. `ChangeRequest::capability_id` is the worked example, and it carries a second blocker of its own: its checked-in schemas constrain it differently from each other, a `pattern` in one and a `minLength` in the other. Closing the class needs each such Rust type to carry its constraint, and for `capability_id` the disagreeing schemas settled onto one, before a guard can prove parity; it is a prerequisite chain, not a missing test. +- `fpsm-capid-guard`: the dedicated guard `AGENTS.md` requires cannot prove parity today for the class of constraint a checked-in schema carries with no Rust-side counterpart to compare against, because the Rust field is a plain type with no constraint attribute and the generated schema therefore states nothing a guard could hold the checked-in constraint against. A guard that opens the checked-in file and asserts the constraint is writable today, but it pins that file against itself and proves no parity. `ChangeRequest::capability_id` is the worked example, and it carries a second blocker of its own: its checked-in schemas constrain it differently from each other, a `pattern` in one and a `minLength` in the other. Closing the class needs each such Rust type to carry its constraint, and for `capability_id` the disagreeing schemas settled onto one, before a guard can prove parity; it is a prerequisite chain, not a missing test. ### Watchdog From 996833582bc3a9dd20b2342a036cb4174f0781b9 Mon Sep 17 00:00:00 2001 From: Jerry Xiao Date: Sun, 2 Aug 2026 11:15:37 +0000 Subject: [PATCH 23/33] no-mistakes(review): file parity classes as contract work, fix parity verbs --- AGENTS.md | 2 +- docs/ARCHITECTURE.md | 11 ++++++++--- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 9b100d9..3d8b36a 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -17,7 +17,7 @@ Start with `docs/README.md`. Read `docs/IMPLEMENTATION_PLAN.md`, `docs/ARCHITECT - Keep shared wire types in `crates/contracts`, and keep `schemas/*.json` in sync with them; the contract tests enforce matching fields and enum strings. - Give every field whose checked-in schema constrains it beyond `type` (a `minLength`, a `pattern`, a numeric bound) or that carries a `deserialize_with` validator its own dedicated test that binds each checked-in schema carrying that constraint, not merely one of them; for a `deserialize_with` validator, which no checked-in schema can state, the counterpart to bind is that field's declared `type` in each checked-in schema publishing it. A test binds a schema by opening the checked-in file and asserting the constraint there; a sibling that only asserts what the Rust type rejects binds nothing and is not the pattern to copy. `protocol_version_zero_is_rejected_like_the_schema` and `the_hypothesis_is_bounded_like_the_schema` bind that way and are also complete for the constraints they assert, each opening the schema that carries it: `schemas/sidecar.schema.json` carries the `protocol_version` minimum alone, and `schemas/experiment.schema.json` the hypothesis length bounds alone. `change_request_parameters_are_an_object_in_both` binds that way for a declared `type`, but does so for fewer checked-in schemas than carry the one it asserts, the class registered as `fpsm-unbound-carrier-parity`. - Schema parity compares property names, `required`, and `additionalProperties` only, whether through `assert_object_parity` and `assert_same_shape` or hand-rolled in `response_variants_match_schema`, `capability_fields_match_capability_schema`, and `manifest_fields_match_sidecar_schema`, so a mismatched `type` or a dropped bound otherwise stays green; not every such constraint is bound today in every checked-in schema carrying it, and that gap is registered in the deferred work list in `docs/ARCHITECTURE.md` as `fpsm-capid-guard` where writing a guard that proves parity is blocked, as it is for `capability_id`, and as `fpsm-unbound-carrier-parity` where it is merely pending. + Schema parity reaches property names, `required`, and `additionalProperties` only, so a mismatched `type` or a dropped bound otherwise stays green wherever the comparison is made: `assert_object_parity` and `assert_same_shape` compare each of those keywords between the generated and checked-in schemas, while `response_variants_match_schema`, `capability_fields_match_capability_schema`, and `manifest_fields_match_sidecar_schema` hand-roll the property-name and `required` half and pin `additionalProperties` to `false` on the checked-in side rather than compare it, so a generated side that drifts on that keyword stays green at those hand-rolled sites too; not every such constraint is bound today in every checked-in schema carrying it, and that gap is registered in the deferred contract work list in `docs/ARCHITECTURE.md` as `fpsm-capid-guard` where writing a guard that proves parity is blocked, as it is for `capability_id`, and as `fpsm-unbound-carrier-parity` where it is merely pending. - Keep provider lifecycle behavior in `crates/provider-sdk`. - Keep the capability registry, policy, broker lifecycle, and experiment journal in `crates/control-plane`. - Keep the local IPC transport, framing, and peer-authentication seams behind traits in `crates/ipc` (Unix domain socket now, Windows named pipe later); the privileged broker in `apps/broker` composes them over the control plane and enforces peer auth, catalog policy, and single-owner-per-knob. The non-`Send` control plane is confined to one worker thread reached through a `Send` handle. diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md index de6e90a..09917fe 100644 --- a/docs/ARCHITECTURE.md +++ b/docs/ARCHITECTURE.md @@ -68,9 +68,6 @@ Deploy it under a supervisor that restarts on failure, and let the watchdog own - `fpsm-broker-splitacl`: the real split-privilege ACL, replacing the interim same-uid policy described above, plus journaling the verified peer uid and pid against each lifecycle and authenticating the client-supplied owner label against them. - Client reconnect on `Closed`: the broker closes a connection idle for 30 seconds, and `BrokerClient` holds one long-lived stream with no keepalive or reconnect, so a caller whose requests are further apart than that gets `ClientError::Closed`. Whether the client reconnects transparently, the server distinguishes a healthy idle peer from a stalled one, or callers connect per request is undecided. - `broker-dispatch-unbounded`: neither `BrokerHandle::dispatch` nor `BrokerClient::request` bounds the wait on the single control-plane worker, so a provider that blocks inside `apply` or `verify` stalls every peer rather than failing one. Deferred to the pass that adds graceful shutdown, which has to answer the same question: what a request already in flight is owed when the broker stops serving. -- `fpsm-lease-ceiling-parity`: the missing `maximum` on `$defs.ChangeRequest.lease_seconds` in `schemas/broker-request.schema.json`, which declares only a minimum while `MAX_LEASE_SECONDS` and the change request lease in `schemas/experiment.schema.json` both carry the ceiling, and the gateway's `tools/list` input schema, which states the ceiling independently as the `MAX_LEASE_SECONDS` doc comment intends but which no test binds to that constant in agreement. Raising `MAX_LEASE_SECONDS` on its own is caught: within `lease_seconds_is_bounded_like_the_schema` the assertion comparing the checked-in experiment literal against the constant fails the moment the constant moves, while the assertion comparing the generated value against that same constant moves with it and stays green. Once the experiment schema has been brought along, nothing is left to fail and the gateway advertises a stale ceiling with the suite green. The deferred work is the binding test, not a reference from the gateway to the constant. The control-plane policy check rejects an over-ceiling lease, so this is drift in the published contract rather than in enforcement. -- `fpsm-unbound-carrier-parity`: the class of constraint whose dedicated test binds fewer checked-in schemas than carry it, leaving the unbound carriers free to drift with the suite green. The quantifier ranges over each checked-in schema carrying the triggering constraint, read per constraint rather than per field, so one field can be compliant for one of its constraints and not for another, and a carried constraint no test binds at all is inside the class whether a lone schema carries it or several do. What separates this class from `fpsm-capid-guard` is that the Rust field here carries a counterpart for the triggering constraint itself, read per constraint as above: `schemars` emits the minimum for the non-zero lease, and the declared `type` where the attribute names the field a JSON object map. So a guard that proves parity is writable today and the work is pending rather than blocked. A plain `String` also emits a declared `type`, but nothing that a `pattern` or a `minLength` can be held against, which is why `capability_id` stays with the blocked class. The lease floor is the worked example: the change request lease declares the same minimum under `$defs.ChangeRequest` in `schemas/broker-request.schema.json` and under `$defs.change_request` in `schemas/experiment.schema.json`, and no test binds that minimum in either - `lease_seconds_is_bounded_like_the_schema` asserts only the ceiling, and `lease_seconds_zero_is_rejected` asserts only what the Rust type rejects, which binds nothing. That same field is compliant for its ceiling, which `lease_seconds_is_bounded_like_the_schema` binds in every checked-in schema carrying it. `ChangeRequest::parameters` is a second instance: `change_request_parameters_are_an_object_in_both` binds the broker request schema, comparing it against the generated schema, while `schemas/experiment.schema.json` publishes the same field's declared `type` and nothing asserts that declared `type` there. A lone carrier falls in the same way: `DecisionBounds::min_samples` declares its minimum in `schemas/experiment.schema.json` alone, and `decision_bounds_are_bounded_like_the_schema` skips that keyword while binding the improvement floor and the exclusive minimums beside it out of the same envelope, so the hole is per keyword in a table that demonstrably does floors. -- `fpsm-capid-guard`: the dedicated guard `AGENTS.md` requires cannot prove parity today for the class of constraint a checked-in schema carries with no Rust-side counterpart to compare against, because the Rust field is a plain type with no constraint attribute and the generated schema therefore states nothing a guard could hold the checked-in constraint against. A guard that opens the checked-in file and asserts the constraint is writable today, but it pins that file against itself and proves no parity. `ChangeRequest::capability_id` is the worked example, and it carries a second blocker of its own: its checked-in schemas constrain it differently from each other, a `pattern` in one and a `minLength` in the other. Closing the class needs each such Rust type to carry its constraint, and for `capability_id` the disagreeing schemas settled onto one, before a guard can prove parity; it is a prerequisite chain, not a missing test. ### Watchdog @@ -102,6 +99,14 @@ The candidate is also measured before it is applied, which only the pure stand-i Each sidecar integrates exactly one service or vendor API. Sidecars advertise semantic capabilities and implement snapshot, preview, apply, verify, and rollback. They do not make cross-provider decisions. +## Deferred contract work + +These span `crates/contracts` and the checked-in schemas rather than any one process, so they are tracked here rather than under a process heading. + +- `fpsm-lease-ceiling-parity`: the missing `maximum` on `$defs.ChangeRequest.lease_seconds` in `schemas/broker-request.schema.json`, which declares only a minimum while `MAX_LEASE_SECONDS` and the change request lease in `schemas/experiment.schema.json` both carry the ceiling, and the gateway's `tools/list` input schema, which states the ceiling independently as the `MAX_LEASE_SECONDS` doc comment intends but which no test binds to that constant in agreement. Raising `MAX_LEASE_SECONDS` on its own is caught: within `lease_seconds_is_bounded_like_the_schema` the assertion comparing the checked-in experiment literal against the constant fails the moment the constant moves, while the assertion comparing the generated value against that same constant moves with it and stays green. Once the experiment schema has been brought along, nothing is left to fail and the gateway advertises a stale ceiling with the suite green. The deferred work is the binding test, not a reference from the gateway to the constant. The control-plane policy check rejects an over-ceiling lease, so this is drift in the published contract rather than in enforcement. +- `fpsm-unbound-carrier-parity`: the class of constraint whose dedicated test binds fewer checked-in schemas than carry it, leaving the unbound carriers free to drift with the suite green. The quantifier ranges over each checked-in schema carrying the triggering constraint, read per constraint rather than per field, so one field can be compliant for one of its constraints and not for another, and a carried constraint no test binds at all is inside the class whether a lone schema carries it or several do. What separates this class from `fpsm-capid-guard` is that the Rust field here carries a counterpart for the triggering constraint itself, read per constraint as above: `schemars` emits the minimum for the non-zero lease, and the declared `type` where the attribute names the field a JSON object map. So a guard that proves parity is writable today and the work is pending rather than blocked. A plain `String` also emits a declared `type`, but nothing that a `pattern` or a `minLength` can be held against, which is why `capability_id` stays with the blocked class. The lease floor is the worked example: the change request lease declares the same minimum under `$defs.ChangeRequest` in `schemas/broker-request.schema.json` and under `$defs.change_request` in `schemas/experiment.schema.json`, and no test binds that minimum in either - `lease_seconds_is_bounded_like_the_schema` asserts only the ceiling, and `lease_seconds_zero_is_rejected` asserts only what the Rust type rejects, which binds nothing. That same field is compliant for its ceiling: `lease_seconds_is_bounded_like_the_schema` binds every checked-in schema carrying that ceiling. `ChangeRequest::parameters` is a second instance: `change_request_parameters_are_an_object_in_both` binds the broker request schema, comparing it against the generated schema, while `schemas/experiment.schema.json` publishes the same field's declared `type` and nothing asserts that declared `type` there. A lone carrier falls in the same way: `DecisionBounds::min_samples` declares its minimum in `schemas/experiment.schema.json` alone, and `decision_bounds_are_bounded_like_the_schema` skips that keyword while binding the improvement floor and the exclusive minimums beside it out of the same envelope, so the hole is per keyword in a table that demonstrably does floors. +- `fpsm-capid-guard`: the dedicated guard `AGENTS.md` requires cannot prove parity today for the class of constraint a checked-in schema carries with no Rust-side counterpart to compare against, because the Rust field is a plain type with no constraint attribute and the generated schema therefore states nothing a guard could hold the checked-in constraint against. A guard that opens the checked-in file and asserts the constraint is writable today, but it pins that file against itself and proves no parity. `ChangeRequest::capability_id` is the worked example, and it carries a second blocker of its own: its checked-in schemas constrain it differently from each other, a `pattern` in one and a `minLength` in the other. `ProviderManifest::targets` is a further member with no such second blocker: `schemas/sidecar.schema.json` requires its array to be non-empty through `minItems`, while the Rust field is a bare `Vec` carrying no attribute, so the generated schema states nothing that keyword can be held against. Closing the class needs each such Rust type to carry its constraint, and for `capability_id` the disagreeing schemas settled onto one, before a guard can prove parity; it is a prerequisite chain, not a missing test. + ## Dependency rule Dependencies point inward: From a1220e81fb57fffb8c67f695f3d49e625b88edbe Mon Sep 17 00:00:00 2001 From: Jerry Xiao Date: Sun, 2 Aug 2026 11:28:22 +0000 Subject: [PATCH 24/33] no-mistakes(review): split parity sentence three ways, gloss minItems --- AGENTS.md | 4 ++-- crates/contracts/src/lib.rs | 12 ++++++------ crates/contracts/src/test_support.rs | 12 ++++++------ 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 3d8b36a..8cf1aed 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -15,9 +15,9 @@ Start with `docs/README.md`. Read `docs/IMPLEMENTATION_PLAN.md`, `docs/ARCHITECT ## Repository rules - Keep shared wire types in `crates/contracts`, and keep `schemas/*.json` in sync with them; the contract tests enforce matching fields and enum strings. -- Give every field whose checked-in schema constrains it beyond `type` (a `minLength`, a `pattern`, a numeric bound) or that carries a `deserialize_with` validator its own dedicated test that binds each checked-in schema carrying that constraint, not merely one of them; for a `deserialize_with` validator, which no checked-in schema can state, the counterpart to bind is that field's declared `type` in each checked-in schema publishing it. +- Give every field whose checked-in schema constrains it beyond `type` (a `minLength`, a `minItems`, a `pattern`, a numeric bound) or that carries a `deserialize_with` validator its own dedicated test that binds each checked-in schema carrying that constraint, not merely one of them; for a `deserialize_with` validator, which no checked-in schema can state, the counterpart to bind is that field's declared `type` in each checked-in schema publishing it. A test binds a schema by opening the checked-in file and asserting the constraint there; a sibling that only asserts what the Rust type rejects binds nothing and is not the pattern to copy. `protocol_version_zero_is_rejected_like_the_schema` and `the_hypothesis_is_bounded_like_the_schema` bind that way and are also complete for the constraints they assert, each opening the schema that carries it: `schemas/sidecar.schema.json` carries the `protocol_version` minimum alone, and `schemas/experiment.schema.json` the hypothesis length bounds alone. `change_request_parameters_are_an_object_in_both` binds that way for a declared `type`, but does so for fewer checked-in schemas than carry the one it asserts, the class registered as `fpsm-unbound-carrier-parity`. - Schema parity reaches property names, `required`, and `additionalProperties` only, so a mismatched `type` or a dropped bound otherwise stays green wherever the comparison is made: `assert_object_parity` and `assert_same_shape` compare each of those keywords between the generated and checked-in schemas, while `response_variants_match_schema`, `capability_fields_match_capability_schema`, and `manifest_fields_match_sidecar_schema` hand-roll the property-name and `required` half and pin `additionalProperties` to `false` on the checked-in side rather than compare it, so a generated side that drifts on that keyword stays green at those hand-rolled sites too; not every such constraint is bound today in every checked-in schema carrying it, and that gap is registered in the deferred contract work list in `docs/ARCHITECTURE.md` as `fpsm-capid-guard` where writing a guard that proves parity is blocked, as it is for `capability_id`, and as `fpsm-unbound-carrier-parity` where it is merely pending. + Schema parity reaches property names, `required`, and `additionalProperties` only, so a mismatched `type` or a dropped bound otherwise stays green wherever the comparison is made: `assert_object_parity` and `assert_same_shape` compare each of those keywords between the generated and checked-in schemas; `response_variants_match_schema` hand-rolls the property-name and `required` comparison between those same sides but pins `additionalProperties` to `false` on the checked-in side rather than comparing it, so a generated side that drifts on that keyword stays green there; and `capability_fields_match_capability_schema` and `manifest_fields_match_sidecar_schema` bind the checked-in `properties` and `required` to the field set serde emits for a sample value and pin `additionalProperties` to `false` on that same checked-in side, holding the wire output to the checked-in schema but taking no generated schema in, so a generated side that drifts on any of the three stays green at those sites. Not every such constraint is bound today in every checked-in schema carrying it, and that gap is registered in the deferred contract work list in `docs/ARCHITECTURE.md` as `fpsm-capid-guard` where writing a guard that proves parity is blocked, as it is for `capability_id`, and as `fpsm-unbound-carrier-parity` where it is merely pending. - Keep provider lifecycle behavior in `crates/provider-sdk`. - Keep the capability registry, policy, broker lifecycle, and experiment journal in `crates/control-plane`. - Keep the local IPC transport, framing, and peer-authentication seams behind traits in `crates/ipc` (Unix domain socket now, Windows named pipe later); the privileged broker in `apps/broker` composes them over the control plane and enforces peer auth, catalog policy, and single-owner-per-knob. The non-`Send` control plane is confined to one worker thread reached through a `Send` handle. diff --git a/crates/contracts/src/lib.rs b/crates/contracts/src/lib.rs index e3781d9..3b93361 100644 --- a/crates/contracts/src/lib.rs +++ b/crates/contracts/src/lib.rs @@ -494,12 +494,12 @@ mod tests { /// compared; neither property types nor bounds are, so a `type` that /// disagrees passes here just as a dropped bound does. A field whose /// checked-in schema constrains it beyond a bare `type` (a `minLength`, a - /// `pattern`, a numeric bound) or that carries a `deserialize_with` - /// validator requires its own dedicated test instead, one that binds each - /// checked-in schema carrying that constraint rather than merely one of - /// them; for a `deserialize_with` validator, which no checked-in schema can - /// state, the counterpart to bind is that field's declared `type` in each - /// checked-in schema publishing it. + /// `minItems`, a `pattern`, a numeric bound) or that carries a + /// `deserialize_with` validator requires its own dedicated test instead, + /// one that binds each checked-in schema carrying that constraint rather + /// than merely one of them; for a `deserialize_with` validator, which no + /// checked-in schema can state, the counterpart to bind is that field's + /// declared `type` in each checked-in schema publishing it. fn assert_object_parity(label: &str, generated: &Value, checked_in: &Value) { let generated_properties: BTreeSet = generated["properties"] .as_object() diff --git a/crates/contracts/src/test_support.rs b/crates/contracts/src/test_support.rs index 5bc4d23..d40af79 100644 --- a/crates/contracts/src/test_support.rs +++ b/crates/contracts/src/test_support.rs @@ -59,12 +59,12 @@ pub fn serialized_fields(value: impl serde::Serialize) -> BTreeSet { /// a definition that drifts in any of the three fails the calling test. Neither /// property types nor bounds are compared, so a `type` that disagrees passes /// here just as a dropped bound does. A field whose checked-in schema constrains -/// it beyond a bare `type` (a `minLength`, a `pattern`, a numeric bound) or that -/// carries a `deserialize_with` validator requires its own dedicated test -/// instead, one that binds each checked-in schema carrying that constraint -/// rather than merely one of them; for a `deserialize_with` validator, which no -/// checked-in schema can state, the counterpart to bind is that field's -/// declared `type` in each checked-in schema publishing it. +/// it beyond a bare `type` (a `minLength`, a `minItems`, a `pattern`, a numeric +/// bound) or that carries a `deserialize_with` validator requires its own +/// dedicated test instead, one that binds each checked-in schema carrying that +/// constraint rather than merely one of them; for a `deserialize_with` +/// validator, which no checked-in schema can state, the counterpart to bind is +/// that field's declared `type` in each checked-in schema publishing it. pub fn assert_same_shape(generated: &schemars::Schema, checked_in: &Value) { let generated = serde_json::to_value(generated).expect("generated schema should serialize"); assert_eq!(properties(&generated), properties(checked_in)); From baf01ceb96a3b689a4d95e74247ad6cd0146cd78 Mon Sep 17 00:00:00 2001 From: Jerry Xiao Date: Sun, 2 Aug 2026 11:38:38 +0000 Subject: [PATCH 25/33] no-mistakes(review): scope capid-guard chain to parity guard, fix bind verb --- AGENTS.md | 2 +- docs/ARCHITECTURE.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 8cf1aed..0282dd9 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -17,7 +17,7 @@ Start with `docs/README.md`. Read `docs/IMPLEMENTATION_PLAN.md`, `docs/ARCHITECT - Keep shared wire types in `crates/contracts`, and keep `schemas/*.json` in sync with them; the contract tests enforce matching fields and enum strings. - Give every field whose checked-in schema constrains it beyond `type` (a `minLength`, a `minItems`, a `pattern`, a numeric bound) or that carries a `deserialize_with` validator its own dedicated test that binds each checked-in schema carrying that constraint, not merely one of them; for a `deserialize_with` validator, which no checked-in schema can state, the counterpart to bind is that field's declared `type` in each checked-in schema publishing it. A test binds a schema by opening the checked-in file and asserting the constraint there; a sibling that only asserts what the Rust type rejects binds nothing and is not the pattern to copy. `protocol_version_zero_is_rejected_like_the_schema` and `the_hypothesis_is_bounded_like_the_schema` bind that way and are also complete for the constraints they assert, each opening the schema that carries it: `schemas/sidecar.schema.json` carries the `protocol_version` minimum alone, and `schemas/experiment.schema.json` the hypothesis length bounds alone. `change_request_parameters_are_an_object_in_both` binds that way for a declared `type`, but does so for fewer checked-in schemas than carry the one it asserts, the class registered as `fpsm-unbound-carrier-parity`. - Schema parity reaches property names, `required`, and `additionalProperties` only, so a mismatched `type` or a dropped bound otherwise stays green wherever the comparison is made: `assert_object_parity` and `assert_same_shape` compare each of those keywords between the generated and checked-in schemas; `response_variants_match_schema` hand-rolls the property-name and `required` comparison between those same sides but pins `additionalProperties` to `false` on the checked-in side rather than comparing it, so a generated side that drifts on that keyword stays green there; and `capability_fields_match_capability_schema` and `manifest_fields_match_sidecar_schema` bind the checked-in `properties` and `required` to the field set serde emits for a sample value and pin `additionalProperties` to `false` on that same checked-in side, holding the wire output to the checked-in schema but taking no generated schema in, so a generated side that drifts on any of the three stays green at those sites. Not every such constraint is bound today in every checked-in schema carrying it, and that gap is registered in the deferred contract work list in `docs/ARCHITECTURE.md` as `fpsm-capid-guard` where writing a guard that proves parity is blocked, as it is for `capability_id`, and as `fpsm-unbound-carrier-parity` where it is merely pending. + Schema parity reaches property names, `required`, and `additionalProperties` only, so a mismatched `type` or a dropped bound otherwise stays green wherever the comparison is made: `assert_object_parity` and `assert_same_shape` compare each of those keywords between the generated and checked-in schemas; `response_variants_match_schema` hand-rolls the property-name and `required` comparison between those same sides but pins `additionalProperties` to `false` on the checked-in side rather than comparing it, so a generated side that drifts on that keyword stays green there; and `capability_fields_match_capability_schema` and `manifest_fields_match_sidecar_schema` compare the field set serde emits for a sample value against the checked-in `properties` and `required` and pin `additionalProperties` to `false` on that same checked-in side, holding the wire output to the checked-in schema but taking no generated schema in, so a generated side that drifts on any of the three stays green at those sites. Not every such constraint is bound today in every checked-in schema carrying it, and that gap is registered in the deferred contract work list in `docs/ARCHITECTURE.md` as `fpsm-capid-guard` where writing a guard that proves parity is blocked, as it is for `capability_id`, and as `fpsm-unbound-carrier-parity` where it is merely pending. - Keep provider lifecycle behavior in `crates/provider-sdk`. - Keep the capability registry, policy, broker lifecycle, and experiment journal in `crates/control-plane`. - Keep the local IPC transport, framing, and peer-authentication seams behind traits in `crates/ipc` (Unix domain socket now, Windows named pipe later); the privileged broker in `apps/broker` composes them over the control plane and enforces peer auth, catalog policy, and single-owner-per-knob. The non-`Send` control plane is confined to one worker thread reached through a `Send` handle. diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md index 09917fe..9f2ac8e 100644 --- a/docs/ARCHITECTURE.md +++ b/docs/ARCHITECTURE.md @@ -105,7 +105,7 @@ These span `crates/contracts` and the checked-in schemas rather than any one pro - `fpsm-lease-ceiling-parity`: the missing `maximum` on `$defs.ChangeRequest.lease_seconds` in `schemas/broker-request.schema.json`, which declares only a minimum while `MAX_LEASE_SECONDS` and the change request lease in `schemas/experiment.schema.json` both carry the ceiling, and the gateway's `tools/list` input schema, which states the ceiling independently as the `MAX_LEASE_SECONDS` doc comment intends but which no test binds to that constant in agreement. Raising `MAX_LEASE_SECONDS` on its own is caught: within `lease_seconds_is_bounded_like_the_schema` the assertion comparing the checked-in experiment literal against the constant fails the moment the constant moves, while the assertion comparing the generated value against that same constant moves with it and stays green. Once the experiment schema has been brought along, nothing is left to fail and the gateway advertises a stale ceiling with the suite green. The deferred work is the binding test, not a reference from the gateway to the constant. The control-plane policy check rejects an over-ceiling lease, so this is drift in the published contract rather than in enforcement. - `fpsm-unbound-carrier-parity`: the class of constraint whose dedicated test binds fewer checked-in schemas than carry it, leaving the unbound carriers free to drift with the suite green. The quantifier ranges over each checked-in schema carrying the triggering constraint, read per constraint rather than per field, so one field can be compliant for one of its constraints and not for another, and a carried constraint no test binds at all is inside the class whether a lone schema carries it or several do. What separates this class from `fpsm-capid-guard` is that the Rust field here carries a counterpart for the triggering constraint itself, read per constraint as above: `schemars` emits the minimum for the non-zero lease, and the declared `type` where the attribute names the field a JSON object map. So a guard that proves parity is writable today and the work is pending rather than blocked. A plain `String` also emits a declared `type`, but nothing that a `pattern` or a `minLength` can be held against, which is why `capability_id` stays with the blocked class. The lease floor is the worked example: the change request lease declares the same minimum under `$defs.ChangeRequest` in `schemas/broker-request.schema.json` and under `$defs.change_request` in `schemas/experiment.schema.json`, and no test binds that minimum in either - `lease_seconds_is_bounded_like_the_schema` asserts only the ceiling, and `lease_seconds_zero_is_rejected` asserts only what the Rust type rejects, which binds nothing. That same field is compliant for its ceiling: `lease_seconds_is_bounded_like_the_schema` binds every checked-in schema carrying that ceiling. `ChangeRequest::parameters` is a second instance: `change_request_parameters_are_an_object_in_both` binds the broker request schema, comparing it against the generated schema, while `schemas/experiment.schema.json` publishes the same field's declared `type` and nothing asserts that declared `type` there. A lone carrier falls in the same way: `DecisionBounds::min_samples` declares its minimum in `schemas/experiment.schema.json` alone, and `decision_bounds_are_bounded_like_the_schema` skips that keyword while binding the improvement floor and the exclusive minimums beside it out of the same envelope, so the hole is per keyword in a table that demonstrably does floors. -- `fpsm-capid-guard`: the dedicated guard `AGENTS.md` requires cannot prove parity today for the class of constraint a checked-in schema carries with no Rust-side counterpart to compare against, because the Rust field is a plain type with no constraint attribute and the generated schema therefore states nothing a guard could hold the checked-in constraint against. A guard that opens the checked-in file and asserts the constraint is writable today, but it pins that file against itself and proves no parity. `ChangeRequest::capability_id` is the worked example, and it carries a second blocker of its own: its checked-in schemas constrain it differently from each other, a `pattern` in one and a `minLength` in the other. `ProviderManifest::targets` is a further member with no such second blocker: `schemas/sidecar.schema.json` requires its array to be non-empty through `minItems`, while the Rust field is a bare `Vec` carrying no attribute, so the generated schema states nothing that keyword can be held against. Closing the class needs each such Rust type to carry its constraint, and for `capability_id` the disagreeing schemas settled onto one, before a guard can prove parity; it is a prerequisite chain, not a missing test. +- `fpsm-capid-guard`: the dedicated guard `AGENTS.md` requires cannot prove parity today for the class of constraint a checked-in schema carries with no Rust-side counterpart to compare against, because the Rust field is a plain type with no constraint attribute and the generated schema therefore states nothing a guard could hold the checked-in constraint against. A guard that opens the checked-in file and asserts the constraint is writable today, but it pins that file against itself and proves no parity. `ChangeRequest::capability_id` is the worked example, and it carries a second blocker of its own: its checked-in schemas constrain it differently from each other, a `pattern` in one and a `minLength` in the other. `ProviderManifest::targets` is a further member with no such second blocker: `schemas/sidecar.schema.json` requires its array to be non-empty through `minItems`, while the Rust field is a bare `Vec` carrying no attribute, so the generated schema states nothing that keyword can be held against. Closing the class needs each such Rust type to carry its constraint, and for `capability_id` the disagreeing schemas settled onto one, before a guard can prove parity; that prerequisite chain is what a parity guard waits on, while the binding test `AGENTS.md` requires is writable today and simply missing. ## Dependency rule From f6b33b7f6fa04e284ddcd505cddf3054cad0f8e0 Mon Sep 17 00:00:00 2001 From: Jerry Xiao Date: Sun, 2 Aug 2026 11:50:19 +0000 Subject: [PATCH 26/33] no-mistakes(review): re-sort parity gap pointer, fix bind object drift --- AGENTS.md | 4 ++-- crates/contracts/src/lib.rs | 5 +++-- crates/contracts/src/test_support.rs | 5 +++-- docs/ARCHITECTURE.md | 4 ++-- 4 files changed, 10 insertions(+), 8 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 0282dd9..9863289 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -15,9 +15,9 @@ Start with `docs/README.md`. Read `docs/IMPLEMENTATION_PLAN.md`, `docs/ARCHITECT ## Repository rules - Keep shared wire types in `crates/contracts`, and keep `schemas/*.json` in sync with them; the contract tests enforce matching fields and enum strings. -- Give every field whose checked-in schema constrains it beyond `type` (a `minLength`, a `minItems`, a `pattern`, a numeric bound) or that carries a `deserialize_with` validator its own dedicated test that binds each checked-in schema carrying that constraint, not merely one of them; for a `deserialize_with` validator, which no checked-in schema can state, the counterpart to bind is that field's declared `type` in each checked-in schema publishing it. +- Give every field whose checked-in schema constrains it beyond `type` (a `minLength`, a `minItems`, a `pattern`, a numeric bound) or that carries a `deserialize_with` validator its own dedicated test that binds each checked-in schema carrying that constraint, not merely one of them; for a `deserialize_with` validator, which no checked-in schema can state, that test binds each checked-in schema publishing it and asserts that field's declared `type` there as the counterpart. A test binds a schema by opening the checked-in file and asserting the constraint there; a sibling that only asserts what the Rust type rejects binds nothing and is not the pattern to copy. `protocol_version_zero_is_rejected_like_the_schema` and `the_hypothesis_is_bounded_like_the_schema` bind that way and are also complete for the constraints they assert, each opening the schema that carries it: `schemas/sidecar.schema.json` carries the `protocol_version` minimum alone, and `schemas/experiment.schema.json` the hypothesis length bounds alone. `change_request_parameters_are_an_object_in_both` binds that way for a declared `type`, but does so for fewer checked-in schemas than carry the one it asserts, the class registered as `fpsm-unbound-carrier-parity`. - Schema parity reaches property names, `required`, and `additionalProperties` only, so a mismatched `type` or a dropped bound otherwise stays green wherever the comparison is made: `assert_object_parity` and `assert_same_shape` compare each of those keywords between the generated and checked-in schemas; `response_variants_match_schema` hand-rolls the property-name and `required` comparison between those same sides but pins `additionalProperties` to `false` on the checked-in side rather than comparing it, so a generated side that drifts on that keyword stays green there; and `capability_fields_match_capability_schema` and `manifest_fields_match_sidecar_schema` compare the field set serde emits for a sample value against the checked-in `properties` and `required` and pin `additionalProperties` to `false` on that same checked-in side, holding the wire output to the checked-in schema but taking no generated schema in, so a generated side that drifts on any of the three stays green at those sites. Not every such constraint is bound today in every checked-in schema carrying it, and that gap is registered in the deferred contract work list in `docs/ARCHITECTURE.md` as `fpsm-capid-guard` where writing a guard that proves parity is blocked, as it is for `capability_id`, and as `fpsm-unbound-carrier-parity` where it is merely pending. + Schema parity reaches property names, `required`, and `additionalProperties` only, so a mismatched `type` or a dropped bound otherwise stays green wherever the comparison is made: `assert_object_parity` and `assert_same_shape` compare each of those keywords between the generated and checked-in schemas; `response_variants_match_schema` hand-rolls the property-name and `required` comparison between those same sides but pins `additionalProperties` to `false` on the checked-in side rather than comparing it, so a generated side that drifts on that keyword stays green there; and `capability_fields_match_capability_schema` and `manifest_fields_match_sidecar_schema` compare the field set serde emits for a sample value against the checked-in `properties` and `required` and pin `additionalProperties` to `false` on that same checked-in side, holding the wire output to the checked-in schema but taking no generated schema in, so a generated side that drifts on any of the three stays green at those sites. Some checked-in schemas carrying such a constraint are bound by no test today, and the deferred contract work list in `docs/ARCHITECTURE.md` registers that gap in both `fpsm-capid-guard` and `fpsm-unbound-carrier-parity`, the missing binding test being writable under either; what differs is whether a guard that proves parity can follow it, blocked as it is for `capability_id` and merely pending for the other. - Keep provider lifecycle behavior in `crates/provider-sdk`. - Keep the capability registry, policy, broker lifecycle, and experiment journal in `crates/control-plane`. - Keep the local IPC transport, framing, and peer-authentication seams behind traits in `crates/ipc` (Unix domain socket now, Windows named pipe later); the privileged broker in `apps/broker` composes them over the control plane and enforces peer auth, catalog policy, and single-owner-per-knob. The non-`Send` control plane is confined to one worker thread reached through a `Send` handle. diff --git a/crates/contracts/src/lib.rs b/crates/contracts/src/lib.rs index 3b93361..4e8e49a 100644 --- a/crates/contracts/src/lib.rs +++ b/crates/contracts/src/lib.rs @@ -498,8 +498,9 @@ mod tests { /// `deserialize_with` validator requires its own dedicated test instead, /// one that binds each checked-in schema carrying that constraint rather /// than merely one of them; for a `deserialize_with` validator, which no - /// checked-in schema can state, the counterpart to bind is that field's - /// declared `type` in each checked-in schema publishing it. + /// checked-in schema can state, that test binds each checked-in schema + /// publishing it and asserts that field's declared `type` there as the + /// counterpart. fn assert_object_parity(label: &str, generated: &Value, checked_in: &Value) { let generated_properties: BTreeSet = generated["properties"] .as_object() diff --git a/crates/contracts/src/test_support.rs b/crates/contracts/src/test_support.rs index d40af79..91462e2 100644 --- a/crates/contracts/src/test_support.rs +++ b/crates/contracts/src/test_support.rs @@ -63,8 +63,9 @@ pub fn serialized_fields(value: impl serde::Serialize) -> BTreeSet { /// bound) or that carries a `deserialize_with` validator requires its own /// dedicated test instead, one that binds each checked-in schema carrying that /// constraint rather than merely one of them; for a `deserialize_with` -/// validator, which no checked-in schema can state, the counterpart to bind is -/// that field's declared `type` in each checked-in schema publishing it. +/// validator, which no checked-in schema can state, that test binds each +/// checked-in schema publishing it and asserts that field's declared `type` +/// there as the counterpart. pub fn assert_same_shape(generated: &schemars::Schema, checked_in: &Value) { let generated = serde_json::to_value(generated).expect("generated schema should serialize"); assert_eq!(properties(&generated), properties(checked_in)); diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md index 9f2ac8e..0eb3e76 100644 --- a/docs/ARCHITECTURE.md +++ b/docs/ARCHITECTURE.md @@ -103,8 +103,8 @@ Each sidecar integrates exactly one service or vendor API. Sidecars advertise se These span `crates/contracts` and the checked-in schemas rather than any one process, so they are tracked here rather than under a process heading. -- `fpsm-lease-ceiling-parity`: the missing `maximum` on `$defs.ChangeRequest.lease_seconds` in `schemas/broker-request.schema.json`, which declares only a minimum while `MAX_LEASE_SECONDS` and the change request lease in `schemas/experiment.schema.json` both carry the ceiling, and the gateway's `tools/list` input schema, which states the ceiling independently as the `MAX_LEASE_SECONDS` doc comment intends but which no test binds to that constant in agreement. Raising `MAX_LEASE_SECONDS` on its own is caught: within `lease_seconds_is_bounded_like_the_schema` the assertion comparing the checked-in experiment literal against the constant fails the moment the constant moves, while the assertion comparing the generated value against that same constant moves with it and stays green. Once the experiment schema has been brought along, nothing is left to fail and the gateway advertises a stale ceiling with the suite green. The deferred work is the binding test, not a reference from the gateway to the constant. The control-plane policy check rejects an over-ceiling lease, so this is drift in the published contract rather than in enforcement. -- `fpsm-unbound-carrier-parity`: the class of constraint whose dedicated test binds fewer checked-in schemas than carry it, leaving the unbound carriers free to drift with the suite green. The quantifier ranges over each checked-in schema carrying the triggering constraint, read per constraint rather than per field, so one field can be compliant for one of its constraints and not for another, and a carried constraint no test binds at all is inside the class whether a lone schema carries it or several do. What separates this class from `fpsm-capid-guard` is that the Rust field here carries a counterpart for the triggering constraint itself, read per constraint as above: `schemars` emits the minimum for the non-zero lease, and the declared `type` where the attribute names the field a JSON object map. So a guard that proves parity is writable today and the work is pending rather than blocked. A plain `String` also emits a declared `type`, but nothing that a `pattern` or a `minLength` can be held against, which is why `capability_id` stays with the blocked class. The lease floor is the worked example: the change request lease declares the same minimum under `$defs.ChangeRequest` in `schemas/broker-request.schema.json` and under `$defs.change_request` in `schemas/experiment.schema.json`, and no test binds that minimum in either - `lease_seconds_is_bounded_like_the_schema` asserts only the ceiling, and `lease_seconds_zero_is_rejected` asserts only what the Rust type rejects, which binds nothing. That same field is compliant for its ceiling: `lease_seconds_is_bounded_like_the_schema` binds every checked-in schema carrying that ceiling. `ChangeRequest::parameters` is a second instance: `change_request_parameters_are_an_object_in_both` binds the broker request schema, comparing it against the generated schema, while `schemas/experiment.schema.json` publishes the same field's declared `type` and nothing asserts that declared `type` there. A lone carrier falls in the same way: `DecisionBounds::min_samples` declares its minimum in `schemas/experiment.schema.json` alone, and `decision_bounds_are_bounded_like_the_schema` skips that keyword while binding the improvement floor and the exclusive minimums beside it out of the same envelope, so the hole is per keyword in a table that demonstrably does floors. +- `fpsm-lease-ceiling-parity`: the missing `maximum` on `$defs.ChangeRequest.lease_seconds` in `schemas/broker-request.schema.json`, which declares only a minimum while `MAX_LEASE_SECONDS` and the change request lease in `schemas/experiment.schema.json` both carry the ceiling, and the gateway's `tools/list` input schema, which states the ceiling independently as the `MAX_LEASE_SECONDS` doc comment intends but which no test compares against that constant in agreement. Raising `MAX_LEASE_SECONDS` on its own is caught: within `lease_seconds_is_bounded_like_the_schema` the assertion comparing the checked-in experiment literal against the constant fails the moment the constant moves, while the assertion comparing the generated value against that same constant moves with it and stays green. Once the experiment schema has been brought along, nothing is left to fail and the gateway advertises a stale ceiling with the suite green. The deferred work is the binding test, not a reference from the gateway to the constant. The control-plane policy check rejects an over-ceiling lease, so this is drift in the published contract rather than in enforcement. +- `fpsm-unbound-carrier-parity`: the class of constraint whose dedicated test binds fewer checked-in schemas than carry it, leaving the unbound carriers free to drift with the suite green. The quantifier ranges over each checked-in schema carrying the triggering constraint, read per constraint rather than per field, so one field can be compliant for one of its constraints and not for another, and a carried constraint no test asserts anywhere is inside the class whether a lone schema carries it or several do. What separates this class from `fpsm-capid-guard` is that the Rust field here carries a counterpart for the triggering constraint itself, read per constraint as above: `schemars` emits the minimum for the non-zero lease, and the declared `type` where the attribute names the field a JSON object map. So a guard that proves parity is writable today and the work is pending rather than blocked. A plain `String` also emits a declared `type`, but nothing that a `pattern` or a `minLength` can be held against, which is why `capability_id` stays with the blocked class. The lease floor is the worked example: the change request lease declares the same minimum under `$defs.ChangeRequest` in `schemas/broker-request.schema.json` and under `$defs.change_request` in `schemas/experiment.schema.json`, and no test binds either schema carrying that minimum - `lease_seconds_is_bounded_like_the_schema` asserts only the ceiling, and `lease_seconds_zero_is_rejected` asserts only what the Rust type rejects, which binds nothing. That same field is compliant for its ceiling: `lease_seconds_is_bounded_like_the_schema` binds every checked-in schema carrying that ceiling. `ChangeRequest::parameters` is a second instance: `change_request_parameters_are_an_object_in_both` binds the broker request schema, comparing it against the generated schema, while `schemas/experiment.schema.json` publishes the same field's declared `type` and nothing asserts that declared `type` there. A lone carrier falls in the same way: `DecisionBounds::min_samples` declares its minimum in `schemas/experiment.schema.json` alone, and `decision_bounds_are_bounded_like_the_schema` skips that keyword while asserting the improvement floor and the exclusive minimums beside it out of the same envelope, so the hole is per keyword in a table that demonstrably does floors. - `fpsm-capid-guard`: the dedicated guard `AGENTS.md` requires cannot prove parity today for the class of constraint a checked-in schema carries with no Rust-side counterpart to compare against, because the Rust field is a plain type with no constraint attribute and the generated schema therefore states nothing a guard could hold the checked-in constraint against. A guard that opens the checked-in file and asserts the constraint is writable today, but it pins that file against itself and proves no parity. `ChangeRequest::capability_id` is the worked example, and it carries a second blocker of its own: its checked-in schemas constrain it differently from each other, a `pattern` in one and a `minLength` in the other. `ProviderManifest::targets` is a further member with no such second blocker: `schemas/sidecar.schema.json` requires its array to be non-empty through `minItems`, while the Rust field is a bare `Vec` carrying no attribute, so the generated schema states nothing that keyword can be held against. Closing the class needs each such Rust type to carry its constraint, and for `capability_id` the disagreeing schemas settled onto one, before a guard can prove parity; that prerequisite chain is what a parity guard waits on, while the binding test `AGENTS.md` requires is writable today and simply missing. ## Dependency rule From b20852b85fb3ef6d7d9b263dd45a9c260b069b08 Mon Sep 17 00:00:00 2001 From: Jerry Xiao Date: Sun, 2 Aug 2026 12:07:18 +0000 Subject: [PATCH 27/33] no-mistakes(review): parameterize bind definition, restore per-constraint quantifier --- AGENTS.md | 4 ++-- docs/ARCHITECTURE.md | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 9863289..f3d20da 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -16,8 +16,8 @@ Start with `docs/README.md`. Read `docs/IMPLEMENTATION_PLAN.md`, `docs/ARCHITECT - Keep shared wire types in `crates/contracts`, and keep `schemas/*.json` in sync with them; the contract tests enforce matching fields and enum strings. - Give every field whose checked-in schema constrains it beyond `type` (a `minLength`, a `minItems`, a `pattern`, a numeric bound) or that carries a `deserialize_with` validator its own dedicated test that binds each checked-in schema carrying that constraint, not merely one of them; for a `deserialize_with` validator, which no checked-in schema can state, that test binds each checked-in schema publishing it and asserts that field's declared `type` there as the counterpart. - A test binds a schema by opening the checked-in file and asserting the constraint there; a sibling that only asserts what the Rust type rejects binds nothing and is not the pattern to copy. `protocol_version_zero_is_rejected_like_the_schema` and `the_hypothesis_is_bounded_like_the_schema` bind that way and are also complete for the constraints they assert, each opening the schema that carries it: `schemas/sidecar.schema.json` carries the `protocol_version` minimum alone, and `schemas/experiment.schema.json` the hypothesis length bounds alone. `change_request_parameters_are_an_object_in_both` binds that way for a declared `type`, but does so for fewer checked-in schemas than carry the one it asserts, the class registered as `fpsm-unbound-carrier-parity`. - Schema parity reaches property names, `required`, and `additionalProperties` only, so a mismatched `type` or a dropped bound otherwise stays green wherever the comparison is made: `assert_object_parity` and `assert_same_shape` compare each of those keywords between the generated and checked-in schemas; `response_variants_match_schema` hand-rolls the property-name and `required` comparison between those same sides but pins `additionalProperties` to `false` on the checked-in side rather than comparing it, so a generated side that drifts on that keyword stays green there; and `capability_fields_match_capability_schema` and `manifest_fields_match_sidecar_schema` compare the field set serde emits for a sample value against the checked-in `properties` and `required` and pin `additionalProperties` to `false` on that same checked-in side, holding the wire output to the checked-in schema but taking no generated schema in, so a generated side that drifts on any of the three stays green at those sites. Some checked-in schemas carrying such a constraint are bound by no test today, and the deferred contract work list in `docs/ARCHITECTURE.md` registers that gap in both `fpsm-capid-guard` and `fpsm-unbound-carrier-parity`, the missing binding test being writable under either; what differs is whether a guard that proves parity can follow it, blocked as it is for `capability_id` and merely pending for the other. + A test binds a schema for a constraint by opening the checked-in file and asserting that constraint there; a sibling that only asserts what the Rust type rejects binds nothing and is not the pattern to copy. `protocol_version_zero_is_rejected_like_the_schema` and `the_hypothesis_is_bounded_like_the_schema` bind that way and are also complete for the constraints they assert, each opening the schema that carries it: `schemas/sidecar.schema.json` carries the `protocol_version` minimum alone, and `schemas/experiment.schema.json` the hypothesis length bounds alone. `change_request_parameters_are_an_object_in_both` binds that way for a declared `type`, but does so for fewer checked-in schemas than carry the one it asserts, the class registered as `fpsm-unbound-carrier-parity`. + Schema parity reaches property names, `required`, and `additionalProperties` only, so a mismatched `type` or a dropped bound otherwise stays green wherever the comparison is made: `assert_object_parity` and `assert_same_shape` compare each of those keywords between the generated and checked-in schemas; `response_variants_match_schema` hand-rolls the property-name and `required` comparison between those same sides but pins `additionalProperties` to `false` on the checked-in side rather than comparing it, so a generated side that drifts on that keyword stays green there; and `capability_fields_match_capability_schema` and `manifest_fields_match_sidecar_schema` compare the field set serde emits for a sample value against the checked-in `properties` and `required` and pin `additionalProperties` to `false` on that same checked-in side, holding the wire output to the checked-in schema but taking no generated schema in, so a generated side that drifts on any of the three stays green at those sites. Some checked-in schemas carrying such a constraint are bound for it by no test today, and the deferred contract work list in `docs/ARCHITECTURE.md` registers that gap in both `fpsm-capid-guard` and `fpsm-unbound-carrier-parity`, the missing binding test being writable under either; what differs is whether a guard that proves parity can follow it, blocked as it is in the first entry and merely pending in the second. - Keep provider lifecycle behavior in `crates/provider-sdk`. - Keep the capability registry, policy, broker lifecycle, and experiment journal in `crates/control-plane`. - Keep the local IPC transport, framing, and peer-authentication seams behind traits in `crates/ipc` (Unix domain socket now, Windows named pipe later); the privileged broker in `apps/broker` composes them over the control plane and enforces peer auth, catalog policy, and single-owner-per-knob. The non-`Send` control plane is confined to one worker thread reached through a `Send` handle. diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md index 0eb3e76..b6454cf 100644 --- a/docs/ARCHITECTURE.md +++ b/docs/ARCHITECTURE.md @@ -104,7 +104,7 @@ Each sidecar integrates exactly one service or vendor API. Sidecars advertise se These span `crates/contracts` and the checked-in schemas rather than any one process, so they are tracked here rather than under a process heading. - `fpsm-lease-ceiling-parity`: the missing `maximum` on `$defs.ChangeRequest.lease_seconds` in `schemas/broker-request.schema.json`, which declares only a minimum while `MAX_LEASE_SECONDS` and the change request lease in `schemas/experiment.schema.json` both carry the ceiling, and the gateway's `tools/list` input schema, which states the ceiling independently as the `MAX_LEASE_SECONDS` doc comment intends but which no test compares against that constant in agreement. Raising `MAX_LEASE_SECONDS` on its own is caught: within `lease_seconds_is_bounded_like_the_schema` the assertion comparing the checked-in experiment literal against the constant fails the moment the constant moves, while the assertion comparing the generated value against that same constant moves with it and stays green. Once the experiment schema has been brought along, nothing is left to fail and the gateway advertises a stale ceiling with the suite green. The deferred work is the binding test, not a reference from the gateway to the constant. The control-plane policy check rejects an over-ceiling lease, so this is drift in the published contract rather than in enforcement. -- `fpsm-unbound-carrier-parity`: the class of constraint whose dedicated test binds fewer checked-in schemas than carry it, leaving the unbound carriers free to drift with the suite green. The quantifier ranges over each checked-in schema carrying the triggering constraint, read per constraint rather than per field, so one field can be compliant for one of its constraints and not for another, and a carried constraint no test asserts anywhere is inside the class whether a lone schema carries it or several do. What separates this class from `fpsm-capid-guard` is that the Rust field here carries a counterpart for the triggering constraint itself, read per constraint as above: `schemars` emits the minimum for the non-zero lease, and the declared `type` where the attribute names the field a JSON object map. So a guard that proves parity is writable today and the work is pending rather than blocked. A plain `String` also emits a declared `type`, but nothing that a `pattern` or a `minLength` can be held against, which is why `capability_id` stays with the blocked class. The lease floor is the worked example: the change request lease declares the same minimum under `$defs.ChangeRequest` in `schemas/broker-request.schema.json` and under `$defs.change_request` in `schemas/experiment.schema.json`, and no test binds either schema carrying that minimum - `lease_seconds_is_bounded_like_the_schema` asserts only the ceiling, and `lease_seconds_zero_is_rejected` asserts only what the Rust type rejects, which binds nothing. That same field is compliant for its ceiling: `lease_seconds_is_bounded_like_the_schema` binds every checked-in schema carrying that ceiling. `ChangeRequest::parameters` is a second instance: `change_request_parameters_are_an_object_in_both` binds the broker request schema, comparing it against the generated schema, while `schemas/experiment.schema.json` publishes the same field's declared `type` and nothing asserts that declared `type` there. A lone carrier falls in the same way: `DecisionBounds::min_samples` declares its minimum in `schemas/experiment.schema.json` alone, and `decision_bounds_are_bounded_like_the_schema` skips that keyword while asserting the improvement floor and the exclusive minimums beside it out of the same envelope, so the hole is per keyword in a table that demonstrably does floors. +- `fpsm-unbound-carrier-parity`: the class of constraint whose dedicated test binds fewer checked-in schemas than carry it, leaving the unbound carriers free to drift with the suite green. The quantifier ranges over each checked-in schema carrying the triggering constraint, read per constraint rather than per field, so one field can be compliant for one of its constraints and not for another, and a carried constraint no test asserts anywhere is inside the class whether a lone schema carries it or several do. What separates this class from `fpsm-capid-guard` is that the Rust field here carries a counterpart for the triggering constraint itself, read per constraint as above: `schemars` emits the minimum for the non-zero lease, and the declared `type` where the attribute names the field a JSON object map. So a guard that proves parity is writable today and the work is pending rather than blocked. A plain `String` also emits a declared `type`, but nothing that a `pattern` or a `minLength` can be held against, which is why `capability_id` stays with the blocked class. The lease floor is the worked example: the change request lease declares the same minimum under `$defs.ChangeRequest` in `schemas/broker-request.schema.json` and under `$defs.change_request` in `schemas/experiment.schema.json`, and no test binds either schema for that minimum - `lease_seconds_is_bounded_like_the_schema` asserts only the ceiling, and `lease_seconds_zero_is_rejected` asserts only what the Rust type rejects, which binds nothing. That same field is compliant for its ceiling: `lease_seconds_is_bounded_like_the_schema` binds for that ceiling every checked-in schema that carries it. `ChangeRequest::parameters` is a second instance: `change_request_parameters_are_an_object_in_both` binds the broker request schema for that field's declared `type`, comparing it against the generated schema, while `schemas/experiment.schema.json` publishes the same declared `type` and nothing asserts it there. A lone carrier falls in the same way: `DecisionBounds::min_samples` declares its minimum in `schemas/experiment.schema.json` alone, and `decision_bounds_are_bounded_like_the_schema` skips that keyword while asserting the improvement floor and the exclusive minimums beside it out of the same envelope, so the hole is per keyword in a table that demonstrably does floors. - `fpsm-capid-guard`: the dedicated guard `AGENTS.md` requires cannot prove parity today for the class of constraint a checked-in schema carries with no Rust-side counterpart to compare against, because the Rust field is a plain type with no constraint attribute and the generated schema therefore states nothing a guard could hold the checked-in constraint against. A guard that opens the checked-in file and asserts the constraint is writable today, but it pins that file against itself and proves no parity. `ChangeRequest::capability_id` is the worked example, and it carries a second blocker of its own: its checked-in schemas constrain it differently from each other, a `pattern` in one and a `minLength` in the other. `ProviderManifest::targets` is a further member with no such second blocker: `schemas/sidecar.schema.json` requires its array to be non-empty through `minItems`, while the Rust field is a bare `Vec` carrying no attribute, so the generated schema states nothing that keyword can be held against. Closing the class needs each such Rust type to carry its constraint, and for `capability_id` the disagreeing schemas settled onto one, before a guard can prove parity; that prerequisite chain is what a parity guard waits on, while the binding test `AGENTS.md` requires is writable today and simply missing. ## Dependency rule From 91f0fb788f95dff261c830afdfc8915571d8deb0 Mon Sep 17 00:00:00 2001 From: Jerry Xiao Date: Sun, 2 Aug 2026 12:16:19 +0000 Subject: [PATCH 28/33] no-mistakes(review): replace status ordinal with per-class attachment in pointer --- AGENTS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AGENTS.md b/AGENTS.md index f3d20da..a08764e 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -17,7 +17,7 @@ Start with `docs/README.md`. Read `docs/IMPLEMENTATION_PLAN.md`, `docs/ARCHITECT - Keep shared wire types in `crates/contracts`, and keep `schemas/*.json` in sync with them; the contract tests enforce matching fields and enum strings. - Give every field whose checked-in schema constrains it beyond `type` (a `minLength`, a `minItems`, a `pattern`, a numeric bound) or that carries a `deserialize_with` validator its own dedicated test that binds each checked-in schema carrying that constraint, not merely one of them; for a `deserialize_with` validator, which no checked-in schema can state, that test binds each checked-in schema publishing it and asserts that field's declared `type` there as the counterpart. A test binds a schema for a constraint by opening the checked-in file and asserting that constraint there; a sibling that only asserts what the Rust type rejects binds nothing and is not the pattern to copy. `protocol_version_zero_is_rejected_like_the_schema` and `the_hypothesis_is_bounded_like_the_schema` bind that way and are also complete for the constraints they assert, each opening the schema that carries it: `schemas/sidecar.schema.json` carries the `protocol_version` minimum alone, and `schemas/experiment.schema.json` the hypothesis length bounds alone. `change_request_parameters_are_an_object_in_both` binds that way for a declared `type`, but does so for fewer checked-in schemas than carry the one it asserts, the class registered as `fpsm-unbound-carrier-parity`. - Schema parity reaches property names, `required`, and `additionalProperties` only, so a mismatched `type` or a dropped bound otherwise stays green wherever the comparison is made: `assert_object_parity` and `assert_same_shape` compare each of those keywords between the generated and checked-in schemas; `response_variants_match_schema` hand-rolls the property-name and `required` comparison between those same sides but pins `additionalProperties` to `false` on the checked-in side rather than comparing it, so a generated side that drifts on that keyword stays green there; and `capability_fields_match_capability_schema` and `manifest_fields_match_sidecar_schema` compare the field set serde emits for a sample value against the checked-in `properties` and `required` and pin `additionalProperties` to `false` on that same checked-in side, holding the wire output to the checked-in schema but taking no generated schema in, so a generated side that drifts on any of the three stays green at those sites. Some checked-in schemas carrying such a constraint are bound for it by no test today, and the deferred contract work list in `docs/ARCHITECTURE.md` registers that gap in both `fpsm-capid-guard` and `fpsm-unbound-carrier-parity`, the missing binding test being writable under either; what differs is whether a guard that proves parity can follow it, blocked as it is in the first entry and merely pending in the second. + Schema parity reaches property names, `required`, and `additionalProperties` only, so a mismatched `type` or a dropped bound otherwise stays green wherever the comparison is made: `assert_object_parity` and `assert_same_shape` compare each of those keywords between the generated and checked-in schemas; `response_variants_match_schema` hand-rolls the property-name and `required` comparison between those same sides but pins `additionalProperties` to `false` on the checked-in side rather than comparing it, so a generated side that drifts on that keyword stays green there; and `capability_fields_match_capability_schema` and `manifest_fields_match_sidecar_schema` compare the field set serde emits for a sample value against the checked-in `properties` and `required` and pin `additionalProperties` to `false` on that same checked-in side, holding the wire output to the checked-in schema but taking no generated schema in, so a generated side that drifts on any of the three stays green at those sites. Some checked-in schemas carrying such a constraint are bound for it by no test today, and the deferred contract work list in `docs/ARCHITECTURE.md` registers that gap in both `fpsm-capid-guard`, where writing a guard that proves parity is blocked, and `fpsm-unbound-carrier-parity`, where writing such a guard is merely pending; the missing binding test is writable under either. - Keep provider lifecycle behavior in `crates/provider-sdk`. - Keep the capability registry, policy, broker lifecycle, and experiment journal in `crates/control-plane`. - Keep the local IPC transport, framing, and peer-authentication seams behind traits in `crates/ipc` (Unix domain socket now, Windows named pipe later); the privileged broker in `apps/broker` composes them over the control plane and enforces peer auth, catalog policy, and single-owner-per-knob. The non-`Send` control plane is confined to one worker thread reached through a `Send` handle. From 748882a7b33920b71205336f07d89758083c1745 Mon Sep 17 00:00:00 2001 From: Jerry Xiao Date: Sun, 2 Aug 2026 12:30:55 +0000 Subject: [PATCH 29/33] no-mistakes(review): document class derivability, pin what closes lease-ceiling parity --- docs/ARCHITECTURE.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md index b6454cf..eff60c7 100644 --- a/docs/ARCHITECTURE.md +++ b/docs/ARCHITECTURE.md @@ -102,8 +102,9 @@ Each sidecar integrates exactly one service or vendor API. Sidecars advertise se ## Deferred contract work These span `crates/contracts` and the checked-in schemas rather than any one process, so they are tracked here rather than under a process heading. +Where an entry states a class rather than a single item it does not enumerate that class: membership is derivable by sweeping the checked-in schemas for constraining keywords and applying the entry's own criterion to each carrier the sweep turns up. -- `fpsm-lease-ceiling-parity`: the missing `maximum` on `$defs.ChangeRequest.lease_seconds` in `schemas/broker-request.schema.json`, which declares only a minimum while `MAX_LEASE_SECONDS` and the change request lease in `schemas/experiment.schema.json` both carry the ceiling, and the gateway's `tools/list` input schema, which states the ceiling independently as the `MAX_LEASE_SECONDS` doc comment intends but which no test compares against that constant in agreement. Raising `MAX_LEASE_SECONDS` on its own is caught: within `lease_seconds_is_bounded_like_the_schema` the assertion comparing the checked-in experiment literal against the constant fails the moment the constant moves, while the assertion comparing the generated value against that same constant moves with it and stays green. Once the experiment schema has been brought along, nothing is left to fail and the gateway advertises a stale ceiling with the suite green. The deferred work is the binding test, not a reference from the gateway to the constant. The control-plane policy check rejects an over-ceiling lease, so this is drift in the published contract rather than in enforcement. +- `fpsm-lease-ceiling-parity`: the missing `maximum` on `$defs.ChangeRequest.lease_seconds` in `schemas/broker-request.schema.json`, which declares only a minimum while `MAX_LEASE_SECONDS` and the change request lease in `schemas/experiment.schema.json` both carry the ceiling, and the gateway's `tools/list` input schema, which states the ceiling independently as the `MAX_LEASE_SECONDS` doc comment intends but which no test compares against that constant in agreement. Raising `MAX_LEASE_SECONDS` on its own is caught: within `lease_seconds_is_bounded_like_the_schema` the assertion comparing the checked-in experiment literal against the constant fails the moment the constant moves, while the assertion comparing the generated value against that same constant moves with it and stays green. Once the experiment schema has been brought along, nothing is left to fail and the gateway advertises a stale ceiling with the suite green. Closing this is the schema edit together with the binding test, still not a reference from the gateway to the constant: `lease_seconds_is_bounded_like_the_schema` has to bind the broker request schema for that ceiling in the same change that adds the `maximum` there, or the ceiling clause in `fpsm-unbound-carrier-parity` goes false the moment that edit lands. The control-plane policy check rejects an over-ceiling lease, so this is drift in the published contract rather than in enforcement. - `fpsm-unbound-carrier-parity`: the class of constraint whose dedicated test binds fewer checked-in schemas than carry it, leaving the unbound carriers free to drift with the suite green. The quantifier ranges over each checked-in schema carrying the triggering constraint, read per constraint rather than per field, so one field can be compliant for one of its constraints and not for another, and a carried constraint no test asserts anywhere is inside the class whether a lone schema carries it or several do. What separates this class from `fpsm-capid-guard` is that the Rust field here carries a counterpart for the triggering constraint itself, read per constraint as above: `schemars` emits the minimum for the non-zero lease, and the declared `type` where the attribute names the field a JSON object map. So a guard that proves parity is writable today and the work is pending rather than blocked. A plain `String` also emits a declared `type`, but nothing that a `pattern` or a `minLength` can be held against, which is why `capability_id` stays with the blocked class. The lease floor is the worked example: the change request lease declares the same minimum under `$defs.ChangeRequest` in `schemas/broker-request.schema.json` and under `$defs.change_request` in `schemas/experiment.schema.json`, and no test binds either schema for that minimum - `lease_seconds_is_bounded_like_the_schema` asserts only the ceiling, and `lease_seconds_zero_is_rejected` asserts only what the Rust type rejects, which binds nothing. That same field is compliant for its ceiling: `lease_seconds_is_bounded_like_the_schema` binds for that ceiling every checked-in schema that carries it. `ChangeRequest::parameters` is a second instance: `change_request_parameters_are_an_object_in_both` binds the broker request schema for that field's declared `type`, comparing it against the generated schema, while `schemas/experiment.schema.json` publishes the same declared `type` and nothing asserts it there. A lone carrier falls in the same way: `DecisionBounds::min_samples` declares its minimum in `schemas/experiment.schema.json` alone, and `decision_bounds_are_bounded_like_the_schema` skips that keyword while asserting the improvement floor and the exclusive minimums beside it out of the same envelope, so the hole is per keyword in a table that demonstrably does floors. - `fpsm-capid-guard`: the dedicated guard `AGENTS.md` requires cannot prove parity today for the class of constraint a checked-in schema carries with no Rust-side counterpart to compare against, because the Rust field is a plain type with no constraint attribute and the generated schema therefore states nothing a guard could hold the checked-in constraint against. A guard that opens the checked-in file and asserts the constraint is writable today, but it pins that file against itself and proves no parity. `ChangeRequest::capability_id` is the worked example, and it carries a second blocker of its own: its checked-in schemas constrain it differently from each other, a `pattern` in one and a `minLength` in the other. `ProviderManifest::targets` is a further member with no such second blocker: `schemas/sidecar.schema.json` requires its array to be non-empty through `minItems`, while the Rust field is a bare `Vec` carrying no attribute, so the generated schema states nothing that keyword can be held against. Closing the class needs each such Rust type to carry its constraint, and for `capability_id` the disagreeing schemas settled onto one, before a guard can prove parity; that prerequisite chain is what a parity guard waits on, while the binding test `AGENTS.md` requires is writable today and simply missing. From f91f41b4598b1ad267931c68a594ade15295452b Mon Sep 17 00:00:00 2001 From: Jerry Xiao Date: Sun, 2 Aug 2026 12:39:08 +0000 Subject: [PATCH 30/33] no-mistakes(review): extend class derivability sweep, add gateway closure item --- docs/ARCHITECTURE.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md index eff60c7..b3f28dd 100644 --- a/docs/ARCHITECTURE.md +++ b/docs/ARCHITECTURE.md @@ -102,9 +102,9 @@ Each sidecar integrates exactly one service or vendor API. Sidecars advertise se ## Deferred contract work These span `crates/contracts` and the checked-in schemas rather than any one process, so they are tracked here rather than under a process heading. -Where an entry states a class rather than a single item it does not enumerate that class: membership is derivable by sweeping the checked-in schemas for constraining keywords and applying the entry's own criterion to each carrier the sweep turns up. +Where an entry states a class rather than a single item it does not enumerate that class: membership is derivable by sweeping the checked-in schemas for constraining keywords and the Rust types for a `deserialize_with` validator, which no checked-in schema can state, then applying the entry's own criterion to each carrier either sweep turns up. -- `fpsm-lease-ceiling-parity`: the missing `maximum` on `$defs.ChangeRequest.lease_seconds` in `schemas/broker-request.schema.json`, which declares only a minimum while `MAX_LEASE_SECONDS` and the change request lease in `schemas/experiment.schema.json` both carry the ceiling, and the gateway's `tools/list` input schema, which states the ceiling independently as the `MAX_LEASE_SECONDS` doc comment intends but which no test compares against that constant in agreement. Raising `MAX_LEASE_SECONDS` on its own is caught: within `lease_seconds_is_bounded_like_the_schema` the assertion comparing the checked-in experiment literal against the constant fails the moment the constant moves, while the assertion comparing the generated value against that same constant moves with it and stays green. Once the experiment schema has been brought along, nothing is left to fail and the gateway advertises a stale ceiling with the suite green. Closing this is the schema edit together with the binding test, still not a reference from the gateway to the constant: `lease_seconds_is_bounded_like_the_schema` has to bind the broker request schema for that ceiling in the same change that adds the `maximum` there, or the ceiling clause in `fpsm-unbound-carrier-parity` goes false the moment that edit lands. The control-plane policy check rejects an over-ceiling lease, so this is drift in the published contract rather than in enforcement. +- `fpsm-lease-ceiling-parity`: the missing `maximum` on `$defs.ChangeRequest.lease_seconds` in `schemas/broker-request.schema.json`, which declares only a minimum while `MAX_LEASE_SECONDS` and the change request lease in `schemas/experiment.schema.json` both carry the ceiling, and the gateway's `tools/list` input schema, which states the ceiling independently as the `MAX_LEASE_SECONDS` doc comment intends but which no test compares against that constant in agreement. Raising `MAX_LEASE_SECONDS` on its own is caught: within `lease_seconds_is_bounded_like_the_schema` the assertion comparing the checked-in experiment literal against the constant fails the moment the constant moves, while the assertion comparing the generated value against that same constant moves with it and stays green. Once the experiment schema has been brought along, nothing is left to fail and the gateway advertises a stale ceiling with the suite green. Closing this is the `maximum` added to the broker request schema, `lease_seconds_is_bounded_like_the_schema` binding that schema for the ceiling in the same change - or the ceiling clause in `fpsm-unbound-carrier-parity` goes false the moment that edit lands - and a test comparing the gateway's inline ceiling against the constant, still not a reference from the gateway to it. The control-plane policy check rejects an over-ceiling lease, so this is drift in the published contract rather than in enforcement. - `fpsm-unbound-carrier-parity`: the class of constraint whose dedicated test binds fewer checked-in schemas than carry it, leaving the unbound carriers free to drift with the suite green. The quantifier ranges over each checked-in schema carrying the triggering constraint, read per constraint rather than per field, so one field can be compliant for one of its constraints and not for another, and a carried constraint no test asserts anywhere is inside the class whether a lone schema carries it or several do. What separates this class from `fpsm-capid-guard` is that the Rust field here carries a counterpart for the triggering constraint itself, read per constraint as above: `schemars` emits the minimum for the non-zero lease, and the declared `type` where the attribute names the field a JSON object map. So a guard that proves parity is writable today and the work is pending rather than blocked. A plain `String` also emits a declared `type`, but nothing that a `pattern` or a `minLength` can be held against, which is why `capability_id` stays with the blocked class. The lease floor is the worked example: the change request lease declares the same minimum under `$defs.ChangeRequest` in `schemas/broker-request.schema.json` and under `$defs.change_request` in `schemas/experiment.schema.json`, and no test binds either schema for that minimum - `lease_seconds_is_bounded_like_the_schema` asserts only the ceiling, and `lease_seconds_zero_is_rejected` asserts only what the Rust type rejects, which binds nothing. That same field is compliant for its ceiling: `lease_seconds_is_bounded_like_the_schema` binds for that ceiling every checked-in schema that carries it. `ChangeRequest::parameters` is a second instance: `change_request_parameters_are_an_object_in_both` binds the broker request schema for that field's declared `type`, comparing it against the generated schema, while `schemas/experiment.schema.json` publishes the same declared `type` and nothing asserts it there. A lone carrier falls in the same way: `DecisionBounds::min_samples` declares its minimum in `schemas/experiment.schema.json` alone, and `decision_bounds_are_bounded_like_the_schema` skips that keyword while asserting the improvement floor and the exclusive minimums beside it out of the same envelope, so the hole is per keyword in a table that demonstrably does floors. - `fpsm-capid-guard`: the dedicated guard `AGENTS.md` requires cannot prove parity today for the class of constraint a checked-in schema carries with no Rust-side counterpart to compare against, because the Rust field is a plain type with no constraint attribute and the generated schema therefore states nothing a guard could hold the checked-in constraint against. A guard that opens the checked-in file and asserts the constraint is writable today, but it pins that file against itself and proves no parity. `ChangeRequest::capability_id` is the worked example, and it carries a second blocker of its own: its checked-in schemas constrain it differently from each other, a `pattern` in one and a `minLength` in the other. `ProviderManifest::targets` is a further member with no such second blocker: `schemas/sidecar.schema.json` requires its array to be non-empty through `minItems`, while the Rust field is a bare `Vec` carrying no attribute, so the generated schema states nothing that keyword can be held against. Closing the class needs each such Rust type to carry its constraint, and for `capability_id` the disagreeing schemas settled onto one, before a guard can prove parity; that prerequisite chain is what a parity guard waits on, while the binding test `AGENTS.md` requires is writable today and simply missing. From 53ee7cf288a4b227588391b20781674ada943756 Mon Sep 17 00:00:00 2001 From: Jerry Xiao Date: Sun, 2 Aug 2026 12:54:11 +0000 Subject: [PATCH 31/33] no-mistakes(review): name field referent, make constraint the sweep unit --- AGENTS.md | 2 +- crates/contracts/src/lib.rs | 4 ++-- crates/contracts/src/test_support.rs | 4 ++-- docs/ARCHITECTURE.md | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index a08764e..b04b81a 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -15,7 +15,7 @@ Start with `docs/README.md`. Read `docs/IMPLEMENTATION_PLAN.md`, `docs/ARCHITECT ## Repository rules - Keep shared wire types in `crates/contracts`, and keep `schemas/*.json` in sync with them; the contract tests enforce matching fields and enum strings. -- Give every field whose checked-in schema constrains it beyond `type` (a `minLength`, a `minItems`, a `pattern`, a numeric bound) or that carries a `deserialize_with` validator its own dedicated test that binds each checked-in schema carrying that constraint, not merely one of them; for a `deserialize_with` validator, which no checked-in schema can state, that test binds each checked-in schema publishing it and asserts that field's declared `type` there as the counterpart. +- Give every field whose checked-in schema constrains it beyond `type` (a `minLength`, a `minItems`, a `pattern`, a numeric bound) or that carries a `deserialize_with` validator its own dedicated test that binds each checked-in schema carrying that constraint, not merely one of them; for a `deserialize_with` validator, which no checked-in schema can state, that test binds each checked-in schema publishing that field and asserts that field's declared `type` there as the counterpart. A test binds a schema for a constraint by opening the checked-in file and asserting that constraint there; a sibling that only asserts what the Rust type rejects binds nothing and is not the pattern to copy. `protocol_version_zero_is_rejected_like_the_schema` and `the_hypothesis_is_bounded_like_the_schema` bind that way and are also complete for the constraints they assert, each opening the schema that carries it: `schemas/sidecar.schema.json` carries the `protocol_version` minimum alone, and `schemas/experiment.schema.json` the hypothesis length bounds alone. `change_request_parameters_are_an_object_in_both` binds that way for a declared `type`, but does so for fewer checked-in schemas than carry the one it asserts, the class registered as `fpsm-unbound-carrier-parity`. Schema parity reaches property names, `required`, and `additionalProperties` only, so a mismatched `type` or a dropped bound otherwise stays green wherever the comparison is made: `assert_object_parity` and `assert_same_shape` compare each of those keywords between the generated and checked-in schemas; `response_variants_match_schema` hand-rolls the property-name and `required` comparison between those same sides but pins `additionalProperties` to `false` on the checked-in side rather than comparing it, so a generated side that drifts on that keyword stays green there; and `capability_fields_match_capability_schema` and `manifest_fields_match_sidecar_schema` compare the field set serde emits for a sample value against the checked-in `properties` and `required` and pin `additionalProperties` to `false` on that same checked-in side, holding the wire output to the checked-in schema but taking no generated schema in, so a generated side that drifts on any of the three stays green at those sites. Some checked-in schemas carrying such a constraint are bound for it by no test today, and the deferred contract work list in `docs/ARCHITECTURE.md` registers that gap in both `fpsm-capid-guard`, where writing a guard that proves parity is blocked, and `fpsm-unbound-carrier-parity`, where writing such a guard is merely pending; the missing binding test is writable under either. - Keep provider lifecycle behavior in `crates/provider-sdk`. diff --git a/crates/contracts/src/lib.rs b/crates/contracts/src/lib.rs index 4e8e49a..12f3c59 100644 --- a/crates/contracts/src/lib.rs +++ b/crates/contracts/src/lib.rs @@ -499,8 +499,8 @@ mod tests { /// one that binds each checked-in schema carrying that constraint rather /// than merely one of them; for a `deserialize_with` validator, which no /// checked-in schema can state, that test binds each checked-in schema - /// publishing it and asserts that field's declared `type` there as the - /// counterpart. + /// publishing that field and asserts that field's declared `type` there as + /// the counterpart. fn assert_object_parity(label: &str, generated: &Value, checked_in: &Value) { let generated_properties: BTreeSet = generated["properties"] .as_object() diff --git a/crates/contracts/src/test_support.rs b/crates/contracts/src/test_support.rs index 91462e2..8e4d599 100644 --- a/crates/contracts/src/test_support.rs +++ b/crates/contracts/src/test_support.rs @@ -64,8 +64,8 @@ pub fn serialized_fields(value: impl serde::Serialize) -> BTreeSet { /// dedicated test instead, one that binds each checked-in schema carrying that /// constraint rather than merely one of them; for a `deserialize_with` /// validator, which no checked-in schema can state, that test binds each -/// checked-in schema publishing it and asserts that field's declared `type` -/// there as the counterpart. +/// checked-in schema publishing that field and asserts that field's declared +/// `type` there as the counterpart. pub fn assert_same_shape(generated: &schemars::Schema, checked_in: &Value) { let generated = serde_json::to_value(generated).expect("generated schema should serialize"); assert_eq!(properties(&generated), properties(checked_in)); diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md index b3f28dd..578e309 100644 --- a/docs/ARCHITECTURE.md +++ b/docs/ARCHITECTURE.md @@ -102,7 +102,7 @@ Each sidecar integrates exactly one service or vendor API. Sidecars advertise se ## Deferred contract work These span `crates/contracts` and the checked-in schemas rather than any one process, so they are tracked here rather than under a process heading. -Where an entry states a class rather than a single item it does not enumerate that class: membership is derivable by sweeping the checked-in schemas for constraining keywords and the Rust types for a `deserialize_with` validator, which no checked-in schema can state, then applying the entry's own criterion to each carrier either sweep turns up. +Where an entry states a class rather than a single item it does not enumerate that class: membership is derivable by sweeping the checked-in schemas for constraining keywords and the Rust types for a field carrying a `deserialize_with` validator, which no checked-in schema can state, then applying the entry's own criterion per constraint to that constraint's carriers - for a keyword, the checked-in schemas stating it; for a validator, the checked-in schemas publishing that field. - `fpsm-lease-ceiling-parity`: the missing `maximum` on `$defs.ChangeRequest.lease_seconds` in `schemas/broker-request.schema.json`, which declares only a minimum while `MAX_LEASE_SECONDS` and the change request lease in `schemas/experiment.schema.json` both carry the ceiling, and the gateway's `tools/list` input schema, which states the ceiling independently as the `MAX_LEASE_SECONDS` doc comment intends but which no test compares against that constant in agreement. Raising `MAX_LEASE_SECONDS` on its own is caught: within `lease_seconds_is_bounded_like_the_schema` the assertion comparing the checked-in experiment literal against the constant fails the moment the constant moves, while the assertion comparing the generated value against that same constant moves with it and stays green. Once the experiment schema has been brought along, nothing is left to fail and the gateway advertises a stale ceiling with the suite green. Closing this is the `maximum` added to the broker request schema, `lease_seconds_is_bounded_like_the_schema` binding that schema for the ceiling in the same change - or the ceiling clause in `fpsm-unbound-carrier-parity` goes false the moment that edit lands - and a test comparing the gateway's inline ceiling against the constant, still not a reference from the gateway to it. The control-plane policy check rejects an over-ceiling lease, so this is drift in the published contract rather than in enforcement. - `fpsm-unbound-carrier-parity`: the class of constraint whose dedicated test binds fewer checked-in schemas than carry it, leaving the unbound carriers free to drift with the suite green. The quantifier ranges over each checked-in schema carrying the triggering constraint, read per constraint rather than per field, so one field can be compliant for one of its constraints and not for another, and a carried constraint no test asserts anywhere is inside the class whether a lone schema carries it or several do. What separates this class from `fpsm-capid-guard` is that the Rust field here carries a counterpart for the triggering constraint itself, read per constraint as above: `schemars` emits the minimum for the non-zero lease, and the declared `type` where the attribute names the field a JSON object map. So a guard that proves parity is writable today and the work is pending rather than blocked. A plain `String` also emits a declared `type`, but nothing that a `pattern` or a `minLength` can be held against, which is why `capability_id` stays with the blocked class. The lease floor is the worked example: the change request lease declares the same minimum under `$defs.ChangeRequest` in `schemas/broker-request.schema.json` and under `$defs.change_request` in `schemas/experiment.schema.json`, and no test binds either schema for that minimum - `lease_seconds_is_bounded_like_the_schema` asserts only the ceiling, and `lease_seconds_zero_is_rejected` asserts only what the Rust type rejects, which binds nothing. That same field is compliant for its ceiling: `lease_seconds_is_bounded_like_the_schema` binds for that ceiling every checked-in schema that carries it. `ChangeRequest::parameters` is a second instance: `change_request_parameters_are_an_object_in_both` binds the broker request schema for that field's declared `type`, comparing it against the generated schema, while `schemas/experiment.schema.json` publishes the same declared `type` and nothing asserts it there. A lone carrier falls in the same way: `DecisionBounds::min_samples` declares its minimum in `schemas/experiment.schema.json` alone, and `decision_bounds_are_bounded_like_the_schema` skips that keyword while asserting the improvement floor and the exclusive minimums beside it out of the same envelope, so the hole is per keyword in a table that demonstrably does floors. From 88d1efe8f2275703142357c566ec0b6bd50682b4 Mon Sep 17 00:00:00 2001 From: Jerry Xiao Date: Sun, 2 Aug 2026 13:19:26 +0000 Subject: [PATCH 32/33] no-mistakes(document): scope broker schema sync claim to contract-test reach --- docs/ARCHITECTURE.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md index 578e309..fc1ada2 100644 --- a/docs/ARCHITECTURE.md +++ b/docs/ARCHITECTURE.md @@ -19,7 +19,8 @@ The privileged Windows service accepts authenticated local requests from the gat `apps/broker` implements this on the Linux-safe path. It owns the control plane on a dedicated worker thread and serves exactly two operations - capability discovery and a bounded provider lifecycle - to authenticated local peers over the transport seam in `crates/ipc` (a Unix domain socket now, a Windows named pipe later). Three fail-closed checks guard the boundary: peer authentication before any request is read (a Linux `SO_PEERCRED` same-uid ACL, shaped so a Windows SID ACL can satisfy the same trait), a capability-catalog check that rejects raw shell, arbitrary Registry paths, and out-of-catalog ids, and single-owner-per-knob enforcement that refuses a second concurrent owner of a setting. -Typed request and response messages live in `crates/contracts` with `schemas/broker-request.schema.json` and `schemas/broker-response.schema.json` kept in sync; a malformed frame is rejected with a typed error without taking the broker down. +Typed request and response messages live in `crates/contracts` with `schemas/broker-request.schema.json` and `schemas/broker-response.schema.json` kept in sync as far as the contract tests reach; a malformed frame is rejected with a typed error without taking the broker down. +The deferred contract work list below registers where that reach falls short today, including the `lease_seconds` ceiling `MAX_LEASE_SECONDS` declares and the request schema omits. A frame is a big-endian `u32` body length followed by that many bytes of JSON, bounded at one mebibyte so a hostile peer cannot force an unbounded allocation; the framing is transport-agnostic, so a named-pipe transport would reuse it unchanged. At most 32 connections are served at once, and one that stalls for 30 seconds in either direction is closed, so a peer cannot pin a task, a descriptor, or a frame buffer; a peer refused by the ACL gets a far shorter deadline to take its rejection frame, because it has not authenticated and must not be able to hold a connection slot for the full idle budget. A response is a tagged union of its outcome and that outcome's payload, so a tag without its payload never crosses the boundary and no consumer has to unwrap one. From 26d3fb6cb579046f27456be5a3d525a7717d9ac9 Mon Sep 17 00:00:00 2001 From: Jerry Xiao Date: Sun, 2 Aug 2026 13:28:45 +0000 Subject: [PATCH 33/33] no-mistakes(document): give bind predicate a for-slot, drop register overclaim --- AGENTS.md | 2 +- crates/contracts/src/lib.rs | 10 +++++----- crates/contracts/src/test_support.rs | 11 +++++++---- docs/ARCHITECTURE.md | 1 - 4 files changed, 13 insertions(+), 11 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index b04b81a..7627524 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -15,7 +15,7 @@ Start with `docs/README.md`. Read `docs/IMPLEMENTATION_PLAN.md`, `docs/ARCHITECT ## Repository rules - Keep shared wire types in `crates/contracts`, and keep `schemas/*.json` in sync with them; the contract tests enforce matching fields and enum strings. -- Give every field whose checked-in schema constrains it beyond `type` (a `minLength`, a `minItems`, a `pattern`, a numeric bound) or that carries a `deserialize_with` validator its own dedicated test that binds each checked-in schema carrying that constraint, not merely one of them; for a `deserialize_with` validator, which no checked-in schema can state, that test binds each checked-in schema publishing that field and asserts that field's declared `type` there as the counterpart. +- Give every field whose checked-in schema constrains it beyond `type` (a `minLength`, a `minItems`, a `pattern`, a numeric bound) or that carries a `deserialize_with` validator its own dedicated test that binds for that constraint each checked-in schema carrying it, not merely one of them; for a `deserialize_with` validator, which no checked-in schema can state, that test binds each checked-in schema publishing that field and asserts that field's declared `type` there as the counterpart. A test binds a schema for a constraint by opening the checked-in file and asserting that constraint there; a sibling that only asserts what the Rust type rejects binds nothing and is not the pattern to copy. `protocol_version_zero_is_rejected_like_the_schema` and `the_hypothesis_is_bounded_like_the_schema` bind that way and are also complete for the constraints they assert, each opening the schema that carries it: `schemas/sidecar.schema.json` carries the `protocol_version` minimum alone, and `schemas/experiment.schema.json` the hypothesis length bounds alone. `change_request_parameters_are_an_object_in_both` binds that way for a declared `type`, but does so for fewer checked-in schemas than carry the one it asserts, the class registered as `fpsm-unbound-carrier-parity`. Schema parity reaches property names, `required`, and `additionalProperties` only, so a mismatched `type` or a dropped bound otherwise stays green wherever the comparison is made: `assert_object_parity` and `assert_same_shape` compare each of those keywords between the generated and checked-in schemas; `response_variants_match_schema` hand-rolls the property-name and `required` comparison between those same sides but pins `additionalProperties` to `false` on the checked-in side rather than comparing it, so a generated side that drifts on that keyword stays green there; and `capability_fields_match_capability_schema` and `manifest_fields_match_sidecar_schema` compare the field set serde emits for a sample value against the checked-in `properties` and `required` and pin `additionalProperties` to `false` on that same checked-in side, holding the wire output to the checked-in schema but taking no generated schema in, so a generated side that drifts on any of the three stays green at those sites. Some checked-in schemas carrying such a constraint are bound for it by no test today, and the deferred contract work list in `docs/ARCHITECTURE.md` registers that gap in both `fpsm-capid-guard`, where writing a guard that proves parity is blocked, and `fpsm-unbound-carrier-parity`, where writing such a guard is merely pending; the missing binding test is writable under either. - Keep provider lifecycle behavior in `crates/provider-sdk`. diff --git a/crates/contracts/src/lib.rs b/crates/contracts/src/lib.rs index 12f3c59..532840f 100644 --- a/crates/contracts/src/lib.rs +++ b/crates/contracts/src/lib.rs @@ -496,11 +496,11 @@ mod tests { /// checked-in schema constrains it beyond a bare `type` (a `minLength`, a /// `minItems`, a `pattern`, a numeric bound) or that carries a /// `deserialize_with` validator requires its own dedicated test instead, - /// one that binds each checked-in schema carrying that constraint rather - /// than merely one of them; for a `deserialize_with` validator, which no - /// checked-in schema can state, that test binds each checked-in schema - /// publishing that field and asserts that field's declared `type` there as - /// the counterpart. + /// one that binds for that constraint each checked-in schema carrying it + /// rather than merely one of them; for a `deserialize_with` validator, + /// which no checked-in schema can state, that test binds each checked-in + /// schema publishing that field and asserts that field's declared `type` + /// there as the counterpart. fn assert_object_parity(label: &str, generated: &Value, checked_in: &Value) { let generated_properties: BTreeSet = generated["properties"] .as_object() diff --git a/crates/contracts/src/test_support.rs b/crates/contracts/src/test_support.rs index 8e4d599..4454a4e 100644 --- a/crates/contracts/src/test_support.rs +++ b/crates/contracts/src/test_support.rs @@ -1,8 +1,11 @@ //! Shared helpers for the schema-synchronization tests. //! //! `schemas/*.json` are hand-written and must agree with the types in this -//! crate. Every schema-sync test module compares them the same way, so the -//! comparison lives here once rather than being re-derived per module. +//! crate. The helpers here collect the pieces those tests compare, and +//! `assert_same_shape` is one body of that comparison: the tests in `ipc` call +//! it, while `lib` has its own `assert_object_parity` beside field-set tests +//! that hold a serialized sample against a checked-in schema with no generated +//! schema in hand. use std::collections::BTreeSet; @@ -61,8 +64,8 @@ pub fn serialized_fields(value: impl serde::Serialize) -> BTreeSet { /// here just as a dropped bound does. A field whose checked-in schema constrains /// it beyond a bare `type` (a `minLength`, a `minItems`, a `pattern`, a numeric /// bound) or that carries a `deserialize_with` validator requires its own -/// dedicated test instead, one that binds each checked-in schema carrying that -/// constraint rather than merely one of them; for a `deserialize_with` +/// dedicated test instead, one that binds for that constraint each checked-in +/// schema carrying it rather than merely one of them; for a `deserialize_with` /// validator, which no checked-in schema can state, that test binds each /// checked-in schema publishing that field and asserts that field's declared /// `type` there as the counterpart. diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md index fc1ada2..2c6551d 100644 --- a/docs/ARCHITECTURE.md +++ b/docs/ARCHITECTURE.md @@ -20,7 +20,6 @@ The privileged Windows service accepts authenticated local requests from the gat It owns the control plane on a dedicated worker thread and serves exactly two operations - capability discovery and a bounded provider lifecycle - to authenticated local peers over the transport seam in `crates/ipc` (a Unix domain socket now, a Windows named pipe later). Three fail-closed checks guard the boundary: peer authentication before any request is read (a Linux `SO_PEERCRED` same-uid ACL, shaped so a Windows SID ACL can satisfy the same trait), a capability-catalog check that rejects raw shell, arbitrary Registry paths, and out-of-catalog ids, and single-owner-per-knob enforcement that refuses a second concurrent owner of a setting. Typed request and response messages live in `crates/contracts` with `schemas/broker-request.schema.json` and `schemas/broker-response.schema.json` kept in sync as far as the contract tests reach; a malformed frame is rejected with a typed error without taking the broker down. -The deferred contract work list below registers where that reach falls short today, including the `lease_seconds` ceiling `MAX_LEASE_SECONDS` declares and the request schema omits. A frame is a big-endian `u32` body length followed by that many bytes of JSON, bounded at one mebibyte so a hostile peer cannot force an unbounded allocation; the framing is transport-agnostic, so a named-pipe transport would reuse it unchanged. At most 32 connections are served at once, and one that stalls for 30 seconds in either direction is closed, so a peer cannot pin a task, a descriptor, or a frame buffer; a peer refused by the ACL gets a far shorter deadline to take its rejection frame, because it has not authenticated and must not be able to hold a connection slot for the full idle budget. A response is a tagged union of its outcome and that outcome's payload, so a tag without its payload never crosses the boundary and no consumer has to unwrap one.