Skip to content

[truealpha-datahub] Accept ephemeral capture persistence - #193

Merged
wangzitian0 merged 3 commits into
mainfrom
batch/d3-e2-persistence
Jul 14, 2026
Merged

[truealpha-datahub] Accept ephemeral capture persistence#193
wangzitian0 merged 3 commits into
mainfrom
batch/d3-e2-persistence

Conversation

@wangzitian0

Copy link
Copy Markdown
Owner

Summary

  • freeze a real one-cell D3 capture scope before the E1 HTTP interaction and bind the Yahoo source/normalizer registry identities
  • persist every retained response through the S3-compatible raw store and raw.fetches before writing the generic normalized record
  • persist replayable registry, scope, manifest, and evaluation contracts through the append-only Postgres repositories
  • make later identical-byte retries reuse the first raw clock and produce zero new normalized/manifest rows; changed bytes append a raw vintage and explicit normalized restatement
  • accept only D3 E2 and advance the canonical target to E3 full-denominator coverage

Acceptance evidence

  • targeted D3 E2 integration suite: 10 passed against a fresh migrated PostgreSQL database and configured S3-compatible store
  • full make check on another fresh database: 709 passed, 4 skipped
  • Ruff, formatting, mypy (93 source files), web typecheck, contract conformance, offline governance, live GitHub parity, and PR authorization passed
  • exact base 3b18ac4585c4f5183bac376b5a105f0760df06ba

Claim ceiling

This accepts ephemeral Local/CI persistence for one frozen NVDA market-price cell. It does not claim the 20-issuer/21-instrument/84-cell denominator, a live Staging run, scheduling, Production access, or release activation.

Advances #171.

Copilot AI review requested due to automatic review settings July 14, 2026 13:24
@wangzitian0
wangzitian0 merged commit b85c1fc into main Jul 14, 2026
8 checks passed

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR advances the D3 Staging TOPT capture batch from E2→E3 by introducing an E2 persistence slice that lands raw Yahoo responses into the S3-compatible raw store and raw.fetches, then appends normalized market-price rows and persists replayable registry/scope/manifest/evaluation contracts into Postgres.

Changes:

  • Advance D3 batch governance metadata to reflect E2 acceptance and target E3.
  • Add staging_topt_capture D3 E2 persistence implementation (persist_e1_execution) for raw + normalized + contract persistence with idempotent identical-byte retries and restatement-on-changed-bytes behavior.
  • Add an integration test suite validating E2 idempotence, append-only enforcement, retry landing, restatement semantics, and S3 round-trip.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 4 comments.

File Description
governance/vision-issue-graph.json Advances the D3 batch target rung to E3 and updates the manifest hash pointer.
governance/batches/D3-staging-topt-capture.v1.json Updates batch revision/acceptance metadata for the E2 slice and pins the base SHA.
apps/data-engine/src/data_engine/batches/staging_topt_capture/e2_slice.py Implements D3 E2 persistence for raw bytes, normalized records, and replayable capture contracts.
apps/data-engine/tests/batches/staging_topt_capture/test_e2_slice.py Adds integration coverage for E2 persistence semantics (idempotence, append-only, restatements, S3 round-trip).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +123 to +124
adapter_id="d3:YahooRawHttpAdapter",
adapter_version=VERSION,
Comment on lines +230 to +236
if (
result.source_id != context.source_entry.source_id
or result.source_version != context.source_entry.version
or response.sha256 != result.normalized_bar.raw_response_sha256
):
raise ValueError("E1 result does not bind the E2 source or raw bytes")

Comment on lines +345 to +349
evidence = CaptureRecordEvidence(
source_coverage_entry_id=SOURCE_COVERAGE_ENTRY_ID,
raw_id=f"raw.object:{record.raw_object_sha256}",
raw_sha256=record.raw_object_sha256,
normalized_id=record.normalized_record_id,
Comment on lines +428 to +469
def persist_e1_execution(
connection: Connection[Any],
raw_store: RawObjectStore,
execution: D3E1TinyExecution,
context: D3E2CaptureContext,
*,
predecessor: NormalizedRecordRef | None = None,
) -> D3E2PersistenceResult:
"""Persist one accepted E1 execution through immutable E2 stores."""

if not execution.landed_raw_responses:
raise ValueError("D3 E2 requires retained E1 raw bytes")
_verify_execution_binding(execution, context)
raw_fetch_ids: list[int] = []
final_landing = execution.landed_raw_responses[-1]
for landed in execution.landed_raw_responses:
response = landed.response
source_record_suffix = "result" if landed is final_landing else f"attempt:{response.attempt_number}"
fetch_id = insert_fetch(
connection,
source=DataSource.YAHOO,
source_record_id=f"{response.call_plan_id}:{source_record_suffix}",
body=response.body,
content_type=response.content_type or "application/octet-stream",
fetched_at=response.fetched_at,
metadata={
"source_id": response.source_id,
"source_version": response.source_version,
"adapter_id": response.adapter_id,
"adapter_version": response.adapter_version,
"call_plan_id": response.call_plan_id,
"configuration_sha256": response.configuration_sha256,
"attempt_number": response.attempt_number,
"landing_id": landed.landing_id,
"e1_interaction_id": execution.result.interaction_id,
},
store=raw_store,
recorded_at=response.fetched_at + timedelta(seconds=2),
)
if get_payload(connection, fetch_id, store=raw_store) != response.body:
raise ValueError("persisted raw bytes failed checksum-verified readback")
raw_fetch_ids.append(fetch_id)
@wangzitian0
wangzitian0 deleted the batch/d3-e2-persistence branch July 15, 2026 03:52
@wangzitian0 wangzitian0 changed the title [truealpha-data] [D3:E2] Accept ephemeral capture persistence [truealpha-datahub] Accept ephemeral capture persistence Jul 15, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants