Imported from Apomera/AlloFlow (
platform_packages/claude-alloflow/skills/alloflow-portable-remediation/SKILL.md). Install upstream withnpx skills add Apomera/AlloFlow --skill alloflow-portable-remediation. Copyright stays with the author.
AlloFlow portable PDF remediation
Keep the document inside the active Claude or ChatGPT file sandbox. Do not call an AlloFlow server, remote MCP, Gemini, web service, analytics endpoint, or telemetry service while using this workflow.
This is the default path when a user attaches a PDF and simply asks to make it accessible. It needs no AlloFlow account, Cloudflare Worker, institution-owned service, or separate AI API key. The host model reads the attachment using the capabilities already available in the current conversation. The workflow is host-agnostic: any harness that can run Python 3 and read the document works the same way (see HARNESSES.md).
Sources may be .pdf, .docx, or .pptx (.docx/.pptx are rebuilt to
accessible HTML and a tagged PDF from the plan, exactly like a PDF source).
Run the one-prompt workflow
Resolve the installed directory containing this SKILL.md as <skill-dir>.
Use absolute paths derived from it for scripts and references; do not assume the
conversation working directory is the Skill directory.
-
Locate the PDF attached to the current conversation. Work on a copy and never overwrite the source.
-
Run:
python "<skill-dir>/scripts/alloflow_portable.py" capabilities --json -
Bind the plan to that exact document:
python "<skill-dir>/scripts/alloflow_portable.py" source-info \ --source "/path/to/source.pdf"Copy the returned
sha256intodocument.source_sha256in the repair plan. Do not calculate it from extracted text or from a renamed/recreated copy.Optional deterministic helpers, all offline:
audit-source --source X— structural before-facts for a PDF (tagged?, language?, text layer?, form fields?) plus severity-ranked issue flags. Record these as the baseline; they are facts, not a score.extract-images --source X --out-dir D— pull image XObjects out of a PDF so figures can be reused in the plan (copy the wanted files next to the plan and reference them via imagepath). Skipped images are listed with reasons; treat every skipped meaningful figure as a review note.extract-office --source X— paragraph/slide text from.docx/.pptxso a plan can be authored without vision. Tables, images, and text boxes are NOT extracted; read the document for them.extract-text --source X --ordered --include-text— best-effort READING-ORDER text (lines grouped by position, top-down per page). The default (unordered) channel reports object order and stays the recall reference; use--orderedwhen authoring so paragraph order and page boundaries are not guessed from shuffled text. Multi-column pages may interleave; compare both channels when in doubt.extract-annotations --source X— every link annotation per page: URI links AND internal GoTo links (footnote markers, cross-references). ALWAYS run this while authoring: a source whose footnote markers are internal links must keep that navigation in the plan (see blockidbelow), and written-out URLs should keep the scheme the annotation actually carries.
-
Read every source page using the host's native document and vision capabilities. Preserve the source wording, reading order, headings, lists, tables, links, page boundaries, and meaningful images. Do not summarize or silently omit repeated content.
-
Write
repair-plan.jsonthat conforms to references/repair-plan.schema.json. Record uncertainty inreview_notes; never invent unreadable content.Carry the source's inline emphasis where it changes meaning. Paragraphs and blockquotes take an optional
runsarray, and lists takeitem_runs(one entry per item); each run is{"text": ..., "style": "normal" | "emphasis" | "strong"}. Styling is strictly additive: the runs must concatenate to the block'stextexactly, and validation rejects a plan where they do not, so styling can never add, drop, or alter content. This matters most where italics alone mark quoted external language with no quotation marks — withoutrunssuch a passage reads as ordinary narration. Where a heading already conveys the emphasis, do not restate it. Table cells cannot carry inline styling; disclose that if a styled cell matters.Carry the source's inline hyperlinks the same way: a run may take an
href(safe schemes only:#,http(s):,mailto:,tel:), andstyleandhrefcombine. The text contract is unchanged — a link can never alter a character of content. Only add anhrefwhere the source really carries a link (an annotation or a written-out URL); do not invent destinations, and verify link text is meaningful out of context. The tagged PDF carries each link as a real Link annotation with an alternate description.Table data cells take the same overlay via
cell_runs: one entry per row (null to skip a row), each an array with one entry per cell (null to skip a cell). The same exact-text rule applies per cell. Column headers stay plain text — header semantics already carry their emphasis.Carry the source's in-document links with block ids: any content block may declare
"id": "note-1"(lowercase[a-z][a-z0-9-]*, unique,main-content/alloflow-*reserved), and a run may then use"href": "#note-1". Validation rejects a#targetwith no declared id, so a rebuilt link can never navigate nowhere. Use this whereverextract-annotationsshows internal GoTo links — typically footnote markers — so navigation the source really carries survives the rebuild.The plan's
review_notesare rendered into the accessible HTML (and the tagged PDF) as a clearly-marked final "Remediation notes" section, so every disclosed transformation travels with the deliverable itself, where the independent verifier and the reader can see it. Write them as complete, reader-facing sentences, in the document's language when the audience needs that.
For a document too long to read and author in one session, author it in
TRANCHES: each session writes a complete plan file covering the contiguous
pages it actually read (only the first carries the h1), then
merge-plans --tranches t1.json t2.json ... --out plan.json concatenates them,
refusing mismatched document headers, out-of-order or overlapping tranches, and
any merged result that fails full validation, and reporting every page no
tranche covered. Remediate and verify the MERGED plan only — tranches are an
authoring format, never an output format.
6. Run one command:
python "<skill-dir>/scripts/alloflow_portable.py" remediate \
--source "/path/to/source.pdf" \
--plan "/path/to/repair-plan.json" \
--out-dir "/path/to/alloflow-output" \
--pdf auto \
--verapdf auto
-
If plan validation fails, correct the plan from the reported errors and run it once more. Do not weaken or bypass a validation rule.
-
Independent verification (the two-model rule). The plan author graded its own fidelity; a second reader must grade it instead whenever the rebuild will be distributed or the source is a scan:
python "<skill-dir>/scripts/alloflow_portable.py" verify-init \ --plan repair-plan.json --source source.pdf \ --html <out-dir>/<name>-accessible.html --out worksheet.jsonHand
worksheet.jsonto a FRESH-CONTEXT reader — a model instance or person who did not author the plan — who reads the source and the rebuilt HTML directly and fills every item. Then:python "<skill-dir>/scripts/alloflow_portable.py" verify-check \ --worksheet worksheet.json --plan repair-plan.json \ --source source.pdf --html <html> --out verification-report.jsonverify-check refuses unfilled, tampered, or unattested worksheets and exits 9 when discrepancies were found — fix the plan and re-run the loop. The report also carries two deterministic recall channels computed during remediation:
sourceTextRecall(how much of a born-digital source's own text layer the plan carries — null on scans, honestly) andoutputTextRecall(whether the tagged PDF carries the plan's text).
For a folder of documents, author one plan per document, list the pairs in a
manifest ({"items": [{"source": ..., "plan": ...}, ...]}, at most 60), and
run batch-remediate --manifest M --out-dir D. Report the per-file scoreboard
it returns — every failure by name — never just "done".
When the run will be reviewed by an administrator or accessibility coordinator, finish with:
python "<skill-dir>/scripts/alloflow_portable.py" summary-report \
--run-dir "<out-dir>" [--before-validation before.json] \
[--verification verification-report.json]
It folds the run's stamped evidence (accessibility report, optional
before-validation from validate-pdf on the ORIGINAL file, optional
verification report, privacy receipt) into one self-contained
plain-language HTML page (*-evidence-summary.html) that can be emailed
or filed without any technical tooling. It adds nothing: every figure is
read from the artifacts, and the no-compliance-claim language is carried
through. Running validate-pdf on the original first gives the page a
real before/after row.
For a translated or plain-language copy, author a second plan from the same
source with document.variant set to "translated" or "simplified", a
review note describing the transformation, and (for translations)
document.language set to the target language. Run remediate again into a
separate output directory. A variant never replaces the faithful rebuild; it
is delivered alongside it.
9. Return every artifact listed in the final report:
- semantic accessible HTML;
- the remediated tagged PDF when this sandbox proved it could generate one;
- the accessibility report; and
- the privacy receipt.
If tagged-PDF generation is unavailable, return the HTML and reports and say plainly that the sandbox could not create a tagged PDF. Do not substitute an ordinary print-to-PDF and call it accessible.
Stop instead of rebuilding
Do not automatically rebuild signed documents, legal records, certificates, or interactive forms where changed layout or field behavior could alter meaning. Return an audit-only explanation and recommend the responsible document owner.
For scanned pages, complex equations, dense charts, handwriting, ambiguous reading order, or tables that cannot be reconstructed confidently, preserve what is legible and add a specific manual-review note. Never guess.
Interpret the result honestly
pdf_generated_validation_passed_review_requiredmeans local veraPDF passed, but a person must still compare meaning and fidelity with the source.pdf_generated_with_known_issuesmeans the PDF was generated and veraPDF found unresolved PDF/UA rules.pdf_generated_unverified_review_requiredmeans a tagged PDF was generated but local PDF/UA validation did not complete.html_only_review_requiredmeans the semantic rebuild exists but tagged-PDF generation was unavailable, disabled, or failed.blockedmeans the document type or plan could not be processed safely.- A veraPDF failure is a real unresolved PDF/UA finding.
- A missing veraPDF capability is
not_run, never a pass. - The generated PDF carries the machine-readable PDF/UA-1 identifier only when
local veraPDF validation passed in full. When validation finds unresolved
rules the file is rebuilt with the identifier withheld
(
pdfUaValidation.identifierWithheld: true), and a missing-identification failure infailedRulesthen reflects that withholding, not an extra defect. - Never say "WCAG compliant," "PDF/UA compliant," "Section 508 compliant," or "legally compliant" from this workflow alone.
Read references/privacy-and-verification.md and PRIVACY.md before handling identifiable student information or interpreting a report. The receipt is scoped to the packaged scripts; it does not certify the host provider, operating system, or synchronization tools.
Remote fallback is explicit opt-in
The older AlloFlow MCP/Cloudflare pipeline is not part of this public workflow. Use it only when the user explicitly requests remote or institution-hosted processing after understanding that the service will receive the document.