Skip to content

docs(spec): admit incremental mediation as a §12.1 exception - #64

Merged
MohammadHaroonAbuomar merged 2 commits into
mainfrom
mhabuomar/streaming-conformance-reconciliation
Aug 7, 2026
Merged

docs(spec): admit incremental mediation as a §12.1 exception#64
MohammadHaroonAbuomar merged 2 commits into
mainfrom
mhabuomar/streaming-conformance-reconciliation

Conversation

@MohammadHaroonAbuomar

@MohammadHaroonAbuomar MohammadHaroonAbuomar commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Summary

The streaming comparison study (agent-control-spec analysis/streaming-acs-vs-maf.md, R6) audited incremental stream mediation against the enforcement lessons of the MAF agent-hooks integration — verdict-before-durability, observer channels on the wrong side of the gate, retry attempts escaping a single covering verdict, abandoned streams leaving no audit outcome — and found a conformance tension on our side: §12.1 mandates assemble-before-post_model_call with no exception, while §12.1a already reserves buffered_output: false for hosts that stream to their caller. A host mediating incrementally under a sound accounting discipline such as ACS §18.1 (already in our CLAIMS table) therefore read as §12.1-non-conformant and could not make a coherent claim. These changes encode enforcement lessons from the agent-hooks integration review in microsoft/agent-framework#7515, and the wording was validated against the merged MAF implementation as the reference buffered_output: true host.

What this prevents

Without the exception, the only conformant postures were full buffering or a blanket stream_incomplete deny — so a latency-sensitive host either abandoned the claim or claimed while quietly violating §12.1, hiding exactly the exposures the study catalogued. The exception makes the incremental posture claimable only under a bounded-exposure accounting discipline: verdict-covered release within a declared exposure bound, a deny that terminates the stream and withholds the unreleased remainder (content an earlier emission permitted included), fail-closed residue at end of stream with host_error:streaming_unsupported, and §6.1-gated durability that also covers withheld-but-permitted content. The §12.1a declaration and §13.3 claim must state the exposure bound, so the claim says what can egress ahead of its verdict instead of leaving it implied.

The MAF cross-validation added four hardenings: §12.1 distinguishes an errored model call (handled per §6.1 — no post_model_call, zero egress/durability) from the stream_incomplete shape, which is for hosts that cannot buffer; exception item 4 extends durability gating to content an earlier emission permitted but the host never released; §12.1a pins released-content identity on the buffered path (released content is the verdicted, post-transform content — no rewriting between verdict and release); and §12.1a defines the caller as any consumer outside the enforcement boundary, observers, callbacks, and preview channels included, matching the clause ACS PR responsibleai/agent-control-spec#30 adds to §18.1.

Scope

Deliberately minimal and capability-shaped (not the full R7 CTK surface): buffered_output remains declaration-only, each incremental emission stays an ordinary post_model_call under §4–§7, and conformance vectors exercising the accounting discipline against a mocked stream are noted as future work. CLAIMS.md, HARNESS.md, THREAT-MODEL.md (TM-11), PRODUCTION.md, and the CHANGELOG are updated to match. Additive; no version bump.

Test plan

  • scripts/check-version-consistency.py — version surfaces agree (0.1.0-alpha.4).
  • No schema, vector, SDK, or workflow changes; the schema-lint and SDK CI jobs are unaffected by this diff.

Section 12.1 mandated assemble-before-post_model_call with no
exception, while ACS section 18.1 (a host contract this spec already
names in its conformance claims table) mediates streams incrementally.
A host adopting that profile therefore read as non-conformant at 12.1
even though 12.1a already reserves the buffered_output: false
capability for exactly this posture. The streaming comparison study
(agent-control-spec analysis/streaming-acs-vs-maf.md, R6) flagged the
tension.

12.1 now carries an exception: a host declaring buffered_output:
false MAY evaluate the stream incrementally, emitting post_model_call
per evaluated segment, provided it satisfies a bounded-exposure
accounting discipline - verdict-covered release within a declared
exposure bound, a deny that terminates the stream and withholds the
unreleased remainder, fail-closed residue at end of stream with
host_error:streaming_unsupported, and durability gated per 6.1. ACS
18.1 is referenced as one implementation of the discipline.

