@agentproto/apps 0.12.0 → 0.13.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. package/dist/agents-overview/panel.mjs +14 -67
  2. package/dist/agents-overview/panel.mjs.map +1 -1
  3. package/dist/agents-overview.mjs +13 -68
  4. package/dist/agents-overview.mjs.map +1 -1
  5. package/dist/bin/sync.d.ts.map +1 -1
  6. package/dist/bin/sync.mjs +2374 -2
  7. package/dist/bin/sync.mjs.map +1 -1
  8. package/dist/bureau-sessions/panel.mjs +14 -67
  9. package/dist/bureau-sessions/panel.mjs.map +1 -1
  10. package/dist/bureau-sessions.mjs +13 -68
  11. package/dist/bureau-sessions.mjs.map +1 -1
  12. package/dist/config/fragment.d.ts +50 -0
  13. package/dist/config/fragment.d.ts.map +1 -0
  14. package/dist/config/index.d.ts +23 -0
  15. package/dist/config/index.d.ts.map +1 -0
  16. package/dist/config/ui.d.ts +43 -0
  17. package/dist/config/ui.d.ts.map +1 -0
  18. package/dist/config.mjs +2373 -0
  19. package/dist/config.mjs.map +1 -0
  20. package/dist/index.d.ts +1 -0
  21. package/dist/index.d.ts.map +1 -1
  22. package/dist/index.mjs +2706 -138
  23. package/dist/index.mjs.map +1 -1
  24. package/dist/live-session/logic.d.ts +2 -0
  25. package/dist/live-session/logic.d.ts.map +1 -1
  26. package/dist/live-session/panel.d.ts.map +1 -1
  27. package/dist/live-session/panel.mjs +27 -74
  28. package/dist/live-session/panel.mjs.map +1 -1
  29. package/dist/live-session.mjs +26 -75
  30. package/dist/live-session.mjs.map +1 -1
  31. package/dist/panel-bridge.d.ts +11 -6
  32. package/dist/panel-bridge.d.ts.map +1 -1
  33. package/dist/session-chat/index.d.ts.map +1 -1
  34. package/dist/session-chat/panel.mjs +14 -67
  35. package/dist/session-chat/panel.mjs.map +1 -1
  36. package/dist/session-chat.mjs +28 -69
  37. package/dist/session-chat.mjs.map +1 -1
  38. package/dist/session-story/panel.mjs +14 -67
  39. package/dist/session-story/panel.mjs.map +1 -1
  40. package/dist/session-story.mjs +13 -68
  41. package/dist/session-story.mjs.map +1 -1
  42. package/dist/session-viewer/ui.d.ts.map +1 -1
  43. package/dist/session-viewer.mjs +10 -0
  44. package/dist/session-viewer.mjs.map +1 -1
  45. package/dist/sessions-panel/panel.d.ts.map +1 -1
  46. package/dist/sessions-panel/panel.mjs +15 -67
  47. package/dist/sessions-panel/panel.mjs.map +1 -1
  48. package/dist/sessions-panel.mjs +14 -68
  49. package/dist/sessions-panel.mjs.map +1 -1
  50. package/dist/work-board/panel.d.ts +1 -1
  51. package/dist/work-board/panel.d.ts.map +1 -1
  52. package/dist/work-board/panel.generated.d.ts +1 -1
  53. package/dist/work-board/panel.generated.d.ts.map +1 -1
  54. package/dist/work-board/panel.mjs +293 -62
  55. package/dist/work-board/panel.mjs.map +1 -1
  56. package/dist/work-board.mjs +293 -62
  57. package/dist/work-board.mjs.map +1 -1
  58. package/package.json +12 -4
  59. package/repo-maintenance/.agentproto/APP.md +22 -0
  60. package/repo-maintenance/.agentproto/agents/repo-maintenance-reviewer/AGENT.md +142 -0
  61. package/repo-maintenance/.agentproto/workflows/maintain/WORKFLOW.md +262 -0
  62. package/repo-maintenance/.agentproto/workflows/maintain/entry.mjs +672 -0
  63. package/repo-maintenance/README.md +80 -0
  64. package/repo-maintenance/routines/repo-maintenance-daily/ROUTINE.md +77 -0
  65. package/repo-maintenance/routines/repo-maintenance-weekly/ROUTINE.md +82 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agentproto/apps",
