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>
This commit is contained in:
119
docs/agent-tools.md
Normal file
119
docs/agent-tools.md
Normal file
@@ -0,0 +1,119 @@
|
||||
# Agent tools
|
||||
|
||||
Reginald gets **few, fat tools** so a small local model (gemma-4b class) can
|
||||
survive with one thing to reach for. One read tool, three write tools. All I/O
|
||||
is compact JSON; ticket data is fetched through tools, never copied into hot
|
||||
memory ([PLAN.md](./PLAN.md) memory layers).
|
||||
|
||||
Model routing (per PLAN.md): the read tool + prose/standup run on the small
|
||||
local model; `capture_work` decomposition and `record_directive` negotiation
|
||||
route to the big model.
|
||||
|
||||
## `query_project` (read)
|
||||
|
||||
The single read tool. A `view` enum selects the shape; `filters` narrows it. The
|
||||
scheduler's deterministic output backs every forecast field — the model never
|
||||
computes, it reports.
|
||||
|
||||
```jsonc
|
||||
query_project({
|
||||
view: "focus" | "issue" | "milestone" | "board" | "runway"
|
||||
| "calibration" | "directives" | "standup" | "search",
|
||||
filters?: {
|
||||
issueId?: number,
|
||||
milestoneId?: number,
|
||||
state?: "diagnosis" | "triage" | "steeping" | "in_review" | "done",
|
||||
assignee?: string, // gitea username
|
||||
label?: string,
|
||||
query?: string, // free text, for view:"search"
|
||||
limit?: number // default 20, max 100
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
View payloads (compact; forecasts always ranges, never point dates):
|
||||
|
||||
- **focus** — `{ now, next[], later[] }`, each `{ issue, title, rationale }`.
|
||||
- **issue** — intent (title, description, comments, assignee, labels) + derived
|
||||
(lifecycle timeline, per-issue forecast range, dependency ids, provenance).
|
||||
- **milestone** — `{ due, hard, stats, cone: {p10,p50,p80 dates}, issues[] }`.
|
||||
- **board** — issues grouped by the five lifecycle columns.
|
||||
- **runway** — per-milestone `{ due, band: {p50,p80}, slack }` + capacity list.
|
||||
- **calibration** — `{ n, coldStart, globalMultiplier, byLabelBias[], byPersonBias[] }`.
|
||||
- **directives** — pending consequence diff + recent ledger entries.
|
||||
- **standup** — drift report, per-person plan, stale blockers.
|
||||
- **search** — issues matching `query`.
|
||||
|
||||
## `capture_work` (write — big model)
|
||||
|
||||
Braindump → interview → proposed issue set. Returns a **proposal**, never files
|
||||
directly; the Capture screen's review tray edits it before `apply_changes` files
|
||||
it. Decomposition + estimate negotiation is the one place the big model earns its
|
||||
keep.
|
||||
|
||||
```jsonc
|
||||
capture_work({
|
||||
braindump: string,
|
||||
answers?: { question: string, answer: string }[] // interview turns so far
|
||||
})
|
||||
// → { needsMoreInfo?: string[], // follow-up questions; present as chips
|
||||
// proposal?: { issues: [{ title, body, estimate: EstimateLabel,
|
||||
// priority?: PriorityLabel, deps?: number[],
|
||||
// milestone?: number }],
|
||||
// consequence: string } } // one-line schedule impact
|
||||
```
|
||||
|
||||
## `apply_changes` (write — unified mutation)
|
||||
|
||||
Every mutation funnels here: filing captured issues, label/estimate/priority/
|
||||
milestone/dependency edits. Additive ops apply directly; **destructive ops
|
||||
require `approved: true`** (the caller obtains approval via the consequence
|
||||
diff / Dialog first — see [decisions.md](./decisions.md) D1). Batched so one call
|
||||
= one coherent change with one consequence.
|
||||
|
||||
```jsonc
|
||||
apply_changes({
|
||||
ops: [
|
||||
{ op: "create_issue", title, body, labels?, milestone?, deps? },
|
||||
{ op: "set_estimate", issue, estimate: EstimateLabel },
|
||||
{ op: "set_priority", issue, priority: PriorityLabel },
|
||||
{ op: "set_milestone", issue, milestone: number | null },
|
||||
{ op: "set_deadline_hard", milestone: number, hard: boolean },
|
||||
{ op: "add_dep", issue, dependsOn: number },
|
||||
{ op: "remove_dep", issue, dependsOn: number }, // destructive
|
||||
{ op: "close_issue", issue }, // destructive
|
||||
{ op: "remove_label", issue, label } // destructive
|
||||
],
|
||||
approved?: boolean // required iff any op is destructive
|
||||
})
|
||||
// → { applied: number, consequence: string, rejected?: {op, reason}[] }
|
||||
```
|
||||
|
||||
Only touches labels in the CommiTea namespaces (`est/*`, `p/*`, `deadline/hard`)
|
||||
plus native issue fields — never invents labels, comments, or synthetic issues
|
||||
(zero-pollution goal).
|
||||
|
||||
## `record_directive` (write — big model)
|
||||
|
||||
Appends to the directive log ([pm-state.md](./pm-state.md)), triggers a scheduler
|
||||
re-run, and returns the consequence diff for propose-approve. Does **not** mutate
|
||||
gitea itself — a directive is intent; its effects land through `apply_changes`
|
||||
after approval.
|
||||
|
||||
```jsonc
|
||||
record_directive({
|
||||
kind: "reprioritize" | "reestimate" | "set-deadline" | "scope" | "capacity" | "note",
|
||||
quote: string, // verbatim PM words, stored in the ledger
|
||||
target?: { issue?: number, milestone?: number, member?: string },
|
||||
params?: object, // structured effect, e.g. { priority: 1 }
|
||||
rationale?: string
|
||||
})
|
||||
// → { directiveId, consequence: { before, after }[], summary: string }
|
||||
```
|
||||
|
||||
## Not tools
|
||||
|
||||
Reads that are pure UI state (theme, current view, back-stack) never go through
|
||||
tools. The scheduler, Monte Carlo, calibration fit, and lifecycle inference are
|
||||
**code**, invoked by the runtime around these tools — the model requests a view
|
||||
or proposes a change; deterministic code produces every number.
|
||||
Reference in New Issue
Block a user