docs(spec): move the git observer and cadence math into BIT
Brian caught that the spec stated a frame and then violated it. The test is 'does it produce or derive facts -> BIT; does it require knowing Brian -> Lyra.' The git observer produces facts and knows nothing about Brian; cadence health derives from BIT's own time_logs and goal fields. Both belong in BIT. Putting them in Lyra would have made BIT's data true only while Lyra was running -- the exact coupling the separable frame exists to prevent. It also makes BIT better standalone: auto-logged time plus cadence on the project cards, which today show only a creation date. Restructured into Part A (BIT, deterministic, no LLM) and Part B (Lyra, the pick and the surfacing). Observer ships in BIT's repo but runs on the host and POSTs over HTTP, so repos need no volume mounts.
This commit is contained in:
@@ -1,9 +1,9 @@
|
|||||||
# Project cadence — Lyra as BIT's observer and picker
|
# Project cadence — BIT observes, Lyra picks
|
||||||
|
|
||||||
- **Date:** 2026-09-02
|
- **Date:** 2026-09-02
|
||||||
- **Status:** Spec — approved to build
|
- **Status:** Spec — approved to build
|
||||||
- **Branch:** `feat/project-cadence`
|
- **Branch:** `feat/project-cadence`
|
||||||
- **Second repo:** `~/break-it-down` (BIT) — needs its own branch work, see Phase 0
|
- **Two repos, both worked on:** `~/break-it-down` (BIT) — Part A; `project-lyra` — Part B
|
||||||
- **Related:** `lyra/thoughts.py` (surfacing machinery), `docs/ROADMAP.md`
|
- **Related:** `lyra/thoughts.py` (surfacing machinery), `docs/ROADMAP.md`
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -56,10 +56,21 @@ Mirrors the frame already committed to for the pokerlog:
|
|||||||
|
|
||||||
> **BIT is the system of record. Lyra is a client of it, not its container.**
|
> **BIT is the system of record. Lyra is a client of it, not its container.**
|
||||||
|
|
||||||
|
**The test that decides where any piece of work goes:**
|
||||||
|
|
||||||
|
> **Does it produce or derive facts? → BIT. Does it require knowing Brian? → Lyra.**
|
||||||
|
|
||||||
| | Owns | Rationale |
|
| | Owns | Rationale |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| **BIT** | Facts: projects, tasks, blockers, estimates, **time logs** | Standalone value. Human-editable UI. Works with Lyra dead. |
|
| **BIT** | Facts and everything derived from them: projects, tasks, blockers, estimates, **time logs**, **the git observer**, **cadence health** | Standalone value. Human-editable UI. Works with Lyra dead — and the observer is what keeps that true. |
|
||||||
| **Lyra** | The relationship: cadence config, nudge state, dormancy, **the pick** | None of this is a fact about the garage. It's her state *about* the garage. |
|
| **Lyra** | The relationship: **the pick**, nudge state, backoff, conversational logging, decomposition offers | Every one of these needs to know it's 9pm, that he has 20 minutes, that he was warm on seismo-relay yesterday. |
|
||||||
|
|
||||||
|
An earlier draft of this spec put the git observer and cadence math in Lyra. That
|
||||||
|
was wrong and violated the frame above: **the observer produces facts and knows
|
||||||
|
nothing about Brian.** Worse, it would have made BIT's data true only while Lyra
|
||||||
|
was running — reintroducing exactly the coupling the separable frame exists to
|
||||||
|
prevent. Auto-logging and cadence health also make BIT meaningfully better as a
|
||||||
|
standalone product, which is the justification for keeping it separable at all.
|
||||||
|
|
||||||
Same distinction as poker's *ledger* (facts) vs *relationship* (her memory of the
|
Same distinction as poker's *ledger* (facts) vs *relationship* (her memory of the
|
||||||
sessions).
|
sessions).
|
||||||
@@ -161,45 +172,48 @@ branch has both halves. `main` (Feb 17) has neither.
|
|||||||
|
|
||||||
```
|
```
|
||||||
┌────────────────────────┐
|
┌────────────────────────┐
|
||||||
│ git repos on disk │
|
│ git repos on host │
|
||||||
│ (7 of 8 BIT projects) │
|
│ (7 of 8 BIT projects) │
|
||||||
└───────────┬────────────┘
|
└───────────┬────────────┘
|
||||||
│ walk history, group by local day
|
│ git_observer.py — BIT's code, runs on the HOST
|
||||||
▼
|
│ walk history, group by local day, no LLM
|
||||||
┌────────────────────────┐ ┌──────────────────────────────┐
|
|
||||||
│ lyra/gitobserver.py │ │ chat: "spent an hour in the │
|
|
||||||
│ deterministic, no LLM │ │ garage" → log_work tool │
|
|
||||||
└───────────┬────────────┘ └──────────────┬───────────────┘
|
|
||||||
│ │
|
|
||||||
└──────────────┬─────────────────────┘
|
|
||||||
▼ POST /api/tasks/{id}/time-logs
|
▼ POST /api/tasks/{id}/time-logs
|
||||||
┌───────────────────────────┐
|
┌──────────────────────────────────────────────────┐
|
||||||
│ BIT (facts) │
|
│ BIT — facts, and everything derived from them │
|
||||||
│ projects · tasks · blockers│
|
│ projects · tasks · blockers · estimates │
|
||||||
│ time_logs · goals │
|
│ time_logs · goals · git_sessions │
|
||||||
└───────────┬───────────────┘
|
│ GET /api/actionable │
|
||||||
│ GET /actionable, /time-summary, /tasks
|
│ GET /api/projects/health (cadence, new) │
|
||||||
|
│ cadence health rendered on the project cards │
|
||||||
|
└────────────────────┬─────────────────────────────┘
|
||||||
|
│ HTTP
|
||||||
▼
|
▼
|
||||||
┌───────────────────────────┐
|
┌──────────────────────────────────────────────────┐
|
||||||
│ lyra/projects.py │
|
│ lyra/bit.py — thin client. No cadence math here. │
|
||||||
│ BIT client + cadence math │
|
└────────────────────┬─────────────────────────────┘
|
||||||
│ (pure, no LLM) │
|
┌───────────┴───────────┐
|
||||||
└───────────┬───────────────┘
|
▼ ▼
|
||||||
│
|
lyra/tools.py lyra/projects.py
|
||||||
┌──────────────┼──────────────────┐
|
log_work, pick_next, nudge state, ignore counts,
|
||||||
▼ ▼ ▼
|
break_down, status backoff, quiet hours
|
||||||
lyra/tools.py cadence state thoughts.py surfacing
|
▲ │
|
||||||
(she can talk (Lyra's DB: (salience → surface →
|
│ ▼
|
||||||
about it) goals, nudge ping → response,
|
chat: "spent an hour thoughts.py surfacing
|
||||||
state, dormancy) budget + backoff)
|
in the garage" (salience → surface →
|
||||||
|
ping → response)
|
||||||
```
|
```
|
||||||
|
|
||||||
**Data flow, one line:** git and chat write facts into BIT; Lyra reads BIT, computes
|
**Data flow, one line:** git and chat write facts into BIT; BIT derives cadence;
|
||||||
cadence, and decides whether and how to open her mouth.
|
Lyra reads BIT and decides whether, when, and how to open her mouth.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Phase 0 — BIT consolidation
|
# Part A — work in `~/break-it-down` (BIT)
|
||||||
|
|
||||||
|
Everything here is deterministic. **No LLM appears anywhere in Part A.** All of it
|
||||||
|
makes BIT better as a standalone product, independently of Lyra.
|
||||||
|
|
||||||
|
## A0 — consolidation and deploy
|
||||||
|
|
||||||
There is no production data. The 8 projects / 77 tasks on `10.0.0.40` were test
|
There is no production data. The 8 projects / 77 tasks on `10.0.0.40` were test
|
||||||
builds; a snapshot lives at `~/bit-seed-snapshot/` if any of it is worth reseeding
|
builds; a snapshot lives at `~/bit-seed-snapshot/` if any of it is worth reseeding
|
||||||
@@ -217,26 +231,28 @@ through the existing JSON import.
|
|||||||
5. Create the real projects. `Clean up march 26` becomes actual physical projects
|
5. Create the real projects. `Clean up march 26` becomes actual physical projects
|
||||||
(garage, music backup, spare closet).
|
(garage, music backup, spare closet).
|
||||||
|
|
||||||
**Exit criteria:** one BIT instance on this box serving blockers *and* time logs,
|
**Exit criteria:** one BIT instance on this box serving blockers *and* time logs.
|
||||||
reachable from Lyra.
|
|
||||||
|
|
||||||
---
|
## A1 — the git observer
|
||||||
|
|
||||||
## Phase 1 — the git observer
|
Ships **with BIT**, in BIT's repo. Deterministic Python, no model, no knowledge of
|
||||||
|
Brian — it produces facts, which is why it lives here.
|
||||||
|
|
||||||
`lyra/gitobserver.py`. **Deterministic. No LLM anywhere in this module** (principle 4),
|
**Deployment note:** BIT runs in Docker; the git repos live on the host. So the
|
||||||
which keeps the backfill reproducible and unit-testable.
|
observer runs **on the host** (cron or systemd timer) and POSTs to BIT's API like
|
||||||
|
any other client. That avoids volume-mounting every repo into the container while
|
||||||
|
keeping the code in BIT's repo where it belongs.
|
||||||
|
|
||||||
### Config
|
### Config
|
||||||
|
|
||||||
A repo↔project mapping in Lyra's config: local repo path → BIT project id.
|
A repo↔project mapping: local repo path → BIT project id. Stored in BIT (a small
|
||||||
Explicit, not auto-discovered — auto-discovery would guess wrong and pollute the
|
`observed_repos` table with a settings UI later, or config file for v1). Explicit,
|
||||||
ledger.
|
never auto-discovered — auto-discovery would guess wrong and pollute the ledger.
|
||||||
|
|
||||||
### Session derivation
|
### Session derivation
|
||||||
|
|
||||||
For each repo, group commits **by local calendar day** (Brian's configured
|
For each repo, group commits **by local calendar day** in Brian's timezone, not
|
||||||
timezone via `clock.py`, not UTC — a 11pm commit belongs to that evening).
|
UTC — an 11pm commit belongs to that evening.
|
||||||
|
|
||||||
For each day with commits:
|
For each day with commits:
|
||||||
|
|
||||||
@@ -245,11 +261,12 @@ For each day with commits:
|
|||||||
- `MIN_MINUTES = 15` — a single-commit day would otherwise be 0
|
- `MIN_MINUTES = 15` — a single-commit day would otherwise be 0
|
||||||
- `MAX_MINUTES = 240` — a 9am and an 11pm commit is not a 14-hour session
|
- `MAX_MINUTES = 240` — a 9am and an 11pm commit is not a 14-hour session
|
||||||
|
|
||||||
These are heuristics and must be **config, not constants**, and documented as
|
These are heuristics. They must be **config, not constants**, and documented as
|
||||||
estimates in the spec and in the code.
|
estimates in both the spec and the code.
|
||||||
|
|
||||||
- `session_type = "git"` — never `'manual'` or `'pomodoro'`. Estimated time must
|
- `session_type = "git"` — never `manual` or `pomodoro`. Estimated time must never
|
||||||
never masquerade as measured time.
|
masquerade as measured time. The field is a free-text `String(50)`, so this is
|
||||||
|
**not a schema change**.
|
||||||
- `note` = commit count and short SHA range, for traceability.
|
- `note` = commit count and short SHA range, for traceability.
|
||||||
|
|
||||||
### Attribution
|
### Attribution
|
||||||
@@ -258,23 +275,19 @@ estimates in the spec and in the code.
|
|||||||
task. Two deterministic tiers:
|
task. Two deterministic tiers:
|
||||||
|
|
||||||
1. **Conventional-commit scope match.** `feat(persona): …` → match `persona`
|
1. **Conventional-commit scope match.** `feat(persona): …` → match `persona`
|
||||||
against task titles and tags in that project, case-insensitive substring. Plain
|
against task titles and tags in that project, case-insensitive substring.
|
||||||
string matching, no model.
|
Plain string matching, no model.
|
||||||
2. **Fallback:** a per-project `Unfiled work` task, created on demand.
|
2. **Fallback:** a per-project `Unfiled work` task, created on demand.
|
||||||
|
|
||||||
Attribution is a nice-to-have; **the totals are the point**. Attribution must never
|
Attribution is a nice-to-have; **the totals are the point**. It must never block or
|
||||||
block or fail a backfill. LLM-assisted attribution is explicitly deferred (see
|
fail a backfill. LLM-assisted attribution is explicitly deferred (see Non-goals).
|
||||||
Non-goals).
|
|
||||||
|
|
||||||
### Idempotency — the critical correctness property
|
### Idempotency — the critical correctness property
|
||||||
|
|
||||||
The observer runs repeatedly and must never double-log.
|
The observer runs repeatedly and must never double-log.
|
||||||
|
|
||||||
Lyra owns a `git_sessions` table: `(repo_path, local_date)` unique → `bit_time_log_id`,
|
A `git_sessions` table in BIT: `(repo_path, local_date)` unique → `time_log_id`,
|
||||||
`last_sha`. A day is logged only if that key is absent. This is idempotent by
|
`last_sha`. A day is logged only if that key is absent. Idempotent by construction.
|
||||||
construction and survives BIT being reset — on a fresh BIT, clear the table and
|
|
||||||
re-backfill cleanly.
|
|
||||||
|
|
||||||
A re-run over a day that gained new commits **updates** the existing time log
|
A re-run over a day that gained new commits **updates** the existing time log
|
||||||
rather than adding a second one.
|
rather than adding a second one.
|
||||||
|
|
||||||
@@ -282,29 +295,18 @@ rather than adding a second one.
|
|||||||
|
|
||||||
One-shot run over history since 2026-03-21 (or repo start). `project-lyra` alone
|
One-shot run over history since 2026-03-21 (or repo start). `project-lyra` alone
|
||||||
should produce ~30 sessions. **This is the emotional payload of the entire
|
should produce ~30 sessions. **This is the emotional payload of the entire
|
||||||
project** — the first time BIT is opened after this, it says "30 days worked since
|
project** — the first time BIT is opened afterwards it says "30 days worked since
|
||||||
March" instead of showing a tombstone.
|
March" instead of showing a tombstone.
|
||||||
|
|
||||||
### Non-code projects in v1
|
|
||||||
|
|
||||||
The git observer does nothing for the garage or the music collection. Those are
|
|
||||||
covered in v1 by **conversational logging**: "I spent an hour in the garage" →
|
|
||||||
`log_work` tool → a real `time_logs` row. Zero new infrastructure. Automated
|
|
||||||
observation of physical work is deferred past v1 (see Non-goals).
|
|
||||||
|
|
||||||
**Exit criteria:** BIT shows true history for every configured repo; re-running the
|
**Exit criteria:** BIT shows true history for every configured repo; re-running the
|
||||||
observer changes nothing.
|
observer changes nothing.
|
||||||
|
|
||||||
---
|
## A2 — cadence health
|
||||||
|
|
||||||
## Phase 2 — cadence
|
Derived from `time_logs` + `Project.weekly_hours_goal`, both of which are BIT's.
|
||||||
|
No knowledge of Brian required, so it belongs here rather than in Lyra.
|
||||||
|
|
||||||
`lyra/projects.py` — BIT HTTP client plus **pure cadence functions** (easy to test,
|
### States
|
||||||
no I/O).
|
|
||||||
|
|
||||||
### Health states
|
|
||||||
|
|
||||||
Computed from `time_logs` + `Project.weekly_hours_goal`:
|
|
||||||
|
|
||||||
- `on_cadence` — trailing-7-day minutes ≥ `weekly_hours_goal`
|
- `on_cadence` — trailing-7-day minutes ≥ `weekly_hours_goal`
|
||||||
- `drifting` — some activity in the window, below goal
|
- `drifting` — some activity in the window, below goal
|
||||||
@@ -314,41 +316,56 @@ Computed from `time_logs` + `Project.weekly_hours_goal`:
|
|||||||
`weekly_hours_goal` is nullable, so `untracked` is the common initial state and
|
`weekly_hours_goal` is nullable, so `untracked` is the common initial state and
|
||||||
must render sensibly.
|
must render sensibly.
|
||||||
|
|
||||||
### Lyra-side state
|
**Trap:** `weekly_hours_goal` and `total_hours_goal` are named *hours* but the
|
||||||
|
source comment says they store **minutes**. Do not multiply by 60.
|
||||||
|
|
||||||
A small table keyed by BIT project id: cadence target, last surfaced, ignore
|
### Surface it
|
||||||
count, dormancy, salience. **Not in BIT** — it's her state about the project, not
|
|
||||||
a fact about it.
|
- `GET /api/projects/health` — cadence state and accumulated time per project
|
||||||
|
- **Render it on the project cards.** They currently show `Created 3/20/2026` and
|
||||||
|
nothing about activity, which is precisely how the graveyard effect happens.
|
||||||
|
Last-touched plus cadence state plus total logged time turns that wall of dead
|
||||||
|
cards into a readable status board — and this is the payoff of A1 becoming
|
||||||
|
visible to a human without Lyra involved at all.
|
||||||
|
|
||||||
|
**Exit criteria:** opening BIT shows, at a glance, which projects are alive.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Phase 3 — Lyra tools
|
# Part B — work in `project-lyra`
|
||||||
|
|
||||||
Following the `lyra/tools.py` spec + dispatch pattern:
|
Everything here needs to know something about Brian. This is where the LLM lives,
|
||||||
|
and it is allowed to be flaky, because a missed nudge costs nothing.
|
||||||
|
|
||||||
- `projects_overview()` — every project with cadence health and accumulated time
|
## B1 — client and tools
|
||||||
|
|
||||||
|
- `lyra/bit.py` — thin HTTP client over BIT's API. **No cadence math**; BIT already
|
||||||
|
computed it. Degrades to a clear "BIT is down" message, never a stack trace into
|
||||||
|
her context and never a fabricated answer about project state.
|
||||||
|
- `lyra/tools.py` additions, following the existing spec + dispatch pattern:
|
||||||
|
- `projects_overview()` — every project with cadence health and logged time
|
||||||
- `project_status(name)` — detail, recent sessions, what's actionable
|
- `project_status(name)` — detail, recent sessions, what's actionable
|
||||||
- `log_work(project, task, minutes, note)` — conversational session logging
|
- `log_work(project, task, minutes, note)` — **conversational session logging**
|
||||||
- `pick_next(minutes_available)` — see Phase 4
|
- `pick_next(minutes_available)` — see B2
|
||||||
- `break_down(task_id)` — generate a subtask tree, push it through BIT's existing
|
- `break_down(task_id)` — generate a subtask tree, push it through BIT's
|
||||||
JSON import
|
existing JSON import
|
||||||
- `set_goal(project, weekly_hours)`
|
- `set_goal(project, weekly_hours)`, `set_dormant(project)`, `wake(project)`
|
||||||
- `set_dormant(project)` / `wake(project)`
|
|
||||||
|
|
||||||
---
|
**Conversational logging is how non-code projects get tracked in v1.** The git
|
||||||
|
observer does nothing for the garage or the music collection; "I spent an hour in
|
||||||
|
the garage" → `log_work` → a real `time_logs` row. Zero new infrastructure.
|
||||||
|
Automated observation of physical work is deferred past v1 (see Non-goals).
|
||||||
|
|
||||||
## Phase 4 — surfacing and the pick
|
## B2 — the pick
|
||||||
|
|
||||||
### The pick
|
|
||||||
|
|
||||||
The one place an LLM is genuinely required. Input: `/api/actionable`, minutes
|
The one place an LLM is genuinely required. Input: `/api/actionable`, minutes
|
||||||
available, recent sessions, cadence health, time of day. Output: **one task and one
|
available, recent sessions, cadence health, time of day. Output: **one task and one
|
||||||
sentence of why.** Not a list. A list is what BIT already does badly.
|
sentence of why.** Not a list — a list is what BIT already does badly, at 68 items.
|
||||||
|
|
||||||
### The decomposition trigger
|
### The decomposition trigger
|
||||||
|
|
||||||
Live data shows tasks like "Multi-user authentication — est 480", "Historical data
|
Live data shows tasks like "Multi-user authentication — est 480" and "Historical
|
||||||
tracking — 360". **You cannot start an eight-hour task**, and these sit in
|
data tracking — 360". **You cannot start an eight-hour task**, and these sit in
|
||||||
`/actionable` forever radiating "why bother."
|
`/actionable` forever radiating "why bother."
|
||||||
|
|
||||||
Rule: `estimated_minutes > DECOMPOSE_THRESHOLD` (default 60) means decomposition
|
Rule: `estimated_minutes > DECOMPOSE_THRESHOLD` (default 60) means decomposition
|
||||||
@@ -356,7 +373,7 @@ hasn't happened yet. When the best candidates are all oversized, Lyra offers to
|
|||||||
break one down instead of proposing it — closing the anti-perfectionism loop
|
break one down instead of proposing it — closing the anti-perfectionism loop
|
||||||
through `break_down`, using the JSON import that already exists for exactly this.
|
through `break_down`, using the JSON import that already exists for exactly this.
|
||||||
|
|
||||||
### Surfacing
|
## B3 — surfacing
|
||||||
|
|
||||||
Reuse `thoughts.py` machinery; **do not put projects in the `threads` table.** A
|
Reuse `thoughts.py` machinery; **do not put projects in the `threads` table.** A
|
||||||
thought is her interiority; a project is a fact about Brian's life. Conflating them
|
thought is her interiority; a project is a fact about Brian's life. Conflating them
|
||||||
@@ -364,6 +381,10 @@ pollutes both — her dream cycle would generate the garage as a thought, and th
|
|||||||
garage would appear in her self-narrative. Separate storage, shared
|
garage would appear in her self-narrative. Separate storage, shared
|
||||||
salience → surface → ping → response loop.
|
salience → surface → ping → response loop.
|
||||||
|
|
||||||
|
Lyra owns a small table keyed by BIT project id holding **nudge state only**: last
|
||||||
|
surfaced, ignore count, snooze, salience. Cadence itself is read from BIT, never
|
||||||
|
recomputed here.
|
||||||
|
|
||||||
**Channel priority:**
|
**Channel priority:**
|
||||||
|
|
||||||
1. **Conversation (default).** Next time Brian's talking to her anyway, she raises
|
1. **Conversation (default).** Next time Brian's talking to her anyway, she raises
|
||||||
@@ -433,28 +454,35 @@ every day life" is the stated goal and feature creep is the named enemy.
|
|||||||
|
|
||||||
## Testing
|
## Testing
|
||||||
|
|
||||||
Follows existing conventions (`tests/`, pytest, replay evals for LLM paths).
|
Split by repo, matching each one's existing conventions.
|
||||||
|
|
||||||
|
### In BIT (`pytest`, backend)
|
||||||
|
|
||||||
- **Git observer:** fixture repo built in a tmpdir with controlled commit
|
- **Git observer:** fixture repo built in a tmpdir with controlled commit
|
||||||
timestamps. Assert day grouping across timezone boundaries, MIN/MAX/padding
|
timestamps. Assert day grouping across timezone boundaries, MIN/MAX/padding
|
||||||
clamps, scope-match attribution, `Unfiled work` fallback, and — most
|
clamps, conventional-commit scope attribution, `Unfiled work` fallback, and —
|
||||||
importantly — **that a second run produces zero new time logs**.
|
most importantly — **that a second run produces zero new time logs**.
|
||||||
- **Cadence functions:** pure, table-driven. Boundary cases: no goal set, goal met
|
- **Cadence functions:** pure, table-driven. Boundary cases: no goal set, goal met
|
||||||
exactly, dormancy threshold ±1 day, zero sessions ever.
|
exactly, dormancy threshold ±1 day, zero sessions ever, and the
|
||||||
- **BIT client:** against a stub server. Include the `/tree` 404 case so a README
|
hours-named-but-minutes-valued goal fields.
|
||||||
regression can't silently break it.
|
- **`/api/projects/health`:** shape and states against a seeded DB.
|
||||||
|
|
||||||
|
### In `project-lyra` (`pytest`, existing `tests/`)
|
||||||
|
|
||||||
|
- **`lyra/bit.py`:** against a stub server. Include a 404 case so a BIT API change
|
||||||
|
can't silently break it, and assert graceful degradation when BIT is down.
|
||||||
|
- **Nudge state:** ignore counts, backoff to dormant, quiet hours, push budget.
|
||||||
|
Pure and deterministic — no model.
|
||||||
- **The pick and the surfacing copy:** replay eval, parameterized by
|
- **The pick and the surfacing copy:** replay eval, parameterized by
|
||||||
`EVAL_BACKEND`/`EVAL_MODEL`, matching the persona eval pattern. Assert it
|
`EVAL_BACKEND`/`EVAL_MODEL`, matching the persona eval pattern. Assert it
|
||||||
returns *one* task, and that it offers decomposition when candidates are
|
returns *one* task, and that it offers decomposition when candidates are
|
||||||
oversized.
|
oversized.
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Open questions
|
## Open questions
|
||||||
|
|
||||||
1. **Ports for BIT on this box.** `:3002/:8002` are free here; confirm at deploy.
|
1. **Ports for BIT on this box.** `:3002/:8002` are free here; confirm at deploy.
|
||||||
2. **Which of the 77 snapshotted tasks are worth reseeding**, versus starting the
|
2. **Which of the 77 snapshotted tasks are worth reseeding**, versus starting the
|
||||||
real projects clean. Brian's call during Phase 0.
|
real projects clean. Brian's call during A0.
|
||||||
3. **Whether `weekly_hours_goal` gets set per project at all in v1**, or whether
|
3. **Whether `weekly_hours_goal` gets set per project at all in v1**, or whether
|
||||||
`untracked` + days-since-last-session is enough to start. Leaning: ship without
|
`untracked` + days-since-last-session is enough to start. Leaning: ship without
|
||||||
goals, add them once real session data shows what a realistic cadence is.
|
goals, add them once real session data shows what a realistic cadence is.
|
||||||
|
|||||||
Reference in New Issue
Block a user