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
- func AnnotateConstraints(cmd *cobra.Command, constraints []Constraint)
- func AttachContract(cmd *cobra.Command, safety contract.SafetySpec, decl ContractDecl, ...)
- func BoolFlag(cmd *cobra.Command, name string) bool
- func BuildArgs(cmd *cobra.Command, flags []FlagSpec) (map[string]any, error)
- func ConfirmSafety(cmd *cobra.Command, safety contract.SafetySpec) error
- func ConstraintHelp(constraints []Constraint) string
- func EffectiveValue(cmd *cobra.Command, flag FlagSpec) string
- func HasDeclaredConfirmFirst(cmd *cobra.Command) bool
- func New(spec Spec) *cobra.Command
- func RegisterFlag(cmd *cobra.Command, kind FlagKind, name, def, usage string)
- func RegisterFlags(cmd *cobra.Command, flags []FlagSpec)
- func ValidateConstraintDecls(use string, flags []FlagSpec, constraints []Constraint)
- func ValidateConstraints(cmd *cobra.Command, flags []FlagSpec, constraints []Constraint) error
- func ValidateEnums(cmd *cobra.Command, flags []FlagSpec) error
- func ValidateRequired(cmd *cobra.Command, flags []FlagSpec) error
- type Constraint
- type ConstraintKind
- type ContractDecl
- type Ctx
- func (c *Ctx) Args() []string
- func (c *Ctx) Bool(name string) bool
- func (c *Ctx) Changed(name string) bool
- func (c *Ctx) Command() *cobra.Command
- func (c *Ctx) DryRun() bool
- func (c *Ctx) Int(name string) int
- func (c *Ctx) Str(name string) string
- func (c *Ctx) StrSlice(name string) []string
- func (c *Ctx) Yes() bool
- type FlagKind
- type FlagSpec
- type FlagValidationMode
- type ParameterProjectionMode
- type Spec
Constants ¶
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 ¶
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 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 ¶
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 ¶
HasDeclaredConfirmFirst reports whether cmd was built from a Spec that declared ConfirmFirst.
func New ¶
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 ¶
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 ¶
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 ¶
ValidateEnums enforces the accepted values declared on changed flags. A registration default does not trigger validation, matching Shortcut's historical behavior.
func ValidateRequired ¶
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
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) 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 ¶
Str returns a flag's effective string value (explicit → alias → env → default). An undeclared name yields "".
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
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
// 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. |