diff --git a/docs/schema-command-issue-fixes.md b/docs/schema-command-issue-fixes.md index ca0befbe..6a65c770 100644 --- a/docs/schema-command-issue-fixes.md +++ b/docs/schema-command-issue-fixes.md @@ -60,3 +60,10 @@ This document records issues found while packaging, building, and executing comm - Cause: the smoke harness had generic JSON samples and did not know which commands require non-empty objects or arrays. - Fix: Generated non-empty record payloads and command-specific non-empty JSON samples for aitable aggregate/card/field-widths/timebar updates. - Verification: targeted smoke for the remaining 20 paths passed 20/20, and the rebuilt CLI passed full smoke 359/359. + +### Issue 8: mail user smoke depended on bound mailbox auto-detection + +- Symptom: `mail.search_mail_users` failed in dry-run smoke on accounts without an enterprise mailbox, even after `dws auth login`, because the command attempted mailbox auto-detection when `--email` was omitted. +- Cause: schema correctly marks `email` as optional for normal use, but the smoke harness used required parameters only; this made dry-run depend on the tester account's mailbox binding. +- Fix: Added a smoke-only extra flag rule so `mail.search_mail_users` supplies a sample `--email` while leaving the runtime schema unchanged. +- Verification: `dws mail user search --email user@example.com --keyword keyword-smoke --dry-run --yes --format json` passed; full smoke passed 359/359 after this fix. diff --git a/scripts/dev/schema_command_smoke.py b/scripts/dev/schema_command_smoke.py index 56e077b7..b1c9801f 100644 --- a/scripts/dev/schema_command_smoke.py +++ b/scripts/dev/schema_command_smoke.py @@ -161,14 +161,23 @@ def value_for(flag: str, param: dict[str, Any], canonical_path: str) -> str | No return scalar_value(flag, param, canonical_path) +def smoke_extra_flags(canonical_path: str) -> set[str]: + # Avoid environment-dependent auto-detection in dry-run smoke. The command + # accepts --email as optional, but without it the CLI probes the bound mailbox. + return { + "mail.search_mail_users": {"email"}, + }.get(canonical_path, set()) + + def build_command(binary: str, leaf: dict[str, Any], include_optional: bool) -> list[str]: cli_path = str(leaf["cli_path"]) canonical_path = str(leaf.get("canonical_path", "")) + extra_flags = smoke_extra_flags(canonical_path) argv = [binary, *shlex.split(cli_path)] params = leaf.get("parameters") or {} for flag in sorted(params): param = params[flag] or {} - if not include_optional and not bool(param.get("required")): + if not include_optional and not bool(param.get("required")) and flag not in extra_flags: continue if str(param.get("type", "")).lower() == "boolean": argv.append(f"--{flag}")