Skip to content

Commit 5554693

Browse files
authored
Merge pull request #19 from reoring/roboppi/loop-20260227-121443
feat(workflow): resolve management agent review findings
2 parents 99211bd + 8339e53 commit 5554693

35 files changed

Lines changed: 2040 additions & 244 deletions

‎.gitignore‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ dist
77

88
# Local Roboppi workflow state
99
.roboppi-loop/
10+
context/
1011

1112
# Local scratch notes (do not commit)
1213
docs/wip/

‎docs/features/workflow-management-agent-implementation-review.md‎

Lines changed: 213 additions & 0 deletions
Large diffs are not rendered by default.

‎docs/features/workflow-management-agent.md‎

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Workflow Management Agent: Adaptive Supervisor for Runtime Workflow Control
22

3-
Status: proposal (not yet implemented)
3+
Status: implemented (with ongoing refinements)
44

55
This document defines a "Workflow Management Agent" feature for Roboppi.
66

@@ -1460,8 +1460,8 @@ orchestrators, but safer and more predictable than fully autonomous agents.
14601460
## 15. Pi (coding-agent) SDK Integration
14611461

14621462
This section describes a concrete implementation path that uses the Pi
1463-
`coding-agent` as an SDK (vendored at `refs/coding-agent-repo/packages/coding-agent/`)
1464-
to power the Workflow Management Agent.
1463+
`coding-agent` as an SDK (installed as `@mariozechner/pi-coding-agent`, loaded via
1464+
dynamic import) to power the Workflow Management Agent.
14651465

14661466
The goal is to reuse Pi's existing agent/session/tooling infrastructure while
14671467
keeping Roboppi's mechanism/policy separation intact: Pi provides an agent
@@ -1474,8 +1474,8 @@ concurrency, and directive validation.
14741474
entire workflow, improving cross-step diagnosis and consistency.
14751475
- **Typed tools and extensions**: use Pi's tool framework to make directive
14761476
emission structured (tool call) instead of relying on free-form text.
1477-
- **Pluggable capabilities**: map `READ/EDIT/RUN_TESTS/RUN_COMMANDS` to an
1478-
explicit Pi tool set.
1477+
- **Capability mapping**: in v1, keep the embedded PiSdkEngine read-only (§15.5)
1478+
regardless of declared capabilities.
14791479
- **Optional reuse**: the same SDK can later be used to implement a first-class
14801480
Roboppi worker kind (Pi-backed step workers), reducing reliance on external
14811481
CLIs.
@@ -1597,16 +1597,16 @@ Engine rules:
15971597

15981598
### 15.5 Capability → Pi tool mapping
15991599

1600-
Map Roboppi capabilities to explicit Pi tools:
1600+
In v1, the embedded PiSdkEngine is intentionally **read-only** to preserve
1601+
mechanism/policy separation.
16011602

1602-
- `READ` → `read, ls, grep, find`
1603-
- `EDIT` → `edit, write` (and usually `read`)
1604-
- `RUN_TESTS` → restricted command execution (see below)
1605-
- `RUN_COMMANDS` → command execution
1603+
- PiSdkEngine exposes only: `read, ls, grep, find`
1604+
- PiSdkEngine does NOT expose `bash`, `edit`, or `write` even if capabilities
1605+
request them.
16061606

1607-
Important: Pi's built-in `bash` tool can execute arbitrary commands. If Roboppi
1608-
policy assumes command gating, prefer wrapping command execution behind a
1609-
Roboppi-controlled tool that enforces:
1607+
Important: Pi's built-in `bash` tool can execute arbitrary commands. If you need
1608+
agent-driven command execution, prefer wrapping it behind a Roboppi-controlled
1609+
tool (or using a sidecar engine) that enforces:
16101610

