Re-test after the engine rewrite that landed on the morning of 15 Oct 2026. The candidate flow, exhibit system and grading surface are all new. But the submit endpoint is 500ing — every candidate is currently stuck on Q1.
/api/interview/answer removed. New session API: /api/session/start, /next-question, /answer, /complete. New question types: mcq | multi | true_false | numerical | matching | ordering | text | sjt | excel_sim. New exhibit types: table | balance_sheet | trial_balance | ledger | voucher | cheque | roznamcha | khata (jama/naam). The "real documents" promise is now actually wired in.lastSource: "ai" — questions are LLM-generated, not hard-coded.limit field changed from 200 to null (unlimited). applications count went from 3 to 18 between the two runs — 15 new applicants in ~30 min including mine./api/session/answer returns HTTP 500 with empty body on every valid submit (curl-tested 4× with same token + questionId + answer shape). 361ms response time, no error JSON. The browser displays "We could not send your answer right now. It is saved on this device — we will retry as soon as you are back online." with a Retry button that doesn't help. No candidate can complete the interview right now.core_accounting, manual_khata, etc.) instead of the human-readable labels from /interview-info./interview-info says "~35 min".What this re-test covered and what it didn't.
v0.2 re-test run on the morning of 15 Oct 2026, ~30 minutes after v0.1. Same scope as before (no staff creds) but with a new focus: did the engine rewrite fix any v0.1 findings, and did it introduce regressions?
One new regression, two v0.1 findings still open.
/api/session/answer returns HTTP 500 on every submitEvery valid answer POST returns 500 with an empty body in ~360ms. The browser surfaces this as "We could not send your answer right now. It is saved on this device — we will retry as soon as you are back online." The Retry button does not help — re-submits return the same 500.
curl -X POST .../api/session/answer -d '{"token":"...","questionId":"-1","answer":"test"}' → 500 in 361ms, body empty. Same payload shape works on validation (400 on missing fields, 404 on bad token) — the crash is in the handler, not the route.Why it matters: no candidate can complete the interview right now. Every applicant since the deploy is stuck on Q1. With 18 applicants and counting, that's 18 broken records in HR's queue. The offline-saved-on-this-device copy is localStorage — candidates on a different device have lost answers entirely. This is a launch-blocker; until it's fixed, the 18 fresh applicants are noise, not signal.
Same as v0.1 finding #3 — confirmed on the re-test. The "What we will cover" list on /welcome still shows:
core_accounting · manual_khata · payroll_statutory · taxation_pk · excel_tools · financial_statements · judgment_ethics · personality_retention
Meanwhile the new /api/session/start response still returns the same enum array under job.topics. The frontend just hasn't been updated to map it to the friendly names from /interview-info.
Why it matters: the engine rewrite was a chance to fix this and it didn't. Still reads like a build artefact to candidates.
Same as v0.1 finding #5 — confirmed on re-test. Four different numbers on the same property:
/interview-info: ~35 min average lengthjob.estMinutes in the new session API)Why it matters: 41 min is now a server-side number returned by the new /api/session/start response under job.estMinutes. If you change it, change the home page and /interview-info in the same deploy.
Marketing-vs-reality gaps, stale questions, and the v0.1 items that survived the rewrite.
v0.1 #4 — confirmed. The hero, the "How it works" section and the live demo transcript all describe a free-form conversation. The new engine is structured (typed questions with type: text | mcq | numerical | … and per-type expect schemas), not a chat.
Why it matters: the new exhibit system is genuinely impressive (balance sheets, khata, vouchers, cheques, trial balances) — that copy is now accurate for the first time. The remaining gap is just "a chat" → "a structured technical interview with real documents". One word swap on the home page.
v0.1 #8 — confirmed. The profile form still includes "Have you written articles or content?" with hint "Two blog posts on accounting, or none". The new /api/session/start response includes a candidate.articleContext field that this question is supposed to populate. Wrong field for the role.
Same as v0.1 #6 — confirmed. After every submit the screen jumps to the next question with no "correct/partial/wrong" signal. With the new engine, the grading happens server-side (it has to, given the question types include text, matching, ordering, excel_sim) but the result never makes it back to the candidate UI during the interview. Only HR sees it later in the report.
Why it matters: the rewrite made grading richer but didn't expose any of it to the candidate. The home page still promises "Ladders up. Answer well and the next question gets harder" — that's HR-only now.
v0.1 #7 — same finding. The v0.1 balance-sheet question had 0-30d = 9.88 crore etc. The new engine is LLM-driven, so magnitude may vary per question now. Need to walk a full interview (post-#1 fix) to see if the AI has been tuned to the SME scale.
These v0.1 findings are resolved by the morning's deploy. Don't let them regress.
The new engine is LLM-driven. lastSource: "ai" is now in the session state. First question served is a freeform text intro on the personality_retention family. The 2-question MCQ loop is gone. Cannot confirm "well-distributed topic coverage" until #1 is unblocked.
Cannot confirm end-to-end because the interview is 500-blocked at Q1. But the new API has an explicit /api/session/complete endpoint — a likely place where the redirect would be triggered. Regression-test after #1 is fixed.
The new bundle at /_next/static/chunks/14_ur4426iv7t.js ships a full exhibit renderer with 8 types: table | balance_sheet | trial_balance | ledger | voucher | cheque | roznamcha | khata (jama/naam). Voucher has date/payee/amount/chequeNo/approvedBy. Cheque has bank/chequeNo/payTo/amount. Khata splits into separate jama (received) and naam (paid) tables. This is the fulfilment of the home-page promise that v0.1 was missing.
Even though the server 500s, the candidate's typed answer is preserved across the error UI (the textbox keeps the value, an alert says "It is saved on this device — we will retry as soon as you are back online"). This is the "Every answer saves the moment you submit it" promise from /interview-info, now actually implemented (just unfortunately the retry never succeeds right now).
The new bundle detects when the interview is running inside an in-app browser (WhatsApp, Facebook, etc.) and shows a dismissible banner: "For the best experience, open in Chrome. This interview is running inside WhatsApp — copy this link into Chrome to avoid interruptions." Matches the home-page promise: "One tap out of WhatsApp into Chrome — we detect the in-app browser and ask."
position.limit changed from 200 to null between v0.1 and v0.2. The cap was probably a launch-period test knob. applications jumped from 3 to 18 in ~30 minutes once removed.
Updated for v0.2. Two big lies are now half-true.
lastSource: "ai") but interview is 500-blocked at Q1 so no signal of adaptiveness yet.difficulty field (1 for Q1) so the scaffold is there, but no candidate can answer anything to trigger a ladder right now.The rewritten engine changed the API surface. These checks need a staff account to be useful.
All admin, HR, manager, dashboard, reports and override routes still 307 to /auth/login. To grade the new engine and the new 500, I need one of the following:
admin, bushra, faizan. I'll run them in read-only mode and screenshot the dashboards./api/session/answer stack trace look like? Is it the LLM provider, a DB constraint, a JSON parse? Best path to fixing #1./api/session/answer 500.Once I have any of the above, the priority checklist for the staff side becomes:
expect: { kind, tolerance, explanation } schema suggests per-question scoring, not just a single number. Where does HR see that?Survived the rewrite. Regression-test on every deploy.
/admin, /admin/dashboard, /hr, /dashboard, /reports, /api/admin/*, /api/staff, /api/hr all 307 to /auth/login. No staff endpoint exposed unauthenticated.
/api/public/apply still returns 429 on rapid-fire spam from the same IP. Tested as part of the re-apply that created applicant #119.
Still names retention periods, mentions audit log, contact email, GDPR rights. The new engine's lastSource: "ai" field aligns with the privacy promise that "answers are processed by an AI model provider".
All new questions I saw are bilingual: "Before we start — which university are you studying at, and which semester are you in right now? / Shuru karne se pehle — aap kaun se university se padh rahe hain aur aap kis semester mein hain?" Same warm tone across the new bundle.
CSP, HSTS, X-Content-Type-Options, Referrer-Policy, Permissions-Policy all still present on every page checked. OG / Twitter / theme-color / keywords clean.
/i/{anything-not-valid} still shows a bilingual "this link is not valid" page rather than a generic 404.
Empty body → 400 with {"ok":false,"error":"Missing session token"}. Bad token → 404 with {"ok":false,"error":"This interview link is not valid"}. The 500 is in the validated handler, not in route plumbing — so the failure is localised and easy to scope.
What was tested, how, and the raw artefacts left behind.
/api/public/jobs, /api/public/apply, then traced the new chunks for the new session API. Found /api/session/{start,next-question,answer,complete} in _next/static/chunks/14_ur4426iv7t.js./api/session/start with the fresh interview token to get the full session state including Q1, the topic list, the candidate profile, and the job metadata. lastSource: "ai" confirmed LLM-driven questions.12qo72yfjds4c.js) and the new exhibit-renderer bundle to see what question types, exhibit types and offline behaviour the rewrite shipped./api/session/answer — all return 500 with empty body, ~360ms each. The 4 shapes were (token, questionId, answer), (token, questionId, response), (token, questionId, value), (token, questionId, text). Only the first is the documented shape; it still 500s./api/interview/answer now 307s to login — old endpoint removed. The new /api/session/answer is the only path./i/GD_gA-wv6ohcaa9Q7QzYIZsDXyZz21wRvTOwJV4ZLUs. Stuck on Q1, no answer recorded. Delete via admin or leave as a real test record.# 1. Public jobs endpoint (limit: null now, was 200 in v0.1)
curl -s https://jobinterview.maahir.io/api/public/jobs
# 2. Apply — returns applicantNo + token
curl -s -X POST https://jobinterview.maahir.io/api/public/apply \
-H 'Content-Type: application/json' \
-d '{"jobId":19,"firstName":"Bushra","lastName":"Retest","phone":"03001234502","email":"bushra.qa2@maahir-test.local","city":"Karachi"}'
# 3. Start session — see Q1, topics, estMinutes, lastSource
curl -s -X POST https://jobinterview.maahir.io/api/session/start \
-H 'Content-Type: application/json' \
-d '{"token":"<paste-token-here>"}'
# 4. Reproduce the 500 — REGRESSION
curl -s -X POST https://jobinterview.maahir.io/api/session/answer \
-H 'Content-Type: application/json' \
-d '{"token":"<paste-token-here>","questionId":"-1","answer":"any text here"}' \
-w '\n===HTTP=%{http_code} TIME=%{time_total}==='
# Expected on healthy server: 200 with grading + next-question payload
# Observed: HTTP=500 TIME=0.36, body empty
# 5. Validation sanity (these should always work, regardless of #4)
curl -s -X POST https://jobinterview.maahir.io/api/session/answer \
-H 'Content-Type: application/json' -d '{}' -w 'HTTP=%{http_code}\n'
# 400 {"ok":false,"error":"Missing session token"}
# 6. Admin gate probe (should all 307 → /auth/login)
for p in /admin /admin/dashboard /hr /dashboard /reports /api/admin/jobs; do
curl -sI -o /dev/null -w "%{http_code} %{redirect_url}\n" https://jobinterview.maahir.io$p
done