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
137 lines
5.2 KiB
YAML
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
|