16111611
- working directory = step workspace
16121612
- per-command timeouts (`max_command_time`)
Lines changed: 186 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,186 @@
1+
# Roboppi Self-Dev Loop: fix management agent review findings
2+
#
3+
# This workflow turns the implementation review doc into a TODO, then loops:
4+
# implement -> (tests + review verdict) -> fix ... until PASS.
5+
#
6+
# Run (from the Roboppi repo root):
7+
# bun run src/workflow/run.ts examples/workflow-management-agent-impl-review-loop.yaml --workspace . --verbose
8+
9+
name: workflow-management-agent-impl-review-loop
10+
version: "1"
11+
description: "Roboppi self-dev: resolve management-agent implementation review findings"
12+
timeout: "300m"
13+
concurrency: 1
14+
create_branch: true
15+
branch_transition_step: "branch"
16+
17+
steps:
18+
bootstrap:
19+
description: "Initialize loop state (.roboppi-loop/*)."
20+
worker: CUSTOM
21+
instructions: |
22+
bash "${ROBOPPI_ROOT:-.}/scripts/self-dev/workflow-management-agent-impl-review/bootstrap.sh"
23+
capabilities: [READ, EDIT, RUN_COMMANDS]
24+
timeout: "2m"
25+
26+
branch:
27+
description: "Create or reuse a working branch"
28+
worker: CUSTOM
29+
depends_on: [bootstrap]
30+
instructions: |
31+
bash "${ROBOPPI_ROOT:-.}/scripts/agent-pr-loop/branch.sh"
32+
capabilities: [READ, RUN_COMMANDS]
33+
timeout: "1m"
34+
35+
todo:
36+
description: "Convert implementation review doc into TODO checklist"
37+
worker: OPENCODE
38+
model: "openai/gpt-5.2"
39+
depends_on: [branch]
40+
instructions: |
41+
You are OpenCode.
42+
43+
Task: Convert the implementation review findings into a concrete TODO checklist.
44+
45+
Read:
46+
- .roboppi-loop/request.md
47+
- docs/features/workflow-management-agent-implementation-review.md
48+
49+
Note: do not rely on file-globbing for dot-directories; `.roboppi-loop/*`
50+
may not be discoverable via glob in some tool environments. Read/write
51+
the paths directly.
52+
53+
Write/update:
54+
- .roboppi-loop/todo.md
55+
56+
Requirements:
57+
- Use Markdown checklist items: "- [ ] ..."
58+
- Group by P0/P1/P2 severity.
59+
- Include file paths and symbols when possible.
60+
- Include explicit test tasks (at least: make typecheck, make test-all).
61+
- If a finding is already fixed, include a task to confirm + update the review doc.
62+
capabilities: [READ, EDIT]
63+
timeout: "20m"
64+
on_failure: retry
65+
max_retries: 2
66+
67+
completion_check:
68+
worker: CUSTOM
69+
instructions: |
70+
bash "${ROBOPPI_ROOT:-.}/scripts/agent-pr-loop/todo-check.sh"
71+
capabilities: [READ, RUN_COMMANDS]
72+
timeout: "30s"
73+
74+
max_iterations: 3
75+
on_iterations_exhausted: abort
76+
outputs:
77+
- name: todo
78+
path: ".roboppi-loop/todo.md"
79+
type: review
80+
81+
implement:
82+
description: "Implement fixes; run tests+review in completion_check; repeat until PASS"
83+
worker: CLAUDE_CODE
84+
model: "claude-opus-4-6"
85+
depends_on: [todo]
86+
instructions: |
87+
You are Claude Code.
88+
89+
Important: you are running as Claude Code via Roboppi.
90+
- Read `.roboppi-loop/request.md` and `.roboppi-loop/todo.md` by file path (do not rely on globbing dot-directories).
91+
92+
Read:
93+
- .roboppi-loop/request.md
94+
- .roboppi-loop/todo.md
95+
- .roboppi-loop/review.md (if present)
96+
- .roboppi-loop/fix.md (if present)
97+
98+
Task:
99+
- If .roboppi-loop/fix.md exists and is non-empty, apply ONLY those fixes (minimal, targeted changes).
100+
- Otherwise, implement the TODO checklist items.
101+
- Update the TODO checkboxes as you complete items.
102+
- Keep changes focused; avoid drive-by refactors.
103+
104+
Notes:
105+
- Tests are run in the completion_check phase; focus here on implementation and documentation updates.
106+
capabilities: [READ, EDIT, RUN_TESTS, RUN_COMMANDS]
107+
timeout: "60m"
108+
on_failure: retry
109+
max_retries: 1
110+
111+
convergence:
112+
enabled: true
113+
stall_threshold: 2
114+
max_stage: 3
115+
fail_on_max_stage: true
116+
117+
completion_check:
118+
worker: OPENCODE
119+
model: "openai/gpt-5.2"
120+
variant: "xhigh"
121+
decision_file: ".roboppi-loop/review.verdict"
122+
instructions: |
123+
You are OpenCode.
124+
125+
Sandbox rule:
126+
- Do NOT read or write outside the workspace directory.
127+
- Treat `/tmp/**` as forbidden (Roboppi will auto-reject external_directory reads).
128+
- If you need temp files/dirs, use `.roboppi-loop/tmp/*`.
129+
130+
Task:
131+
1) Run tests:
132+
- make test-all
133+
2) Review the changes against the request + TODO + implementation-review doc.
134+
3) Write/update:
135+
- .roboppi-loop/review.md
136+
- .roboppi-loop/review.verdict (single-line JSON; see Output rules)
137+
4) If verdict is FAIL, also write/update:
138+
- .roboppi-loop/fix.md (non-empty; concrete, actionable steps; include file paths)
139+
5) If verdict is PASS:
140+
- Clear .roboppi-loop/fix.md if it exists (truncate to empty)
141+
142+
Before reviewing, generate deterministic review inputs:
143+
- bash "${ROBOPPI_ROOT:-.}/scripts/agent-pr-loop/review-inputs.sh"
144+
145+
Debugging rule (branch verification):
146+
- If `make test-all` fails in the branch verification phase and you need logs,
147+
re-run branch verification with a verify dir INSIDE the workspace, e.g.:
148+
- bash "bash tests/branch/run-branch-verification.sh .roboppi-loop/tmp/branch-verify"
149+
- Do not use `mktemp -d /tmp/...`.
150+
151+
You must read at least:
152+
- .roboppi-loop/request.md
153+
- .roboppi-loop/todo.md
154+
- docs/features/workflow-management-agent-implementation-review.md
155+
- .roboppi-loop/review.base_ref
156+
- .roboppi-loop/review.diff
157+
- .roboppi-loop/review.status
158+
- .roboppi-loop/review.untracked
159+
- .roboppi-loop/review.untracked.diff
160+
161+
Format for .roboppi-loop/review.md:
162+
- Sections: Summary, Issues, Verification
163+
164+
Output rules:
165+
- Write .roboppi-loop/review.verdict as a single-line JSON object:
166+
- complete => {"decision":"complete","check_id":"$ROBOPPI_COMPLETION_CHECK_ID"}
167+
- incomplete => {"decision":"incomplete","check_id":"$ROBOPPI_COMPLETION_CHECK_ID"}
168+
- When FAIL, also include:
169+
- "reasons": ["..."]
170+
- "fingerprints": ["..."]
171+
- Fingerprints should be stable across iterations (e.g. test name, file:line, or finding id).
172+
capabilities: [READ, EDIT, RUN_TESTS, RUN_COMMANDS]
173+
timeout: "90m"
174+
175+
max_iterations: 8
176+
on_iterations_exhausted: abort
177+
outputs:
178+
- name: review
179+
path: ".roboppi-loop/review.md"
180+
type: review
181+
- name: verdict
182+
path: ".roboppi-loop/review.verdict"
183+
type: text
184+
- name: fix
185+
path: ".roboppi-loop/fix.md"
186+
type: review
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
#!/usr/bin/env bash
2+
set -euo pipefail
3+
4+
# Bootstrap for the Roboppi self-dev loop targeting:
5+
# docs/features/workflow-management-agent-implementation-review.md
6+
7+
if ! git rev-parse --git-dir > /dev/null 2>&1; then
8+
echo "Error: workspace must be a git repository" >&2
9+
exit 1
10+
fi
11+
12+
LOOP_DIR=.roboppi-loop
13+
mkdir -p "${LOOP_DIR}"
14+
15+
# Clear derived artifacts from prior runs (keep request + branch/base settings).
16+
rm -f \
17+
"${LOOP_DIR}/review.md" \
18+
"${LOOP_DIR}/review.verdict" \
19+
"${LOOP_DIR}/fix.md" \
20+
"${LOOP_DIR}/review.base_ref" \
21+
"${LOOP_DIR}/review.diff" \
22+
"${LOOP_DIR}/review.status" \
23+
"${LOOP_DIR}/review.untracked" \
24+
"${LOOP_DIR}/review.untracked.diff"
25+
26+
if [ ! -f "${LOOP_DIR}/request.md" ]; then
27+
cat > "${LOOP_DIR}/request.md" <<'EOF'
28+
# Request
29+
30+
Roboppi を使って Roboppi 自体を開発するために、
31+
`docs/features/workflow-management-agent-implementation-review.md` に記載されている
32+
指摘 (P0/P1/P2) をすべて解消してください。
33+
34+
## Scope
35+
- 対象: `docs/features/workflow-management-agent-implementation-review.md`
36+
- 目的: TODO 化 -> 実装 -> テストパス -> 実装レビュー完了 までのループ
37+
38+
## Acceptance Criteria
39+
- [ ] `docs/features/workflow-management-agent-implementation-review.md` の P0 指摘が解消されている
40+
- [ ] P1/P2 も必要な分だけ解消され、仕様/実装/ドキュメントが整合している
41+
- [ ] `make test-all` が PASS
42+
- [ ] 実装レビュー (差分+仕様照合) が PASS
43+
EOF
44+
fi
45+
46+
REQ_BYTES=$(wc -c < "${LOOP_DIR}/request.md" | tr -d ' ')
47+
if [ "${REQ_BYTES}" -lt 120 ]; then
48+
echo "Error: ${LOOP_DIR}/request.md is too small. Please fill it in first." >&2
49+
exit 1
50+
fi
51+
52+
if [ -n "${BASE_BRANCH:-}" ]; then
53+
BASE_BRANCH="${BASE_BRANCH}"
54+
else
55+
BASE_BRANCH="$(git rev-parse --abbrev-ref HEAD 2>/dev/null || echo HEAD)"
56+
fi
57+
58+
if [ "${BASE_BRANCH}" = "HEAD" ]; then
59+
echo "Error: detached HEAD detected. Set BASE_BRANCH or checkout a branch." >&2
60+
exit 1
61+
fi
62+
63+
echo "${BASE_BRANCH}" > "${LOOP_DIR}/base-branch.txt"
64+
git rev-parse "${BASE_BRANCH}^{commit}" > "${LOOP_DIR}/base-sha.txt" 2>/dev/null || true
65+
66+
command -v opencode > /dev/null 2>&1 || { echo "Error: opencode not found in PATH" >&2; exit 1; }
67+
68+
echo "OK" > "${LOOP_DIR}/bootstrap.ok"

