Vibecode Amazing Marvin
track this build5 phases, 15 steps, beginner friendly0%The core loop is small enough for a capable coding agent to produce a useful local version in one sitting. For Amazing Marvin, build a configurable personal task system from strategies, views, timers, and reviews. The hard boundary is very deep strategy library, cross-platform sync, and years of workflow experimentation, plus cross-device reliability and workflow polish.
You are building a lean indie version of Amazing Marvin. Create the following project files first, then implement the application by following them. Keep the files updated as decisions change. Do not collapse this into a single README or prompt. ===== README.md ===== # Amazing Marvin · indie build A task system whose central mechanic is the day plan with a time budget: tasks carry estimates, the day refuses to silently accept more than fits, and the record of what you planned against what happened is what makes your estimates get better. Estimated effort: **multi-day**. Work `BUILD_PLAN.md` top to bottom · every phase ends in a check that has to pass before the next one starts. ## Stack | Part | Choice | Why | | --- | --- | --- | | Runtime | TypeScript with a local application and SQLite | a task list is personal and should work on a train | | Model | Tasks with estimates, a day plan, and a completion record | the plan against actual comparison is the entire point | | Time | Every timestamp stored in UTC with the local zone recorded | day boundaries are where task managers break | | Review | Scheduled prompts driven by data, not by a calendar | a review that shows your actual overcommitment is worth attending | | Export | JSON and Markdown, complete | a task history is a record of your working life | ## Before you start Have every one of these ready. The plan assumes them from step one. - [ ] **Node.js 22 or newer** · free - Why: Runs the local application. - Get it: nodejs.org, or nvm install 22. - Verify: node --version prints v22 or higher - [ ] **Your honest daily budget** · free, and mildly deflating - Why: The budget is the constraint everything else checks against, and setting it to eight hours guarantees the system tells you nothing useful. - Get it: Look at a real week and count the hours you actually spent on planned work rather than meetings, interruptions and admin. - Verify: A number is written down with the reasoning behind it - [ ] **Two weeks of real tasks and time** · free, but it takes two weeks - Why: Estimate accuracy, rollover distribution and budget suggestion need real data, and synthetic data will confirm whatever you assumed. - Get it: Use the tool for two weeks before trusting the review, or import from an existing system with times. - Verify: Two weeks of plans with actual times exist - [ ] **How your day boundaries work** · free - Why: Day plans, rollover and recurrence all depend on when a day starts, and someone working past midnight breaks the naive answer. - Get it: Decide the hour a new day begins for you and whether travel changes it. Write it down before phase 2. - Verify: A written note states the day start hour and travel behaviour ## Quick start Follow Phase 1 in `BUILD_PLAN.md`; it creates the project. Then copy `.env.example` to `.env` and fill in the values it documents. ## Honest limits This build deliberately does not replace: - The extensive configurability of the hosted product. - Mobile applications. - Calendar integration against the day budget. - Collaboration and delegation. - very deep strategy library, cross-platform sync, and years of workflow experimentation - perfect mobile sync - calendar and email integrations - shared workspaces - behavioral coaching polish If one of those is essential to you, that is the reason to keep paying for Amazing Marvin, and the README should say so rather than pretend. ===== BRIEF.md ===== # Build brief · Amazing Marvin The one-shot brief this plan expands. `BUILD_PLAN.md` (or `MILESTONES.md`) is the same sequence broken into steps and checks; where the two disagree, the plan wins. Build me a task manager built around the fact that you will over-commit your day to replace Amazing Marvin. Build it in phases, in the order below. Do not write the whole thing in one pass. Finish a phase, run its "Done when" check, fix what fails, and only then start the next phase. ### Stack (fixed, do not substitute) - Runtime: TypeScript with a local application and SQLite · a task list is personal and should work on a train - Model: Tasks with estimates, a day plan, and a completion record · the plan against actual comparison is the entire point - Time: Every timestamp stored in UTC with the local zone recorded · day boundaries are where task managers break - Review: Scheduled prompts driven by data, not by a calendar · a review that shows your actual overcommitment is worth attending - Export: JSON and Markdown, complete · a task history is a record of your working life ### Data model (create this before Phase 1) - tasks(id, title, project_id, estimate_minutes, due_at, created_at, completed_at, dropped_at) - day_plans(date, budget_minutes, planned_at, local_zone) · the budget is the constraint the day is checked against - plan_items(day_plan_date, task_id, ordinal, estimate_at_plan_minutes) · the estimate is captured at planning time - sessions(id, task_id, started_at, ended_at, source) · source is timer or entered_later - outcomes(day_plan_date, planned_minutes, actual_minutes, completed_count, rolled_over_count) - The estimate is snapshotted into the plan item, because comparing today's outcome against a later revised estimate tells you nothing. ### Phase 1 · Tasks with honest estimates Build: Tasks with title, project, estimate and due date. Creation must require an estimate, with a coarse scale rather than a free number. A running total of estimates for any set. Trap: A free-text minutes field produces false precision and slows down capture until people stop estimating, which removes the mechanic the whole system is built on. Use a coarse scale of a few buckets, which is fast to choose and accurate enough for a day budget. Done when: Creating a task requires an estimate from a coarse scale. A set of tasks shows a running estimate total. Capture with an estimate takes only a few seconds, timed by hand. Tasks without estimates cannot exist, verified by attempting to create one. Do not build yet: No day plan or timing yet. ### Phase 2 · A day that refuses to hold more than it can Build: A day plan with a time budget. Adding tasks accumulates against it. Exceeding the budget requires an explicit acknowledgement and is recorded as an overcommitment. Snapshot each estimate into the plan item. Trap: Blocking overcommitment outright means people plan outside the tool the first time a real day demands it, and blocking is also wrong because some days genuinely are like that. Allow it, require an acknowledgement, and record it, so the review can show the pattern. Done when: A day plan accumulates estimates against a budget and shows remaining time. Exceeding requires an explicit acknowledgement rather than being blocked or silent. The overcommitment is recorded on the plan. Estimates are snapshotted at planning time, verified by changing a task's estimate afterwards. Do not build yet: No timing or review yet. ### Phase 3 · What actually happened Build: A timer per task, and an equally easy path to enter time afterwards. Compute the day's outcome: planned against actual, completed, rolled over. Handle a timer left running overnight rather than recording sixteen hours. Trap: A system that only records time from a timer produces mostly empty data, because nobody starts a timer every time, and then the plan against actual comparison is built on nothing. Make entering time afterwards as easy as starting the timer and mark which is which. Done when: Time can be timed or entered afterwards with equal ease, and the source is recorded. A timer running past a threshold prompts rather than recording sixteen hours. The day's outcome shows planned against actual. A day with no timing at all still produces a completion outcome. Do not build yet: No review or rollover yet. ### Phase 4 · Rollover that does not hide the problem Build: Roll unfinished tasks into the next day, counting how many days each has rolled. Surface tasks rolled repeatedly. Rolled tasks consume budget in the new day like anything else. Trap: Silent rollover produces a task that has moved forward forty times and looks identical to one created this morning, which is the exact information you need and the exact information the interface hides. Count the rolls and show the count. Done when: Unfinished tasks roll to the next day with an incremented count. A task rolled more than a threshold is surfaced distinctly. Rolled tasks consume budget in the new day. A task rolled repeatedly can be dropped, and dropping is recorded rather than deleting it. Do not build yet: No review or projects yet. ### Phase 5 · A review that shows you your own numbers Build: A weekly review computing estimate accuracy by project and task size, overcommitment frequency, and rollover distribution. Offer a suggested budget derived from actual completed time rather than from what you hoped. Trap: A review showing only completions is flattering and useless. The numbers that change behaviour are the ratio of actual to estimated time, how often you exceeded budget, and how long things sit before being done or dropped. Compute those even though they are uncomfortable. Done when: The review reports estimate accuracy as a ratio, by project and size bucket. Overcommitment frequency is shown for the period. The suggested budget derives from actual completed time. The review runs on a partial week without dividing by zero, tested with one day of data. Do not build yet: Export and projects come last. ### Phase 6 · Projects, recurrence and getting out Build: Projects with tasks, recurring tasks that generate correctly across zones and daylight changes, and a complete export of tasks, plans, sessions and outcomes. Trap: Recurring tasks generated in local time drift or duplicate across a daylight saving change, producing either two of a task or none on that day. Store the rule with a zone, generate in UTC, and test explicitly across both transitions. Done when: Recurrence generates correctly across both daylight saving transitions, tested with dates on either side. Projects group tasks and show their total estimate. Export contains tasks, plans, sessions and outcomes and re-imports identically. A completed recurring task does not regenerate for the same period. Do not build yet: Nothing after this. ### Out of scope (and why) - The enormous configurability the hosted product is known for, where nearly every behaviour is a toggle, which is a design philosophy rather than a feature you can bolt on. - Mobile applications, which is where most task capture actually happens. - Calendar integration showing meetings against the day budget, which would genuinely improve the budget's accuracy. - Collaboration and delegation, which is a different product. ### README must contain - That estimates use a coarse scale and are required, because that is what the budget needs - That overcommitment is allowed, acknowledged and recorded rather than blocked - That time can be entered afterwards as easily as timed, and the source is recorded - That rollover counts are kept and surfaced - That the review reports estimate accuracy and overcommitment, not just completions ===== AGENTS.md ===== # Agent instructions · Amazing Marvin indie build - Read `README.md` and `BUILD_PLAN.md` before writing code. The stack is fixed: TypeScript with a local application and SQLite, Tasks with estimates, a day plan, and a completion record, Every timestamp stored in UTC with the local zone recorded, Scheduled prompts driven by data, not by a calendar, JSON and Markdown, complete. Do not substitute. - Work one phase at a time, in order. Do not start a phase until every "Done when" item of the previous one passes. - Prefer the fewest moving parts that satisfy the step. No frameworks, services or dependencies the plan does not name. - Secrets live in `.env`, never in source or logs. Keep `.env.example` current when a variable is introduced. - Do not invent cryptography, security guarantees, APIs or compliance claims. - Add a focused test for every destructive, security-sensitive or data-loss path the plan names. - Run the project checks before declaring a phase complete, and record any deliberate shortcut in the README under "Tradeoffs". ## Known traps - A free-text minutes field produces false precision and slows down capture until people stop estimating, which removes the mechanic the whole system is built on. Use a coarse scale of a few buckets, which is fast to choose and accurate enough for a day budget. - Blocking overcommitment outright means people plan outside the tool the first time a real day demands it, and blocking is also wrong because some days genuinely are like that. Allow it, require an acknowledgement, and record it, so the review can show the pattern. - A system that only records time from a timer produces mostly empty data, because nobody starts a timer every time, and then the plan against actual comparison is built on nothing. Make entering time afterwards as easy as starting the timer and mark which is which. - Silent rollover produces a task that has moved forward forty times and looks identical to one created this morning, which is the exact information you need and the exact information the interface hides. Count the rolls and show the count. - A review showing only completions is flattering and useless. The numbers that change behaviour are the ratio of actual to estimated time, how often you exceeded budget, and how long things sit before being done or dropped. Compute those even though they are uncomfortable. ===== BUILD_PLAN.md ===== # Build plan · Amazing Marvin A task system whose central mechanic is the day plan with a time budget: tasks carry estimates, the day refuses to silently accept more than fits, and the record of what you planned against what happened is what makes your estimates get better. Phases are in dependency order. Each ends in a "Done when" list; treat an unticked item as a blocker, not a note. ## Phase 1 · Tasks with honest estimates Every task carries a time estimate and you can see them accumulate. ### Steps 1. Use a coarse estimate scale A handful of buckets. False precision is what kills estimating. Files: `src/estimate.ts` 2. Require it at creation An optional estimate is an absent estimate within a week. Files: `src/tasks.ts` 3. Sum estimates for any set The total is what the day plan will check against. Files: `src/totals.ts` ### Done when - [ ] Task creation requires an estimate from a scale - [ ] A set shows its estimate total - [ ] Capture with an estimate is fast - [ ] An estimateless task cannot be created ### Watch out - A free-text minutes field produces false precision and slows down capture until people stop estimating, which removes the mechanic the whole system is built on. Use a coarse scale of a few buckets, which is fast to choose and accurate enough for a day budget. ## Phase 2 · A day that refuses to hold more than it can Planning past your budget is possible but never silent. ### Steps 1. Budget per day, not a fixed number Days differ. A budget you set is a budget you believe. Files: `src/plan.ts` 2. Acknowledge, do not block Blocking pushes planning out of the tool. Recording produces the review. Files: `src/plan.ts` 3. Snapshot the estimate into the plan Comparing against a revised estimate later measures nothing. Files: `src/plan.ts` ### Done when - [ ] A day plan shows remaining budget - [ ] Exceeding requires acknowledgement - [ ] Overcommitment is recorded - [ ] Estimates are snapshotted at plan time ### Watch out - Blocking overcommitment outright means people plan outside the tool the first time a real day demands it, and blocking is also wrong because some days genuinely are like that. Allow it, require an acknowledgement, and record it, so the review can show the pattern. ## Phase 3 · What actually happened You can compare the plan against the day without perfect timer discipline. ### Steps 1. Two equally easy paths Timer and after the fact. Recording the source keeps the data honest. Files: `src/time.ts` 2. Handle the abandoned timer Prompt past a threshold. Sixteen-hour sessions poison the comparison. Files: `src/time.ts` 3. Compute the day outcome Planned, actual, completed, rolled over. Four numbers that mean something. Files: `src/outcome.ts` ### Done when - [ ] Timed and entered time are equally easy and distinguished - [ ] A long-running timer prompts rather than recording - [ ] The day outcome shows planned against actual - [ ] A day without timing still produces an outcome ### Watch out - A system that only records time from a timer produces mostly empty data, because nobody starts a timer every time, and then the plan against actual comparison is built on nothing. Make entering time afterwards as easy as starting the timer and mark which is which. ## Phase 4 · Rollover that does not hide the problem Unfinished tasks carry forward visibly, with their history. ### Steps 1. Count the rolls The number is the signal. Rolling silently discards it. Files: `src/rollover.ts` 2. Surface repeat offenders Past a threshold, distinctly. It is usually a task that needs breaking up or dropping. Files: `src/rollover.ts` 3. Record drops rather than deleting What you chose not to do is data about your planning. Files: `src/tasks.ts` ### Done when - [ ] Rollover increments a count per task - [ ] Repeatedly rolled tasks are surfaced - [ ] Rolled tasks consume the new day's budget - [ ] Dropping is recorded rather than deleting ### Watch out - Silent rollover produces a task that has moved forward forty times and looks identical to one created this morning, which is the exact information you need and the exact information the interface hides. Count the rolls and show the count. ## Phase 5 · A review that shows you your own numbers You find out how wrong your estimates are, by how much, and in which direction. ### Steps 1. Compute accuracy by bucket By project and size. The pattern is usually specific rather than global. Files: `src/review.ts` 2. Report overcommitment frequency The uncomfortable number. It is the one that changes planning. Files: `src/review.ts` 3. Suggest a budget from actuals What you actually complete, not what you hoped to. Files: `src/budget.ts`, `src/budget.test.ts` ### Done when - [ ] Estimate accuracy is reported by project and size - [ ] Overcommitment frequency is shown - [ ] The suggested budget derives from actuals - [ ] A partial week does not divide by zero ### Watch out - A review showing only completions is flattering and useless. The numbers that change behaviour are the ratio of actual to estimated time, how often you exceeded budget, and how long things sit before being done or dropped. Compute those even though they are uncomfortable. ## Not in this build - The extensive configurability of the hosted product. - Mobile applications. - Calendar integration against the day budget. - Collaboration and delegation. ## After v1, if you want it - Estimate suggestions from your own history for similar tasks, once accuracy data exists - Energy or context tagging, so a low-energy hour gets the right task - A monthly view of where time actually went by project, which the sessions already support ===== .env.example ===== # Copy to .env and fill in. Never commit .env; this file documents it. # Required. Tasks, plans and time. Your working history. DB_PATH=~/.local/share/marvin/tasks.db # Required. When a new day begins, so work past midnight lands on the right day. DAY_START_HOUR=4 # Required. The honest number, not the hopeful one. Four hours of planned work is a real day. DEFAULT_BUDGET_MINUTES=240 # Required. When a running timer prompts, so an abandoned one does not record sixteen hours. TIMER_PROMPT_MINUTES=180 # Required. How many rolls before a task is surfaced. It usually needs breaking up or dropping. ROLLOVER_ALERT_COUNT=5
You are building a lean indie version of Amazing Marvin. Create the following project files first, then implement the application by following them. Keep the files updated as decisions change. Do not collapse this into a single README or prompt. ===== README.md ===== # Amazing Marvin · indie build A task system whose central mechanic is the day plan with a time budget: tasks carry estimates, the day refuses to silently accept more than fits, and the record of what you planned against what happened is what makes your estimates get better. Estimated effort: **multi-day**. Work `BUILD_PLAN.md` top to bottom · every phase ends in a check that has to pass before the next one starts. ## Stack | Part | Choice | Why | | --- | --- | --- | | Runtime | TypeScript with a local application and SQLite | a task list is personal and should work on a train | | Model | Tasks with estimates, a day plan, and a completion record | the plan against actual comparison is the entire point | | Time | Every timestamp stored in UTC with the local zone recorded | day boundaries are where task managers break | | Review | Scheduled prompts driven by data, not by a calendar | a review that shows your actual overcommitment is worth attending | | Export | JSON and Markdown, complete | a task history is a record of your working life | ## Before you start Have every one of these ready. The plan assumes them from step one. - [ ] **Node.js 22 or newer** · free - Why: Runs the local application. - Get it: nodejs.org, or nvm install 22. - Verify: node --version prints v22 or higher - [ ] **Your honest daily budget** · free, and mildly deflating - Why: The budget is the constraint everything else checks against, and setting it to eight hours guarantees the system tells you nothing useful. - Get it: Look at a real week and count the hours you actually spent on planned work rather than meetings, interruptions and admin. - Verify: A number is written down with the reasoning behind it - [ ] **Two weeks of real tasks and time** · free, but it takes two weeks - Why: Estimate accuracy, rollover distribution and budget suggestion need real data, and synthetic data will confirm whatever you assumed. - Get it: Use the tool for two weeks before trusting the review, or import from an existing system with times. - Verify: Two weeks of plans with actual times exist - [ ] **How your day boundaries work** · free - Why: Day plans, rollover and recurrence all depend on when a day starts, and someone working past midnight breaks the naive answer. - Get it: Decide the hour a new day begins for you and whether travel changes it. Write it down before phase 2. - Verify: A written note states the day start hour and travel behaviour ## Quick start Follow Phase 1 in `BUILD_PLAN.md`; it creates the project. Then copy `.env.example` to `.env` and fill in the values it documents. ## Honest limits This build deliberately does not replace: - The extensive configurability of the hosted product. - Mobile applications. - Calendar integration against the day budget. - Collaboration and delegation. - very deep strategy library, cross-platform sync, and years of workflow experimentation - perfect mobile sync - calendar and email integrations - shared workspaces - behavioral coaching polish If one of those is essential to you, that is the reason to keep paying for Amazing Marvin, and the README should say so rather than pretend. ===== BRIEF.md ===== # Build brief · Amazing Marvin The one-shot brief this plan expands. `BUILD_PLAN.md` (or `MILESTONES.md`) is the same sequence broken into steps and checks; where the two disagree, the plan wins. Build me a task manager built around the fact that you will over-commit your day to replace Amazing Marvin. Build it in phases, in the order below. Do not write the whole thing in one pass. Finish a phase, run its "Done when" check, fix what fails, and only then start the next phase. ### Stack (fixed, do not substitute) - Runtime: TypeScript with a local application and SQLite · a task list is personal and should work on a train - Model: Tasks with estimates, a day plan, and a completion record · the plan against actual comparison is the entire point - Time: Every timestamp stored in UTC with the local zone recorded · day boundaries are where task managers break - Review: Scheduled prompts driven by data, not by a calendar · a review that shows your actual overcommitment is worth attending - Export: JSON and Markdown, complete · a task history is a record of your working life ### Data model (create this before Phase 1) - tasks(id, title, project_id, estimate_minutes, due_at, created_at, completed_at, dropped_at) - day_plans(date, budget_minutes, planned_at, local_zone) · the budget is the constraint the day is checked against - plan_items(day_plan_date, task_id, ordinal, estimate_at_plan_minutes) · the estimate is captured at planning time - sessions(id, task_id, started_at, ended_at, source) · source is timer or entered_later - outcomes(day_plan_date, planned_minutes, actual_minutes, completed_count, rolled_over_count) - The estimate is snapshotted into the plan item, because comparing today's outcome against a later revised estimate tells you nothing. ### Phase 1 · Tasks with honest estimates Build: Tasks with title, project, estimate and due date. Creation must require an estimate, with a coarse scale rather than a free number. A running total of estimates for any set. Trap: A free-text minutes field produces false precision and slows down capture until people stop estimating, which removes the mechanic the whole system is built on. Use a coarse scale of a few buckets, which is fast to choose and accurate enough for a day budget. Done when: Creating a task requires an estimate from a coarse scale. A set of tasks shows a running estimate total. Capture with an estimate takes only a few seconds, timed by hand. Tasks without estimates cannot exist, verified by attempting to create one. Do not build yet: No day plan or timing yet. ### Phase 2 · A day that refuses to hold more than it can Build: A day plan with a time budget. Adding tasks accumulates against it. Exceeding the budget requires an explicit acknowledgement and is recorded as an overcommitment. Snapshot each estimate into the plan item. Trap: Blocking overcommitment outright means people plan outside the tool the first time a real day demands it, and blocking is also wrong because some days genuinely are like that. Allow it, require an acknowledgement, and record it, so the review can show the pattern. Done when: A day plan accumulates estimates against a budget and shows remaining time. Exceeding requires an explicit acknowledgement rather than being blocked or silent. The overcommitment is recorded on the plan. Estimates are snapshotted at planning time, verified by changing a task's estimate afterwards. Do not build yet: No timing or review yet. ### Phase 3 · What actually happened Build: A timer per task, and an equally easy path to enter time afterwards. Compute the day's outcome: planned against actual, completed, rolled over. Handle a timer left running overnight rather than recording sixteen hours. Trap: A system that only records time from a timer produces mostly empty data, because nobody starts a timer every time, and then the plan against actual comparison is built on nothing. Make entering time afterwards as easy as starting the timer and mark which is which. Done when: Time can be timed or entered afterwards with equal ease, and the source is recorded. A timer running past a threshold prompts rather than recording sixteen hours. The day's outcome shows planned against actual. A day with no timing at all still produces a completion outcome. Do not build yet: No review or rollover yet. ### Phase 4 · Rollover that does not hide the problem Build: Roll unfinished tasks into the next day, counting how many days each has rolled. Surface tasks rolled repeatedly. Rolled tasks consume budget in the new day like anything else. Trap: Silent rollover produces a task that has moved forward forty times and looks identical to one created this morning, which is the exact information you need and the exact information the interface hides. Count the rolls and show the count. Done when: Unfinished tasks roll to the next day with an incremented count. A task rolled more than a threshold is surfaced distinctly. Rolled tasks consume budget in the new day. A task rolled repeatedly can be dropped, and dropping is recorded rather than deleting it. Do not build yet: No review or projects yet. ### Phase 5 · A review that shows you your own numbers Build: A weekly review computing estimate accuracy by project and task size, overcommitment frequency, and rollover distribution. Offer a suggested budget derived from actual completed time rather than from what you hoped. Trap: A review showing only completions is flattering and useless. The numbers that change behaviour are the ratio of actual to estimated time, how often you exceeded budget, and how long things sit before being done or dropped. Compute those even though they are uncomfortable. Done when: The review reports estimate accuracy as a ratio, by project and size bucket. Overcommitment frequency is shown for the period. The suggested budget derives from actual completed time. The review runs on a partial week without dividing by zero, tested with one day of data. Do not build yet: Export and projects come last. ### Phase 6 · Projects, recurrence and getting out Build: Projects with tasks, recurring tasks that generate correctly across zones and daylight changes, and a complete export of tasks, plans, sessions and outcomes. Trap: Recurring tasks generated in local time drift or duplicate across a daylight saving change, producing either two of a task or none on that day. Store the rule with a zone, generate in UTC, and test explicitly across both transitions. Done when: Recurrence generates correctly across both daylight saving transitions, tested with dates on either side. Projects group tasks and show their total estimate. Export contains tasks, plans, sessions and outcomes and re-imports identically. A completed recurring task does not regenerate for the same period. Do not build yet: Nothing after this. ### Out of scope (and why) - The enormous configurability the hosted product is known for, where nearly every behaviour is a toggle, which is a design philosophy rather than a feature you can bolt on. - Mobile applications, which is where most task capture actually happens. - Calendar integration showing meetings against the day budget, which would genuinely improve the budget's accuracy. - Collaboration and delegation, which is a different product. ### README must contain - That estimates use a coarse scale and are required, because that is what the budget needs - That overcommitment is allowed, acknowledged and recorded rather than blocked - That time can be entered afterwards as easily as timed, and the source is recorded - That rollover counts are kept and surfaced - That the review reports estimate accuracy and overcommitment, not just completions ===== AGENTS.md ===== # Agent instructions · Amazing Marvin indie build - Read `README.md` and `BUILD_PLAN.md` before writing code. The stack is fixed: TypeScript with a local application and SQLite, Tasks with estimates, a day plan, and a completion record, Every timestamp stored in UTC with the local zone recorded, Scheduled prompts driven by data, not by a calendar, JSON and Markdown, complete. Do not substitute. - Work one phase at a time, in order. Do not start a phase until every "Done when" item of the previous one passes. - Prefer the fewest moving parts that satisfy the step. No frameworks, services or dependencies the plan does not name. - Secrets live in `.env`, never in source or logs. Keep `.env.example` current when a variable is introduced. - Do not invent cryptography, security guarantees, APIs or compliance claims. - Add a focused test for every destructive, security-sensitive or data-loss path the plan names. - Run the project checks before declaring a phase complete, and record any deliberate shortcut in the README under "Tradeoffs". ## Known traps - A free-text minutes field produces false precision and slows down capture until people stop estimating, which removes the mechanic the whole system is built on. Use a coarse scale of a few buckets, which is fast to choose and accurate enough for a day budget. - Blocking overcommitment outright means people plan outside the tool the first time a real day demands it, and blocking is also wrong because some days genuinely are like that. Allow it, require an acknowledgement, and record it, so the review can show the pattern. - A system that only records time from a timer produces mostly empty data, because nobody starts a timer every time, and then the plan against actual comparison is built on nothing. Make entering time afterwards as easy as starting the timer and mark which is which. - Silent rollover produces a task that has moved forward forty times and looks identical to one created this morning, which is the exact information you need and the exact information the interface hides. Count the rolls and show the count. - A review showing only completions is flattering and useless. The numbers that change behaviour are the ratio of actual to estimated time, how often you exceeded budget, and how long things sit before being done or dropped. Compute those even though they are uncomfortable. ===== BUILD_PLAN.md ===== # Build plan · Amazing Marvin A task system whose central mechanic is the day plan with a time budget: tasks carry estimates, the day refuses to silently accept more than fits, and the record of what you planned against what happened is what makes your estimates get better. Phases are in dependency order. Each ends in a "Done when" list; treat an unticked item as a blocker, not a note. ## Phase 1 · Tasks with honest estimates Every task carries a time estimate and you can see them accumulate. ### Steps 1. Use a coarse estimate scale A handful of buckets. False precision is what kills estimating. Files: `src/estimate.ts` 2. Require it at creation An optional estimate is an absent estimate within a week. Files: `src/tasks.ts` 3. Sum estimates for any set The total is what the day plan will check against. Files: `src/totals.ts` ### Done when - [ ] Task creation requires an estimate from a scale - [ ] A set shows its estimate total - [ ] Capture with an estimate is fast - [ ] An estimateless task cannot be created ### Watch out - A free-text minutes field produces false precision and slows down capture until people stop estimating, which removes the mechanic the whole system is built on. Use a coarse scale of a few buckets, which is fast to choose and accurate enough for a day budget. ## Phase 2 · A day that refuses to hold more than it can Planning past your budget is possible but never silent. ### Steps 1. Budget per day, not a fixed number Days differ. A budget you set is a budget you believe. Files: `src/plan.ts` 2. Acknowledge, do not block Blocking pushes planning out of the tool. Recording produces the review. Files: `src/plan.ts` 3. Snapshot the estimate into the plan Comparing against a revised estimate later measures nothing. Files: `src/plan.ts` ### Done when - [ ] A day plan shows remaining budget - [ ] Exceeding requires acknowledgement - [ ] Overcommitment is recorded - [ ] Estimates are snapshotted at plan time ### Watch out - Blocking overcommitment outright means people plan outside the tool the first time a real day demands it, and blocking is also wrong because some days genuinely are like that. Allow it, require an acknowledgement, and record it, so the review can show the pattern. ## Phase 3 · What actually happened You can compare the plan against the day without perfect timer discipline. ### Steps 1. Two equally easy paths Timer and after the fact. Recording the source keeps the data honest. Files: `src/time.ts` 2. Handle the abandoned timer Prompt past a threshold. Sixteen-hour sessions poison the comparison. Files: `src/time.ts` 3. Compute the day outcome Planned, actual, completed, rolled over. Four numbers that mean something. Files: `src/outcome.ts` ### Done when - [ ] Timed and entered time are equally easy and distinguished - [ ] A long-running timer prompts rather than recording - [ ] The day outcome shows planned against actual - [ ] A day without timing still produces an outcome ### Watch out - A system that only records time from a timer produces mostly empty data, because nobody starts a timer every time, and then the plan against actual comparison is built on nothing. Make entering time afterwards as easy as starting the timer and mark which is which. ## Phase 4 · Rollover that does not hide the problem Unfinished tasks carry forward visibly, with their history. ### Steps 1. Count the rolls The number is the signal. Rolling silently discards it. Files: `src/rollover.ts` 2. Surface repeat offenders Past a threshold, distinctly. It is usually a task that needs breaking up or dropping. Files: `src/rollover.ts` 3. Record drops rather than deleting What you chose not to do is data about your planning. Files: `src/tasks.ts` ### Done when - [ ] Rollover increments a count per task - [ ] Repeatedly rolled tasks are surfaced - [ ] Rolled tasks consume the new day's budget - [ ] Dropping is recorded rather than deleting ### Watch out - Silent rollover produces a task that has moved forward forty times and looks identical to one created this morning, which is the exact information you need and the exact information the interface hides. Count the rolls and show the count. ## Phase 5 · A review that shows you your own numbers You find out how wrong your estimates are, by how much, and in which direction. ### Steps 1. Compute accuracy by bucket By project and size. The pattern is usually specific rather than global. Files: `src/review.ts` 2. Report overcommitment frequency The uncomfortable number. It is the one that changes planning. Files: `src/review.ts` 3. Suggest a budget from actuals What you actually complete, not what you hoped to. Files: `src/budget.ts`, `src/budget.test.ts` ### Done when - [ ] Estimate accuracy is reported by project and size - [ ] Overcommitment frequency is shown - [ ] The suggested budget derives from actuals - [ ] A partial week does not divide by zero ### Watch out - A review showing only completions is flattering and useless. The numbers that change behaviour are the ratio of actual to estimated time, how often you exceeded budget, and how long things sit before being done or dropped. Compute those even though they are uncomfortable. ## Not in this build - The extensive configurability of the hosted product. - Mobile applications. - Calendar integration against the day budget. - Collaboration and delegation. ## After v1, if you want it - Estimate suggestions from your own history for similar tasks, once accuracy data exists - Energy or context tagging, so a low-energy hour gets the right task - A monthly view of where time actually went by project, which the sessions already support ===== .env.example ===== # Copy to .env and fill in. Never commit .env; this file documents it. # Required. Tasks, plans and time. Your working history. DB_PATH=~/.local/share/marvin/tasks.db # Required. When a new day begins, so work past midnight lands on the right day. DAY_START_HOUR=4 # Required. The honest number, not the hopeful one. Four hours of planned work is a real day. DEFAULT_BUDGET_MINUTES=240 # Required. When a running timer prompts, so an abandoned one does not record sixteen hours. TIMER_PROMPT_MINUTES=180 # Required. How many rolls before a task is surfaced. It usually needs breaking up or dropping. ROLLOVER_ALERT_COUNT=5
You are building a production product version of Amazing Marvin. Create the following project files first, then implement the application by following them. Keep the files updated as decisions change. Do not collapse this into a single README or prompt. ===== PRODUCT.md ===== # Amazing Marvin · product brief ## Problem The core loop is small enough for a capable coding agent to produce a useful local version in one sitting. For Amazing Marvin, build a configurable personal task system from strategies, views, timers, and reviews. The hard boundary is very deep strategy library, cross-platform sync, and years of workflow experimentation, plus cross-device reliability and workflow polish. ## Product outcome A task manager that knows a day holds a finite number of hours, records what you planned against what happened, and shows you the estimate accuracy you would rather not see. ## Target user A builder who needs a maintainable product foundation, not a one-off demo. ## Required capabilities - macOS, Windows, or Linux - notification permission - local SQLite database ## Explicit non-goals for v1 - The extensive configurability of the hosted product. - Mobile applications. - Calendar integration against the day budget. - Collaboration and delegation. - very deep strategy library, cross-platform sync, and years of workflow experimentation - perfect mobile sync - calendar and email integrations - shared workspaces - behavioral coaching polish ## Success criteria - Estimateless task creation is confirmed impossible - Overcommitment is confirmed to require acknowledgement and be recorded - An abandoned timer is confirmed to prompt rather than record - Recurrence is confirmed correct across both daylight transitions - The export round trip is confirmed identical ===== BRIEF.md ===== # Build brief · Amazing Marvin The one-shot brief this plan expands. `BUILD_PLAN.md` (or `MILESTONES.md`) is the same sequence broken into steps and checks; where the two disagree, the plan wins. Build me a task manager built around the fact that you will over-commit your day to replace Amazing Marvin. Build it in phases, in the order below. Do not write the whole thing in one pass. Finish a phase, run its "Done when" check, fix what fails, and only then start the next phase. ### Stack (fixed, do not substitute) - Runtime: TypeScript with a local application and SQLite · a task list is personal and should work on a train - Model: Tasks with estimates, a day plan, and a completion record · the plan against actual comparison is the entire point - Time: Every timestamp stored in UTC with the local zone recorded · day boundaries are where task managers break - Review: Scheduled prompts driven by data, not by a calendar · a review that shows your actual overcommitment is worth attending - Export: JSON and Markdown, complete · a task history is a record of your working life ### Data model (create this before Phase 1) - tasks(id, title, project_id, estimate_minutes, due_at, created_at, completed_at, dropped_at) - day_plans(date, budget_minutes, planned_at, local_zone) · the budget is the constraint the day is checked against - plan_items(day_plan_date, task_id, ordinal, estimate_at_plan_minutes) · the estimate is captured at planning time - sessions(id, task_id, started_at, ended_at, source) · source is timer or entered_later - outcomes(day_plan_date, planned_minutes, actual_minutes, completed_count, rolled_over_count) - The estimate is snapshotted into the plan item, because comparing today's outcome against a later revised estimate tells you nothing. ### Phase 1 · Tasks with honest estimates Build: Tasks with title, project, estimate and due date. Creation must require an estimate, with a coarse scale rather than a free number. A running total of estimates for any set. Trap: A free-text minutes field produces false precision and slows down capture until people stop estimating, which removes the mechanic the whole system is built on. Use a coarse scale of a few buckets, which is fast to choose and accurate enough for a day budget. Done when: Creating a task requires an estimate from a coarse scale. A set of tasks shows a running estimate total. Capture with an estimate takes only a few seconds, timed by hand. Tasks without estimates cannot exist, verified by attempting to create one. Do not build yet: No day plan or timing yet. ### Phase 2 · A day that refuses to hold more than it can Build: A day plan with a time budget. Adding tasks accumulates against it. Exceeding the budget requires an explicit acknowledgement and is recorded as an overcommitment. Snapshot each estimate into the plan item. Trap: Blocking overcommitment outright means people plan outside the tool the first time a real day demands it, and blocking is also wrong because some days genuinely are like that. Allow it, require an acknowledgement, and record it, so the review can show the pattern. Done when: A day plan accumulates estimates against a budget and shows remaining time. Exceeding requires an explicit acknowledgement rather than being blocked or silent. The overcommitment is recorded on the plan. Estimates are snapshotted at planning time, verified by changing a task's estimate afterwards. Do not build yet: No timing or review yet. ### Phase 3 · What actually happened Build: A timer per task, and an equally easy path to enter time afterwards. Compute the day's outcome: planned against actual, completed, rolled over. Handle a timer left running overnight rather than recording sixteen hours. Trap: A system that only records time from a timer produces mostly empty data, because nobody starts a timer every time, and then the plan against actual comparison is built on nothing. Make entering time afterwards as easy as starting the timer and mark which is which. Done when: Time can be timed or entered afterwards with equal ease, and the source is recorded. A timer running past a threshold prompts rather than recording sixteen hours. The day's outcome shows planned against actual. A day with no timing at all still produces a completion outcome. Do not build yet: No review or rollover yet. ### Phase 4 · Rollover that does not hide the problem Build: Roll unfinished tasks into the next day, counting how many days each has rolled. Surface tasks rolled repeatedly. Rolled tasks consume budget in the new day like anything else. Trap: Silent rollover produces a task that has moved forward forty times and looks identical to one created this morning, which is the exact information you need and the exact information the interface hides. Count the rolls and show the count. Done when: Unfinished tasks roll to the next day with an incremented count. A task rolled more than a threshold is surfaced distinctly. Rolled tasks consume budget in the new day. A task rolled repeatedly can be dropped, and dropping is recorded rather than deleting it. Do not build yet: No review or projects yet. ### Phase 5 · A review that shows you your own numbers Build: A weekly review computing estimate accuracy by project and task size, overcommitment frequency, and rollover distribution. Offer a suggested budget derived from actual completed time rather than from what you hoped. Trap: A review showing only completions is flattering and useless. The numbers that change behaviour are the ratio of actual to estimated time, how often you exceeded budget, and how long things sit before being done or dropped. Compute those even though they are uncomfortable. Done when: The review reports estimate accuracy as a ratio, by project and size bucket. Overcommitment frequency is shown for the period. The suggested budget derives from actual completed time. The review runs on a partial week without dividing by zero, tested with one day of data. Do not build yet: Export and projects come last. ### Phase 6 · Projects, recurrence and getting out Build: Projects with tasks, recurring tasks that generate correctly across zones and daylight changes, and a complete export of tasks, plans, sessions and outcomes. Trap: Recurring tasks generated in local time drift or duplicate across a daylight saving change, producing either two of a task or none on that day. Store the rule with a zone, generate in UTC, and test explicitly across both transitions. Done when: Recurrence generates correctly across both daylight saving transitions, tested with dates on either side. Projects group tasks and show their total estimate. Export contains tasks, plans, sessions and outcomes and re-imports identically. A completed recurring task does not regenerate for the same period. Do not build yet: Nothing after this. ### Out of scope (and why) - The enormous configurability the hosted product is known for, where nearly every behaviour is a toggle, which is a design philosophy rather than a feature you can bolt on. - Mobile applications, which is where most task capture actually happens. - Calendar integration showing meetings against the day budget, which would genuinely improve the budget's accuracy. - Collaboration and delegation, which is a different product. ### README must contain - That estimates use a coarse scale and are required, because that is what the budget needs - That overcommitment is allowed, acknowledged and recorded rather than blocked - That time can be entered afterwards as easily as timed, and the source is recorded - That rollover counts are kept and surfaced - That the review reports estimate accuracy and overcommitment, not just completions ===== ARCHITECTURE.md ===== # Architecture · Amazing Marvin ## Stack | Part | Choice | Why | | --- | --- | --- | | Runtime | TypeScript with a local application and SQLite | a task list is personal and should work on a train | | Model | Tasks with estimates, a day plan, and a completion record | the plan against actual comparison is the entire point | | Time | Every timestamp stored in UTC with the local zone recorded | day boundaries are where task managers break | | Review | Scheduled prompts driven by data, not by a calendar | a review that shows your actual overcommitment is worth attending | | Export | JSON and Markdown, complete | a task history is a record of your working life | ## Modules Each module has one owner concern and a documented way to replace it. | Module | Owns | How to replace it | | --- | --- | --- | | Tasks | Titles, projects and required estimates. | Any store. The required coarse estimate is the design requirement. | | Plan | The day budget and overcommitment record. | Not swappable for a plain list, which is the thing this exists not to be. | | Time | Timed and entered sessions. | Any implementation, provided entering afterwards is as easy as timing. | | Rollover | Carrying forward with counts. | Any implementation. Keeping the count is the requirement. | | Review | Accuracy, overcommitment and budget suggestion. | Any computation, provided it reports the uncomfortable numbers. | ## Configuration Every runtime setting is an environment variable documented in `.env.example`, validated at startup, with a safe local default wherever one exists. - `DB_PATH` · required · Tasks, plans and time. Your working history. - `DAY_START_HOUR` · required · When a new day begins, so work past midnight lands on the right day. - `DEFAULT_BUDGET_MINUTES` · required · The honest number, not the hopeful one. Four hours of planned work is a real day. - `TIMER_PROMPT_MINUTES` · required · When a running timer prompts, so an abandoned one does not record sixteen hours. - `ROLLOVER_ALERT_COUNT` · required · How many rolls before a task is surfaced. It usually needs breaking up or dropping. ## Production baseline - Security: least privilege, input validation at every boundary, secret redaction in logs, rate limits on abuse-prone paths, no invented security primitives. - Data: explicit schema and migrations, transactional writes where integrity matters, backup and restore procedures that have been exercised. - Integrations: adapters around third-party providers, idempotent webhook or job processing, bounded retries, timeouts. - Observability: structured logs with request or operation ids, an error-tracking hook, and health and readiness checks where a server exists. - Quality: unit tests for domain rules, integration tests at module boundaries, one end-to-end test of the critical path. ## Decision records For each dependency in the stack table, keep a short note: why it was chosen, its failure mode, and how it is replaced. Do not add infrastructure until a requirement in `PRODUCT.md` justifies it. ===== AGENTS.md ===== # Agent instructions · Amazing Marvin product build - Read `PRODUCT.md` and `ARCHITECTURE.md` before changing code. The stack is fixed: TypeScript with a local application and SQLite, Tasks with estimates, a day plan, and a completion record, Every timestamp stored in UTC with the local zone recorded, Scheduled prompts driven by data, not by a calendar, JSON and Markdown, complete. - Implement milestone by milestone from `MILESTONES.md`; keep each change reviewable and leave the application runnable at every commit. - Treat authentication, payments, encryption, imports, webhooks and destructive actions as high-risk boundaries when present. - Never invent cryptography or silently weaken a requirement to make a check pass. - Put every external service behind an interface with a deterministic fake for tests. - Add migrations and rollback or recovery notes for every persistent data change. - Log useful operational context without credentials, tokens, passwords or personal data. - Update documentation and run every check before completing a milestone. ## Known traps - A free-text minutes field produces false precision and slows down capture until people stop estimating, which removes the mechanic the whole system is built on. Use a coarse scale of a few buckets, which is fast to choose and accurate enough for a day budget. - Blocking overcommitment outright means people plan outside the tool the first time a real day demands it, and blocking is also wrong because some days genuinely are like that. Allow it, require an acknowledgement, and record it, so the review can show the pattern. - A system that only records time from a timer produces mostly empty data, because nobody starts a timer every time, and then the plan against actual comparison is built on nothing. Make entering time afterwards as easy as starting the timer and mark which is which. - Silent rollover produces a task that has moved forward forty times and looks identical to one created this morning, which is the exact information you need and the exact information the interface hides. Count the rolls and show the count. - A review showing only completions is flattering and useless. The numbers that change behaviour are the ratio of actual to estimated time, how often you exceeded budget, and how long things sit before being done or dropped. Compute those even though they are uncomfortable. - Recurring tasks generated in local time drift or duplicate across a daylight saving change, producing either two of a task or none on that day. Store the rule with a zone, generate in UTC, and test explicitly across both transitions. ===== MILESTONES.md ===== # Delivery milestones · Amazing Marvin Estimated effort: **multi-day** for the indie phases; the production-only milestones add the trust and operability layer. ## M1 · Tasks with honest estimates Every task carries a time estimate and you can see them accumulate. ### Steps 1. Use a coarse estimate scale A handful of buckets. False precision is what kills estimating. Files: `src/estimate.ts` 2. Require it at creation An optional estimate is an absent estimate within a week. Files: `src/tasks.ts` 3. Sum estimates for any set The total is what the day plan will check against. Files: `src/totals.ts` ### Done when - [ ] Task creation requires an estimate from a scale - [ ] A set shows its estimate total - [ ] Capture with an estimate is fast - [ ] An estimateless task cannot be created ### Watch out - A free-text minutes field produces false precision and slows down capture until people stop estimating, which removes the mechanic the whole system is built on. Use a coarse scale of a few buckets, which is fast to choose and accurate enough for a day budget. ## M2 · A day that refuses to hold more than it can Planning past your budget is possible but never silent. ### Steps 1. Budget per day, not a fixed number Days differ. A budget you set is a budget you believe. Files: `src/plan.ts` 2. Acknowledge, do not block Blocking pushes planning out of the tool. Recording produces the review. Files: `src/plan.ts` 3. Snapshot the estimate into the plan Comparing against a revised estimate later measures nothing. Files: `src/plan.ts` ### Done when - [ ] A day plan shows remaining budget - [ ] Exceeding requires acknowledgement - [ ] Overcommitment is recorded - [ ] Estimates are snapshotted at plan time ### Watch out - Blocking overcommitment outright means people plan outside the tool the first time a real day demands it, and blocking is also wrong because some days genuinely are like that. Allow it, require an acknowledgement, and record it, so the review can show the pattern. ## M3 · What actually happened You can compare the plan against the day without perfect timer discipline. ### Steps 1. Two equally easy paths Timer and after the fact. Recording the source keeps the data honest. Files: `src/time.ts` 2. Handle the abandoned timer Prompt past a threshold. Sixteen-hour sessions poison the comparison. Files: `src/time.ts` 3. Compute the day outcome Planned, actual, completed, rolled over. Four numbers that mean something. Files: `src/outcome.ts` ### Done when - [ ] Timed and entered time are equally easy and distinguished - [ ] A long-running timer prompts rather than recording - [ ] The day outcome shows planned against actual - [ ] A day without timing still produces an outcome ### Watch out - A system that only records time from a timer produces mostly empty data, because nobody starts a timer every time, and then the plan against actual comparison is built on nothing. Make entering time afterwards as easy as starting the timer and mark which is which. ## M4 · Rollover that does not hide the problem Unfinished tasks carry forward visibly, with their history. ### Steps 1. Count the rolls The number is the signal. Rolling silently discards it. Files: `src/rollover.ts` 2. Surface repeat offenders Past a threshold, distinctly. It is usually a task that needs breaking up or dropping. Files: `src/rollover.ts` 3. Record drops rather than deleting What you chose not to do is data about your planning. Files: `src/tasks.ts` ### Done when - [ ] Rollover increments a count per task - [ ] Repeatedly rolled tasks are surfaced - [ ] Rolled tasks consume the new day's budget - [ ] Dropping is recorded rather than deleting ### Watch out - Silent rollover produces a task that has moved forward forty times and looks identical to one created this morning, which is the exact information you need and the exact information the interface hides. Count the rolls and show the count. ## M5 · A review that shows you your own numbers You find out how wrong your estimates are, by how much, and in which direction. ### Steps 1. Compute accuracy by bucket By project and size. The pattern is usually specific rather than global. Files: `src/review.ts` 2. Report overcommitment frequency The uncomfortable number. It is the one that changes planning. Files: `src/review.ts` 3. Suggest a budget from actuals What you actually complete, not what you hoped to. Files: `src/budget.ts`, `src/budget.test.ts` ### Done when - [ ] Estimate accuracy is reported by project and size - [ ] Overcommitment frequency is shown - [ ] The suggested budget derives from actuals - [ ] A partial week does not divide by zero ### Watch out - A review showing only completions is flattering and useless. The numbers that change behaviour are the ratio of actual to estimated time, how often you exceeded budget, and how long things sit before being done or dropped. Compute those even though they are uncomfortable. ## M6 · Projects, recurrence and getting out (production only) Structure for longer work, and a complete export. ### Steps 1. Generate recurrence in UTC from a zoned rule Test both transitions explicitly. This is where task managers reliably break. Files: `src/recurrence.ts`, `src/recurrence.test.ts` 2. Group by project with totals A project's remaining estimate is what makes it plannable. Files: `src/projects.ts` 3. Export everything Tasks, plans, sessions, outcomes. Round trip tested. Files: `src/export.ts`, `tests/roundtrip.test.ts` ### Done when - [ ] Recurrence is correct across both daylight transitions - [ ] Projects group tasks with totals - [ ] Export round trips identically - [ ] A completed recurrence does not regenerate ### Watch out - Recurring tasks generated in local time drift or duplicate across a daylight saving change, producing either two of a task or none on that day. Store the rule with a zone, generate in UTC, and test explicitly across both transitions. ===== OPERATIONS.md ===== # Operations · Amazing Marvin ## Backup Task history is a record of your working life and gets more valuable with age. Regular backups with a tested restore, plus periodic exports in a format that outlives the application. ## Restore Restore and confirm plans, sessions and outcomes are intact, since losing sessions silently makes every accuracy number wrong without any visible error. Do a restore drill before the first real user, and write the date here when it passes. ## Monitoring For a personal tool, the review is the monitoring. A rising overcommitment frequency or a widening estimate ratio is the signal, and both are visible in the weekly numbers. ## Incident checklist If recurrence produces two of a task or none on a daylight change day, the generation is happening in local time. If accuracy numbers look implausibly good, check for abandoned timers inflating actuals. 1. Contain the issue without destroying evidence or user data. 2. Record the timeline and affected scope. 3. Rotate exposed secrets and revoke compromised sessions or credentials. 4. Restore from a verified backup when needed. 5. Document the root cause, the remediation and the regression test. ## Release gate - [ ] Estimateless task creation is confirmed impossible - [ ] Overcommitment is confirmed to require acknowledgement and be recorded - [ ] An abandoned timer is confirmed to prompt rather than record - [ ] Recurrence is confirmed correct across both daylight transitions - [ ] The export round trip is confirmed identical ## Launch constraint Do not market omitted Amazing Marvin capabilities as implemented. The non-goals in `PRODUCT.md` remain user-visible limitations until they are deliberately delivered. ===== .env.example ===== # Copy to .env and fill in. Never commit .env; this file documents it. # Required. Tasks, plans and time. Your working history. DB_PATH=~/.local/share/marvin/tasks.db # Required. When a new day begins, so work past midnight lands on the right day. DAY_START_HOUR=4 # Required. The honest number, not the hopeful one. Four hours of planned work is a real day. DEFAULT_BUDGET_MINUTES=240 # Required. When a running timer prompts, so an abandoned one does not record sixteen hours. TIMER_PROMPT_MINUTES=180 # Required. How many rolls before a task is surfaced. It usually needs breaking up or dropping. ROLLOVER_ALERT_COUNT=5
# Amazing Marvin · indie build A task system whose central mechanic is the day plan with a time budget: tasks carry estimates, the day refuses to silently accept more than fits, and the record of what you planned against what happened is what makes your estimates get better. Estimated effort: **multi-day**. Work `BUILD_PLAN.md` top to bottom · every phase ends in a check that has to pass before the next one starts. ## Stack | Part | Choice | Why | | --- | --- | --- | | Runtime | TypeScript with a local application and SQLite | a task list is personal and should work on a train | | Model | Tasks with estimates, a day plan, and a completion record | the plan against actual comparison is the entire point | | Time | Every timestamp stored in UTC with the local zone recorded | day boundaries are where task managers break | | Review | Scheduled prompts driven by data, not by a calendar | a review that shows your actual overcommitment is worth attending | | Export | JSON and Markdown, complete | a task history is a record of your working life | ## Before you start Have every one of these ready. The plan assumes them from step one. - [ ] **Node.js 22 or newer** · free - Why: Runs the local application. - Get it: nodejs.org, or nvm install 22. - Verify: node --version prints v22 or higher - [ ] **Your honest daily budget** · free, and mildly deflating - Why: The budget is the constraint everything else checks against, and setting it to eight hours guarantees the system tells you nothing useful. - Get it: Look at a real week and count the hours you actually spent on planned work rather than meetings, interruptions and admin. - Verify: A number is written down with the reasoning behind it - [ ] **Two weeks of real tasks and time** · free, but it takes two weeks - Why: Estimate accuracy, rollover distribution and budget suggestion need real data, and synthetic data will confirm whatever you assumed. - Get it: Use the tool for two weeks before trusting the review, or import from an existing system with times. - Verify: Two weeks of plans with actual times exist - [ ] **How your day boundaries work** · free - Why: Day plans, rollover and recurrence all depend on when a day starts, and someone working past midnight breaks the naive answer. - Get it: Decide the hour a new day begins for you and whether travel changes it. Write it down before phase 2. - Verify: A written note states the day start hour and travel behaviour ## Quick start Follow Phase 1 in `BUILD_PLAN.md`; it creates the project. Then copy `.env.example` to `.env` and fill in the values it documents. ## Honest limits This build deliberately does not replace: - The extensive configurability of the hosted product. - Mobile applications. - Calendar integration against the day budget. - Collaboration and delegation. - very deep strategy library, cross-platform sync, and years of workflow experimentation - perfect mobile sync - calendar and email integrations - shared workspaces - behavioral coaching polish If one of those is essential to you, that is the reason to keep paying for Amazing Marvin, and the README should say so rather than pretend.
# Build brief · Amazing Marvin The one-shot brief this plan expands. `BUILD_PLAN.md` (or `MILESTONES.md`) is the same sequence broken into steps and checks; where the two disagree, the plan wins. Build me a task manager built around the fact that you will over-commit your day to replace Amazing Marvin. Build it in phases, in the order below. Do not write the whole thing in one pass. Finish a phase, run its "Done when" check, fix what fails, and only then start the next phase. ### Stack (fixed, do not substitute) - Runtime: TypeScript with a local application and SQLite · a task list is personal and should work on a train - Model: Tasks with estimates, a day plan, and a completion record · the plan against actual comparison is the entire point - Time: Every timestamp stored in UTC with the local zone recorded · day boundaries are where task managers break - Review: Scheduled prompts driven by data, not by a calendar · a review that shows your actual overcommitment is worth attending - Export: JSON and Markdown, complete · a task history is a record of your working life ### Data model (create this before Phase 1) - tasks(id, title, project_id, estimate_minutes, due_at, created_at, completed_at, dropped_at) - day_plans(date, budget_minutes, planned_at, local_zone) · the budget is the constraint the day is checked against - plan_items(day_plan_date, task_id, ordinal, estimate_at_plan_minutes) · the estimate is captured at planning time - sessions(id, task_id, started_at, ended_at, source) · source is timer or entered_later - outcomes(day_plan_date, planned_minutes, actual_minutes, completed_count, rolled_over_count) - The estimate is snapshotted into the plan item, because comparing today's outcome against a later revised estimate tells you nothing. ### Phase 1 · Tasks with honest estimates Build: Tasks with title, project, estimate and due date. Creation must require an estimate, with a coarse scale rather than a free number. A running total of estimates for any set. Trap: A free-text minutes field produces false precision and slows down capture until people stop estimating, which removes the mechanic the whole system is built on. Use a coarse scale of a few buckets, which is fast to choose and accurate enough for a day budget. Done when: Creating a task requires an estimate from a coarse scale. A set of tasks shows a running estimate total. Capture with an estimate takes only a few seconds, timed by hand. Tasks without estimates cannot exist, verified by attempting to create one. Do not build yet: No day plan or timing yet. ### Phase 2 · A day that refuses to hold more than it can Build: A day plan with a time budget. Adding tasks accumulates against it. Exceeding the budget requires an explicit acknowledgement and is recorded as an overcommitment. Snapshot each estimate into the plan item. Trap: Blocking overcommitment outright means people plan outside the tool the first time a real day demands it, and blocking is also wrong because some days genuinely are like that. Allow it, require an acknowledgement, and record it, so the review can show the pattern. Done when: A day plan accumulates estimates against a budget and shows remaining time. Exceeding requires an explicit acknowledgement rather than being blocked or silent. The overcommitment is recorded on the plan. Estimates are snapshotted at planning time, verified by changing a task's estimate afterwards. Do not build yet: No timing or review yet. ### Phase 3 · What actually happened Build: A timer per task, and an equally easy path to enter time afterwards. Compute the day's outcome: planned against actual, completed, rolled over. Handle a timer left running overnight rather than recording sixteen hours. Trap: A system that only records time from a timer produces mostly empty data, because nobody starts a timer every time, and then the plan against actual comparison is built on nothing. Make entering time afterwards as easy as starting the timer and mark which is which. Done when: Time can be timed or entered afterwards with equal ease, and the source is recorded. A timer running past a threshold prompts rather than recording sixteen hours. The day's outcome shows planned against actual. A day with no timing at all still produces a completion outcome. Do not build yet: No review or rollover yet. ### Phase 4 · Rollover that does not hide the problem Build: Roll unfinished tasks into the next day, counting how many days each has rolled. Surface tasks rolled repeatedly. Rolled tasks consume budget in the new day like anything else. Trap: Silent rollover produces a task that has moved forward forty times and looks identical to one created this morning, which is the exact information you need and the exact information the interface hides. Count the rolls and show the count. Done when: Unfinished tasks roll to the next day with an incremented count. A task rolled more than a threshold is surfaced distinctly. Rolled tasks consume budget in the new day. A task rolled repeatedly can be dropped, and dropping is recorded rather than deleting it. Do not build yet: No review or projects yet. ### Phase 5 · A review that shows you your own numbers Build: A weekly review computing estimate accuracy by project and task size, overcommitment frequency, and rollover distribution. Offer a suggested budget derived from actual completed time rather than from what you hoped. Trap: A review showing only completions is flattering and useless. The numbers that change behaviour are the ratio of actual to estimated time, how often you exceeded budget, and how long things sit before being done or dropped. Compute those even though they are uncomfortable. Done when: The review reports estimate accuracy as a ratio, by project and size bucket. Overcommitment frequency is shown for the period. The suggested budget derives from actual completed time. The review runs on a partial week without dividing by zero, tested with one day of data. Do not build yet: Export and projects come last. ### Phase 6 · Projects, recurrence and getting out Build: Projects with tasks, recurring tasks that generate correctly across zones and daylight changes, and a complete export of tasks, plans, sessions and outcomes. Trap: Recurring tasks generated in local time drift or duplicate across a daylight saving change, producing either two of a task or none on that day. Store the rule with a zone, generate in UTC, and test explicitly across both transitions. Done when: Recurrence generates correctly across both daylight saving transitions, tested with dates on either side. Projects group tasks and show their total estimate. Export contains tasks, plans, sessions and outcomes and re-imports identically. A completed recurring task does not regenerate for the same period. Do not build yet: Nothing after this. ### Out of scope (and why) - The enormous configurability the hosted product is known for, where nearly every behaviour is a toggle, which is a design philosophy rather than a feature you can bolt on. - Mobile applications, which is where most task capture actually happens. - Calendar integration showing meetings against the day budget, which would genuinely improve the budget's accuracy. - Collaboration and delegation, which is a different product. ### README must contain - That estimates use a coarse scale and are required, because that is what the budget needs - That overcommitment is allowed, acknowledged and recorded rather than blocked - That time can be entered afterwards as easily as timed, and the source is recorded - That rollover counts are kept and surfaced - That the review reports estimate accuracy and overcommitment, not just completions
# Agent instructions · Amazing Marvin indie build - Read `README.md` and `BUILD_PLAN.md` before writing code. The stack is fixed: TypeScript with a local application and SQLite, Tasks with estimates, a day plan, and a completion record, Every timestamp stored in UTC with the local zone recorded, Scheduled prompts driven by data, not by a calendar, JSON and Markdown, complete. Do not substitute. - Work one phase at a time, in order. Do not start a phase until every "Done when" item of the previous one passes. - Prefer the fewest moving parts that satisfy the step. No frameworks, services or dependencies the plan does not name. - Secrets live in `.env`, never in source or logs. Keep `.env.example` current when a variable is introduced. - Do not invent cryptography, security guarantees, APIs or compliance claims. - Add a focused test for every destructive, security-sensitive or data-loss path the plan names. - Run the project checks before declaring a phase complete, and record any deliberate shortcut in the README under "Tradeoffs". ## Known traps - A free-text minutes field produces false precision and slows down capture until people stop estimating, which removes the mechanic the whole system is built on. Use a coarse scale of a few buckets, which is fast to choose and accurate enough for a day budget. - Blocking overcommitment outright means people plan outside the tool the first time a real day demands it, and blocking is also wrong because some days genuinely are like that. Allow it, require an acknowledgement, and record it, so the review can show the pattern. - A system that only records time from a timer produces mostly empty data, because nobody starts a timer every time, and then the plan against actual comparison is built on nothing. Make entering time afterwards as easy as starting the timer and mark which is which. - Silent rollover produces a task that has moved forward forty times and looks identical to one created this morning, which is the exact information you need and the exact information the interface hides. Count the rolls and show the count. - A review showing only completions is flattering and useless. The numbers that change behaviour are the ratio of actual to estimated time, how often you exceeded budget, and how long things sit before being done or dropped. Compute those even though they are uncomfortable.
# Build plan · Amazing Marvin A task system whose central mechanic is the day plan with a time budget: tasks carry estimates, the day refuses to silently accept more than fits, and the record of what you planned against what happened is what makes your estimates get better. Phases are in dependency order. Each ends in a "Done when" list; treat an unticked item as a blocker, not a note. ## Phase 1 · Tasks with honest estimates Every task carries a time estimate and you can see them accumulate. ### Steps 1. Use a coarse estimate scale A handful of buckets. False precision is what kills estimating. Files: `src/estimate.ts` 2. Require it at creation An optional estimate is an absent estimate within a week. Files: `src/tasks.ts` 3. Sum estimates for any set The total is what the day plan will check against. Files: `src/totals.ts` ### Done when - [ ] Task creation requires an estimate from a scale - [ ] A set shows its estimate total - [ ] Capture with an estimate is fast - [ ] An estimateless task cannot be created ### Watch out - A free-text minutes field produces false precision and slows down capture until people stop estimating, which removes the mechanic the whole system is built on. Use a coarse scale of a few buckets, which is fast to choose and accurate enough for a day budget. ## Phase 2 · A day that refuses to hold more than it can Planning past your budget is possible but never silent. ### Steps 1. Budget per day, not a fixed number Days differ. A budget you set is a budget you believe. Files: `src/plan.ts` 2. Acknowledge, do not block Blocking pushes planning out of the tool. Recording produces the review. Files: `src/plan.ts` 3. Snapshot the estimate into the plan Comparing against a revised estimate later measures nothing. Files: `src/plan.ts` ### Done when - [ ] A day plan shows remaining budget - [ ] Exceeding requires acknowledgement - [ ] Overcommitment is recorded - [ ] Estimates are snapshotted at plan time ### Watch out - Blocking overcommitment outright means people plan outside the tool the first time a real day demands it, and blocking is also wrong because some days genuinely are like that. Allow it, require an acknowledgement, and record it, so the review can show the pattern. ## Phase 3 · What actually happened You can compare the plan against the day without perfect timer discipline. ### Steps 1. Two equally easy paths Timer and after the fact. Recording the source keeps the data honest. Files: `src/time.ts` 2. Handle the abandoned timer Prompt past a threshold. Sixteen-hour sessions poison the comparison. Files: `src/time.ts` 3. Compute the day outcome Planned, actual, completed, rolled over. Four numbers that mean something. Files: `src/outcome.ts` ### Done when - [ ] Timed and entered time are equally easy and distinguished - [ ] A long-running timer prompts rather than recording - [ ] The day outcome shows planned against actual - [ ] A day without timing still produces an outcome ### Watch out - A system that only records time from a timer produces mostly empty data, because nobody starts a timer every time, and then the plan against actual comparison is built on nothing. Make entering time afterwards as easy as starting the timer and mark which is which. ## Phase 4 · Rollover that does not hide the problem Unfinished tasks carry forward visibly, with their history. ### Steps 1. Count the rolls The number is the signal. Rolling silently discards it. Files: `src/rollover.ts` 2. Surface repeat offenders Past a threshold, distinctly. It is usually a task that needs breaking up or dropping. Files: `src/rollover.ts` 3. Record drops rather than deleting What you chose not to do is data about your planning. Files: `src/tasks.ts` ### Done when - [ ] Rollover increments a count per task - [ ] Repeatedly rolled tasks are surfaced - [ ] Rolled tasks consume the new day's budget - [ ] Dropping is recorded rather than deleting ### Watch out - Silent rollover produces a task that has moved forward forty times and looks identical to one created this morning, which is the exact information you need and the exact information the interface hides. Count the rolls and show the count. ## Phase 5 · A review that shows you your own numbers You find out how wrong your estimates are, by how much, and in which direction. ### Steps 1. Compute accuracy by bucket By project and size. The pattern is usually specific rather than global. Files: `src/review.ts` 2. Report overcommitment frequency The uncomfortable number. It is the one that changes planning. Files: `src/review.ts` 3. Suggest a budget from actuals What you actually complete, not what you hoped to. Files: `src/budget.ts`, `src/budget.test.ts` ### Done when - [ ] Estimate accuracy is reported by project and size - [ ] Overcommitment frequency is shown - [ ] The suggested budget derives from actuals - [ ] A partial week does not divide by zero ### Watch out - A review showing only completions is flattering and useless. The numbers that change behaviour are the ratio of actual to estimated time, how often you exceeded budget, and how long things sit before being done or dropped. Compute those even though they are uncomfortable. ## Not in this build - The extensive configurability of the hosted product. - Mobile applications. - Calendar integration against the day budget. - Collaboration and delegation. ## After v1, if you want it - Estimate suggestions from your own history for similar tasks, once accuracy data exists - Energy or context tagging, so a low-energy hour gets the right task - A monthly view of where time actually went by project, which the sessions already support
# Copy to .env and fill in. Never commit .env; this file documents it. # Required. Tasks, plans and time. Your working history. DB_PATH=~/.local/share/marvin/tasks.db # Required. When a new day begins, so work past midnight lands on the right day. DAY_START_HOUR=4 # Required. The honest number, not the hopeful one. Four hours of planned work is a real day. DEFAULT_BUDGET_MINUTES=240 # Required. When a running timer prompts, so an abandoned one does not record sixteen hours. TIMER_PROMPT_MINUTES=180 # Required. How many rolls before a task is surfaced. It usually needs breaking up or dropping. ROLLOVER_ALERT_COUNT=5
# Amazing Marvin · product brief ## Problem The core loop is small enough for a capable coding agent to produce a useful local version in one sitting. For Amazing Marvin, build a configurable personal task system from strategies, views, timers, and reviews. The hard boundary is very deep strategy library, cross-platform sync, and years of workflow experimentation, plus cross-device reliability and workflow polish. ## Product outcome A task manager that knows a day holds a finite number of hours, records what you planned against what happened, and shows you the estimate accuracy you would rather not see. ## Target user A builder who needs a maintainable product foundation, not a one-off demo. ## Required capabilities - macOS, Windows, or Linux - notification permission - local SQLite database ## Explicit non-goals for v1 - The extensive configurability of the hosted product. - Mobile applications. - Calendar integration against the day budget. - Collaboration and delegation. - very deep strategy library, cross-platform sync, and years of workflow experimentation - perfect mobile sync - calendar and email integrations - shared workspaces - behavioral coaching polish ## Success criteria - Estimateless task creation is confirmed impossible - Overcommitment is confirmed to require acknowledgement and be recorded - An abandoned timer is confirmed to prompt rather than record - Recurrence is confirmed correct across both daylight transitions - The export round trip is confirmed identical
# Build brief · Amazing Marvin The one-shot brief this plan expands. `BUILD_PLAN.md` (or `MILESTONES.md`) is the same sequence broken into steps and checks; where the two disagree, the plan wins. Build me a task manager built around the fact that you will over-commit your day to replace Amazing Marvin. Build it in phases, in the order below. Do not write the whole thing in one pass. Finish a phase, run its "Done when" check, fix what fails, and only then start the next phase. ### Stack (fixed, do not substitute) - Runtime: TypeScript with a local application and SQLite · a task list is personal and should work on a train - Model: Tasks with estimates, a day plan, and a completion record · the plan against actual comparison is the entire point - Time: Every timestamp stored in UTC with the local zone recorded · day boundaries are where task managers break - Review: Scheduled prompts driven by data, not by a calendar · a review that shows your actual overcommitment is worth attending - Export: JSON and Markdown, complete · a task history is a record of your working life ### Data model (create this before Phase 1) - tasks(id, title, project_id, estimate_minutes, due_at, created_at, completed_at, dropped_at) - day_plans(date, budget_minutes, planned_at, local_zone) · the budget is the constraint the day is checked against - plan_items(day_plan_date, task_id, ordinal, estimate_at_plan_minutes) · the estimate is captured at planning time - sessions(id, task_id, started_at, ended_at, source) · source is timer or entered_later - outcomes(day_plan_date, planned_minutes, actual_minutes, completed_count, rolled_over_count) - The estimate is snapshotted into the plan item, because comparing today's outcome against a later revised estimate tells you nothing. ### Phase 1 · Tasks with honest estimates Build: Tasks with title, project, estimate and due date. Creation must require an estimate, with a coarse scale rather than a free number. A running total of estimates for any set. Trap: A free-text minutes field produces false precision and slows down capture until people stop estimating, which removes the mechanic the whole system is built on. Use a coarse scale of a few buckets, which is fast to choose and accurate enough for a day budget. Done when: Creating a task requires an estimate from a coarse scale. A set of tasks shows a running estimate total. Capture with an estimate takes only a few seconds, timed by hand. Tasks without estimates cannot exist, verified by attempting to create one. Do not build yet: No day plan or timing yet. ### Phase 2 · A day that refuses to hold more than it can Build: A day plan with a time budget. Adding tasks accumulates against it. Exceeding the budget requires an explicit acknowledgement and is recorded as an overcommitment. Snapshot each estimate into the plan item. Trap: Blocking overcommitment outright means people plan outside the tool the first time a real day demands it, and blocking is also wrong because some days genuinely are like that. Allow it, require an acknowledgement, and record it, so the review can show the pattern. Done when: A day plan accumulates estimates against a budget and shows remaining time. Exceeding requires an explicit acknowledgement rather than being blocked or silent. The overcommitment is recorded on the plan. Estimates are snapshotted at planning time, verified by changing a task's estimate afterwards. Do not build yet: No timing or review yet. ### Phase 3 · What actually happened Build: A timer per task, and an equally easy path to enter time afterwards. Compute the day's outcome: planned against actual, completed, rolled over. Handle a timer left running overnight rather than recording sixteen hours. Trap: A system that only records time from a timer produces mostly empty data, because nobody starts a timer every time, and then the plan against actual comparison is built on nothing. Make entering time afterwards as easy as starting the timer and mark which is which. Done when: Time can be timed or entered afterwards with equal ease, and the source is recorded. A timer running past a threshold prompts rather than recording sixteen hours. The day's outcome shows planned against actual. A day with no timing at all still produces a completion outcome. Do not build yet: No review or rollover yet. ### Phase 4 · Rollover that does not hide the problem Build: Roll unfinished tasks into the next day, counting how many days each has rolled. Surface tasks rolled repeatedly. Rolled tasks consume budget in the new day like anything else. Trap: Silent rollover produces a task that has moved forward forty times and looks identical to one created this morning, which is the exact information you need and the exact information the interface hides. Count the rolls and show the count. Done when: Unfinished tasks roll to the next day with an incremented count. A task rolled more than a threshold is surfaced distinctly. Rolled tasks consume budget in the new day. A task rolled repeatedly can be dropped, and dropping is recorded rather than deleting it. Do not build yet: No review or projects yet. ### Phase 5 · A review that shows you your own numbers Build: A weekly review computing estimate accuracy by project and task size, overcommitment frequency, and rollover distribution. Offer a suggested budget derived from actual completed time rather than from what you hoped. Trap: A review showing only completions is flattering and useless. The numbers that change behaviour are the ratio of actual to estimated time, how often you exceeded budget, and how long things sit before being done or dropped. Compute those even though they are uncomfortable. Done when: The review reports estimate accuracy as a ratio, by project and size bucket. Overcommitment frequency is shown for the period. The suggested budget derives from actual completed time. The review runs on a partial week without dividing by zero, tested with one day of data. Do not build yet: Export and projects come last. ### Phase 6 · Projects, recurrence and getting out Build: Projects with tasks, recurring tasks that generate correctly across zones and daylight changes, and a complete export of tasks, plans, sessions and outcomes. Trap: Recurring tasks generated in local time drift or duplicate across a daylight saving change, producing either two of a task or none on that day. Store the rule with a zone, generate in UTC, and test explicitly across both transitions. Done when: Recurrence generates correctly across both daylight saving transitions, tested with dates on either side. Projects group tasks and show their total estimate. Export contains tasks, plans, sessions and outcomes and re-imports identically. A completed recurring task does not regenerate for the same period. Do not build yet: Nothing after this. ### Out of scope (and why) - The enormous configurability the hosted product is known for, where nearly every behaviour is a toggle, which is a design philosophy rather than a feature you can bolt on. - Mobile applications, which is where most task capture actually happens. - Calendar integration showing meetings against the day budget, which would genuinely improve the budget's accuracy. - Collaboration and delegation, which is a different product. ### README must contain - That estimates use a coarse scale and are required, because that is what the budget needs - That overcommitment is allowed, acknowledged and recorded rather than blocked - That time can be entered afterwards as easily as timed, and the source is recorded - That rollover counts are kept and surfaced - That the review reports estimate accuracy and overcommitment, not just completions
# Architecture · Amazing Marvin ## Stack | Part | Choice | Why | | --- | --- | --- | | Runtime | TypeScript with a local application and SQLite | a task list is personal and should work on a train | | Model | Tasks with estimates, a day plan, and a completion record | the plan against actual comparison is the entire point | | Time | Every timestamp stored in UTC with the local zone recorded | day boundaries are where task managers break | | Review | Scheduled prompts driven by data, not by a calendar | a review that shows your actual overcommitment is worth attending | | Export | JSON and Markdown, complete | a task history is a record of your working life | ## Modules Each module has one owner concern and a documented way to replace it. | Module | Owns | How to replace it | | --- | --- | --- | | Tasks | Titles, projects and required estimates. | Any store. The required coarse estimate is the design requirement. | | Plan | The day budget and overcommitment record. | Not swappable for a plain list, which is the thing this exists not to be. | | Time | Timed and entered sessions. | Any implementation, provided entering afterwards is as easy as timing. | | Rollover | Carrying forward with counts. | Any implementation. Keeping the count is the requirement. | | Review | Accuracy, overcommitment and budget suggestion. | Any computation, provided it reports the uncomfortable numbers. | ## Configuration Every runtime setting is an environment variable documented in `.env.example`, validated at startup, with a safe local default wherever one exists. - `DB_PATH` · required · Tasks, plans and time. Your working history. - `DAY_START_HOUR` · required · When a new day begins, so work past midnight lands on the right day. - `DEFAULT_BUDGET_MINUTES` · required · The honest number, not the hopeful one. Four hours of planned work is a real day. - `TIMER_PROMPT_MINUTES` · required · When a running timer prompts, so an abandoned one does not record sixteen hours. - `ROLLOVER_ALERT_COUNT` · required · How many rolls before a task is surfaced. It usually needs breaking up or dropping. ## Production baseline - Security: least privilege, input validation at every boundary, secret redaction in logs, rate limits on abuse-prone paths, no invented security primitives. - Data: explicit schema and migrations, transactional writes where integrity matters, backup and restore procedures that have been exercised. - Integrations: adapters around third-party providers, idempotent webhook or job processing, bounded retries, timeouts. - Observability: structured logs with request or operation ids, an error-tracking hook, and health and readiness checks where a server exists. - Quality: unit tests for domain rules, integration tests at module boundaries, one end-to-end test of the critical path. ## Decision records For each dependency in the stack table, keep a short note: why it was chosen, its failure mode, and how it is replaced. Do not add infrastructure until a requirement in `PRODUCT.md` justifies it.
# Agent instructions · Amazing Marvin product build - Read `PRODUCT.md` and `ARCHITECTURE.md` before changing code. The stack is fixed: TypeScript with a local application and SQLite, Tasks with estimates, a day plan, and a completion record, Every timestamp stored in UTC with the local zone recorded, Scheduled prompts driven by data, not by a calendar, JSON and Markdown, complete. - Implement milestone by milestone from `MILESTONES.md`; keep each change reviewable and leave the application runnable at every commit. - Treat authentication, payments, encryption, imports, webhooks and destructive actions as high-risk boundaries when present. - Never invent cryptography or silently weaken a requirement to make a check pass. - Put every external service behind an interface with a deterministic fake for tests. - Add migrations and rollback or recovery notes for every persistent data change. - Log useful operational context without credentials, tokens, passwords or personal data. - Update documentation and run every check before completing a milestone. ## Known traps - A free-text minutes field produces false precision and slows down capture until people stop estimating, which removes the mechanic the whole system is built on. Use a coarse scale of a few buckets, which is fast to choose and accurate enough for a day budget. - Blocking overcommitment outright means people plan outside the tool the first time a real day demands it, and blocking is also wrong because some days genuinely are like that. Allow it, require an acknowledgement, and record it, so the review can show the pattern. - A system that only records time from a timer produces mostly empty data, because nobody starts a timer every time, and then the plan against actual comparison is built on nothing. Make entering time afterwards as easy as starting the timer and mark which is which. - Silent rollover produces a task that has moved forward forty times and looks identical to one created this morning, which is the exact information you need and the exact information the interface hides. Count the rolls and show the count. - A review showing only completions is flattering and useless. The numbers that change behaviour are the ratio of actual to estimated time, how often you exceeded budget, and how long things sit before being done or dropped. Compute those even though they are uncomfortable. - Recurring tasks generated in local time drift or duplicate across a daylight saving change, producing either two of a task or none on that day. Store the rule with a zone, generate in UTC, and test explicitly across both transitions.
# Delivery milestones · Amazing Marvin Estimated effort: **multi-day** for the indie phases; the production-only milestones add the trust and operability layer. ## M1 · Tasks with honest estimates Every task carries a time estimate and you can see them accumulate. ### Steps 1. Use a coarse estimate scale A handful of buckets. False precision is what kills estimating. Files: `src/estimate.ts` 2. Require it at creation An optional estimate is an absent estimate within a week. Files: `src/tasks.ts` 3. Sum estimates for any set The total is what the day plan will check against. Files: `src/totals.ts` ### Done when - [ ] Task creation requires an estimate from a scale - [ ] A set shows its estimate total - [ ] Capture with an estimate is fast - [ ] An estimateless task cannot be created ### Watch out - A free-text minutes field produces false precision and slows down capture until people stop estimating, which removes the mechanic the whole system is built on. Use a coarse scale of a few buckets, which is fast to choose and accurate enough for a day budget. ## M2 · A day that refuses to hold more than it can Planning past your budget is possible but never silent. ### Steps 1. Budget per day, not a fixed number Days differ. A budget you set is a budget you believe. Files: `src/plan.ts` 2. Acknowledge, do not block Blocking pushes planning out of the tool. Recording produces the review. Files: `src/plan.ts` 3. Snapshot the estimate into the plan Comparing against a revised estimate later measures nothing. Files: `src/plan.ts` ### Done when - [ ] A day plan shows remaining budget - [ ] Exceeding requires acknowledgement - [ ] Overcommitment is recorded - [ ] Estimates are snapshotted at plan time ### Watch out - Blocking overcommitment outright means people plan outside the tool the first time a real day demands it, and blocking is also wrong because some days genuinely are like that. Allow it, require an acknowledgement, and record it, so the review can show the pattern. ## M3 · What actually happened You can compare the plan against the day without perfect timer discipline. ### Steps 1. Two equally easy paths Timer and after the fact. Recording the source keeps the data honest. Files: `src/time.ts` 2. Handle the abandoned timer Prompt past a threshold. Sixteen-hour sessions poison the comparison. Files: `src/time.ts` 3. Compute the day outcome Planned, actual, completed, rolled over. Four numbers that mean something. Files: `src/outcome.ts` ### Done when - [ ] Timed and entered time are equally easy and distinguished - [ ] A long-running timer prompts rather than recording - [ ] The day outcome shows planned against actual - [ ] A day without timing still produces an outcome ### Watch out - A system that only records time from a timer produces mostly empty data, because nobody starts a timer every time, and then the plan against actual comparison is built on nothing. Make entering time afterwards as easy as starting the timer and mark which is which. ## M4 · Rollover that does not hide the problem Unfinished tasks carry forward visibly, with their history. ### Steps 1. Count the rolls The number is the signal. Rolling silently discards it. Files: `src/rollover.ts` 2. Surface repeat offenders Past a threshold, distinctly. It is usually a task that needs breaking up or dropping. Files: `src/rollover.ts` 3. Record drops rather than deleting What you chose not to do is data about your planning. Files: `src/tasks.ts` ### Done when - [ ] Rollover increments a count per task - [ ] Repeatedly rolled tasks are surfaced - [ ] Rolled tasks consume the new day's budget - [ ] Dropping is recorded rather than deleting ### Watch out - Silent rollover produces a task that has moved forward forty times and looks identical to one created this morning, which is the exact information you need and the exact information the interface hides. Count the rolls and show the count. ## M5 · A review that shows you your own numbers You find out how wrong your estimates are, by how much, and in which direction. ### Steps 1. Compute accuracy by bucket By project and size. The pattern is usually specific rather than global. Files: `src/review.ts` 2. Report overcommitment frequency The uncomfortable number. It is the one that changes planning. Files: `src/review.ts` 3. Suggest a budget from actuals What you actually complete, not what you hoped to. Files: `src/budget.ts`, `src/budget.test.ts` ### Done when - [ ] Estimate accuracy is reported by project and size - [ ] Overcommitment frequency is shown - [ ] The suggested budget derives from actuals - [ ] A partial week does not divide by zero ### Watch out - A review showing only completions is flattering and useless. The numbers that change behaviour are the ratio of actual to estimated time, how often you exceeded budget, and how long things sit before being done or dropped. Compute those even though they are uncomfortable. ## M6 · Projects, recurrence and getting out (production only) Structure for longer work, and a complete export. ### Steps 1. Generate recurrence in UTC from a zoned rule Test both transitions explicitly. This is where task managers reliably break. Files: `src/recurrence.ts`, `src/recurrence.test.ts` 2. Group by project with totals A project's remaining estimate is what makes it plannable. Files: `src/projects.ts` 3. Export everything Tasks, plans, sessions, outcomes. Round trip tested. Files: `src/export.ts`, `tests/roundtrip.test.ts` ### Done when - [ ] Recurrence is correct across both daylight transitions - [ ] Projects group tasks with totals - [ ] Export round trips identically - [ ] A completed recurrence does not regenerate ### Watch out - Recurring tasks generated in local time drift or duplicate across a daylight saving change, producing either two of a task or none on that day. Store the rule with a zone, generate in UTC, and test explicitly across both transitions.
# Operations · Amazing Marvin ## Backup Task history is a record of your working life and gets more valuable with age. Regular backups with a tested restore, plus periodic exports in a format that outlives the application. ## Restore Restore and confirm plans, sessions and outcomes are intact, since losing sessions silently makes every accuracy number wrong without any visible error. Do a restore drill before the first real user, and write the date here when it passes. ## Monitoring For a personal tool, the review is the monitoring. A rising overcommitment frequency or a widening estimate ratio is the signal, and both are visible in the weekly numbers. ## Incident checklist If recurrence produces two of a task or none on a daylight change day, the generation is happening in local time. If accuracy numbers look implausibly good, check for abandoned timers inflating actuals. 1. Contain the issue without destroying evidence or user data. 2. Record the timeline and affected scope. 3. Rotate exposed secrets and revoke compromised sessions or credentials. 4. Restore from a verified backup when needed. 5. Document the root cause, the remediation and the regression test. ## Release gate - [ ] Estimateless task creation is confirmed impossible - [ ] Overcommitment is confirmed to require acknowledgement and be recorded - [ ] An abandoned timer is confirmed to prompt rather than record - [ ] Recurrence is confirmed correct across both daylight transitions - [ ] The export round trip is confirmed identical ## Launch constraint Do not market omitted Amazing Marvin capabilities as implemented. The non-goals in `PRODUCT.md` remain user-visible limitations until they are deliberately delivered.
# Copy to .env and fill in. Never commit .env; this file documents it. # Required. Tasks, plans and time. Your working history. DB_PATH=~/.local/share/marvin/tasks.db # Required. When a new day begins, so work past midnight lands on the right day. DAY_START_HOUR=4 # Required. The honest number, not the hopeful one. Four hours of planned work is a real day. DEFAULT_BUDGET_MINUTES=240 # Required. When a running timer prompts, so an abandoned one does not record sixteen hours. TIMER_PROMPT_MINUTES=180 # Required. How many rolls before a task is surfaced. It usually needs breaking up or dropping. ROLLOVER_ALERT_COUNT=5
$ choose a build depth, inspect the files, then open the complete pack in your agent
People still pay for Amazing Marvin because task software is sticky because trust, speed, and ubiquitous capture matter more than the database schema. The recurring cost buys recurrence edge cases, notifications, sync conflicts, calendar APIs, mobile capture, and backups, not just the visible interface.
xvery deep strategy library, cross-platform sync, and years of workflow experimentation
xperfect mobile sync
xcalendar and email integrations
xshared workspaces
xbehavioral coaching polish
Don't feel like building it? These folks already made it free.
no votes, no pay-to-list · just what's real
Amazing Marvin pricing
| plan | monthly | annual (per mo) | what you get |
|---|---|---|---|
| marvin pro | — | $8/user | 1 user; 100+ features; unlimited tasks and projects. |
free tierno free tier
billingmonthly + annual (-33% advertised); exact monthly dollar amount not independently exposed
verified 2026-08-14 · source ↗
Vibecode Amazing Marvin
Yes. A competent AI coding agent (Claude Code, Codex, Cursor) can build a usable personal Amazing Marvin replacement in one session with the prompt on this page. It runs on your own machine or server with no subscription.
How much does Amazing Marvin cost?
Amazing Marvin costs about $8/month (Marvin Pro, checked 2026-08-14), which is $96 per year. That's what you save by replacing it with one prompt.
What do I lose by replacing Amazing Marvin?
Honestly: very deep strategy library, cross-platform sync, and years of workflow experimentation; perfect mobile sync; calendar and email integrations; shared workspaces; behavioral coaching polish. If any of those are load-bearing for you, keep paying.
Is there an open-source alternative to Amazing Marvin?
Yes: Super Productivity (A local task manager with timeboxing, Pomodoro, and no account begging to be created) Lunatask (Tasks, seven habits, a daily calendar, and Pomodoro for free; external calendar sync is the upsell) The prompt is for when you want it exactly your way.