feat(dimensions): PR3 tagging — voucher-form pickers, MCP dimension tools with resolve-don't-select, engine soft validation (#859)

Phase 3 of dev_docs/dimensions_implementation_plan.md. Companies with
dimensions_enabled=false see zero change; existing free-text API writers keep
working (validation is toggle-governed).

Engine (soft validation):
- validateEntryDimensions() in dimension-resolver: zero queries for untagged
  entries; toggle off → passthrough; toggle on → one settings fetch + two
  registry queries, rejects unknown dims/codes and archived values with
  Swedish per-code messages (DimensionValidationError, 400, details.issues).
  Wired into createDraftEntry + updateDraftEntry before any insert; reversal/
  storno paths untouched (verbatim copies). Fails open on transient registry
  errors — soft validation must never block bookkeeping.

MCP (agent write path):
- New tools: gnubok_list_dimensions, gnubok_list_dimension_values (fuse.js
  fuzzy), gnubok_create_dimension_value (STAGED via pending_operations —
  agents never silently mint reporting values; new op type + CHECK migration
  + executor with duplicate-idempotency).
- create_voucher/correct_entry: per-line dimensions bag + default_dimensions,
  resolve-don't-select server-side (code OR natural-language name; exact →
  fuzzy ≤0.30 with ≥0.15 runner-up margin; non-exact resolutions echoed with
  confidence; ambiguous → ranked candidates, no auto-create).
- gnubok_get_agent_briefing gains a dimensions block (enabled, dims, top
  values) — omitted when registry empty.
- TOOL_SCOPE_MAP entries; risk tier low for staged value creation.

UI:
- JournalEntryForm (manual voucher + TransactionBookingDialog embed): header
  "+ Kostnadsställe/Projekt" progressive disclosure (gäller alla rader with
  documented inheritance rule) + per-row tag popover + compact KS·PR badges;
  gated on dimensions_enabled.
- Voucher detail: display-only dimension badges with registry-name resolution.
- EditDraftEntryDialog carries line dimensions so editing a draft no longer
  strips tags.

categorize/bulk_book dims deferred to PR7 (needs the bulk_book RPC migration).

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Jakob Wennberg
2026-07-02 13:36:45 +02:00
committed by GitHub
co-authored by Claude Fable 5
parent 6be6510d73
commit 11126d6d56
28 changed files with 3152 additions and 43 deletions
+3
View File
@@ -1800,6 +1800,9 @@ export type PendingOperationType =
// (returns a signing link); the user's signature in the browser files it.
| 'submit_vat_declaration'
| 'submit_agi'
// Dimensions PR3: stage a new dimension value (kostnadsställe/projekt object
// code, SIE #OBJEKT) — agents never silently mint reporting values.
| 'create_dimension_value'
export type PendingOperationStatus = 'pending' | 'committing' | 'committed' | 'rejected'
// 'agent_chat' = the in-app AI chat (DB CHECK widened in migration