Click to copy
<role>The verification desk from prompt 01, working as an engineer in Claude Code.</role>
<task>Build a small tool that ties claimed figures to the facts a company filed with the SEC.
Create this tree at {{PROJECT_DIR}} and write every file. Do not summarise the plan back.
tieout/check.py reads claims.csv, writes out/tieout.csv, prints one line per claim
tieout/__init__.py
tests/test_check.py hand-answer tests, written FIRST
claims.csv one row per claim
out/ results only
Setup: check `python3 --version` is 3.10 or higher (Windows: `python --version`). Make a venv
(a private Python folder for this tool): `python3 -m venv .venv` (Windows: `python -m venv
.venv`, then `.venv\Scripts\python` wherever `.venv/bin/python` appears), then
`.venv/bin/python -m pip install edgartools==5.59.1 pytest==9.1.1`.
claims.csv columns: claim_id, ticker, metric, concept (optional), period_start, period_end,
stated (the number as written, e.g. 281.7), scale (1000000000 for billions, 1 for per share).
check.py logic, edgartools 5.59.1:
- set_identity from the EDGAR_IDENTITY environment variable ({{EDGAR_ID}}).
- facts = Company(ticker).get_facts(); candidates via facts.query().by_concept(c).execute().
Each fact has concept, numeric_value, period_start, period_end, unit, accession,
form_type, filing_date, is_dimensioned. by_concept also returns near names (Revenues
brings back RevenuesNetOfInterestExpense): keep a fact only if its concept, after the
prefix, equals the name asked for.
- metric to concepts, tried in order, the first with a fact for the exact period wins:
revenue: RevenueFromContractWithCustomerExcludingAssessedTax, Revenues,
RevenueFromContractWithCustomerIncludingAssessedTax, SalesRevenueNet; net_income:
NetIncomeLoss, ProfitLoss; operating_income: OperatingIncomeLoss; gross_profit:
GrossProfit; eps_diluted: EarningsPerShareDiluted; total_assets: Assets; cash:
CashAndCashEquivalentsAtCarryingValue; operating_cash_flow:
NetCashProvidedByUsedInOperatingActivities; capex:
PaymentsToAcquirePropertyPlantAndEquipment. A concept column value overrides the map.
- Match on period_end (and period_start for durations) and is_dimensioned False. Never
match on the fiscal_year label.
- Tolerance: half of the last written decimal, times scale (281.7 at 1e9 allows 0.05e9).
- Verdicts: TIES; RESTATED (equals an older filed value for the period, the latest differs);
WRONG PERIOD (equals another period's fact; name that period and the
earliest accession that filed it); MISMATCH; NO FACT FOR
PERIOD (no candidate has the period); NOT IN XBRL (metric not mapped: non-GAAP, KPI,
segment).
- Output columns: claim fields, verdict, concept (the one that answered), filed_value, diff, tolerance, accession
(earliest filing carrying the current value), form, filing_date, latest_accession, note.
TEST FIRST. Write tests/test_check.py with a stub facts object (no network), run
`.venv/bin/python -m pytest -q`, show it failing, then write check.py and re-run to green.
Hand answers: stated "391.0" gives tolerance 0.05, "7" gives 0.5; a 100.0M claim ties a
100,000,000 fact; 100.04 does not; 90.0 against a prior-year 90,000,000 fact is WRONG PERIOD;
a dimensioned 95,000,000 fact is never a match; a claim equal to an older value while the
latest filing says 98,000,000 is RESTATED; metric adjusted_ebitda is NOT IN XBRL; a
RevenuesNetOfInterestExpense fact never answers a Revenues request; a WRONG PERIOD note
cites the earliest filing of the other period, not the later comparative.
FIRST RUN, pass condition. claims.csv with two rows: AAPL revenue 2024-09-29 to 2025-09-27
stated 416.2 scale 1000000000, and the same period stated 391.0. Run
`EDGAR_IDENTITY="{{EDGAR_ID}}" .venv/bin/python -m tieout.check claims.csv out/tieout.csv`.
PASS: row 1 TIES to 416,161,000,000 with accession 0000320193-25-000079, and row 2 is WRONG
PERIOD naming 2023-10-01 to 2024-09-28 and accession 0000320193-24-000123. Anything else
is a FAIL: go to prompt 13.
Print `ls -R` when done.</task>
<trap>The first concept tried can be empty for a period while a sibling concept holds the
figure (a company that stopped tagging Revenues years ago). A blank on one concept is not a
missing number; the tool must try the list before it says NO FACT FOR PERIOD.</trap>
<stop>If Python is below 3.10 (the macOS built in is 3.9), stop: install current Python from
python.org and build the venv with it, for example `python3.12 -m venv .venv`. If pip fails,
print the error and stop; do not swap in another package. If tests are not green, do not
touch real data.</stop>
<output_format>The ls -R tree, the pytest line, the two first-run lines, PASS or FAIL.</output_format>
<review_gate>{{REVIEWER}} opens the filing at that accession and finds 416,161 on the income
statement once, by hand.</review_gate>