Beyond the page

AI Engineering Maturity (Systems)

Who this questionnaire is for
Engineering teams, ML engineers, platform teams, and technical leads building or operating AI systems.

What it assesses
The technical maturity of AI systems — including evaluation practices, failure-path testing, monitoring, logging, drift detection, and separation of retrieval vs reasoning.

How it helps
This questionnaire reveals whether systems are engineered for reliability, not just demos. It identifies gaps that allow behaviour to drift between releases, obscure failures, or prevent effective debugging and audit review. Results help teams prioritise engineering work that directly improves trustworthiness and operational resilience.

Best used when

  • Preparing systems for production
  • Investigating unexplained failures or regressions
  • Strengthening monitoring and evaluation pipelines
/* Force clickability under aggressive themes */ #oyez-ai-engineering-maturity{ position:relative !important; z-index:2147483647 !important; pointer-events:auto !important; isolation:isolate; } #oyez-ai-engineering-maturity, #oyez-ai-engineering-maturity *{ pointer-events:auto !important; } #oyez-ai-engineering-maturity{font:inherit;color:inherit;max-width:980px;margin:0 auto} #oyez-ai-engineering-maturity *{box-sizing:border-box} #oyez-ai-engineering-maturity .q-wrap{ border:1px solid rgba(0,0,0,.12); border-radius:18px; padding:18px 18px 12px; background:rgba(255,255,255,.82); backdrop-filter:saturate(1.15) blur(10px); box-shadow:0 18px 55px rgba(0,0,0,.10); position:relative; } #oyez-ai-engineering-maturity h1{font-size:28px;line-height:1.15;margin:0 0 6px;letter-spacing:-.02em} #oyez-ai-engineering-maturity .sub{opacity:.82;margin:0 0 14px;font-size:14px;line-height:1.45} #oyez-ai-engineering-maturity .bar{height:10px;border-radius:999px;border:1px solid rgba(0,0,0,.14);overflow:hidden;background:rgba(0,0,0,.04);margin:10px 0 14px} #oyez-ai-engineering-maturity .bar > div{height:100%;width:0%;background:linear-gradient(90deg, rgba(0,0,0,.88), rgba(0,0,0,.62));transition:width .22s ease} #oyez-ai-engineering-maturity .pillrow{display:flex;flex-wrap:wrap;gap:8px;margin:6px 0 12px} #oyez-ai-engineering-maturity .pill{ display:inline-flex;align-items:center;gap:8px;padding:7px 10px;border-radius:999px; border:1px solid rgba(0,0,0,.14);background:rgba(255,255,255,.94); font-size:12px;white-space:nowrap;box-shadow:0 10px 24px rgba(0,0,0,.07) } #oyez-ai-engineering-maturity .pill b{font-weight:750} #oyez-ai-engineering-maturity .note{font-size:13px;opacity:.85;line-height:1.5;margin:0 0 10px} /* Meta grid (make org wide) */ #oyez-ai-engineering-maturity .meta{display:grid;grid-template-columns:repeat(12,1fr);gap:10px;margin:14px 0 10px} #oyez-ai-engineering-maturity label{display:block;font-weight:650;font-size:13px;margin:0 0 6px} #oyez-ai-engineering-maturity input[type=”text”], #oyez-ai-engineering-maturity select{ width:100%;padding:10px 10px;border-radius:12px;border:1px solid rgba(0,0,0,.16); background:rgba(255,255,255,.96);font:inherit;font-size:14px;line-height:1.35;outline:none; box-shadow:0 10px 22px rgba(0,0,0,.06) } #oyez-ai-engineering-maturity .span-4{grid-column:span 4} #oyez-ai-engineering-maturity .span-8{grid-column:span 8} #oyez-ai-engineering-maturity .span-12{grid-column:span 12} @media (max-width:860px){ #oyez-ai-engineering-maturity .meta{grid-template-columns:repeat(6,1fr)} #oyez-ai-engineering-maturity .span-4, #oyez-ai-engineering-maturity .span-8{grid-column:span 6} } /* Big score row */ #oyez-ai-engineering-maturity .scoreRow{display:flex;gap:12px;flex-wrap:wrap;align-items:stretch;margin:12px 0 6px} #oyez-ai-engineering-maturity .scoreBox{ flex:0 0 auto;min-width:220px; border:1px solid rgba(0,0,0,.12);border-radius:16px;background:#fff; padding:12px;box-shadow:0 16px 40px rgba(0,0,0,.09) } #oyez-ai-engineering-maturity .scoreLabel{font-size:13px;opacity:.78} #oyez-ai-engineering-maturity .scoreBig{font-size:42px;font-weight:900;line-height:1;margin-top:6px} #oyez-ai-engineering-maturity .scoreMax{font-size:13px;opacity:.78;margin-top:4px} #oyez-ai-engineering-maturity .tierBox{ flex:1;min-width:260px; border:1px solid rgba(0,0,0,.12);border-radius:16px;background:#fff; padding:12px;box-shadow:0 16px 40px rgba(0,0,0,.09) } #oyez-ai-engineering-maturity .tierLabel{font-size:13px;opacity:.78} #oyez-ai-engineering-maturity .tierVal{font-size:18px;font-weight:900;margin-top:6px} #oyez-ai-engineering-maturity .tierNote{font-size:13px;opacity:.82;line-height:1.45;margin-top:6px} /* Sections + questions */ #oyez-ai-engineering-maturity .sec{border-top:1px solid rgba(0,0,0,.12);padding:14px 0 6px} #oyez-ai-engineering-maturity .sec h2{font-size:18px;margin:0 0 8px} #oyez-ai-engineering-maturity .q{ border:1px solid rgba(0,0,0,.12); border-radius:16px; padding:12px; background:rgba(255,255,255,.97); margin:10px 0; box-shadow:0 14px 34px rgba(0,0,0,.07) } #oyez-ai-engineering-maturity .qtitle{display:flex;gap:10px;align-items:flex-start;justify-content:space-between} #oyez-ai-engineering-maturity .qtitle h3{font-size:15px;margin:0;line-height:1.35} #oyez-ai-engineering-maturity .tag{ font-size:11px;opacity:.72;border:1px solid rgba(0,0,0,.12); padding:4px 8px;border-radius:999px;white-space:nowrap;background:#fff } #oyez-ai-engineering-maturity .help{font-size:13px;opacity:.78;margin:6px 0 10px;line-height:1.45} /* Options as premium tiles */ #oyez-ai-engineering-maturity .opts{display:grid;grid-template-columns:repeat(12,1fr);gap:10px} #oyez-ai-engineering-maturity .opt{ grid-column:span 6; border:1px solid rgba(0,0,0,.12); border-radius:16px; padding:12px; background:#fff; box-shadow:0 14px 34px rgba(0,0,0,.06); transition:transform .06s ease, box-shadow .12s ease, border-color .12s ease; cursor:pointer; display:flex;gap:10px;align-items:flex-start; } #oyez-ai-engineering-maturity .opt:hover{transform:translateY(-1px);box-shadow:0 18px 42px rgba(0,0,0,.10)} #oyez-ai-engineering-maturity .opt input[type=”radio”]{margin-top:3px;transform:scale(1.05);flex:0 0 auto;} #oyez-ai-engineering-maturity .opt .txt strong{display:block;font-size:13px} #oyez-ai-engineering-maturity .opt .txt span{display:block;font-size:12px;opacity:.78;margin-top:4px;line-height:1.35} #oyez-ai-engineering-maturity .opt.selected{border-color:rgba(0,0,0,.35);box-shadow:0 22px 55px rgba(0,0,0,.13)} @media (max-width:860px){#oyez-ai-engineering-maturity .opt{grid-column:span 12}} /* Actions + results */ #oyez-ai-engineering-maturity .actions{ display:flex;flex-wrap:wrap;gap:10px;margin:14px 0 6px; position:relative;z-index:2147483647; } #oyez-ai-engineering-maturity button{ border-radius:12px;border:1px solid rgba(0,0,0,.18); padding:10px 12px;background:#fff;cursor:pointer; font:inherit;font-weight:850;font-size:14px; box-shadow:0 14px 34px rgba(0,0,0,.09); } #oyez-ai-engineering-maturity button.primary{background:rgba(0,0,0,.9);color:#fff;border-color:rgba(0,0,0,.9)} #oyez-ai-engineering-maturity button:disabled{opacity:.55;cursor:not-allowed;box-shadow:none} #oyez-ai-engineering-maturity .results{border-top:1px solid rgba(0,0,0,.12);margin-top:10px;padding-top:14px} #oyez-ai-engineering-maturity .rgrid{display:grid;grid-template-columns:repeat(12,1fr);gap:10px} #oyez-ai-engineering-maturity .card{grid-column:span 6;border:1px solid rgba(0,0,0,.12);border-radius:16px;background:#fff;padding:12px;box-shadow:0 16px 40px rgba(0,0,0,.09)} #oyez-ai-engineering-maturity .card.full{grid-column:span 12} #oyez-ai-engineering-maturity .card h4{margin:0 0 6px;font-size:14px} #oyez-ai-engineering-maturity .big{font-size:22px;font-weight:900;line-height:1.2;margin:0} #oyez-ai-engineering-maturity .muted{font-size:13px;opacity:.78;line-height:1.45;margin:6px 0 0} #oyez-ai-engineering-maturity .list{margin:8px 0 0;padding-left:18px;font-size:13px;line-height:1.45} #oyez-ai-engineering-maturity .footer{margin:10px 0 6px;font-size:12px;opacity:.7;line-height:1.45}

