@@ -87,6 +87,53 @@ or `01_pcc` (`PCC_RESEARCH_QUESTION`); the optional `07_research_software`
8787(` RESEARCH_SOFTWARE ` ) and ` 08_synthesis ` (` RESEARCH_SYNTHESIS ` ) steps append when
8888applicable.
8989
90+ ## Repeatable and complex fields — array-shaped, form-field names
91+
92+ A few template fields are ** repeatable groups** (an "add another" list) or custom
93+ widgets, and for these the component's form-field name is ** not** the template
94+ placeholder name and the value is ** not** a flat string. ` prefill ` must use the
95+ form-field name and the exact shape below (verified against the platform's
96+ ` create/components/templates/*.tsx ` ). The producer hard-codes these; the wizard
97+ stays a pass-through.
98+
99+ | Step | Form field (prefill key) | Shape | Notes |
100+ | ---| ---| ---| ---|
101+ | ` 06_citation ` | ` st02 ` | ` [{ cites, cited }] ` | ** required ≥1.** ` cites ` = a CiTO relation URI, ` cited ` = the cited work. This replaces flat ` cites ` /` cited ` . |
102+ | ` 08_synthesis ` | ` sources ` | ` [{ source }] ` | required ≥1 |
103+ | ` 08_synthesis ` | ` topicSelection ` | ` [{ uri, label }] ` | required ≥1 |
104+ | ` 02_aida ` | ` st3 ` / ` st4 ` | ` [{ dataset }] ` / ` [{ publication }] ` | optional |
105+ | ` 02_aida ` | ` topic ` | ` [{ uri, label }] ` | optional |
106+ | ` 04_study ` | ` keywordSelection ` | ` [{ uri, label }] ` | optional |
107+ | ` 04_study ` | ` disciplineSelection ` | ` { uri, label } ` | optional — a single object, ** not** an array |
108+ | ` 07_research_software ` | ` datasets ` / ` researchOutputs ` | ` ["url", …] ` | optional — plain-string arrays |
109+
110+ Two runtime notes for the wizard: ** date** fields (` 05_outcome.date ` ,
111+ ` 08_synthesis.date ` ) want a JS ` Date ` — the wizard converts a ` YYYY-MM-DD ` prefill
112+ string to a ` Date ` before passing it on; and the ` minItems: 1 ` groups above must
113+ always carry at least one entry or the form won't submit.
114+
115+ ## Judgment fields are pre-filled, not left blank
116+
117+ The ` restricted_choice ` dropdowns (claim type, study type, validation status,
118+ confidence, CiTO relation) are ** decisions the agent already made during the
119+ replication** , recorded in the drafts — not things to leave to a form default
120+ (which can be wrong). The producer reads the agent's ticked option from the draft
121+ and puts it in ` prefill ` as an editable suggestion, ** and** keeps the field in
122+ ` manual ` so the wizard flags it "confirm" rather than "you choose". The CiTO
123+ relation is derived from the validation status (Validated→` confirms ` ,
124+ PartiallySupported→` qualifies ` , Contradicted→` disputes ` , …).
125+
126+ The ** URI-suffix id** of each step (` claim ` , ` study ` , ` outcome ` , …), if the draft
127+ gives none, is suggested as ` <org>-<repo>-<step> ` (from ` CITATION.cff ` 's
128+ ` repository-code ` ), editable.
129+
130+ ** Wikidata concept fields** (` 04_study.keywordSelection ` /` disciplineSelection ` ,
131+ ` 02_aida.topic ` , ` 08_synthesis.topicSelection ` ) need a ` {uri, label} ` — but the
132+ draft records only plain labels. The producer resolves each label to a Wikidata
133+ QID at build time (one ` wbsearchentities ` call per label; this is the producer's
134+ only network use, and it degrades to leaving the field empty if Wikidata is
135+ unreachable). ` disciplineSelection ` is a single object; the rest are arrays.
136+
90137## Carry-forward topology
91138
92139Each step's published URI fills one field of the next step. These edges are fixed
@@ -103,6 +150,29 @@ for a FORRT chain and are declared in `carry_forward` so the wizard is generic:
103150The wizard fills the carry-forward field from its captured URI; it does ** not**
104151appear in the producer's ` prefill ` (the URI does not exist until publish time).
105152
153+ ### Optional side-branches (07 / 08) — multiple, non-adjacent, shaped edges
154+
155+ The two optional layers don't continue the linear chain — they link ** back** to
156+ earlier steps, and a step can have ** several** incoming edges. So a step may be
157+ the ` into ` of more than one edge, the ` from ` may be any earlier step (not just the
158+ immediately-preceding one), and the target field may be an array rather than a
159+ scalar. Two optional keys on an edge describe the target shape:
160+
161+ | From (published) | Into | Field | ` mode ` / ` itemKey ` | Injected as |
162+ | ---| ---| ---| ---| ---|
163+ | ` 03_claim ` | ` 07_research_software ` | ` project ` | — (scalar) | ` "<uri>" ` |
164+ | ` 05_outcome ` | ` 07_research_software ` | ` researchOutputs ` | ` mode: "uriList" ` | ` ["<uri>"] ` (appended) |
165+ | ` 05_outcome ` | ` 08_synthesis ` | ` sources ` | ` mode: "uriObjectList" ` , ` itemKey: "source" ` | ` [{ "source": "<uri>" }] ` (appended) |
166+
167+ - ** No ` mode ` ** → scalar string (the linear edges above, and ` 07.project ` ).
168+ - ** ` mode: "uriList" ` ** → append the URI to an array-of-strings field.
169+ - ** ` mode: "uriObjectList" ` ** (+ ` itemKey ` ) → append ` { [itemKey]: uri } ` to an
170+ array-of-objects field.
171+
172+ These edges are emitted only when ** both** ends are present in the chain (the
173+ producer appends 07/08 only when their drafts have content). As with the linear
174+ edges, the carried field is absent from the step's ` prefill ` .
175+
106176### Known friction (for the wizard implementer)
107177
108178Most back-reference fields are plain text inputs (` 02_aida.project ` ,
@@ -121,7 +191,8 @@ fields.
121191 " chain_shape" : " paper-rooted" , // "paper-rooted" | "pico" | "pcc"
122192 " source" : {
123193 " repository" : " https://github.com/OWNER/REPO" ,
124- " commit" : " <sha>" // the repo state the values were drawn from
194+ " commit" : " <sha>" , // the repo state the values were drawn from
195+ " figure" : " figures/main_result.png" // optional; absent when the repo has none
125196 },
126197 " steps" : [
127198 {
@@ -147,7 +218,11 @@ fields.
147218 { " from" : " 02_aida" , " into" : " 03_claim" , " field" : " aida" },
148219 { " from" : " 03_claim" , " into" : " 04_study" , " field" : " claim" },
149220 { " from" : " 04_study" , " into" : " 05_outcome" , " field" : " study" },
150- { " from" : " 05_outcome" , " into" : " 06_citation" , " field" : " work" }
221+ { " from" : " 05_outcome" , " into" : " 06_citation" , " field" : " work" },
222+ // optional side-branches — only when 07/08 are in the chain (see above):
223+ { " from" : " 03_claim" , " into" : " 07_research_software" , " field" : " project" },
224+ { " from" : " 05_outcome" , " into" : " 07_research_software" , " field" : " researchOutputs" , " mode" : " uriList" },
225+ { " from" : " 05_outcome" , " into" : " 08_synthesis" , " field" : " sources" , " mode" : " uriObjectList" , " itemKey" : " source" }
151226 ]
152227}
153228```
@@ -166,6 +241,31 @@ Rules:
166241- ** Determinism:** the producer does not stamp a timestamp (so regenerating on an
167242 unchanged repo yields an identical file); ` source.commit ` records the state.
168243
244+ ## The headline figure
245+
246+ ` source.figure ` is the repo-relative path to the one image that represents the
247+ replication. It is ** not** published in any nanopublication and the wizard does
248+ not consume it — it is recorded because the producer is where a missing figure
249+ can still be noticed and fixed.
250+
251+ The story page the platform generates from a published chain finds the figure by
252+ resolving the chain's Zenodo DOI to its GitHub repo and looking in ` figures/ ` .
253+ So the figure reaches the blog by * being committed at that path* , not by being
254+ declared here. The producer applies the same rule the platform does:
255+
256+ - only ` figures/ ` is scanned — never ` results/ ` , which collects run artefacts;
257+ - among several images, a name matching ` main ` , ` result ` , ` headline ` or ` hero `
258+ wins; otherwise the alphabetically first, so the pick never varies by machine;
259+ - ` .png ` , ` .jpg ` , ` .jpeg ` , ` .webp ` , ` .svg ` count as images.
260+
261+ When nothing is found the producer says so on stderr. The failure this catches is
262+ a figure written to a ** git-ignored** path: it exists on the machine that ran the
263+ experiment, the author sees it locally, and the published story page has no image.
264+
265+ Because the choice is inferred from filenames rather than stated by the author,
266+ it is a sensible default and not a permanent contract — a future FORRT template
267+ field would let the author name the figure explicitly and have it signed.
268+
169269## Value sources (what the producer fills from where)
170270
171271| Field(s) | Source |
0 commit comments