Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ user opts in with `/plugin enable`; an existing install is never flipped by cata

### Autonomy

- [`autonomy`](plugins/autonomy) — Governed autonomous agent operation: role-topology, binding-seam, wiring-vs-advisor, telemetry, and return-accounting contracts for climbing the AI-adoption ladder, plus a guided-setup skill that discovers an adopting org's state, writes its schema-versioned binding, wires standards-pinned OTLP emission with a zero-cost file-artifact default, and wires human-attested return capture at the task boundary.
- [`autonomy`](plugins/autonomy) — Governed autonomous agent operation: role-topology, binding-seam, wiring-vs-advisor, telemetry, return-accounting, and trigger-dispatch contracts for climbing the AI-adoption ladder, plus a guided-setup skill that discovers an adopting org's state, writes its schema-versioned binding, wires standards-pinned OTLP emission with a zero-cost file-artifact default, wires human-attested return capture at the task boundary, and wires signal adapters with one governed dispatch entrypoint.

### Security

Expand Down
8 changes: 4 additions & 4 deletions docs/topics/ai-ladder-wp4-trigger-dispatch/PLAN.md
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ admission binding exists (absent policy → every dispatch human-gated), and WP5
policy surface that relaxes it — no dead link in either direction, no dispatch window ever
runs ungoverned.

### Phase 1: Trigger-dispatch contract doc [TODO]
### Phase 1: Trigger-dispatch contract doc [DONE]

| File | Action | What changes |
|---|---|---|
Expand All @@ -126,7 +126,7 @@ runs ungoverned.
- Vendor+fleet deny-list grep empty over the doc (`node scripts/validate-plugin-contracts.mjs` exit 0)
- lychee lane passes

### Phase 2: Guided-setup trigger/dispatch slice [TODO]
### Phase 2: Guided-setup trigger/dispatch slice [DONE]

Extends the `setup` skill (discovery-first per D7/WP1 D7). First work item — fresh-docs
mandate (repo CLAUDE.md): re-fetch the official docs for any vendor surface the slice names
Expand All @@ -150,7 +150,7 @@ mandate (repo CLAUDE.md): re-fetch the official docs for any vendor surface the
- `node plugins/autonomy/skills/setup/scripts/check-signal-envelope.mjs` (no args) exits 2 with usage
- Fleet-name sweep (`validate-plugin-contracts.mjs`) exit 0

### Phase 3: Conforming-path demonstration [TODO]
### Phase 3: Conforming-path demonstration [DONE]

