openmerit 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +270 -0
  3. package/benchmark/invoice_ocr/data/invoice_01_ground_truth.json +38 -0
  4. package/benchmark/invoice_ocr/data/invoice_01_row_2.jpg +0 -0
  5. package/benchmark/invoice_ocr/data/invoice_02_ground_truth.json +32 -0
  6. package/benchmark/invoice_ocr/data/invoice_02_row_5.jpg +0 -0
  7. package/benchmark/invoice_ocr/data/invoice_03_ground_truth.json +26 -0
  8. package/benchmark/invoice_ocr/data/invoice_03_row_6.jpg +0 -0
  9. package/benchmark/invoice_ocr/data/invoice_04_ground_truth.json +26 -0
  10. package/benchmark/invoice_ocr/data/invoice_04_row_7.jpg +0 -0
  11. package/benchmark/invoice_ocr/data/invoice_05_ground_truth.json +38 -0
  12. package/benchmark/invoice_ocr/data/invoice_05_row_947.jpg +0 -0
  13. package/benchmark/invoice_ocr/data/invoice_06_ground_truth.json +38 -0
  14. package/benchmark/invoice_ocr/data/invoice_06_row_948.jpg +0 -0
  15. package/benchmark/invoice_ocr/data/invoice_07_ground_truth.json +20 -0
  16. package/benchmark/invoice_ocr/data/invoice_07_row_949.jpg +0 -0
  17. package/benchmark/invoice_ocr/data/invoice_08_ground_truth.json +38 -0
  18. package/benchmark/invoice_ocr/data/invoice_08_row_1888.jpg +0 -0
  19. package/benchmark/invoice_ocr/data/invoice_09_ground_truth.json +26 -0
  20. package/benchmark/invoice_ocr/data/invoice_09_row_1890.jpg +0 -0
  21. package/benchmark/invoice_ocr/data/invoice_10_ground_truth.json +20 -0
  22. package/benchmark/invoice_ocr/data/invoice_10_row_1892.jpg +0 -0
  23. package/benchmark/invoice_ocr/data/manifest.json +97 -0
  24. package/dist/benchmarks.js +98 -0
  25. package/dist/catalog.js +51 -0
  26. package/dist/cli.js +261 -0
  27. package/dist/daemon.js +305 -0
  28. package/dist/frontier.js +49 -0
  29. package/dist/invoice-eval.js +33 -0
  30. package/dist/invoice-score.js +124 -0
  31. package/dist/judge.js +43 -0
  32. package/dist/llm.js +66 -0
  33. package/dist/pi-trials.js +224 -0
  34. package/dist/policy.js +110 -0
  35. package/dist/recommend.js +63 -0
  36. package/dist/store.js +55 -0
  37. package/dist/strategist.js +64 -0
  38. package/dist/task-input.js +30 -0
  39. package/dist/traces.js +123 -0
  40. package/dist/trials.js +101 -0
  41. package/dist/types.js +2 -0
  42. package/examples/invoice-prompt.txt +19 -0
  43. package/examples/task.example.json +6 -0
  44. package/extension/openmerit.ts +705 -0
  45. package/instructions/OPENMERIT.md +51 -0
  46. package/instructions/openmerit.policy.json +33 -0
  47. package/package.json +77 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 openmerit contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,270 @@
