리랜딩: 피드백 자동 트리아지 스킬 (Plan B) — 거버넌스 정합 게이트 - #8
Merged
Conversation
This reverts commit d7ceb6a.
구현과 SKILL.md는 처음부터 needs-human을 쓰는데(board-register.sh --state needs-human) 스펙 본문 5곳만 구 어휘로 남아 있었다. v8 who-unparks 판별식 기준으로도 정정이 맞다: 트리아지 티켓은 인간 본인의 제품/우선순위 결정을 기다린다 — 스펙의 괄호 정의 자체가 이미 needs-human의 v8 정의였다. Revision Notes에 드리프트 기록 추가.
SSFSKIM
added a commit
that referenced
this pull request
Jul 10, 2026
Two-tier trust (review #1, human design call): developer feedback — the server-resolved role snapshot in TRIAGE_TRUSTED_ROLES (default admin), or a stripped .env #TRIAGE_DEV_CODE body prefix — is read as instruction (R1/R4 waived: dev ideas can be born ready-for-agent, labeled source:dev-feedback); user feedback keeps the conservative gate, residual risk explicitly accepted in the Decision Log. The dev code is stripped before the body reaches the prompt or ticket so it never leaks into a public issue. The rest of the review, all fixed: - #2 R2 requires a REAL file citation (path-shaped after :line strip; unknown:12 no longer counts) - #3 R3 scans risk SYMBOLS (assertStudentAccess, supabaseAdmin, RLS, generate-plan layout fns, past_exam_problems, SUPABASE_SERVICE_ROLE_KEY) in addition to paths - #4 claim issues a lease token; writeback is lease-conditional (late writeback after reclaim throws instead of clobbering); reclaim window validated at config load; second idempotency check right before registerTicket - #5 findExisting fails closed on gh search errors - #6 ticket body temp files: mkdtemp dir, mode 0600, removed in finally - #7 TRIAGE_ENABLED checked before config parsing - #8 spec drift fixed (feedback-dispatch.ts references, two-kill-switches) p86 DDL note gains triage_lease UUID. New src/trust.ts. 91 tests green, tsc clean.
SSFSKIM
added a commit
that referenced
this pull request
Jul 12, 2026
… soul, seeding contract Runnable form of the steals doc §2 (state/compute separation): - infra/worker-host/cloud-init.yaml — disposable body for a CX43/Ubuntu 24.04 host: blank-only volume format + /data mount before user creation, worker user (fixed uid, home ON the volume, no sudo), Node LTS, gh, codex, claude (native installer as worker), tailscale, swap. No Docker by design (host- process registry model, codex Landlock on a real kernel, cloud-init IS the reproducibility). - infra/worker-host/env.example — seeding contract: two-token scope split (board token in env, push token only in clone remotes), setup-token / auth.json paths, SSL_CERT_FILE pin. - infra/worker-host/README.md — layer split, hcloud creation, seeding checklist, Linux verification gate (dogfood cell), body-rebuild drill. - _codex_launch + review-engine.sh: SSL_CERT_FILE probe now also covers /etc/ssl/certs/ca-certificates.crt — TECH-DEBT #8 RESOLVED. Suites: codex-scripts, review-engine, shell lint — green; cloud-init YAML syntax-checked.
SSFSKIM
added a commit
that referenced
this pull request
Jul 12, 2026
…iveness (managed-agents steals) (#10) * feat(orchestrating-daemons): host-stamped registry + host-aware pid liveness — managed-agents steals Adopted from Anthropic's 'Scaling Managed Agents: Decoupling the brain from the hands' (transfer analysis in docs/doperpowers/2026-07-12-managed-agents-steals.md): - Every registration/resume stamps `host` (DAEMON_HOST, default hostname) into daemon metas; _pid_alive() in _lib.sh treats a foreign-host pid as dead regardless of kill -0 (a registry migrated on a state volume carries pid numbers, not processes). Empty host = legacy meta = local. - All four pid consumers routed through host-aware checks: codex-resume one-turn guard, daemon-retire kill, review/land-dispatch _is_live dedupe, review-dispatch _wt_occupied worktree-removal guard. - Steals doc also records the state-volume convention (steal 2) and the token-wired-remote scope-split recipe (steal 3, narrows TECH-DEBT accepted note on GH_TOKEN in worker env — pointer added). - Tests: foreign-host pid → resume proceeds + re-stamps, retire leaves the unrelated process alone, dispatchers retire+respawn; same-host controls unchanged. All 5 suites + shell lint green. * feat(infra): worker-host provisioning — cloud-init body, state-volume soul, seeding contract Runnable form of the steals doc §2 (state/compute separation): - infra/worker-host/cloud-init.yaml — disposable body for a CX43/Ubuntu 24.04 host: blank-only volume format + /data mount before user creation, worker user (fixed uid, home ON the volume, no sudo), Node LTS, gh, codex, claude (native installer as worker), tailscale, swap. No Docker by design (host- process registry model, codex Landlock on a real kernel, cloud-init IS the reproducibility). - infra/worker-host/env.example — seeding contract: two-token scope split (board token in env, push token only in clone remotes), setup-token / auth.json paths, SSL_CERT_FILE pin. - infra/worker-host/README.md — layer split, hcloud creation, seeding checklist, Linux verification gate (dogfood cell), body-rebuild drill. - _codex_launch + review-engine.sh: SSL_CERT_FILE probe now also covers /etc/ssl/certs/ca-certificates.crt — TECH-DEBT #8 RESOLVED. Suites: codex-scripts, review-engine, shell lint — green; cloud-init YAML syntax-checked. * feat(infra): triage tenant layer — separate uid, systemd timer, seeding contract First production tenant of the worker host: the triaging-feedback poller moves off the Mac's launchd onto the VM as its burn-in workload. - cloud-init: triage user (uid 1011, /data/triage — separate from worker because its env holds SUPABASE_SERVICE_ROLE_KEY while worker executes PR-derived code); doper-triage systemd oneshot+timer replacing the launchd label (same single-instance serialization the reclaim design needs); ExecCondition on the seeded .env makes pre-seed ticks silent no-ops and rebuilds zero-touch. - env.triage.example: skill-dir .env contract — VM deltas vs Mac (explicit GH_TOKEN issues-scope since no keychain; contents-READ-only PAT in the ida-solution remote; triage never pushes). - README: §5 tenant seeding + one-tick verification + Mac handoff; rebuild drill and stale feedback-intake bullet updated. * fix(infra): worker-host review findings — per-body hostname, runner env/label, honest PAT boundary Five findings from PR #10 review, all confirmed against the code: - Static hostname doper-worker-1 broke host-aware liveness on the rebuild path (_lib.sh stamps $(hostname); same name = old metas read local, a recycled pid could alias an unrelated process). runcmd now sets doper-worker-$(machine-id prefix) — unique per body since machine-id is minted at first boot — with preserve_hostname guarding per-boot reverts. - Runner registration label doper-worker never matched the shipped workflow's runs-on [self-hosted, claude-review]; jobs would queue forever. - Runner jobs read ~/runner/.env + .path, not .bashrc (non-login; Ubuntu .bashrc early-returns non-interactive). §2.6 now seeds both; the cloud-init comment claiming bash -lc coverage is corrected. - Rebuild drill said 'restart the runner service' but the svc.sh systemd unit lived on the discarded root fs — drill now reinstalls it. - README claimed the push PAT never enters worker reach; any worker-uid process can read it via git remote get-url. Text now states the honest boundary (workers ARE contents-write principals) and requires branch protection before first run. * fix(infra): /data mount hard gate + codex-auth seeding path Second review wave, both findings confirmed: - nofail (kept: a missing volume must degrade to a reachable system, not systemd emergency mode) let provisioning 'succeed' with /data on the disposable root fs — the users module creates the homedirs there before runcmd. runcmd now opens with a mountpoint assertion that aborts loudly; final_message and README §1 direct to 'cloud-init status --long' before seeding instead of claiming readiness. - README §2.2's scp to worker@host always failed: worker has a locked password, no authorized keys, and no ~/.codex. Documented the real path — through the login account, install(1) with owner/mode set from birth, no temp-file exposure. * fix(infra): tenant home hardening, git identity seeding, fail-fast provisioning Third review wave, all three confirmed: - The uid boundary relied on the image's login.defs default home mode; anything group/other-traversable lets triage read worker's clones (push PAT in each .git/config). runcmd now chmods both homes 0700 (idempotent against an existing soul), and the runner .env recipe adds chmod 600 — it carries the same tokens as ~/.env but was born under default umask. - A fresh soul has no git identity and git refuses to auto-detect email from the machine-id hostname, so a worker's first commit dies with 'Author identity unknown'. Seeding §2.4 now sets user.name/user.email once per soul (~/.gitconfig rides the volume). - runcmd merged into one sh script with no set -e meant a failed NodeSource/Tailscale/claude installer still yielded 'cloud-init status: done'; curl|bash additionally masked download failures. First item is now set -e (governs the whole merged script), curl|bash split into download-then-execute (sh is dash — no pipefail; the claude installer keeps the pipe but under an inner bash with pipefail), and provisioning ends with an explicit binary/Node-major/claude-on-worker-PATH gate. * fix(orchestrating-daemons): bind liveness to host boot * fix(orchestrating-daemons,infra): strip RUNNER_TRACKING_ID at detach; triage verify from admin shell Fourth review wave, both findings confirmed: - Detached workers spawned from an Actions dispatch job inherited RUNNER_TRACKING_ID, and the runner's post-job cleanup kills any surviving process whose environ carries that marker — nohup/--bg detach the session, not the env, so the primary automated dispatch path reaped its own workers at job exit (stale 'working' meta left behind). All three detach points (daemon-spawn, daemon-resume fork, _codex_launch wrapper) now spawn under env -u RUNNER_TRACKING_ID — a no-op outside Actions. README §2.6 names this as the mechanism instead of implying nohup suffices. - README §5.4 had the first-tick verification run 'sudo systemctl' inside the sudo -iu triage shell — triage has no sudo, a locked password, and no journal access. Verification now runs from the admin shell; §5 intro marks step 4 as the exception. Suites: test-daemon-scripts, test-codex-scripts, test-review-dispatch all pass; shell lint clean. * fix(infra): codex-auth seeding — GNU install refuses pipe-backed /dev/stdin Fifth review wave, confirmed empirically (GNU coreutils install exits 1 with 'skipping file /dev/stdin, as it was replaced while being copied' and creates nothing): the §2.2 recipe could never seed auth.json on the Ubuntu target. Replaced with umask 077 + cat (file born 0600, still no exposure window) followed by chown to worker. * fix(orchestrating-daemons): register resumed turn early * fix(orchestrating-daemons): gate superseded-turn stop/purge on recorded host identity A migrated meta's short is host-local and reusable — stop/rm through it can hit an unrelated local agent. Capture the identity verdict before the fork re-stamps the meta; foreign metas skip both (leftover old-host session files are cosmetic, a purge through a reused short is destructive). * fix(orchestrating-daemons): parse the LEADING sec field of kern.boottime The greedy .*sec-= match landed inside 'usec = ' and recorded microseconds as the boot identity — a value that can repeat across reboots, defeating the host-boot liveness gate on macOS. Anchor on the leading '{ sec = N,'. Regression cross-checks _boot_id against an independent parse. env.triage.example: header marks the file fork-local (names the fork's real consumer repo on purpose; never upstream) — review finding triaged as void for a personal fork, kernel kept as a permanent guard note.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
무엇
피드백 자동 트리아지 스킬(
skills/triaging-feedback, Plan B)의 리랜딩 PR. 내용은 PR #7에서 리뷰·머지됐던 최종 상태와 비트 단위 동일(스킬 서브트리4834856·스펙 blob4c5fb00해시 일치 확인).왜 다시 PR인가 — 이력
81a8c19) — 태스크별 리뷰 + Opus 전체-브랜치 리뷰 + 머지 전 외부 3자 리뷰(Codex/gpt-5.5, Critical 2 포함 F1–F7 수정) 통과.79e063a·058a475등)과의 정합(reconcile) 확인을 위해 사람 요청으로 리버트(185ad75).aad1bf3)를 main에 직접 랜딩 — 실수로 확인됨 → 재리버트(d7ceb6a).d7ceb6a의 리버트(리랜딩) — 거버넌스 정합 확인 후 사람 리뷰·머지 게이트를 거치기 위함.머지 전 확인할 것
79e063a리뷰어 Standards +058a475fork park/exit 조항)과 이 스킬의 디스패치·티켓·게이트 정책이 상충하지 않는지리뷰 근거·검증 기록은 PR #7 본문과 코멘트(외부 리뷰 findings 표) 참조.