make_spec(){# dir (spec with 2-row table; row 2 has \| and regex chars)
mkdir -p "$1"
cat > "$1/spec.md"<<'EOF'
# Widget Design
## Requirements
Widgets render a table with a TOTAL row.
## E2E scenario cards
| Card | Covers | Falsification |
| --- | --- | --- |
| widget-show-table | Rendered table incl. TOTAL row | If stdout's last line is not `TOTAL` followed by the two-decimal sum (20.85 for the seed fixture), or the TOTAL row is absent entirely, the scenario FAILS. |
| widget-status-flags | Status output | If `widget status` does not print exactly `OK \| DEGRADED` (a literal pipe) with dots . and stars * intact, the scenario FAILS. |
EOF
}
good_card_1(){
cat <<'EOF'
# widget-show-table: table renders with TOTAL
**What this covers**: the rendered table.
## Pre-state
A built widget binary.
## Steps
1. Run `widget show`.
## Expected
If stdout's last line is not `TOTAL` followed by the
two-decimal sum (20.85 for the seed
fixture), or the TOTAL row is absent entirely, the scenario FAILS.
## Cleanup
Nothing to clean.
EOF
}
good_card_2(){
cat <<'EOF'
# widget-status-flags: status output
**What this covers**: status flags.
## Pre-state
A built widget binary.
## Steps
1. Run `widget status`.
## Expected
If `widget status` does not print exactly `OK | DEGRADED` (a literal pipe) with dots . and stars * intact, the scenario FAILS.
**What this covers**: If stdout's last line is not `TOTAL` followed by the two-decimal sum (20.85 for the seed fixture), or the TOTAL row is absent entirely, the scenario FAILS.
## Pre-state
A built widget binary.
## Steps
1. Run `widget show`.
## Expected
The widget prints a friendly banner and exits zero.
## Cleanup
Nothing to clean.
EOF
assert_exit 1"line only outside Expected -> exit 1"\