Documentation
¶
Overview ¶
Package canon holds the declared command canon: the embedded side table that records what cobra cannot know about a command (canon status, side-effect class, output kind, JSON support, state exit codes and flag escalations).
Purpose: contract:cli.command-registry v1 input and producer of
contract:cli.canon-fragments v1. canon.yaml keeps the schema version and the core verbs; every command entry lives in domains/<domain>.yaml (one fragment per domain, ADR 0016).
Inputs: canon.yaml and domains/*.yaml compiled into the binary
(go:embed), an fs.FS (LoadFS, fixtures) or bytes (Parse).
Outputs: Load: the registry view for the running compat mode; LoadRaw: the
merged raw data (canonical paths plus the move rows); both validated. Tree-dependent rules (completeness, flag existence, targets) are checked by internal/cmdregistry.Build.
Constraints: stdlib + gopkg.in/yaml.v3 + internal/compat only (Constitution
2.1, L0). Decoding is strict: an unknown key is an error.
Index ¶
- Constants
- Variables
- func Depth(key string) int
- func NewValidationError(problems []string) error
- func Rank(sideEffect string) int
- func RenderGoTable(f *File) []byte
- func ValidCanon(s string) bool
- func ValidJSON(s string) bool
- func ValidOutput(s string) bool
- type Breakout
- type Confirm
- type Entry
- type File
- type FlagOverride
- type Fragment
- type Hub
- type PlanForm
- type Removed
- type Row
- type Rows
- type Table
- type TableRow
- type ValidationError
Constants ¶
const ( // CanonCore marks one of the ADR 0016 verbs. CanonCore = "core" // CanonSubcommand marks a command at depth >= 2 (the default there). CanonSubcommand = "subcommand" // CanonPlugin is reserved for plugin-mounted commands; no cobra-native // command may carry it. CanonPlugin = "plugin" // CanonShim marks a hidden alias kept for the deprecation window; its // Target names the canonical path. CanonShim = "deprecated-shim" // CanonPending marks a top-level command outside the canon whose // disposition P7-CANON decides. CanonPending = "pending" // CanonBuiltin marks framework-provided commands (help); not counted // against the canon. CanonBuiltin = "builtin" )
Canon status values (Epic P7-REG D4).
const ( SideEffectRead = "read" SideEffectWrite = "write" SideEffectRemote = "remote" SideEffectDestructive = "destructive" )
Side-effect classes (D5), in total order read < write < remote < destructive.
const ( OutputDocument = "document" OutputStream = "stream" OutputInteractive = "interactive" )
Output kinds (D6).
const ( JSONEnvelope = "envelope" JSONLegacy = "legacy" JSONNone = "none" )
JSON support values (D7).
const GeneratedMarker = "// GENERATED BY tools/canongen — DO NOT HAND EDIT"
GeneratedMarker is the first line of the generated move table.
const MaxVerbs = 20
MaxVerbs is the ceiling on the core verb list (ADR 0016, VMI). It is a ceiling, not a target: the list may hold fewer verbs, never more.
const ModeV14 = "v1.4"
ModeV14 is the only value of an entry's `mode`: the entry exists only in v1.4 mode.
const SchemaVersion = 1
SchemaVersion is the only canon.yaml schema version this package accepts.
Variables ¶
var RequiredFragments = []string{
"lifecycle", "build", "io", "observe", "config", "account", "data",
"deploy", "services", "extend", "mcp", "breakouts", "admin",
}
RequiredFragments are the fragments the embedded canon must contain (EPIC P7-CANON contract table). Later Tickets add fragments; none may remove these.
Functions ¶
func NewValidationError ¶
NewValidationError returns nil for no problems, else a *ValidationError with the problems sorted so the message is deterministic.
func Rank ¶
Rank returns the position of a side-effect class in the total order read(0) < write(1) < remote(2) < destructive(3), or -1 for an unknown value.
func RenderGoTable ¶
RenderGoTable renders the Go source of the move table for f.
func ValidCanon ¶
ValidCanon reports whether s is one of the six canon status values.
func ValidOutput ¶
ValidOutput reports whether s is one of the three output kinds.
Types ¶
type Breakout ¶
type Breakout struct {
From string `yaml:"from"`
Plugin string `yaml:"plugin"`
To string `yaml:"to"`
Since string `yaml:"since"`
}
Breakout is a core command that moves to a plugin.
type Entry ¶
type Entry struct {
// Canon is the status (D4). Empty means subcommand at depth >= 2.
Canon string `yaml:"canon"`
// Target is the canonical path (without "nself ") a deprecated-shim runs.
Target string `yaml:"target"`
// SideEffect is the class of running the command with default flags (D5).
SideEffect string `yaml:"side_effect"`
// Output is the output kind (D6); empty means document.
Output string `yaml:"output"`
// JSON is the pre-contract JSON support, legacy or none (D7). "envelope"
// is never declared: it is derived from the registered data types.
JSON string `yaml:"json"`
// ExitCodes documents state exit codes in v1.4 mode (keys "0".."125").
ExitCodes map[string]string `yaml:"exit_codes"`
// ExitCodesV15 documents state exit codes in v1.5 mode (D10).
ExitCodesV15 map[string]string `yaml:"exit_codes_v15"`
// Flags maps a flag name to the escalation it causes when set.
Flags map[string]FlagOverride `yaml:"flags"`
Confirm *Confirm `yaml:"confirm"`
Surface string `yaml:"surface"`
SecretArgs []string `yaml:"secret_args"`
// Mode is empty (the entry exists in both modes) or "v1.4" (it exists only
// in v1.4 mode: break-outs, removed commands, shim and retired-hub sources).
Mode string `yaml:"mode"`
}
Entry is the declared data for one command.
type File ¶
type File struct {
// SchemaVersion is the canon.yaml schema version (1).
SchemaVersion int `yaml:"schema_version"`
// Verbs lists the ADR 0016 core verbs in ADR order (at most MaxVerbs).
Verbs []string `yaml:"verbs"`
// Commands maps a command path without the leading "nself " to its entry.
Commands map[string]Entry `yaml:"commands"`
// Rows are the move rows of contract:cli.canon-fragments v1.
Rows `yaml:",inline"`
// contains filtered or unexported fields
}
File is the decoded canon.yaml document.
func Effective ¶
Effective returns the registry view for a compat mode (see (*File).View), built from LoadRaw and memoised per mode. The result is read-only.
func Load ¶
Load returns the registry view of the running compat mode, so every registry caller sees the right surface without knowing about modes. Callers must treat the returned *File as read-only.
func LoadFS ¶
LoadFS loads canon.yaml and every domains/*.yaml of fsys (lexical order), merges them and validates the result. It is the loader behind LoadRaw and the entry point for fixtures. A failure returns one aggregated *ValidationError (or a decode error for canon.yaml itself) naming file and path.
func LoadRaw ¶
LoadRaw parses and validates the embedded canon.yaml and domains/*.yaml and returns the merged raw data: keys are canonical (v1.5) paths and the move rows are present. The result is memoised and read-only. tools/canongen and tests use it; the registry uses Load.
func Parse ¶
Parse strictly decodes canon.yaml bytes (unknown keys are errors) and validates the result. On a validation failure the error is a *ValidationError naming every offending path.
type FlagOverride ¶
type FlagOverride struct {
// SideEffect escalates the command's class; it must outrank the command's.
SideEffect string `yaml:"side_effect"`
// JSON overrides the command's JSON support: legacy or none.
JSON string `yaml:"json"`
// Output is empty or "stream" (D6, invalidation 2026-09-30): the only
// flag-level output value, allowed on a command whose output is document.
Output string `yaml:"output"`
CLIOnly bool `yaml:"cli_only"`
Secret bool `yaml:"secret"`
}
FlagOverride is what setting a flag changes about its command.
type Fragment ¶
type Fragment struct {
SchemaVersion int `yaml:"schema_version"`
Commands map[string]Entry `yaml:"commands"`
Rows `yaml:",inline"`
}
Fragment is the decoded form of one domains/<name>.yaml.
type Removed ¶
type Removed struct {
From string `yaml:"from"`
Since string `yaml:"since"`
Message string `yaml:"message"`
}
Removed is a command removed without replacement.
type Row ¶
type Row struct {
From string `yaml:"from"`
To string `yaml:"to"`
// Since is the release that introduces the new spelling (vX.Y.Z).
Since string `yaml:"since"`
// RemovalAt is the release that removes the old spelling (vX.Y.Z, after Since).
RemovalAt string `yaml:"removal_at"`
// Equivalence names the Go test proving a shim equals its target (shims only).
Equivalence string `yaml:"equivalence"`
}
Row is one move, shim or retired-hub row.
type Rows ¶
type Rows struct {
// Hubs are non-runnable hubs the engine creates in v1.5 mode.
Hubs []Hub `yaml:"hubs"`
// Moves relocate a command with its subtree (From old path, To canonical).
Moves []Row `yaml:"moves"`
// Shims replace an old command with a forward to an equivalent command.
Shims []Row `yaml:"shims"`
// RetiredHubs turn an emptied old hub into a stub forwarding to To.
RetiredHubs []Row `yaml:"retired_hubs"`
// Builtins are hidden framework commands (canon builtin in v1.5).
Builtins []string `yaml:"builtins"`
// Breakouts leave the core tree for a plugin in v1.5 mode.
Breakouts []Breakout `yaml:"breakouts"`
// Removed lists commands removed in v1.5 with the message to print.
Removed []Removed `yaml:"removed"`
}
Rows are the lists of contract:cli.canon-fragments v1 that describe how the v1.4 surface maps to the v1.5 surface. A fragment and the merged File both carry them. Paths are command paths without the leading "nself ".
type Table ¶
type Table struct {
Verbs []string
Moves []TableRow
Shims []TableRow
RetiredHubs []TableRow
Hubs []TableRow
Builtins [][]string
Breakouts []TableRow
Removed []TableRow
}
Table is the engine's view of the raw canon: no YAML, no maps, token slices.
func BuildTable ¶
BuildTable turns the raw canon into a Table. Rows of each list are sorted by prefix length (longest first), then lexically, so a reader scanning the list meets the most specific row first.
type TableRow ¶
type TableRow struct {
From []string
To []string
Since string
RemovalAt string
Plugin string // breakouts: the plugin that now owns the command
Message string // removed: the text E410 prints
Summary string // hubs: the one-line summary (From holds the hub path)
}
TableRow is one row of the table. From and To are command tokens without the leading "nself ". Which fields are set depends on the list the row is in.
type ValidationError ¶
type ValidationError struct {
// Problems are sorted, one per violated rule instance.
Problems []string
}
ValidationError aggregates every problem found in one validation pass. Each problem names the offending path (for example `commands["config get"]`).
func (*ValidationError) Error ¶
func (e *ValidationError) Error() string
Error renders every problem, one per line.