‎src/core/agentcore.ts‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,7 @@ export class AgentCore {
275275
workspaceRef: payload.workspaceRef,
276276
instructions: payload.instructions,
277277
...(payload.model ? { model: payload.model } : {}),
278+
...(payload.variant ? { variant: payload.variant } : {}),
278279
capabilities: payload.capabilities,
279280
outputMode: payload.outputMode,
280281
budget: payload.budget,

‎src/types/worker-task-job-payload.ts‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ export interface WorkerTaskJobPayload {
1111
workspaceRef: string;
1212
instructions: string;
1313
model?: string;
14+
variant?: string;
1415
capabilities: WorkerCapability[];
1516
outputMode: OutputMode;
1617
budget: {
@@ -42,6 +43,9 @@ export function isWorkerTaskJobPayload(value: unknown): value is WorkerTaskJobPa
4243
if (typeof v.workspaceRef !== "string") return false;
4344
if (typeof v.instructions !== "string") return false;
4445

46+
if (v.model !== undefined && typeof v.model !== "string") return false;
47+
if (v.variant !== undefined && typeof v.variant !== "string") return false;
48+
4549
// workerKind must be a known enum value
4650
if (typeof v.workerKind !== "string" || !VALID_WORKER_KINDS.has(v.workerKind)) return false;
4751

‎src/types/worker-task.ts‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ export interface WorkerTask {
3333
instructions: string;
3434
/** Optional model identifier for LLM-backed workers (adapter-specific format). */
3535
model?: string;
36+
/** Optional model variant / reasoning effort hint (worker-specific). */
37+
variant?: string;
3638
capabilities: WorkerCapability[];
3739
outputMode: OutputMode;
3840
budget: WorkerBudget;

‎src/worker/adapters/claude-code-adapter.ts‎

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { WorkerStatus, ErrorClass } from "../../types/index.js";
2-
import { WorkerKind, WorkerCapability } from "../../types/index.js";
2+
import { WorkerKind, WorkerCapability, OutputMode } from "../../types/index.js";
33
import type { WorkerTask } from "../../types/index.js";
44
import type { WorkerResult, Artifact, Observation } from "../../types/index.js";
55
import type { WorkerEvent, WorkerHandle } from "../worker-adapter.js";
@@ -10,7 +10,7 @@ export interface ClaudeCodeAdapterConfig {
1010
claudeCommand?: string;
1111
defaultArgs?: string[];
1212
gracePeriodMs?: number;
13-
outputFormat?: "json" | "text";
13+
outputFormat?: "json" | "text" | "stream-json";
1414
}
1515

1616
export function mapCapabilitiesToAllowedTools(
@@ -63,8 +63,22 @@ export function buildArgs(
6363
args.push("--print", task.instructions);
6464

6565
// Output format
66-
if (config.outputFormat === "json") {
66+
// - For streaming tasks (TUI), prefer Claude's `stream-json` to emit events
67+
// incrementally; otherwise logs can be empty until the process exits.
68+
// - Preserve legacy config behavior for non-streaming tasks.
69+
const effectiveOutputFormat =
70+
config.outputFormat === "json" && task.outputMode === OutputMode.STREAM
71+
? "stream-json"
72+
: config.outputFormat;
73+
74+
if (effectiveOutputFormat === "json") {
6775
args.push("--output-format", "json");
76+
} else if (effectiveOutputFormat === "stream-json") {
77+
args.push("--output-format", "stream-json");
78+
// Claude CLI requires --verbose when using --print with stream-json.
79+
args.push("--verbose");
80+
// Best-effort: include partial chunks so the TUI gets incremental updates.
81+
args.push("--include-partial-messages");
6882
}
6983

7084
// Allowed tools from capabilities

0 commit comments

Comments
 (0)