fix(pm-product): second review round — bad --as-of exits 2, real --sample on the two fixed tools, ost_linter docstring exception

- jira_snapshot_bridge.py: a malformed --as-of now refuses with exit 2 instead of
  raising TypeError (same guard as discovery_cadence_tracker).
- user_story_generator.py / persona_generator.py: add a real --sample flag so the
  harness manifests can smoke-test them (supports_sample now true; product-team
  manifest regenerated).
- ost_linter.py: document the --sample-always-exits-0 exception in the exit-code
  contract.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019Uzm8dKoeXPayJVMojpSbw
This commit is contained in:
Claude 2026-07-03 13:30:29 +00:00
parent 5c811661c9
commit 261c158eaf
No known key found for this signature in database
5 changed files with 24 additions and 2 deletions

View file

@ -21,12 +21,17 @@
{
"script": "product-team/agile-product-owner/skills/agile-product-owner/scripts/user_story_generator.py",
"wired": true,
"supports_sample": false,
"supports_sample": true,
"verification": [
{
"cmd": "python3 product-team/agile-product-owner/skills/agile-product-owner/scripts/user_story_generator.py --help",
"expect_exit": 0,
"kind": "smoke"
},
{
"cmd": "python3 product-team/agile-product-owner/skills/agile-product-owner/scripts/user_story_generator.py --sample",
"expect_exit": 0,
"kind": "sample"
}
]
}
@ -587,12 +592,17 @@
{
"script": "product-team/skills/ux-researcher-designer/scripts/persona_generator.py",
"wired": true,
"supports_sample": false,
"supports_sample": true,
"verification": [
{
"cmd": "python3 product-team/skills/ux-researcher-designer/scripts/persona_generator.py --help",
"expect_exit": 0,
"kind": "smoke"
},
{
"cmd": "python3 product-team/skills/ux-researcher-designer/scripts/persona_generator.py --sample",
"expect_exit": 0,
"kind": "sample"
}
]
}

View file

@ -336,6 +336,9 @@ def main():
"a sprint from that backlog (default: epic).")
parser.add_argument("capacity", nargs="?", type=int, default=30,
help="Sprint capacity in story points (sprint mode, default: 30).")
parser.add_argument("--sample", action="store_true",
help="Break the bundled sample epic into stories and exit 0 "
"(same as the default epic mode; kept for harness smoke tests).")
args = parser.parse_args()
generator = UserStoryGenerator()

View file

@ -29,6 +29,8 @@ Input JSON (see --sample):
}
Exit codes: 0 clean (warnings allowed) · 2 violations found · 3 unreadable input.
Exception: `--sample` always exits 0 it is a smoke test, and the bundled tree
deliberately contains one O2 and one O4 violation so the report output is visible.
Stdlib only, deterministic.
"""

View file

@ -551,6 +551,9 @@ def main():
help="Output format (flag form, overrides the positional).")
parser.add_argument("--seed", type=int, default=42,
help="RNG seed for deterministic persona names (default: 42).")
parser.add_argument("--sample", action="store_true",
help="Generate the bundled sample persona and exit 0 "
"(same as the default run; kept for harness smoke tests).")
args = parser.parse_args()
output = args.output_flag or args.format

View file

@ -269,6 +269,10 @@ def main() -> int:
as_of = parse_date(args.as_of) if args.as_of else max(
(i["resolved"] or i["created"]) for i in issues)
if as_of is None:
print(f"ERROR: --as-of '{args.as_of}' is not a valid YYYY-MM-DD date.",
file=sys.stderr)
return 2
report = flow_report(issues, as_of, args.sle_days, args.forecast, args.seed)
print(json.dumps(report, indent=2))
return 0