kings-guard/workplans/KG-WP-0003-evidence-completeness-and-live-observation.md
tegwick 9daea96c43 Finish KG-WP-0003: stream completeness and live qonto observation
Classify evidence as load-bearing or attributive, draft the emission-cadence
declaration for Taxonomy, treat silence as a stream finding, keep completeness
separate from record richness, forbid immune memory as a state plane, and make
containment proposals reconstructable to their origin. Observe real
qonto-assistant audit events; deny-class completeness stays unknown until the
source publishes a heartbeat.

Assistant: grok
Assistant-Session: 01a05ef1-9e5a-70f2-b0ff-0b05d6b38ae9
2026-09-02 00:11:57 +02:00

13 KiB
Raw Permalink Blame History

id type title domain repo status owner topic_slug created updated source_review standard state_hub_workstream_id
KG-WP-0003 workplan Evidence completeness and live observation infotech kings-guard finished kings-guard netkingdom 2026-08-29 2026-09-01 history/2026-08-29-layer-model-v0.7-scope-intent-review.md net-kingdom/canon/standards/security-layer-model_v0.7.md a6c1c760-1386-58fa-9392-d9c3c4dadc41

Evidence completeness and live observation

Close the gap between what INTENT.md and SCOPE.md now claim under Security Layer Model v0.7 and what src/kings_guard/ actually does. Carries G1G8 of history/2026-08-29-layer-model-v0.7-scope-intent-review.md.

Two things are being fixed. The repository consumes evidence and treats a quiet stream as a healthy one, which the statute now forbids (§9.6). And statute §12's fourth step — kings-guard observes it in operation — is unstaffed, because every input is a fixture.

Boundaries this workplan does not cross

  • No actuation. kings-guard proposes containment and never performs it (§9.2). T06 makes proposals reconstructable; it does not make them act.
  • No Tooling contact. dependencies = [] stays empty; make check-layer must stay green on every task. qonto-assistant publishes its own stream and is not a Tooling row, so T07 needs no engine in the path.
  • No engine gap worked around. Identity and secret observation stay at zero.

Dependency order

T01 evidence classification
  -> T02 emission-cadence declaration (draft, handed to Taxonomy)
    -> T03 stream-completeness evaluation
      -> T04 completeness in the posture output
T05 immune memory is not a state plane   (independent)
T06 proposals carry their origin          (independent)
T07 live observation                      (independent; makes the rest real)
T08 agent-principal conformance checks    (after T05)

Task: Classify consumed evidence load-bearing or attributive

id: KG-WP-0003-T01
status: done
priority: high
state_hub_task_id: "dd660dbf-9148-5f35-aa4a-74deb10e6f8a"

Statute §9.6 attaches different obligations to each class, and the repository currently records neither. ImmuneObservation carries source_system and no class; SecurityGenome declares no sources at all.

Done when:

  • the evidence class is expressible on a declared source and on an observation;
  • specs/ImmuneContracts.md states the obligation difference — a load-bearing source MUST declare a cadence, an attributive source SHOULD — and states that the class is the source's declaration, not kings-guard's inference;
  • the qonto-assistant fixture declares a class for its audit stream, with the reasoning recorded;
  • tests cover both classes.

Done 2026-09-01: DeclaredEvidenceSource on the genome and evidence_class on ImmuneObservation. The adapter copies the source declaration and refuses to infer class from event contents. qonto audit.deny / audit.heartbeat are load-bearing; audit.allow is attributive, with reasoning in the fixture. tests/test_evidence_class.py covers both classes.

Task: Draft the emission-cadence declaration and hand it to Taxonomy

id: KG-WP-0003-T02
status: done
priority: high
state_hub_task_id: "5b66aec0-a753-5039-bcbe-bc69cf1ad13e"

Statute §17 requires the artifact and records kings-guard as its drafter, being its only consumer. Ownership stays with Taxonomy. Inventing a local shape is the drift §17 exists to prevent, so this is a draft for handover, not an internal schema.

Must cover both forms, because one does not substitute for the other:

  • an expected rate for volume classes;
  • reconciliation or a heartbeat for low-volume load-bearing classes — revocations, denials, containment actions — where rate monitoring cannot work because a suppressed month is indistinguishable from a quiet one. The required property is a positive claim that can itself go missing.

