← Back to Tasks & Projects OS

How it all works

A visual map of every tab, rule, and automation in the Tasks & Projects OS — written so anyone can follow along, even if they've never opened the dashboard before.

1 The big picture

The Tasks & Projects OS is one screen with seven tabs. Each tab gives a different way to look at the same set of tasks and projects. Rules and automations run quietly in the background to keep everything tidy.

Mental model: Tasks live in Airtable. The dashboard is a window into them. Edits made anywhere — drawer, grid, Kanban, drag-drop — save directly to Airtable. Automations check rules and fire follow-up actions (a Slack DM, a status update, a re-render of the team count).

📅

My Day

Today's calendar with tasks slotted in around your meetings. Default tab.

How it works ›
📋

Task List

Spreadsheet view of every Urgent / High / Not Urgent task. Inline edit anything.

How it works ›
📊

Kanban

Project work laid out by week. Drag cards to reschedule.

How it works ›
🎯

Projects

Quarterly projects with KPI progress bars and drill-downs.

How it works ›
📈

Capacity

Each team member's daily workload at a glance.

How it works ›
🔄

Recurring

Tasks that repeat (daily, weekly, monthly). Rolls forward on completion.

How it works ›
🔧

Contractor Tasks

Maintenance jobs grouped by property. Gary / Rob / Roy live here.

How it works ›

Reading the colour codes

Throughout this doc:

User action = a person clicks something
Automation = the app does it for you
Rule = a logical "if this then that" in the code
AI = a Claude model is called
Slack = sends a DM
Data = reads from / writes to Airtable

2 Task lifecycle — start to finish

Every task that ends up in this system goes through some or all of these stages.

Created

Add Task modal, inline timeline, KPI auto-spawn, or Strategy → Projects push

Assigned

To a team member. Slack DM fires.

Scheduled

Auto-placed on My Day or pinned to a Kanban week

Worked on

Status auto-derives from due date

Completed

All collaborators get a Slack DM

Rules in play at every stage: assignee email goes on the record, the creator stamps as Created By Email, project link cascades into priority/business/collaborators, and a status is derived from the due date. None of this needs the user to do anything manual — it just happens on save.
flowchart LR
  A[Click + Add Task]:::user --> B[Fill modal]:::user
  B --> C[Submit]:::user
  C --> D[Cascade rules apply]:::auto
  D --> E[POST to Airtable]:::data
  E --> F[Slack DM fires
to assignee]:::slack E --> G[Stamp Created By]:::auto E --> H[Re-render UI]:::auto classDef user fill:#DBE5F5,stroke:#5A86CF,color:#1e3a8a classDef auto fill:#DDE8DF,stroke:#2C6E49,color:#14532d classDef data fill:#E5E8E1,stroke:#5A6660,color:#1C2422 classDef slack fill:#E1ECF4,stroke:#4A154B,color:#4A154B

What happens the moment you press "Add Task"

3 Tab: My Day

For: the daily user — Kevin, Mica, Erica each on their own filtered view. Default tab on open.

What you see

  • Vertical timeline — your day from working start to end, with hour markers
  • Calendar events in plum (pulled from Google Calendar via the gcal proxy)
  • Routine blocks in amber (Run, Lunch, Get Ready — configurable per user)
  • Tasks in their priority colour: Urgent (red), High (yellow), Project (blue), Not Urgent (green)
  • Side panel on the right: today's other tasks not yet placed on the timeline

What you can do

  • User Drag a task between time slots → due date stays today, just changes start time
  • User Drag the bottom edge of a task → resize duration
  • User Drag a task into the side panel → reschedules to next available day with capacity
  • User Drag from side panel onto timeline → schedules at that time
  • User Double-click an empty slot → inline-add a task at that time (15-minute default)
  • User Click the Auto-Schedule button → run the planner across the next two weeks

Automations fired here

WhenWhat happens
Page loads (Kevin only)Auto Overdue tasks pulled forward to today (skips hard-deadline + project beyond this week)
Inline-add a taskAuto Task assigned to whoever's day you're viewing (not the logged-in user). Pinned at the clicked time. Slack DM to assignee if not yourself.
Drag onto side panelRule Find the next workday (skip weekends) within capacity for that assignee → reschedule due date there
Click Auto-ScheduleAuto Run scheduler with the rules in section 9

