From 949724729daa6669d73805cace10b4f50b76fcc3 Mon Sep 17 00:00:00 2001 From: vitya Date: Mon, 8 Jun 2026 15:32:35 +0300 Subject: [PATCH] task(agents-task-runner-vds-deploy): take + DRY_RUN validated + .admin claim-guard MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Take task to 🔴, create per-task file (was on board w/o file). - DRY_RUN smoke passed end-to-end on this workstation (host task-runner :3000, one tick via POST/GET). Real shared-board read; preview candidate OpeItcLoc03/MoreThenCms/cms-maljarka-https-mode-bug-fix; no claim/spawn. - Finding: .admin had NO policy.toml; claim gate ignores consult_policy, so the HARD ".admin excluded from autonomous claim" guard was UNENFORCED. Add .tasks/policy.toml default_weight="needs-human" → every .admin task fails the L3 needs-human claim gate. Gates autonomous poller only; INERT until pushed (claim reads policy.toml via Gitea backend, not local disk). - Build-prereq in task Next-action was a phantom: runner is plain JS (no tsc); only projects-meta-mcp needs build and its dist/ already exists. Co-Authored-By: Claude Opus 4.8 (1M context) --- .tasks/STATUS.md | 6 +-- .tasks/agents-task-runner-vds-deploy.md | 55 +++++++++++++++++++++++++ .tasks/policy.toml | 21 ++++++++++ 3 files changed, 79 insertions(+), 3 deletions(-) create mode 100644 .tasks/agents-task-runner-vds-deploy.md create mode 100644 .tasks/policy.toml diff --git a/.tasks/STATUS.md b/.tasks/STATUS.md index 68617d9..24e5576 100644 --- a/.tasks/STATUS.md +++ b/.tasks/STATUS.md @@ -340,10 +340,10 @@ vehicles-loader (stostayer) деплоится в Docker у клиента (lite --- -## ⚪ [agents-task-runner-vds-deploy] — Deploy agents-task-runner (the poller) on WORKER machine(s) — per-machine federation (agent-orchestration-without-user Q9). Each worker runs its own runner, claims from the SHARED Gitea board, runs the agent LOCALLY, commits/pushes. VDS hosts the Gitea board ONLY (already up) — it is NOT a worker, nothing deploys on VDS. [Slug legacy-named '-vds-deploy'; scope corrected 2026-06-08, VDS-as-worker DROPPED.] Runtime code deploy-ready (poller registered in tasks.json, DRY_RUN + requirements-filter + confirm-gate built; compose+Dockerfile). Credentialed per-machine setup (ops). +## 🔴 [agents-task-runner-vds-deploy] — Deploy agents-task-runner (the poller) on WORKER machine(s) — per-machine federation (agent-orchestration-without-user Q9). Each worker runs its own runner, claims from the SHARED Gitea board, runs the agent LOCALLY, commits/pushes. VDS hosts the Gitea board ONLY (already up) — it is NOT a worker, nothing deploys on VDS. [Slug legacy-named '-vds-deploy'; scope corrected 2026-06-08, VDS-as-worker DROPPED.] Runtime code deploy-ready (poller registered in tasks.json, DRY_RUN + requirements-filter + confirm-gate built; compose+Dockerfile). Credentialed per-machine setup (ops). -**Status:** ready -**Where I stopped:** (not started) Re-scoped 2026-06-08: poller runs on worker machines; VDS = board host only (Gitea, already up). VDS-as-worker dropped per user. +**Status:** active +**Where I stopped:** Взята в работу 2026-06-08, oriented. Раннер локализован (`~/projects/.common/lib/agents-task-runner` v0.16.2, plain JS), common pull актуален (`e7b1143`). **Build-prereq из Next action оказался фантомом** — раннер не TS, собирать нечего; `npm run build` релевантен только projects-meta-mcp, его dist/ уже есть. Завис на user-решении: первая worker-машина (workstation vs factory Linux). См. [agents-task-runner-vds-deploy.md](agents-task-runner-vds-deploy.md). **Next action:** (0) BUILD PREREQ (from consult-execution-policy-governance review-outcome, OpeItcLoc03/common): repo tracks TS source only — `dist/` is gitignored. After pulling OpeItcLoc03/common on each worker, run `npm run build` (tsc) in BOTH lib/projects-meta-mcp AND lib/agents-task-runner, then (re)start the runner; otherwise the execution-policy governance lever (consult_policy + needs-human claim-gate, runner v0.16.x) is INERT — the old compiled JS keeps running. (1) Pick first worker machine (workstation / factory Linux). (2) Install + run agents-task-runner there, pointed at the shared Gitea board. (3) Secrets PER MACHINE: ANTHROPIC_API_KEY (headless) or `claude login` + Gitea token + projects-meta config; 600 root, not in git. (4) Capability filter: claims only what that machine can do (requirements/runtime_allowed); cheap model (sonnet/haiku) for impl polling. (5) HARD: .admin excluded from autonomous claim until governance L2/L3 lands (see blocker). (6) DRY_RUN on prod board first → then one live cycle on a real non-.admin task → spawn→commit→push, verified. (7) anti-self-review: distinct machine-id per worker. **Branch:** n/a diff --git a/.tasks/agents-task-runner-vds-deploy.md b/.tasks/agents-task-runner-vds-deploy.md new file mode 100644 index 0000000..b19e01f --- /dev/null +++ b/.tasks/agents-task-runner-vds-deploy.md @@ -0,0 +1,55 @@ +# agents-task-runner-vds-deploy + +> Slug legacy-named `-vds-deploy`; scope corrected 2026-06-08 — VDS-as-worker DROPPED. +> Per-machine federation: each WORKER runs its own `agents-task-runner`, claims from the +> SHARED Gitea board, runs the agent LOCALLY, commits/pushes. VDS hosts the Gitea board +> ONLY (already up) — not a worker, nothing deploys on it. + +## Goal +Поднять `agents-task-runner` (the poller) на первой worker-машине, нацелив на shared +Gitea-board. Машина клеймит только то, что умеет (capability-filter), `.admin` исключён +из автономного клейма до governance L2/L3. Сначала DRY_RUN на prod-board, затем один +живой цикл на реальной non-`.admin` таске: spawn → commit → push, verified. + +## Key files +- `~/projects/.common/lib/agents-task-runner/` — runtime (plain JS, `type:module`, v0.16.2) + - `server.js` — reconcile loop entry (`npm start`) + - `task-runner/server.js` — task-runner entry (`npm run task-runner`) + - `lib/cross-project-poller.js` — claim loop, requirements-filter, confirm-gate + - `lib/consult-backend/` — execution-policy governance (consult_policy + needs-human gate) + - `docker-compose.yml` / `docker-compose.host.yml` / `Dockerfile` + - `secrets.env.example` — секреты-шаблон (ANTHROPIC_API_KEY / Gitea token / projects-meta) + - `config/` — node-config overlays +- `~/projects/.common/lib/projects-meta-mcp/dist/` — уже собран (build-prereq для НЕГО, не для раннера) + +## Decisions log +- 2026-06-08: Взята в работу из ⚪ ready. **Build-prereq в Next action неточен** — раннер + это чистый JS (нет tsconfig / `npm run build`, запускается `node server.js`), собирать + нечего; `npm run build` релевантен только `projects-meta-mcp`, а его `dist/` уже есть. + Источник заблуждения — общий BUILD-prereq из consult-execution-policy-governance review, + где TS-only касался projects-meta-mcp. +- 2026-06-08: Re-scoped (из STATUS-блока): VDS = board-host only, VDS-as-worker dropped. + Poller живёт на worker-машинах (workstation / factory Linux). + +## Open questions +- [ ] **Первая worker-машина** — эта workstation (Windows) или factory Linux? (user-решение) +- [ ] Headless-auth: `ANTHROPIC_API_KEY` или `claude login`? Cheap-модель (sonnet/haiku) для impl-polling. +- [ ] Capability-filter: что именно эта машина объявляет в requirements/runtime_allowed. + +## Completed steps +- [x] 2026-06-08: orientation — раннер локализован (`~/projects/.common/lib/agents-task-runner`, + v0.16.2, JS), build-prereq разобран (фантом для раннера), common pull актуален (`e7b1143`). +- [x] 2026-06-08: prereq-чек на workstation зелёный — node v22.22, docker 29.3.1 up, + `projects-meta-mcp/dist/tasks-cli.js` собран, runner `node_modules` есть, `auth.toml` есть. +- [x] 2026-06-08: **DRY_RUN-смок прошёл end-to-end.** Хост-процесс `task-runner` (PORT 3000, + `DRY_RUN=1 AGENT_RUNTIME=claude-opus AGENT_CAPABILITIES=needs-internet SPAWN_MODE=local`), + один тик через `POST /tasks/crossProjectAgentPoller` + `GET /runs/:id` (curl `--noproxy "*"`). + Результат: `{dryRun:true, claimed:false, candidate:{project:"OpeItcLoc03/MoreThenCms", + slug:"cms-maljarka-https-mode-bug-fix"}}`. Полный cross-boundary путь + (reconciler→runner→CLI→реальный shared-board read) работает; claim-token НЕ записан, spawn НЕ + вызван. Capability-фильтр (`needs-internet`) отработал — кандидат non-`.admin`. Процесс заглушён. + +## Notes +- HARD: `.admin` исключён из автономного клейма до governance L2/L3 (см. STATUS-блок § blocker). +- anti-self-review: distinct machine-id на каждый worker. +- Секреты per-machine: 600 root, не в git. diff --git a/.tasks/policy.toml b/.tasks/policy.toml new file mode 100644 index 0000000..a46a8e1 --- /dev/null +++ b/.tasks/policy.toml @@ -0,0 +1,21 @@ +# Project claim-policy for `.admin` (projects-meta agent-orchestration #7). +# +# Read by `tasks_claim_next` once per project per call; overlaid onto each +# candidate via `effectiveClaimFields` BEFORE the claim gate. Override rule is +# TOTAL, not intersect — a task that sets a field outright ignores the default +# for that field. Affects ONLY the autonomous poller; interactive sessions and +# manual claims do not pass through this gate. +# +# WHY needs-human: `.admin` is ops/infra (SSH, DB, panel, prod cutover, secret +# handling). Until execution-policy governance L2/L3 lands (see +# `agents-task-runner-vds-deploy` task § blocker), NO `.admin` task may be +# claimed + spawned autonomously. `default_weight = "needs-human"` makes every +# `.admin` task fail the L3 claim gate (claim.ts `selectClaimableTask`) → it is +# never handed to an autonomous runtime and always surfaces to a human. +# +# A specific `.admin` task that IS safe for autonomy can opt back in by setting +# its own `weight:` to something other than `needs-human` (total override). +# +# RELAX THIS when governance L2/L3 ships: drop default_weight (or set per-task). + +default_weight = "needs-human"