Every directory attempt ends with one command. scripts/record.py writes a single current row per platform into submissions.json in the product folder, and it refuses rows that the kit considers unproven or unsafe. That refusal is the whole point: the tracker is what stops “we submitted to 40 directories” from meaning “we filled in 40 forms and hoped”. This guide covers the states, the evidence each state needs, the command’s flags, and what may and may not go in a note. It is a summary of RUNBOOK.md and the script’s own checks, not a replacement for them.
The command
The runbook’s example, from the kit directory with an already-created private project folder:
On Windows, use py -3 instead of python3 in the commands below (or python if that is your Python 3.10+ command). Keep your workspace in a private local folder outside OneDrive or other sync folders. For multiline shell examples, put the command on one line and remove the trailing \ characters in PowerShell.
python3 scripts/record.py --project ../private-product pitchwall draft \
--note "Product import corrected; final form not sent" \
--next-action "Check saved profile and review final form"
Two positional arguments (platform id, state) and two required options (--note, --next-action). The optional flags are --public-url, --confirmed-public, --launch-date and --replace. The platform id must be a lowercase slug, the state must be one of the eleven below, and the tracker exits with an explanation whenever a rule is not met. The local dashboard’s record form calls the same function with the same rules.
The eleven states and their minimum evidence
The runbook’s table, in short:
| State | What you must have observed |
|---|---|
draft |
Work prepared; final submission not confirmed. |
prepared_needs_human |
A precise owner action or challenge (CAPTCHA, 2FA) blocks prepared work. |
submitted_pending_review |
The platform explicitly received the submission; moderation remains. |
queued |
The platform confirms a queue position or waiting-list state. |
scheduled |
The platform confirms a launch date on or after the floor; outstanding approval stays in the note. |
live |
Public listing verified, no pending label; public URL and --confirmed-public required. |
already_listed |
An existing public listing verified; same requirements as live. |
blocked |
Eligibility, account capacity or a mandatory missing fact prevents progress. |
deferred_paid |
The usable route requires payment; nothing was bought. |
not_a_fit |
The product does not meet the audience or listing criteria. |
unavailable |
The route or platform cannot currently be used; note the problem. |
The distinctions that matter most are draft vs. submitted and pending vs. live. A thank-you screen does not make a listing live. A page you can reach can still be pending approval. A ticked “also distribute to our partner” box does not mean a second platform received anything. Each platform’s result stays independent so that totals are never inflated.
The rules the script enforces
- Public states need proof.
liveandalready_listedrequire--public-urlwith a reviewed HTTPS URL — no query string, no fragment, no account, dashboard or login paths — and--confirmed-public, your statement that you looked at the page. - Scheduled needs a date.
--launch-date YYYY-MM-DDis mandatory and must not be earlier thanearliest_launch_dateinproduct.json; the launch-date floor guide explains why. - Notes stay clean. Notes and next actions may not contain links, email addresses,
password=-style pairs or known token prefixes. The tracker file is meant to be shareable; evidence with account URLs belongs in private storage. - One row per platform. If the platform already has a row, the command fails unless you pass
--replace— after inspecting both the existing row and the platform. Replacing is intentional, never a side effect. - No symlinks, atomic writes, a lock file. Boring details, but they are why two agents writing at once do not corrupt the tracker.
Resuming without duplicates
At the start of the next session, read the tracker before touching any form. Prioritise human handoffs and scheduled launches due for verification, then pending submissions whose stated review window has passed. If a platform gives no review timing, agree a follow-up date with the owner instead of inventing one. And never resubmit to move up a queue: recheck the existing record. The tracker stores current state, not history; if you need an audit trail, archive redacted run summaries separately.
For worked examples of the states on real platforms, read the submission-states article and the older guide on tracking without double counting; the vocabulary itself is defined under listing status.