Acceptance probe on a scratch consumer repo (NOT this repo, WP2 Phase 3 precedent — the ban
there is on FLEET bindings/plugins, not on composing a sibling CAPABILITY: the scratch repo
Expand All @@ -174,7 +174,7 @@ binding means no classification rules, so the item carries no `signal.work_class
- No second dispatch path exercised anywhere in the demo; no paid service touched
- Demo transcript attached to the PR body

### Phase 4: Gates [TODO]
### Phase 4: Gates [DONE]

Full in-repo gate run (WP2 Phase 4 roster): `scripts/validate-plugins.sh`,
`scripts/run-plugin-tests.sh`, `node scripts/validate-plugin-contracts.mjs`, markdown/typos/
Expand Down
4 changes: 2 additions & 2 deletions plugins/autonomy/.claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
{
"$schema": "https://json.schemastore.org/claude-code-plugin-manifest.json",
"name": "autonomy",
"version": "0.3.0",
"description": "Governed autonomous agent operation: role-topology, binding-seam, wiring-vs-advisor, telemetry, and return-accounting contracts for climbing the AI-adoption ladder, plus a guided-setup skill that discovers an adopting org's state, writes its schema-versioned binding, wires standards-pinned OTLP emission with a zero-cost file-artifact default, and wires human-attested return capture at the task boundary.",
"version": "0.4.0",
"description": "Governed autonomous agent operation: role-topology, binding-seam, wiring-vs-advisor, telemetry, return-accounting, and trigger-dispatch contracts for climbing the AI-adoption ladder, plus a guided-setup skill that discovers an adopting org's state, writes its schema-versioned binding, wires standards-pinned OTLP emission with a zero-cost file-artifact default, wires human-attested return capture at the task boundary, and wires signal adapters with one governed dispatch entrypoint.",
"author": {
"name": "Melodic Software",
"email": "info@melodicsoftware.com"
Expand Down
10 changes: 8 additions & 2 deletions plugins/autonomy/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ AI-adoption-ladder contract set: it ships the tool-agnostic contracts an adoptin
its own repositories, tools, and policies, plus a guided-setup skill that discovers the org's
state and records that binding.

## Shipped capability (0.3.0)
## Shipped capability (0.4.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
Expand All @@ -19,6 +19,12 @@ state and records that binding.
autonomous-class work, joinable to cost telemetry by the join attribute — plus the setup
capture slice and its close-boundary templates. Agents prompt and aggregate; they never
estimate the human fields.
- **Trigger-dispatch contract** (`reference/trigger-dispatch.md`): four signal-surface
classes normalized by adapters into the governed work-item queue under six class-generic
obligations, a schema-versioned signal envelope, security-surface work-class stamping, and
one dispatch entrypoint (push kick + scheduled drain through the queue seam's race-safe
lease) — plus the setup trigger/dispatch slice, its adapter and acknowledgment templates,
and the signal-envelope conformance check.
- **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.
Expand All @@ -30,7 +36,7 @@ locked (no step-skipping — trust before scale).

| Capability | Trigger |
|---|---|
| Trigger/dispatch adapters | Trigger-layer work package build lands. |
| Fleet adapter materializations (reusable workflows, labels, drain routine) | Work-item backlog, post trigger-package graduation. |
| 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). |
Expand Down
161 changes: 161 additions & 0 deletions plugins/autonomy/reference/trigger-dispatch.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
# Trigger dispatch

Normative contract for signal adapters and autonomous dispatch: adapters normalize signals
from four surface classes into the governed work-item queue; one dispatch entrypoint drains
it; the executor is swappable behind the invocation-adapter seam. The contract fixes
vocabulary, obligations, and invariants; every concrete instance (which surfaces exist,
which tracker holds the queue, where the executor runs) is an org-binding outcome.

## Signal-surface classes

Four classes, ALL contract-active. Per-org availability is a binding outcome — a surface the
org lacks, or an entitlement gap on a surface it has, routes to the advisory path; it is
never a contract deferral.

| Class token | Surface |
|---|---|
| `tracker-vcs-event` | Tracker/VCS-host events: label applied, assignment, @-mention, PR event |
| `temporal` | Schedules and poll-fallback detectors for push-less surfaces |
| `agent-internal` | A session emits follow-up work while executing |
| `channel-feed` | Chat mention and continuous channel/data-feed monitoring |

Carried research gaps, stated in surface-class vocabulary (vendor specifics live in the
setup skill, never here): whether a channel-monitor may ambiently INITIATE work versus only
notify is UNVERIFIED; the channel-agent surfaces this class relies on are alpha/beta moving
targets; one major chat platform has no first-party trigger (UNVERIFIED-absence — re-verify
at wire time).

## Recorded signal attributes

Two attributes are recorded on every queued signal:

- **Initiator provenance** — `human` | `agent` | `system`. Audit data and guardrail-matrix
input; recorded, never trusted as an isolation axis (provenance is claimable; isolation
decisions key on the work class and surface verdicts, not on who claims to have asked).
- **Transport** — `push` | `push-lifecycle` | `poll`. Push preferred where the surface
offers it; poll is the universal fallback via the `temporal` class. `push-lifecycle`
carries subscription obligations: expiry tracking, renewal, and the platform's validation
handshake. Expiry semantics are normative: every `push-lifecycle` wiring is backed by a
`temporal` poll-detector backstop for the same surface, or the subscription-health lapse
fail-closes — it files a human-gated alert item — so a lapsed subscription can never
silently drop signals.

## Adapter obligations

Six class-generic obligations bind every adapter:

1. **Normalize and enqueue only.** An adapter never executes work and never bypasses the
queue. No second path from signal to execution exists.
2. **Idempotent dedup**, keyed on `signal.identity`. The identity is the surface-native
unique event id where the surface issues one. The FALLBACK identity is never a bare
content hash: it composes source scope (surface class + origin locator) + an
event-instance discriminator (delivery id or event timestamp) + the content hash, so two
legitimate repeated signals with identical payloads stay distinct instances. State-based
poll detectors that re-observe a continuing condition have no instance identity; their
dedup retention is BOUNDED to items still open — the same finding may re-enqueue once its
prior item closes (a re-detected regression is a new signal). Enforcement is not a bare
read-then-write: concurrent at-least-once deliveries can both pass a search before either
item exists, so the adapter uses an atomic identity-keyed create/upsert or queue-side
uniqueness guarantee where the tracker offers one; otherwise search-before-create is
backed by create-then-reconcile — after creating, re-search by `signal.identity` and, on
finding an older item with the same identity, close the newer one as an audited duplicate
(oldest wins, deterministically). A drain-side guard scoped to LIVE duplicates completes
the defense: the drain never claims an item whose `signal.identity` matches another
currently-open item, while completed items are excluded from the guard so re-detections
execute.
3. **Provenance capture and a durable raw-signal link** (`signal.raw_link`) on the item.
4. **Trace-context propagation.** The adapter injects `signal.traceparent` so the telemetry
contract's causal tree spans trigger → CI → agent session.
5. **Admission enforcement at the seam.** Admission-policy CONTENT is owned by the guardrail
matrix and bound on the org's security governance surface; the adapter ENFORCES it,
never defines it. An unadmitted signal becomes a human-gated item or an audited
rejection — never a silent drop. An ABSENT admission binding fail-closes: everything
enqueues human-gated.
6. **Closed-loop acknowledgment.** Bidirectional surfaces echo the queued item reference
back to the source (tracker comment, chat thread reply); reply-less surfaces satisfy the
obligation through `signal.raw_link` alone.

## Work-class classification

Admission and the whole guardrail matrix key on the risk class (`C1`–`C5`), so a queued item
needs one. The adapter STAMPS `signal.work_class` from the classification rules on the org's
SECURITY governance surface — the adapter stamps, never defines, and no repo-local
(agent-writable) surface may supply the class used for admission:

- `tracker-vcs-event` resolves through the security-bound label→class rules.
- `temporal` signals carry the class their bound routine/detector definition derives.
- `agent-internal` items must PROVE protected provenance: the envelope serializes the
emitting session's own admitted source item as `signal.parent_item`, and the admission
seam verifies the session-to-parent association against protected dispatch data — the
queue's own lease record of which item the emitting session was dispatched on. An
agent-supplied URL alone proves nothing (any session could cite an unrelated low-class
item to launder higher-risk follow-up work); an association the seam cannot verify is NO
provenance. Admission then resolves the verified parent's class from its own protected
classification rather than trusting the stamped value: the effective class is the HIGHER
of the inherited class and the class the security-surface rules derive for the target.
- `channel-feed`, and any signal the rules cannot resolve, stays UNCLASSIFIED.

Unclassified → fail-closed human-gated, always.

## Signal envelope

Serialization is a JSON-fenced marker record on the queued item (the return-accounting
convention's marker-record precedent): the marker `<!-- autonomy:signal:v1 -->` plus one
fenced JSON block holding the record, written by the adapter at enqueue. `schema_version`
starts at `"1.0"` with additive evolution under the same reviewed-migration governance as
every contract schema. Keys:

| Key | Value |
|---|---|
| `signal.class` | surface-class token |
| `signal.transport` | `push` \| `push-lifecycle` \| `poll` |
| `signal.provenance` | `human` \| `agent` \| `system` |
| `signal.identity` | dedup identity per obligation 2 |
| `signal.raw_link` | durable absolute reference to the source event; form branched by origin — web-origin signals carry an absolute https URL with query and fragment PRESERVED (the telemetry contract's strip rule applies only to the work-item join key); a temporal signal from a local-scheduler surface may carry a durable local/artifact URI (absolute `file:` URI or org artifact-store locator); relative or ephemeral references conform on no branch |
| `signal.traceparent` | W3C trace context from the trigger hop |
| `signal.work_class` | optional; the stamped risk class per the classification rules — absent = unclassified = human-gated |
| `signal.parent_item` | REQUIRED when `signal.class` is `agent-internal`: canonical URL of the emitting session's admitted source item, verified against the queue's lease record |
| `signal.source_surface` | REQUIRED when `signal.class` is `temporal`: the originating scheduling surface's id as recorded in the org's trigger/routine binding — the discriminator raw-link form validation branches on |

## Dispatch

Push kick where the platform offers it (an event-fired job on enqueue) plus a standing
scheduled drain as the universal fallback and catch-up net for ENQUEUED items. The drain's
default cadence is hourly (org-bindable); the drain never re-scans a source surface —
missed enqueues are the poll-detector backstop's job.

**One-entrypoint invariant.** Every kick funnels into the work-item queue capability's
existing autonomous drain mode via the invocation-adapter seam. The seam's race-safe lease
makes concurrent kicks harmless. No second claim or dispatch mechanism exists anywhere.

**Execution-surface attestation.** Every kick/drain wiring records its named execution
surface, but the recorded id is repo-local convenience only: the admission/executor seam
derives the ACTUAL execution-surface identity from trusted dispatch/runner context —
platform-attested runtime metadata matched against the per-surface identifying markers the
security binding's isolation entries declare — and verifies it against the recorded id,
consulting the ACTUAL surface's isolation verdict. A mismatch, an unattestable actual
surface, or a surface without the required isolation binding each fail-close to
human-gated; rewriting the recorded id cannot launder execution onto an unbound runner.

Concurrency and per-run item caps are guardrail-policy knobs: this contract names them
descriptively; their serialized tokens (`autonomous_concurrency`, `items_per_run`) are
owned by the admission policy on the security surface.

## Executor surface classes

Two classes, imported unchanged from the runner charter: **self-operated** CLI/SDK
executors — including SDK-embedded pull/drain daemons — and **vendor-hosted** executors,
whose merge policy caps at human-gated. The executor-class determination that gates merge
policy is SECURITY-surface data (the security binding's `executor_class`), never a
repo-local value. Other executor hosting configuration is deployment-owned per the hosting
stance: this contract fixes only the isolation floor (L2+ for unattended execution),
credential scoping, and the queue contract.

## Constraints

- No queue bypass, no second dispatch mechanism, no second claim path.
- The contract never invents an event bus and never raises domain events; the adopting
org's own systems own event definition and raising.
- No new cost by default: paid surfaces are advisory with cost surfaced, explicit opt-in.
- Vendor and fleet names never appear in this contract's normative text; mechanisms are
named as classes with vendor specifics in binding docs and the setup skill.
Loading
Loading