SIMS Onboarding
Pedro & Vusal, joining cold while Joaquim is out (~2 weeks from Jun 2). Mission: get productive fast and land the client demo Jun 22-23. Gabriel is the other active SIMS dev.
Hard calendar spine
| Date | Gate |
|---|---|
| Jun 12 | Cloudflare Tunnel + Pages live (DEV2-603). E2E suite (DEV2-631). HARD GATE |
| Jun 15 | All D2/D3/D4 merged + deployed to Plastaze VM. Feature freeze. |
| Jun 18 | Internal full-script dry-run (DEV2-606). Bug list + go/no-go. |
| Jun 19 | R1 Phase-2 deploy to Plastaze (DEV2-650). |
| Jun 21 | Paulo rehearsal — he plays the client. Final go/no-go. |
| Jun 22-23 | Demo. |
1 · What SIMS is
SIMS (Simoldes Industrial Monitoring System) is an MES for injection-molding factories. It replaces Simoldes' legacy proGrow platform with real-time OEE/KPI calculation straight from EWON IoT devices, plus a tablet-first manual-input layer for what machines can't self-report.
Two data sources, one KPI engine
- Automated — EWON telemetry (OPC-UA) → ingestion → backend →
production_events. No human. Tells you that a machine stopped / produced a cycle. - Manual — operators on tablets enter why: stoppage code, rejections, OF start, mould changes. Queued offline when network drops.
Manual SIMS entries are canonical; proGrow is fallback/validation only and is being removed at D4.
2 · Monorepo + run it
Root: sims-project. Three independent git repos (each own .git).
| Repo | Stack | Entry | Port |
|---|---|---|---|
| sims-backend | Python 3.11+, FastAPI, SQLAlchemy async + asyncpg, Postgres 15, Alembic, Redis, JWT | app/main.py | 8000 |
| sims-frontend | React 19, Vite 7, TS, TanStack Query, React Router 7, shadcn/Radix, Tailwind 4, i18next, idb, vite-plugin-pwa | src/App.tsx | 5173 |
| sims-ingestion | Python 3.11+, asyncua (OPC-UA), APScheduler, SQLite buffer | src/main.py | — |
src/opcua_client.py, no mqtt_client.py). MQTT survives only as a local simulator path. Trust the code.Run locally (Mac, Apple Silicon)
cd sims-backend && docker compose up -d # whole stack
# services: redis db api ewon-sim ingestion mqtt-broker simulator frontend
# frontend :5173 · DB role sims_user / db sims_db
# api 500s on missing columns? local migration drift:
docker exec sims-api alembic upgrade head # then restart api
# psql:
docker exec sims-db psql -U sims_user -d sims_db -c "SELECT ..." # NOT -U postgres
# frontend stale ("Network Error" while logged in):
cd sims-backend && docker compose restart frontend
G1 gates — run before every PR
| Repo | Gates |
|---|---|
| backend | make lint · mypy app/ --strict · make test (cov 80% / 100% KPI). Full CI: make test-ci |
| frontend | npm run lint · npx tsc --noEmit · npm run test · npm run build |
| ingestion | ruff check src/ tests/ · black src/ tests/ · pytest |
Frontend gotchas (day one)
- i18n: app is
lng:"pt"with pt fallback. Missing pt key silently renders EnglishdefaultValueto supervisors. CI guardi18n-key-coverage.test.tsenforces it — add the pt key with every newt(). pt-PT modern orthography (Ações/Ativo). - API types are generated:
npm run generate:types→src/types/generated/api.ts. Never hand-write. - Offline PWA cache + queue is sensitive (
offline-cache.ts24h TTL;offline-queue.ts1000 items/3 retries). Verify with real data on a real 768px tablet.
/api/v1/*. /machine-data is exempt (X-API-Key server-to-server). Ingestion sends BACKEND_API_KEY; backend checks INGESTION_API_KEY — these must match or 401.3 · Data pipeline end-to-end
EWON Flexy OPC-UA (opc.tcp://10.2.61.2:4840, ns=4, 24 tags of 651)
→ opcua_client.py polls every 5s, buffers a snapshot only when
N_Ciclo (new cycle) or TS_Estado_RT (state change) flips → SQLite (30-day)
→ APScheduler every 60s POSTs ≤100 unsynced rows + heartbeat
→ api_client.py POST {BACKEND_API_URL}/machine-data header X-API-Key
machine_code via DEVICE_MAPPING {"KM850II":"KM 850 II"}
→ backend POST /api/v1/machine-data: X-API-Key → lookup Machine (404 if not seeded!)
→ classify event (ewon_parser) → SHA256 dedup → JSONB in production_events
→ frontend TanStack Query polls /machines/:code/status + /kpis/... every 10s
machines table is manually seeded, no auto-seed. /machine-data returns 404 if a code isn't there. Mapping gotcha: OPC topic KM850II (no spaces) ↔ DB/frontend KM 850 II (spaces) — DEVICE_MAPPING must be in the .env compose reads.4 · Backend domain + KPIs
Models in app/models/: machines, production_events (raw JSONB), stoppages/stoppage_codes, rejections/rejection_codes, work_orders (OFs) + moulds + machine_mould_runs, operators/sessions/tablets, kpi_snapshots, proGrow sync tables. ~30 routers in app/api/v1/.
KPI engine — app/services/kpi_calculator.py (~2200 lines)
- OEE = Availability × Performance × Quality. Performance uses per-OF cycle time from proGrow with a SIMS fallback. Functions return a
performance_source:"progrow" | "sims_fallback" | "sims". - KPIs rounded to 4 decimals. Snapshot scheduler (
KPI_SNAPSHOT_ENABLED) snapshots current hour every 5min + recomputes past 24h hourly. - Mould (turno-molde), NOT OF, is the KPI attribution unit. RFI mandates two distinct cavity fields — Teórico vs Efetivo. Conflating them was the historic MES ~50%-OEE bug. SIMS now owns a
mouldstable, backfilled once from proGrow.
PROGROW_USE_MOCK gates the sync loop. Slated for removal from calculate_oee/teep/ppm at D4 (DEV2-602). Setting USE_PROGROW_FALLBACK=False does NOT make it standalone — it only governs the /stoppages read path.5 · Current state
| Milestone | Target | State |
|---|---|---|
| D1 Foundation | May 4 | Done nav, tablet auth, PWA, manual-input scaffolding |
| D2 Core Manual Inputs | Jun 1 | ~99% — all 4 named demo-blockers closed |
| D3 Dashboards & Integration | Jun 22 | 1.5% demo runs against these · unassigned |
| D4 proGrow Elimination | Jun 30 | 0% · holds Epic 16 (demo coordination) |
| D5 Multi-Tenant DB | Jul 22 | rollout prereq, not demo |
| R1 Plastaze → R8 | Jul-Dec | 8 factories, proGrow off by year-end |
DEV2-tablet-device-pairing, 31 commits ahead of main, open PRs #94 (backend) + #104 (frontend) since May 27. Bundles per-machine PIN login + moulds/cavities schema (5 migrations) + OF-start mould-run lifecycle. Shipped with no Linear ticket / AC — now governance-ticketed (DEV2-705/706/707/708).Deploy topology — don't confuse the three
- Local (Mac/ARM) —
sims-backend/docker-compose.yml. - Prod/pilot VM
172.30.1.160(linux/amd64) —/opt/sims/sims-backend/..., single root-owned.env. Build--platform linux/amd64. VM service names:backend,front-end,ingestion.docker rm -fold containers beforecompose up. - Office dev VM
192.168.1.247— Ubuntu, SSH key~/.ssh/sims_dev_vm. - Demo target — Cloudflare Pages FE + Cloudflare Tunnel to on-prem VM backend (DEV2-603).
6 · Client commitments (verbatim)
Paulo Brás (Simoldes Operations), 2026-05-27 — closing EWON/Xpert questions:
- EWON is standard across all machines/factories → deployments are replacement only. Key line: "sempre que muda uma OF têm de escrever no ewon o molde, referencia mais baixa e ciclo teórico" — mould + lowest reference + theoretical cycle are written to EWON tags at every OF change. Candidate OF→mould source ahead of proGrow.
- All factories use Xpert (until SAP migration; INPLAS first). Cadence: OFs every 10min, operators 1×/shift, qualification 1×/day, per-factory tables.
7 · Demo script (Jun 22-23)
Canonical: docs/sims-demo-script.md (~15 min, 12 sections, European Portuguese):
- Supervisor login (
/login) - Machines overview (KM 850 II + KM1300 live)
- Machine detail (Produção/Timeline/Validação/Diagnóstico)
- +5. Tablet provisioning + activation
- Machine identify + handover
- Operator clock-in (keypad) + manual input
- Rejection registration
- Stoppage justification (1ª Peça OK = honest "Em breve" placeholder)
- A Minha Sessão (audit trail)
- Relatório Tempo de Trabalho (central D2 deliverable, CSV in proGrow schema)
- Admin
8 · Risk register
| ID | Risk | Sev |
|---|---|---|
| STOP-1 | "N por justificar" badge recomputes from raw events and never decrements as operators justify — wrong on screen. | crit |
| CLOCK-01 | Clock-in on a new machine doesn't close the prior open session → inflated Tempo de Trabalho + double-counted parts. | crit |
| PGW-* | Overview/Timeline still render proGrow numbers next to canonical SIMS KPIs, no staleness badge — can visibly disagree. | high |
| Mould 404 | Unknown mould 404s as "Máquina não encontrada" (should be "Molde"). Re-verify fix held. | high |
| DEV2-535 | Bulk-justify lacks shift-boundary check. Paulo demanded shift-scoped edits. (Carries DEV2-599's requirement.) | high |
| Stoppage↔WO | Frontend StoppageResponse TS type missing work_order_id (backend sends it). Low-effort fix. | low |
9 · Demo-readiness checklist
Run the actual docs/sims-demo-script.md flow on the demo VM and confirm each.
Functional path
- Supervisor login →
/machinesshows KM 850 II + KM1300 live (machines seeded). - Machine detail tabs render with real data.
- Operator keypad clock-in (1001/1002/1003) →
/input. - Rejection submits + offline-queue replays.
- Stoppage justify: "N por justificar" decrements (STOP-1).
- Tempo de Trabalho CSV exports in proGrow schema, opens cleanly in Excel.
Data integrity + infra
- No proGrow-vs-SIMS disagreement on Overview/Timeline.
- Machine-switch closes prior session (CLOCK-01).
- Day-boundary / timezone correct for the demo shift (Lisbon vs UTC).
- Mould-404 says "Molde", not "Máquina".
- Cloudflare Tunnel + Pages live (DEV2-603) OR decision to demo on plain VM. IT outbound-443 confirmed.
- Frontend built
--platform linux/amd64; old containersdocker rm -f;.envhas DEVICE_MAPPING + matching API keys. - 768px tablet smoke, real KM 850 II data, offline cache + input queue.
10 · Ownership split
Nothing in D3/D4 had an owner. Suggested split (your tickets carry the detail):
| Dev | Lane | Tickets |
|---|---|---|
| Pedro DEV2-703 | Work Order Management (recommended D3 starter, no external blocker) + "próxima OF" tile (Paulo-demanded) | DEV2-346 · 359 · 360 · 536 |
| Vusal DEV2-704 | proGrow Comparison + cut (the demo's credibility story) + evidence package | DEV2-347 · 361 · 362 · 602 · 604 |
| Shared w/ Gabriel | Cloudflare (Jun 12 gate), runbook, dry-runs, demo-visible data bugs | DEV2-603 · 605 · 606 · STOP-1 · CLOCK-01 · PGW-* |
| Blocked (escalate via Paulo) | Xpert ERP — needs Simoldes IT DB2/MS-SQL creds + FIRM_CODE. Soft for demo. | DEV2-345 · 354 (owner TBD) |
Governance tickets filed 2026-06-01
- DEV2-705 per-machine PIN tablet login (D2)
- DEV2-706 SIMS moulds/cavities model (D4 — needs Paulo sign-off vs DEV2-271)
- DEV2-707 OF-start WO + mould-run lifecycle (D2)
- DEV2-708 OF→mould auto-lookup (D3 — needs Xpert/EWON-tag)
11 · Who to ask
- Joaquim Luzia — SIMS Team Lead (on vacation — async only). This doc + your tickets stand in.
- Gabriel Shomorin — other active SIMS dev; ran the demo-script E2E smoke; KPI/proGrow expertise.
- João Faria — IT PMO (project plan, rollout, demo logistics). João Viegas — Eng lead. Gonçalo Pereira — commercial gatekeeper. Guilherme Fontes — CEO.
- Client: Paulo Brás (Simoldes Operations, primary), Nuno Almeida.
- Slack:
#ops-weekly-updates(primary SIMS status). Weekly SIMS+MES sync Fri 11:30. (SIMS + MES share machine data — parallel MES Plastaze project.) - Don't confuse: new dev Pedro Cardoso vs existing Pedro Cordeiro (QA/platform).
12 · First-day runbook
- Clone all three repos;
cd sims-backend && docker compose up -d;alembic upgrade headif api 500s. - Open :5173, log in as supervisor, click through
/machines→ machine detail → admin. - Read
docs/sims-demo-script.mdand run the flow locally (operator + supervisor paths). - Read your Linear ticket — DEV2-703 (Pedro) / DEV2-704 (Vusal). It's your queue.
- Run the G1 gates on a no-op change to confirm your toolchain.
- Pull the open tablet-PIN branch (
DEV2-tablet-device-pairing); PRs #94/#104. - Post in
#ops-weekly-updatesthat you're onboarded; sync with Gabriel on the split.
Compiled 2026-06-01 from codebase, Linear (D2/D3/D4 + cycle 8), Gmail (Paulo EWON/Xpert + rollout plan), Slack #ops-weekly-updates, Granola notes, and the docs/ audit set. Dated decisions override older ones. · Source: docs/ONBOARDING-pedro-vusal-2026-06.md