corecmd

package
v1.0.58-beta.5 Latest Latest
Warning

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

Go to latest
Published: Aug 13, 2026 License: Apache-2.0 Imports: 15 Imported by: 0

Documentation

Overview

Package corecmd is the shared, dispatch-agnostic base for building leaf commands. It concentrates flag registration, the alias/env/default effective value fallback chain, required validation, cross-flag constraint declaration checks + runtime enforcement, SafetySpec-driven confirmation, toolArgs assembly, and Agent Runtime Schema projection.

Declaration vs execution (framework rule):

  • Declare = Spec data fields (Flags, Constraints, Safety, ConstParams, Use/Short/Long/Example). New registers, validates, confirms, and embeds those facts into dws.schema.*.
  • Execute = Validate / Invoke / Orchestrate / RunE / PostMount. Hooks consume assembled args; they must not invent the CLI surface.
  • Annotate = explicit cobra annotations when a fact is not (yet) a Contract field (e.g. a cross-flag constraint or parameter metadata fact). Inference-only Schema/help is forbidden.
  • Selection / product routing prose is declared on ContractDecl / ProductDecl (delivered as contract_final). schema_hints/ is retired. Identity is collected from ContractFinal.Identity on the live leaves. Interface / dry-run reviewed sources must not create CLI flags.

Full ToolSpec field authority: RFC §5.0.4 / homology §1.4.

It is deliberately dispatch-agnostic: it never calls an MCP tool. LeafSpec (internal/helpers) and Shortcut (internal/shortcut) wrap these primitives and supply dispatch. Invoke / Orchestrate / Ctx are the #830 transitional dispatch API still used in production; the RFC target is mcpbind + Handler (do not treat removal of Invoke/Orchestrate as already landed).

Behavioral contract: flag registration, value fallback, required/constraint semantics, confirmation behavior, and schema projection stay shared across Leaf and Shortcut. Evidence is split: check-generated-drift proves build-time projection; runtime pipeline order is covered by this package's tests plus leaf/risk/constraint unit tests.

Index

Constants

View Source
const ConfirmFirstAnnotation = "dws.contract.confirm_first"

ConfirmFirstAnnotation marks commands whose Spec declared ConfirmFirst. The delivery gate reads it to tell a declared guard-first command apart from an accidental confirm-before-validate inversion: guard-first is only legitimate when the declaration says so.

Variables

This section is empty.

Functions

func AnnotateConstraints

func AnnotateConstraints(cmd *cobra.Command, constraints []Constraint)

