Use this Skill to preregister a study on OSF or AsPredicted, generate CONSORT/STROBE/PRISMA compliance checklists, and track deviations between the registered protocol and final analysis.
Installer avec Codex ou Claude Copiez ce prompt, collez-le dans Codex, Claude ou un autre assistant, puis laissez-le vérifier la page du skill et l'installer pour vous.
Une commande directe contourne le prompt de vérification. Examinez la source avant de l'exécuter.
Use this Skill to preregister a study on OSF or AsPredicted, generate CONSORT/STROBE/PRISMA compliance checklists, and track deviations between the registered protocol and final analysis.
One-line summary: Automate study preregistration on OSF/AsPredicted, generate compliance
checklists (CONSORT, STROBE, PRISMA), and maintain a deviation log between plan and execution.
When to Use This Skill
When you need to preregister a study on OSF (Open Science Framework) or AsPredicted before data collection
When you need to generate a CONSORT checklist for a randomized controlled trial (RCT)
When you need a STROBE checklist for an observational study (cohort, case-control, cross-sectional)
When you need a PRISMA 2020 checklist for a systematic review
When you want to log deviations from the preregistered analysis plan
When you are preparing a Registered Report (Stage 1 / Stage 2) for a journal
Trigger keywords: preregister, preregistration, OSF registration, AsPredicted, open science, registered report, CONSORT, STROBE, PRISMA, study protocol, HARKing, p-hacking prevention
Background & Key Concepts
Why Preregister?
Preregistration timestamps a study's hypotheses, design, and analysis plan before data collection.
It prevents two major threats to research validity:
HARKing (Hypothesizing After Results are Known): presenting exploratory findings as confirmatory
p-hacking: selectively reporting analyses that yield p < .05
Preregistered findings carry stronger evidential weight because the researcher could not have adjusted the
hypothesis to fit the data.
Platform Comparison
Platform
Best for
Output
API
OSF
All designs, flexible schema
Timestamped PDF + DOI
REST API
AsPredicted
Quick pre-registration (9 questions)
PDF
Manual only
ClinicalTrials.gov
Clinical trials (required by journals)
XML
REST API
PROSPERO
Systematic reviews
Web record
Limited
Deviation Tracking
Every deviation from the preregistered protocol must be documented with:
# 1. Go to https://osf.io/settings/tokens/# 2. Create a personal access token with osf.full_write scope# 3. Set environment variable:export OSF_TOKEN="<paste-your-osf-token>"
import os
from dotenv import load_dotenv
load_dotenv()
OSF_TOKEN = os.getenv("OSF_TOKEN", "")
ifnot OSF_TOKEN:
print("Warning: OSF_TOKEN not set. Set export OSF_TOKEN='<paste-your-token>'")
HEADERS = {
"Authorization": f"Bearer {OSF_TOKEN}",
"Content-Type": "application/json"
}
Core Workflow
Step 1: Create an OSF Project and Draft Registration
import requests
import json
import os
OSF_API = "https://api.osf.io/v2"
OSF_TOKEN = os.getenv("OSF_TOKEN", "")
HEADERS = {"Authorization": f"Bearer {OSF_TOKEN}", "Content-Type": "application/json"}
defcreate_osf_project(title: str, description: str, public: bool = False) -> dict:
"""Create a new OSF project (node) via API."""
payload = {
"data": {
"type": "nodes",
"attributes": {
"title": title,
"description": description,
"category": "project",
"public": public,
}
}
}
resp = requests.post(f"{OSF_API}/nodes/", headers=HEADERS, json=payload)
resp.raise_for_status()
project = resp.json()["data"]
print(f"Created project: {project['id']} — {project['attributes']['title']}")
print(f"URL: https://osf.io/{project['id']}/")
return project
defupload_protocol_file(node_id: str, file_path: str, filename: str) -> dict:
"""Upload a file (e.g., protocol PDF) to an OSF project."""
upload_url = f"https://files.osf.io/v1/resources/{node_id}/providers/osfstorage/"withopen(file_path, "rb") as fh:
resp = requests.put(
f"{upload_url}?name={filename}",
headers={"Authorization": f"Bearer {OSF_TOKEN}"},
data=fh
)
resp.raise_for_status()
print(f"Uploaded {filename} → node {node_id}")
return resp.json()
# Demo (requires valid OSF_TOKEN):if OSF_TOKEN:
project = create_osf_project(
title="Study: Effect of X on Y — Preregistration",
description="Preregistration for RCT testing the effect of intervention X on outcome Y.",
public=False
)
PROJECT_ID = project["id"]
else:
PROJECT_ID = "demo_node_id"print("Skipping OSF API call — set OSF_TOKEN to enable")
import pandas as pd
# --- CONSORT 2010 Checklist (abridged) ---
CONSORT_ITEMS = [
("1a", "Title", "Identification as RCT in title"),
("1b", "Abstract", "Structured summary of trial design, methods, results, conclusions"),
("2a", "Background", "Scientific background and explanation of rationale"),
("2b", "Objectives", "Specific objectives or hypotheses"),
("3a", "Trial design", "Description of trial design including allocation ratio"),
("3b", "Trial design", "Important changes to methods after trial commencement"),
("4a", "Participants", "Eligibility criteria for participants"),
("4b", "Setting", "Settings and locations where the data were collected"),
("5", "Interventions", "Interventions for each group with details to allow replication"),
("6a", "Outcomes", "Pre-specified primary and secondary outcome measures"),
("7a", "Sample size", "How sample size was determined"),
("8a", "Randomization", "Method used to generate random allocation sequence"),
("9", "Allocation concealment", "Mechanism used to implement allocation concealment"),
("10", "Implementation", "Who generated the sequence, enrolled, and assigned participants"),
("11a","Blinding", "If done, who was blinded after assignment"),
("12a","Statistical methods", "Methods for primary and secondary outcomes"),
("13a","Participant flow", "Numbers randomized to each group"),
("16", "Recruitment", "Dates defining the periods of recruitment and follow-up"),
("17a","Baseline data", "Baseline demographic and clinical characteristics"),
("18", "Numbers analyzed", "Number of participants in each group included in analysis"),
("19", "Outcomes", "Results for each outcome for each group, effect size and CI"),
("20", "Ancillary analyses", "Results of any subgroup or adjusted analyses"),
("21", "Harms", "All important harms or unintended effects in each group"),
("22", "Limitations", "Trial limitations, sources of potential bias"),
("23", "Generalisability", "Generalisability/external validity of trial findings"),
("24", "Interpretation", "Interpretation consistent with results"),
("25", "Registration", "Registration number and name of trial registry"),
("26", "Protocol", "Where the full trial protocol can be accessed"),
("27", "Funding", "Sources of funding and other support; role of funders"),
]
defgenerate_consort_checklist() -> pd.DataFrame:
"""Return CONSORT 2010 checklist as a DataFrame for self-assessment."""
df = pd.DataFrame(CONSORT_ITEMS, columns=["Item", "Section", "Description"])
df["Reported?"] = "[ ]"
df["Page/Line"] = ""
df["Notes"] = ""return df
consort = generate_consort_checklist()
print("CONSORT 2010 Checklist:")
print(consort[["Item", "Section", "Reported?"]].to_string(index=False))
consort.to_csv("consort_checklist.csv", index=False)
print(f"\nSaved consort_checklist.csv ({len(consort)} items)")
# --- STROBE Observational Checklist (brief) ---
STROBE_ITEMS = [
("1", "Title/Abstract", "Indicate study design with commonly used term"),
("2", "Background", "Explain scientific background and rationale"),
("3", "Objectives", "State specific objectives, including pre-specified hypotheses"),
("4", "Study design", "Present key elements of study design early"),
("5", "Setting", "Describe setting, locations, and dates"),
("6", "Participants", "Eligibility criteria, and methods of selection"),
("7", "Variables", "Define all outcomes, exposures, predictors, confounders, effect modifiers"),
("8", "Measurement", "Give sources and methods of assessment for each variable"),
("9", "Bias", "Describe any efforts to address potential sources of bias"),
("10", "Study size", "Explain how study size was arrived at"),
("11", "Quantitative variables", "Explain how quantitative variables were handled"),
("12", "Statistical methods", "Describe all statistical methods including control of confounding"),
("16", "Main results", "Report unadjusted and adjusted estimates and precision (CIs)"),
("22", "Limitations", "Discuss limitations, taking into account sources of potential bias"),
]
strobe_df = pd.DataFrame(STROBE_ITEMS, columns=["Item", "Section", "Description"])
strobe_df["Reported?"] = "[ ]"
strobe_df.to_csv("strobe_checklist.csv", index=False)
print(f"Saved strobe_checklist.csv ({len(strobe_df)} items)")
Advanced Usage
Deviation Log
import pandas as pd
import datetime
defcreate_deviation_log(preregistration_id: str) -> pd.DataFrame:
"""Initialize a structured deviation log for a preregistered study."""
columns = [
"deviation_id",
"date_noted",
"preregistered_plan",
"actual_action",
"reason",
"impact_on_inference",
"prespecified_contingency",
"logged_by"
]
return pd.DataFrame(columns=columns)
deflog_deviation(df: pd.DataFrame, **kwargs) -> pd.DataFrame:
"""Add a deviation entry."""
entry = {"date_noted": datetime.date.today().isoformat(), **kwargs}
return pd.concat([df, pd.DataFrame([entry])], ignore_index=True)
# Example usage
log = create_deviation_log("osf.io/abc12")
log = log_deviation(
log,
deviation_id="D001",
preregistered_plan="Primary analysis: two-sided independent t-test",
actual_action="Switched to Welch t-test due to unequal variances (Levene p=.02)",
reason="Levene's test indicated heteroscedasticity; Welch is more robust",
impact_on_inference="Minimal: df reduced from 98 to 94, conclusion unchanged",
prespecified_contingency="Yes — protocol stated 'Welch if Levene p<.05'",
logged_by="Jane Doe"
)
log = log_deviation(
log,
deviation_id="D002",
preregistered_plan="Secondary analysis includes SWLS at T2",
actual_action="SWLS data not collected at T2 due to survey software error",
reason="Platform error deleted SWLS items for 12% of T2 responses; excluded as planned",
impact_on_inference="Secondary outcome missing; primary unaffected",
prespecified_contingency="No — unplanned deviation",
logged_by="John Smith"
)
print("\nDeviation Log:")
print(log.to_string())
log.to_csv("deviation_log.csv", index=False)
Registered Report Stage 1/Stage 2 Template
REGISTERED_REPORT_OUTLINE = """
# Registered Report — Stage 1 Submission
## 1. Abstract (250 words max)
## 2. Introduction
- Theoretical background (~2 pages)
- Critical test: primary hypothesis with clear falsification criteria
## 3. Methods
### 3.1 Participants
- Target sample, eligibility, recruitment
- Power analysis with justification
### 3.2 Design
- Between/within subjects, counterbalancing
### 3.3 Stimuli and Procedure
- Sufficient detail for exact replication
### 3.4 Measures
- Primary DV with reliability estimate
- Secondary DVs
### 3.5 Analysis Plan
- Exact statistical test, software, alpha level
- Decision rule for H1 vs H0
- Planned exploratory analyses (clearly labeled)
### 3.6 Exclusion Criteria
- Data quality checks, outlier rules
## 4. Timeline
## References
---
# Stage 2 Addition (post-data-collection):
## 5. Results
- Follow Stage 1 analysis plan exactly
- Label any exploratory deviations with [EXPLORATORY] tag
## 6. Discussion
## 7. Deviation Log
[Attach deviation_log.csv]
"""print(REGISTERED_REPORT_OUTLINE)
withopen("registered_report_outline.md", "w") as f:
f.write(REGISTERED_REPORT_OUTLINE)
print("Saved registered_report_outline.md")
Troubleshooting
Error: 401 Unauthorized from OSF API
Cause: Invalid or expired OSF token.
Fix:
# Re-generate token at https://osf.io/settings/tokens/# Ensure token has osf.full_write scopeexport OSF_TOKEN="<your-new-token>"
Error: 403 Forbidden when creating registration
Cause: Registration endpoint requires project to have specific node settings.
Fix: Create the registration via the OSF web interface for initial setup; use API for file uploads.