AI Engineering Maturity (Systems)

Scores automatically as you click. The top fields are optional — only the questions affect scoring.

Status: Not scored Coverage: 0% Score: — Decision: —

Optional fields: these help with internal benchmarking, but are not required to score.

Your role (optional) — Select role — Engineering ML / Applied AI Data Platform / Infra Product / Operations Risk / Governance / Compliance Other
Company or project identifier (optional)
Your score
0
out of 45
Maturity
—
Answer the questions to see your maturity level.

Section A — Tasking, Retrieval & Data Discipline

1) Are tasks typed and routed (e.g., summarise vs extract vs decide) with different policies and prompts?

Tasking
Typed task routing reduces policy drift and allows stage-specific controls.
No — single prompt pathEverything runs through one generic prompt and policy path.
Some task typingOnly a few routes exist; coverage is incomplete.
Most tasks typed and routedMost tasks have explicit routes/policies.
Fully typed + tested + enforcedRouting is tested and enforced in production.

2) Is retrieval constrained to approved sources (domain/corpus allowlist) with metadata filters?

Retrieval
Allowlists + metadata filters are the core anti-hallucination infrastructure.
NoRetrieval pulls from broad sources without enforceable constraints.
Partially (some filters)Some filters exist, but allowlisting is incomplete.
Mostly (allowlist + filters)Most retrieval is constrained to approved corpora and filtered.
Enforced end-to-endAllowlists/filters are enforced end-to-end and tested.