The colour-coded blocks

When two blocks land in the same time slot the timeline splits the column horizontally so they sit side-by-side instead of hiding each other.

4 Tab: Task List

For: the spreadsheet view of operational work. Shows tasks with priority Urgent / High / Not Urgent. Project-priority tasks live on the Kanban tab, not here.

Columns

Data Task · Assignee · Due Date · Hard? · Time Estimate · Priority · Project · Status · Business · Recurring · Actions

What you can do

  • User Click any cell to inline-edit. Saves on blur.
  • User Click anywhere on a row (outside an edit cell) to open the drawer
  • User Filter by any column header — assignee, due, priority, project, business, recurring, status, time estimate
  • User Bulk select with checkboxes → reassign / reschedule / mark complete / delete in one go
  • User Sort by clicking column headers (default: due date then priority)

Automations fired here

TriggerWhat happens
Change Status to CompletedAuto Stamps Completion Date. Slack DM to every collaborator (except you). If recurring → roll the due date by the cadence and flip back to Upcoming.
Change Due DateAuto Status re-derives instantly (Overdue / Today / Upcoming). Patched back to Airtable.
Change AssigneeSlack DM to new assignee. Auto The actor (whoever clicked) and the previous assignee both become collaborators.
Pick a ProjectRule Priority flips to "Project". Business inherits from project. Project's collaborators merged in. The drawer's Priority + Business dropdowns update in real-time.
Any inline edit succeedsAuto Team filter counts at the top + KPI tiles re-render to match

5 Tab: Kanban

For: planning project work week-by-week. Only Project-priority tasks appear here.

Three view modes

ModeShowsDrag drops to
4 Weeks (default)Rolling 4 weeks from this MondayMonday of that week
12 WeeksRolling 12 weeks (horizontal scroll)Monday of that week
12 MonthsCalendar months from this month1st of that month (or today if same month)

The Overdue column

If any open Project task has a due date before the visible window, a red-bordered Overdue column auto-appears at the front. Drop a card onto a week → moves it there. Disappears when nothing is overdue.

The "leave my plan alone" rule

Project tasks pinned to future weeks are immune to the My Day auto-scheduler. Once you drop a Project task onto Week 3 of the Kanban, the auto-scheduler will not pull it back into Week 1 — even if you have the capacity. Urgent / High / Not Urgent tasks are still movable.

6 Tab: Projects

For: seeing how the strategic projects are progressing.

What each card shows

  • Project name + business
  • KPI progress bar — current value vs target
  • Linked tasks (active count + overdue)
  • Owner
  • Click to expand → details + auto-opens the KPI drill-down

The KPI drill-down

For projects with computed KPIs, the drill-down has different shapes depending on what the compute returns:

KPI kindDrill-down showsExample
Revenue / costThree cards (Revenue / Costs / Cushion) + transaction tables, plus per-month pillsOperating Cushion, MRR
Task completionThree cards (Completed / Outstanding / Total) + tables of those task namesWeb App module completion %

Compute logic is hand-written JS stored in each project's KPI Compute Code field on Airtable. The Leadership Dashboard runs the compute and writes the result back as JSON in KPI Detail JSON. Task OS just reads what's already been computed — no compute happens here.

7 Tab: Capacity

For: who has the most on their plate this week. Each team member shows allocated hours per day for the next 14 days.

Configurable daily cap (default 6 hours) per person via localStorage. Coloured red when over capacity, amber when 80–100%, green below.

8 Tab: Recurring

For: seeing every task with a cadence (Daily, Weekly, Fortnightly, Monthly, Quarterly, Bi-Annually, Annually). Grouped by person and frequency.

Option A — Single Rolling Record: we don't spawn a new record each cycle. Instead, the same task record advances its due date when you mark it Complete. A separate Task Completions log records each cycle for productivity reporting. This means deleting a recurring task is permanent — no phantom respawns.

Full lifecycle is in section 12.

9 Tab: Contractor Tasks

For: Gary, Rob, and Roy — the maintenance team. Tabbed switcher between the three of them.

How it differs from regular tasks

