Technical prototype portfolio — demonstration environment.
Working demonstrations of document extraction, structured transformation and validation workflows. Explore the methods, sample outputs and limitations behind selected prototypes.
These prototypes explore extraction, transformation and quality-control workflows. Each documented demonstration identifies its inputs, processing steps, implemented checks, human decisions and known limitations. Test evidence is scoped to the cases and versions reported; it does not establish production readiness.
Of the 54 prototypes below, these five are fully documented end to end — inputs, pipeline, validation discipline, committed test evidence, and known limitations, all in one place in §08. Start with these; the full 54-row catalog in §02 is supporting detail for everything else in the portfolio.
Most prototypes in this portfolio follow the same loop: an AI-assisted step proposes a result, something real — deterministic code, an independently re-read source document, a genuine third-party signal — checks it, and a human decides before anything ships. A number of them skip the AI step entirely: the task is deterministic from the start (a schema check, a geometric comparison, a record match), with no model call anywhere in the path. Either way, a human reviews the result before anything is exported — whether unresolved findings also block the export itself varies by app; see §AC-07 in §09.
This is the opposite of an AI demo that asks you to trust the model's output on faith. Every prototype below names, specifically, what checks its AI layer — and in several cases, that same discipline caught an issue during development and fixed it before anything was ever wired into a review screen.
Supporting detail beyond the five featured demonstrations above — the full catalog of everything else this portfolio covers. Each row is live right now at the path shown, under poc.chrisianinc.com. Every demo runs its own bundled synthetic sample with one click — none accepts a real file, a pasted document, or an arbitrary request; that's the fastest way to judge fit without putting any real content anywhere near it. Grouped by capability below, not alphabetically — the five featured demonstrations documented in full in §08 appear here too, in their own category, with a link back to their detail page.
Availability — every row below is a live, running demo at the path shown; that's the one status this catalog asserts uniformly for all 54. Prototype maturity and production readiness are not rated per row here — no app in this broad catalog has been scored against a maturity rubric, and none is claimed production-ready. Evidence status (Implemented / Tested / Described / Proposed) is only documented to the §08 standard for the five featured demonstrations; the "Implemented Checks and Limits" column below describes what each app's own README and source claim, not an independently re-verified fact for all 54 — see §08 for the five that have been re-verified this pass.
Getting content or structured data out of a source document, site, or live feed.
| Prototype | Capabilities Demonstrated | Implemented Checks and Limits |
|---|---|---|
| Web Data Collection | Web Scraping; Data Collection from Websites | robots.txt respected; low-confidence extractions flagged for review; 3 bundled sample jobs (Wikipedia, Google Patents, PR Newswire) run with one click |
| OCR Digitization | OCR Capability (NDA Documents); Data Digitization & Conversion | Real Tesseract OCR confidence score, not a model's self-report |
| Academic PDF Parsing (full §08 detail page) | Academic PDF Parsing | No AI in the structure pass — a real deterministic pass finds a paper's section headings, reference list, and figure/table captions from the file's own real extracted text, with references split on a real [N] marker so a wrapped entry still reads as one; Claude adds a one-sentence description per real section, matched verbatim back to the real heading list, with a paraphrase or invented heading dropped and counted rather than shown |
| Patent Litigation Collection | Patent Litigation Data Collection | Verified against a real SEC EDGAR filing, not an invented one: a no-AI section-locator finds the real litigation-disclosure heading in a live-fetched document; Claude reports every distinct patent-litigation matter (a district-court suit, an ITC Section 337 investigation, a PTAB proceeding); a real, closed list of all 94 federal judicial districts plus ITC/PTAB/Federal Circuit independently validates every forum; every patent number is checked for valid format and separately cross-checked against its own record's quoted anchor text, catching a claim anchor-verification alone would miss |
| Court Document Collection | Court Document Collection | Fetches a real U.S. court opinion live from govinfo.gov's official "United States Courts Opinions" collection via its real public REST API — real structured metadata (court, parties with real roles, case number) straight from the government's own fields; Claude's one job is identifying the real disposition from the real opinion PDF text, independently re-verified against a real closed vocabulary and the opinion's own anchor text, with every party role in the real API response separately checked against a real, closed list of standard U.S. court-party roles |
Converting a document from one format or structure into another.
| Prototype | Capabilities Demonstrated | Implemented Checks and Limits |
|---|---|---|
| Document Conversion Pipeline | eBooks/ePub Conversion; Digital Content Transformation; Word/XML Conversion | Output checked against independently re-read source document stats |
| Back of the Book Indexing | Back of the book indexing | Real term-frequency analysis with real page numbers; AI-suggested conceptual topics are verified against the real page they claim to be on |
| Citation Normalization | Citation Normalization | A regex parser built from a known set of U.S. case-law reporter abbreviations extracts and reformats citations; every normalization is re-parsed and compared component-by-component against the original |
| Case Summarization | Case Summarization | Claude structures a case into standard brief sections; every point cites a quote checked against the real source — an unverifiable claim is flagged, not hidden |
| EPUB3 & DocBook Conversion | Convert epub2 to Accessible ePub3; Convert word into dtd specific xml file | No AI step — a real EPUB2 archive's own NCX and OPF are read and rebuilt into a real EPUB3 package (real nav.xhtml, real accessibility metadata); a real DOCX is mapped into genuine DocBook 5 XML with correctly nested sections; both outputs are independently re-parsed and checked against the source |
| Document Diff | Read against reprint; AI – Edition Evolution Analyzer | A real word-level diff (not an AI guess at what changed) finds every real edit between two document versions; Claude classifies each edit, and the classification is checked — a count mismatch, an uncategorized-edit check, and an independent word-count reconciliation between the two full real texts, so a demo-scoped processing limit can never masquerade as a diffing bug |
| Lease Abstraction (full §08 detail page) | Lease Abstraction | Case Summarization's anchor-verified extraction pattern applied to a real lease-specific field schema (Parties, Premises, Lease Term, Base Rent, Rent Escalation, Renewal Options, Termination Clauses, Security Deposit), plus real lease-domain checks a generic extractor doesn't have — a real lease-term end date after the start, a Rent Escalation schedule checked for a real decrease, a Security Deposit checked against Base Rent for a plausible ratio, and coverage of the fields every real lease states |
| Semantic Tagging & Linking (full §08 detail page) | Semantic Tagging/Linking | Text Annotation's proven schema-constrained tagging, plus the real "linking" half it never built: Claude proposes pairs of genuinely related items, each required to quote a real supporting phrase from both sides; every link is independently re-verified, with a link to a nonexistent item, a self-link, an unverified anchor, or a duplicate pair dropped and counted before a reviewer sees it. A real, AI-free lexical-overlap score is shown alongside every link as a transparency signal, never used to reject a genuinely related pair |
| OA Journal JATS/NLM Conversion (full §08 detail page) | OA Journal JATS/NLM Publishing | Converts a real .docx manuscript into the real NISO JATS 1.3 Archiving and Interchange Tag Set, a different, specific XML vocabulary from DocBook used by PubMed Central and open-access journals; the generated XML is validated against the real, official JATS 1.3 XSD schema from NLM/NCBI, checked via a real libxml2 build (xmllint-wasm), not a hand-built approximation. Claude's one job is classifying each reference's real publication type, independently re-checked against the real JATS Tag Library's controlled vocabulary (the XSD itself leaves that attribute unconstrained) and the citation's own anchor text |
| Abstract & Keywords Generation | Gen AI – Abstract and Keywords Generation | Claude writes a generic abstract and keyword list for any document, not a structured legal brief; every keyword is independently re-verified as a real, verbatim substring of the source text, with a case/whitespace-variant repeat caught as a duplicate, and the abstract is separately checked for a real compression-ratio bound and for any standalone number it states that doesn't actually appear in the source |
| Abstract Translation Fidelity | Creation/Translation of non-English abstracts | Claude translates a pasted English abstract into a real target language, then translates that output back into English without ever seeing the original — a blind round trip so the check is genuine, not an echo; every number in the original is checked against the back-translation, with a real length-ratio bound and a lexical-overlap transparency signal rounding out the check |
| Auto Pagination | Auto pagination for XML and Word workflow | No AI step — every real page break comes from actually rendering the uploaded .docx through LibreOffice Writer, the same real engine PowerPoint/Word Accessibility Audits already use; every real Word heading is matched to the real page it first appears on, and the same verified page numbers are applied to a paginated XML skeleton too |
| Typesetting | Typesetting | Not a checker — the first app in this portfolio to actually apply a real template (page size, margins, default body font) directly to a .docx's own OOXML and write a new file, independently re-verified three separate ways including a real LibreOffice open/convert attempt |
| Maps Digitization | Maps Digitization (POI, Geo Rectification, Geo Referencing, Geo Tagging) | No AI step — a real affine transform fit by least squares from operator-given control points, independently re-checked via real meter-converted residuals, exported as a real standard GIS world file, and used to convert real points of interest into real GeoJSON |
| ePDF/Web PDF Conversion | ePDF/Web PDF Conversion | No AI step — a real .docx converted to a real PDF with LibreOffice Writer, independently checked by three separate tools: real source vs. output word counts, real page count, and real per-font embedding via poppler |
| XML Updating | XML Updating | No AI step — real XPath-targeted updates against the document's own structure, each immediately re-validated against its own real XSD schema (xmllint-wasm) and rolled back on the spot if it would break validity; an XPath matching zero or more than one real node is rejected rather than guessed at |
| Tabling | Tabling | Claude organizes free-text content into an operator-defined, multi-column table, every value required to carry a real verbatim quote from the source — independently checked against the real source before a reviewer sees it, with an unverified quote, an empty value, or a column outside the defined structure caught and flagged |
Auditing a document's real structure, accessibility, or composition against a spec or standard.
| Prototype | Capabilities Demonstrated | Implemented Checks and Limits |
|---|---|---|
| Accessibility Compliance Checker | PDF Accessibility; Accessibility Audit – PDF | Reads the PDF's real tag structure, not visual appearance; 11 bundled samples, each built to trigger one specific check |
| PowerPoint Accessibility Audit | Accessibility Audit - PowerPoint Presentation | Reads the deck's real Office Open XML — title placeholders, alt text, not visual appearance; 7 bundled samples |
| Word Accessibility Audit | Accessibility Audit - Word Document | Reads the document's real heading styles and header-row markers, not visual appearance; 9 bundled samples |
| Closed Captioning | Accessibility - Closed Captioning (CC) Text | Real local Whisper speech recognition (no API call) with timing; caption-format QC against published broadcast guidelines, in plain code |
| Audio Description | Accessibility - Audio Description (AD) | Real silence detection finds narration gaps; real text-to-speech measures whether Claude's proposed description actually fits, not a model self-estimate |
| Alt Text Generator | AltText - English/Non-English (AI enabled) | Deterministic QC (length, redundant "image of" phrasing, empty text, filename-as-text) checks every AI draft before a reviewer sees it |
| Courseware Accessibility Compliance | Courseware Accessibility Compliance; Courseware Translation & Localization | A real SCORM package's own manifest is read to find each real content page, each one checked for declared language, page title, image alt text, and heading structure (no AI step) — plus an optional real translation pass: Claude translates each page's text and alt text, the output is independently verified against the source, then re-checked by the same real rules |
| Document Score | AI – Document Score | A single real whole-document score (0-100), not a per-field confidence number — combines real exact-phrase checklist coverage, real Flesch Reading Ease readability from the document's own real word/sentence/syllable counts, and a consistency score penalizing real, anchor-verified contradictions Claude finds and quotes, with a fabricated quote dropped and counted rather than shown; the combination is independently recomputed from the three stored sub-scores before being trusted |
| Research Integrity Support | Research Integrity Support | No AI for the two criteria this line names specifically — a real difference hash of each uploaded image's own pixel data, compared against every other image in every real orientation (flipped, rotated 180°), catches a reused or duplicated figure; two real exact arithmetic checks recompute a stated count/percentage triple and check a percentage breakdown against 100%. Claude adds disclosure-statement screening corroborated by an independent keyword search, and numeric-contradiction detection anchor-verified on both quotes |
| Image Duplication Checker | Image Duplication Checker | Checks a PDF's own embedded image objects, extracted directly via poppler's pdfimages, or a directly-uploaded image set, for real duplicates using a real perceptual difference hash in every real orientation (as uploaded, flipped, rotated 180°) — reusing Research Integrity Support's own proven hashing engine, generalized beyond its single-manuscript scope |
| PDF Composition and QC | PDF Composition and QC | No AI step — every real composition property is read directly from the PDF with poppler (real page geometry, real per-font embedding status, real per-image effective print resolution and color mode) and compared against an operator-defined spec, reusing Artwork Processing's own real-metadata-vs-spec discipline generalized to a whole PDF document |
| RTF Styling | RTF Styling | No AI step — every real paragraph's real applied font and size, and the document's own real page margins, are read directly from the RTF's own control words with a real pure-JS parser (no system-binary dependency) and compared against an operator-defined spec |
| eBook Composition and QC | eBook composition and QC | No AI step — every real EPUB property (package metadata, manifest, spine, navigation TOC coverage, per-content-document structure, real embedded-image dimensions and format) is read directly from the archive's own XML and checked against an operator-defined spec, the same real-metadata-vs-spec discipline PDF Composition and QC and RTF Styling already use |
| MS Excel Accessibility | MS Excel Accessibility - English | No AI step — real workbook title/language, per-sheet tab names, real Excel Table coverage, merged-cell ranges, and per-image alt text read directly from the archive's own OOXML and checked against WCAG-cited rules, the same structural-audit discipline the Word and PowerPoint accessibility audits already use |
| AI – Layout QC | AI – Layout QC | Claude proposes a real pixel position, size, and font size for every content block; plain geometry independently checks the real page margin, every pair of blocks for a genuine overlap, every font size against its own defined range, and the real reading order and gap — a real bug was caught live when the API returned one block with an incomplete geometry object |
Screening, classifying, or cross-checking records and flagging items for a human decision.
| Prototype | Capabilities Demonstrated | Implemented Checks and Limits |
|---|---|---|
| AI Proofreading | AI Proofreading | Human accepts, rejects, or edits every flagged span; full audit log |
| Invoice Verification | Email Invoice Verification; Bill Tracking | Arithmetic checked in plain code — line items, tax, totals, PO match; 10 bundled sample invoices, each built to trigger one specific check |
| Text Annotation | AI-Based Data Annotation Services | Schema-constrained — the model cannot invent a label outside the set |
| Content Detector (full §08 detail page) | AI - Content Detector | Fixed detectors (SSN/email/phone, Luhn-validated card check, profanity) always run first; every AI-flagged quote for an operator-defined criterion is verified against the real content before it's shown |
| Image Relabelling | AI – Image relabelling | Schema-constrained label from an operator-defined taxonomy; 6 bundled sample images, each drawn programmatically to clearly match exactly one category |
| LaTeX Author Proofing | Author Proofing service – LaTeX | A real LaTeX tokenizer separates prose from markup — comments, math, and code are never sent to Claude, only the actual text is proofread |
| Claims Processing | Claims Processing | Same shape as Invoice Verification applied to insurance claims — real arithmetic, date-range, and policy-limit checks, real payable amount computed in plain code |
| Rate Audit | Rate Audit | No AI step — each billed shipment is looked up against a real contracted rate schedule by carrier, service level, zone, real weight-tier bounds, and a real effective date window, then the real charged amount is compared against the real contracted rate |
| Systematic Review Screening | Systematic Review Data Annotation Services | A real PRISMA-style inclusion/exclusion protocol, not a single taxonomy label: Claude reports Include, Exclude, or Maybe per record, with an Exclude only valid alongside one real reason from a controlled list and an Include only alongside one real inclusion criterion — either independently downgraded to "maybe" when the pick isn't actually one of the real listed options, rather than trusting the tool schema's enum alone. A real PRISMA flow diagram is computed live from the records' own current decisions, never cached, with a reconciliation check confirming the exclude count equals the sum of its per-reason breakdown |
| Forms Processing and Updating | Forms processing and updating | No AI step — real PDF AcroForm fields read, updated, and independently re-verified with pdf-lib; an unknown field name is caught, and a dropdown value outside its own declared option list is rejected by hand since pdf-lib itself accepts it silently |
| Peer Review Database Cleanup | Peer review database cleanup | No AI step — real rows grouped by a real composite key into exact and conflicting duplicates, one representative row per key compared pairwise with a real Levenshtein similarity score for near-duplicate typos, and a migration-ready CSV export that never silently drops data, only marking a row once a reviewer has actually confirmed the finding |
Narrower, task-specific tools that don't fit the four groups above.
| Prototype | Capabilities Demonstrated | Implemented Checks and Limits |
|---|---|---|
| Appointment Scheduling | Appointment Scheduling | Real calendar conflict, business-hours, and weekday-sanity checks |
| Audiobook Production | Audio Book Services | No AI call — real local TTS renders each section; a real pacing check compares measured seconds-per-word against the job's own median to catch synthesis failures |
| Artwork Processing | Artwork processing | No AI step — real file metadata (dimensions, resolution, color space) checked field by field against an operator-defined print spec |
| Podcast Production | Podcast production | No AI step — real local text-to-speech (espeak-ng) in genuinely distinct voices per speaker, stitched into one real MP3 with real embedded chapter markers built from each segment's own measured duration, independently re-read with ffprobe afterward and checked against what was actually declared |
| Image Redaction | AI – Image Processing | Real transformative image editing, not metadata reading — Claude (vision) proposes regions to redact, with every box's real geometry validated against the real image bounds before a reviewer sees it; only confirmed regions get a real solid-black rectangle composited onto the real pixel data, then independently verified by measuring the real output pixels directly and sampling outside every confirmed region to catch bleed |
| PDF Redaction | PDF Redaction | Every real PDF page is rasterized and sent to Claude for sensitive-region detection; confirmed regions get a real pixel composite, and the whole document is reassembled as a flat image-only PDF with zero extractable text, independently confirmed via poppler's own pdftotext |
"Tested against real fixtures" is a claim worth showing, not just stating. Eleven issues were caught and fixed during development of this portfolio, before any of them ever reached a review screen — all of them by actually running the code against real inputs, not by reading it over:
The QC step compares converted output against the source document's own word count. A naive HTML-to-text pass concatenated adjacent block elements with no space (</h1><p> → "ReportThis"), which would have undercounted words by roughly 20% on every single conversion — flagging content loss that never happened. Caught by comparing the actual extracted strings side by side on a real document, not by reading the code.
Mixing local-time Date construction with .toISOString() silently shifted calendar dates by a day. Found while sketching test fixtures for the conflict-detection engine, before any of it was wired up — fixed by doing all date arithmetic in explicit UTC, then re-verified against sixteen known calendar dates.
resetCalendar() failed outright on a clean checkout because the directory-creation check only lived in the read path, not the write path. Caught immediately by running the test suite, not by inspecting the function.
pdf-parse's underlying pdfjs-dist engine loads a separate worker file at runtime; Next.js's production bundler broke that lookup in a way the dev server never surfaced. Only caught by running an actual production build — not next dev — against a real PDF, and fixed by excluding the package from bundling entirely. The same fix was applied proactively to Invoice Verification, which uses the same library, before it ever had the chance to hit the same wall.
Building the bundled sample jobs for Web Data Collection ruled out a federal regulations site that actively blocks automated access — caught by testing it, not by reading its robots.txt — in favor of three sources confirmed to extract cleanly end-to-end. One bundled Invoice Verification sample was redesigned after Claude reasonably inferred a line item from a single-service invoice, which is exactly the behavior a human reviewer exists to catch.
The AI-assisted "does this text look like an untagged heading" check only ever told the model a bare count of real tagged headings, with no way to know which heading-looking line those already covered — so in practice it flagged nearly every heading-looking line, including ones already correctly tagged. Caught by testing a sample meant to be a clean, zero-finding baseline and watching it come back with a false positive on its own real heading, not by reading the prompt. Fixed by having the reader also capture a heading's exact text where the format allows it, and handing that to the model to exclude by name — the same design was then built into the PowerPoint and Word accessibility audits from day one, so they never had the bug to begin with.
The structure reader read a heading paragraph's style with a plain attribute lookup, but unlike an image's alt-text attribute, Word's own heading-style attribute carries a namespace prefix on the attribute name itself, not just the element. Every sample — including one deliberately built with real Heading 1 / Heading 2 paragraphs — came back with zero headings detected. Caught immediately by running the reader against real test fixtures and checking its output, not by reading the parsing code; fixed and reverified against all nine samples.
Building Closed Captioning's "too long" sample hit a real tooling limit: macOS's text-to-speech has a practical speech-rate floor — a sentence won't render shorter no matter how low the rate is set below a certain point, confirmed by testing identical output at three different rates — so a sample isolating only the duration rule wasn't realistic; it now demonstrates the too-much-text rule instead, which is what it actually, verifiably triggers. Building Audio Description's sample surfaced a similar real measurement: Claude's natural description of a test frame renders to roughly 4.2–4.6 real seconds of text-to-speech narration, found by running it, not predicted — so the sample's two silence gaps were sized at 3s and 7s specifically to produce one genuine "doesn't fit" result and one genuine "fits" result, instead of two identical failures.
The first production build failed every real upload with "Cannot transfer object of unsupported type" — only under a real production server against a real file, never when the same code was called directly as a script. The PDF text-extraction library documents that a TypedArray passed as input is generally transferred to its worker thread, taking ownership of the buffer; the code called it twice on the same bytes in one request (once to check the page count, again to actually process the file), so the second call hit an already-detached buffer. Caught by testing a real upload against the live production server, not by reading the code — the same discipline that caught the PDF library bundling bug above. Fixed by extracting once and passing the result through, with the extraction function now always working on a defensive copy so a second call can never be affected by what the first one did; re-verified against the same real file afterward, including that the saved document itself still serves back intact.
Both caught by running the parser against real test citations, not by reading the regex. First, the case-name capture was initially greedy enough to swallow surrounding sentence text — a citation embedded mid-sentence ("the court relied on Brown v. Board...") came back with the whole preceding clause folded into the case name instead of just "Brown v. Board...". Second, a court designation ("2d Cir.") was silently dropped during normalization — a real data-loss bug the round-trip verification check was specifically built to catch, and did, the first time it ran against a citation that included one. Both fixed and re-verified against the full real test set before the AI-assisted layer for malformed citations was built on top.
The first version of the DocBook well-formedness check re-parsed its own generated XML with the same lenient, HTML-style XML parser used for structural traversal elsewhere in the app. A deliberate tamper test — feeding it XML with an unclosed tag — proved the check was decorative: the parser silently "repaired" the malformed input instead of rejecting it, so the "not well-formed" finding never fired on genuinely broken output. Caught only because the check was tested against a known-bad input, not just a known-good one; fixed by adding a dedicated strict XML validator for well-formedness specifically, keeping the lenient parser only for traversal once well-formedness is independently confirmed. Separately, the EPUB2 reader initially returned "Untitled" for every file — its title selector was a bare, unprefixed match against a namespaced <dc:title> element, which the parser keeps as part of the tag name rather than stripping; fixed by matching the selector against the real prefixed name. Both caught and fixed before either conversion pipeline was wired into the review screen.
This app's SCORM manifest well-formedness check was built with a dedicated strict XML validator from the start, specifically because of the EPUB3 & DocBook Conversion app's well-formedness bug above — rather than assuming that lesson generalized, it was verified the same way: a deliberately malformed manifest (an unclosed tag) correctly produced a "not well-formed" finding before any further structural reading was attempted, and a non-SCORM zip with no manifest at all was correctly rejected outright rather than silently producing an empty, misleadingly clean result.
Fifty-four prototypes on shared infrastructure is only safe if one of them misbehaving can't touch the others. Every prototype in this portfolio is isolated the same way:
poc.chrisianinc.com is request-rate-limited, independent of anything the application code does.Illustrative — real identifiers (account names, ports) are withheld; the pattern below applies identically across all 54 prototypes.
This is a conceptual, illustrative diagram of the stage sequence most prototypes in this portfolio follow — it is not a literal trace of any one process or request. Not every stage applies to every prototype, and not every prototype calls a language model at all: several (Artwork Processing, Auto Pagination, Rate Audit, Peer Review Database Cleanup, and others listed in §02) are deterministic end to end, with no AI step anywhere in the path. Where a prototype skips a stage — most commonly OCR/extraction, when the input is already plain text — that stage is not run, not silently assumed to pass.
Illustrative — adapted per prototype; see each app's own §08 pipeline for what it actually runs.
Four of the five stage transitions shown above (input checks, extraction, normalization, validation) are deterministic code, not model calls. The one box genuinely requiring a model call — deterministic processing and/or AI proposal — is itself optional: a prototype either calls the model there to propose something a human will check, or runs its own deterministic logic in that same slot with no model call at all. Either way, the pipeline does not treat a completed stage as correctness on its own — each failure path shown feeds a finding or a rejection, not a silent pass-through.
pdf-parse); structure detection (sections/figures/references) is fully deterministic, no AI; the only AI box is a one-sentence description per already-detected heading."Validated" is not one thing. Six different kinds of check appear across this portfolio, and they establish different facts — none of them, alone, establishes that an output is correct:
| Check type | What it establishes | What it does not establish |
|---|---|---|
| Syntax / schema validity | The output is structurally well-formed and conforms to a defined vocabulary (e.g. the real JATS 1.3 XSD). | Valid XML does not prove factual accuracy. A document with no ISSN and no DOI still passes the real JATS schema — see the documented limitation below. |
| Source-quote presence | A claimed fact's exact text genuinely appears in the source document (anchor verification). | A matching quote does not prove the interpretation drawn from it is correct — two real anchors can support a fabricated relationship (see Semantic Tagging & Linking below). |
| Arithmetic / consistency checks | Numbers that should agree, do (e.g. a rent-escalation step strictly increases; a lease end date falls after its start date). | Consistency is not legal or factual correctness — a heuristic flag (e.g. a deposit outside the usual 0.5x–3x ratio) prompts a second look, it does not mean the lease is wrong. |
| Domain plausibility | A value falls within a heuristic range this portfolio's authors consider normal for the domain. | A real lease, invoice, or citation can validly fall outside a plausibility heuristic; it is a prompt for review, not a rule. |
| Semantic correctness | Generally: nothing in this portfolio establishes this automatically. Lexical overlap is shown as a transparency signal in Semantic Tagging & Linking, never used to accept or reject a link. | Lexical overlap does not prove a semantic relationship, and its absence does not disprove one — a genuinely related pair can share almost no vocabulary. |
| Human confirmation | A person looked at the specific finding and confirmed, corrected, or dismissed it. | Confirmation quality depends on the reviewer; nothing here measures reviewer accuracy. |
Per app: a recorded case with input, expected behavior, actual behavior, and disposition. Every example below is a real, committed, reproducible test in test/pure.test.mts (Tested — run today, see §09 for the full console output) — not a narrative claim.
Mechanical checks vs. human judgment of relatedness, kept separate: a pair with two real, verbatim anchors but no actual relationship between the stories is not caught by anchor verification — both quotes are real, so the mechanical check passes. The only signal distinguishing it from a true match is the independent lexical-overlap score (asserted < 0.1 on this case, vs. ~0.238 on a genuinely related pair). Disposition: documented as a blind spot, not fixed — relatedness itself is a human judgment this portfolio does not automate.
Also covered: invalid endpoint ID (dropped), self-link (dropped), fabricated anchor (dropped), duplicate/reversed pair (collapsed to one) — all four reject correctly and are counted, not silently absorbed.
Target schema/version: NISO JATS 1.3 Archiving and Interchange Tag Set (the real XSD from NLM/NCBI, checked via xmllint-wasm). Malformed XML (an unclosed tag) is caught by strict well-formedness before schema validation runs. A citation with a publication type outside the real JATS Tag Library's controlled vocabulary is flagged — the XSD itself leaves @publication-type unconstrained (plain xsd:string), so this is a check the schema structurally cannot perform. Unresolved references: not applicable — this pipeline has no <xref> cross-reference mechanism to resolve, so nothing can be reported "unresolved."
Documented limitation: a document with no ISSN and no DOI still passes real schema validation — the standard itself does not require them. Disposition: left as a known gap, not silently expanded with a new required-metadata rule this app would then have to invent and maintain.
Multi-column / scanned input, tested as two separate documented limitations, not one: a scanned (image-only, zero extracted text) page silently produces zero detections — no warning is raised for the no-text case. A heading that lands on the same extracted text line as adjacent column text (the real effect of naive multi-column extraction) is silently missed by the heading regex. Invented heading: a description paired with a heading never actually detected is rejected and counted, not shown. Unsupported layout: covered by the same two documented-limitation cases above — this parser has one layout model (single-column, selectable text) and does not detect when that assumption doesn't hold.
Not a featured demonstration this pass — substituted for Content Detector (see §08 and docs/portfolio-revision-checklist.md) because it had no bundled downloadable sample and no committed test evidence for these required failure cases. It remains in the broader catalog (§02) with its existing, unverified claim, not promoted to featured status.
Negative control, not a positive-only test set: a 16-digit number that is the right length for a card number but fails the real Luhn checksum is correctly not reported. On the AI-assisted layer, matchAiFindings drops a match whose excerpt is a paraphrase rather than a genuine verbatim quote (a fabricated/hallucinated excerpt) and a match with an empty excerpt — both rejected before a reviewer ever sees them, exactly the anchor-verification discipline used across the rest of this portfolio.
Missing terms: a missing core category (Base Rent) is flagged, while a missing non-core category (Rent Escalation, which a real lease may legitimately omit) is correctly not flagged. Contradictory dates: an end date before — or exactly equal to — the start date (the real inclusive boundary) each produce the correct critical finding. Documented limitation — ambiguous rent wording: two contradictory real Base Rent fields (e.g. two different dollar figures both labeled "monthly rent") produce no ambiguity-specific finding today; the check only verifies that a single quoted amount is a real positive number, not that two extracted values don't conflict with each other. Disposition: documented as a real gap, not silently patched with a new cross-field consistency rule.
Every featured demonstration's AI-assisted step returns a schema-constrained structured object, not free text — the model cannot return a shape the application doesn't expect. That schema constraint is necessary but not sufficient on its own: each app independently re-verifies the content of what comes back (anchor quotes, enum membership, numeric sanity) rather than trusting that a well-formed response is a correct one.
| Demo | Structured output shape | Independent re-verification beyond the schema |
|---|---|---|
| Semantic Tagging & Linking | Per-item: {label, confidence, reason}. Per-link: {itemAId, itemBId, anchorA, anchorB, relationship} | matchLinks() — ID existence, self-link, anchor-substring, duplicate-pair checks |
| OA Journal JATS/NLM Conversion | Per-citation: {publicationType, anchor}, assembled into real JATS 1.3 XML | verifyJats() — real XSD schema validation, controlled-vocabulary check, anchor-substring check |
| Academic PDF Parsing | Per-heading: {heading, page, description} | matchDescriptions() / verifyParse() — heading+page pair must match a real detected entry; numbering-gap checks |
| Lease Abstraction | Per-field: {category, value, structuredValue?, anchor} across 8 real lease categories | matchFields() / verifyLease() — anchor-substring check, category-enum check, date/amount/sequence domain checks |
| Content Detector | Per-finding: {criterion, excerpt} | matchAiFindings() — excerpt-substring check against the real content |
The common pattern across all five: a structured field is only ever shown to a reviewer once it has been independently matched back against something real — the source document's own text, a closed enum the schema itself doesn't enforce, or a detected structural element from a deterministic pass that ran first. A field that fails this match is dropped and counted, not silently included and not silently hidden — it becomes its own finding.
Five of this portfolio's 54 prototypes are documented here to this standard: every claim below is labeled Implemented (confirmed directly in source), Tested (a real, committed, reproducible test — run today, see §09 for the console output), Described (claimed in this app's own README from its development-time verification, not independently re-run this pass), or Proposed (not yet built). A description-only catalog entry (§02) is not a substitute for this — none of the other 49 apps are documented to this standard, and none are claimed to be.
Why these five: the working list (Semantic Tagging & Linking, OA Journal JATS/NLM Conversion, Academic PDF Parsing, Lease Abstraction) is unchanged from the suggested default. Content Detector replaces Document Conversion Pipeline — the latter had no bundled downloadable sample and no committed test evidence for the required failure cases (removed text, changed numbers, reordered content), and is recorded as a shortfall against that slot rather than filled with invented examples. Content Detector already had real negative controls (the Luhn-checksum case) and a clear deterministic/AI split in its own README.
apps/semantic-tagging-linkingImplemented Tags free-text items against an operator-defined taxonomy, then proposes and verifies links between items describing the same underlying story or matter. Intended user: an operator who needs items classified and related to each other — e.g. a news/intake triage workflow — not just a single-label classifier (that half alone is Text Annotation, a separate catalog entry).
Implemented Working prototype, package.json version 0.1.0. First committed 2026-10-30. This page reviewed 2026-11-04 against commit f5d7db3 and the local build run the same day (§09).
Implemented Pasted plain-text items against an operator-defined label taxonomy. Excluded, by real enforced limits: capped at 20 items per job and 500 characters per item (MAX_ITEMS_PER_JOB, MAX_ITEM_CHARS — a demo-scoped cost/review control, not a structural limit of the matching logic). No file upload. No multi-item graph clustering beyond pairwise links. On the public demo specifically: no free-text input of any kind — see field 04 and AC-03 in §09.
Implemented sample-items.txt — sha256:91f69608ebf51f3a… (1,994 bytes). Ten invented news items built around four real underlying stories, plus the 4-label taxonomy. The public demo's backend accepts only this exact bundled fixture (fixtureId: "sample") — a submitted file or pasted text is never read server-side.
Tested Expected: all 10 items tagged into the 4 real categories; 8 real cross-item links found (3 Meridian/Glenfield, 3 Baxter Energy, 1 Northline, 1 Quantum Robotics), 0 cross-cluster false links. Described (README, not re-run live this pass, since that requires a real Anthropic API call outside this local review): this exact outcome was recorded at development time, with 0 consistency findings. See field 11 for what was re-run today.
Implemented
classify.ts: per-item label + confidence + reason, schema-constrained to the real taxonomy.link-items.ts: proposes related-item pairs, each required to quote a real anchor phrase from both sides.matchLinks(): independently re-verifies every proposed link (ID existence, self-link, anchor-substring, duplicate-pair).lexical-overlap.ts: Jaccard similarity over significant words, shown as a transparency signal only.Implemented Model: claude-sonnet-5 (src/lib/classify.ts:5, src/lib/link-items.ts:7 — overridable via ANTHROPIC_MODEL). Sample data authored in src/lib/sample-data.ts, invented for this demo, not drawn from a real client source.
Implemented Anchor-substring verification on both sides of every link; item-ID existence check; self-link rejection; duplicate/reversed-pair collapse; per-item label must be a member of the real defined taxonomy (schema-constrained).
Tested Anchor verification establishes the quoted text genuinely exists in both items — it does not establish the two items are actually related. See the documented blind-spot test in §06: a pair with two real anchors but no real connection is not caught by mechanical verification; only the independent lexical-overlap score (a transparency signal, not a filter) distinguishes it, and only probabilistically.
Tested Items: pending → confirmed | corrected. Links: pending → confirmed | dismissed. Export (GET /api/jobs/[id]/export) was found, on inspection today, to include every item's tag regardless of review status, while links were already correctly filtered to confirmed only — an inconsistency with this app's own stated review discipline. Fixed (commit a217ed4): the export route now filters items to confirmed/corrected only, matching the links behavior. Rebuilt and retested clean (11/11) after the change, then deployed to the live server and reconfirmed there directly: an unapproved request to the real live endpoint still correctly 400s, and the real bundled fixture still runs end to end — see AC-07 in §09.
Tested 11 committed tests in test/pure.test.mts, run via npm test (Node's native test runner through tsx, zero network calls, zero API key required). Run 2026-11-04 against commit f5d7db3: 11/11 passed. Fixture: sha256:91f69608… above. Reproduce: cd apps/semantic-tagging-linking && npm install && npm test. Full console output in §09.
Blocked Storage is a flat JSON file (data/db.json), confirmed in source — not a database, no documented retention or deletion policy. Data owner: Chrisian Data Architecture (confirmed by Darrence 2026-11-04). The retention/deletion/third-party-processing policy itself is still unconfirmed and not published here. See AC-08 in §09.
apps/jats-nlm-conversionImplemented Converts a .docx manuscript into the real NISO JATS 1.3 Archiving and Interchange Tag Set, the XML vocabulary used by PubMed Central and most open-access journals. Intended user: a publishing/editorial team needing a manuscript in the specific JATS vocabulary, not a generic XML export.
Implemented Working prototype, version 0.1.0. First committed 2026-10-30. Reviewed 2026-11-04 against commit f5d7db3.
Implemented A .docx manuscript plus operator-supplied journal metadata (title, ISSN, DOI, authors, year — not inferable from body text). Excluded: no images or tables (<table-wrap>/<fig> out of scope); citations are kept as a single real <mixed-citation>, not decomposed into per-field <element-citation> elements. On the public demo: only the bundled fixture, no uploaded file — see field 04.
Implemented sample-oa-manuscript.docx — sha256:d8bd07e15475d0ce… (10,244 bytes). A short manuscript built with four distinct real citation types (journal, conference proceedings, web, patent). Public-demo backend accepts only this fixture.
Described (README, development-time run, not re-called live this pass — requires a real API call): the 4 citations classify into their 4 distinct real publication types, every anchor verified, and the generated XML passes real JATS 1.3 schema validation with zero findings. Tested independently today: the schema-validation and well-formedness logic itself (field 11), using hand-built fixture XML, not a live API call.
Implemented
html-to-jats.ts: DOM-tree walk, headings → nested <sec>, paragraphs/lists mapped directly; a References/Bibliography heading switches into citation-collection mode.classify-citations.ts: Claude's one job is picking each citation's real publication type from the JATS Tag Library's vocabulary, with a required anchor quote.jats-schema.ts: validates the assembled XML against the real official JATS 1.3 XSD via xmllint-wasm.verify-jats.ts, match-citations.ts: strict well-formedness check (separate from the lenient parser), controlled-vocabulary check, anchor-substring check.Implemented Model: claude-sonnet-5 (src/lib/classify-citations.ts:5). Schema: the real NISO JATS 1.3 XSD, downloaded unmodified from NLM/NCBI (provenance recorded in schema/SOURCE.md). Sample manuscript invented for this demo.
Implemented Strict XML well-formedness (dedicated parser, checked before schema validation). Full JATS 1.3 XSD schema validation (real external standard). Publication-type controlled-vocabulary check. Citation-anchor substring check.
Tested Schema validity establishes structural conformance to JATS 1.3 — it does not establish factual accuracy, and does not require ISSN or DOI (documented-limitation test, §06: a document with neither still validates cleanly). The controlled-vocabulary check exists specifically because the XSD leaves @publication-type unconstrained (plain xsd:string) — confirmed by reading the real schema, not assumed.
Tested Findings: pending → confirmed | dismissed. Decision confirmed by Darrence 2026-11-04: the generated XML (GET /api/jobs/[id]/output) is now blocked while any finding is still pending — the route returns 409 with the pending count, and the download button is disabled in the UI with the same count shown inline, until every finding is confirmed or dismissed. See AC-07 in §09.
Tested 12 committed tests in test/pure.test.mts, including 3 new ones covering the export gate. Run 2026-11-04: 12/12 passed, including real JATS 1.3 XSD validation exercised both ways (a well-formed document passes; a malformed/unknown-element document is rejected by the real schema, not a stub). Fixture: sha256:d8bd07e1… above. Reproduce: cd apps/jats-nlm-conversion && npm install && npm test.
Blocked Storage is a flat JSON file plus the generated XML on disk, confirmed in source — not a database. Data owner: Chrisian Data Architecture (confirmed by Darrence 2026-11-04). The retention/deletion/third-party-processing policy itself is still unconfirmed and not published here. See AC-08 in §09.
apps/academic-pdf-parsingImplemented Detects an academic paper's sections, figures/tables, and references from a PDF, with one AI-written description per section. Intended user: an editorial or production team needing a structural map of a paper, not a full-text OCR or citation-parsing tool (those are separate catalog entries).
Implemented Working prototype, version 0.1.0. First committed 2026-10-30. Reviewed 2026-11-04 against commit f5d7db3.
Implemented A PDF with selectable text, up to 15 pages / 10MB (MAX_PAGES, MAX_FILE_BYTES — demo-scoped cost control). Excluded: scanned/image-only pages (documented limitation, field 12); multi-column layouts where a heading lands on the same extracted line as adjacent column text; a fixed English-language section-heading vocabulary, so non-English or non-standard headings are under-detected, not a bug. On the public demo: only the bundled fixture.
Implemented sample-01-lightweight-transformers.pdf — sha256:b3e9840b77f53ba2… (5,441 bytes). A bundled 2-page test paper with 8 section headings, 3 figure/table captions, 7 references. Public-demo backend accepts only this fixture.
Described (README, development-time run against the real Anthropic API, not re-called live this pass): all 8 sections correctly described, 3 figure/table captions, 7 references, zero findings. Tested independently today: the deterministic detection and verification logic (field 11), which does not require an API call.
Implemented
detect-structure.ts: three independent regex passes over the PDF's own extracted text (via pdf-parse) for sections, figure/table captions, and references, with real page numbers.describe-sections.ts: one sentence per already-detected heading, required to copy the heading and page number verbatim — Claude never proposes new structure.verify-parse.ts: matches every description back to a real (heading, page) pair; numbering-gap checks on figures, tables and references.Implemented Model: claude-sonnet-5 (src/lib/describe-sections.ts:6). Text extraction via pdf-parse. Sample PDF built for this demo, not a real published paper.
Implemented Heading+page match against the real detected list (exact or case/whitespace-normalized). Figure/table/reference numbering-gap detection. Uncovered-heading detection (a real heading with no AI description). Empty-references-list-with-heading-present detection.
Tested A matched description establishes the heading and page are real and the description was generated for that real entry — it does not establish the one-sentence description is an accurate summary of the section's content (no independent fact-check of description accuracy exists). Two documented blind spots verified today, in §06: scanned/image-only input silently produces zero detections (no warning), and a heading sharing an extraction line with column text is silently missed.
Tested Sections and findings: pending → confirmed | dismissed (with an optional note). Different export model, checked on inspection today: unlike Lease Abstraction, Semantic Tagging & Linking, and Content Detector, the exported Markdown report includes every section, figure/table, reference, and finding — not confirmed-only — with each section's and finding's real review status printed inline (e.g. "— pending"). Nothing is silently presented as reviewed; the status is visible in the document itself, but a pending item is not excluded from the export the way it is in the other three apps. Documented as a real, deliberate design difference, not a defect to silently patch to match the other apps. See AC-07 in §09.
Tested 12 committed tests in test/pure.test.mts. Run 2026-11-04 against commit f5d7db3: 12/12 passed. Fixture: sha256:b3e9840b… above. Reproduce: cd apps/academic-pdf-parsing && npm install && npm test.
Blocked Storage is a flat JSON file plus uploaded PDFs under data/media/, confirmed in source — neither is a database, neither is pruned automatically. Data owner: Chrisian Data Architecture (confirmed by Darrence 2026-11-04). The retention/deletion/third-party-processing policy itself is still unconfirmed and not published here. See AC-08 in §09.
apps/lease-abstractionImplemented Extracts a commercial lease into 8 structured field categories (Parties, Premises, Lease Term, Base Rent, Rent Escalation, Renewal Options, Termination Clauses, Security Deposit), with lease-specific domain checks. Intended user: a reviewer abstracting commercial lease terms, not a generic contract summarizer.
Implemented Working prototype, version 0.1.0. First committed 2026-10-30. Reviewed 2026-11-04 against commit f5d7db3.
Implemented Pasted lease text, capped at 10,000 characters (MAX_CHARS — demo-scoped cost control). Excluded: a fixed, English-language commercial-lease schema only — a residential lease, ground lease, or non-English lease would need its own schema and domain checks (anchor verification generalizes, the specific checks don't). On the public demo: only the bundled fixture.
Implemented harborview-bluepeak-lease.txt — sha256:83a54679959a76df… (1,564 bytes). An invented commercial lease, not a real document, built with a deliberate Year 3 rent decrease and a deliberately low security deposit so the domain checks have something real to catch. Public-demo backend accepts only this fixture.
Described (README, development-time run against the real Anthropic API): all 13 real fields across all 8 categories extracted with zero unverified quotes, and exactly the two findings the sample was built to trigger (the escalation decrease, the deposit ratio), no false positives on the otherwise-valid dates/amounts. Tested independently today: the anchor-matching and domain-check logic (field 11).
Implemented
abstract-lease.ts: extracts the 8 real field categories with structured values (dollar amount, ISO date, sequence number) plus a required anchor quote per field.matchFields(): verifies every quote against the real source text; drops and counts a fabricated anchor or an unrecognized category.verify-lease.ts: end-after-start date check, positive-amount check, escalation-sequence check, deposit-ratio check, core-category coverage check.Implemented Model: claude-sonnet-5 (src/lib/abstract-lease.ts:7). Sample lease invented for this demo (Harborview Properties LLC / Bluepeak Software Inc., fictional parties).
Implemented Anchor-substring verification per field. Category-enum check. End-date-after-start-date check (inclusive boundary — an end date equal to the start date is flagged). Positive-dollar-amount check. Rent-escalation sequence-decrease check. Security-deposit 0.5x–3x ratio check. Core-category coverage check (Parties, Premises, Lease Term, Base Rent required; Rent Escalation, Renewal Options, Termination Clauses, Security Deposit legitimately optional).
Tested The deposit-ratio and escalation-sequence checks are heuristics, not legal rules — a real lease can validly fall outside them; they prompt a second look, they don't mean the lease is wrong. Documented blind spot verified today (§06): two contradictory Base Rent fields (two different dollar figures both labeled "monthly rent") produce no ambiguity-specific finding — the check only verifies a single quoted amount is a real positive number, not that two extracted values agree with each other.
Tested Fields and findings: pending → confirmed | corrected | dismissed. Export (GET /api/jobs/[id]/export) confirmed on inspection today to filter to confirmed-status fields only, grouped by category — a pending or dismissed field is correctly excluded from the Markdown abstract, matching this app's own stated review discipline. No gap found here.
Tested 12 committed tests in test/pure.test.mts. Run 2026-11-04 against commit f5d7db3: 12/12 passed. Fixture: sha256:83a54679… above. Reproduce: cd apps/lease-abstraction && npm install && npm test.
Blocked Storage is a flat JSON file (data/db.json), confirmed in source — not a database. Data owner: Chrisian Data Architecture (confirmed by Darrence 2026-11-04). The retention/deletion/third-party-processing policy itself is still unconfirmed and not published here. See AC-08 in §09.
apps/content-detectorImplemented Screens free text against a fixed set of deterministic PII/profanity detectors plus operator-defined custom criteria. Intended user: a reviewer screening intake content for sensitive or policy-relevant passages before further processing.
Implemented Working prototype, version 0.1.0. First committed 2026-10-29. Reviewed 2026-11-04 against commit f5d7db3.
Implemented Plain text pasted/typed — not a file upload (a real deployment would extract text from native document formats first). The fixed detector list (SSN, email, phone, Luhn-validated card number, profanity) is intentionally small — a real deployment would use a larger, configurable ruleset. One AI call per job covers all custom criteria together, not one call per criterion. On the public demo: only the bundled fixture.
Implemented sample-case-note.txt — sha256:838a05371e0d4fe6… (867 bytes). An invented case-intake note containing one of each deterministic pattern plus two passages written to trigger the two sample custom criteria. Public-demo backend accepts only this fixture.
Described (README, development-time run against the real Anthropic API): all 5 deterministic patterns found; both custom criteria found with real quoted excerpts; a clean control with neither produced zero AI findings. Tested independently today: the deterministic detectors and the anchor-matching logic (field 11), which do not require an API call.
Implemented
detect-deterministic.ts: pattern matches for SSN/email/phone/profanity, plus a Luhn-checksum-validated card-number check.detect-ai.ts: screens the full content against all operator-defined custom criteria in one call, required to quote the exact triggering passage.matchAiFindings() (extracted this pass from inline logic in runAiDetector, identical behavior, confirmed via build): verifies every quote is a genuine verbatim substring of the real content before it is shown.Implemented Model: claude-sonnet-5 (src/lib/detect-ai.ts:5). Sample case note invented for this demo.
Implemented Luhn checksum on candidate card numbers (not length alone). Excerpt-substring verification against the real content for every AI-flagged finding. Empty-excerpt rejection.
Tested Excerpt verification establishes the flagged text genuinely exists in the content — it does not establish the criterion was correctly applied to it (a genuinely present but wrongly-matched excerpt would still pass this check). The Luhn check establishes the number is checksum-valid, not that it is a real, currently-active card.
Tested Findings: pending → confirmed | dismissed (both deterministic and AI-sourced findings share the same review flow). Export (GET /api/jobs/[id]/export) confirmed on inspection today to filter to confirmed-status findings only — a pending or dismissed finding is correctly excluded from the report. No gap found here.
Tested 12 committed tests in test/pure.test.mts. Run 2026-11-04 against commit f5d7db3: 12/12 passed, including the negative control (a 16-digit number of valid length that fails the real Luhn checksum is not reported). Fixture: sha256:838a0537… above. Reproduce: cd apps/content-detector && npm install && npm test.
Blocked Storage is a flat JSON file (data/db.json), confirmed in source — not a database. Data owner: Chrisian Data Architecture (confirmed by Darrence 2026-11-04). The retention/deletion/third-party-processing policy itself is still unconfirmed and not published here. See AC-08 in §09.
Pass counts referenced below are test pass counts, not end-to-end accuracy — they confirm the pure logic (anchor verification, schema validation, numbering-gap detection, domain checks) behaves correctly against hand-built fixtures and tamper cases. None of this portfolio measures accuracy against a held-out, independently labeled dataset; no such dataset exists for any of these five demos.
56 of 56 committed tests pass across the five featured apps (local working tree + after redeploy, build/lint clean). AC-03's sample-only enforcement is deployed and live-verified for all 54 apps: every app rejects an unapproved request with HTTP 400, and a representative handful were run to completion against the real live endpoint, including real Anthropic API calls. Full run logs, exact dates/commit hashes, and the publication/deployment history are in the Technical Appendix, not reproduced here.
| Criterion | Verdict | Evidence |
|---|---|---|
| AC-01 Positioning | PASS | Headline, environment label, and executive copy replaced with the required text (header); universal claims rewritten in §01; prototype count (54) shown with its review date, not asserted as precise beyond what the catalog lists. |
| AC-02 Confidentiality | PASS, deployed and live | Full sweep of all 54 apps' own public surface (rendered text, client bundle, error responses, sample-file contents, source maps, secrets) completed 2026-11-04 — 8 findings, 6 fixed (a systemic error-message leak across all 54 apps, a real internal-infrastructure exposure in one app, a hardcoded personal email in two apps, and real-looking identifiers in several sample files), 1 decided by Darrence (the internal service stays off public pages for good — its dead code was removed from the repo entirely), 1 no-action. A non-public plaintext key (separate from this AC's public-exposure scope) is being rotated by Darrence directly. Deployed to all 54 live apps 2026-11-04, each individually re-verified against the real production endpoint. See docs/portfolio-revision-checklist.md for the full finding-by-finding record. |
| AC-03 Public data entry | PASS (all 54, live) | All 54 apps' backends accept only an approved fixture/sample identifier and resolve real job content server-side; deployed, and directly curl-verified against the real production endpoint for all 54 (rejects an unapproved/bogus/old-style request with HTTP 400), with the full run-to-completion path spot-checked live on a representative handful across input shapes (full deploy and sweep history in the Technical Appendix). |
| AC-04 Architecture and navigation | PASS | All five destinations (§05–§09) exist as working in-page anchors; diagram labeled illustrative, shows real AI/deterministic branches and failure paths (§05); existing routes/anchors preserved. |
| AC-05 Featured documentation | PASS | Five detail sections (§08), each with all 13 required fields, a real downloadable sample, and documented limitations. None are description-only. |
| AC-06 Evidence | PASS | 56/56 committed tests reproduced against the local working tree, then the 5 apps redeployed and independently re-verified directly against the real live endpoints (full run log and publication history in the Technical Appendix) — both the local test suite and the live production behavior are confirmed, not just one of the two. |
| AC-07 Review/export | PASS, deployed and live | Lease Abstraction and Content Detector: confirmed-only export verified, no gap. Semantic Tagging & Linking: a real gap was found and fixed (items export was not filtered by review status — now is, verified live). Academic PDF Parsing: exports all items with status labeled inline, not confirmed-only — a deliberate, disclosed difference, not a silent-finalization defect. JATS/NLM Conversion: decision confirmed by Darrence 2026-11-04 — export is now gated on completed review (any pending finding blocks the download with a 409 and a disabled button in the UI); 3 new committed tests added, 12/12 passing, build clean, deployed and live-verified (a real sample run against the production endpoint exported successfully with zero pending findings, confirming the allow-path live). |
| AC-08 Data handling | BLOCKED | Darrence confirmed a named data owner (Chrisian Data Architecture) for each of the five featured apps 2026-11-04 — see field 13 on each app's detail section below. The retention/deletion/access/third-party-processing policy itself remains deliberately unconfirmed and unpublished; no reassuring default copy was written in its place. Full draft statement prepared and ready for review in docs/portfolio-revision-checklist.md, pending that confirmation. |
| AC-09 Usability | PASS (owner-confirmed real-device use) | Checked visually in a local browser pane: navigation, links, mobile layout (one real regression found and fixed this round). "Request a technical walkthrough" now links to chrisian@chrisianinc.com, a confirmed dedicated address. Darrence confirmed 2026-11-04, per Ian's own use of the live site, that it works fine on both mobile and desktop — real-device evidence this environment can't produce itself. That confirmation covers general mobile/desktop usability, not specifically a screen reader. |
| AC-10 Handoff | PASS | Changed files tracked in git history on the poc repo, commits e840f09 through a217ed4 (Phase 1 + Phase 2, this document included); requirement checklist in docs/portfolio-revision-checklist.md; test results above (reproduced pre-commit, against the working tree that became commit a217ed4); blockers listed throughout this section; rollback is git revert against a clean, isolated commit history. |
Owner decisions still open: confirmation of a draft data-handling statement prepared for review (not yet published anywhere — see docs/portfolio-revision-checklist.md), and where to publish it once confirmed (AC-08) — kept deliberately blocked for now; the only item left. Decided this round: a named data owner (Chrisian Data Architecture) is now confirmed and shown on each of the 5 featured apps' detail sections, though the retention/deletion/access/third-party policy itself stays unconfirmed (AC-08); JATS/NLM Conversion's export is now gated on completed review (AC-07); "Request a technical walkthrough" now links to a confirmed dedicated address, chrisian@chrisianinc.com (AC-09); real-device mobile/desktop usability confirmed by Ian directly, no further manual testing needed (AC-09); and the real internal service patent-litigation-collection previously showcased stays off every public-facing page for good (AC-02) — the dead code for it was removed from the repo entirely rather than left parked. This revision, the 5 featured apps' fixes, the 49-app sample-only sweep, and everything in this round above are all published and live, deployed and individually re-verified against the real production endpoints 2026-11-04 — the one exception is AC-08, deliberately kept unpublished pending confirmation of the data-handling statement.