3) Do you control freshness (document dates, snapshots, versioning) and prevent outdated retrieval?

Freshness
Freshness control prevents “quiet outdated truth” in deployed systems.
NoNo reliable control of snapshot/version/freshness.
Ad-hocManual processes exist; behaviour is inconsistent.
Mostly controlledSnapshots/versioning are used for key corpora.
Controlled + monitoredFreshness is controlled and monitored for regressions.

4) Do you store retrieval context (top-k, scores, chunk IDs) per response for audit/debug?

Provenance
Per-response top-k capture is the minimum viable audit trail for RAG.
NoNo retrieval context is stored per response.
Partial loggingSome responses store partial retrieval context.
Most responses loggedMost responses capture top-k and IDs.
Always logged + exportableAlways captured and exportable for audits/incidents.

5) Are prompts/tools treated as code (reviews, tests, versioning, rollback)?

Change control
Prompt/tool changes are production changes. Treat them as code changes.
NoNo review/test/versioning discipline for prompts/tools.
Some versioningSome versioning exists; review/testing is limited.
Reviews + rollback existReview and rollback paths exist, but aren’t comprehensive.
CI-style checks + approvals + rollbackChanges pass CI-style checks with approvals and rollback.

Section B — Verification, Refusal & Safety Behaviour

6) Does the system reliably refuse or defer when evidence is missing or contradictory?

Refusal
Reliable refusal is a safety feature and a trust feature.
NoAnswers are returned even without evidence.
SometimesRefusals happen, but behaviour is inconsistent.
UsuallyMost missing/contradictory cases result in refusal/defer.
Enforced + testedRefusal behaviour is enforced and regression-tested.

7) Are there automated checks (schema, citation presence, groundedness, policy gates) before returning an answer?

