← Try the mock

Ledger: how it's built

A swing-trading practice where bounds are data and code holds the pen.

Agent sessions and scheduled cloud jobs research, enter and exit trades within written rules, on one account only. The repository is the record and a local app is a view that can be rebuilt. Not financial advice.

Architecture

Who can do what

Cloud jobs cannot reach the Mac; the local app pulls their commits.

Who can do whatCloud jobsThis MacRepositoryOutsideResearch routineGuard routineBriefing routineNewsletter routineAgent sessionOrder hookLocal watchersLocal appGit repositoryTrading validatorBrokerMarket data123456789101112131415
  1. Research routine → Git repository: write a funded entry ticket (cron, async)
  2. Guard routine → Git repository: claim the ticket with a pushed commit (cron, async)
  3. Guard routine → Trading validator: every order checked; the exit code decides (request, sync)
  4. Guard routine → Broker: orders only after a passing verdict (request, sync)
  5. Agent session → Order hook: every order tool call (request, sync)
  6. Order hook → Trading validator: fails closed; verdicts are single use (request, sync)
  7. Order hook → Broker: place or cancel after a verdict (request, sync)
  8. Briefing routine → Git repository: a read-only report (cron, async)
  9. Newsletter routine → Git repository: a weekly letter; no broker access (cron, async)
  10. Local watchers → Market data: prices every 10 to 30 minutes; no order path (timer, async)
  11. Local watchers → Broker: read-only positions every 15 minutes (timer, async)
  12. Local app → Git repository: pull and rebuild the view on weekday mornings (cron, async)
  13. Research routine → Broker: sell to fund a ticket; validator first (request, sync)
  14. Briefing routine → Broker: read-only reads; no order tools (request, sync)
  15. Agent session → Git repository: claims, fills and exit plans (push, async)

The order-authority path

Exits skip the lease because an exit cannot wait for the round trip.

The order-authority pathResearchExecutorBrokerRecordFunded ticketClaim commit pushedValidator verdictOrder hookRecorded verdictBroker orderFill appendedApp timeline12345678
  1. Funded ticket → Claim commit pushed: the pushed commit is the lease (event, async)
  2. Claim commit pushed → Validator verdict: deny by default, bounds as data (request, sync)
  3. Validator verdict → Order hook: local session: checked at the tool boundary (request, sync)
  4. Validator verdict → Recorded verdict: cloud job: recorded; detection, not prevention (request, sync)
  5. Order hook → Broker order: place or cancel (request, sync)
  6. Recorded verdict → Broker order: place or cancel (request, sync)
  7. Broker order → Fill appended: one line per order (event, sync)
  8. Fill appended → App timeline: the next sync pulls it (cron, async)

Wiremocks

A mock-up of a screen — Here, a static picture of a screen, drawn to show layout and flow, not the working app. — a static picture, not the real app

A trading day

A weekday in Eastern Time — The US East Coast clock the market and the scheduled jobs are timed in. daylight time, each job marked can trade, read-only or alerts only.

One weekday, times in Eastern Time — The US East Coast clock the market and the scheduled jobs are timed in.

Eastern Time — The US East Coast clock the market and the scheduled jobs are timed in., daylight time; an hour earlier after the clock change.

  1. 09:00Hourly guard legs, 09:00 to 16:00can trade
  2. 09:25Price fetch, every 30 minutesread-only
  3. 09:25Broker fetch, every 15 minutesread-only
  4. 09:30Exit-line watcher, every 10 minutesalerts only
  5. 09:40Guard leg, opening windowcan trade
  6. 10:00Briefing, first runread-only
  7. 10:30Morning syncread-only
  8. 14:00Weekly letter, Thursday onlyno broker access
  9. 15:00Briefing, second runread-only
  10. 15:00Research, sells to fund a ticketcan trade
  11. 17:00Guard leg, post-closeread-only

A mock-up of a screen — Here, a static picture of a screen, drawn to show layout and flow, not the working app. — a static picture, not the real app

A guard-leg report

A made-up report in the real report's shape; the orders line says none.

Intraday check

Session so far: low $98.50, high $102.00. No exit line has fired.