3
- "version": "0.12.0",
3
+ "version": "0.13.1",
4
4
  "description": "@agentproto/apps — a home for ready-made agentproto apps (teams of agents + their workflows), declared with @agentproto/app-kit. Import a team (code-team, content-team, …) and use any of its agents/workflows from your own host: in-process via toMastraAgents(), or emit its manifests to disk.",
5
5
  "keywords": [
6
6
  "agentproto",
@@ -59,6 +59,11 @@
59
59
  "import": "./dist/ops-panel.mjs",
60
60
  "default": "./dist/ops-panel.mjs"
61
61
  },
62
+ "./config": {
63
+ "types": "./dist/config/index.d.ts",
64
+ "import": "./dist/config.mjs",
65
+ "default": "./dist/config.mjs"
66
+ },
62
67
  "./session-viewer": {
63
68
  "types": "./dist/session-viewer/index.d.ts",
64
69
  "import": "./dist/session-viewer.mjs",
@@ -138,6 +143,7 @@
138
143
  },
139
144
  "files": [
140
145
  "dist",
146
+ "repo-maintenance",
141
147
  "README.md",
142
148
  "LICENSE"
143
149
  ],
@@ -147,8 +153,9 @@
147
153
  "dependencies": {
148
154
  "zod": "^4.6.5",
149
155
  "@agentproto/agent": "0.2.4",
150
- "@agentproto/app-kit": "1.2.1",
151
- "@agentproto/workflow": "0.6.1"
156
+ "@agentproto/app-client": "0.4.0",
157
+ "@agentproto/app-kit": "1.3.0",
158
+ "@agentproto/workflow": "0.7.0"
152
159
  },
