docs: split roadmap out of readme into Documentation/roadmap.md
The readme served two roles: design-decision source of truth and
work-status tracker. The status section grew into a plan the
orchestrator must navigate, so it moves to its own file with task
IDs, dependency edges, statuses, and per-item acceptance criteria.
readme.md remains authoritative for decisions (stack, formats,
workflow); workflow step 7 and AGENTS.md pointers now name
roadmap.md for status. Cross-references verified.
Also records: stale feature/epsilon-parser branch pointer (676e55e,
2 behind main) deleted locally; recreate from main when B1 starts.
This commit is contained in:
@@ -1,12 +1,14 @@
|
|||||||
# AGENTS.md — working rules for coding agents on RustyRPN
|
# AGENTS.md — working rules for coding agents on RustyRPN
|
||||||
|
|
||||||
readme.md is the single source of truth for design decisions and roadmap.
|
readme.md is the single source of truth for design decisions. The
|
||||||
Read at minimum these sections before starting work:
|
roadmap lives in Documentation/roadmap.md.
|
||||||
|
Read at minimum these before starting work:
|
||||||
|
|
||||||
- §Workflow — the TDD loop you are expected to follow
|
- readme.md §Workflow — the TDD loop you are expected to follow
|
||||||
- §General guidelines for AI — hard prohibitions
|
- readme.md §General guidelines for AI — hard prohibitions
|
||||||
- §Data formats — input formats, edge cases, and where test fixtures live
|
- readme.md §Data formats — input formats, edge cases, and where test
|
||||||
- §Roadmap and status of functionality — what is green, red, or unstarted
|
fixtures live
|
||||||
|
- Documentation/roadmap.md — what is green, red, or unstarted
|
||||||
|
|
||||||
## Environment
|
## Environment
|
||||||
|
|
||||||
@@ -18,17 +20,18 @@ Read at minimum these sections before starting work:
|
|||||||
`src/cli` (rpn-cli, binary `rpnc`). `src/server` and `src/web` are
|
`src/cli` (rpn-cli, binary `rpnc`). `src/server` and `src/web` are
|
||||||
planned but not scaffolded yet.
|
planned but not scaffolded yet.
|
||||||
|
|
||||||
## Current state (verify against readme.md roadmap; update both when it changes)
|
## Current state (verify against Documentation/roadmap.md; update both when it changes)
|
||||||
|
|
||||||
- core/config: implemented, tests green.
|
- core/config: implemented, tests green.
|
||||||
- core/db: tests committed and RED (they reference functions that do not
|
- core/db: tests committed and RED (they reference functions that do
|
||||||
exist yet — the crate does not compile its test target). The first task
|
not exist yet — the crate does not compile its test target). The first
|
||||||
is the minimal implementation to turn them green. Do not weaken or
|
task is the minimal implementation to turn them green. Do not weaken or
|
||||||
rewrite these tests to make them pass; they encode agreed behaviour.
|
rewrite these tests to make them pass; they encode agreed behaviour.
|
||||||
- cli: `fn main() {}`. Command surface specified in Documentation/cli.md.
|
- cli: `fn main() {}`. Command surface specified in Documentation/cli.md.
|
||||||
- feature/epsilon-parser: branch exists, zero commits. Needs workflow
|
- feature/epsilon-parser: does not exist yet. Create it from `main`
|
||||||
step 2 (spec + test checklist agreed with the maintainer) before any
|
when parser work starts (a stale early pointer was deleted
|
||||||
failing test is written.
|
2026-10-08). Workflow step 2 (spec + test checklist agreed with the
|
||||||
|
maintainer) must complete before any failing test is written.
|
||||||
|
|
||||||
## Test data
|
## Test data
|
||||||
|
|
||||||
@@ -58,6 +61,7 @@ Read at minimum these sections before starting work:
|
|||||||
`cargo clippy` clean for files you touched.
|
`cargo clippy` clean for files you touched.
|
||||||
2. Every checklist item from the task's spec verified — by a test or by
|
2. Every checklist item from the task's spec verified — by a test or by
|
||||||
a command you actually ran, not by inspection alone.
|
a command you actually ran, not by inspection alone.
|
||||||
3. readme.md roadmap updated in the same branch.
|
3. Documentation/roadmap.md updated in the same branch (and readme.md
|
||||||
|
if a design decision changed).
|
||||||
4. A short summary for the maintainer: what changed, what is still red,
|
4. A short summary for the maintainer: what changed, what is still red,
|
||||||
suggested next step.
|
suggested next step.
|
||||||
|
|||||||
@@ -0,0 +1,147 @@
|
|||||||
|
# Roadmap and status of functionality
|
||||||
|
|
||||||
|
This file is the roadmap. Design decisions that a roadmap item depends
|
||||||
|
on are still owned by readme.md (the source of truth); this file tracks
|
||||||
|
*what is done, in flight, and planned*, with status, dependencies, and
|
||||||
|
acceptance criteria per item.
|
||||||
|
|
||||||
|
Status legend:
|
||||||
|
- ✅ done — implemented, tests green, merged to main
|
||||||
|
- 🔴 red — tests committed and failing (TDD in progress)
|
||||||
|
- 🟡 spec — specified, no code or tests yet
|
||||||
|
- ⚪ idea — planned, not specified
|
||||||
|
|
||||||
|
| ID | Area | Item | Status | Depends on |
|
||||||
|
|---|---|---|---|---|
|
||||||
|
| A1 | core | config: load, resolve, defaults, mask, validate | ✅ | — |
|
||||||
|
| A2 | core | db: connection URL, migration split/embed, backup/restore | 🔴 | A1 |
|
||||||
|
| B1 | core+cli | epsilon parser: file → rows → batch aggregates | 🟡 | A2 |
|
||||||
|
| B2 | cli | `file import` / `file list`: ingest + idempotency | 🟡 | B1 |
|
||||||
|
| B3 | cli | customer / card CRUD (`batch`, `card`, `customer`) | 🟡 | A2 |
|
||||||
|
| B4 | cli | invoice creation from batch data (`invoice prepare`) | 🟡 | B2, B3 |
|
||||||
|
| C1 | core | tsdrms xlsx parser (GL journal, cutoff partitioning) | ⚪ | A2 |
|
||||||
|
| C2 | core | subfranchise PDF statement parser | ⚪ | A2 |
|
||||||
|
| D1 | core | Fortnox voucher mapping (port spreadsheet → TOML) | ⚪ | C1 |
|
||||||
|
| E1 | server | axum API + sessions + roles | ⚪ | A2 |
|
||||||
|
| E2 | web | Leptos SPA (invoice portal for rental firms) | ⚪ | E1 |
|
||||||
|
| F1 | cli | daemon start/stop/status | ⚪ | E1 |
|
||||||
|
| G1 | spa | receipt reissue (retail fuel, by date + last4) | ⚪ | E2 |
|
||||||
|
| G2 | spa | to-do application for employees | ⚪ | E1 |
|
||||||
|
| G3 | core | car registry (owned/leased, costs, besiktning, status) | ⚪ | A2 |
|
||||||
|
|
||||||
|
## Track A — foundations
|
||||||
|
|
||||||
|
### A1 core/config ✅
|
||||||
|
Loading (`--config` flag → `$RUSTYRPN_CONFIG` → `./config.toml`,
|
||||||
|
`--env` selects dev/test variants in the last slot only), built-in
|
||||||
|
defaults, secret masking for `config show`, validation. Tests green
|
||||||
|
(commit 9452962).
|
||||||
|
|
||||||
|
### A2 core/db 🔴 — next task
|
||||||
|
12 unit tests committed red (commit 676e55e): `connection_url`
|
||||||
|
(percent-encoded credentials, with/without database),
|
||||||
|
`split_statements` (comment/string-aware), `MIGRATION_V1` (embeds
|
||||||
|
Documentation/schema.sql as v1), `backup_command` /
|
||||||
|
`restore_command` (mariadb-dump/mariadb via MYSQL_PWD, never argv),
|
||||||
|
`backup_filename` (timestamped).
|
||||||
|
Scope: implement minimal green path. Pure functions — no live
|
||||||
|
database, no new dependencies. Do not alter the tests' intent.
|
||||||
|
Accept: `cargo test` green workspace-wide; fmt + clippy clean.
|
||||||
|
|
||||||
|
## Track B — fuel station data (epsilon)
|
||||||
|
|
||||||
|
### B1 epsilon parser 🟡
|
||||||
|
Branch `feature/epsilon-parser` to be created **from main** when work
|
||||||
|
starts (a stale earlier pointer was deleted 2026-10-08). Workflow
|
||||||
|
step 2 (spec + test checklist agreed with maintainer) is pending —
|
||||||
|
no failing test may be written before it. Fixtures ready:
|
||||||
|
`data/fixtures/epsilon` (batches 9405–9412, cumulative slice).
|
||||||
|
Sketch: 16-field TSV per readme §Data formats; filename batch number
|
||||||
|
must match every row; `M/d/yyyy h:mm:ss AM/PM` dates; rust_decimal
|
||||||
|
amounts; Quality 0 zero-value rows preserved; batch aggregates
|
||||||
|
(totals per quality, row count, date range) for the `batches` table.
|
||||||
|
|
||||||
|
### B2 file ingest & idempotency 🟡
|
||||||
|
`files` table: filename = natural key + content hash (sha2, already a
|
||||||
|
core dep). Re-ingesting the same file must be a no-op. Open decision
|
||||||
|
(maintainer): test against scratch MariaDB vs mocked repo layer.
|
||||||
|
Open decision: `Amount == Volume × Price` — hard error or reported
|
||||||
|
warning.
|
||||||
|
|
||||||
|
### B3 customers & cards 🟡
|
||||||
|
Contract cards = epsilon rows with non-empty customer number; stored
|
||||||
|
unmasked as delivered (personal data rule: schema.sql / cli.md). CRUD
|
||||||
|
per Documentation/cli.md; delete blocked while referenced.
|
||||||
|
|
||||||
|
### B4 invoice creation 🟡
|
||||||
|
From batch/card data into `invoices` + `invoice_items`; Fortnox
|
||||||
|
export format TBD (depends on D1 decision).
|
||||||
|
|
||||||
|
## Track C — rental data (tsdrms / Enterprise)
|
||||||
|
|
||||||
|
### C1 tsdrms xlsx parser ⚪
|
||||||
|
GL journal (double-entry pairs), `calamine`-class crate needed —
|
||||||
|
**ask before adding dependency**. Critical quirk: monthly files
|
||||||
|
partition by Cutoff Date, not Transaction Date. Floats round to 2
|
||||||
|
decimals on ingest. Fixtures ready: `data/fixtures/tsdrms`.
|
||||||
|
|
||||||
|
### C2 subfranchise PDF parser ⚪
|
||||||
|
Text-based 1-page statements; PDF text-extraction crate chosen when
|
||||||
|
the feature starts. Parse defensively (layout verified on 6 samples
|
||||||
|
only); European number format incl. `(x,yy)` negatives; line items by
|
||||||
|
pattern, not exact string. Fixtures ready as extracted text:
|
||||||
|
`data/fixtures/subfranchise`.
|
||||||
|
|
||||||
|
## Track D — bookkeeping
|
||||||
|
|
||||||
|
### D1 Fortnox voucher mapping ⚪
|
||||||
|
First task is porting the Apple Numbers mapping
|
||||||
|
(`data/other_resources/`, gitignored — read, never modify) into a
|
||||||
|
versioned TOML table in-repo *before* writing code against it.
|
||||||
|
Depends on C1 data model.
|
||||||
|
|
||||||
|
## Track E — server & SPA
|
||||||
|
|
||||||
|
### E1 axum API ⚪
|
||||||
|
JSON API, argon2id login, MariaDB-backed sessions behind
|
||||||
|
HttpOnly/Secure/SameSite=Lax cookie, rate-limited, no user
|
||||||
|
enumeration, roles director/employee/customer (customer queries
|
||||||
|
scoped to session's company). New deps (axum, sqlx already partly in
|
||||||
|
place) — ask before adding.
|
||||||
|
|
||||||
|
### E2 Leptos SPA ⚪
|
||||||
|
Served by the same binary as the API.
|
||||||
|
|
||||||
|
## Track F — deployment
|
||||||
|
|
||||||
|
### F1 daemon 🟡→⚪
|
||||||
|
`rpnc daemon start|status|stop` per cli.md (pidfile + logs under
|
||||||
|
state dir; local-only status checks). Caddy reverse proxy and FreeBSD
|
||||||
|
jail packaging are out of scope for the repo (readme §Technology).
|
||||||
|
|
||||||
|
## Track G — later features
|
||||||
|
|
||||||
|
### G1 receipt reissue ⚪ (low priority)
|
||||||
|
Identify by date + last 4 (masked consumer cards make last4
|
||||||
|
available); render template; e-mail to customer.
|
||||||
|
|
||||||
|
### G2 employee to-do app ⚪
|
||||||
|
|
||||||
|
### G3 car registry ⚪
|
||||||
|
Owned/leased cars, per-car costs, besiktning tracking, status
|
||||||
|
(active/broken/repair), tyre seasons.
|
||||||
|
|
||||||
|
## Near-term ordering
|
||||||
|
|
||||||
|
1. A2 → green baseline for everything.
|
||||||
|
2. B1 spec discussion (maintainer gate) → B1 → B2 → B3 → B4: the
|
||||||
|
fuel-sales vertical slice usable from the CLI.
|
||||||
|
3. C1/C2/D1 extend into rentals + bookkeeping.
|
||||||
|
4. E/F make it multi-user; G fills in.
|
||||||
|
|
||||||
|
## Maintenance rules
|
||||||
|
|
||||||
|
- Every task updates this file in its own branch (workflow step 7);
|
||||||
|
decision changes go to readme.md in the same commit.
|
||||||
|
- Status changes commit with the merge, not before.
|
||||||
|
- AGENTS.md §Current state must agree with this file; update both.
|
||||||
@@ -271,9 +271,11 @@ Use a test-driven-development inspired approach, specifically the following work
|
|||||||
5.3 Create a git commit per passing test
|
5.3 Create a git commit per passing test
|
||||||
5.4 Iterate for each test until they all pass
|
5.4 Iterate for each test until they all pass
|
||||||
6. Verify everything on the checklist has been completed
|
6. Verify everything on the checklist has been completed
|
||||||
7. Update roadmap
|
7. Update roadmap (Documentation/roadmap.md)
|
||||||
- this file is the source of truth
|
- roadmap.md tracks what is done, in flight, or planned
|
||||||
- any task that changes a decision (stack, format, workflow) updates it in the same commit
|
- readme.md is the source of truth for design decisions: any task
|
||||||
|
that changes a decision (stack, format, workflow) updates it in
|
||||||
|
the same commit
|
||||||
8. Provide a short list of suggestions for improvements and include a suggested global next step
|
8. Provide a short list of suggestions for improvements and include a suggested global next step
|
||||||
|
|
||||||
### General guidelines for AI
|
### General guidelines for AI
|
||||||
@@ -296,42 +298,13 @@ Use a test-driven-development inspired approach, specifically the following work
|
|||||||
- Be concise
|
- Be concise
|
||||||
|
|
||||||
## Roadmap and status of functionality
|
## Roadmap and status of functionality
|
||||||
### Active
|
|
||||||
* core/config — done (loading, resolution, defaults, masking, validation;
|
The roadmap lives in Documentation/roadmap.md: per-item status (done /
|
||||||
tests green, commit 9452962)
|
red / spec / idea), dependencies, acceptance criteria, and near-term
|
||||||
### In development
|
ordering. Workflow step 7 updates that file; this document remains the
|
||||||
* core/db — tests committed and RED (connection URL, migration splitting,
|
source of truth for design decisions (stack, formats, workflow) —
|
||||||
embedded schema v1, backup/restore; commit 676e55e). Next step: minimal
|
a task that changes a decision updates readme.md, a task that changes
|
||||||
implementation until green; do not alter the tests' intent.
|
*what is built next* updates roadmap.md.
|
||||||
* cli
|
|
||||||
* command structure specified in Documentation/cli.md
|
|
||||||
* ingest tab-separated .txt files containing transactions from automated gas station into a MariaDB
|
|
||||||
* feature branch feature/epsilon-parser is open but empty: no
|
|
||||||
spec/checklist yet (workflow step 2 pending); sanitized
|
|
||||||
fixtures are ready (data/fixtures/epsilon)
|
|
||||||
* create invoices from data in database
|
|
||||||
### Future / planned
|
|
||||||
* cli
|
|
||||||
* ingest xlsx files containing car rental transactions exported from tsdrms
|
|
||||||
* prepare bookkeeping voucher to be entered into Fortnox accounting/bookkeeping software suite
|
|
||||||
* ingest pdf files containing monthly settlement data from Enterprise
|
|
||||||
* spa
|
|
||||||
* website for car rental firms to check details regarding invoices
|
|
||||||
* receipt reissue for retail fuel sales (low priority)
|
|
||||||
* customer requests a receipt for a past fuel purchase (forgot to take it, or a printing issue)
|
|
||||||
* identifies the transaction by date + last 4 digits of the card number
|
|
||||||
* consumer cards are stored masked (e.g. `549543******5778`), so the last 4 digits are available for lookup
|
|
||||||
* creates a new receipt from a template
|
|
||||||
* sends it to the customer by e-mail
|
|
||||||
* to-do-application for employees
|
|
||||||
* car registry for RPN
|
|
||||||
* cars directly owned
|
|
||||||
* leased cars
|
|
||||||
* keeps track of costs associated with each car
|
|
||||||
* keeps track of yearly car inspections (besiktning)
|
|
||||||
* keeps track of general car status
|
|
||||||
* winter or summer tyres
|
|
||||||
* active, broken, being repaired (i.e. general status)
|
|
||||||
|
|
||||||
## Glossary
|
## Glossary
|
||||||
- aktiebolag: limited company
|
- aktiebolag: limited company
|
||||||
|
|||||||
Reference in New Issue
Block a user