Files
dingtalk-workspace-cli/internal/cli/runtime_schema.go
T
玉澜 affc8715be refactor(cli): drop the always-empty interface_metadata wire projection
embeddedMCPMetadata only feeds interface validation now; its summary was
projected onto every schema payload as a constant-empty blob. Remove the
SchemaRegistry field, all three payload projections, the snapshot wire
field, the overview copy, the compact strip entry, and the jq policy gate.
Also delete the redundant io.Discard dead-code suppressor in
event_command.go (io has five genuine uses there).
2026-08-03 22:21:30 +08:00

1409 lines
51 KiB
Go

// Copyright 2026 Alibaba Group
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package cli
import (
"bytes"
"encoding/json"
"fmt"
"reflect"
"sort"
"strconv"
"strings"
"github.com/DingTalk-Real-AI/dingtalk-workspace-cli/internal/corecmd/contract"
"github.com/DingTalk-Real-AI/dingtalk-workspace-cli/internal/corecmd/runtimeannotate"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
)
const (
// Annotation keys are owned by runtimeannotate; aliases keep assembly readers stable.
runtimeSchemaProductAnnotation = runtimeannotate.AnnotationProduct
runtimeSchemaToolAnnotation = runtimeannotate.AnnotationTool
runtimeSchemaSourceAnnotation = runtimeannotate.AnnotationSource
runtimeSchemaTitleAnnotation = runtimeannotate.AnnotationTitle
runtimeSchemaDescAnnotation = runtimeannotate.AnnotationDescription
runtimeSchemaMetaAnnotation = runtimeannotate.AnnotationMetaSource
runtimeSchemaExcludeAnnotation = runtimeannotate.AnnotationExclude
runtimeSchemaRulesAnnotation = runtimeannotate.AnnotationConstraints
runtimeSchemaArgsAnnotation = runtimeannotate.AnnotationPositionals
runtimeSchemaFlagPropertyAnnotation = runtimeannotate.AnnotationFlagProperty
runtimeSchemaFlagTypeAnnotation = runtimeannotate.AnnotationFlagType
runtimeSchemaFlagDescriptionAnnotation = runtimeannotate.AnnotationDescription
runtimeSchemaFlagRequiredAnnotation = runtimeannotate.AnnotationFlagRequired
runtimeSchemaFlagRequiredWhenAnnotation = runtimeannotate.AnnotationFlagReqWhen
runtimeSchemaFlagExampleAnnotation = runtimeannotate.AnnotationFlagExample
runtimeSchemaContractAnnotation = runtimeannotate.AnnotationContract
runtimeSchemaRiskAnnotation = runtimeannotate.AnnotationRisk
runtimeSchemaRuntimeGateAnnotation = runtimeannotate.AnnotationRuntimeGate
)
type embeddedMCPMetadata struct {
Version int `json:"version"`
Source string `json:"source"`
SourceRevision string `json:"source_revision,omitempty"`
SourceHash string `json:"source_hash"`
Coverage embeddedMCPMetadataCoverage `json:"coverage,omitempty"`
Tools map[string]embeddedMCPToolMetadata `json:"tools"`
}
type embeddedMCPMetadataCoverage struct {
SurfaceScope string `json:"surface_scope,omitempty"`
SourceServices int `json:"source_services,omitempty"`
SnapshotServices int `json:"snapshot_services,omitempty"`
MissingServices []string `json:"missing_services,omitempty"`
SourceTools int `json:"source_tools,omitempty"`
SurfaceTools int `json:"surface_tools,omitempty"`
MatchedTools int `json:"matched_tools,omitempty"`
AliasedTools int `json:"aliased_tools,omitempty"`
UnmatchedTools int `json:"unmatched_tools,omitempty"`
}
type embeddedMCPInterfaceRef struct {
ProductID string `json:"product_id"`
RPCName string `json:"rpc_name"`
}
type embeddedMCPToolMetadata struct {
Title string `json:"title,omitempty"`
Description string `json:"description,omitempty"`
Parameters map[string]embeddedMCPParamMeta `json:"parameters,omitempty"`
InterfaceRef *embeddedMCPInterfaceRef `json:"interface_ref,omitempty"`
}
type embeddedMCPParamMeta struct {
Type string `json:"type,omitempty"`
Description string `json:"description,omitempty"`
Default string `json:"default,omitempty"`
Format string `json:"format,omitempty"`
Enum []string `json:"enum,omitempty"`
Required *bool `json:"required,omitempty"`
RequiredWhen string `json:"required_when,omitempty"`
}
var runtimeSchemaConstraintsByCanonical = map[string]RuntimeSchemaConstraints{}
// RegisterRuntimeSchemaConstraints records reviewed cross-parameter CLI rules
// independently from the generated Catalog, preventing stale Catalog data
// from becoming the source of its own next generation.
func RegisterRuntimeSchemaConstraints(canonicalPath string, constraints RuntimeSchemaConstraints) {
canonicalPath = strings.TrimSpace(canonicalPath)
constraints = normalizeRuntimeSchemaConstraints(constraints)
if canonicalPath == "" || runtimeSchemaConstraintsEmpty(constraints) {
return
}
runtimeSchemaConstraintsByCanonical[canonicalPath] = constraints
}
// emptyPinnedMCPMetadata returns the retired pin shape with no tools.
// schema_mcp_metadata.json is deleted; production assembly does not embed or
// load a pinned MCP snapshot. Test fixtures may still inject non-empty maps
// through schemaRegistryForTestWithMetadata.
func emptyPinnedMCPMetadata() embeddedMCPMetadata {
return embeddedMCPMetadata{Tools: map[string]embeddedMCPToolMetadata{}}
}
// applyContractRiskToSafety overlays Schema Safety fields from an embedded
// Contract Risk value. Path A: Contract wins effect/risk/confirmation for the
// managed surface; other Safety fields (e.g. idempotency) are preserved.
func applyContractRiskToSafety(base contract.SafetySpec, contractRisk string) contract.SafetySpec {
out := base
switch strings.TrimSpace(contractRisk) {
case "write":
out.Effect = "write"
out.EffectSource = "corecmd.contract"
out.Risk = "medium"
out.Confirmation = "user_required"
case "high-risk-write":
out.Effect = "destructive"
out.EffectSource = "corecmd.contract"
out.Risk = "high"
out.Confirmation = "user_required"
case "read":
out.Effect = "read"
out.EffectSource = "corecmd.contract"
out.Risk = "low"
out.Confirmation = "not_required"
}
return out
}
// applyContractGateToSafety ensures a write-guard annotation cannot leave Schema
// claiming confirmation is not required. Reviewed effect/risk are kept when set.
func applyContractGateToSafety(base contract.SafetySpec, gate string) contract.SafetySpec {
out := base
if strings.TrimSpace(gate) == "" {
return out
}
out.Confirmation = "user_required"
if out.Effect == "" || out.Effect == "read" {
out.Effect = "write"
out.EffectSource = "corecmd.contract_gate"
}
if out.Risk == "" || out.Risk == "low" {
out.Risk = "medium"
}
return out
}
type runtimeSchemaEntry struct {
ProductID string
SourceProductID string
ProductName string
ToolName string
CLIName string
Group string
CLIPath string
Title string
Description string
Source string
MetadataSource string
Command *cobra.Command
PrimaryCLIPath string
Aliases []string
IsAlias bool
IdentityField contract.FieldProvenance
}
func collectRuntimeSchemaEntries(root *cobra.Command) ([]runtimeSchemaEntry, error) {
effective, err := BuildEffectiveCommandRegistry(root)
if err != nil {
return nil, err
}
bound, err := BindEffectiveCommandRegistry(root, effective)
if err != nil {
return nil, err
}
return collectRuntimeSchemaEntriesFromBound(bound)
}
// collectRuntimeSchemaEntriesFromBound is the sole identity hand-off into the
// Schema assembler. It never scans annotations to discover commands: identity
// collection has already selected the exact command set and the binder has
// already proved that every path resolves to a runnable Cobra leaf.
func collectRuntimeSchemaEntriesFromBound(bound BoundCommandRegistry) ([]runtimeSchemaEntry, error) {
entries := make([]runtimeSchemaEntry, 0, len(bound.Commands))
for _, command := range bound.Commands {
productID, toolName, ok := splitManualSchemaCanonicalPath(command.CanonicalPath)
if !ok {
return nil, fmt.Errorf("bound Schema command has invalid canonical path %q", command.CanonicalPath)
}
if command.Visibility != SchemaVisibilityPublic {
continue
}
leaf := command.PrimaryCommand
AnnotateRuntimeConstraints(leaf, runtimeSchemaConstraintsByCanonical[command.CanonicalPath])
parts := splitSchemaPathTokens(command.PrimaryCLIPath)
group := ""
if len(parts) > 2 {
group = strings.Join(parts[1:len(parts)-1], ".")
}
productName := ""
if top := topLevelCommand(leaf); top != nil {
productName = strings.TrimSpace(top.Short)
}
entries = append(entries, runtimeSchemaEntry{
ProductID: productID,
SourceProductID: command.SourceProductID,
ProductName: productName,
ToolName: toolName,
CLIName: leaf.Name(),
Group: group,
CLIPath: command.PrimaryCLIPath,
Title: runtimeCommandTitle(leaf),
Description: runtimeCommandDescription(leaf),
Source: command.Source,
MetadataSource: runtimeCommandMetadataSource(leaf),
Command: leaf,
PrimaryCLIPath: command.PrimaryCLIPath,
Aliases: append([]string(nil), command.Aliases...),
IdentityField: commandRegistryIdentityProvenance(command),
})
}
sort.Slice(entries, func(i, j int) bool {
if entries[i].ProductID != entries[j].ProductID {
return entries[i].ProductID < entries[j].ProductID
}
if entries[i].ToolName != entries[j].ToolName {
return entries[i].ToolName < entries[j].ToolName
}
return entries[i].CLIPath < entries[j].CLIPath
})
return entries, nil
}
func pinnedMCPMetadataForEntryFrom(entry runtimeSchemaEntry, agentMetadata agentMetadata, mcpMetadata embeddedMCPMetadata) (embeddedMCPToolMetadata, bool) {
// Optional test/diagnostic lookup only. Production mcpMetadata is empty;
// Contract/ParamDecl own interface facts. When a non-empty fixture is
// injected, ContractFinal Interface.Ref remaps CLI canonical names onto
// fixture keys (e.g. reply_personal_message → chat.send_personal_message).
if len(mcpMetadata.Tools) == 0 {
return embeddedMCPToolMetadata{}, false
}
if entry.Command != nil {
if final, ok := RuntimeContractFinal(entry.Command); ok && final.Interface != nil && final.Interface.Ref != nil {
if metadata, found := mcpMetadataForInterfaceRef(mcpMetadata, final.Interface.Ref.ProductID, final.Interface.Ref.RPCName); found {
return metadata, true
}
}
}
paths := []string{
entry.PrimaryCLIPath,
entry.CLIPath,
entry.ProductID + "." + entry.ToolName,
}
paths = append(paths, entry.Aliases...)
if toolMetadata, ok := lookupAgentToolMetadataFrom(agentMetadata, paths...); ok && toolMetadata.InterfaceRef != nil {
if metadata, found := mcpMetadataForInterfaceRef(mcpMetadata, toolMetadata.InterfaceRef.ProductID, toolMetadata.InterfaceRef.RPCName); found {
return metadata, true
}
}
for _, key := range []string{
entry.SourceProductID + "." + entry.ToolName,
entry.ProductID + "." + entry.ToolName,
} {
key = strings.Trim(key, ".")
if key == "" {
continue
}
if meta, ok := mcpMetadata.Tools[key]; ok {
return meta, true
}
}
return embeddedMCPToolMetadata{}, false
}
func mcpMetadataForInterfaceRef(mcpMetadata embeddedMCPMetadata, productID, rpcName string) (embeddedMCPToolMetadata, bool) {
productID = strings.TrimSpace(productID)
rpcName = strings.TrimSpace(rpcName)
key := strings.Trim(productID+"."+rpcName, ".")
if key == "" {
return embeddedMCPToolMetadata{}, false
}
metadata, exists := mcpMetadata.Tools[key]
if !exists {
return embeddedMCPToolMetadata{}, false
}
metadata.InterfaceRef = &embeddedMCPInterfaceRef{ProductID: productID, RPCName: rpcName}
return metadata, true
}
func runtimeSchemaAnnotations(cmd *cobra.Command) (productID, toolName, source string) {
if cmd == nil || cmd.Annotations == nil {
return "", "", ""
}
productID = strings.TrimSpace(cmd.Annotations[runtimeSchemaProductAnnotation])
toolName = strings.TrimSpace(cmd.Annotations[runtimeSchemaToolAnnotation])
source = strings.TrimSpace(cmd.Annotations[runtimeSchemaSourceAnnotation])
if source == "" && productID != "" {
source = "runtime:" + productID
}
return productID, toolName, source
}
func runtimeSchemaExcluded(cmd *cobra.Command) bool {
return cmd != nil && cmd.Annotations != nil &&
strings.EqualFold(strings.TrimSpace(cmd.Annotations[runtimeSchemaExcludeAnnotation]), "true")
}
func runtimeCommandTitle(cmd *cobra.Command) string {
if cmd == nil {
return ""
}
if cmd.Annotations != nil {
if title := strings.TrimSpace(cmd.Annotations[runtimeSchemaTitleAnnotation]); title != "" {
return title
}
}
return strings.TrimSpace(cmd.Short)
}
func runtimeCommandDescription(cmd *cobra.Command) string {
if cmd == nil {
return ""
}
if cmd.Annotations != nil {
if desc := strings.TrimSpace(cmd.Annotations[runtimeSchemaDescAnnotation]); desc != "" {
return desc
}
}
if desc := strings.TrimSpace(cmd.Long); desc != "" {
return desc
}
return strings.TrimSpace(cmd.Short)
}
func runtimeCommandMetadataSource(cmd *cobra.Command) string {
if cmd == nil || cmd.Annotations == nil {
return ""
}
return strings.TrimSpace(cmd.Annotations[runtimeSchemaMetaAnnotation])
}
func commandPathParts(cmd *cobra.Command) []string {
parts := []string{}
for c := cmd; c != nil && c.HasParent(); c = c.Parent() {
parts = append([]string{c.Name()}, parts...)
}
return parts
}
func topLevelCommand(cmd *cobra.Command) *cobra.Command {
var top *cobra.Command
for c := cmd; c != nil && c.HasParent(); c = c.Parent() {
top = c
}
return top
}
func schemaProductToolCount(product map[string]any) int {
switch value := product["tool_count"].(type) {
case int:
return value
case int64:
return int(value)
case float64:
return int(value)
}
if tools, ok := product["tools"].([]map[string]any); ok {
return len(tools)
}
if tools, ok := product["tools"].([]any); ok {
return len(tools)
}
return 0
}
func runtimeToolTextMetadataFromMetadata(entry runtimeSchemaEntry, metadata runtimeSchemaMetadataSources) (title, description, metadataSource string, provenance map[string]contract.FieldProvenance, err error) {
baseSource := "cobra_help"
baseTitle := runtimeSchemaStringCandidate(entry.Title, baseSource)
baseDescription := runtimeSchemaStringCandidate(entry.Description, baseSource)
if strings.TrimSpace(entry.MetadataSource) != "" {
baseSource = strings.TrimSpace(entry.MetadataSource)
baseTitle = runtimeSchemaStringCandidateAtRank(entry.Title, baseSource, runtimeSchemaRankNativeAnnotation, "native_annotation")
baseDescription = runtimeSchemaStringCandidateAtRank(entry.Description, baseSource, runtimeSchemaRankNativeAnnotation, "native_annotation")
}
titleCandidates := []runtimeSchemaFieldCandidate{baseTitle}
descriptionCandidates := []runtimeSchemaFieldCandidate{baseDescription}
titleWinner, err := resolveRuntimeSchemaField("title", titleCandidates...)
if err != nil {
return "", "", "", nil, err
}
descriptionWinner, err := resolveRuntimeSchemaField("description", descriptionCandidates...)
if err != nil {
return "", "", "", nil, err
}
title, _ = titleWinner.Value.(string)
description, _ = descriptionWinner.Value.(string)
selectedSource := descriptionWinner.Source
if selectedSource == "" {
selectedSource = titleWinner.Source
}
switch selectedSource {
case "mcp_metadata", "pinned_mcp_metadata":
// Retained for fixture/diagnostic inject paths; production no longer
// nominates MCP text candidates.
metadataSource = ProvenanceEmbeddedMCPMetadata
case "cobra_help":
metadataSource = ""
default:
metadataSource = strings.TrimSpace(selectedSource)
}
provenance = map[string]contract.FieldProvenance{}
if titleWinner.Present {
provenance["title"] = runtimeSchemaFieldProvenance(titleWinner)
}
if descriptionWinner.Present {
provenance["description"] = runtimeSchemaFieldProvenance(descriptionWinner)
}
if metadataSource != "" {
provenance["metadata_source"] = runtimeSchemaFieldProvenance(runtimeSchemaStringCandidate(metadataSource, "metadata_source_resolution"))
}
return strings.TrimSpace(title), strings.TrimSpace(description), strings.TrimSpace(metadataSource), provenance, nil
}
type runtimeSchemaFieldCandidate struct {
Value any
Present bool
Source string
Rank int
Precedence string
Resolution string
ReviewReason string
Compared []runtimeSchemaFieldCandidate
}
const (
runtimeSchemaRankDefault = 0
runtimeSchemaRankDerived = 50
runtimeSchemaRankInference = 100
runtimeSchemaRankMCP = 400
runtimeSchemaRankCobraHelp = 450
runtimeSchemaRankCobraDefault = 600
runtimeSchemaRankCobraContract = 610
runtimeSchemaRankNativeAnnotation = 620
runtimeSchemaRankTypedMetadata = 630
runtimeSchemaRankConstraint = 640
runtimeSchemaRankVersionedBinding = 650
// ParamDecl.Property (dws.schema.property) outranks residual versioned
// binding candidates (active bindings JSON is empty after Phase 2).
// Mapping exclusions stay highest so an explicit "no MCP property" review
// cannot be overridden by a leaf ParamDecl that still carries a Property.
runtimeSchemaRankParamDeclProperty = 655
runtimeSchemaRankMappingExclusion = 660
runtimeSchemaPrecedenceDefault = "default"
runtimeSchemaPrecedenceDerived = "derived_resolution"
runtimeSchemaPrecedenceInference = "inference"
runtimeSchemaPrecedenceMCP = "mcp_metadata"
runtimeSchemaPrecedenceCobraHelp = "cobra_help"
runtimeSchemaPrecedenceCobra = "cobra_contract"
runtimeSchemaPrecedenceNativeAnnotation = "native_annotation"
runtimeSchemaPrecedenceTypedMetadata = "typed_metadata"
runtimeSchemaPrecedenceConstraint = "command_constraint"
runtimeSchemaPrecedenceVersionedBinding = "versioned_binding"
runtimeSchemaPrecedenceMappingExclusion = "reviewed_mapping_exclusion"
)
func runtimeSchemaCandidate(value any, present bool, source string) runtimeSchemaFieldCandidate {
rank, precedence := runtimeSchemaSourcePriority(source)
return runtimeSchemaStringCandidateAtPriority(value, present, source, rank, precedence)
}
func runtimeSchemaStringCandidateAtRank(value any, source string, rank int, precedence string) runtimeSchemaFieldCandidate {
present := true
if text, ok := value.(string); ok {
value = strings.TrimSpace(text)
present = value != ""
}
return runtimeSchemaStringCandidateAtPriority(value, present, source, rank, precedence)
}
func runtimeSchemaStringCandidateAtPriority(value any, present bool, source string, rank int, precedence string) runtimeSchemaFieldCandidate {
return runtimeSchemaFieldCandidate{
Value: value,
Present: present,
Source: strings.TrimSpace(source),
Rank: rank,
Precedence: strings.TrimSpace(precedence),
Resolution: "highest_precedence",
}
}
// resolveRuntimeSchemaCandidate is the only scalar resolver used while
// assembling the typed runtime contract. Call-site order is deliberately
// irrelevant: source rank selects the winner, values never do, and two
// disagreeing candidates at the same rank fail closed instead of silently
// depending on merge order.
func resolveRuntimeSchemaCandidate(field string, candidates ...runtimeSchemaFieldCandidate) (runtimeSchemaFieldCandidate, error) {
present := make([]runtimeSchemaFieldCandidate, 0, len(candidates))
for _, candidate := range candidates {
if candidate.Present {
candidate.Compared = nil
present = append(present, candidate)
}
}
if len(present) == 0 {
return runtimeSchemaFieldCandidate{}, nil
}
// Sort the complete candidate set, not just the winning rank. This keeps
// both winner selection and diagnostics independent from call-site order.
sort.Slice(present, func(i, j int) bool {
left, right := present[i], present[j]
if left.Rank != right.Rank {
return left.Rank > right.Rank
}
if left.Source != right.Source {
return left.Source < right.Source
}
if left.Precedence != right.Precedence {
return left.Precedence < right.Precedence
}
leftValue, _ := json.Marshal(left.Value)
rightValue, _ := json.Marshal(right.Value)
if comparison := bytes.Compare(leftValue, rightValue); comparison != 0 {
return comparison < 0
}
return left.ReviewReason < right.ReviewReason
})
// A higher-ranked winner must not hide an internally contradictory lower
// rank. Every precedence layer is a reviewed contract in its own right, so
// conflicting scalar values at any rank fail closed.
for start := 0; start < len(present); {
end := start + 1
for end < len(present) && present[end].Rank == present[start].Rank {
end++
}
reference := present[start]
for _, candidate := range present[start+1 : end] {
if !reflect.DeepEqual(candidate.Value, reference.Value) {
referenceValue, _ := json.Marshal(reference.Value)
candidateValue, _ := json.Marshal(candidate.Value)
return runtimeSchemaFieldCandidate{}, fmt.Errorf(
"%s has conflicting equal-precedence sources %s=%s and %s=%s",
strings.TrimSpace(field), reference.Source, referenceValue, candidate.Source, candidateValue,
)
}
}
start = end
}
winner := present[0]
winner.Compared = present
return winner, nil
}
// resolveRuntimeSchemaField keeps field resolution replaceable in focused
// tests without changing the deterministic production resolver.
var resolveRuntimeSchemaField = resolveRuntimeSchemaCandidate
// resolveRequiredProjection merges required candidates with a Cobra hard-required
// floor. Other Schema fields still use value-neutral resolveRuntimeSchemaCandidate;
// required alone cannot project optional when the executable flag is MarkFlagRequired.
func resolveRequiredProjection(cobraHard bool, candidates ...runtimeSchemaFieldCandidate) (runtimeSchemaFieldCandidate, error) {
winner, err := resolveRuntimeSchemaField("required", candidates...)
if err != nil {
return runtimeSchemaFieldCandidate{}, err
}
if !cobraHard {
return winner, nil
}
if required, _ := winner.Value.(bool); required {
return winner, nil
}
floor := runtimeSchemaCandidate(true, true, "cobra_hard_required")
floor.Resolution = "cobra_hard_required_floor"
compared := make([]runtimeSchemaFieldCandidate, 0, len(winner.Compared)+1)
compared = append(compared, floor)
for _, candidate := range winner.Compared {
if candidate.Source == "cobra_hard_required" {
continue
}
copyCandidate := candidate
copyCandidate.Compared = nil
compared = append(compared, copyCandidate)
}
floor.Compared = compared
return floor, nil
}
func runtimeSchemaFieldProvenance(candidate runtimeSchemaFieldCandidate) contract.FieldProvenance {
if !candidate.Present {
return contract.FieldProvenance{}
}
value, err := json.Marshal(candidate.Value)
if err != nil {
value = json.RawMessage("null")
}
provenance := contract.FieldProvenance{
Value: value,
Source: candidate.Source,
Precedence: candidate.Precedence,
Resolution: candidate.Resolution,
ReviewReason: candidate.ReviewReason,
}
compared := candidate.Compared
if len(compared) == 0 {
copyCandidate := candidate
copyCandidate.Compared = nil
compared = []runtimeSchemaFieldCandidate{copyCandidate}
}
provenance.Candidates = make([]contract.FieldCandidateProvenance, 0, len(compared))
for idx, item := range compared {
selected := idx == 0
value, err := json.Marshal(item.Value)
if err != nil {
// Runtime Schema candidates are closed scalar values (string/bool).
// Keep provenance structurally valid if a future adapter violates
// that contract; the resolved typed field remains authoritative.
value = json.RawMessage("null")
}
provenance.Candidates = append(provenance.Candidates, contract.FieldCandidateProvenance{
Value: value,
Source: item.Source,
Precedence: item.Precedence,
ReviewReason: item.ReviewReason,
Selected: &selected,
})
}
return provenance
}
func runtimeSchemaSourcePriority(source string) (int, string) {
switch strings.TrimSpace(source) {
case "reviewed_mapping_exclusion":
return runtimeSchemaRankMappingExclusion, runtimeSchemaPrecedenceMappingExclusion
case "require_one_of_constraint":
return runtimeSchemaRankConstraint, runtimeSchemaPrecedenceConstraint
case "versioned_parameter_binding":
return runtimeSchemaRankVersionedBinding, runtimeSchemaPrecedenceVersionedBinding
case "typed_parameter_metadata":
return runtimeSchemaRankTypedMetadata, runtimeSchemaPrecedenceTypedMetadata
case "native_annotation":
return runtimeSchemaRankNativeAnnotation, runtimeSchemaPrecedenceNativeAnnotation
case "cobra_hard_required", "cobra_nonzero_default", "cobra_flag_type", "cobra_usage":
if strings.TrimSpace(source) == "cobra_nonzero_default" {
return runtimeSchemaRankCobraDefault, runtimeSchemaPrecedenceCobra
}
return runtimeSchemaRankCobraContract, runtimeSchemaPrecedenceCobra
case "mcp_metadata", "pinned_mcp_metadata":
return runtimeSchemaRankMCP, runtimeSchemaPrecedenceMCP
case "cobra_help":
return runtimeSchemaRankCobraHelp, runtimeSchemaPrecedenceCobraHelp
case "flag_name_inference", "usage_required_inference", "usage_format_inference":
return runtimeSchemaRankInference, runtimeSchemaPrecedenceInference
case "metadata_source_resolution":
return runtimeSchemaRankDerived, runtimeSchemaPrecedenceDerived
case "default", "effect-default", "risk-default":
return runtimeSchemaRankDefault, runtimeSchemaPrecedenceDefault
default:
return runtimeSchemaRankDerived, "source_order"
}
}
func runtimeSchemaStringCandidate(value, source string) runtimeSchemaFieldCandidate {
value = strings.TrimSpace(value)
return runtimeSchemaCandidate(value, value != "", source)
}
func runtimeSchemaAnnotatedBoolCandidate(flag *pflag.Flag, annotation, source string) runtimeSchemaFieldCandidate {
raw := firstFlagAnnotation(flag, annotation)
if raw == "" {
return runtimeSchemaFieldCandidate{}
}
value, err := strconv.ParseBool(raw)
if err != nil {
return runtimeSchemaFieldCandidate{}
}
return runtimeSchemaCandidate(value, true, source)
}
func runtimeFlagCobraHardRequired(flag *pflag.Flag) bool {
return flag != nil && len(flag.Annotations[cobra.BashCompOneRequiredFlag]) > 0
}
func runtimeSchemaParameterMappingKey(canonicalPath, flagName string) string {
return strings.TrimSpace(canonicalPath) + " --" + strings.TrimSpace(flagName)
}
// runtimeSchemaParameterMappingCandidates resolves the two reviewed,
// versioned property-mapping inputs. An exclusion is an explicit statement
// that the CLI parameter is not a direct MCP property: it therefore supplies
// a present empty candidate (rather than allowing name inference to survive)
// and keeps the review reason in provenance.
func runtimeSchemaParameterMappingCandidates(snapshot schemaParameterBindingSnapshot, canonicalPath, flagName string) (runtimeSchemaFieldCandidate, runtimeSchemaFieldCandidate, error) {
binding := strings.TrimSpace(snapshot.Bindings[strings.TrimSpace(canonicalPath)][strings.TrimSpace(flagName)])
bindingCandidate := runtimeSchemaStringCandidate(binding, "versioned_parameter_binding")
reason, excluded := snapshot.MappingExclusions[runtimeSchemaParameterMappingKey(canonicalPath, flagName)]
if !excluded {
return bindingCandidate, runtimeSchemaFieldCandidate{}, nil
}
reason = strings.TrimSpace(reason)
if reason == "" {
return runtimeSchemaFieldCandidate{}, runtimeSchemaFieldCandidate{}, fmt.Errorf("reviewed mapping exclusion has no reason")
}
if binding != "" {
return runtimeSchemaFieldCandidate{}, runtimeSchemaFieldCandidate{}, fmt.Errorf("versioned binding %q conflicts with reviewed mapping exclusion", binding)
}
exclusionCandidate := runtimeSchemaCandidate("", true, "reviewed_mapping_exclusion")
exclusionCandidate.ReviewReason = reason
return runtimeSchemaFieldCandidate{}, exclusionCandidate, nil
}
// runtimeCommandParameterSpecs resolves every source into the typed contract
// model. Most fields use value-neutral source precedence: a higher-priority
// source may intentionally raise or lower type/mapping/description semantics.
// required is different: Cobra MarkFlagRequired is a hard floor that cannot be
// lowered by manual/hint overlays (see resolveRequiredProjection).
func runtimeCommandParameterSpecs(cmd *cobra.Command, canonicalPath string, pinnedParams map[string]embeddedMCPParamMeta, constraints RuntimeSchemaConstraints) ([]ParameterSpec, error) {
if cmd == nil {
return nil, nil
}
params := make([]ParameterSpec, 0)
var resolveErr error
metadata := runtimeSchemaParameterMetadataByCanonical[canonicalPath]
bindingSnapshot, err := schemaParameterBindingData()
if err != nil {
return nil, fmt.Errorf("load reviewed Schema parameter bindings: %w", err)
}
inherited := metadata.Inherited
visitRuntimeCommandFlags(cmd, inherited, func(flag *pflag.Flag) {
if resolveErr != nil || flag == nil || flag.Hidden || flag.Name == "help" || isGenericPayloadFlag(flag) {
return
}
bindingProperty, excludedProperty, err := runtimeSchemaParameterMappingCandidates(bindingSnapshot, canonicalPath, flag.Name)
if err != nil {
resolveErr = fmt.Errorf("flag --%s: %w", flag.Name, err)
return
}
propertyWinner, err := resolveRuntimeSchemaField("property",
excludedProperty,
bindingProperty,
runtimeSchemaStringCandidate(firstFlagAnnotation(flag, runtimeSchemaFlagBindingPropertyAnnotation), "versioned_parameter_binding"),
// ParamDecl.Property is authored on the leaf and applied at assembly
// via ApplyParamDecls. It outranks any residual versioned binding
// candidate; active bindings JSON rows are empty after Phase 2.
runtimeSchemaStringCandidateAtRank(
firstFlagAnnotation(flag, runtimeSchemaFlagPropertyAnnotation),
"native_annotation",
runtimeSchemaRankParamDeclProperty,
runtimeSchemaPrecedenceNativeAnnotation,
),
runtimeSchemaStringCandidate(lowerCamelFlagName(flag.Name), "flag_name_inference"),
)
if err != nil {
resolveErr = fmt.Errorf("flag --%s: %w", flag.Name, err)
return
}
property, _ := propertyWinner.Value.(string)
// pinnedParams remains for test fixtures that inject MCP-shaped maps;
// production assembly always passes an empty map (pin retired).
pinnedParam, hasPinnedParam := embeddedMCPParamMeta{}, false
if len(pinnedParams) > 0 && strings.TrimSpace(property) != "" {
pinnedParam, hasPinnedParam = lookupPinnedMCPParam(pinnedParams, property, flag.Name)
}
flagName := flag.Name
paramType := runtimeFlagCLIType(flag)
interfaceTypeCandidates := []runtimeSchemaFieldCandidate{
runtimeSchemaStringCandidate(firstFlagAnnotation(flag, runtimeSchemaFlagTypeAnnotation), "native_annotation"),
}
if hasPinnedParam {
interfaceTypeCandidates = append(interfaceTypeCandidates, runtimeSchemaStringCandidate(pinnedParam.Type, "mcp_metadata"))
}
interfaceTypeCandidates = append(interfaceTypeCandidates,
runtimeSchemaStringCandidateAtRank(paramType, "cobra_flag_type", runtimeSchemaRankInference, "fallback"),
)
interfaceTypeWinner, err := resolveRuntimeSchemaField("interface_type", interfaceTypeCandidates...)
if err != nil {
resolveErr = fmt.Errorf("flag --%s: %w", flag.Name, err)
return
}
interfaceType, _ := interfaceTypeWinner.Value.(string)
descriptionCandidates := []runtimeSchemaFieldCandidate{
runtimeSchemaStringCandidate(firstFlagAnnotation(flag, runtimeSchemaFlagDescriptionAnnotation), "native_annotation"),
runtimeSchemaStringCandidate(flag.Usage, "cobra_usage"),
}
if hasPinnedParam {
descriptionCandidates = append(descriptionCandidates, runtimeSchemaStringCandidate(pinnedParam.Description, "mcp_metadata"))
}
descriptionCandidates = append(descriptionCandidates, runtimeSchemaCandidate("", true, "default"))
descriptionWinner, err := resolveRuntimeSchemaField("description", descriptionCandidates...)
if err != nil {
resolveErr = fmt.Errorf("flag --%s: %w", flag.Name, err)
return
}
description, _ := descriptionWinner.Value.(string)
interfaceDescription := ""
if hasPinnedParam {
interfaceDescription = strings.TrimSpace(pinnedParam.Description)
}
// Required uses field-level safe merge: higher sources may raise required, but
// Cobra MarkFlagRequired cannot be projected away as optional.
constraintRequired := runtimeSchemaFieldCandidate{}
if runtimeSchemaRequireOneOfContains(constraints, flag.Name, flagName, property) {
constraintRequired = runtimeSchemaCandidate(false, true, "require_one_of_constraint")
}
usageRequired := usageImpliesRequired(flag.Usage)
cobraDefaultOptional := (runtimeFlagDefault(flag) != "" || usageImpliesDefault(flag.Usage)) && !usageRequired
typedRequired := false
for _, name := range metadata.Required {
if strings.TrimSpace(name) == flag.Name {
typedRequired = true
break
}
}
cobraHardRequired := runtimeFlagCobraHardRequired(flag)
requiredCandidates := []runtimeSchemaFieldCandidate{
constraintRequired,
runtimeSchemaCandidate(true, typedRequired, "typed_parameter_metadata"),
runtimeSchemaAnnotatedBoolCandidate(flag, runtimeSchemaFlagMetadataRequiredAnnotation, "typed_parameter_metadata"),
runtimeSchemaAnnotatedBoolCandidate(flag, runtimeSchemaFlagRequiredAnnotation, "native_annotation"),
runtimeSchemaCandidate(true, cobraHardRequired, "cobra_hard_required"),
runtimeSchemaCandidate(false, cobraDefaultOptional, "cobra_nonzero_default"),
runtimeSchemaCandidate(usageRequired, usageRequired, "usage_required_inference"),
}
if hasPinnedParam && pinnedParam.Required != nil {
requiredCandidates = append(requiredCandidates, runtimeSchemaCandidate(*pinnedParam.Required, true, "mcp_metadata"))
}
requiredCandidates = append(requiredCandidates, runtimeSchemaCandidate(false, true, "default"))
requiredWinner, err := resolveRequiredProjection(cobraHardRequired, requiredCandidates...)
if err != nil {
resolveErr = fmt.Errorf("flag --%s: %w", flag.Name, err)
return
}
if requiredWinner.Source == "default" {
requiredWinner.Resolution = "fallback"
}
required, _ := requiredWinner.Value.(bool)
fieldProvenance := map[string]contract.FieldProvenance{
"type": runtimeSchemaFieldProvenance(runtimeSchemaStringCandidate(paramType, "cobra_flag_type")),
"description": runtimeSchemaFieldProvenance(descriptionWinner),
"required": runtimeSchemaFieldProvenance(requiredWinner),
}
parameter := ParameterSpec{
Name: flagName,
Type: paramType,
Description: description,
Property: property,
Required: required,
CLIRequired: runtimeFlagCobraHardRequired(flag),
FieldProvenance: fieldProvenance,
}
// An explicit reviewed mapping exclusion is a present winner whose
// value is intentionally empty. Preserve its provenance even though
// the wire payload omits property; otherwise final delivery cannot
// distinguish reviewed absence from an accidentally dropped field.
if propertyWinner.Present {
fieldProvenance["property"] = runtimeSchemaFieldProvenance(propertyWinner)
}
if parameter.CLIRequired {
fieldProvenance["cli_required"] = runtimeSchemaFieldProvenance(
runtimeSchemaCandidate(true, true, "cobra_hard_required"),
)
}
if interfaceDescription != "" && interfaceDescription != description {
parameter.InterfaceDescription = interfaceDescription
}
if interfaceType != "" && interfaceType != paramType {
parameter.InterfaceType = interfaceType
fieldProvenance["interface_type"] = runtimeSchemaFieldProvenance(interfaceTypeWinner)
}
requiredWhenWinner, err := resolveRuntimeSchemaField("required_when",
runtimeSchemaStringCandidate(metadata.RequiredWhen[flag.Name], "typed_parameter_metadata"),
runtimeSchemaStringCandidate(firstFlagAnnotation(flag, runtimeSchemaFlagMetadataRequiredWhenAnnotation), "typed_parameter_metadata"),
runtimeSchemaStringCandidate(firstFlagAnnotation(flag, runtimeSchemaFlagRequiredWhenAnnotation), "native_annotation"),
runtimeSchemaStringCandidate(pinnedParam.RequiredWhen, "mcp_metadata"),
runtimeSchemaCandidate("", true, "default"),
)
if err != nil {
resolveErr = fmt.Errorf("flag --%s: %w", flag.Name, err)
return
}
requiredWhen, _ := requiredWhenWinner.Value.(string)
parameter.RequiredWhen = requiredWhen
fieldProvenance["required_when"] = runtimeSchemaFieldProvenance(requiredWhenWinner)
if def := runtimeFlagDefault(flag); def != "" {
parameter.Default = runtimeSchemaJSONString(def)
}
if hasPinnedParam {
interfaceDefault := strings.TrimSpace(pinnedParam.Default)
if interfaceDefault != "" && interfaceDefault != runtimeFlagDefault(flag) {
parameter.InterfaceDefault = runtimeSchemaJSONString(interfaceDefault)
}
}
formatWinner, err := resolveRuntimeSchemaField("format",
runtimeSchemaStringCandidate(metadata.Formats[flag.Name], "typed_parameter_metadata"),
runtimeSchemaStringCandidate(firstFlagAnnotation(flag, runtimeSchemaFlagMetadataFormatAnnotation), "typed_parameter_metadata"),
runtimeSchemaStringCandidate(firstFlagAnnotation(flag, "x-cli-format"), "native_annotation"),
runtimeSchemaStringCandidate(pinnedParam.Format, "mcp_metadata"),
runtimeSchemaStringCandidate(inferredRuntimeFlagFormat(flag), "usage_format_inference"),
runtimeSchemaCandidate("", true, "default"),
)
if err != nil {
resolveErr = fmt.Errorf("flag --%s: %w", flag.Name, err)
return
}
if format, _ := formatWinner.Value.(string); format != "" {
parameter.Format = format
fieldProvenance["format"] = runtimeSchemaFieldProvenance(formatWinner)
}
enumWinner, err := resolveRuntimeSchemaField("enum",
runtimeSchemaEnumCandidate(metadata.Enums[flag.Name], "typed_parameter_metadata"),
runtimeSchemaEnumCandidate(runtimeFlagEnumAnnotation(flag, runtimeSchemaFlagMetadataEnumAnnotation), "typed_parameter_metadata"),
runtimeSchemaEnumCandidate(runtimeFlagEnum(flag), "native_annotation"),
runtimeSchemaEnumCandidate(pinnedParam.Enum, "mcp_metadata"),
runtimeSchemaCandidate([]string{}, true, "default"),
)
if err != nil {
resolveErr = fmt.Errorf("flag --%s: %w", flag.Name, err)
return
}
if enum, _ := enumWinner.Value.([]string); len(enum) > 0 {
parameter.Enum = append([]string(nil), enum...)
fieldProvenance["enum"] = runtimeSchemaFieldProvenance(enumWinner)
}
exampleWinner, err := resolveRuntimeSchemaField("example",
runtimeSchemaStringCandidate(metadata.Examples[flag.Name], "typed_parameter_metadata"),
runtimeSchemaStringCandidate(firstFlagAnnotation(flag, runtimeSchemaFlagMetadataExampleAnnotation), "typed_parameter_metadata"),
runtimeSchemaStringCandidate(firstFlagAnnotation(flag, runtimeSchemaFlagExampleAnnotation), "native_annotation"),
runtimeSchemaCandidate("", true, "default"),
)
if err != nil {
resolveErr = fmt.Errorf("flag --%s: %w", flag.Name, err)
return
}
if example, _ := exampleWinner.Value.(string); example != "" {
parameter.Example = runtimeSchemaJSONString(example)
fieldProvenance["example"] = runtimeSchemaFieldProvenance(exampleWinner)
}
params = append(params, parameter)
})
if resolveErr != nil {
return nil, resolveErr
}
if len(params) == 0 {
return nil, nil
}
sort.Slice(params, func(i, j int) bool { return params[i].Name < params[j].Name })
return params, nil
}
func runtimeSchemaJSONString(value string) json.RawMessage {
encoded, _ := json.Marshal(value)
return encoded
}
// runtimeCommandParameters is the compatibility wire adapter for callers that
// have not yet moved to ToolSpec. Resolution happens only in the typed path;
// this wrapper serializes the resulting ParameterSpecs without re-merging or
// re-interpreting any source.
var runtimeCommandParameterSpecsForPayload = runtimeCommandParameterSpecs
func runtimeCommandParameters(cmd *cobra.Command, canonicalPath string, pinnedParams map[string]embeddedMCPParamMeta, constraints RuntimeSchemaConstraints) (map[string]any, error) {
specs, err := runtimeCommandParameterSpecsForPayload(cmd, canonicalPath, pinnedParams, constraints)
if err != nil {
return nil, err
}
if len(specs) == 0 {
return nil, nil
}
parameters := make(map[string]any, len(specs))
for _, spec := range specs {
payload, payloadErr := spec.ToPayload()
if payloadErr != nil {
return nil, fmt.Errorf("serialize Schema parameter %q: %w", spec.Name, payloadErr)
}
parameters[spec.Name] = payload
}
return parameters, nil
}
func runtimeSchemaRequireOneOfContains(constraints RuntimeSchemaConstraints, names ...string) bool {
wanted := map[string]bool{}
for _, name := range names {
if name = strings.TrimSpace(name); name != "" {
wanted[name] = true
}
}
for _, group := range constraints.RequireOneOf {
for _, name := range group {
if wanted[strings.TrimSpace(name)] {
return true
}
}
}
return false
}
func runtimeCommandFlag(cmd *cobra.Command, name string) *pflag.Flag {
return runtimeannotate.CommandFlag(cmd, name)
}
func visitRuntimeCommandFlags(cmd *cobra.Command, inheritedNames []string, visit func(*pflag.Flag)) {
if cmd == nil || visit == nil {
return
}
root := cmd.Root()
rootPersistent := map[*pflag.Flag]bool{}
ancestorPersistent := map[*pflag.Flag]bool{}
if root != nil {
root.PersistentFlags().VisitAll(func(flag *pflag.Flag) {
rootPersistent[flag] = true
})
}
for parent := cmd.Parent(); parent != nil && parent != root; parent = parent.Parent() {
parent.PersistentFlags().VisitAll(func(flag *pflag.Flag) {
ancestorPersistent[flag] = true
})
}
allowedInherited := map[string]bool{}
for _, name := range inheritedNames {
if name = strings.TrimSpace(name); name != "" {
allowedInherited[name] = true
}
}
seen := map[string]bool{}
visitSet := func(flags *pflag.FlagSet) {
flags.VisitAll(func(flag *pflag.Flag) {
if flag == nil || rootPersistent[flag] || seen[flag.Name] ||
(ancestorPersistent[flag] && !allowedInherited[flag.Name]) {
return
}
seen[flag.Name] = true
visit(flag)
})
}
visitSet(cmd.Flags())
visitSet(cmd.PersistentFlags())
for parent := cmd.Parent(); parent != nil && parent != root; parent = parent.Parent() {
parent.PersistentFlags().VisitAll(func(flag *pflag.Flag) {
if flag != nil && allowedInherited[flag.Name] && !seen[flag.Name] {
seen[flag.Name] = true
visit(flag)
}
})
}
}
func runtimeCommandConstraints(cmd *cobra.Command) RuntimeSchemaConstraints {
return runtimeannotate.CommandConstraints(cmd)
}
func runtimeCommandPositionals(cmd *cobra.Command) []contract.RuntimeSchemaPositional {
return runtimeannotate.CommandPositionals(cmd)
}
func normalizeRuntimeSchemaConstraints(constraints RuntimeSchemaConstraints) RuntimeSchemaConstraints {
return runtimeannotate.NormalizeConstraints(constraints)
}
func normalizeRuntimeSchemaGroups(groups [][]string, minimum int) [][]string {
// Test-facing thin wrapper over NormalizeConstraints group rules.
c := RuntimeSchemaConstraints{}
switch minimum {
case 1:
c.RequireOneOf = groups
default:
c.MutuallyExclusive = groups
}
out := runtimeannotate.NormalizeConstraints(c)
if minimum == 1 {
return out.RequireOneOf
}
return out.MutuallyExclusive
}
func runtimeSchemaConstraintsEmpty(constraints RuntimeSchemaConstraints) bool {
return runtimeannotate.ConstraintsEmpty(constraints)
}
func lookupPinnedMCPParam(params map[string]embeddedMCPParamMeta, property, flagName string) (embeddedMCPParamMeta, bool) {
if len(params) == 0 {
return embeddedMCPParamMeta{}, false
}
if meta, ok := params[property]; ok {
return meta, true
}
if meta, ok := params[flagName]; ok {
return meta, true
}
return embeddedMCPParamMeta{}, false
}
func isGenericPayloadFlag(flag *pflag.Flag) bool {
if flag == nil {
return false
}
switch flag.Name {
case "json":
return strings.TrimSpace(flag.Usage) == "Base JSON object payload for this tool invocation"
case "params":
return strings.TrimSpace(flag.Usage) == "Additional JSON object payload merged after --json"
default:
return false
}
}
func runtimeFlagCLIType(flag *pflag.Flag) string {
switch flag.Value.Type() {
case "int", "int8", "int16", "int32", "int64",
"uint", "uint8", "uint16", "uint32", "uint64", "count":
return "integer"
case "float32", "float64":
return "number"
case "bool":
return "boolean"
case "stringSlice", "stringArray", "intSlice", "int32Slice", "int64Slice",
"uintSlice", "float32Slice", "float64Slice", "boolSlice", "durationSlice":
return "array"
default:
return "string"
}
}
func runtimeFlagRequiredState(flag *pflag.Flag) (bool, bool) {
// This helper reports the projected Schema annotation first. Cobra's
// executable marker is retained as a lower-priority observation; the typed
// contract exposes both candidates when an explicit overlay lowers it.
if raw := firstFlagAnnotation(flag, runtimeSchemaFlagRequiredAnnotation); raw != "" {
required, err := strconv.ParseBool(raw)
if err == nil {
return required, true
}
}
if runtimeFlagCobraHardRequired(flag) {
return true, true
}
usage := strings.ToLower(strings.TrimSpace(flag.Usage))
if usageImpliesRequired(usage) {
return true, true
}
return false, false
}
func usageImpliesRequired(usage string) bool {
usage = strings.ToLower(strings.TrimSpace(usage))
if usage == "" {
return false
}
for _, conditional := range []string{
"可选", "时必填", "下必填", "二选一", "至少传一个", "至少填一个", "至少提供一项",
"at least one", "required when", "required if", "conditionally required",
} {
if strings.Contains(usage, conditional) {
return false
}
}
return strings.Contains(usage, "required") || strings.Contains(usage, "必填")
}
func usageImpliesDefault(usage string) bool {
usage = strings.ToLower(strings.TrimSpace(usage))
return strings.Contains(usage, "默认") || strings.Contains(usage, "default")
}
func lowerCamelFlagName(flagName string) string {
flagName = strings.TrimSpace(flagName)
parts := strings.FieldsFunc(flagName, func(r rune) bool { return r == '-' || r == '_' })
if len(parts) == 0 {
return flagName
}
if len(parts) == 1 {
return parts[0]
}
for i := range parts {
parts[i] = strings.TrimSpace(parts[i])
}
out := strings.ToLower(parts[0])
for _, part := range parts[1:] {
lower := strings.ToLower(part)
out += strings.ToUpper(lower[:1]) + lower[1:]
}
return out
}
func runtimeFlagDefault(flag *pflag.Flag) string {
def := strings.TrimSpace(flag.DefValue)
if def == "" || def == "0s" || def == "[]" || def == "{}" {
return ""
}
switch flag.Value.Type() {
case "bool":
if def == "false" {
return ""
}
case "int", "int8", "int16", "int32", "int64",
"uint", "uint8", "uint16", "uint32", "uint64", "count",
"float32", "float64":
if def == "0" {
return ""
}
}
return def
}
func firstFlagAnnotation(flag *pflag.Flag, key string) string {
if flag == nil || flag.Annotations == nil {
return ""
}
values := flag.Annotations[key]
if len(values) == 0 {
return ""
}
return strings.TrimSpace(values[0])
}
func runtimeFlagEnum(flag *pflag.Flag) []string {
return runtimeFlagEnumAnnotation(flag, "x-cli-enum")
}
func runtimeFlagEnumAnnotation(flag *pflag.Flag, annotation string) []string {
if flag == nil || flag.Annotations == nil {
return nil
}
values := flag.Annotations[annotation]
if len(values) == 0 {
return nil
}
out := make([]string, 0, len(values))
for _, value := range values {
if value = strings.TrimSpace(value); value != "" {
out = append(out, value)
}
}
return out
}
func runtimeSchemaEnumCandidate(values []string, source string) runtimeSchemaFieldCandidate {
// Normalize at the candidate boundary exactly as ParameterSpec does. This
// keeps the selected provenance value byte-for-byte aligned with the final
// delivery even when an authored enum repeats a value.
clean := stableUniqueStrings(values)
return runtimeSchemaCandidate(clean, len(clean) > 0, source)
}
func inferredRuntimeFlagFormat(flag *pflag.Flag) string {
if flag == nil {
return ""
}
usage := strings.ToLower(strings.TrimSpace(flag.Usage))
if strings.Contains(usage, "iso-8601") || strings.Contains(usage, "rfc3339") {
return "date-time"
}
if strings.Contains(usage, "a1") {
return "a1-range"
}
return ""
}
func strconvQuote(value string) string {
return "\"" + strings.ReplaceAll(value, "\"", "\\\"") + "\""
}
// ─── --compact mode ──────────────────────────────────────────────────────────
// schemaCompactStripKeys are top-level tool/product keys removed in --compact mode.
var schemaCompactStripKeys = map[string]bool{
// provenance / debug
"agent_metadata_source": true,
"agent_source_refs": true,
"agent_summary_source": true,
"effect_source": true,
"metadata_source": true,
"source": true,
"agent_metadata": true,
"field_provenance": true,
"reviewed": true,
// redundant with canonical_path / cli_path
"name": true,
"path": true,
"cli_name": true,
"primary_cli_path": true,
"is_alias": true,
"has_parameters": true,
"parameter_count": true,
"product_id": true,
"display": true,
"title": true,
"group": true,
"source_product_id": true,
"aliases": true,
"catalog_hash": true,
"surface_hash": true,
"workflow_refs": true,
"prerequisites": true,
"tips": true,
"interface_ref": true,
}
// schemaCompactParamStripKeys are per-parameter keys removed in --compact mode.
var schemaCompactParamStripKeys = map[string]bool{
"interface_description": true,
"interface_type": true,
"property": true,
"field_provenance": true,
}
// stripSchemaPayloadCompact walks a schema payload map and removes provenance,
// debug and redundant keys so that only agent-essential fields remain.
// It operates recursively on nested maps, slices, and parameter objects.
func stripSchemaPayloadCompact(payload map[string]any) map[string]any {
if payload == nil {
return nil
}
result := make(map[string]any, len(payload))
for k, v := range payload {
if schemaCompactStripKeys[k] {
continue
}
if k == "parameters" {
result[k] = stripSchemaParametersCompact(v)
continue
}
result[k] = stripSchemaValueCompact(v)
}
return result
}
func stripSchemaParametersCompact(value any) any {
parameters, ok := value.(map[string]any)
if !ok {
return stripSchemaValueCompact(value)
}
result := make(map[string]any, len(parameters))
for name, raw := range parameters {
parameter, ok := raw.(map[string]any)
if !ok {
result[name] = stripSchemaValueCompact(raw)
continue
}
// Parameter names are contract data. They may legitimately be
// "name", "path", "source", or another key that is redundant only
// at tool/product level, so never run them through the top-level key
// filter.
result[name] = stripSchemaParamCompact(parameter)
}
return result
}
func stripSchemaValueCompact(v any) any {
switch val := v.(type) {
case map[string]any:
// Check if this looks like a parameter object (has "type" or "required" or "description")
_, isParam := val["required"]
if !isParam {
_, isParam = val["type"]
}
if isParam {
return stripSchemaParamCompact(val)
}
return stripSchemaPayloadCompact(val)
case []map[string]any:
result := make([]map[string]any, len(val))
for i, item := range val {
result[i] = stripSchemaPayloadCompact(item)
}
return result
case []any:
result := make([]any, len(val))
for i, item := range val {
result[i] = stripSchemaValueCompact(item)
}
return result
default:
return v
}
}
func stripSchemaParamCompact(param map[string]any) map[string]any {
result := make(map[string]any, len(param))
for k, v := range param {
if schemaCompactParamStripKeys[k] {
continue
}
result[k] = v
}
return result
}