Commit Graph
100 Commits
Author SHA1 Message Date
host 0f0fcd3242 gapfill G2 (goal): cover all 15 missing goal_live_update edge branches (write validation, bad applied_version fallback, non-dict signals, consume failure paths, apply CAS null-version branch and CAS miss); directed coverage 81% -> 100%, production code untouched 2026-11-04 21:03:54 +00:00
host 85ce1def7d gapfill G5: wire optional ?current_main_head drift check into GET /audit-scorecard (caller-supplied only, no git/subprocess; absent param means no staleness verdict, verdict never rewrites overall); endpoint tests for passed/absent/empty 2026-11-04 21:03:54 +00:00
host 7962135395 gapfill G4: cover caps.py:54-55 env-get-exception fallback and quota.py:73-74 illegal-env fallback (A9 subset gaps); line numbers verified unchanged after rebase 2026-11-04 21:03:54 +00:00
host 65e8ed3d64 gapfill G3: unify all 5 private row_get onto peer_messages.row_get (approvals, automations, marker_tools, todos, wait_ops; resident import retargeted); semantics identical on None/dict/sqlite3.Row, identity tests added 2026-11-04 21:03:54 +00:00
host b46bf8d7e0 gapfill G1: remove 5 ruff F401 unused imports (3 unused os in production files, 2 in tests); no assert lines changed, ruff all cloud now 0 2026-11-04 21:03:54 +00:00
host 5f9e3c69d9 code-to10 reconcile: fix pre-existing worker F821 in playwright skipped-modified log branch
Target-line bug, not introduced by the replay: Worker._tenant_dirs
only receives project_id, yet the script_skipped_modified log line
used task.get("project_id"), raising NameError whenever seeding
reported a tenant-modified script (the refreshed sibling branch was
already fixed to project_id with its own regression test; this test
only covered the refreshed branch, so the full suite stayed green).
Fix mirrors the sibling (project_id) plus a regression test for the
skipped branch. Ruff F821 in worker.py is thereby cleared.
2026-11-04 21:03:54 +00:00
host da7a76d0e4 code-to10 reconcile: re-pin handler accounting and longfunc inventory for the unified line
Target keeps the 6-mixin split, so the source line's 239/223/16 and
its mixin-homed 17-method list do not apply here. Recomputed by AST
on this line: handler accounting 244 total / 150 in server.py /
94 moved, no duplicates (243/149 + _update_goal_task); longfunc
still 17 methods with the same names, 16 homed in server.py and
_full_auto_execute in handler_fullauto.py, plus module-level
migrate_tasks_table in server.py (114 lines). No method split or
dropped; both tests' docstrings state the re-pin explicitly.
2026-11-04 21:03:54 +00:00
host 79835cf3c1 code-to10 v5: fix November date failure in arch-converge quota gate fixture (fixture day follows current UTC month; assertions and gate semantics unchanged; frozen-semantics header updated explicitly)
(cherry picked from commit 073950043ed65039e19be8a4b6d725a44a662879)

Reconcile-note: this datefix was missing from the solidify line (aa30d40's test_arch_converge.py had no _current_month_day and still failed in November, while 10023fb/6841f28 contained it); added here as the separately-labeled fix for that replay omission, per the reconcile brief.
2026-11-04 21:03:54 +00:00
host b3f3f8bcab code-to10 goal live update: POST /tasks/{id}/goal updates a running goal loop at the next round boundary
Server writes goal + monotonic goal_version + task_goal_history in one
transaction (CAS on version, approve_merge only, new-semantic goal tasks
only, terminal/merged 409, same-goal noop). Worker mirror thread (30s)
and breakpoint-resume claim hook write the update as a signal file next
to host-state.json; host run_goal_loop applies it at round boundaries
(top of round and before the declaration check, so a declaration made
for the old goal in a turn during which the goal changed is voided),
with an explicit old->new notice, same thread/worktree, rounds/usage/
budget/failed counters untouched. handler method accounting is a
contract update: 239 total / 223 mixins / 16 in server.py.

(cherry picked from commit 6841f287219d2b36cfbb8803642344b84dae4377)

Reconcile-port: handler_lifecycle.py contents redirected — _update_goal_task method + _goal_update_reject/_goal_signal_status pure functions + goal_live_update import into cloud/server.py (target keeps 6-mixin split); _task_to_dict goal fields into cloud/handler_support.py; migrate columns into cloud/server.py migrate_tasks_table; test patch target handler_lifecycle→server; test_handler_split_conformance.py kept at target version, to be re-pinned for the unified line in a final commit.
2026-11-04 21:03:54 +00:00
host 51b26633b8 code-to10 v7 mech merge fix: silence mypy misc redefinition on Protocol fallback in gate_verification.py (item6-introduced), no runtime semantics changed
(cherry picked from commit 9f8b95fa03643db7bef028b9877cc1c1bc78ef4e)
2026-11-04 21:03:33 +00:00
host a4c92d888c code-to10 v7 mech merge fix: SqliteScorecardGainLedger uses cloud.db.connect instead of sqlite3.connect (arch conformance layer rule), no semantics changed
(cherry picked from commit bde36a84880574c2297aaee9ed08312cd0e2c0fc)
2026-11-04 21:03:33 +00:00
host 83485b9316 code-to10 v7 mech merge fix: wrap two merged docstring lines over 120 chars (E501) in audit_scorecard.py, no code semantics changed
(cherry picked from commit a4fdc78930f597e7793a054c1775842fe5496143)
2026-11-04 21:03:33 +00:00
host 81e1448c6d v7 mech-7: scorecard user_side_items + three-table rule (code unchanged, production forced not_pass on user-side pending/unknown/invalid)
(cherry picked from commit 59b4c49a896972501aeeb8472a9fc2918ec226fa)
2026-11-04 21:03:33 +00:00
host c6a3a22606 v7 mech-2: split scorecard into code/production/product tables
(cherry picked from commit 67b7f5e42d001b655aef3e04e1d3c1d98166b98f)

Reconcile-port: handler_admin.py hunks redirected into cloud/server.py _audit_scorecard (target keeps 6-mixin split; scorecard module itself applied cleanly).
2026-11-04 21:03:33 +00:00
host 80fbf76e2d code-to10 v7 mech-4: scorecard evidence ledger head + row ids, injectable signature verifier (fail-closed)
(cherry picked from commit bcd385c6979db77abea458af66e21ef891453064)
2026-11-04 21:03:33 +00:00
host a49b9556f8 v7 mech-5: scorecard baseline_head machine field, stale check, frozen store (append-only)
(cherry picked from commit e3e1f517e916eaac597b82d04bac5307a3f8b126)
2026-11-04 21:03:33 +00:00
host 76f67ce310 code-to10 v7 mech1: scorecard rubric versioning, append-only rubric + snapshot tables
(cherry picked from commit 368475243367685bf9db9335ec929958de031ca6)
2026-11-04 21:03:33 +00:00
host c1d2a57486 v7 mech-6: production-evidence fail-closed live wiring seam (no real reader, no endpoint wiring yet)
- LiveEvidenceReader protocol: get_checks(repo, ref) /
  get_branch_protection(repo, branch), results carry status
  plus raw evidence; production code has no HTTP call, no
  token read, no real GitHub API call (AST-asserted).
- verify_live_evidence: no reader / no repo-ref / reader
  failure / mismatch all verified=False; comparison shared
  with verify_gate_evidence via _compare_claimed_vs_live.
- live_gate_decision: verified=False -> allowed=False,
  http_status=409, status=blocked; verified=True -> 200.
- Endpoints _merge_task/_release_task NOT wired yet (no
  production reader exists; wiring None would block all
  merges/releases); real live verification still pending
  B6 real App install and B1 user-side items.

(cherry picked from commit 7e8bfdee1f22c28329602314f3e166cde34eb6cf)
2026-11-04 21:03:33 +00:00
host a50bd702ec v7 mech-3: scorecard diff scope, gain ledger, stagnation stop table
- cloud/scorecard_diff.py: audit_scope (changed files + claimed_fixed,
  unchanged/baseline-out files out of package), ScorecardGainLedger
  (memory) + SqliteScorecardGainLedger (SQLite only, PG_DDL text-only),
  three tables code/production/product kept separately, average
  reference-only; check_stagnation: two consecutive code gains <0.5
  (test_default_unapproved) escalate, no auto pushback; rubric_version
  change starts a new sequence.
- cloud/tests/test_scorecard_mech_diff.py: 24 tests, all passing.
- No change to audit_loop_driver.py semantics, #238 auto_apply,
  #247 correction-pass semantics, or v1.1 contract.

(cherry picked from commit 57d44becaf559a074c995249e95bd36924dae13f)
2026-11-04 21:03:33 +00:00
host da8ac2261d v7 mech 8: MCDT acceptance/key-fact nodes as scorecard input model only
(cherry picked from commit 93e491b6a1b83fcdbbacf3493cdd2fd76418d0b6)
2026-11-04 21:03:33 +00:00
host b5a3f30f3f code-to10 v6: workers _default_audit docstring follows 2026-11-02 finalization (migration side, no revert)
(cherry picked from commit b7ac9d7d6af842a182964b0aa0524708e7cdc923)

Reconcile-note: resolution kept target's finalized wording verbatim, so this commit is empty by content (docstring-only commit; both sides agreed: migration side, no revert).
2026-11-04 21:03:33 +00:00
host e579e5131e code-to10 v6 A14 batch2: test E402/F401 cleanup plus touched-file residual E,F cleanup
(cherry picked from commit 1db02545f74c96b3b92be4fc32954659cec1f814)

Reconcile-conflict: A14b E402 imports referencing cloud.handler_core (does not exist here; core methods live in server.py) — kept HEAD imports with incoming's noqa: E402 markers, dropped the unused core_mod import (verified unused elsewhere in both files).
2026-11-04 21:03:33 +00:00
host 7598574f81 code-to10 v6 A14 batch1: workers F601 duplicates and check_transplant E741 renames
(cherry picked from commit 4411186681584bf55e065c654fe909a3320d4a22)

Reconcile-conflict: test_skill_transplant_prep artifact count — kept HEAD's finalized 0 refs (2026-11-02 user sign-off deleting §4's 6 references, already in target) with incoming's l→line rename; incoming's 6-ref assertion is pre-finalization and must not overwrite.
2026-11-04 21:03:33 +00:00
host 7529fb8b6f code-to10 v6 A13: 17-method long-function inventory incl _full_auto_execute plus support domain boundary comments
(cherry picked from commit 908df30d1a3cf328ea05344f0660af9b77bf24a1)

