hypgraph 0.4.2__tar.gz → 0.5.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. {hypgraph-0.4.2 → hypgraph-0.5.0}/CHANGELOG.md +51 -0
  2. {hypgraph-0.4.2 → hypgraph-0.5.0}/PKG-INFO +1 -1
  3. hypgraph-0.5.0/docs/profile-workflows-plan.md +110 -0
  4. hypgraph-0.5.0/docs/workflows/README.md +30 -0
  5. hypgraph-0.5.0/docs/workflows/knowledge.md +82 -0
  6. hypgraph-0.5.0/docs/workflows/optimization.md +80 -0
  7. hypgraph-0.5.0/docs/workflows/scientific.md +75 -0
  8. hypgraph-0.5.0/docs/workflows/software.md +78 -0
  9. hypgraph-0.5.0/docs/workflows/trading.md +81 -0
  10. {hypgraph-0.4.2 → hypgraph-0.5.0}/src/hypgraph/__init__.py +1 -1
  11. {hypgraph-0.4.2 → hypgraph-0.5.0}/src/hypgraph/checks.py +35 -4
  12. {hypgraph-0.4.2 → hypgraph-0.5.0}/src/hypgraph/derive.py +62 -2
  13. {hypgraph-0.4.2 → hypgraph-0.5.0}/src/hypgraph/graph.py +65 -5
  14. {hypgraph-0.4.2 → hypgraph-0.5.0}/src/hypgraph/mcp.py +23 -0
  15. {hypgraph-0.4.2 → hypgraph-0.5.0}/src/hypgraph/plan.py +17 -0
  16. {hypgraph-0.4.2 → hypgraph-0.5.0}/src/hypgraph/profiles.py +275 -8
  17. {hypgraph-0.4.2 → hypgraph-0.5.0}/src/hypgraph/schema.py +33 -7
  18. {hypgraph-0.4.2 → hypgraph-0.5.0}/src/hypgraph/server.py +4 -0
  19. hypgraph-0.5.0/src/hypgraph/workflow.py +598 -0
  20. {hypgraph-0.4.2 → hypgraph-0.5.0}/tests/test_engine_fixes.py +5 -6
  21. {hypgraph-0.4.2 → hypgraph-0.5.0}/tests/test_refusals.py +2 -1
  22. hypgraph-0.5.0/tests/test_vocabulary_friction.py +130 -0
  23. hypgraph-0.5.0/tests/test_workflows.py +363 -0
  24. {hypgraph-0.4.2 → hypgraph-0.5.0}/.gitignore +0 -0
  25. {hypgraph-0.4.2 → hypgraph-0.5.0}/AGENTS.md +0 -0
  26. {hypgraph-0.4.2 → hypgraph-0.5.0}/CITATION.cff +0 -0
  27. {hypgraph-0.4.2 → hypgraph-0.5.0}/LICENSE +0 -0
  28. {hypgraph-0.4.2 → hypgraph-0.5.0}/NOTICE +0 -0
  29. {hypgraph-0.4.2 → hypgraph-0.5.0}/README.md +0 -0
  30. {hypgraph-0.4.2 → hypgraph-0.5.0}/docs/PLAN.md +0 -0
  31. {hypgraph-0.4.2 → hypgraph-0.5.0}/docs/decisions/ADR-001-token-bound-authors.md +0 -0
  32. {hypgraph-0.4.2 → hypgraph-0.5.0}/docs/decisions/ADR-002-governance-profiles.md +0 -0
  33. {hypgraph-0.4.2 → hypgraph-0.5.0}/docs/review-2026-10-24.md +0 -0
  34. {hypgraph-0.4.2 → hypgraph-0.5.0}/docs/spec.md +0 -0
  35. {hypgraph-0.4.2 → hypgraph-0.5.0}/pyproject.toml +0 -0
  36. {hypgraph-0.4.2 → hypgraph-0.5.0}/src/hypgraph/__main__.py +0 -0
  37. {hypgraph-0.4.2 → hypgraph-0.5.0}/src/hypgraph/bundle.py +0 -0
  38. {hypgraph-0.4.2 → hypgraph-0.5.0}/src/hypgraph/cli.py +0 -0
  39. {hypgraph-0.4.2 → hypgraph-0.5.0}/src/hypgraph/coord.py +0 -0
  40. {hypgraph-0.4.2 → hypgraph-0.5.0}/src/hypgraph/demos/__init__.py +0 -0
  41. {hypgraph-0.4.2 → hypgraph-0.5.0}/src/hypgraph/demos/broad_street.py +0 -0
  42. {hypgraph-0.4.2 → hypgraph-0.5.0}/src/hypgraph/language.py +0 -0
  43. {hypgraph-0.4.2 → hypgraph-0.5.0}/src/hypgraph/policy.py +0 -0
  44. {hypgraph-0.4.2 → hypgraph-0.5.0}/src/hypgraph/refusals.py +0 -0
  45. {hypgraph-0.4.2 → hypgraph-0.5.0}/src/hypgraph/report_check.py +0 -0
  46. {hypgraph-0.4.2 → hypgraph-0.5.0}/src/hypgraph/skill/SKILL.md +0 -0
  47. {hypgraph-0.4.2 → hypgraph-0.5.0}/src/hypgraph/stats.py +0 -0
  48. {hypgraph-0.4.2 → hypgraph-0.5.0}/src/hypgraph/store.py +0 -0
  49. {hypgraph-0.4.2 → hypgraph-0.5.0}/src/hypgraph/ui/__init__.py +0 -0
  50. {hypgraph-0.4.2 → hypgraph-0.5.0}/src/hypgraph/ui/atlas.css +0 -0
  51. {hypgraph-0.4.2 → hypgraph-0.5.0}/src/hypgraph/ui/atlas.js +0 -0
  52. {hypgraph-0.4.2 → hypgraph-0.5.0}/src/hypgraph/ui/hypgraph.svg +0 -0
  53. {hypgraph-0.4.2 → hypgraph-0.5.0}/src/hypgraph/ui/index.html +0 -0
  54. {hypgraph-0.4.2 → hypgraph-0.5.0}/src/hypgraph/ui/vendor/LICENSES.md +0 -0
  55. {hypgraph-0.4.2 → hypgraph-0.5.0}/src/hypgraph/ui/vendor/cose-base.js +0 -0
  56. {hypgraph-0.4.2 → hypgraph-0.5.0}/src/hypgraph/ui/vendor/cytoscape-fcose.js +0 -0
  57. {hypgraph-0.4.2 → hypgraph-0.5.0}/src/hypgraph/ui/vendor/cytoscape.min.js +0 -0
  58. {hypgraph-0.4.2 → hypgraph-0.5.0}/src/hypgraph/ui/vendor/layout-base.js +0 -0
  59. {hypgraph-0.4.2 → hypgraph-0.5.0}/studies/harmony/tests/test_suite.py +0 -0
  60. {hypgraph-0.4.2 → hypgraph-0.5.0}/tests/test_cancel_releases_lease.py +0 -0
  61. {hypgraph-0.4.2 → hypgraph-0.5.0}/tests/test_coord.py +0 -0
  62. {hypgraph-0.4.2 → hypgraph-0.5.0}/tests/test_d10.py +0 -0
  63. {hypgraph-0.4.2 → hypgraph-0.5.0}/tests/test_engine.py +0 -0
  64. {hypgraph-0.4.2 → hypgraph-0.5.0}/tests/test_incremental.py +0 -0
  65. {hypgraph-0.4.2 → hypgraph-0.5.0}/tests/test_log_and_check.py +0 -0
  66. {hypgraph-0.4.2 → hypgraph-0.5.0}/tests/test_order_detail.py +0 -0
  67. {hypgraph-0.4.2 → hypgraph-0.5.0}/tests/test_profiles.py +0 -0
  68. {hypgraph-0.4.2 → hypgraph-0.5.0}/tests/test_profiles_041.py +0 -0
  69. {hypgraph-0.4.2 → hypgraph-0.5.0}/tests/test_questions_not_assertions.py +0 -0
  70. {hypgraph-0.4.2 → hypgraph-0.5.0}/tests/test_server_auth.py +0 -0
  71. {hypgraph-0.4.2 → hypgraph-0.5.0}/tests/test_stats_values.py +0 -0
  72. {hypgraph-0.4.2 → hypgraph-0.5.0}/tests/test_surfaces.py +0 -0
