77
88TechEngine owns everything * around* the data: schema validation, the FastAPI
99read API, the static JSON dump generator, the engine's own landing site,
10- automated coverage checks, and the weekly ingestion/refresh crawlers.
10+ coverage checks, the ingestion/refresh collectors and the verification tiers.
11+ Nothing here runs on a schedule; collectors run only when a maintainer
12+ dispatches them.
1113
1214The dataset and the public-facing playground site live in
1315[ TechAPI] ( https://github.com/GetTechAPI/TechAPI ) so each can be versioned,
@@ -17,60 +19,89 @@ engine's own landing: what TechEngine is, what it runs, and links out to docs.
1719## Layout
1820
1921``` text
20- app/
21- validate.py # schema/range/uniqueness checks
22- seed.py # data/ -> SQLModel database
23- dump.py # API -> static JSON tree
24- main.py # FastAPI entrypoint
22+ app/ # the engine (the one installable Python package)
23+ main.py # FastAPI entry point; mounts every router under /v1
24+ routers/ # /v1 routes, one module per collection (list below)
2525 models/ # SQLModel tables
26- routers/ # /v1/{brands,socs,smartphones,gpus,cpus}
27- schemas/ # Pydantic response models
28- services/ # scoring (algorithm_version-tagged)
29- coverage/ # upstream-vs-curated diff + Markdown report
30- ingest/ # draft new records from upstream pages
31- tests/ # unit + integration
32- site/ # Astro engine landing (deploys to Pages)
33- docs/ # SPEC / DATA_PIPELINE / DEVELOPMENT
34- TechAPI/ # submodule -> GetTechAPI/TechAPI (clickable @ <sha> link)
35- .github/workflows/
36- test.yml # lint + type-check + tests
37- validate-data.yml # read-only data validation (workflow_call or manual)
38- deploy-pages.yml # build & deploy engine site + dump
39- coverage-report.yml # manual: gap report to the job summary + artifact
40- ingest.yml # workflow_call: draft new SKUs -> collect.patch
41- refresh.yml # workflow_call: re-scrape benchmarks -> collect.patch
42- verify-promote.yml # workflow_call: Tier 1-3 checks + verified promotion patch
43- final-check.yml # label-triggered checks + one TechEngineBot comment
26+ schemas/ # Pydantic response models + serializers
27+ services/scoring/ # 0-100 scores, weights from config/scoring.yaml
28+ data_root.py # finds the TechAPI dataset (see below)
29+ categories.py # the 13 dataset categories and their collection names
30+ validate.py # schema/range/uniqueness checks on the dataset
31+ seed.py # dataset -> SQL database
32+ dump.py # API -> static JSON tree (./dump)
33+ coverage/ # upstream-vs-curated gap report
34+ ingest/ # collectors: draft new records, refresh benchmarks
35+ verify/ # trust tiers 0-3, verified promotion, backfill tools
36+ config/scoring.yaml # scoring weights and reference scales
37+ integrity_check.py # whole-dataset anomaly scan (the --strict gate)
38+ tests/ # unit/, integration/, verify/
39+ site/ # Astro landing page, deployed to GitHub Pages
40+ docs/ # SPEC, DATA_PIPELINE, DEVELOPMENT
41+ .github/workflows/ # CI; every workflow is listed below
42+ Dockerfile, docker-compose.yml # stale, do not build (see Docker)
4443```
4544
46- ## How The Two Repos Connect
45+ Routes under ` /v1 ` : ` health ` , ` version ` , ` brands ` , ` socs ` , ` smartphones ` ,
46+ ` tablets ` , ` watches ` , ` pdas ` , ` gpus ` , ` cpus ` , ` laptops ` , ` monitors ` ,
47+ ` software ` , ` websites ` , ` device-catalog ` . Dataset folders are singular
48+ (` cpu/ ` ), routes are plural (` /v1/cpus ` ); ` app/categories.py ` holds the mapping.
49+
50+ ** How the engine finds the dataset.** This repo holds no data. Every entry
51+ point asks ` app/data_root.py ` , which returns the first of: the
52+ ` TECHAPI_DATA_DIR ` environment variable; ` ../data ` (this repo checked out as
53+ TechAPI's ` TechEngine ` submodule); ` ../TechAPI/data ` (the two repos cloned side
54+ by side). CI checks TechAPI out into ` ./TechAPI ` , which is git-ignored, and
55+ sets ` TECHAPI_DATA_DIR ` to its ` data/ ` folder.
56+
57+ Workflows:
58+
59+ ``` text
60+ test.yml # lint + type-check + tests
61+ validate-data.yml # read-only data validation (workflow_call or manual)
62+ deploy-pages.yml # on push to main: build site/ + static dump -> Pages
63+ coverage-report.yml # manual: gap report to the job summary + artifact
64+ ingest.yml # workflow_call: draft new SKUs -> collect.patch
65+ refresh.yml # workflow_call: re-scrape benchmarks -> collect.patch
66+ verify-promote.yml # workflow_call: Tier 1-3 checks + verified promotion patch
67+ final-check.yml # label-triggered checks + one TechEngineBot comment
68+ ```
4769
48- Both repos live in the ** GetTechAPI** org and each includes the other as a git
49- ** submodule** (a clickable ` @ <sha> ` pin). Nothing syncs them automatically.
70+ ## How The Two Repos Connect
5071
51- No workflow here runs on a schedule or uses a personal access token (ADR-017).
52- The one comment any workflow posts is TechEngineBot's final check, and only when
53- a maintainer adds the ` final-check ` label to a PR (` final-check.yml ` ).
72+ Both repos live in the ** GetTechAPI** org. TechAPI pins this repo as its
73+ ` TechEngine ` git ** submodule** (a clickable ` @ <sha> ` pin); this repo does not
74+ pin TechAPI back, so there is no submodule loop. Nothing syncs them
75+ automatically: the pin moves only when a TechAPI commit moves it.
76+
77+ No workflow here runs on a schedule or uses a personal access token (ADR-017),
78+ and no workflow opens or approves a PR. TechEngineBot opens PRs by hand from a
79+ maintainer's machine, with its gh login kept apart from the maintainer's own;
80+ the maintainer's account still commits, pushes and merges. The one comment any
81+ workflow posts is TechEngineBot's final check, and only when a maintainer adds
82+ the ` final-check ` label to a PR (` final-check.yml ` ).
5483Collection runs only when a maintainer dispatches TechAPI's ` collect.yml ` , which
5584calls ` ingest.yml ` , ` refresh.yml ` or ` verify-promote.yml ` with a read-only
5685token. Each run commits locally, gates the result with ` app.validate ` and
5786` integrity_check.py --strict ` , and uploads the commit as ` collect.patch ` . A
58- maintainer opens the PR from their own account with TechAPI's
59- ` .github/scripts/open-collect-pr.sh ` ; no workflow pushes or opens a PR. The
87+ maintainer then runs TechAPI's ` .github/scripts/open-collect-pr.sh ` by hand:
88+ their account pushes the run's ` collect/* ` branch and TechEngineBot opens the
89+ PR. No workflow pushes or opens a PR. The
6090engine that runs is the TechEngine commit TechAPI pins as its submodule.
6191Crawlers identify themselves with a ` TechEngine-* ` User-Agent.
6292
6393Every Python entry point reads data from a ** TechAPI checkout** . The location
6494can be overridden via ` TECHAPI_DATA_DIR ` ; by default TechEngine supports both
65- layouts: ` TechAPI/TechEngine ` as a submodule and ` TechAPI ` beside ` TechEngine ` .
95+ layouts: ` TechAPI/TechEngine ` as TechAPI's submodule and ` TechAPI ` beside
96+ ` TechEngine ` (see Layout).
6697
6798## Quickstart
6899
69100``` bash
70101git clone https://github.com/GetTechAPI/TechAPI.git ../TechAPI # data source
71102pip install -e " .[dev]"
72103python -m app.validate # check data integrity
73- python -m app.seed # data/ -> ./techapi.db (SQLite)
104+ python -m app.seed # dataset -> ./techapi.db (SQLite)
74105uvicorn app.main:app --reload # serve; curl localhost:8000/v1/cpus/ryzen-9-9950x3d
75106python -m app.dump # generate ./dump/v1/... static tree
76107```
@@ -82,13 +113,13 @@ seed records may omit them or use `null` when no source value is known, and API
82113detail responses and static dumps preserve unknown values as ` null ` .
83114Smartphones continue to require numeric values for both fields.
84115
85- ### Docker Compose (Postgres)
86-
87- ``` bash
88- docker compose up --build
89- ```
116+ ### Docker
90117
91- Spins up Postgres 16, seeds from the mounted TechAPI checkout, serves on ` :8000 ` .
118+ ` Dockerfile ` and ` docker-compose.yml ` predate the split from TechAPI and do
119+ not work as they are: the Dockerfile copies ` data/ ` and ` scripts/ ` , which no
120+ longer exist here, so the image does not build, and the compose file mounts no
121+ TechAPI checkout for ` app.seed ` to read. No workflow builds or uses them. Use
122+ the Quickstart above; for Postgres, point ` DATABASE_URL ` at your own instance.
92123
93124## Roadmap
94125
0 commit comments