Record net-kingdom's Emission Cadence declaration and fix the stale digest (INFO-WP-0029)

net-kingdom published the first source-owned declaration (116643f). It passes
emission-review. Record it as feedback, and file its session-scoped-silence
incompatibility as demand/EmissionActivityScope.md. T02 is done, and T04 is in
progress until activity-core answers.

The adoption brief sent owners the 0.1.0 draft digest, because the candidate
promotion changed the standard's text after the digest was taken. The export
manifest also hard-coded status "draft". The manifest now derives status and
version from the standard, a test pins that, and the brief names the candidate
digest b08b4d95fc4b0bd3. The wire schema is unchanged.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 121421@bnt-lap001
Assistant-Session: 36f8657c-ebfa-4a2e-9ba0-bff06738f233
This commit is contained in:
tegwick 2026-09-22 16:14:10 +02:00
parent 146e461355
commit 038677ab53
7 changed files with 213 additions and 7 deletions

View file

@ -0,0 +1,47 @@
# Demand: Emission Cadence activity scope — silence while a source is not running
**Status:** proposed (change proposal to the Emission Cadence standard)
**Date:** 2026-09-21
**Source:** net-kingdom (source owner), domain `infotech`
**Owner:** InfoTechCanon Emission Cadence standard (`standards/emission-cadence`)
**Consumer evidence:** `net-kingdom/local-identity/emission-cadence-findings.md` (commit `116643f`)
**Feedback:** `feedback/2026-09-21-net-kingdom-emission-cadence-declaration.md`
**Workplan:** `INFO-WP-0029` (T04 records it; no design workplan exists yet)
---
## Demand signal
The first source-owned declaration came from a source that can emit only while
an attended process runs: `local-identity serve`, plus operator-invoked CLI
commands. For such a source, silence has two meanings. Silence while the
process runs may be a finding. Silence while the process is not running
carries no information. The contract cannot tell the two apart:
- `expected-rate` needs a floor. `expected_min: 0` is the only honest value,
and with it silence means nothing.
- `heartbeat-or-reconciliation` with a heartbeat assumes a process that can
emit `nothing-to-report`. Outside a session no such process exists.
The consumer fell back to reconciliation only. That preserves correctness but
leaves the observer unable to bound silence at all.
## Options named by the consumer
1. An **activity-scope** or session-bounded form. The source emits start/stop
(or open/close) markers, and the cadence expectation applies only inside the
bounded interval.
2. An explicit statement in the standard that session-scoped sources are out
of scope. Such sources would then declare reconciliation only, and observers
would not evaluate their silence.
## Constraints on a disposition
- A new form changes the wire schema (`0.1`). Under the `0.x` rules that is
allowed with migration guidance. Existing declarations stay valid only if the
form is additive.
- Declarations pinned before the change stay pinned to their digest. Stable
promotion needs declarations against one fixed reading of the contract, so
a schema change before stable resets which pin later evidence should use.
- This demand is not accepted. Choosing between the options, or rejecting both,
is a canon-owner decision.

View file

@ -27,7 +27,9 @@ and a declaration is never evidence that the emission actually happens.
observer's. observer's.
2. **The contract digest you implemented against**, so the declaration is pinned 2. **The contract digest you implemented against**, so the declaration is pinned
to a fixed reading of the contract rather than to whatever the canon says to a fixed reading of the contract rather than to whatever the canon says
later. Current digest: `972c0b6701d1693f` later. Current digest: `b08b4d95fc4b0bd3`
(candidate, document 0.2.0; `972c0b6701d1693f` was the 0.1.0 draft text and
the same wire schema)
(`info_tech_canon export-emission-contract <path.tar>` regenerates it). (`info_tech_canon export-emission-contract <path.tar>` regenerates it).
3. **Nothing else.** No deployment, no runtime proof, no conformance claim. A 3. **Nothing else.** No deployment, no runtime proof, no conformance claim. A
declaration is a statement of intended cadence. declaration is a statement of intended cadence.

