Wire composite references and add per-field rejecting fixtures #5

Merged
korr merged 1 commit from fix/composite-schema-refs into main 2026-07-29 05:07:07 +00:00
Owner

Closes #4

Adds deterministic, self-contained local-reference bundles for exact Protocol document compositions, field-specific rejecting fixtures, populated accepting fixtures, stale-bundle validation, and packaging documentation.

<!-- homeostat:effect:issue-13:research:plan-composite-schema-assertions:code-composite-refs-and-fixtures:retry-composite-refs-and-fixtures:create-composite-refs-pr --> Closes #4 Adds deterministic, self-contained local-reference bundles for exact Protocol document compositions, field-specific rejecting fixtures, populated accepting fixtures, stale-bundle validation, and packaging documentation.
Wire composite schema references
All checks were successful
Validate Protocol / validate (pull_request) Successful in 11s
Validate Protocol / validate (push) Successful in 11s
516e96e098
Homeostat-Effect: issue-13:research:plan-composite-schema-assertions:code-composite-refs-and-fixtures:retry-composite-refs-and-fixtures:commit-composite-refs
Homeostat-Provider: codex
Author
Owner

Homeostat invocation issue-13:research:plan-composite-schema-assertions:code-composite-refs-and-fixtures:retry-composite-refs-and-fixtures:review-composite-refs

Status: complete
Capability: review
Provider/model: claude/default

Input to AI

Independently review the exact pushed head and verify the bundled references, fixtures, and packaging checks.

Subject: Review composite schema references and fixtures

Output from AI

Reviewed the exact pushed head of PR #5 (homeostat/protocol, fix/composite-schema-refs @ 516e96e098) against issue #4's acceptance criteria. Approved.

What the PR does: it wires the four composite fields that name an exact Protocol document type — capability-result findings and completion.evidence, invocation readings, and ledger-entry deferred — to their part schemas through local $ref fragments into embedded $defs, generated deterministically by the new tools/bundle.py and enforced non-stale by tools/validate.py. Fields that are genuinely open (capability-result evidence, invocation trusted_inputs/guides) are correctly left alone since no part schema exists for them.

Independent verification performed (not just re-reading the diff):

  • python3 tools/validate.py passes clean on the exact head (9 schemas, 27 accepting fixtures, 41 rejecting fixtures).
  • python3 tools/bundle.py --check reports no stale bundles.
  • Copied only schemas/ledger-entry.schema.json into an empty directory and validated a real fixture against it in total isolation — 0 errors, proving the doubly-nested ledger-entry -> invocation -> reading embedding is genuinely self-contained with no cross-file resolution, which is the actual constraint (transducer/governor pass a single file path) that blocked this fix originally per NOTES.md.
  • Injected an unexpected property into a nested finding and confirmed jsonschema rejects it — the nested $id inside $defs does not defeat local $ref enforcement.
  • Each of the four wired fields has its own distinct rejecting fixture naming the field it proves; existing valid fixtures were updated to keep passing, and one of those updates (adding budget.ledger to fixtures/valid/ledger-entry.deferred-join.json) fixes a real pre-existing gap the old inert bare-object deferred field never caught.
  • Both required Forgejo checks succeed on this exact SHA, and the PR head matches the pushed branch tip.

No material finding. One non-blocking maintainability note is recorded: tools/bundle.py's BUNDLES dict relies on insertion order for single-pass convergence of the nested ledger-entry/invocation/reading embedding; --check is self-healing against this in CI, but it's worth a comment.

Requesting forgejo.review.submit (approved) followed by forgejo.merge.schedule, both pinned to 516e96e098.

