idea-posterior
Skill20 starsChanged 22 days agoMITView on GitHub
Turn a research idea into an auditable posterior: run an admission gate before any graph is built, decompose the idea into five source-grounded sub-criteria, encode them as a Gaia argument graph (gaia-lang, pinned 0.5.0a4), run exact inference, and write the posterior back to the idea store. Enforces a parameter honesty discipline — three fixed likelihood grades on the Jeffreys evidence scale, a mandatory anchor note on every number, MaxEnt fallback when an anchor fails review — plus pairwise expansion for mutual exclusivity, tournament-result absorption, revival by appending evidence, and review that audits anchors rather than scores. Use when admitting an idea into a tracked portfolio, when new evidence (literature, trial computation, tournament result) should move an idea's posterior, or when auditing why a posterior is what it is.
- Installs packages
In this repository34 other files it gives its agents.
- AGENTS.mdAGENTS.md
- CLAUDE.mdCLAUDE.md
- citation-triangulationSkill
- claim-groundingSkill
- claude-cli-runnerSkill
- codex-cli-runnerSkill
- deep-literature-reviewSkill
- derivation-verifySkill
- dsh-cli-runnerSkill
- figure-hygieneSkill
- gemini-cli-runnerSkill
- hep-calcSkill
- hep-mcp-usageSkill
- idea-allocationSkill
- idea-generationSkill
- idea-pairwise-matchSkill
- julia-packageSkill
- julia-perfSkill
- kimi-cli-runnerSkill
- literature-graph-builderSkill
- literature-to-packageSkill
- markdown-hygieneSkill
- numerical-reliability-gateSkill
- opencode-cli-runnerSkill
- paper-reviserSkill
- pdg-lookupSkill
- physics-diagramsSkill
- referee-reviewSkill
- research-harnessSkill
- research-integritySkill
- research-teamSkill
- research-writerSkill
- review-swarmSkill
- zotero-importSkill
The file
Show its rules and text
We split this skill into the rules it gives an agent
27 rules. About 0 are common, 7 are distinctive, and 20 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈7
Distinctive · estimate
This author's own choices. Worth a look.
20
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 8
Use this skill to hold beliefs about research ideas in an inspectable form: every idea worth tracking gets one Gaia argument graph whose …
- Very specific: line 46
If the version check reports anything but 0.5.0a4, stop and say so.
- Very specific: line 65
Read references/renderer.md when rendering docs/detailed-reasoning.html, installing its toolchain or debugging its generation (the Optional …
- Very specific: line 67
Read references/sync.md when a project containing graph packages is synced to or opened on another machine (the Moving between machines …
- Distinctive: line 71
No idea enters this skill from generation as allocation-ready.
- Distinctive: line 75
Not every idea deserves a graph.
- Distinctive: line 106
Not admissible on any route: fitting a small amount of data with functions of no assigned meaning — no mechanism, no new prediction, free …
- Very specific: line 140
Before building or updating a Gaia graph, before running node.set_posterior, and before any portfolio surface may treat the idea as …
- Very specific: line 153
Every expansion round records expansion_candidates_screened and new_core_papers.
- Very specific: line 183
Every close-prior/core paper must be source-first and machine-readable: read_status is one of full_text_read, section_read, metadata_only, …
- Very specific: line 209
If a later close-prior audit finds important missed prior work, take the idea out of current guidance in the store: move the node to …
- Very specific: line 276
Soft inference uses exactly three likelihood grades: Every infer() uses one of three fixed conditional-probability pairs, aligned with the …
- Very specific: line 305
Every observe() rationale also declares exactly one stable evidence_family: <token> and one correlation_model: single before its anchor.
- Very specific: line 428
Revival is just new evidence: When new literature, a passed trial computation, or a tournament result arrives for a dormant idea, append …
- Very specific: line 568
Read references/graph-reader-surface.md when changing or accepting the argument-graph reader surface (visible-probability formatter, …
- Very specific: line 596
Read references/renderer.md when detailed-reasoning.md was edited by hand and the HTML and graph must be regenerated in the right order …
- Very specific: line 610
Read references/migration.md when writeback rejects an older #sha256: reference or a package predates the current contract (the migration …
- Very specific: line 643
After a legal write the engine moves the lifecycle itself: a current posterior yields admitted (the only state strict ranking and …
- Distinctive: line 690
When the posterior is identical to an earlier write (for example, restoring a node to a previous state after intervening revisions), the …
- Very specific: line 696
When a fresh revision is the intent despite identical content, pass --new-write, which mints a unique key for the invocation.
- Very specific: line 728
Read references/report-links.md when writing or checking posterior_report_v1.md (every anchor as a link, report-relative targets, the two …
- Distinctive: line 756
Stale posteriors are flagged, not trusted: When the graph's current root belief no longer equals the stored posterior, the row is flagged: …
- Distinctive: line 761
Run the same two normalizers on this report as on posterior reports, and check deterministic Markdown hygiene (math escaping, link …
- Very specific: line 774
Read references/scan-boundary.md when reviewing a graph or stating what the extraction script's static scan does and does not cover (the …
- Very specific: line 776
Run gaia review calibration: it ranks claims by the shift between prior and posterior.
- Very specific: line 780
Run gaia review package for structural findings (unsupported strategies, statements with no recorded justification) and fix what it reports.
- Very specific: line 848
Every one found while following this skill is recorded in the maintainer issue log (default: ~/.nullius-dev/trackers/gaia-issues.md) as a …
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Idea Posterior
Use this skill to hold beliefs about research ideas in an inspectable form: every idea worth tracking gets one Gaia argument graph whose top-level claim is "this idea merits sustained verification effort", whose structure records the argument, and whose exact-inference posterior is written back to the idea store. The point is not the number itself but the audit trail behind it: every probability in the graph traces to an anchored source or is absent by design.
Beliefs and decisions are separate layers. The graph holds beliefs; budget allocation, tournament execution, and portfolio scheduling read the posterior but live outside the graph and outside this skill.
Scope and boundaries
- Gaia owns the belief layer only: argument structure, posterior computation, and absorption of new evidence including tournament results.
- The admission decision procedure (below) runs before any graph exists; its verdict is recorded as an artifact, not as graph content.
- Whether a cited source actually supports a claimed statement is verified
with the
claim-groundingskill; this skill consumes those verdicts as anchors and does not re-implement source verification. - Numbers from trial computations enter the graph only after the existing
numerical disciplines have passed:
numerical-reliability-gatefor numerical soundness and the independent reproduction check taught byresearch-harness. This skill does not re-teach either. - Resource allocation and match scheduling are portfolio-scheduler concerns; this skill only defines how a finished match result updates belief.
Installation and version pin
Gaia is pinned to an exact version. Upgrading is an explicit, reviewed action, never a side effect of environment drift.
uv venv .gaia-venv --python 3.12
uv pip install --python .gaia-venv/bin/python gaia-lang==0.5.0a4
.gaia-venv/bin/gaia --version # first line must report 0.5.0a4 — stop if notIf the version check reports anything but 0.5.0a4, stop and say so; the
skill's statement forms and parsing points are validated against this version
only. The Gaia-driving scripts below enforce the same check and print this
install recipe when the executable is missing or mismatched.
Materialize the authoring reference once per exact Gaia version, outside every research package:
python3 scripts/prepare_gaia_sdk_reference.pyThe command prints the cached path, normally
~/.cache/gaia-sdk/gaia-lang-0.5.0a4/; read its CHEATSHEET.md as the
authoritative statement reference for the pinned version, including the
Lindley–Jeffreys section referenced below. Never run gaia sdk inside an
argument-graph package: gaia-sdk/ is regenerable authoring help, not graph
source, and must not be duplicated per idea.
Read references/renderer.md when rendering docs/detailed-reasoning.html, installing its toolchain or debugging its generation (the Optional static browser renderer section, moved there verbatim).
Read references/sync.md when a project containing graph packages is synced to or opened on another machine (the Moving between machines section, moved there verbatim).
Admission gate — before any graph is built
No idea enters this skill from generation as allocation-ready. Generation can only produce candidates; posterior construction starts from independently checked close-prior evidence, not from a generator score.
Not every idea deserves a graph. An idea is admitted only if it clears at least one of the four routes below. Judge the routes on recorded evidence, not on enthusiasm; each route names what counts as its anchor.
- Resolves an anchored open problem or tension. The problem or tension must already be recorded in a survey artifact or stated explicitly in a citable source. The anchor is that recorded statement; "everyone knows this is open" does not qualify.
- Supplies a new mechanistic understanding. The idea states a testable mechanism — what drives what, through which pathway — rather than re-describing a known result in new words. The anchor is what the mechanism explains or newly predicts, stated concretely enough to check.
- Provides a new computational or solution method. Two obligations, both required. First, an impact chain: a list of currently uncomputable or impractical quantities the method would unlock, each item anchored in the literature as genuinely out of reach today. Second, the size of the advance must be supported by a trial computation or a complexity argument; a verbal claim of speedup or reach is not admissible evidence.
- Proposes a new theoretical framework or formulation. Two obligations, both required, and checked at admission time. The equivalence obligation: the framework must reproduce results already established in the framework it would replace or generalize — reproduce them now, not promise to. The generative obligation: at least one object, question, or computation that the old framework cannot naturally express or carry out must be exhibited as expressible and workable in the new one; a trial demonstration suffices. Missing either obligation, the idea is classified as repackaging and is not admitted.
Not admissible on any route: fitting a small amount of data with functions of no assigned meaning — no mechanism, no new prediction, free parameters traded for goodness of fit. Parsimony (how many phenomena are explained and predicted per free parameter) is a useful supporting signal in close calls, but it is a signal, not a doctrine.
Record the verdict as a gate_result in the idea's artifact directory:
{
"artifact": "gate_result_v1",
"idea_slug": "example-idea",
"verdict": "passed",
"route": "open_problem | mechanism | method | framework",
"anchors": [
{"statement": "what the anchor establishes",
"reference": "survey artifact section or citable source"}
],
"rejection_reason": null,
"date": "YYYY-MM-DD"
}Framework-route ideas may enter with a low initial posterior. Both obligations are still checked at the gate — equivalence by actual reproduction, the generative obligation by its trial demonstration. What accumulates afterwards is further generative evidence beyond that first demonstration, entering as appended observations (see revival semantics below). Admission says the idea deserves a graph, not that the graph starts high; an idea with neither reproduction nor a trial demonstration is not a low-posterior admit, it is a rejection.
Close-prior literature gate — before posterior or portfolio scoring
Before building or updating a Gaia graph, before running node.set_posterior,
and before any portfolio surface may treat the idea as allocation guidance, the
idea must have a literature_survey_v1 or equivalent close-prior artifact and
a close-prior matrix. If either artifact is missing, stop: the idea is still a
candidate or reconnaissance item, not posterior-ready.
The survey must show snowball discovery, not a one-shot topic search:
seed_searchbackward_referencesforward_citationscritique_specific_search
Every expansion round records expansion_candidates_screened and
new_core_papers. saturated is legal only when the final measured round did
real screening and admitted zero new core papers; if the final round still adds
core papers, or no real expansion round was measured, the status is
coverage_incomplete.
Snowball convergence is not sufficient by itself. The survey coverage receipt
must also bind to the detailed literature_saturation.json ledger: every core
source bibliography is reconciled, every extracted candidate has an explicit
disposition, unresolved identities remain coverage debt, and every core source
has a method-family audit grounded in its method text plus one explicit
method_bearing, not_method_bearing, or coverage_debt screening disposition
for every reconciled bibliography candidate. Negative as well as positive method
screening must cite source text; title/year queries cannot prove the absence of a
method line. Canonical identities must bind to exact-SHA local archives of
provider metadata or triangulation blocks, not self-attested remote pointers.
The separate display URL is not identity authority unless it is also the archived
canonical id or an explicit archived alias.
Both compact receipts must carry
the same project-root-bounded exact-byte project://...#sha256:... ledger ref;
the write gate resolves it, validates the raw bibliography pins, matches its
canonical core identities to the current survey, and recomputes the summary
counts/statuses. Any missing/stale/cross-ledger reference, summary mismatch, open
bibliography, disposition, or method-taxonomy gap keeps
the close prior at coverage_incomplete even when the terminal expansion round
adds no new core paper. Writeback also revalidates finite provider request bounds,
complete coverage of every declared query, terminal continuation/exhaustion and
known totals, page/cursor accounting, candidate discovery origin records, the exact core disposition
set, and bounded citation-graph coverage from the same ledger.
Every close-prior/core paper must be source-first and machine-readable:
read_status is one of full_text_read, section_read, metadata_only, or
unavailable; source links, read locators, and read sections are recorded; the
citation identity is triangulated across at least two independent providers
with verdict consistent; and the deep-read summary has a source-fidelity
audit with status pass. For full_text_read, the minimum checked regions are
introduction, formalism/method, results/discussion, and conclusion/outlook.
metadata_only and unavailable entries cannot anchor Gaia likelihoods.
Subagent literature audits are allowed only as discovery/synthesis input. The main coordinator must verify source links, identity triangulation, source form, quoted spans, locators, and summary fidelity before any extracted proposition can become a graph anchor.
Gaia input is proposition-level, not paper-level. The allowed chain is:
deep-read paper -> extracted proposition -> claim-grounding quote and locator
-> mapped sub-criterion anchor -> observe() or infer() rationale. A paper,
paper count, provider metadata record, or subagent summary cannot directly
"count as a score."
Negative novelty claims ("no existing work does X") need reviewer gating: close-prior matrix, critique-search record, closest-hit same-scope exclusion reasons, and an independent reviewer check of the search terms plus the top close priors' discussion/conclusion sections. Without that gate, write only "not found in incomplete search" and do not use the claim as strong evidence.
If a later close-prior audit finds important missed prior work, take the idea
out of current guidance in the store: move the node to needs_refresh via
node.set_lifecycle — the engine marks the stored posterior stale in the
same atomic write (value and evidence count preserved as history), so the
store itself says the score is no longer current guidance; no separate
stale-echo write is needed. Re-running node.set_posterior with status
stale/provisional remains the path when the recorded values themselves
must change. When one evidence artifact demotes several nodes at once, use
node.apply_evidence_event — one call, one recorded evidence reference, one
engine-recorded event group across all the affected nodes' ledger entries.
Historical posterior records remain audit history, but they are not current
allocation guidance until the graph is rebuilt and node.set_posterior is run
again with a current result — the lifecycle machine has no shortcut edge
back to admitted from a demoted state; re-admission is always a fresh
posterior derivation.
Sub-criterion decomposition
The worth of an admitted idea decomposes into five sub-criteria. Each becomes one claim in the graph; each names its evidence sources so that every update has a place to point.
| Sub-criterion | Question it answers | Evidence sources |
tension_resolution | How far does the idea resolve an anchored open tension? Conceptual and structural tensions carry the same weight as numerical ones: incompatible frameworks, an approximation in use without justification, a missing mechanism. | tensions section of the literature survey artifact (literature_survey_v1) |
downstream_reach | How long is the chain of downstream problems the idea feeds, and how broad is its generality — how many phenomenon domains does it unify or apply to? Breadth is a first-class dimension, rewarded non-linearly through the grade-promotion rule below; the top of the breadth scale is reserved for frameworks whose generality spans essentially every domain of a discipline. | idea card claims, each with support_type and evidence_uris |
mechanism_insight | How much new, testable mechanistic understanding does the idea supply? | idea card claims; survey artifact |
testability_timing | Can the idea be tested, and is the verification window open now — data, tools, and comparison points available on a relevant horizon? | idea card claims |
verification_cost | Does a bounded, decisive first check exist? Only the belief-relevant part enters the graph: evidence that such a check exists raises feasibility belief. The budget decision itself stays outside. | the idea card's minimal_compute_plan field; trial computation artifacts |
A tension is anchored by the literature that engages it, not by machinery
that assumes it. tension_resolution is graded off the tensions section of a
real literature_survey_v1 that surfaces both the strongest existing
statement of the tension and the strongest existing challenge or competing
resolution — the prior work that already argues, quantifies, or disputes it. A
single citable source may supply the statement half, but it never excuses the
challenge search: the competing or critical prior work is searched either way,
and when a diligent search finds none, that null result is recorded explicitly
and the tension is graded at the weakest grade — an unengaged tension is not a
substantiated one. Method or formalism papers that merely exhibit the apparatus
the idea reasons about are evidence for mechanism_insight, not anchors for
tension_resolution: they show the machinery exists, not that the tension is
real and open.
Two obligations remain separate. The literature establishes that a tension
exists and is relevant enough for admission; it does not establish that the
proposed idea resolves it. A raising likelihood into tension_resolution
requires idea-specific resolution evidence: a derived mechanism that closes
the stated gap, an executed test that discriminates the competing accounts, or
an explicitly scoped demonstrated partial resolution. Its rationale includes
one machine-readable clause before the anchor:
resolution_evidence: mechanism,
resolution_evidence: discriminating_test, or
resolution_evidence: demonstrated_partial_resolution. A proposed test or
compute plan may support testability_timing or verification_cost; until it
is executed and bears on resolution, it cannot raise tension_resolution.
Parameter honesty discipline
This section is where the method stands or falls. A posterior computed from invented numbers is worse than no posterior: it looks like knowledge.
- Anchored facts are hard observations. Anything already established by a
survey artifact, a grounded claim verdict, or a passed trial computation
enters as
observe(), which pins the fact near certainty. Never soften an anchored fact into a guessed probability. Soft inference uses exactly three likelihood grades. Every
infer()uses one of three fixed conditional-probability pairs, aligned with the Jeffreys evidence scale (Jeffreys 1961, Theory of Probability; modern treatment in Kass & Raftery 1995, "Bayes Factors", JASA 90:773):Grade Likelihood ratio p_e_given_hp_e_given_not_hweak 3 0.75 0.25 substantial 10 0.90 0.09 strong 30 0.90 0.03 To let evidence lower a hypothesis, swap the two numbers of the grade — updates are symmetric in strength whichever direction they push. Free-hand decimals ("0.85 feels right") are forbidden; if none of the three grades fits, the evidence is probably not understood well enough to enter yet. The grades are written as literal numbers at the statement, never routed through variables or helper functions: literality is what makes the graph auditable line by line, and the extraction script refuses statements whose grade or note it cannot read as a literal.
Every number carries an anchor note. The
rationaleof everyobserve()andinfer()ends withanchor: <artifact reference or resolvable URI>. Review asks one question of every number: what does this trace to? A number whose anchor cannot be produced or does not surviveclaim-groundingis deleted — not adjusted, deleted — and the affected claim falls back to MaxEnt (Gaia's default when no prior or evidence binds). MaxEnt is the correct failure mode: honest ignorance beats fabricated precision.Every
observe()rationale also declares exactly one stableevidence_family: <token>and onecorrelation_model: singlebefore its anchor. The family identifies the underlying calculation, dataset, sample, literature claim-chain, or other evidence-producing source—not the wording of the observation. Gaia 0.5.0a4 multiplies separateinfer()likelihoods; routing correlated observations through one shared claim does not encode a joint distribution and therefore does not make the votes independent. A family may have at most one observation on one likelihood-bearing path toworth. Completely redundant or correlated material is merged into one composite observed fact with one authored likelihood update. Repeated family labels are allowed only on disconnected source notes that cannot change the exported posterior.An
infer()rationale also carries substantive authored prose before the trailing anchor, introduced by the explicit sentinelreader_reasoning: <why the evidence changes the hypothesis>.rationale="anchor: ...", criterion text alone, and prose without that authorship sentinel are refused. The rationale contract is structural: authors may state criteria in the language appropriate to the idea, while the marked rationale records why the evidence changes that criterion at the selected likelihood grade. Separately, the six exact scaffold axis sentences are authoring placeholders and are refused if left unchanged.- Grade promotion for breadth. A
downstream_reachupdate may use the strong grade (ratio 30) only when the reach claim has anchored impact chains in at least three independent phenomenon domains, each domain anchored separately. Single-domain reach uses the weak or substantial grade. Counting domains means counting anchors, one per domain — an unanchored domain does not count. A raising strong-gradedownstream_reachupdate must carry the domain list in its rationale as a machine-checkable clause,domains: <one>; <two>; <three>(three or more entries,;or|separated), before the trailing anchor note; the extraction script refuses a raising strong reach update without it. Whether the listed domains are genuinely independent and genuinely anchored stays a review question. - Utility and cost never enter the graph. Beliefs and decisions are
separate layers. No quantity of money, hours, or hardware ever appears in
the graph — not as a claim, not in a rationale, not as a likelihood
choice. What the
verification_costclaim holds is a belief about a fact: that a bounded, decisive first check exists, anchored by a written compute plan or a passed trial run. The budget decision that consumes the posterior happens downstream, outside the graph. Test for violations by asking: does this statement give a reason to prefer the idea (utility — out), or evidence that a checkable fact is true (belief — in)? - Lindley–Jeffreys trap. Testing a point hypothesis against a diffuse alternative manufactures enormous Bayes factors — a single observation driving a posterior above 0.99 or below 0.01 is the symptom. Match the level of commitment on both sides of every comparison (point against point, composite against composite) unless the theory genuinely demands a point value. The pinned CHEATSHEET carries a section on this trap; follow it whenever a distribution-level comparison enters a graph.
Graph construction rules
- One idea, one package, outside the tool repository. Each idea's graph
lives at
<project_root>/argument-graphs/<idea_slug>-gaia/in the external research project — a directory for the reasoning graphs, kept distinct from the engine'sidea-store/(which holds the idea nodes and their posteriors). Packages must never be created inside a development repository; the tool repository holds only the skeleton template and test fixtures.gaia build initcreates a nested git repository inside the package; the scaffold removes that fresh, zero-commit repository so the research project's own version control can track the package. A pre-existing package with real git history is a different matter: absorb it into the project deliberately (move its history or accept the loss explicitly) — never delete a non-empty repository automatically. - The top-level claim is named and exported as
worth, and gets no prior. The package module must declare__all__ = ["worth"]; after compilation,worthmust be the sole knowledge node markedexported. This is checked by extraction, both renderers, and writeback. A package with an empty or different__all__is refused with a migration command instead of producing an unmarked conclusion. The module variable name must beworth(extraction keys on that label). Do notregister_priorit — or any claim — unless a genuine external prior exists. Aregister_priorjustification follows the same anchor discipline as every other number: it ends withanchor: <artifact reference or resolvable URI>, and a prior whose anchor fails review is deleted so the claim reverts to MaxEnt. No prior means MaxEnt, by design. - Reader roles are explicit metadata, not prose matching. The scaffold
marks
worthwithreader_role="conclusion"and its five structural criteria withreader_role="criterion". Existing scientifically sound packages without these markers remain readable as long as they carry substantive infer rationales; the renderer labels their intermediate nodes conservatively. Role detection does not inspect prose. Independently, each of the six reasoning claims must state an idea-specific research proposition: extraction, rendering, reporting, and writeback reject empty claims and the scaffold's exact generic axis sentences. This prevents a comparison-axis definition from being presented as the explanation of an idea's score. Standard wiring per sub-criterion. Anchored facts enter as
observe(); aninfer()updates the sub-criterion claim from each observation with a graded likelihood pair; a secondinfer()updatesworthfrom the sub-criterion. Enter each piece of evidence once. If one source bears on several criteria, do not give it several scored paths: state the combined consequence in one composite observation and route it through one criterion path. Gaia 0.5.0a4 has no correlated-likelihood factor that would make several paths safe.Copying one observation into several observed nodes does not create independent evidence, and routing one observed node through several claims still duplicates its effect on
worth. The extractor groups observations by their authoredevidence_familyrather than by prose or path strings and refuses either form of parallel worth-connected likelihood update. During review, compare family ids and anchors across criteria; assigning different ids to paraphrases of one source is a contract violation, not a route around the gate.- Mutual exclusivity is pairwise. In gaia-lang 0.5.0a4,
exclusive()takes exactly two claims; three or more raisesTypeError. Expand mutual exclusivity over n rival hypotheses into all pairwiseexclusive()calls. This is a recorded upstream limitation (see the issue log section). - Trial computation evidence. A small-scale feasibility or
order-of-magnitude result enters as
observe()only after passing the existing numerical disciplines (numerical-reliability-gate; independent reproduction check fromresearch-harness). Its anchor names the passed computation artifact. An unchecked number does not enter the graph, however encouraging it looks. - Revival is just new evidence. When new literature, a passed trial
computation, or a tournament result arrives for a dormant idea, append the
corresponding
observe()andinfer()statements, re-run inference, and write the posterior back. No revival approval step exists; the posterior moves because evidence moved. One store mechanic: if the node was archived, first move it back into the machine vianode.set_lifecycle— toneeds_refreshwhen it carries a posterior history, tocandidatewhen it never had one (the engine enforces exactly this split, and forbids jumping from the archive straight toadmitted) — then the fresh writeback re-admits it through the normal derivation.
Absorbing pairwise tournament results
Tournament execution is external; a finished match arrives as a
pairwise_match_v1 artifact with a match identifier and a panel verdict.
Absorb it into both contestants' graphs:
match_win = observe(
"The idea won its pairwise match against a rival idea under the "
"committed judging criteria.",
rationale=(
"evidence_family: pairwise-match-id; correlation_model: single; "
"anchor: pairwise_match_v1 <match_id> at <artifact path>"
),
)
infer(
match_win,
hypothesis=worth,
p_e_given_h=0.90, p_e_given_not_h=0.09, # unanimous verdict: substantial
rationale=(
"reader_reasoning: A unanimous panel verdict under committed "
"criteria raises worth. "
"anchor: pairwise_match_v1 <match_id> at <artifact path>"
),
)- Unanimous verdicts (all judges one way, e.g. 4-0 or 3-0) use the substantial grade (ratio 10).
- Split verdicts (e.g. 3-1 or 2-1) use the weak grade (ratio 3).
- Ties produce no update at all.
- Symmetry. The loser's graph absorbs the same match with the same grade in the lowering direction (swap the two conditional probabilities). A win raises, a loss lowers, with equal strength.
- The
rationalemust carryreader_reasoning:, cite the match artifact path, and end withanchor: pairwise_match_v1 <match_id>; a match result with no artifact reference is not absorbable.
Workflow: three scripts
The scripts under scripts/ do the mechanical part; judgment — what to
claim, which grade, which anchor — stays with the author. The inference and
writeback path is standard-library-only and drives Gaia or the RPC caller as
subprocesses. The optional detailed-page renderer uses the presentation
dependencies listed above. Every script prints a readable diagnosis when a
stage fails.
Generate the package skeleton.
python3 scripts/gaia_package_scaffold.py \ --slug my-idea --dest <project_root>/argument-graphsRuns
gaia build init my-idea-gaiain the destination and writes the skeleton module: aworthclaim plus the five sub-criterion claims, with comment guidance restating the likelihood grades, the anchor-note format, and the pairwise-exclusivity rule. The skeleton compiles as generated (all claims MaxEnt, no evidence). Refuses to overwrite an existing package. The freshly generated package is then hardened: the zero-commit nested git repository fromgaia build initis removed, and the generated environment pins are retargeted togaia-lang==0.5.0a4/ Python 3.12 (gaia's own template still writes>=0.4.4/ 3.13 — a recipe observed to break silently in the field); the init-time package venv is dropped so the next gaia run re-syncs it from the corrected pins.Run inference and extract the posterior.
python3 scripts/run_infer_and_extract.py \ --package <project_root>/argument-graphs/my-idea-gaiaFirst runs a static discipline scan over the authored modules. A statement passes only when the scan can prove it follows the discipline: probability pairs must be literal numbers in the three grades; rationales and
register_priorjustifications must be literal strings ending with ananchor: <reference>note; a raising strong-gradedownstream_reachupdate must carry itsdomains:clause; statement names are resolved through import aliases, and referencing a statement name without calling it (assignment aliasing, passing it around) is itself a violation. Anything unprovable — non-literal grades, notes, or prior values, wrapper indirection — is a violation, not a pass (better to reject a sound graph than to pass an unsound one), and the script refuses to extract a posterior.--allow-discipline-warningsdowngrades violations as an explicit, logged exception for deliberate exploration, but the extracted reference is then prefixedexploration-only:and the writeback script refuses to store it. What the scan does and does not promise is stated plainly under "Scan boundary" below; deliberately obfuscated authoring is review's business, and review stays the authority on substance either way. Then runsgaia build compile, verifies thatworthis the unique exported conclusion, runsgaia build check,gaia run infer, and — unless--no-render— renders a viewable graph after inference: an interactive single-fileargument-graph.htmlbuilt by the siblingrender_argument_graph.py(no external dependency; open it in a browser). Every card on that page carries the node's full statement — short variable labels appear only as card headers — and eachinferis drawn as an arrow from the evidence into the claim it updates: solid blue when it raises belief, dashed warm red when it lowers it, line width and a weak/substantial/strong chip showing the likelihood ratio. Clicking a card opens the statement, posterior, likelihoods P(e|h) and P(e|not h), rationale, and source anchors. HTTP(S) anchors and existing in-project Markdown anchors become links; project-root-relative artifact paths are rewritten relative to the graph page, while missing, escaping, non-Markdown, and engine references remain plain text. The run also emits a staticstarmap.svgwhen Graphviz is onPATH, Gaia's exactdocs/detailed-reasoning.md, and — when the optional browser-render dependencies are present — a self-containeddocs/detailed-reasoning.html. Its first section follows observed evidence through the authored likelihood rationales and criterion updates intoworth; direct and indirect lowering paths are rendered alongside support. Pandoc supplies Markdown structure and MathML; Mermaid CLI runs once per Pandoc-identified Mermaid code block under strict security and its static SVG is embedded as an image data URI; source raw HTML is removed from the Pandoc AST and the final fragment is sanitized by nh3. Ordinary relative and HTTP(S) links survive, while active URL schemes, event handlers, and scripts do not. No browser-side renderer, server, CDN, or network request is needed when the page is opened directly as a local file. Gaia 0.5.0a4 can legitimately emit no Mermaid block when a package has one ordered module and one exported conclusion. In that zero-diagram case only, the renderer reconstructs Gaia's raw generative graph from the already validated compiled IR, marks the unique exported root, and states the premise/background arrow semantics. Unknown references or malformed graph records fail closed. If Gaia emitted any Mermaid block, the renderer preserves that source path and continues to require exactly one exported-root marker across the upstream diagrams.Read
references/graph-reader-surface.mdwhen changing or accepting the argument-graph reader surface (visible-probability formatter, reader-surface contract, interaction-state evidence) (the reader-surface paragraphs, moved there verbatim).Each card's detail panel links to the exact case-preserving node fragment in the HTML page. The renderer accepts only Gaia's explicit empty anchor immediately preceding the matching node heading; missing, duplicated, or mismatched anchors fail closed, so a later same-named human heading cannot move the target. The link is generation-bound by
docs/detailed-reasoning.manifest.json, which carries deterministic SHA-256 digests of the current.gaia/beliefs.json, the exact compiled.gaia/ir.json, the exact Markdown bytes, and the generated HTML bytes.render_argument_graph.pyindependently recomputes all four; missing, malformed, stale, unreadable, or escaping artifacts produce nodoc_href. The HTML is installed first and the manifest last, so a crash can leave only an unverifiable page, never an authorized stale one. Rendering never gates the posterior — a render failure is reported and skipped. It then parses.gaia/beliefs.json(the entry labelledworth) and.gaia/ir.json(observation supports, one perobserve()statement), and prints:{ "value": 0.8499, "evidence_count": 2, "gaia_package_ref": "project://argument-graphs/my-idea-gaia#sha256:..." }Read
references/renderer.mdwhendetailed-reasoning.mdwas edited by hand and the HTML and graph must be regenerated in the right order (the standalone-renderer order, moved there verbatim).gaia_package_refis machine-portable by construction: research projects sync across machines, so the reference names the package RELATIVE to the project root — the nearest ancestor containing.nullius/, or an explicit--project-root— never as this machine's absolute path (path segments are percent-encoded; the form satisfies the engine's URI typing of this field). The#sha256:fragment is the SHA-256 digest of the exact.gaia/ir.jsonbytes. It deliberately does not reuse Gaia 0.5.0a4's internalir_hash: that upstream hash does not change when an exported marker changes. Hashing the complete compiled artifact binds graph structure and exported-root metadata in one reference. A later recompile that changes either yields a visibly different reference.Read
references/migration.mdwhen writeback rejects an older#sha256:reference or a package predates the current contract (the migration paragraph, moved there verbatim).Write the posterior back to the idea store.
python3 scripts/run_infer_and_extract.py --package <pkg> | python3 scripts/posterior_writeback.py \ --campaign-id <campaign> --node-id <node> \ --store-root <store_root> \ --literature-survey-json <artifact_dir>/literature_survey_v1.json \ --close-prior-matrix-json <artifact_dir>/close_prior_matrix.json \ --posterior-report-md <artifact_dir>/posterior_report_v1.md \ --project-root <absolute_project_root> \ --idea-rpc <repo>/packages/idea-engine/bin/idea-rpc.mjsSends
{"method": "node.set_posterior", "params": {campaign_id, node_id, idempotency_key, posterior, literature_coverage}, "store_root": ...}on stdin to the idea-engine thin RPC caller and fails loudly on an error response.The engine enforces the idea lifecycle machine around this write. A node fresh from seed import or generation sits in
candidate, where posterior writes are rejected — declare the review first, so admission has a logged, timestamped start in the store:echo '{"method":"node.set_lifecycle","params":{"campaign_id":"<campaign>", "node_id":"<node>","idempotency_key":"<key>", "lifecycle_state":"admission_review"},"store_root":"<store_root>"}' \ | node <repo>/packages/idea-engine/bin/idea-rpc.mjsAfter a legal write the engine moves the lifecycle itself: a
currentposterior yieldsadmitted(the only state strict ranking and allocation sample), anything else yieldsneeds_refresh. Never set those two states by hand around a writeback — the derivation is the single writer that keeps lifecycle and stored posterior consistent. The consistency runs in both directions:node.set_posteriorremains the only writer of posterior VALUES and of thecurrent/provisionalstatuses, whilenode.set_lifecycle(andnode.apply_evidence_event) own the demotion half — enteringneeds_refresh,admission_blocked, orarchivedmarks acurrentposteriorstalein the same atomic write. If the admission gate instead finds named evidence missing, record it on the node asadmission_blockedwith anactivation_condition(kindrequired_evidence) rather than leaving the review open. Before anything is sent,posterior_writeback.pyruns the close-prior validator over the survey, matrix, report, and exact-byte-pinned detailed reconciliation ledger. It refuses a missing close-prior matrix, missing critique search, one-sided above-weakesttension_resolution, metadata-only Gaia anchors, untriangulated core-paper identity, failed source-fidelity audit, or acoverage_incompleteresult that claims current/allocation-eligible status.coverage_incompletemay be written only as provisional guidance; it can be allocation eligible only when--allow-exploratory-allocationis passed and the matrix declares the allocation exploratory.The matrix and compiled graph are checked together. A singular
tension_resolution.grademust equal the actual raising likelihood grade targeting that criterion in.gaia/ir.json. When several raising updates target it,graderecords the strongest andraising_likelihood_gradesrecords the exact multiset; a missing, weaker, stronger, or incomplete declaration is refused. Matrixposterior_statusdescribes readiness for the write being attempted, not pre-rebuild history:stalecannot enter current writeback even when coverage is saturated andallocation_eligibleis false. Rebuild the matrix and graph, then declare the resulting readiness state.The
project://reference is also verified against the project on disk: it must resolve under the project root (the nearest ancestor of--store-rootcontaining.nullius/, or an explicit--project-root) and its#sha256:pin must match the exact bytes of the package's current.gaia/ir.json; the same check requiresworthto remain its unique exported conclusion. A reference nobody could follow, or one whose graph changed after extraction, is refused with the refresh command (re-runrun_infer_and_extract.py) instead of being archived into the store. The idempotency key is a deterministic digest of campaign, node, package reference, value, and evidence count: retrying the same write is a no-op, while any real change produces a new key. Two consequences of that default are surfaced rather than left silent:- When the posterior is identical to an earlier write (for example,
restoring a node to a previous state after intervening revisions), the
key collides with that write's key and the store replays the
archived response — no new revision is created. The script detects
this via the response's
idempotency.is_replayand warns on stderr instead of reporting a fresh write. - When a fresh revision is the intent despite identical content, pass
--new-write, which mints a unique key for the invocation. To retry that specific write after a failure, reuse the key it printed via--idempotency-keyrather than repeating--new-write.
- When the posterior is identical to an earlier write (for example,
restoring a node to a previous state after intervening revisions), the
key collides with that write's key and the store replays the
archived response — no new revision is created. The script detects
this via the response's
Report — posterior_report_v1
The scripts above produce the machine artifacts; the human-facing summary is
posterior_report_v1.md in the idea's artifact directory. Its job is to make
the posterior auditable at a glance: it states the admission verdict and
route, each sub-criterion's grade and its anchor, and the final posterior with
its gaia_package_ref. Display the posterior value rounded to three decimals
for humans, while the exact machine value remains in JSON artifacts and the
idea-store snapshot. When the render step produced one, it also links the
viewable argument graph (argument-graph.html) so a reader can open the
graph the posterior came from. That page shows every statement in full and
each update's direction and strength, so it doubles as a reading surface for
a human weighing the idea — but the durable decision record (what raises the
posterior, what lowers it, what evidence is still required) belongs in this
report and in the portfolio status report below, which travel with the
project and survive re-renders.
The report must include a close-prior matrix. For every close prior, list the reference/link, read status, source link, locator, same-scope status, supported sub-propositions, weakened novelty claims, identity-triangulation verdict, source-fidelity audit status, and whether the posterior should be marked stale/provisional. The matrix also records critique-search queries and top hits, same-scope exclusion reasons for closest hits, and reviewer notes for negative novelty claims. Missing matrix, missing critique search, or missing reviewer gate means the report is provisional and cannot support allocation eligibility.
Read references/report-links.md when writing or checking posterior_report_v1.md (every anchor as a link, report-relative targets, the two normalizers) (the anchor-link rules, moved there verbatim).
Portfolio status report — one page across all ideas
Per-idea posterior reports answer "why is this idea's posterior what it is"; the portfolio question — which idea deserves the next unit of effort, and what is holding each one back — needs one page across all nodes. Build it from the campaign store instead of hand-maintaining a status table that must be rewritten every time evidence lands:
python3 skills/idea-posterior/scripts/build_portfolio_status_report.py \
--nodes <idea-store>/campaigns/<campaign_id>/nodes_latest.json \
--project-root <project_root> \
--out-md artifacts/<campaign>/portfolio_status_report_v1.md \
--out-json artifacts/<campaign>/portfolio_status_report_v1.jsonPer node it renders: lifecycle state, literature-coverage status, the store posterior (three decimals for humans; exact machine values in the JSON artifact), a relative link to the graph page, and — read directly from the compiled graph — the top support and top lowering drivers, each with its signed strength and the author's recorded reasoning. Two disciplines are built in:
- Score families stay separate. The table shows the store posterior with its recorded status; nodes without a written-back posterior show a placeholder, never a triage number promoted into the posterior column.
- Stale posteriors are flagged, not trusted. When the graph's current root belief no longer equals the stored posterior, the row is flagged: the stored value is historical evidence, not allocation guidance, until the posterior is re-extracted and written back.
Run the same two normalizers on this report as on posterior reports, and check deterministic Markdown hygiene (math escaping, link portability) with the markdown-hygiene skill before committing or handing the report to another host.
Review: audit anchors, not scores
A graph review never argues with the posterior directly; it attacks the inputs. The extraction script's static scan stops mechanical slips (off-grade pairs, missing trailing anchor notes) before a posterior can be extracted at all; everything it cannot decide statically it hands to the reviewer.
Read references/scan-boundary.md when reviewing a graph or stating what the extraction script's static scan does and does not cover (the Scan boundary paragraph, moved there verbatim).
- Run
gaia review calibration: it ranks claims by the shift between prior and posterior. Large-shift claims are where wrong grades do the most damage — question them first. Observed claims sit near zero shift because observation pins them; that is expected, not suspicious. - Run
gaia review packagefor structural findings (unsupported strategies, statements with no recorded justification) and fix what it reports. - For every
infer(), the reviewer asks three questions:- What justifies this likelihood grade — why this grade and not the one below it?
- Is the anchor reachable — does the cited artifact or URI exist, and
does its content actually establish the stated fact (route through
claim-groundingwhen in doubt)? Inposterior_report_v1the anchor must be a rendered link, not a bare identifier: a reference the reader cannot click through is not a reachable anchor. - Were both conditionals thought about —
p_e_given_handp_e_given_not_h? A grade chosen by imagining only the hypothesis-true world is not a considered grade.
- For every raising
tension_resolutionupdate, the reviewer checks the declaredresolution_evidenceclass against the anchored content. A source that only documents the open tension discharges admission relevance, not resolution; an unexecuted plan discharges neither full nor partial resolution. - Across criteria, the reviewer groups observations by statement, anchor, and causal origin. Repeated or paraphrased copies of one fact are traced to one shared source and are not accepted as independent updates.
- Any number that fails these questions is deleted and the claim reverts to MaxEnt; then inference is re-run and the posterior re-extracted. Review outcomes change graphs, not narratives.
- For a
tension_resolutionupdate graded above the weakest grade, the reviewer confirms the survey engaged the critique — its tensions section surfaces a genuine challenge or competing resolution, not only papers that assume or apply the idea. A one-sided pool (all confirming, none contesting) iscoverage_incomplete: only an actual challenge or competing resolution supports a grade above weakest; a documented null result records the debt but the tension stays at the weakest grade. This is a reviewer judgement by design — one-sidedness cannot be decided by a survey's shape alone, so no machine field stands in for reading the pool.
Activation conditions
Some ideas depend on something that does not exist yet: a tool reaching
readiness, a dataset being released, a project stage arriving, a trial
computation finishing. Do not build a speculative full graph for these. Park
the node in waiting_activation via node.set_lifecycle with the condition
recorded on it (the engine requires the condition for this state and clears
it on exit):
{
"activation_condition": {
"kind": "tool_readiness | data_release | stage_reached | exploratory_computation | other",
"description": "what must become true, stated so a third party can check it",
"satisfied": false
}
}Distinguish this from admission_blocked: waiting is about the external
world (nothing to do but wait and check), while blocked means the admission
gate named evidence that WORK must produce (kind required_evidence). When
the condition is met, the activation monitor in idea-allocation prints the
engine-legal return transition (a waiting node with no posterior returns to
candidate; with a current, coverage-eligible posterior to admitted;
otherwise to needs_refresh — a satisfied blocked node re-enters
admission_review). Then run the admission gate (if not already passed),
build the graph, and proceed normally. Monitoring activation conditions is
the portfolio scheduler's job, not this skill's; this skill only defines the
judgment and the record format.
Gaia issue log
Gaia is pinned and pre-release; defects and limitations surface during use.
Every one found while following this skill is recorded in the maintainer
issue log (default: ~/.nullius-dev/trackers/gaia-issues.md) as a table row:
date, symptom, minimal reproduction, affected workstream, workaround, status.
The mainline work continues on the documented workaround; escalation of
blocking defects follows the process note at the top of that file. Known at
pin time: exclusive() accepts exactly two claims (TypeError with three or
more), worked around by pairwise expansion as specified above.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

