Repository navigation
PTYCAP-05: throwaway-repo due->PR proof (code + owner runbook) [QC BLOCKED] - #511
Draft
finedesignz wants to merge 136 commits into
Draft
finedesignz wants to merge 136 commits into
finedesignz wants to merge 136 commits into
Conversation
Goal-backward verification of Phase 1 (PTY token accounting, #395) and Phase 2 (PTY pre-flight gate, #493) against ROADMAP success criteria, with every proving test run per-file. - Phase 1: 3/3 SC implemented; gaps_found (G-1 MAJOR: emitter dedupes on record uuid, not message.id, so the PTY ledger over-counts; G-2 MINOR: live-Postgres proofs not observed locally). - Phase 2: passed 3/3; three MINOR gaps (CRLF-fragile guard test, stale docs mechanism claim, Telegram permission keystrokes un-preflighted). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Read-only recon of the gate chain, actor inference, PTY write paths, counters, owner notification, token-cap defaults and kill-switch precedents, with file:line evidence. Input to discuss/plan for the governed-automation guard and the lifetime counter + kill switch. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ONTEXT Unattended discuss for Phase 3 (governed-automation guard): the eight design forks were answered by a claude+codex+agy design-fork panel (record in GATES/design-fork-1.md, VERDICT PASS with amendments). CONTEXT captures the binding decisions D-01..D-17: governance primitives only (no PTY byte-producer), fail-closed lifetime/kill-switch slots, enabled-ceiling rule, call-time flag default OFF, hard rename with eligible-actor rule, automation-only governed chain (human chain untouched), door pins. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Planner (opus) output verified by gsd-plan-checker: 0 blockers, 2 warnings (fails_when pass-count floors; plan 03-04 doc-heavy scope), accepted for execution. Waves: 03-01 tracer (governed-pty module + rename + OFF==legacy differential), 03-02 preflight automation branch + CRLF fix, 03-03 door pins + spoof tests + Telegram required source, 03-04 docs/OpenAPI/baseline gate. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…with OFF==legacy differential - add hub/src/dispatch/governed-pty.ts: flag reader, eligible-actor rule, four governors (kill_switch/lifetime_counter fail closed), test-only DI, governedAutomationPtyGate - export isDailyTokenCapEnforced from gates.ts - telegram dispatch composes governedAutomationPtyGate - add differential test against a frozen legacy oracle and flag-ON telegram cases Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…tionPtyGate - ask and work compose governedAutomationPtyGate with unchanged server-inferred resolvers - pin that an external-ask actor stays blocked with the flag ON and every governor passing Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…rnor semantics - remove humanOnlyPtyGate from gates.ts (hard rename, no alias); keep AUTOMATION_ACTORS and humanOnlyRejectsActor - human-only-guard test targets governedAutomationPtyGate with the flag pinned OFF - pin governor order, enabled rule, fail-closed slots, throw, non-PTY, DI-only and no-alias Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…preflight - automation actor refused before any DB gate unless the governed-automation flag is ON - flag ON: spend chain then governors, prefixed reasons; throw/hang stay fail closed - human chain and scanned gates literal untouched Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
… humanInteractive guard CRLF-safe - no governor in either chain constant; human turn passes with fail-closed governors and flag ON - split source on optional CR plus LF (Phase-2 MINOR-1) Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…ed when missing The webhook and the doctor replay assert source 'human' at the authenticated boundary; a call without a source is refused on a pty-interactive session instead of defaulting to human (D-09 iv). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…s and preflights as human - term.input with source/actor extras -> preflight actor human, forwarded keys exactly type/session_id/bytes - term.attach_file stays preflight-exempt (D-10) and forwards no source/actor keys Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…outing, privileged callers, flag/DI, exemptions - emitter allowlist (ws/client.ts, telegram/transcript/pty-inject.ts) with non-vacuous self-check - supervisor canary: user_message/permission_response never touch the PTY, term.input does - caller pins for automation/human actor, preflight, injectPtyKeystroke, dispatchToSession - flag/DI literals confined to dispatch/governed-pty.ts; actor-inference and Telegram source pins - EXEMPTIONS record: injectPtyKeystroke and term.attach_file Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…-2 mechanism claims, Phase-4 hand-off - usage-cost.md: PTYCAP Phase 3 section; structural reason automation cannot reach the PTY - CLAUDE.md: REMO_GOVERNED_AUTOMATION_PTY env bullet, docs-map row, invariant, token-cap fail-closed fix - ROADMAP: Phase 4 hand-off note (no SC change) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ate rename across docs and SESSION-ASK spec Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…onPtyGate; finish rename in hub/src comments Comment-only source changes; docs:sync regenerated. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…59 fail 0) with phase-3 accounting Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…nity) ceiling config maxInjectsPerHour() coerces non-finite env to the default 4, so the governor passed an invalid value. Add isInjectRateConfigured() (raw validity, governor only; legacy gate behavior unchanged) and align docs. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…am/doctor.ts) doctor.ts takes dispatchToSession as an injected dispatch param, so the bare call-site needle missed it. Pin importers instead (webhook + doctor), and assert the doctor replay call passes source: 'human'. Docs name doctor.ts. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… pass) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Eight executable plans (G-1 emitter fix first, tracer-led controls core, counting expansion, PTY door + governors, owner surfaces + 60% alarm, kill-switch coverage, spawn-site guards, e2e + docs + 20M cap last), VALIDATION map with source coverage audit, and 04-FORKS.md recording planner forks for panel confirm or overturn. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Apply the locked fork-panel verdicts and the plan-check fixes: heal route classified machine (F-2), separate final halt check before send (F-3), release resumes every scope and once-task re-arm (F-4), 80 percent lifetime warning page (F-5a), triage key per application (F-5b), one atomic lifetime + de-duplicated rate-union reservation with routine_run_log.inject_token (F-6), zero new skipped tests with the DB proof moved into 04-02 via an existing e2e test body (F-8). 04-02 split into 4 tasks, 04-03 gains a run-log token task, 04-07 gains a heal task, 04-08 reduced to docs + cap-last-code-commit. Includes 04-FORKS-PANEL.md and 04-PLAN-CHECK.md. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ima and positive deltas - G-1/D-15: records of one assistant message share message.id and carry cumulative usage; count once - key = message.id, fallback uuid; negatives clamp to 0; maxima never decrease; replay emits nothing - FIFO bound SEEN_UUID_CAP kept; six new fixtures in pty-usage-tail.test.ts Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- disarm transaction runs first; session kill switch best-effort after, never throws - enable only on an armed run (proof_not_armed otherwise) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…arm with static guard - refuses before importing the DAL without DATABASE_URL - read-only installation/session lookups live in a DAL file (script holds no SQL) - static scan: no env assignment, no Coolify, no network, no SQL text, no cap setter Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…stack - 7 OFF combinations: zero sql, zero fetch, no proof guard/verifier/github, identical inject args - gates pass through with zero dep calls; merge routing unchanged Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… e2e body - proof-checks.ts: 8 sections (DDL x2, 5-way arm single-flight, partial unique indexes, CHECKs, exactly-once claim/terminalize, attribution survives session delete, budget gate on real ledger, exact-row disarm); own synthetic users, cleanup by id - called from the first autospawn e2e test body: zero new test() calls, zero skips Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…o new skips Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ay-repo proof - ordered rollback (kill switch or disarm first, then flags, then redeploy) - GitHub App permission grant, ruleset and non-admin credential prerequisites - correct autospawn runbook pr_url statement; point at the proof runbook Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… permissions - CLAUDE.md env entry, docs map row, gate-list invariant - auto-dev-orchestrator and usage-cost proof sections - HANDOFF: extra read permissions the proof needs Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…r Phase 5 - 10 tests: OWNER GO, rollback order, permissions, empty bypass list, refusal codes, no merge instruction - ROADMAP: plans ticked, progress row 'live proof pending owner GO', Phase 5 stays unchecked Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…MAJOR 1) Arm, the dry run and --enable refuse (other_orchestrator_task_enabled) while ANY other orchestrator task is enabled, across all users, because the REMO_ORCHESTRATOR_* flags are hub-global. At runtime, with the flag stack ON, the proof guard blocks and the budget gate refuses every orchestrator dispatch that is not the claimed proof task (proof_mode_non_proof_task); the old pass_through for a task without a proof row is gone. Runbook prerequisite and refusal-table row added. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… (codex #2, codex #3 recheck) Proof dispatch requests now carry a server-only proofRunId (DispatchRequest, set by runMacroCycle through injectOrchestratorPrompt on both the online and autospawn paths). The budget gate and a new final pre-send check (finalHaltCheck, reached only by proof gate lists and only with the flag stack ON) require it to equal the ACTIVE run, so an ordinary dev prompt queued or parked before the arm - which carries the reusable task:<id> counter key - can never be authorized as proof traffic or reach send, and a run that goes terminal after the gates still stops the send. Arm now also halts the session (session kill switch) and cancels pending routine cycles in the same transaction; --enable releases the halt. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… terminal transition (codex #3) disarmProofRunTx now inserts the session kill-switch row first, in the same transaction and before the run UPDATE to disarmed, so a rollback undoes both and there is never a committed state where the run is terminal but the session can still be dispatched to. The separate best-effort post-transaction engage (and its dep) is removed; the script reports the in-transaction engage. The pre-send proof-run identity recheck landed with the previous commit. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…der any flag combination (adversary MINOR 2) The arm transaction marks the task scheduled_tasks.proof_owned (additive idempotent column, set on both created and reused tasks). The marker rides the task row the cycle already loads (getOrchestratorTaskForSession -> resolveCycleContext -> MacroCycleInput.proofOwned), so runMacroCycle refuses (proofDecision blocked) before any reconcile or db work whenever the full flag stack is not ON; with the stack ON the proof guard still decides. Non-proof tasks are untouched, so flag-OFF stays a true no-op. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…the proof as budget_attribution_lost (codex #4) The agent ws handler logged and dropped a failed token_usage insert, so the proof's hard token budget silently under-counted while the session row still existed. The handler now marks the session in an in-process registry; sumSessionTokensSince reports attributionLost for any proof window the loss falls in, and the budget gate and tick evaluator both fail closed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…R to come from the armed repo (codex #5) The adapter dropped every off-prefix PR before the verifier could judge scope, and a fork PR reusing the exact proof/<run-id> branch name could be reported pr_open_green. listPulls now returns all recent PRs with head repository, author and creation time; the verifier terminates a PR created after arming from any non-proof/ head, and a run-branch PR whose head repo is not the armed repo (or is deleted), as pr_scope_violation. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… allowlist, proof row, session match and merge refusal (codex #6) owner/repo path names are case-insensitive, so github://Owner/Repo and github://owner/repo were two idents for one repository and bypassed single-flight and the merge refusal. armProof and armProofRunTx canonicalize through lib/repo-key.ts, findActiveProofRunForRepo canonicalizes the lookup, and schema.sql adds an additive NOT VALID CHECK (repo_ident = lower(repo_ident)) so the existing partial unique indexes are single-flight over the canonical value. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…o repo key (lens-correctness MINOR 2) With the proof flag stack on, runMergeToMain skipped the proof-repo refusal entirely when ctx.repoKey was null, leaving the only auto-merge path unguarded for a keyless session. It now refuses with proof_repo_never_merges:unverifiable. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…unds the budgets (adversary MINOR 3, 6) An admin agent identity can edit the ruleset and merge in one turn, yet arm only warned when --agent-login was missing or unreadable; it now refuses agent_permission_unverified. The owner-supplied "hard" budget had no upper bound; arm refuses above injects 50 / tokens 50M / wall 24h and schema.sql adds matching additive NOT VALID CHECK ceilings. Runbook updated (agent-login required, ceilings, canonical repo ident, attribution-loss and PR-scope behavior). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…m and enable (codex r2 new #1) The exclusivity count ran under a per-user lock, so two users could both see zero enabled orchestrator tasks and both enable. All proof state changes now share one global lock and recheck the count under it. The fake sql models real blocking advisory-lock semantics so the race is exercised. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…-send boundary under the arm/disarm lock (codex r2 #2, #3) buildSend persisted the prompt (awaited) after the pipeline's final halt check, so an arm or disarm that committed in that window was followed by a stale send. With proof mode ON the delivery now runs after persistence behind sendAtProofBoundary: a fresh kill-switch + active-run identity recheck while holding the same global advisory lock arm/disarm/enable take. Flag OFF is unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…emoves allowlist case twins (codex r2 new #2, sonnet MINOR 1, MINOR 3) Arm now refuses (session_halt_engaged) when a foreign session halt is engaged, releases only stale halts left by the proof tooling, records the id of the row it engaged on the run (additive kill_switch_id column) and --enable releases exactly that row, so an owner emergency stop engaged after arm survives. Disarm deletes the allowlist row by lower(repo_ident), so a mixed-case twin no longer survives. Runbook gets the new refusal. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…nspected, fails closed otherwise (codex r2 #5) The adapter read only the newest 50 PRs, so a post-arm scope violation on a later page was invisible. It now pages newest-first until a page is short or its last PR predates armed_at (the verifier passes it); hitting the page cap or any page error throws and the verifier stays pending (never green). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… durable across restart (codex r2 #4) sumSessionTokensSince now also compares completed assistant turns of the session since arming (older than a 120s grace) with token_usage rows over the same window; fewer rows than turns reports attributionLost, which the budget gate and tick evaluator already terminalize as budget_attribution_lost. The in-process mark stays as an additional early signal. No new DDL; nothing is evicted or forgotten on restart. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…-owner, SHIP-AFTER-OWNER-GO) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Contributor
AgentAutofix AI ReviewclaudePASSED
codexBLOCKED
agyadvisory -- not part of the gate decision PASSED No findings. Result: Blocking finding from: codex Reviewer models (requested pin, not independently confirmed):
|
…agged session halts Budget attribution: chose the nullable additive turn_id column on messages and token_usage (supervisor stamps one id on a turn's assistant_message and result/usage_event) over a usage outbox: smaller, no new table, no backfill. The durable detector now anti-joins each completed assistant message to a token_usage row of the SAME (session, turn_id); aggregate counts are gone and a message without a turn_id fails closed. Kill switch: session halts are unique per (session_id, engaged_by) while engaged, so a manual emergency engage after arm is a separate row, effective on its own, and proof --enable releases only its own row by id. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…tive MAJOR recorded) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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.
PTYCAP Phase 5 - Throwaway-Repo Due->PR Proof (code + owner runbook)
Status: DRAFT - /qc BLOCKED (2 open MAJOR after 2 fix rounds). Live proof is an OWNER GO/NO-GO gate and was NOT run.
What it builds (all flag-gated, default OFF = true no-op)
orchestrator_proof_runstable + DAL (additive idempotent DDL; frozen budgets with CHECKs; single-flight partial unique indexes; canonical lowercase repo identity).pr_open_green, else a typed "did nothing and why" terminal.GET /api/orchestrator/proof(OpenAPI + docs synced).docs/ptycap-05-proof-runbook.md(throwaway repo + ruleset, GitHub App permissions incl. the bypass_actors visibility decision, arming, rollback order: kill switch/disarm FIRST, then flags).QC
Seats: sonnet correctness + adversary lenses, Codex read-only (agy MISSING). Record:
.planning/phases/PTYCAP-05-throwaway-repo-due-to-pr-proof/QC/.Open MAJOR (see QC/VERDICT.md): (1) attribution check compares aggregate counts, not per-turn; (2) a manual session halt engaged AFTER arm is indistinguishable from the proof-owned row. Both reachable only after an owner arms the proof.
Verification
bun run check-baseline: OK (pass 3169, skip 259, fail 0). One known flaky timeout (transcript-adapter-codex, AgentAutofix 74489ffe) on a first run.Not done here (owner-gated)
SC-2/SC-3 live proof: arming
REMO_ORCHESTRATOR_AUTOSPAWN+ proof flag + allowlist in prod. Runbook steps indocs/ptycap-05-proof-runbook.md.🤖 Generated with Claude Code