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

3.7 KiB
Raw Permalink Blame History

Settled design decisions

Resolves the "Open items for design session" in PLAN.md. Dated 2026-07-08. Companion docs: pm-state.md (sidecar formats), 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 runningsince/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); 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 for the file/table split.