1
+ # openmerit
2
+
3
+ An **experimental model-merit harness** for [pi](https://pi.dev). Start
4
+ pi with model A, and the OpenMerit extension observes
5
+ its completed trace, trials B and C sequentially through pi, compares quality,
6
+ price, and latency, and recommends a model for that exact pi session. The
7
+ shipped policy is supervised: you review and apply a recommendation with
8
+ `/openmerit apply`. Automatic swaps are available as an explicit opt-in.
9
+
10
+ ```text
11
+ pi task A → saved pi trace → extension trial job → pi trials B, C → scored frontier
12
+ ↑ │
13
+ └──── pi.setModel() ← approval/policy ← recommendation ┘
14
+ ```
15
+
16
+ ## How it maps to the design
17
+
18
+ 1. **Instruction file + policy file** — [`instructions/OPENMERIT.md`](instructions/OPENMERIT.md)
19
+ goes into the main harness's context (AGENTS.md-style);
20
+ [`instructions/openmerit.policy.json`](instructions/openmerit.policy.json)
21
+ (copied to `~/.openmerit/policy.json` by `openmerit init`) gates autonomy:
22
+ supervised recommendations by default, optional auto-apply thresholds,
23
+ budgets, and provider allow-lists. Public-benchmark relevance lives in
24
+ [`src/benchmarks.ts`](src/benchmarks.ts) (task category → benchmarks that
25
+ matter) plus a refreshable digest at `~/.openmerit/benchmarks/digest.json`.
26
+ 2. **Trial workflow** — the pi extension starts a session-bound comparison
27
+ after a supported task settles. It runs candidate trials sequentially under
28
+ configured candidate-trial caps. `openmerit watch` remains an optional CLI
29
+ mode. Pi's traces and JSON event stream supply results, cost,
30
+ latency, and errors; a judge or known-ground-truth scorer measures quality.
31
+ 3. **Per-task pareto frontier** — trials are keyed by task signature
32
+ ([`src/frontier.ts`](src/frontier.ts), 3 objectives: quality ↑, price ↓,
33
+ latency ↓). The aggregate across all of an agent's tasks is the union of
34
+ its task frontiers (`openmerit frontier`).
35
+ 4. **Model discovery** — the OpenRouter catalog is snapshotted and diffed;
36
+ newly appeared models are queued for future release experiments. The
37
+ per-task loop shortlists currently available pi/OpenRouter models with
38
+ OpenRouter benchmark signals and the existing strategist
39
+ ([`src/catalog.ts`](src/catalog.ts) + [`src/daemon.ts`](src/daemon.ts)).
40
+ 5. **Informing the main harness** — recommendations land in
41
+ `~/.openmerit/recommendations.jsonl`. The pi extension
42
+ ([`extension/openmerit.ts`](extension/openmerit.ts)) reports progress, polls it, and applies
43
+ swaps with `pi.setModel()` — automatically when the policy gate passes,
44
+ otherwise after user approval (`/openmerit`, `/openmerit apply`). The same
45
+ recommendation carries the updated fallback, used when the active model
46
+ starts failing.
47
+
48
+ ## Install from npm
49
+
50
+ You need Node 22.18+, pi 0.85.1+, and an OpenRouter API key with available
51
+ credits. Install the package into pi, then initialize its policy and state:
52
+
53
+ ```bash
54
+ pi install npm:openmerit
55
+ npx --yes openmerit init
56
+ pi list
57
+ ```
58
+
59
+ `pi install` makes the extension and its trial engine available to pi. The
60
+ one-off `npx` command creates `~/.openmerit/policy.json`; install OpenMerit
61
+ globally with `npm install --global openmerit` only if you also want persistent
62
+ shell access to `openmerit status`, `frontier`, or the optional watcher. Install
63
+ the extension from only one source—remove any older copied `openmerit.ts` first
64
+ so pi does not load it twice.
65
+
66
+ For development from a local checkout instead, run:
67
+
68
+ ```bash
69
+ npm ci
70
+ node dist/cli.js init
71
+ pi install "$PWD"
72
+ ```
73
+
74
+ Keep that checkout available because pi loads a local package from its path.
75
+
76
+ ## Run OpenMerit with pi
77
+
78
+ 1. Initialize OpenMerit if you did not do so during installation:
79
+
80
+ ```bash
81
+ npx --yes openmerit init
82
+ ```
83
+
84
+ `init` creates `~/.openmerit/policy.json` if missing and **keeps an existing
85
+ policy**. The shipped policy uses `"mode": "recommend"` and does not change
86
+ the active model without approval.
87
+
88
+ 2. Give **Pi and the extension trial job** OpenRouter access. The job reads
89
+ `OPENROUTER_API_KEY` from its environment or `~/.openmerit/.env`. If using
90
+ the file, edit it to contain `OPENROUTER_API_KEY=your-key` and protect it:
91
+
92
+ ```bash
93
+ nano ~/.openmerit/.env
94
+ chmod 600 ~/.openmerit/.env
95
+ ```
96
+
97
+ Pi does **not** read OpenMerit's `.env` file. Log in to OpenRouter with
98
+ `/login openrouter` inside pi, or export `OPENROUTER_API_KEY` in the shell
99
+ that starts pi. Verify pi's side without printing the key:
100
+
101
+ ```bash
102
+ pi auth check --provider openrouter --json
103
+ ```
104
+
105
+ A ready configuration prints `{"status":"ready","provider":"openrouter",...}`.
106
+ Older `model_search/.env` files are not read by the trial engine.
107
+
108
+ 3. Verify the extension appears in `pi list`. The instruction file
109
+ [`instructions/OPENMERIT.md`](instructions/OPENMERIT.md) can be added to a
110
+ pi project's AGENTS.md for agent context, but the extension does
111
+ not require it.
112
+
113
+ 4. Start pi in one terminal with an OpenRouter model and tools disabled:
114
+
115
+ ```bash
116
+ pi --provider openrouter --model openai/gpt-4o-mini --no-tools
117
+ ```
118
+
119
+ For a first text task, ask: “Give the shortest valid word ladder from cat
120
+ to dog. Each step changes one letter and must be a common English word.
121
+ Return only the path.” Wait for A to finish and leave the pi session open.
122
+ The extension automatically starts B and C **sequentially through pi**,
123
+ reports each score in Pi, and writes a recommendation for this exact
124
+ session. With the shipped supervised policy, use
125
+ `/openmerit` inside pi to inspect the evidence and `/openmerit apply` to
126
+ switch. Then send a second message to see which model actually handles it.
127
+ You do not need a watcher terminal or the standalone `trial` command.
128
+
129
+ To opt in to automatic swaps, edit `~/.openmerit/policy.json`, set
130
+ `"mode": "auto"` and `"auto_apply.enabled": true`, review the score-gain
131
+ and price-ratio thresholds, and run the next task.
132
+
133
+ ### Try an invoice-to-JSON task
134
+
135
+ Use the same one-terminal setup. Start pi with a vision-capable model, for
136
+ example `openai/gpt-4o-mini`, and `--no-tools`. In pi, type `@` to select
137
+ [`benchmark/invoice_ocr/data/invoice_01_row_2.jpg`](benchmark/invoice_ocr/data/invoice_01_row_2.jpg)
138
+ and paste the **entire, unchanged** text from
139
+ [`examples/invoice-prompt.txt`](examples/invoice-prompt.txt) into the same
140
+ message. Pi also accepts pasted or dragged images. Wait for the JSON answer;
141
+ keep pi open while the extension trials two other vision models. OpenMerit uses
142
+ the existing benchmark's visibility-audited exact-field scorer when the saved
143
+ task contains the exact example prompt and original bytes of a pinned JPEG.
144
+ Pi may resize an attached image or add a file header to the prompt; in that
145
+ case, the run uses the vision judge that sees the image and answer. Other
146
+ uploaded invoices also use that judge because they have no ground truth.
147
+
148
+ A real pinned-invoice run produced this trial output (models and scores will
149
+ vary between runs):
150
+
151
+ ```text
152
+ [openmerit] task 0e7642522dc5: A=openai/gpt-4o-mini score=1.00 from pi trace
153
+ [openmerit] task 0e7642522dc5: google/gemma-3-12b-it score=0.31 cost=$0.0001
154
+ [openmerit] task 0e7642522dc5: mistralai/ministral-14b-2512 score=1.00 cost=$0.0007
155
+ [openmerit] task 0e7642522dc5: selected mistralai/ministral-14b-2512; auto=false
156
+ ```
157
+
158
+ Pi candidate runs rely on the explicit invoice prompt for JSON structure.
159
+ The standalone invoice benchmark sends a strict OpenRouter `response_format`
160
+ schema, so its published scores are not directly comparable to these pi runs.
161
+
162
+ ### Inspect or troubleshoot a run
163
+
164
+ `npx openmerit status` shows the latest pi model and pending recommendations;
165
+ `npx openmerit frontier` shows measured quality, blended price, latency, and
166
+ the chosen frontier per task. `/openmerit` inside pi shows the current model,
167
+ fallback, the model currently being compared, completed models with quality,
168
+ cost, and latency, trial budget, pending recommendations, and any exact-task result
169
+ measured in another session. When the gate declines an automatic swap, it
170
+ prints reasons and `/openmerit apply` remains available.
171
+
172
+ The daily trial-count and dollar limits come from `~/.openmerit/policy.json`.
173
+ If a limit is reached, the extension reports why it skipped the comparison;
174
+ the count resets at midnight UTC. You may raise `budgets.max_trials_per_day`
175
+ for local experiments while keeping `budgets.max_usd_per_day` as a conservative
176
+ candidate-spend threshold.
177
+
178
+ If no comparison starts after Pi settles, confirm that pi loaded the extension
179
+ (`pi list`), the task finished, the pi session is saved (do not use
180
+ `--no-session`), and the task used no tools. Image candidates must advertise
181
+ image input in OpenRouter's current model catalog. The extension queues
182
+ completed tasks from its current session and runs one comparison at a time.
183
+ Closing or switching the session cancels the active job.
184
+ Candidate runs use the same text and uploaded image bytes, but they do not
185
+ replay earlier answers or file changes. An exact task in another session
186
+ (including identical image bytes) appears as **advice**, not a pending swap;
187
+ the new session still gets its own comparison. The optional `trial` command
188
+ remains for controlled text-task runs from a task JSON file.
189
+
190
+ ## Alpha boundaries
191
+
192
+ - With the extension installed and an OpenRouter key configured, each supported
193
+ settled task can start comparison calls automatically. Candidate, judge, and
194
+ strategist requests send the task text, attached images, and candidate output
195
+ to OpenRouter and can incur charges. Use non-sensitive test tasks and
196
+ conservative account limits while evaluating this alpha.
197
+ - The extension queues tasks from its current pi session, compares one at a
198
+ time, and skips tasks that use tools. Candidate sessions replay the latest
199
+ text and images, not earlier conversation context or workspace changes.
200
+ - `ledger.json` counts reported candidate-trial spend and the daily number of
201
+ trials. It does not yet include rubric, judge, or strategist request cost,
202
+ and `max_usd_per_trial` is not yet a hard provider-side cap.
203
+ - Each comparison has one observed baseline plus a small candidate slate and
204
+ one quality score per answer. Treat recommendations as experimental evidence,
205
+ not a universal model ranking.
206
+
207
+ ## State layout (`~/.openmerit/`)
208
+
209
+ | file | contents |
210
+ |---|---|
211
+ | `policy.json` | the policy file (gate thresholds, budgets, intervals) |
212
+ | `harness-state.json` | written by the pi extension: current model, fallback, latest session and settled task |
213
+ | `recommendations.jsonl` | shared append-only channel: session-bound swap recommendations + status updates |
214
+ | `trials.jsonl` | every model trial point (source, score, price, latency) |
215
+ | `observations.jsonl` | task observations extracted from session traces |
216
+ | `catalog/snapshot.json` + `candidates.json` | catalog snapshot (including input modalities) + new-model queue |
217
+ | `benchmarks/digest.json` | public-benchmark scores per model (seed + refresh) |
218
+ | `ledger.json` | daily trial spend (budget enforcement) |
219
+ | `watch/processed.json` | latest task handled by optional CLI watcher |
220
+ | `watch/jobs/*.json` | per-session comparison status and retry marker |
221
+
222
+ ## Benchmarks
223
+
224
+ From a source checkout, the benchmark runners are TypeScript and execute
225
+ directly on Node 22.18+; no transpilation step or Python environment is
226
+ required. The slim npm artifact keeps only the pinned invoice data needed by
227
+ runtime scoring; use the repository checkout for these developer commands:
228
+
229
+ ```bash
230
+ npm run benchmark:invoice -- --models google/gemini-3.8-flash
231
+ npm run benchmark:invoice:round2 -- --verify-only
232
+ npm run benchmark:text-to-sql -- --verify-only
233
+ npm run benchmark:policy:validate
234
+ npm run benchmark:policy -- --verify-only
235
+ npm run benchmark:verify-recorded
236
+ ```
237
+
238
+ - `benchmark/invoice_ocr/` — two real vision/OCR model slates over the same
239
+ pinned 10-invoice dataset.
240
+ - `benchmark/text_to_sql/` — executable SQLite evaluation over 10 analytical
241
+ tasks.
242
+ - `benchmark/policy_adjudication/` — 12 adversarial reimbursement-policy cases,
243
+ including prompt-injection cases and frozen input hashes.
244
+
245
+ All three benchmark families preserve raw JSONL observations, audited summaries,
246
+ cost/latency/quality rankings, and Pareto layers. `npm run typecheck` covers both
247
+ the application and every benchmark runner. `npm run benchmark:verify-recorded`
248
+ replays the checked-in raw results locally and compares them with their audited
249
+ artifacts without making provider calls or writing new results.
250
+
251
+ ## Maintainer release
252
+
253
+ OpenMerit follows pi's [package format](https://github.com/earendil-works/pi/blob/main/packages/coding-agent/docs/packages.md):
254
+ the npm manifest has the `pi-package` keyword, a `pi.extensions` entry, and the
255
+ pi API as a peer dependency. Public npm packages with that keyword are eligible
256
+ for pi's package gallery; a separate approval from the pi team is not part of
257
+ the standard listing flow.
258
+
259
+ Before publishing a release:
260
+
261
+ ```bash
262
+ npm run check
263
+ npm pack --dry-run
264
+ npm publish --access public
265
+ ```
266
+
267
+ Then verify the actual public artifact with `npm view openmerit` and a clean
268
+ `pi install npm:openmerit`. Gallery indexing may not be immediate. A featured
269
+ or curated mention in pi-owned documentation is separate and would require the
270
+ maintainers to accept a contribution or request.
@@ -0,0 +1,38 @@
1
+ {
2
+ "supplier_name": "PixelWave Solutions Inc.",
3
+ "customer_name": "Greenfield Marketing Ltd.",
4
+ "invoice_number": "INV-2023-0098",
5
+ "po_number": "PO-5678",
6
+ "document_date": "2023-07-15",
7
+ "due_date": "2023-08-14",
8
+ "document_currency": "CAD",
9
+ "document_total_net": 2220.0,
10
+ "document_total_tax": 111.0,
11
+ "document_total_amount": 2331.0,
12
+ "line_items": [
13
+ {
14
+ "description": "Website design services",
15
+ "quantity": 1.0,
16
+ "unit_price": 1200.0,
17
+ "amount": 1200.0
18
+ },
19
+ {
20
+ "description": "Content writing package",
21
+ "quantity": 10.0,
22
+ "unit_price": 50.0,
23
+ "amount": 500.0
24
+ },
25
+ {
26
+ "description": "SEO optimization",
27
+ "quantity": 5.0,
28
+ "unit_price": 80.0,
29
+ "amount": 400.0
30
+ },
31
+ {
32
+ "description": "Hosting subscription",
33
+ "quantity": 12.0,
34
+ "unit_price": 10.0,
35
+ "amount": 120.0
36
+ }
37
+ ]
38
+ }
@@ -0,0 +1,32 @@
1
+ {
2
+ "supplier_name": "TechSolutions Ltd",
3
+ "customer_name": null,
4
+ "invoice_number": "IE-INV-2024-000123",
5
+ "po_number": null,
6
+ "document_date": "2024-03-15",
7
+ "due_date": null,
8
+ "document_currency": "EUR",
9
+ "document_total_net": 6200.0,
10
+ "document_total_tax": 1143.0,
11
+ "document_total_amount": 7343.0,
12
+ "line_items": [
13
+ {
14
+ "description": "Consulting services for project X",
15
+ "quantity": 3.0,
16
+ "unit_price": 1500.0,
17
+ "amount": 4500.0
18
+ },
19
+ {
20
+ "description": "High-performance laptop (Model Y)",
21
+ "quantity": 1.0,
22
+ "unit_price": 1200.0,
23
+ "amount": 1200.0
24
+ },
25
+ {
26
+ "description": "International shipping to Germany",
27
+ "quantity": 1.0,
28
+ "unit_price": 500.0,
29
+ "amount": 500.0
30
+ }
31
+ ]
32
+ }
@@ -0,0 +1,26 @@
1
+ {
2
+ "supplier_name": "CloudCompute Solutions Inc.",
3
+ "customer_name": "Acme Corp.",
4
+ "invoice_number": "INV-20230815-001",
5
+ "po_number": "PO-987654",
6
+ "document_date": "2023-08-15",
7
+ "due_date": "2023-09-14",
8
+ "document_currency": "USD",
9
+ "document_total_net": 110.0,
10
+ "document_total_tax": 9.07,
11
+ "document_total_amount": 119.07,
12
+ "line_items": [
13
+ {
14
+ "description": "Enterprise Cloud Storage Subscription",
15
+ "quantity": 1.0,
16
+ "unit_price": 50.0,
17
+ "amount": 50.0
18
+ },
19
+ {
20
+ "description": "Premium Support Add-On",
21
+ "quantity": 2.0,
22
+ "unit_price": 30.0,
23
+ "amount": 60.0
24
+ }
25
+ ]
26
+ }
@@ -0,0 +1,26 @@
1
+ {
2
+ "supplier_name": "Tech Solutions Ltd",
3
+ "customer_name": "Acme Construction Ltd",
4
+ "invoice_number": "INV-20230815-001",
5
+ "po_number": "PO-7654321",
6
+ "document_date": "2023-08-15",
7
+ "due_date": "2023-09-14",
8
+ "document_currency": "GBP",
9
+ "document_total_net": 1500.0,
10
+ "document_total_tax": 240.0,
11
+ "document_total_amount": 1740.0,
12
+ "line_items": [
13
+ {
14
+ "description": "High-performance laptop",
15
+ "quantity": 1.0,
16
+ "unit_price": 1200.0,
17
+ "amount": 1200.0
18
+ },
19
+ {
20
+ "description": "Office desk chair",
21
+ "quantity": 2.0,
22
+ "unit_price": 150.0,
23
+ "amount": 300.0
24
+ }
25
+ ]
26
+ }
@@ -0,0 +1,38 @@
1
+ {
2
+ "supplier_name": "Celtic Code Solutions",
3
+ "customer_name": "North Star Consulting Ltd.",
4
+ "invoice_number": "INV-2023-0075",
5
+ "po_number": null,
6
+ "document_date": "2023-07-15",
7
+ "due_date": "2023-08-14",
8
+ "document_currency": "EUR",
9
+ "document_total_net": 4600.0,
10
+ "document_total_tax": 1058.0,
11
+ "document_total_amount": 5658.0,
12
+ "line_items": [
13
+ {
14
+ "description": "UI Development Consulting",
15
+ "quantity": 20.0,
16
+ "unit_price": 80.0,
17
+ "amount": 1600.0
18
+ },
19
+ {
20
+ "description": "UX Research",
21
+ "quantity": 10.0,
22
+ "unit_price": 90.0,
23
+ "amount": 900.0
24
+ },
25
+ {
26
+ "description": "Custom API Integration",
27
+ "quantity": 15.0,
28
+ "unit_price": 100.0,
29
+ "amount": 1500.0
30
+ },
31
+ {
32
+ "description": "Project Management Support",
33
+ "quantity": 5.0,
34
+ "unit_price": 120.0,
35
+ "amount": 600.0
36
+ }
37
+ ]
38
+ }
@@ -0,0 +1,38 @@
1
+ {
2
+ "supplier_name": "Oak Property Management Ltd",
3
+ "customer_name": "John Doe",
4
+ "invoice_number": "RENT-2023-001",
5
+ "po_number": null,
6
+ "document_date": "2023-05-01",
7
+ "due_date": "2023-05-15",
8
+ "document_currency": "EUR",
9
+ "document_total_net": 1650.0,
10
+ "document_total_tax": 103.5,
11
+ "document_total_amount": 1753.5,
12
+ "line_items": [
13
+ {
14
+ "description": "Monthly Base Rent",
15
+ "quantity": 1.0,
16
+ "unit_price": 1200.0,
17
+ "amount": 1200.0
18
+ },
19
+ {
20
+ "description": "Utilities (Electricity/Gas)",
21
+ "quantity": 1.0,
22
+ "unit_price": 200.0,
23
+ "amount": 200.0
24
+ },
25
+ {
26
+ "description": "Property Tax",
27
+ "quantity": 1.0,
28
+ "unit_price": 150.0,
29
+ "amount": 150.0
30
+ },
31
+ {
32
+ "description": "Cleaning Service",
33
+ "quantity": 1.0,
34
+ "unit_price": 100.0,
35
+ "amount": 100.0
36
+ }
37
+ ]
38
+ }
@@ -0,0 +1,20 @@
1
+ {
2
+ "supplier_name": "Acme Office Supplies Inc.",
3
+ "customer_name": "Global Tech Corp.",
4
+ "invoice_number": "INV-2023-0001",
5
+ "po_number": null,
6
+ "document_date": "2023-07-15",
7
+ "due_date": "2023-08-15",
8
+ "document_currency": "USD",
9
+ "document_total_net": 600.0,
10
+ "document_total_tax": 42.0,
11
+ "document_total_amount": 642.0,
12
+ "line_items": [
13
+ {
14
+ "description": "Office chairs",
15
+ "quantity": 5.0,
16
+ "unit_price": 120.0,
17
+ "amount": 600.0
18
+ }
19
+ ]
20
+ }
@@ -0,0 +1,38 @@
1
+ {
2
+ "supplier_name": "Digital Solutions Pty Ltd",
3
+ "customer_name": "Global Tech Industries Ltd",
4
+ "invoice_number": "INV-2024-005",
5
+ "po_number": null,
6
+ "document_date": "2024-06-15",
7
+ "due_date": "2024-07-15",
8
+ "document_currency": "AUD",
9
+ "document_total_net": 3840.0,
10
+ "document_total_tax": 384.0,
11
+ "document_total_amount": 4224.0,
12
+ "line_items": [
13
+ {
14
+ "description": "Cloud hosting services",
15
+ "quantity": 12.0,
16
+ "unit_price": 120.0,
17
+ "amount": 1440.0
18
+ },
19
+ {
20
+ "description": "Software license renewal",
21
+ "quantity": 1.0,
22
+ "unit_price": 1200.0,
23
+ "amount": 1200.0
24
+ },
25
+ {
26
+ "description": "Subscription data analytics package",
27
+ "quantity": 1.0,
28
+ "unit_price": 800.0,
29
+ "amount": 800.0
30
+ },
31
+ {
32
+ "description": "Technical support",
33
+ "quantity": 1.0,
34
+ "unit_price": 400.0,
35
+ "amount": 400.0
36
+ }
37
+ ]
38
+ }
@@ -0,0 +1,26 @@
1
+ {
2
+ "supplier_name": "Acme Consulting Group",
3
+ "customer_name": null,
4
+ "invoice_number": "INV-2023-0789",
5
+ "po_number": "PO-2023-4567",
6
+ "document_date": "2023-07-15",
7
+ "due_date": "2023-08-14",
8
+ "document_currency": "USD",
9
+ "document_total_net": 3250.0,
10
+ "document_total_tax": 268.12,
11
+ "document_total_amount": 3518.12,
12
+ "line_items": [
13
+ {
14
+ "description": "Business Strategy Consultation",
15
+ "quantity": 10.0,
16
+ "unit_price": 200.0,
17
+ "amount": 2000.0
18
+ },
19
+ {
20
+ "description": "Technology Roadmap Development",
21
+ "quantity": 5.0,
22
+ "unit_price": 250.0,
23
+ "amount": 1250.0
24
+ }
25
+ ]
26
+ }
@@ -0,0 +1,20 @@
1
+ {
2
+ "supplier_name": "VirtualCo Solutions",
3
+ "customer_name": "John Doe",
4
+ "invoice_number": "INV-2023-000123",
5
+ "po_number": null,
6
+ "document_date": "2023-07-15",
7
+ "due_date": "2023-08-14",
8
+ "document_currency": "USD",
9
+ "document_total_net": 1200.0,
10
+ "document_total_tax": 96.0,
11
+ "document_total_amount": 1296.0,
12
+ "line_items": [
13
+ {
14
+ "description": "Enterprise SaaS Subscription for Q3 2023",
15
+ "quantity": 1.0,
16
+ "unit_price": 1200.0,
17
+ "amount": 1200.0
18
+ }
19
+ ]
20
+ }