Skip to content

Fix attestation credential delivery and test coverage (#4411) - #4420

Merged
Trecek merged 10 commits into
developfrom
bounded-open-kitchen-never-delivers-the-attestation-values-r/4411
Jul 30, 2026
Merged

Fix attestation credential delivery and test coverage (#4411)#4420
Trecek merged 10 commits into
developfrom
bounded-open-kitchen-never-delivers-the-attestation-values-r/4411

Conversation

@Trecek

@Trecek Trecek commented Jul 30, 2026

Copy link
Copy Markdown
Collaborator

Summary

Part A makes arming and delivery of the recipe-execution credential inseparable: a typed credential value object with one producer consumed by both renderers; a shared completion-receipt renderer; an install-site registry ratchet that fails when an install_recipe_execution call's declaring entry does not name a response builder calling the sanctioned producer; a differential cross-delivery-mode reachability test driven against the real tool functions; a build-time fitness assertion across every bundled recipe; and structured failures naming their own remedy. Part A also remediates seven test requirements trimmed during implementation (digest stability, real-driver reachability, attested run_skill using only delivered values, parametrized 3-mode differential, response_budget_error pinning, registered delivery surfaces, fitness on real receipts), all driven against the real tool drivers with no payload.json reads and no synthetic hand-built dicts.

Individual Group Plans

Plan 1 — Rectify: Install-Implies-Deliver — the Recipe Execution Credential (Part A)

run_skill arms a hard attestation requirement the moment a recipe execution is installed
(tools_execution.py:884-892). The values that satisfy it — execution_id and the per-step
invocation_template_digest — are rendered by a different function, in a different call,
and only on some delivery paths. On the bounded (delivery_bound_spill: True) path the
requirement is armed by complete_recipe_initialization (_recipe_initialization.py:241) and
that call's six-key receipt carries none of them (:254-311). The orchestrator is required to
send a value it was never handed.

The bug class is broader than one missing key:

A requirement is armed in one place; the credential that satisfies it is rendered in
another, by hand, per branch. Nothing structurally ties arming to delivery.

Part A makes arming and delivery inseparable:

  1. One typed credential value object (RecipeExecutionCredential) with one producer
    (build_recipe_execution_credential), consumed by both renderers. Two hand-maintained
    dict literals become zero.
  2. One completion-receipt renderer shared by both branches of build_completion_response,
    so the two renderings cannot silently diverge — the exact recurrence the investigation
    warns about (Test Gap make-script-skill: Add pipeline data-flow quality checks #7).
  3. An install-site registry ratchet (RECIPE_EXECUTION_INSTALL_SITE_REGISTRY) modelled
    directly on the #4413 canonical-JSON producer/consumer ratchet: an AST guard that fails
    when any call to install_recipe_execution exists whose declaring entry does not name a
    response builder that calls the sanctioned credential producer. You cannot add a new way
    to install an execution without declaring — and proving — which response delivers its
    credential.
  4. A differential cross-delivery-mode reachability test that drives the real tool
    functions in every delivery mode and asserts the credential is reachable from responses
    alone, then completes a real attested run_skill. No payload.json read anywhere.
  5. Removal of the size landmine the fix could otherwise re-create: a build-time fitness
    assertion over every bundled recipe, plus conversion of the silent
    enforced != finalized.rendered swallow into a loud structured failure.
  6. Error strings that name their own remedy, and an instruction-surface ratchet that fails
    when a server-required run_skill parameter is named by no shipped instruction.

Part B (a separate task) covers the destructive named re-open and its diagnostics.

Plan 2 — Remediate Trimmed Test Coverage for the Recipe Execution Credential (#4411 Part A)

Part A's production changes all landed — 36 of 43 requirements are COVERED by audit round 1 — but
seven test requirements were trimmed or substituted during implementation. The NO GO authority
records them as MISSING:
REQ-021 (no digest-stability test for the install-site registry), REQ-031 (reachability file
holds synthetic tests over hand-built dicts), REQ-032 (no test_attested_run_skill_succeeds_using_only_delivered_values),
REQ-033 (no parametrized 3-mode differential test), REQ-035 (response_budget_error never asserted),
REQ-039 (no test_registered_delivery_surfaces_are_real_tools), and REQ-043 (fitness test hand-builds
receipts with fake digests, checks one bound, reuses no helper).

Test-only. No production source file changes. Every symbol the new tests need already exists
and is already exported through autoskillit.core.

Key design decisions: drive the real tools with the driver already in the repo (_open_kitchen_patched
moved into tests/server/_helpers.py); mode is chosen by backend capability plus real payload size,
never by a stub; ATTESTED_INLINE is driven at the finalizer (no MCP tool accepts host attestation);
nothing reads payload.json (enforced structurally via monkeypatch); the attested run_skill uses
only caller-visible values; the fitness test builds real receipts through the real renderer.

Closes #4411

Implementation Plan

Plan files:

  • /home/talon/projects/autoskillit-runs/remediation-20260729-093623-404122/.autoskillit/temp/rectify/rectify_attestation_credential_delivery_2026-07-29_103426_part_a.md
  • /home/talon/projects/autoskillit-runs/remediation-20260729-093623-404122/.autoskillit/temp/make-plan/remediate_attestation_delivery_test_coverage_2026-07-29_155013.md

🤖 Generated with Claude Code via AutoSkillit

Token Usage Summary

Step Model count uncached output cache_read peak_ctx turns cache_write time
investigate claude-opus-5[1m] 1 56.2k 55.7k 6.6M 197.7k 109 198.2k 13m 21s
rectify claude-opus-5[1m] 1 119.9k 100.1k 17.7M 316.6k 132 299.1k 44m 0s
review_approach* sonnet 1 5.7k 8.5k 489.5k 107.4k 39 115.8k 4m 46s
dry_walkthrough* sonnet 2 91.6k 134.1k 9.2M 232.7k 164 985.2k 24m 42s
audit_impl* sonnet 2 181.3k 204.3k 30.3M 398.1k 314 825.9k 46m 21s
make_plan claude-opus-5[1m] 1 191.3k 148.8k 40.0M 503.7k 239 1.0M 34m 36s
prepare_pr* MiniMax-M3 1 65.6k 3.7k 297.2k 0 18 0 1m 9s
compose_pr* MiniMax-M3 1 41.7k 4.5k 263.7k 0 17 0 55s
review_pr* sonnet 1 19.2k 27.2k 3.7M 120.9k 86 162.5k 6m 3s
resolve_review* sonnet 2 71.7k 30.1k 5.3M 125.8k 111 379.1k 13m 50s
Total 844.4k 717.0k 114.0M 503.7k 4.0M 3h 9m

* Step used a non-Anthropic provider; caching behavior may differ.

Token Efficiency

Step LoC Changed cache_read/LoC cache_write/LoC output/LoC
investigate 0
rectify 0
review_approach 0
dry_walkthrough 0
audit_impl 0
make_plan 0
prepare_pr 0
compose_pr 0
review_pr 0
resolve_review 8 667382.8 47382.5 3756.6
Total 8 14253033.2 497612.8 89628.4

Model Usage Breakdown

Model steps uncached output cache_read cache_write time
claude-opus-5[1m] 3 367.4k 304.6k 64.4M 1.5M 1h 31m
sonnet 5 369.6k 404.1k 49.1M 2.5M 1h 35m
MiniMax-M3 2 107.4k 8.3k 560.9k 0 2m 5s

Trecek and others added 10 commits July 29, 2026 12:25
…edential

Make arming and delivery of the recipe execution attestation inseparable:
- one typed credential value object (RecipeExecutionCredential) and
  build_recipe_execution_credential producer consumed by both renderers;
- one completion-receipt renderer _render_completion_receipt routed from
  both branches of build_completion_response;
- install-site registry ratchet RECIPE_EXECUTION_INSTALL_SITE_REGISTRY
  with AST guard test_execution_install_delivery;
- differential cross-delivery-mode reachability test
  test_attestation_delivery_reachability;
- build-time fitness assertion test_completion_receipt_fitness for the
  receipt with credential against every backend bound;
- loud structured failure recipe_initialization_receipt_altered when the
  response budget rewrites the receipt (was: silent return enforced);
- error message constants RECIPE_EXECUTION_ATTESTATION_MISSING_MESSAGE
  and RECIPE_EXECUTION_INACTIVE_MESSAGE name their remedy and replace
  the "standalone mode cannot claim recipe attestation" literal;
- instruction surface updates to _MCP_RETRY_INSTRUCTION and
  sous-chef/SKILL.md document the attestation forwarding rule.

Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com>
The canonical install-site digest was previously not asserted anywhere, so any
drift in the registry (added/removed entry, edited _asdict shape) would go
undetected. Mirror the RESPONSE_BACKSTOP_EXEMPTION_REGISTRY digest test
pattern at tests/core/test_type_constants.py:54-71.

No production source change.
The real open_kitchen driver (_mock_fmcp_ctx + _open_kitchen_patched) was
duplicated only in test_serve_idempotence.py. Move it byte-identically into
_helpers.py, the designated shared-builder module (tests/server/AGENTS.md:10),
and replace the local copies with a re-import. Add _credit_initialization_sections
and _pull_step_section so the reachability rewrite can credit pages to the
initialization without re-implementing pagination.

Drop the now-unused AsyncMock/MagicMock/patch imports from
test_serve_idempotence.py. All 11 pre-existing test functions in that file
keep passing — the helpers were not referenced by any other module.

No production source change.
The previous suite contained three synthetic dict-shape tests over hand-built
payloads that called none of the real tools. Replace it with a single
parametrized 3-mode reachability test plus two focused tests:

* REQ-031: drive open_kitchen (remediation, ENVELOPE), credit every section
  through get_recipe_section, then complete_recipe_initialization, asserting
  the credential appears on the completion receipt alone — no payload.json
  read.
* REQ-032: derive run_skill inputs exclusively from the receipt and the
  pulled step body, then prove the executor was reached (not merely a deny
  string avoided) by asserting the runner call count grew.
* REQ-033: parametrize over RecipeDeliveryMode with match/case dispatch.
  ORDINARY_INLINE reads body.recipe_execution; ATTESTED_INLINE is driven at
  finalize_recipe_delivery (no MCP tool accepts host attestation evidence);
  ENVELOPE asserts the credential is absent from the first response and
  present on the completion receipt.

A forbid_artifact_reads fixture patches the consuming module's bound name
(tools_recipe.load_recipe_artifact) to prove nothing reads the persisted
artifact — the poison is armed after the last pull so get_recipe_section
still serves pages.

Register the new test in tests/_test_filter.py under
LAYER_CASCADE_CONSERVATIVE['recipe'] so test-cascade-map_guard picks it up.

No production source change.
…error

The completion-enforcement contract asserts that an altered receipt returns
recipe_initialization_receipt_altered with response_budget_error surfaced.
Previously this field was asserted neither as the empty string (no
budget-error context) nor as the extracted value (when the altered payload
was a parseable dict containing 'error').

Add both assertions inside the existing
test_completion_is_server_owned_and_commits_ready_only_after_enforcement. A
membership-style check would pass against a hardcoded empty string; the
=='' form does not, so the new code cannot degrade to a vacuous assertion.
The extraction branch is exercised by a second altered call before the
existing success path.

No production source change.
The install-site registry's delivery_surface values are promises to the rest
of the system that the credential reaches the caller via those tools. A
typo'd or retired surface name would silently break the catalog without
breaking any existing test.

Add a fourth test method to TestExecutionInstallDelivery that resolves the
delivery_surface set against the IL-0 tool registry via
autoskillit.core.all_tool_names() (NOT the FastMCP mcp singleton — pulling
that into tests/arch/ would activate the mcp._transforms clear/restore
machinery in unrelated workers).

Both current surfaces (open_kitchen, complete_recipe_initialization) are in
TOOL_REGISTRY, so the test passes on landing and fails on any future drift.

No production source change.
… enumeration

The previous fitness test hand-built three receipts with fake digests, asserted
on one bound (response_max_bytes), and reused no helper — a vacuous size check.

Replace it with a single parametrized test that, for every bundled recipe:

* Builds the canonical artifact payload and a real execution credential
  through prepare_recipe_delivery_generation + build_recipe_execution_credential.
* Persists under tmp_path with persist_recipe_artifact.
* Renders the completion receipt through the production _render_completion_receipt
  (no synthetic digests).
* Asserts the receipt fits response_max_bytes AND every backend's general output
  token limit, reusing _backend_capabilities() and _generic_backstop_bound_bytes()
  from tests/contracts/test_delivery_bound_fitness.
* Asserts the measured credential matches the real credential: same key set,
  same execution_id, same template_digests dict — so the test cannot degrade
  to a size check on a credential-less receipt.

backend=None is deliberate: prepare_recipe_delivery_generation compiles the
snapshot without consulting the backend, while the bound loop covers every
registered backend explicitly. prepared.canonical_artifact_payload (not the
raw payload) is required because persist_recipe_artifact validates
flow_records/recipe_flow.

No production source change.
- _pull_step_section unwraps parsed[step_name] because _extract_step_body
  wraps the step in {step_name: step_obj}; consumers read step_body['with'].
- ATTESTED_INLINE test uses _payload(...) since real remediation (453 KB
  rendered) exceeds the 56,750 byte attested budget — measured in plan
  was body-only and missed flow_records/metadata added by finalize.
…n test_no_delivery_mode_omits_the_attestation_credential
@Trecek
Trecek added this pull request to the merge queue Jul 30, 2026
Merged via the queue into develop with commit 9bd7858 Jul 30, 2026
3 checks passed
@Trecek
Trecek deleted the bounded-open-kitchen-never-delivers-the-attestation-values-r/4411 branch July 30, 2026 01:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant