| name | scientistone |
| description | Run a paper-faithful ScientistOne Chain-of-Evidence workflow for repository audits, 2-hop scholarly citation-graph surveys, full-text multi-round literature investigation, experiment discovery, provenance-first paper writing, claim verification, and CoE integrity audits. Use when the user mentions ScientistOne, UltraCode, Chain-of-Evidence, CoE audit, research-topic selection, prior-work surveys, project improvement directions, research planning, paper hooks, evidence provenance, claim verification, or autonomous research workflows. |
ScientistOne
Run ScientistOne natively with Codex tools and subagents. Do not execute the Claude UltraCode
JavaScript; it requires Claude's Workflow host.
Install the pinned PDF dependency before using the paper profile. The dotfiles installer exposes a
scientistone-python wrapper backed by the system interpreter when compatible, or by an isolated
user venv otherwise. Use python3 only for a manual dependency bootstrap; then route every bundled
ScientistOne script through the wrapper, with an explicit interpreter override when needed:
python3 -m pip install --requirement <skill-dir>/requirements.txt
S1PY="${SCIENTISTONE_PYTHON:-scientistone-python}"
Select The Stop Stage
Choose the narrowest stage that satisfies the request, but include every prerequisite stage:
project: audit an existing repository and produce evidence-linked improvement axes.
investigate: ground topic selection in a full-scale literature survey and protocol audit.
discover: implement and externally evaluate competing branches.
write: build a grounded representation and verified paper draft.
audit: run CoE integrity checks I1-I4 and issue a release verdict.
Requests for research topics, novelty, prior art, experiment plans, or improvement directions that
depend on literature require at least investigate. Requests for a paper hook or manuscript require
write; do not compose or promote prose until the Investigation gate passes. Never imply a later
stage ran when its prerequisites did not.
Initialize An Immutable Run
Create a new workspace before substantive work. Default to the paper-fidelity profile; use compact
only when the user explicitly requests a bounded triage rather than ScientistOne-scale research.
"$S1PY" <skill-dir>/scripts/init_run.py \
--project "$PWD" \
--topic "<objective>" \
--stage <stop-stage> \
--profile paper
Use the printed directory as RUN_DIR. Never reuse or overwrite a prior run. Fill
graph/seeds.json with 2-4 resolvable seed identities before starting Investigation. Update
pipeline_state.json only through scripts/update_state.py, which performs atomic replacement.
Build the initial graph with the bundled collector when its providers cover the seeds:
"$S1PY" <skill-dir>/scripts/build_citation_graph.py \
--seeds "$RUN_DIR/graph/seeds.json" \
--output "$RUN_DIR/graph/raw/citation_graph_wave_2000.json" \
--min-candidates 2000 \
--max-candidates 2000
When SEMANTIC_SCHOLAR_API_KEY is set, the collector uses authenticated Semantic Scholar first
and spaces requests by at least one second through a host-level file lock; otherwise it uses
OpenAlex first. It invokes the other provider only after recording a source failure or incomplete
graph. If a recent seed is not yet indexed, use the fail-closed supplemental-seed path below; never
drop the seed silently. Expose OpenAlex credentials as
OPENALEX_API_KEY; the collector redacts credentials from provider receipts. Do not run the same
S2 key concurrently on different hosts unless SCIENTISTONE_RATE_LIMIT_DIR is a reliable shared
lock directory or requests pass through a shared provider gateway.
A recent unindexed seed is admissible only from locally retrieved PDF bytes, not from an official
event page, author page, repository, title match, or search snippet alone. Record the PDF path,
SHA-256, byte count, page count, retrieval URL/receipt, and a complete PDF-derived bibliography
ledger that enumerates every reference with a page/reference locator and normalized citation. Bind
the first REFERENCES heading through the next top-level APPENDIX/APPENDICES
heading (or PDF EOF) to the pypdf version and normalized-region hash; after removing only
deterministic repeated headers/footers and page numbers, the ordered full citation texts must cover
that region exactly. A ledger's own COMPLETE label or title-only entries are insufficient.
Identity pages may corroborate the seed but cannot replace that evidence. Before admitting the
supplemental route, bind exact-title zero-candidate receipts from both Semantic Scholar and
OpenAlex. Supply at least two distinct UTF-8 identity files with distinct bytes; every file must
contain the normalized exact seed title, and at least one declared role must be
official_identity. The union of official_identity files must contain the title, year token, and
full abstract. The union of all identity files must contain every non-provider identifier and the
literal landing URL. It must also contain the literal PDF URL, unless the PDF and landing URLs have
the same host and share a query identifier. A declared role is classification metadata, not an
attestation of where bytes originated, so preserve the actual retrieval transaction or browser
evidence separately. CLI values alone are not grounding evidence. Give the supplemental seed an
explicit non-provider namespace and never synthesize an S2/OpenAlex ID.
Resolve every declared bibliography target as a canonical S2 paperId, require the returned title
to match the PDF citation, and admit it as a mandatory hop-one node and frontier root inside the
existing cap. A supplied hop-two allocation is stale unless its exact hop-one set/hash includes
those mandatory roots. Bind each target-metadata batch to its canonical request-body hash, exact
captured response bytes/receipt, and the semantic hashes of the admitted nodes. Emit bibliography
edges only for ledger entries with a defensible target
identity, retain unresolved entries in the ledger, and keep forward citations UNKNOWN
rather than zero or complete. A mixed provider-plus-supplemental graph is valid only when the
validator binds each node and edge to its own provenance route and recomputes the PDF and ledger
hashes. Structural validation does not convert UNKNOWN forward citations into complete coverage
or promotion eligibility. Supplemental records count inside the same declared candidate cap; they
do not increase it.
The supplemental preparation path is staged and copy-pasteable. Outputs are immutable, so use a
new timestamped filename after any failed attempt:
"$S1PY" <skill-dir>/scripts/prepare_supplemental_seed_evidence.py \
--create-retrieval-receipt --pdf "$PDF" --retrieval-url "$PDF_SOURCE_URL" \
--receipt-output "$EVIDENCE_DIR/pdf.receipt.json" --method http_get
"$S1PY" <skill-dir>/scripts/prepare_supplemental_seed_evidence.py \
--create-bibliography-ledger --pdf "$PDF" \
--bibliography-output "$EVIDENCE_DIR/bibliography.unresolved.json"
"$S1PY" <skill-dir>/scripts/prepare_supplemental_seed_evidence.py \
--create-provider-identity-refresh \
--seeds "$RUN_DIR/graph/seeds.json" --seed-id "$SEED_ID" --year "$YEAR" \
--output "$EVIDENCE_DIR/provider-identity-refresh.json"
"$S1PY" <skill-dir>/scripts/prepare_supplemental_seed_evidence.py \
--apply-bibliography-resolution-map \
--bibliography-ledger "$EVIDENCE_DIR/bibliography.unresolved.json" \
--resolution-map "$EVIDENCE_DIR/bibliography-resolution-map.json" \
--bibliography-output "$EVIDENCE_DIR/bibliography.resolved.json"
"$S1PY" <skill-dir>/scripts/prepare_supplemental_seed_evidence.py \
--seeds "$RUN_DIR/graph/seeds.json" --seed-id "$SEED_ID" --pdf "$PDF" \
--retrieval-url "$PDF_SOURCE_URL" \
--retrieval-receipt "$EVIDENCE_DIR/pdf.receipt.json" \
--bibliography-ledger "$EVIDENCE_DIR/bibliography.resolved.json" \
--provider-identity-refresh "$EVIDENCE_DIR/provider-identity-refresh.json" \
--identity-source "official_identity:$OFFICIAL_URL:$OFFICIAL_FILE" \
--identity-source "author_repository:$AUTHOR_URL:$AUTHOR_FILE" \
--year "$YEAR" --abstract "$ABSTRACT" --landing-url "$LANDING_URL" \
--pdf-url "$CANONICAL_PDF_URL" --id "$ID_NAMESPACE:$ID_VALUE" \
--output "$EVIDENCE_DIR/supplemental-evidence.json"
"$S1PY" <skill-dir>/scripts/build_citation_graph.py \
--provider semantic-scholar \
--seeds "$RUN_DIR/graph/seeds.json" \
--frontier-allocation "$ALLOCATION" \
--supplemental-seed-evidence "$EVIDENCE_DIR/supplemental-evidence.json" \
--output "$RUN_DIR/graph/raw/citation_graph_wave_2000.supplemental.json" \
--min-candidates 2000 --max-candidates 2000
Provider refresh requires SEMANTIC_SCHOLAR_API_KEY and optionally uses OPENALEX_API_KEY. It
creates the refresh manifest only when both exact-title probes return zero candidates; candidate or
provider-failure outcomes exit nonzero while retaining their sibling receipt logs. Each resolution
map value must be a canonical 40-character lowercase hexadecimal S2 paperId.
The PDF retrieval receipt binds locally present bytes to a declared URL and timestamp; it is not a
cryptographic attestation that the remote server returned those bytes. Preserve the original
download transaction or browser evidence when stronger provenance is available.
The S2 collector first packs small, count-aware frontier groups into official POST /paper/batch
requests with parent counts and nested reference/citation metadata. It stays below conservative
budgets derived from the provider's 500-parent, 10 MB, and 9,999-citation limits. A nested relation
is complete only when its array length equals the same response's declared count and every nested
paperId is non-null and unique. In an allocated hop-two wave, batch every active parent before
issuing any relation GET. Preserve valid unique rows from an incomplete nested array as the
receipt-bound paper_batch_nested_capped sample, with provider_complete=false and
provider_capped=true; this route never upgrades relation completeness. A relation GET is a lazy
refill, not an automatic response to every incomplete array. Split 400/413 responses; persistent
429/5xx and singleton failures remain explicit incomplete evidence rather than invented edges.
Graph coverage and every emitted edge record the complete-batch, capped-batch, or paginated route.
For a paginated fallback, distinguish provider rows from resolvable paper IDs. Pagination is
complete when the exhausted endpoint returns exactly the declared raw row count with no duplicate
valid paperId; rows whose provider paper object has a null/unusable paperId are counted
explicitly and produce no invented node or edge. A raw-count mismatch, duplicate valid ID,
malformed payload, or publisher-elided relation remains incomplete and blocks promotion.
The current core collector and validator record provider-elided outcomes but do not yet enforce a
typed exclusion binding inside the later allocation and graph chain. Therefore exclusion is an
external precondition, not a capability to infer from the core artifacts: do not omit the relation
or reassign its capacity unless a separate immutable audit binds provider, parent ID, relation,
declared/raw counts, exhaustion state, request receipts, and response hashes and a downstream check
binds that audit into the allocation and graph. Otherwise retain the relation, keep the run
PARTIAL, and forbid promotion. Even a valid external exclusion is provider-availability metadata;
it does not complete the relation, define a research axis or gap, affect relevance scores or tiers,
or authorize candidate-cap expansion.
For an unallocated graph wave, follow every references/citations page until the provider is
exhausted or the declared global node cap is reached. For a calibrated hop-two allocation, sample a
provisional union from all complete and capped batch samples, excluding already admitted hop-zero
and hop-one identities. Canonicalize strong aliases, SHA-order each relation, and apply weighted DRR
from scratch. If that union fills the fixed candidate cap, stop without relation GETs. Otherwise,
refill only under-supplied relations through deterministic cumulative prefixes of 64, 128, 256, and
512 provider rows; over-budget parents enter the same deterministic refill order. After every refill,
recompute aliases, relation ordering, and weighted DRR from scratch, and stop immediately at the
fixed cap. If the first relation of an over-budget parent fills that parent's owner cap, or the
global cap is reached, do not GET its remaining relations. Record each as the zero-row/no-receipt
allocation_satisfied_before_relation_fetch route with provider_complete=false and
provider_capped=true; it is admissible only as PARTIAL staging evidence. Mark every
non-exhausted prefix provider_capped; it is reproducible sampling evidence, never complete
relation coverage. Record the sampling policy, termination reason, remaining
frontier, expanded nodes, and page count. Never infer complete two-hop coverage from node count
alone. Persist request receipts incrementally to
the collector's JSONL receipt log so a mid-crawl failure does not erase source evidence. Cache
successful raw responses by provider and request hash; on S2 429, use the configured cooldown
instead of repeatedly probing the quota window, add bounded jitter, and increase the shared
inter-request interval. After a configured success streak, bounded AIMD-style recovery gradually
returns the interval to its base value. Every receipt records a UTC timestamp, method, and
request-body hash without persisting a secret. Relation and batch receipts do not embed response
bodies. As a narrow exception, each successful S2 seed-resolution receipt embeds the exact raw
response bytes as base64 so the validator can recompute its SHA/size, deterministic winner, provider
paper ID, and compact graph node without access to the operational cache. This is portable internal
evidence, not a provider signature or freshness proof. GET cache identities remain backward
compatible; POST identities also bind the canonical body hash.
Treat 5,000 candidates as a hard ceiling, not the default fill target. Start the collector with 2,000
unique provider paper IDs, then merge only strong DOI or version-normalized arXiv aliases before
scoring; collect replacements if the canonical count falls below 2,000. Use
project/improvement_axes.json only as an allocation aid: distribute generalized queries, the 2-4
seed papers, score shards, Librarian selection, and the five logical Researcher lanes across those
axes, allowing bridge papers to cover more than one. Do not create a new axis phase or mistake an
axis label for evidence that a gap is open.
After the first complete scoring pass, raise the cap in 500-candidate waves when the provisional
top-500 remains unstable, new Core/Adjacent papers are still arriving, or marginal deduplicated
yield remains high. Axis labels may help distribute the next wave's work, but axis balance is
neither a stop condition nor a coverage gate. Reuse successful provider responses and unchanged
score records by stable paper identity, metadata hash, and frozen rubric. Treat 2,000 as the scored
baseline; the earliest evidence-based stop is the first 500-paper comparison wave for which
top-500 churn, new Core/Adjacent arrivals,
and deduplicated yield all satisfy the frozen stability thresholds. Missing wave statistics or
incomplete scoring means UNKNOWN and forces another wave or, at the 5,000 ceiling, a
PARTIAL/NEEDS_SHARDING result. Promote exactly one final staging graph to
graph/citation_graph.json; intermediate waves are not canonical evidence.
For a balanced graph, create its immutable audit before freezing any scoring policy:
"$S1PY" <skill-dir>/scripts/audit_balanced_graph_v1.py \
--graph "$GRAPH" --seeds "$RUN_DIR/graph/seeds.json" \
--frontier-allocation "$ALLOCATION" --target-max "$TARGET_MAX" \
--output "$GRAPH_AUDIT"
For the paper profile, freeze a self-contained two-dimension rubric and scoring contract bound to
the exact graph/seed/audit/allocation hashes, then create balanced fresh-context shards with the
strict preparer:
"$S1PY" <skill-dir>/scripts/prepare_full_graph_scoring_v1.py \
--graph "$GRAPH" \
--seeds "$RUN_DIR/graph/seeds.json" \
--rubric "$RUBRIC" \
--scoring-contract "$CONTRACT" \
--graph-audit "$GRAPH_AUDIT" \
--manifest "$RUN_DIR/graph/raw/full_graph_scoring_manifest.json" \
--output-dir "$RUN_DIR/graph/raw/full_graph_scoring_inputs" \
--shard-size 50
Score every candidate exactly once from its bound title/abstract metadata. Citation count, hop,
origin seed, discovery relation, and descriptive axis labels cannot affect scores or tiers. A paper
without an abstract is LOW confidence and both relevance scores are capped at three. Merge only
after all score shards exist:
"$S1PY" <skill-dir>/scripts/merge_select_full_graph_scores_v1.py \
--scoring-contract "$CONTRACT" \
--manifest "$RUN_DIR/graph/raw/full_graph_scoring_manifest.json" \
--input-shards-dir "$RUN_DIR/graph/raw/full_graph_scoring_inputs" \
--scores-dir "$RUN_DIR/graph/raw/full_graph_scores" \
--ranking-output "$RUN_DIR/graph/raw/full_graph_ranking.json" \
--elite-output "$RUN_DIR/graph/elite_pool.json" \
--receipt-output "$RUN_DIR/graph/raw/full_graph_merge_receipt.json"
When the graph or audit chain is PARTIAL, canonical elite output is forbidden. Continue only with
paths explicitly named staging plus --allow-partial-staging; keep promotion FORBIDDEN and do
not copy or link the staging pool to graph/elite_pool.json. The legacy
scripts/filter_literature.py flow remains available for an explicitly requested compact triage,
not for paper-profile completion.
If a later immutable graph wave changes a chain after the rubric and contract were frozen, use
rebind_full_graph_scoring_v1.py to rebind only graph-specific hashes while proving the scoring
policy unchanged. Then use prepare_delta_scoring_v1.py to carry a score forward only when provider
paper ID, node semantic hash, and frozen policy are unchanged; freshly score every new or
metadata-changed node before the ordinary merge. Both tools write immutable derivatives and keep a
PARTIAL audit staging-only.
Load Stage Instructions
Preserve Paper-Scale Investigation
For the default paper profile, do not shrink the workload to the number of available concurrent
agents. Schedule sequential waves when fewer than five researcher slots exist.
- Traverse references and citations from 2-4 seeds to depth two; retain 2,000-5,000 candidates.
- Score every candidate 1-5 on methodology relevance and problem alignment; produce an elite
pool of approximately 500 with Core, Adjacent, Spark, and Noise labels.
- Abort topic selection when Core+Adjacent contains fewer than five supported papers.
- Run three investigation rounds. Each round must record Librarian selection, five independent
Researcher lanes, SubdomainWriter synthesis, and IslandConsolidator decisions.
- Produce approximately 100 base full-text notes across 5-15 directions. One researcher invocation
reads one full-text paper and emits atomic, page-locatable facts.
- Audit candidate protocols until a direction passes, then run a focused mini-crawl and add 20-30
targeted-refresh notes.
- Produce an Experiment Brief with landscape, experiment plan, and literature context, citing
25-40 sources that resolve to full-text notes.
Do not treat the five-paper relevance abort threshold as the survey target. It is only a weak-seed
abort gate.
Orchestrate With File-Backed Roles
Give every worker exact inputs, a single bounded role, and one output path under RUN_DIR.
Require stable source locators for every factual record. A reducer may read normalized worker
artifacts; it must not invent missing facts. Keep authoring, grounding, criticism, and claim
verification in fresh contexts.
For Paper Writing, preserve this order: Conceive -> Ground -> Critic -> Resolve (at most two
loops, stop on convergence or plateau) -> Compose -> Claim Verifier -> refinement. Keep evidence
tags in the representation; remove them only from a final draft with zero blocking violations.
Validate And Gate Strictly
Run the deterministic validator before promoting a phase:
"$S1PY" <skill-dir>/scripts/validate_run.py --run-dir "$RUN_DIR" --stage <stage>
Commit COMPLETE only with that phase's passing receipt:
"$S1PY" <skill-dir>/scripts/update_state.py \
--run-dir "$RUN_DIR" --phase <stage> --status COMPLETE \
--artifact validation=validation/<passing-receipt>.json
Use only COMPLETE, PARTIAL, NEEDS_SHARDING, SOURCE_UNAVAILABLE, SCHEMA_ERROR, or
BLOCKED as terminal states. A paper-profile run below its quantitative contract is PARTIAL or
NEEDS_SHARDING, never COMPLETE. Missing evidence is UNKNOWN or UNSUPPORTED, never an
inferred pass.
For invalidated historical experiments, do not silently delete the only forensic evidence. Retain a
content-addressed archive manifest and exclude the archive from promotable registries.
Finish
Return the run directory, stop stage, profile, terminal status, first unmet gate, highest-priority
evidence-linked findings, dependency-ordered next actions, commands executed, and validation
results. Do not promote a topic, result, hook, or paper claim unless its full evidence chain passes.