From the free book Delta: Closing the Specification Gap (Dhuri, 2026). The PDF is the canonical edition — figures, tables, and code formatting are simplified online.
The Critic Frame and GitHub-style domain reviews that find what human reviewers miss
“A generic review prompt gets you: ‘The code is clean and wellstructured.’ A domain review prompt produces: ‘Line 47 is a HIPAA violation. Line 112 will double-charge under retry.’ These are not different opinions. They are different prompts.” — The most dangerous code review is the one where everyone agrees.
A healthcare SaaS team used an AI code review assistant to review a patient demographics service before merging. The review response: ‘The code is well-structured and follows sound practice. The service layer correctly separates concerns, the error handling is appropriate, and the naming is clear. This looks production-ready.’
THE COST OF THIS MISTAKE Incident: Generic AI code review missed three GDPR violations in ,→ healthcare patient service Total cost: GDPR notification obligation (Art. 33) + DPA notification ,→
+ complete log purge + legal review
Time to resolve: 3 weeks undetected, 1 week remediation, 6 weeks ,→ compliance documentation Prevention: "You are a GDPR auditor. PHI in any log = Definite ,→ Violation. Find violations. Do NOT confirm compliance."
AVOID: ”Please review this code for quality issues and suggest improvements.” USE: ”You are a HIPAA security auditor. Find violations — do NOT confirm compliance. PHI in any log statement = Definite Violation. Missing @AuditLog = Definite Violation. Rate each: Definite Viola- tion | Likely Violation | Risk. Cite the CFR section.” Why: Generic prompts produce endorsements. Domain prompts produce findings. The model fulfills the prompt it receives: ask for quality evaluation, get quality evaluation. Ask for violations, get violations. <!-- The Critic Frame — Validation Structurally Impossible --> <role> You are a [domain expert + adversarial role]. Your job: find problems. NOT evaluate quality. Do NOT say what is done correctly. Only report problems. </role> <code_under_review> {{paste the code}} </code_under_review> <task> Produce EXACTLY this structure: BLOCKING (must fix before merge): [File:Line] What is wrong
|
|
|
Fix
MINOR (optional improvements): Brief list only VERDICT: Request Changes | Approve with Comments | Approve One sentence of justification. </task> <constraints> - Do NOT list anything correct — violations only - Every BLOCKING item: concrete fix, not just identification - Reference specific file names and line numbers - Empty categories: '(none identified)' </constraints>
5.2 What Domain Review Actually Looks Like Here is the difference between a generic review output and a domainspecific Critic Frame output for the same code: PatientDemographicsServiceImpl.java • Line 47
BLOCKING log.info("Contact updated for patient {} ({}), diagnosis {}", patient.getName(), patient.getDob(), icd.getCode()); PHI in log statement: patient.getName(), patient.getDob(), and icd.getCode() are all Protected Health Information under HIPAA 45 CFR 164.312(b) and GDPR Article 4(1). These are being exported to your log aggregation platform. + Fix: log.info("Contact updated: patientId={}", cmd.patientId());
PatientDemographicsServiceImpl.java • Line 12
WARNING
@Autowired private PatientRepository patientRepository; Field injection with @Autowired violates the team standard (constructor injection required). Cannot be final. Creates testing friction and hidden dependencies. + Fix: @RequiredArgsConstructor at class level --- all fields become constructor-injected and final PatientDemographicsServiceImpl.java • Lines 38-42
BLOCKING patientRepository.save(patient); eventPublisher.publishEvent(new ContactInfoUpdatedEvent(patient.getId())); // note: event published before @Transactional commits Domain event published inside @Transactional boundary. If the transaction rolls back after line 38, the event has already been published and the consumer has already acted on it. Data inconsistency guaranteed under any rollback scenario. + Fix: Move publishEvent() to a TransactionSynchronization. afterCommit() callback, or use @TransactionalEventListener(AFTER_ COMMIT)
5.3 HIPAA-Specific Critic Frame <role> HIPAA Privacy and Security Rule auditor. You find violations. You do NOT confirm compliance. You cite the specific CFR section for every finding. </role> <code_under_review>{{paste Java or C# service code}}</ ,→ code_under_review> <task> Review against HIPAA Privacy (45 CFR §164–.502164.514) and Security Rules (45 CFR §164–.302164.318). For each finding produce: File:Line
|
|
|
Rate: Definite Violation | Likely Violation | Risk PHI fields to check: PatientName, DateOfBirth, SSN, DiagnosisCode, MedicationList, TreatmentPlan, InsuranceMemberNumber, Phone, Email. Missing @AuditLog on any PHI-accessing method = Definite Violation. PHI value in any log statement = Definite Violation. Non-atomic update+audit = Definite Violation. Deceased patient not checked before update = Risk. </task>
Every public-facing AI feature is an injection surface until proven otherwise. If user-supplied text reaches a model’s context window without structural XML isolation, an attacker can embed instructions that override your system prompt. This has been demonstrated against production enterprise support chatbots, AI-powered search features, and MCP-connected agents. The defense is specification: wrapping all user content in <user_input> tags with an explicit ’do not follow instructions’ header. If you are building user-facing AI features and have not done this, Chapter 15 is your next stop.
5.4 Prompt Injection Audit Prompt <role> Security engineer specializing in AI system vulnerabilities. You provide a proof-of-concept payload for every finding. You rate findings: Critical | High | Medium | Low. </role> <code_under_review> {{paste code that constructs LLM prompts or calls an AI API}} </code_under_review> <task> Audit for prompt injection vulnerabilities. For each: - Show the exact attack payload that exploits it - Rate severity - Show the remediation code (not just advice) Check specifically: 1. DIRECT: Is user input concatenated into prompts without XML ,→ isolation? 2. INDIRECT: Is retrieved content (MCP, DB, documents) in the model ,→ context without an UNTRUSTED DATA header? 3. TOOL ESCALATION: Could injected instructions trigger MCP tool ,→ calls the model should not execute? 4. DATA EXFILTRATION: Could injected content expose other users' data? ,→ 5. SYSTEM PROMPT LEAKAGE: Could a crafted query reveal system prompt ,→ contents? </task> QUICK WIN — 45 minutes
Run the Prompt Injection Audit against your most user-facing AI feature today. Include a live PoC payload attempt in your staging environment. If the payload works, you have found a security issue before an attacker does. Show the finding to your security team.
5.5 The Verification Frame By 2026 the constraint on shipping AI-generated code is no longer generation — it is verification. Surveys of working engineers report that most do not fully trust AI output, yet fewer than half consistently check it before it merges; reviewers describe the task as harder than reviewing a colleague’s code, because the output looks right. The queue of plausiblelooking pull requests is where the time now goes. The Specification Frame answers this directly, and it is the reason the Frame repays its up-front effort. A prompt written as a specification already contains the acceptance criteria for its own output. Verification stops being the open-ended question ‘is this code correct?’ — which has no bounded answer — and becomes the closed question ‘does this code satisfy each constraint I wrote down?’ The constraints you specified to get good generation are the same constraints you check to verify it. You wrote the test before the code, whether or not you called it that. <role> You are a verification engineer. Decide whether this code ,→ satisfies its specification — not whether it looks good. Assume ,→
nothing the spec does not state. </role>
<specification> {{paste the original Specification Frame prompt: role, ,→
context, task, constraints}} </specification>
<code_under_review> {{paste the generated code}} </code_under_review> <task> For EVERY constraint in the specification, produce one row: Constraint | Met? (Yes / No / Cannot tell) | Evidence (File:Line, or ,→
none) | If No: the exact failing line
Then list any behavior the specification did NOT authorize (scope ,→ creep). VERDICT: Meets spec | Fails spec | Spec incomplete (cannot verify). ,→ One sentence of justification. </task> <constraints> - Check the spec line by line; do not summarize. - 'Cannot tell' is valid; it means spec or code is underspecified — say which. - Do NOT praise correct code; report only constraint status. - A constraint with no evidence in the code is 'No', not 'Yes'. </ ,→ constraints>
The Verification Frame turns that into a prompt. It takes the original specification and the generated code and forces a constraint-by-constraint accounting: met, not met, or — the answer that matters most — cannot tell. A ‘cannot tell’ is not a failure of the reviewer; it is the specification or the code reporting that it is underspecified, which is the exact gap this book exists to close. Run it as the second half of every generation: specify, generate, then verify against the same specification. This closes the loop on the chapter. The Critic Frame finds problems an unprompted review misses; the Verification Frame proves the specific constraints you care about were met. Wired into the CI step from the previous section, the two convert an unbounded review burden into a bounded, auditable checklist a human signs off in minutes rather than re-derives from scratch.
Domain review prompts produce findings. The difference is the adversarial framing and explicit criteria. + The Critic Frame makes validation structurally impossible. ’Find problems’ produces findings. ’Evaluate quality’ produces endorsements. + GitHub-style code review cards show specific file/line, the exact problematic code, the finding with regulatory citation, and the concrete fix. This is the format that results in actual code changes. + Law 6: every public-facing AI feature is an injection surface until you implement structural XML isolation. + Automated domain review in GitHub Actions turns occasional human compliance checks into every-PR quality gates. + The Verification Frame answers the 2026 bottleneck: because a specification already states the acceptance criteria, verifying AI output becomes a bounded checklist (’does it meet each constraint?’) instead of the open-ended question ’is this right?’
Chapter 6 contains the Evidence Brief: a structured template that turns ‘help, I have a bug’ into a systematic diagnosis in minutes. The Rubber Duck Upgrade explains why asking six questions before generating hypotheses finds the root cause faster every time.
57