@aperant/framework 0.13.0 → 0.15.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 +87 -0
- package/README.md +1 -1
- package/agents/apt-pr-review-i18n.md +190 -0
- package/agents/apt-pr-review-xplatform.md +189 -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/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 +980 -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 +4 -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-i18n.md +190 -0
- package/dist/plugin/agents/apt-pr-review-xplatform.md +189 -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_i18n_agent.md +279 -0
- package/prompts/github/pr_xplatform_agent.md +283 -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/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 +1023 -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 +4 -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
|
@@ -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
|
+
"xplatform": { "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,xplatform}` ∈ `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
|
+
"xplatform": { "engaged": false, "reason": "no signals" }
|
|
504
|
+
}
|
|
505
|
+
```
|
|
506
|
+
|
|
507
|
+
```
|
|
508
|
+
i18n: ENGAGED (strong: locale-file src/locales/fr.json)
|
|
509
|
+
xplatform: SKIPPED (no platform signals; config: auto)
|
|
510
|
+
```
|
|
511
|
+
|
|
512
|
+
Store `result.i18n.engage` and `result.xplatform.engage` as `ENGAGE_I18N` /
|
|
513
|
+
`ENGAGE_XPLATFORM` 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_XPLATFORM` 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_XPLATFORM is true:
|
|
913
|
+
Agent(
|
|
914
|
+
name: "xplatform-reviewer",
|
|
915
|
+
subagent_type: "apt-pr-review-xplatform",
|
|
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 xplatform.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.xplatform` | `"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-xplatform.md` | Read, Write, Grep, Glob | 3 — spawned only when `detect-specialists` engages xplatform (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 |
|
|
@@ -29,7 +29,7 @@ Execute a small task quickly without full pipeline overhead. For small fixes, do
|
|
|
29
29
|
- **Working directory:** The project root (where you were invoked) UNLESS an active task has a task-level worktree (see below).
|
|
30
30
|
- **Constitution:** Read `AGENTS.md` in the project root if it exists
|
|
31
31
|
- **State directory:** `.aperant/quick/{task-id}/`
|
|
32
|
-
- **Task-level worktree isolation:**
|
|
32
|
+
- **Task-level worktree isolation:** Use the `worktree_path` the router passed in skill context (router path) OR that §1a parsed from `task create`'s envelope (direct path) — this is the worktree `task create` literally just provisioned for this task. When present, run all editing Bash commands with `cd {worktree_path} &&` prefix so the fix lands on the task branch. `apt-tools` calls still take the project root as `<project-dir>` so they coordinate through the main repo's shared `.aperant/`. The quick task's `.aperant/quick/{task-id}/` directory lives in the main repo, not the worktree. (Last-resort fallback only: if neither source supplied a `worktree_path` but `.aperant/state.json` has an active task with one, you may use that.)
|
|
33
33
|
</your_environment>
|
|
34
34
|
|
|
35
35
|
<state_files>
|
|
@@ -82,6 +82,15 @@ Sequence:
|
|
|
82
82
|
|
|
83
83
|
The task id is now canonical (no more `quick-YYYYMMDD-*` invention). `QuickTaskSchema` accepts both the canonical `{slug}_YY-MM-DD` form and the legacy `quick-YYYYMMDD-{slug}` form for back-compat with already-shipped task records on disk.
|
|
84
84
|
|
|
85
|
+
**Worktree isolation (both paths).** `task create` provisions a worktree when `task_isolation.worktree_per_task` is enabled (track-agnostic — QUICK gets one too). Parse `worktree.worktree_path`, `worktree.branch`, and `worktree.base_branch` from the `task create` envelope (direct path); on the router path the orchestrator already passed `worktree_path` into your skill context — use that. When a `worktree` block is present, print the banner and run all subsequent editing Bash commands with `cd {worktree_path} &&`:
|
|
86
|
+
|
|
87
|
+
```
|
|
88
|
+
[APT] Working in isolated worktree: {worktree_path}
|
|
89
|
+
[APT] Task branch: {branch} (from {base_branch})
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
If no `worktree` block is returned (isolation off, no host support, or already inside a worktree), proceed in the project root as before. `apt-tools` calls always take the project root as `<project-dir>`.
|
|
93
|
+
|
|
85
94
|
### 1b. Create QUICK working directory
|
|
86
95
|
|
|
87
96
|
```bash
|
|
@@ -205,6 +214,20 @@ Use appropriate conventional commit type:
|
|
|
205
214
|
|
|
206
215
|
## 7. Record Task
|
|
207
216
|
|
|
217
|
+
**Persistence & git (quick records follow `share.tasks`).** Quick-task records
|
|
218
|
+
live under `.aperant/quick/{task-id}/` and are governed by the SAME share policy
|
|
219
|
+
as full-task artifacts (`.aperant/.gitignore` is policy-driven — see
|
|
220
|
+
`share-policy.mjs`). Two rules:
|
|
221
|
+
|
|
222
|
+
- `.aperant/quick/INDEX.md` is a **derived** index — it is ALWAYS gitignored
|
|
223
|
+
(regenerated from the per-task records, like `tasks/INDEX.md`). Never
|
|
224
|
+
`git add` it. Writing/updating it leaves no dirty tracked file.
|
|
225
|
+
- The per-task record directory follows `share.tasks`. When sharing is **off**
|
|
226
|
+
(the `solo` default), the records are gitignored — write them and do nothing
|
|
227
|
+
else. When `share.tasks` is **on**, the records are committable; stage
|
|
228
|
+
`.aperant/quick/{task-id}/` alongside the code commit in Step 6 (or in a
|
|
229
|
+
follow-up `chore` commit) so they ride into version control like task specs.
|
|
230
|
+
|
|
208
231
|
Write `.aperant/quick/{task-id}/TASK.md`:
|
|
209
232
|
|
|
210
233
|
```markdown
|
|
@@ -276,6 +276,12 @@ node packages/framework/bin/apt-tools.mjs commit "fix: {finding title}" --files
|
|
|
276
276
|
|
|
277
277
|
Update `review.json` with final state after the loop completes (findings resolved vs remaining, iteration count).
|
|
278
278
|
|
|
279
|
+
### Follow-ups: `in-pr` rows execute ONLY inside this loop (G45)
|
|
280
|
+
|
|
281
|
+
A follow-up ledger row whose `class_proposed: 'in-pr'` may be executed **only inside this pre-ship fix-all loop** — the loop already re-verifies, re-reviews the fixed files, rewrites `review.json`, and re-scores `qa_signoff.json` (§6b), so there is no stale-artifact problem (ID-10). When you fix an `in-pr` row here, flip its `{task_dir}/followups.json` row `status: 'fixed'` (optionally recording `executed_commit`).
|
|
282
|
+
|
|
283
|
+
Discoveries made AFTER review (or outside this loop) may NOT take the in-PR path — executing them post-review would stale the QA evidence. Route those to `new-task` (file via the triage machine at close-task) or trigger a bounded re-review instead.
|
|
284
|
+
|
|
279
285
|
## 6. Update Task Documentation
|
|
280
286
|
|
|
281
287
|
After fixes are applied, update the task artifacts to reflect what happened:
|
package/skills/apt-run/SKILL.md
CHANGED
|
@@ -103,7 +103,7 @@ If `.aperant/config.json` has `task_isolation.worktree_per_task: true` AND the h
|
|
|
103
103
|
node packages/framework/bin/apt-tools.mjs task create . --description "{task}" --track {track} --autonomy {autonomy}
|
|
104
104
|
```
|
|
105
105
|
|
|
106
|
-
Parse `worktree.worktree_path`, `worktree.branch`, and `worktree.base_branch` from the result. For every subsequent step in this pipeline, prefix Bash commands with `cd {worktree_path} &&` OR pass `worktree_path` as the spawned agent's `cwd`. `apt-tools` commands
|
|
106
|
+
Parse `worktree.worktree_path`, `worktree.branch`, and `worktree.base_branch` from the result. For every subsequent step in this pipeline, prefix Bash commands with `cd {worktree_path} &&` OR pass `worktree_path` as the spawned agent's `cwd`. **Ephemeral `.aperant/` state resolves to the main repo from any cwd automatically** (state-fork-fix): `apt-tools` commands may receive `.` (or the worktree path) as their `<project-dir>` — `state.json` + `tasks/<task-id>/` (spec/plan/progress) and locks/events all resolve to the one main-repo `.aperant/` board, so the board never forks into a worktree. (Committable artifacts like `roadmap/` + `features/` stay worktree-local so they ride the PR branch.) `worktree create --task` likewise anchors at main from any cwd — invoking it from inside a worktree creates the new task worktree under the **main** repo's `.aperant/worktrees/` instead of erroring.
|
|
107
107
|
|
|
108
108
|
Otherwise fall back to the legacy branch flow:
|
|
109
109
|
|
|
@@ -199,7 +199,7 @@ AskUserQuestion([
|
|
|
199
199
|
|
|
200
200
|
**Routing:**
|
|
201
201
|
- "Verification" → jump to **Step 2** (Batch 1 + Batch 2 only), then skip to **Step 4** (mapping) and **Step 5** (write)
|
|
202
|
-
- "Pipeline" → jump to **Step 3** (Batch 2: auto-branch, code review, TDD, PR Review Auto-Suggest, **Sparring Auto-Fire**) AND **Step 3b** (Batch 3 only, including Diagram Mode), then skip to **Step 4** and **Step 5**
|
|
202
|
+
- "Pipeline" → jump to **Step 3** (Batch 2: auto-branch, code review, TDD, PR Review Auto-Suggest, CI Watcher, **Sparring Auto-Fire**) AND **Step 3b** (Batch 3 only, including Diagram Mode), then skip to **Step 4** and **Step 5**
|
|
203
203
|
- "Orchestration" → jump to **Step 3c** (Batch 4 only), then skip to **Step 4** and **Step 5**
|
|
204
204
|
- "Team Collaboration" → jump to **Step 3d** (Batch 5 only), then skip to **Step 4** and **Step 5**
|
|
205
205
|
- "Visibility" → jump to **Step 3e** (Batch 6 only), then skip to **Step 4** and **Step 5**
|
|
@@ -412,6 +412,16 @@ AskUserQuestion([
|
|
|
412
412
|
{ label: "Ask me", description: "Prompt [Y/n] each time — choose per-PR." },
|
|
413
413
|
{ label: "Never", description: "Silent. Run /apt:pr-review manually if needed." }
|
|
414
414
|
]
|
|
415
|
+
},
|
|
416
|
+
{
|
|
417
|
+
question: "After /apt:ship opens a PR, run the post-ship CI watcher? It polls checks, auto-fixes the first red check and pushes, and can auto-merge once CI is green.",
|
|
418
|
+
header: "CI Watcher",
|
|
419
|
+
multiSelect: false,
|
|
420
|
+
options: [
|
|
421
|
+
{ label: "Watch & auto-fix (Recommended)", description: "Ship auto-arms the watcher: it polls CI, fixes the first red check + pushes, then stops at green for you to merge. Ticks automatically on cron-capable hosts (Claude Code/Pi); elsewhere you advance ticks manually with /apt:watch-ci --tick." },
|
|
422
|
+
{ label: "Watch, fix & auto-merge on green", description: "Same as above, plus auto-merges the PR (squash) once CI is green, then suggests /apt:close-task. Fully hands-off run." },
|
|
423
|
+
{ label: "Off", description: "Ship does not arm the watcher. Watch CI and merge yourself, or run /apt:watch-ci manually." }
|
|
424
|
+
]
|
|
415
425
|
}
|
|
416
426
|
])
|
|
417
427
|
```
|
|
@@ -728,8 +738,8 @@ AskUserQuestion([
|
|
|
728
738
|
options: [
|
|
729
739
|
{ label: "Auto", description: "Best available for your CLI" },
|
|
730
740
|
{ label: "Agent Team", description: "Uses Claude Code agent teams (requires CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1)" },
|
|
731
|
-
{ label: "Sub-Agents", description: "Spawns 6 parallel sub-agents for review (available on Claude Code and Codex)" },
|
|
732
|
-
{ label: "Sequential", description: "Runs 6 review passes inline, one at a time — works on any CLI" }
|
|
741
|
+
{ label: "Sub-Agents", description: "Spawns 6-8 parallel sub-agents for review (available on Claude Code and Codex)" },
|
|
742
|
+
{ label: "Sequential", description: "Runs 6-8 review passes inline, one at a time — works on any CLI" }
|
|
733
743
|
]
|
|
734
744
|
},
|
|
735
745
|
{
|
|
@@ -1378,6 +1388,13 @@ Map the user's selections to config values:
|
|
|
1378
1388
|
- "Ask me" → `pr_review.suggest_after_ship: "ask"`
|
|
1379
1389
|
- "Never" → `pr_review.suggest_after_ship: "never"`
|
|
1380
1390
|
|
|
1391
|
+
**CI Watcher (post-ship):** maps to the SHARED `.aperant/config.json` `ci_watch` block (team policy — NOT a per-device AUDIT-001 field, so it stays in shared `config.json`):
|
|
1392
|
+
- "Watch & auto-fix (Recommended)" → `ci_watch.after_ship: "auto"`, `ci_watch.auto_merge_on_green: false`
|
|
1393
|
+
- "Watch, fix & auto-merge on green" → `ci_watch.after_ship: "auto"`, `ci_watch.auto_merge_on_green: true`
|
|
1394
|
+
- "Off" → `ci_watch.after_ship: "never"`, `ci_watch.auto_merge_on_green: false`
|
|
1395
|
+
|
|
1396
|
+
The existing `ci_watch.merge_method` key (default `"squash"`) is preserved untouched — this question does not change it. On non-cron hosts, `after_ship: "auto"` still creates the watcher state and ship prints manual-tick instructions; the host-capability fallback already lives in `apt-ship/SKILL.md` §7.2, so the value is safe to store as team policy regardless of the setup-runner's host.
|
|
1397
|
+
|
|
1381
1398
|
**Sparring Auto-Fire (FRAMEWORK-RFC-001):**
|
|
1382
1399
|
- Phase 1 "No" → `spar.enabled: false`, ask Phase 3 (hint sub-picker)
|
|
1383
1400
|
- Phase 1 "Yes" → `spar.enabled: true`, ask Phase 2 (partner picker)
|
|
@@ -1522,6 +1539,7 @@ Display:
|
|
|
1522
1539
|
| Auto Branch | {Yes/No} |
|
|
1523
1540
|
| Code Review | {Yes/No} |
|
|
1524
1541
|
| TDD Iron Law | {Yes/No} |
|
|
1542
|
+
| CI Watcher | {Off / Watch & fix / Watch, fix & auto-merge} |
|
|
1525
1543
|
| Sparring Auto-Fire | {Off / On (codex), On (claude), On (gemini)} (hint: {Yes/No}) |
|
|
1526
1544
|
| Date Format | {DD-MM-YY / MM-DD-YY / YY-MM-DD} |
|
|
1527
1545
|
| Time Format | {24h / 12h} |
|
package/skills/apt-ship/SKILL.md
CHANGED
|
@@ -20,6 +20,7 @@ gates:
|
|
|
20
20
|
- constitution-read
|
|
21
21
|
- verify-approved
|
|
22
22
|
- review-clean
|
|
23
|
+
- followups-adjudicated
|
|
23
24
|
- consistency-check
|
|
24
25
|
- r-persona-alignment
|
|
25
26
|
- gitignore-in-sync
|
|
@@ -149,15 +150,18 @@ Capture `remote_tip_sha_pre_rebase` now — §6's lease uses it.
|
|
|
149
150
|
```
|
|
150
151
|
Proceed to §1. §6's push will use `--force-with-lease=refs/heads/<branch>:$remote_tip_sha_pre_rebase` because history was rewritten.
|
|
151
152
|
|
|
152
|
-
- **`behind > 0` AND `mergeable === false`** →
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
153
|
+
- **`behind > 0` AND `mergeable === false`** → the rebase would conflict. Default behavior is a hard STOP; AI resolution is **opt-in** via `pipeline.resolve_merge_conflicts` (default false) in `.aperant/config.json`.
|
|
154
|
+
|
|
155
|
+
- **Resolution opted in (`pipeline.resolve_merge_conflicts === true`)** → hand off to **`/apt:merge-conflict-resolution`** (`--base origin/{base_branch}`). That skill drives the rebase, resolves the conflicted files inline (reading the markers via `apt-tools merge markers`), and re-probes mergeability. On success it returns here — proceed to §1 with `--force-with-lease=refs/heads/<branch>:$remote_tip_sha_pre_rebase` (history was rewritten). On its non-convergence STOP, it aborts to a clean tree and hands back; fall through to the manual-STOP message below.
|
|
156
|
+
- **Resolution NOT opted in (default)** → STOP. Emit a structured error with the conflict preview verbatim:
|
|
157
|
+
```
|
|
158
|
+
[APT:ship] Cannot ship — task branch is behind origin/{base_branch} and the rebase would conflict.
|
|
159
|
+
Conflicts preview:
|
|
160
|
+
- {path1}
|
|
161
|
+
- {path2}
|
|
162
|
+
Resolve manually (rebase or merge in the worktree) or enable pipeline.resolve_merge_conflicts to use /apt:merge-conflict-resolution, then re-run /apt:ship.
|
|
163
|
+
```
|
|
164
|
+
Exit the skill — do NOT auto-resolve, do NOT proceed to §5 or §6.
|
|
161
165
|
|
|
162
166
|
- **`mergeable === null` AND `audit_warning === "git-version-too-old"`** → STOP with a friendlier message:
|
|
163
167
|
```
|
|
@@ -175,8 +179,8 @@ Capture `remote_tip_sha_pre_rebase` now — §6's lease uses it.
|
|
|
175
179
|
**Autonomy gating.** Read the active task's autonomy level from `.aperant/state.json` (`active_tasks[{task-id}].autonomy`, falling back to `autonomy.default`):
|
|
176
180
|
|
|
177
181
|
- **Autonomy 0–1 (step / guided)** — print the audit envelope to the operator and ask `Rebase now? [Y/n]` before executing the `git rebase` line. On `N`, exit the skill (user can rebase manually and re-invoke).
|
|
178
|
-
- **Autonomy 2 (auto-chain)** — proceed silently on the clean-rebase branch;
|
|
179
|
-
- **Autonomy 3 (YOLO)** — same as 2: silent on clean
|
|
182
|
+
- **Autonomy 2 (auto-chain)** — proceed silently on the clean-rebase branch; on conflict, hand off to `/apt:merge-conflict-resolution` when `pipeline.resolve_merge_conflicts` is enabled, else STOP.
|
|
183
|
+
- **Autonomy 3 (YOLO)** — same as 2: silent on clean; on conflict, AI-resolve via `/apt:merge-conflict-resolution` when opted in, else STOP. Even at YOLO the resolved branch still flows through PR → review → CI — apt:ship never auto-merges.
|
|
180
184
|
|
|
181
185
|
The captured `remote_tip_sha_pre_rebase` and `behind` integer are referenced verbatim in §6's push command. Treat them as read-only state for the remainder of the skill.
|
|
182
186
|
|
|
@@ -380,11 +384,21 @@ The body structure below is the full-pipeline template — unchanged from the pr
|
|
|
380
384
|
|
|
381
385
|
{If no review: "No code review was run for this task."}
|
|
382
386
|
|
|
387
|
+
## Follow-ups
|
|
388
|
+
|
|
389
|
+
{Read `{task_dir}/followups.json` and enumerate EVERY open/dispositioned row VERBATIM — never a count. One line per row:}
|
|
390
|
+
|
|
391
|
+
- [{status}] {title} — {adjudication.verdict ?? 'unadjudicated'} → {disposition.kind ?? 'pending'}
|
|
392
|
+
|
|
393
|
+
{If no followups.json: "No follow-ups recorded for this task."}
|
|
394
|
+
|
|
383
395
|
---
|
|
384
396
|
|
|
385
397
|
Built with [Aperant Framework](https://github.com/Mikalsen-AI/aperant-cloud-desktop/tree/main/packages/framework)
|
|
386
398
|
```
|
|
387
399
|
|
|
400
|
+
Counts hide work; the verbatim row list is the visibility contract (ID-16). The `followups-adjudicated` gate (Section 0) has already guaranteed every open row is adjudicated and every load-bearing row is fixed before you reach this section.
|
|
401
|
+
|
|
388
402
|
## 4. Determine Ship Mode
|
|
389
403
|
|
|
390
404
|
Read `.aperant/config.json` for `project_type`.
|
|
@@ -520,8 +534,15 @@ Review: logic={n} security={n} quality={n} architecture={n} performance={n}
|
|
|
520
534
|
Commits: {count}
|
|
521
535
|
Review findings: {count by severity or "none"}
|
|
522
536
|
Decisions traced: {count}
|
|
537
|
+
|
|
538
|
+
Follow-ups:
|
|
539
|
+
{Enumerate EVERY open/dispositioned row from {task_dir}/followups.json VERBATIM,
|
|
540
|
+
one per line — `- [{status}] {title} — {verdict} → {disposition.kind ?? 'pending'}`.
|
|
541
|
+
Never a count. "none" only when followups.json is absent or has zero rows.}
|
|
523
542
|
```
|
|
524
543
|
|
|
544
|
+
The report's Follow-ups block mirrors the PR-body `## Follow-ups` section (ID-16) — rows verbatim, never counts.
|
|
545
|
+
|
|
525
546
|
### 7.1 Post-ship /apt:pr-review hint
|
|
526
547
|
|
|
527
548
|
After printing the ship summary, conditionally emit a tip suggesting `/apt:pr-review` for a deep multi-agent review of the freshly-opened PR. The hint is controlled by `pr_review.suggest_after_ship` in `.aperant/config.json` (tri-state: `always` | `ask` | `never`; default when absent: `always`).
|
|
@@ -97,6 +97,14 @@ The response is JSON to stdout. On success:
|
|
|
97
97
|
|
|
98
98
|
`depth` is the new terminal's level (caller_depth + 1). Record `sessionId` in your task notes.
|
|
99
99
|
|
|
100
|
+
The worktree the spawned terminal opens in already has the project's stored env
|
|
101
|
+
blobs materialized (the per-project encrypted env store, #354) — worktree-create
|
|
102
|
+
copies each `.env*` blob verbatim (traversal-guarded, best-effort) so the sibling
|
|
103
|
+
terminal's CLI runs with the real env instead of crashing in no-cloud mode. If a
|
|
104
|
+
long-lived worktree's stored env later drifts, re-copy on demand with
|
|
105
|
+
`node packages/framework/bin/apt-tools.mjs worktree sync-env <dir> --task <id>`
|
|
106
|
+
(the store is the source of truth — sync-env overwrites, never merges).
|
|
107
|
+
|
|
100
108
|
## 4. Recognise the graceful-degrade error envelopes
|
|
101
109
|
|
|
102
110
|
These are **expected** error shapes — do not retry blindly. Each one tells you exactly which obligation discharged:
|
|
@@ -49,6 +49,10 @@ OUT-OF-SCOPE.md sub-files ported from
|
|
|
49
49
|
- An inbound task / bug / feature request needs status assignment
|
|
50
50
|
- Periodic review of `needs-triage` tasks
|
|
51
51
|
- Re-triage when new info arrives on a `needs-info` task
|
|
52
|
+
- A `new-task` follow-up disposition (G45) — `/apt:close-task` files an open
|
|
53
|
+
follow-up as a fresh task and enters it here at `needs-triage` via
|
|
54
|
+
`apt-tools triage init` (the configured backend mirrors it). This is a normal
|
|
55
|
+
entry point; the chained-task depth marker rides `triage.json` `extra.followups_chain`.
|
|
52
56
|
|
|
53
57
|
## When NOT to Use
|
|
54
58
|
|
|
@@ -266,6 +266,30 @@ for ITERATION in 1 2 3 4:
|
|
|
266
266
|
|
|
267
267
|
**Exhaustion:** If issues remain after 4 iterations, mark them in `qa_signoff.json` and report them. The verdict should reflect the remaining issues.
|
|
268
268
|
|
|
269
|
+
## 6.5 Follow-ups Adjudication (mandatory — G45)
|
|
270
|
+
|
|
271
|
+
This pass is **mandatory** on every full-pipeline verify. It is the owner of follow-up adjudication: `apt:verify` always runs in the pipeline (`apt:run` = plan → execute → verify → review), whereas `apt:verify-proof` is opt-in and therefore cannot be the sole owner. (When `verify-proof` runs later it MAY overwrite an adjudication with stronger evidence, `by: 'verify-proof'`.)
|
|
272
|
+
|
|
273
|
+
Run the deterministic check first:
|
|
274
|
+
|
|
275
|
+
```bash
|
|
276
|
+
node packages/framework/bin/apt-tools.mjs followups check . --task-id {task-id}
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
The envelope returns `missing_expected[]` — the derived expected universe (parsed `## Out of Scope` bullets ∪ raw review rows ∪ qa findings, `status !== 'fixed'`) that the ledger does not yet cover. Create/sync `{task_dir}/followups.json` rows **mechanically** from those payloads:
|
|
280
|
+
|
|
281
|
+
- Append one row per `missing_expected[]` entry: `{ id, title, origin, class_proposed: <class_hint>, files: [], outcome_refs: [], status: 'open' }`. `class_proposed` is only a PROPOSAL (ID-03) — the verdict below is the authority; never let the class self-certify a deferral.
|
|
282
|
+
- Voluntary rows (origin `discuss | execute | ci`) may also be present; they are adjudicated the same way.
|
|
283
|
+
|
|
284
|
+
Then **adjudicate every open row**. For each, answer the single question:
|
|
285
|
+
|
|
286
|
+
> "Would the feature satisfy its stated `## User Outcomes` right now WITHOUT this follow-up?"
|
|
287
|
+
|
|
288
|
+
- If NO → `adjudication: { verdict: 'load-bearing', by: 'verify', outcome_ref: '<O-n>' }`. A load-bearing row blocks ship until it is fixed (flip `status: 'fixed'` once the work lands in this PR's fix loop) or bypassed via `--force --reason`.
|
|
289
|
+
- If YES → `adjudication: { verdict: 'deferrable', by: 'verify', outcome_ref: '<O-n> | null' }`. `outcome_ref` is the `O<n>` id (from `parseUserOutcomes`) the row relates to; it is nullable for refactor-only specs that declare no outcomes.
|
|
290
|
+
|
|
291
|
+
Re-run `followups check` until it is **derivation-clean** (exit 0 — no `missing_expected`, no `invalid_outcome_refs`, no `schema_errors`) BEFORE writing `qa_signoff.json`. The `followups-adjudicated` ship gate will block the PR otherwise.
|
|
292
|
+
|
|
269
293
|
## 7. Write QA Sign-off
|
|
270
294
|
|
|
271
295
|
Create `qa_signoff.json` using the `ScoredQASignoff` format (see `packages/framework/src/types/qa-scoring.ts`):
|
|
@@ -125,7 +125,9 @@ When `action === 'fix'` (or `diverged-rebased`/`diverged-bailed`):
|
|
|
125
125
|
5. **Emit event.** `apt-tools event append . --type ci-watch.fix-pushed --data '{pr, attempts, commit_sha}'`.
|
|
126
126
|
6. **Reschedule** per §3 step 4.
|
|
127
127
|
|
|
128
|
-
For `diverged-rebased`: the cmd already returned the verb; the orchestrator runs `git -C {worktree} fetch && git rebase origin/{base}` BEFORE the fix step. On conflict the action becomes `diverged-bailed
|
|
128
|
+
For `diverged-rebased`: the cmd already returned the verb; the orchestrator runs `git -C {worktree} fetch && git rebase origin/{base}` BEFORE the fix step. On conflict the action becomes `diverged-bailed`.
|
|
129
|
+
|
|
130
|
+
For `diverged-bailed`: default behavior is to exit with a PR comment summarizing the conflict. Self-heal is **opt-in** via `ci_watch.resolve_merge_conflicts` (default false) in `.aperant/config.json`. When enabled, instead of bailing, hand off to **`/apt:merge-conflict-resolution`** (`--base origin/{base}`) for the worktree; it resolves the rebase conflict inline and re-probes mergeability. On success, continue to the §5 fix-and-push step (`git push origin {branch}`) and reschedule per §3 — the watcher keeps running. On its non-convergence STOP (it aborts the rebase to a clean tree first), fall back to the bail-with-PR-comment path. The resolved branch still goes through CI; the watcher never auto-merges except via the existing config-gated `gh pr merge --auto`.
|
|
129
131
|
|
|
130
132
|
---
|
|
131
133
|
|
|
@@ -42,7 +42,7 @@ import { err, ok } from '../util/result.mjs'
|
|
|
42
42
|
* @param {string} cwd
|
|
43
43
|
* @param {string[]} args
|
|
44
44
|
*/
|
|
45
|
-
function gitTry(cwd, args) {
|
|
45
|
+
export function gitTry(cwd, args) {
|
|
46
46
|
try {
|
|
47
47
|
const stdout = execFileSync('git', args, {
|
|
48
48
|
cwd,
|
|
@@ -94,7 +94,7 @@ function parseBaseFlag(extraArgs) {
|
|
|
94
94
|
* @param {string} stdout
|
|
95
95
|
* @returns {string[]}
|
|
96
96
|
*/
|
|
97
|
-
function parseConflictPaths(stdout) {
|
|
97
|
+
export function parseConflictPaths(stdout) {
|
|
98
98
|
const paths = new Set()
|
|
99
99
|
for (const rawLine of stdout.split('\n')) {
|
|
100
100
|
const line = rawLine.replace(/\0/g, '')
|
|
@@ -125,7 +125,7 @@ function parseConflictPaths(stdout) {
|
|
|
125
125
|
* @param {string} stderr
|
|
126
126
|
* @returns {boolean}
|
|
127
127
|
*/
|
|
128
|
-
function isGitVersionTooOld(stderr) {
|
|
128
|
+
export function isGitVersionTooOld(stderr) {
|
|
129
129
|
return /unknown option|did you mean|usage: git merge-tree/i.test(stderr)
|
|
130
130
|
}
|
|
131
131
|
|