What is broken
Sixteen of the twenty-two hook schemas say nothing about which dispositions they accept, and no hook says what a runtime does when it receives one it cannot honor.
Six hooks constrain eligibility today, each in its own wording:
| Hook |
Wording in the schema description |
preCompact |
"Decision-eligible" and "MAY return 'deny'" |
postCompact |
"MAY return 'modify'" and "MUST NOT return 'deny'" |
subagentStop |
"Not decision-eligible" |
turnStart |
"Decision-eligible" |
turnEnd |
"Audit-only" |
agbomSnapshot |
"MAY return 'deny'" |
The other sixteen are silent, so a reader cannot tell whether silence means all five dispositions apply or that nobody wrote the rule down. memoryStore and knowledgeRetrieval are the ones that matter most in practice and are both in the silent set.
This is the machine-readability half of the problem. The terminology half, that "Not decision-eligible" carries two different meanings and that subagentStop is labelled inconsistently across two normative surfaces, is #146. Fixing the wording there does not by itself make eligibility checkable, and fixing it here does not by itself resolve which meaning was intended for subagentStop.
Where
specification/v0.1.0/hooks/*.json, specification/v0.1.0/response-envelope.json
What the specification says, and what happens instead
response-envelope.json permits all five dispositions on every hook. Its decision field is a flat enum of allow, deny, modify, ask, defer with no per-method constraint, so a validator can confirm a response carries a legal disposition and cannot confirm the disposition is legal for the method that was called.
postCompact is the clearest case of a rule that exists and is unenforceable. It says a Guardian MUST NOT return deny because compaction has already happened and the chain must record the post-compact state. Nothing stops a Guardian returning deny, and nothing says what the runtime does when it arrives.
The specification has answers for the two cases where a disposition is unhonorable because of a client limitation. §9.2 covers the approver-incapable client and §6.5 covers the MODIFY-incapable client, both with mandatory substitutions and audit events. Neither covers the case where the disposition is unhonorable because it was never eligible at that hook. Those are different failures. One is a capability gap in the client and the other is a Guardian returning something the protocol does not define for that method.
Impact on implementers
A runtime receiving an ineligible disposition has three defensible behaviors, and they produce three different audit trails from one Guardian decision. It can ignore it and proceed, which silently discards an enforcement decision. It can substitute by analogy to §6.5 or §9.2, which invents a rule the specification does not state. It can error, which turns a Guardian bug into an agent outage.
A policy author writing against memoryStore has no way to learn what it accepts short of reading every hook description and inferring a pattern from six inconsistent examples. That inference does not survive contact with a second harness, which is the thing the contract exists to prevent.
A conformance test cannot be written for any of this. #19 already notes that nobody verifies a conformance claim in v0.1.0, and this is one of the requirements that would resist verification even with a suite, because there is no stated rule to test against for sixteen of the hooks.
Direction, keeping the two halves separable: state eligible dispositions per hook in a machine-readable form, and define runtime behavior on an ineligible disposition once rather than leaving each runtime to generalize from the two client-capability cases.
Verified against PR #21's head. #21 adds §6.5 and reshapes the ACS-Core floor, and leaves all six eligibility statements above exactly as quoted, so this survives that merge unchanged.
Current Priority Scope
Feeds conformance evidence
What is broken
Sixteen of the twenty-two hook schemas say nothing about which dispositions they accept, and no hook says what a runtime does when it receives one it cannot honor.
Six hooks constrain eligibility today, each in its own wording:
preCompactpostCompactsubagentStopturnStartturnEndagbomSnapshotThe other sixteen are silent, so a reader cannot tell whether silence means all five dispositions apply or that nobody wrote the rule down.
memoryStoreandknowledgeRetrievalare the ones that matter most in practice and are both in the silent set.This is the machine-readability half of the problem. The terminology half, that "Not decision-eligible" carries two different meanings and that
subagentStopis labelled inconsistently across two normative surfaces, is #146. Fixing the wording there does not by itself make eligibility checkable, and fixing it here does not by itself resolve which meaning was intended forsubagentStop.Where
specification/v0.1.0/hooks/*.json,specification/v0.1.0/response-envelope.jsonWhat the specification says, and what happens instead
response-envelope.jsonpermits all five dispositions on every hook. Itsdecisionfield is a flat enum ofallow,deny,modify,ask,deferwith no per-method constraint, so a validator can confirm a response carries a legal disposition and cannot confirm the disposition is legal for the method that was called.postCompactis the clearest case of a rule that exists and is unenforceable. It says a Guardian MUST NOT returndenybecause compaction has already happened and the chain must record the post-compact state. Nothing stops a Guardian returningdeny, and nothing says what the runtime does when it arrives.The specification has answers for the two cases where a disposition is unhonorable because of a client limitation. §9.2 covers the approver-incapable client and §6.5 covers the MODIFY-incapable client, both with mandatory substitutions and audit events. Neither covers the case where the disposition is unhonorable because it was never eligible at that hook. Those are different failures. One is a capability gap in the client and the other is a Guardian returning something the protocol does not define for that method.
Impact on implementers
A runtime receiving an ineligible disposition has three defensible behaviors, and they produce three different audit trails from one Guardian decision. It can ignore it and proceed, which silently discards an enforcement decision. It can substitute by analogy to §6.5 or §9.2, which invents a rule the specification does not state. It can error, which turns a Guardian bug into an agent outage.
A policy author writing against
memoryStorehas no way to learn what it accepts short of reading every hook description and inferring a pattern from six inconsistent examples. That inference does not survive contact with a second harness, which is the thing the contract exists to prevent.A conformance test cannot be written for any of this. #19 already notes that nobody verifies a conformance claim in v0.1.0, and this is one of the requirements that would resist verification even with a suite, because there is no stated rule to test against for sixteen of the hooks.
Direction, keeping the two halves separable: state eligible dispositions per hook in a machine-readable form, and define runtime behavior on an ineligible disposition once rather than leaving each runtime to generalize from the two client-capability cases.
Verified against PR #21's head. #21 adds §6.5 and reshapes the ACS-Core floor, and leaves all six eligibility statements above exactly as quoted, so this survives that merge unchanged.
Current Priority Scope
Feeds conformance evidence