AspectRegular taskContractor task
Due dateRequiredNone — just a Created Date
StatusDerived from due dateAlways Upcoming until Completed
Sort orderBy due date then priorityBy Priority Level then oldest Created Date
Grouped byNothing in the gridProperty (gradient sage card per property)
Identified by(any task)Maintenance Ticket = TRUE on Airtable

10 Automation: Status derivation

The Status field is derived from the due date for almost every task. It's not something you usually set manually.

flowchart TD
  A[Task in scope]:::data --> B{Stored status
= Completed
or Approval?}:::rule B -->|Yes| C[Keep stored status]:::auto B -->|No| D{Maintenance ticket?}:::rule D -->|Yes| E[Force Upcoming]:::auto D -->|No| F{Has due date?}:::rule F -->|No| G[Upcoming]:::auto F -->|Yes| H{Due < today?}:::rule H -->|Yes| I[Overdue]:::auto H -->|No| J{Due = today?}:::rule J -->|Yes| K[Today]:::auto J -->|No| L[Upcoming]:::auto classDef rule fill:#FEF3C7,stroke:#C6A15B,color:#92400e classDef auto fill:#DDE8DF,stroke:#2C6E49,color:#14532d classDef data fill:#E5E8E1,stroke:#5A6660,color:#1C2422

How deriveTaskStatus decides what status to show

Why derived? Due dates roll past on their own — Airtable wouldn't update the status without an automation. Computing on the client every render means the grid always shows the truth, even if Airtable's stored value is stale.

When you change a due date inline, the new status is also patched back to Airtable so downstream consumers (other automations, the dashboard, exports) see the same value. The Sync popover surfaces drift here as a "stale statuses" count with a one-click "Reconcile all" button.

11 Automation: Auto-scheduler

The "Auto-Schedule" button on My Day re-arranges your tasks across the next ~14 days, respecting calendar events, routine blocks, and capacity.

flowchart TD
  A[Click Auto-Schedule]:::user --> B[Fetch calendar + routines]:::data
  B --> C[Compute free slots per day]:::auto
  C --> D[Walk tasks priority-first]:::auto
  D --> E{Hard deadline?}:::rule
  E -->|Yes| F[Skip — never moved]:::auto
  E -->|No| G{Project priority
past Sunday?}:::rule G -->|Yes| H[Skip — Kanban-pinned]:::auto G -->|No| I{Due > 14 days?}:::rule I -->|Yes| J[Skip — far future]:::auto I -->|No| K[Place in next free slot
within daily cap]:::auto classDef user fill:#DBE5F5,stroke:#5A86CF,color:#1e3a8a classDef rule fill:#FEF3C7,stroke:#C6A15B,color:#92400e classDef auto fill:#DDE8DF,stroke:#2C6E49,color:#14532d classDef data fill:#E5E8E1,stroke:#5A6660,color:#1C2422

Order of checks the scheduler runs against each task

The four exclusions, in plain English

  1. Hard deadline — never moves. If you flagged it immovable, the scheduler reserves capacity on its existing day and walks past.
  2. Project past this week — never pulled forward. If you put a Project task on Kanban Week 3, the scheduler respects that — you planned it deliberately.
  3. Far future (>14 days) — left alone. If you intentionally pushed something out, don't pull it back.
  4. Within the horizon, no flags — fair game. Scheduler places it in the next free slot that has capacity.

For Kevin specifically: on dashboard load, overdue tasks (excluding hard-deadline + project-future) get a one-shot pull-forward to today. Other team members keep their overdue counts visible for accountability.

12 Automation: Slack notifications

Four event types fire DMs via the slack-notify Cloudflare Worker.

TriggerRecipientDM readsSkipped when
Task assigned (created with assignee) Assignee "Creator assigned a task to you" Self-assignment
Task reassigned New assignee "Actor reassigned to you" Reassign to same person, or to actor
Task completed Every collaborator (except completer) "Completer completed a task you collaborate on" No collaborators, or completer is the only one
Comment added Every collaborator + assignee (except commenter) "Author left a comment" + the comment quoted No other collaborators
flowchart LR
  A[Web app event]:::user --> B[POST to Cloudflare Worker]:::auto
  B --> C[Worker: lookup
email → Slack user ID]:::auto C --> D{Found?}:::rule D -->|No| E[Return 404 — log to console]:::auto D -->|Yes| F[chat.postMessage]:::slack F --> G[DM lands in Slack]:::slack classDef user fill:#DBE5F5,stroke:#5A86CF,color:#1e3a8a classDef rule fill:#FEF3C7,stroke:#C6A15B,color:#92400e classDef auto fill:#DDE8DF,stroke:#2C6E49,color:#14532d classDef slack fill:#E1ECF4,stroke:#4A154B,color:#4A154B