@@ -1,5 +1,56 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.5.0 — 2026-10-26: profiles carry their discipline's workflow
4
+
5
+ Each discipline's method, as the record enforces it — one page each in `docs/workflows/`, taken from the method
6
+ itself (hypothetico-deductive with preregistration; continuous integration and code review; preregistered
7
+ backtesting and risk management; source criticism and fact-checking; operations-research practice). The `@1`
8
+ profiles are frozen as they were; `scientific@2` … `optimization@2` add the workflow. No profile → unchanged.
9
+
10
+ - **The stage is derived, never set.** `Graph.stage(question)` / `stages(inv)`, `GET /stage/{id}` / `/stages`, MCP
11
+ `stage`: a question is in the first stage whose gate the record does not meet, every gate MET / NOT MET with what
12
+ would meet it. `Profile.workflow` (`Workflow`, `Stage`) holds the stages, gates, invalidation, typed shapes.
13
+ - **Gates double as order predicates**: `hypothesis_stated`, `preregistered` (the experiment, with its expected
14
+ outcome, precedes any run that executes it), `decided`, `diff_registered`, `tests_pass_current`,
15
+ `instance_registered`, `source_quoted`, `search_recorded`, `backtested` (out of sample, after costs, trials
16
+ declared), `positioned`, `still_valid`, `solved`, `result_reviewed`. The `@2` profiles' `done_when` use them.
17
+ - **A workflow widens what counts as resting on.** `uses` (scientific, software, trading, optimization) and `cites`
18
+ (knowledge) join `schema.RISKY` for that profile only (`derive.EXTRA_RISKY`): a corrected data file, a superseded
19
+ diff or instance, a withdrawn source puts what rested on it AT RISK. Records under `@1` keep exactly the standing
20
+ they had.
21
+ - **Freshness** (`derive.stale`, in every standing): a result whose run used an artifact that is now superseded or
22
+ withdrawn, or whose new `valid_until` has passed, is STALE; a claim is stale when every result behind it is. A
23
+ check on stale evidence doesn't meet `reviewed`; `requirements_verified_current` and `incumbent_verified` need
24
+ fresh instrument runs.
25
+ - **Typed shapes.** `artifact.kind` + `artifact.meta` with required fields per workflow (`diff`: base_sha,
26
+ head_sha, files; `instance`; `prices`; `solution`: objective, feasible …) → `ARTIFACT_MISSING_FIELDS`;
27
+ `source.kind` primary / secondary / tertiary and `reliability`; `decision.kind` with `size`, `stop`,
28
+ `review_date`, `paper`, `sensitivity`. `supersedes` now joins artifacts; `corrects` joins sources.
29
+ - **The disciplines' refusals**: `TESTS_ON_STALE_HEAD`, `REVIEW_BY_AUTHOR` (the diff's author can't check the
30
+ claim), `EDGE_WITHOUT_TRIALS`, `POSITION_WITHOUT_STOP`, `LIVE_ORDER` (no such path exists), `PASSAGE_MISSING`,
31
+ `SOLVED_WITHOUT_INSTANCE`, `OPTIMAL_ON_STALE_INSTANCE`.
32
+ - **Report**: under an `@2` profile, `report()` adds the workflow's section — each question's stage and next gate,
33
+ and the evidence that has gone stale.
34
+ - Schema additions are fields and relation endpoints only; no migration. Deferred to later phases, and said so in
35
+ the specs: per-workflow evidence rank (documented, not derived), the knowledge re-fetch check and
36
+ `NUMBER_NOT_IN_PASSAGE`, CI as the software instrument, mechanical feasibility recomputation.
37
+
38
+ ## 0.4.3 — 2026-10-26
39
+
40
+ Five vocabulary-friction fixes from the HypSwarm discovery study, where 110 of 118 refusals were binding, naming
41
+ and shape errors rather than overclaims — and one correct answer was refused fifteen times.
42
+ - **A named p-value backs "significantly".** A bound field named `p`, `p_value` or `p_<test>` (an exact McNemar
43
+ `p_exact`), or such a field on a supporting result, satisfies the significance check; below 0.05 the word is
44
+ accepted, above it `SIGNIFICANCE_NOT_SHOWN` quotes it. The record's own two-proportion test stays the fallback.
45
+ - **A bound measurement's result supports the claim.** A claim written with `measurements` that name a result gets
46
+ a `supports` edge from that result, so its standing counts the line of support the writer already bound.
47
+ - **A wrong relation names the right one.** `executes can't join run → question … — a run joins a question with
48
+ part_of, motivated_by; the other way round, a question joins a run with …`.
49
+ - **Enum synonyms** (`schema.SYNONYMS`): `outcome=success` → `positive`, `kind=fact` → `finding`,
50
+ `state=done` → `succeeded`, and more; the stored value is canonical.
51
+ - **Small integers bind to a value the sentence names.** "produced 0 trades" binds to `oos_trades`,
52
+ "capacity is 7" to `capacity_total`; an unnamed small integer still binds only to a count.
53
+
3
54
  ## 0.4.2 — 2026-10-25
4
55
 