The capability stays declaration-only and the exception is
capability-shaped: 12.1a and 13.3 now require the declaration and
claim to state the exposure bound, and conformance vectors exercising
the accounting discipline against a mocked stream are left as future
work. CLAIMS/HARNESS/THREAT-MODEL/PRODUCTION updated to match.
Additive; no version bump.

Signed-off-by: MohammadHaroonAbuomar <40180927+MohammadHaroonAbuomar@users.noreply.github.com>
@MohammadHaroonAbuomar MohammadHaroonAbuomar added the spec:additive Additive normative change (optional fields, new vectors) label Aug 7, 2026
@MohammadHaroonAbuomar MohammadHaroonAbuomar added the spec:additive Additive normative change (optional fields, new vectors) label Aug 7, 2026
Four adjustments from validating the wording against the merged MAF
implementation as the reference buffered_output: true host:

- 12.1 distinguishes an errored model call from the stream_incomplete
  shape. Assembly that fails because the call itself errored is an
  errored action handled per 6.1 - nothing partial egresses or
  persists, and post_model_call is not the vehicle for reporting the
  provider's failure. stream_incomplete is for hosts that cannot
  buffer.
- Exception item 4 covers withheld-but-permitted content: durability
  gating extends to content an earlier emission permitted but the
  host had not yet released at termination, not only denied or
  unevaluated content.
- 12.1a pins released-content identity on the buffered path: the
  content released once the verdict permits is the verdicted
  (post-transform) content; a host must not rewrite content between
  the verdict and its release.
- 12.1a defines the caller as any consumer outside the host's
  enforcement boundary, observers, callbacks, and preview channels
  included, matching the ACS 18.1 clause so the observer-channel
  protection no longer rests on an undefined term.

