P3-DATA-ENGINE-002: Data Engine v1 implementation + qualification suite (QUALIFIED)
Implements the frozen P3_DATA_ENGINE_V1_SPEC (SHA 84bf0f217ffba51197112a6bbacbcc297058e04b5ca47f0459028fe33e0321e5).
Components: engine/ producer (certify, chunkmap, parse, canonical, worker,
dispatcher, aggregate, storage, journal, checkpoint, lock, evidence, manifest,
run_complete, dataset_builder, cli) + engine/verify independent verifier
(vparse, vaggregate, vinvariants, vcompare); headless CLI sniper-data; golden
corpus G01-G17; unit/property/adversarial/mutation/legacy-diff/CLI suites.
Qualification verdict: QUALIFIED (all 9 mandatory gates pass; independent
verifier accepted). Spec, governance record, and legacy checkpoint untouched.
G-14 NOT AUTHORIZED honored; no real-data processing, no pilot, no workload 46,
no chunk 760 access.
2026-09-07 14:15:25 +07:00 | | | """Persistent canonical storage (Layer 6).
|
| | |
|
| | | Parquet with zstd level 3 and pinned pyarrow writer (spec 12.1, determinism
|
| | | pins in spec 26). Physical Parquet bytes are integrity evidence only; the
|
| | | logical content-id contract lives in engine/canonical.py.
|
| | |
|
| | | Writer/reader version is pinned to pyarrow 25.0.0 (env check performed at
|
| | | import time).
|
| | | """
|
| | |
|
| | | import os
|
| | |
|
| | | import pyarrow as pa
|
| | | import pyarrow.parquet as pq
|
| | |
|
| | | from . import versions
|
| | |
|
| | | _PYARROW_PIN = versions.PYARROW_VERSION_PIN
|
| | | _PA_ACTUAL = pa.__version__
|
| | | if _PA_ACTUAL != _PYARROW_PIN:
|
| | | raise RuntimeError("pyarrow must be %s (pinned), found %s"
|
| | | % (_PYARROW_PIN, _PA_ACTUAL))
|
| | |
|
| | | TICK_SCHEMA = pa.schema([
|
| | | ("ts_ms", pa.int64()),
|
| | | ("bid_u", pa.int64()),
|
| | | ("ask_u", pa.int64()),
|
| | | ("spread_u", pa.int64()),
|
| | | ("vol", pa.int64()),
|
| | | ("src_line", pa.int64()),
|
| | | ("rec_ord", pa.int64()),
|
| | | ])
|
| | |
|
| | | BAR_SCHEMA = pa.schema([
|
| | | ("bar_idx", pa.int64()),
|
| | | ("period_id", pa.int64()),
|
| | | ("start_ms", pa.int64()),
|
| | | ("end_ms", pa.int64()),
|
| | | ("open_u2", pa.int64()),
|
| | | ("high_u2", pa.int64()),
|
| | | ("low_u2", pa.int64()),
|
| | | ("close_u2", pa.int64()),
|
| | | ("tick_count", pa.int64()),
|
| | | ("vol_sum", pa.int64()),
|
| | | ("spread_min_u", pa.int64()),
|
| | | ("spread_max_u", pa.int64()),
|
| | | ("spread_sum_u", pa.int64()),
|
| | | ("spread_avg_u", pa.int64()),
|
| | | ("is_final", pa.bool_()),
|
| | | ("first_src_line", pa.int64()),
|
| | | ("last_src_line", pa.int64()),
|
| | | ])
|
| | |
|
| | | TICK_FIELDS = [f.name for f in TICK_SCHEMA]
|
| | | BAR_FIELDS = [f.name for f in BAR_SCHEMA]
|
| | |
|
| | | # Canonical directory layout (spec 12.2)
|
| | | def cert_path(out_root):
|
| | | return os.path.join(out_root, "certification", "source_certificate.json")
|
| | |
|
| | |
|
| | | def chunkmap_path(out_root, source_id):
|
| | | return os.path.join(out_root, "chunkmap", "chunkmap-%s.json" % source_id)
|
| | |
|
| | |
|
| | | def ticks_chunk_path(out_root, index):
|
| | | return os.path.join(out_root, "ticks", "chunk_%06d.parquet" % index)
|
| | |
|
| | |
|
| | | def ticks_staging_path(out_root, index):
|
| | | return os.path.join(out_root, "staging", "chunk_%06d.parquet.tmp" % index)
|
| | |
|
| | |
|
 P3-DATA-ENGINE-004: source-grammar correction + re-qualification (QUALIFIED) - spec 1.1.0 controlled amendment (Appendix C): G_TICKSTORY_MT5 six-col YYYYMMDD,HH:MM:SS,bid,ask,last,volume; compact timestamp; mandatory volume; last preserved via source-preservation sidecar (spec 8.6; CTS_V1 unchanged; G-4/G-5 intact); SHA effbaf2624cd46137c22a246fdabff4067052807b6b6224be464366bec4745d9 (machine-verified) - implementation: grammar registry, source_grammar config identity + fail-closed validation, compact timestamp parse, _parse_chunk_tickstory, preservation serialization + sidecars, certificate grammar_id + compact sniffing, init cert/config mismatch BLOCK, independent verifier v_parse_chunk_tickstory + preservation ids, evidence + verify_dataset preservation checks; ENGINE_VERSION 1.1.0, PARSER_V1.1 - CLI defect repair: status/resume on run-less dir exit 4 BLOCKED without traceback (P3-DE-003 NEW_ENGINE_DEFECT) + regression tests - qualification: unit, golden G01-G17, SG01-SG15 + e2e, property, adversarial, mutation 8/8, independent verifier dataset+run-complete ACCEPTED, legacy diff 0 unresolved legacy untouched, dataset-builder determinism, CLI E2E; VERDICT QUALIFIED - G-14 unchanged BLOCKED/NOT AUTHORIZED; no real-data ingestion; no workload 46; no chunk 760+; legacy checkpoint 759/18442355762 untouched