Evidence

  • {'kind': 'command', 'command': 'python3 tools/validate.py', 'result': 'validated 9 schemas, 27 accepting fixtures, and 41 rejecting fixtures', 'exit_code': 0}
  • {'kind': 'command', 'command': 'python3 tools/bundle.py --check', 'result': 'exit 0', 'exit_code': 0}
  • {'kind': 'test', 'description': 'isolated single-file validation: copied only schemas/ledger-entry.schema.json plus a valid fixture into an empty temp directory, validated with jsonschema.Draft202012Validator with no other files present', 'result': '0 errors, proving the ledger-entry -> invocation -> reading double-nested $defs embedding resolves with zero external file access'}
  • {'kind': 'test', 'description': "injected an unexpected property into fixtures/valid/capability-result.complete.json's findings[0] and re-validated against schemas/capability-result.schema.json", 'result': 'rejected: "Additional properties are not allowed ('bogus_extra_field' was unexpected)" at path ['findings', 0], proving nested additionalProperties:false is enforced through the local $ref despite the embedded $defs entry carrying its own $id'}
  • {'kind': 'api', 'endpoint': 'GET /repos/homeostat/protocol/commits/516e96e0986c94f76168e1fbf0fb71c1fc77ab22/status', 'result': 'state: success, 2/2 contexts success (Validate Protocol / validate, pull_request and push)'}
  • {'kind': 'api', 'endpoint': 'GET /repos/homeostat/protocol/pulls/5', 'result': 'head.sha 516e96e098 matches origin/fix/composite-schema-refs tip; mergeable true; not yet merged'}
  • {'kind': 'api', 'endpoint': 'GET /repos/homeostat/protocol/issues/4', 'result': 'acceptance criteria text used to cross-check PR scope: wire composite fields via $ref, add per-field rejecting fixtures, keep representative valid documents passing, prove references resolve in the bundled/packaged form'}
  • {'kind': 'file_diff', 'description': 'git diff origin/main...origin/fix/composite-schema-refs reviewed in full: NOTES.md, README.md, tools/bundle.py (new), tools/validate.py, schemas/capability-result.schema.json, schemas/invocation.schema.json, schemas/ledger-entry.schema.json, and all fixture additions/changes'}

Findings

  • BUNDLES dict order is a load-bearing implicit topological order (invocation must precede ledger-entry) with no comment or assertion protecting it.

Requested effects

  • {'id': 'review-composite-refs', 'kind': 'forgejo.review.submit', 'subject': 'homeostat/protocol#5', 'expected_revision': '516e96e098', 'parameters': {'verdict': 'approved', 'body': "Independently reviewed exact head 516e96e098 against issue #4's acceptance criteria. Verified: (1) python3 tools/validate.py passes clean (9 schemas, 27 accepting fixtures, 41 rejecting fixtures); (2) python3 tools/bundle.py --check reports no stale bundles; (3) copying only schemas/ledger-entry.schema.json into an empty directory and validating a real fixture against it in isolation succeeds with zero errors and zero external file access, proving the consumer-facing single-file form (the actual constraint that blocked this fix per NOTES.md) is genuinely self-contained through the doubly-nested ledger-entry -> invocation -> reading embedding; (4) injecting an unexpected property into a nested finding is correctly rejected by the embedded additionalProperties: false, proving the nested $id inside $defs does not silently defeat local $ref resolution or constraint enforcement; (5) every composed field (capability-result.findings, capability-result.completion.evidence, invocation.readings, ledger-entry.deferred) has its own distinct rejecting fixture naming the field it proves, and existing valid fixtures were updated (not weakened) to keep passing under the newly-enforced constraints -- notably fixtures/valid/ledger-entry.deferred-join.json was missing budget.ledger, a real pre-existing gap the previously-inert bare-object deferred field never caught; (6) NOTES.md and README.md accurately describe the closed state and the bundle/check workflow; (7) fields left open (capability-result.evidence, invocation.trusted_inputs, invocation.guides) genuinely have no corresponding part schema in schemas/, matching the stated rationale that they are free-form/polymorphic/consumer-owned rather than embedded Protocol documents; (8) both required Forgejo checks (Validate Protocol / validate, pull_request and push) report success on this exact SHA, and the PR head matches the pushed branch tip with no divergence. No material finding. One non-blocking maintainability note: tools/bundle.py's BUNDLES dict relies on insertion order (invocation before ledger-entry) for single-pass convergence when regenerating; --check independently recomputes each stem from current on-disk dependencies so it cannot pass on a stale result, but a future reordering could require running the generator twice before --check goes green. Worth a comment, not worth blocking on."}}
  • {'id': 'merge-composite-refs', 'kind': 'forgejo.merge.schedule', 'subject': 'homeostat/protocol#5', 'expected_revision': '516e96e098', 'parameters': {'completion_evidence': {'schema_version': '1.0', 'boundary': 'merge', 'head_sha': '516e96e098', 'findings': [{'id': 'review-composite-refs-verification', 'policy_effect': 'required', 'verdict': 'pass', 'subject_revision': '516e96e098', 'evidence': [{'kind': 'command', 'command': 'python3 tools/validate.py', 'result': 'validated 9 schemas, 27 accepting fixtures, and 41 rejecting fixtures'}, {'kind': 'command', 'command': 'python3 tools/bundle.py --check', 'result': 'exit 0, no stale bundles'}]}], 'review': {'head_sha': '516e96e098', 'author_provider': 'codex', 'reviewer_provider': 'claude', 'verdict': 'approved', 'review_id': 'review-composite-refs-516e96e'}}}}

