Repository navigation
[debate] agent-spec v1: per-action mandate with enforced_by, replacing the autonomy label #10
Description
What you're proposing
Replace agent-spec.schema.yaml v0.1.0 with a v1 that assigns authority action by action, each row requiring an enforcing mechanism, and drop the single per-agent autonomy label the current format requires.
What it affects
- An
aux.H*heuristic ID or definition - An
aux.T*trust stage ID or definition - A
tg.*gap ID or definition - A schema file in
/schemas/ - Public vocabulary (the words we use externally)
- Other —
aux-audit's rule set and its published output contract
Why now
The repository contradicts itself, in one file.
schemas/trust-architecture.yaml says:
Autonomy is not a slider you push to the right. It is a spectrum you choose per action, calibrated to evidence and stakes.
Enforcement lives in a mechanism, not in a prompt. A prompt saying "only update qualification information" is not the same as a tool that exposes only the qualification field. The first is a request; the second is a boundary.
schemas/agent-spec.schema.yaml requires:
autonomy:
type: enum
values: ["human-in-the-loop", "human-on-the-loop", "autonomous"]
required: trueOne slider position, for the whole agent. The reference input format requires precisely the abstraction the standard tells readers to avoid.
It is not cosmetic. aux-audit scores on it:
rules.ts—aux.H01andaux.H03take their base score fromspec.autonomy(lines 55–70, 99–112)guaranteesis free text, described in the schema as "explicit contracts the agent makes with the user (e.g. 'will always ask before sending external email')" — a promise. Three rules read it. There is no field anywhere in the format for the mechanism that enforces it.
So the audit's two most prominent heuristics rest on a label the canon calls wrong, and its notion of a guarantee is the exact thing enforcement.rule says is not a control.
Second, smaller defect: the file is not JSON Schema, though it uses the reserved $schema key as a container for a bespoke notation ({ type: string, required: true }). Any JSON Schema tool reads it wrong, and check_schema fails on it.
This is the first thing a careful reader finds. The docs say "don't use autonomy labels"; the reference implementation requires one.
Proposal
Adopt a v1 built as real JSON Schema draft 2020-12, whose core is:
mandate:
type: array
description: Assigned authority, action by action. Never an autonomy score.
items:
required: [action, authority, enforced_by]
properties:
authority:
enum: [autonomous, human_approval, human_only, prohibited]
enforced_by:
description: The mechanism, not the intention.
"System prompt" is not a valid answer for human_only or prohibited.Plus human_control (observe / interrupt / approve / override / disable — a kill switch alone is not oversight) and shutdown with a required tested boolean, because an untested kill switch is a claim, not a control.
A working draft exists and is the basis of this proposal.
Two things to settle before adoption
- ID namespace. The draft's
trust_stageenum isT01–T04. This repo's canon isaux.T01–aux.T04. Left unfixed this re-introduces the same fork that feat(schemas): merge the substance from the parallel schema set #9 had to unpick. - Should the input carry the output at all?
trust_stagein the draft is described as "the stage demonstrably earned" — butaux-auditcomputes the trust stage. Either the audit ignores the field, or it does something better: compares the claim against its own computation and reports the gap. "You declare T03; the spec supports T01" would be the most useful line the tool could print. That is a feature decision, not a schema detail.
Migration note
This is aux-audit v0.2, not a patch. Concretely:
spec.ts— rewritten. Real JSON Schema validation needs a validator; the package currently has exactly one runtime dependency (yaml), so addingajvis its own call.rules.ts—aux.H01andaux.H03stop asking "what is the autonomy label" and start asking "does every non-autonomous action name an enforcing mechanism". That is a better question and a different computation.- All fixtures and 34 tests.
repos/aux-audit/README.mdpublishes the v0.1 output contract; scores computed under v1 are not comparable to scores computed under v0.1, so the version has to move where anyone can see it.
Proposed sequencing, one PR:
schemas/agent-spec.v0.yaml— the current file, kept readable for anything already written against itschemas/agent-spec.schema.yaml— v1- the CLI rewrite lands in the same PR. Renaming first would leave a window where the canonical filename describes a format the shipped CLI cannot read.
Alternatives considered
- Keep v0.1, soften the docs. Rejected: the doctrine is the product. Weakening "define authority for specific actions" to match a schema is the wrong direction of fit.
- Add
mandatealongsideautonomy, keep both. Rejected as a permanent state — two ways to say the same thing is how a standard rots — but it is a reasonable transitional shape if v1 needs to ship before the CLI rewrite is ready. - Do nothing before launch. Rejected. This is a self-contradiction in the flagship artifact, and it is more expensive to be shown it than to fix it.
Interim, regardless of this outcome
The repository should not ship a known self-contradiction silently. A deprecation header on agent-spec.schema.yaml naming both defects and pointing here is going up now — the same treatment evolution_stage: schema-undefined got, which is: name the defect where the reader meets it.
Activity
RevenuePuzzles commentedon Sep 4, 2026
Measured: the migration is cheaper than this Issue estimated, and it has one trap
A v1 package arrived — schema,
migrate-v0-to-v1.py,MIGRATION.md,example-agent-spec.yaml,validate.py. Tested against a copy ofmainrather than reasoned about.Cost: about four lines, not a rewrite
The Migration note above called this "
aux-auditv0.2, not a patch". For the file swap, that was wrong.agent-spec.schema.yaml, no CLI changespec.tsrepointed toagent-spec.v0.yamlTotal: one line in
spec.ts:14, one entry insync-schemas.mjs, two references intest/spec.test.ts. The v0 file's content is semantically identical to what is onmaintoday — only comments differ.What remains genuinely v0.2 is the rule work:
aux.H01andaux.H03reading mandate rows andenforced_byinstead of a label. That is unchanged and still the real job.The trap: publishing v1 under the canonical name breaks the tool
With v1 as
agent-spec.schema.yamland the CLI reading v0, a spec written to the canonical schema gets:Four errors demanding fields v1 deliberately removed, including
autonomy— the exact field this Issue exists to eliminate. That trades an inconsistent document for a broken tool, which is worse: a reader can reason around the first.Proposed: land v1 canonical, with a shim
Rather than defer v1 until v0.2 is ready, add version detection to
spec.ts— roughly fifteen lines:mandateorspec_versionis v1aux-auditv0.1 does not score v1, and says so:"This is an agent-spec v1 document. aux-audit 0.1.0 reads v0.1.0 — see MIGRATION.md. v1 scoring lands in 0.2.0."
Doctrine gets fixed at the canonical filename now, which is the launch-blocking half. The tool stops lying about why it refused. And v0 specs keep scoring exactly as they do today.
Two corrections to the incoming package
validate.pyglobs its own directory, so it must live atschemas/validate.py. My first run pointed it elsewhere and it skipped nearly everything — my error, not the tool's.mainit fails, catching thatbrain-spec.schema.yamlusedT01–T04against this repo'saux.T01–aux.T04. That was my bug from feat(schemas): merge the substance from the parallel schema set #9. Fixed in fix(schemas): brain-spec used the wrong ID namespace; add a cross-schema check #12, which also adds the validator to CI.Still open here
The two questions from this Issue are untouched by any of the above: whether the input format should carry
trust_stageat all when the audit computes it, and — if it does — whetheraux-auditshould report the gap between claimed and supported stage. That second one is still the most useful line this tool could print.Generated by Claude Code