Skip to content

Latest commit

 

History

History
113 lines (98 loc) · 7.05 KB

File metadata and controls

113 lines (98 loc) · 7.05 KB

ACE Extension API — stability contract

Applies to: the ace.extensions plugin layer (core/engine/extensions/). Versioning: the extension API version IS the kernel version (SemVer). Breaking changes to any Stable surface happen only on a kernel MAJOR release, with migration notes in the changelog. Experimental surfaces may change on MINOR releases.

Stable

Surface Contract
Entry-point group ace.extensions Permanent. name = "pkg.module:ExtensionClass" per extension.
Extension protocol name: str, version: str, register(reg: Registry) -> None.
Registry.register_instrument(slug, module_path) Contribute an instrument.
Registry.register_recipe(...) Contribute a recipe + its discipline/task-type routing.
Registry.register_committee(name, builder) Contribute a committee builder.
Registry.register_personas(personas) Contribute personas.
Registry.register_frameworks(frameworks) Contribute frameworks.
Registry.register_tool(fn, *, title=None) Contribute an MCP tool.
Registry.register_schema(surql_path) Contribute a SurrealQL schema the extension migrator applies.
load_extensions() semantics Idempotent; a broken extension is logged and skipped, never fatal.
ACE_DISABLE_EXTENSIONS=1 Kill switch: boot the naked kernel (process-lifetime).

Exact signatures live in core/engine/extensions/registry.py — the table names the commitment; the source names the types.

Experimental

  • Registry.register_task_action(...) — register extension-owned structured context preparation and optional outcome projection on Core's durable task lifecycle. The public wire contracts are extension-invocation-v1 and extension-invocation-receipt-v1; interrupted execution resumes as a linked successor attempt, never a fictitious continuation of a lost provider stream. See the experimental invocation contract for wire fields, authority, failure behavior, restart evidence, and limitations. Registration returns the experimental RegisteredTaskAction handle used by run_task_action_conformance(...); ignoring the return remains valid.
  • Registry.register_sentinel(...) — sentinel engine contribution.
  • Registry.register_briefing_section(...) — briefing composition hooks.
  • Registry.register_grounded_state_adapter(name, adapter) — register a bounded, provider-neutral source-extraction mapper. The adapter may propose domain records and entity-resolution bindings, but it never receives a persistence handle: Core injects product scope, derives identity and hashes, validates temporal/lifecycle semantics, writes the append-only substrate, and owns per-item and batch receipts. The adapter must expose build_manifest(...). The 0.3.x Productized State candidate makes this mapping reachable through authenticated GET /product-state/capabilities and POST /product-state/ingestions; neither endpoint accepts a caller product identifier. The registration hook remains experimental until the candidate is published and its compatibility policy is finalized.
  • Canvas extension wiring (core/ui/canvas/src/app/ext/).
  • ACE_EXTENSIONS dev-list loading (unpackaged local extensions).

What belongs in an extension

Would it be useless to a different domain? Then it is extension config, not kernel. The dependency direction is one-way — extensions import core; core never imports extensions (enforced by tests/test_kernel_boundary.py).

For task actions, that rule means Core owns authentication, product/user scope, workspace-claim enforcement, contract negotiation, idempotency, task persistence, provider execution, attempt lineage, cancellation state, and receipt normalization. The extension owns reference resolution, domain authorization, prompt preparation, artifact creation, and domain outcome projection. A resolver must report each reference as resolved, declared, missing, or rejected; carrying an identifier into a prompt is not reported as retrieval. resolved requires matching private context content plus immutable version, hash, resolver, and product-scope evidence. Projected recommendations remain separate from human decisions and later adoption.

For grounded-state ingestion, extensions own source parsing, domain extraction, raw surface forms, and optional resolution proposals. Core owns the canonical product boundary, record identity, exact idempotency, timestamps, correction and supersession lineage, storage, replay, isolation, and receipts. Extensions must not write source claims through observation or insight, and ingestion adapters must not require a primary-model call per record. The shipped extensions/reference/grounded_state_adapter.py is a fixture-backed OLC-style example; it is not a claim that the full OLC corpus is import-ready.

For TP6 reasoning, the shipped reference extension also registers the experimental evidence-query task action. Authenticated Core actor context supplies product, workspace, user, invocation, and authorization scope; caller parameters cannot override product identity. The action uses Core's TP3/TP4 resolver to return one bounded ResolvedContextRecord with immutable context-pack version/hash and product scope. Retrieved text is enclosed as untrusted evidence data and receives no task, system, tool, secret, mutation, or scope authority. The action uses the existing durable task/status lifecycle and adds no MCP tool or public endpoint.

The experimental capability manifest negotiates accepted input versions, one output version, lifecycle operations, cancellation support, resolver/artifact capabilities, required authorities, and feature flags. Discovery is deterministic, bounded to 200 actions, and rejects exact duplicate registrations. The registration store uses the (extension_id, action_name) pair directly, so delimiter characters cannot collapse two distinct identities. Invalid identifiers, empty required lists, duplicate list values, and cancellation without the cancel lifecycle operation are rejected before discovery. The 200-action limit is enforced at registration and defensively at discovery. Manifests are sorted by the identity pair and never serialize preparation, resolver, projector, or validator callables. Machine-readable schemas are available from authenticated GET /extension-invocations/schemas.

The candidate Python SDK surface for task actions is exported from core.engine.extensions: Registry, RegisteredTaskAction, ExtensionCapabilityManifest, ExtensionInvocationEnvelope, ExtensionActorContext, ExtensionReference, ContextResolution, ResolvedContextRecord, ExtensionTaskPlan, ExtensionOutcome, ExtensionArtifactProvenance, ExtensionInvocationReceipt, and run_task_action_conformance. The entire task-action surface remains experimental.

Starting point

Run python -m scripts.scaffold_extension <your_domain> (see Build your first extension) — it copies the shipped reference extension (extensions/reference/), so the template can never drift from the worked example.