AnnotateConstraints projects the relationship constraints into the Agent Runtime Schema: exactly_one decomposes into require_one_of + mutually_exclusive (matching the handwritten commands' use of AnnotateRuntimeConstraints).

When a group still has hidden siblings, the full declared flag list is projected (not collapsed to a single visible "required"). ValidateConstraints accepts any member of the declared group — including hidden — so marking the sole visible flag required would falsely claim declare ≡ execute.

func AttachContract

func AttachContract(cmd *cobra.Command, safety contract.SafetySpec, decl ContractDecl, short, long string)

AttachContract registers a ContractFinal overlay on an existing leaf without replacing its RunE/Execute body. Used to migrate reviewed facts onto helpers while keeping execution substance frozen. Overwrites any prior ContractFinal on cmd; does not alter an already-installed ConfirmSafety closure.

Production registration always goes through contractfinal.RegisterRuntimeContractFinal (annotate + store). Do not call the store/Register APIs except via contractfinal — no cli-root wrapper exists.

Title/Description stored on the payload are the declared Contract values only. Catalog assembly may prefer Cobra Long for delivered description (Short never enters description) and must stamp provenance to the real winner (cobra_help vs contract_final). Declared Title still wins over Short.

func BoolFlag

func BoolFlag(cmd *cobra.Command, name string) bool

BoolFlag robustly reads a bool flag that may live on the command, its inherited flags, or the root's persistent flags (e.g. root-injected global --yes / --dry-run).

It ORs across flagsets, matching confirmationBypass. Returning the first resolving flagset instead let a leaf-local --dry-run (default false) shadow a root persistent --dry-run=true, so confirmation could be bypassed as a dry run while Ctx.DryRun() reported false — a real write with no confirmation.

func BuildArgs

func BuildArgs(cmd *cobra.Command, flags []FlagSpec) (map[string]any, error)

BuildArgs assembles toolArgs from the flag set by binding relationship.

func ConfirmSafety

func ConfirmSafety(cmd *cobra.Command, safety contract.SafetySpec) error

ConfirmSafety enforces the command's declared confirmation requirement. Effect, risk and idempotency are metadata only and never imply confirmation. Semantics:

  • read-only, --dry-run, --yes, or --user-say-yes → nil (proceed);
  • interactive yes/y → nil;
  • interactive decline → validation "用户取消了操作" (existing command path);
  • no interactive answer (EOF / closed stdin) → confirmation_required.

EOF must not be treated as decline: that silently drops writes in agent/CI. Prompt text is terminal-gated; a readable piped answer is still honored for non-Sheet leaves. Sheet destructive commands keep a separate --yes-only outer gate (helpers.protectSheetMutationCommand) so agents cannot authorize those via stdin alone.

func ConstraintHelp

func ConstraintHelp(constraints []Constraint) string

ConstraintHelp renders the --help "参数约束" section, matching the shortcut leaf help shape; returns "" when there are no constraints.

func EffectiveValue

func EffectiveValue(cmd *cobra.Command, flag FlagSpec) string

EffectiveValue reads the value by "explicit main flag → alias → env → registration default" order (string form, integers uniformly formatted); Trim TrimSpace's the result.

func HasDeclaredConfirmFirst

func HasDeclaredConfirmFirst(cmd *cobra.Command) bool

HasDeclaredConfirmFirst reports whether cmd was built from a Spec that declared ConfirmFirst.

func New

func New(spec Spec) *cobra.Command

NewCommand builds a cobra command from a Spec. It is the single orchestration path: dispatch declaration check → flag registration → constraint declaration checks → Runtime Schema projection → constraint help → PostMount → generated RunE{ [ConfirmFirst: ConfirmSafety →] required → constraints → Validate → BuildArgs → ConfirmSafety → Invoke/Orchestrate }.

Behavior matches the former helpers.NewLeafCommand, which always dispatched (Call → Server → callMCPTool) and therefore could not express a dispatcher-less spec. Here that is a programming error caught at construction time, so a malformed spec can never run the pipeline — write-confirmation prompt included — and then silently exit 0 having done nothing.

func RegisterFlag

func RegisterFlag(cmd *cobra.Command, kind FlagKind, name, def, usage string)

RegisterFlag registers one flag by Kind. Default is applied at registration for every kind so --help DefValue matches the declared fallback. Malformed KindInt / KindBool Default values panic at registration (fail-closed) instead of silently degrading to 0 / false.

func RegisterFlags

func RegisterFlags(cmd *cobra.Command, flags []FlagSpec)

RegisterFlags registers every flag (plus hidden aliases and MarkFlagRequired) declared by the spec set onto cmd.

func ValidateConstraintDecls

func ValidateConstraintDecls(use string, flags []FlagSpec, constraints []Constraint)

ValidateConstraintDecls validates constraint declarations at build time: an unknown kind, an under-sized flag group, or a reference to an undeclared flag is a programming error and panics so any test/startup path fails immediately rather than at user runtime. use is only used for the panic message.

func ValidateConstraints

func ValidateConstraints(cmd *cobra.Command, flags []FlagSpec, constraints []Constraint) error

ValidateConstraints enforces the relationship constraints. Error wording matches the shortcut framework's RuntimeContext.AtLeastOne/ExactlyOne/ MutuallyExclusive verbatim, so atomic commands and smart shortcuts fail identically for users and agents.

func ValidateEnums

func ValidateEnums(cmd *cobra.Command, flags []FlagSpec) error

ValidateEnums enforces the accepted values declared on changed flags. A registration default does not trigger validation, matching Shortcut's historical behavior.

func ValidateRequired

func ValidateRequired(cmd *cobra.Command, flags []FlagSpec) error

ValidateRequired reproduces the handwritten required semantics: plain Required flags report a unified "missing required flag(s)" error; Required flags with EnvVar/RequiredHint report their hint separately. The plain group is checked before the env group to preserve the handwritten order. Both groups use the declared "main flag → alias → env" fallback: a compatible alias counts as provided. Shortcut mode keeps its stricter contract: it demands an explicit token, so the main flag or an alias must be Changed on the command line — a registration default does not satisfy it.

Types

type Constraint

type Constraint struct {
	Kind  ConstraintKind
	Flags []string
	// Description, when non-empty, replaces the constraint's default help text.
	Description string
}

Constraint declares a relationship over a group of flags. It is enforced after required validation and before the framework's Validate hook; "provided" reuses the effective-value fallback chain (explicit main flag → alias → env), so passing a compatible alias counts as provided — a capability the shortcut framework's bare Changed check lacks. The constraint is also projected into the Agent Runtime Schema (mutually_exclusive / require_one_of) and rendered into the --help "参数约束" section.

type ConstraintKind

type ConstraintKind string

ConstraintKind is the type of a cross-flag relationship constraint. Values match the shortcut framework's ConstraintKind verbatim.

const (
	// AtLeastOne requires at least one of Flags to be provided.
	AtLeastOne ConstraintKind = "at_least_one"
	// ExactlyOne requires exactly one of Flags to be provided.
	ExactlyOne ConstraintKind = "exactly_one"
	// MutuallyExclusive allows at most one of Flags.
	MutuallyExclusive ConstraintKind = "mutually_exclusive"
	// Custom documents validation implemented by Spec.Validate. command
	// validates the declaration and renders its help, but does not infer the
	// command-specific runtime rule.
	Custom ConstraintKind = "custom"
)

type ContractDecl

type ContractDecl struct {
	Title       string
	Description string // required at construction; Catalog may prefer Cobra Long
	Positionals []contract.RuntimeSchemaPositional
	Parameters  []contract.ParamDecl
	DryRun      *contract.DryRunSpec
	Result      *contract.ResultSpec
	Pagination  *contract.PaginationSpec
	Interface   *contract.InterfaceSpec
	Selection   contract.SelectionSpec
	Identity    contract.ToolIdentitySpec
}

ContractDecl is the authoring-time leaf contract declaration.

Naming: this is not a Catalog / ToolSpec "Schema" object. Authors declare leaf Contract facts (selection / interface / parameters / dry-run / identity prose). AttachContract converts once into contract.ContractFinalPayload; Catalog assembly pass-throughs that payload. Nested fields reuse contract.* types directly so authoring cannot drift from the registry model.

Description declare vs delivery (not dual authority, not "declare = wire"):

  • Construction requires Description (declaration evidence / fail-closed).
  • Catalog delivery: Cobra Long wins when present → provenance cobra_help; without Long, declared Description is delivered → contract_final.
  • Title: declared Title/ContractFinal first, then Cobra Short, then MCP.

The payload stores the declared text; assembly stamps the real winner.

func (ContractDecl) Empty

func (s ContractDecl) Empty() bool

Empty reports whether no ContractDecl field was authored.

type Ctx

type Ctx struct {
	// contains filtered or unexported fields
}

Ctx is the framework-neutral execution context handed to Invoke/Orchestrate. It deliberately knows nothing about MCP or any other backend: it exposes the command, its positional args, and typed flag access that reuses the declared alias → env → default fallback chain, so a consumer reading a flag through Ctx gets exactly the value the required/constraint checks saw.

func (*Ctx) Args

func (c *Ctx) Args() []string

Args returns the positional arguments.

func (*Ctx) Bool

func (c *Ctx) Bool(name string) bool

Bool returns a boolean flag's value.

func (*Ctx) Changed

func (c *Ctx) Changed(name string) bool

Changed reports whether the user explicitly passed the flag.

func (*Ctx) Command

func (c *Ctx) Command() *cobra.Command

Command returns the running cobra command.

func (*Ctx) DryRun

func (c *Ctx) DryRun() bool

DryRun reports the effective global --dry-run.

func (*Ctx) Int

func (c *Ctx) Int(name string) int

Int returns a flag's effective integer value; an unparseable or undeclared value yields 0 (BuildArgs reports the precise parse error for Invoke specs).

func (*Ctx) Str

func (c *Ctx) Str(name string) string

Str returns a flag's effective string value (explicit → alias → env → default). An undeclared name yields "".

func (*Ctx) StrSlice

func (c *Ctx) StrSlice(name string) []string

StrSlice returns a list flag's effective elements (trimmed, empties dropped).

func (*Ctx) Yes

func (c *Ctx) Yes() bool

Yes reports the effective global --yes.

type FlagKind

type FlagKind int

FlagKind is the value type of a flag.

const (
	// KindString is a string flag (default).
	KindString FlagKind = iota
	// KindInt is an integer flag (registered as cobra Int); it enters toolArgs
	// only when the value is non-zero, matching the handwritten "putInt only
	// when non-zero" semantics (e.g. devapp app-group-id).
	KindInt
	// KindBool is a boolean flag (registered as cobra Bool); it enters toolArgs
	// only when the user explicitly provided it (Changed), matching the
	// handwritten "transmit on Changed, explicit false is still sent" semantics.
	// Booleans do not participate in the alias/env fallback chain.
	KindBool
	// KindStringSlice is a string-list flag (registered as cobra StringSlice);
	// it enters toolArgs only when a non-empty element exists, elements are
	// always TrimSpace'd and empties dropped.
	KindStringSlice
)

type FlagSpec

type FlagSpec struct {
	Name      string   // flag name (kebab-case)
	Shorthand string   // optional one-character Cobra shorthand
	Usage     string   // registration usage text
	Kind      FlagKind // value type, defaults to KindString
	Default   string   // registration default for every Kind; also the fallback-chain tail when aliases/env are empty
	Hidden    bool     // hide the real flag from help/Schema while keeping it invocable

	// Required, when true, validates a non-empty effective value in RunE. Plain
	// Required flags aggregate into a cmdutil.ValidateRequiredFlags-compatible
	// error; when EnvVar is configured the env var is a fallback and, still
	// empty, RequiredHint (or a default hint) is reported.
	Required       bool
	ValidationMode FlagValidationMode
	RequiredError  string // exact missing-token error for ValidationShortcut
	RequiredHint   string
	// MarkRequired, when true, calls cobra MarkFlagRequired (the hard floor for
	// the catalog required projection); cobra errors before RunE. It cannot be
	// combined with Aliases (RegisterFlags panics on that declaration).
	MarkRequired bool

	Aliases []string // hidden aliases, registered with the main flag's Kind; used in order when the main flag is not explicitly provided
	EnvVar  string   // environment variable consulted when the effective value is empty (an integer flag's env value must be parseable)
	// ArgDefault covers the case where the registration default is empty but
	// toolArgs still needs a fallback. For KindString it is used when the
	// effective value is empty. For KindInt it is also the floor: when the
	// resolved integer is < 1, ArgDefault is emitted instead (cursor page-size
	// semantics).
	ArgDefault string
	// Bind is the toolArgs key; empty uses Name.
	Bind string
	// Transform converts a string effective value into the arg value; nil sends
	// it as-is. Returning (nil, nil) skips the key (for "nullable numeric: skip
	// on empty or parse failure" semantics).
	Transform func(raw string) (any, error)
	// OmitEmpty, when true, drops an empty effective value from toolArgs (KindInt
	// is always "non-zero only" and ignores this field).
	OmitEmpty bool
	// Trim, when true, TrimSpace's the effective value (main flag/alias/env
	// alike) and makes a whitespace-only value count as empty in required checks.
	Trim bool

	// Schema parameter final facts (embedded to dws.schema.*; assembly pass-through).
	Enum              []string // accepted values
	Format            string   // machine-readable format (e.g. uri)
	Example           string   // representative CLI value
	RequiredWhen      string   // conditional required expression (descriptive)
	SchemaDescription string   // Schema description; empty uses Usage
}

FlagSpec declares how a flag is registered and bound into MCP toolArgs. Its fields intentionally mirror the former helpers.LeafFlag one-for-one so that helpers can alias to it without touching any call site.

type FlagValidationMode

type FlagValidationMode string

FlagValidationMode selects runtime validation semantics for a flag.

The zero value keeps LeafSpec's fallback-aware effective-value semantics. ValidationShortcut preserves Shortcut's declaration-order checks: Required means the user must explicitly provide the flag token (even with a default), followed immediately by that flag's Enum validation.

const ValidationShortcut FlagValidationMode = "shortcut"

ValidationShortcut is the declaration-order explicit-token mode described on FlagValidationMode.

type ParameterProjectionMode

type ParameterProjectionMode string

ParameterProjectionMode selects how declared flags are embedded into Runtime Schema annotations. The zero value makes the declaration the final parameter authority (the LeafSpec/command default).

const (
	// ProjectCobraParameters preserves Cobra usage/type/default provenance and
	// annotates only facts Cobra cannot express: Required and Enum. Shortcut
	// uses this mode to converge its runtime without rewriting Catalog facts.
	ProjectCobraParameters ParameterProjectionMode = "cobra"
)

type Spec

type Spec struct {
	Use           string
	Short         string
	Long          string
	Example       string
	Hidden        bool
	OutputRollout output.RolloutState

	Flags       []FlagSpec
	Constraints []Constraint
	// ParameterProjection controls whether parameter facts are final
	// declaration annotations or Cobra-backed compatibility facts.
	ParameterProjection ParameterProjectionMode
	// Safety is the command's single safety source. The same contract.SafetySpec
	// is used for runtime confirmation and the published Schema. A completely
	// empty value keeps the historical read-only default; a non-empty value
	// must declare effect/risk/confirmation/idempotency together.
	Safety contract.SafetySpec
	// ConfirmFirst runs the Safety confirmation before required/constraint/
	// Validate checks instead of after them. Use it where the legacy semantics
	// were guard-first (a write without --yes fails fast with
	// confirmation_required regardless of parameter completeness). The default
	// preserves the shortcut order (checks first, confirmation just before the
	// backend call).
	ConfirmFirst bool
	// ConstParams are fixed toolArgs merged after flag assembly (e.g. precheckOnly).
	// They are payload declaration, not user flags, and never satisfy Required.
	ConstParams map[string]any
	// Contract is the authoring-time leaf contract declaration (selection /
	// interface / parameters / dry-run / identity). When non-empty, embed
	// converts it once to ContractFinal for Catalog pass-through.
	Contract ContractDecl

	// Validate is the cross-flag validation hook, run after required/constraint
	// checks and before args assembly; nil skips it. Not a declaration surface.
	Validate func(cmd *cobra.Command, args []string) error
	// PostMount adjusts the built command after flag registration and before
	// RunE is set (Args/DisableAutoGenTag/annotate/…); always runs. Business
	// flags belong in Flags, not here.
	PostMount func(cmd *cobra.Command)
	// RunE fully replaces the generated body (escape hatch).
	RunE func(cmd *cobra.Command, args []string) error
	// Invoke executes a single-step command with the assembled toolArgs.
	Invoke func(c *Ctx, toolArgs map[string]any) error
	// ResultInvoke executes once and returns an immutable framework 2.0 result.
	ResultInvoke func(c *Ctx, toolArgs map[string]any) (output.CommandResult, error)
	// Orchestrate executes a multi-step command; it assembles whatever payloads
	// it needs from the Ctx.
	Orchestrate func(c *Ctx) error
}

Spec is the single typed definition of a leaf command, shared by the LeafSpec and (via FromShortcut) Shortcut frameworks.

Declaration surface is the final Schema data source for managed leaves:

Flags (+ parameter Schema fields), Constraints, Safety, ConstParams,
Use/Short/Long/Example, Contract (ToolSpec groups)

Schema assembly pass-throughs embedded dws.schema.* — no reviewed/hints parallel authority for declared fields. Safety uses contract.SafetySpec directly: confirmation drives the runtime gate, while effect/risk/idempotency are published unchanged. No safety field is inferred from another.

Execution surface (hooks — not declaration):

  • RunE — full escape hatch: the framework only registers flags/constraints/ help and hands control over.
  • Invoke — #830 transitional single-step dispatch: runs after required/ constraint/Validate checks, args assembly and the Safety confirmation gate, receiving the assembled toolArgs. Target: mcpbind Bind.
  • Orchestrate — #830 transitional multi-step dispatch: same checks and confirmation, receives only the Ctx. Target: Handler / orchestration.
  • Validate / PostMount — orchestration only; must not register business flags or assemble business params that belong in Flags/ConstParams.

Exactly one of RunE / Invoke / Orchestrate must be set; New validates this at construction time. corecmd stays dispatch-agnostic and never calls a backend: the adapters (FromLeafSpec / FromShortcut) supply the body.

Directories

Path Synopsis
Package contract owns command-framework declaration DTOs and the ProductDecl registry.
Package contract owns command-framework declaration DTOs and the ProductDecl registry.
Package contractfinal owns the Cobra-keyed ContractFinal runtime store and the annotate+store registration seam.
Package contractfinal owns the Cobra-keyed ContractFinal runtime store and the annotate+store registration seam.
Package runtimeannotate owns Cobra dws.schema.* annotation writers and the RuntimeSchemaConstraints helpers used by the command framework.
Package runtimeannotate owns Cobra dws.schema.* annotation writers and the RuntimeSchemaConstraints helpers used by the command framework.

Jump to

Keyboard shortcuts

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