PositionEntryStopMarkerSpikeFired?
Instrument Illustrative instrument symbol — The stand-in name for the position replayed on this page, with no claim about real listings. (illustrative symbol)$100.00$96.00$106.00$108.00no
Protection spot-check
  • Resting stop is on the bookpresent
  • Stop price matches the journaled linematches $96.00
  • Stop quantity matches the positionmatches

Orders placed: none

Running cost

ResourceFigureStatusSource
Guard runs10 per weekdayDerived
trigger registry, lines 46 and 64, times in lines 47 and 65; the readme calls it authoritative, line 93
Inputs: 9 (the hourly cron, 09:00–17:00 Eastern Time — The US East Coast clock the market and the scheduled jobs are timed in. in daylight time, an hour earlier after the clock change, configured) + 1 (the 09:40 trigger, configured) = 10
Read on 2026-10-17
Conflicts with newsletter routine doc, line 40 (~9 per weekday, read on 2026-10-17): That counts the hourly expression alone and leaves out the second trigger, so the registry governs.
Research runs1 per weekdaySet in the project's code
trigger registry, lines 86-87 (cron); research routine doc, line 28
Read on 2026-10-17
Briefing runs2 per weekdaySet in the project's code
automation readme, line 84 (two cron times, weekdays)
Read on 2026-10-17
Newsletter runs1 per weekSet in the project's code
trigger registry, lines 141-142 (cron); newsletter routine doc, line 39
Read on 2026-10-17
Cloud runs in all~277 per monthDerived from an estimate
derived (see inputs)
Inputs: 10 × 21 + 21 + 2 × 21 + 4.3 = 277.3, using the sources' own ~21 weekdays and ~4.3 weeks a month, which are estimates (projected)
Read on 2026-10-17
Claude allocation per run—Unknown
owner's metered-resource table (Claude / Claude Code row: check the usage dashboard; names no project, gives no figure)
Read on 2026-10-17
Broker read-only calls~486 per market dayDerived
derived (see inputs)
Inputs: 18 calls a run × 27 runs a market day = 486 (configured, broker fetch tool, lines 24-26); the source rounds to about 490
Read on 2026-10-17
Broker endpoint pricefree, no published capPublished price
broker fetch tool, lines 24-26
Read on 2026-10-17
Market-data requests~3,080 per market dayDerived from an estimate
derived (see inputs)
Inputs: ~220 a run (the source's estimate) × 13 runs + ~220 history = 3,080 (market fetch tool, lines 32-33); the front-overhaul spec, lines 94-96, gives ~2,900 for the 13 runs plus ~220 for the history pass
Read on 2026-10-17
Market-data pricefree, no published capEstimate (the project's own)
market fetch tool, lines 32-33 (the source has no vendor price list)
Read on 2026-10-17
Research broker calls~25–40 per full boardEstimate (the project's own)
research routine doc, line 28 (a one-line range is one figure)
Read on 2026-10-17
Email reads~2 per weekEstimate (the project's own)
newsletter routine doc, lines 41-42
Read on 2026-10-17
HostingnoneSet in the project's code
the app's readme, lines 9-11 and 71 (local Mac only)
Read on 2026-10-17

Pure I/O polling runs as local scripts, so it spends no Claude allocation.

Design decisions

  • Bounds are data, enforced by an exit codeA prompt instruction is a suggestion to a language model; an exit code is not. Limits sit in data, and a validator denies by default.
  • Reporting and trading are separate jobsA reporter bug cannot place an order. The newsletter job reads untrusted text and holds no order authority.
  • A tool-boundary gate that fails closedVerdicts are single-use and under 30 minutes old. Cloud jobs are checked by detection, not prevention; that limit is stated.
  • A local-only app over a rebuildable viewAccount data stays on the machine, and cloud jobs cannot reach it, so a local sync pulls their commits. The repository is the truth and the database can be rebuilt from it.
  • A git push is the lease for entriesOne executor opens positions. Two triggers once ran one ticket 5.6 s apart, so the server accepting the first push is the lock.

Open questions

  • Claude allocation per run: the owner's table names no project and gives no figure, so only the usage dashboard can answer
  • Watchers: requests per price-watch, drawdown and drift run are not counted
  • Research inputs: prediction-market call counts are not recorded
  • Git: pushes a day are not counted