Reconcile-port: handler_support.py kept at HEAD (189 lines; A13 domain comments describe source's 1616-line handler_support layout, which does not exist here — functions live in server.py). test_longfunc_inventory.py kept as-is for now; it pins source architecture and will be re-pinned for the unified line in a final commit (recorded).
2026-11-04 21:03:33 +00:00
host c25854fff7 code-to10 v6 A12: scorecard example renamed to 2026-10-31 snapshot with timeliness fields
(cherry picked from commit 633cdbc94e7a7b0c5d3b0b135189faf3de6673f4)

Reconcile-port: handler_admin.py hunks redirected into cloud/server.py _audit_scorecard (target keeps 6-mixin split; scorecard module itself applied cleanly).
2026-11-04 21:03:33 +00:00
host bbc7103dec code-to10 v6 A11: whole-tree audit_log single-writer scan assertion
(cherry picked from commit 9308503f90090526bb91b5aa2ae0971f84781a1d)
2026-11-04 21:03:32 +00:00
host fd22f03c15 code-to10 v6 A10: release gate single evaluator via wiring adapter
(cherry picked from commit 77ed1c3094798f75bc41323f9aa60f744f5ba507)
2026-11-04 21:03:32 +00:00
host 3ef4411c32 code-to10 v6 A8 driver round 2: remaining subset gaps (first gate acceptance, fallbacks, signals, ledger branches, guards, confirm branches)
(cherry picked from commit e3cac9f3e62f01c49fca9b7cbf80431a4d55b8ad)
2026-11-04 21:03:32 +00:00
host 65f0b5bf97 code-to10 v6 A8 worker: cover process_auto_memories logger-failure inner except (2088-2089)
(cherry picked from commit 930f722641bb91f1f1e4d67f5937064eab8bee1e)
2026-11-04 21:03:32 +00:00
host c65ef372e6 code-to10 v6 A8 worker: worker gap tests (auto-memories, tenant skill failure, prepare-env failures, pr-job failures, run-loop drain)
(cherry picked from commit 903bd560bf2b5796daf4b86dacc29b0732513607)
2026-11-04 21:03:32 +00:00
host 718dd8ecf9 code-to10 v6 A8 driver: audit_loop_driver gap tests (rebuilds_used, normalize, result map, test-change validate, root-cause local)
(cherry picked from commit 5e874f1a924289230f5a3143696358f72f9216e1)
2026-11-04 21:03:32 +00:00
host 2555b50ead code-to10 v6 A9: caps/quota gap tests (caps 70-71, quota 79-80, 128-131, 140-143)
(cherry picked from commit 0c733b0805a45057de9b618943f9a5b2af5d7bc4)
2026-11-04 21:03:32 +00:00
host 776be69a25 code-to10 v6 A7: unify row_get on peer_messages
- peer_messages.row_get gains default=None (was None-only); the
  three old variants agree on all real row types (None / dict /
  sqlite3.Row): auto_memory's old default was already None, and
  lifecycle's old None special-case and dict .get give identical
  results on those types, so no call-site behavior changes and no
  call site passes a non-None default.
- auto_memory and lifecycle delete their private _row_get copies
  and import peer_messages.row_get as _row_get (precedent: server,
  worker, handler_project, handler_support already do this);
  peer_messages imports no cloud modules, so no import cycle.
  lifecycle's old broad-Exception catch differs only for pathological
  __getitem__ inputs, which are not DB rows and are out of contract;
  this is documented on row_get, not left as a second story.
- Scope note: other modules' own row_get copies (approvals,
  automations, marker_tools, todos, wait_ops) are out of this item's
  stated scope and are untouched.
- Also drops auto_memory's unused 'import os' (pre-existing F401),
  so touched files are ruff E,F clean.
- Tests: cloud/tests/test_row_get_unified.py locks the identity
  (both aliases ARE row_get), the real-row-type matrix, the
  None-default fallback, and snapshot_to_dict via the unified path.

(cherry picked from commit 1644a0b837bfefb13cdc3c93d87fc1b246026607)
2026-11-04 21:03:32 +00:00
host 324c19686c code-to10 v6 A6: fix mypy cost.py:551 tuple annotation
- model_breakdown inferred params as a 1-tuple from the first
  branch, so params + (month,) was tuple[Any] vs tuple[Any, str].
  Annotate params as bare tuple (tuple[Any, ...]) before branching.
- Annotation only: the () initializer is never used (if/elif/else
  always overwrites it), runtime semantics unchanged.
- mypy cloud/: 0 errors in 94 files (was 1 error); ruff clean;
  cost tests 39 pass.

(cherry picked from commit a9fd0692361e8169554413b725c81135be2c5525)
2026-11-04 21:03:32 +00:00
host 8b3d80670d code-to10 v6 A5: admin CLI wiring for stale-worker reap
- New production caller cloud/worker_sweep.py (python -m
  cloud.worker_sweep): AuthStore.authenticate + CODEX_GLOBAL_ADMINS
  global-admin check (same fail-closed semantics as
  handler_admin._is_global_admin) before any reap call; denied
  authenticated non-admins get an admin_worker_sweep_denied audit
  row; authorized runs reuse reap_stale_workers (classify, re-verify,
  pre-kill audit fail-closed, per-pid SIGKILL only, post-kill
  verification) plus an admin_worker_sweep summary audit; --dry-run
  lists classifications only.
- No new HTTP route, no container enumeration, no name/prefix
  matching, no workers-row deletion; workers.py docstring only notes
  the new caller.
- Tests: cloud/tests/test_worker_sweep_admin.py, 6 cases (bad key,
  non-admin, unconfigured admin list fail-closed, authorized full
  chain, dry-run, CLI main authorized/refused).

(cherry picked from commit c7d217549c5ccedf61dcc924b8998fffeddc76c6)
2026-11-04 21:03:32 +00:00
host bb00ba57aa code-to10 v6 A3: enforce signer separation on audit-verdict submission
process_audit_verdict now calls validate_signer_separation
before any state save or ledger write (previously the function
had no production caller on this path: it only ran inside
collect_failed_checks via decide_pushback, which itself has no
production caller). Signer is bound to the authenticated
caller -- a body signer differing from the caller is rejected
-- and executor/coordinator_approver/qa_tester must be
declared and distinct from the caller; missing field,
self-audit, or forged signer raises ValueError, mapped by
_loop_run to HTTP 400 with no side effects. No new route.
Honest limits are in the helper docstring: declared-identity
enforcement only (task rows store no authoritative executor /
coordinator / QA identity; task executor is a backend, not a
person), and audit-fix reaudit verdicts are out of scope
(the fix poster is not necessarily the re-auditor, so binding
signer to the fix poster would be a mis-binding).

(cherry picked from commit 56dce5165f4d08f38fe1730b9eea3b78f90cb97d)

