Use when converting an uploaded PDF, worksheet, exam page, or source-photo into a structured editable worksheet sheet.
Use this skill to translate source material into the paper-sheet JSON contract. It is for draft-sheet runs, source-paper-only grader runs, and grader runs that truly need source-paper reconstruction.
brief.mdrequest.jsongrader/uploads/index.jsonsheet/task.md or grader/task.mdgrader/uploads/<filename>knowledge-base/extract_pdf_reference_text once as a navigation aid.extract_text again. Use the deterministic markdown reference and targeted line-range reads; reserve extract_text for student submissions and genuinely visual/non-text source pages.extract_text call that covers all remaining primary source targets. When one call includes multiple files, pass instructions that mention every workspace path and identify each file's role, so source problem text, student submissions, and official solutions stay in separate sections.grep_workspace_files to locate headings, question numbers, figure labels, and mark-scheme items; generated-reference matches include nearby context. Use read_workspace_file with startLine/lineCount only for ranges where grep context is insufficient.read_workspace_file calls on the same large extracted reference. After the first outline or any content omitted response, use grep or targeted line ranges.knowledge-base/index.md and call kb_search_pdfs. If a matching entry exists, call kb_download_pdf and use that local cached PDF. If no match exists, call kb_cache_pdf_from_url with semi-structured classification text such as gcse/aqa/biology/2024/<original filename> plus source identity, session, component, and whether it is a question paper, mark scheme, examiner report, grade boundary, or threshold document.storagePath in references.paperStoragePath or references.markSchemeStoragePath and in run-summary.json as paperStoragePath or markSchemeStoragePath. Keep paperUrl and markSchemeUrl only as provenance.extract_pdf_images once on the relevant page range when available. Use useful embedded raster outputs as candidates, but remember they may omit on-page labels/captions or coordinates; validate them like any other crop and fall back to rendered pages for vector/layout-sensitive visuals.pdf_to_images when page pixels are needed. In grader-publish runs, use view_image for source-page/photo fidelity checks and rendered PDF pages when text or layout matters. Use extract_text for primary transcription and the fresh visual helper tools for localized crop planning/validation.pageNumbers to pdf_to_images; choose those pages from deterministic text extraction, grep results, or the upload manifest. Do not render a whole exam paper just to look around. If pdf_to_images fails only because pageNumbers were omitted, immediately retry with explicit pageNumbers; that failure is a tool-use error, not evidence that the page or visual is unavailable.Figure 1 asks... or Table 1 gives.... Copy the exact source question wording for every answered item, omitting only irrelevant administration chrome. Do not use Use Figure N in the linked original PDF. as the default for answer-critical visuals. Embed the source table as Markdown or crop the source figure when it is needed to understand the task, the student's answer, or the feedback. Preserve source column arithmetic, number grids, stacked calculations, flow/box layouts, and circled/lettered labels with visible Markdown, renderable LaTeX display layout, or a validated crop; never flatten them into a prose cue. Use a linked-source-PDF instruction only after a real render/crop/table attempt failed and the failure is recorded in the artifact plan plus the source-fidelity audit.pdf_to_images, extract_text, or the fresh visual helper tools fail for a printed worksheet or exam page that truly needs visual handling, stop and fix or report that failure instead of publishing a partial text-only worksheet.validate_source_fidelity_with_fresh_agent before publishing and write its reviewMarkdown to grader/output/source-fidelity-audit.md. Split the audit by source page or root question when there is more than one page/root, and give the reviewer a narrow rubric: source wording is verbatim apart from minimal OCR cleanup, every visible answer-bearing or partially answered item is represented, numbering/badges match the source hierarchy, and all named figures/tables/layout-critical structures are visible near the relevant prompt.badgeLabel to the visible source subpart label, for example a, b, c, i, ii, or A.A computer has a Central Processing Unit (CPU). with a topic summary such as Central Processing Unit.marks. For source-paper-only unanswered sheets, marks are still the source total for that question even though no score is awarded yet.S1, invent difficulty labels, put a long paper in one giant section, or group multiple large multipart roots into one numeric range.Before writing a large sheet.json or draft.json, make a compact artifact plan. For long papers, write it to grader/output/sheet-plan.md or sheet/output/sheet-plan.md so later repairs have one source of truth.
The plan should list:
Figure N, Table N, graph, map, photo, or option-diagram block, its source page number, and the nearest source-faithful placement,mcq, answer_bank, calc, lines, etc.),Use this plan to catch schema and placement errors before the first publish attempt. In particular, do not start a large JSON artifact until you have decided whether each fixed-option blank is an answer_bank, each MCQ is full_options or labels_only, and each reused figure/table is rendered once at the first source-faithful location.
Use validate_source_fidelity_with_fresh_agent after sheet-plan.md and sheet.json exist and before the first publish attempt whenever the source is a printed worksheet, official exam paper, source photo, or any PDF page whose wording/figures/tables are copied into the sheet. Write the returned reviewMarkdown to grader/output/source-fidelity-audit.md; publish_sheet rejects source-paper sheets without a passing audit record.
sheet.json fragment.Use only these question types:
groupanswer_bankfillclozemcqlinescalcmatchspellingflowUse group when one numbered source question owns shared context such as a stem, table, figure, or instruction before answer-bearing subparts. Put only the shared source text that appears before the first subpart in group.prompt; put interstitial text before later subparts into the following child prompt.
Do not use group for a standalone one-part question. If the source has no answer-bearing subparts, put the full source prompt and marks on one leaf question instead of inventing a child prompt such as give the conclusion or duplicating the same display number.
Use displayNumber whenever the source has visible numbering such as 01.1, 9(a), or 10(b). Use badgeLabel when the circular badge should be shorter than the full source label.
When the collapsible section label is already the root, such as Question 6, do not create an additional visible parent badge also labelled 6 just to hold the root stem. If the source has one answer-bearing root item, use a single direct question entry instead of a 6 group containing a 6 child. If the source has a root stem followed by subparts, keep the exact root stem in an unnumbered shared context where possible, or at the nearest source-faithful prompt level, and give the subparts full displayNumber values plus short badgeLabel values such as a, b, and c.
If a root stem is shared by both a direct first-level subpart and a later first-level group, such as 7 followed by (a) and then (b)(i), do not attach the root stem to the (a) prompt where it will render beside the a badge. Put the exact root stem in section.theory or another unbadged section-level context, then render (a) and (b) as separate top-level entries.
Example shape for a Question 7 section with root text, a direct (a) item, and nested (b)(i) leaves:
{
"label": "Question 7",
"theory": "Embedded system: Follow Me car system.",
"questions": [
{
"id": "q7a",
"type": "lines",
"displayNumber": "7(a)",
"badgeLabel": "a",
"marks": 3,
"prompt": "Explain why the system is an example of an embedded system."
},
{
"id": "q7b",
"type": "group",
"displayNumber": "b",
"prompt": "For the Follow Me system:",
"questions": [
{
"id": "q7bi",
"type": "lines",
"displayNumber": "7(b)(i)",
"badgeLabel": "i",
"marks": 2,
"prompt": "State two items that will be stored in ROM for the Follow Me system."
}
]
}
]
}
For nested subparts such as 1(a), 1(b), and 1(c), use displayNumber for the full source label and badgeLabel for the visible subpart marker (a, b, c) when the renderer shows a circular item badge. Do not let those badges default to 1, 2, 3.
For two-level nested source labels such as 2(a)(i), make the root question the section label (Question 2) when possible, then create one top-level group per first-level subpart with displayNumber: "a", displayNumber: "b", etc. Put the (a) shared stem in that group prompt. Put the answer-bearing (i), (ii), etc. leaves inside that group with source-faithful displayNumber: "2(a)(i)" and short badgeLabel: "i" / "ii". Do not put all 2(a)(i), 2(a)(ii), 2(b)(i) leaves directly under a single displayNumber: "2" group, because that renders only one composite item badge instead of separate first- and second-level circles.
For decimal-style exam labels such as 01, 01.1, and 01.2, prefer one collapsible section labelled Question 1. Do not render an additional parent circle labelled 01. Put the root stem in section.theory or the nearest unbadged context, then render the answer-bearing 01.x leaves directly in the section with source-faithful displayNumber values and short badgeLabel values such as 1, 2, and 3. The visible badges inside Question 1 should be 1, 2, 3, not 01.1, 01.2, 01.3.
Use answer_bank when the source prints visible blanks plus a fixed option bank such as (A) to (D). Keep running sentence prose in segments[], keep source labels in options[].label, and omit decorative underscore or bracket markers from segments. Use displayMode: "inline_labeled" by default; use banked only when the source shows a separate answer bank or the labelled option text is too long for the selector.
For answer_bank, segments.length must equal blanks.length + 1. Each blank has a plain object such as { "placeholder": "term" } or {}. Each option needs a stable id, a source label such as A, and source option text. Example:
{
"id": "q02_1",
"type": "answer_bank",
"displayNumber": "02.1",
"marks": 3,
"prompt": "Complete the sentences.",
"displayMode": "inline_labeled",
"segments": [
"Nuclear fission is the splitting of ",
". It releases energy and ",
"."
],
"blanks": [{ "placeholder": "particle" }, { "placeholder": "radiation" }],
"options": [
{ "id": "nuclei", "label": "A", "text": "nuclei" },
{ "id": "neutrons", "label": "B", "text": "neutrons" },
{ "id": "gamma", "label": "C", "text": "gamma rays" }
]
}
Use mcq for multiple choice. Keep the stem in prompt, options in options[], and choose displayMode: "full_options" by default. Use labels_only only when the source options are already visible in the prompt or are diagram labels/positions. Do not invent placeholder option text such as Option A.
For mcq in labels_only mode, every option still needs a source-faithful label such as A, B, C, or D. If the choice meaning is not already visible in the prompt or diagram, use full_options. For diagram-position MCQs, options[].text may be omitted or empty; do not invent generic option text.
Use calc or fill for short numeric answer lines such as Answer ____ £. Use lines only for longer free responses, explanations, proofs, or working that do not fit richer structured types.
For calc, include inputLabel and unit. Do not add unsupported fields such as lines to a calc question. For section introduction blocks, use only top-level section entries shaped exactly as { "type": "hook", "text": "..." } inside sheet.sections[]. Never put a hook object inside a section's questions[]; questions[] may contain only group, answer_bank, fill, cloze, mcq, lines, calc, match, spelling, or flow entries. Otherwise put shared stems, tables, and figures in group.prompt or a question prompt.
Use flow for box-and-arrow calculation structures. Keep each row's items array in printed left-to-right order and use direction only to describe arrow direction.
\[ array/aligned expression only when it renders cleanly. In JSON strings, LaTeX row breaks must contain two backslash characters in the final Markdown, which means escaping them as \\\\ inside the JSON string. Do not use fenced code blocks for arithmetic layouts; the renderer adds code UI chrome that is not part of the source paper.array, matrix, or aligned environments with borders where appropriate) when that is closer to the source than a Markdown table.First grid rows: ... / ...; render the grid itself with display LaTeX.source-image-cropping skill and link the final crop near the source-faithful prompt.pad_image commonly returns .png, and the worksheet link, crop-validation record, and fresh validation call must all use that same .png path.grader/output/assets/... or sheet/output/assets/..., but never invent a .jpg variant when the tool produced .png.[](grader/output/assets/q1-figure-1.jpg) or [](grader/output/assets/q1-figure-1-border.png) with the matching sheet/output/assets/... path for draft-sheet runs.group.prompt only when shared by all subparts or before the first subpart; child prompt when introduced inside one subquestion.Figure N caption text immediately adjacent to the crop and Table N caption text immediately adjacent to the Markdown table.[Figure N](#figure-n) / [Table N](#table-n) or with Figure N above / Table N above.see source transcription where a student needs the visual. If the visible prompt mentions an answer-critical visual, the worksheet prompt/group prompt itself must include the linked crop or a Markdown table whenever the source pixels/text are available.Figure N wording, and write a visible instruction such as Use Figure N in the linked original PDF.Figure 9 or Table 5; every included answer-critical Figure N must have a linked image near that label unless the artifact plan records why embedding was impossible, and every extracted text/numeric Table N must have a Markdown table near that label.review_run_progress_with_fresh_agent and follow its continue/switch/stop recommendation instead of trying the same path again.Before calling publish_sheet_draft or publish_sheet:
grader/output/sheet.json is the full graded report wrapper (schemaVersion, sheet, answers, review, optional references), not the bare sheet object,sheet/output/draft.json is the draft wrapper (schemaVersion, mode, sheet, optional references),sheet-plan.md and the source-fidelity audit record why a real crop/table attempt failed,\n; use real Markdown line breaks, tables, or clean crops for layout-critical content,references.paperUrl or references.markSchemeUrl are omitted unless a real non-empty URL is known; use paperStoragePath / markSchemeStoragePath for cached shared PDFs whenever available,sheet.title, sheet.subtitle, sheet.level, and presentation fields,presentation.footer is source/provenance identity only, not a process label such as transcription, OCR text, or artifact; naming the OCR exam board is fine when it is the actual source identity, but do not repeat the visible title, subject, level, or subtitle,If publishing fails: