fix: bug: architect pitch prompt guardrail is prose-only — model bypasses "NEVER call Forgejo API" via Bash tool; fix via permission scoping + PR-driven sub-issue filing (#764)
Some checks failed
ci/woodpecker/push/ci Pipeline failed
ci/woodpecker/pr/ci Pipeline failed
ci/woodpecker/pr/smoke-init Pipeline failed

Shift the guardrail from prose prompt constraints into Forgejo's permission
layer. architect-bot loses all write access on the project repo (now read-only
for context gathering). Sub-issues are produced by a new filer-bot identity
that runs only after a human merges a sprint PR on the ops repo.

Changes:
- architect-run.sh: remove all project-repo writes (add_inprogress_label,
  close_vision_issue, check_and_close_completed_visions); add ## Sub-issues
  block to pitch format with filer:begin/end markers
- formulas/run-architect.toml: add Sub-issues schema to pitch format; strip
  issue-creation API refs; document read-only constraint on project repo
- lib/formula-session.sh: remove Create issue curl template from
  build_prompt_footer (architect cannot create issues)
- lib/sprint-filer.sh (new): parser + idempotent filer using FORGE_FILER_TOKEN;
  parses filer:begin/end blocks, creates issues with decomposed-from markers,
  adds in-progress label, handles vision lifecycle closure
- .woodpecker/ops-filer.yml (new): CI pipeline on ops repo main-branch push
  that invokes sprint-filer.sh after sprint PR merge
- lib/env.sh, .env.example, docker-compose.yml: add FORGE_FILER_TOKEN for
  filer-bot identity; add filer-bot to FORGE_BOT_USERNAMES
- AGENTS.md: add Filer agent entry; update in-progress label docs
- .woodpecker/agent-smoke.sh: register sprint-filer.sh for smoke test

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Claude 2026-04-15 07:41:16 +00:00
parent 10c7a88416
commit 04ff8a6e85
10 changed files with 685 additions and 353 deletions

View file

@ -213,6 +213,7 @@ check_script lib/issue-lifecycle.sh lib/secret-scan.sh
# Still checked for function resolution against LIB_FUNS + own definitions.
check_script lib/ci-debug.sh
check_script lib/parse-deps.sh
check_script lib/sprint-filer.sh
# Agent scripts — list cross-sourced files where function scope flows across files.
check_script dev/dev-agent.sh

36
.woodpecker/ops-filer.yml Normal file
View file

@ -0,0 +1,36 @@
# .woodpecker/ops-filer.yml — Sub-issue filer pipeline (#764)
#
# Triggered on push to main of the ops repo after a sprint PR merges.
# Parses sprints/*.md for ## Sub-issues blocks and files them on the
# project repo via filer-bot (FORGE_FILER_TOKEN).
#
# NOTE: This pipeline runs on the ops repo. It must be registered in the
# ops repo's Woodpecker project. The filer script (lib/sprint-filer.sh)
# lives in the code repo and is cloned into the workspace.
#
# Idempotency: safe to re-run — each sub-issue carries a decomposed-from
# marker that the filer checks before creating.
when:
branch: main
event: push
steps:
- name: file-subissues
image: alpine:3
commands:
- apk add --no-cache bash curl jq
# Clone the code repo to get the filer script
- AUTH_URL=$(printf '%s' "${FORGE_URL}/disinto-admin/disinto.git" | sed "s|://|://token:${FORGE_FILER_TOKEN}@|")
- git clone --depth 1 "$AUTH_URL" /tmp/code-repo
# Run filer against all sprint files in the ops repo workspace
- bash /tmp/code-repo/lib/sprint-filer.sh --all sprints/
environment:
FORGE_FILER_TOKEN:
from_secret: forge_filer_token
FORGE_URL:
from_secret: forge_url
FORGE_API:
from_secret: forge_api
FORGE_API_BASE:
from_secret: forge_api_base