Reconcile-port: handler_lifecycle.py docstring hunk redirected into cloud/server.py audit-verdict handler (target keeps 6-mixin split; enforcement itself is in audit_loop_wiring.py and applied cleanly).
2026-11-04 21:03:32 +00:00
host 72d16a95dc code-to10 v6 A4: fix AuthStore.audit NameError (import sqlite3) + retry regression test
Pre-fix any first-attempt audit failure raised NameError at
auth.py:424 (sqlite3 never imported), aborting the 5-attempt
retry loop on attempt 1 and masking the original error. The
424-line coverage mystery is also explained: the only full-suite
hit is test_child_model.test_coordinator_inherits_child_defaults
via worker best-effort _audit swallowing an OperationalError
(database is locked); 422-423/426-427 stay uncovered because
rollback succeeds and NameError aborts before either raise.
Bubble audit (see report): no merge/release gate swallows the
NameError and proceeds, so this stays a downgrade, not a
production blocker.

(cherry picked from commit 039c6adbac3b120b5b9a1dcbafeff6a91407ce70)
2026-11-04 21:03:32 +00:00
host 0b52a561df code-to10 v6 A2: single controlled PG guard entry (code side only)
Postgres audit_ledger append-only guard gains exactly one
execution entry: cloud/ledger_pg_guard.apply_pg_guard, runnable
as 'python3 -m cloud.ledger_pg_guard' (explicit ops command,
not a migration script). It executes PG_GUARD_SQL verbatim from
the constant -- no second copy of the SQL anywhere -- refuses
non-PgConnection targets, does not commit itself (caller/CLI
commits), and refuses with exit 2 on a non-postgres backend so
a no-PG environment can never claim hardening. ensure_schema
still skips PG triggers; POSTGRES_SCHEMA still builds only the
table. Tests lock all of this with a recording fake connection
(no PG execution is faked), a source scan asserting only
ledger.py and ledger_pg_guard.py reference the constant, and
CLI dry-run/refusal cases. Real-PG syntax and UPDATE/DELETE
blocking verification is explicitly left to B5, not claimed here.

(cherry picked from commit b1f6c9158d628186965a9e57576ff8c9500e3f73)
2026-11-04 21:03:32 +00:00
host e6a1346420 code-to10 v6 A1: delete server merge-gate modes, hard only
Server POST /tasks/{id}/merge no longer has record/enforce/off:
hard_mode_from_env and HARD_MODES deleted (not re-defaulted),
handler always evaluates the hard gate, env CLOUD_MERGE_GATE_MODE
and body merge_gate_mode are ignored server-side. The record
'no-evidence passes' and 'unprotected+confirm passes with
merge_gate_risk' server paths are gone with the dead risk audit;
no production caller justified keeping them (only production
caller of the non-hard evaluator was the merge handler itself;
audit_loop_wiring already used the hard gate). cloud/merge_gate
pure functions keep their #209 semantics but are documented as
non-server: they are no longer wired to any endpoint.
Server-level record/enforce/off tests rewritten to the new
behavior (renamed, not deleted silently); pure-function tests
unchanged.

(cherry picked from commit 08e75edbd6d04701965c5db951fa054cfbb75bb0)

Reconcile-port: handler_lifecycle.py hunks redirected into cloud/server.py _merge_task (target keeps 6-mixin split; mixin file does not exist here); handler_support.py kept at HEAD (its A1 hunk is a docstring of _validate_hard_gate_body, ported to server.py copy); test mock paths cloud.handler_lifecycle.* rewritten to cloud.server.*.
2026-11-04 21:03:32 +00:00
host 593197a4a2 B3a: 全自动问用户清单加第五种情形(验收失败推倒前确认),四件事/四类改写为五件 2026-11-04 21:03:32 +00:00
host 27464aa76d v5: rebase 融合修复(main 演进 + 附录源同步)
- websearch.py:补回 import socket(栈 46ca59f 的 lint 清理在栈
  上无害,replay 到 main 后 main #274 的超时/DNS 显式报错
  代码引用 socket,缺 import 致 2 项 NameError;re 在 main
  与重排后树中均 0 引用,不补)
- 3 个 websearch fake 补 scope="general" 参数(main 的
  handle_request 现必传 scope,旧 fake 致 TypeError 被吞成
  isError,3 项失败)
- playwright 工具数 14→18(main 新增 4 个,与 main _TOOLS
  逐名一致、无重复)
- playwright 种子测试改按 main 安全升级规则:源脚本 v1→v2
  且 manifest 证明未改动才刷新;未知改动只上报跳过不覆盖
- 附录源同步:01/02/07 三个 roles 源文件与 SKILL.md 附录章
  做同一改写,check_appendix 来源一致性恢复
2026-11-04 21:03:32 +00:00
host 631275ce78 code-to10 v5 rebase follow-up: keep main #275 resident working on rebased tree
- restore _audit_row in cloud/automations.py as a thin wrapper over
  cloud.auth.audit_on_conn (legacy row + ledger entry pair,
  user_id system, best-effort self-commit preserved). The stack's
  gap-4 option A deleted the direct writer; main #275 resident.py
  imports _audit_row, so the bare rebase broke server import.
  No direct audit_log INSERT is reintroduced, so the #250
  no-bypass scan stays green.
- conformance accounting 238/144 -> 243/149: main #275 added 5
  resident methods that legitimately stay in server.py; moved
  count stays 94, no duplicates.
- directional: resident x3, audit chain, conformance, automations
  x3 suites, 51 tests OK
2026-11-04 21:03:32 +00:00
host 102dd07f33 code-to10 v5: solidify 7 provisional resolutions per user confirmation (2026-11-02)
- whitelist expansion (tr + exit builtin) confirmed, comment only
- B4 viewport wording: temp banner removed, wording untouched,
  change-list table stays in draft, not merged into body
- B3-tail (a)/(b): no content change (bullet still absent), recorded
  as decided; v2 record showed it unselected, no side picked here
- section 4: 6 templates/artifacts/ refs deleted per signed verdict;
  tripwire test updated 6 -> 0 to pin the new inventory
- CHANGELOG pointer line kept, no marker present
- workers audit landing migration confirmed, comment only
- verify-script gate evidence confirmed, gate hard untouched
- 2 temp stances NOT touched: actual-only quota, evidence binding
  not enforced / no anti-restamp
- behavior code unchanged; directional skill tests 39/39 OK
2026-11-04 21:03:32 +00:00
host c292fcc878 code-to10 v4 coverage thickening: 219 new assertion tests (batches A/B1/C/D1-D6)
Baseline merge head e5ff26a: 28144 stmts, 2807 missing, exact 90.0263%, margin +7.
After thickening (full run): 2350 missing, exact 91.6501%, margin +464.
Full suite 3516 items: 3509 pass, 1 failure (pre-existing November date
failure, untouched), 6 skipped. No production code changed.
2026-11-04 21:03:32 +00:00
host 27c2acd5d0 v2 evidence: bind release evidence with ts/nonce, pin actual-only quota, ledger onboarding checklist, ledger failure outbox, read-only gate verifier (no live wiring)
- cloud/evidence_binding.py: bind/validate/nonce single-use store;
  release endpoint consumes nonce on first validated submission,
  replay -> 409 evidence_replayed, stale/future -> 409
  evidence_stale, partial -> 400, absent -> old path + label.
  Binding blocks exact replay and stale evidence, NOT restamping
  (unsigned evidence cannot prove content freshness).
