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
324 lines
13 KiB
Markdown
324 lines
13 KiB
Markdown
---
|
||
id: KG-WP-0003
|
||
type: workplan
|
||
title: "Evidence completeness and live observation"
|
||
domain: infotech
|
||
repo: kings-guard
|
||
status: finished
|
||
owner: kings-guard
|
||
topic_slug: netkingdom
|
||
created: "2026-08-29"
|
||
updated: "2026-09-01"
|
||
source_review: history/2026-08-29-layer-model-v0.7-scope-intent-review.md
|
||
standard: net-kingdom/canon/standards/security-layer-model_v0.7.md
|
||
state_hub_workstream_id: "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 G1–G8 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
|
||
|
||
```text
|
||
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
|
||
|
||
```task
|
||
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
|
||
|
||
```task
|
||
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
|
||
|
||
```task
|
||
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
|
||
|
||
```task
|
||
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
|
||
|
||
```task
|
||
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
|
||
|
||
```task
|
||
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
|
||
|
||
```task
|
||
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`, `capability`→`resource_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
|
||
|
||
```task
|
||
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.
|