From button click to Slack DM in < 2 seconds

The fail-safes

  • 📨 Resend Slack button on the drawer — manually re-fires the assignment DM. Uses the task's stored Created By Email as the actor name (falls back to current user, then "(unknown)").
  • Sync popover diagnostic panel — "Send test DM" picks a member and sends a test ping. "Check all recipients" runs a lookup-only check across the whole TEAM with no DMs sent.
  • Per-member slackEmail override — for people whose Airtable email differs from Slack (Gary). Translation happens on the way to the worker.
  • Fire-and-forget — Slack failures never block the user's save. Errors log to browser console + Cloudflare Worker logs.

13 Automation: Collaborator cascades

Three sources contribute to a task's collaborator list. They merge additively, deduplicated by email.

SourceTriggers whenAdds
Project inheritanceTask gets a project linkEvery member listed on that project's Project Collaborators field
Creator-as-collaboratorTask is created and assignee ≠ creatorThe creator (current user)
Reassigner-as-collaboratorAn existing task's assignee changes (and actor ≠ new assignee, ≠ already on list)The actor (whoever clicked the dropdown)
Why it matters: the completed Slack DM goes to every collaborator. So if Mica creates a task for Erica, Mica is automatically added → Mica gets the completion DM when Erica finishes. No manual collaborator management needed.

The Sync popover's drift check verifies the collaborator list locally vs Airtable for every active task — surfaces anywhere a cascade silently dropped.

14 Automation: Recurring rolling

Recurring tasks use the single rolling record model. One Airtable record per recurring task — its due date advances on completion.

flowchart TD
  A[Recurring task with cadence]:::data --> B[User marks Completed]:::user
  B --> C[Log completion to Task Completions table]:::auto
  C --> D[Roll due date forward by cadence]:::auto
  D --> E[Flip status back to Upcoming]:::auto
  E --> F[Same record continues to live]:::auto
  classDef user fill:#DBE5F5,stroke:#5A86CF,color:#1e3a8a
  classDef auto fill:#DDE8DF,stroke:#2C6E49,color:#14532d
  classDef data fill:#E5E8E1,stroke:#5A6660,color:#1C2422
        

Option A: one record forever, with an immutable completion log

Why this model?

  • Clean delete semantics — deleting a recurring task is permanent. No phantom respawn from auto-spawn logic.
  • Permanent productivity record — every cycle's completion is logged to the Task Completions table, independent of the live task.
  • Natural capacity projection — each task = one row, makes capacity calculation simple.

15 Automation: KPI computation

Each Project record has two KPI fields wired:

FieldTypePurpose
KPI Compute CodemultilineTextHand-written JS function body. Receives ctx with transactions / costs / tasks / project / today + helpers. Returns a number or an object with value + detail.
KPI Detail JSONmultilineTextMost recent compute result, written by the Leadership Dashboard. Capped at ~95KB — long transaction lists trim progressively.

Where compute runs

Leadership Dashboard

Loads. Fetches transactions + tasks. Builds ctx. Runs every project's compute code in a sandbox.

Result PATCHed

Writes kpiCurrent + kpiDetailJson back to the Project record on Airtable.

Task OS reads

Projects tab and Strategic KPIs section parse the JSON and render. No compute on this side.

Three KPI shapes currently live:

  • Operating Cushion (Real Estate) — Revenue minus Fixed Costs, rolling 31 days + monthly breakdown
  • MRR (Operations Director) — Sum of Fixed Income transactions, monthly breakdown
  • Task Completion % (Web App project) — Linked tasks completed / total × 100

16 Automation: Sync & health check

The green ✓ Saved pill in the top-right opens a popover with everything you need to know about save state and data integrity.

What it monitors