Gates
Hard gates prevent “looks plausible” output from escaping into production.
NoNo automated checks run before returning outputs.
One or two checksA small number of checks exist (not comprehensive).
Several checksMultiple checks exist, but coverage/logging may be incomplete.
Comprehensive + logged outcomesChecks are comprehensive and logged per response.

8) Do you separate retrieval quality from reasoning quality in evaluation (stage-separated metrics)?

Metrics
Stage-separated metrics tell you if failures come from RAG or reasoning.
NoEvaluation is not stage-separated.
PartiallySome separation exists, but not systematic.
MostlyRetrieval vs reasoning are usually separated.
Fully + continuousStage-separated evaluation is continuous and tracked.

9) Are “high-stakes” requests detected and handled with stronger controls (human review, higher refusal threshold, stricter evidence)?

High-stakes
High-stakes requires detection + stronger controls, not only policy text.
NoNo high-stakes detection/handling exists.
InformalSome extra care exists, but it’s not enforced.
Defined handlingHandling is defined by tier, with some enforcement.
Enforced + auditedEnforced in code and audited with evidence.

10) Can the system produce an answer trace (what it used, what checks ran, and why it answered/refused)?

Trace
Traces are the glue between engineering observability and governance evidence.
NoNo traces are produced for outputs.
Partial tracesSome traces exist, but are incomplete or inconsistent.
Most outputs tracedMost outputs include usable traces.
Fully traced + exportableTraces are consistent and exportable.

Section C — Observability, Drift & Operations

11) Do you monitor key runtime signals (refusal rate, verification pass rate, latency, tool errors) with alerting?

Ops
Without alerting and ownership, dashboards are decorative.
NoNo monitoring of key runtime signals exists.
Basic dashboardsDashboards exist, but alerting/ownership is missing.
Dashboards + regular reviewReview cadence exists; alerting may be partial.
Alerting + SLOs + ownershipAlerts, SLOs, and ownership are defined and used.

12) Do you test failure paths (empty retrieval, conflicts, prompt injection, tool failure) before release?

Testing
Failure-path tests prevent “it worked in the demo” deployments.
NoNo consistent failure-path testing exists.
OccasionallySome tests exist, but not systematic or enforced.
UsuallyMost releases include failure-path testing.
Always + regression suiteFailure paths are in a regression suite and always run.

13) Do you run structured evaluations on representative tasks before/after changes (not just ad-hoc demos)?

Eval
Structured evaluation makes changes measurable and reversible.
NoNo structured evaluation exists.
OccasionallySome evaluation exists, but coverage is limited.
Before major releasesStructured eval runs before major releases.
Continuous evaluation + drift trackingContinuous evaluation + drift tracking is in place.

14) Is there an incident loop with rollback, postmortems, and documented remediation?

IR
Incident discipline is a maturity marker: rollback + learning loop.
NoNo incident loop exists for AI behaviour changes/failures.
InformalSome response exists, but postmortems/rollback are inconsistent.
DocumentedIncident loop is documented and used sometimes.
Practiced + measurable outcomesPracticed with measurable remediation outcomes.

15) Are logs structured and exportable for audit (inputs, retrieval, checks, outputs, versions)?

Logs
Exportable structured logs connect engineering truth to audit evidence.
NoLogs are missing or not structured for audit/exports.
Partial logsSome pieces exist, but not end-to-end or exportable.
Mostly exportableMost key events are logged and exportable.
Fully exportable + retention policyFully exportable logs with retention/access governance.

Tip: When engineering and governance disagree on maturity, it usually means controls exist but are not enforced or not measurable.