Done when:

  • the draft lives in specs/ and is written against qonto-assistant as the one real source;
  • it explains where the declaration belongs — alongside the security genome, on the argument that expected cadence is a claim of intent like the rest of the genome — and why;
  • GH-WP-0002-T04 is referenced as the reference instance for the heartbeat form;
  • it is sent to gate-house and to the Taxonomy repositories for ownership, and the handover is recorded.

Done 2026-09-01: Draft at specs/EmissionCadenceDeclaration.md, worked example against qonto-assistant, both forms specified, genome-adjacent rationale stated, GH-WP-0002-T04 / approval-engine/cadence.yaml cited as the heartbeat reference. Runtime consumer is src/kings_guard/fixtures/qonto_assistant_cadence.json (draft-shaped, not a fork). Handover messages sent to gate-house, net-kingdom, and info-tech-canon.

Task: Evaluate the stream, not only the observation

id: KG-WP-0003-T03
status: done
priority: high
state_hub_task_id: "2cd878c0-8b70-5f2b-9f82-c4d74df5833c"

PostureEvaluator.evaluate() is stateless and per-observation. An event that is never emitted is never evaluated, so the last posture stands and suppression biases posture optimistic. Silence must become a finding in its own right.

Done when:

  • a stream-level evaluation path exists alongside the per-observation one;
  • an unmet declared cadence produces a finding;
  • a missing heartbeat, or a reconciliation divergence between the source's own state transitions and the evidence count per class, produces a finding;
  • the findings are distinguishable from content findings — the stream observed, not its contents;
  • no Tooling contact is introduced; the source publishes its own stream.

Done 2026-09-01: PostureEvaluator.evaluate_stream / evaluate_with_stream compare a declared cadence to arrived events. Unmet rate, missing heartbeat, and reconciliation divergence emit stream:* findings, distinct from content findings, and a stream_completeness signal. No Tooling client. Tests in tests/test_stream.py.

Task: Carry stream completeness in the posture output

id: KG-WP-0003-T04
status: done
priority: high
state_hub_task_id: "73367acf-d888-5acc-ae85-7231a9cbe9fe"

confidence_score starts at 70 and rises with field richness of the record received. It measures the record, never the stream: a well-formed observation from a 90%-suppressed stream scores 85. The judgment must be able to say this rests on a stream I cannot vouch for.

Done when:

  • completeness is separated from richness in PostureAssessment;
  • an unmet cadence or missing heartbeat degrades the completeness dimension;
  • the rationale text says so in words, not only in a number;
  • a posture derived from an incomplete stream can never read as more trustworthy than one derived from a complete one.

Done 2026-09-01: PostureAssessment carries stream_completeness and completeness_reason separately from confidence_score. Rationale states completeness in words. assessment_trust_key orders completeness above richness, so a 95-from-degraded stream cannot outrank a 70-from-complete one. tests/test_completeness.py.

Task: State and test that immune memory is not a state plane

id: KG-WP-0003-T05
status: done
priority: medium
state_hub_task_id: "d7ed9faf-58ee-59a1-ad1e-b2fcf817317f"

Statute §3.4 rule 3: agent memory, tool-call traces and prompt caches MUST NOT become state another layer depends on at runtime unless catalogued as Tooling. ImmuneMemoryEntry has no such rule, and INTENT.md stage 5 (federated memory) is exactly the shape that could drift into one.

Done when:

  • specs/ImmuneContracts.md states it: immune memory informs kings-guard's own judgment and may be published as evidence; no engine, PEP or workload may read it as a runtime input, and making it one is a §4 Tooling catalog change;
  • a test asserts the constraint rather than leaving it to prose;
  • the constraint is reflected in the Direction of Evolution stage-5 entry.

Done 2026-09-01: ImmuneMemoryEntry.runtime_input_for_other_layers is forbidden. specs/ImmuneContracts.md states the rule. tests/test_immune_memory.py asserts the evaluator does not take memory as input and that INTENT stage 5 keeps the constraint.

Task: Make containment proposals reconstructable to their origin

id: KG-WP-0003-T06
status: done
priority: medium
state_hub_task_id: "98326ed2-ee5f-58ce-9f99-429e621117a6"

§9.2 rules that a containment action is a decision record, not a side channel. EffectorRequest names a target and an action and carries no reference to what produced it, so once a proposal leaves this repository it cannot be tied back to the observation that caused it.

