- 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)
- 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)
(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).
(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).
(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.
(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).
- 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)
- 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)
- 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)
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).
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)
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)
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.*.
- 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
- 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
- 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)
- 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)
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.
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.
- 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.
- 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.
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.