@aperant/framework 0.13.0 → 0.16.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/CHANGELOG.md +106 -0
- package/README.md +1 -1
- package/agents/apt-pr-review-crossplatform.md +189 -0
- package/agents/apt-pr-review-i18n.md +190 -0
- package/dist/cli/commands/audit-branch-current.d.mts +27 -5
- package/dist/cli/commands/audit-branch-current.d.mts.map +1 -1
- package/dist/cli/commands/audit-branch-current.mjs +3 -3
- package/dist/cli/commands/audit-branch-current.mjs.map +1 -1
- package/dist/cli/commands/event.d.mts.map +1 -1
- package/dist/cli/commands/event.mjs +6 -4
- package/dist/cli/commands/event.mjs.map +1 -1
- package/dist/cli/commands/fan-out.d.mts.map +1 -1
- package/dist/cli/commands/fan-out.mjs +3 -1
- package/dist/cli/commands/fan-out.mjs.map +1 -1
- package/dist/cli/commands/features-audit.d.mts.map +1 -1
- package/dist/cli/commands/features-audit.mjs +6 -1
- package/dist/cli/commands/features-audit.mjs.map +1 -1
- package/dist/cli/commands/followups.d.mts +5 -0
- package/dist/cli/commands/followups.d.mts.map +1 -0
- package/dist/cli/commands/followups.mjs +266 -0
- package/dist/cli/commands/followups.mjs.map +1 -0
- package/dist/cli/commands/health-check.d.mts.map +1 -1
- package/dist/cli/commands/health-check.mjs +3 -1
- package/dist/cli/commands/health-check.mjs.map +1 -1
- package/dist/cli/commands/init.d.mts.map +1 -1
- package/dist/cli/commands/init.mjs +30 -1
- package/dist/cli/commands/init.mjs.map +1 -1
- package/dist/cli/commands/merge-detect.d.mts +29 -0
- package/dist/cli/commands/merge-detect.d.mts.map +1 -0
- package/dist/cli/commands/merge-detect.mjs +196 -0
- package/dist/cli/commands/merge-detect.mjs.map +1 -0
- package/dist/cli/commands/merge-integrate.d.mts +28 -0
- package/dist/cli/commands/merge-integrate.d.mts.map +1 -0
- package/dist/cli/commands/merge-integrate.mjs +383 -0
- package/dist/cli/commands/merge-integrate.mjs.map +1 -0
- package/dist/cli/commands/pr-review/detect-specialists.d.mts +58 -0
- package/dist/cli/commands/pr-review/detect-specialists.d.mts.map +1 -0
- package/dist/cli/commands/pr-review/detect-specialists.mjs +984 -0
- package/dist/cli/commands/pr-review/detect-specialists.mjs.map +1 -0
- package/dist/cli/commands/pr-review.d.mts.map +1 -1
- package/dist/cli/commands/pr-review.mjs +11 -2
- package/dist/cli/commands/pr-review.mjs.map +1 -1
- package/dist/cli/commands/precompact-hook.d.mts.map +1 -1
- package/dist/cli/commands/precompact-hook.mjs +10 -6
- package/dist/cli/commands/precompact-hook.mjs.map +1 -1
- package/dist/cli/commands/roadmap.d.mts.map +1 -1
- package/dist/cli/commands/roadmap.mjs +24 -11
- package/dist/cli/commands/roadmap.mjs.map +1 -1
- package/dist/cli/commands/seed.d.mts.map +1 -1
- package/dist/cli/commands/seed.mjs +3 -1
- package/dist/cli/commands/seed.mjs.map +1 -1
- package/dist/cli/commands/state.d.mts.map +1 -1
- package/dist/cli/commands/state.mjs +9 -3
- package/dist/cli/commands/state.mjs.map +1 -1
- package/dist/cli/commands/statusline.d.mts.map +1 -1
- package/dist/cli/commands/statusline.mjs +5 -1
- package/dist/cli/commands/statusline.mjs.map +1 -1
- package/dist/cli/commands/task.d.mts.map +1 -1
- package/dist/cli/commands/task.mjs +126 -23
- package/dist/cli/commands/task.mjs.map +1 -1
- package/dist/cli/commands/worktree.d.mts +1 -1
- package/dist/cli/commands/worktree.d.mts.map +1 -1
- package/dist/cli/commands/worktree.mjs +282 -83
- package/dist/cli/commands/worktree.mjs.map +1 -1
- package/dist/cli/config/post-merge-sweep.d.mts.map +1 -1
- package/dist/cli/config/post-merge-sweep.mjs +3 -2
- package/dist/cli/config/post-merge-sweep.mjs.map +1 -1
- package/dist/cli/config/share-policy.d.mts +3 -1
- package/dist/cli/config/share-policy.d.mts.map +1 -1
- package/dist/cli/config/share-policy.mjs +16 -3
- package/dist/cli/config/share-policy.mjs.map +1 -1
- package/dist/cli/config/upgrade-gitignore.d.mts.map +1 -1
- package/dist/cli/config/upgrade-gitignore.mjs +27 -5
- package/dist/cli/config/upgrade-gitignore.mjs.map +1 -1
- package/dist/cli/consistency/parse-qa.mjs +12 -1
- package/dist/cli/consistency/parse-qa.mjs.map +1 -1
- package/dist/cli/consistency/parse-review.d.mts +23 -0
- package/dist/cli/consistency/parse-review.d.mts.map +1 -1
- package/dist/cli/consistency/parse-review.mjs +36 -0
- package/dist/cli/consistency/parse-review.mjs.map +1 -1
- package/dist/cli/consistency/parse-spec.d.mts +16 -0
- package/dist/cli/consistency/parse-spec.d.mts.map +1 -1
- package/dist/cli/consistency/parse-spec.mjs +44 -0
- package/dist/cli/consistency/parse-spec.mjs.map +1 -1
- package/dist/cli/coordination/agent-identity.d.mts +5 -2
- package/dist/cli/coordination/agent-identity.d.mts.map +1 -1
- package/dist/cli/coordination/agent-identity.mjs +6 -4
- package/dist/cli/coordination/agent-identity.mjs.map +1 -1
- package/dist/cli/coordination/store.d.mts +1 -1
- package/dist/cli/dispatch.d.mts.map +1 -1
- package/dist/cli/dispatch.mjs +4 -0
- package/dist/cli/dispatch.mjs.map +1 -1
- package/dist/cli/followups/derive.d.mts +63 -0
- package/dist/cli/followups/derive.d.mts.map +1 -0
- package/dist/cli/followups/derive.mjs +115 -0
- package/dist/cli/followups/derive.mjs.map +1 -0
- package/dist/cli/followups/schema.d.mts +165 -0
- package/dist/cli/followups/schema.d.mts.map +1 -0
- package/dist/cli/followups/schema.mjs +251 -0
- package/dist/cli/followups/schema.mjs.map +1 -0
- package/dist/cli/gate/context.d.mts +1 -1
- package/dist/cli/gate/gates/followups-adjudicated.d.mts +69 -0
- package/dist/cli/gate/gates/followups-adjudicated.d.mts.map +1 -0
- package/dist/cli/gate/gates/followups-adjudicated.mjs +141 -0
- package/dist/cli/gate/gates/followups-adjudicated.mjs.map +1 -0
- package/dist/cli/gate/gates/index.mjs +1 -0
- package/dist/cli/gate/gates/index.mjs.map +1 -1
- package/dist/cli/git/materialize-env.d.mts +39 -0
- package/dist/cli/git/materialize-env.d.mts.map +1 -0
- package/dist/cli/git/materialize-env.mjs +217 -0
- package/dist/cli/git/materialize-env.mjs.map +1 -0
- package/dist/cli/help.d.mts.map +1 -1
- package/dist/cli/help.mjs +9 -1
- package/dist/cli/help.mjs.map +1 -1
- package/dist/cli/install/legacy-paths.d.mts.map +1 -1
- package/dist/cli/install/legacy-paths.mjs +5 -0
- package/dist/cli/install/legacy-paths.mjs.map +1 -1
- package/dist/cli/roadmap/lifecycle.d.mts.map +1 -1
- package/dist/cli/roadmap/lifecycle.mjs +4 -1
- package/dist/cli/roadmap/lifecycle.mjs.map +1 -1
- package/dist/cli/task/ids.d.mts +9 -0
- package/dist/cli/task/ids.d.mts.map +1 -1
- package/dist/cli/task/ids.mjs +9 -0
- package/dist/cli/task/ids.mjs.map +1 -1
- package/dist/cli/task/index-md.d.mts +5 -0
- package/dist/cli/task/index-md.d.mts.map +1 -1
- package/dist/cli/task/index-md.mjs +12 -4
- package/dist/cli/task/index-md.mjs.map +1 -1
- package/dist/cli/util/io.d.mts +6 -0
- package/dist/cli/util/io.d.mts.map +1 -1
- package/dist/cli/util/io.mjs +16 -1
- package/dist/cli/util/io.mjs.map +1 -1
- package/dist/cli/util/project.d.mts +7 -2
- package/dist/cli/util/project.d.mts.map +1 -1
- package/dist/cli/util/project.mjs +11 -14
- package/dist/cli/util/project.mjs.map +1 -1
- package/dist/cli/util/state-paths.d.mts +19 -0
- package/dist/cli/util/state-paths.d.mts.map +1 -0
- package/dist/cli/util/state-paths.mjs +45 -0
- package/dist/cli/util/state-paths.mjs.map +1 -0
- package/dist/plugin/.claude-plugin/plugin.json +4 -1
- package/dist/plugin/agents/apt-pr-review-crossplatform.md +189 -0
- package/dist/plugin/agents/apt-pr-review-i18n.md +190 -0
- package/dist/plugin/skills/apt/SKILL.md +9 -3
- package/dist/plugin/skills/apt-close-task/SKILL.md +48 -0
- package/dist/plugin/skills/apt-debug/SKILL.md +19 -9
- package/dist/plugin/skills/apt-execute/SKILL.md +3 -1
- package/dist/plugin/skills/apt-fan-out/SKILL.md +65 -1
- package/dist/plugin/skills/apt-merge-conflict-resolution/SKILL.md +227 -0
- package/dist/plugin/skills/apt-pr-review/SCHEMA.md +4 -2
- package/dist/plugin/skills/apt-pr-review/SKILL.md +117 -29
- package/dist/plugin/skills/apt-quick/SKILL.md +24 -1
- package/dist/plugin/skills/apt-review/SKILL.md +6 -0
- package/dist/plugin/skills/apt-run/SKILL.md +1 -1
- package/dist/plugin/skills/apt-setup/SKILL.md +21 -3
- package/dist/plugin/skills/apt-ship/SKILL.md +32 -11
- package/dist/plugin/skills/apt-terminal/SKILL.md +8 -0
- package/dist/plugin/skills/apt-triage/SKILL.md +4 -0
- package/dist/plugin/skills/apt-verify/SKILL.md +24 -0
- package/dist/plugin/skills/apt-watch-ci/SKILL.md +3 -1
- package/dist/types/config.d.ts +33 -0
- package/dist/types/config.d.ts.map +1 -1
- package/package.json +1 -1
- package/prompts/conductor-framework-context.md +1 -1
- package/prompts/github/pr_crossplatform_agent.md +283 -0
- package/prompts/github/pr_i18n_agent.md +279 -0
- package/prompts/inbox-clarification.md +18 -11
- package/skills/apt/SKILL.md +9 -3
- package/skills/apt-close-task/SKILL.md +48 -0
- package/skills/apt-debug/SKILL.md +19 -9
- package/skills/apt-execute/SKILL.md +3 -1
- package/skills/apt-fan-out/SKILL.md +65 -1
- package/skills/apt-merge-conflict-resolution/SKILL.md +227 -0
- package/skills/apt-pr-review/SCHEMA.md +4 -2
- package/skills/apt-pr-review/SKILL.md +117 -29
- package/skills/apt-quick/SKILL.md +24 -1
- package/skills/apt-review/SKILL.md +6 -0
- package/skills/apt-run/SKILL.md +1 -1
- package/skills/apt-setup/SKILL.md +21 -3
- package/skills/apt-ship/SKILL.md +32 -11
- package/skills/apt-terminal/SKILL.md +8 -0
- package/skills/apt-triage/SKILL.md +4 -0
- package/skills/apt-verify/SKILL.md +24 -0
- package/skills/apt-watch-ci/SKILL.md +3 -1
- package/src/cli/commands/audit-branch-current.mjs +3 -3
- package/src/cli/commands/event.mjs +6 -4
- package/src/cli/commands/fan-out.mjs +3 -1
- package/src/cli/commands/features-audit.mjs +6 -1
- package/src/cli/commands/followups.mjs +303 -0
- package/src/cli/commands/health-check.mjs +3 -1
- package/src/cli/commands/init.mjs +29 -0
- package/src/cli/commands/merge-detect.mjs +203 -0
- package/src/cli/commands/merge-integrate.mjs +392 -0
- package/src/cli/commands/pr-review/__fixtures__/android-strings/app/src/main/res/values-fr/strings.xml +3 -0
- package/src/cli/commands/pr-review/__fixtures__/babel-js/package.json +4 -0
- package/src/cli/commands/pr-review/__fixtures__/c-ifdef/src/main.c +4 -0
- package/src/cli/commands/pr-review/__fixtures__/ci-matrix/.github/workflows/ci.yml +10 -0
- package/src/cli/commands/pr-review/__fixtures__/cmake-win/CMakeLists.txt +5 -0
- package/src/cli/commands/pr-review/__fixtures__/diffs/add-arb.patch +9 -0
- package/src/cli/commands/pr-review/__fixtures__/diffs/ci-single-os-dep.patch +13 -0
- package/src/cli/commands/pr-review/__fixtures__/diffs/ci-single-os-list-item-dep.patch +17 -0
- package/src/cli/commands/pr-review/__fixtures__/diffs/lone-weak-t.patch +8 -0
- package/src/cli/commands/pr-review/__fixtures__/diffs/monorepo-b.patch +7 -0
- package/src/cli/commands/pr-review/__fixtures__/diffs/two-weak-xpl.patch +12 -0
- package/src/cli/commands/pr-review/__fixtures__/dropped-underscore/src/app.js +2 -0
- package/src/cli/commands/pr-review/__fixtures__/electron-app/package.json +4 -0
- package/src/cli/commands/pr-review/__fixtures__/i18n-locale-file/src/locales/fr.json +1 -0
- package/src/cli/commands/pr-review/__fixtures__/monorepo/packages/a/locales/fr.json +1 -0
- package/src/cli/commands/pr-review/__fixtures__/monorepo/packages/b/src/index.ts +1 -0
- package/src/cli/commands/pr-review/__fixtures__/py-babel/pyproject.toml +3 -0
- package/src/cli/commands/pr-review/__fixtures__/qt-i18n-dir/i18n/app_fr.ts +11 -0
- package/src/cli/commands/pr-review/__fixtures__/rust-cli/Cargo.toml +7 -0
- package/src/cli/commands/pr-review/__fixtures__/rust-cli/src/main.rs +1 -0
- package/src/cli/commands/pr-review/__fixtures__/ts-dir/ts/foo.ts +3 -0
- package/src/cli/commands/pr-review/detect-specialists.mjs +1029 -0
- package/src/cli/commands/pr-review.mjs +12 -2
- package/src/cli/commands/precompact-hook.mjs +10 -6
- package/src/cli/commands/roadmap.mjs +24 -11
- package/src/cli/commands/seed.mjs +3 -1
- package/src/cli/commands/state.mjs +9 -3
- package/src/cli/commands/statusline.mjs +5 -1
- package/src/cli/commands/task.mjs +135 -23
- package/src/cli/commands/worktree.mjs +298 -81
- package/src/cli/config/post-merge-sweep.mjs +3 -2
- package/src/cli/config/share-policy.mjs +16 -3
- package/src/cli/config/upgrade-gitignore.mjs +27 -5
- package/src/cli/consistency/parse-qa.mjs +11 -1
- package/src/cli/consistency/parse-review.mjs +36 -0
- package/src/cli/consistency/parse-spec.mjs +43 -0
- package/src/cli/coordination/agent-identity.mjs +6 -4
- package/src/cli/dispatch.mjs +4 -0
- package/src/cli/followups/derive.mjs +123 -0
- package/src/cli/followups/schema.mjs +264 -0
- package/src/cli/gate/gates/followups-adjudicated.mjs +158 -0
- package/src/cli/gate/gates/index.mjs +1 -0
- package/src/cli/git/materialize-env.mjs +212 -0
- package/src/cli/help.mjs +9 -1
- package/src/cli/install/legacy-paths.mjs +5 -0
- package/src/cli/roadmap/lifecycle.mjs +4 -1
- package/src/cli/task/ids.mjs +9 -0
- package/src/cli/task/index-md.mjs +12 -4
- package/src/cli/util/io.mjs +15 -1
- package/src/cli/util/project.mjs +11 -14
- package/src/cli/util/state-paths.mjs +45 -0
- package/prompts/followup_planner.md +0 -399
|
@@ -555,10 +555,12 @@ Read `state.active_tasks[<task-id>].install_status`. Branch on the value:
|
|
|
555
555
|
```
|
|
556
556
|
Do NOT let the failure surface as a downstream "command not found" — the executor's job here is to make the install failure legible. The caller can re-run the task after fixing the install (or invoke with `--no-bootstrap` to skip the install entirely).
|
|
557
557
|
|
|
558
|
+
> **State resolves to the main repo from any cwd (state-fork-fix).** You no longer need to pass the main project root to keep the board coherent: ephemeral `.aperant/` state — `state.json`, `tasks/<id>/` (spec/plan/build-progress), locks, events — resolves to the **one main-repo board** even when `apt-tools` is invoked with `.` from a worktree cwd. The board never forks. (Committable `roadmap/` + `features/` stay worktree-local so they ride the PR branch.) `worktree create --task` likewise anchors at main from any cwd — invoking the **task-mode** create from inside a worktree retargets to the main repo instead of erroring. The **subtask-mode** worktree path below keeps its nested-worktree skip (back-compat only).
|
|
559
|
+
|
|
558
560
|
**2b. Continue with the existing worktree-mode logic:**
|
|
559
561
|
- Run `node packages/framework/bin/apt-tools.mjs detect-worktree .` — if `is_worktree: true`:
|
|
560
562
|
- Log: "Skipping worktree isolation (already in worktree)"
|
|
561
|
-
- Do NOT create worktrees (
|
|
563
|
+
- Do NOT create SUBTASK-mode worktrees from here (the legacy subtask-mode path refuses nesting; task-mode `worktree create --task` is safe — it anchors at main)
|
|
562
564
|
- Agents execute in the current working directory directly
|
|
563
565
|
- Note: locks still coordinate correctly (apt-tools uses shared lock dir via git common dir)
|
|
564
566
|
- If `use_worktrees` is `true` AND `is_worktree` is `false` AND no task-level `worktree_path` is present: set `WORKTREE_MODE=true`
|
|
@@ -85,6 +85,15 @@ node packages/framework/bin/apt-tools.mjs worktree create --task ${task_id}
|
|
|
85
85
|
|
|
86
86
|
(Skip if `state.active_tasks[task_id].worktree_path` is already set — the create command is idempotent.)
|
|
87
87
|
|
|
88
|
+
`worktree create` also materializes the project's stored env blobs (the
|
|
89
|
+
per-project encrypted env store, #354) into the fresh worktree as a best-effort,
|
|
90
|
+
traversal-guarded step — so each fan-out worker's checkout has the real `.env*`
|
|
91
|
+
files instead of crashing in no-cloud mode. The result is surfaced on the
|
|
92
|
+
envelope as `env_materialized` (null when no env is stored). For a long-lived
|
|
93
|
+
worktree whose stored env later drifted, re-copy on demand with
|
|
94
|
+
`node packages/framework/bin/apt-tools.mjs worktree sync-env <dir> --task ${task_id}`
|
|
95
|
+
(the store is the source of truth — sync-env overwrites, never merges).
|
|
96
|
+
|
|
88
97
|
## 3. Spawn N apt-executor subagents
|
|
89
98
|
|
|
90
99
|
Read the `parallelization.max_tasks` cap from `.aperant/config.json` (or default 4). Slice `task_ids` into batches of size `min(cap, task_ids.length)`. For each task in the current batch, dispatch via the host CLI's `Task` tool with `run_in_background: true`:
|
|
@@ -129,7 +138,62 @@ Churned for {Xm Ys} · {K} local agents still running
|
|
|
129
138
|
|
|
130
139
|
The first panel uses `┌─ ... │` (top-with-stem); the LAST panel uses `└─ ... ` (bottom corner). Footer line: "Churned" = elapsed since the most recent lifecycle event across all in-flight workers; "K local agents still running" = count of workers whose `lifecycle_phase` is non-terminal AND `assigned_to` is non-null.
|
|
131
140
|
|
|
132
|
-
## 5.
|
|
141
|
+
## 5. Integration phase — serialize N PRs against the moving base (opt-in)
|
|
142
|
+
|
|
143
|
+
The N workers each opened an independent PR against the same base. Nothing
|
|
144
|
+
ordered or reconciled them — two same-milestone tasks touching overlapping code
|
|
145
|
+
are otherwise only reconciled when a human merges each PR. This phase closes
|
|
146
|
+
that gap. It is **opt-in** via `pipeline.resolve_merge_conflicts` (default
|
|
147
|
+
false) in `.aperant/config.json`; when disabled, skip straight to §6 and let
|
|
148
|
+
the human serialize the PRs (today's report-only behavior — byte-unchanged).
|
|
149
|
+
|
|
150
|
+
When enabled, after all workers reach a terminal state, run the
|
|
151
|
+
`apt-tools merge integrate` command — it resolves the batch's task → branch/PR
|
|
152
|
+
set, computes a **merge order** (topological when `depends_on` edges exist
|
|
153
|
+
among the batch tasks, else a stable alphabetical task-id order), and probes
|
|
154
|
+
each PR's mergeability against the current base via the same `git merge-tree`
|
|
155
|
+
detection `apt:merge-conflict-resolution` uses. It is **read-only** — it never
|
|
156
|
+
merges, rebases, or auto-pushes; it ORDERS and PROBES, you RESOLVE.
|
|
157
|
+
|
|
158
|
+
First fetch the latest base tips so the probes are against the moving base, then
|
|
159
|
+
call `integrate` with the batch's task list (or `--batch ${batch_id}` to recover
|
|
160
|
+
it from the worker rows):
|
|
161
|
+
|
|
162
|
+
```bash
|
|
163
|
+
git -C "$conductor_root" fetch origin "$base_branch"
|
|
164
|
+
node packages/framework/bin/apt-tools.mjs merge integrate . --tasks ${task_ids_csv}
|
|
165
|
+
# OR recover the task list from the batch's worker rows:
|
|
166
|
+
node packages/framework/bin/apt-tools.mjs merge integrate . --batch ${batch_id}
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
Returns a structured integration report:
|
|
170
|
+
```json
|
|
171
|
+
{
|
|
172
|
+
"status": "ok",
|
|
173
|
+
"command": "merge-integrate",
|
|
174
|
+
"order_strategy": "topological",
|
|
175
|
+
"order": ["task-a", "task-b"],
|
|
176
|
+
"summary": { "total": 2, "mergeable": 1, "conflicted": 1, "needs_human": 0 },
|
|
177
|
+
"tasks": [
|
|
178
|
+
{ "task_id": "task-a", "status": "mergeable", "action": "advance", "mergeable": true },
|
|
179
|
+
{ "task_id": "task-b", "status": "conflicted", "action": "resolve-conflict",
|
|
180
|
+
"conflicts_preview": ["src/x.ts"],
|
|
181
|
+
"resolution": { "skill": "apt:merge-conflict-resolution", "worktree_path": "…", "base": "origin/main" } }
|
|
182
|
+
]
|
|
183
|
+
}
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
Walk the `tasks` array **in `order`** (the command already serialized it):
|
|
187
|
+
|
|
188
|
+
1. **`status: "mergeable"`** (`action: "advance"`) → no inter-PR conflict introduced by the branches ordered before it. Nothing to do; continue.
|
|
189
|
+
2. **`status: "conflicted"`** (`action: "resolve-conflict"`) → an earlier-ordered branch conflicts with this one. Hand off to **`/apt:merge-conflict-resolution`** using the entry's `resolution` block (`worktree_path` + `base`); it resolves the markers inline and re-probes. On its non-convergence STOP, leave that branch for the human and note it in the §6 report — do **not** block the remaining branches. After it converges, re-run `merge integrate` to re-probe the rest against the now-updated base.
|
|
190
|
+
3. **`status: "needs-human"` / `"skipped"` / `"unknown"`** → not integrable by the agent (no `pr_url`, missing worktree, or probe-failed). Carry the `reason` into the §6 report and move on.
|
|
191
|
+
|
|
192
|
+
The resolved branches still flow through PR → review → CI — this phase never
|
|
193
|
+
auto-merges. It only ensures each PR is mergeable against the base the prior
|
|
194
|
+
PRs established, so the human's final merge is conflict-free.
|
|
195
|
+
|
|
196
|
+
## 6. Report
|
|
133
197
|
|
|
134
198
|
When all workers reach a terminal state, render the rail one final time. For each shipped worker (lifecycle `shipped-pending-merge` + `pr_url` set), collapse that panel to the SHIPPED variant:
|
|
135
199
|
|
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: apt:merge-conflict-resolution
|
|
3
|
+
description: "Agent-inline merge-conflict resolution — detect conflicts via apt-tools merge, resolve markers inline, re-probe, fall back to STOP"
|
|
4
|
+
apt-skill-version: {{APT_VERSION}}
|
|
5
|
+
stage: ship
|
|
6
|
+
intent: x-merge-resolve
|
|
7
|
+
when_to_use: "A clean fast-forward rebase or merge is impossible because the task branch conflicts with its base (apt:ship §0.7, a fan-out integration sweep, or an apt:watch-ci diverged-bailed branch) and you want the executing agent to resolve the conflicts inline before re-probing mergeability."
|
|
8
|
+
user_invocable: true
|
|
9
|
+
internal: false
|
|
10
|
+
spawns_agent: false
|
|
11
|
+
agent_name: null
|
|
12
|
+
task_context: require-existing
|
|
13
|
+
default_execution_mode: auto
|
|
14
|
+
execution_modes:
|
|
15
|
+
- auto
|
|
16
|
+
- step
|
|
17
|
+
allowed-tools: "Bash, Read, Write, Edit, Grep, Glob"
|
|
18
|
+
argument-hint: "apt:merge-conflict-resolution [--base <ref>] [--head <ref>]"
|
|
19
|
+
gates: []
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
# /apt:merge-conflict-resolution — Agent-Inline Merge Conflict Resolution
|
|
23
|
+
|
|
24
|
+
<objective>
|
|
25
|
+
You are the Aperant merge-conflict resolver. When a task branch can no longer
|
|
26
|
+
fast-forward or rebase cleanly onto its base, you resolve the conflicting
|
|
27
|
+
files **inline** — reading the conflict markers, deciding the correct merged
|
|
28
|
+
content with full repository context, and writing it back — then re-probe
|
|
29
|
+
mergeability and continue. You are the opt-in resolution path the three
|
|
30
|
+
framework merge gates fall into instead of hard-STOPping: `apt:ship` §0.7
|
|
31
|
+
(single-task base-drift), the fan-out integration sweep (inter-PR conflicts
|
|
32
|
+
as each branch lands), and `apt:watch-ci`'s `diverged-bailed` branch
|
|
33
|
+
(self-heal instead of bail).
|
|
34
|
+
|
|
35
|
+
The decisive architectural rule: resolution is **agent-inline**, never a
|
|
36
|
+
programmatic provider client. The framework CLI is self-contained ESM and
|
|
37
|
+
declares no `@aperant/core` dependency, so there is no app credential store
|
|
38
|
+
or LLM transport to call from `.mjs`. The agent driving the CLI is already
|
|
39
|
+
an LLM with a transport — you read the markers `apt-tools merge` surfaces and
|
|
40
|
+
resolve them with your own reasoning. Detection is deterministic (`git
|
|
41
|
+
merge-tree`); resolution is yours.
|
|
42
|
+
|
|
43
|
+
The human stays the final gate. A resolved merge still flows through PR →
|
|
44
|
+
review → CI; you never push to a protected branch and never auto-merge.
|
|
45
|
+
</objective>
|
|
46
|
+
|
|
47
|
+
<your_environment>
|
|
48
|
+
- **Working directory:** The task worktree (or project root) whose branch needs to integrate its base. All `apt-tools` and `git` calls run with this as the cwd / `<project-dir>` argument.
|
|
49
|
+
- **apt-tools path:** `node packages/framework/bin/apt-tools.mjs` (or `node .aperant/deps/node_modules/@aperant/framework/bin/apt-tools.mjs` when running from an install mirror).
|
|
50
|
+
- **Detection primitive:** `apt-tools merge detect <dir> [--base <ref>] [--head <ref>]` — a read-only trial-merge probe (`git merge-tree --write-tree`) that reuses the exact detection from `audit branch-current`. Emits `{ mergeable, conflicts_preview? }`. NO history rewrite, NO index mutation. `--base` defaults to `origin/main`; `--head` defaults to `HEAD`.
|
|
51
|
+
- **Marker reader:** `apt-tools merge markers <dir>` — after a real `git merge`/`git rebase` leaves the worktree conflicted, lists the unmerged paths and reads each file's full content (markers and all) so you can resolve them inline. Emits `{ conflicted, files: [{ path, content }] }`.
|
|
52
|
+
- **git:** You drive the actual `git merge` / `git rebase` / `git add` / `git rebase --continue` yourself — the CLI only observes, it never mutates. Requires git ≥ 2.38 for the `detect` probe.
|
|
53
|
+
</your_environment>
|
|
54
|
+
|
|
55
|
+
<state_files>
|
|
56
|
+
## State Files
|
|
57
|
+
|
|
58
|
+
**Reads:**
|
|
59
|
+
- `.aperant/state.json` — `active_tasks[{task-id}].autonomy` (autonomy gating) and `autonomy.default` fallback.
|
|
60
|
+
- The conflicted source files themselves, via `apt-tools merge markers` (full content with markers).
|
|
61
|
+
|
|
62
|
+
**Writes:**
|
|
63
|
+
- The resolved source files in the worktree (via Edit/Write — your inline resolution).
|
|
64
|
+
- The git index + a merge/rebase-continuation commit, via `git add` + `git commit` / `git rebase --continue` (you drive git; the CLI never does).
|
|
65
|
+
|
|
66
|
+
This skill writes NO `.aperant/` state of its own — it is a leaf resolution
|
|
67
|
+
step invoked by `apt:ship`, `apt:fan-out`, or `apt:watch-ci`, each of which
|
|
68
|
+
owns its own state. Detection (`apt-tools merge detect|markers`) is pure
|
|
69
|
+
read-only.
|
|
70
|
+
</state_files>
|
|
71
|
+
|
|
72
|
+
<process>
|
|
73
|
+
|
|
74
|
+
## 1. Probe mergeability
|
|
75
|
+
|
|
76
|
+
Resolve the base and head refs (defaults: `--base origin/main`, `--head HEAD`).
|
|
77
|
+
Fetch the base first so the probe is against the live remote tip:
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
git -C "$dir" fetch origin "$base_branch"
|
|
81
|
+
node packages/framework/bin/apt-tools.mjs merge detect "$dir" --base "origin/$base_branch"
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
Branch on the envelope:
|
|
85
|
+
|
|
86
|
+
- **`mergeable === true`** → nothing to resolve. Return to the caller (or run the clean rebase the caller requested). DONE.
|
|
87
|
+
- **`mergeable === null`** (`audit_warning: "git-version-too-old"` or `"merge-tree-probe-failed"`) → STOP. You cannot safely probe. Emit the warning verbatim and hand back to the human:
|
|
88
|
+
```
|
|
89
|
+
[APT:merge] Cannot resolve — mergeability is unprobeable ({audit_warning}). Upgrade git ≥ 2.38 or rebase manually, then re-run.
|
|
90
|
+
```
|
|
91
|
+
- **`mergeable === false`** → conflicts exist. Print `conflicts_preview` verbatim and proceed to §2.
|
|
92
|
+
|
|
93
|
+
## 2. Materialize the conflict in the worktree
|
|
94
|
+
|
|
95
|
+
The `detect` probe is read-only — it never touched your index. To resolve, you
|
|
96
|
+
need the real conflicted state on disk. Drive git yourself (the SKILL owns
|
|
97
|
+
history changes, the CLI never does):
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
git -C "$dir" rebase "origin/$base_branch" # or: git -C "$dir" merge "origin/$base_branch"
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
Prefer `rebase` for single-task base-drift (apt:ship §0.7) and the fan-out
|
|
104
|
+
integration sweep so the branch stays linear; prefer `merge` only when the
|
|
105
|
+
caller explicitly asked for it. The command will exit non-zero and leave the
|
|
106
|
+
worktree in a conflicted (rebasing/merging) state — that is expected.
|
|
107
|
+
|
|
108
|
+
## 3. Read the markers + resolve inline
|
|
109
|
+
|
|
110
|
+
```bash
|
|
111
|
+
node packages/framework/bin/apt-tools.mjs merge markers "$dir"
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
For each entry in `files`, the `content` field carries the file verbatim with
|
|
115
|
+
`<<<<<<<` / `=======` / `>>>>>>>` markers. For every conflicted file:
|
|
116
|
+
|
|
117
|
+
1. **Understand both sides.** The `HEAD` side (above `=======`) is the current
|
|
118
|
+
branch's change; the other side (below `=======`, up to `>>>>>>>`) is the
|
|
119
|
+
base's change. Read the surrounding file and, when the conflict is
|
|
120
|
+
semantic, the related modules — you have full repository context the
|
|
121
|
+
deterministic merger does not.
|
|
122
|
+
2. **Resolve with intent, not by picking a side.** Produce the content that
|
|
123
|
+
correctly carries BOTH intents where they are compatible (e.g. both sides
|
|
124
|
+
added an import → keep both; both edited the same function → reconcile the
|
|
125
|
+
two edits). Pick one side only when the changes are genuinely mutually
|
|
126
|
+
exclusive and you can justify which wins.
|
|
127
|
+
3. **Remove every marker.** The resolved file MUST contain no `<<<<<<<`,
|
|
128
|
+
`=======`, or `>>>>>>>` line. Write it back with Edit/Write.
|
|
129
|
+
4. **Stage it.** `git -C "$dir" add "<path>"`.
|
|
130
|
+
|
|
131
|
+
Do this for every conflicted path before continuing.
|
|
132
|
+
|
|
133
|
+
## 4. Continue the merge/rebase
|
|
134
|
+
|
|
135
|
+
```bash
|
|
136
|
+
git -C "$dir" rebase --continue # or: git -C "$dir" commit --no-edit (for a merge)
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
A rebase may surface a SECOND round of conflicts on the next replayed commit.
|
|
140
|
+
If so, loop back to §3 (`apt-tools merge markers` again) and resolve the new
|
|
141
|
+
round. Repeat until the rebase/merge completes.
|
|
142
|
+
|
|
143
|
+
## 5. Re-probe + verify
|
|
144
|
+
|
|
145
|
+
Confirm the branch is now clean against the base and the tree is whole:
|
|
146
|
+
|
|
147
|
+
```bash
|
|
148
|
+
node packages/framework/bin/apt-tools.mjs merge detect "$dir" --base "origin/$base_branch"
|
|
149
|
+
grep -rEn '^(<<<<<<<|=======|>>>>>>>)' "$dir" --include='*.*' && echo "STRAY MARKERS — re-resolve" || true
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
- **`mergeable === true` AND no stray markers** → resolution succeeded. Hand
|
|
153
|
+
back to the caller, which proceeds to its push / PR / re-run-CI step. The
|
|
154
|
+
resolved branch still goes through PR → review → CI; you do NOT auto-merge.
|
|
155
|
+
- **Still `mergeable === false`** → you missed a conflict. Loop back to §3.
|
|
156
|
+
- **Loop budget exhausted** (you have re-entered §3 more than **3** times, or
|
|
157
|
+
the same files keep re-conflicting) → STOP. Abort the in-progress operation
|
|
158
|
+
to leave a clean tree, and hand back to the human:
|
|
159
|
+
```bash
|
|
160
|
+
git -C "$dir" rebase --abort # or: git -C "$dir" merge --abort
|
|
161
|
+
```
|
|
162
|
+
```
|
|
163
|
+
[APT:merge] Could not converge after 3 resolution rounds — handing back. Conflicts: {paths}. Resolve manually, then re-run.
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
## 6. Insertion points (where this skill is invoked from)
|
|
167
|
+
|
|
168
|
+
This skill is the opt-in resolution path for three existing framework gates.
|
|
169
|
+
Each gate decides — by autonomy level + config — whether to fall into this
|
|
170
|
+
skill or keep its legacy hard-STOP. The references are doc-only here; the
|
|
171
|
+
gates document the hand-off in their own SKILL.md:
|
|
172
|
+
|
|
173
|
+
- **`apt:ship` §0.7** — the `mergeable === false` branch. Legacy behavior is a
|
|
174
|
+
hard STOP ("resolve manually"). With resolution opted in, the branch hands
|
|
175
|
+
to §2 of this skill instead, then resumes §1 of apt:ship on success.
|
|
176
|
+
- **`apt:fan-out` integration sweep** — the new serialization phase between
|
|
177
|
+
spawn and report. As each worker's branch lands against the moving base,
|
|
178
|
+
re-probe via `apt-tools merge detect` and resolve inter-PR conflicts here
|
|
179
|
+
before the next branch integrates.
|
|
180
|
+
- **`apt:watch-ci` `diverged-bailed`** — instead of bailing on a rebase
|
|
181
|
+
conflict, run this skill to self-heal, then push the resolved branch and let
|
|
182
|
+
the watcher reschedule.
|
|
183
|
+
|
|
184
|
+
</process>
|
|
185
|
+
|
|
186
|
+
<rationalization>
|
|
187
|
+
Common ways an agent rationalizes the wrong move — and why each is wrong:
|
|
188
|
+
|
|
189
|
+
- "I'll just `git checkout --theirs` / `--ours` to clear the conflict fast." →
|
|
190
|
+
That blindly discards one side's intent. The whole reason this is
|
|
191
|
+
agent-inline (not the deterministic core merger) is that you reconcile BOTH
|
|
192
|
+
intents with repository context. Side-picking is the last resort in §3.2,
|
|
193
|
+
not the default.
|
|
194
|
+
- "The probe said `mergeable: false`, I'll resolve from the `conflicts_preview`
|
|
195
|
+
list without reading the files." → The preview is only a path list. You MUST
|
|
196
|
+
materialize the conflict (§2) and read the actual markers (§3) before
|
|
197
|
+
editing — guessing from filenames produces wrong merges.
|
|
198
|
+
- "I resolved the markers, I can skip the re-probe and push." → Without §5 you
|
|
199
|
+
can ship stray markers or an incomplete rebase. Always re-probe + grep for
|
|
200
|
+
stray markers before handing back.
|
|
201
|
+
- "It's still conflicting after a few tries, I'll force it through." → A
|
|
202
|
+
non-converging conflict is a human decision. After 3 rounds, abort to a clean
|
|
203
|
+
tree and hand back — never leave a half-rebased worktree or force a bad
|
|
204
|
+
resolution into a PR.
|
|
205
|
+
- "I'll just merge the PR since I resolved it." → You are not the final gate.
|
|
206
|
+
Resolved branches flow through PR → review → CI. Never auto-merge.
|
|
207
|
+
</rationalization>
|
|
208
|
+
|
|
209
|
+
<autonomy_interaction>
|
|
210
|
+
Read the active task's autonomy level from `.aperant/state.json`
|
|
211
|
+
(`active_tasks[{task-id}].autonomy`, falling back to `autonomy.default`):
|
|
212
|
+
|
|
213
|
+
- **Autonomy 0–1 (plan-only / step)** — after §1 detects conflicts, print the
|
|
214
|
+
`conflicts_preview` and ask `Resolve these N conflicts inline? [Y/n]` before
|
|
215
|
+
driving the rebase in §2. On `N`, exit so the human can resolve manually.
|
|
216
|
+
After resolving each file in §3, show the diff and confirm before staging at
|
|
217
|
+
higher-stakes files (anything under a path the task did not touch).
|
|
218
|
+
- **Autonomy 2 (auto-chain)** — resolve silently through §2–§5; STOP per §5 on
|
|
219
|
+
non-convergence after 3 rounds.
|
|
220
|
+
- **Autonomy 3 (YOLO)** — same as 2: silent on convergence, STOP on
|
|
221
|
+
non-convergence. Even at YOLO you do NOT auto-merge the resulting PR — the
|
|
222
|
+
human/CI gate is non-negotiable.
|
|
223
|
+
|
|
224
|
+
This skill is recoverable by construction: every STOP path (§1 unprobeable,
|
|
225
|
+
§5 non-convergence) aborts the in-progress git operation to leave a clean tree
|
|
226
|
+
before handing back, so a bailout never strands a half-rebased worktree.
|
|
227
|
+
</autonomy_interaction>
|
|
@@ -26,7 +26,7 @@ Every finding produced by a review agent MUST conform to this schema:
|
|
|
26
26
|
{
|
|
27
27
|
"id": "SEC-001",
|
|
28
28
|
"severity": "critical|high|medium|low",
|
|
29
|
-
"category": "security|quality|logic|codebase-fit|test-integrity|performance|auto-checks",
|
|
29
|
+
"category": "security|quality|logic|codebase-fit|test-integrity|performance|i18n|cross-platform|auto-checks",
|
|
30
30
|
"title": "Short description (max 80 chars)",
|
|
31
31
|
"description": "Detailed explanation of the issue",
|
|
32
32
|
"impact": "Real-world consequences if not fixed",
|
|
@@ -62,7 +62,7 @@ Every finding MUST include all of the following. A finding missing any required
|
|
|
62
62
|
|-------|------|-------------|
|
|
63
63
|
| `id` | `string` | Unique identifier. Format: `{CATEGORY_PREFIX}-{NNN}`. See [ID Prefixes](#id-prefixes) below. |
|
|
64
64
|
| `severity` | `enum` | One of: `critical`, `high`, `medium`, `low`. See [Severity Definitions](#severity-definitions). |
|
|
65
|
-
| `category` | `enum` | One of: `security`, `quality`, `logic`, `codebase-fit`, `test-integrity`, `performance`, `auto-checks`. |
|
|
65
|
+
| `category` | `enum` | One of: `security`, `quality`, `logic`, `codebase-fit`, `test-integrity`, `performance`, `i18n`, `cross-platform`, `auto-checks`. The `i18n` and `cross-platform` categories are emitted only by the two CONDITIONAL specialists, which the orchestrator spawns when `detect-specialists` engages them. |
|
|
66
66
|
| `title` | `string` | Short description, max 80 characters. Must be specific enough to act on without reading the full description. |
|
|
67
67
|
| `description` | `string` | Detailed explanation of what the issue is and why it matters. No filler -- every sentence must add information. |
|
|
68
68
|
| `impact` | `string` | Real-world consequences if this issue is not fixed. Must describe a concrete scenario, not a vague risk statement. |
|
|
@@ -100,6 +100,8 @@ Each category has a standard prefix for finding IDs:
|
|
|
100
100
|
| `codebase-fit` | `FIT` | `FIT-001` |
|
|
101
101
|
| `test-integrity` | `TST` | `TST-001` |
|
|
102
102
|
| `performance` | `PRF` | `PRF-001` |
|
|
103
|
+
| `i18n` | `I18N` | `I18N-001` |
|
|
104
|
+
| `cross-platform` | `XPL` | `XPL-001` |
|
|
103
105
|
| `auto-checks` | `CHK` | `CHK-001` |
|
|
104
106
|
|
|
105
107
|
Each agent numbers its findings sequentially starting from 001.
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: apt:pr-review
|
|
3
|
-
description: "Multi-agent PR review — 6 parallel specialists, validator, fixer, self-reviewer"
|
|
3
|
+
description: "Multi-agent PR review — 6-8 parallel specialists (i18n + cross-platform engage conditionally), validator, fixer, self-reviewer"
|
|
4
4
|
apt-skill-version: {{APT_VERSION}}
|
|
5
5
|
stage: review
|
|
6
6
|
intent: ship
|
|
7
|
-
when_to_use: "Use when the user asks to review a GitHub PR — by number, URL, 'the PR', 'my PR', 'Adam's PR', 'deep-verify this PR'. Spawns 6 parallel specialist agents + validator + fixer + self-reviewer in an isolated worktree. Handles owned (in-session fix loop, auto-push) and external (single-round comment-only) authorship modes, detected automatically."
|
|
7
|
+
when_to_use: "Use when the user asks to review a GitHub PR — by number, URL, 'the PR', 'my PR', 'Adam's PR', 'deep-verify this PR'. Spawns 6-8 parallel specialist agents (6 core + i18n + cross-platform conditionally) + validator + fixer + self-reviewer in an isolated worktree. Handles owned (in-session fix loop, auto-push) and external (single-round comment-only) authorship modes, detected automatically."
|
|
8
8
|
user_invocable: true
|
|
9
9
|
internal: false
|
|
10
10
|
spawns_agent: false
|
|
@@ -21,7 +21,7 @@ gates: []
|
|
|
21
21
|
|
|
22
22
|
# /apt:pr-review -- Multi-Agent PR Review System
|
|
23
23
|
|
|
24
|
-
You are a **senior staff engineer and orchestrator** performing a thorough code review using a team of specialized agents. Your job is to coordinate 6 parallel review agents, validate their findings, synthesize results, and optionally auto-fix issues before the code ships.
|
|
24
|
+
You are a **senior staff engineer and orchestrator** performing a thorough code review using a team of specialized agents. Your job is to coordinate 6-8 parallel review agents (the 6 core specialists, plus the i18n and cross-platform specialists when `detect-specialists` engages them), validate their findings, synthesize results, and optionally auto-fix issues before the code ships.
|
|
25
25
|
|
|
26
26
|
**You orchestrate agents using Claude Code's `Agent` tool.** Review agents write detailed findings to files. Fix agents read those files directly and verify their own work. A self-review agent reviews and fixes autonomously. **Your context stays minimal throughout.**
|
|
27
27
|
|
|
@@ -37,7 +37,7 @@ YOU (Orchestrator) -- LIGHTWEIGHT COORDINATOR ONLY
|
|
|
37
37
|
Phase 0: Set up isolated worktree (for PR/branch reviews)
|
|
38
38
|
Phase 1: Gather diff, create review directory, detect triggers + toolchain
|
|
39
39
|
Phase 2: Spawn 1 agent for auto-checks (runs in worktree)
|
|
40
|
-
Phase 3: Spawn 6 review agents (parallel, read files from worktree)
|
|
40
|
+
Phase 3: Spawn 6-8 review agents (6 core + up to 2 conditional, parallel, read files from worktree)
|
|
41
41
|
Phase 4: Spawn 1 validator agent (reads from worktree)
|
|
42
42
|
Phase 5: Read validated findings, synthesize, write review.json
|
|
43
43
|
Phase 6: Spawn fix agents (edit files in worktree, up to 4 iterations)
|
|
@@ -50,14 +50,20 @@ YOU (Orchestrator) -- LIGHTWEIGHT COORDINATOR ONLY
|
|
|
50
50
|
PHASE 2 -- AUTO-CHECKS (1 agent):
|
|
51
51
|
auto-checks -> Run lint, typecheck, tests using detected toolchain
|
|
52
52
|
|
|
53
|
-
PHASE 3 -- PARALLEL REVIEW (6 agents, independent, all spawned in ONE message):
|
|
54
|
-
security -> OWASP, injection, auth bypass, secrets
|
|
55
|
-
quality -> Error handling, duplication, complexity, naming
|
|
56
|
-
logic -> Off-by-one, null handling, edge cases,
|
|
57
|
-
codebase-fit -> Naming conventions, import patterns,
|
|
58
|
-
test-integrity -> Deleted tests, weakened assertions, coverage
|
|
59
|
-
performance -> N+1 queries, re-renders, memory leaks, bundle
|
|
60
|
-
|
|
53
|
+
PHASE 3 -- PARALLEL REVIEW (6-8 agents, 6 core + up to 2 conditional, independent, all spawned in ONE message):
|
|
54
|
+
security -> OWASP, injection, auth bypass, secrets [core]
|
|
55
|
+
quality -> Error handling, duplication, complexity, naming [core]
|
|
56
|
+
logic -> Off-by-one, null handling, edge cases, races [core]
|
|
57
|
+
codebase-fit -> Naming conventions, import patterns, arch [core]
|
|
58
|
+
test-integrity -> Deleted tests, weakened assertions, coverage [core]
|
|
59
|
+
performance -> N+1 queries, re-renders, memory leaks, bundle [core]
|
|
60
|
+
i18n -> Hardcoded strings, missing locale keys, [conditional —
|
|
61
|
+
locale-unsafe formatting, RTL/encoding engages per
|
|
62
|
+
cross-platform -> Path/line-ending/case-sensitivity, platform detect-specialists]
|
|
63
|
+
APIs, arch/endianness, shell/native portability
|
|
64
|
+
|
|
65
|
+
** The 6 core ALWAYS run. i18n + cross-platform are appended ONLY when **
|
|
66
|
+
** `detect-specialists` engages them (or config forces `always`). **
|
|
61
67
|
** Each has Read/Grep/Glob tools for evidence verification **
|
|
62
68
|
** Each writes DETAILED findings to .aperant/pr-reviews/{review-id}/findings/{name}.md **
|
|
63
69
|
** Each returns ONLY a brief 3-5 line summary to orchestrator **
|
|
@@ -171,13 +177,13 @@ If `downgrades` contains an entry for `review_mode`, display the warning:
|
|
|
171
177
|
[APT] Warning: review_mode requested '{requested}' but host does not support it — using '{resolved}'. {reason}
|
|
172
178
|
```
|
|
173
179
|
|
|
174
|
-
Store `resolved.review_mode` as `REVIEW_MODE`. This determines how the 6 specialist agents in Phase 3 are launched:
|
|
180
|
+
Store `resolved.review_mode` as `REVIEW_MODE`. This determines how the 6-8 specialist agents in Phase 3 are launched (the 6 core plus any conditional specialist engaged in Step 4b):
|
|
175
181
|
|
|
176
|
-
- **`agent-team`**: Use TeamCreate to spawn all
|
|
177
|
-
- **`sub-agents`**: Spawn all
|
|
178
|
-
- **`sequential`**: Run each
|
|
182
|
+
- **`agent-team`**: Use TeamCreate to spawn all selected reviewers (6-8) as a coordinated team
|
|
183
|
+
- **`sub-agents`**: Spawn all selected agents (6-8) in a single message using the Agent tool (current default behavior)
|
|
184
|
+
- **`sequential`**: Run each selected review perspective (6-8) inline, one at a time — the orchestrator adopts each specialist role in sequence, writing findings to the same finding files
|
|
179
185
|
|
|
180
|
-
**Runtime fallback (FRAMEWORK-BUG-003):** if `REVIEW_MODE` resolves to `sub-agents` or `agent-team` BUT the orchestrator runtime doesn't actually expose the `Agent` / `Task` / `TeamCreate` tool (e.g. some host-LLM environments don't propagate `Agent` to nested sub-agents — observed on PR #68 + PR #69 pr-reviews where a general-purpose orchestrator was spawned and lost Agent-tool access), **degrade to `sequential` automatically** and continue. Record the downgrade in `metadata.json` as `review_mode_resolved: 'sequential'` with `review_mode_requested: '<original>'` and `review_mode_downgrade_reason: 'Agent tool not exposed in this runtime'`. Findings rigor is identical — same
|
|
186
|
+
**Runtime fallback (FRAMEWORK-BUG-003):** if `REVIEW_MODE` resolves to `sub-agents` or `agent-team` BUT the orchestrator runtime doesn't actually expose the `Agent` / `Task` / `TeamCreate` tool (e.g. some host-LLM environments don't propagate `Agent` to nested sub-agents — observed on PR #68 + PR #69 pr-reviews where a general-purpose orchestrator was spawned and lost Agent-tool access), **degrade to `sequential` automatically** and continue. Record the downgrade in `metadata.json` as `review_mode_resolved: 'sequential'` with `review_mode_requested: '<original>'` and `review_mode_downgrade_reason: 'Agent tool not exposed in this runtime'`. Findings rigor is identical — same selected perspectives, same evidence rule, same audit gate. Only the spawn shape changes.
|
|
181
187
|
|
|
182
188
|
### Create Workflow Gate
|
|
183
189
|
|
|
@@ -455,6 +461,57 @@ CHANGED_FILES=$(git diff main...HEAD --name-only)
|
|
|
455
461
|
|
|
456
462
|
If the diff is empty, report "No changes to review" and exit.
|
|
457
463
|
|
|
464
|
+
### Step 4b: Detect Conditional Specialists
|
|
465
|
+
|
|
466
|
+
Decide whether the two CONDITIONAL Phase-3 specialists (i18n + cross-platform)
|
|
467
|
+
engage for this project. **The orchestrator does NOT read the diff itself to
|
|
468
|
+
decide** — it calls the deterministic detector and obeys the JSON (spec ID-01).
|
|
469
|
+
|
|
470
|
+
```bash
|
|
471
|
+
# Runs over the worktree (repo baseline) ∪ the PR diff. v1 passes NO --scope
|
|
472
|
+
# flag → defaults to `repo` (spec ID-02a). The --diff is the diff.patch you
|
|
473
|
+
# just wrote.
|
|
474
|
+
SPECIALISTS_JSON=$(node packages/framework/bin/apt-tools.mjs pr-review detect-specialists \
|
|
475
|
+
${WORKTREE_PATH:-.} --diff .aperant/pr-reviews/${REVIEW_ID}/diff.patch)
|
|
476
|
+
```
|
|
477
|
+
|
|
478
|
+
The detector returns:
|
|
479
|
+
|
|
480
|
+
```json
|
|
481
|
+
{
|
|
482
|
+
"i18n": { "engage": true, "signals": [{ "kind": "...", "detail": "...", "tier": "strong|weak" }], "reason": "strong: locale-file src/locales/fr.json" },
|
|
483
|
+
"crossplatform": { "engage": false, "signals": [], "reason": "no signals" }
|
|
484
|
+
}
|
|
485
|
+
```
|
|
486
|
+
|
|
487
|
+
Engagement precedence (the detector encodes it; you just read the result):
|
|
488
|
+
config `pr_review.specialists.{i18n,crossplatform}` ∈ `auto|always|never` (default
|
|
489
|
+
`auto`) is checked FIRST and is absolute — `always` engages with no scan,
|
|
490
|
+
`never` skips with no scan (even when the diff introduces the first locale
|
|
491
|
+
file). Otherwise `auto` defers to the STRONG/WEAK tier scan.
|
|
492
|
+
|
|
493
|
+
**Write the result into `metadata.json` under `conditional_specialists`** (ID-05)
|
|
494
|
+
so the decision is auditable, and **emit one visible ENGAGED/SKIPPED line per
|
|
495
|
+
conditional specialist** in your orchestrator output. A config-`never` skip MUST
|
|
496
|
+
be distinguishable from a no-signal skip (the `reason` names the override
|
|
497
|
+
verbatim, e.g. `config override: never`):
|
|
498
|
+
|
|
499
|
+
```jsonc
|
|
500
|
+
// metadata.json (additive key)
|
|
501
|
+
"conditional_specialists": {
|
|
502
|
+
"i18n": { "engaged": true, "reason": "strong: locale-file src/locales/fr.json" },
|
|
503
|
+
"crossplatform": { "engaged": false, "reason": "no signals" }
|
|
504
|
+
}
|
|
505
|
+
```
|
|
506
|
+
|
|
507
|
+
```
|
|
508
|
+
i18n: ENGAGED (strong: locale-file src/locales/fr.json)
|
|
509
|
+
crossplatform: SKIPPED (no platform signals; config: auto)
|
|
510
|
+
```
|
|
511
|
+
|
|
512
|
+
Store `result.i18n.engage` and `result.crossplatform.engage` as `ENGAGE_I18N` /
|
|
513
|
+
`ENGAGE_CROSSPLATFORM` for Phase 3.
|
|
514
|
+
|
|
458
515
|
**R3: pin the reviewed head SHA (PR reviews only).** After `gh pr diff` fetches into `pr-review-${REVIEW_ID}`, capture the SHA and pass it to `pr-review start-round`. All subsequent evidence reads within this round should reference this pinned SHA, not a fresh `gh pr view` call — otherwise a mid-round force-push invalidates cited line numbers.
|
|
459
516
|
|
|
460
517
|
```bash
|
|
@@ -782,7 +839,7 @@ DO NOT return full error output in your response -- write it to the file.
|
|
|
782
839
|
node packages/framework/bin/apt-tools.mjs workflow advance . --id ${REVIEW_ID} --phase specialist-review
|
|
783
840
|
```
|
|
784
841
|
|
|
785
|
-
**CRITICAL: Spawn all
|
|
842
|
+
**CRITICAL: Spawn all SELECTED review agents (6-8) in ONE message using parallel Agent tool calls.** The 6 core specialists ALWAYS spawn. Additionally append the **i18n** agent when `ENGAGE_I18N` is true and the **cross-platform** agent when `ENGAGE_CROSSPLATFORM` is true (from Step 4b). So the set is 6, 7, or 8 agents — all in the SAME message.
|
|
786
843
|
|
|
787
844
|
Each agent receives:
|
|
788
845
|
1. The changed file list
|
|
@@ -795,7 +852,7 @@ Each agent receives:
|
|
|
795
852
|
|
|
796
853
|
### Agent Spawning Pattern
|
|
797
854
|
|
|
798
|
-
In a SINGLE message, make 6 Agent tool calls:
|
|
855
|
+
In a SINGLE message, make 6-8 Agent tool calls (the 6 core below, plus each engaged conditional specialist):
|
|
799
856
|
|
|
800
857
|
```
|
|
801
858
|
Agent(
|
|
@@ -841,9 +898,29 @@ Agent(
|
|
|
841
898
|
)
|
|
842
899
|
```
|
|
843
900
|
|
|
901
|
+
**Conditional specialists — include each ONLY when Step 4b engaged it:**
|
|
902
|
+
|
|
903
|
+
```
|
|
904
|
+
# Append ONLY if ENGAGE_I18N is true:
|
|
905
|
+
Agent(
|
|
906
|
+
name: "i18n-reviewer",
|
|
907
|
+
subagent_type: "apt-pr-review-i18n",
|
|
908
|
+
description: "Internationalization review of PR changes",
|
|
909
|
+
prompt: "{CONSTRUCTED_PROMPT_WITH_FILLED_PLACEHOLDERS}",
|
|
910
|
+
)
|
|
911
|
+
|
|
912
|
+
# Append ONLY if ENGAGE_CROSSPLATFORM is true:
|
|
913
|
+
Agent(
|
|
914
|
+
name: "crossplatform-reviewer",
|
|
915
|
+
subagent_type: "apt-pr-review-crossplatform",
|
|
916
|
+
description: "Cross-platform review of PR changes",
|
|
917
|
+
prompt: "{CONSTRUCTED_PROMPT_WITH_FILLED_PLACEHOLDERS}",
|
|
918
|
+
)
|
|
919
|
+
```
|
|
920
|
+
|
|
844
921
|
### Constructing Agent Prompts
|
|
845
922
|
|
|
846
|
-
For each
|
|
923
|
+
For each SELECTED specialist agent (the 6 core + any engaged conditional), read the agent definition from `.claude/agents/apt-pr-review-{name}.md` and fill in these placeholders:
|
|
847
924
|
|
|
848
925
|
| Placeholder | Value |
|
|
849
926
|
|-------------|-------|
|
|
@@ -854,7 +931,7 @@ For each of the 6 specialist agents, read the agent definition from `.claude/age
|
|
|
854
931
|
| `[WORKTREE_PATH]` | The worktree path from Phase 0 (or `.` for HEAD vs main / staged reviews) |
|
|
855
932
|
| `[LOCKED_DECISIONS]` | **(R6)** ≤500-token digest from `.aperant/context/notes/{task-id}.md` if a task-id can be derived from the PR/branch. Empty string if no ledger found. |
|
|
856
933
|
|
|
857
|
-
**R6 — Decision ledger inject (required):** Before spawning the
|
|
934
|
+
**R6 — Decision ledger inject (required):** Before spawning the specialist agents, look for `.aperant/context/notes/{task-id}.md` (where task-id is parseable from the PR branch name or the latest task directory). If found, read the file and extract a ≤500-token digest of locked decisions. Pass it into every specialist prompt as `[LOCKED_DECISIONS]` so reviewers don't flag decisions the team already settled. If no ledger exists, pass an empty string and skip the block.
|
|
858
935
|
|
|
859
936
|
Append to each agent prompt:
|
|
860
937
|
|
|
@@ -898,7 +975,7 @@ If the diff exceeds approximately 3000 lines:
|
|
|
898
975
|
|
|
899
976
|
### Waiting for Completion
|
|
900
977
|
|
|
901
|
-
Wait for all
|
|
978
|
+
Wait for all selected agents (6-8) to complete. Each returns a brief 3-5 line summary:
|
|
902
979
|
- Finding count
|
|
903
980
|
- Severity breakdown
|
|
904
981
|
- Most critical issue (if any)
|
|
@@ -949,7 +1026,8 @@ Review ID: {REVIEW_ID}
|
|
|
949
1026
|
Review Directory: {REVIEW_DIR}
|
|
950
1027
|
|
|
951
1028
|
Read all finding files from {REVIEW_DIR}/findings/ (excluding validated.md if it exists).
|
|
952
|
-
The finding files are: security.md, quality.md, logic.md, codebase-fit.md, test-integrity.md, performance.md
|
|
1029
|
+
The core finding files are: security.md, quality.md, logic.md, codebase-fit.md, test-integrity.md, performance.md.
|
|
1030
|
+
Additionally read i18n.md and/or crossplatform.md when present (the conditional specialists write them only when engaged).
|
|
953
1031
|
|
|
954
1032
|
For each finding in each file, run the hypothesis-validation process from your instructions.
|
|
955
1033
|
|
|
@@ -1031,13 +1109,19 @@ Score each dimension 1-10 based on validated findings:
|
|
|
1031
1109
|
| Dimension | What lowers the score |
|
|
1032
1110
|
|-----------|----------------------|
|
|
1033
1111
|
| Security | Security findings (critical = -4, high = -2, medium = -1) |
|
|
1034
|
-
| Quality | Quality findings (same scale) |
|
|
1112
|
+
| Quality | Quality findings **and `i18n` findings** (same scale) |
|
|
1035
1113
|
| Logic | Logic findings (same scale) |
|
|
1036
|
-
| Architecture | Codebase-fit findings (same scale) |
|
|
1114
|
+
| Architecture | Codebase-fit findings **and `cross-platform` findings** (same scale) |
|
|
1037
1115
|
| Performance | Performance findings (same scale) |
|
|
1038
1116
|
|
|
1039
1117
|
Start at 10 for each dimension. Subtract based on finding severity. Floor at 1.
|
|
1040
1118
|
|
|
1119
|
+
> The two conditional categories fold into existing dimensions (lower-churn,
|
|
1120
|
+
> per spec ID-04 — no new `scores` key in `review.json`): `i18n` findings
|
|
1121
|
+
> reduce **Quality**, `cross-platform` findings reduce **Architecture**
|
|
1122
|
+
> (compatibility is an architecture concern). They only contribute when the
|
|
1123
|
+
> orchestrator spawned that conditional specialist.
|
|
1124
|
+
|
|
1041
1125
|
### Step 6: Determine Assessment
|
|
1042
1126
|
|
|
1043
1127
|
| Assessment | Condition |
|
|
@@ -1223,7 +1307,7 @@ A specialist agent MAY emit a new finding in verification phase if ALL three hol
|
|
|
1223
1307
|
|
|
1224
1308
|
The agent marks the finding with `regression_from_fix: true` and `regression_from_fix_round: {PRIOR_ROUND}`. The validator (Phase 4) honors this field and does NOT dismiss the finding as "out-of-scope for verification phase." Medium/low regressions are silently skipped — they'll be caught by the author or by a future cycle.
|
|
1225
1309
|
|
|
1226
|
-
Each
|
|
1310
|
+
Each Phase 3 specialist agent definition (the 6 core + the 2 conditional) carries a `## Regression Detection (verification rounds only)` block with this carve-out written out.
|
|
1227
1311
|
|
|
1228
1312
|
### Iteration Loop (owned mode — max 4 iterations, discovery/verification split)
|
|
1229
1313
|
|
|
@@ -1389,7 +1473,7 @@ git diff > .aperant/pr-reviews/${REVIEW_ID}/iterations/${ITERATION}/diff.patch
|
|
|
1389
1473
|
If fixes were applied:
|
|
1390
1474
|
|
|
1391
1475
|
1. Capture the new diff (post-fix changes vs the original base)
|
|
1392
|
-
2. Spawn fresh review agents (same 6
|
|
1476
|
+
2. Spawn fresh review agents (the same selected specialists — 6 core + any conditional engaged in Step 4b) on the NEW code state
|
|
1393
1477
|
3. Each fresh agent writes to `.aperant/pr-reviews/${REVIEW_ID}/iterations/${ITERATION}/findings/`
|
|
1394
1478
|
4. Spawn a fresh validator on the new findings
|
|
1395
1479
|
5. Read validated results
|
|
@@ -1774,7 +1858,7 @@ Fix agents self-report their outcome via a status line (`FIXED: X | FAILED: Y |
|
|
|
1774
1858
|
### Mistake 2: Spawning the Phase 3 REVIEW Agents Sequentially
|
|
1775
1859
|
|
|
1776
1860
|
**Wrong:** Spawn security agent, wait, spawn quality agent, wait, etc.
|
|
1777
|
-
**Right:** Spawn all
|
|
1861
|
+
**Right:** Spawn all selected review agents (6-8) in ONE message using parallel Agent tool calls. They run concurrently.
|
|
1778
1862
|
|
|
1779
1863
|
> Scope note: this applies ONLY to the Phase 3 review specialists, which are read-only (Read/Grep/Glob,
|
|
1780
1864
|
> no Edit/Bash, no git writes) and therefore cannot race the index. The Phase 6 FIXERS are the
|
|
@@ -1817,7 +1901,7 @@ Fix agents self-report their outcome via a status line (`FIXED: X | FAILED: Y |
|
|
|
1817
1901
|
|
|
1818
1902
|
### Mistake 9: Processing All Agent Files in Orchestrator Context
|
|
1819
1903
|
|
|
1820
|
-
**Wrong:** Reading all 6 finding files + validated.md in one go, causing context bloat.
|
|
1904
|
+
**Wrong:** Reading all 6-8 finding files + validated.md in one go, causing context bloat.
|
|
1821
1905
|
**Right:** In Phase 5 synthesis, read validated.md first (it has the condensed verdicts). Only read original agent files if you need to resolve a specific cross-validation question.
|
|
1822
1906
|
|
|
1823
1907
|
### Mistake 10: Spawning Fixers for Non-Fixable Findings
|
|
@@ -1850,6 +1934,8 @@ Fix agents self-report their outcome via a status line (`FIXED: X | FAILED: Y |
|
|
|
1850
1934
|
| `pipeline.skip_review` | boolean | false | If true, `/apt:run` skips the review phase. Does not affect direct `/apt:pr-review` invocation. |
|
|
1851
1935
|
| `review.max_iterations` | number | 4 | Maximum fix-review iterations before stopping. |
|
|
1852
1936
|
| `review.optional_agents` | string[] | [] | Reserved for future use. Additional specialist agents to spawn beyond the core 6. |
|
|
1937
|
+
| `pr_review.specialists.i18n` | `"auto"\|"always"\|"never"` | `"auto"` | Override for the conditional i18n specialist. `always` forces engage, `never` forces skip (over the detector AND over a diff-introduced signal), `auto`/absent defers to `detect-specialists`. Override is the TOP of the precedence chain (ID-01a). |
|
|
1938
|
+
| `pr_review.specialists.crossplatform` | `"auto"\|"always"\|"never"` | `"auto"` | Override for the conditional cross-platform specialist. Same semantics as `pr_review.specialists.i18n`. |
|
|
1853
1939
|
|
|
1854
1940
|
---
|
|
1855
1941
|
|
|
@@ -1877,6 +1963,8 @@ Agent(
|
|
|
1877
1963
|
| Codebase-fit reviewer | `.claude/agents/apt-pr-review-codebase-fit.md` | Read, Write, Grep, Glob | 3 |
|
|
1878
1964
|
| Test-integrity reviewer | `.claude/agents/apt-pr-review-test-integrity.md` | Read, Write, Grep, Glob | 3 |
|
|
1879
1965
|
| Performance reviewer | `.claude/agents/apt-pr-review-performance.md` | Read, Write, Grep, Glob | 3 |
|
|
1966
|
+
| i18n reviewer **(conditional)** | `.claude/agents/apt-pr-review-i18n.md` | Read, Write, Grep, Glob | 3 — spawned only when `detect-specialists` engages i18n (or config `always`) |
|
|
1967
|
+
| Cross-platform reviewer **(conditional)** | `.claude/agents/apt-pr-review-crossplatform.md` | Read, Write, Grep, Glob | 3 — spawned only when `detect-specialists` engages crossplatform (or config `always`) |
|
|
1880
1968
|
| Finding validator | `.claude/agents/apt-pr-review-validator.md` | Read, Write, Grep, Glob | 4 |
|
|
1881
1969
|
| Fix agent (x3) | `.claude/agents/apt-pr-review-fixer.md` | Read, Write, Edit, Bash, Grep, Glob | 6 |
|
|
1882
1970
|
| Self-reviewer | `.claude/agents/apt-pr-review-self-reviewer.md` | Read, Write, Edit, Bash, Grep, Glob | 7 |
|