Merge pull request #188 from ArtemFilin1990/feature/everest-stage3-oem-engineering-20261021

EVEREST stage 3: wire official OEM codebook to analogue gate, add isolated PostgreSQL smoke
This commit is contained in:
Artem Filin authored and GitHub committed 2026-10-21 06:17:53 -07:00
commit c013435b45
9 files changed
+354

No files matched your search

@@ -0,0 +1,46 @@
name: EVEREST engineering core Postgres integration
on:
push:
branches:
- 'feature/everest-stage3-oem-engineering-20261021'
pull_request:
paths:
- 'sql/engineering_core/**'
- 'src/oem_evidence_bridge.py'
- 'src/engineering_core.py'
- 'src/verified_designation_dictionary.py'
permissions:
contents: read
jobs:
test-postgres-migration:
runs-on: ubuntu-latest
services:
postgres:
image: postgres:16
env:
POSTGRES_USER: tester
POSTGRES_PASSWORD: ci_password
POSTGRES_DB: everest_bearings_ci
ports:
- 5432:5432
options: >-
--health-cmd "pg_isready -U tester -d everest_bearings_ci"
--health-interval 5s
--health-timeout 5s
--health-retries 10
env:
PGHOST: localhost
PGPORT: 5432
PGUSER: tester
PGPASSWORD: ci_password
PGDATABASE: everest_bearings_ci
steps:
- uses: actions/checkout@v4
- name: Apply engineering schema to ephemeral PostgreSQL
run: psql -X -v ON_ERROR_STOP=1 -f sql/engineering_core/001_engineering_core_postgres.sql
- name: Run rollback-only SQL assertions
run: psql -X -v ON_ERROR_STOP=1 -f sql/engineering_core/tests/smoke.sql
- name: Verify Python gate and OEM bridge
run: |
python -m pip install pytest
PYTHONPATH=. python -m pytest -q tests/test_engineering_core.py tests/test_verified_dictionary.py tests/test_oem_evidence_bridge.py tests/test_bearing_dimension_roles.py
@@ -0,0 +1,2 @@
gost_designation,iso_assembly,bearing_code,adapter_code,assembly_kind,bearing_bore_d_mm,shaft_seat_d1_mm,outside_D_mm,bearing_width_B_mm,product_compatibility,source_bearing,source_assembly,note
11215,1217K+H217,1217K,H217,BEARING_WITH_ADAPTER,85,75,150,28,CANDIDATE_ONLY,https://skf-us-cad-download.skf.com/item/self-aligning-ball/aligning-ball-bearings-with-tapered-bore-1/1217k,https://www.irbis.ua/catalog/product/11215-1217kh217-sh00004877,"Bearing bore 85 is NOT the sleeve's shaft-seat 75; B=28 is bearing width, not mounted overall assembly width. No approved substitution."
1 gost_designation iso_assembly bearing_code adapter_code assembly_kind bearing_bore_d_mm shaft_seat_d1_mm outside_D_mm bearing_width_B_mm product_compatibility source_bearing source_assembly note
2 11215 1217K+H217 1217K H217 BEARING_WITH_ADAPTER 85 75 150 28 CANDIDATE_ONLY https://skf-us-cad-download.skf.com/item/self-aligning-ball/aligning-ball-bearings-with-tapered-bore-1/1217k https://www.irbis.ua/catalog/product/11215-1217kh217-sh00004877 Bearing bore 85 is NOT the sleeve's shaft-seat 75; B=28 is bearing width, not mounted overall assembly width. No approved substitution.
@@ -0,0 +1,22 @@
# One-shot PostgreSQL migration test in an ephemeral Docker build layer.
# No database credentials or product data, nothing persists to runtime.
FROM postgres:16-alpine AS verify
WORKDIR /opt/everest-smoke
COPY --chown=postgres:postgres sql/engineering_core/001_engineering_core_postgres.sql ./migration.sql
COPY --chown=postgres:postgres sql/engineering_core/tests/smoke.sql ./smoke.sql
USER postgres
RUN set -eu; \
initdb -D /tmp/everest-pg16 --username=postgres --auth-local=trust >/dev/null; \
pg_ctl -D /tmp/everest-pg16 -o "-c listen_addresses=''" -w start; \
createdb -U postgres everest_bearings_ci; \
psql -X -v ON_ERROR_STOP=1 -U postgres -d everest_bearings_ci -f migration.sql; \
psql -X -v ON_ERROR_STOP=1 -U postgres -d everest_bearings_ci -f smoke.sql; \
pg_ctl -D /tmp/everest-pg16 -m fast -w stop; \
mkdir -p /tmp/everest-smoke-status; \
printf '%s\n' 'EVEREST PostgreSQL 16 migration smoke: PASSED' > /tmp/everest-smoke-status/index.html; \
rm -rf /tmp/everest-pg16
FROM python:3.13-alpine
COPY --from=verify /tmp/everest-smoke-status /status
USER 10001
EXPOSE 10000
CMD ["python", "-m", "http.server", "10000", "--bind", "0.0.0.0", "--directory", "/status"]
+28
View File
@@ -0,0 +1,28 @@
# EVEREST — external source governance (21 October 2026)
1. Primary manufacturer catalogues: SKF Product Select, NTN Bearing Finder, NSK online catalogue, Timken Engineering. Verify *exact* OEM SKU, publication edition and product feature before granting attribute provenance `CATALOG_VERIFIED`.
2. Secondary cross-references: IRBIS, Podshipnik.info, 2rs.com.ua, Podshipnikon.ru, Planeta Podshipnik, BearingWorks. Search candidates only. A listing of GOST=ISO is NOT an approved analogue.
3. Further candidates for source review: KOYO/JTEKT, AST, RBC, Kugellager Express, Sacom.lt, GlobalSpec, Size.name, Technodrive.pro, Universal Bearings. Recheck official domain, product coverage, copyright, terms and robots rules before any automated import.
4. Reject numeric zero dimensions, ambiguous width concept B/T/C/H, inferred tolerance equivalence and unsupported manufacturer suffixes. Keep the original supplier designation and source.
5. Every accepted attribute requires a source ID, document version, date, SKU and source location. Unknown or conflicting attributes block auto-replacement.
6. `IDT/MOD/NEQ` is a relationship of standard *editions*, not products.
7. Only a reviewed `analogue_decision` with immutable passport evidence and valid application scope can authorize a substitute.
Verified public landing pages:
- https://productselect.skf.com/
- https://bearingfinder.ntnamericas.com/
- https://www.nsk.com/catalogs-and-cad/
- https://engineering.timken.com/engineering-tool/bearing-search/
- https://www.rbcbearings.com/Catalogs-Industrial
- https://www.irbis.ua/ru/production/podshipniki-optom/razmery-podshipnikov
- https://podshipnik.info/catalog
- https://2rs.com.ua/ru/select-bearings/
- https://podshipnikon.ru/razmeri-podshipnikov
- https://planetapodshipnik.ru/news/post/tablica-markirovki-podshipnikov-iso-i-gost
- https://www.bearingworks.com/bearing-sizes/
Batch proof: 4,583 source rows; 874 matching dictionary brand tokens; 141 fully recognized suffix sequences; 4,583 auto-replacements denied because documented scoped approvals were absent. Locally validated with 42 pytest tests; no approval of product pairs.
## Обнаруженный конфликт данных (не импортировать автоматически)
`6208`: BearingWorks показывает B=15 мм в таблице серии 6200, тогда как официальная карточка NSK `6208` указывает B=18 мм при d=40 мм, D=80 мм. Вторичный источник — https://www.bearingworks.com/bearing-sizes/ ; первичный — https://www.nsk.com/engineering/products/bearings/ball-bearings/deep-groove-ball-bearings/single-row-deep-groove-ball-bearings/6208-apn.html . Занести в реестр ошибок источников, не копировать размеры из противоречащей таблицы.
+80
View File
@@ -0,0 +1,80 @@
\set ON_ERROR_STOP on
-- Run only against a disposable PostgreSQL database.
DO $$ BEGIN
IF current_database() <> 'everest_bearings_ci' THEN
RAISE EXCEPTION 'Refusing smoke outside everest_bearings_ci';
END IF;
END $$;
BEGIN;
DO $$ DECLARE n integer; BEGIN
SELECT count(*) INTO n FROM information_schema.tables WHERE table_schema = 'everest_engineering';
IF n <> 10 THEN RAISE EXCEPTION 'Expected ten engineering tables, found %', n; END IF;
IF EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema='everest_engineering' AND column_name='is_direct_analog') THEN
RAISE EXCEPTION 'Legacy unsafe is_direct_analog field leaked to engineering schema';
END IF;
END $$;
INSERT INTO everest_engineering.source_documents(id,document_type,publisher,title,source_version)
VALUES('smoke-doc','OTHER','Test suite','Ephemeral verification','1');
INSERT INTO everest_engineering.bearing_products
(id,original_raw_designation,brand,standard_system,basic_designation,attribute_profile,origin_document_id)
VALUES ('smoke-a','6205','SKF','ISO','6205','RADIAL_BALL_V1','smoke-doc'),
('smoke-b','6305','SKF','ISO','6305','RADIAL_BALL_V1','smoke-doc');
INSERT INTO everest_engineering.bearing_equivalences
(id,source_bearing_id,candidate_bearing_id,discovery_source_id,candidate_basis)
VALUES ('smoke-pair','smoke-a','smoke-b','smoke-doc','DIMENSIONS');
INSERT INTO everest_engineering.attribute_provenance
(bearing_id,attribute_name,origin,canonical_value)
VALUES ('smoke-a','clearance','UNKNOWN',NULL);
-- Expected-failure tests must assert a CHECK error actually occurred.
DO $$ DECLARE rejected boolean := FALSE; BEGIN
BEGIN
INSERT INTO everest_engineering.attribute_provenance
(bearing_id,attribute_name,origin,canonical_value)
VALUES ('smoke-a','precision','EXPLICIT','NORMAL');
EXCEPTION WHEN check_violation THEN rejected := TRUE;
END;
IF NOT rejected THEN RAISE EXCEPTION 'BUG: Explicit provenance without source was accepted'; END IF;
END $$;
DO $$ DECLARE rejected boolean := FALSE; BEGIN
BEGIN
INSERT INTO everest_engineering.analogue_decisions
(id,equivalence_id,status,approved_by,approval_date,valid_until,justification,
restrictions,evidence_source_id,source_snapshot_digest,candidate_snapshot_digest)
VALUES ('smoke-unsafe','smoke-pair','CONDITIONAL','engineer',date '2026-10-21',
date '2027-01-01','unscoped','["limit"]'::jsonb,'smoke-doc',repeat('a',64),repeat('b',64));
EXCEPTION WHEN check_violation THEN rejected := TRUE;
END;
IF NOT rejected THEN RAISE EXCEPTION 'BUG: CONDITIONAL without scope was accepted'; END IF;
END $$;
INSERT INTO everest_engineering.analogue_decisions(id,equivalence_id,status)
VALUES ('smoke-dimensional','smoke-pair','DIMENSIONAL');
INSERT INTO everest_engineering.decision_audit(decision_id,operation,actor,allowed,reason_codes)
VALUES ('smoke-dimensional','DENIED','smoke-suite',FALSE,'["NO_APPROVED_DECISION"]'::jsonb);
DO $$ DECLARE rejected boolean := FALSE; msg text; BEGIN
BEGIN
UPDATE everest_engineering.decision_audit SET allowed=TRUE WHERE actor='smoke-suite';
EXCEPTION WHEN raise_exception THEN
GET STACKED DIAGNOSTICS msg = MESSAGE_TEXT;
IF msg NOT LIKE 'Append-only%' THEN RAISE; END IF;
rejected := TRUE;
END;
IF NOT rejected THEN RAISE EXCEPTION 'BUG: audit UPDATE was accepted'; END IF;
IF (SELECT allowed FROM everest_engineering.decision_audit WHERE actor='smoke-suite') THEN
RAISE EXCEPTION 'BUG: audit row was modified'; END IF;
END $$;
DO $$ DECLARE rejected boolean := FALSE; msg text; BEGIN
BEGIN
DELETE FROM everest_engineering.analogue_decisions WHERE id='smoke-dimensional';
EXCEPTION WHEN raise_exception THEN
GET STACKED DIAGNOSTICS msg = MESSAGE_TEXT;
IF msg NOT LIKE 'Append-only%' THEN RAISE; END IF;
rejected := TRUE;
END;
IF NOT rejected THEN RAISE EXCEPTION 'BUG: decision DELETE was accepted'; END IF;
END $$;
ROLLBACK;
SELECT 'PASS: temporary PostgreSQL 16 engineering migration + fail-closed checks' AS result;
+69
View File
@@ -0,0 +1,69 @@
"""Explicit dimensional roles for bearings and mounted adapter assemblies.
Does not infer sizes or substitution rights from a designation string.
"""
from __future__ import annotations
from dataclasses import dataclass
from decimal import Decimal
from typing import Literal
AssemblyKind = Literal["SINGLE_BEARING", "BEARING_WITH_ADAPTER"]
@dataclass(frozen=True)
class BearingGeometry:
designation: str
assembly_kind: AssemblyKind
bearing_bore_d_mm: Decimal | None
outside_d_mm: Decimal | None
bearing_width_b_mm: Decimal | None
shaft_seat_d1_mm: Decimal | None
sleeve_designation: str | None
bearing_source_url: str | None
sleeve_source_url: str | None
def evidence_problems(self) -> tuple[str, ...]:
issues: list[str] = []
if any(value is not None and value <= 0 for value in
(self.bearing_bore_d_mm, self.outside_d_mm, self.bearing_width_b_mm,
self.shaft_seat_d1_mm)):
issues.append("NONPOSITIVE_DIMENSIONS")
if self.bearing_bore_d_mm is not None and self.outside_d_mm is not None and self.bearing_bore_d_mm >= self.outside_d_mm:
issues.append("INVALID_BEARING_BORE_GEOMETRY")
if self.assembly_kind == "BEARING_WITH_ADAPTER":
if not self.sleeve_designation or self.shaft_seat_d1_mm is None:
issues.append("ADAPTER_OR_SHAFT_SEAT_MISSING")
if self.bearing_bore_d_mm == self.shaft_seat_d1_mm:
issues.append("ADAPTER_ROLE_AMBIGUITY")
if not self.bearing_source_url or not self.sleeve_source_url:
issues.append("MISSING_COMPONENT_PROVENANCE")
elif self.sleeve_designation is not None:
issues.append("SLEEVE_WITHOUT_ASSEMBLY")
return tuple(issues)
def ddb_for_single_bearing(self) -> tuple[Decimal, Decimal, Decimal] | None:
"""No unqualified d/D/B entry for an adapter-bearing set."""
if self.assembly_kind != "SINGLE_BEARING" or self.evidence_problems():
return None
if any(x is None for x in (self.bearing_bore_d_mm, self.outside_d_mm, self.bearing_width_b_mm)):
return None
return self.bearing_bore_d_mm, self.outside_d_mm, self.bearing_width_b_mm
def compare_geometry(left: BearingGeometry, right: BearingGeometry) -> tuple[str, ...]:
"""Identify dimensional incompatibility, never grant analogue status."""
issues = list(left.evidence_problems()) + list(right.evidence_problems())
if left.assembly_kind != right.assembly_kind:
issues.append("SINGLE_VS_ASSEMBLY")
for field in ("bearing_bore_d_mm", "outside_d_mm", "bearing_width_b_mm"):
a, b = getattr(left, field), getattr(right, field)
if a is None or b is None:
issues.append(f"UNKNOWN:{field}")
elif a != b:
issues.append(f"DIFFERENT:{field}")
if left.assembly_kind == right.assembly_kind == "BEARING_WITH_ADAPTER":
if left.shaft_seat_d1_mm is None or right.shaft_seat_d1_mm is None:
issues.append("UNKNOWN:shaft_seat_d1_mm")
elif left.shaft_seat_d1_mm != right.shaft_seat_d1_mm:
issues.append("DIFFERENT:shaft_seat_d1_mm")
if left.sleeve_designation != right.sleeve_designation:
issues.append("DIFFERENT:adapter_sleeve")
return tuple(dict.fromkeys(issues))
+49
View File
@@ -0,0 +1,49 @@
"""Manufacturer code meaning is not per-SKU evidence or an analogue approval."""
from __future__ import annotations
from dataclasses import dataclass
from src.engineering_core import (
ApplicationContext,
AnalogueDecision,
BearingPassport,
GateResult,
evaluate_autoreplace,
)
from src.verified_designation_dictionary import VerifiedCodebook
@dataclass(frozen=True)
class CodeObservation:
code: str
brand: str
feature: str
contact_type: str
source_url: str
status: str = "OFFICIAL_CODE_ONLY"
@dataclass(frozen=True)
class InspectionResult:
observations: tuple[CodeObservation, ...]
unknown_suffix_parts: tuple[str, ...]
code_parse_status: str
gate: GateResult
def inspect_candidate(
source: BearingPassport,
candidate: BearingPassport,
decision: AnalogueDecision | None,
context: ApplicationContext,
codebook: VerifiedCodebook | None = None,
) -> InspectionResult:
"""No mutation of source attributes, provenance or engineering approval."""
book = codebook or VerifiedCodebook()
decoded = book.decode_suffix(candidate.brand, candidate.suffix)
observations = tuple(
CodeObservation(c.code, c.manufacturer, c.feature, c.contact_type, c.source_url)
for c in decoded.codes
)
gate = evaluate_autoreplace(source, candidate, decision, context)
return InspectionResult(observations, decoded.unknown_parts, decoded.status, gate)
+37
View File
@@ -0,0 +1,37 @@
"""Regression for ГОСТ 11215 / 1217K+H217 and false 75 mm bearing bore."""
from decimal import Decimal as D
from src.bearing_dimension_roles import BearingGeometry, compare_geometry
SKF = "https://skf-us-cad-download.skf.com/item/self-aligning-ball/aligning-ball-bearings-with-tapered-bore-1/1217k"
IRBIS = "https://www.irbis.ua/catalog/product/11215-1217kh217-sh00004877"
def assembly():
return BearingGeometry("11215 / 1217K+H217", "BEARING_WITH_ADAPTER",
D(85), D(150), D(28), D(75), "H217", SKF, IRBIS)
def test_bore_and_shaft_seat_are_not_same_diameter():
a = assembly()
assert a.evidence_problems() == ()
assert (a.bearing_bore_d_mm, a.shaft_seat_d1_mm) == (D(85), D(75))
assert a.ddb_for_single_bearing() is None
def test_false_75mm_bore_is_detected():
bad = BearingGeometry("11215","BEARING_WITH_ADAPTER",D(75),D(150),D(28),D(75),"H217",SKF,IRBIS)
assert "ADAPTER_ROLE_AMBIGUITY" in bad.evidence_problems()
def test_assembly_not_indexed_as_single_bearing():
standalone = BearingGeometry("1217K","SINGLE_BEARING",D(85),D(150),D(28),None,None,SKF,None)
assert "SINGLE_VS_ASSEMBLY" in compare_geometry(assembly(),standalone)
assert standalone.ddb_for_single_bearing() == (D(85),D(150),D(28))
def test_assembly_component_sources_required():
bad = BearingGeometry("11215","BEARING_WITH_ADAPTER",D(85),D(150),D(28),D(75),"H217",None,IRBIS)
assert "MISSING_COMPONENT_PROVENANCE" in bad.evidence_problems()
def test_different_shaft_seat_not_equal_assembly():
other = BearingGeometry("1217K+H???","BEARING_WITH_ADAPTER",D(85),D(150),D(28),D(80),"H217",SKF,IRBIS)
assert "DIFFERENT:shaft_seat_d1_mm" in compare_geometry(assembly(),other)
def test_bearing_data_missing_blocks_diameter_comparison():
other = BearingGeometry("unknown","SINGLE_BEARING",None,D(150),D(28),None,None,None,None)
assert "UNKNOWN:bearing_bore_d_mm" in compare_geometry(assembly(),other)
+21
View File
@@ -0,0 +1,21 @@
from datetime import date
from src.engineering_core import ApplicationContext, AttributeFact, BearingPassport
from src.oem_evidence_bridge import inspect_candidate
def passport(ident, brand, code):
return BearingPassport(
ident, code, brand, "ISO", "", "6205", code.split("6205")[-1],
{"clearance": AttributeFact(None, "UNKNOWN")},
)
def test_official_code_does_not_grant_equivalence():
source = passport("a", "NSK", "6205DDU")
candidate = passport("b", "SKF", "6205-2RSH/C3")
result = inspect_candidate(source, candidate, None, ApplicationContext(date(2026, 10, 21), None))
assert [o.code for o in result.observations] == ["2RSH", "C3"]
assert not result.gate.allow_autoreplace
assert result.gate.reasons == ("NO_APPROVED_DECISION",)
assert all(o.status == "OFFICIAL_CODE_ONLY" for o in result.observations)