FastForm Task 11: single-shot fire CLI (Phases 0–4 complete) - #2
Conversation
Assembles the pipeline into `python3 -m fastform.fire --url ...`: resolve the Chrome profile (required; refuses to guess, lists accounts if unset), read cookies live from Chrome, GET on a warm connection, check sign-in before parsing, match, compile with token/tag, POST once, classify. Updated from the plan's original which used the now-dead static cookies.load() and config/cookies.txt. Adds an explicit --profile override and a CONFIG exit code (7) for the no-profile / cookie-error paths. Verified live end to end against F1: outcome RECORDED, status 200, exit 0, submitting as 6622781084@g.siit.tu.ac.th on Profile 1. Single-shot by construction — no retry path, since there is no server-side duplicate protection and the RECORDED stop is the only safeguard. 12 fire tests (decide_exit total coverage + load_profile); full suite green. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HvAS3iP5DJxYkmGuwXadoL
Two Important findings from the Task 11 review: - conn.connect() was outside the try/finally, so a socket failure at connect time escaped as an unhandled traceback with no classified exit and no guaranteed close(). connect() is now inside the try, and an except OSError returns UNDETERMINED (exit 5) with a check-the-sheet warning — conservative by design, since erring toward "verify" never risks the duplicate an automatic resend would. - README was still the 11-byte stub. Written properly: the live-cookie model, Chrome profile selection, usage, the exit-code table, and status. The plan's own README template was stale (referenced the abandoned config/cookies.txt), so this is accurate to what shipped, not a copy of it. Re-verified live end to end against F1 after the change: RECORDED, exit 0. Full suite green (105 tests). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HvAS3iP5DJxYkmGuwXadoL
There was a problem hiding this comment.
🟡 Changes recommended
There are several correctness/documentation issues that can cause crashes or non-runnable instructions (URL/host handling in fire.py, config parsing robustness, and README referencing a missing dryrun script).
Once you've addressed the issues Copilot identified, you can request another Copilot review.
This review doesn't count toward merge requirements. Sign up for the private preview to control whether Copilot approvals count.
Pull request overview
Adds the fastform.fire single-command CLI that wires the existing phases 0–4 pipeline into a one-shot “GET → auth check → parse → match → compile → POST → classify” execution flow, plus documentation and small unit tests to support the new entrypoint.
Changes:
- Introduces
fastform/fire.pywith CLI args, exit-code mapping, Chrome profile resolution, live cookie read, and single-shot submit/classify flow. - Adds unit tests for exit-code mapping and
profile.tomlreading behavior. - Expands README usage/setup guidance and updates the phase plan doc to reflect the new CLI and tests.
File summaries
| File | Description |
|---|---|
fastform/fire.py |
New CLI entrypoint that connects transport, parsing, matching, compile/build, and classification into a single-shot runner. |
tests/test_fire.py |
Adds unit tests for decide_exit() and load_profile() behavior. |
README.md |
Documents setup, usage, and exit codes for the CLI. |
docs/superpowers/plans/2026-08-05-fastform-phases-0-4.md |
Updates the plan doc’s embedded snippets to match the implemented CLI/tests. |
Review details
- Files reviewed: 4/4 changed files
- Comments generated: 5
- Review effort level: Lite
We're testing this review assessment. Please use 👍 or 👎 to tell us if it's correct.
| if not path.exists(): | ||
| return None | ||
| data = tomllib.loads(path.read_text(encoding="utf-8")) | ||
| value = data.get("chrome", {}).get("profile") | ||
| return value or None |
| parts = urllib.parse.urlsplit(args.url) | ||
| conn = WarmConnection(parts.netloc) | ||
| try: |
| try: | ||
| spec = parse.parse(page.body, args.url) | ||
| except parse.NotParseable as exc: | ||
| print(f"NOT PARSEABLE: {exc}") |
| def _write(self, text): | ||
| p = Path(tempfile.mkdtemp()) / "profile.toml" | ||
| p.write_text(text, encoding="utf-8") | ||
| return p |
| ```bash | ||
| # Build the request and print it, sending nothing: | ||
| python3 tools/dryrun.py --url <viewform-url> | ||
|
|
||
| # Fill and submit, exactly once: | ||
| python3 -m fastform.fire --url <viewform-url> | ||
| ``` |
Completes Phases 0–4: wires the pipeline (merged in #1) into a single runnable
command,
python3 -m fastform.fire.What it does
Resolve the Chrome profile → read cookies live from Chrome → GET the form on a
warm connection → check sign-in → parse → match answers → compile with the
scraped token/tag → POST once → classify the outcome. A
dryrun.pycompanionbuilds and prints the request without sending.
Verified live end to end against the real test form:
outcome RECORDED,HTTP 200, exit 0.
Design decisions worth noting
protection (no
fbzxdedupe; "limit to 1 response" does not bind a directPOST), so a second send is a real duplicate row. The
RECORDEDstop is theonly safeguard, so exactly one
send()exists and every failure branchreturns before it.
several Chrome profiles on different accounts; submitting as the wrong one is
unrecoverable. With none set, it lists the available accounts and exits 7.
every few minutes, so a captured header is useless within ~20 minutes.
HTTP 200 with the full structure rather than redirecting.
Exit codes
0recorded ·1rejected ·2not parseable ·3closed ·4auth failed ·5undetermined (check the sheet) ·6gaps/blockers (nothing sent) ·7config (no profile / cookies unreadable).Tests
105 tests, stdlib
unittest, no network (local server for transport, fixturesfor everything else).
Review
Reviewed; two Important findings fixed in this branch:
connect()is now insidethe
try/finallywith anOSErrorhandler returning a classified exit, and theREADME is written accurately (setup, profile selection, usage, exit codes). One
follow-up for the final review: a unit test for the connect-failure branch.
🤖 Generated with Claude Code
https://claude.ai/code/session_01HvAS3iP5DJxYkmGuwXadoL