Done when:

  • an effector request carries the originating observation and signal identity;
  • the eventual decision record can name what the proposal was rendered for;
  • docs/AdjacentSystemBoundary.md states the expectation on the receiving side;
  • the authority boundary remains explicit and no value widens authority.

Done 2026-09-01: EffectorRequest carries originating observation and signal ids, stream completeness, and a restrictive direction. Authority boundaries in use remain advisory_only and metadata_only. Applied gate-house/docs/contracts/posture-findings-return.md through this task. docs/AdjacentSystemBoundary.md rule 7 states the receiving-side expectation. tests/test_effector_origin.py.

Task: Observe qonto-assistant in operation

id: KG-WP-0003-T07
status: done
priority: high
state_hub_task_id: "ae516be8-5199-5f81-b47f-7843b5993f97"

Statute §12's fourth step is aspiration until this is done, and §19's verdict names kings-guard as the watching half of can propose and decide but cannot watch or act. Every input today is a hand-built fixture; ten tests pass and none has met a real event.

Nothing blocks it. qonto-assistant publishes its own genome record and audit stream, needs no engine in the path, and its genome has not drifted since it was written.

Done when:

  • real emitted audit events from qonto-assistant reach the evaluator;
  • the observation mapping is confirmed against real events or corrected, and the correction is reported back to qonto-assistant;
  • output stays advisory — posture hints and metadata-only evidence, nothing that actuates;
  • the fixture is retained as a regression case rather than deleted;
  • gate-house is told that step four is staffed, with what was found.

Done 2026-09-01: Real events from qonto-assistant.audit.AuditLogger via CapabilityService (allow + deny) reach the evaluator. Mapping confirmed: request_id, capabilityresource_scope, decision, protocol hold. Corrections reported to qonto-assistant: AuditEvent still omits identity_binding and egress_destination; no heartbeat is published yet, so deny-class completeness is unknown. Fixture retained. Output stays advisory. gate-house notified that §12 step four is staffed for this lane. tests/test_live_qonto_observation.py; python3 -m kings_guard.main --pilot qonto-assistant --live.

Task: Check the agent-principal rules that can be checked

id: KG-WP-0003-T08
status: done
priority: medium
state_hub_task_id: "e7003fb3-2e7c-5440-b489-b619b3f0c65d"

All four §3.4 rules are now claimed in INTENT.md and none is verified. The no-Tooling-client claim showed the pattern: a claim in prose becomes a claim in a test, and the test carries the reason.

Done when:

  • scripts/check_layer_conformance.py covers what is mechanically checkable — at minimum rule 1, no standing credential held in the repository or its configuration;
  • rule 3 is covered by T05;
  • rules that remain assertion rather than test are recorded as such in layer.yaml, honestly, rather than implied to be checked;
  • make check-layer stays green.

Done 2026-09-01: scripts/check_layer_conformance.py scans for standing credential files and secret literals (rule 1). Rule 3 is tests/test_immune_memory.py. layer.yaml agent_principal_rule_checks records rule 2 as assertion and rule 4 as mixed. make check-layer green; pyproject.toml dependencies = [].

Success criteria

  1. Every task above is done.
  2. make test and make check-layer both pass.
  3. pyproject.toml still declares dependencies = [].
  4. INTENT.md and SCOPE.md claim nothing the implementation does not do.
  5. The emission-cadence draft has been handed to Taxonomy and the handover recorded.
  6. gate-house has been told that §12's fourth step is staffed.

Residuals

No leftover kings-guard work is parked only in prose. Source-side follow-ups were sent as coordination messages, not new workplans here:

  • qonto-assistant — emit identity_binding and egress_destination on AuditEvent if they become known; publish the cadence declaration and a deny-class heartbeat. Until then deny-class completeness stays unknown.
  • Taxonomy (net-kingdom, info-tech-canon) — take ownership of specs/EmissionCadenceDeclaration.md. kings-guard will consume what they publish and will not fork it.
  • secrets-engine secret-use evidence contract — assented as a proposed Lifecycle surface; observation stays at zero until it ships. Not a WP-0003 residual.

Pre-existing open intake KG-IN-0002 (architecture vocabulary sweep) is unrelated and remains open.