@agentproto/apps 0.12.0 → 0.13.0
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.
- package/dist/agents-overview/panel.mjs +14 -67
- package/dist/agents-overview/panel.mjs.map +1 -1
- package/dist/agents-overview.mjs +13 -68
- package/dist/agents-overview.mjs.map +1 -1
- package/dist/bin/sync.d.ts.map +1 -1
- package/dist/bin/sync.mjs +2374 -2
- package/dist/bin/sync.mjs.map +1 -1
- package/dist/bureau-sessions/panel.mjs +14 -67
- package/dist/bureau-sessions/panel.mjs.map +1 -1
- package/dist/bureau-sessions.mjs +13 -68
- package/dist/bureau-sessions.mjs.map +1 -1
- package/dist/config/fragment.d.ts +50 -0
- package/dist/config/fragment.d.ts.map +1 -0
- package/dist/config/index.d.ts +23 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/ui.d.ts +43 -0
- package/dist/config/ui.d.ts.map +1 -0
- package/dist/config.mjs +2373 -0
- package/dist/config.mjs.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.mjs +2706 -138
- package/dist/index.mjs.map +1 -1
- package/dist/live-session/logic.d.ts +2 -0
- package/dist/live-session/logic.d.ts.map +1 -1
- package/dist/live-session/panel.d.ts.map +1 -1
- package/dist/live-session/panel.mjs +27 -74
- package/dist/live-session/panel.mjs.map +1 -1
- package/dist/live-session.mjs +26 -75
- package/dist/live-session.mjs.map +1 -1
- package/dist/panel-bridge.d.ts +11 -6
- package/dist/panel-bridge.d.ts.map +1 -1
- package/dist/session-chat/index.d.ts.map +1 -1
- package/dist/session-chat/panel.mjs +14 -67
- package/dist/session-chat/panel.mjs.map +1 -1
- package/dist/session-chat.mjs +28 -69
- package/dist/session-chat.mjs.map +1 -1
- package/dist/session-story/panel.mjs +14 -67
- package/dist/session-story/panel.mjs.map +1 -1
- package/dist/session-story.mjs +13 -68
- package/dist/session-story.mjs.map +1 -1
- package/dist/session-viewer/ui.d.ts.map +1 -1
- package/dist/session-viewer.mjs +10 -0
- package/dist/session-viewer.mjs.map +1 -1
- package/dist/sessions-panel/panel.d.ts.map +1 -1
- package/dist/sessions-panel/panel.mjs +15 -67
- package/dist/sessions-panel/panel.mjs.map +1 -1
- package/dist/sessions-panel.mjs +14 -68
- package/dist/sessions-panel.mjs.map +1 -1
- package/dist/work-board/panel.d.ts +1 -1
- package/dist/work-board/panel.d.ts.map +1 -1
- package/dist/work-board/panel.generated.d.ts +1 -1
- package/dist/work-board/panel.generated.d.ts.map +1 -1
- package/dist/work-board/panel.mjs +293 -62
- package/dist/work-board/panel.mjs.map +1 -1
- package/dist/work-board.mjs +293 -62
- package/dist/work-board.mjs.map +1 -1
- package/package.json +12 -4
- package/repo-maintenance/.agentproto/APP.md +22 -0
- package/repo-maintenance/.agentproto/agents/repo-maintenance-reviewer/AGENT.md +142 -0
- package/repo-maintenance/.agentproto/workflows/maintain/WORKFLOW.md +262 -0
- package/repo-maintenance/.agentproto/workflows/maintain/entry.mjs +672 -0
- package/repo-maintenance/README.md +79 -0
- package/repo-maintenance/routines/repo-maintenance-daily/ROUTINE.md +77 -0
- 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.
|
|
3
|
+
"version": "0.13.0",
|
|
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-
|
|
151
|
-
"@agentproto/
|
|
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.
|
|
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: branchGcApply
|
|
152
|
+
kind: tool
|
|
153
|
+
name: Apply branch gc (reclaim only)
|
|
154
|
+
description: >-
|
|
155
|
+
`apply` is $input.applyMerged — a dry-run plan again when false.
|
|
156
|
+
`includeReviewed` stays false: this workflow never reclaims a
|
|
157
|
+
review-class branch, even an agreed one (see the approve-reviewed
|
|
158
|
+
seam below).
|
|
159
|
+
tool: branch_gc
|
|
160
|
+
inputs:
|
|
161
|
+
repoRoot: $input.repoRoot
|
|
162
|
+
workspaceSlug: $input.workspaceSlug
|
|
163
|
+
apply: $input.applyMerged
|
|
164
|
+
includeReviewed: false
|
|
165
|
+
scopes: [local, remote, orphan]
|
|
166
|
+
|
|
167
|
+
- id: worktreeGcApply
|
|
168
|
+
kind: tool
|
|
169
|
+
name: Apply worktree gc
|
|
170
|
+
tool: worktree_gc
|
|
171
|
+
inputs:
|
|
172
|
+
repoRoot: $input.repoRoot
|
|
173
|
+
workspaceSlug: $input.workspaceSlug
|
|
174
|
+
apply: $input.applyMerged
|
|
175
|
+
salvageDirty: false
|
|
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.
|