View file

@ -0,0 +1,95 @@
---
id: feedback/2026-09-21-net-kingdom-emission-cadence-declaration
type: consumer-feedback
status: reviewed
date: "2026-09-21"
consumer: net-kingdom
consumer_domain: infotech
canon_version: "0.7.0"
artifacts:
- standard/emission-cadence
related_demand:
- demand/EmissionActivityScope.md
related_workplan:
- INFO-WP-0029
spawned_demand:
- demand/EmissionActivityScope.md
spawned_workplan: []
---
# Feedback: first source-owned Emission Cadence declaration (local-identity audit log)
**Consumer:** net-kingdom
**Canon version used:** 0.7.0; Emission Cadence document 0.2.0, wire schema 0.1
**Artifacts exercised:** `infospace/schemas/emission-cadence.schema.yaml`,
`standards/emission-cadence/InfoTechCanonEmissionCadenceStandard.md`
**Related demand:** `demand/EmissionActivityScope.md`
Source: net-kingdom's reply to INFO-WP-0029-T02 (State Hub message
`3b2db043-b910-4552-930f-65d87b475f3b`, thread `3432a831`), and the files it
published at net-kingdom commit `116643f`:
`local-identity/emission-cadence.yaml` and
`local-identity/emission-cadence-findings.md`. The consumer's own findings file
is the authoritative account. The sections below summarize it and do not
restate it.
---
## Consumer purpose
Declare the intended cadence of the local-identity audit log (`serve/token`
issuance, `revoke-token`) as load-bearing security evidence, so that an
observer could read silence in that stream.
## Hits
- `heartbeat-or-reconciliation` with a `reconciliation` block. This expressed
a local-count versus observed-count comparison without inventing a heartbeat
the source does not emit.
- `extensions`. These carried NetKingdom's evidence class, the
rate-monitoring prohibition, and `completeness_claimed: false` without
touching the generic contract.
- The schema was sufficient for a valid declaration. The consumer found it
`contract_valid` through its own profile tool.
## Friction
- `emission-review` could not be run by the consumer because
`infospace-bench==0.1.0` is not installable from a package index. This is the
packaging limitation SCOPE.md already records. It now costs an adopter a
validation step.
- `reconciliation` needs an observer that does not exist, so
`compare_observed` is a declared reference with no feed behind it.
## Gaps
- **Session-scoped silence.** The source can emit only while an attended process
runs. `expected-rate` has no meaningful floor (`expected_min: 0` makes
silence meaningless), and a heartbeat outside a session does not exist.
Neither form can say "silent because not running". Filed as
`demand/EmissionActivityScope.md`.
## Drop candidates
None.
## Steward notes
- **Validated canon-side on 2026-09-22.** `info_tech_canon emission-review` on
the declaration at `116643f` returned `ok: true`, `errors: []`,
`operational_truth_assessed: false`.
- **The pin was stale because of our brief, not because of the consumer.** The
consumer pinned `972c0b6701d1693f` and labelled it document 0.2.0, as
`docs/emission-cadence-adoption.md` instructed. That digest is the 0.1.0 draft
bundle. The candidate promotion (`4d0851c`) changed the standard's text after
the digest was taken, and the brief was not updated. The wire schema is
identical in both bundles, so the declaration's validity is unaffected. The
export manifest also hard-coded `status: draft`. It now reads status and
version from the standard. The brief names the corrected candidate digest,
`b08b4d95fc4b0bd3`.
- **What this counts toward.** This is one source-owned declaration from an owner
independent of this repository. It also records an incompatibility, which is
the third element of the stable gate (standard §10). It is not a second
declaration and not an observer result. The standard stays at candidate.
- The NetKingdom security profile's rare-heartbeat MUST failure belongs to
NetKingdom's profile. It is not a defect of the generic contract.

View file