Signed-off-by: MohammadHaroonAbuomar <40180927+MohammadHaroonAbuomar@users.noreply.github.com>
@MohammadHaroonAbuomar
MohammadHaroonAbuomar merged commit 4f13545 into main Aug 7, 2026
29 checks passed
MohammadHaroonAbuomar added a commit that referenced this pull request Aug 7, 2026
All four SDK manifests, their lockfiles and the committed npm platform
package dirs move to 0.1.0-alpha.5 (scripts/check-version-consistency
passes). The CHANGELOG folds the Unreleased §12.1 spec items (#64)
into the alpha.5 section alongside Python Verdict.allow() and the new
linux-arm64-gnu napi target.

Signed-off-by: MohammadHaroonAbuomar <40180927+MohammadHaroonAbuomar@users.noreply.github.com>
MohammadHaroonAbuomar added a commit that referenced this pull request Aug 7, 2026
…tion

Deliver the vectors PR #64 left as future work, making the
buffered_output: false posture CTK-testable (streaming comparison
study, agent-control-spec analysis/streaming-acs-vs-maf.md, R7).

New streaming/incremental vector part, one vector per exception
condition:

- AH-CTK-110: a fully permitted stream is released segment by
  segment under covering verdicts (item 1).
- AH-CTK-111: a terminating deny withholds the unreleased remainder,
  the harmless undelivered tail included, while the released prefix
  stays released (items 1-2).
- AH-CTK-112: residue no emission evaluated fails closed at end of
  stream with host_error:streaming_unsupported (item 3), via the new
  stream_truncated scenario form.
- AH-CTK-113: durable incorporation is gated by the same discipline
  as release; withheld and unevaluated content never becomes durable
  (item 4, section 6.1).

The vector grammar grows respond.stream / respond.stream_truncated
(chunked mock stream; chunk boundaries pin the evaluated segments)
and expect.released_output / expect.persisted_must_not_contain (the
egress and durability observables). The part is gated on the new
incremental_output capability: buffering hosts (buffered_output:
true, the default) do not declare it and skip, so the vectors are
additive and no existing declared surface changes. Reference-harness
skip manifests in all five SDKs pin the new skips; the Python
Capability enum and vendored vector copies are updated.

Spec section 12.1's future-work note now points at the part; section
13.1/13.3, CLAIMS.md, HARNESS.md (incremental drive conventions and
coverage boundaries), PRODUCTION.md row 8, and THREAT-MODEL.md TM-11
are updated to match. Spec version unchanged (agent-hooks/0.1,
0.1.0-alpha).

Verified: ajv vector validation green; Rust CTK reference self-test
green with the pinned skip set; agent-control-spec's conformance
suite run against this corpus reports 46 passed, 0 failed, 5 skipped
of 51 (the four new skips are the capability gate working).

Signed-off-by: MohammadHaroonAbuomar <40180927+MohammadHaroonAbuomar@users.noreply.github.com>
MohammadHaroonAbuomar added a commit that referenced this pull request Aug 7, 2026
…tion

Deliver the vectors PR #64 left as future work, making the
buffered_output: false posture CTK-testable (streaming comparison
study, agent-control-spec analysis/streaming-acs-vs-maf.md, R7).

New streaming/incremental vector part, one vector per exception
condition:

- AH-CTK-110: a fully permitted stream is released segment by
  segment under covering verdicts (item 1).
- AH-CTK-111: a terminating deny withholds the unreleased remainder,
  the harmless undelivered tail included, while the released prefix
  stays released (items 1-2).
- AH-CTK-112: residue no emission evaluated fails closed at end of
  stream with host_error:streaming_unsupported (item 3), via the new
  stream_truncated scenario form.
- AH-CTK-113: durable incorporation is gated by the same discipline
  as release; withheld and unevaluated content never becomes durable
  (item 4, section 6.1).

The vector grammar grows respond.stream / respond.stream_truncated
(chunked mock stream; chunk boundaries pin the evaluated segments)
and expect.released_output / expect.persisted_must_not_contain (the
egress and durability observables). The part is gated on the new
incremental_output capability: buffering hosts (buffered_output:
true, the default) do not declare it and skip, so the vectors are
additive and no existing declared surface changes. Reference-harness
skip manifests in all five SDKs pin the new skips; the Python
Capability enum and vendored vector copies are updated.

Spec section 12.1's future-work note now points at the part; section
13.1/13.3, CLAIMS.md, HARNESS.md (incremental drive conventions and
coverage boundaries), PRODUCTION.md row 8, and THREAT-MODEL.md TM-11
are updated to match. Spec version unchanged (agent-hooks/0.1,
0.1.0-alpha).

Verified: ajv vector validation green; Rust CTK reference self-test
green with the pinned skip set; agent-control-spec's conformance
suite run against this corpus reports 46 passed, 0 failed, 5 skipped
of 51 (the four new skips are the capability gate working).

Signed-off-by: MohammadHaroonAbuomar <40180927+MohammadHaroonAbuomar@users.noreply.github.com>
MohammadHaroonAbuomar added a commit that referenced this pull request Aug 7, 2026
…tion

Deliver the vectors PR #64 left as future work, making the
buffered_output: false posture CTK-testable (streaming comparison
study, agent-control-spec analysis/streaming-acs-vs-maf.md, R7).

New streaming/incremental vector part, one vector per exception
condition:

- AH-CTK-110: a fully permitted stream is released segment by
  segment under covering verdicts (item 1).
- AH-CTK-111: a terminating deny withholds the unreleased remainder,
  the harmless undelivered tail included, while the released prefix
  stays released (items 1-2).
- AH-CTK-112: residue no emission evaluated fails closed at end of
  stream with host_error:streaming_unsupported (item 3), via the new
  stream_truncated scenario form.
- AH-CTK-113: durable incorporation is gated by the same discipline
  as release; withheld and unevaluated content never becomes durable
  (item 4, section 6.1).

The vector grammar grows respond.stream / respond.stream_truncated
(chunked mock stream; chunk boundaries pin the evaluated segments)
and expect.released_output / expect.persisted_must_not_contain (the
egress and durability observables). The part is gated on the new
incremental_output capability: buffering hosts (buffered_output:
true, the default) do not declare it and skip, so the vectors are
additive and no existing declared surface changes. Reference-harness
skip manifests in all five SDKs pin the new skips; the Python
Capability enum and vendored vector copies are updated.

Spec section 12.1's future-work note now points at the part; section
13.1/13.3, CLAIMS.md, HARNESS.md (incremental drive conventions and
coverage boundaries), PRODUCTION.md row 8, and THREAT-MODEL.md TM-11
are updated to match. Spec version unchanged (agent-hooks/0.1,
0.1.0-alpha).

Verified: ajv vector validation green; Rust CTK reference self-test
green with the pinned skip set; agent-control-spec's conformance
suite run against this corpus reports 46 passed, 0 failed, 5 skipped
of 51 (the four new skips are the capability gate working).

Signed-off-by: MohammadHaroonAbuomar <40180927+MohammadHaroonAbuomar@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

spec:additive Additive normative change (optional fields, new vectors)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant