Skip to content

FastForm Task 11: single-shot fire CLI (Phases 0–4 complete) - #2

Merged
SupaOhm merged 2 commits into
mainfrom
task-11-fire
Aug 6, 2026
Merged

FastForm Task 11: single-shot fire CLI (Phases 0–4 complete)#2
SupaOhm merged 2 commits into
mainfrom
task-11-fire

Conversation

@SupaOhm

@SupaOhm SupaOhm commented Aug 6, 2026

Copy link
Copy Markdown
Owner

Completes Phases 0–4: wires the pipeline (merged in #1) into a single runnable
command, python3 -m fastform.fire.

What it does

python3 -m fastform.fire --url <viewform-url> --profile "Profile 1"

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.py companion
builds 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

  • Single-shot, no retry path. Measurement found no server-side duplicate
    protection (no fbzx dedupe; "limit to 1 response" does not bind a direct
    POST), so a second send is a real duplicate row. The RECORDED stop is the
    only safeguard, so exactly one send() exists and every failure branch
    returns before it.
  • Profile is required — the tool refuses to guess. A machine may have
    several Chrome profiles on different accounts; submitting as the wrong one is
    unrecoverable. With none set, it lists the available accounts and exits 7.
  • Cookies are read live, never cached — Chrome rotates the session token
    every few minutes, so a captured header is useless within ~20 minutes.
  • Sign-in is checked before parsing, because a signed-out form returns
    HTTP 200 with the full structure rather than redirecting.

Exit codes

0 recorded · 1 rejected · 2 not parseable · 3 closed · 4 auth failed ·
5 undetermined (check the sheet) · 6 gaps/blockers (nothing sent) ·
7 config (no profile / cookies unreadable).

Tests

105 tests, stdlib unittest, no network (local server for transport, fixtures
for everything else).

Review

Reviewed; two Important findings fixed in this branch: connect() is now inside
the try/finally with an OSError handler returning a classified exit, and the
README 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

ohm and others added 2 commits August 6, 2026 11:07
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
Copilot AI lite review requested due to automatic review settings August 6, 2026 04:15
@SupaOhm
SupaOhm merged commit 1f0b425 into main Aug 6, 2026
1 check passed

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 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.py with 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.toml reading 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.

Comment thread fastform/fire.py
Comment on lines +58 to +62
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
Comment thread fastform/fire.py
Comment on lines +113 to +115
parts = urllib.parse.urlsplit(args.url)
conn = WarmConnection(parts.netloc)
try:
Comment thread fastform/fire.py
Comment on lines +130 to +133
try:
spec = parse.parse(page.body, args.url)
except parse.NotParseable as exc:
print(f"NOT PARSEABLE: {exc}")
Comment thread tests/test_fire.py
Comment on lines +35 to +38
def _write(self, text):
p = Path(tempfile.mkdtemp()) / "profile.toml"
p.write_text(text, encoding="utf-8")
return p
Comment thread README.md
Comment on lines +47 to +53
```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>
```
@SupaOhm
SupaOhm deleted the task-11-fire branch August 6, 2026 06:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants