Skip to content

V10: A hook AGT has no host for - #31

Merged
afogel merged 1 commit into
slice/v9from
slice/v10
Sep 6, 2026
Merged

afogel merged 1 commit into
slice/v9from
slice/v10

Conversation

@afogel

@afogel afogel commented Aug 17, 2026

Copy link
Copy Markdown
Owner

Closes #29

Stacked on slice/v9. Review the diff against that base, not main. Slice 10 of 10.

What this slice is for

Drive an AGT stock gate from an ACS hook no AGT host package implements. This is R8.3 answered by building it rather than by showing a surface exists, and it is the first place the headroom argument is run.

What a reviewer is looking at

Planning only: slices/v10/README.md's frozen subject. No V10 implementation yet. The shaping and breadboard for both slices land in #30, which this is stacked on.

Why it is reachable — two measured facts, neither obvious from reading AGT

$defs/tool is additionalProperties: true, so a manifest tool entry may declare a content_hash — legal rather than merely tolerated. And the SDK carries it through. Reading AGT's own policyInput back out of the bridge's evidence path:

{"content_hash":"sha-256:APPROVED","id":"code-reviewer","type":"Tool","name":"code-reviewer"}

With config.content_hash.enforce: true and the observed hash at snapshot.tool_call.content_hash, all three stock behaviours fire:

Observed Verdict
matches allow
differs deny tool_content_hash_mismatch"declared sha-256:APPROVED but observed sha-256:POISONED"
absent deny tool_content_hash_mismatch"manifest declared tool.content_hash but snapshot.tool_call.content_hash was missing"

The gate needs one thing from this side: a snapshot.tool_call.content_hash. ACS supplies it at steps/skillLoad.

Two documents, written independently about the same threat

hooks/skill-load.json requires digest {algorithm, value} and says the Guardian compares it against the digest approved at steps/skillRegister, and that a load whose digest differs "is unverifiable and SHOULD be denied." That is, clause for clause, what content_hash.rego decides. Neither cites the other.

The claim, stated precisely — this is what slices/v10/README.md freezes

AGT's gate is about a tool. ACS v0.1.0 puts the integrity digest on a skill, and the AgBOM makes that split deliberate rather than incidental: skill_fields.definition is required to carry {ref, digest} and is described as "the surface attackers poison", while tool_fields requires only capability.

Same control, different component class. The published claim is "AGT's unforked rule decides an ACS-native subject" — never "ACS carries AGT's tool hash". The demo is more interesting because the subjects differ, not less.

The limit, recorded before anyone can find it in a demo

The approved digest is manifest-static, and cannot be otherwise from this side. content_hash.rego reads the declared hash from input.tool.content_hash and nowhere else; the SDK resolves input.tool from the manifest catalog; there is no destination_paths counterpart and annotations are not consulted. A digest a Guardian approved at steps/skillRegister cannot reach this gate through session state.

This slice declares it in the manifest and says so. The (skill_id, digest) binding ACS specifies is a Guardian-side control AGT has no part in, and V10 does not build it. Closing it the other way would mean AGT accepting a declared hash from the snapshot, which weakens AGT's own trust model — an upstream conversation, not a slice.

Depends on V9

A skill-load snapshot has no command argument, so under the pre-V9 manifest it hits runtime_error:path_missing before content_hash is consulted. The normalised policy-target leaf is the dependency, not the egress gate.

Closes D3 and R5.4

Three steps/* hooks of nineteen: steps/toolCallRequest, steps/toolCallResult, steps/skillLoad. Both counts in circulation are right for different sets — 22 is every hook payload schema, 19 is the steps/* subset R5.4 asks about.

Slice notes: slices/v10/README.md.

https://claude.ai/code/session_019qZbQWyJHrYG7UodpyKjYr

The collision here is not a word, it is a subject, and it is the one this
slice is most able to overclaim. AGT's content_hash gate is about a TOOL;
ACS v0.1.0 puts the integrity digest on a SKILL. The AgBOM makes that split
deliberate rather than incidental -- skill_fields.definition is required to
carry {ref, digest} and is called "the surface attackers poison", while
tool_fields requires only capability.

So commitment 1 is the published claim itself: AGT's unforked rule decides an
ACS-native subject, never "ACS carries AGT's tool hash". The demo is more
interesting because the subjects differ, not less.

Also records the limit before anyone can discover it in a demo: the approved
digest is manifest-static and cannot be otherwise from this side.
content_hash.rego reads input.tool.content_hash and nowhere else, the SDK
resolves that from the manifest catalog, and there is no destination_paths
counterpart. A digest approved at steps/skillRegister cannot reach the gate
through session state.

Claude-Session: https://claude.ai/code/session_019qZbQWyJHrYG7UodpyKjYr
@afogel
afogel merged commit 0156d78 into main Sep 6, 2026
2 of 4 checks passed
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.

V10: A hook AGT has no host for

1 participant