SectionTells you
Save statePending / OK / Failed counts for the current session
Drift detection (Check Sync button)Tasks where local state ≠ Airtable. Compares name, status, priority, due date, description, collaborators, Created By Email.
Stale statusesTasks where derived status ≠ Airtable's stored status. One-click "Reconcile all" to backfill at 5 req/s.
Missing creatorsActive tasks without a Created By Email. One-click "Backfill with my email" to stamp the current user.
Slack diagnosticTest DM to a single member, or batch lookup of every team member with no DMs sent (lookup-only mode).
Recent savesLast 50 field-level edits with status. Persists across reloads via localStorage.
Drift ≠ bug. The most common drift signal is "stale statuses" — Airtable holding an out-of-date value because the date rolled past without a touch. The Reconcile button isn't fixing data corruption; it's just propagating client-derived truth to the server.

17 Where AI helps

AI calls are limited to deliberate, scoped use cases — never a global "do my work" loop.

WhereModelWhat it doesLives in
Strategy → Projects pushAI SonnetExtracts discrete tasks from each Monthly Stepping Stone descriptionos/strategy/strategy.js
KPI compute generationAI Sonnet (manual)Drafts JS compute bodies. Stored in Airtable, runs sandboxed in dashboard.Hand-written, not in-app wizard
Reconciliation suggestionsAI SonnetSuggests Chart of Accounts categories for unreconciled transactionsReconciliation skill

All AI calls go through claude-proxy.kevinbrittain.workers.dev — Cloudflare Worker that holds the Anthropic API key server-side.

18 The data model

flowchart LR
  T[Tasks]:::data
  P[Projects]:::data
  B[Businesses]:::data
  TM[Team Members]:::data
  C[Task Completions]:::data
  TX[Transactions]:::data
  T -->|Assignee| TM
  T -->|Collaborators| TM
  T -->|Project link| P
  T -->|Business link| B
  T -->|Created By Email| TM
  P -->|Project Collaborators| TM
  P -->|Business| B
  T -->|On complete, log| C
  P -->|KPI compute reads| TX
  classDef data fill:#E5E8E1,stroke:#5A6660,color:#1C2422
        

How tables relate. Everything written by the web app PATCHes to Airtable directly.

Identity flow

On dashboard load you pick your identity ("Who are you?" overlay). That sets currentUser = name + email + key. Stored in localStorage so it sticks across reloads. Used everywhere the app needs to know "who is doing this": new task creator, comment author, complete actor, Slack DM sender, etc.

19 Glossary

Active task
Any task whose status isn't Completed and whose Some Day flag isn't set. The default filter for almost every list in the app.
Assignee
The single person responsible for completing a task. Stored as an Airtable singleCollaborator field. Changing this fires a Slack reassignment DM.
Cadence
The repeat interval on a recurring task: Daily, Weekly, Fortnightly, Monthly, Quarterly, Bi-Annually, Annually.
Collaborator
Anyone CC'd on a task — they get the completion + comment DMs. Auto-populated by the cascades in section 13. Distinct from Assignee.
Created By Email
Plain-text field stamped on every web-app-created task with the creator's email. Survives identity switching, app upgrades, localStorage clears. Not set on tasks created in Airtable's native UI.
Hard deadline
A task flag that immobilises it. The auto-scheduler will not move a hard-deadline task in either direction.
KPI Compute Code
Hand-written JavaScript function body stored on a Project record. Runs sandboxed in the Leadership Dashboard's KPI engine to compute the project's current KPI value.
Maintenance Ticket
Boolean flag on a task that marks it as a contractor job. Tasks with this flag appear on the Contractor Tasks tab and are sorted differently (priority + age, not due date).
Option A (recurring)
The single-rolling-record model for recurring tasks: one record per task, due date advances on completion, completions logged separately. Replaces older auto-spawn-on-complete logic.
Pull-in horizon
The 14-day window from today within which the auto-scheduler is allowed to move tasks forward. Past this, tasks are left alone.
Sync drift
A mismatch between local state and Airtable that the Sync popover surfaces. Most commonly stale statuses; rarely a real save failure.
currentUser
The identity selected at login. Used as the actor for Slack DMs, the value stamped into Created By Email, the collaborator added by reassign cascades, and the default assignee for inline-add.