@ -2,7 +2,7 @@
# Normative canon artifacts must not depend on this file. # Normative canon artifacts must not depend on this file.
directory: feedback directory: feedback
purpose: Consumer reports on whether InfoTechCanon concepts provide utility purpose: Consumer reports on whether InfoTechCanon concepts provide utility
updated: "2026-08-15" updated: "2026-09-22"
judgments: judgments:
- hits - hits
- friction - friction
@ -76,3 +76,25 @@ reports:
- ITC-WP-0014 - ITC-WP-0014
- ITC-WP-0015 - ITC-WP-0015
- ADHOC-2026-08-15 - ADHOC-2026-08-15
- id: feedback/2026-09-21-net-kingdom-emission-cadence-declaration
path: feedback/2026-09-21-net-kingdom-emission-cadence-declaration.md
date: "2026-09-21"
consumer: net-kingdom
consumer_domain: infotech
status: reviewed
canon_version: "0.7.0"
artifacts:
- standard/emission-cadence
hits:
- heartbeat-or-reconciliation (reconciliation)
- extensions
friction:
- emission-review not runnable by adopter (infospace-bench not installable)
- reconciliation with no existing observer feed
gaps:
- session-scoped silence (activity scope)
drop_candidates: []
related_demand:
- demand/EmissionActivityScope.md
related_workplan:
- INFO-WP-0029

View file

@ -72,10 +72,17 @@ def export_emission_bundle(root: Path, destination: Path) -> dict:
"standards/emission-cadence/InfoTechCanonEmissionCadenceStandard.md", "standards/emission-cadence/InfoTechCanonEmissionCadenceStandard.md",
"standards/emission-cadence/examples/qonto-assistant.yaml"] "standards/emission-cadence/examples/qonto-assistant.yaml"]
files = {path: (root / path).read_bytes() for path in paths} files = {path: (root / path).read_bytes() for path in paths}
manifest = {"contract": "emission-cadence/0.1", "status": "draft", # Status and version come from the standard itself, so a promotion cannot
# leave the manifest describing an earlier maturity.
standard = files[paths[1]].decode()
header = re.match(r"---\n(.*?)\n---", standard, re.S)
fields = dict(re.findall(r"^(status|version):\s*(\S+)", header.group(1) if header else "", re.M))
manifest = {"contract": "emission-cadence/0.1", "status": fields.get("status"),
"document_version": fields.get("version"),
"files": {name: hashlib.sha256(data).hexdigest() for name, data in files.items()}, "files": {name: hashlib.sha256(data).hexdigest() for name, data in files.items()},
"semantic_checks": ["unique source_id in sources"], "semantic_checks": ["unique source_id in sources"],
"adoption_evidence": "Two independent source-owned implementations required; example does not count."} "adoption_evidence": ("Stable requires two source-owned declarations from independent owners "
"and one observer result from a third party; example does not count.")}
files["manifest.json"] = (json.dumps(manifest, sort_keys=True, indent=2) + "\n").encode() files["manifest.json"] = (json.dumps(manifest, sort_keys=True, indent=2) + "\n").encode()
output = io.BytesIO() output = io.BytesIO()
with tarfile.open(fileobj=output, mode="w", format=tarfile.USTAR_FORMAT) as archive: with tarfile.open(fileobj=output, mode="w", format=tarfile.USTAR_FORMAT) as archive:

View file