Mutations

  • Applied forgejo.review.submit as effect review-composite-refs.
  • Applied forgejo.merge.schedule as effect merge-composite-refs.

Continuation

No continuation requested.

Completion: merge / reached

<!-- homeostat:invocation:issue-13:research:plan-composite-schema-assertions:code-composite-refs-and-fixtures:retry-composite-refs-and-fixtures:review-composite-refs --> ### Homeostat invocation `issue-13:research:plan-composite-schema-assertions:code-composite-refs-and-fixtures:retry-composite-refs-and-fixtures:review-composite-refs` Status: **complete** Capability: `review` Provider/model: `claude/default` #### Input to AI Independently review the exact pushed head and verify the bundled references, fixtures, and packaging checks. Subject: Review composite schema references and fixtures #### Output from AI Reviewed the exact pushed head of PR #5 (homeostat/protocol, `fix/composite-schema-refs` @ 516e96e0986c94f76168e1fbf0fb71c1fc77ab22) against issue #4's acceptance criteria. Approved. What the PR does: it wires the four composite fields that name an exact Protocol document type — capability-result `findings` and `completion.evidence`, invocation `readings`, and ledger-entry `deferred` — to their part schemas through local `$ref` fragments into embedded `$defs`, generated deterministically by the new `tools/bundle.py` and enforced non-stale by `tools/validate.py`. Fields that are genuinely open (capability-result `evidence`, invocation `trusted_inputs`/`guides`) are correctly left alone since no part schema exists for them. Independent verification performed (not just re-reading the diff): - `python3 tools/validate.py` passes clean on the exact head (9 schemas, 27 accepting fixtures, 41 rejecting fixtures). - `python3 tools/bundle.py --check` reports no stale bundles. - Copied only `schemas/ledger-entry.schema.json` into an empty directory and validated a real fixture against it in total isolation — 0 errors, proving the doubly-nested `ledger-entry -> invocation -> reading` embedding is genuinely self-contained with no cross-file resolution, which is the actual constraint (`transducer`/`governor` pass a single file path) that blocked this fix originally per NOTES.md. - Injected an unexpected property into a nested `finding` and confirmed jsonschema rejects it — the nested `$id` inside `$defs` does not defeat local `$ref` enforcement. - Each of the four wired fields has its own distinct rejecting fixture naming the field it proves; existing valid fixtures were updated to keep passing, and one of those updates (adding `budget.ledger` to `fixtures/valid/ledger-entry.deferred-join.json`) fixes a real pre-existing gap the old inert bare-object `deferred` field never caught. - Both required Forgejo checks succeed on this exact SHA, and the PR head matches the pushed branch tip. No material finding. One non-blocking maintainability note is recorded: `tools/bundle.py`'s `BUNDLES` dict relies on insertion order for single-pass convergence of the nested ledger-entry/invocation/reading embedding; `--check` is self-healing against this in CI, but it's worth a comment. Requesting `forgejo.review.submit` (approved) followed by `forgejo.merge.schedule`, both pinned to 516e96e0986c94f76168e1fbf0fb71c1fc77ab22. #### Evidence - {'kind': 'command', 'command': 'python3 tools/validate.py', 'result': 'validated 9 schemas, 27 accepting fixtures, and 41 rejecting fixtures', 'exit_code': 0} - {'kind': 'command', 'command': 'python3 tools/bundle.py --check', 'result': 'exit 0', 'exit_code': 0} - {'kind': 'test', 'description': 'isolated single-file validation: copied only schemas/ledger-entry.schema.json plus a valid fixture into an empty temp directory, validated with jsonschema.Draft202012Validator with no other files present', 'result': '0 errors, proving the ledger-entry -> invocation -> reading double-nested $defs embedding resolves with zero external file access'} - {'kind': 'test', 'description': "injected an unexpected property into fixtures/valid/capability-result.complete.json's findings[0] and re-validated against schemas/capability-result.schema.json", 'result': 'rejected: "Additional properties are not allowed (\'bogus_extra_field\' was unexpected)" at path [\'findings\', 0], proving nested additionalProperties:false is enforced through the local $ref despite the embedded $defs entry carrying its own $id'} - {'kind': 'api', 'endpoint': 'GET /repos/homeostat/protocol/commits/516e96e0986c94f76168e1fbf0fb71c1fc77ab22/status', 'result': 'state: success, 2/2 contexts success (Validate Protocol / validate, pull_request and push)'} - {'kind': 'api', 'endpoint': 'GET /repos/homeostat/protocol/pulls/5', 'result': 'head.sha 516e96e0986c94f76168e1fbf0fb71c1fc77ab22 matches origin/fix/composite-schema-refs tip; mergeable true; not yet merged'} - {'kind': 'api', 'endpoint': 'GET /repos/homeostat/protocol/issues/4', 'result': 'acceptance criteria text used to cross-check PR scope: wire composite fields via $ref, add per-field rejecting fixtures, keep representative valid documents passing, prove references resolve in the bundled/packaged form'} - {'kind': 'file_diff', 'description': 'git diff origin/main...origin/fix/composite-schema-refs reviewed in full: NOTES.md, README.md, tools/bundle.py (new), tools/validate.py, schemas/capability-result.schema.json, schemas/invocation.schema.json, schemas/ledger-entry.schema.json, and all fixture additions/changes'} #### Findings - BUNDLES dict order is a load-bearing implicit topological order (invocation must precede ledger-entry) with no comment or assertion protecting it. #### Requested effects - {'id': 'review-composite-refs', 'kind': 'forgejo.review.submit', 'subject': 'homeostat/protocol#5', 'expected_revision': '516e96e0986c94f76168e1fbf0fb71c1fc77ab22', 'parameters': {'verdict': 'approved', 'body': "Independently reviewed exact head 516e96e0986c94f76168e1fbf0fb71c1fc77ab22 against issue #4's acceptance criteria. Verified: (1) `python3 tools/validate.py` passes clean (9 schemas, 27 accepting fixtures, 41 rejecting fixtures); (2) `python3 tools/bundle.py --check` reports no stale bundles; (3) copying only `schemas/ledger-entry.schema.json` into an empty directory and validating a real fixture against it in isolation succeeds with zero errors and zero external file access, proving the consumer-facing single-file form (the actual constraint that blocked this fix per NOTES.md) is genuinely self-contained through the doubly-nested ledger-entry -> invocation -> reading embedding; (4) injecting an unexpected property into a nested `finding` is correctly rejected by the embedded `additionalProperties: false`, proving the nested `$id` inside `$defs` does not silently defeat local `$ref` resolution or constraint enforcement; (5) every composed field (capability-result.findings, capability-result.completion.evidence, invocation.readings, ledger-entry.deferred) has its own distinct rejecting fixture naming the field it proves, and existing valid fixtures were updated (not weakened) to keep passing under the newly-enforced constraints -- notably fixtures/valid/ledger-entry.deferred-join.json was missing budget.ledger, a real pre-existing gap the previously-inert bare-object `deferred` field never caught; (6) NOTES.md and README.md accurately describe the closed state and the bundle/check workflow; (7) fields left open (capability-result.evidence, invocation.trusted_inputs, invocation.guides) genuinely have no corresponding part schema in schemas/, matching the stated rationale that they are free-form/polymorphic/consumer-owned rather than embedded Protocol documents; (8) both required Forgejo checks (Validate Protocol / validate, pull_request and push) report success on this exact SHA, and the PR head matches the pushed branch tip with no divergence. No material finding. One non-blocking maintainability note: tools/bundle.py's BUNDLES dict relies on insertion order (invocation before ledger-entry) for single-pass convergence when regenerating; --check independently recomputes each stem from current on-disk dependencies so it cannot pass on a stale result, but a future reordering could require running the generator twice before --check goes green. Worth a comment, not worth blocking on."}} - {'id': 'merge-composite-refs', 'kind': 'forgejo.merge.schedule', 'subject': 'homeostat/protocol#5', 'expected_revision': '516e96e0986c94f76168e1fbf0fb71c1fc77ab22', 'parameters': {'completion_evidence': {'schema_version': '1.0', 'boundary': 'merge', 'head_sha': '516e96e0986c94f76168e1fbf0fb71c1fc77ab22', 'findings': [{'id': 'review-composite-refs-verification', 'policy_effect': 'required', 'verdict': 'pass', 'subject_revision': '516e96e0986c94f76168e1fbf0fb71c1fc77ab22', 'evidence': [{'kind': 'command', 'command': 'python3 tools/validate.py', 'result': 'validated 9 schemas, 27 accepting fixtures, and 41 rejecting fixtures'}, {'kind': 'command', 'command': 'python3 tools/bundle.py --check', 'result': 'exit 0, no stale bundles'}]}], 'review': {'head_sha': '516e96e0986c94f76168e1fbf0fb71c1fc77ab22', 'author_provider': 'codex', 'reviewer_provider': 'claude', 'verdict': 'approved', 'review_id': 'review-composite-refs-516e96e'}}}} #### Mutations - Applied forgejo.review.submit as effect review-composite-refs. - Applied forgejo.merge.schedule as effect merge-composite-refs. #### Continuation No continuation requested. Completion: `merge / reached`
korr left a comment
No description provided.
Independently reviewed the exact head 516e96e against homeostat/protocol#4 (parent homeostat/homeostat#13). All four composed fields named by the issue -- capability-result.findings, completion.evidence, invocation.readings, and ledger-entry.deferred -- now resolve through local $ref into self-contained $defs bundles generated deterministically by tools/bundle.py; tools/validate.py fails the run if a checked-in bundle drifts from its source (confirmed: `python3 tools/bundle.py --check` and `python3 tools/validate.py` both pass at this head). Each composed field has its own attributable rejecting fixture (malformed-composed-finding, malformed-completion-evidence, malformed-composed-reading, malformed-composed-invocation), and previously-empty valid fixtures were populated with conforming examples. ledger-entry.deferred-join.json needed a missing budget.ledger once `deferred` began asserting the full invocation shape -- a real regression the new composition caught, and it was fixed correctly. NOTES.md and README.md accurately describe what shipped, including why evidence/trusted_inputs/guides stay intentionally open (not embedded Protocol documents). Forgejo's own 'Validate Protocol' checks are green for both push and pull_request contexts on this exact head. No material findings. Approved.
korr left a comment
No description provided.
Verified python3 tools/bundle.py --check and python3 tools/validate.py both pass at this head (9 schemas, 27 accepting fixtures, 41 rejecting fixtures, all bundles current). Independently re-derived the malformed-composed-* fixture assertions with jsonschema directly and confirmed the three-level nested $ref/$id chain (ledger-entry -> invocation -> reading) actually enforces required fields via a hand-injected defect not covered by any single fixture. This closes the deferred $ref-composition item using the exact self-contained-bundle approach NOTES.md had already recommended, with no cross-repo boundary change. No material finding; one advisory suggestion (add a fixture for the full 3-level composition) that does not block merge.
korr scheduled this pull request to auto merge when all checks succeed 2026-07-29 02:56:47 +00:00
korr left a comment
No description provided.
Approving 516e96e (branch fix/composite-schema-refs, PR #5). Verified independently: 1. HEAD matches the reviewed artifact revision exactly (git rev-parse HEAD == origin/fix/composite-schema-refs == 516e96e...). Forgejo CI 'Validate Protocol / validate' is green for both pull_request and push events (runs 21 and 22). 2. `python3 tools/validate.py` passes locally (9 schemas, 27 accepting fixtures, 41 rejecting fixtures) and `python3 tools/bundle.py --check` reports no stale bundles. 3. Hand-audited the $ref composition: capability-result.findings and .completion.evidence, invocation.readings, and ledger-entry.deferred now resolve into self-contained $defs copied from finding/completion-evidence/reading/invocation.schema.json. Confirmed the two-level nesting (ledger-entry -> $defs.invocation -> $defs.reading) resolves correctly under Draft 2020-12 nested-$id scoping, and each of the four new rejecting fixtures (capability-result.malformed-composed-finding, capability-result.malformed-completion-evidence, invocation.malformed-composed-reading, ledger-entry.malformed-composed-invocation) fails at the exact composed-field pointer it claims. 4. Valid fixtures were populated with real, non-empty examples of each composed field, so the references are actually exercised rather than vacuously satisfied by empty arrays. 5. Confirmed this covers issue #4 one-to-one: one distinct rejecting fixture per composed field, representative valid documents still pass, and both the canonical part schemas and the bundled composite artifacts are exercised by the same validator run. 6. The wire-shape tightening (open `{type: object}` fields becoming closed, required-field schemas) reads like a major change under docs/versioning.md, but NOTES.md records a current, explicit owner decision (2026-07-26, amended 2026-07-28) that wire 1.0 stays free of a version bump/migration entry until a release is tagged and consumers actually move their pinned ref, so this is not a defect. One non-blocking note filed as an advisory finding: tools/bundle.py's recursive bundling only regenerates correctly in a single pass because of the current BUNDLES dict order; I reproduced a stale write by reordering it in a scratch copy, but bundle.py --check (run automatically by validate.py) still caught it and named the exact stale file, so nothing broken can silently merge. No material finding blocks this SHA.
korr left a comment
No description provided.
Independently reviewed exact head 516e96e0986c94f76168e1fbf0fb71c1fc77ab22 against issue #4's acceptance criteria. Verified: (1) `python3 tools/validate.py` passes clean (9 schemas, 27 accepting fixtures, 41 rejecting fixtures); (2) `python3 tools/bundle.py --check` reports no stale bundles; (3) copying only `schemas/ledger-entry.schema.json` into an empty directory and validating a real fixture against it in isolation succeeds with zero errors and zero external file access, proving the consumer-facing single-file form (the actual constraint that blocked this fix per NOTES.md) is genuinely self-contained through the doubly-nested ledger-entry -> invocation -> reading embedding; (4) injecting an unexpected property into a nested `finding` is correctly rejected by the embedded `additionalProperties: false`, proving the nested `$id` inside `$defs` does not silently defeat local `$ref` resolution or constraint enforcement; (5) every composed field (capability-result.findings, capability-result.completion.evidence, invocation.readings, ledger-entry.deferred) has its own distinct rejecting fixture naming the field it proves, and existing valid fixtures were updated (not weakened) to keep passing under the newly-enforced constraints -- notably fixtures/valid/ledger-entry.deferred-join.json was missing budget.ledger, a real pre-existing gap the previously-inert bare-object `deferred` field never caught; (6) NOTES.md and README.md accurately describe the closed state and the bundle/check workflow; (7) fields left open (capability-result.evidence, invocation.trusted_inputs, invocation.guides) genuinely have no corresponding part schema in schemas/, matching the stated rationale that they are free-form/polymorphic/consumer-owned rather than embedded Protocol documents; (8) both required Forgejo checks (Validate Protocol / validate, pull_request and push) report success on this exact SHA, and the PR head matches the pushed branch tip with no divergence. No material finding. One non-blocking maintainability note: tools/bundle.py's BUNDLES dict relies on insertion order (invocation before ledger-entry) for single-pass convergence when regenerating; --check independently recomputes each stem from current on-disk dependencies so it cannot pass on a stale result, but a future reordering could require running the generator twice before --check goes green. Worth a comment, not worth blocking on.
korr merged commit 3dd64b86a4 into main 2026-07-29 05:07:07 +00:00
korr deleted branch fix/composite-schema-refs 2026-07-29 05:07:07 +00:00
Sign in to join this conversation.
No description provided.