153
160
  "peerDependencies": {
154
161
  "@mastra/core": ">=1.0.0"
@@ -156,12 +163,13 @@
156
163
  "devDependencies": {
157
164
  "@mastra/core": "1.66.0",
158
165
  "@types/node": "^25.9.5",
166
+ "jsdom": "^29.1.1",
159
167
  "tsup": "^8.5.1",
160
168
  "typescript": "^5.9.3",
161
169
  "vite": "^7.3.6",
162
170
  "vite-plugin-singlefile": "^2.3.0",
163
171
  "vitest": "^3.2.7",
164
- "@agentproto/mastra": "0.2.14",
172
+ "@agentproto/mastra": "0.2.15",
165
173
  "@agentproto/tooling": "0.1.0"
166
174
  },
167
175
  "scripts": {
@@ -0,0 +1,22 @@
1
+ ---
2
+ schema: app/v1
3
+ id: '@agentproto/repo-maintenance'
4
+ name: Repo Maintenance
5
+ version: 0.1.0
6
+ description: >-
7
+ Plans and (opt-in) applies branch_gc + worktree_gc for a repo, with a
8
+ reviewer agent fanned out over every unmerged branch candidate before any
9
+ apply happens. Built on the branch_gc/branch_gc_verdict/worktree_gc tools
10
+ (agentproto/ts).
11
+ agents:
12
+ - id: '@agentproto/repo-maintenance-reviewer'
13
+ path: .agentproto/agents/repo-maintenance-reviewer/AGENT.md
14
+ workflows:
15
+ - id: maintain
16
+ path: .agentproto/workflows/maintain/WORKFLOW.md
17
+ ---
18
+
19
+ Plans and (opt-in) applies branch_gc + worktree_gc for a repo, with a
20
+ reviewer agent fanned out over every unmerged branch candidate before any
21
+ apply happens. See README.md for how to install and run it, and
22
+ `routines/` for the daily/weekly scheduled templates.
@@ -0,0 +1,142 @@
1
+ ---
2
+ schema: agent/v1
3
+ id: '@agentproto/repo-maintenance-reviewer'
4
+ description: >-
5
+ Reviews one stale, unmerged git branch at a time (spawned by the
6
+ `maintain` workflow's `review` map step) and decides whether deleting it
7
+ loses anything of value. Records its verdict via the branch_gc_verdict
8
+ tool — it never writes files and never deletes anything itself.
9
+ model: claude-sonnet-5
10
+ boundaries:
11
+ - Read-only on git — never checkout, switch, branch -d, reset, stash, commit, fetch, push, or touch a worktree
12
+ - Never edit, create, or delete any file in the repo
13
+ - Call branch_gc_verdict exactly once for the branch this turn is about, then stop
14
+ - agree:true only for obsolete/superseded, and only with concrete cited evidence
15
+ - Never merge, rebase, or otherwise mutate branch history
16
+ tools:
17
+ - run_command
18
+ - list_dir
19
+ - read_file
20
+ - branch_gc_verdict
21
+ workflows:
22
+ - ref: maintain
23
+ ---
24
+
25
+ You review one stale git branch and decide whether deleting it loses
26
+ anything of value. You are the gate: a branch only gets reclaimed later if
27
+ you say `agree: true` in your verdict, so be conservative and cite evidence.
28
+
29
+ ## Hard rules
30
+
31
+ - READ-ONLY on git. Allowed: `git log`, `git show`, `git diff`, `git grep`,
32
+ `git cat-file`, `git merge-base`, `git rev-list`, `git branch --contains`,
33
+ `git ls-tree`. Forbidden: anything that changes refs, the index, or the
34
+ working tree (no checkout, switch, branch -d, reset, stash, commit, fetch,
35
+ push, worktree). Do not edit any repo file. The repo path in your prompt
36
+ is a disposable detached worktree made for this review — the live checkout
37
+ is elsewhere and off limits — but the stash list and refs are shared with
38
+ every checkout of the repo, so the rule still holds there. Read a branch
39
+ through its sha: `git show <sha>:<path>`, `git ls-tree -r <sha>`.
40
+ - Always pass `-C <repo path from the prompt>` to git, and use that same path
41
+ as `repoRoot` for `branch_gc_verdict`.
42
+ - Cap output: pipe big diffs through `head -300`, or use `--stat` first.
43
+ - Never write temp files (no `git show … > /tmp/x && diff …`). Git compares
44
+ revisions directly: `git diff <a>:<path> <b>:<path>` for one file across
45
+ two revisions (paths may differ, e.g. after a move), or
46
+ `git diff <a> <b> -- <path>` when the path is the same on both.
47
+
48
+ ## What you're given per branch
49
+
50
+ `sha` (the tip), the base ref + its sha, `mergeBase`, `compareBase` (only
51
+ set for pre-rewrite history — see below), `mergedTree` (the tree base would
52
+ have if this branch merged cleanly, `null` when the merge conflicts),
53
+ `coverage`, `residualFiles`, and the push state.
54
+
55
+ The push state says whether a remote holds this work: `same-tip-on-remote`
56
+ / `contained-in-remote` (a remote ref has this tip), `diverged-from-remote`
57
+ (a same-named remote branch exists but lacks this tip), `local-only` (no
58
+ remote ref at all), or — for an orphan ref — `contained-elsewhere` /
59
+ `only-copy`. A local branch whose push state is `local-only`, empty, or
60
+ `null` is NOT recoverable from a remote, and neither is the unpushed part of
61
+ a `diverged-from-remote` one: deleting it deletes the only copy. Never cite
62
+ "recoverable from the remote" as evidence unless the push state is
63
+ `same-tip-on-remote` or `contained-in-remote`.
64
+
65
+ `coverage` is already computed for you, by content, before you're spawned:
66
+ `covered` (the exact blob exists somewhere in base) and `ignored`
67
+ (gitignored in base) files are settled — don't re-check them. `residualFiles`
68
+ lists only what is NOT provably in base: `evolved` (same filename exists in
69
+ base with different content — usually base kept editing a file this branch
70
+ also touched) and `unique` (no trace in base at all: could be a build
71
+ artifact, could be real lost work). Spend your effort on the residual files.
72
+
73
+ If a `compareBase` is present, the repo's history was re-rooted after this
74
+ branch was cut — `compareBase` is the old-history twin of the current base.
75
+ Commit shas from that old history do not exist on the current base; compare
76
+ by CONTENT (`git grep` on the current base, diff paths), never by sha.
77
+
78
+ ## Traps seen in practice
79
+
80
+ - A merge-conflict residual made only of `<<<<<<<`/`>>>>>>>` markers around
81
+ rows base already has (ledgers, READMEs) is NOT unique content — base
82
+ appended more rows after this branch's row, and the branch's own row is
83
+ usually already there. `git grep` the row's text on base.
84
+ - A reorg on base moves content, it doesn't delete it — before calling
85
+ anything "missing on base", look for the same filename elsewhere
86
+ (`git ls-tree -r --name-only <base> | grep /<name>`).
87
+ - "The feature landed via PR #N" is not evidence that THIS branch's residual
88
+ landed. Say specifically what the evolved/unique files are and where their
89
+ content (or the lack of it) actually is on base.
90
+
91
+ ## Method
92
+
93
+ 1. What this branch still adds: if a merged tree is given,
94
+ `git diff --stat <base> <mergedTree>` then `git diff <base> <mergedTree>
95
+ -- <path>` per residual file. Otherwise `git diff --stat <mergeBase>
96
+ <sha>`. Commits: `git log --oneline <compareBase-or-base>..<sha> | head -40`.
97
+ 2. For each meaningful residual file, check whether base already has the
98
+ same intent under a different form: `git log --oneline -n 15 <base> --
99
+ <path>`, `git grep -n '<distinctive string>' <base> -- <path>`, look for
100
+ a squash-merge commit whose subject matches this branch's commits. To
101
+ compare a residual file against its counterpart on base, diff the blobs
102
+ in place — `git diff <base>:<path> <sha>:<path>` (or
103
+ `<base>:<other-path>` when base moved it) — never via a temp file.
104
+ 3. Classify:
105
+ - `obsolete`: dead work (abandoned experiment, reverted approach,
106
+ generated snapshots, lockfile-only churn, deleted-on-base files this
107
+ branch only tweaks).
108
+ - `superseded`: the intent landed on base in another form (show where).
109
+ - `salvage`: real unlanded work with value — code, tests, docs, or unique
110
+ facts in plans/ledgers/runbooks/evidence files. A unique fact counts as
111
+ value even if it's small.
112
+ - `in-progress`: active work toward something not merged yet.
113
+ - `unclear`: you genuinely can't tell.
114
+ 4. `agree: true` ONLY for `obsolete`/`superseded`, and only with concrete
115
+ evidence (a sha or path plus what it shows). Anything with a unique
116
+ ledger/plan/evidence entry, or real code not on base, is `agree: false`.
117
+ Check the push state before relying on a remote copy: an unpushed
118
+ (`local-only`) branch has none — see "What you're given" above.
119
+
120
+ ## Recording your verdict
121
+
122
+ The tool is served by the agentproto MCP server — in Claude Code it shows up
123
+ as `mcp__agentproto__branch_gc_verdict`. If your harness lists it as
124
+ deferred, load its schema once (one tool search for that exact name), then
125
+ call it; don't search again. Call `branch_gc_verdict` exactly once, with:
126
+
127
+ ```
128
+ {
129
+ repoRoot: "<repo root you were given>",
130
+ name: "<branch name>",
131
+ sha: "<the exact tip sha you were given>",
132
+ triage: { verdict, confidence (0..1), reason, salvage? },
133
+ gate: { agree, verdict, reason, evidence: ["<sha or path>: what it shows", ...] },
134
+ reviewer: "repo-maintenance-reviewer",
135
+ }
136
+ ```
137
+
138
+ `gate.agree: true` with empty `evidence` is rejected by the tool — always
139
+ cite at least one concrete sha or path when you agree. After the tool call
140
+ succeeds, reply with one line: `<verdict> <agree> <name> — <reason under 20
141
+ words>`, then stop. You do not delete the branch, and you do not need to ask
142
+ permission to record the verdict — recording is not deleting.
@@ -0,0 +1,262 @@
1
+ ---
2
+ name: Repo Maintenance
3
+ id: maintain
4
+ description: >-
5
+ Plan worktree_gc + branch_gc, fan a review agent out over up to
6
+ `maxReviews` unreviewed branch candidates, newest first (small model for a
7
+ small residual, large model otherwise), verify every candidate got a verdict, optionally apply
8
+ (reclaim-only) worktree/branch gc, and report — plus an agentpush
9
+ notification when `notify` is set. Entry-based (see entry.mjs): the
10
+ `review` map step's per-candidate model selector is a real run-time
11
+ function, which the pure-.md path cannot express (`defineWorkflow` rejects
12
+ a non-string `model` — "a run-time selector is only available on the
13
+ TS-authored runtime step").
14
+ version: 0.1.0
15
+ entry: ./entry.mjs
16
+ inputs:
17
+ repoRoot:
18
+ type: string
19
+ description: Absolute path to the git repo. Wins over `workspaceSlug`.
20
+ workspaceSlug:
21
+ type: string
22
+ description: Workspace slug. The active workspace when both are omitted.
23
+ applyMerged:
24
+ type: boolean
25
+ description: Execute branch_gc/worktree_gc (reclaim-class only) after review.
26
+ default: false
27
+ reviewModelSmall:
28
+ type: string
29
+ description: Model for a review candidate with residualFileCount <= 3.
30
+ default: claude-haiku-4-5-20251001
31
+ reviewModelLarge:
32
+ type: string
33
+ description: Model for a review candidate with residualFileCount > 3.
34
+ default: claude-sonnet-5
35
+ maxReviews:
36
+ type: number
37
+ description: >-
38
+ Most review candidates to review this run — newest tip first, then the
39
+ larger residual. The rest are reported as not reviewed this run; tips
40
+ with a stored verdict are never re-reviewed, so daily runs walk the
41
+ backlog.
42
+ default: 40
43
+ notify:
44
+ type: object
45
+ description: >-
46
+ Optional agentpush `to` target ({ channel, address }) to notify with
47
+ the report when set. Omit for no notification.
48
+ outputs: {}
49
+ steps:
50
+ - id: worktreeGcPlan
51
+ kind: tool
52
+ name: Plan worktree gc
53
+ tool: worktree_gc
54
+ inputs:
55
+ repoRoot: $input.repoRoot
56
+ workspaceSlug: $input.workspaceSlug
57
+ apply: false
58
+
59
+ - id: branchGcPlan
60
+ kind: tool
61
+ name: Plan branch gc
62
+ tool: branch_gc
63
+ inputs:
64
+ repoRoot: $input.repoRoot
65
+ workspaceSlug: $input.workspaceSlug
66
+ apply: false
67
+ includeReviewed: false
68
+
69
+ - id: reviewQueue
70
+ kind: transform
71
+ name: Queue unreviewed review candidates, one per branch name
72
+ description: >-
73
+ Entry-based — no string expression language for `compute` in the
74
+ declarative manifest. See entry.mjs's buildReviewQueue: dedupes by tip
75
+ sha, then merges candidates whose refs share one branch name (a local
76
+ branch and its remote twin review together even when their tips
77
+ diverged — the newest tip is primary, the older ones ride along as
78
+ otherTips), skips names whose every tip already carries a stored
79
+ verdict, and orders oldest first, then the larger residual.
80
+
81
+ - id: reviewCandidates
82
+ kind: transform
83
+ name: Take this run's share of the queue
84
+ description: Entry-based — the first `maxReviews` of reviewQueue.
85
+
86
+ - id: reviewWorktreePaths
87
+ kind: transform
88
+ name: Name each candidate's disposable review worktree
89
+ description: >-
90
+ Entry-based. Every candidate carries `reviewWorktree`, a detached
91
+ worktree path under the OS tmp dir (`agentproto-maintain-review/`),
92
+ never the live checkout. This step lists them for the cleanups.
93
+
94
+ - id: review
95
+ kind: map
96
+ name: Review every unmerged branch
97
+ description: >-
98
+ One reviewer-agent turn per branch name, parallelism 4. Model is
99
+ picked per item by entry.mjs: haiku when residualFileCount <= 3, else
100
+ sonnet. The agent records its verdict via branch_gc_verdict — one call
101
+ PER tip the item carries (an item may hold a local + a remote tip that
102
+ diverged); this step never applies anything. After the turn,
103
+ branch_gc_verdict_get checks the store for EVERY tip; with any
104
+ verdict missing, the SAME session is re-prompted once, then one fresh
105
+ large-model reviewer retries, and only then are the still-missing tips
106
+ left as gaps. Each item first creates its own
107
+ detached review worktree of the primary tip (`branch_gc_review_worktree`),
108
+ runs its reviewers there — never in the live checkout — and removes it
109
+ last. Three spawn
110
+ failures in a row open the engine's circuit breaker: the remaining
111
+ candidates are not started and are reported as not reviewed. See
112
+ entry.mjs for the body.
113
+ over: $steps.reviewCandidates
114
+ parallelism: 4
115
+ onError: collect
116
+ steps:
117
+ - id: reviewOne
118
+ kind: agent
119
+ agent:
120
+ ref: "@agentproto/repo-maintenance-reviewer"
121
+ prompt: See entry.mjs — mustache-templated over $item + branchGcPlan.
122
+
123
+ - id: reviewCleanup
124
+ kind: tool
125
+ name: Remove every review worktree
126
+ description: >-
127
+ An item that failed never reached its own removal — clear them all
128
+ before anything re-plans or gc's worktrees. The entry's `finally`
129
+ block runs the same removal again whatever happens (failure, cancel).
130
+ tool: branch_gc_review_worktree
131
+ inputs:
132
+ repoRoot: $steps.branchGcPlan.plan.repoRoot
133
+ action: remove
134
+ paths: $steps.reviewWorktreePaths
135
+
136
+ - id: branchGcVerify
137
+ kind: tool
138
+ name: Re-plan to pick up recorded verdicts
139
+ tool: branch_gc
140
+ inputs:
141
+ repoRoot: $input.repoRoot
142
+ workspaceSlug: $input.workspaceSlug
143
+ apply: false
144
+ includeReviewed: false
145
+
146
+ - id: gaps
147
+ kind: transform
148
+ name: Review candidates with no recorded verdict
149
+ description: Entry-based — see entry.mjs's computeReviewGaps.
150
+
151
+ - id: worktreeGcApply
152
+ kind: tool
153
+ name: Apply worktree gc
154
+ tool: worktree_gc
155
+ inputs:
156
+ repoRoot: $input.repoRoot
157
+ workspaceSlug: $input.workspaceSlug
158
+ apply: $input.applyMerged
159
+ salvageDirty: false
160
+
161
+ - id: branchGcApply
162
+ kind: tool
163
+ name: Apply branch gc (reclaim only)
164
+ description: >-
165
+ `apply` is $input.applyMerged — a dry-run plan again when false.
166
+ `includeReviewed` stays false: this workflow never reclaims a
167
+ review-class branch, even an agreed one (see the approve-reviewed
168
+ seam below).
169
+ tool: branch_gc
170
+ inputs:
171
+ repoRoot: $input.repoRoot
172
+ workspaceSlug: $input.workspaceSlug
173
+ apply: $input.applyMerged
174
+ includeReviewed: false
175
+ scopes: [local, remote, orphan]
176
+
177
+ - id: report
178
+ kind: transform
179
+ name: Build the markdown summary
180
+ description: Entry-based — see entry.mjs's buildReport.
181
+
182
+ - id: notifyBody
183
+ kind: transform
184
+ name: Format the agentpush notification body
185
+ description: Entry-based — turns the report into agentpush's send_message JSON body.
186
+
187
+ - id: shouldNotify
188
+ kind: transform
189
+ name: Decide whether there's anything worth notifying about
190
+ description: >-
191
+ Entry-based — true only when `notify` is set AND there's a
192
+ reclaimable ref or a review candidate. A clean plan-only sweep
193
+ shouldn't page anyone.
194
+
195
+ - id: maybeNotify
196
+ kind: branch
197
+ name: Notify only when shouldNotify is true
198
+ branches:
199
+ - when: $steps.shouldNotify
200
+ next: notify
201
+ default: skip-notify
202
+
203
+ - id: notify
204
+ kind: tool
205
+ name: Send the agentpush notification
206
+ tool: command_execute
207
+ inputs:
208
+ command: bash
209
+ args:
210
+ - "-c"
211
+ - >-
212
+ curl -s --max-time 30 -X POST -H "Authorization: Bearer
213
+ ${AGENTPUSH_API_KEY:-}" -H "Content-Type: application/json"
214
+ https://api.agentpush.io/tools/send_message --data-binary @-
215
+ stdin: $steps.notifyBody
216
+
217
+ - id: skip-notify
218
+ kind: gate
219
+ name: No notification requested
220
+ command: "true"
221
+
222
+ result:
223
+ report: $steps.report
224
+ gaps: $steps.gaps
225
+ applyMerged: $input.applyMerged
226
+ branchGcApply: $steps.branchGcApply
227
+ worktreeGcApply: $steps.worktreeGcApply
228
+ ---
229
+
230
+ # Repo Maintenance — `maintain` workflow
231
+
232
+ `worktree_gc` + `branch_gc` plan → fan a reviewer agent out over every
233
+ unmerged branch (small model for a small residual, large model otherwise) →
234
+ verify every candidate got a verdict → optionally apply (reclaim-class only)
235
+ → markdown report, plus an agentpush notification when `notify` is set.
236
+
237
+ Entry-based (`entry.mjs`) for one reason: `review`'s per-candidate `model`
238
+ selector is a real run-time function, which only the entry-loader path can
239
+ carry (see the description above and entry.mjs's own docblock).
240
+
241
+ ## Review worktrees
242
+
243
+ Reviewers never run in the live checkout. Each review item creates a
244
+ disposable DETACHED worktree of the tip under review under the OS tmp dir
245
+ (`branch_gc_review_worktree`, which refuses any other location) and removes
246
+ it when the item ends; `reviewCleanup` removes them all after the map, and
247
+ entry.mjs's `finally` block removes them once more on failure or cancel — a
248
+ `finally` step always runs.
249
+
250
+ ## Out of scope, on purpose
251
+
252
+ Recording a verdict via `branch_gc_verdict` never reclaims a branch by
253
+ itself — `branchGcApply` always runs with `includeReviewed: false`. A
254
+ human-in-the-loop gate that reclaims `review`-class branches whose stored
255
+ verdict agreed is a documented, unwired seam (`approve-reviewed`), not built
256
+ here — see the app README, "Out of scope: the approval gate".
257
+
258
+ ## Enabling
259
+
260
+ `command_execute` (the `notify` step) needs `bash` allowlisted in the
261
+ workspace's `.agentproto/allowed-commands.json`, and `AGENTPUSH_API_KEY` set
262
+ in the daemon's environment, before passing a `notify` input.