Commit Graph

7 Commits

Author SHA1 Message Date
Marcos 513de0e3a8 docs(pilot): document AI-USAGE label, token attribution, webhook denylist
- new "AI-USAGE label" section: what gets reported, the attributed-vs-measured
  distinction, PRAGENT_USAGE_ALWAYS, regression-clean without the label.
- new "Webhook fires on any PR update (except closed)" section: denylist
  semantics + why the AI-REVIEW gate + sha dedupe keep it safe.
- arch diagram gate updated (allowlist → denylist; AI-USAGE side-gate).
- opencode engine step 4: --format json + parse_opencode_events → (text, usage).

Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-18 04:17:32 +00:00
Marcos 76b6752f48 fix(review): language-tagged suggestion fence for Gitea syntax highlighting
Gitea 1.26.x has no GitHub-style 'Apply suggestion' button — a ```suggestion
fence is just an unknown-language code block, so chroma does not highlight it
and there is no apply control. Switch inline_comment_body to wrap the suggested
fix in a fence tagged with the file's language (new _lang_for_path helper,
.java→java, .ts→typescript, .py→python, ...), so Gitea syntax-highlights the
code. No capability lost (there was never an apply button on this Gitea
version). Correct the docstrings/skills/README that wrongly claimed an
apply-button was rendered.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-18 01:26:37 +00:00
Marcos c7c6c3edd2 fix(opencode): resolve /usr/local/bin -> /usr/bin opencode path in pod
The npm prefix in the Dockerfile is /usr, so opencode installs to
/usr/bin/opencode (symlink to /usr/lib/node_modules/...), not
/usr/local/bin/opencode. The cluster E2E failed with ENOENT on
/usr/local/bin/opencode. Fix in three places:
- Dockerfile ENV PRAGENT_OPENCODE_BIN=/usr/bin/opencode
- ~/k8s/pragent-webhook.yaml env value
- _opencode_bin() now defensive: if the configured path is missing,
  falls back to shutil.which('opencode') before the linuxbrew last-resort.
- Dockerfile + README deploy notes: containerd import is sudoless via
  the group-readable raw socket (the microk8s ctr wrapper sudo-wraps).

Verified: rebuilt + reimported + rolled out; PR #5 (sha 985061c0) review
posted in-pod via the opencode engine (findings=2 inline=2 ok=True),
summary + 2 [CRITICAL] inline comments with suggestions + refs + sha marker.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-17 23:31:53 +00:00
Marcos 8912f6721b deploy: combined opencode image + k8s + docs
- pilot/Dockerfile: python:3.12-slim + node 20 + opencode-ai@1.3.10 +
  ripgrep + pyright/typescript-language-server/eslint (npm) + ruff (pip).
  Factory + pilot scripts baked at /app. imagePullPolicy: Never (local
  import into microk8s containerd).
- .dockerignore: lean build context.
- ~/k8s/pragent-webhook.yaml: image pragent-webhook:opencode, emptyDir work
  at /tmp/pragent-work, env (PRAGENT_ENGINE, OPENCODE_MODEL, PRAGENT_FACTORY_DIR,
  PRAGENT_OPENCODE_BIN, PRAGENT_WORK_ROOT, PRAGENT_RTK_DIR='', timeout 540),
  resources 200m/512Mi -> 1500m/2Gi. Drops the ConfigMap scripts volume.
- pilot/README-webhook.md + .opencode/README.md: opencode engine section,
  build/import/apply steps, factory guide fixes (parse_review_output, steps).

Image builds (1.62GB, smoke-tested: opencode+LSPs+factory+env all present).
Import into microk8s containerd + apply pending (ctr needs sudo).

Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-17 23:11:58 +00:00
Marcos 8758b22802 docs: techspark user webhook (id=6) + org-webhook note + cleanup token
Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-17 20:38:14 +00:00
Marcos 90cea84f6f pilot: dedupe + repo config + inline comments w/ suggestions
- Dedupe: Gitea-as-state. Scan existing reviews for a hidden
  <!-- pragent:sha=... --> marker matching the head sha; skip if present
  (kills duplicate reviews on label-toggle / re-fire). Prior review bodies
  fed back as 'already said' context (light framework §6.1).
- Repo-local focus: optional .pr-review.json at repo root
  ({focus,exclude_paths,languages,instructions}), fetched at head ref.
- Inline comments + apply-able suggestions: model emits JSON findings
  {severity,path,line,problem,fix,suggestion}; diff hunks parsed into valid
  (path,new_line) RIGHT-side anchors; anchored findings become positional
  review comments with a ```suggestion fence (Gitea apply-button);
  unanchored findings fold into the summary body.
- Tests: parse_diff_anchors, parse_findings (tolerant JSON), split_findings,
  inline_comment_body, summary_bullets, parse_repo_config, reviewed_shas,
  prior_review_bodies, sha-marker. 35 pass.
- Bump OLLAMA_MAX_TOKENS default 6000 -> 8000 (suggestions add length).

Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-17 19:59:36 +00:00
Marcos 789fb38bae pilot: central webhook service (user-level Gitea webhook + AI-REVIEW gate)
- pilot/webhook_server.py: stdlib HTTP receiver. HMAC-verifies X-Gitea-Signature,
  gates on pull_request action + AI-REVIEW label, runs review_pr in a background
  thread (responds 202 immediately so Gitea's delivery timeout never fires).
  Accepts both GitHub-style (labeled/synchronize) and Gitea event-type-style
  (label_updated/synchronized) action names.
- pilot/ai_review.py: extract review_pr() core so both the CI run() and the
  webhook server share one review path. run() is now an env-driven wrapper.
- pilot/README-webhook.md: architecture, onboarding, one-time per-owner
  user-webhook setup, the Gitea 1.26.1 system-webhook bug, the SSRF
  ALLOWED_HOST_LIST change, K8s deploy + script-update recipe.
- README.md + design doc: note the webhook service as the preferred delivery
  path (partially reverses 'central webhook = non-goal', pilot only).

Gitea 1.26.1 system webhooks broken (POST /admin/hooks -> 201 but never
persists); user-level webhooks (one per repo-owner) are the working fallback.
Gitea SSRF allow-list blocks in-cluster webhook targets by default; required a
scoped [webhook] ALLOWED_HOST_LIST addition + gitea restart.

E2E verified 2026-08-17: pragent-bot reviewed gitea_admin/pragent PR #2 and
masi/portfolio PR #3 via the webhook service (glm-5.2:cloud).

Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-17 19:38:07 +00:00