v2.7.0
v2.7.0 Release Summary
What's New
This release turns invoice itemization into a one-click, AI-assisted workflow and makes budget bookkeeping far more forgiving. Cornerstone can now read the line items off a vendor's PDF invoice for you, you can edit and re-home invoice-linked budget lines without deleting them, and a brand-new in-app editor lets you mark up diary photos directly in the browser. No manual migration steps are required.
Highlights
-
Auto-itemize Invoices (LLM-powered) -- Open a linked invoice PDF and let Cornerstone extract its line items for you. A dedicated review page shows the original document side-by-side with the extracted lines, each on its own card with editable amounts, a confidence indicator, and inline category, funding-source, and item-assignment pickers. Works with any OpenAI-compatible provider -- Google Gemini, Anthropic, OpenAI, or a self-hosted Ollama model -- auto-detected from the endpoint you configure. The feature is opt-in and off by default: nothing leaves your server until you set the LLM environment variables, and even then only the document's OCR text and a few invoice details are sent -- never the PDF itself or your API key.
-
Photo Annotation Editor -- A Shottr-style markup editor for diary photos, right in the browser. Open any diary photo and annotate it with arrows, rectangles, ellipses, lines, text labels, dimension measurements, freehand strokes, and translucent highlights. It is optimized for touch and Apple Pencil, fully non-destructive (the original is always preserved, with a View original toggle and Reset to original action), and the annotated copy is saved alongside the original.
-
Inline budget line editing & move -- Edit invoice-linked budget lines directly from the Work Item and Household Item detail pages -- no need to unlink first. You can now also move a line to a different work item or household item, so a line that landed on the wrong item (a common case with auto-itemized lines) can be re-homed instead of deleted and re-created.
-
Document viewer "hide already-linked" toggle -- The document picker gains a system-wide filter that hides any document already linked anywhere in Cornerstone, making it easy to find documents you have not filed yet.
Notable Fixes
- Print/export of the Budget Overview now restores your expansion state afterwards and resets dark-mode styling correctly for a clean printout.
- The Budget Overview no longer shows a redundant "Auto-itemized" badge that provided no useful information.
- Diary entry editing no longer triggers spurious native form-validation popups.
- Save buttons on budget forms now meet the 44px minimum touch-target size on mobile.
Upgrade
docker pull steilerdev/cornerstone:latestRestart your container. Schema migrations run automatically on first boot. To enable Auto-itemize, set the LLM_BASE_URL, LLM_API_KEY, and LLM_MODEL environment variables -- see the Auto-itemize guide for provider examples.
2.7.0 (2026-06-13)
Features
- add cornerstone-docs-writer agent definition (#1609) (f3031b6)
- auto-itemize: full auto-itemize flow with preview modal and apply (#1547) (#1550) (37c7769), closes #1545
- auto-itemize: operator-configurable LLM_MAX_TOKENS env var (#1547) (#1563) (857597f), closes #1562 #1562
- auto-itemize: redesign as dedicated page with per-row assignment picker (#1564) (#1566) (c7d28d7)
- auto-itemize: rework UI with PDF iframe, cards, spinner, status field (#1576) (#1577) (a9be1c4)
- budget-extraction: BudgetExtractionService with OpenAI-compatible LLM gateway (#1546) (#1549) (49978bc)
- budget-lines: full edit + linked-item move (#1553) (#1554) (a5c002d), closes #budget-line-amount #budget-itemized-amount #1425
- budget: enable editing invoice-linked budget lines from work/household item pages (#1607) (e37f5d6), closes #1603
- budget: surface discretionary funding source on auto-itemized lines (#1551) (#1610) (75c11f2)
- documents: hide-linked toggle filters system-wide (#1557) (#1559) (4f261f1), closes #42 #55
- photo-annotator: fix PhotoViewer post-annotation button state and adopt konva 10 capabilities (#1608) (37479fd), closes #1482 #1569
- unassigned budget lines & one-shot parent assignment (#1545) (#1548) (88ded38)
Bug Fixes
- auto-itemize: assignment dialog overflow, create-new affordance, auto-prefill from extraction (#1601) (6f7418e), closes #1600 #1600 #1600 #1600
- auto-itemize: bump max_tokens to 16384 + detect truncation explicitly (#1562) (74be802)
- auto-itemize: drop ineffective position:sticky on previewColumn (#1599) (e6df173), closes #1590
- auto-itemize: extract invoiceNumber+notes via LLM, fix sticky PDF (#1581) (#1582) (ce47b9f)
- auto-itemize: provider-aware LLM request shaping (#1547) (#1558) (c70d4c9), closes #1553 #1545 #parent-picker-body #budget-itemized-amount #budget-line-amount #budget-itemized-amount 1555/#1557 #1553
- auto-itemize: regression follow-ups + ParentPicker extraction + LLM category (#1586,#1590,#1591,#1595,#1596,#1597) (#1598) (55bc09d), closes #1594
- auto-itemize: repair dead iframe PDF fallback + clean up E2E/unit tests (#1612) (4f2e17e), closes #1578 #1583 #1614 #1594
- auto-itemize: restore mainContent scroll + drop align-items:start on pageBody (#1602) (eaf27e7), closes #1592 #1599
- auto-itemize: set strict=true on Anthropic json_schema response format (#1561) (a889cfe), closes #1558
- auto-itemize: snapshot wasCreatedFromExtraction ref before setLines to fix WebKit badge race (#1613) (#1619) (676a84f)
- auto-itemize: UX fixes + assignment flow polish (#1586-#1591) (#1592) (08efaf5), closes #1584 #1585 #1588 #1589 #1584 #1585 #1587 #1588 #1589 #1590
- budget-lines: remove overrestrictive guard on parent move (#1555) (#1556) (e1a5b48)
- budget-print: restore pre-print expansion state and dark-mode print CSS reset (#1606) (70a4140), closes #1450 #1451
- budget: ensure save button touch target ≥ 44px on mobile WebKit (#1626) (#1654) (7ebdf93)
- budget: remove dead auto-origin badge from Budget Overview (#1615) (#1655) (f19a1a8), closes #1551 #1610
- diary: suppress native validation on DiaryEntryEditPage form (#1434) (#1623) (7a04730)
- e2e: add explicit waits after radio clicks in Perspective toggle test (#1666) (8ad7e60), closes #1658
- e2e: avoid WebKit double-toggle on nested checkbox in budget-source-move (#1575) (#1660) (1b0e24a)
- e2e: comprehensively harden all shard 3 budget-source timing-sensitive tests (#1671) (59099a4), closes #1658
- e2e: make multi-deselection refetchB predicate specific to SOURCE_B_ID (#1667) (9a80be4), closes #1658
- e2e: remove legacy auto-itemize modal tests that block shard 1 promotion (#1662) (3cba571), closes #1564 #1564
- e2e: resolve admin/auth shard 1 E2E failures blocking promotion (#1663) (5bdea6e), closes #ffffff #ffffff #fff #1606
- e2e: resolve shard 1 pre-existing failures blocking promotion (#1575) (#1661) (33d918c), closes #1655 #1615 #1615 #1655
- e2e: resolve shard 3 budget-source-filter failures blocking promotion (#1665) (50442f1), closes #1658
- e2e: robustify Perspective toggle + multi-deselect predicate for shard 3 (#1668) (6acf745), closes #1658
- invoices: restore eagerLinkInvoice=true in InvoiceBudgetLinesSection (#1611) (#1617) (30bd873)
- security: allow same-origin iframes via CSP frame-src 'self' (#1579) (#1580) (8819e37)
Documentation
- auto-itemize: user guide + configuration + roadmap (#1547) (#1552) (99dd418), closes #1551
- claude: expand CI quirks section to cover both skip-directive failure modes (#1544) (3dc9b4d)
- claude: reorganize CLAUDE.md for clearer section grouping (#1650) (9dc3e9e)
- server/services: document better-sqlite3 12.10.0 percentile adoption opportunity (#1571) (#1644) (1c2850d)
- update documentation for photo annotator + auto-itemize release (#1669) (6506063)
- update wiki submodule — API Contract GET /api/config autoItemizeEnabled (#1629) (dd96923)
Chores
- deps-dev: bump the dev-dependencies group across 1 directory with 13 updates (#1652) (d3d379c)
- deps-dev: bump the dev-dependencies group with 9 updates (#1511) (1287ce7)
- deps-dev: bump tmp from 0.2.5 to 0.2.7 (#1604) (df744bb)
- deps: bump qs and express (#1560) (bb3a07d)
- deps: bump the github-actions group with 2 updates (#1510) (6e9af5d)
- deps: bump the github-actions group with 7 updates (#1647) (cf2a670)
- deps: bump the prod-dependencies group across 1 directory with 5 updates (#1527) (f87d4c2)
- eslint: add cleanup for setTimeout/setInterval/addEventListener in useEffect (#1468) (#1643) (148d993), closes #1455
- eslint: add test-files override to relax React Compiler rules (#1618) (d338328), closes #1456
- eslint: extract IIFEs from JSX to const variables (#1460) (#1632) (9bc6660), closes #1455
- eslint: fix @typescript-eslint/no-unused-vars across all workspaces (#1457) (#1628) (5e5c9d0), closes #1560
- eslint: fix eslint-react/purity warnings — move side effects to useEffect (#1471) (#1640) (fb4c5d9), closes #1455
- eslint: fix jsx-no-children-prop — use JSX children syntax (#1461) (#1634) (7a6f122), closes #1455
- eslint: fix miscellaneous @eslint-react structural errors (#1462) (#1642) (9c1ced3), closes #1455
- eslint: fix React 19 migration warnings (no-context-provider, no-use-context) (#1464) (#1636) (e06c5b3), closes #1455
- eslint: rename useRef variables to *Ref naming convention (#1467) (#1639) (3af0d23), closes #1455
- eslint: replace array index keys with stable identifiers (#1466) (#1641) (64d8a73), closes #1455
- eslint: wrap non-trivial useState initializers in arrow functions (#1465) (#1638) (473501e), closes #1455
- retrigger promotion CI (post-docs auto-fix skip-ci) (#1670) (1717704)
- retrigger promotion CI after auto-fix skip-ci (#1664) (28fe6ae)
- skills: add /dependabot for end-to-end alert and PR processing (#1567) (8f30048)
- test-infra: add afterEach(jest.clearAllMocks) hygiene to unit tests (#1622) (36d1cfe), closes #1620 #1646
- update implementation checklist with lessons from release (#1659) (3a4068d)