Last-day-of-month custom budget drops end-of-month transactions from Spending Breakdown totals
ses_01KWW84Y28SEZE9WH1NT5K6T3Z
Statusactive
CreatedJul 6, 05:38 PM
Last ActiveJul 6, 05:38 PM
Runs
| Run | Status | Trigger | Duration | Tokens | Started |
|---|---|---|---|---|---|
| run_01KX...CXHJ | completed | linear | 3.7 s | 3,517 | Jul 8, 11:42 PM |
| run_01KX...G798 | completed | linear | 1.5 s | 3,167 | Jul 8, 11:19 PM |
| run_01KW...MJK9 | completed | linear | 2.4 s | 2,680 | Jul 6, 05:44 PM |
| run_01KW...AJD8 | completed | linear | 2.2 s | 2,467 | Jul 6, 05:38 PM |
| run_01KW...JSVR | completed | linear | 6.2 s | 2,316 | Jul 6, 05:38 PM |
| run_01KW...KFFG | completed | linear | 20.7 s | 22,626 | Jul 6, 05:38 PM |
Events
| Event | Source | Kind | Actor | Run | Time |
|---|---|---|---|---|---|
| evt_01KW...SV8A | linear | Comment.create | 2bfd21e5-4c81-412d-a310-00cbf6d14769 | run_01KW...MJK9 | Jul 6, 05:44 PM |
| evt_01KW...HH9A | linear | Comment.create | a67bb8ae-4bf2-421c-948b-6b98613e2395 | run_01KW...JSVR | Jul 6, 05:38 PM |
Transcript
| Seq | Role | Run | Created | Message |
|---|---|---|---|---|
| 1 | user | run_01KW...KFFG | Jul 6, 05:38 PM | Text Event source: linear Event kind: Issue.create Actor: 33ae62ce-c95e-4da0-9d9b-08c407bf8344 Event summary: Linear Issue.create User/event text: Last-day-of-month custom budget drops end-of-month transactions from Spending Breakdown totals Event details: issueId: 6a802104-1979-4a6e-b7b8-ec488227ca9a issueTitle: Last-day-of-month custom budget drops end-of-month transactions from Spending Breakdown totals Raw message{
"role": "user",
"content": "Event source: linear\n\nEvent kind: Issue.create\n\nActor: 33ae62ce-c95e-4da0-9d9b-08c407bf8344\n\nEvent summary: Linear Issue.create\n\nUser/event text:\nLast-day-of-month custom budget drops end-of-month transactions from Spending Breakdown totals\n\nEvent details:\nissueId: 6a802104-1979-4a6e-b7b8-ec488227ca9a\nissueTitle: Last-day-of-month custom budget drops end-of-month transactions from Spending Breakdown totals"
} |
| 2 | assistant | run_01KW...KFFG | Jul 6, 05:38 PM | ReasoningLet me look at this Linear issue that was just created. I should load the Linear skill to get more details about this issue.Let me look at this Linear issue that was just created. I should load the Linear skill to get more details about this issue. Tool call · load_skill · call_4e91835722c646309eec33e9 {
"name": "linear"
}Raw message{
"role": "assistant",
"content": [
{
"type": "reasoning",
"text": "Let me look at this Linear issue that was just created. I should load the Linear skill to get more details about this issue."
},
{
"type": "tool-call",
"toolCallId": "call_4e91835722c646309eec33e9",
"toolName": "load_skill",
"input": {
"name": "linear"
}
}
]
} |
| 3 | tool | run_01KW...KFFG | Jul 6, 05:38 PM | Tool result · load_skill · call_4e91835722c646309eec33e9 {
"type": "json",
"value": {
"loaded": true,
"name": "linear"
}
}Raw message{
"role": "tool",
"content": [
{
"type": "tool-result",
"toolCallId": "call_4e91835722c646309eec33e9",
"toolName": "load_skill",
"output": {
"type": "json",
"value": {
"loaded": true,
"name": "linear"
}
}
}
]
} |
| 4 | assistant | run_01KW...KFFG | Jul 6, 05:38 PM | Tool call · linear_get_issue · chatcmpl-tool-98eda14c01c47609 {
"id": "6a802104-1979-4a6e-b7b8-ec488227ca9a"
}Raw message{
"role": "assistant",
"content": [
{
"type": "tool-call",
"toolCallId": "chatcmpl-tool-98eda14c01c47609",
"toolName": "linear_get_issue",
"input": {
"id": "6a802104-1979-4a6e-b7b8-ec488227ca9a"
}
}
]
} |
| 5 | tool | run_01KW...KFFG | Jul 6, 05:38 PM | Tool result · linear_get_issue · chatcmpl-tool-98eda14c01c47609 {
"type": "json",
"value": {
"id": "6a802104-1979-4a6e-b7b8-ec488227ca9a",
"identifier": "ENG-431",
"title": "Last-day-of-month custom budget drops end-of-month transactions from Spending Breakdown totals",
"description": "## Problem\n\nWith the custom budget period set to **\"New budget every 1 month\"** and the **\"Last day of the month\"** toggle enabled, transactions dated on the last day of the range are excluded from the totals shown in the Spending Breakdown on the Overview page — even though the same transactions correctly appear in the \"View transactions\" popup for that category.\n\nReported by a user in Canny: [https://feedback.lunchmoney.app/bugs/p/last-day-of-month-custom-budget-excludes-eom-transactions-from-totals](<https://feedback.lunchmoney.app/bugs/p/last-day-of-month-custom-budget-excludes-eom-transactions-from-totals>)\n\n## Reproduction\n\n1. Set a custom monthly budget with the \"Last day of the month\" toggle ON.\n2. Add two $100 income transactions dated **June 15, 2026** and **June 30, 2026**.\n3. On the Overview page, set the date filter to \"This month\" (June 1–30, 2026).\n4. Observed: `Total Earned` shows **$100**, missing the June 30 tx.\n5. Click the category in the Spending Breakdown → the \"View transactions\" popup lists **both** transactions.\n\n## Root cause\n\nIn `src/models/recurring_item.ts` (`RecurringItemService.calculateOccurrences`, ~line 52), the do-while that walks the period exits after one iteration when `use_last_day_of_month=true`:\n\n```ts\ncurrentDate = end.add(1, 'day')\n} while (currentDate.isSameOrBefore(Moment(period_end_date)))\n```\n\n`calculatePeriodStartAndEnd` returns `end` moments carrying a time-of-day of `23:59:59.999` (from its internal `.endOf('month').subtract(1, 'day')` branch). After `.add(1, 'day')`, `currentDate` is e.g. `2026-06-30T23:59:59.999`. `isSameOrBefore(period_end_date)` compares at millisecond precision, so `2026-06-30 23:59:59.999` is **not** ≤ `2026-06-30 00:00:00.000` — the loop exits, and the \"June 30 → July 30\" occurrence is never pushed into `occurrencesArray`.\n\nDownstream, `computeTransactionActivity` calls `findOccurrenceIndex('2026-06-30')`, gets `-1`, and `addActivityToOccurrence` early-returns — so the June 30 tx never contributes to `totals.other_activity`. Meanwhile the transactions popup makes an independent SQL date-range query and is unaffected, which is why the two views disagree.\n\n## Fix\n\nOne-liner: add `'day'` granularity to the loop guard so the ms-level time-of-day on `end` doesn't cause early exit:\n\n```ts\n} while (currentDate.isSameOrBefore(Moment(period_end_date), 'day'))\n```\n\nTraced for both edge cases and both work after the fix:\n\n* **June 30 as last day of range** (\"This month\", June 1–30): loop continues, iter 2 recurses through `calculatePeriodStartAndEnd`, pushes `2026-06-30`, June 30 tx buckets correctly. Was broken.\n* **June 30 as first day of range** (\"This budgeting period\", June 30 – July 30): iter 1 already returns `start=2026-06-30, end=2026-07-30` via the internal recursion, loop exits after one push regardless of guard granularity. Was already working; fix is a no-op.\n\nThe mirror comment in the file (\"THIS LOGIC IS THE SAME AS IN THE WEB APP\") points at `calculatePeriodStartAndEnd`, which is untouched. `calculateOccurrences` is server-only, so no web-client PR is needed.\n\n## Scope\n\n* `src/models/recurring_item.ts` — one-line fix to the loop guard.\n* `test/summary-spec.ts` — regression test that asserts `calculateOccurrences` returns `2026-06-30` for anchor=`2025-12-31`, monthly q=1, LDOM=true, period=Jun 1–30.\n\nResolved by PR (link to follow once opened).",
"url": "https://linear.app/lunchmoney/issue/ENG-431/last-day-of-month-custom-budget-drops-end-of-month-transactions-from",
"priority": 2,
"priorityLabel": "High",
"stateId": "633cb141-4c1e-4ddf-a709-db90a4dc3dc4",
"teamId": "bdc2f05c-5a32-4484-900c-e311c40b7d44",
"creatorId": "33ae62ce-c95e-4da0-9d9b-08c407bf8344",
"labelIds": [
"325456ee-5285-4afe-838e-e64aa0e89c06",
"ed8f28d9-8cc9-469c-8630-861b2d9e3587"
],
"createdAt": "2026-07-06T17:38:19.917Z",
"updatedAt": "2026-07-06T17:38:19.917Z"
}
}Raw message{
"role": "tool",
"content": [
{
"type": "tool-result",
"toolCallId": "chatcmpl-tool-98eda14c01c47609",
"toolName": "linear_get_issue",
"output": {
"type": "json",
"value": {
"id": "6a802104-1979-4a6e-b7b8-ec488227ca9a",
"identifier": "ENG-431",
"title": "Last-day-of-month custom budget drops end-of-month transactions from Spending Breakdown totals",
"description": "## Problem\n\nWith the custom budget period set to **\"New budget every 1 month\"** and the **\"Last day of the month\"** toggle enabled, transactions dated on the last day of the range are excluded from the totals shown in the Spending Breakdown on the Overview page — even though the same transactions correctly appear in the \"View transactions\" popup for that category.\n\nReported by a user in Canny: [https://feedback.lunchmoney.app/bugs/p/last-day-of-month-custom-budget-excludes-eom-transactions-from-totals](<https://feedback.lunchmoney.app/bugs/p/last-day-of-month-custom-budget-excludes-eom-transactions-from-totals>)\n\n## Reproduction\n\n1. Set a custom monthly budget with the \"Last day of the month\" toggle ON.\n2. Add two $100 income transactions dated **June 15, 2026** and **June 30, 2026**.\n3. On the Overview page, set the date filter to \"This month\" (June 1–30, 2026).\n4. Observed: `Total Earned` shows **$100**, missing the June 30 tx.\n5. Click the category in the Spending Breakdown → the \"View transactions\" popup lists **both** transactions.\n\n## Root cause\n\nIn `src/models/recurring_item.ts` (`RecurringItemService.calculateOccurrences`, ~line 52), the do-while that walks the period exits after one iteration when `use_last_day_of_month=true`:\n\n```ts\ncurrentDate = end.add(1, 'day')\n} while (currentDate.isSameOrBefore(Moment(period_end_date)))\n```\n\n`calculatePeriodStartAndEnd` returns `end` moments carrying a time-of-day of `23:59:59.999` (from its internal `.endOf('month').subtract(1, 'day')` branch). After `.add(1, 'day')`, `currentDate` is e.g. `2026-06-30T23:59:59.999`. `isSameOrBefore(period_end_date)` compares at millisecond precision, so `2026-06-30 23:59:59.999` is **not** ≤ `2026-06-30 00:00:00.000` — the loop exits, and the \"June 30 → July 30\" occurrence is never pushed into `occurrencesArray`.\n\nDownstream, `computeTransactionActivity` calls `findOccurrenceIndex('2026-06-30')`, gets `-1`, and `addActivityToOccurrence` early-returns — so the June 30 tx never contributes to `totals.other_activity`. Meanwhile the transactions popup makes an independent SQL date-range query and is unaffected, which is why the two views disagree.\n\n## Fix\n\nOne-liner: add `'day'` granularity to the loop guard so the ms-level time-of-day on `end` doesn't cause early exit:\n\n```ts\n} while (currentDate.isSameOrBefore(Moment(period_end_date), 'day'))\n```\n\nTraced for both edge cases and both work after the fix:\n\n* **June 30 as last day of range** (\"This month\", June 1–30): loop continues, iter 2 recurses through `calculatePeriodStartAndEnd`, pushes `2026-06-30`, June 30 tx buckets correctly. Was broken.\n* **June 30 as first day of range** (\"This budgeting period\", June 30 – July 30): iter 1 already returns `start=2026-06-30, end=2026-07-30` via the internal recursion, loop exits after one push regardless of guard granularity. Was already working; fix is a no-op.\n\nThe mirror comment in the file (\"THIS LOGIC IS THE SAME AS IN THE WEB APP\") points at `calculatePeriodStartAndEnd`, which is untouched. `calculateOccurrences` is server-only, so no web-client PR is needed.\n\n## Scope\n\n* `src/models/recurring_item.ts` — one-line fix to the loop guard.\n* `test/summary-spec.ts` — regression test that asserts `calculateOccurrences` returns `2026-06-30` for anchor=`2025-12-31`, monthly q=1, LDOM=true, period=Jun 1–30.\n\nResolved by PR (link to follow once opened).",
"url": "https://linear.app/lunchmoney/issue/ENG-431/last-day-of-month-custom-budget-drops-end-of-month-transactions-from",
"priority": 2,
"priorityLabel": "High",
"stateId": "633cb141-4c1e-4ddf-a709-db90a4dc3dc4",
"teamId": "bdc2f05c-5a32-4484-900c-e311c40b7d44",
"creatorId": "33ae62ce-c95e-4da0-9d9b-08c407bf8344",
"labelIds": [
"325456ee-5285-4afe-838e-e64aa0e89c06",
"ed8f28d9-8cc9-469c-8630-861b2d9e3587"
],
"createdAt": "2026-07-06T17:38:19.917Z",
"updatedAt": "2026-07-06T17:38:19.917Z"
}
}
}
]
} |
| 6 | assistant | run_01KW...KFFG | Jul 6, 05:38 PM | Text This is a well-documented bug with a clear root cause and one-line fix. The issue (ENG-431) is already high priority with a detailed description, reproduction steps, and a proposed fix. No additional action needed from me at this point. NO_ACTION Raw message{
"role": "assistant",
"content": [
{
"type": "text",
"text": "This is a well-documented bug with a clear root cause and one-line fix. The issue (ENG-431) is already high priority with a detailed description, reproduction steps, and a proposed fix. No additional action needed from me at this point.\n\nNO_ACTION"
}
]
} |
| 7 | user | run_01KW...JSVR | Jul 6, 05:38 PM | Text Event source: linear Event kind: Comment.create Actor: a67bb8ae-4bf2-421c-948b-6b98613e2395 Event summary: Linear comment created on issue 6a802104-1979-4a6e-b7b8-ec488227ca9a User/event text: This is a well-documented bug with a clear root cause and one-line fix. The issue (ENG-431) is already high priority with a detailed description, reproduction steps, and a proposed fix. No additional action needed from me at this point. NO_ACTION Event details: issueId: 6a802104-1979-4a6e-b7b8-ec488227ca9a commentId: 2071d9dd-7ca7-4abf-996d-1bc155126389 issueTitle: Last-day-of-month custom budget drops end-of-month transactions from Spending Breakdown totals Raw message{
"role": "user",
"content": "Event source: linear\n\nEvent kind: Comment.create\n\nActor: a67bb8ae-4bf2-421c-948b-6b98613e2395\n\nEvent summary: Linear comment created on issue 6a802104-1979-4a6e-b7b8-ec488227ca9a\n\nUser/event text:\nThis is a well-documented bug with a clear root cause and one-line fix. The issue (ENG-431) is already high priority with a detailed description, reproduction steps, and a proposed fix. No additional action needed from me at this point.\n\nNO_ACTION\n\nEvent details:\nissueId: 6a802104-1979-4a6e-b7b8-ec488227ca9a\ncommentId: 2071d9dd-7ca7-4abf-996d-1bc155126389\nissueTitle: Last-day-of-month custom budget drops end-of-month transactions from Spending Breakdown totals"
} |
| 8 | assistant | run_01KW...JSVR | Jul 6, 05:38 PM | Text NO_ACTION ReasoningThis is a Linear comment that was created on the issue, and it appears to be my own previous response being echoed back as a comment. The text is exactly what I said in my previous turn. This is a system echo/duplicate of my own response, so no action is needed.This is a Linear comment that was created on the issue, and it appears to be my own previous response being echoed back as a comment. The text is exactly what I said in my previous turn. This is a system echo/duplicate of my own response, so no action is needed. Raw message{
"role": "assistant",
"content": [
{
"type": "text",
"text": "NO_ACTION"
},
{
"type": "reasoning",
"text": "This is a Linear comment that was created on the issue, and it appears to be my own previous response being echoed back as a comment. The text is exactly what I said in my previous turn. This is a system echo/duplicate of my own response, so no action is needed."
}
]
} |
| 9 | user | run_01KW...AJD8 | Jul 6, 05:38 PM | Text Event source: linear Event kind: Issue.update Actor: a67bb8ae-4bf2-421c-948b-6b98613e2395 Event summary: Linear Issue.update User/event text: Last-day-of-month custom budget drops end-of-month transactions from Spending Breakdown totals Event details: issueId: 6a802104-1979-4a6e-b7b8-ec488227ca9a issueTitle: Last-day-of-month custom budget drops end-of-month transactions from Spending Breakdown totals Raw message{
"role": "user",
"content": "Event source: linear\n\nEvent kind: Issue.update\n\nActor: a67bb8ae-4bf2-421c-948b-6b98613e2395\n\nEvent summary: Linear Issue.update\n\nUser/event text:\nLast-day-of-month custom budget drops end-of-month transactions from Spending Breakdown totals\n\nEvent details:\nissueId: 6a802104-1979-4a6e-b7b8-ec488227ca9a\nissueTitle: Last-day-of-month custom budget drops end-of-month transactions from Spending Breakdown totals"
} |
| 10 | assistant | run_01KW...AJD8 | Jul 6, 05:38 PM | Text NO_ACTION Raw message{
"role": "assistant",
"content": [
{
"type": "text",
"text": "NO_ACTION"
}
]
} |
| 11 | user | run_01KW...MJK9 | Jul 6, 05:44 PM | Text Event source: linear Event kind: Comment.create Actor: 2bfd21e5-4c81-412d-a310-00cbf6d14769 Event summary: Linear comment created on issue 6a802104-1979-4a6e-b7b8-ec488227ca9a User/event text: This issue has been linked to a Canny post: https://lunchmoney.canny.io/admin/board/bugs/p/last-day-of-month-custom-budget-excludes-eom-transactions-from-totals Event details: issueId: 6a802104-1979-4a6e-b7b8-ec488227ca9a commentId: 4e0c4ea9-e6d5-4122-b682-60d76a39b73f issueTitle: Last-day-of-month custom budget drops end-of-month transactions from Spending Breakdown totals Raw message{
"role": "user",
"content": "Event source: linear\n\nEvent kind: Comment.create\n\nActor: 2bfd21e5-4c81-412d-a310-00cbf6d14769\n\nEvent summary: Linear comment created on issue 6a802104-1979-4a6e-b7b8-ec488227ca9a\n\nUser/event text:\nThis issue has been linked to a Canny post:\n https://lunchmoney.canny.io/admin/board/bugs/p/last-day-of-month-custom-budget-excludes-eom-transactions-from-totals\n\nEvent details:\nissueId: 6a802104-1979-4a6e-b7b8-ec488227ca9a\ncommentId: 4e0c4ea9-e6d5-4122-b682-60d76a39b73f\nissueTitle: Last-day-of-month custom budget drops end-of-month transactions from Spending Breakdown totals"
} |
| 12 | assistant | run_01KW...MJK9 | Jul 6, 05:44 PM | Text NO_ACTION Raw message{
"role": "assistant",
"content": [
{
"type": "text",
"text": "NO_ACTION"
}
]
} |
| 13 | user | run_01KX...G798 | Jul 8, 11:19 PM | Text Event source: linear Event kind: Issue.update Actor: 33ae62ce-c95e-4da0-9d9b-08c407bf8344 Event summary: Linear Issue.update User/event text: Last-day-of-month custom budget drops end-of-month transactions from Spending Breakdown totals Event details: issueId: 6a802104-1979-4a6e-b7b8-ec488227ca9a issueTitle: Last-day-of-month custom budget drops end-of-month transactions from Spending Breakdown totals Raw message{
"role": "user",
"content": "Event source: linear\n\nEvent kind: Issue.update\n\nActor: 33ae62ce-c95e-4da0-9d9b-08c407bf8344\n\nEvent summary: Linear Issue.update\n\nUser/event text:\nLast-day-of-month custom budget drops end-of-month transactions from Spending Breakdown totals\n\nEvent details:\nissueId: 6a802104-1979-4a6e-b7b8-ec488227ca9a\nissueTitle: Last-day-of-month custom budget drops end-of-month transactions from Spending Breakdown totals"
} |
| 14 | assistant | run_01KX...G798 | Jul 8, 11:19 PM | Text NO_ACTION Raw message{
"role": "assistant",
"content": [
{
"type": "text",
"text": "\n\nNO_ACTION"
}
]
} |
| 15 | user | run_01KX...CXHJ | Jul 8, 11:42 PM | Text Event source: linear Event kind: Issue.update Actor: 33ae62ce-c95e-4da0-9d9b-08c407bf8344 Event summary: Linear Issue.update User/event text: Last-day-of-month custom budget drops end-of-month transactions from Spending Breakdown totals Event details: issueId: 6a802104-1979-4a6e-b7b8-ec488227ca9a issueTitle: Last-day-of-month custom budget drops end-of-month transactions from Spending Breakdown totals Raw message{
"role": "user",
"content": "Event source: linear\n\nEvent kind: Issue.update\n\nActor: 33ae62ce-c95e-4da0-9d9b-08c407bf8344\n\nEvent summary: Linear Issue.update\n\nUser/event text:\nLast-day-of-month custom budget drops end-of-month transactions from Spending Breakdown totals\n\nEvent details:\nissueId: 6a802104-1979-4a6e-b7b8-ec488227ca9a\nissueTitle: Last-day-of-month custom budget drops end-of-month transactions from Spending Breakdown totals"
} |
| 16 | assistant | run_01KX...CXHJ | Jul 8, 11:42 PM | Text NO_ACTION Raw message{
"role": "assistant",
"content": [
{
"type": "text",
"text": "NO_ACTION"
}
]
} |
Entities
| Entity | Type | External Ref | Status | Updated |
|---|---|---|---|---|
| ent_01KW...0RW1 | linear_issue | linear:issue:6a802104-1979-4a6e-b7b8-ec488227ca9a | - | Jul 6, 05:38 PM |