@open-agent-toolkit/cli 0.0.42 → 0.0.50
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/assets/agents/oat-phase-implementer.md +230 -0
- package/assets/agents/oat-reviewer.md +3 -3
- package/assets/docs/cli-utilities/configuration.md +15 -3
- package/assets/docs/docs-tooling/add-docs-to-a-repo.md +12 -1
- package/assets/docs/docs-tooling/commands.md +4 -0
- package/assets/docs/reference/cli-reference.md +17 -14
- package/assets/docs/reference/oat-directory-structure.md +17 -17
- package/assets/docs/workflows/projects/artifacts.md +34 -0
- package/assets/docs/workflows/projects/implementation-execution.md +161 -0
- package/assets/docs/workflows/projects/lifecycle.md +22 -29
- package/assets/docs/workflows/projects/reviews.md +4 -2
- package/assets/docs/workflows/skills/index.md +0 -1
- package/assets/public-package-versions.json +4 -4
- package/assets/skills/oat-docs-bootstrap/SKILL.md +11 -3
- package/assets/skills/oat-doctor/SKILL.md +3 -3
- package/assets/skills/oat-project-implement/SKILL.md +368 -126
- package/assets/skills/oat-project-import-plan/SKILL.md +2 -3
- package/assets/skills/oat-project-next/SKILL.md +11 -12
- package/assets/skills/oat-project-plan/SKILL.md +23 -5
- package/assets/skills/oat-project-plan-writing/SKILL.md +2 -2
- package/assets/skills/oat-project-progress/SKILL.md +29 -35
- package/assets/skills/oat-project-quick-start/SKILL.md +14 -3
- package/assets/skills/oat-project-review-provide/SKILL.md +24 -2
- package/assets/skills/oat-project-review-receive/SKILL.md +5 -1
- package/assets/skills/oat-worktree-bootstrap-auto/SKILL.md +2 -2
- package/assets/templates/docs-app-fuma/docs/index.md +2 -0
- package/assets/templates/implementation.md +8 -3
- package/assets/templates/plan.md +24 -3
- package/assets/templates/state.md +1 -1
- package/dist/commands/config/index.d.ts.map +1 -1
- package/dist/commands/config/index.js +17 -4
- package/dist/commands/docs/index-generate/index.d.ts +1 -0
- package/dist/commands/docs/index-generate/index.d.ts.map +1 -1
- package/dist/commands/docs/index-generate/index.js +8 -1
- package/dist/commands/docs/init/index.d.ts.map +1 -1
- package/dist/commands/docs/init/index.js +46 -0
- package/dist/commands/docs/init/resolve-options.d.ts +2 -0
- package/dist/commands/docs/init/resolve-options.d.ts.map +1 -1
- package/dist/commands/docs/init/resolve-options.js +1 -0
- package/dist/commands/docs/init/root-package.d.ts +23 -0
- package/dist/commands/docs/init/root-package.d.ts.map +1 -0
- package/dist/commands/docs/init/root-package.js +226 -0
- package/dist/commands/init/tools/index.js +1 -1
- package/dist/commands/init/tools/shared/skill-manifest.d.ts +2 -2
- package/dist/commands/init/tools/shared/skill-manifest.d.ts.map +1 -1
- package/dist/commands/init/tools/shared/skill-manifest.js +1 -1
- package/dist/commands/project/index.d.ts.map +1 -1
- package/dist/commands/project/index.js +3 -1
- package/dist/commands/project/set-mode/index.d.ts +0 -6
- package/dist/commands/project/set-mode/index.d.ts.map +1 -1
- package/dist/commands/project/set-mode/index.js +16 -96
- package/dist/commands/project/validate-plan/index.d.ts +3 -0
- package/dist/commands/project/validate-plan/index.d.ts.map +1 -0
- package/dist/commands/project/validate-plan/index.js +44 -0
- package/dist/commands/project/validate-plan/validate-plan.d.ts +20 -0
- package/dist/commands/project/validate-plan/validate-plan.d.ts.map +1 -0
- package/dist/commands/project/validate-plan/validate-plan.js +77 -0
- package/dist/commands/tools/update/index.d.ts +4 -0
- package/dist/commands/tools/update/index.d.ts.map +1 -1
- package/dist/commands/tools/update/index.js +17 -1
- package/dist/commands/tools/update/update-tools.d.ts +1 -0
- package/dist/commands/tools/update/update-tools.d.ts.map +1 -1
- package/dist/commands/tools/update/update-tools.js +80 -1
- package/dist/config/oat-config.d.ts +1 -0
- package/dist/config/oat-config.d.ts.map +1 -1
- package/dist/config/oat-config.js +3 -0
- package/dist/config/resolve.d.ts.map +1 -1
- package/dist/config/resolve.js +9 -0
- package/package.json +2 -2
- package/assets/skills/oat-project-subagent-implement/SKILL.md +0 -549
- package/assets/skills/oat-project-subagent-implement/examples/pattern-hill-checkpoint.md +0 -110
- package/assets/skills/oat-project-subagent-implement/examples/pattern-parallel-phases.md +0 -118
- package/assets/skills/oat-project-subagent-implement/scripts/dispatch.sh +0 -133
- package/assets/skills/oat-project-subagent-implement/scripts/reconcile.sh +0 -182
- package/assets/skills/oat-project-subagent-implement/scripts/review-gate.sh +0 -187
- package/assets/skills/oat-project-subagent-implement/tests/fixtures/sample-plan.md +0 -234
- package/assets/skills/oat-project-subagent-implement/tests/test-dry-run.sh +0 -126
- package/assets/skills/oat-project-subagent-implement/tests/test-hill-checkpoint.sh +0 -127
- package/assets/skills/oat-project-subagent-implement/tests/test-reconcile.sh +0 -254
- package/assets/skills/oat-project-subagent-implement/tests/test-review-gate.sh +0 -220
|
@@ -1,118 +0,0 @@
|
|
|
1
|
-
# Usage Pattern: Simple Parallel Phases
|
|
2
|
-
|
|
3
|
-
Two independent phases execute in parallel, then merge cleanly.
|
|
4
|
-
|
|
5
|
-
## Plan Excerpt
|
|
6
|
-
|
|
7
|
-
```yaml
|
|
8
|
-
---
|
|
9
|
-
oat_plan_hill_phases: ['p03']
|
|
10
|
-
---
|
|
11
|
-
```
|
|
12
|
-
|
|
13
|
-
```markdown
|
|
14
|
-
## Phase 1: API Endpoints
|
|
15
|
-
|
|
16
|
-
### Task p01-t01: Create user endpoint
|
|
17
|
-
|
|
18
|
-
**Files:**
|
|
19
|
-
|
|
20
|
-
- Create: `src/routes/user.ts`
|
|
21
|
-
- Create: `src/routes/user.test.ts`
|
|
22
|
-
|
|
23
|
-
### Task p01-t02: Create settings endpoint
|
|
24
|
-
|
|
25
|
-
**Files:**
|
|
26
|
-
|
|
27
|
-
- Create: `src/routes/settings.ts`
|
|
28
|
-
- Create: `src/routes/settings.test.ts`
|
|
29
|
-
|
|
30
|
-
## Phase 2: UI Components
|
|
31
|
-
|
|
32
|
-
### Task p02-t01: Create user profile component
|
|
33
|
-
|
|
34
|
-
**Files:**
|
|
35
|
-
|
|
36
|
-
- Create: `src/components/UserProfile.tsx`
|
|
37
|
-
- Create: `src/components/UserProfile.test.tsx`
|
|
38
|
-
|
|
39
|
-
### Task p02-t02: Create settings panel component
|
|
40
|
-
|
|
41
|
-
**Files:**
|
|
42
|
-
|
|
43
|
-
- Create: `src/components/SettingsPanel.tsx`
|
|
44
|
-
- Create: `src/components/SettingsPanel.test.tsx`
|
|
45
|
-
|
|
46
|
-
## Phase 3: Integration
|
|
47
|
-
|
|
48
|
-
### Task p03-t01: Wire API to UI
|
|
49
|
-
|
|
50
|
-
**Files:**
|
|
51
|
-
|
|
52
|
-
- Modify: `src/routes/user.ts`
|
|
53
|
-
- Modify: `src/components/UserProfile.tsx`
|
|
54
|
-
```
|
|
55
|
-
|
|
56
|
-
## Orchestration Flow
|
|
57
|
-
|
|
58
|
-
1. **Dispatch manifest** identifies p01 and p02 as parallel-safe (no overlapping files).
|
|
59
|
-
2. **Bootstrap** creates two worktrees:
|
|
60
|
-
- `project-name/p01` (branch from orchestration base)
|
|
61
|
-
- `project-name/p02` (branch from orchestration base)
|
|
62
|
-
3. **Subagents** execute concurrently:
|
|
63
|
-
- Subagent A: implements p01-t01 and p01-t02 in worktree p01
|
|
64
|
-
- Subagent B: implements p02-t01 and p02-t02 in worktree p02
|
|
65
|
-
4. **Review gate** runs per unit:
|
|
66
|
-
- p01: spec compliance (pass) -> code quality (pass) -> eligible for merge
|
|
67
|
-
- p02: spec compliance (pass) -> code quality (pass) -> eligible for merge
|
|
68
|
-
5. **Reconciliation** merges in deterministic order:
|
|
69
|
-
- Merge p01 (order 1) -> integration verification passes
|
|
70
|
-
- Merge p02 (order 2) -> integration verification passes
|
|
71
|
-
6. **HiLL checkpoint** at p03: orchestrator pauses, reports progress, waits for user.
|
|
72
|
-
7. After user approval, p03 executes sequentially (it modifies files from both p01 and p02).
|
|
73
|
-
|
|
74
|
-
## Expected Artifact Output
|
|
75
|
-
|
|
76
|
-
In `implementation.md` under `## Orchestration Runs`:
|
|
77
|
-
|
|
78
|
-
```markdown
|
|
79
|
-
### Run 1 — 2026-02-17 14:30
|
|
80
|
-
|
|
81
|
-
**Branch:** autonomous-orchestration-impl
|
|
82
|
-
**Policy:** baseline=strict, merge=merge, retry-limit=2
|
|
83
|
-
**Units:** 2 dispatched, 2 passed, 0 failed, 0 conflicts
|
|
84
|
-
|
|
85
|
-
#### Unit Outcomes
|
|
86
|
-
|
|
87
|
-
| Unit | Status | Commits | Tests | Review | Disposition |
|
|
88
|
-
| ---- | ------ | ------- | ----- | ------ | ----------- |
|
|
89
|
-
| p01 | pass | abc1234 | pass | pass | merged |
|
|
90
|
-
| p02 | pass | def5678 | pass | pass | merged |
|
|
91
|
-
|
|
92
|
-
#### Review Interaction Log
|
|
93
|
-
|
|
94
|
-
**p01:**
|
|
95
|
-
|
|
96
|
-
- **Spec compliance:** pass (0 findings)
|
|
97
|
-
- **Code quality:** pass (0 findings)
|
|
98
|
-
- **Verdict:** pass
|
|
99
|
-
- **Disposition:** merged
|
|
100
|
-
|
|
101
|
-
**p02:**
|
|
102
|
-
|
|
103
|
-
- **Spec compliance:** pass (0 findings)
|
|
104
|
-
- **Code quality:** pass (0 findings)
|
|
105
|
-
- **Verdict:** pass
|
|
106
|
-
- **Disposition:** merged
|
|
107
|
-
|
|
108
|
-
#### Merge Outcomes
|
|
109
|
-
|
|
110
|
-
| Order | Unit | Strategy | Result | Integration |
|
|
111
|
-
| ----- | ---- | -------- | ------ | ----------- |
|
|
112
|
-
| 1 | p01 | merge | clean | tests pass |
|
|
113
|
-
| 2 | p02 | merge | clean | tests pass |
|
|
114
|
-
|
|
115
|
-
#### Outstanding Items
|
|
116
|
-
|
|
117
|
-
- None
|
|
118
|
-
```
|
|
@@ -1,133 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env bash
|
|
2
|
-
# oat-project-subagent-implement: Fan-out dispatch and result collection
|
|
3
|
-
#
|
|
4
|
-
# Usage: dispatch.sh <plan-path> <project-path> <orchestration-branch> [--unit-granularity <phase|task>]
|
|
5
|
-
#
|
|
6
|
-
# This script is a reference implementation for the orchestrator agent.
|
|
7
|
-
# It parses the plan, identifies parallelizable units, and outputs
|
|
8
|
-
# a dispatch manifest for the orchestrator to execute via the Task tool.
|
|
9
|
-
#
|
|
10
|
-
# The orchestrator reads the manifest and dispatches subagents accordingly.
|
|
11
|
-
# This script does NOT dispatch subagents directly — that requires the
|
|
12
|
-
# Task tool, which is only available to the agent runtime.
|
|
13
|
-
|
|
14
|
-
set -euo pipefail
|
|
15
|
-
|
|
16
|
-
# ─── Defaults ───────────────────────────────────────────────────────────────
|
|
17
|
-
PLAN_PATH=""
|
|
18
|
-
PROJECT_PATH=""
|
|
19
|
-
ORCHESTRATION_BRANCH=""
|
|
20
|
-
UNIT_GRANULARITY="phase"
|
|
21
|
-
|
|
22
|
-
# ─── Parse Arguments ────────────────────────────────────────────────────────
|
|
23
|
-
while [[ $# -gt 0 ]]; do
|
|
24
|
-
case "$1" in
|
|
25
|
-
--unit-granularity) UNIT_GRANULARITY="$2"; shift 2 ;;
|
|
26
|
-
-*) echo "error: unknown flag $1" >&2; exit 1 ;;
|
|
27
|
-
*)
|
|
28
|
-
if [[ -z "$PLAN_PATH" ]]; then PLAN_PATH="$1"
|
|
29
|
-
elif [[ -z "$PROJECT_PATH" ]]; then PROJECT_PATH="$1"
|
|
30
|
-
elif [[ -z "$ORCHESTRATION_BRANCH" ]]; then ORCHESTRATION_BRANCH="$1"
|
|
31
|
-
fi
|
|
32
|
-
shift
|
|
33
|
-
;;
|
|
34
|
-
esac
|
|
35
|
-
done
|
|
36
|
-
|
|
37
|
-
if [[ -z "$PLAN_PATH" || -z "$PROJECT_PATH" || -z "$ORCHESTRATION_BRANCH" ]]; then
|
|
38
|
-
echo "error: required: <plan-path> <project-path> <orchestration-branch>" >&2
|
|
39
|
-
exit 1
|
|
40
|
-
fi
|
|
41
|
-
|
|
42
|
-
# ─── Step 1: Parse Plan Structure ───────────────────────────────────────────
|
|
43
|
-
# Extract phase and task structure from plan.md
|
|
44
|
-
# Output: list of units with task IDs, files, and verification commands
|
|
45
|
-
|
|
46
|
-
echo "--- dispatch_manifest ---"
|
|
47
|
-
echo "orchestration_branch: $ORCHESTRATION_BRANCH"
|
|
48
|
-
echo "unit_granularity: $UNIT_GRANULARITY"
|
|
49
|
-
echo "plan_path: $PLAN_PATH"
|
|
50
|
-
echo "project_path: $PROJECT_PATH"
|
|
51
|
-
echo "log_path: $PROJECT_PATH/implementation.md"
|
|
52
|
-
echo "units:"
|
|
53
|
-
|
|
54
|
-
# Parse phases (## Phase N: ...)
|
|
55
|
-
CURRENT_PHASE=""
|
|
56
|
-
CURRENT_TASK=""
|
|
57
|
-
TASK_FILES=""
|
|
58
|
-
IN_FILES_BLOCK=false
|
|
59
|
-
|
|
60
|
-
while IFS= read -r line; do
|
|
61
|
-
# Detect phase headers
|
|
62
|
-
if [[ "$line" =~ ^##\ Phase\ ([0-9]+):\ (.+)$ ]]; then
|
|
63
|
-
CURRENT_PHASE="p$(printf '%02d' "${BASH_REMATCH[1]}")"
|
|
64
|
-
PHASE_NAME="${BASH_REMATCH[2]}"
|
|
65
|
-
|
|
66
|
-
if [[ "$UNIT_GRANULARITY" == "phase" ]]; then
|
|
67
|
-
echo " - unit_id: \"$CURRENT_PHASE\""
|
|
68
|
-
echo " phase: \"$CURRENT_PHASE\""
|
|
69
|
-
echo " phase_name: \"$PHASE_NAME\""
|
|
70
|
-
echo " type: phase"
|
|
71
|
-
echo " tasks:"
|
|
72
|
-
fi
|
|
73
|
-
fi
|
|
74
|
-
|
|
75
|
-
# Detect task headers (### Task pNN-tNN: ...)
|
|
76
|
-
if [[ "$line" =~ ^###\ Task\ (p[0-9]+-t[0-9]+):\ (.+)$ ]]; then
|
|
77
|
-
CURRENT_TASK="${BASH_REMATCH[1]}"
|
|
78
|
-
TASK_NAME="${BASH_REMATCH[2]}"
|
|
79
|
-
|
|
80
|
-
if [[ "$UNIT_GRANULARITY" == "task" ]]; then
|
|
81
|
-
echo " - unit_id: \"$CURRENT_TASK\""
|
|
82
|
-
echo " phase: \"$CURRENT_PHASE\""
|
|
83
|
-
echo " task_id: \"$CURRENT_TASK\""
|
|
84
|
-
echo " task_name: \"$TASK_NAME\""
|
|
85
|
-
echo " type: task"
|
|
86
|
-
elif [[ "$UNIT_GRANULARITY" == "phase" ]]; then
|
|
87
|
-
# Append task to current phase unit
|
|
88
|
-
echo " - \"$CURRENT_TASK\""
|
|
89
|
-
fi
|
|
90
|
-
fi
|
|
91
|
-
|
|
92
|
-
# Detect file boundaries
|
|
93
|
-
if [[ "$line" =~ ^\*\*Files:\*\*$ ]]; then
|
|
94
|
-
IN_FILES_BLOCK=true
|
|
95
|
-
if [[ "$UNIT_GRANULARITY" == "task" ]]; then
|
|
96
|
-
echo " files:"
|
|
97
|
-
fi
|
|
98
|
-
elif [[ "$IN_FILES_BLOCK" == true ]]; then
|
|
99
|
-
if [[ "$line" =~ ^-\ (Create|Modify):\ \`(.+)\`$ ]]; then
|
|
100
|
-
if [[ "$UNIT_GRANULARITY" == "task" ]]; then
|
|
101
|
-
echo " - action: \"${BASH_REMATCH[1]}\""
|
|
102
|
-
echo " path: \"${BASH_REMATCH[2]}\""
|
|
103
|
-
fi
|
|
104
|
-
elif [[ ! "$line" =~ ^- ]]; then
|
|
105
|
-
IN_FILES_BLOCK=false
|
|
106
|
-
fi
|
|
107
|
-
fi
|
|
108
|
-
done < "$PLAN_PATH"
|
|
109
|
-
|
|
110
|
-
echo "---"
|
|
111
|
-
|
|
112
|
-
# ─── Step 2: Check HiLL Checkpoints ─────────────────────────────────────────
|
|
113
|
-
# Extract oat_plan_hill_phases from frontmatter
|
|
114
|
-
HIL_PHASES=$(sed -n '/^---$/,/^---$/p' "$PLAN_PATH" | grep 'oat_plan_hill_phases' | sed 's/.*: //' || true)
|
|
115
|
-
echo "hill_checkpoints: $HIL_PHASES"
|
|
116
|
-
|
|
117
|
-
# ─── Step 3: Output Branch Naming Plan ──────────────────────────────────────
|
|
118
|
-
PROJECT_NAME=$(basename "$PROJECT_PATH")
|
|
119
|
-
echo "branch_naming:"
|
|
120
|
-
echo " pattern: \"${PROJECT_NAME}/{unit-id}\""
|
|
121
|
-
echo " base_ref: \"$ORCHESTRATION_BRANCH\""
|
|
122
|
-
echo " examples:"
|
|
123
|
-
|
|
124
|
-
# Re-parse to list branch names
|
|
125
|
-
while IFS= read -r line; do
|
|
126
|
-
if [[ "$UNIT_GRANULARITY" == "phase" && "$line" =~ ^##\ Phase\ ([0-9]+): ]]; then
|
|
127
|
-
PHASE_ID="p$(printf '%02d' "${BASH_REMATCH[1]}")"
|
|
128
|
-
echo " - \"${PROJECT_NAME}/${PHASE_ID}\""
|
|
129
|
-
elif [[ "$UNIT_GRANULARITY" == "task" && "$line" =~ ^###\ Task\ (p[0-9]+-t[0-9]+): ]]; then
|
|
130
|
-
TASK_ID="${BASH_REMATCH[1]}"
|
|
131
|
-
echo " - \"${PROJECT_NAME}/${TASK_ID}\""
|
|
132
|
-
fi
|
|
133
|
-
done < "$PLAN_PATH"
|
|
@@ -1,182 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env bash
|
|
2
|
-
# oat-project-subagent-implement: Fan-in merge/reconcile logic
|
|
3
|
-
#
|
|
4
|
-
# Usage: reconcile.sh <orchestration-branch> [--merge-strategy <merge|cherry-pick>] <unit-branch>...
|
|
5
|
-
#
|
|
6
|
-
# This script merges passing unit branches back into the orchestration
|
|
7
|
-
# branch in deterministic order (by task ID) with integration verification
|
|
8
|
-
# after each merge.
|
|
9
|
-
#
|
|
10
|
-
# If merge fails, falls back to cherry-pick. If both fail, classifies
|
|
11
|
-
# the conflict and reports for manual resolution.
|
|
12
|
-
|
|
13
|
-
set -euo pipefail
|
|
14
|
-
|
|
15
|
-
# ─── Defaults ───────────────────────────────────────────────────────────────
|
|
16
|
-
ORCHESTRATION_BRANCH=""
|
|
17
|
-
MERGE_STRATEGY="merge"
|
|
18
|
-
UNIT_BRANCHES=()
|
|
19
|
-
|
|
20
|
-
# ─── Parse Arguments ────────────────────────────────────────────────────────
|
|
21
|
-
while [[ $# -gt 0 ]]; do
|
|
22
|
-
case "$1" in
|
|
23
|
-
--merge-strategy) MERGE_STRATEGY="$2"; shift 2 ;;
|
|
24
|
-
-*) echo "error: unknown flag $1" >&2; exit 1 ;;
|
|
25
|
-
*)
|
|
26
|
-
if [[ -z "$ORCHESTRATION_BRANCH" ]]; then
|
|
27
|
-
ORCHESTRATION_BRANCH="$1"
|
|
28
|
-
else
|
|
29
|
-
UNIT_BRANCHES+=("$1")
|
|
30
|
-
fi
|
|
31
|
-
shift
|
|
32
|
-
;;
|
|
33
|
-
esac
|
|
34
|
-
done
|
|
35
|
-
|
|
36
|
-
if [[ -z "$ORCHESTRATION_BRANCH" || ${#UNIT_BRANCHES[@]} -eq 0 ]]; then
|
|
37
|
-
echo "error: required: <orchestration-branch> <unit-branch>..." >&2
|
|
38
|
-
exit 1
|
|
39
|
-
fi
|
|
40
|
-
|
|
41
|
-
# ─── Sort Branches by Task ID ──────────────────────────────────────────────
|
|
42
|
-
# Deterministic ordering: sort by the unit ID suffix (p01-t01, p02-t01, etc.)
|
|
43
|
-
IFS=$'\n' SORTED_BRANCHES=($(printf '%s\n' "${UNIT_BRANCHES[@]}" | sort)); unset IFS
|
|
44
|
-
|
|
45
|
-
# ─── Checkout Orchestration Branch ──────────────────────────────────────────
|
|
46
|
-
git checkout "$ORCHESTRATION_BRANCH"
|
|
47
|
-
|
|
48
|
-
echo "--- reconcile_manifest ---"
|
|
49
|
-
echo "orchestration_branch: $ORCHESTRATION_BRANCH"
|
|
50
|
-
echo "merge_strategy: $MERGE_STRATEGY"
|
|
51
|
-
echo "unit_count: ${#SORTED_BRANCHES[@]}"
|
|
52
|
-
echo "merge_outcomes:"
|
|
53
|
-
|
|
54
|
-
MERGE_ORDER=0
|
|
55
|
-
TOTAL_MERGED=0
|
|
56
|
-
TOTAL_CONFLICTS=0
|
|
57
|
-
TOTAL_REVERTED=0
|
|
58
|
-
TOTAL_NO_COMMITS=0
|
|
59
|
-
|
|
60
|
-
for UNIT_BRANCH in "${SORTED_BRANCHES[@]}"; do
|
|
61
|
-
MERGE_ORDER=$((MERGE_ORDER + 1))
|
|
62
|
-
UNIT_ID=$(echo "$UNIT_BRANCH" | sed 's|.*/||') # Extract unit ID from branch name
|
|
63
|
-
|
|
64
|
-
echo " - order: $MERGE_ORDER"
|
|
65
|
-
echo " unit_id: \"$UNIT_ID\""
|
|
66
|
-
echo " branch: \"$UNIT_BRANCH\""
|
|
67
|
-
|
|
68
|
-
# ─── Attempt Merge ────────────────────────────────────────────────────
|
|
69
|
-
STRATEGY_USED="$MERGE_STRATEGY"
|
|
70
|
-
MERGE_RESULT="pending"
|
|
71
|
-
PRE_MERGE_SHA=$(git rev-parse HEAD)
|
|
72
|
-
|
|
73
|
-
if [[ "$MERGE_STRATEGY" == "merge" ]]; then
|
|
74
|
-
if git merge --no-ff "$UNIT_BRANCH" -m "merge($UNIT_ID): reconcile unit into orchestration branch" 2>/dev/null; then
|
|
75
|
-
MERGE_RESULT="clean"
|
|
76
|
-
else
|
|
77
|
-
# Merge conflict — abort and try cherry-pick fallback
|
|
78
|
-
git merge --abort 2>/dev/null || true
|
|
79
|
-
STRATEGY_USED="cherry-pick (fallback)"
|
|
80
|
-
|
|
81
|
-
# Get commits unique to the unit branch
|
|
82
|
-
COMMITS=$(git log --reverse --format='%H' "$ORCHESTRATION_BRANCH..$UNIT_BRANCH" 2>/dev/null || true)
|
|
83
|
-
if [[ -n "$COMMITS" ]]; then
|
|
84
|
-
CHERRY_FAILED=false
|
|
85
|
-
while IFS= read -r COMMIT; do
|
|
86
|
-
if ! git cherry-pick "$COMMIT" 2>/dev/null; then
|
|
87
|
-
git cherry-pick --abort 2>/dev/null || true
|
|
88
|
-
CHERRY_FAILED=true
|
|
89
|
-
break
|
|
90
|
-
fi
|
|
91
|
-
done <<< "$COMMITS"
|
|
92
|
-
|
|
93
|
-
if [[ "$CHERRY_FAILED" == true ]]; then
|
|
94
|
-
MERGE_RESULT="conflict"
|
|
95
|
-
else
|
|
96
|
-
MERGE_RESULT="clean"
|
|
97
|
-
fi
|
|
98
|
-
else
|
|
99
|
-
MERGE_RESULT="no_commits"
|
|
100
|
-
fi
|
|
101
|
-
fi
|
|
102
|
-
elif [[ "$MERGE_STRATEGY" == "cherry-pick" ]]; then
|
|
103
|
-
COMMITS=$(git log --reverse --format='%H' "$ORCHESTRATION_BRANCH..$UNIT_BRANCH" 2>/dev/null || true)
|
|
104
|
-
if [[ -n "$COMMITS" ]]; then
|
|
105
|
-
CHERRY_FAILED=false
|
|
106
|
-
while IFS= read -r COMMIT; do
|
|
107
|
-
if ! git cherry-pick "$COMMIT" 2>/dev/null; then
|
|
108
|
-
git cherry-pick --abort 2>/dev/null || true
|
|
109
|
-
CHERRY_FAILED=true
|
|
110
|
-
break
|
|
111
|
-
fi
|
|
112
|
-
done <<< "$COMMITS"
|
|
113
|
-
|
|
114
|
-
if [[ "$CHERRY_FAILED" == true ]]; then
|
|
115
|
-
MERGE_RESULT="conflict"
|
|
116
|
-
else
|
|
117
|
-
MERGE_RESULT="clean"
|
|
118
|
-
fi
|
|
119
|
-
else
|
|
120
|
-
MERGE_RESULT="no_commits"
|
|
121
|
-
fi
|
|
122
|
-
fi
|
|
123
|
-
|
|
124
|
-
echo " strategy: \"$STRATEGY_USED\""
|
|
125
|
-
|
|
126
|
-
# ─── Integration Verification ─────────────────────────────────────────
|
|
127
|
-
if [[ "$MERGE_RESULT" == "clean" ]]; then
|
|
128
|
-
INTEGRATION="pending"
|
|
129
|
-
|
|
130
|
-
# Run integration checks
|
|
131
|
-
TESTS_PASS=true
|
|
132
|
-
LINT_PASS=true
|
|
133
|
-
TYPECHECK_PASS=true
|
|
134
|
-
|
|
135
|
-
pnpm test >/dev/null 2>&1 || TESTS_PASS=false
|
|
136
|
-
pnpm lint >/dev/null 2>&1 || LINT_PASS=false
|
|
137
|
-
pnpm type-check >/dev/null 2>&1 || TYPECHECK_PASS=false
|
|
138
|
-
|
|
139
|
-
if [[ "$TESTS_PASS" == true && "$LINT_PASS" == true && "$TYPECHECK_PASS" == true ]]; then
|
|
140
|
-
INTEGRATION="pass"
|
|
141
|
-
TOTAL_MERGED=$((TOTAL_MERGED + 1))
|
|
142
|
-
else
|
|
143
|
-
INTEGRATION="fail"
|
|
144
|
-
# Rollback to pre-merge state
|
|
145
|
-
git reset --hard "$PRE_MERGE_SHA" 2>/dev/null || true
|
|
146
|
-
MERGE_RESULT="reverted"
|
|
147
|
-
TOTAL_REVERTED=$((TOTAL_REVERTED + 1))
|
|
148
|
-
fi
|
|
149
|
-
|
|
150
|
-
echo " result: $MERGE_RESULT"
|
|
151
|
-
echo " integration:"
|
|
152
|
-
echo " tests: $([ "$TESTS_PASS" == true ] && echo 'pass' || echo 'fail')"
|
|
153
|
-
echo " lint: $([ "$LINT_PASS" == true ] && echo 'pass' || echo 'fail')"
|
|
154
|
-
echo " type_check: $([ "$TYPECHECK_PASS" == true ] && echo 'pass' || echo 'fail')"
|
|
155
|
-
echo " verdict: $INTEGRATION"
|
|
156
|
-
else
|
|
157
|
-
echo " result: $MERGE_RESULT"
|
|
158
|
-
if [[ "$MERGE_RESULT" == "conflict" ]]; then
|
|
159
|
-
TOTAL_CONFLICTS=$((TOTAL_CONFLICTS + 1))
|
|
160
|
-
elif [[ "$MERGE_RESULT" == "no_commits" ]]; then
|
|
161
|
-
TOTAL_NO_COMMITS=$((TOTAL_NO_COMMITS + 1))
|
|
162
|
-
fi
|
|
163
|
-
echo " integration: skipped (merge not clean)"
|
|
164
|
-
|
|
165
|
-
# Classify conflict
|
|
166
|
-
if [[ "$MERGE_RESULT" == "conflict" ]]; then
|
|
167
|
-
echo " conflict_type: file-level"
|
|
168
|
-
echo " resolution: manual_required"
|
|
169
|
-
fi
|
|
170
|
-
fi
|
|
171
|
-
done
|
|
172
|
-
|
|
173
|
-
# ─── Summary ────────────────────────────────────────────────────────────────
|
|
174
|
-
echo "summary:"
|
|
175
|
-
echo " total_units: ${#SORTED_BRANCHES[@]}"
|
|
176
|
-
echo " merged: $TOTAL_MERGED"
|
|
177
|
-
echo " conflicts: $TOTAL_CONFLICTS"
|
|
178
|
-
echo " reverted: $TOTAL_REVERTED"
|
|
179
|
-
echo " no_commits: $TOTAL_NO_COMMITS"
|
|
180
|
-
echo " final_branch: $ORCHESTRATION_BRANCH"
|
|
181
|
-
echo " final_commit: $(git rev-parse HEAD 2>/dev/null || echo 'unknown')"
|
|
182
|
-
echo "---"
|
|
@@ -1,187 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env bash
|
|
2
|
-
# oat-project-subagent-implement: Autonomous review gate with fix-loop retry
|
|
3
|
-
#
|
|
4
|
-
# Usage: review-gate.sh <unit-branch> <worktree-path> [--retry-limit <N>]
|
|
5
|
-
#
|
|
6
|
-
# This script is a reference implementation for the review gate logic.
|
|
7
|
-
# The orchestrator agent uses it (or follows its logic) to run the
|
|
8
|
-
# two-stage review gate per unit after subagent implementation.
|
|
9
|
-
#
|
|
10
|
-
# Stage 1: Spec compliance (does the implementation match the plan?)
|
|
11
|
-
# Stage 2: Code quality (is the code well-written and passing checks?)
|
|
12
|
-
#
|
|
13
|
-
# If a stage fails, the fix-loop dispatches the implementer to fix,
|
|
14
|
-
# then re-runs the same stage. Up to --retry-limit attempts.
|
|
15
|
-
|
|
16
|
-
set -euo pipefail
|
|
17
|
-
|
|
18
|
-
# ─── Defaults ───────────────────────────────────────────────────────────────
|
|
19
|
-
UNIT_BRANCH=""
|
|
20
|
-
WORKTREE_PATH=""
|
|
21
|
-
RETRY_LIMIT=2
|
|
22
|
-
RETRY_COUNT=0
|
|
23
|
-
|
|
24
|
-
# ─── Parse Arguments ────────────────────────────────────────────────────────
|
|
25
|
-
while [[ $# -gt 0 ]]; do
|
|
26
|
-
case "$1" in
|
|
27
|
-
--retry-limit) RETRY_LIMIT="$2"; shift 2 ;;
|
|
28
|
-
--retry-count) RETRY_COUNT="$2"; shift 2 ;;
|
|
29
|
-
-*) echo "error: unknown flag $1" >&2; exit 1 ;;
|
|
30
|
-
*)
|
|
31
|
-
if [[ -z "$UNIT_BRANCH" ]]; then UNIT_BRANCH="$1"
|
|
32
|
-
elif [[ -z "$WORKTREE_PATH" ]]; then WORKTREE_PATH="$1"
|
|
33
|
-
fi
|
|
34
|
-
shift
|
|
35
|
-
;;
|
|
36
|
-
esac
|
|
37
|
-
done
|
|
38
|
-
|
|
39
|
-
if [[ -z "$UNIT_BRANCH" || -z "$WORKTREE_PATH" ]]; then
|
|
40
|
-
echo "error: required: <unit-branch> <worktree-path>" >&2
|
|
41
|
-
exit 1
|
|
42
|
-
fi
|
|
43
|
-
|
|
44
|
-
cd "$WORKTREE_PATH"
|
|
45
|
-
|
|
46
|
-
# ─── Stage 1: Spec Compliance ──────────────────────────────────────────────
|
|
47
|
-
# The orchestrator agent runs this check by comparing the implementer's
|
|
48
|
-
# output against the plan task specification.
|
|
49
|
-
#
|
|
50
|
-
# Checks:
|
|
51
|
-
# 1. All planned files exist (created/modified as specified)
|
|
52
|
-
# 2. Verification commands from plan pass
|
|
53
|
-
# 3. No files modified outside the task's file boundary
|
|
54
|
-
# 4. No scope creep (features not in the plan)
|
|
55
|
-
#
|
|
56
|
-
# This stage is primarily agent-driven (reading code vs spec).
|
|
57
|
-
# The shell checks below handle the automatable parts.
|
|
58
|
-
|
|
59
|
-
echo "--- review_gate ---"
|
|
60
|
-
echo "unit_branch: $UNIT_BRANCH"
|
|
61
|
-
echo "worktree_path: $WORKTREE_PATH"
|
|
62
|
-
echo "retry_limit: $RETRY_LIMIT"
|
|
63
|
-
|
|
64
|
-
SPEC_VERDICT="pass"
|
|
65
|
-
QUALITY_VERDICT="pending"
|
|
66
|
-
FINDINGS_CRITICAL=()
|
|
67
|
-
FINDINGS_IMPORTANT=()
|
|
68
|
-
FINDINGS_MINOR=()
|
|
69
|
-
|
|
70
|
-
# Automatable spec checks: verification commands
|
|
71
|
-
echo "stage: spec_compliance"
|
|
72
|
-
echo "checks:"
|
|
73
|
-
|
|
74
|
-
# Check: tests pass
|
|
75
|
-
if pnpm test >/dev/null 2>&1; then
|
|
76
|
-
echo " tests: pass"
|
|
77
|
-
else
|
|
78
|
-
echo " tests: fail"
|
|
79
|
-
SPEC_VERDICT="fail"
|
|
80
|
-
FINDINGS_CRITICAL+=("Tests failing in unit branch")
|
|
81
|
-
fi
|
|
82
|
-
|
|
83
|
-
# Check: git status is clean (all work committed)
|
|
84
|
-
if [[ -z "$(git status --porcelain)" ]]; then
|
|
85
|
-
echo " git_clean: pass"
|
|
86
|
-
else
|
|
87
|
-
echo " git_clean: fail"
|
|
88
|
-
SPEC_VERDICT="fail"
|
|
89
|
-
FINDINGS_IMPORTANT+=("Uncommitted changes in unit branch")
|
|
90
|
-
fi
|
|
91
|
-
|
|
92
|
-
echo " spec_verdict: $SPEC_VERDICT"
|
|
93
|
-
|
|
94
|
-
# ─── Stage 2: Code Quality ─────────────────────────────────────────────────
|
|
95
|
-
# Only runs if spec compliance passes.
|
|
96
|
-
|
|
97
|
-
if [[ "$SPEC_VERDICT" == "pass" ]]; then
|
|
98
|
-
echo "stage: code_quality"
|
|
99
|
-
echo "checks:"
|
|
100
|
-
QUALITY_VERDICT="pass"
|
|
101
|
-
|
|
102
|
-
# Check: lint
|
|
103
|
-
if pnpm lint >/dev/null 2>&1; then
|
|
104
|
-
echo " lint: pass"
|
|
105
|
-
else
|
|
106
|
-
echo " lint: fail"
|
|
107
|
-
QUALITY_VERDICT="fail"
|
|
108
|
-
FINDINGS_IMPORTANT+=("Lint errors in unit branch")
|
|
109
|
-
fi
|
|
110
|
-
|
|
111
|
-
# Check: type-check
|
|
112
|
-
if pnpm type-check >/dev/null 2>&1; then
|
|
113
|
-
echo " type_check: pass"
|
|
114
|
-
else
|
|
115
|
-
echo " type_check: fail"
|
|
116
|
-
QUALITY_VERDICT="fail"
|
|
117
|
-
FINDINGS_IMPORTANT+=("Type errors in unit branch")
|
|
118
|
-
fi
|
|
119
|
-
|
|
120
|
-
# Check: build
|
|
121
|
-
if pnpm build >/dev/null 2>&1; then
|
|
122
|
-
echo " build: pass"
|
|
123
|
-
else
|
|
124
|
-
echo " build: fail"
|
|
125
|
-
QUALITY_VERDICT="fail"
|
|
126
|
-
FINDINGS_CRITICAL+=("Build failure in unit branch")
|
|
127
|
-
fi
|
|
128
|
-
|
|
129
|
-
echo " quality_verdict: $QUALITY_VERDICT"
|
|
130
|
-
fi
|
|
131
|
-
|
|
132
|
-
# ─── Verdict Summary ────────────────────────────────────────────────────────
|
|
133
|
-
if [[ "$SPEC_VERDICT" == "pass" && "$QUALITY_VERDICT" == "pass" ]]; then
|
|
134
|
-
OVERALL="pass"
|
|
135
|
-
DISPOSITION="eligible_for_merge"
|
|
136
|
-
elif [[ "$SPEC_VERDICT" == "fail" || "$QUALITY_VERDICT" == "fail" ]]; then
|
|
137
|
-
OVERALL="fail"
|
|
138
|
-
DISPOSITION="needs_fix_or_exclude"
|
|
139
|
-
else
|
|
140
|
-
OVERALL="incomplete"
|
|
141
|
-
DISPOSITION="blocked"
|
|
142
|
-
fi
|
|
143
|
-
|
|
144
|
-
echo "verdict:"
|
|
145
|
-
echo " overall: $OVERALL"
|
|
146
|
-
echo " spec_compliance: $SPEC_VERDICT"
|
|
147
|
-
echo " code_quality: $QUALITY_VERDICT"
|
|
148
|
-
echo " retry_count: $RETRY_COUNT"
|
|
149
|
-
echo " disposition: $DISPOSITION"
|
|
150
|
-
echo " findings:"
|
|
151
|
-
echo " critical:"
|
|
152
|
-
for f in "${FINDINGS_CRITICAL[@]:-}"; do
|
|
153
|
-
[[ -n "$f" ]] && echo " - \"$f\""
|
|
154
|
-
done
|
|
155
|
-
echo " important:"
|
|
156
|
-
for f in "${FINDINGS_IMPORTANT[@]:-}"; do
|
|
157
|
-
[[ -n "$f" ]] && echo " - \"$f\""
|
|
158
|
-
done
|
|
159
|
-
echo " minor:"
|
|
160
|
-
for f in "${FINDINGS_MINOR[@]:-}"; do
|
|
161
|
-
[[ -n "$f" ]] && echo " - \"$f\""
|
|
162
|
-
done
|
|
163
|
-
|
|
164
|
-
# ─── Fix-Loop ────────────────────────────────────────────────────────────────
|
|
165
|
-
# The orchestrator agent drives the fix-loop:
|
|
166
|
-
# 1. If verdict is "fail" and retries remain → action: retry
|
|
167
|
-
# Orchestrator dispatches implementer subagent with findings,
|
|
168
|
-
# then re-runs this script with --retry-count <N+1>
|
|
169
|
-
# 2. If verdict is "fail" and retry_count >= retry_limit → action: dispatch_fix
|
|
170
|
-
# Terminal failure — manual intervention or exclusion needed
|
|
171
|
-
# 3. If verdict is "pass" → action: finalize
|
|
172
|
-
|
|
173
|
-
echo "fix_loop:"
|
|
174
|
-
echo " retry_count: $RETRY_COUNT"
|
|
175
|
-
echo " retry_limit: $RETRY_LIMIT"
|
|
176
|
-
if [[ "$OVERALL" == "fail" ]]; then
|
|
177
|
-
if [[ $RETRY_COUNT -lt $RETRY_LIMIT ]]; then
|
|
178
|
-
echo " action: retry"
|
|
179
|
-
echo " next_retry_count: $((RETRY_COUNT + 1))"
|
|
180
|
-
else
|
|
181
|
-
echo " action: dispatch_fix"
|
|
182
|
-
fi
|
|
183
|
-
else
|
|
184
|
-
echo " action: finalize"
|
|
185
|
-
fi
|
|
186
|
-
|
|
187
|
-
echo "---"
|