feat(corecmd): add declarative Wait capability (Contract.Wait + wait phase)
Framework-only: adds the reviewed wait contract mirroring the DryRunSpec
pattern (types declaration -> ContractDecl -> ContractFinal -> ToolSpec ->
Schema wait key). No business command declares it yet.
- contract.WaitSpec (mode poll/event/auto, poll_command, status_query,
terminal status->success/failure map, pending_values, event_key,
match_field, default_timeout_secs) with closed-set Validate
- Spec.WaitPoll hook pairs with the declaration at construction time
(declared without hook / hook without declaration both panic)
- declared leaves register --wait / --wait-timeout natively (never
FlagSpec, so they cannot enter MCP toolArgs); undeclared leaves reject
the flags as unknown instead of ignoring them
- internal/wait engine: immediate-first-poll, x1.5 backoff capped 30s,
dotted status extraction, fail-closed on unknown status, timeout ->
pending
- ResultInvoke path closes the unified envelope: success terminal ->
success, failure terminal -> failure with new wire-stable
error.type "wait" (exit code 8, additive like partial=7), timeout ->
pending + meta.operation.timed_out with last observed state (exit 0)
- output.WithOutcome / WithErrorInfo / WithOperationTimedOut preserve
envelope invariants (I2/I3, pending requires meta.operation)
Verified: go test ./... green; check-generated-drift.sh ok (schema
assembly deterministic, wire unchanged); check-schema-catalog.sh ok
(27 products, 1121 tools).