Skip to content

chore(release): 2.9.0 - #37

Merged
pavansky merged 11 commits into
mainfrom
release/2.9.0
Oct 12, 2026
Merged

pavansky merged 11 commits into
mainfrom
release/2.9.0

Conversation

@pavansky

@pavansky pavansky commented Oct 11, 2026 •

Copy link
Copy Markdown
Owner

Release 2.9.0. Eleven commits, grouped by area so each can be reviewed on its own.

What changes

  • One total cost for every strategy, the exact solver and the benchmark.
  • Heuristics insert a job only when it lowers that cost.
  • Corrected shift model: no idle wait before the first job, priority 3 means constraint-family downs, the Overstaffed preset adds a certified engineer.
  • Live dispatch: ticketed streams, idempotent writes, faithful re-plans.
  • API and platform hardening: auth, rate limits, CSP and HSTS, nginx headers, configurable size limits.
  • Assistant: server-side recommendation, checked LLM rewrite, better retrieval.
  • UI: paired t verdicts with Holm adjustment, steadier requests, WCAG AA.
  • Reproducible parallel study scripts and regenerated ANALYSIS tables.

Results (80 full-size shifts, 14 x 45, gap to the proven optimum)

Strategy Mean gap Worst
PyVRP 3.85% 11.23%
ALNS (300 iterations) 5.74% 23.17%
ALNS (20,000 iterations) 1.36% 4.61%
Regret 20.09% 61.35%
Greedy 29.33% 74.29%
Hungarian 29.75% 83.25%

The gap table was reproduced to the decimal on a second machine.

Tests

  • Backend: 498 passed, 16 skipped, 5 slow deselected.
  • Frontend: 219 passed.

@vercel

vercel Bot commented Oct 11, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
fab-dispatch Ready Ready Preview Oct 12, 2026 2:36am UTC

Comment thread backend/app/assistant/agent.py Fixed
Comment thread backend/app/assistant/agent.py Fixed
Comment thread backend/app/assistant/agent.py Fixed
Comment thread backend/app/observability.py Fixed
Comment thread backend/tests/test_api.py Fixed
Comment thread backend/app/observability.py Fixed
Comment thread backend/tests/test_api.py Fixed
…ft model

The planner, the engine and the generator now agree on a single objective.

- Total cost is soft cost plus the workload term, reassignment and unserved priority.
  The engine reports it as the objective metric.
- Insertion cost is summed unrounded, so it equals the change in the objective.
- No idle wait is charged before an engineer's first job.
- Priority 3 is reserved for tool-downs on the constraint family.
- Cross-trained level-1 engineers can take some constraint-family PMs.
- The Overstaffed preset adds a certified engineer and stays provable at full size.
- Unassigned jobs report the real reason.
- Ids shared by an engineer and a job are rejected.
… solver with the objective

- Greedy, Hungarian and regret insert a job only when it lowers the total cost.
- Regret ranks by every feasible engineer and gates only the commit.
- The ALNS budget starts after the warm start. Annealing cools to near-greedy by the last iteration.
- ALNS counts stability in worst removal.
- PyVRP keeps the plan that is cheapest by the planner's cost, warm start included.
- PyVRP cancels walking and service time exactly at the charged rate.
- The exact MILP prices frozen work and stability like total_cost.
- The exact MILP takes a time limit and raises instead of returning an unproven plan.
- FAB_EXACT_THREADS caps HiGHS threads so many proofs can run side by side.
- Streams use a 90-second ticket instead of the access token in the URL.
- Stream opens are rate-limited and capped per user.
- Idempotency keys are claimed atomically with the shift write.
- The shift ETag works as an If-Match precondition.
- Reported jobs are validated, ended shifts are frozen and no-op writes are skipped.
- Started jobs are replayed at their recorded times on re-plan.
- Unreported tool-downs stay out of the shift view.
- Guests may only change the live shifts they started.
- Shift state is serialised once per write.
- Tokens must carry exp. The bootstrap grant needs a verified email.
- Revoked fab lists are honoured. Demo sign-in is limited to local and test.
- Forwarding headers are trusted only as configured. Idle rate-limit buckets are evicted.
- Anonymous calls write no rate-limit rows. Expensive endpoints fail closed.
- The API sends a Content-Security-Policy and HSTS.
- Router 404 and 405 use the error envelope. 500s carry CORS headers.
- The UI image sends security headers from every nginx location and runs nginx unprivileged.
- Strategy lists and benchmark work are bounded.
- Shift size limits are settings (FAB_MAX_ENGINEERS, FAB_MAX_JOBS) reported in /api/meta.
- Tenant names stay out of /meta. /health is cached.
- Postgres connections are reused.
- Idle guest accounts are deleted in the retention prune.
…t repair predictions