2026-09-07 17:34:57 +07:00 | | | def preservation_chunk_path(out_root, index):
|
| | | """Source-preservation sidecar for the G_TICKSTORY_MT5 ``last`` column
|
| | | (P3-DE-004 spec 8.6); dotted-grammar runs produce no sidecars."""
|
| | | return os.path.join(out_root, "source_preservation",
|
| | | "chunk_%06d.jsonl" % index)
|
| | |
|
| | |
|
| | |
|
P3-DATA-ENGINE-002: Data Engine v1 implementation + qualification suite (QUALIFIED)
Implements the frozen P3_DATA_ENGINE_V1_SPEC (SHA 84bf0f217ffba51197112a6bbacbcc297058e04b5ca47f0459028fe33e0321e5).
Components: engine/ producer (certify, chunkmap, parse, canonical, worker,
dispatcher, aggregate, storage, journal, checkpoint, lock, evidence, manifest,
run_complete, dataset_builder, cli) + engine/verify independent verifier
(vparse, vaggregate, vinvariants, vcompare); headless CLI sniper-data; golden
corpus G01-G17; unit/property/adversarial/mutation/legacy-diff/CLI suites.
Qualification verdict: QUALIFIED (all 9 mandatory gates pass; independent
verifier accepted). Spec, governance record, and legacy checkpoint untouched.
G-14 NOT AUTHORIZED honored; no real-data processing, no pilot, no workload 46,
no chunk 760 access.
2026-09-07 14:15:25 +07:00 | | | def malformed_chunk_path(out_root, index):
|
| | | return os.path.join(out_root, "malformed", "malformed_%06d.jsonl" % index)
|
| | |
|
| | |
|
| | | def bar_part_path(out_root, timeframe, workload_index):
|
| | | return os.path.join(out_root, "bars", timeframe,
|
| | | "wl_%03d.parquet" % workload_index)
|
| | |
|
| | |
|
| | | def bar_dir(out_root, timeframe):
|
| | | return os.path.join(out_root, "bars", timeframe)
|
| | |
|
| | |
|
| | | def state_dir(out_root):
|
| | | return os.path.join(out_root, "state")
|
| | |
|
| | |
|
| | | def checkpoint_path(out_root):
|
| | | return os.path.join(out_root, "state", "checkpoint.json")
|
| | |
|
| | |
|
| | | def journal_path(out_root):
|
| | | return os.path.join(out_root, "state", "commits.jsonl")
|
| | |
|
| | |
|
| | | def lock_path(out_root):
|
| | | return os.path.join(out_root, "state", "lock")
|
| | |
|
| | |
|
| | | def control_path(out_root):
|
| | | return os.path.join(out_root, "state", "control.json")
|
| | |
|
| | |
|
| | | def progress_path(out_root):
|
| | | return os.path.join(out_root, "progress.json")
|
| | |
|
| | |
|
| | | def evidence_path(out_root):
|
| | | return os.path.join(out_root, "evidence", "evidence.json")
|
| | |
|
| | |
|
| | | def run_complete_path(out_root):
|
| | | return os.path.join(out_root, "RUN_COMPLETE.json")
|
| | |
|
| | |
|
| | | def datasets_dir(out_root):
|
| | | return os.path.join(out_root, "datasets")
|
| | |
|
| | |
|
| | | def verify_dir(out_root):
|
| | | return os.path.join(out_root, "verification")
|
| | |
|
| | |
|
| | | def logs_dir(out_root):
|
| | | return os.path.join(out_root, "logs")
|
| | |
|
| | |
|
| | | def _with_meta(schema, meta):
|
| | | md = dict(schema.metadata) if schema.metadata else {}
|
| | | md.update({k.encode(): str(v).encode() for k, v in meta.items()})
|
| | | return schema.with_metadata(md)
|
| | |
|
| | |
|
| | | def _tick_meta(cfg, source_id, chunk_index):
|
| | | return {
|
| | | "schema_version": versions.SCHEMA_TICKS,
|
| | | "engine_version": versions.ENGINE_VERSION,
|
| | | "parser_version": versions.PARSER_VERSION,
|
| | | "algorithm_version": versions.ALGORITHM_VERSION,
|
| | | "source_id": source_id,
|
| | | "chunk_index": str(chunk_index),
|
| | | "price_scale": str(versions.PRICE_SCALE),
|
| | | "pyarrow_version": str(_PA_ACTUAL),
|
| | | }
|
| | |
|
| | |
|
| | | def _bar_meta(cfg, timeframe, workload_index):
|
| | | return {
|
| | | "schema_version": versions.SCHEMA_BARS,
|
| | | "engine_version": versions.ENGINE_VERSION,
|
| | | "parser_version": versions.PARSER_VERSION,
|
| | | "algorithm_version": versions.ALGORITHM_VERSION,
|
| | | "timeframe": timeframe,
|
| | | "price_scale_bar": str(versions.PRICE_SCALE_BAR),
|
| | | "pyarrow_version": str(_PA_ACTUAL),
|
| | | }
|
| | |
|
| | |
|
| | | def write_ticks_chunk(path, records, cfg, source_id, chunk_index):
|
| | | """Write canonical tick records (7-tuples in CTS_V1 order) to parquet."""
|
| | | arrays = [pa.array([r[i] for r in records], pa.int64()) for i in range(len(TICK_FIELDS))]
|
| | | table = pa.Table.from_arrays(arrays, schema=TICK_SCHEMA)
|
| | | table = table.replace_schema_metadata(_tick_meta(cfg, source_id, chunk_index))
|
| | | pq.write_table(table, path, compression="zstd", compression_level=3)
|
| | | return len(records)
|
| | |
|
| | |
|
| | | def read_ticks_chunk(path):
|
| | | """Read canonical tick parquet into a list of 7-tuples in row order."""
|
| | | table = pq.read_table(path, columns=TICK_SCHEMA.names)
|
| | | cols = [table.column(i).to_pylist() for i in range(len(TICK_FIELDS))]
|
| | | rows = [tuple(c[i] for c in cols) for i in range(len(cols[0]))]
|
| | | return rows
|
| | |
|
| | |
|
| | | def write_bar_part(path, rows, timeframe, workload_index, cfg):
|
| | | """Write CBS_V1 bar rows (tuples in BAR_SCHEMA order)."""
|
| | | n = len(BAR_FIELDS)
|
| | | arrays = []
|
| | | for i, f in enumerate(BAR_SCHEMA):
|
| | | if f.type == pa.bool_():
|
| | | arrays.append(pa.array([r[i] for r in rows], pa.bool_()))
|
| | | else:
|
| | | arrays.append(pa.array([r[i] for r in rows], pa.int64()))
|
| | | table = pa.Table.from_arrays(arrays, schema=BAR_SCHEMA)
|
| | | table = table.replace_schema_metadata(_bar_meta(cfg, timeframe, workload_index))
|
| | | pq.write_table(table, path, compression="zstd", compression_level=3)
|
| | | return len(rows)
|
| | |
|
| | |
|
| | | def read_bar_part(path):
|
| | | table = pq.read_table(path, columns=BAR_SCHEMA.names)
|
| | | cols = [table.column(i).to_pylist() for i in range(len(BAR_FIELDS))]
|
| | | rows = [tuple(c[i] for c in cols) for i in range(len(cols[0]))]
|
| | | return rows
|