Help us shape the future of Go! Take the 2026 Go Developer Survey

capability

package
v1.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 12, 2026 License: Apache-2.0 Imports: 18 Imported by: 0

Documentation

Overview

Package capability holds the built-in admission rules (the pure leaf): given an Event + Projection it returns a RuleDecision, never writing. It imports rule/projection/contract only — binding->rule translation and runtime wiring live in app. Memory + skill are the two P0 capabilities.

Index

Constants

View Source
const (
	BudgetWarmItems   = 8
	BudgetDigestItems = 1
)

Budget item caps per tier (P4b). REDUCER-FREE by construction: a tier bounds the COUNT of items the local mirror renders (most-recent-first), never a model summary (which would be a reducer — out of scope / B1, the no-remote-reducer entry decision). "digest-only" is therefore the minimal recent-context tier (the single latest item), "warm" a bounded recent window, "hot" the full set. A true semantic-summary digest is a sync-abi-v2 / reducer concern, deliberately deferred.

View Source
const (
	MemoryWriteCandidateObserved = "memory.write_candidate.observed"
	MemoryWriteProposed          = "memory.write.proposed"
)
View Source
const (
	SkillWriteCandidateObserved = "skill.write_candidate.observed"
	SkillWriteProposed          = "skill.write.proposed"
)
View Source
const SyncImportSkippedObserved = "sync.import_skipped.observed"

