Skip to content

[Bug] Disposition eligibility is undefined for 16 of 22 hooks, and runtime behavior on an ineligible disposition is unspecified #148

Description

@rocklambros

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

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    status:needs-triageNot yet triaged. Applied by the issue formstype:bugSomething isn't working

    Type

    No type

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions