task(agents-task-runner-vds-deploy): take + DRY_RUN validated + .admin claim-guard

- 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) <noreply@anthropic.com>
This commit is contained in:
2026-06-08 15:32:35 +03:00
parent 47057484a9
commit 949724729d
3 changed files with 79 additions and 3 deletions

View File

@@ -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 **Status:** active
**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. **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. **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 **Branch:** n/a
<!-- created-by: OpeItcLoc03@DESKTOP-NSEF0UK / from: OpeItcLoc03/workshop / 2026-06-08T10:10:16.420Z --> <!-- created-by: OpeItcLoc03@DESKTOP-NSEF0UK / from: OpeItcLoc03/workshop / 2026-06-08T10:10:16.420Z -->

View File

@@ -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.

21
.tasks/policy.toml Normal file
View File

@@ -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"