SyncImportSkippedObserved is the observation a sync puller ingests for a pulled commit whose resource kind has no import mapping (v1.1 #4): instead of a silent continue, the skip enters the canonical log exactly-once (ExternalID = the six-part pull key + ":skipped") and the deny rule below turns it into a durable sync.diagnostic via the existing pre-gate. Payload: {kind, origin_replica_id, local_decision_id, remote_id}.

Variables

This section is empty.

Functions

func EmbeddedCatalog

func EmbeddedCatalog() map[string]Capability

EmbeddedCatalog returns the first-party capability catalog: the embedded half of ResolveCatalog and the backward-compatible default when no resolved catalog is supplied.

func ImportableKinds

func ImportableKinds(catalog map[string]Capability) []contract.ResourceKind

ImportableKinds returns the resource kinds the catalog imports from Remote Workspace pulls, sorted — the descriptor-derived syncable-kind set (PD6).

func LoadExternal

func LoadExternal(fsys fs.FS, requiredFields map[contract.ResourceKind][]string) (map[string]Capability, error)

LoadExternal compiles every external capability package under fsys. Each TOP-LEVEL directory is one package — `<name>/capability.json` in capability-spec-v1 form, strict-decoded through the same decodeSpec + FromSpec machinery the embedded loader uses — loaded in lexicographic package order (deterministic). Non-directory top-level entries (stray files, .DS_Store) are not packages and are ignored.

fs.ErrNotExist on the root listing is the NORMAL pre-stage-5 install: empty catalog, never an error — a missing .mnemon/loops must not break a single existing installation.

Everything else fails closed with the package path in the message: ① bad JSON / trailing garbage / unknown JSON keys (decodeSpec); ② unknown spec vocabulary and ③ a resource kind outside contract.KindCatalog (FromSpec); ⑥ any hooks/ or skills/ presence (no host projection assets in v1 — deliberately WIDER than loop-package-v1's minimum obligation); ⑦ statically derived header keys that cannot satisfy requiredFields (the kernel SchemaGuard lockstep, at LOAD time); ⑧ unsafe spec surfaces, external only, in two halves — VALUES are scanned (scanExternalSpecText), IDENTIFIERS are pattern-locked (checkExternalSpecIdentifiers); ⑨ directory ≠ name ≠ kind or an off-pattern directory name; ⑪ a kernel-internal reserved kind (externalReservedKinds). Classes ④⑤ (shadowing/dups beyond one package) are enforced by the shared specRegistry here and the four-axis merge in ResolveCatalog; class ⑩ (symlinks) needs the real OS path — fs.FS has no lstat — and lives in ResolveCatalog's screening.

func RemoteCommitEventType

func RemoteCommitEventType(catalog map[string]Capability, kind contract.ResourceKind) (string, bool)

RemoteCommitEventType returns the import observation event type for a pulled commit kind when the catalog imports that kind — the descriptor-derived replacement for the hardcoded kind→type switch.

func RemoteImportRule

func RemoteImportRule(cap Capability, principal contract.ActorID) (rule.Rule, bool)

RemoteImportRule builds the remote-import admission rule for one importable capability and the sync import principal: it observes the capability's system-derived <kind>.remote_commit.observed event and dispatches to the capability's declared (closed-set) merge strategy. Returns ok=false when the capability is not importable (the caller skips it).

func RemoteImportRules

func RemoteImportRules(catalog map[string]Capability, principal contract.ActorID) []rule.Rule

RemoteImportRules builds the remote-import rules for every importable capability in the catalog, sorted by kind for determinism — the descriptor-derived replacement for the hardcoded memory/skill import-rule list (PD6).

func ResolveCatalog

func ResolveCatalog(projectRoot string, requiredFields map[contract.ResourceKind][]string) (map[string]Capability, error)

ResolveCatalog builds the boot capability catalog: the embedded Builtins plus every external capability package under <projectRoot>/.mnemon/loops — the ONLY external root in v1. It is the one production entry point: symlink screening on the real path (class ⑩), LoadExternal over os.DirFS, then a merge with FOUR-axis shadowing rejection (name, observed type, proposed type, resource kind) — an external package may never shadow an embedded capability, and two externals may not share a kind. A missing .mnemon/loops resolves to the embedded catalog.

func RiskEvidenceGate

func RiskEvidenceGate(cap Capability, principal contract.ActorID) rule.Rule

RiskEvidenceGate is the mid-risk governance gate (P3 three-tier risk): a candidate for this capability's kind must carry a non-empty `evidence` field, else it is DENIED with a durable diagnostic. It is a SEPARATE rule that handles the same observed type as the admission rule; when it denies, rule.Evaluate's deny-priority reduction makes the deny outrank the admission rule's propose, so the write is refused — no new kernel verdict or held state (M1 review correction). It gates on the cap's principal (a foreign principal's event passes through) and emits no proposal.

High-risk (operator-only) gating is deferred to P3e, where its consumer (the high-risk loopdef kind) and its principal model (the human@owner operator binding, G9) are designed together — a high-risk gate without an operator principal to exempt would make a kind ungovernable.

func RiskOperatorGate

func RiskOperatorGate(cap Capability, principal contract.ActorID) rule.Rule

RiskOperatorGate is the high-risk governance gate (P3e): it DENIES the gated principal's candidate with a durable diagnostic — the agent's high-risk proposal lands in the Inbox, and a human/operator (a control-agent principal) re-submits the same candidate through the normal admission path. The assembler builds this gate ONLY for NON-operator (host-agent) principals, so the operator's own high-risk candidate is never gated. Like the evidence gate, the deny outranks the admission propose (rule.Evaluate is deny-priority) — no new kernel verdict or held state (the M1 correction).

func ShapeByBudget

func ShapeByBudget(cap Capability, fields map[string]any, tier contract.BudgetTier) map[string]any

ShapeByBudget returns the resource fields shaped for a context-budget tier: it keeps only the most-recent K items (K per tier; hot = all) and RE-RENDERS the capability's header over the kept subset, so a content-rendered surface — e.g. the memory mirror, which reads the rendered `content` field, not the raw item list — actually shrinks. "Most-recent" = the tail of the item list, whose order is the local append/import sequence (replica-deterministic, so an offline replay reshapes identically — B6). Non-item kinds, an unknown tier, and an already-within-budget set are returned UNCHANGED (exact passthrough preserves updated_by and any header the writer set; unknown fails open to hot — never silently drops data, the closed-set guard lives at config time in ResolveBudgetTier).

This is a pure LOCAL presentation transform: it never reduces on the hub and never alters authority (the grant scope is the security boundary — budget bounds CONTEXT only; B2 remote settles, local decides).

func SyncImportSkippedRule

func SyncImportSkippedRule(principal contract.ActorID) rule.Rule

SyncImportSkippedRule is the legal diagnostic mechanism for skipped kinds: it Handles ONLY the skipped observation, gates on the sync import principal (foreign events pass through), and always denies with a reason naming the kind — the deny is what produces the durable *.diagnostic (S7); no write, no proposal.

Types

type Capability

type Capability struct {
	Name         string
	ObservedType string
	ProposedType string
	ResourceKind contract.ResourceKind
	ItemsField   string // resource field holding the item list
	Decode       func(payload map[string]any) (Item, error)
	Header       func(items []Item) map[string]any // resource fields besides the item list + updated_by
	// RequiredHeader is the kind's kernel-required header fields, derived from the spec (the
	// render-produced keys, or the declared `required` subset). The assembler reads it to build the
	// assembly-time SchemaGuard so a declared kind's required set has ONE source — the capability.
	RequiredHeader []string
	// Sync, when Importable, opts the kind into Remote Workspace import under the named (closed-set)
	// merge strategy. The sync-import path derives its rules and syncable-kind set from this, so the
	// importable kinds are no longer a hardcoded list (PD6).
	Sync SyncOptions
	// DefaultEnabled opts the kind into governance on every local boot without an explicit --loop
	// (P3 coordination package). The app boot grants it to every host-agent principal.
	DefaultEnabled bool
	// Risk is the kind's governance risk tier ("low"|"mid"|"high"; P3). The assembler builds the
	// matching risk-gate rule per binding (mid = evidence required; high = operator-only).
	Risk   string
	Limits Limits
}

Capability is the built-in descriptor that turns config selection into one compiled rule kind. ALL built-in capabilities admit a candidate through the SAME generic append-item-to-resource rule (appendItemRule); they differ only by DATA — the observed/proposed types, the resource kind, the item-list field, how a payload decodes to an Item, and the resource "header" fields a write carries (e.g. memory's rendered content, skill's name). A new capability is a new descriptor + config, not new rule code.

func FromSpec

func FromSpec(spec CapabilitySpec) (Capability, error)

FromSpec compiles a CapabilitySpec into a Capability, fail-closed on everything the spec gets wrong: unknown/missing core fields, a resource kind outside contract.KindCatalog, duplicate field names, unknown validator/render members, bad or extra member params, forward default-from references, list:strings sharing a field with other validators, and render keys colliding with the reserved items/updated_by keys.

The compiled Decode contract (parity-frozen, capability spec v1):

  • ONLY declared fields are processed; payload keys outside the declared set NEVER enter the Item (no leakage into governed state).
  • For each string field, in declaration order: raw = strings.TrimSpace(stringField(payload, name)); validators run in declared order against the processed value, first error rejects; the processed (trimmed/defaulted) value is what lands in the Item — and EVERY declared string field emits its key (possibly ""), matching the handwritten decoders.
  • list:strings is the one exception: it uses stringSliceField's full semantics ([]string / []any dropping non-strings / comma-separated string; trimmed, empties compacted) and OMITS the key when the list is empty.
  • Deny messages are protocol surface: "<name> candidate denied: <member message>".

func (Capability) RemoteCommitObserved

func (c Capability) RemoteCommitObserved() string

RemoteCommitObserved is the event type the platform mints for a pulled remote commit of this kind (the system-derived sync-import observation form, capability-spec v2 grammar). The import rule observes it; the puller emits it.

func (Capability) Rule

func (c Capability) Rule(principal contract.ActorID, ref contract.ResourceRef, limits Limits) rule.Rule

Rule builds the capability's admission rule for one principal + resource ref. limits bounds the capability (MaxPayloadBytes; 0 = unbounded — the 1 MiB channel body cap still applies upstream) without changing the compiled kind.

Deviation from the locked Phase-2 signature Rule(..., cfg config.CapabilityConfig) (plan-control-plane.md:241): the same plan locks capability as a rule/projection/contract-only leaf (:51,:61); the leaf wins, and the assembler maps config.CapabilityConfig -> Limits.

type CapabilitySpec

type CapabilitySpec struct {
	SchemaVersion int         `json:"schema_version"` // capability spec v1
	Name          string      `json:"name"`
	ObservedType  string      `json:"observed_type"`
	ProposedType  string      `json:"proposed_type"`
	ResourceKind  string      `json:"resource_kind"`
	ItemsField    string      `json:"items_field"`
	Fields        []FieldSpec `json:"fields"`
	Render        RenderSpec  `json:"render"`
	// Required SELECTS the kind's kernel-required header fields from the render-produced keys
	// (capability-spec v2 §Declared kind). Omitted = every produced key is required; when present,
	// each entry must be a render-produced key (a kind cannot require a field its writes never carry).
	// It is the single source the assembly-time SchemaGuard derives a user kind's required set from.
	Required []string `json:"required,omitempty"`
	// Sync declares whether this capability's kind is imported from Remote Workspace pulls, and which
	// CLOSED merge strategy the import uses (capability-spec v2 §Sync). Omitted = not importable.
	Sync *SyncSpec `json:"sync,omitempty"`
	// DefaultEnabled opts the kind into governance on EVERY local boot, without an explicit `--loop`
	// (P3: the coordination package is on out of the box; memory/skill stay opt-in). The boot grants
	// every host-agent principal the kind's observe + scope, so a default-enabled kind is governable
	// from setup alone. Omitted = opt-in (enabled only when named in config.loops / a binding scope).
	DefaultEnabled bool `json:"default_enabled,omitempty"`
	// Risk is the kind's governance risk tier (P3, CLOSED set): "" / "low" = no gate; "mid" requires
	// the candidate to carry non-empty `evidence`; "high" requires an operator (control-agent)
	// principal — an agent's high-risk candidate is denied with a durable diagnostic (Inbox) and a
	// human re-submits. The tier maps to a generated risk-gate rule (define≠select), never a new
	// kernel verdict/state.
	Risk string `json:"risk,omitempty"`
}

CapabilitySpec is the DATA form of a built-in capability: what a capability author declares in assets/capabilities/<name>.json. FromSpec compiles it against the two CLOSED catalogs (validators, renders) — a spec can only SELECT compiled members, never define behavior (A3/I8); anything unknown fails closed.

func LoadSpec

func LoadSpec(fsys fs.FS, name string) (CapabilitySpec, error)

LoadSpec reads capabilities/<name>.json from fsys and strictly decodes it into its DATA form, for consumers that need the spec itself rather than the compiled Capability (e.g. the SKILL payload-contract generator). It goes through decodeSpec — the one fail-closed decode path — so there is no second, weaker decoding scheme to drift from it.

type ContentRender

type ContentRender struct {
	Member string            `json:"member"`
	Params map[string]string `json:"params,omitempty"`
}

type FieldSpec

type FieldSpec struct {
	Name       string         `json:"name"`
	Validators []ValidatorRef `json:"validators,omitempty"`
}

type Item

type Item map[string]any

Item is one decoded, validated candidate as a field map. The generic kind stamps id/actor/ingest_seq onto it and appends it to a resource's item list.

type Limits

type Limits struct {
	MaxPayloadBytes int
}

type RenderSpec

type RenderSpec struct {
	Content *ContentRender    `json:"content,omitempty"` // nil = no rendered content header
	Static  map[string]string `json:"static,omitempty"`  // literal header fields
}

type SyncOptions

type SyncOptions struct {
	Importable bool
	Merge      string
}

type SyncSpec

type SyncSpec struct {
	Importable bool   `json:"importable"`
	Merge      string `json:"merge"` // closed set: see syncMergeStrategies
}

SyncSpec is the sync-import descriptor: a kind opts into remote import (Importable) and selects a merge strategy from the CLOSED set. The strategies encapsulate the per-shape append/conflict logic; a kind SELECTS one, it never defines behavior (define≠select).

type ValidatorRef

type ValidatorRef struct {
	ID     string            `json:"id"`
	Params map[string]string `json:"params,omitempty"`
}

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL