Files
commitea/docs/decisions.md
Croissant Le Doux 9920634e74 docs: settle open design items + dogfood backlog
Resolve the five design-session open items from PLAN.md:
- decisions.md: soft write-path, poll-only sync (NAT), lognormal
  cold-start priors, purity test binds the SQLite cache
- pm-state.md: sidecar layout + directive/capacity/calibration
  schemas + lifecycle inference table
- agent-tools.md: query_project read tool + three write tools

Also gitignore .env.* (protect the gitea PAT) and record the P0
actual: 10 labels, 5 milestones, 34 tracer-bullet issues + 51
dependencies filed on christian/commitea as the first managed project.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-08 11:30:23 -04:00

74 lines
3.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Settled design decisions
Resolves the "Open items for design session" in [PLAN.md](./PLAN.md). Dated
2026-07-08. Companion docs: [pm-state.md](./pm-state.md) (sidecar formats),
[agent-tools.md](./agent-tools.md) (tool schemas).
## D1 — Write path is soft, split by semantics
Chat (Reginald) is the write path for **PM-semantic** mutations; gitea-native
content stays directly editable.
- **Through the agent** — estimates (`est/*`), priority (`p/*`),
`deadline/hard`, milestone assignment, dependency edits, and directives.
Additive ops act directly; destructive ops go propose-approve (Dialog or the
consequence diff on the Directives screen).
- **Direct, reconciled** — issue title/description, comments, assignees. Edit
them in the CommiTea UI ("composer writes to gitea, as you") or in the gitea
web UI; reconcile absorbs out-of-band edits because **gitea is the source of
truth** for intent. The agent observes changes on the next reconcile and may
object in standup, but never blocks them.
Rejected: strict (every write through chat). Hostile to quick edits and fights
the reconcile-from-gitea model — an edit made in gitea's own web UI would be
un-representable.
## D2 — Sync is poll + reconcile, no live webhooks in v1
`gitea.stephenmann.io` is remote and the desktop app sits behind NAT, so the
server cannot POST to a localhost webhook. v1:
- **Reconcile on launch** — full read of the work repo(s) + `pm-state` repo into
the local SQLite cache.
- **Light poll while running** — `since`/conditional-request poll of issues and
the issue timeline (target 3060 s cadence; visible < 2 s is a webhook-era
goal, relaxed to the poll interval for v1).
- The change-source is an **interface** (`ChangeSource`) with a polling
implementation; a webhook implementation can plug in later for a LAN /
self-hosted / tunnelled instance without touching the reconcile core.
Rejected now: reachability-detection hybrid (moving parts, cleanup-on-quit),
outbound tunnel (runtime dependency + public ingress). Both remain future
options behind the same interface.
## D3 — Cold-start forecasts use lognormal per-bucket priors
Before the team has n 20 closed issues with estimates, Monte Carlo samples a
**lognormal** actual-duration distribution per estimate bucket
(`1d/2d/3d/5d/8d`), with a pessimism-skewed median (actuals run long). The
priors live in code (`@commitea/core`), not in a data file. At n 20 the
scheduler switches to the team's own empirical fit (see calibration model in
[pm-state.md](./pm-state.md)); `byLabel` / `byPerson` bias terms layer on once
their own sample sizes clear a floor.
Rejected: uniform pessimism multiplier (`actual = est × U[1.3, 2.0]`) cruder,
dishonest tails, no path to per-bucket calibration.
## D4 — Purity test applies to the SQLite cache, not the pm-state repo
The plan's invariant *delete the sidecar → resync → no truth lost* is about
the **local SQLite cache**, which is a rebuildable index over two durable
sources:
- **Work repo(s) in gitea** human-authored intent (issues, milestones + due
dates, dependencies, assignees, labels, comments).
- **`pm-state` repo in gitea** the sidecar's own durable truth that is *not*
regenerable from the work repo: directive log, capacity config, charter, and
the (cached-but-committed) calibration model.
Delete SQLite rebuild from both repos nothing lost. The `pm-state` repo is
never the thing you delete; it is versioned and backed up in gitea like any
other repo. Regenerable state (issue mirror, inferred lifecycle timestamps,
Monte Carlo forecasts, focus snapshot) lives in SQLite only and is recomputed on
rebuild. See [pm-state.md](./pm-state.md) for the file/table split.