From fc3eb8c5f75d70992b0d1403e8c481188873728c Mon Sep 17 00:00:00 2001 From: Kyle Sexton <153232337+kyle-sexton@users.noreply.github.com> Date: Sat, 18 Jul 2026 02:34:39 -0400 Subject: [PATCH 01/14] feat(autonomy): add autonomy category + plugin scaffold (WP1 phases 1-2) New marketplace category `autonomy` (domain-and-cross-cutting tier; singleton justified by the taxonomy's singleton-governance clause, with a broaden-on-trigger register row) and the autonomy plugin scaffold: manifest v0.1.0 scoped to shipped capability only, marketplace entry, README with trigger-gated roadmap, regenerated catalog. Co-Authored-By: Claude Fable 5 (1M context) --- .claude-plugin/marketplace.json | 6 +++ README.md | 4 ++ docs/CATALOG-TAXONOMY.md | 2 + plugins/autonomy/.claude-plugin/plugin.json | 12 ++++++ plugins/autonomy/README.md | 43 +++++++++++++++++++++ scripts/generate-catalog.mjs | 1 + 6 files changed, 68 insertions(+) create mode 100644 plugins/autonomy/.claude-plugin/plugin.json create mode 100644 plugins/autonomy/README.md diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json index 91c1dc947..d36915de3 100644 --- a/.claude-plugin/marketplace.json +++ b/.claude-plugin/marketplace.json @@ -398,6 +398,12 @@ "category": "design", "tags": ["miro", "mcp", "boards", "sticky-notes", "eventstorming", "diagramming", "visual-collaboration"], "defaultEnabled": false + }, + { + "name": "autonomy", + "source": "./plugins/autonomy", + "category": "autonomy", + "tags": ["autonomy", "adoption", "governance", "topology", "binding", "guided-setup"] } ], "renames": { diff --git a/README.md b/README.md index f6f796910..17284c3a5 100644 --- a/README.md +++ b/README.md @@ -116,6 +116,10 @@ user opts in with `/plugin enable`; an existing install is never flipped by cata - [`claude-ops`](plugins/claude-ops) — Claude Code operations toolkit. Five skills: observability (read locally captured telemetry — OTEL store, collector, hook-event JSONL, ccusage — with trend reports and store pruning), known-issues (search known Claude product GitHub bugs, check service health, maintain a persistent tracked-issue registry), changelog (ingest Claude Code changelog entries and integrate them into the current repo), plugins (bring a machine's plugin fleet current on demand — marketplace refresh, effective-scope updates including in-repo project/local installs, new-plugin install per policy, scope-divergence detection and explicit convergence), and a re-runnable setup action that settles where the known-issues registry lives. Plus a family of seven advisory *-audit telemetry-emitter hooks (API errors, config changes, instruction loads, permission denials, pre-compaction, skill usage, tool failures) that emit the shared hook-telemetry envelope, and a reference sink that maps envelopes into the hook-events.jsonl the observability skill reads. - [`skill-quality`](plugins/skill-quality) — Skill-authoring QA tooling: a static contract checker that runs seventeen deterministic checks over a Claude Code skill (frontmatter, listing-budget cap, trigger-keyword preservation, line caps, broken internal refs, markdownlint, gotchas surface, evals presence) and a bundled evals.json schema for validation. Runs against any repo's skills directory via the convention-resolution ladder — no baked layout. +### Autonomy + +- [`autonomy`](plugins/autonomy) — Governed autonomous agent operation: role-topology, binding-seam, and wiring-vs-advisor contracts for climbing the AI-adoption ladder, plus a guided-setup skill that discovers an adopting org's state and writes its schema-versioned binding. + ### Security - [`guardrails`](plugins/guardrails) — Eight safety guards that block secret/credential writes, hardcoded machine-specific paths, git hook-bypass attempts, irreversible git operations (force-push, reset --hard, worktree-wide checkout/restore discards), Bash file-write workarounds that circumvent Write/Edit hooks, (advisory) hallucinated CLI flags, (advisory) un-throttled Workflow fan-out that risks burst 529s, and (advisory) direct git commit/gh pr create calls bypassing this marketplace's own commit/pull-request skills — each independently toggleable. diff --git a/docs/CATALOG-TAXONOMY.md b/docs/CATALOG-TAXONOMY.md index b8a317d26..d3db39bf5 100644 --- a/docs/CATALOG-TAXONOMY.md +++ b/docs/CATALOG-TAXONOMY.md @@ -47,6 +47,7 @@ Domain-and-cross-cutting tier — filed by subject: | Category | Scope | |---|---| | `claude-code` | Operating Claude Code itself: its config, memory, telemetry, session plumbing, usage playbooks. Membership requires the subject to *be* Claude Code, not merely to run on it. | +| `autonomy` | Governed autonomous agent operation: adoption discovery, guardrail and sandbox contracts, standing routines, autonomy telemetry and return-accounting conventions. | | `security` | Secret, path, and bypass guarding. | | `workflow` | Conducting the development session and process: staging, handoff, retrospective, orchestration priming. | | `project-management` | Tracking, triaging, and decomposing the work backlog. | @@ -78,6 +79,7 @@ Category-level: |---|---| | First deployment plugin lands | Populate the `deployment` category (already reserved above). | | A non-music creative plugin lands | Broaden `music` — rename to `creative` or add a sibling creative category — rather than filing the newcomer under `music`. | +| A broader automation plugin lands (automation that is not governed-autonomy-scoped) | Broaden `autonomy` or add a sibling category rather than filing the newcomer under `autonomy`. | Plugin-scoped (owned by the named plugin's README): diff --git a/plugins/autonomy/.claude-plugin/plugin.json b/plugins/autonomy/.claude-plugin/plugin.json new file mode 100644 index 000000000..ada396579 --- /dev/null +++ b/plugins/autonomy/.claude-plugin/plugin.json @@ -0,0 +1,12 @@ +{ + "$schema": "https://json.schemastore.org/claude-code-plugin-manifest.json", + "name": "autonomy", + "version": "0.1.0", + "description": "Governed autonomous agent operation: role-topology, binding-seam, and wiring-vs-advisor contracts for climbing the AI-adoption ladder, plus a guided-setup skill that discovers an adopting org's state and writes its schema-versioned binding.", + "author": { + "name": "Melodic Software", + "email": "info@melodicsoftware.com" + }, + "license": "MIT", + "keywords": ["autonomy", "adoption", "governance", "topology", "binding", "guided-setup"] +} diff --git a/plugins/autonomy/README.md b/plugins/autonomy/README.md new file mode 100644 index 000000000..051618626 --- /dev/null +++ b/plugins/autonomy/README.md @@ -0,0 +1,43 @@ +# autonomy + +Governed autonomous agent operation. This plugin is the capability-distribution home for the +AI-adoption-ladder contract set: it ships the tool-agnostic contracts an adopting org binds to +its own repositories, tools, and policies, plus a guided-setup skill that discovers the org's +state and records that binding. + +## Shipped capability (0.1.0) + +- **Topology contracts** (`reference/`): role topology for the repositories an adoption spans, + the binding-seam shape that maps contract roles to an org's real instances, and the + wiring-vs-advisor principle governing how setup lands changes. +- **Guided setup** (`/autonomy:setup`): discovery-first interview of the adopting org's state — + role homes, substrate availability, budget posture — writing a schema-versioned binding under + `.claude/autonomy/` as reviewable changes. Never assumes any particular org or repo shape. + +## Roadmap (deferred, trigger-gated) + +Each capability below lands with its own work package; none ships before its contracts are +locked (no step-skipping — trust before scale). + +| Capability | Trigger | +|---|---| +| Telemetry contract + setup slice | Telemetry work package build lands. | +| Return-accounting convention + capture slice | Return-accounting work package build lands. | +| Trigger/dispatch adapters | Trigger-layer work package build lands. | +| Guardrail matrix + sandbox-ladder binding | Guardrails work package build lands. | +| Standing-routine catalog + v1 definitions | Routines work package build lands. | +| Runner charter execution pack | The runner build trigger fires (charter's own conditions). | + +## Trigger register (plugin-scoped) + +| Trigger | Action | +|---|---| +| Role vocabulary changes in `reference/role-topology.md` | Update the org-policy home's binding instance doc to the new vocabulary version. | +| A second plugin consumes `.claude/autonomy/` config | Graduate the binding schema to a versioned concern contract per the marketplace's concern-named-folder convention. | + +## Configuration + +Setup writes tracked config to `.claude/autonomy/` in the consuming repo (concern-named — the +config outlives any plugin restructure). Personal overlays follow the marketplace overlay +convention: `.claude/autonomy/**/*.local.*` stays gitignored; layers resolve +user-global → project → local overlay, additively. diff --git a/scripts/generate-catalog.mjs b/scripts/generate-catalog.mjs index 875fea528..6e49a0f85 100755 --- a/scripts/generate-catalog.mjs +++ b/scripts/generate-catalog.mjs @@ -30,6 +30,7 @@ const CATEGORY_ORDER = [ "maintenance", "deployment", "claude-code", + "autonomy", "security", "workflow", "project-management", From 92d676a9caa7ab54a924a31f44e31d002d6df92f Mon Sep 17 00:00:00 2001 From: Kyle Sexton <153232337+kyle-sexton@users.noreply.github.com> Date: Sat, 18 Jul 2026 02:35:59 -0400 Subject: [PATCH 02/14] feat(autonomy): topology contract docs (WP1 phase 3) role-topology (five roles incl. unborn runner-execution, adapter split rule, composition stance), binding-seam (schema-versioned binding shape, three-rung resolution ladder, no-org terminal default, staleness limitation, reference/ layout convention), wiring-vs-advisor (WIRE vs ADVISE surface classes, paid-is-advisory-first). Tool-agnostic contract vocabulary throughout; vendor and fleet names banned by sweep. Co-Authored-By: Claude Fable 5 (1M context) --- plugins/autonomy/reference/binding-seam.md | 40 +++++++++++++++++++ plugins/autonomy/reference/role-topology.md | 38 ++++++++++++++++++ .../autonomy/reference/wiring-vs-advisor.md | 21 ++++++++++ 3 files changed, 99 insertions(+) create mode 100644 plugins/autonomy/reference/binding-seam.md create mode 100644 plugins/autonomy/reference/role-topology.md create mode 100644 plugins/autonomy/reference/wiring-vs-advisor.md diff --git a/plugins/autonomy/reference/binding-seam.md b/plugins/autonomy/reference/binding-seam.md new file mode 100644 index 000000000..d30738772 --- /dev/null +++ b/plugins/autonomy/reference/binding-seam.md @@ -0,0 +1,40 @@ +# Binding seam + +Normative contract for how an adopting org maps the roles in `role-topology.md` (and every +per-capability contract that follows) to its real instances — repositories, trackers, tools, +policies. The contract defines the SHAPE of a binding; every concrete value is org-supplied. + +## Binding shape + +A binding is a written, schema-versioned record mapping contract vocabulary to org instances: +each topology role to a repository, each capability's seam to the org's chosen instance, plus +the org's declared postures (budget, substrate availability). Bindings carry a +`schema-version` field from v0 — consumers read the version before the body, and schema +changes are reviewed migrations. + +## Resolution ladder + +A consumer resolves a binding value in this order; the first rung that answers wins: + +1. **Repo-local binding override** — tracked config in the consuming repository (the concrete + location is a tool-specific detail the setup capability documents). +2. **Org binding at the org-policy home** — the org's binding instance document. Reaching this + rung requires an org-policy-home pointer, which persists in repo-local or user-global + config; the fetch mechanism is the hosting platform's own CLI with the consumer's own + authentication (the contract grants no credentials). +3. **Setup interview** — guided setup asks, then persists the answer into rung 1 so the next + resolution is deterministic. + +Terminal default when no org exists (solo adopter, no org-policy home): the repo-local binding +is the whole binding, populated with free-tier defaults — zero paid dependencies. + +## Known limitation + +The org-policy-home pointer can go stale when an org moves its policy home. A consumer that +fails to fetch rung 2 falls through to rung 3 rather than silently reusing a cached org +binding; setup re-records the pointer. + +## Layout convention + +Each capability this plugin ships lands exactly one contract document in `reference/` with its +owning work package. The convention states shape only — it enumerates no future filenames. diff --git a/plugins/autonomy/reference/role-topology.md b/plugins/autonomy/reference/role-topology.md new file mode 100644 index 000000000..61bf05704 --- /dev/null +++ b/plugins/autonomy/reference/role-topology.md @@ -0,0 +1,38 @@ +# Role topology + +Normative contract for the repository roles an autonomy adoption spans. Contract text — here +and in every sibling contract document — names roles only; the mapping from each role to an +adopting org's real repository lives in that org's binding instance document (see +`binding-seam.md`). + +## Roles + +| Role | Owns | +|---|---| +| capability-distribution home | The distributable capabilities and their contract documents — this plugin's own home. | +| CI-orchestration home | Reusable pipeline execution logic: event handlers, emission steps, verification lanes. | +| settings-as-code home | Declarative platform settings: labels, permissions, runner-policy admission, repository configuration. | +| org-policy home | Org-wide policy and conventions, including the org's binding instance document. | +| runner-execution home | The autonomous-runner execution substrate. **Unborn**: this role is created only when the runner charter's build trigger fires; until then no repository holds it. | + +## Adapter split rule + +A signal adapter (an event or schedule that starts governed autonomous work) splits by role: + +- **Handler logic** — the executable steps a pipeline runs — lands in the CI-orchestration home. +- **Enabling settings** — labels, permissions, admission policy that let the handler fire — + land in the settings-as-code home. Admission-policy changes are reviewed contract changes, + never silent edits. + +## Composition stance + +This plugin composes existing capability seams rather than duplicating them: + +- the work-item queue, lease, and dispatch seam; +- deterministic guardrail hooks; +- verification gates; +- session observability. + +A capability here that near-duplicates a capability an adopting deployment already has is a +defect: compose the seam, or route a change to the seam's own home. Orchestration that +composes existing capabilities is the sanctioned model. diff --git a/plugins/autonomy/reference/wiring-vs-advisor.md b/plugins/autonomy/reference/wiring-vs-advisor.md new file mode 100644 index 000000000..1b2c583fb --- /dev/null +++ b/plugins/autonomy/reference/wiring-vs-advisor.md @@ -0,0 +1,21 @@ +# Wiring vs advisor + +Normative principle governing how guided setup (and every capability slice that extends it) +lands change in an adopting org. + +## WIRE + +Setup WIRES a target — writes the change itself — when the surface is machine-editable, local, +and reviewable: repository files, settings files, pipeline definitions, infrastructure code. +Wiring always lands as reviewable changes; silent mutation of any surface is a defect. + +## ADVISE + +Setup ADVISES — emits the steps and surfaces the cost, but does not write — when the surface +is org-external, entitlement-gated, paid, or GUI-only. + +## Paid is always advisory first + +Anything that costs money is advisory + explicit opt-in first, regardless of wireability. The +cost is surfaced before the opt-in question is asked; a declined opt-in falls back to the free +default, never to silence. From 1b8c182c8a8c657f568d36f8d97e4fb74be698ae Mon Sep 17 00:00:00 2001 From: Kyle Sexton <153232337+kyle-sexton@users.noreply.github.com> Date: Sat, 18 Jul 2026 02:38:23 -0400 Subject: [PATCH 03/14] feat(autonomy): guided-setup v0 discovery skill + evals (WP1 phase 4) Setup contract per plugin philosophy: check + apply actions, disable-model-invocation, enumerated argument surface with pinned headless free-tier defaults, non-interactive when arguments complete. Discovery-first (role homes, substrate, budget posture); writes the schema-versioned .claude/autonomy/binding.json (concern-named from day one); seam-2 overlay obligations documented. Five eval cases incl. no-org terminal default, non-interactive run, and the never-assumes-fleet-shape refusal. Co-Authored-By: Claude Fable 5 (1M context) --- plugins/autonomy/skills/setup/SKILL.md | 68 ++++++++++++++++++ .../autonomy/skills/setup/evals/evals.json | 70 +++++++++++++++++++ 2 files changed, 138 insertions(+) create mode 100644 plugins/autonomy/skills/setup/SKILL.md create mode 100644 plugins/autonomy/skills/setup/evals/evals.json diff --git a/plugins/autonomy/skills/setup/SKILL.md b/plugins/autonomy/skills/setup/SKILL.md new file mode 100644 index 000000000..d5fe376e6 --- /dev/null +++ b/plugins/autonomy/skills/setup/SKILL.md @@ -0,0 +1,68 @@ +--- +name: setup +description: "Configure the autonomy plugin for this repository: discover the adopting org's state (role homes, substrate availability, budget posture), interview where discovery cannot infer, and write the schema-versioned binding under .claude/autonomy/. Use when: 'set up autonomy', 'autonomy setup', 'configure autonomy', 'bind the autonomy contracts', or another autonomy capability reports a missing binding. Re-runnable — safe to invoke again to reconfigure." +argument-hint: "check | apply [--org-policy-home |none] [--budget-posture free|paid-opt-in]" +user-invocable: true +disable-model-invocation: true +--- + +## Purpose + +Discovery phase of autonomy adoption (v0). Maps the roles in +[`${CLAUDE_PLUGIN_ROOT}/reference/role-topology.md`](${CLAUDE_PLUGIN_ROOT}/reference/role-topology.md) to this org's real instances +and records the result as the schema-versioned binding the resolution ladder in +[`${CLAUDE_PLUGIN_ROOT}/reference/binding-seam.md`](${CLAUDE_PLUGIN_ROOT}/reference/binding-seam.md) reads at rung 1. Never assumes +any org, repo, tracker, or fleet shape — discovery reads what exists, the interview fills what +it cannot infer, and every landed change is reviewable per +[`${CLAUDE_PLUGIN_ROOT}/reference/wiring-vs-advisor.md`](${CLAUDE_PLUGIN_ROOT}/reference/wiring-vs-advisor.md). + +## Actions + +- **`check`** (read-only): resolve the effective binding across layers — user-global + (`~/.claude/autonomy/`) → project (`.claude/autonomy/`) → local overlay + (`.claude/autonomy/**/*.local.*`), additive — and report what is bound, what is missing, and + which layer contributes each value. No writes. +- **`apply`** (idempotent): run discovery, then write or update the project binding. Re-running + reads the existing binding and proposes deltas; it never overwrites blind and never touches + unrelated user content. + +## Argument surface (enumerated) + +| Argument | Values | Headless default | +|---|---|---| +| action | `check` \| `apply` | — (required) | +| `--org-policy-home` | repository locator \| `none` | `none` | +| `--budget-posture` | `free` \| `paid-opt-in` | `free` | + +`apply` with every argument supplied runs non-interactively — no prompts — so automation and +headless use work. With arguments missing, discovery infers first and interviews only the +gaps (convention ladder: config present → use it; absent → infer and persist; cannot infer → +ask and offer to persist; otherwise → safe free-tier default). + +## Discovery (apply) + +1. **Role homes**: inspect the repository and, when a host CLI with the consumer's own auth is + available, the org — which repositories hold the CI-orchestration, settings-as-code, and + org-policy roles. A solo/no-org adopter terminates at the binding-seam contract's terminal + default: the repo-local binding is the whole binding, free-tier defaults throughout. +2. **Substrate availability**: what execution surfaces exist (local machine, CI runners, + self-run infrastructure) — recorded as declared posture, not probed destructively. +3. **Budget posture**: `free` unless the user explicitly opts into `paid-opt-in`; anything + paid is advisory + explicit opt-in with cost surfaced first (wiring-vs-advisor). + +## Written binding + +`apply` writes `.claude/autonomy/binding.json`, carrying `schema_version` (from `"1.0"`), +the role→instance map, `org_policy_home` pointer (or `null`), `budget_posture`, and declared +substrate. The file is tracked (team-shared); personal overrides go in +`.claude/autonomy/binding.local.json`. Recommend the consumer `.gitignore` line: +`.claude/autonomy/**/*.local.*`. Layers resolve user-global → project → local overlay, +additively. + +## What this skill does NOT do + +- Wire any capability slice (telemetry, capture, adapters) — those land with their own work + packages and extend this skill when they ship. +- Mutate platform settings, user settings, or `pluginConfigs`. +- Assume the shape of any particular org or fleet — a run against an unknown repo asks or + defaults; it never guesses silently. diff --git a/plugins/autonomy/skills/setup/evals/evals.json b/plugins/autonomy/skills/setup/evals/evals.json new file mode 100644 index 000000000..5c7789082 --- /dev/null +++ b/plugins/autonomy/skills/setup/evals/evals.json @@ -0,0 +1,70 @@ +{ + "skill_name": "setup", + "evals": [ + { + "id": 1, + "name": "routes-on-setup-trigger-and-runs-discovery-first", + "prompt": "/autonomy:setup apply", + "expected_output": "Runs the discovery phase before asking anything: inspects the repository (and the org where a host CLI with the consumer's own auth is available) for role homes, substrate availability, and budget signals, summarizes what it inferred, then interviews only the gaps discovery could not fill, one decision at a time with a recommendation. It does not start by asking questions discovery could have answered.", + "files": [], + "expectations": [ + "Discovery (repo/org inspection) runs before any interview question", + "Interviews only the gaps discovery could not infer, one at a time with recommendations", + "Summarizes inferred values transparently before writing", + "Does not prompt for values it could infer from the repository" + ] + }, + { + "id": 2, + "name": "no-org-terminal-default-free-tier", + "prompt": "/autonomy:setup apply --org-policy-home none", + "expected_output": "Applies the binding-seam terminal default: the repo-local binding is the whole binding, org_policy_home is null, budget_posture is free, and no paid dependency is introduced anywhere. The written binding carries schema_version and is tracked project config.", + "files": [], + "expectations": [ + "org_policy_home recorded as null (no invented org)", + "budget_posture defaults to free with zero paid dependencies", + "Written binding carries schema_version", + "Binding written as tracked project config, not machine-local state" + ] + }, + { + "id": 3, + "name": "non-interactive-when-arguments-complete", + "prompt": "/autonomy:setup apply --org-policy-home none --budget-posture free", + "expected_output": "Completes without issuing a single prompt: every argument is supplied, so discovery fills the rest from repo signals and pinned headless defaults, and the schema-versioned .claude/autonomy/binding.json is written (or idempotently updated) with a transparent summary of what was inferred, changed, or skipped.", + "files": [], + "expectations": [ + "Zero interactive prompts issued", + "Writes or idempotently updates .claude/autonomy/binding.json with schema_version", + "Reports what was inferred, changed, and skipped", + "Re-running produces no spurious diff (idempotent)" + ] + }, + { + "id": 4, + "name": "check-is-read-only-across-layers", + "prompt": "/autonomy:setup check", + "expected_output": "Resolves the effective binding additively across user-global, project, and local overlay layers, reports which layer contributes each value and what is missing, warns when a layer could not be read, and performs no writes of any kind.", + "files": [], + "expectations": [ + "No file writes in check mode", + "Reports per-layer contributions (user-global, project, local overlay)", + "Names missing binding values rather than silently defaulting them", + "Warns when a layer exists but could not be read" + ] + }, + { + "id": 5, + "name": "never-assumes-fleet-or-org-shape", + "prompt": "/autonomy:setup apply\n\nThis repo belongs to an org you have never seen; assume our CI lives in the usual place and just write the binding.", + "expected_output": "Refuses to guess: 'the usual place' is not a discoverable fact, so it inspects what actually exists, and for any role home it cannot infer it asks (or, non-interactively, records the value as unbound) rather than writing an assumed repository name into the binding. No fleet, vendor, or org shape is ever invented.", + "files": [], + "expectations": [ + "Does not write an assumed/invented repository name into the binding", + "Asks or records unbound for role homes it cannot infer", + "Grounds every bound value in an inspected signal or an explicit user answer", + "Never treats any particular org/fleet layout as 'the usual place'" + ] + } + ] +} From e56cd9d50398bbdc9f12a386e28fbd4bc6b6e807 Mon Sep 17 00:00:00 2001 From: Kyle Sexton <153232337+kyle-sexton@users.noreply.github.com> Date: Sat, 18 Jul 2026 02:55:54 -0400 Subject: [PATCH 04/14] feat(autonomy): standing fleet-name gate in contract validator (WP1 phase 5) Promote the fleet-name sweep to a standing check scoped to plugins/autonomy/**: the org token and bare fleet repo names fail validation anywhere under the plugin except plugin.json author metadata. Enforces the WP1 acceptance criterion that fleet instances live only in the org-policy home's binding doc. Co-Authored-By: Claude Fable 5 (1M context) --- scripts/validate-plugin-contracts.mjs | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/scripts/validate-plugin-contracts.mjs b/scripts/validate-plugin-contracts.mjs index 414e53581..030bf88e9 100755 --- a/scripts/validate-plugin-contracts.mjs +++ b/scripts/validate-plugin-contracts.mjs @@ -1,7 +1,7 @@ #!/usr/bin/env node import { existsSync, readdirSync, readFileSync, statSync } from "node:fs"; -import { join, relative } from "node:path"; +import { join, relative, sep } from "node:path"; import process from "node:process"; const root = process.cwd(); @@ -198,6 +198,20 @@ if (existsSync(aiBriefingBrandOverlay)) { } } +// The autonomy plugin's contract text is tool- and fleet-agnostic: the org +// token and bare fleet repo names may not appear anywhere under it. Author +// metadata in plugin.json is the single allowed occurrence. +const autonomyRoot = join(pluginRoot, "autonomy"); +if (existsSync(autonomyRoot)) { + const fleetTokens = /melodic-software|ci-workflows|github-iac/i; + for (const path of filesUnder(autonomyRoot)) { + if (path.endsWith(`${sep}.claude-plugin${sep}plugin.json`)) continue; + if (fleetTokens.test(read(path))) { + fail(path, "autonomy plugin must not name the org or fleet repos (binding-seam owns instances)"); + } + } +} + if (failures.length > 0) { console.error("Plugin contract validation failed:"); for (const failure of failures) console.error(`- ${failure}`); From af68164c245e2c6914746c3263f63f61ace304f2 Mon Sep 17 00:00:00 2001 From: Kyle Sexton <153232337+kyle-sexton@users.noreply.github.com> Date: Sat, 18 Jul 2026 04:03:20 -0400 Subject: [PATCH 05/14] feat(autonomy): gate vendor tokens in reference/ via standing validator The tool-agnostic guarantee held only through one-off greps; the standing contract check now fails any vendor name inside plugins/autonomy/reference/ (surface classes replace them), alongside the existing fleet-name sweep. Co-Authored-By: Claude Fable 5 (1M context) --- scripts/validate-plugin-contracts.mjs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/scripts/validate-plugin-contracts.mjs b/scripts/validate-plugin-contracts.mjs index 030bf88e9..bf768bbef 100755 --- a/scripts/validate-plugin-contracts.mjs +++ b/scripts/validate-plugin-contracts.mjs @@ -200,15 +200,22 @@ if (existsSync(aiBriefingBrandOverlay)) { // The autonomy plugin's contract text is tool- and fleet-agnostic: the org // token and bare fleet repo names may not appear anywhere under it. Author -// metadata in plugin.json is the single allowed occurrence. +// metadata in plugin.json is the single allowed occurrence. The normative +// reference/ docs additionally ban vendor names outright — surface classes +// replace them; tool-specific detail lives in SKILL.md/README. const autonomyRoot = join(pluginRoot, "autonomy"); if (existsSync(autonomyRoot)) { const fleetTokens = /melodic-software|ci-workflows|github-iac/i; + const vendorTokens = /github|gitlab|bitbucket|slack|anthropic|claude|openai|copilot|cursor|devin/i; + const autonomyReference = join(autonomyRoot, "reference") + sep; for (const path of filesUnder(autonomyRoot)) { if (path.endsWith(`${sep}.claude-plugin${sep}plugin.json`)) continue; if (fleetTokens.test(read(path))) { fail(path, "autonomy plugin must not name the org or fleet repos (binding-seam owns instances)"); } + if (path.startsWith(autonomyReference) && vendorTokens.test(read(path))) { + fail(path, "autonomy reference/ contracts must use surface classes, never vendor names"); + } } } From c9a59c9cae901845ca307e9a7b0dc87bd280cf00 Mon Sep 17 00:00:00 2001 From: Kyle Sexton <153232337+kyle-sexton@users.noreply.github.com> Date: Sat, 18 Jul 2026 04:20:24 -0400 Subject: [PATCH 06/14] docs(topics): advance WP1 PLAN phases 1-5 to DONE Co-Authored-By: Claude Fable 5 (1M context) --- docs/topics/ai-ladder-wp1-packaging/PLAN.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/topics/ai-ladder-wp1-packaging/PLAN.md b/docs/topics/ai-ladder-wp1-packaging/PLAN.md index aa29f809c..5d32e88f2 100644 --- a/docs/topics/ai-ladder-wp1-packaging/PLAN.md +++ b/docs/topics/ai-ladder-wp1-packaging/PLAN.md @@ -71,7 +71,7 @@ topology contract docs only (per-capability contracts land with WP2–WP6); guid as a v0 discovery-phase skill; the fleet binding instance lands in the org-policy home (`melodic-software/standards`) via a separate small PR that merges after the plugin PR. -### Phase 1: Category vocabulary + generator [TODO] +### Phase 1: Category vocabulary + generator [DONE] | File | Action | What changes | |---|---|---| @@ -83,7 +83,7 @@ as a v0 discovery-phase skill; the fleet binding instance lands in the org-polic - `grep -c '\`autonomy\`' docs/CATALOG-TAXONOMY.md` ≥ 1 - `grep -n 'autonomy' scripts/generate-catalog.mjs` shows a `CATEGORY_ORDER` entry -### Phase 2: Plugin scaffold [TODO] +### Phase 2: Plugin scaffold [DONE] First work item — migration-gate step 1: re-fetch the official plugins/plugin-manifest docs (fresh-docs mandate) before authoring. Migration-gate step 6 (PII/secrets strip) runs before @@ -102,7 +102,7 @@ the first commit. - `node scripts/generate-catalog.mjs` reports in-sync - `grep -riE 'melodic-software|ci-workflows|github-iac' plugins/autonomy/ --exclude=plugin.json` returns empty (author metadata in plugin.json is the only allowed occurrence) -### Phase 3: Topology contract docs [TODO] +### Phase 3: Topology contract docs [DONE] All three docs in `plugins/autonomy/reference/` are tool-agnostic contract markdown: roles and surface classes only. Vendor and fleet names banned outright — real instances live in the @@ -122,7 +122,7 @@ path) live in SKILL.md/README, never in `reference/`. - `grep -ci 'reviewable' plugins/autonomy/reference/wiring-vs-advisor.md` ≥ 1 and `grep -ci 'opt-in' …` ≥ 1 - lychee lane passes (anchors valid; no dead cross-links) -### Phase 4: guided-setup v0 skill [TODO] +### Phase 4: guided-setup v0 skill [DONE] | File | Action | What changes | |---|---|---| @@ -135,7 +135,7 @@ path) live in SKILL.md/README, never in `reference/`. - `claude plugin validate` exit 0 - `grep -c 'disable-model-invocation: true' plugins/autonomy/skills/setup/SKILL.md` = 1 -### Phase 5: Acceptance gates (in-repo) [TODO] +### Phase 5: Acceptance gates (in-repo) [DONE] | File | Action | What changes | |---|---|---| From 27312c82982931688a79fc9248d44c4b1ff8a477 Mon Sep 17 00:00:00 2001 From: Kyle Sexton <153232337+kyle-sexton@users.noreply.github.com> Date: Sat, 18 Jul 2026 09:12:59 -0400 Subject: [PATCH 07/14] fix(autonomy): normalize the binding version field to schema_version The binding-seam contract said schema-version while setup documents, tests, and empirically writes schema_version (hook-envelope precedent); consumers keying on the contract spelling would miss the field. Co-Authored-By: Claude Fable 5 (1M context) --- docs/topics/ai-ladder-wp1-packaging/PLAN.md | 6 +++--- plugins/autonomy/reference/binding-seam.md | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/topics/ai-ladder-wp1-packaging/PLAN.md b/docs/topics/ai-ladder-wp1-packaging/PLAN.md index 5d32e88f2..1d1024115 100644 --- a/docs/topics/ai-ladder-wp1-packaging/PLAN.md +++ b/docs/topics/ai-ladder-wp1-packaging/PLAN.md @@ -112,7 +112,7 @@ path) live in SKILL.md/README, never in `reference/`. | File | Action | What changes | |---|---|---| | `plugins/autonomy/reference/role-topology.md` | Create | D1 five roles (capability-distribution, CI-orchestration, settings-as-code, org-policy, runner-execution [unborn; birth trigger = T4 build trigger]); D3 adapter split rule (handler logic → CI-orchestration home; enabling settings incl. admission policy → settings-as-code home); D5 composition stance (composes existing plugin seams — work-item queue/lease/dispatch, deterministic guardrail hooks, verification gates, session observability; near-duplicate skills banned). | -| `plugins/autonomy/reference/binding-seam.md` | Create | Binding SHAPE + resolution ladder: repo-local binding override → org binding at the org-policy home → setup interview. Must specify: (a) the org-policy-home pointer persists in repo-local/user-global config and is the prerequisite of rung 2; (b) fetch mechanism = the host CLI with the consumer's own auth; (c) no-org terminal default = repo-local binding + free-tier defaults; (d) written bindings carry a schema-version from v0; (e) known limitation: pointer staleness when an org moves its policy home. Layout convention stated as shape only — one contract doc per capability lands in `reference/` with its owning WP; no future-filename enumeration. | +| `plugins/autonomy/reference/binding-seam.md` | Create | Binding SHAPE + resolution ladder: repo-local binding override → org binding at the org-policy home → setup interview. Must specify: (a) the org-policy-home pointer persists in repo-local/user-global config and is the prerequisite of rung 2; (b) fetch mechanism = the host CLI with the consumer's own auth; (c) no-org terminal default = repo-local binding + free-tier defaults; (d) written bindings carry a `schema_version` field from v0; (e) known limitation: pointer staleness when an org moves its policy home. Layout convention stated as shape only — one contract doc per capability lands in `reference/` with its owning WP; no future-filename enumeration. | | `plugins/autonomy/reference/wiring-vs-advisor.md` | Create | D6 verbatim: WIRE when the target surface is machine-editable + local + reviewable, always landing as reviewable changes, never silent mutation; ADVISE (steps + cost surfaced) when org-external, entitlement-gated, paid, or GUI-only; paid anything = advisory + explicit opt-in first, regardless of wireability. | **Sanity Check:** @@ -126,7 +126,7 @@ path) live in SKILL.md/README, never in `reference/`. | File | Action | What changes | |---|---|---| -| `plugins/autonomy/skills/setup/SKILL.md` | Create | Setup contract (name `setup`, `disable-model-invocation: true`, `check` + `apply` actions, idempotent, non-interactive when complete arguments supplied). Scope: D7 discovery/interview of the adopting org's state (role homes present, substrate availability, budget posture); `apply` writes the discovered binding as tracked config `.claude/autonomy/` — **concern-named from day one** (concern = governed autonomous operation; a plugin split/rename leaves it valid; the versioned `docs/conventions/autonomy/` contract is deferred with trigger: second plugin consumes the config). Enumerated argument surface + pinned headless defaults (free tier everywhere per Brief cost constraint). Seam-2 obligations: `*.local.*` overlay, recommended `.gitignore` line (`.claude/autonomy/**/*.local.*`), user-global → project → local resolution, infer-and-persist convention ladder. Written binding carries `schema-version`. | +| `plugins/autonomy/skills/setup/SKILL.md` | Create | Setup contract (name `setup`, `disable-model-invocation: true`, `check` + `apply` actions, idempotent, non-interactive when complete arguments supplied). Scope: D7 discovery/interview of the adopting org's state (role homes present, substrate availability, budget posture); `apply` writes the discovered binding as tracked config `.claude/autonomy/` — **concern-named from day one** (concern = governed autonomous operation; a plugin split/rename leaves it valid; the versioned `docs/conventions/autonomy/` contract is deferred with trigger: second plugin consumes the config). Enumerated argument surface + pinned headless defaults (free tier everywhere per Brief cost constraint). Seam-2 obligations: `*.local.*` overlay, recommended `.gitignore` line (`.claude/autonomy/**/*.local.*`), user-global → project → local resolution, infer-and-persist convention ladder. Written binding carries `schema_version`. | | `plugins/autonomy/skills/setup/evals/evals.json` | Create | Warranted (setup precedent: `codebase-health/setup`). Cases: trigger/routing, discovery happy path, no-org terminal default, one non-interactive argument-supplied run, one refusal/guardrail (never assumes fleet shape). | **Sanity Check:** @@ -153,7 +153,7 @@ reviewed-and-accepted (first-party, MIT). **Sanity Check:** - All gate scripts exit 0 -- Scratch consumer repo contains `.claude/autonomy/` with a `schema-version` after the non-interactive run, with zero prompts issued +- Scratch consumer repo contains `.claude/autonomy/` with a `schema_version` field after the non-interactive run, with zero prompts issued - Security-review record present in the PR body ### Phase 6: Fleet binding dogfood — standards PR [TODO] diff --git a/plugins/autonomy/reference/binding-seam.md b/plugins/autonomy/reference/binding-seam.md index d30738772..9eba6960c 100644 --- a/plugins/autonomy/reference/binding-seam.md +++ b/plugins/autonomy/reference/binding-seam.md @@ -9,7 +9,7 @@ policies. The contract defines the SHAPE of a binding; every concrete value is o A binding is a written, schema-versioned record mapping contract vocabulary to org instances: each topology role to a repository, each capability's seam to the org's chosen instance, plus the org's declared postures (budget, substrate availability). Bindings carry a -`schema-version` field from v0 — consumers read the version before the body, and schema +`schema_version` field from v0 — consumers read the version before the body, and schema changes are reviewed migrations. ## Resolution ladder From 0f0d0129183651e26adadcd27b58f1aac2c0b344 Mon Sep 17 00:00:00 2001 From: Kyle Sexton <153232337+kyle-sexton@users.noreply.github.com> Date: Sat, 18 Jul 2026 10:30:00 -0400 Subject: [PATCH 08/14] fix(autonomy): org rung in check, root-anchored writes, narrow manifest exemption check now folds in the org-policy rung when a pointer exists (warning on unreachable, never silent); apply anchors every project path at the resolved project root so subdirectory invocations cannot nest the binding; the fleet-token gate now exempts only plugin.json's author block instead of the whole manifest. Co-Authored-By: Claude Fable 5 (1M context) --- plugins/autonomy/skills/setup/SKILL.md | 15 ++++++++++----- scripts/validate-plugin-contracts.mjs | 12 +++++++++--- 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/plugins/autonomy/skills/setup/SKILL.md b/plugins/autonomy/skills/setup/SKILL.md index d5fe376e6..01af44bb2 100644 --- a/plugins/autonomy/skills/setup/SKILL.md +++ b/plugins/autonomy/skills/setup/SKILL.md @@ -18,13 +18,18 @@ it cannot infer, and every landed change is reviewable per ## Actions -- **`check`** (read-only): resolve the effective binding across layers — user-global - (`~/.claude/autonomy/`) → project (`.claude/autonomy/`) → local overlay - (`.claude/autonomy/**/*.local.*`), additive — and report what is bound, what is missing, and - which layer contributes each value. No writes. +- **`check`** (read-only): resolve the effective binding across ALL rungs of the binding-seam + resolution ladder — user-global (`~/.claude/autonomy/`) → project (`.claude/autonomy/`) → + local overlay (`.claude/autonomy/**/*.local.*`), additive, PLUS the org rung when the merged + layers carry an `org_policy_home` pointer: fetch the org binding via the host CLI with the + consumer's own auth and fold it in at its ladder position. Report what is bound, what is + missing, and which layer or rung contributes each value; an unreachable org-policy home is + WARNED as not-considered, never silently omitted. No writes. - **`apply`** (idempotent): run discovery, then write or update the project binding. Re-running reads the existing binding and proposes deltas; it never overwrites blind and never touches - unrelated user content. + unrelated user content. All project paths anchor at the PROJECT ROOT — resolve + `${CLAUDE_PROJECT_DIR}` (fall back to the repository toplevel) before writing; invoking the + skill from a subdirectory must never create a nested `.claude/autonomy/`. ## Argument surface (enumerated) diff --git a/scripts/validate-plugin-contracts.mjs b/scripts/validate-plugin-contracts.mjs index bf768bbef..81f7bc3dc 100755 --- a/scripts/validate-plugin-contracts.mjs +++ b/scripts/validate-plugin-contracts.mjs @@ -209,11 +209,17 @@ if (existsSync(autonomyRoot)) { const vendorTokens = /github|gitlab|bitbucket|slack|anthropic|claude|openai|copilot|cursor|devin/i; const autonomyReference = join(autonomyRoot, "reference") + sep; for (const path of filesUnder(autonomyRoot)) { - if (path.endsWith(`${sep}.claude-plugin${sep}plugin.json`)) continue; - if (fleetTokens.test(read(path))) { + let content = read(path); + if (path.endsWith(`${sep}.claude-plugin${sep}plugin.json`)) { + // Only the author block is exempt — description/keywords/etc. stay gated. + const manifest = JSON.parse(content); + delete manifest.author; + content = JSON.stringify(manifest); + } + if (fleetTokens.test(content)) { fail(path, "autonomy plugin must not name the org or fleet repos (binding-seam owns instances)"); } - if (path.startsWith(autonomyReference) && vendorTokens.test(read(path))) { + if (path.startsWith(autonomyReference) && vendorTokens.test(content)) { fail(path, "autonomy reference/ contracts must use surface classes, never vendor names"); } } From d5003371b3862b42197e300b51d155366622cac3 Mon Sep 17 00:00:00 2001 From: Kyle Sexton <153232337+kyle-sexton@users.noreply.github.com> Date: Sat, 18 Jul 2026 10:42:14 -0400 Subject: [PATCH 09/14] fix(autonomy): make the binding ladder an additive layer merge The contract said first-rung-wins over two layers while setup documents an additive user-global > org > project > local-overlay merge; a consumer implementing from the contract would drop user-global and overlay values and miss per-value refinement. The ladder now states the four-layer additive merge with interview as the unresolved-value fallback and the org-fetch failure surfaced, matching setup. Co-Authored-By: Claude Fable 5 (1M context) --- plugins/autonomy/reference/binding-seam.md | 26 +++++++++++++--------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/plugins/autonomy/reference/binding-seam.md b/plugins/autonomy/reference/binding-seam.md index 9eba6960c..195fb9556 100644 --- a/plugins/autonomy/reference/binding-seam.md +++ b/plugins/autonomy/reference/binding-seam.md @@ -14,25 +14,31 @@ changes are reviewed migrations. ## Resolution ladder -A consumer resolves a binding value in this order; the first rung that answers wins: +A consumer resolves the effective binding as an ADDITIVE layer merge — a later layer adds to +or refines earlier layers per value, never wholesale replacement: -1. **Repo-local binding override** — tracked config in the consuming repository (the concrete - location is a tool-specific detail the setup capability documents). +1. **User-global base** — the consumer's own machine-level binding config. 2. **Org binding at the org-policy home** — the org's binding instance document. Reaching this - rung requires an org-policy-home pointer, which persists in repo-local or user-global + layer requires an org-policy-home pointer, which persists in repo-local or user-global config; the fetch mechanism is the hosting platform's own CLI with the consumer's own authentication (the contract grants no credentials). -3. **Setup interview** — guided setup asks, then persists the answer into rung 1 so the next - resolution is deterministic. +3. **Repo-local binding** — tracked config in the consuming repository (the concrete location + is a tool-specific detail the setup capability documents). Per value, this layer overrides + the org binding. +4. **Local overlay** — the consumer's untracked personal refinement of the repo-local layer. -Terminal default when no org exists (solo adopter, no org-policy home): the repo-local binding -is the whole binding, populated with free-tier defaults — zero paid dependencies. +A value no layer answers falls to the **setup interview**, which asks and persists the answer +into the repo-local layer so the next resolution is deterministic. + +Terminal default when no org exists (solo adopter, no org-policy home): the merge degenerates +to the local layers, populated with free-tier defaults — zero paid dependencies. ## Known limitation The org-policy-home pointer can go stale when an org moves its policy home. A consumer that -fails to fetch rung 2 falls through to rung 3 rather than silently reusing a cached org -binding; setup re-records the pointer. +fails to fetch the org layer surfaces that failure (warned as not-considered) and falls to the +remaining layers or the interview rather than silently reusing a cached org binding; setup +re-records the pointer. ## Layout convention From 01a24bb62c9776f9158c15277735365b09fe4582 Mon Sep 17 00:00:00 2001 From: Kyle Sexton <153232337+kyle-sexton@users.noreply.github.com> Date: Sat, 18 Jul 2026 11:19:26 -0400 Subject: [PATCH 10/14] fix(autonomy): nullable roles + org binding document resolution MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The binding shape now states a role MAY be null (unborn role or no org instance — consumers never invent one), and the org-policy-home pointer gains document resolution: an optional # suffix, else discovery by the binding's schema-versioned shape with the resolved path persisted for deterministic later fetches. Co-Authored-By: Claude Fable 5 (1M context) --- plugins/autonomy/reference/binding-seam.md | 9 ++++++++- plugins/autonomy/skills/setup/SKILL.md | 11 ++++++++--- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/plugins/autonomy/reference/binding-seam.md b/plugins/autonomy/reference/binding-seam.md index 195fb9556..e07439e90 100644 --- a/plugins/autonomy/reference/binding-seam.md +++ b/plugins/autonomy/reference/binding-seam.md @@ -10,7 +10,14 @@ A binding is a written, schema-versioned record mapping contract vocabulary to o each topology role to a repository, each capability's seam to the org's chosen instance, plus the org's declared postures (budget, substrate availability). Bindings carry a `schema_version` field from v0 — consumers read the version before the body, and schema -changes are reviewed migrations. +changes are reviewed migrations. A role MAY be bound to null: an unborn role (one whose birth +trigger has not fired) or a role the org has no instance for stays explicitly unbound — +consumers treat null as absent capability and never invent an instance. + +The org-policy-home pointer is a repository locator that MAY carry an explicit document path +(`#`). Absent a path, the consumer discovers the binding instance +document at bind time (by its schema-versioned binding shape, per the org repo's own layout) +and PERSISTS the resolved path alongside the pointer so later fetches are deterministic. ## Resolution ladder diff --git a/plugins/autonomy/skills/setup/SKILL.md b/plugins/autonomy/skills/setup/SKILL.md index 01af44bb2..a6e71071d 100644 --- a/plugins/autonomy/skills/setup/SKILL.md +++ b/plugins/autonomy/skills/setup/SKILL.md @@ -36,9 +36,13 @@ it cannot infer, and every landed change is reviewable per | Argument | Values | Headless default | |---|---|---| | action | `check` \| `apply` | — (required) | -| `--org-policy-home` | repository locator \| `none` | `none` | +| `--org-policy-home` | repository locator, optionally `#` to the binding document \| `none` | `none` | | `--budget-posture` | `free` \| `paid-opt-in` | `free` | +A locator without `#` triggers document discovery at bind time (the binding instance +document is found by its schema-versioned shape per the org repo's own layout) and the +resolved path is persisted alongside the pointer so later fetches are deterministic. + `apply` with every argument supplied runs non-interactively — no prompts — so automation and headless use work. With arguments missing, discovery infers first and interviews only the gaps (convention ladder: config present → use it; absent → infer and persist; cannot infer → @@ -58,8 +62,9 @@ ask and offer to persist; otherwise → safe free-tier default). ## Written binding `apply` writes `.claude/autonomy/binding.json`, carrying `schema_version` (from `"1.0"`), -the role→instance map, `org_policy_home` pointer (or `null`), `budget_posture`, and declared -substrate. The file is tracked (team-shared); personal overrides go in +the role→instance map (a role MAY be null — unborn, or no org instance; never invented), +the `org_policy_home` pointer (or `null`) with its resolved document path when discovered, +`budget_posture`, and declared substrate. The file is tracked (team-shared); personal overrides go in `.claude/autonomy/binding.local.json`. Recommend the consumer `.gitignore` line: `.claude/autonomy/**/*.local.*`. Layers resolve user-global → project → local overlay, additively. From 057fcef60f5a692bfa264316e5603977d0f1a33c Mon Sep 17 00:00:00 2001 From: Kyle Sexton <153232337+kyle-sexton@users.noreply.github.com> Date: Sat, 18 Jul 2026 11:58:04 -0400 Subject: [PATCH 11/14] fix(autonomy): check eval covers the org rung The check eval only asserted the three local layers, so an implementation omitting the promised org-binding fetch would stay green; it now requires the org rung when a pointer exists and the not-considered warning on fetch failure. Co-Authored-By: Claude Fable 5 (1M context) --- plugins/autonomy/skills/setup/evals/evals.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/plugins/autonomy/skills/setup/evals/evals.json b/plugins/autonomy/skills/setup/evals/evals.json index 5c7789082..26aed554f 100644 --- a/plugins/autonomy/skills/setup/evals/evals.json +++ b/plugins/autonomy/skills/setup/evals/evals.json @@ -44,13 +44,13 @@ "id": 4, "name": "check-is-read-only-across-layers", "prompt": "/autonomy:setup check", - "expected_output": "Resolves the effective binding additively across user-global, project, and local overlay layers, reports which layer contributes each value and what is missing, warns when a layer could not be read, and performs no writes of any kind.", + "expected_output": "Resolves the effective binding additively across every rung of the ladder: user-global, project, and local overlay layers, PLUS the org layer when the merged layers carry an org_policy_home pointer (fetched via the host CLI with the consumer's own auth). Reports which layer or rung contributes each value and what is missing, warns when a layer or the org-policy home could not be read (not-considered, never silently omitted), and performs no writes of any kind.", "files": [], "expectations": [ "No file writes in check mode", - "Reports per-layer contributions (user-global, project, local overlay)", - "Names missing binding values rather than silently defaulting them", - "Warns when a layer exists but could not be read" + "Reports per-layer contributions (user-global, org rung when pointed, project, local overlay)", + "Fetches and folds in the org binding when an org_policy_home pointer exists", + "Warns when a layer or the org-policy home exists but could not be read, never silently omitting it" ] }, { From 9fa88cdd3f1bfa0c8acf803a6defd179269a3afd Mon Sep 17 00:00:00 2001 From: Kyle Sexton <153232337+kyle-sexton@users.noreply.github.com> Date: Sat, 18 Jul 2026 12:19:03 -0400 Subject: [PATCH 12/14] fix(autonomy): layer summary includes the org rung Co-Authored-By: Claude Fable 5 (1M context) --- plugins/autonomy/skills/setup/SKILL.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/autonomy/skills/setup/SKILL.md b/plugins/autonomy/skills/setup/SKILL.md index a6e71071d..ac366a417 100644 --- a/plugins/autonomy/skills/setup/SKILL.md +++ b/plugins/autonomy/skills/setup/SKILL.md @@ -66,8 +66,8 @@ the role→instance map (a role MAY be null — unborn, or no org instance; neve the `org_policy_home` pointer (or `null`) with its resolved document path when discovered, `budget_posture`, and declared substrate. The file is tracked (team-shared); personal overrides go in `.claude/autonomy/binding.local.json`. Recommend the consumer `.gitignore` line: -`.claude/autonomy/**/*.local.*`. Layers resolve user-global → project → local overlay, -additively. +`.claude/autonomy/**/*.local.*`. Layers resolve per the binding-seam ladder — +user-global → org binding (when pointed) → project → local overlay — additively. ## What this skill does NOT do From 5a168c1858641479bcdd304674b730c082274e5e Mon Sep 17 00:00:00 2001 From: Kyle Sexton <153232337+kyle-sexton@users.noreply.github.com> Date: Sat, 18 Jul 2026 12:52:46 -0400 Subject: [PATCH 13/14] fix(autonomy): align purpose sentence and README with the four-layer ladder Co-Authored-By: Claude Fable 5 (1M context) --- plugins/autonomy/README.md | 5 +++-- plugins/autonomy/skills/setup/SKILL.md | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/plugins/autonomy/README.md b/plugins/autonomy/README.md index 051618626..0f13af1de 100644 --- a/plugins/autonomy/README.md +++ b/plugins/autonomy/README.md @@ -39,5 +39,6 @@ locked (no step-skipping — trust before scale). Setup writes tracked config to `.claude/autonomy/` in the consuming repo (concern-named — the config outlives any plugin restructure). Personal overlays follow the marketplace overlay -convention: `.claude/autonomy/**/*.local.*` stays gitignored; layers resolve -user-global → project → local overlay, additively. +convention: `.claude/autonomy/**/*.local.*` stays gitignored; layers resolve per the +binding-seam ladder — user-global → org binding (when pointed) → project → local overlay — +additively. diff --git a/plugins/autonomy/skills/setup/SKILL.md b/plugins/autonomy/skills/setup/SKILL.md index ac366a417..58006e95f 100644 --- a/plugins/autonomy/skills/setup/SKILL.md +++ b/plugins/autonomy/skills/setup/SKILL.md @@ -11,7 +11,7 @@ disable-model-invocation: true Discovery phase of autonomy adoption (v0). Maps the roles in [`${CLAUDE_PLUGIN_ROOT}/reference/role-topology.md`](${CLAUDE_PLUGIN_ROOT}/reference/role-topology.md) to this org's real instances and records the result as the schema-versioned binding the resolution ladder in -[`${CLAUDE_PLUGIN_ROOT}/reference/binding-seam.md`](${CLAUDE_PLUGIN_ROOT}/reference/binding-seam.md) reads at rung 1. Never assumes +[`${CLAUDE_PLUGIN_ROOT}/reference/binding-seam.md`](${CLAUDE_PLUGIN_ROOT}/reference/binding-seam.md) reads at the repo-local layer. Never assumes any org, repo, tracker, or fleet shape — discovery reads what exists, the interview fills what it cannot infer, and every landed change is reviewable per [`${CLAUDE_PLUGIN_ROOT}/reference/wiring-vs-advisor.md`](${CLAUDE_PLUGIN_ROOT}/reference/wiring-vs-advisor.md). From 62f21bd0f132ec208d588420bd1a10d4e8e611f2 Mon Sep 17 00:00:00 2001 From: Kyle Sexton <153232337+kyle-sexton@users.noreply.github.com> Date: Sat, 18 Jul 2026 13:19:58 -0400 Subject: [PATCH 14/14] fix(autonomy): serialize binding keys + standardize per-layer file name The written-binding section now names the exact JSON keys (roles object keyed by the kebab-case topology role names, substrate surface keys, budget_posture values) and fixes binding.json / binding.local.json as the shape at every layer including user-global, so independent consumers serialize and resolve identically. Co-Authored-By: Claude Fable 5 (1M context) --- plugins/autonomy/skills/setup/SKILL.md | 27 +++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/plugins/autonomy/skills/setup/SKILL.md b/plugins/autonomy/skills/setup/SKILL.md index 58006e95f..52ee19d12 100644 --- a/plugins/autonomy/skills/setup/SKILL.md +++ b/plugins/autonomy/skills/setup/SKILL.md @@ -61,13 +61,26 @@ ask and offer to persist; otherwise → safe free-tier default). ## Written binding -`apply` writes `.claude/autonomy/binding.json`, carrying `schema_version` (from `"1.0"`), -the role→instance map (a role MAY be null — unborn, or no org instance; never invented), -the `org_policy_home` pointer (or `null`) with its resolved document path when discovered, -`budget_posture`, and declared substrate. The file is tracked (team-shared); personal overrides go in -`.claude/autonomy/binding.local.json`. Recommend the consumer `.gitignore` line: -`.claude/autonomy/**/*.local.*`. Layers resolve per the binding-seam ladder — -user-global → org binding (when pointed) → project → local overlay — additively. +`apply` writes `.claude/autonomy/binding.json` with these serialized keys: + +- `schema_version` (string, from `"1.0"`); +- `roles` — an object keyed by the kebab-case role names of the role-topology contract + (`capability-distribution-home`, `ci-orchestration-home`, `settings-as-code-home`, + `org-policy-home`, `runner-execution-home`); a value MAY be null (unborn role, or no org + instance — never invented); +- `org_policy_home` — the pointer (or `null`), with its resolved document path when + discovered; +- `budget_posture` — `free` | `paid-opt-in`; +- `substrate` — an object with kebab-case surface keys (`local-machine`, `ci-runners`, + `self-run-infrastructure`), boolean values. + +Capability slices add their own sections under their slice name. The same file name is the +shape at EVERY layer: the user-global layer is `~/.claude/autonomy/binding.json`, the project +layer `.claude/autonomy/binding.json`, and each layer's personal overlay +`binding.local.json` beside it. The project file is tracked (team-shared); recommend the +consumer `.gitignore` line: `.claude/autonomy/**/*.local.*`. Layers resolve per the +binding-seam ladder — user-global → org binding (when pointed) → project → local overlay — +additively. ## What this skill does NOT do