(function(){ function init(){ const qRoot = document.getElementById(‘oyez-ai-engineering-maturity’); if(!qRoot) return false; if(qRoot.__oyezInit) return true; qRoot.__oyezInit = true; const MAX = 45; const TOTAL_Q = 15; const bar = qRoot.querySelector(‘#oyezEngBar’); const statusEl = qRoot.querySelector(‘#oyezEngStatus’); const coverageEl = qRoot.querySelector(‘#oyezEngCoverage’); const scorePillEl = qRoot.querySelector(‘#oyezEngScorePill’); const decisionEl = qRoot.querySelector(‘#oyezEngDecision’); const scoreBigEl = qRoot.querySelector(‘#oyezEngScoreBig’); const maturityTopEl = qRoot.querySelector(‘#oyezEngMaturityTop’); const maturityTopNoteEl = qRoot.querySelector(‘#oyezEngMaturityTopNote’); const calcBtn = qRoot.querySelector(‘#oyezEngCalc’); const copyBtn = qRoot.querySelector(‘#oyezEngCopy’); const emailBtn = qRoot.querySelector(‘#oyezEngEmail’); const resetBtn = qRoot.querySelector(‘#oyezEngReset’); const results = qRoot.querySelector(‘#oyezEngResults’); const maturityEl = qRoot.querySelector(‘#oyezEngMaturity’); const maturityNoteEl = qRoot.querySelector(‘#oyezEngMaturityNote’); const recEl = qRoot.querySelector(‘#oyezEngRec’); const recDescEl = qRoot.querySelector(‘#oyezEngRecDesc’); const risksEl = qRoot.querySelector(‘#oyezEngRisks’); const nextEl = qRoot.querySelector(‘#oyezEngNext’); const meta = { role: qRoot.querySelector(‘#oyezEngRole’), org: qRoot.querySelector(‘#oyezEngOrg’), }; const questions = Array.from({length: TOTAL_Q}, (_,i)=>`q${i+1}`); function updateSelected(){ qRoot.querySelectorAll(‘.opt’).forEach(opt=>{ const r = opt.querySelector(‘input[type=”radio”]’); opt.classList.toggle(‘selected’, !!(r && r.checked)); }); } function answeredCount(){ let n=0; for(const q of questions){ if(qRoot.querySelector(`input[name=”${q}”]:checked`)) n++; } return n; } function getScore(){ let total=0; for(const q of questions){ const picked = qRoot.querySelector(`input[name=”${q}”]:checked`); if(picked) total += parseInt(picked.value,10); } return total; } function pickValue(qNum){ const picked = qRoot.querySelector(`input[name=”q${qNum}”]:checked`); return picked ? parseInt(picked.value,10) : null; } function maturityFromScore(s){ if (s<=15) return 'Prototype'; if (s<=30) return 'Production'; return 'Assured'; } function statusFromCoverage(ans){ if (ans===0) return 'Not scored'; if (ans<TOTAL_Q) return 'In progress'; return 'Completed'; } function packFor(m){ const packs = { Prototype: { note: 'You can build useful pilots, but reliability will collapse under scale without enforced retrieval constraints and verification.', risks: [ 'No strong refusal/verification means silent hallucinations will reach users.', 'Retrieval may leak outdated or unapproved sources.', 'Observability gaps will prevent debugging and regression control.' ], next: [ 'Add enforceable allowlists + metadata filters, and log retrieval top-k per response.', 'Implement at least one hard gate: citation/evidence presence + refuse when missing.', 'Treat prompts/tools as code: reviews, versioning, and rollback.' ] }, Production: { note: 'You have a deployable system. Your risk is inconsistent enforcement and weak drift discipline over time.', risks: [ 'Controls exist but are not regression-tested; behaviour can drift release-to-release.', 'Monitoring may exist without alert ownership or SLOs.', 'High-stakes handling may be policy-only rather than system-enforced.' ], next: [ 'Build a failure-path regression suite (empty retrieval, contradictions, injection, tool failure).', 'Separate retrieval metrics vs reasoning metrics and track both over time.', 'Add structured, exportable logs: inputs, retrieval, checks, outputs, versions.' ] }, Assured: { note: 'You have strong engineering discipline and are positioned to scale. Your risk is complexity outpacing auditability.', risks: [ 'Multiple components may make traces inconsistent unless standardised.', 'Rapid iteration can outpace evaluation and approvals.', 'Audit readiness can degrade without retention and periodic review.' ], next: [ 'Standardise trace schemas across services and enforce per-response provenance capture.', 'Run continuous evaluation and drift monitoring with alerting and owner SLAs.', 'Operationalise postmortems and quarterly control reviews.' ] } }; return packs[m]; } // Decision + critical gaps for engineering: // retrieval allowlist (Q2), retrieval logging (Q4), // gates/checks (Q7), traceability (Q10), exportable logs (Q15). function decisionFrom(maturity, answered){ if (answered===0) return '—'; if (answered pickValue(q) === 0); if (criticalFail) return ‘Hold (critical gap)’; if (maturity===’Prototype’) return ‘Hold (build controls)’; if (maturity===’Production’) return ‘Ship with mitigations’; return ‘Ship / Scale’; } function compute(){ updateSelected(); const answered = answeredCount(); const coverage = Math.round((answered/TOTAL_Q)*100); const score = getScore(); const maturity = maturityFromScore(score); const status = statusFromCoverage(answered); const decision = decisionFrom(maturity, answered); const pack = packFor(maturity); // Coverage bar bar.style.width = coverage + ‘%’; // Pills statusEl.textContent = status; coverageEl.textContent = coverage + ‘%’; scorePillEl.textContent = answered ? `${score}/45` : ‘—’; decisionEl.textContent = answered ? decision : ‘—’; // Big score + top maturity scoreBigEl.textContent = score; maturityTopEl.textContent = answered ? maturity : ‘—’; maturityTopNoteEl.textContent = answered ? pack.note : ‘Answer the questions to see your maturity level.’; // Results panel let recLabel=’—’, recText=’—’; if(answered>0 && answered{ const li=document.createElement(‘li’); li.textContent=t; risksEl.appendChild(li); }); pack.next.forEach(t=>{ const li=document.createElement(‘li’); li.textContent=t; nextEl.appendChild(li); }); } results.style.display = answered ? ‘block’ : ‘none’; copyBtn.disabled = (answered===0); emailBtn.disabled = (answered===0); return {answered,coverage,score,maturity,status,decision,pack,recLabel,recText}; } function buildSummary(state){ const lines=[]; lines.push(‘OYEZ — AI Engineering Maturity (Systems)’); lines.push(‘————————————–‘); lines.push(`Role: ${meta.role.value || ‘—’}`); lines.push(`Company / Project: ${meta.org.value || ‘—’}`); lines.push(”); lines.push(`Status: ${state.status}`); lines.push(`Coverage: ${state.coverage}% (${state.answered}/${TOTAL_Q})`); lines.push(`Score: ${state.score}/45`); lines.push(`Maturity: ${state.maturity}`); lines.push(`Decision: ${state.decision}`); lines.push(”); lines.push(‘Top risks:’); state.pack.risks.forEach((r,i)=>lines.push(`${i+1}. ${r}`)); lines.push(”); lines.push(‘Recommended next steps:’); state.pack.next.forEach((n,i)=>lines.push(`${i+1}. ${n}`)); return lines.join(‘\n’); } // Auto-score on every click qRoot.addEventListener(‘change’, function(e){ if(e.target && e.target.matches(‘input[type=”radio”]’)) compute(); }); calcBtn.addEventListener(‘click’, function(e){ e.preventDefault(); compute(); }); copyBtn.addEventListener(‘click’, async function(e){ e.preventDefault(); const state = compute(); if(!state.answered) return; const text = buildSummary(state); try{ await navigator.clipboard.writeText(text); copyBtn.textContent=’Copied’; setTimeout(()=>copyBtn.textContent=’Copy Summary’, 900); } catch(err){ const ta=document.createElement(‘textarea’); ta.value=text; document.body.appendChild(ta); ta.select(); document.execCommand(‘copy’); document.body.removeChild(ta); copyBtn.textContent=’Copied’; setTimeout(()=>copyBtn.textContent=’Copy Summary’, 900); } }); emailBtn.addEventListener(‘click’, function(e){ e.preventDefault(); const state = compute(); if(!state.answered) return; const subject = encodeURIComponent(`Oyez — AI Engineering Maturity (${state.maturity}, ${state.score}/45)`); const body = encodeURIComponent(buildSummary(state)); window.location.href = `mailto:?subject=${subject}&body=${body}`; }); resetBtn.addEventListener(‘click’, function(e){ e.preventDefault(); qRoot.querySelectorAll(‘input[type=”radio”]’).forEach(r=>r.checked=false); if(meta.role) meta.role.value=”; if(meta.org) meta.org.value=”; compute(); copyBtn.disabled=true; emailBtn.disabled=true; }); compute(); return true; } // Init now, then retry (WP may execute scripts before block renders) if(!init()){ let tries = 0; const t = setInterval(()=>{ tries++; if(init() || tries>=50) clearInterval(t); }, 100); } })();