- The recommendation is computed on the server instead of echoed from the browser.
- The optional LLM rewrite is checked against the grounded draft and falls back with a reason.
- Retrieval uses IDF-weighted lexical scoring with glossary terms.
- Duration questions such as "how long will J006 take" route correctly.
- Feedback is validated and de-duplicated per user and question.
- Repair history makes no prediction below a similarity floor.
- Repair symptoms carry partial root-cause signal.
- Stored Qdrant collections are versioned by history content.
- The roster limits which engineers a repair estimate draws on.
…ccessibility

- Verdicts use paired t intervals, Holm-adjusted, and warn below ten seeds.
- Weight sliders commit on release. Identical solves share one request and retry once on 429.
- Writes send If-Match and explain a 409. A 401 renews the session before sign-out.
- Absent metrics show "n/a". Workload spread is shown in minutes.
- Contrast, reduced motion, live regions, keyboard-operable rows and focusable tooltips meet WCAG AA.
- Crash reports keep shift ids and emails out of the issue body.
- The floor plan, schedule, workforce, live and benchmark views load on demand.
- Size fields follow the limits in /api/meta.
@pavansky pavansky changed the title fix: release 2.9.0 — review fixes, honest benchmarks and studies chore(release): 2.9.0 Oct 11, 2026
@pavansky
pavansky marked this pull request as ready for review October 11, 2026 19:57
…ber in ANALYSIS

- Benchmark gains a revealed-information mode, paired bootstrap intervals and a changeable-cost gap.
- Full-size gap proofs and bound route enumeration run in parallel worker processes.
- The ALNS iteration override reaches the worker processes.
- The certified bound runs several seeds and presets.
- The duration study uses realistic baselines and separate interval checks.
- The predictive study counts planned repair and false-alarm time, and sweeps planned repair length.
- The learned-policy study runs several search seeds with cached optima.
- The scale study records caps, iterations and cost per area, and saves after every section.
- feedback_to_eval.py turns user feedback into evaluation cases.
- Every study has a main(argv) with size flags. Defaults reproduce the published tables.
…the merged API

- Every study script runs at a tiny size and checks that no heuristic beats a proven optimum.
- The exact solver is held to the hard constraints on every preset of both fabs.
- The full-size optimality proof covers every preset.
- A slow test runs ALNS and PyVRP at their shipped budgets.
- README test counts are checked against the suites.
- UI fixtures are regenerated from the API with measured runtimes.
- The fixture contract compares enum-like fields.
- Component and end-to-end tests follow the lazy views and the new metrics.
- A release tag must be on main. Production is promoted only after a green UAT deployment.
- Every action is pinned to a commit and every job has a timeout.
- Python 3.11 to 3.14 and Node 20 and 22 are tested. Slow tests run on pushes to main.
- Coverage counts scripts/ with a floor one point below the measured run.
- The commit check rejects co-author and session trailers.
- CodeQL regex findings are fixed.
- highspy is pinned in pyproject and requirements.
- Dependabot watches Docker images.
….9.0 results

- ANALYSIS.md tables come from the 2.9.0 runs, with confidence intervals.
- Gap to the proven optimum on 80 full-size shifts: PyVRP 3.85%, ALNS 5.74%, regret 20.09%.
- ALNS at 20,000 iterations is 1.36% from the optimum and optimal on 10 of 80 shifts.
- README, design review, decisions, architecture and help articles carry the same numbers.
- SECURITY.md and the deployment docs say exactly what the CSP, RLS, tokens and rate limits do.
- Solver lineage and citations are corrected. The technician-routing literature is cited.
- ai.md describes the retrieval, what leaves the server and the evaluation.
- Version 2.9.0 in the backend, frontend and fixtures.
- Changelog entry for 2.9.0.
@pavansky
pavansky merged commit 063697b into main Oct 12, 2026
23 checks passed
@pavansky
pavansky deleted the release/2.9.0 branch October 12, 2026 02:59

This branch was successfully deployed

1 active deployment
Preview — d04c6479 Deployed Oct 12, 2026 by vercel[bot]
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