5
56
  - **A question is not an assertion.** `language.interrogative` / `asserted` return nothing for a sentence that ends
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: hypgraph
3
- Version: 0.4.2
3
+ Version: 0.5.0
4
4
  Summary: The evidence layer for AI research agents: a hash-chained research record that checks every claim as it is written and derives how well each is known.
5
5
  Project-URL: Homepage, https://hypgraph.com
6
6
  Project-URL: Documentation, https://hypgraph.com/engineers/
@@ -0,0 +1,110 @@
1
+ # Profiles as workflows — plan
2
+
3
+ *Written 2026-10-26. Status: plan. Nothing in it is built yet beyond what §1 lists as present.*
4
+
5
+ ## 0. The question this answers
6
+
7
+ HypSwarm's trading and software profiles run on HypGraph's scientific graph with discipline labels. Is that a
8
+ feature of HypSwarm bolted onto a scientific HypGraph, or should HypGraph itself be built from each discipline's
9
+ method the way it is built from the scientific one?
10
+
11
+ **Answer: the record's kernel should stay one thing — the general shape of justified belief, which the scientific
12
+ method happens to be the clearest statement of — and each discipline's *workflow* should become a first-class,
13
+ versioned object inside a HypGraph profile that the kernel enforces and HypSwarm executes.** Today the workflow
14
+ exists only as a paragraph in the profile's notes and as a diagram on hypswarm.com. That is the gap.
15
+
16
+ ## 1. What a profile is today, and what it is not
17
+
18
+ | a profile controls today (hypgraph 0.4.3) | a profile does not control |
19
+ |---|---|
20
+ | vocabulary: a meaning per node type ("experiment = a test plan") | the node types and relations (fixed, 12 + 22) |
21
+ | `done_when` per target type (which predicates an order needs) | the **stages** a question passes through and the gate between each |
22
+ | domain predicates: `tests_pass`, `backtested_oos`, `sourced`, `feasible_bounded` | what **invalidates** a claim later: `RISKY` is fixed to the scientific relations; `cites` is not in it, so a withdrawn source leaves a knowledge claim standing |
23
+ | write-time validators: `PASS_WITHOUT_INSTRUMENT_RUN`, `EDGE_WITHOUT_OOS_COSTS`, … | the **evidence ranking** (`external > new_data > separate_implementation > …` is scientific replication; software needs *runs on the current code*, trading needs *out of sample, after costs, recent*) |
24
+ | completion criteria (`requirements_verified`, `position_recorded`, …) | typed **artifacts** (a diff with its base commit, a position with size and stop, a source with the passage that says it) — all are `artifact` / `decision` / `source` with no required discipline fields |
25
+ | suggested seats | the **report**: every profile prints "Facts from the research graph" |
26
+ | | the **order**: HypSwarm issues from the question board, not from the stage a question is in |
27
+
28
+ The discovery study (HypSwarm `studies/discovery/`) showed what this costs: 110 of 118 refusals were vocabulary
29
+ friction because the models were writing discipline work into scientific slots, and the honesty rules by themselves
30
+ did not beat a prompt. What a prompt cannot do is remember that the code changed since the tests ran, that the
31
+ source was retracted, that the regime moved, that the teammate's number is stale — the workflow's *invalidation*
32
+ and *gates*. That is where the record should win, and it is exactly what profiles don't yet encode.
33
+
34
+ ## 2. The design: one kernel, five workflows
35
+
36
+ A **Workflow** is data on the Profile, versioned with it (`software@2`), hash-chained with the investigation that
37
+ pins it:
38
+
39
+ ```python
40
+ @dataclass(frozen=True)
41
+ class Stage:
42
+ name: str # "specified", "implemented", "verified", "reviewed", "released"
43
+ holds: tuple[str, ...] # node types that live in this stage ("experiment", "artifact")
44
+ gate: tuple[str, ...] # predicates that must hold to leave it (existing + new ones)
45
+ who: str # the role that works it (worker | reviewer | lead | instrument)
46
+
47
+ @dataclass(frozen=True)
48
+ class Workflow:
49
+ stages: tuple[Stage, ...] # in order; a question is "in" the first stage whose gate is not met
50
+ invalidates: tuple[str, ...] # relations that put dependants at risk when the far end changes or falls
51
+ freshness: dict[str, str] # per node type: what "current" means ("artifact": "same sha as the run used")
52
+ artifacts: dict[str, dict] # typed artifacts: kind → required fields ("diff": {base_sha, head_sha, files})
53
+ evidence_rank: tuple[str, ...] # the profile's own ranking for `evidence`
54
+ report: str # the report template's name
55
+ ```
56
+
57
+ The kernel keeps: twelve node types, hash chain, append-only, derived standing, refusals, the instrument. The
58
+ profile supplies: which relations are risky here, what fresh means, what each stage needs, what the report says.
59
+ HypSwarm reads the stage and issues the next gate's order to the seat whose role owns that stage.
60
+
61
+ ### The five workflows (the §P0 deliverable is one page each; this is the shape)
62
+
63
+ | profile | stages | gates (new predicates in bold) | invalidation | typed artifacts |
64
+ |---|---|---|---|---|
65
+ | scientific | asked → conjectured → tested → evidenced → claimed → reviewed → decided | hypothesis stated, experiment preregistered, run registered, result, claim, review | the present `RISKY` | data (sha), protocol |
66
+ | software | specified → implemented → verified → reviewed → released | requirement question; **diff registered** (base + head sha); `tests_pass` on **that head**; review; decision | a new head sha supersedes the diff → every `tests_pass` result on the old head is **stale**, its claims AT RISK | diff, build, test-run |
67
+ | trading | asked → thesised → preregistered → backtested → risk-reviewed → positioned → monitored | hypothesis with the move it predicts; experiment with window + costs **before** the run; `backtested_oos`; review by risk; decision with size/stop/review_date; **`still_valid`** (data newer than the backtest's window, regime check) | time: a result **expires** at `review_date`; a regime-change notice puts positions AT RISK | backtest, position (paper) |
68
+ | knowledge | asked → sourced → claimed → checked → compiled | source with passage + retrieved; `sourced` claim; fact-checker review; report lint | **`cites` becomes risky**: a withdrawn or superseded source puts its claims AT RISK; a source older than `max_age` is stale | source, excerpt |
69
+ | optimization | modelled → solved → bounded → verified → recommended | hypothesis = modelling choice; experiment = solve config; `feasible_bounded`; verifier review; decision names the incumbent | a changed instance artifact (new sha) supersedes every solve on it | instance, solution |
70
+
71
+ Two cross-cutting rules the workflow makes possible and the kernel can't express today:
72
+
73
+ - **Freshness.** A result is *current* only if the artifacts its run `uses` are the live versions. Software and
74
+ optimization need this most; it is the "code changed since the tests ran" case nothing in a prompt survives.
75
+ - **Expiry.** A trading result carries `valid_until`; past it the standing says STALE and the claim needs a rerun.
76
+
77
+ ## 3. Phases, gates, spend
78
+
79
+ | phase | work | where | gate |
80
+ |---|---|---|---|
81
+ | **P0 — specs** | one page per profile: stages, gates, invalidation, artifacts, report; reviewed before code | `HypGraph/docs/workflows/<profile>.md` | the user reads all five and agrees the stages are the discipline's, not ours |
82
+ | **P1 — kernel** | `Workflow` / `Stage` on `Profile`; profile-defined `invalidates` merged into at-risk derivation; `freshness` in `derive`; typed artifacts (required fields by `kind`); `Graph.stage(question)`; `evidence_rank` per profile; report templates; new predicates (`diff_registered`, `still_valid`, `fresh`); schema bump with migration (old records = `@1`) | HypGraph, tests per profile + a replay of the discovery records to see what would change | 100 % of existing tests pass; every old record derives the same standing under `@1` |
83
+ | **P2 — orders from stages** | the scheduler asks the record which stage each question is in and issues that gate's order to the role that owns it; order text names stage and gate; the lead's report comes from the profile's template; `completion` reads the last stage | HypSwarm, scripted-model tests for every path (as now) | the stub discovery run settles every family through its stages |
84
+ | **P3 — the test that can show it** | extend the discovery harness with the change-per-discipline cases: a commit after the tests (software), a retracted source (knowledge), a regime notice and an expired backtest (trading), a changed instance (optimization), a corrected file (scientific); P vs R; predictions first | HypSwarm `studies/discovery/`, ≈ $2 | this is where a prompt cannot hold state and the record can; if R does not win **here**, the workflow design is wrong |
85
+ | **P4 — docs** | profiles presented as HypGraph's, with the workflow on hypgraph.com as it is on hypswarm.com; the engineers pages; `hypgraph profiles` prints stages | both sites | — |
86
+
87
+ P1 is the considerable part: two to three days of kernel work with tests, and the first schema version bump that
88
+ needs a migration story. P0 is a day and decides whether P1 is right. P3 is the only spend.
89
+
90
+ **Status (2026-10-26).** P0 written (`docs/workflows/`), P1 built as hypgraph 0.5.0 (`workflow.py`,
91
+ `tests/test_workflows.py`; CHANGELOG). The schema change turned out additive (fields and relation endpoints), so
92
+ no migration: `@1` records derive exactly as before, the `@2` profiles opt in. Left for later phases, each named in
93
+ its spec: per-workflow evidence rank (documented, not derived), the knowledge re-fetch check, CI as the software
94
+ instrument, mechanical feasibility recomputation (P3). P2 (HypSwarm issues orders from stages) is next.
95
+
96
+ ## 4. What stays as it is, on purpose
97
+
98
+ - Twelve node types. A commit is an artifact with required fields, not a new type; a position is a decision with
99
+ required fields. The spec, the Atlas, the MCP tools and the playground don't fork per discipline.
100
+ - One hash chain and one `verify`. A workflow is data the chain covers, not code the chain can't see.
101
+ - Dependency-free kernel. Workflows are tables and predicates, like profiles are now.
102
+ - The honesty rules. They held in the discovery study; the workflow adds the state they can't carry.
103
+
104
+ ## 5. Risks
105
+
106
+ - **Over-specifying a discipline we don't practise.** P0 is where a trader or an engineer corrects the stages; the
107
+ specs should quote the method they're taken from (preregistration, CI gates, source criticism, verification).
108
+ - **Schema version.** Old records must keep deriving identically; `profile@1` is the frozen behaviour.
109
+ - **Stage inference, not stage setting.** A question's stage must be *derived* from what the record holds (the
110
+ first unmet gate), never written by an agent — same rule as standing.
@@ -0,0 +1,30 @@
1
+ # Workflow specs — P0 of the profiles-as-workflows plan
2
+
3
+ One page per profile, for review before any kernel code (see `../profile-workflows-plan.md`). Each spec names the
4
+ method it is taken from, then states what the record would enforce: the stages a question passes through, the gate
5
+ out of each stage (predicates the record checks), who works the stage, what later invalidates a claim, what
6
+ "fresh" means, the typed artifacts with their required fields, the report, and completion.
7
+
8
+ Conventions used in every spec:
9
+
10
+ - **A stage is derived, never set.** A question is in the first stage whose gate is not met. Agents write nodes;
11
+ the record reads the stage off them.
12
+ - **Gates are predicates** the record evaluates from the record alone (existing ones in `coord.PREDICATES` and
13
+ `profiles.PRED_DESC`; new ones are marked **new**).
14
+ - **Invalidation** names the relations that, when the far end falls, changes version or expires, put dependants
15
+ AT RISK. Today only the scientific set (`requires`, `derived_from`, `based_on`, `works_on`, `rests_on`) does.
16
+ - **Fresh** says when a result still speaks for the thing it measured.
17
+ - **Typed artifacts** are `artifact` / `source` / `decision` nodes with required fields per `kind`, not new types.
18
+
19
+ | spec | method it is taken from | the one gate a prompt can't keep |
20
+ |---|---|---|
21
+ | [scientific](scientific.md) | hypothetico-deductive method, preregistration | a corrected data file after the analysis |
22
+ | [software](software.md) | continuous integration and code review | a commit after the tests ran |
23
+ | [trading](trading.md) | preregistered backtesting, risk management | a backtest past its review date, a regime notice |
24
+ | [knowledge](knowledge.md) | source criticism, fact-checking practice | a retracted or superseded source |
25
+ | [optimization](optimization.md) | operations-research practice: model, solve, bound, verify | a changed instance after the solve |
26
+
27
+ Each spec ends with its review questions and the decision taken on each (2026-10-26). **Built as hypgraph 0.5.0**
28
+ (`src/hypgraph/workflow.py`, the `@2` profiles in `profiles.py`, `tests/test_workflows.py`): the stages and gates,
29
+ `Graph.stage()`, the invalidation relations, freshness, the typed shapes and the refusals. What each spec defers to
30
+ a later phase is named in its decisions.
@@ -0,0 +1,82 @@
1
+ # Workflow: `knowledge`
2
+
3
+ ## The method it is taken from
4
+
5
+ Source criticism and professional fact-checking: a statement is only as good as the source that says it, the
6
+ passage that says it must be quoted, the source's reliability and date are part of the claim, and a check is done
7
+ by someone who did not write the claim. The historian's external and internal criticism of sources; the
8
+ International Fact-Checking Network's code (cite primary sources, show the evidence, correct openly); and the
9
+ systematic-review discipline of recording what was searched and what was excluded. The record holds what was
10
+ read, not what was recalled, and a correction propagates to everything built on the source.
11
+
12
+ ## Stages
13
+
14
+ | # | stage | holds | gate out of it | who |
15
+ |---|---|---|---|---|
16
+ | 1 | asked | question | stated | lead |
17
+ | 2 | searched | experiment `kind=search`: where it looked, with what terms, what it excluded | `search_recorded` **new**: an experiment on the question states the sources consulted (optional stage: required when the task asks for a systematic answer) | researcher |
18
+ | 3 | sourced | source nodes: `citation`, `url` or `doi`, **`passage`**, `retrieved`, `kind` (primary / secondary / tertiary), `reliability` note | `source_quoted` **new**: a source with a non-empty `passage` and `retrieved` date `cites`-able from a claim | researcher |
19
+ | 4 | claimed | claim `cites` the source; measurements bound to numbers in the passage (0.4.1) | `sourced` (today); validator `CLAIM_WITHOUT_SOURCE` | researcher |
20
+ | 5 | checked | review by the fact-checker: opened the source, the passage says it | `reviewed`, with method naming the source opened | fact_checker |
21
+ | 6 | compiled | the report, linted so no sentence treats an unchecked claim as settled | `report_clean` (today) | lead |
22
+
23
+ A question whose honest answer is "no source" is settled by a claim of `kind=inconclusive` that `cites` the search
24
+ experiment ("searched X, Y, Z; nothing answers it") — the LIB-NOTES "stuck but honest" case becomes a settled one.
25
+
26
+ ## Invalidation
27
+
28
+ - **`cites` becomes an at-risk relation.** A source that is withdrawn (retracted, taken down, corrected) puts
29
+ every claim that cites it AT RISK, and every decision on those claims. Today `cites` is not in `RISKY`.
30
+ - **Supersession of sources**: a newer edition or a correction `supersedes` the old source node; claims on the old
31
+ one are STALE until re-cited.
32
+ - `derived_from`, `based_on`, `rests_on` as usual.
33
+
34
+ ## Freshness
35
+
36
+ A source has `retrieved`; the profile sets `max_age` (none by default; a task may set "sources newer than 2024").
37
+ A claim whose only sources are older than `max_age` is STALE. A URL source is fresh while its content hash (stored
38
+ at retrieval, when the host fetched it) matches a re-fetch; the instrument can re-fetch and compare, as it re-runs
39
+ code for results.
40
+
41
+ ## Typed sources
42
+
43
+ | kind | required fields | note |
44
+ |---|---|---|
45
+ | `primary` | `citation`, `url` or `doi`, `passage`, `retrieved` | the thing itself: a paper, a dataset, a document |
46
+ | `secondary` | the same + `cites` (what it summarises) when known | an encyclopaedia, a review |
47
+ | `tertiary` | the same | an index, a listing; a claim resting only on tertiary sources is flagged |
48
+ | `excerpt` artifact | `sha256`, `source` (id), `path` | the fetched text, hashed, for the re-fetch check |
49
+
50
+ ## Evidence rank
51
+
52
+ `two_independent_primary > primary > secondary > tertiary > unsourced`. "Independent" = different publishers,
53
+ not two pages of one site.
54
+
55
+ ## Report
56
+
57
+ "Sourced brief": each question with its answer, the claim, the source (citation, passage), the checker's verdict;
58
+ unanswered questions with what was searched; sources by kind; what is stale or withdrawn.
59
+
60
+ ## Completion
61
+
62
+ `questions_settled` + `all_sourced` (today) + **`all_checked`**: every claim in the brief has a fact-checker's
63
+ review.
64
+
65
+ ## Refusals this workflow adds
66
+
67
+ - `PASSAGE_MISSING`: a source without the passage that says the thing.
68
+ - `NUMBER_NOT_IN_PASSAGE`: a claim number that the cited passage does not contain (0.4.1 allows passage numbers;
69
+ this is the converse refusal).
70
+ - `TERTIARY_ONLY` (warning): a finding resting only on tertiary sources.
71
+
72
+ ## Review questions and decisions (2026-10-26)
73
+
74
+ 1. *Is `searched` required?* **Optional** (reported, never blocks); a task that wants a systematic answer puts
75
+ `search_recorded` in its `done_when`.
76
+ 2. *The re-fetch check?* **P3**, with `NUMBER_NOT_IN_PASSAGE`; both need the host's fetch at review time.
77
+ 3. *Can the fact-checker re-kind a source?* **Yes**: `corrects` now joins sources; the correcting source carries
78
+ the kind, and the old one is superseded.
79
+
80
+ Also decided: "compiled" is not a question stage — the report is investigation-level and stays under completion
81
+ (`report_clean` on the investigation order). The knowledge stages are asked → searched (optional) → sourced →
82
+ claimed → checked.
@@ -0,0 +1,80 @@
1
+ # Workflow: `optimization`
2
+
3
+ ## The method it is taken from
4
+
5
+ Operations-research practice: a problem is modelled (objective, decision variables, constraints) before it is
6
+ solved; a solution is only a solution if it is feasible; "optimal" is a statement about a **bound**, not about
7
+ effort; and a solver's answer is verified against the constraints by someone other than the modeller. The
8
+ mixed-integer programming convention that an incumbent is reported with its optimality gap (the gap between the
9
+ best solution and the best bound); the sensitivity-analysis norm that a recommendation says how it changes when
10
+ the data does; and the modelling-lifecycle view (Williams, *Model Building in Mathematical Programming*) that the
11
+ model is a hypothesis about the problem and can be wrong independently of the solver.
12
+
13
+ ## Stages
14
+
15
+ | # | stage | holds | gate out of it | who |
16
+ |---|---|---|---|---|
17
+ | 1 | posed | question: what to minimise or maximise, under which constraints; the instance as an artifact | `instance_registered` **new**: an artifact `kind=instance` with its sha | lead |
18
+ | 2 | modelled | hypothesis = the modelling choice (variables, objective, constraints as stated); `predictions` = what the solution should look like | `hypothesis_stated` **new** | modeller |
19
+ | 3 | configured | experiment = the solve configuration: solver, time limit, tolerances, `tests` the hypothesis | `preregistered` **new** (the configuration precedes the solve) | solver |
20
+ | 4 | solved | run `executes` the experiment, `uses` the instance; result with `objective`, `feasible`, `bound`, `gap`, `runtime_s`, `solution` artifact | `feasible_bounded` (today) | solver, instrument |
21
+ | 5 | verified | review by the verifier: the solution satisfies the constraints of the **instance artifact** (recomputed, not trusted) | `reviewed` with method naming the check | verifier |
22
+ | 6 | claimed | claim "best found, gap g" or "optimal" with the bound; `OPTIMAL_WITHOUT_BOUND` (today) | `claim_made` | solver |
23
+ | 7 | recommended | decision `based_on` the claim: the incumbent to use, with the sensitivity note | `decided` **new** | lead |
24
+
25
+ Infeasibility is a settled outcome: a result with `feasible: false` and a claim of `kind=exclusion` ("no feasible
26
+ assignment exists: total capacity 7 < 8 customers") settles the question. Today that path trips
27
+ `ABSOLUTE_WITHOUT_COUNT`; the workflow makes "no feasible X" bind to the result's `feasible` value.
28
+
29
+ ## Invalidation
30
+
31
+ - **A changed instance** (new sha) `supersedes` the old instance artifact; every run that `uses` it is STALE, its
32
+ results, claims and the recommendation AT RISK. Same mechanism as software's new head.
33
+ - A revised model (new hypothesis version) marks solves of the old model as "of the old model".
34
+ - `uses`, `derived_from`, `based_on`, `rests_on`.
35
+
36
+ ## Freshness
37
+
38
+ Fresh = the run's instance artifact is the live one and the model hypothesis is at its reviewed version.
39
+
40
+ ## Typed artifacts
41
+
42
+ | kind | required fields | note |
43
+ |---|---|---|
44
+ | `instance` | `sha256`, `path`, `size` | the data the model is solved on |
45
+ | `solution` | `sha256`, `path`, `objective`, `feasible` | the assignment / schedule / plan |
46
+ | `model` | `sha256`, `path` (the formulation file), `solver` | optional; when the model is a file |
47
+
48
+ ## Evidence rank
49
+
50
+ `proven_optimal (gap 0 or bound = objective) > bounded (gap stated) > feasible_only > infeasible_claimed >
51
+ unverified`. A `bound` that comes from enumeration counts as a proof for the instance size it names.
52
+
53
+ ## Report
54
+
55
+ "Solution report": the problem; the model (variables, objective, constraints); the configuration; the incumbent
56
+ with objective, feasibility, bound and gap; the verifier's check; the recommendation and its sensitivity; what is
57
+ stale (solves on superseded instances or models).
58
+
59
+ ## Completion
60
+
61
+ `questions_settled` + `incumbent_feasible` (today) + **`verified`**: the incumbent has a verifier's review that
62
+ recomputed feasibility.
63
+
64
+ ## Refusals this workflow adds
65
+
66
+ - `SOLVED_WITHOUT_INSTANCE`: a run with no `uses` → instance artifact.
67
+ - `VERIFIED_BY_SOLVER`: a review of a solution by its own author.
68
+ - `OPTIMAL_ON_STALE_INSTANCE`: "optimal" bound to a solve whose instance is superseded.
69
+
70
+ ## Review questions and decisions (2026-10-26)
71
+
72
+ 1. *The model: hypothesis or experiment?* **Hypothesis** (`modelled`, gate `hypothesis_stated`): it can be wrong
73
+ independently of the solve and is revisable with its own version.
74
+ 2. *Mechanical feasibility recomputation?* **P3** (`check_solution` reproducer). Built now: `result_reviewed` —
75
+ the verifier's check on the result, by someone who is not its author — and `incumbent_verified` needs it on the
76
+ current instance.
77
+ 3. *Sensitivity?* **An optional `sensitivity` field on the decision.**
78
+
79
+ Also decided: `SOLVED_WITHOUT_INSTANCE` refuses a solve result with no producing run as well as one whose run uses
80
+ no instance — otherwise the gate is dodged by not linking the run.
@@ -0,0 +1,75 @@
1
+ # Workflow: `scientific`
2
+
3
+ ## The method it is taken from
4
+
5
+ The hypothetico-deductive method as practised in empirical science, with the modern discipline of
6
+ **preregistration**: state the hypothesis and the analysis before seeing the outcome, so the test cannot be bent
7
+ to the result. Popper's criterion that a scientific statement must be falsifiable; the Center for Open Science's
8
+ preregistration practice (hypothesis, design, analysis plan fixed before data); and the replication norm that a
9
+ finding stands on independent lines of evidence, not repeated copies of one. HypGraph's kernel was built from this
10
+ workflow, so this spec mostly names what the kernel already does and marks the two things it doesn't.
11
+
12
+ ## Stages
13
+
14
+ | # | stage | holds | gate out of it | who |
15
+ |---|---|---|---|---|
16
+ | 1 | asked | question | the question is stated (`question` node with `text`) | lead |
17
+ | 2 | conjectured | hypothesis with `predictions` | `hypothesis_stated` **new**: a hypothesis `answers` the question with at least one checkable prediction | lead / worker |
18
+ | 3 | preregistered | experiment with `aim`, `protocol`, `success_criteria`, `tests` → hypothesis with `expected` | `preregistered` **new**: an experiment `tests` the hypothesis with an expected outcome stated **before** any run `executes` it (created_at order) | worker |
19
+ | 4 | run | run (`agent` or `lab`), artifacts it `uses` | `run_registered` | worker, instrument |
20
+ | 5 | evidenced | result `produced` by the run, values | `result_exists`; the instrument's replicate when code was registered | worker, instrument |
21
+ | 6 | claimed | claim with measurements, `answers` the question | `claim_made` | worker |
22
+ | 7 | reviewed | review by a policy reviewer, not the author | `reviewed` | reviewer |
23
+ | 8 | decided | decision `based_on` the claim | `decided` **new** (optional stage; required only when the task asks for a decision) | lead |
24
+
25
+ A question is **settled** at stage 7 (today's rule). Stage 3's gate is what preregistration adds: an experiment
26
+ created *after* its run's result is not preregistered, and its result's evidence rank is capped at `exploratory`.
27
+
28
+ ## Invalidation (at-risk relations)
29
+
30
+ Today's set, unchanged: `requires`, `derived_from`, `based_on`, `works_on`, `rests_on`. Plus **`uses`**: a run
31
+ that `uses` an artifact which is later withdrawn (a corrected data file) puts its results, their claims and the
32
+ decisions on them AT RISK — the F7 case. Today this works only through `derived_from` chains that happen to pass
33
+ through the artifact; it should be the relation itself.
34
+
35
+ ## Freshness
36
+
37
+ A result is fresh while every artifact its run `uses` is the live version (same sha). A result on a withdrawn or
38
+ superseded artifact is STALE; a claim resting only on stale results needs a rerun before a review counts.
39
+
40
+ ## Typed artifacts
41
+
42
+ | kind | required fields | note |
43
+ |---|---|---|
44
+ | `data` | `sha256`, `path`, `size` | what the run read; registered by the task or the host |
45
+ | `protocol` | `sha256`, `path` | the analysis code or plan, when it is a file |
46
+ | `figure` | `sha256`, `path`, `format` | produced by a run |
47
+
48
+ ## Evidence rank (unchanged)
49
+
50
+ `external > new_data > separate_implementation > same_code > unverified`, from `replicates` links and their
51
+ `differs` field; an unprovenanced line counts once.
52
+
53
+ ## Report
54
+
55
+ "Facts from the record" as today: claims with standing and verdicts, results and whether a claim carries them,
56
+ hypotheses, experiments (preregistered or not), open items, spend; interpretation underneath; linted.
57
+
58
+ ## Completion
59
+
60
+ `questions_settled` (today). Optional: `decisions_recorded` when the task asked for a decision.
61
+
62
+ ## Refusals this workflow adds
63
+
64
+ - `EXPERIMENT_AFTER_RUN`: an experiment linked `tests` after a run already `executes` it — allowed, but the record
65
+ marks the result exploratory and says so.
66
+ - `STALE_EVIDENCE`: a review on a claim whose only results are stale is recorded as `comment`, not `checked`.
67
+
68
+ ## Review questions and decisions (2026-10-26)
69
+
70
+ 1. *Preregistration: a gate or a label?* **A gate** (`preregistered`: the experiment, with its expected outcome,
71
+ precedes any run that executes it; one written after is named as such). The evidence-rank cap is not built:
72
+ `report()` already lists experiments as preregistered or not, and the gate's reason says why.
73
+ 2. *Is `decided` a scientific stage?* **Optional**: reported, never blocks; a question is complete at `reviewed`.
74
+ 3. *`uses` as at-risk changes old records?* **Only under `scientific@2`** (`derive.EXTRA_RISKY`); `@1` records derive
75
+ exactly as before. Freshness (`stale`) is universal, since no record could have had a superseded artifact.
@@ -0,0 +1,78 @@
1
+ # Workflow: `software`
2
+
3
+ ## The method it is taken from
4
+
5
+ Continuous integration and code review as practised in professional engineering: a change is a reviewable unit
6
+ against a known base; the tests that count are the ones a machine ran on **that** change; nothing merges without
7
+ them; and a later change re-opens the question. Fowler's continuous integration ("every commit is built and
8
+ tested"), the pull-request review norm (author ≠ approver), and the DORA practice of trunk-based delivery where a
9
+ release is a decision on evidence the pipeline produced. The requirement plays the role of the question; the
10
+ instrument plays the role of CI.
11
+
12
+ ## Stages
13
+
14
+ | # | stage | holds | gate out of it | who |
15
+ |---|---|---|---|---|
16
+ | 1 | specified | question = the requirement or the bug, with acceptance stated | the question has an acceptance criterion in its text or `success_criteria` **new** on a linked experiment (the test plan) | lead |
17
+ | 2 | implemented | artifact `kind=diff` registered: `base_sha`, `head_sha`, `files`, `sha256` of the patch | `diff_registered` **new**: a diff artifact `part_of` the question, newer than the last one | implementer |
18
+ | 3 | verified | run `kind=lab` that `uses` the diff artifact; result `tests` with `passed k of n`, `exit_code` | `tests_pass` **on that head**: the instrument's run `uses` the diff whose `head_sha` is current | tester, instrument |
19
+ | 4 | claimed | claim "requirement met" with measurements bound to the lab result | `claim_made`; validator `PASS_WITHOUT_INSTRUMENT_RUN` (today) | tester |
20
+ | 5 | reviewed | review by a reviewer who is not the diff's author | `reviewed` | reviewer |
21
+ | 6 | released | decision `based_on` the claim: merge / ship / hold, with the head_sha it releases | `decided` **new** | lead |
22
+
23
+ ## Invalidation
24
+
25
+ - A **new diff artifact** on the same question (a newer `head_sha`) `supersedes` the old one. Every lab run that
26
+ `uses` the old diff is STALE; its results, the claims on them, and the release decision go AT RISK. This is the
27
+ gate a prompt cannot keep: the model that ran the tests at 14:02 does not know about the commit at 14:10.
28
+ - `uses`, `derived_from`, `based_on`, `rests_on` as at-risk relations (as scientific), plus **`supersedes` on
29
+ artifacts** (today supersedes is for claims and decisions only).
30
+
31
+ ## Freshness
32
+
33
+ A test result is fresh only if the diff its run `uses` has the current `head_sha` for the question. A `tests_pass`
34
+ predicate evaluated on a stale run is NOT MET with the reason "tests ran on <old sha>; current head is <new sha>".
35
+
36
+ ## Typed artifacts
37
+
38
+ | kind | required fields | note |
39
+ |---|---|---|
40
+ | `diff` | `base_sha`, `head_sha`, `files` (list), `sha256` (of the patch), `path` | the reviewable unit |
41
+ | `test_run` | `command`, `exit_code`, `passed`, `failed`, `sha256` (of the log) | produced by the instrument's run |
42
+ | `build` | `head_sha`, `sha256` (of the artifact), `path` | optional |
43
+
44
+ A diff registered by an agent is `kind=agent` provenance; only the instrument's `uses` of it makes it evidence.
45
+
46
+ ## Evidence rank
47
+
48
+ `lab_on_current_head > lab_on_old_head (stale) > agent_reported > unverified`. Replication across environments
49
+ (`new_env`: another OS or Python) ranks above `same_code` as in scientific.
50
+
51
+ ## Report
52
+
53
+ "Change report": the requirement; the diff (base → head, files); the instrument's test run on that head (passed k
54
+ of n, exit code, command); the claim and its review; the release decision; **what is stale** (any earlier runs on
55
+ superseded heads, listed as superseded); open requirements.
56
+
57
+ ## Completion
58
+
59
+ `requirements_verified` (today) tightened: every requirement's claim rests on a lab run whose diff is current. Plus
60
+ `released` when the task asks for a release decision.
61
+
62
+ ## Refusals this workflow adds
63
+
64
+ - `TESTS_ON_STALE_HEAD`: a claim of passing bound to a lab result whose diff is superseded.
65
+ - `DIFF_WITHOUT_BASE`: a diff artifact without `base_sha` / `head_sha`.
66
+ - `REVIEW_BY_AUTHOR`: a review of a claim whose diff the reviewer authored (today only the claim's author is
67
+ blocked; the diff's author should be too).
68
+
69
+ ## Review questions and decisions (2026-10-26)
70
+
71
+ 1. *Requirement = question or experiment?* **Question**, with the test plan as an experiment linked to it. Stage 1's
72
+ gate is the question itself (`stated`); an acceptance criterion in `success_criteria` is encouraged, not gated.
73
+ 2. *Diff bytes or hashes?* **Hashes and the file list** (`artifact.kind=diff`, `meta: base_sha, head_sha, files`,
74
+ `sha256` of the patch); the host keeps the bytes.
75
+ 3. *CI as the instrument?* **P3.** Built now: the `uses` relation to the current diff is what `tests_pass_current`
76
+ reads, so a CI reproducer only has to file a lab run that `uses` the diff.
77
+
78
+ Also decided: `REVIEW_BY_AUTHOR` covers the diff's author (built); `supersedes` joins artifacts (built).
@@ -0,0 +1,81 @@
1
+ # Workflow: `trading`
2
+
3
+ ## The method it is taken from
4
+
5
+ Quantitative strategy research as the sceptical part of the field describes it: a thesis is a hypothesis; its
6
+ test is a backtest whose window, costs and rules are fixed **before** it runs (the trading analogue of
7
+ preregistration); only an **out-of-sample, after-cost** result speaks to an edge; and a result has a shelf life.
8
+ Bailey, Borwein, López de Prado and Zhu on backtest overfitting ("the probability of backtest overfitting" — the
9
+ more configurations tried, the less an in-sample result means); the deflated Sharpe ratio; walk-forward
10
+ validation; and the risk-management norm that a position is a sized decision with a stop and a review date, taken
11
+ by someone other than the analyst. No live-order path exists anywhere in this workflow.
12
+
13
+ ## Stages
14
+
15
+ | # | stage | holds | gate out of it | who |
16
+ |---|---|---|---|---|
17
+ | 1 | asked | question: the market question | stated | lead |
18
+ | 2 | thesised | hypothesis with `predictions` = the move, the horizon, the universe | `hypothesis_stated` **new** | quant |
19
+ | 3 | preregistered | experiment: `protocol` names the in-sample and out-of-sample windows, the costs (fees, slippage), the rules, the number of configurations to be tried; `expected` on the `tests` link | `preregistered` **new**: the experiment exists **before** the run that `executes` it, with windows and costs in the protocol | quant |
20
+ | 4 | backtested | run `executes` the experiment, `uses` the data artifact; result with `oos_*` and cost values, `trials` (configurations tried) | `backtested_oos` (today) + **`trials_declared`** new: the result states how many configurations were tried | quant, instrument |
21
+ | 5 | claimed | claim about the edge or its absence, bound to the oos result | `claim_made`; validators `EDGE_WITHOUT_OOS_COSTS`, `BACKTEST_WITHOUT_COSTS` (today), **`EDGE_WITHOUT_TRIALS`** new | quant |
22
+ | 6 | risk-reviewed | review by the risk seat (never the quant) | `reviewed` | risk |
23
+ | 7 | positioned | decision `based_on` the claim: `size`, `stop`, `review_date`, `paper: true` | `position_recorded` (today's completion criterion becomes a gate) | lead |
24
+ | 8 | monitored | later results on the same hypothesis with newer data; notices | `still_valid` **new**: a result newer than the position's `review_date` or a regime check on the hypothesis | quant, risk |
25
+
26
+ ## Invalidation
27
+
28
+ - **Expiry.** A backtest result carries `valid_until` (default: the decision's `review_date`). Past it the result is
29
+ STALE and the position AT RISK until a newer result on the same hypothesis exists.
30
+ - **Regime notice.** A host notice ("regime changed: rates / volatility / venue") withdraws the data artifact's
31
+ claim to represent the present; every position whose claim rests on results `uses`-ing it goes AT RISK.
32
+ - `uses`, `derived_from`, `based_on`, `rests_on` as at-risk relations.
33
+
34
+ ## Freshness
35
+
36
+ Fresh = `now ≤ valid_until` and the data artifact the run `uses` is live. A claim of an edge on a stale result is
37
+ reported as "edge as of <window>, not re-tested since".
38
+
39
+ ## Typed artifacts and decisions
40
+
41
+ | kind | required fields | note |
42
+ |---|---|---|
43
+ | artifact `prices` | `sha256`, `path`, `from`, `to`, `frequency` | the data window |
44
+ | artifact `backtest` | `sha256` (of the code), `path`, `trials` | the code and how many configurations it tried |
45
+ | decision `position` | `size`, `stop`, `review_date`, `paper` (must be true), `based_on` → claim | the only kind of position the record accepts |
46
+
47
+ ## Evidence rank
48
+
49
+ `oos_after_costs_new_data > oos_after_costs > in_sample > unverified`. A result whose `trials` is large relative to
50
+ its window is flagged (the overfitting warning), not refused.
51
+
52
+ ## Report
53
+
54
+ "Desk note": the thesis; the preregistered protocol (windows, costs, trials); the out-of-sample result after costs
55
+ with the trade count; the risk review; the position (size, stop, review date, paper); what is stale or past review;
56
+ open theses.
57
+
58
+ ## Completion
59
+
60
+ `questions_settled` + `position_recorded` (today) + **`nothing_past_review`**: no position whose `review_date` has
61
+ passed without a newer result.
62
+
63
+ ## Refusals this workflow adds
64
+
65
+ - `EDGE_WITHOUT_TRIALS`: "edge" on a result that does not state how many configurations were tried.
66
+ - `POSITION_WITHOUT_STOP`: a position decision missing `size`, `stop` or `review_date`.
67
+ - `LIVE_ORDER`: any decision or artifact kind that names a venue order; there is no path, and the refusal says so.
68
+ - `BACKTEST_AFTER_PROTOCOL_EDIT`: an experiment revised after its run (a changed window) — allowed, but the result
69
+ is re-ranked `in_sample`.
70
+
71
+ ## Review questions and decisions (2026-10-26)
72
+
73
+ 1. *Will agents report `trials` honestly?* **Required now, checked later**: `backtested` and `EDGE_WITHOUT_TRIALS`
74
+ need the value; the instrument's count of the parameter grid is P3.
75
+ 2. *`review_date` default?* **Required, no default** (`POSITION_WITHOUT_STOP` names what is missing).
76
+ 3. *Who raises a regime notice?* **The host or the risk seat**: it is a withdrawal (or supersession) of the data
77
+ artifact, which only they write; `uses` then carries it to every position.
78
+
79
+ Also decided: `still_valid` counts a result as newer only if written after both the review date and the position
80
+ (the evidence a position was taken on doesn't renew it). `BACKTEST_AFTER_PROTOCOL_EDIT` is not a separate refusal:
81
+ `preregistered` already names an experiment written after its run.
@@ -16,7 +16,7 @@ Standing is derived on every read, never stored; every write is an event in a SH
16
16
  their numbers; reviews pin versions; independence is counted, not assumed. See https://hypgraph.com.
17
17
  """
18
18
 
19
- __version__ = "0.4.2"
19
+ __version__ = "0.5.0"
20
20
 
21
21
  from .bundle import verify_bundle # noqa: E402
22
22
  from .graph import Author, Graph, GraphError, file_sha256 # noqa: E402