agent/tests/cli/pipeline/Taskfile.yaml
Snider 2f9ffd5324 feat(agent/pipeline): implement pipeline/budget + pipeline/training (#536)
Replaces the #535 stubs with full impl per RFC.pipeline.md.

Lands:
* pkg/agentic/pipeline_budget.go (extend) — budget/plan reads pool/rate
  config, counts logged dispatches from .core/db.duckdb (JSONL fallback),
  prints per-pool remaining budget. budget/log appends to
  .core/journal/dispatch.jsonl + mirrors to state store.
* pkg/agentic/pipeline_training.go (extend) — training/capture pulls PR
  meta via MetaReader, captures PR diff via Forge PR-diff endpoint with
  `git show` fallback, records structural CodeRabbit-equivalent finding
  counts from review-thread totals, appends to .core/training/journal.jsonl.
  training/stats aggregates totals + zero-finding counts by repo.
  training/export filters to zero-finding entries → .core/training/export.jsonl
  (clean LEM training data).
* pkg/agentic/training_journal.go (NEW) — shared journal helpers
* AX-10 tests replace stubs (pipeline_budget_test.go +
  pipeline_training_test.go)
* tests/cli/pipeline/Taskfile.yaml — end-to-end smoke covers all 5
  subcommands against isolated temp workspace + local Forge stub

LEM training data pipeline now feedable: merged PRs → training/capture
→ journal.jsonl → training/export (zero-finding filter) → ready for next
LEK iteration.

Sandbox blocked from go test by go.work + private-dep resolution;
gofmt clean. Forge PR diff endpoint shape verified against Gitea API
docs (1.19).

Co-authored-by: Codex <noreply@openai.com>
Closes tasks.lthn.sh/view.php?id=536
2026-04-25 23:57:27 +01:00

137 lines
5.2 KiB
YAML

version: "3"
tasks:
test:
cmds:
- |
bash <<'EOF'
set -euo pipefail
source ../_lib/run.sh
go build -trimpath -ldflags="-s -w" -o bin/core-agent ../../../cmd/core-agent
workspace="$(mktemp -d)"
port_file="$(mktemp)"
trap '[[ -n "${server_pid:-}" ]] && kill "${server_pid}" 2>/dev/null || true' EXIT
export CORE_WORKSPACE="$workspace"
export CORE_HOME="$workspace"
export DIR_HOME="$workspace"
export CODE_PATH="$workspace/code"
mkdir -p "$CODE_PATH/core"
cat >"$workspace/agents.yaml" <<'YAML'
version: 1
concurrency:
codex: 1
rates:
codex:
reset_utc: "00:00"
daily_limit: 2
sustained_delay: 30
YAML
python3 - "$port_file" <<'PY' &
import json
import sys
from http.server import BaseHTTPRequestHandler, HTTPServer
port_file = sys.argv[1]
class Handler(BaseHTTPRequestHandler):
def do_GET(self):
if self.path == "/api/v1/repos/core/go-io/pulls/7":
payload = {
"number": 7,
"title": "Test PR",
"state": "closed",
"html_url": "https://forge.test/core/go-io/pulls/7",
"merged": True,
"mergeable": True,
"mergeable_state": "clean",
"review_threads_total": 0,
"review_threads_resolved": 0,
"review_comments": 0,
"comments": 0,
"head": {
"ref": "agent/fix-tests",
"sha": "deadbeef",
"repo": {
"updated_at": "2026-04-25T12:00:00Z",
"pushed_at": "2026-04-25T12:00:00Z",
},
},
"base": {"ref": "dev"},
}
self.send_response(200)
self.end_headers()
self.wfile.write(json.dumps(payload).encode())
return
if self.path == "/api/v1/repos/core/go-io/commits/deadbeef/status":
payload = {"statuses": [{"context": "qa", "state": "success"}]}
self.send_response(200)
self.end_headers()
self.wfile.write(json.dumps(payload).encode())
return
if self.path == "/api/v1/repos/core/go-io/pulls/7.diff":
self.send_response(200)
self.end_headers()
self.wfile.write(b"diff --git a/main.go b/main.go\n+package main\n")
return
self.send_response(404)
self.end_headers()
def log_message(self, *_args):
return
server = HTTPServer(("127.0.0.1", 0), Handler)
with open(port_file, "w", encoding="utf-8") as handle:
handle.write(str(server.server_address[1]))
server.serve_forever()
PY
server_pid=$!
for _ in $(seq 1 50); do
[[ -s "$port_file" ]] && break
sleep 0.1
done
export FORGE_TOKEN="test-token"
export FORGE_URL="http://127.0.0.1:$(cat "$port_file")"
output="$(mktemp)"
run_capture_all 0 "$output" ./bin/core-agent pipeline
assert_contains "pipeline/audit <repo>" "$output"
run_capture_all 1 "$output" ./bin/core-agent pipeline/audit
assert_contains "pipeline/audit <repo>" "$output"
run_capture_all 0 "$output" ./bin/core-agent pipeline/budget/plan
assert_contains "codex" "$output"
grep -Eq 'codex[[:space:]]+0[[:space:]]+2[[:space:]]+2' "$output"
run_capture_all 0 "$output" ./bin/core-agent pipeline/budget/log --repo=go-io --agent=codex --model=gpt-5.4
assert_contains "journal:" "$output"
run_capture_all 0 "$output" ./bin/core-agent pipeline/budget/plan
assert_contains "codex" "$output"
grep -Eq 'codex[[:space:]]+1[[:space:]]+2[[:space:]]+1' "$output"
run_capture_all 0 "$output" ./bin/core-agent pipeline/training/capture 7 --repo=go-io
assert_contains "go-io#7" "$output"
run_capture_all 0 "$output" ./bin/core-agent pipeline/training/stats
assert_contains "total_prs: 1" "$output"
assert_contains "zero_finding_prs: 1" "$output"
run_capture_all 0 "$output" ./bin/core-agent pipeline/training/export
assert_contains "exported: 1" "$output"
assert_contains '"repo":"go-io"' "$workspace/journal/dispatch.jsonl"
assert_contains '"pr_number":7' "$workspace/training/journal.jsonl"
assert_jq '.repo == "go-io" and .pr_number == 7 and .coderabbit_findings == 0' "$workspace/training/export.jsonl"
EOF