Repository navigation
feat: add isolated US liquidity scanner v2 lab - #2
Draft
Vikkrantpol wants to merge 100 commits into
Draft
Vikkrantpol wants to merge 100 commits into
Vikkrantpol wants to merge 100 commits into
Conversation
…on accounting, atomic writes
…symbol adaptation
Single shared provider fetches both control sources bound to one immutable source snapshot; resolution binds its provider snapshot digest; cross-source validator checks source digests, snapshot binding, membership and anchor collisions; load_phase9_* loaders reject missing/invalid/mismatched snapshots and drift; report reconciles the 30-symbol set; sample/verify write atomically and revalidate.
18 new focused tests cover cross-source validation, loader fail-closed cases, 30-symbol report reconciliation and offline producer CLI E2E. conftest blocks socket/requests/urllib/yfinance when US_V2_OFFLINE_TEST=1 and CI relabels the job to Offline US-v2 tests with the guard set on the pytest step.
Cross-row enrichment promotes a compact W-ending canonical symbol to a high-confidence warrant hint only when a canonical common/class-share base record with a matching issuer stem exists in the same listing set (rule corroborated_compact_warrant). Validators independently rederive the assignment with stable failure codes. The universe classifier and control resolution accept strong listing evidence only under explicitly authorized rules, and resolve-controls runs a static control-capacity preflight that fails closed before any provider budget is spent. Frozen attempt-2 evidence: 240 compact-W warrants fully corroborated (name_keyword/low -> corroborated_compact_warrant/high), sufficient to fill the warrant quota without lowering the strong quota contract.
…universe on session history Phase 9 exact-500 readiness fixes: - universe: apply_session_history gate demotes qualified records with fewer completed sessions than min_history_sessions (indeterminate stays qualified) - scan-plan: with universe.reconcile_reject_list the manifest reject list drops symbols the authoritative universe classifies as qualified, so weak name_keyword hints (e.g. 'unit' inside 'United'/'Community') no longer cause deterministic reject-list scan failures - config: add universe.enforce_history_gate and universe.reconcile_reject_list keys + schema; cli exposes --no-history-gate - doctor: classify ETFs from authoritative screener hint readiness fixes - tests: history gate core + integration, reject reconciliation, doctor readiness
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.
US v2 upgrade validation COMPLETE — awaiting merge decision
Final HEAD:
4d1e6c5(branchexperiment/us-liquidity-scanner-v2, basemain). No further development phase is planned; this PR is merge-ready pending human decision. Draft retained; not merged; not marked ready.Validation evidence
20260807-084027-783789-3dfb— 205 scanned / 118 qualified / 87 rejected / 0 errors,provenance_valid=true, benchmark ok.20260807-235426-316691-9e78— 205 scanned / 118 qualified / 87 rejected / 0 errors,provenance_valid=true, benchmark ok.ba041a2e9063121a.runtime/us_v2_full_shadow/, run20260808-042934-560490-4d60): 7121 universe records / 3561 scanned / 1594 qualified / 1937 rejected / 30 expected data-availability warnings; benchmark_status ok.insufficient_history(young listings, completed sessions < 120) + 1no_data(no daily bars — delisted). No schema / authorization / provenance / classification-contract / database / benchmark / unexpected-exception failures.US_V2_OFFLINE_TEST=1in an isolated temp runtime root; live runtime state byte-identical pre/post (sha256-verified); India isolation manifest unchanged;git diff --checkclean.git diff --checkclean.Normal shell operator workflow (documented in
us_v2/docs/runbook.md)A plan-less
scanis the normal daily mode (require_scan_plan=false);--plan PATH --yesscans are only for the exact-500 Phase 9 validation runs. Runtime lives underruntime/us_v2/;fresh --yesresets it;US_V2_RUNTIME_ROOTpoints at an isolated shadow root. Validation manifests/control baskets are upgrade-validation assets, not ordinary daily requirements.Not performed
Phase 9 — Session 2 validation (completed session 2026-08-07)
What changed (
us_v2/config.py,us_v2/config_schema.py,us_v2/scan_plan.py,us_v2/cli_actions.py)universe.reconcile_reject_list, defaultfalse) — closed the Session-1 divergence where the manifest reject list carried 6 symbols (CBU/CYH/GEL/NECB/UPS/UTHR) that the authoritative universe classifies as qualified candidates. When enabled, a symbol the universe qualifies is deterministically dropped from the manifest reject list at plan creation (scan_plan.py), so the plan reject list and the live universe can never disagree. Enabled in the privatephase9_config.json; default config stays false.Session 1 vs Session 2 comparison (same 500-symbol chain, same private config)
20260807-084027-783789-3dfb, completed session 2026-08-06, scanned 205 / qualified 118 / rejected 87 / errors 0, benchmark_status ok, planff5b98c7(single-use, consumed once), provider success rate 1.0.20260807-235426-316691-9e78, completed session 2026-08-07, scanned 205 / qualified 118 / rejected 87 / errors 0, benchmark_status ok, plan319a7322(single-usestage5-phase9-session2, bound to HEADf5cabaa, consumed once), provider success rate 1.0.candidate_set_digest=ba041a2e9063121ain both; universe rebuild 500 records / 205 qualified / 270 rejected (10 via the session-history gate) / 25 classification_unknown; reject list reconciled to 156 symbols with zero qualified overlap.--persisted-scan-readiness): 83/86 pass, 3 warn, 0 fail,ready=true; all plan/binding/control/exact-500/relaibility checks pass.Full-universe shadow scan (isolated root
runtime/us_v2_full_shadow/)20260808-042934-560490-4d60: scanned 3561 / qualified 1594 / rejected 1937 / errors 30 (completed_with_warnings— all 30 are expectedinsufficient_history/ 1no_dataon recent/delisted listings, no data corruption). Top: CCK 84.71, DELL 84.63, ALAB 84.11. Summary, report (json/csv/md), export csv, and history all captured inside the shadow root.Final offline suite (run once, isolated temp runtime root)
US_V2_OFFLINE_TEST=1(639.55s) withUS_V2_RUNTIME_ROOTpointed at a fresh temp root; live runtime state byte-identical pre/post (sha256-verified), no tracked runtime mutations.Status
9478369, basemain, pushed toexperiment/us-liquidity-scanner-v2. Draft retained; no merge; no ready.chore: gitignore the isolated full-universe shadow runtime root(the new shadow root was outside the existingruntime/us_v2/ignore rule).Phase 8O — discovery-integrity & live-accounting closure
What changed (
us_v2/control_resolution.py,us_v2/cli_actions.py)DISCOVERY_BUDGET_CONTRACT_V1is now validated by exact equality, so an internally-consistent-but-mutated contract (e.g. ADR cap 24→25 / foreign 64→63 with the total held at 88 and digests recomputed) fails closed (resolution_budget_contract_immutability_mismatch).effective_discovery_budgets(+effective_discovery_budgets_digest); both new fields are bound into_resolution_digest. The validator checks the effective digest, increasing caps ending at the effective hard cap (never above the official cap), and that only the terminal override may be a non-official cap.candidate_probe_countshard cap / progressive caps / budget version must match the effective budget (resolution_budget_probe_{cap,progressive_caps,version}_mismatch);progressive_caps_seenis validated for membership / duplicates / ordering / magnitude (resolution_budget_progressive_caps_seen_{membership,duplicate,out_of_order,beyond_logical}).stop_reason(resolution_budget_flag_stop_reason_mismatch):quota_reached,budget_exhausted,pool_exhaustedand both-flags cases are mutually consistent by construction.[8,16,20], 10 →[8,10], 3 →[3], 32 →[8,16,32](the override is no longer silently dropped from the cap list).budget_exhausted(previously fell through toquota_reached).max(0, attempts-1)from a single authoritative attempt count, and zero-attempt rate-limited / circuit-rejected results stay at zero provider attempts (no forgedmax(1, attempts)). The resolution CLI probe now returns structured attempt/retry/rate/circuit results taken fromReliableProvider.call().ProviderReliabilityoutcomes before returning, so provider health on the failure path stays auditable.Validation
tests/us_v2/test_phase8o_discovery_integrity.py(27 tests): each of the fifteen gaps was proven by a test that failed against the Phase 8N head and passes after this closure; effective-budget artifact embedding + digest binding included. High-risk resolution/accounting tests re-run 20x with zero flakes.US_V2_OFFLINE_TEST=1on py3.11 (845.90s) and py3.12 (556.99s); Phase 8N/8I/8K/8M/8L/8G/8H and all Phase 9x/CLI/provider-reliability suites green;py_compileandgit diff --checkclean; runtime evidence gitignored/untracked.us_v2_cisuccess on headd332ff6for all four jobs (py3.11 + py3.12, two runs each, ~8m30s) — nothing cancelled/superseded.Status
d332ff6, basemain, pushed toexperiment/us-liquidity-scanner-v2. Draft retained; no merge; no ready.PHASE8O_DISCOVERY_INTEGRITY_CLOSURE_PUSHED_AWAITING_GITHUB_AUDIT.---## Phase 8N — category-specific progressive ADR/foreign discovery budgets
What changed
us_v2/control_resolution.py): the under-calibrated shared--max-probes 8default that caused Phase 9A attempt 3 to fail closed (need 2 have 1, probed 8 of pool 5306) is replaced bycontrol-discovery-budget-v1: ADR quota 3 / caps [8,16,24] / hard cap 24; foreign equity quota 2 / caps [8,16,32,64] / hard cap 64; total cap 88.CandidateProber.resolve): each category gets one deterministic tier-aware ordering (_tiered_ordered: tier 0 = already-hinted records first, tier 1 = ordinary common equity; priority only, never exclusion or auto-acceptance), probed once left-to-right. A candidate is never probed twice; progressive caps are checkpoints, not restarts; retries never count as new logical candidates; budget never bleeds between categories. Exact stop reasonsquota_reached/budget_exhausted/pool_exhaustedwith budget/pool flags.us_v2/cli_actions.py):--adr-max-probes(default 24) and--foreign-max-probes(default 64); deprecated shared--max-probesalias mapsmin(v,24)/min(v,64)and is rejected when combined with either category flag; overrides below quota, above the per-category contract cap, or above the 88 total are rejected. A fail-closed resolution now writes a privacy-safecontrol_resolution_failure_diagnostic.json(aggregates only — no symbols/names/countries/raw metadata)._validate_discovery_budget): re-verifies the bound contract digest, official quota/caps/total equality, strictly-increasing caps, final cap == hard cap, cap >= quota, and per-category logical/selected/attempt/retry/stop-reason/pool consistency; combined logical <= total cap. The budget fields are bound into_resolution_digest, and the operation snapshotlogical_request_countmust equal the summed category logical candidates.phase8n/discovery_budget_baseline.json) proves the failure was a budget-boundary artifact, not provider unavailability — foreign quota 2, pool 5306, probed 8, accepted 1, 7not_foreign_equity,pool_remaining_after_budget 5298. Offline reproduction (phase8n/attempt3_aggregate_reproduction.json) replays the identical head state and shows the new budget continues the same ordering past probe 8 (no claim about any fixed post-probe-8 position).Validation
tests/us_v2/test_phase8n_discovery_budget.py(32 tests): budget defaults/clamps/rejections, tiering reorders but never excludes, progressive success across caps, budget exhaustion, no-duplicate probes, category-local accounting, retry/logical separation, pool exhaustion, artifact embedding + digest binding, validator mutations, exact foreign acceptance rules (EQUITY + non-US + no ADR only).US_V2_OFFLINE_TEST=1(1227 baseline + 32); Phase 8N high-risk tests re-run 20x with zero flakes; targeted 199-test bundle green;compileallandgit diff --checkclean; all runtime evidence gitignored/untracked.us_v2_cisuccess on the current PR head (py3.11 + py3.12, re-run after the initial push-run was superseded/cancelled).Status
96475f5, basemain, pushed toexperiment/us-liquidity-scanner-v2. Draft retained; no merge; no ready.PHASE8N_DISCOVERY_BUDGET_CLOSURE_PUSHED_AWAITING_GITHUB_AUDIT.Phase 8M — corroborated compact unit/right evidence + real-chain re-root
What changed
us_v2/listing.py):enrich_cross_row_instrument_evidencenow also promotes a compactU- orR-ending canonical symbol to a high-confidencecorroborated_compact_unit/corroborated_compact_righthint when the same listing set contains a canonical common/class-share record for the base symbol, the name is anchored (Unit(s)/Right(s)with a bounded tail: period,expiring <date>,each consisting of,to receive,to purchase), the name carries no fund/ADR/ADS conflict markers, and the normalized issuer stem matches the base exactly or via a bounded prefix of enumerated class letters (a-e; plusTangible Equityfor units only). Same deterministic/idempotent/never-demote contract as 8L; weakname_keywordunit/right hints are never authorized.us_v2/listing.pyrederive_corroborated_warrant_evidence→ generalized,us_v2/control_listing.py_cross_row_evidence_errors): both validators independently rederive warrant/unit/right assignments from immutable source fields with stable codescontrol_listing_corroborated_{warrant,unit,right}_rule(should-carry but wrong/missing) and_drift(claims rule without corroborating base).us_v2/universe.py,us_v2/control_resolution.py):_STRONG_LISTING_RULES_BY_KINDandALLOWED_HINT_RULES_BY_CATEGORYnow authorize the corroborated compact rules for unit/right; staticcontrol_capacity_preflightcovers all four strong categories.runtime/us_v2/validation/stage5/evidence/frozen_phase9a_attempt2/and the evidence chain was regenerated from those records under current code via the offline CLI path — snapshote914d1cbb3a21877(self-authenticates), stock listing0d6b6cb62c23ccf5/ canonicalb67033f1000cad3e, ETF listing8df78650063f539a/ canonical4ddffc4a03c760e8;load_phase9_stock_listing_audit_v1ok and CLAvalid=true usable=true, both snapshot-bound. Decision recorded inphase8m/reroot_digest_scheme_decision.json.phase8m/unit_right_evidence_audit.json,phase8m/evidence_sufficiency_decision.json): capacity on the regenerated real chain = unit 104 (>= 3) viacorroborated_compact_unit(base_U only; base_UN/base_UT rejected), right 55 (>= 2) viacorroborated_compact_right(base_R only; base_RT rejected). Strong pools now preferred 381 / warrant 240 / unit 104 / right 55 — quota satisfied from real listing evidence alone.Validation
compileallclean,git diff --checkclean, all runtime evidence confirmed gitignored and untracked.us_v2_cisuccess on push run and PR run for new head (py3.11 + py3.12).Status
193fe69, basemain, pushed toexperiment/us-liquidity-scanner-v2. Draft retained; no merge.PHASE9A_NO_GOfail-closed.Phase 8L — corroborated compact-warrant evidence (warrant quota fix)
What changed
us_v2/listing.py):enrich_cross_row_instrument_evidence(wired intoingest_listing) promotes a compactW-ending canonical symbol (pure alphanumeric, e.g.AACIW) to a high-confidencecorroborated_compact_warrantwarrant hint only when the same listing set also contains a canonical common-equity or class-share record for the base symbol whose normalized issuer stem matches. Deterministic (plain symbol map, list-order visited), idempotent, never demotes an existing rule, and only upgrades weakname_keyword/defaultevidence. Never promotesWS/WT/delimited.Wforms (those staysymbol_suffix).us_v2/listing.py::rederive_corroborated_warrant_evidence): computes the expected corroborated assignment purely fromcanonical_symbol/raw_name/instrument_hint, never from the persistedinstrument_hint_rule, so validators check artifacts against a rederived expectation.us_v2/control_listing.py): bothvalidate_control_listing_audit_v1andvalidate_phase9_stock_listing_audit_v1call_corroborated_warrant_errors, which emits stable failure codescontrol_listing_corroborated_warrant_rule(should-carry but wrong/missing) andcontrol_listing_corroborated_warrant_drift(claims the rule without corroborating base evidence).us_v2/universe.py):_strong_listing_kindnow requires the hint rule to be explicitly authorized for the category (_STRONG_LISTING_RULES_BY_KIND: preferred→preferred_symbol, warrant→symbol_suffix+corroborated_compact_warrant, unit/right→symbol_suffix, class_share→class_share_slash, index→unsupported). Aname_keywordwarrant hint can never be strong listing evidence even if marked high-confidence.us_v2/control_resolution.py):STRONG_SYMBOL_RULESreplaced byALLOWED_HINT_RULES_BY_CATEGORY;_strong_candidatesonly accepts authorized rules per category;validate_resolved_controls_v1gained per-rowresolution_unauthorized_rule.us_v2/control_resolution.py,us_v2/cli_actions.py):control_capacity_preflight(called at the start ofresolve_controlsand by the CLI beforebuild_provider) computes the deterministic provider-free candidate pool per strong category and fails closed withControlResolutionErrorbefore any provider budget is spent when a category cannot reach its quota (ADR/foreign excluded — provider-backed).control_listing_audit.jsonshows all 296 warrant-hint records arename_keyword/low; 288 compact-W; fully corroborated capacity 240 (grammar 287 ok, base present 243, base common 241 / adr 2, issuer exact 111 / prefix 129). Rejections: 44 base absent, 2 ADR base, 1 issuer mismatch, 1 grammar. Audit cached atruntime/us_v2/validation/stage5/phase8l/warrant_evidence_audit.json(aggregate only, no symbols).corroborated_compact_warrantrecords (rule distributioncorroborated_compact_warrant: 240), warrant strong pool = 240, rederived expectation == actual corroborated set; the preflight fails closed on the frozen data for unit/right (static control-capacity shortfall: right need 2 have 0, unit need 3 have 0) because those remainname_keyword— only warrant is remediated and other strong sources are unchanged.Validation
tests/us_v2/test_phase8l_warrant_remediation.py(26 tests): corroboration predicate positives/negatives (anchored vs non-anchored names, base present/absent, class-share base, issuer prefix match, no base, ADR base, existing rule never demoted, existingname_keyworduntouched, delimitedWSuntouched, unknown base not promoted), validator rederivation (rule-must-carry, drift, tamper), classifier authorization (authorized rule accepted, unjustifiedname_keywordfails closed, unknown rule never strong), resolution category rules, and static control-capacity preflight (passes with full quota fixtures, rejects provider-backed paid categories).test_cli.py::test_build_universe_listing_evidence_from_manifestnow supplies the authorizedpreferred_symbolrule (the old test relied on a rule-less high-confidence hint being strong — exactly what 8L closes), andtest_control_verification.py::test_verdict_stays_provider_independentsuppliespreferred_symbolfor the strong-listing path (mirroring its siblingtest_final_classifier_conflict_surfaced).compileall,pip check-equivalent gates, India isolation manifest check, runtime isolation guard, andgit diff --checkall clean.us_v2_cisuccess on both the push run and the PR run for the new head (py3.11 + py3.12).Status
8eef47d, basemain, pushed toexperiment/us-liquidity-scanner-v2. Draft retained; no merge.PHASE9A_NO_GO); no live Phase 9 work has run against the private config.Phase 8K — source-producer closure (authorization chain complete)
What changed
us_v2/cli_actions.py,us_v2/provider_reliability.py):control-listing-auditnow fetches the ordinary stock screener AND the authoritative ETF/ETN/ETP screener through oneReliableProvider(single circuit breaker,--max-attempts/--rate-limit) and binds a single immutable source-operation snapshot (control_listing_provider_snapshot.json). Bothstock-listing-audit-v1andcontrol-listing-audit-v1bind that snapshot's digest. Fail-closed: a source failure or empty source writes no canonical artifact.us_v2/control_resolution.py,us_v2/cli_actions.py):resolve-controlspersistscontrol_resolution_provider_snapshot.json(attempt/retry/success/empty/rate-limited/circuit-breaker/terminal counts), binds its digest viafinalize_resolution_artifactafter the snapshot exists, then atomically writes + revalidates.CandidateProberrecords category-local accounting (logical_candidates_attempted,provider_attempt_count,retry_count,metadata_success_count,provider_unavailable_count,selected_count,rejections).us_v2/control_resolution.py):validate_resolved_controls_v1now takes the stock + control listing audits and the resolution operation snapshot and verifies source-digest equality (resolution_source_digest_mismatch), snapshot-digest binding (resolution_operation_snapshot_mismatch), source membership of every selected row (stock vs authoritative ETF section), and anchor collisions.us_v2/phase9_loaders.py):load_phase9_resolved_controls_v1requires the immutable control-listing audit, the resolution operation snapshot (operation_type=resolve-controls/operation_family=control_resolution), and the stock listing audit, then runs the full cross-source validation. Distinct error codes:phase9_operation_snapshot_missing/_invalid/_binding/phase9_resolution_invalid.load_phase9_control_report_v3checks verification snapshotoperation_type/operation_family/operation_ididentity.us_v2/control_verification_v3.py):validate_control_verification_report_v3reconciles the exact 30-symbol set across the manifestcontrol_symbols, the resolved basket, and the report rows (CONTROL_REPORT_ERROR_MISSING_CONTROL/CONTROL_REPORT_ERROR_COUNT).us_v2/cli_actions.py):sample_universewritestickers_500.json+sample_manifest.jsonandverify-controlswrites the verification report through_write_atomic_revalidated, re-validating on reload.tests/us_v2/conftest.py,.github/workflows/us_v2_ci.yml): autouse network guard blocks socket, requests, urllib and yfinance entrypoints whenUS_V2_OFFLINE_TEST=1; the hosted CI job is relabeled "Offline US-v2 tests" and sets the guard on the pytest step.Validation
US_V2_OFFLINE_TEST=1on hosted CI — py3.11 440s, py3.12 468s. Local guarded run 584s, unguarded 606s.tests/us_v2/test_phase8k_source_chain.py(18 tests): cross-source validation positives/negatives, loader fail-closed cases (missing/tampered/updated snapshot, drifted listing), 30-symbol report reconciliation, offline producer CLI E2E.test_phase8k_source_chain20x,test_phase8i_v3_chain20x,test_control_verification_v3_negatives20x, doctor suites 10x,test_phase9_stress10x — all green, zero flakes.pip check,compileall, pytest exit 0, India isolation manifest check, runtime isolation guard, whitespace/conflict-marker check. Localgit diff --checkclean.Status
8eef47d(Phase 8L on top), basemain, pushed toexperiment/us-liquidity-scanner-v2. Hosted CIus_v2_cisuccess on both the push run and the PR run for the new head.PHASE9A_NO_GO— see the Phase 9A section below). No live Phase 9 work has ever run; no runtime state or scan has run against the private config. Draft retained; no merge.Phase 8J — Phase 9 consumers migrated to the v3 chain (official-path hardening)
What changed
us_v2/phase9_loaders.py, new):load_phase9_manifest_v3,load_phase9_resolved_controls_v1,load_phase9_control_listing_v1, andload_phase9_control_report_v3— the single official path every Phase 9 consumer now routes through, with stablePHASE9_*error codes. The v3 report loader additionally binds the immutable provider-operation snapshot: it now fails closed onoperation_idmismatch (report vs on-disk snapshot) and onlogical_request_count != requested_control_count, so bounded retries can never inflate the logical control count.us_v2/control_verification_v3.py): added manifest-expectation cross-checks per control row (control_category,listing_source_kind,listing_hint+ confidence/rule/evidence,expected_security_type,expected_classification_outcome), nonempty binding checks for every sealed binding field (control_report_missing_binding), and a timezone-awaregenerated_atcheck (control_report_invalid_timestamp). Bothvalidate_control_verification_report_v3andevaluate_control_verification_report_v3enforce the new rules.us_v2/cli_actions.py):load_phase9_control_reportnow returnsmanifest/resolved_controlsin its result (populated on both the fail and success paths), and_control_report_digests/_phase9_live_values/ the strict doctor gate all consume the v3 digests only.test_phase8g_remediation.py,test_control_verification_cli_v2.py,test_phase8h_pre_live_gate.py,test_doctor_readiness.py(build_phase9_ready_runtimebinds a real reliability digest),test_phase8i_v3_chain.py(untrusted-control test no longer mutates expectations), andtest_cli.pycreate-plan case now use stage5-manifest-v3 / resolved-controls-v1 / control-verification-v3 with live digests.tests/us_v2/test_control_verification_v3_negatives.py, 34 tests): unknown statuses, incorrect top-level/trusted/all-trusted counts, all rederived count fields, edited row semantics with recomputed digests, manifest-expectation mismatch per field, duplicate/missing/extra rows, binding + timestamp negatives, and loader-leveloperation_id/logical_request_countbinding failures.Validation
compileall,git diff --check, no forbidden-path changes, no secrets staged.Status
ea93a38, pushed toexperiment/us-liquidity-scanner-v2.us_v2_cisuccess on both the push run and the PR run for the new head.Phase 8I — v3 control chain (production-aligned, tamper-evident)
What changed
us_v2/control_listing.py(control-listing-audit-v1, combined control-source digest, authoritative ETF/ETN/ETP hint rule),us_v2/control_oracle.py(trust matrix judging the reconciled production classification, not the coarse provider label),us_v2/control_resolution.py(resolved-controls-v1, exact-30 quota contract, bounded fail-closed ADR/foreign discovery), andus_v2/control_verification_v3.py(self-authenticatingcontrol-verification-v3report withvalidvs Phase 9ready).sample_stage5_universe_v4consumes the resolved controls as the authoritative cohort B;build_validation_manifest_v3/validate_validation_manifest_v3bind both listing sections, the combined control-source digest, the resolution digest, and re-derive every digest and the exact quota contract.control-listing-audit(with--stock-offline-file/--etf-offline-fileoffline repro) andresolve-controls, wired intocli.pyhelp, the command map, andstart_us_v2.sh.scan, plan-authorized dry run, persisted-scan preflight,create-scan-plan,validate-scan-plan, andexplain-runall consume the canonical Phase 9 validator / fail-closedload_phase9_control_report.Validation
test_phase8i_v3_chain.py(+ sharedphase8i_fixtures.py): oracle status matrix, listing digest determinism/sensitivity, resolution determinism/tamper/shortfall, sampler v4 cohorts and guards, manifest v3 validate/tamper, verification v3 build/validate/evaluate/digest self-authentication, offline CLI, and end-to-end chain readiness.pip check,compileall, pytest exit 0, India isolation manifest check, runtime isolation guard,git diff --check.Status
20b1dbd, 6 commits added on top of the Phase 8H baseline.Phase 8H — pre-live gate correction (merged toward Phase 9A)
What changed
us_v2/cli_actions.py):verify-controlsnow resolves the stage5 v2 manifest and runs the canonicalvalidate_validation_manifestbeforetelemetry().reset(), operation snapshot,build_provider, provider reliability load, and runtime evidence mutation. Stable failure codes:manifest_not_found,manifest_unreadable,manifest_not_object,manifest_invalid,manifest_ineligible,control_count_mismatch,control_membership_invalid. No absolute paths are printed; a failed gate creates no report, no operation snapshot, and no reliability file.us_v2/docs/runbook.md,us_v2/docs/stage5_phase8g_closure_report.md,--single-usehelp): the plan is reserved + consumed after canonical authorization and lock acquisition and before mutable persisted scan work; a preflight failure never consumes it, a dry run never consumes it, and once reservation succeeds a later scan failure does not restore or reuse the authorization. The earlier "consume after its first successful scan" wording is inaccurate and is removed.tests/us_v2/test_phase8h_pre_live_gate.py, 12 tests): invalid-but-eligible, duplicate-control, semantic/digest-error, missing-manifest, and ineligible manifests all fail beforebuild_provider(provider spy records zero calls, zero info fetches); no report/op-snapshot/reliability state is created on failure; corrected help wording is asserted; the valid-manifest path stays green (30/30 controls, report + snapshot + reliability persisted). Run 20 consecutive iterations green.Validation
pip check,compileall, pytest exit 0, India isolation manifest check (hashes unchanged), runtime isolation guard (no runtime/us_v2 files tracked), whitespace/conflict-marker check,set -eo pipefailthroughout.git diff --checkclean;india_isolation_manifest.py --checkOK.Status
49e782c, base61031603, 7 commits ahead of the Phase 8F baselinedb639dab.Phase 9A — live session 1 attempt (fail-closed, NOT completed)
Phase 9A was started per the operating plan and stopped at the live control-verification gate:
/tmp/us_v2_pre_phase9a_20260804_160958.tar.gz, sha256e08d0d17fc49de68e1c160d9f54740b5c2fda54ff3cc2df39c5c57f4f7080273).runtime/us_v2/private/phase9_config.json(mode 600,provider=yfinance,strict_error_accounting=true,require_benchmark=true, bounded retries + 2 rps pacing):validate-configOK, doctor--scope config6/6.listing_digest=a8822c46b61ade70,canonical_listing_digest=b442cebcb9e04f33.--profile stage5-500 --size 500 --seed 20260801produced byte-identicaltickers_500.jsonacross 3 runs (sha256fc0fb306…), manifeststage5-manifest-v2with 500 symbols (20 anchors / 30 controls / 450 random),validation_eligible=true,validate-sample-manifest= valid, listing digest verified.verify-controls(real provider): 11 verified, 19 untrusted — 11rejected_candidate, 8conflicting_evidence, 0provider_unavailable.all_controls_trusted=false,phase9_ready=false,report_valid=true,error_code=control_report_not_ready.provider_unavailablewith no rejections/conflicts and no edits. Rejected/conflicting controls are present and the control set may not be silently replaced, so no retry was taken.PHASE9A_NO_GO— fail-closed at Part 10. No universe build, no plan, no scan, no dry run ran. Evidence preserved underruntime/us_v2/validation/stage5/phase9/(all gitignored).runtime/us_v2.Next action requires an operator decision (control set redesign / new deterministic manifest) before any Phase 9A session can resume.