- cloud/quota.py docstring: actual-only is the v2 integration
  position (already converged in v1 base via fef09ae, NOT in
  main); original PR semantics (#86 all-rows vs #90 actual-only)
  still pending coordinator confirmation at merge time.
- cloud/ledger_onboarding.py: DDL checklist referencing
  PG_DDL/PG_MARKER_DDL constants, read-only verify_ledger_ready
  and ledger_setup_report; default stays OFF, PG DDL stays an
  operator action (never claimed as executed).
- cloud/ledger_outbox.py + worker hook: ledger write failures
  go to a JSONL outbox in addition to the log and can be
  replayed; task outcome still unaffected (rule 7 kept),
  audit fail-closed untouched -- asymmetry documented, not
  silently changed.
- cloud/gate_verification.py: read-only verifier over an
  injected reader (match/mismatch/skipped); live wiring in
  merge/release is NOT possible on the current contract (no
  repo/ref in body or task row, no guaranteed trusted token),
  proven in the module header; no fake verification claimed.
- cloud/tests/test_v2_evidence.py: 18 new tests, all passing.

(cherry picked from commit bd85e33cd5e846fa6ee5d7e2440182dbd9c758b0)
2026-11-04 21:03:32 +00:00
host f16941347f fix: transplant PG init backfill rollback scope + audit-loop state upsert registration (code-to10 v2, from 854f810)
- db: translate INSERT OR IGNORE ... SELECT to ON CONFLICT DO NOTHING;
  register task_audit_loop_state (task_id) in _OR_REPLACE_PK (direct port).
- server: _backfill_default_quotas uses SAVEPOINT containment, no longer
  commits the caller's transaction (direct port; callers are init_db only).
- worker: NOT ported — integration _coord_child_rows has no column-fallback
  retry loop, so the InFailedSqlTransaction cascade site does not exist here.
- tests: rewritten for the integration base (no cloud.audit_loop /
  _coord_audit_loop_merge here); real-PG cases skip without DSN/driver.

(cherry picked from commit 79e6843610fcd275af874e7b4afc57af7ffa579e)
2026-11-04 21:03:32 +00:00
host 36ddc7a874 test: retarget v2 coverage monkeypatch targets to definition modules after handler split (assertions unchanged) 2026-11-04 21:03:03 +00:00
host 3a72ed3847 test: code-to10 v2 coverage additions (14 files, production code unchanged)
(cherry picked from commit 473338c35d59bfd50929542e7f08c0a4a22c5987)
2026-11-04 21:03:03 +00:00
host 2032043b60 split: handler mixins for oauth/identity/project/automation/fullauto (94 methods) on integration base 02835f6
- CloudControlPlaneHandler mixes in OAuthMixin, IdentityMemoryMixin,
  ProjectMixin, AutomationMixin, FullAutoMixin; shared helpers move to
  cloud/handler_support.py with server.py re-exports (old import paths
  keep working, incl. _validate_env_branch for tests).
- Method bodies moved verbatim; routers, base plumbing, task/lifecycle,
  webhooks stay in server.py. No >100-line method body split.
- test_handler_split_conformance.py (6 tests) pins resolution, layer
  bans and method accounting (238 total, 144 + 94, no duplicates).
- test_p1_security_server.py: monkeypatch targets follow the defining
  module (handler_project MAX_PROJECTS_PER_USER, handler_identity
  relay helpers); assertions unchanged.

(cherry picked from commit 92165a2b097126470e4827327d96d592a253adf1)
2026-11-04 21:03:03 +00:00
host 81fa61c0c7 v2 provisional: clear integration 9 failures (whitelist tr+exit, B4 viewport draft, CHANGELOG pointer, workers audit via audit_on_conn, verify-multiuser gate evidence)
9 failures from v1 baseline 02835f6 cleared with provisional resolutions only;
each option pair is annotated provisional in verification/code-to10-v2-failures-summary.md
and awaits user confirmation. No check deleted, no skip added, no bare-phrase
stuffing, default hard merge gate untouched. Known remainder: one pre-existing
date-dependent test_arch_converge failure (Oct-dated fixture vs Nov current
month), failing on pristine v1 too, left for the quota track.
2026-11-04 20:58:34 +00:00
host 933251e07d release: gate-check contract for future release endpoint + ledger anchor ops (prep, no endpoint, no deploy) 2026-11-04 20:58:34 +00:00
host e88192d43c integrate: rebase transplant-prep auditor expectation to v0.5 chapter table (11-auditor) 2026-11-04 20:58:34 +00:00
host c4f9199701 docs(skill): transplant prep for #244 audit additions into v0.3/v0.4/v0.5
Preparation only: no v0.3/v0.4/v0.5 text is changed, nothing is
claimed transplanted or deployed. Stacked on feat-audit-pushback
(#244, 39966bd).

- Appendix provenance 00..09: templates/roles/00-08 sources
  (byte-identical to #217) plus 09-auditor extracted from #244's
  appendix; check_appendix.py extended 00..08 -> 00..09.
  SKILL.md sole change (1 line, format-only): 09 chapter heading
  normalised to the strict source form, otherwise the #217
  checker cannot recognise the chapter. check_appendix.py passes
  on the real pack: 10 chapters match; --emit outputs 10 chapters.
- TRANSPLANT-PREP-244.md: per-paragraph transplant diffs for
  #244's +459 lines into v0.3/v0.4/v0.5 with anchors, grades
  (merge / merge+note / partial stop / full stop), chapter-number
  mapping (v0.5: 11-auditor, colliding 09-ops noted), the
  templates/artifacts delete-references decision with 6 sites and
  replacements, and the draft-sync checklist (sync itself is
  post-deployment only, not done here).
- tools/check_transplant.py: anchors / draft-apply /
  check-transplanted modes; draft-apply on the real v0.3/v0.4/v0.5
  texts passes check-transplanted (drafts in /tmp only, not
  committed). Stopped paragraphs are listed, never silently
  rewritten: v0.3 G7/full-auto sentences, v0.4 G7 sentences and
  the tighten-3 pre-rebuild confirmation, v0.5 whole QA section
  plus its checklist item and the confirmation paragraph.
- Tests: test_skill_appendix_provenance.py (00..09) and
  test_skill_transplant_prep.py; 13 new tests pass.
  Suites on this tree: cloud 1523 OK (skipped=4), top-level 105
  OK, deploy 39 OK.
2026-11-04 20:58:34 +00:00
host e758e8dd44 host: 验测命令白名单 + 结构化 verify_argv(shell=True 收口)
方案 A(白名单)+ 方案 B-lite(结构化 argv)双轨:
- 分类器 classify_verify_command:POSIX 引号状态机扫描,
  simple(无 shell 形态)/ simple-env(仅 VAR=val 前缀)走
  shell=False,shell(白名单内形态)走唯一的 shell=True 门,
  denied(嵌套 shell、命令替换、未列首词、绝对/越界重定向、
  多行等)拒绝执行并审计,返回 126 按验测失败处理。
- 验测线 shell=True 从 4 处收口到 1 处(run_gated_verify),
  run_verify 与轮次验收 2 处全部改走该门;bandit High 4->2
 (nosec 0,未做任何压制)。
- verify_argv:merge/goal/goal-resume 的 --verify-argv
  (REMAINDER,须放最后;空数组报 usage 退出,不静默跳过),
  任务记录 verify_argv,goal-resume 原样重放;goal-resume
  的 max_rounds==0 钳制计入 argv 形态。
- verify-audit:扫描 state 旧任务并分类;--apply 只转 simple,
  shell/denied 只列清单;审计本身不启动 codex server。
- notify_failure 不动:算子自有配置 + 插值已 shlex.quote
  (main 已有),白名单不适用,见 PR 正文定性表。
测试:新增 tests/test_host_shell_policy.py 30 项(含 naive
shlex.split 破坏回归锁、拒绝不执行标记文件、merge 回滚、
goal unmet/argv 达标、CLI REMAINDER/空数组、verify-audit
端到端);顶层 135、deploy 39、cloud 1430(skipped 4)全过。
2026-11-04 20:58:34 +00:00
host 2d50831e33 audit: lifecycle hook writes the attempt ledger (gap 3 follow-up)
- cloud/attempt_hook.py (new): canonical policy -- one counted
  dispatch = one row, is_defect always False from the worker;
  human/first rounds and human breakpoint resumes count;
  platform auto-resume reruns, coordinator fan-out, and
  pre-execution gate failures do not; transient retries inside
  one dispatch are not new attempts. Platform origin survives
  via the task_attempt_origin_markers table (same-transaction
  write on requeue, queued_at generation guard on consume).
  Defects are explicit-recorder only; corrections are
  append-only (record_correction, last-wins).
- cloud/worker.py: Worker(attempt_ledger_hook=False) + CLI
  --attempt-ledger-hook (default OFF = gap-3 behaviour exactly);
  marker write in auto_resume_interrupted, marker consume +
  classify in run_one, one ledger write at each terminal point
  (cancel branch, normal terminal block); all hook writes
  best-effort, never fail the task or block a requeue.
- cloud/attempt_ledger.py: corrects_attempt_no column (new DDL
  supersedes gap 3's pre-merge DDL) + record_correction +
  correction-aware aggregation; read path uses SELECT * so
  gap-3-era tables still read; cost code untouched.
- cloud/tests/test_attempt_hook.py: 32 tests (policy, markers,
  corrections, worker integration, mixed endpoint).
- docs/arch-conformance-metrics.md: policy, switch, PG manual
  steps (new PG_DDL + PG_MARKER_DDL), remaining user decisions.
2026-11-04 20:57:44 +00:00
host 32e2b70f20 fix: close bare open() in host.py and ResourceWarning in test_host_thread_cli
- host.py: 7 one-shot reads switched to with open (run_health_check
  pidfile, daemon-status pid/log, daemon-stop pid, daemon old pid,
  interrupt poll state, parallel jobs); read content, encoding args
  and error semantics unchanged.
- tests/test_host_thread_cli.py: test_old_archive_unchanged state
  read switched to with open; added a warnings-capture assertion
  scoped to the state read so a regression fails the test.
- Intentionally untouched: daemonize log handle (daemon-lifetime
  dup2 target) and the two _load_config_file / init sites owned
  by PR #266.
2026-11-04 20:56:06 +00:00
host 1462195872 fix(host): daemon 循环把显式全局 flag 透传给 recover/run-due 子进程
上一轨 #266 只修了 --state,本轨补其余项:--codex-home、
--codex-bin、--model、--model-provider、--effort、--sandbox、
--approval-policy、--approval、--turn-timeout、--progress-interval。
旧循环只传 --config,子进程重解析回落到配置/默认值,与 daemon
本体跑 turn 时的 CLI 覆盖值不是同一套(run-due 的 Server 与
dispatch/run_task_turn 全读这些值)。
修法:配置解析覆盖 args 之前先快照显式 CLI 值,循环里只把显式
值原样放进子进程 argv;数值 flag 用 is not None 判定(0 是合法
显式值:turn-timeout 0 不限时、progress-interval 0 关进度);
相对路径原样透传(daemonize 不 chdir,子进程 cwd 一致)。
有意不传:--config(已传解析后 config_path)、daemon 专属
--interval/--foreground(子命令不接受)、--ignore-host-budget
(定给云端 worker 路径,且 recover/run-due 都不查预算,传了
无行为差异、只留将来预算门继承口)。
--state 透传沿用 #266 语义原样(显式 is not None 才传),未改动。
回归:tests/test_host_daemon_passthrough.py 4 项。
2026-11-04 20:56:06 +00:00
host 2f68bb103d fix(host): _read_loop 跳过非 dict params 等脏消息,不杀死读循环
顶层为 dict 但 params 为真值非 dict 时,旧代码在 params.get 处抛
AttributeError,被外层 except 吞掉、读线程退出,后续正常消息
再也送达不了。改后校验跳过并记 stderr 日志、脏消息不进 events、
读循环继续;None/缺失/假值沿用旧 or {} 语义。审计同函数其它
get 路径:一并守住不可哈希的响应 id(pending.get)与 threadId /
thread.id(turn_queues.get)的 TypeError 致死路径;params.thread
已有 isinstance 守卫、_append_trace 已有 try 包裹,均不动。
2026-11-04 20:56:06 +00:00
host 9dcd5549d3 test: test_queue_sandbox robustness 断言不再读 sys.modules["queue"](全量语境下该槽位已被其它测试的 cloud/ 遮蔽污染) 2026-11-04 20:56:06 +00:00
host 38243d3e7f test: test_queue_sandbox 改 cloud 包导入,不再依赖顶层 queue 遮蔽标准库
旧写法把 cloud/ 插到 sys.path 前面再 from queue import TaskQueue:
一旦其它测试模块先 import 标准库 queue(缓进 sys.modules),本文件
即 ImportError。改成 cloud.queue / cloud.sandbox 包导入(失败时按
test_docker_sandbox.py 同款 fallback 补项目根目录),mock.patch 目标
同步改成 cloud.sandbox.*。新增 TestImportRobustness:断言标准库 queue
未被遮蔽,子进程先 import 标准库 queue 再加载本文件仍全过(子进程
以环境变量跳过自身用例防递归)。
2026-11-04 20:56:06 +00:00
host d39a772701 docs(autoscaler): correct queue_depth docstring on dependency cycles
Cycle tasks never reach topo sort: ready_tasks filters by
'deps all completed' first, so they neither raise ValueError nor
zero out other ready tasks (5 ready + 1 cycle pair still counts 5;
only a pure cycle counts 0, because its ready set is empty).
Counting logic unchanged.
2026-11-04 20:56:06 +00:00
host 8c540f1154 fix(server): remove unreachable duplicate lines in _latest_ts
Delete the second vals/return pair after the first return (was
lines 718-719); behaviour unchanged: max of numeric values, else None.
2026-11-04 20:56:06 +00:00
host e5d570c233 feat: 7-dim project audit scorecard (all >=9 to pass, average never a pass criterion)
- cloud/audit_scorecard.py: pure stdlib scorer, structured evidence in,
  7 dimension scores (0-10, 1 decimal), basis, missing/untested items,
  overall pass only when all 7 >= 9; unknown -> None, never 0/10/estimated;
  fixture/viewport/code-review evidence -> untested, never pass;
  thresholds all test_default_unapproved, user_approved only on explicit input.
- server.py: GET /audit-scorecard read-only, same auth/member scope as
  /metrics, no DB writes, no ledger writes, no pushback/reaudit triggers;
  on main base it honestly reports unknown/not-enforced, overall not_pass.
- docs/audit-scorecard.md: spec, formulas, threshold table, unknown
  handling, overall rule, 10-to-7 merge mapping, relations to
  #238 metrics-report, #244 sampling, #260/#261 loop, and a system-computed
  example (current state, overall not_pass) clearly separated from the
  previous judgement estimates.
- tests: 12 new items pin all-pass, one-below-nine fails, average 9.1
  with one 4 still fails, unknown None, fixture untested, conditional
  not a pass, thresholds unapproved, endpoint 401/200 read-only.
- suites: cloud 1442 OK (skipped 4), top-level 105 OK, deploy 39 OK.
2026-11-04 20:56:06 +00:00
host b36f4adc58 audit: wire loop driver to server endpoints and release gate (track 2)
Server-side execution for the track-1 pure driver (#260), no driver
semantics changed: audit verdict / fix completion / correction /
rebuild confirmation endpoints persist LoopState in audit_loop_state,
write every step through the #241/#247 ledger path (ledger first,
state second, fail-closed), derive fix/rebuild subtasks, and block
merge/release via the existing #247 chain reader. POST
/tasks/{id}/release follows the #259 contract (global-admin write,
fresh hard-gate evidence, merged status, multi-source 409 with no
audit write on block); deploy.py stays outside task gates.
2026-11-04 20:56:06 +00:00
host eb8c4c0356 audit: pure loop driver for the project-level audit rework loop (track 1)
LoopState + decide_audit + after_fix + apply_correction +
confirm_rebuild + emit, all pure: the driver returns Action
objects, the caller executes (subtask creation, merge/release
blocking, ledger persistence). Counts per (module, contract
version); pushbacks 1-3, 4th failure (> 3) rebuilds, 1 rebuild
and 1 targeted round per version, third-failure triage
(structural -> early rebuild, contract/design -> refreeze,
near-complete -> targeted), rebuild-only-implementation with
the old-test first gate, acceptance rebuilds pending user
confirmation, quota blocks consume nothing, cost threshold
escalates rebuilds to the user with full history, corrections
to pass do not unblock, ledger events match the #241 table
with CONDITIONAL mapped to fail at the boundary.

No server wiring, no release endpoint, no task creation, no
DB access in this track; wiring is the next track's job
against this interface.
2026-11-04 20:56:06 +00:00
host 6dcd965542 audit: unify audit-of-audit sampling rule (gap 2)
Single sampling rule; track 3 (#244) is authoritative for WHO is
mandatory, track 5 (#238) for HOW the rest are drawn:

- Mandatory (1.0): golden-task records + rebuild / refreeze /
  escalation records + third-failure near-complete still-failed
  cases (mandatory_triggers, full list per case). Track 3's old
  deterministic every-10th ordinary rule is removed (it drew zero
  from batches under 10 ordinary records and was predictable);
  track 5's old narrow mandatory list is expanded with golden /
  refreeze / escalate. blocked_quota stays non-mandatory.
- Random tiers: normal 0.10, critical-path 0.50, seed required
  and recorded, ceil so a non-empty group is never rounded to
  zero. 0.10/0.50 are TEST DEFAULTS, not approved production
  values; production rates remain a user decision.
- One pass, no double counting: mandatory records leave the
  random pools before drawing; a multi-trigger record (e.g.
  golden + rebuild) is sampled once with all triggers listed,
  and its correction follows the (original, corrected) verdict
  pair, never the trigger list.
- cloud/audit_pushback.py::select_audit_sample is now only a
  record-shaped adapter over cloud/audit_sampling.py::select_sample
  (seed required, retired reason names critical_path-for-kinds
  and periodic_sample removed); AUDIT_SAMPLE_EVERY_NTH deleted.
- Correction: original never mutated, correction appended,
  corrector != signer enforced in audit_sampling when both names
  are supplied; gate effect pinned (correction to pass never
  unblocks by itself -- schedule/cancel-and-rerun, blocked until
  a new passing re-audit; correction to fail re-blocks at once).
  Track 3 / track 5 retrigger vocabularies documented as synonyms.
- Skill text (tightening 3 item 2 + correction paragraph)
  rewritten to the unified rule; new test file pins the
  boundaries (mandatory union, dedup, ceil incl. the 9-record
  case, seed reproducibility, golden-set construction under both
  sample vocabularies, adapter order/non-mutation, correction
  preservation on both tracks).
2026-11-04 20:56:06 +00:00
host f83bd79525 audit: route automation audit rows through hash-chain pair (gap 4, option A)
Bypass closed: automations._audit_row (direct audit_log INSERT,
best-effort swallow) is deleted. run_due_automation now writes via
cloud.auth.audit_on_conn, the same audit_log + audit_ledger pair
AuthStore.audit() writes, sharing created_at. The audit pair runs
before record_automation_run's commit, so task row, run row and
audit pair commit or roll back together; chain-head IntegrityError
retries the whole block up to 5 times, other errors roll back and
raise (fail-closed). The claim stays committed, so a failed run is
retried next interval, never recorded as a failed run.
AuthStore.audit() now delegates to audit_on_conn; its pair, retry
count and fail-closed semantics are unchanged.
2026-11-04 20:56:06 +00:00
host d303dedf32 audit: task-attempt ledger feeds real first-pass/defect/rework rates (gap 3)
- cloud/attempt_ledger.py: separate task_attempts table (not tasks
  columns) with per-attempt rows, MAX+1 attempt_no, append-only
  intent; interrupted rows kept but never counted; is_defect is
  explicit, never inferred from failure; first defect category
  wins; no-ledger tasks stay unknown (None), never backfilled.
  SQLite DDL is CREATE TABLE IF NOT EXISTS (idempotent); PG_DDL
  is the verbatim manual step for production Postgres, kept out
  of POSTGRES_SCHEMA on purpose (migrations coverage untouched).
- cloud/server.py GET /metrics-report: aggregates the ledger
  into compute_metrics records; missing ledger table degrades to
  unknown rates, not an error. Cost dual-column code untouched.
- cloud/metrics.py: docstring only (ledger is now the source);
  compute_metrics logic and all #238 semantics unchanged.
- Tests: 16 ledger tests (store/aggregate/metrics/PG adapter
  evidence) + 3 endpoint tests (real rates, old task beside
  ledger task, interrupted status non-terminal).
2026-11-04 20:56:06 +00:00
host 8a4e80c20d integrate: restore CostStore import dropped with #241 dual_column_view line
The #241 import resolution deleted the whole 'from cloud.cost import
CostStore, dual_column_view' line to drop the unused alias, which
also removed the CostStore import that _quota_snapshot needs; every
task creation then failed closed with 503 quota_check_unavailable
(4 EndpointChainTestCase failures in test_audit_wiring). Restored
as a plain CostStore import; dual_column_view stays available in
cloud/cost.py for #241's own tests.
2026-11-04 20:56:06 +00:00
host ace7503515 feat: audit-of-audit sampling rules (golden set and critical paths)
- cloud/audit_sampling.py (pure, stdlib): mandatory sampling (1.0)
  for rebuild cases and for third-failure near-complete cases whose
  continuation round still failed; random sampling for the rest
  (normal 0.10, critical-path 0.50, ceil so small groups are never
  rounded to zero, seed required and recorded for reproducibility).
- Wrong-verdict handling: correct the original conclusion and
  retrigger the corresponding flow (wrong pushback ->
  cancel_pushback_and_rerun_audit; wrong rebuild ->
  halt_rebuild_and_restore; wrong pass -> reopen_audit_and_pushback;
  unknown original -> escalate_to_human); every result, correct or
  corrected, is appended to the audit-of-audit record.
- Golden-set approval checklist: list reviewed, criteria defined,
  sample exclusion, approver+timestamp -- all human-confirmed before
  approval; sample entries (sample=True or sample- ids) are dropped
  and counted, never counted as golden.
- metrics.build_report gains an optional sampling_plan section;
  without a plan it states sampling is pending, never implying the
  audit was re-examined.
2026-11-04 20:55:49 +00:00
host 38a10db0c8 feat: architecture conformance checks in CI and metrics feedback loop
- cloud/arch_conformance.py: contract-version (+1 only, approved
  change record), forbidden-directory (own dir only, .. and symlink
  escapes resolved), forbidden-import layer bans audited against the
  baseline (foundation/execution/driver, server sqlite3 Row adapters
  deliberately allowed), G2 frozen-stack swap guard; skill-project
  one-call check.
- cloud/metrics.py: first-pass/defect/rework rates over terminal
  tasks, unknown rates as None (never 0), #212 dual-column per-task
  cost (total None when incomplete), pure feedback rules
  (tighten/route-with-extra-audit/recalibrate, auto_apply False),
  golden-set gate: unapproved sample set is never decision-ready.
- GET /metrics-report (authenticated, member-scoped, same as
  /metrics): attempts/defects are None until an attempt ledger
  exists, so rates stay unknown rather than fabricated.
- Tests: 29 arch + 15 metrics + 3 endpoint, each check with
  positive and negative cases; repo-level scan pins zero layer
  violations on the baseline so a future violation fails CI via the
  existing host-verify discover run (no workflow change).
2026-11-04 20:55:49 +00:00
host 4c38e3c452 audit: wire pushback gate to hard merge gate and hash-chain ledger (gap 1)
Track 3 decisions (audit_pushback) now really block the server merge
endpoint and really land on the track 4 hash chain, via the new
cloud/audit_wiring.py translation layer:

- POST /tasks/{id}/merge ANDs the chain pushback block
  (merge_blocked/release_blocked/blocked_by=audit_pushback/round/
  failed_checks, replayed per module+contract version) with the
  hard gate's five checks in every gate mode; either side blocks
  -> 409, status unchanged, audit_pushback_blocked appended to
  merge_gate.blocks. Ledger reads that fail (other than a missing
  audit_ledger table) fail closed to 409.
- Every pushback/fix/re-audit/rebuild/escalation step is written
  to the ledger with track 3 fields authoritative and track 4
  storage authoritative; CONDITIONAL maps to fail at the boundary
  with the original preserved, history never rewritten.
- Hard-gate 409 blocks codes feed pushback packages machine-first
  (branch protection survives as its own extra check).
- Re-audit QA guard: a claimed pass with un-rerun or failed QA
  links never reaches the chain.
- Track 4 compat: one audit_wiring_event action for escalation /
  blocked-quota / audit-sample kinds, counted in the timeline.
- Resolved tension (documented in audit_wiring.py): a meta-review
  correction to fail re-blocks at once, but a correction to pass
  does NOT unblock by itself -- track 3 schedules a re-audit,
  it does not release the gate; track 4 failure counts still use
  effective verdicts, so the two views may disagree while a
  re-audit is pending.

Tests: cloud/tests/test_audit_wiring.py (18 items), incl. a real
HTTP end-to-end chain (fail -> 409 -> fix -> re-audit pass ->
200) and a separate QA-link chain test.
2026-11-04 20:55:49 +00:00
host 04a7a4280b feat: tamper-evident audit ledger (hash chain) + dual-column cost view
- Hash-chain ledger (cloud/ledger.py): prev_hash/entry_hash per record,
  SQLite append-only triggers, UNIQUE prev/entry hash with fail-closed
  retry at the transaction boundary; verify/export (incl. expected-head
  check for tail truncation); legacy audit_log rows marked pre-chain via
  a single ledger_genesis marker, never rewritten.
- AuthStore.audit() writes audit_log + chain entry in one transaction.
- Track-3 interface: audit_verdict / audit_pushback_round /
  audit_rebuild / third-failure assessment / test-change audit /
  meta-review / rebuild-notice entries; per-(module, contract-version)
  failure counts derived from the ledger (pass or completed rebuild
  resets; total > 3 triggers rebuild); acceptance-triggered rebuilds
  require a confirmed user notice.
- Admin read-only endpoints: GET /admin/audit-ledger/verify|export.
- Cost: dual_column_view (priced_usd_micros + billing note, wording
  reused verbatim from PR #212) wired into project/task cost endpoints;
  by-model and per-creator reporting stay in #212, not duplicated here.
- PG schema + migration lists updated for audit_ledger (incl. sequence
  setval alignment).
2026-11-04 20:55:49 +00:00
host e26624b1bc integrate: appendix count assertion follows 12-chapter table 2026-11-04 20:54:50 +00:00
host 4307d24649 audit: independent audit role, auto-pushback, rebuild branch, three tightenings, QA full-chain
Independent audit (no code, independent re-run, separate signature;
CONDITIONAL never passes; deviation needs due todo) and automatic
pushback (fail -> derived fix subtask, merge/release blocked,
package with per-item evidence, full re-audit, 3-round limit with
a separate CI auto-fix counter, ledger hash-chain interface for
track 4, gate-block interface for track 1). Over 3 failures per
module per contract version: rebuild only that module from the
frozen contract (old implementation archived, avoidance list),
contract/design root cause -> G2 re-freeze escalation instead.
Tightenings: 3rd-failure triage (structural early rebuild /
early refreeze, near-complete one targeted round), rebuild keeps
tests and passed assets with an old-test first gate, audit-of-
audit sampling/correction and G6 user-only acceptance plus
acceptance-rebuild user confirmation. QA full chain: self-test
three parts, PRD coverage, agent six, cross-client matrix with
honest uncompiled verdicts, G5 gates, impact-scoped regression,
dual QA/audit signatures, failed-link re-runs in re-audit.
Skill text is purely additive (+459/-0) against main v0.2 text;
port this section into v0.3/v0.4/v0.5 texts on merge, never
overwrite them with this file.
2026-11-04 20:54:50 +00:00
host facc2a249a feat: cloud 门禁/超时/成本/沙箱收敛为单一判定源
- 新增标准库叶子层 timeouts/gates/quota/sandbox_policy:
  审批 3600 与单轮 600 各有名常量与环境覆盖层,已建项
  expires_at 永不重算;目录/控制/合并状态门禁统一判定,
  目录违规无任何覆盖参数;配额取数与比较唯一来源
  (USD 先于无价、命中均为 >=、无价只计 actual 行);
  /tmp 隔离矩阵与失联清理判定纯函数化。
- 调用点委托:server/worker/automations/auto_memory 的
  配额 SQL 与比较、server/tree/marker 的目录解析、
  marker 的控制门、sandbox 的任务容器名正则、两处 300 秒
  陈旧阈值默认值均收敛,别名与错误文案不变。
- 统一两个 P0 口径分歧:服务端无价计数由全部 usd IS NULL
  行改为 actual-only;显式不限额用户在服务端准入亦不受
  无价上限约束(与 worker 运行时一致)。
- 不新增门禁种类与 record 模式(主线无此实现);不改
  skill_seed/skills/SKILL.md;不改 v1.1 契约与分支保护。
- 新增 test_arch_converge.py 18 项。
2026-11-04 20:54:50 +00:00
host 17fa493da7 integrate: sync appendix sources to v0.5 appendix table (00-10)
Integration arbitration, not a PR commit: v0.3/v0.4/v0.5 synced body
changes into appendix chapters 00/02/04/06/07 while templates/roles/
sources stayed at v0.2, so check_appendix failed 6 chapters; and
09-ops/10-iteration chapters (v0.5) were invisible to the strict
chapter regex because of the ', v0.5 new' title suffix, breaking
the #214 matrix-vs-appendix test. Direction is sources follow the
appendix (appendix is the tenant-visible authoritative version;
never overwrite v0.5 text with v0.2). 09/10 headers normalized to
strict form (suffix only); 09/10 sources split mechanically from
the appendix; EXPECTED_IDS extended to 11 chapters in the checker
and both appendix tests.
2026-11-04 20:54:33 +00:00
host e1ba572a5a test: pin skill appendix sync and SKILL.md-only seeding (C-line, no behaviour change)
- test_skill_appendix_sync: all 9 appendix chapters 00..08 in order,
  body role-matrix set == appendix role-title set, authority
  statement on both sides, GitHub guarantee in body + named
  appendix chapters 00/04/07, seeded copy byte-identical with
  full appendix. Previously only 00/08 existence was asserted.
- test_skill_seed_pinning: only SKILL.md copied (pack extras never
  land, never resurrected), tenant extras left alone, tenant-modified
  SKILL.md never overwritten across repeats, identical = noop,
  deleted SKILL.md re-seeded (documented boundary, not deletion
  preservation).
- skill_seed.py: evaluation note only (why whole-dir copy is not
  done); no code change.
2026-11-04 20:54:33 +00:00
host b42b650fb7 feat: 沙箱规模——/tmp 顺序加严、注册表寻址与失联精确清理、超时边界抽取
- Docker /tmp tmpfs 移到全部 -v 之前(父挂载在前,seed 子挂载在后);
  宿主级 bwrap /tmp 仍宣告未隔离,口径见 tmp_isolation_status()
- workers 表补 host/pid/address(老库幂等补列),心跳透传与保留语义,
  _claim 写 claimed_by_worker;orphaned_containers 精确识别失联容器,
  Worker.cleanup_orphaned_containers 默认只杀 pid_verified 的精确容器名
- docker_run_timeout() 纯函数抽取(行为与原内联一致),README 补边界与
  未验证清单;新增 test_sandbox_scale.py 20 项
2026-11-04 20:54:33 +00:00
host e079b9b44a feat: cost/quota set — dual-column priced reports, creator split, hard cutoff, approval-timeout auto-threshold
- CostStore: per-model breakdown, report_by_creator (JOIN tasks.created_by),
  dual-column reports with priced_usd_micros, unpriced_models listed
  separately and a billing note (proxy price, not the relay bill);
  _report itself untouched, old exact-key tests keep passing.
- Hard cutoff: cost.quota_cutoff_reason is the single USD/unpriced-cap
  decision; worker._quota_exceeded now delegates to it (identical
  messages); claim gate, turn boundary and poll kill stop spend and
  record interrupted + quota reason + audit; auto-resume re-checks
  live quota before requeueing.
- Approval timeout (G7 ops metric): cloud/approval_timeout.py —
  default stays 600s, >20% timeout rate recommends 1800s, <5% keeps,
  mid-range keeps; stats + recommendation + info log; wired into
  /metrics (member projects, no log spam) and a global-admin
  /admin/ops/approval-timeout endpoint (sweeps overdue first).
- Server: task/project cost endpoints return dual-column reports;
  new GET /users/me/cost and GET /admin/cost-by-creator.
- Tests: cloud/tests/test_cost_quota.py, 10 tests.
2026-11-04 20:54:05 +00:00
host cc32f51502 skill: cross-task artifact pass with sha256 dual-channel verification
Core artifacts travel as an explicit manifest; coordinator triple-checks
(core report vs manifest vs recomputed hash) before cleanup, regression
rewrites files verbatim, recomputes sha256, stops on ARTIFACT-HASH-MISMATCH
and only then runs the same core code plus import-only regression tests.
2026-11-04 20:54:04 +00:00
host 5feb639696 feat: wire full-auto executor to server HTTP endpoints
GET /full-auto/status, GET /full-auto/config-plan, POST
/full-auto/validate-action|merge-gate|ci-fix|release-plan|
rollback-plan, POST /full-auto/execute (global admin only,
FULL_AUTO_ENABLED + verified installation + branch protection
verified via GitHub API, else 403 + audit), GET /full-auto/audit.
Guards reused from cloud/full_auto.py; token only in Authorization
header; audit via audit_record redaction into AuthStore audit_log.
2026-11-04 20:54:04 +00:00
host a2ed8f8a79 refactor: remaining longfunc small extractions after #231 (no module split)
Only pure computation/validation sub-blocks of _handle_github_webhook,
_create_followup, _deliver_to_thread and _task_chat_history are extracted;
all DB writes, audits, external calls and side-effect blocks stay in the
callers, error strings/codes and response shapes verbatim. _deliver_to_thread
uses the shared goal classifier only for /goal input: its non-goal terminal
path still goes to CAS revive (not 409) and its merged path keeps its own
wording. New tests: test_longfunc_remaining.py (15).
2026-11-04 20:54:04 +00:00
host 48afcf42da refactor: extract minimal pure helpers from _continue_task, _task_wait, _task_thread_read and _metrics
_continue_task 226->168 via _validate_continue_options;
_task_wait 158->139 via _validate_wait_params;
_task_thread_read 187->152 via _summarize_trace_entries;
_metrics 123->104 via _summarize_metrics_tasks.
No behaviour, message, status or route change; error strings verbatim.
New tests: test_longfunc_extra (9). Cloud full suite: 1439 OK, skipped=4.
Follows #229 pattern; must merge after #229 and be rebased/checked then.
2026-11-04 20:54:04 +00:00
host 200c8be16f refactor: extract minimal helpers from _dispatch, _dispatch_project and _create_task
Move the /tasks/* sub-route out of _dispatch into _dispatch_task_route
(query passed explicitly; the files/tree/thread branches use it), move
the push-subscription DELETE branch out of _dispatch_project into
_project_push_subscription_delete, and turn the goal-validation block
of _create_task into the pure module function
_validate_task_goal_options (returns error string instead of sending
400, caller sends it unchanged). Statements are moved verbatim except
indentation and the goal send+return -> return-error transform; no
behaviour change. server.py module split intentionally not done: it
remains a larger, higher-risk refactor.

Add test_longfunc_split covering the pure goal validator's success
paths and all eight error strings.
2026-11-04 20:54:04 +00:00
host 9e90efd5ee workers: reap pid_verified stale workers with pre-kill audit and post-kill verification 2026-11-04 20:54:04 +00:00
host 32e264054c workers: land host/pid/address columns with idempotent migration and pid_verified stale classification
- ensure_workers_table: new tables include host TEXT, pid BIGINT,
  address TEXT; old tables gain them via _ensure_hostpid_columns
  (PRAGMA column check, missing-only ALTER, old rows keep NULL,
  never fabricates host/pid). SQLite and Postgres share this path
  (PG via the db adapter's PRAGMA translation); POSTGRES_SCHEMA
  deliberately still excludes workers, which is volatile heartbeat
  data in UNMIGRATED_TABLES (adding it broke the P2 migration
  alignment tests, verified and reverted).
- heartbeat/register: given host/pid/address refresh, omitted
  values preserve the old row; address has no derived source.
  Local worker passes host_name + own pid; HTTP heartbeat only
  stores caller-supplied values, never the server's own.
- classify_stale_workers: kill only when age strictly exceeds the
  threshold AND host matches local host AND pid is proven dead;
  equal threshold, foreign host, missing pid, or live/unknown pid
  are list_only. Classification only, never kills, never matches
  by name/prefix, never touches infra containers.
2026-11-04 20:54:04 +00:00
host 26630bafec docs(skill): add software-engineering README and same-dir reference test
SKILL.md header pointed at same-dir README.md but the pack had no
such file (CHANGELOG was supplied by #217, README was not). This
track adds the README only: purpose, chapter map, appendix
provenance entry point, seeding behaviour, and known boundaries.
It states no rule, changes no SKILL.md semantics, and does not
duplicate the CHANGELOG/script explanations -- overlapping parts
are pointers, with an explicit division-of-labour section.
Deletion retention is written only as the tombstone-design
placeholder, deferring to the skill_seed implementation, because
no tombstone implementation has landed. Test pins that every
file SKILL.md cites as same-directory exists (CHANGELOG, README).
2026-11-04 20:54:04 +00:00
host 99ce8cf72d docs(skill): add appendix provenance sources, checker and CHANGELOG
SKILL.md claimed its appendix was spliced verbatim from
templates/roles/ by a generation script (see CHANGELOG), but the pack
contained none of the three. Add the nine role sources (mechanically
split from the v0.2 appendix; SKILL.md untouched, zero semantic
change), tools/check_appendix.py (verify + --emit, stdlib only, never
edits SKILL.md), CHANGELOG.md, and test_skill_appendix_provenance.py
(5 tests). Seeding unchanged: skill_seed copies SKILL.md only, so
templates/tools/CHANGELOG never reach the tenant home.
2026-11-04 20:54:04 +00:00
host 93f2b350ac feat: hard merge gate by default (CI + directory + contract + coordinator + reviews)
- cloud/merge_gate_hard.py (new): pure hard gate; mode resolution is
  env-only (unset/invalid -> hard, fail-closed); five checks plus
  branch protection must be protected; unknown/unprotected block
  even with explicit confirm; no-evidence blocks (fail-closed);
  directory check reuses #209 check_directory_isolation (v0.3 rule);
  blocks codes + merge_gate_blocked audit detail are the track-3
  pushback interface (no pushback state machine in this track).
- cloud/server.py: POST /tasks/{id}/merge uses hard mode by default;
  record/enforce/off only when explicitly set via env (preserving
  #209 semantics); body merge_gate_mode is ignored server-side so
  callers cannot downgrade the gate; every gate block writes a
  merge_gate_blocked audit before returning 409, status unchanged;
  hard-mode body type errors return 400.
- docs/merge-gate-branch-protection.md (new): protection payload
  (PR + strict status checks + no force-push + no deletion +
  enforce_admins), empty required_checks = unconfigured, Pro/public
  prerequisites, 403 causes; states protection is NOT claimed enabled.
- SKILL.md (gate-mechanism wording only): four checks -> five checks;
  body + coordinator + client appendix gate paragraphs updated to
  default hard, merge_gate_blocked audit, payload doc reference.
- tests: 31 new hard-gate tests (pure + endpoint + skill text);
  #209 endpoint tests now set record env explicitly (their intent);
  test_server_merge 200-path calls now carry full hard evidence.
2026-11-04 20:54:04 +00:00
host f6d721158e feat: configurable merge gate (branch protection + directory isolation) and skill body/appendix checks
- cloud/merge_gate.py: pure gate; directory check reuses the v0.3
  git diff --name-only merge-base command; protection modes
  record (default, explicit confirm required when unprotected),
  enforce (always blocks when unprotected), off (explicit only).
  Confirm covers protection risk only, never directory violations.
  Protection status is caller/env-declared only; unknown is a
  recorded risk, not a claim of protection.
- server POST /tasks/{id}/merge: applies the gate only when gate
  evidence is supplied (or env declares protection); no-evidence
  calls behave as before plus a merge_gate field in the response.
  Blocked merges return 409 without changing status; confirmed
  unprotected merges write a merge_gate_risk audit entry.
- skill_seed.py: whole-directory seeding evaluated and rejected
  (cannot preserve tenant deletions; no benefit while the pack
  holds only SKILL.md); SKILL.md-only behaviour unchanged.
- software-engineering SKILL.md: gate paragraph added to the body
  and to the coordinator + client appendix sections (v0.2 text on
  this base; port to v0.3 text on rebase after #199 merges).
- tests: 16 new tests covering gate modes, directory reuse,
  body/appendix bidirectional assertions naming the missing side,
  SKILL.md-only seeding and tenant-edit preservation.
2026-11-04 20:54:04 +00:00
host 04a2c4d7f8 feat: software-engineering skill v0.5 (G7/G8 ops + iteration)
Stacked on v0.3 + v0.4 (HEAD d6522ba feat-full-auto): v0.3/v0.4
content preserved, not reverted. Adds G7 post-release ops and
observation (monitoring, errors, cost/quota, feedback, hotfix loop,
rollback triggers, ops manual) and G8 iteration and scaling (v1.1
handover list, contract v1->v2 protocol, new-end onboarding,
scale/performance, deprecation), with G6->G7 and G7->G8 gates,
DAG, gate table, coordinator derivation, G0-G8 todos, checklist,
09-ops and 10-iteration role templates, and ops-manual / v1.1
handover templates in both body and appendix. Settles web+React+
multi-viewport focus, cross-viewport E2E, web single-end release
with iOS/Android native postposed, open-source-first, and the
TypeScript full-stack default (user-request-only language change;
codex-app-server itself stays Python). Pending #199 and #205
merge, then one rebase round. PR only, do not merge or deploy.
2026-11-04 20:54:04 +00:00
host cd85157b54 feat: full-auto mode v0.4 (host executor + skill + CI fix loop, stacked on v0.3)
Host auto executor (cloud/full_auto.py, stdlib only): default off
(FULL_AUTO_ENABLED + verified installation), forbidden actions
fail-closed (delete repo, force-push, visibility change, secret
read/expose, branch-protection delete/bypass, GitHub account
auto-registration), token only in request header, audit log
redacted, branch protection requires PR + strict checks +
no force-push + no deletions + enforce_admins, merge gate
(CI green + directory check + contract version + coordinator
approval), CI fix loop max 3 then escalate, rollback only via
revert PR or previous tag. Skill: v0.4 full-auto mode, coordinator
reviews, host executor executes, task agent never executes
merge/deploy; repo-creation honesty branch (org via App token,
user repo needs_user_once); no web auto-registration of GitHub
accounts. Tests: 19 new, cloud full 1451 OK (skipped=4).
2026-11-04 20:54:04 +00:00
host c76ef9dcec feat: software-engineering skill v0.3 (P1-1..P1-4 + P2)
- P1-1 directory-isolation executable check: git diff --name-only
  against merge-base, output recorded in merge record
- P1-2 derivation checklist table (8 required items, missing one blocks dispatch)
- P1-3 QA split into single-client review and cross-client E2E with
  fixed deliverables and agent-test attribution
- P1-4 sub-task slim-pack trimming rules (listed chapters only, never full copies)
- P2: inter-thread Q&A default policy, docs/decisions.md append-only,
  per-client onboarding docs (web first at G4a), v1.1 handover checklist
- Body and appendix kept in sync; new lightweight keyword test
2026-11-04 20:54:04 +00:00
host 6ff3855419 coverage85-threshold: 覆盖率门槛 75% -> 85%(实测 85.2565%,余量 57 行) 2026-11-04 20:54:04 +00:00
host 1f06a3ef30 coverage85-step4e-fix: misc 不再 import stdlib queue,避免遮蔽 test_queue_sandbox 的 cloud/queue 导入 2026-11-04 20:54:04 +00:00
host 887d8f7afb coverage85-step4f: host 纯函数与小方法长尾测试 2026-11-04 20:54:04 +00:00
host 1ba96dc61c coverage85-step4e: workers/autoscaler/playwright 长尾测试(+29 项) 2026-11-04 20:54:04 +00:00
host 3a310c062b coverage85-step4d: host main 尾部命令块测试(+30 项) 2026-11-04 20:54:04 +00:00
host 6c123bfb23 coverage85-step4c: server 长尾端点与子路由测试(+19 项) 2026-11-04 20:54:04 +00:00