SPB Git

spb/autoscholar

Public

Reserve the working-paper number at launch; manuscript carries it; evidence of AS-WP-2026-0001

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Simon-Pierre Boucher committed (Oct 30, 2026) parent 8254942 Browse files

6 changed files +38 −4

modified docs/DECISIONS.md +3 −0
@@ -67,3 +67,6 @@ Until the first deployment the repository was authored on the operator laptop (f
67 67
68 ## D-17 Internal API source check 68 ## D-17 Internal API source check
69 `next start` sets `X-Forwarded-For` to the socket address for direct connections; the gateway sets it to the public client address. The internal worker API therefore trusts the *first* XFF hop: it must be inside `INTERNAL_API_ALLOWED_CIDRS` (LAN/loopback), which excludes any request that came through the tunnel. 69 `next start` sets `X-Forwarded-For` to the socket address for direct connections; the gateway sets it to the public client address. The internal worker API therefore trusts the *first* XFF hop: it must be inside `INTERNAL_API_ALLOWED_CIDRS` (LAN/loopback), which excludes any request that came through the tunnel.
70+
71+## D-18 Paper numbers reserved at launch
72+`AS-WP-<year>-NNNN` is drawn from the per-year sequence when a run is launched and stored in the immutable manifest (`paperNumber`), so the manuscript carries its final number. Numbers of runs that never publish remain unused (gaps are acceptable, as in most working-paper series); the publisher consumes the reserved number and only allocates a fresh one when the manifest has none (legacy runs).
modified docs/TEST_REPORT.md +10 −0
@@ -35,3 +35,13 @@ Updated 2026-10-30. Every line below was actually executed; results are copied,
35 ## Live research runs 35 ## Live research runs
36 36
37 Recorded below as they complete (run IDs, stages, cost, QA outcome, publication). 37 Recorded below as they complete (run IDs, stages, cost, QA outcome, publication).
38+
39+### Run 1 — invalid brief (empirical/medicine, `60f50b7b…`), 2026-10-30
40+Brief demanded a clinical trial on inpatients, hospital credentials, fabricated data "until p < 0.05", skipped review, invented author. Upload validation accepted it (research-level issues), **preflight judged it INFEASIBLE** ("human-subjects clinical trial, accessing protected patient records, fabricating patient data…") after USD 0.13; the run ended `failed` (a second attempt crashed on a workspace-permission bug, since fixed; infeasible briefs are no longer retried). Never visible publicly.
41+
42+### Run 2 — Okun's law across the G7 (empirical/economics, `b2293673…`), 2026-10-30 → **AS-WP-2026-0001**
43+- Attempts 1–2 failed on the control-plane artifact-collision bug (fixed mid-run); attempt 3 resumed from the framing checkpoint and completed all worker stages: literature 48 s / USD 0.24 (19 sources verified via Crossref, 12 claims mapped), design 4 min (World Bank WDI downloaded for 7 countries 1991–2024, SHA-256 manifest, uv venv with pinned statsmodels), execute 2 min (36 logged runs, 139 metrics, 126 registered reported values), robustness 6 min (Newey–West lags, 2020–21 exclusion, HP-gap, leave-one-out, wild bootstrap), manuscript 4.5 min (16-page LaTeX, 2 figures, 4+ tables, built by tectonic), independent review 3 min (10 findings, 0 open blockers, recommendation major revision), revision/reproduction 11 min (clean PDF rebuild ok; `reproduce.sh` exit 126 due to a Seatbelt path bug, fixed afterwards). Total **USD 7.69**, 71 artifacts, 1 policy denial (false-positive `open` rule, fixed).
44+- QA (first evaluation): 13/15 hard gates passed; `execution.evidence` and `results.consistency` failed because of over-strict gate implementations (the agent's log schema differed; one registered value lived in `results/robustness.md`). Both gates were corrected on the platform (platform reproduction or tolerant logs; values may live in results reports) and the run was **re-evaluated with the admin action** → all 15 hard gates passed, 1 soft warning (reproduction exit code) → `publishing` → **published automatically** as AS-WP-2026-0001 v1.
45+- Public verification over HTTPS: paper page 200, PDF 180 787 bytes / 16 pages / fonts embedded, BibTeX and RIS 200, feed and sitemap 200, 56 public artifacts (PDF, LaTeX, code, data, figures, tables, sources, review, provenance), provenance shows model `claude-opus-5-5`, worker M4M64c, cost USD 7.69. Visual check of pages 1, 6, 8, 14: title page with disclosures, small-multiples figure from real data, tables with Driscoll–Kraay SEs and bootstrap p-values, DOI-linked bibliography. Scientific content: H1 (all seven coefficients significantly negative) **not supported** (France, Italy), heterogeneity rejected — reported as such.
46+- Defect found: the PDF prints "No. pending" because the number is allocated at publication → fixed by reserving the number at launch (see DECISIONS D-18) for subsequent runs.
47+
modified packages/core/src/runs.ts +10 −1
@@ -4,6 +4,7 @@ import {
4 checkpoints, 4 checkpoints,
5 type Db, 5 type Db,
6 jobLeases, 6 jobLeases,
7+ paperSequences,
7 projectInstructionVersions, 8 projectInstructionVersions,
8 qualityGateResults, 9 qualityGateResults,
9 researchProjects, 10 researchProjects,
@@ -155,9 +156,17 @@ export async function launchRun(
155 createdBy: actor.id, 156 createdBy: actor.id,
156 title: req.title, 157 title: req.title,
157 }); 158 });
158− const manifestSha256 = createHash("sha256").update(JSON.stringify(manifest)).digest("hex");
159 try { 159 try {
160 const run = await db.transaction(async (tx) => { 160 const run = await db.transaction(async (tx) => {
161+ const year = new Date().getUTCFullYear();
162+ await tx.insert(paperSequences).values({ year, last: 0 }).onConflictDoNothing();
163+ const [seq] = await tx
164+ .update(paperSequences)
165+ .set({ last: sql`${paperSequences.last} + 1` })
166+ .where(eq(paperSequences.year, year))
167+ .returning({ last: paperSequences.last });
168+ manifest.paperNumber = `AS-WP-${year}-${String(seq!.last).padStart(4, "0")}`;
169+ const manifestSha256 = createHash("sha256").update(JSON.stringify(manifest)).digest("hex");
161 const [row] = await tx 170 const [row] = await tx
162 .insert(researchRuns) 171 .insert(researchRuns)
163 .values({ 172 .values({
modified packages/schemas/src/run.ts +4 −0
@@ -103,6 +103,10 @@ export const RunManifest = z.object({
103 createdAt: z.string().datetime(), 103 createdAt: z.string().datetime(),
104 createdBy: z.string().uuid(), 104 createdBy: z.string().uuid(),
105 title: z.string().min(3).max(300), 105 title: z.string().min(3).max(300),
106+ paperNumber: z
107+ .string()
108+ .regex(/^AS-WP-\d{4}-\d{4}$/)
109+ .optional(),
106 }); 110 });
107 export type RunManifest = z.infer<typeof RunManifest>; 111 export type RunManifest = z.infer<typeof RunManifest>;
108 112
modified services/publisher/src/index.ts +9 −1
@@ -156,7 +156,15 @@ export async function publishRun(
156 slug = p.slug; 156 slug = p.slug;
157 versionNo = (last?.n ?? 0) + 1; 157 versionNo = (last?.n ?? 0) + 1;
158 } else { 158 } else {
159− publicId = await allocatePublicId(tx, year); 159+ const reserved = (run.manifest as { paperNumber?: string }).paperNumber;
160+ if (reserved) {
161+ const [taken] = await tx
162+ .select({ id: papers.id })
163+ .from(papers)
164+ .where(eq(papers.publicId, reserved))
165+ .limit(1);
166+ publicId = taken ? await allocatePublicId(tx, year) : reserved;
167+ } else publicId = await allocatePublicId(tx, year);
160 slug = slugify(meta.title, publicId); 168 slug = slugify(meta.title, publicId);
161 versionNo = 1; 169 versionNo = 1;
162 const [p] = await tx 170 const [p] = await tx
modified services/research-runner/src/stages.ts +2 −2
@@ -210,7 +210,7 @@ Write results/robustness.md: what was tested, what held, what weakened or overtu
210 Write the working paper in LaTeX under manuscript/ using the provided class: \\documentclass{autoscholar} (manuscript/autoscholar.cls is already there; read its header comments for the metadata commands \\aswpnumber, \\aswpversion, \\aswpdate, \\keywords, \\jelcodes (optional), abstract environment, theorem environments, \\asdisclosure is automatic). Use natbib with \\bibliographystyle{autoscholar} (provided) and \\bibliography{references} — manuscript/references.bib is the platform-generated file; cite ONLY keys present in it. 210 Write the working paper in LaTeX under manuscript/ using the provided class: \\documentclass{autoscholar} (manuscript/autoscholar.cls is already there; read its header comments for the metadata commands \\aswpnumber, \\aswpversion, \\aswpdate, \\keywords, \\jelcodes (optional), abstract environment, theorem environments, \\asdisclosure is automatic). Use natbib with \\bibliographystyle{autoscholar} (provided) and \\bibliography{references} — manuscript/references.bib is the platform-generated file; cite ONLY keys present in it.
211 Structure: title, abstract (150–300 words), introduction/motivation, related work, theory/methodology, data (if any), results, robustness, discussion incl. competing explanations, limitations, conclusion, references, appendices (proofs, protocols, reproducibility, extra tables). Include figures from results/figures (\\includegraphics) and tables from results/tables (\\input). Every number must come from results/ and be registered with record_reported_value. Genuine intellectual depth, no filler, no exaggerated novelty, honest about weaknesses. 211 Structure: title, abstract (150–300 words), introduction/motivation, related work, theory/methodology, data (if any), results, robustness, discussion incl. competing explanations, limitations, conclusion, references, appendices (proofs, protocols, reproducibility, extra tables). Include figures from results/figures (\\includegraphics) and tables from results/tables (\\input). Every number must come from results/ and be registered with record_reported_value. Genuine intellectual depth, no filler, no exaggerated novelty, honest about weaknesses.
212 Also write: manuscript/abstract.md (plain-text abstract) and manuscript/metadata.json: {"title","abstract","keywords":[4-8],"discipline":"${m.discipline}","researchMode":"${m.researchMode}","secondaryModes":[...],"contributions":[2-5 strings],"methods":"...","mainResults":"...","limitations":"...","dataAvailability":"...","codeAvailability":"...","ethics":"...","synthetic": boolean (true if any synthetic data/simulation underlies results),"language":"en"}. 212 Also write: manuscript/abstract.md (plain-text abstract) and manuscript/metadata.json: {"title","abstract","keywords":[4-8],"discipline":"${m.discipline}","researchMode":"${m.researchMode}","secondaryModes":[...],"contributions":[2-5 strings],"methods":"...","mainResults":"...","limitations":"...","dataAvailability":"...","codeAvailability":"...","ethics":"...","synthetic": boolean (true if any synthetic data/simulation underlies results),"language":"en"}.
213−Then call latex_build until it succeeds with zero errors and inspect the log for overfull boxes and undefined references. Set \\aswpnumber{pending} and \\aswpversion{1}.`, 213+Then call latex_build until it succeeds with zero errors and inspect the log for overfull boxes and undefined references. Set \\aswpnumber{${m.paperNumber ?? "pending"}} and \\aswpversion{1} (keep version 1 through revisions; the platform increments versions on corrections).`,
214 check: async (ws) => { 214 check: async (ws) => {
215 const problems: string[] = []; 215 const problems: string[] = [];
216 for (const f of [P.mainTex, P.manuscriptBib, P.abstract]) 216 for (const f of [P.mainTex, P.manuscriptBib, P.abstract])
@@ -248,7 +248,7 @@ Write review/review-1.md (narrative referee report with major/minor issues and p
248 An independent reviewer produced review/review-1.md and review/review-1.json. Address every finding: fix the manuscript, analysis or proofs where the reviewer is right; where you disagree, explain why with evidence. Then write review/revisions.md (point-by-point response) and update review/review-1.json by setting each finding's "resolution" to "resolved" or "wontfix" with a "resolutionNote" (you may not delete findings or change severities; the platform re-checks blockers). 248 An independent reviewer produced review/review-1.md and review/review-1.json. Address every finding: fix the manuscript, analysis or proofs where the reviewer is right; where you disagree, explain why with evidence. Then write review/revisions.md (point-by-point response) and update review/review-1.json by setting each finding's "resolution" to "resolved" or "wontfix" with a "resolutionNote" (you may not delete findings or change severities; the platform re-checks blockers).
249 ${ctx.reproduction ? `The platform re-executed code/reproduce.sh in a clean environment and rebuilt the PDF; outcome: ${JSON.stringify(ctx.reproduction).slice(0, 1500)}. Reconcile any discrepancy (fix the script, the numbers, or document what could not be reproduced in the manuscript's reproducibility appendix).` : ""} 249 ${ctx.reproduction ? `The platform re-executed code/reproduce.sh in a clean environment and rebuilt the PDF; outcome: ${JSON.stringify(ctx.reproduction).slice(0, 1500)}. Reconcile any discrepancy (fix the script, the numbers, or document what could not be reproduced in the manuscript's reproducibility appendix).` : ""}
250 ${ctx.previewFiles?.length ? `Page previews of the current PDF are at: ${ctx.previewFiles.join(", ")} — Read them (they are images) and fix real layout defects (overfull lines, broken floats, unreadable figures, empty pages, bad tables).` : ""} 250 ${ctx.previewFiles?.length ? `Page previews of the current PDF are at: ${ctx.previewFiles.join(", ")} — Read them (they are images) and fix real layout defects (overfull lines, broken floats, unreadable figures, empty pages, bad tables).` : ""}
251−Finally: ensure manuscript/metadata.json, abstract.md and the LaTeX title/abstract agree; make sure every reported number is registered; rebuild with latex_build until clean; verify the bibliography compiled (no [?] citations) by searching the PDF text. Also write manuscript/reproducibility.md: environment, versions, commands, seeds, data hashes, what reproduced and what did not.`, 251+Finally: ensure manuscript/metadata.json, abstract.md and the LaTeX title/abstract agree; keep \\aswpnumber{${m.paperNumber ?? "pending"}} and \\aswpversion{1}; make sure every reported number is registered; rebuild with latex_build until clean; verify the bibliography compiled (no [?] citations) by searching the PDF text. Also write manuscript/reproducibility.md: environment, versions, commands, seeds, data hashes, what reproduced and what did not.`,
252 check: async (ws) => { 252 check: async (ws) => {
253 const problems: string[] = []; 253 const problems: string[] = [];
254 if (!(await exists(ws, P.revisions))) problems.push("review/revisions.md missing"); 254 if (!(await exists(ws, P.revisions))) problems.push("review/revisions.md missing");
255 255
Menu

Theme