Expand description
Shared synthetic corpora + per-journey fixtures for the worked-example journeys (J1–J9).
Hoisted here (from xtask, TUI-walkthrough spec §4.1) so ALL consumers share ONE source of truth: the
xtask examples generator, and the btctax-tui / btctax-tui-edit screen-walkthrough emit tests. A
plain pub module (like btctax_forms::testonly) — the corpora are tiny synthetic CSVs, and the
generator’s generate() is a non-test fn, so they cannot be #[cfg(test)].
The CSV corpora carry explicit CRLF: committed .csv files are force-LF’d by .gitattributes and would
break the Coinbase parser, so they live as string consts (a driver writes them to a tempdir at runtime).
These bytes are byte-identical to their previous home in xtask/src/examples.rs — the
examples_golden_matches_committed gate proves the move changed nothing.
Structs§
- Journey
Fixture - One journey’s synthetic input: the named corpus files a driver writes to a tempdir before
import. The SAME fixture seeds both walkthrough capture halves (the editor emit test drives its flows; the viewer emit test re-seeds this corpus and replays the equivalent decisions viabtctax-cli), so the two halves of a journey converge by construction on one source of truth (walkthrough spec §4.2).
Constants§
- J1_CSV
- J1 corpus: a single-buyer happy path — one Buy + one partial Sell in 2025.
- J2_CSV
- J2 corpus: an LT lot (2023) + an ST lot (2025) + a 2025 Send of 2 BTC donated to charity.
- J3_CSV
- J3 corpus: a Buy + a Receive (an inbound transfer with unknown basis → a hard blocker until classified).
- J4_CSV
- J4 corpus: two River staking-income deposits in 2025 (FMV resolved from the bundled dataset).
- J5_CSV
- J5 corpus: an LT lot + a higher-basis ST lot + a 2025 sell — a genuine changed-selection scenario (HIFO ≠ FIFO) so the optimizer has a tax-saving pick to propose.
- J6_
COINBASE_ CSV - J6 Coinbase corpus: a cheap 2020 long-term lot, a small 2024 sale, and a 2024 charitable Send of 0.1 BTC (§170(e) donation ⇒ Form 8283). NOTE: HIFO reconstruction draws the 2024 sale from the higher-basis 2024 mining lot (not this 2020 lot) ⇒ it is SHORT-term (Schedule D Part I). Amounts kept small so the return stays under the AMT screen.
- J6_
FULLRETURN_ TOML - The committed full-return ReturnInputs (the
kitchen_sink_household()oracle, TOML-serialized). J6 imports it viaincome import. The fixture lives in this crate (self-contained), so this is a SAME-crateinclude_str!— retiring the cross-crate include the xtask copy carried (M-5 exception). - J6_
RIVER_ CSV - J6 River corpus: one small 2024 business mining-income deposit (FMV from the bundled dataset). Kept modest deliberately: the kitchen-sink household clears the 2024 Form-6251 AMT-screen worksheet by only a thin margin — a corpus editor who enlarges the sale, income, or donation must keep the household on the computable side of that screen.
- J7_CSV
- J7 corpus (UX-P1-7): a single 2024 Coinbase Receive of staking rewards — an unknown-basis inbound the
single-event
classify-inbound-incomecommand values only from a hand-supplied--fmv. - J8_
COINBASE_ CSV - J8 Coinbase corpus (UX-P1-8): the matching inbound Receive of 0.10 BTC — the SAME coins landing at a second exchange, so the pair is a cross-wallet RELOCATE (not a same-wallet DROP).
- J8_
RIVER_ CSV - J8 River corpus (UX-P1-8): a buy (to give the coins a basis) then a Withdrawal OUT of 0.10 BTC — the out-leg of a cross-exchange self-transfer whose in-leg lands on Coinbase below.
- J9_CSV
- J9 corpus (UX-P1-10): a cheap 2023 long-term lot (0.60) + a pricier 2024 lot (0.40), then a 2025 sale of only 0.50 — less than the combined holdings, so specific-lot identification is meaningful.
Functions§
- j1
- The nine journey fixtures, keyed by the same corpus filenames the examples journeys use.
- j2
- j3
- j4
- j5
- j6
- j7
- j8
- J8 — the PoC journey: a cross-exchange self-transfer (River Withdrawal out → Coinbase Receive in).
- j9
- seed_
j1_ with_ profile - Seed J1 (single buyer: one Buy + one partial Sell, no transfers → no reconciliation) and set the 2025
tax profile its walkthrough VIEWER needs for the Tax tab to compute — single filer, $100k ordinary
income, mirroring the J1 worked example’s
tax-profilestep. The viewer half then only opens + reads. - seed_
j2_ donated - Seed J2’s fully post-decision state — the outbound reclassified as a donation, the Form 8283 appraiser/donee details recorded (Section B complete), and a 2025 profile so the viewer’s Tax tab computes the charitable-deduction line. The walkthrough’s VIEWER renders Forms (the two 8283 rows) + Tax. Made-date threaded from the caller.
- seed_
j2_ reclassified - Seed J2 with the outbound Send reclassified as a §170(e) charitable DONATION (FMV $217,992.34 = 2 BTC
× the contribution-date close, donee “Habitat for Humanity”) — but WITHOUT the Form 8283 appraiser/donee
details yet. This is the state the walkthrough’s
d(set-donation-details) EDITOR frame drives from (the details form still empty). Made-date threaded from the caller. - seed_
j3_ self_ transfer - Seed J3 (an unknown-basis inbound Receive → a hard blocker) classified as a SELF-TRANSFER of the filer’s own coins returning — non-taxable, carrying a supplied basis ($19,000) and acquisition date (2024-11-01, so the holding period runs from then). The post-classify state the VIEWER renders (Holdings). The editor half seeds only the raw import and drives the classify. Made-date threaded from the caller.
- seed_
j4_ reclassified - Seed J4 (two River staking receipts) with a 2025 profile AND both receipts reclassified as a trade or
business (
--business true --kind staking) — the post-reclassify state the walkthrough’s VIEWER half renders (Income now on Schedule C/SE; Tax shows the self-employment tax). The editor half drives the reclassify itself, so it seeds only the raw import (seed_journey(&j4())). Made-date pinned for determinism. Refs embed the ms-timestamp of each receipt (not wall-clock). - seed_
j5_ elected - Seed J5 (an LT lot $30k + a higher-basis ST lot $80k + a 2025 sale $50k) with a 2025 profile AND a
standing FIFO election — but NOT the optimizer’s accept. This is the state the walkthrough’s
z(optimize-accept) EDITOR frames drive from: the optimizer proposes swapping to the ST lot to realize a loss. The election made-date is hardcoded 2025-01-01 (the engine blocks effective_from before the made-date, so a later threadednowwould trip MethodElectionBackdated). - seed_
j5_ optimized - Seed J5’s post-accept state — the FIFO election PLUS the optimizer’s proposed lot pick accepted (the
whole sale moved onto the short-term
opt-buy-stlot to realize a loss). The walkthrough’s VIEWER renders the resulting Disposals (ST loss) + Tax (§1211 deduction + carryforward).nowis the accept made-date — MUST be ≤ the 2025-06-01 sale so the selection is Contemporaneous; the caller passes the same instant the editor frames pin. - seed_
j6_ full - Seed J6 — a COMPLETE Form 1040 (the kitchen-sink MFJ household). Combines the crypto reconciliation
(mining income → a trade or business; the 0.10 BTC Send → a §170(e) donation with Form 8283 details)
with the non-crypto household imported from the committed
kitchen_sink_household()TOML. This is the state BOTH walkthrough halves render: the editor half opens the tax-inputs authoring form (T) over these committed inputs; the viewer shows Forms (the crypto forms) + Tax (the merged MFJ return). No raw tax-profile — the full-return inputs take precedence andbuild_snapshotderives the MFJ profile from them. Made-date threaded from the caller. - seed_
j7_ income - Seed J7 (a single off-exchange Receive with no market price → a hard unknown-basis blocker) classified as staking INCOME with a hand-supplied FMV ($3,300), plus a 2024 profile — the post-classify state the walkthrough’s VIEWER renders (Income + Tax). The editor half seeds only the raw import and drives the classify. Made-date threaded from the caller (matches the depicted editor session’s clock).
- seed_
j8_ relocated - Seed J8 and apply its RELOCATE self-transfer (river out → coinbase in) — the post-match state the
walkthrough’s VIEWER half renders (BALANCED). Refs are J8’s deterministic event refs; RELOCATE routes
to
link_transfer(out → in), the same decision the editor’s confirm modal makes. - seed_
j9_ selected - Seed J9 (a cheap 2023 LT lot 0.60 + a pricier 2024 lot 0.40, then a 2025 sale of 0.50 — less than the
combined holdings, so specific-lot identification is meaningful) with the whole 0.50 IDENTIFIED against the
cheap long-term
lot-a(a deliberate per-disposal specific identification). The post-selection state the walkthrough’s VIEWER renders (Disposals drawing from lot-a; Compliance now satisfied). The editor half seeds only the raw import and drives the select-lots flow. Made-date threaded from the caller (the identification is contemporaneous — before/at the sale). - seed_
journey - Init a vault at
dir/vault.pgpand import the journeyfx’s corpus via the REAL adapter ingest.