simocracy-v2 · gathering-default-constitution · r2
Re-ran the r1 flow against the production redeploy containing commit adaad59. The template picker no longer hangs — the curated “Default Constitution” template loads on first open, Use attaches it, and submitting the form writes an org.simocracy.gathering record on the user’s PDS with a suggestedInterviewTemplates StrongRef pointing at the facilitator’s template.
Round arc so far: r1 fail → r2 pass.
Headline. The r1 blocker is fixed. The curated Default Constitution interview template (28 questions — 14 open-ended + 14 yes/no) now renders in the picker on first open, attaches to the form via Use, and persists to the user’s PDS as a suggestedInterviewTemplates StrongRef when the gathering is created. Verified end-to-end on the production URL.
Commit adaad59 in components/events/gathering-form-dialog.tsx:
useState to useRef: templatesLoadingRef and allTemplatesLoadedRef.[showTemplatePicker, allTemplates.length, templatesLoading] to [showTemplatePicker].setTemplatesLoading(true) call inside the effect still drives the UI spinner but no longer re-invokes the effect, so the cleanup (cancelled = true) doesn’t race ahead of the async fetch.// before
useEffect(() => {
if (!showTemplatePicker) return;
if (allTemplates.length > 0 || templatesLoading) return;
let cancelled = false;
(async () => {
setTemplatesLoading(true); // ← re-runs effect, cancelled becomes true
try { /* fetch … */ }
finally { if (!cancelled) setTemplatesLoading(false); } // ← never runs
})();
return () => { cancelled = true; };
}, [showTemplatePicker, allTemplates.length, templatesLoading]);
// after
useEffect(() => {
if (!showTemplatePicker) return;
if (allTemplatesLoadedRef.current || templatesLoadingRef.current) return;
templatesLoadingRef.current = true;
setTemplatesLoading(true);
let cancelled = false;
(async () => {
try { /* fetch … */ allTemplatesLoadedRef.current = true; }
finally {
templatesLoadingRef.current = false;
if (!cancelled) setTemplatesLoading(false);
}
})();
return () => { cancelled = true; };
}, [showTemplatePicker]);
/events/<did>/<rkey> renders the Senate walking-world scene with “0 sims” — expected for a freshly-created gathering with no council members yet.The gathering record — including the StrongRef to the facilitator’s curated template — was fetched directly from the user’s PDS before cleanup:
DID=did:plc:cpoagodpqrgs4t7thi5z37uf
curl -s "https://climateai.org/xrpc/com.atproto.repo.listRecords" \
--data-urlencode "repo=$DID" \
--data-urlencode "collection=org.simocracy.gathering" -G | jq '.records[0].value'
{
"$type": "org.simocracy.gathering",
"name": "Default Constitution Test (post-fix)",
"status": "application",
"simSize": "normal",
"createdAt": "2026-04-20T05:24:24.357Z",
"gatheringType": "governance",
"allocationMechanism": "s-process",
"suggestedInterviewTemplates": [
{
"uri": "at://did:plc:awtx57rxuisy4sf4kzzr3uhf/org.simocracy.interviewTemplate/3mjtodp56ps2e",
"cid": "bafyreihqwpezjm4rck4hhldwp4hltwpvlamkg4ia62pjllb5d26er63cwi"
}
]
}
Fixed. Root cause confirmed — templatesLoading was both a state value driving the UI and a dependency of the effect that owned it, so the setter inside the effect re-ran the effect and cleanup flipped cancelled to true before the fetch resolved. Switching the two guards to refs keeps the StrictMode double-invoke happy.
attachTemplateViaUse builds a {uri, cid} pair from the curated template and the submit handler serialises it into suggestedInterviewTemplates. The record round-trips through the PDS exactly as expected for org.simocracy.gathering per AGENTS.md / lib/lexicon-types.ts.
Carried over from r1 — not addressed by this fix. Immediately after Event created!, handleCreated → window.location.reload() re-fetches via the Simocracy indexer and still shows the old count until the indexer catches up (~10 s in this run). Worth a separate issue to either optimistically merge the just-written record into the gallery or to fall back to a PDS read for the current viewer.
satyam2.climateai.org · did:plc:cpoagodpqrgs4t7thi5z37uf
Targethttps://www.simocracy.org/events
Commit under testadaad59 — fix(gathering-form): unstick template picker Loading state
Driveragent-browser (open → snapshot -i → click / fill → screenshot)
Previous roundgathering-default-constitution-r1
Screenshotsassets/01-template-picker-loaded.png … 04-gathering-detail.png