diff --git a/cmd/mesh-controller/seatverbs.go b/cmd/mesh-controller/seatverbs.go index 2f2e47f6..92e42822 100644 --- a/cmd/mesh-controller/seatverbs.go +++ b/cmd/mesh-controller/seatverbs.go @@ -1367,7 +1367,10 @@ var commandReadForms = map[string]func(rest []string) bool{ // `plan ` previews a node's declaration; it sends nothing. "plan": func([]string) bool { return true }, // `plans` lists and `plans ` shows one; `plans stop|close|go` acts. - "plans": func(r []string) bool { return !subIn(r, "stop", "close", "go") }, + // Judged on every word, not the first: a flag before the subcommand (`plans --json go `) still acts. + "plans": func(r []string) bool { + return !slices.ContainsFunc(r, func(w string) bool { return slices.Contains(plansActs, w) }) + }, // `doctor` answers the last run, `probes` and `signals` describe; `doctor run` runs. "doctor": func(r []string) bool { return flagsOnly(r) || subIn(r, "probes", "signals") }, "conditions": func(r []string) bool { return flagsOnly(r) || subIn(r, "list", "show", "history") }, @@ -1388,6 +1391,9 @@ var commandReadForms = map[string]func(rest []string) bool{ }, } +// plansActs are the `plans` subcommands that act on a walk; no other word of a plans line is one of them. +var plansActs = []string{"go", "stop", "close", "retry"} + // heldAtTheTerminal is a refusal of policy (novox/hq ADR 0266): the verb is known and served, and this line is // the operator's at the controller's terminal. Never read as a verb this binary is behind on. type heldAtTheTerminal struct{ msg string } diff --git a/cmd/mesh-controller/seatverbs_test.go b/cmd/mesh-controller/seatverbs_test.go index 9a6643ab..e1a5bf24 100644 --- a/cmd/mesh-controller/seatverbs_test.go +++ b/cmd/mesh-controller/seatverbs_test.go @@ -369,7 +369,8 @@ func TestTheCommandVerbOnlyReads(t *testing.T) { "secret recover a", "secret export a", "token issue --new x", "identity show", "broker users", "api key", "licence show", "push anchor --why w", "assign novox m", "settings set m {}", "settings clear m", "module add f", "module check /etc", "module forget m", "module issue m --node a", - "seat rename a b", "plans close p --why w", "plans go p", "doctor run", "conditions silence c --why w", + "seat rename a b", "plans close p --why w", "plans go p", "plans retry p", "plans stop p", + "plans --json go p", "plans -n 3 close p", "plans --what-if r retry p", "doctor run", "conditions silence c --why w", "retire approve x", "cleanup delete x", "delivery check", "delivery go x", "bus upgrade", "mirrors --record x", "mirrors --confirm", "hand-act record x --why y --cause z", "serve", "migrate", "prepare", "declare x", "overlay x", "facts", "merge-gate", "check-here", "build x", "rebuild x",