120 lines
6.2 KiB
Markdown
120 lines
6.2 KiB
Markdown
# Plan: The work board surface
|
|
|
|
**The decision V-431 asked for. Written 04-08-2026.**
|
|
|
|
**Verdict: build it, in a smaller shape than the task imagined.** The board is worth
|
|
moving out of the file. The intake form belongs on the `/tasks` page, not on the voice
|
|
path. The argument is not built, now or later.
|
|
|
|
## Why it is worth building
|
|
|
|
The reason is the one the task gives and it holds: company rules forbid pointing Claude
|
|
at work repos, and Maven is the one assistant on the box that work material may reach.
|
|
No telemetry, no cloud model, no third-party account. That is not a preference here, it
|
|
is the whole permission.
|
|
|
|
The build is also small, because most of it landed already:
|
|
|
|
| Piece | Where | State |
|
|
|---|---|---|
|
|
| task rows, dedupe, status lifecycle | `internal/store/migrations.go:149` and migration #15 | done |
|
|
| capture from speech, urgency stripped | `router.ParseTaskCapture`, `router.TaskCaptureGrammar` | done |
|
|
| recite the list on request | `router.IsTaskListQuery` | done |
|
|
| a page to read and change the board | `/tasks` in `cmd/mavweb` | done |
|
|
| counting a shape without judging it | `internal/memory/behavior.go` | done, as precedent |
|
|
| a proposal he reads when he chooses | `/routines`, the proposed-routine queue | done, as precedent |
|
|
|
|
`tasks` already carries `status` (candidate, open, done, dropped), `due_ts`, `weight`,
|
|
`source`, `evidence`, `ext_id` and `resolved_by`. Three things are missing. It has no
|
|
definition of done and no blocked-on. There is no way to edit a task after capture:
|
|
`SetTaskStatus` moves the status and nothing writes text, date or weight again. And
|
|
there is no grouping he controls, because order is computed by `tasks.Rank` alone.
|
|
|
|
## Where the form lives, and why not voice
|
|
|
|
The task asks the form to refuse a capture with no definition of done. That refusal
|
|
cannot live on the voice path, for two reasons.
|
|
|
|
**The parked-state mechanism is binary.** `resolveConfirm` in `cmd/mavend/confirm.go`
|
|
answers yes or no against a slot with a 90-second life. Filling four fields over four
|
|
turns is slot filling, which is a different mechanism and a new one. Nothing in the
|
|
daemon does it today.
|
|
|
|
**The definition of done is the worst possible field to dictate.** It is the one string
|
|
that has to be exact, because its whole purpose is to be unarguable later. Whisper
|
|
transcribing a sentence of Russian work vocabulary is where exactness goes to die, and
|
|
the capture path already had to strip a question mark that whisper invented.
|
|
|
|
So: voice captures a line and recites the list. The page is where a line becomes an
|
|
item with a definition of done, a blocked-on and a date. A captured line lands as
|
|
`candidate` and stays there until it is filled in, which is what `candidate` was for.
|
|
|
|
The refusal the task wants survives, moved: the page will not promote a candidate to
|
|
`open` without a definition of done, the same way `ParseTaskCapture` will not file a
|
|
marker with nothing after it. And the field must close on either outcome, so "it already
|
|
works" counts as complete. A definition of done that only one result satisfies is a wish.
|
|
|
|
## Does the stage-0 trick stretch
|
|
|
|
The task asks this before any shape is committed to. It was checked. The answer is
|
|
partly.
|
|
|
|
`TaskCaptureGrammar` matches every utterance and lets `ParseTaskCapture` decide inside
|
|
`Build`, keeping the intent at `note` and leaving the frozen seven-intent contract alone.
|
|
That trick stretches to **recite** and to **status change**: both are a marker plus a
|
|
referent, both are a lookup, and a status change is a small closed verb set over a list
|
|
he can see. It does not stretch to **intake**, because intake is not one utterance, and
|
|
it does not need to, because intake moved to the page.
|
|
|
|
One cost to name. Each such grammar matches everything and runs its parser on every
|
|
turn, ahead of the resident model. Two more of them is fine. A dozen would make stage 0
|
|
a second router with no evaluation behind it, and at that point the frozen enum is the
|
|
smaller problem.
|
|
|
|
## What is not built: the argument
|
|
|
|
Not now and not later behind a flag. The task is right about why, and
|
|
`internal/memory/behavior.go` already argued it for habits: a 1.7B asked whether evidence
|
|
proves anything will agree fluently and launder a guess into a decision. A wrong claim
|
|
about his work, stated confidently, is the most expensive kind of wrong Maven can be.
|
|
|
|
The line is the same line behaviour memory drew. She may **count**:
|
|
|
|
- no state change in eleven days
|
|
- blocked on a person, with no date
|
|
- four of nine waiting on two people
|
|
|
|
Those are queries over rows. She may not assess whether a build proves anything, whether
|
|
a blocker is real, or whether a task should be dropped.
|
|
|
|
## Persona
|
|
|
|
A progress tracker is a nag by default, and "not a nag" is hard. The line is already
|
|
drawn twice in the codebase and it is drawn the same way here:
|
|
|
|
- A date he set becomes a reminder. He set it, so it is not her raising it.
|
|
- A stall becomes a proposal he reads when he chooses, on a page, like `/routines`.
|
|
- Ask what is on the board and she recites. She never opens with it.
|
|
|
|
The day plan is the place to watch. `tickLoop.dayPlan` reads calendar events, pending
|
|
reminders and checklist facts, and it does not read tasks. Adding the board to the
|
|
morning nudge is exactly the move that turns this into a nag, so the board goes on the
|
|
page and into the answer when asked, and not into the unprompted morning message.
|
|
|
|
## The build, as tasks
|
|
|
|
1. Two columns on `tasks`: definition of done, and blocked-on. Blocked-on resolves
|
|
through Nexus like any other person reference, because identity lives in Nexus.
|
|
2. An edit path. Today a task is write-once except for its status, so the form has
|
|
nothing to save into.
|
|
3. `/tasks` grows the form: promote candidate to open only with a definition of done,
|
|
set a date, set blocked-on. A date set here writes a reminder.
|
|
4. A status-change grammar at stage 0, following `TaskCaptureGrammar`.
|
|
5. Counted stall shapes on `/tasks`, phrased as counts. No assessment.
|
|
|
|
Note for whoever picks up 3: `/tasks` accepts its POST without the step-up gate, while
|
|
`/routines` and `/tools` require a passkey. That was deliberate for capture. Adding an
|
|
edit path is the moment to re-argue it, not to inherit it silently.
|
|
|
|
Each is separable and each is worth stopping after.
|