Build TimeHero

KINDAreplaces $5/mosaves $60/yrback to the verdict

0%0 of 17 items done

Saved on this device only. Tick prerequisites first, then work the phases in order · do not start one until the checks above it pass.

A local work planner whose hard problems are computing capacity that really exists, placing tasks by an algorithm you can explain, and refusing to hide the fact that a deadline is going to be missed.

estimated effort weekendthe files for this build are in the project pack

ShellTauri 2 with React and TypeScript, keyboard firstSchedulerOne named deterministic algorithm with a stated tie-breakStorageSQLite where each plan is a version rather than an overwriteTimeInstants in UTC, working hours as local rules plus a named zoneCalendarOptional read-only import of busy intervals from an iCalendar file or URL

Before step 1

Everything below is assumed from the first step. Tick each one when you actually have it, not when you plan to.

  1. installfree

    Why Tauri 2 needs both, and the desktop shell is what makes the keyboard-first behaviour possible.

    Get it nodejs.org and rustup.rs, then the Tauri prerequisites for your platform. open ↗

    Verify node --version prints v22 or higher and cargo --version succeeds

  2. have readyfree

    Why Capacity computed without your actual meetings is fiction, and the whole build rests on capacity being true.

    Get it Most calendars publish a private subscription address; download the file or point the importer at it.

    Verify Imported busy intervals match a week you can check by eye

  3. decidefree

    Why The plan is only arguable if the rule is written down, and picking the rule after seeing the output means picking whatever the code already did.

    Get it Choose one rule, such as earliest deadline first with a stated tie-break on priority then creation order, and write it into the documentation before implementing it.

    Verify The README names the rule and the tie-break, and the code refers to the same names

  4. decidefree

    Why Each is asserted by a test, and stability is a decision rather than an emergent property.

    Get it Write down how far ahead placements are pinned, how many minutes of movement is acceptable for a small change, and your working hours with their zone.

    Verify All three are in the configuration and named in tests

  5. have readyfree

    Why Infeasibility is only testable against a week that genuinely does not fit, and a made-up one will not.

    Get it Take an actual busy week, enter the tasks and estimate them without flattering yourself.

    Verify The planner produces at least one miss with a shortfall you recognise

Data model

Create these before the first phase that stores anything. Changing a table later is the expensive kind of change.

- tasks(id, title, estimate_minutes, remaining_minutes, deadline_at, earliest_start_at, priority, project_id, state, created_at)
- dependencies(task_id, depends_on_task_id) · a cycle is rejected at write time, not discovered at plan time
- hours(weekday, start_local, end_local, timezone) · when you can actually work, as local rules
- busy_blocks(id, source, starts_at, ends_at, external_uid) · imported, times only, and tagged with where they came from
- plans(id, computed_at, algorithm, params_json, horizon_end, feasible, churn_minutes)
- placements(plan_id, task_id, starts_at, ends_at, ordinal, reason) · the reason names the rule that put it there
- misses(plan_id, task_id, deadline_at, would_finish_at, shortfall_minutes) · the output that is never hidden
- A plan is data with a reason attached to every placement, so 'why is this on Thursday' has an answer that is not a shrug.

Environment variables

These go in a .env file the app reads at startup. The pack's .env.example is this table as a file · copy it, never commit the filled-in version.

VariableNeededExampleWhere the value comes from
DATABASE_PATHrequired~/.local/share/planner/plan.dbTasks, plans and plan history. History is the part you cannot recompute.
WORK_TIMEZONErequiredEurope/LondonWorking hours expand from this zone's rules per date.
PLAN_HORIZON_DAYSrequired21How far ahead the scheduler places work.
PIN_HORIZON_HOURSrequired48Placements inside this window survive a replan.
CHURN_LIMIT_MINUTESrequired120A small change moving more than this is a scheduler bug, and the test says so.
CALENDAR_ICS_URLsecretoptionalhttps://calendar.example.com/private/basic.icsOptional. Read-only busy intervals. The app works without it.
EXPORT_ORIGIN_TAGrequiredplanner-generatedMarks exported events so the importer can exclude them.

The build, in order

  1. Capacity that actually exists

    Available minutes come from working hours minus real commitments, computed per date.

    1. Not from a fixed offset. Write both transition days as tests first.

      Files src/time/hours.tstests/dst.test.ts

    2. Tag each one with its source so you can tell yours from theirs.

      Files src/time/capacity.ts

    3. A cycle discovered inside the scheduler is a hang with a nice name.

      Files src/tasks/dependencies.tstests/cycle.test.ts

    done when · tick each as it passes
    watch out
    • Treating capacity as eight hours a day produces a plan built on time you do not have, and the first thing it does is quietly assume your Tuesday meetings are not happening. Subtract real busy intervals, expand hours from the zone's rules for each date so the two clock change days are right, and show the daily total so a fantasy week is visible before anything is scheduled.
  2. A scheduler you can name

    The same inputs produce the same plan, and every placement carries the rule that caused it.

    1. In the code and in the README. An unnamed heuristic drifts.

      Files src/plan/schedule.tsdocs/algorithm.md

    2. The bug this phase exists to prevent is a day that quietly overfills.

      Files src/plan/schedule.tstests/capacity-invariant.test.ts

    3. The reason is what makes the plan arguable instead of magical.

      Files src/plan/reasons.ts

    done when · tick each as it passes
    watch out
    • A greedy pass that sorts by deadline and assigns each task a start time without decrementing the capacity it just consumed puts eleven hours of work into a seven hour Tuesday, and nothing errors because nobody asked whether the day was full. Consume capacity as you place, and assert that the sum of placements in any day never exceeds that day's available minutes.
  3. Saying what will not fit

    A deadline that cannot be met is reported with a number, never absorbed.

    1. A test that fails on any write to the field, not a comment.

      Files src/plan/schedule.tstests/no-estimate-writes.test.ts

    2. In minutes. A number is arguable; a warning icon is not.

      Files src/plan/misses.ts

    3. Add these hours, drop this task, or move this date.

      Files src/plan/resolutions.ts

    done when · tick each as it passes
    watch out
    • A planner that shaves estimates to make the week fit is worse than a list, because it hands you a schedule that looks achievable, is not, and teaches you within a fortnight to ignore it. Never write to an estimate from the scheduler; produce a miss with a shortfall in minutes and let the person decide what gives.
  4. A plan that does not reshuffle every morning

    Replanning moves what it must and reports how much it moved.

    1. Stability beats optimality once a human is following the plan.

      Files src/plan/pinning.tstests/stability.test.ts

    2. Minutes moved, against the previous plan.

      Files src/plan/churn.ts

    3. What changed, and what made it change.

      Files src/views/PlanDiff.tsx

    done when · tick each as it passes
    watch out
    • Recomputing the whole plan whenever anything changes rearranges half your week at nine in the morning, and since each rearrangement is individually defensible you cannot argue with it, so by Wednesday you have stopped looking. Pin what has started and the near horizon, replan on triggers, and put a churn number on every plan so a restless scheduler is visible rather than merely annoying.
what this build does not replace
after v1, if you want it

Need the files? The project pack on the verdict page hands your agent the whole brief · more productivity utilities.