@ -4,6 +4,7 @@ import json
from pathlib import Path from pathlib import Path
import shutil import shutil
import tarfile import tarfile
import tempfile
import pytest import pytest
import yaml import yaml
@ -92,6 +93,15 @@ def test_bundle_is_reproducible_and_refuses_corruption(tmp_path):
export_emission_bundle(DEFAULT_INFOSPACE_ROOT, tmp_path) export_emission_bundle(DEFAULT_INFOSPACE_ROOT, tmp_path)
def test_bundle_manifest_reports_the_standards_own_status():
standard = (DEFAULT_INFOSPACE_ROOT / "standards/emission-cadence/"
"InfoTechCanonEmissionCadenceStandard.md").read_text()
manifest = export_emission_bundle(DEFAULT_INFOSPACE_ROOT, Path(tempfile.mkdtemp()))["manifest"]
assert f"status: {manifest['status']}\n" in standard
assert f"version: {manifest['document_version']}\n" in standard
assert "observer" in manifest["adoption_evidence"]
def test_mapping_schema_and_explicit_ownership_are_enforced(corpus): def test_mapping_schema_and_explicit_ownership_are_enforced(corpus):
from info_tech_canon.contracts import bound_artifact_errors from info_tech_canon.contracts import bound_artifact_errors
mapping = corpus / "mappings/capability-anchors.yaml" mapping = corpus / "mappings/capability-anchors.yaml"

View file

@ -8,7 +8,7 @@ status: active
owner: claude owner: claude
topic_slug: canon-optimization topic_slug: canon-optimization
created: "2026-09-21" created: "2026-09-21"
updated: "2026-09-21" updated: "2026-09-22"
flavor: coordination flavor: coordination
state_hub_workstream_id: "d743e220-9d2d-52d8-8df3-880805269639" state_hub_workstream_id: "d743e220-9d2d-52d8-8df3-880805269639"
--- ---
@ -48,7 +48,7 @@ what is being asked cannot drift between recipients.
```task ```task
id: INFO-WP-0029-T02 id: INFO-WP-0029-T02
status: progress status: done
priority: high priority: high
state_hub_task_id: "845c27d1-5b66-5317-8abb-0a62eb0d9638" state_hub_task_id: "845c27d1-5b66-5317-8abb-0a62eb0d9638"
``` ```
@ -62,6 +62,9 @@ Ask for one source-owned declaration for an event class it already emits.
Waiting for a reply is expected; this task tracks the ask, not the answer. Waiting for a reply is expected; this task tracks the ask, not the answer.
Sent 2026-09-21 as State Hub message `3432a831-b25f-4717-ad8b-cb19fb1b6633`. Sent 2026-09-21 as State Hub message `3432a831-b25f-4717-ad8b-cb19fb1b6633`.
Answered the same day (`3b2db043`): a declaration was published at net-kingdom
`116643f`, `local-identity/emission-cadence.yaml`, together with an
incompatibility finding. It is recorded under T04.
## Ask a second, independent source ## Ask a second, independent source
@ -100,7 +103,7 @@ of section 10 and defeat its purpose.
```task ```task
id: INFO-WP-0029-T04 id: INFO-WP-0029-T04
status: wait status: progress
priority: medium priority: medium
state_hub_task_id: "4771ff59-264e-5917-a49d-8989b361b8ed" state_hub_task_id: "4771ff59-264e-5917-a49d-8989b361b8ed"
``` ```
@ -111,6 +114,26 @@ declaration cannot be expressed in either form, that is the finding, and it goes
to the standard as a change proposal rather than being worked around in the to the standard as a change proposal rather than being worked around in the
declaration. declaration.
### Recorded so far — 2026-09-22
net-kingdom's declaration passes `emission-review` (`ok: true`). It is recorded
as `feedback/2026-09-21-net-kingdom-emission-cadence-declaration.md`. Its
incompatibility is that a session-scoped source cannot make its silence
meaningful in either form. That finding goes to the standard as
`demand/EmissionActivityScope.md` and was not worked around in the
declaration.
Checking the pin exposed a canon-side defect. The brief quoted digest
`972c0b6701d1693f`, which is the 0.1.0 draft bundle, because the candidate
promotion changed the standard's text after the digest was taken. The export
manifest also hard-coded `status: draft`. The manifest now reads status and
version from the standard. A test pins that behaviour, and the brief names the
candidate digest `b08b4d95fc4b0bd3`. The wire schema did not change, so the
declaration stays valid.
This task stays in progress until activity-core's declaration (T03) arrives or
the ask is withdrawn.
## Observer result ## Observer result
```task ```task