solicitation-doc-modifications-udm¶
solicitation-doc-modifications-udm1.0.01.0.0Tags: solicitation requirements modifications udm research-administration proposal-preparation
Audience: pre-award-staff, ingest-pipelines, proposal-checklist-builders
Manifestations in repo: prompt.md · skill/SKILL.md
Given a solicitation text and a sponsor's default document requirements, emit only the diff: modifications to the defaults and net-new documents the solicitation introduces. Each entry links back to the default it overrides (when applicable) via modifies_default and carries a verbatim source_excerpt from the solicitation.
Output contract: see schema.json
Inputs¶
- Solicitation text — markdown, typically OCR-derived from a PDF solicitation.
- Sponsor defaults — a JSON object matching the output shape of
sponsor-doc-defaults-udm. Thedocument_requirementsarray is the baseline the component diffs against.
The component answers the solicitation-specific question: "What does this program change or add, on top of what the sponsor already requires?" The baseline "what does the sponsor require" question is the job of the sibling component sponsor-doc-defaults-udm.
Outputs¶
One JSON object with:
sponsor_name— echoed from the sponsor-defaults inputsponsor_division— echoed from the sponsor-defaults inputsolicitation_id— the solicitation's printed identifier (e.g.,"NSF 24-507"), or null when not discoverablesolicitation_notes— free-text caveats (version analyzed, sections that could not be resolved)document_requirements— array of requirement entries; empty when the solicitation makes no changes
Each requirement entry carries the full sponsor-doc-defaults field set (code, label, description, page_limit, format_spec, is_required, is_per_person, conditional_on) plus:
modifies_default— the defaultcodethis entry overrides, or null for net-newsource_excerpt— verbatim text from the solicitation grounding the entry
See schema.json for the authoritative definition.
Controlled code vocabulary¶
cover_sheet, cover_letter, project_summary, project_narrative, proposal_narrative, specific_aims, references_cited, biosketch, current_pending, collaborators_and_affiliations, facilities, equipment, budget, budget_justification, data_mgmt, postdoc_mentoring, mentoring_plan, results_prior_support, resource_sharing, authentication_key_resources, leadership_plan, human_subjects, vertebrate_animals, select_agent, inclusion_enrollment_report, letter_support, letter_collaboration, letter_of_intent, other.
Same enum as sponsor-doc-defaults-udm. Adding a new code is a MINOR change; removing or renaming one is MAJOR. The two components' enums must stay in lockstep.
Merge semantics¶
A downstream merge of sponsor-doc-defaults-udm output with this component's output should:
- Start from the defaults
document_requirementsarray. - For each entry in this component's
document_requirements: - If
modifies_defaultis set, replace the default with matchingcodewholesale. - If
modifies_defaultis null, append the entry. - Defaults whose
codedoes not appear in anymodifies_defaultpass through unchanged — silence means "use the default."
Why only emit the diff?¶
Emitting only modifications and net-new keeps the solicitation pass focused, makes the source_excerpt requirement enforceable (no grounding, no entry), and keeps the merged result auditable: every deviation from the sponsor default is traceable to a quoted passage in the solicitation.
Manifestations¶
prompt.md— canonical, LLM-agnostic promptskill/SKILL.md— Claude Skill form
Schema¶
schema.json is a JSON Schema (draft 2020-12) defining the full output contract.
Relationship to other components¶
| Component | Role |
|---|---|
sponsor-doc-defaults-udm |
Upstream: emits the sponsor's baseline document requirements |
solicitation-doc-modifications-udm (this) |
Pairs with defaults: emits only the solicitation's diff |
document-type-classifier-udm |
Shares the code vocabulary; classifies incoming documents against it |
proposal-completeness-review-udm |
Consumes the merged defaults + modifications to check a draft proposal |
Evals¶
See evals/ for reference inputs and known-good outputs. The initial set covers three shapes:
- a solicitation that only modifies defaults,
- a solicitation that only adds net-new documents,
- a solicitation that does both.
Provenance¶
Designed 2026-04-19 in response to issue #3. The diff-only output shape was chosen over "emit the full merged checklist" so that every deviation from the sponsor default is grounded in a verbatim solicitation excerpt and so the sponsor and solicitation passes can be evolved independently.
Contract scope¶
-
Output format:
json_object -
Contract scope:
repo_local_requirements_diff_contract -
Validation surfaces:
json_schema,golden_eval_cases -
Schema entrypoints:
# -
Notes: Repo-local solicitation-diff contract. Although the component name carries -udm, the schema is a prompt-library document-requirements diff surface rather than a shared AI4RA-UDM schema.
-
Machine-readable catalog entry:
component_catalog.json
Triad integration¶
-
UDM alignment:
repo_local_requirements_diff_contract— The output feeds UDM-backed proposal workflows, but the requirement-diff semantics and code list are maintained locally in prompt-library. -
Evaluation datasets: no shared
evaluation-data-setscatalog entry recorded yet; current references are repo-local eval artifacts. -
Harness notes: Invoke only after resolving sponsor-doc-defaults-udm, then merge the diff onto the defaults by code/modifies_default semantics. Current eval coverage is repo-local synthetic cases.
-
Related component:
sponsor-doc-defaults-udm(depends_on_upstream_prior) — The solicitation diff requires sponsor defaults as an input prior. -
Related component:
document-type-classifier-udm(shares_document_code_vocabulary) — Both use the same repo-local document code vocabulary.
Prompt body¶
Source: prompt.md.
Show prompt
Solicitation Document Modifications — UDM¶
Purpose: Given a solicitation (markdown, typically OCR-derived) and the sponsor's default document requirements, emit (a) modifications the solicitation makes to those defaults and (b) additional documents the solicitation introduces.
Expected input: A solicitation text block plus a sponsor-defaults JSON object matching the output shape of
sponsor-doc-defaults-udm.Expected output: A single JSON object that validates against
schema.json. No prose, no markdown outside the JSON.
Prompt¶
You are a research-administration extraction engine. You are given two inputs: a solicitation text and a sponsor-defaults JSON object. Your job is to emit the subset of document requirements the solicitation changes from the defaults plus the documents it introduces as net-new — nothing else. Defaults that the solicitation leaves unchanged must not appear in the output; downstream consumers will treat absent codes as pass-through.
Produce one JSON object matching the output contract — no preamble, no commentary, no markdown outside the JSON. If the runtime requires a fenced block, wrap the object in a single ```json ... ``` block and emit nothing else.
Inputs¶
-
Solicitation text. A markdown block — typically OCR-derived from a PDF solicitation. May contain tables, bullet lists, and administrative headers. Treat it as authoritative for this solicitation.
-
Sponsor defaults. A JSON object with
sponsor_name,sponsor_division,knowledge_notes, anddocument_requirements, as emitted bysponsor-doc-defaults-udm. Use thedocument_requirementsarray as the baseline you are diffing against.
Output contract¶
Emit one object with these fields:
-
sponsor_name— echo the value from the sponsor-defaults input verbatim. -
sponsor_division— echo the value from the sponsor-defaults input verbatim. -
solicitation_id— the solicitation's printed identifier (e.g.,"NSF 24-507","PAR-24-123","DE-FOA-0003100"). Null when the solicitation text does not expose one. -
solicitation_notes— free-text caveats: which version of the solicitation was analyzed, sections that could not be resolved, program families the solicitation belongs to. Null when no caveats apply. -
document_requirements— array of requirement entries. May be empty when the solicitation neither modifies defaults nor introduces new documents.
Each requirement entry must include all of:
-
code— from the controlled vocabulary below. -
label— the solicitation's printed label for the document. Prefer the solicitation's term. -
description— one or two sentences. For modifications, emphasize the delta from the default. -
page_limit— integer or null. Use null when the solicitation does not state a limit and the entry is net-new; for a modification that removes a limit, use null and state the removal indescription. -
format_spec— formatting constraints the solicitation imposes. Null when none beyond the sponsor's general rules. -
is_required—truefor required documents (including conditional requirements, which also populateconditional_on).falseonly when the solicitation explicitly marks the document optional. -
is_per_person—truewhen the solicitation requires one instance per senior person. Echo the default's per-person flag when the solicitation is silent. -
conditional_on— short English condition. Null when unconditional. -
modifies_default— the defaultcodethis entry overrides, or null for a net-new document. The code value must exist in the sponsor-defaults input'sdocument_requirementswhen set. -
source_excerpt— verbatim text from the solicitation grounding the modification or the new requirement. Short (a sentence or two). Quote exactly; do not paraphrase. When the solicitation uses a table or bulleted list, quote the relevant row or bullet.
Controlled code vocabulary¶
Use only these code values:
cover_sheet, cover_letter, project_summary, project_narrative, proposal_narrative, specific_aims, references_cited, biosketch, current_pending, collaborators_and_affiliations, facilities, equipment, budget, budget_justification, data_mgmt, postdoc_mentoring, mentoring_plan, results_prior_support, resource_sharing, authentication_key_resources, leadership_plan, human_subjects, vertebrate_animals, select_agent, inclusion_enrollment_report, letter_support, letter_collaboration, letter_of_intent, other.
This is the same vocabulary sponsor-doc-defaults-udm uses. When the solicitation introduces a document that fits no enumerated code, use other with a distinctive label and describe the document in description.
What counts as a modification¶
A solicitation modifies a default when it changes any of the following on a document already present in the defaults:
-
page_limit(tighter or looser, or removal of a limit) -
format_spec(new required subheadings, new font rules, a prescribed template) -
is_required(flipping an optional default to required, or a required default to optional) -
is_per_person(rarely — most commonly when the solicitation names a new per-person role) -
conditional_on(adding or dropping a condition) -
descriptionmaterially — when the solicitation redefines what the document must contain
When a modification applies, emit the full requirement object — not just the changed fields. Downstream consumers replace the default with this entry wholesale. Fields the solicitation does not touch should be carried over from the default (e.g., when the solicitation only shortens the page limit, is_required, is_per_person, and conditional_on echo the default).
What counts as net-new¶
A solicitation introduces a document when it requires a document that is not present in the sponsor's defaults — even if a similar document exists under a different code. Examples:
-
NSF ERC solicitations requiring a Strategic Plan or Knowledge Transfer Plan
-
NIH RFAs requiring a Milestones and Timeline supplement
-
DoE FOAs requiring a Community Benefits Plan or an Equity Plan
-
Any sponsor adding a program-specific narrative distinct from
proposal_narrative
Emit these with modifies_default: null. Use the most specific enumerated code that fits; fall back to other only when no enumerated code describes the document.
What not to emit¶
-
Do not emit defaults that pass through unchanged. Silence means "use the default."
-
Do not emit a modification when the solicitation merely restates a default. Restatement without change is not a modification.
-
Do not invent constraints the solicitation does not state. If the solicitation is silent on
page_limit, carry the default's value (or null for net-new) rather than guessing. -
Do not synthesize a
source_excerpt. If you cannot quote a grounding excerpt from the solicitation, omit the entry.
Empty output¶
When the solicitation neither modifies the defaults nor introduces new documents (rare but possible for a brief reissuance), emit:
{
"sponsor_name": "<echo>",
"sponsor_division": "<echo>",
"solicitation_id": "<id or null>",
"solicitation_notes": "Solicitation analyzed; no modifications to sponsor defaults detected.",
"document_requirements": []
}
Ordering¶
Order document_requirements with modifications first (grouped by the order of the defaults they override) and net-new documents last. This ordering is a convention for readability; downstream consumers should not rely on it semantically.
Quality standards¶
-
Verbatim grounding. Every entry has a
source_excerptthat is a literal quote from the solicitation. A paraphrased or synthesized excerpt is a failure. -
Deltas, not copies. The output is only the diff — modifications and net-new. Emitting unchanged defaults is a failure.
-
Modification targets a real default.
modifies_default, when set, is a code present in the sponsor-defaults input. -
Full object on modification. A modification emits all required fields, not just the changed ones.
-
Vocabulary fidelity. Only enumerated codes.
otheris a fallback, not a convenience. -
Schema conformance. Output validates against
schema.json.
Produce the JSON now.
Output schema¶
Source: schema.json.
Show schema.json
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://github.com/AI4RA/prompt-library/components/solicitation-doc-modifications-udm/schema.json",
"title": "Solicitation Document Modifications \u2014 UDM Output",
"description": "Single JSON object listing solicitation-specific modifications to a sponsor's default document requirements and any net-new documents the solicitation introduces. Consumes the output shape of sponsor-doc-defaults-udm as a prior and pairs with it to form a two-pass requirements pipeline.",
"version": "1.0.0",
"type": "object",
"additionalProperties": false,
"required": [
"sponsor_name",
"sponsor_division",
"solicitation_id",
"solicitation_notes",
"document_requirements"
],
"properties": {
"sponsor_name": {
"type": "string",
"minLength": 1,
"description": "Sponsor as carried forward from the sponsor-defaults input. Echo the value verbatim so downstream merging can key on it."
},
"sponsor_division": {
"type": [
"string",
"null"
],
"description": "Division, directorate, institute, or center as carried forward from the sponsor-defaults input. Null when the caller did not provide one."
},
"solicitation_id": {
"type": [
"string",
"null"
],
"description": "The sponsor's printed identifier for the solicitation (e.g., 'NSF 24-507', 'PAR-24-123', 'DE-FOA-0003100'). Null when the solicitation text does not expose one."
},
"solicitation_notes": {
"type": [
"string",
"null"
],
"description": "Free-text caveats: which version of the solicitation was analyzed, sections that could not be resolved, or program families the solicitation belongs to. Null when no caveats apply."
},
"document_requirements": {
"type": "array",
"description": "Array of document requirement entries. Each entry is either a modification to a default (modifies_default set to the code of the default it overrides) or a net-new document the solicitation introduces (modifies_default null). Defaults that the solicitation leaves unchanged are not emitted \u2014 a downstream merge should treat absent codes as pass-through.",
"items": {
"$ref": "#/$defs/documentRequirement"
}
}
},
"$defs": {
"documentCode": {
"type": "string",
"enum": [
"cover_sheet",
"cover_letter",
"project_summary",
"project_narrative",
"proposal_narrative",
"specific_aims",
"references_cited",
"biosketch",
"current_pending",
"collaborators_and_affiliations",
"facilities",
"equipment",
"budget",
"budget_justification",
"data_mgmt",
"postdoc_mentoring",
"mentoring_plan",
"results_prior_support",
"resource_sharing",
"authentication_key_resources",
"leadership_plan",
"human_subjects",
"vertebrate_animals",
"select_agent",
"inclusion_enrollment_report",
"letter_support",
"letter_collaboration",
"letter_of_intent",
"other"
],
"description": "Controlled document-code vocabulary shared with sibling prompt-library components (sponsor-doc-defaults-udm, document-type-classifier-udm, proposal-completeness-review-udm). Use 'other' with a descriptive label when no enumerated code fits and consider proposing a new code in a follow-up PR."
},
"documentRequirement": {
"type": "object",
"additionalProperties": false,
"required": [
"code",
"label",
"description",
"page_limit",
"format_spec",
"is_required",
"is_per_person",
"conditional_on",
"modifies_default",
"source_excerpt"
],
"properties": {
"code": {
"$ref": "#/$defs/documentCode"
},
"label": {
"type": "string",
"minLength": 1,
"description": "The solicitation's printed label for the document. Prefer the solicitation's term over a generic one. When the solicitation only changes one attribute (e.g., page limit) and reuses the sponsor's label, echo the sponsor label here."
},
"description": {
"type": "string",
"minLength": 1,
"description": "One or two sentences explaining what the document is, using the solicitation's framing. When the entry is a modification, emphasize the delta from the default."
},
"page_limit": {
"type": [
"integer",
"null"
],
"minimum": 1,
"description": "Page limit as stated in the solicitation. For a modification, this is the solicitation's page limit (which may be tighter or looser than the default). For a net-new document, this is the solicitation's limit or null when unstated."
},
"format_spec": {
"type": [
"string",
"null"
],
"description": "Formatting constraints the solicitation imposes (font, line spacing, margins, required subheadings, file type, template). Null when the solicitation does not specify constraints beyond the sponsor's general rules."
},
"is_required": {
"type": "boolean",
"description": "True when the solicitation requires this document. False only when the solicitation explicitly marks it optional. Conditionally-required documents set is_required=true and populate conditional_on."
},
"is_per_person": {
"type": "boolean",
"description": "True when the solicitation requires one instance per senior person. Echo the default's per-person flag when the solicitation does not speak to it."
},
"conditional_on": {
"type": [
"string",
"null"
],
"description": "Short English description of the condition that makes this requirement apply, when the requirement is conditional. Null when unconditional."
},
"modifies_default": {
"oneOf": [
{
"$ref": "#/$defs/documentCode"
},
{
"type": "null"
}
],
"description": "When this entry modifies a sponsor default, the code of the default it overrides. Null when this entry is a net-new document introduced by the solicitation. Downstream merging replaces the default with this entry when set; when null, the entry is appended."
},
"source_excerpt": {
"type": "string",
"minLength": 1,
"description": "Verbatim text from the solicitation grounding the modification or the new requirement. Short \u2014 a sentence or two. Quote exactly; do not paraphrase. If the solicitation uses a table or bulleted list, quote the relevant row or bullet."
}
}
}
}
}
Evals¶
Reference cases¶
Golden cases under evals/cases/.
-
nih-rfa-mixed— NIH RFA shortens Research Strategy and adds Milestones and Timeline (artifacts: input, expected) -
nsf-dcl-narrative-tightened— NSF Dear Colleague Letter tightens narrative and DMP (artifacts: input, expected) -
nsf-erc-net-new-plans— NSF Engineering Research Center adds Strategic Plan and Knowledge Transfer Plan (artifacts: input, expected)
Changelog¶
Source: CHANGELOG.md.
All notable changes to this component. Versions follow semver: MAJOR for output-contract breaks (schema changes that drop or rename fields, or remove / rename vocabulary codes), MINOR for backward-compatible additions (new vocabulary codes, new optional fields, new manifestations), PATCH for wording or clarity with no behavior change expected.
The schema.json version is kept in lockstep with the component version. The controlled code vocabulary is shared with sponsor-doc-defaults-udm; vocabulary changes must be coordinated across both components.
[1.0.0] — 2026-04-19¶
- Initial version.
- JSON Schema (
schema.json) defining a single output object withsponsor_name,sponsor_division,solicitation_id,solicitation_notes, and adocument_requirementsarray. Each requirement object extends thesponsor-doc-defaults-udmrequirement shape withmodifies_default(nullable code) andsource_excerpt(verbatim solicitation text). - Diff-only output semantics: defaults the solicitation leaves unchanged are not echoed back; downstream merging treats absent codes as pass-through.
- Controlled 29-code vocabulary shared with
sponsor-doc-defaults-udm,document-type-classifier-udm, and (when introduced)proposal-completeness-review-udm. - Canonical prompt (
prompt.md) defining what counts as a modification, what counts as net-new, verbatim-grounding requirements, and the empty-output case. - Claude Skill manifestation (
skill/SKILL.md) tuned for "what does this solicitation change or add beyond the sponsor defaults?" triggers. - Three golden eval cases: modify-only, net-new-only, and a case that exercises both shapes.