hypgraph 0.3.0__tar.gz → 0.4.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.
- {hypgraph-0.3.0 → hypgraph-0.4.0}/.gitignore +3 -0
- hypgraph-0.4.0/CHANGELOG.md +151 -0
- {hypgraph-0.3.0 → hypgraph-0.4.0}/PKG-INFO +20 -1
- {hypgraph-0.3.0 → hypgraph-0.4.0}/README.md +19 -0
- hypgraph-0.4.0/docs/decisions/ADR-001-token-bound-authors.md +46 -0
- hypgraph-0.4.0/docs/decisions/ADR-002-governance-profiles.md +50 -0
- hypgraph-0.4.0/docs/review-2026-10-24.md +206 -0
- {hypgraph-0.3.0 → hypgraph-0.4.0}/src/hypgraph/__init__.py +1 -1
- {hypgraph-0.3.0 → hypgraph-0.4.0}/src/hypgraph/checks.py +43 -7
- {hypgraph-0.3.0 → hypgraph-0.4.0}/src/hypgraph/cli.py +55 -2
- hypgraph-0.4.0/src/hypgraph/coord.py +845 -0
- {hypgraph-0.3.0 → hypgraph-0.4.0}/src/hypgraph/derive.py +59 -5
- {hypgraph-0.3.0 → hypgraph-0.4.0}/src/hypgraph/graph.py +213 -4
- {hypgraph-0.3.0 → hypgraph-0.4.0}/src/hypgraph/language.py +50 -0
- {hypgraph-0.3.0 → hypgraph-0.4.0}/src/hypgraph/mcp.py +133 -3
- {hypgraph-0.3.0 → hypgraph-0.4.0}/src/hypgraph/policy.py +6 -2
- hypgraph-0.4.0/src/hypgraph/profiles.py +387 -0
- {hypgraph-0.3.0 → hypgraph-0.4.0}/src/hypgraph/refusals.py +78 -4
- {hypgraph-0.3.0 → hypgraph-0.4.0}/src/hypgraph/schema.py +15 -5
- {hypgraph-0.3.0 → hypgraph-0.4.0}/src/hypgraph/server.py +108 -15
- {hypgraph-0.3.0 → hypgraph-0.4.0}/src/hypgraph/stats.py +10 -2
- hypgraph-0.4.0/studies/harmony/tests/test_suite.py +107 -0
- hypgraph-0.4.0/tests/test_cancel_releases_lease.py +39 -0
- hypgraph-0.4.0/tests/test_coord.py +213 -0
- hypgraph-0.4.0/tests/test_d10.py +146 -0
- hypgraph-0.4.0/tests/test_engine_fixes.py +167 -0
- hypgraph-0.4.0/tests/test_order_detail.py +31 -0
- hypgraph-0.4.0/tests/test_profiles.py +138 -0
- hypgraph-0.4.0/tests/test_server_auth.py +110 -0
- hypgraph-0.4.0/tests/test_stats_values.py +67 -0
- hypgraph-0.3.0/CHANGELOG.md +0 -88
- {hypgraph-0.3.0 → hypgraph-0.4.0}/AGENTS.md +0 -0
- {hypgraph-0.3.0 → hypgraph-0.4.0}/CITATION.cff +0 -0
- {hypgraph-0.3.0 → hypgraph-0.4.0}/LICENSE +0 -0
- {hypgraph-0.3.0 → hypgraph-0.4.0}/NOTICE +0 -0
- {hypgraph-0.3.0 → hypgraph-0.4.0}/docs/PLAN.md +0 -0
- {hypgraph-0.3.0 → hypgraph-0.4.0}/docs/spec.md +0 -0
- {hypgraph-0.3.0 → hypgraph-0.4.0}/pyproject.toml +0 -0
- {hypgraph-0.3.0 → hypgraph-0.4.0}/src/hypgraph/__main__.py +0 -0
- {hypgraph-0.3.0 → hypgraph-0.4.0}/src/hypgraph/bundle.py +0 -0
- {hypgraph-0.3.0 → hypgraph-0.4.0}/src/hypgraph/demos/__init__.py +0 -0
- {hypgraph-0.3.0 → hypgraph-0.4.0}/src/hypgraph/demos/broad_street.py +0 -0
- {hypgraph-0.3.0 → hypgraph-0.4.0}/src/hypgraph/plan.py +0 -0
- {hypgraph-0.3.0 → hypgraph-0.4.0}/src/hypgraph/report_check.py +0 -0
- {hypgraph-0.3.0 → hypgraph-0.4.0}/src/hypgraph/skill/SKILL.md +0 -0
- {hypgraph-0.3.0 → hypgraph-0.4.0}/src/hypgraph/store.py +0 -0
- {hypgraph-0.3.0 → hypgraph-0.4.0}/src/hypgraph/ui/__init__.py +0 -0
- {hypgraph-0.3.0 → hypgraph-0.4.0}/src/hypgraph/ui/atlas.css +0 -0
- {hypgraph-0.3.0 → hypgraph-0.4.0}/src/hypgraph/ui/atlas.js +0 -0
- {hypgraph-0.3.0 → hypgraph-0.4.0}/src/hypgraph/ui/hypgraph.svg +0 -0
- {hypgraph-0.3.0 → hypgraph-0.4.0}/src/hypgraph/ui/index.html +0 -0
- {hypgraph-0.3.0 → hypgraph-0.4.0}/src/hypgraph/ui/vendor/LICENSES.md +0 -0
- {hypgraph-0.3.0 → hypgraph-0.4.0}/src/hypgraph/ui/vendor/cose-base.js +0 -0
- {hypgraph-0.3.0 → hypgraph-0.4.0}/src/hypgraph/ui/vendor/cytoscape-fcose.js +0 -0
- {hypgraph-0.3.0 → hypgraph-0.4.0}/src/hypgraph/ui/vendor/cytoscape.min.js +0 -0
- {hypgraph-0.3.0 → hypgraph-0.4.0}/src/hypgraph/ui/vendor/layout-base.js +0 -0
- {hypgraph-0.3.0 → hypgraph-0.4.0}/tests/test_engine.py +0 -0
- {hypgraph-0.3.0 → hypgraph-0.4.0}/tests/test_incremental.py +0 -0
- {hypgraph-0.3.0 → hypgraph-0.4.0}/tests/test_log_and_check.py +0 -0
- {hypgraph-0.3.0 → hypgraph-0.4.0}/tests/test_refusals.py +0 -0
- {hypgraph-0.3.0 → hypgraph-0.4.0}/tests/test_surfaces.py +0 -0
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 0.4.0 — 2026-10-25: the coordination layer
|
|
4
|
+
|
|
5
|
+
Held until the harmony study had exercised every path (pilots 1–4, a 142-run confirmatory, two follow-up rounds). Governance profiles, token-bound authors, work orders with predicates, order text that carries the target, instrument reproduction, replayable refusals.
|
|
6
|
+
|
|
7
|
+
### Identity and arithmetic (2026-10-25)
|
|
8
|
+
- `hypgraph serve --token SECRET[=authors]` binds writes to bearer tokens (401 without one, 403 for an author the token isn't bound to; a reserved name needs a token that names it). `--token-file`, `$HYPGRAPH_TOKEN`. Without tokens: unchanged. `Policy.extra_reserved` lets a host reserve its own names (hypswarm reserves `harness`). ADR-001.
|
|
9
|
+
- **Governance profiles** (`hypgraph.profiles`, ADR-002): `scientific@1` (the default), `software@1`, `trading@1`, `knowledge@1`, `optimization@1` — each a versioned set of default predicates per target, domain predicates (`tests_pass`, `backtested_oos`, `sourced`, `feasible_bounded`), write-time refusals (`PASS_WITHOUT_INSTRUMENT_RUN`, `EDGE_WITHOUT_OOS_COSTS`, `BACKTEST_WITHOUT_COSTS`, `CLAIM_WITHOUT_SOURCE`, `OPTIMAL_WITHOUT_BOUND`, `OBJECTIVE_WITHOUT_FEASIBILITY`) and completion criteria. Pinned on the investigation (`fields.profile`); `Graph.completion(inv)`, `GET /api/graph/completion|profiles`, MCP `completion`; the briefing names the profile and its criteria. A cited source counts as a claim's evidence.
|
|
10
|
+
- The order text carries the target's own content (a claim's statement, scope, measurements and the values of the results it rests on; a result's values; a question's text; an experiment's protocol), and names a replication of the author's run when one exists — the harmony confirmatory showed 11–16 `show` calls a run reading back what the reply had said.
|
|
11
|
+
- `cancel_work` releases the target's lease when the order was still open, so the target can be issued to someone else at once (a resumed hypswarm run with a replaced seat found it blocked).
|
|
12
|
+
- `stats.two_proportions` / `detectable` no longer divide by zero on an empty arm (undefined, p = 1, the whole range). `tests/test_stats_values.py` pins Wilson, rule-of-three, Newcombe and the z-test to reference values.
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
- **Honest negations pass.** A word counts only when its sentence asserts it (`language.asserted`): "A is not
|
|
16
|
+
significantly better", "no evidence that it ever fails", "we cannot conclude that…" are accepted; the unnegated
|
|
17
|
+
overclaim is refused as before. New code `SIGNIFICANCE_CONTRADICTED`: "not significant" when the bound counts
|
|
18
|
+
are (p < 0.05). Found by the harmony pilot, where the checker refused the honest sentence its own message asked
|
|
19
|
+
for.
|
|
20
|
+
- **The record binds the numbers it already holds.** A claim's loose numbers are bound to the author's own results
|
|
21
|
+
in the investigation (linked results first) before any refusal; a `derived_from` link is added to the result
|
|
22
|
+
they came from, and the reply says what was bound. Small integers (≤ 12) bind only to counts. In the pilot,
|
|
23
|
+
61 of 106 refused numbers were already in a result.
|
|
24
|
+
- **The done signal.** After every write by an assignee, the reply carries its open orders with each predicate
|
|
25
|
+
MET / NOT MET, and "return_work now" when all are (`coord.done_lines`; `orders` on create / revise / review
|
|
26
|
+
results; shown by the MCP tools). In the pilot 8 of 9 sub-agents worked to their turn cap past done.
|
|
27
|
+
- **Orders meetable by construction.** `done_when` accepts `predicate` / `name` / a bare string as spellings of
|
|
28
|
+
`p`, and a bad predicate's refusal shows the valid form. Each predicate in an order carries how to meet it with
|
|
29
|
+
the assignee's tools. `result_exists` and `run_registered` count what the assignee wrote while holding the
|
|
30
|
+
order, so no link vocabulary stands between an honest result and a met predicate. A third rework of an order
|
|
31
|
+
whose predicate hasn't moved is refused, with the choices spelled out.
|
|
32
|
+
- **The question board.** The briefing's unit is the question: settled (a checked claim answers it), contested,
|
|
33
|
+
answered (unchecked), in progress, open; the frontier is driven by it, and one review settles a question
|
|
34
|
+
(`question_board`). `settle` / MCP `settle_work` accepts every returned order whose predicates are all met.
|
|
35
|
+
Standing in the briefing is now exceptions only (contested, at risk, fallen).
|
|
36
|
+
- **Absolutes over an enumerated set pass.** "A trails B in every subset: math −2.6, code −2.2, reading −0.4",
|
|
37
|
+
"all three subsets", "over all 818 items" quantify over what the sentence lists; they are not
|
|
38
|
+
generalisations and are no longer refused. "below zero" is a number, not "never".
|
|
39
|
+
- **Replay.** Refusals are logged with the whole claim body and its support, and `hypgraph replay-refusals`
|
|
40
|
+
(`Graph.replay_refusals`) runs every logged refusal through the checker as it is now: same, changed, passes.
|
|
41
|
+
A rule change is judged on the corpus of what agents wrote before it ships.
|
|
42
|
+
- **A result written twice is written once.** The same author re-registering the same numbers (the multiset of
|
|
43
|
+
a result's values, rounded, keys ignored) is refused with `RESULT_RESTATES`; a declared rerun (a run that
|
|
44
|
+
`replicates`) is kept and marked; another author's restatement is kept and its standing says `RESTATES RSn`.
|
|
45
|
+
Restated results are collapsed in work-order text.
|
|
46
|
+
|
|
47
|
+
- **Coordinating a team through the record** (`coord.py`). All of it is deterministic and makes no model calls.
|
|
48
|
+
- `briefing(inv)`: the orchestrator's context compiled from the record (mission, rules, roster, standing,
|
|
49
|
+
frontier, orders in flight and returned with their predicates checked, budget, what changed since the last
|
|
50
|
+
one), with a hash.
|
|
51
|
+
- Work orders are `task` nodes: `issue_work` (the target is leased to the assignee; a duplicate is refused),
|
|
52
|
+
`order_text`, `return_work`, `check_work` (each predicate MET / NOT MET with the nodes that satisfy it),
|
|
53
|
+
`accept_work` (a decision based on the evidence, only when every predicate is met), `rework`, `cancel_work`
|
|
54
|
+
and `cancel_moot`.
|
|
55
|
+
- An order's status is derived, never set: open, returned, overdue, accepted, reworked, cancelled or moot.
|
|
56
|
+
Only evidence written after the order was issued counts toward it.
|
|
57
|
+
- **Schema.**
|
|
58
|
+
- `task` gains optional `objective`, `assignee`, `role`, `prediction`, `method`, `done_when`, `budget` and
|
|
59
|
+
`note`; `kanban_id` is no longer required.
|
|
60
|
+
- New relations `rests_on` (an order's pinned premises) and `settles` (a decision accepting an order).
|
|
61
|
+
- `works_on` and `rests_on` join the at-risk relations, so the blast radius of a withdrawal now lists the work
|
|
62
|
+
orders it makes moot.
|
|
63
|
+
- **Surfaces.** MCP tools `briefing`, `issue_work`, `my_work`, `check_work`, `return_work`, `accept_work`,
|
|
64
|
+
`rework`, `cancel_work` and `cancel_moot`; CLI `hypgraph brief` and `hypgraph orders`.
|
|
65
|
+
|
|
66
|
+
## 0.3.0 — 2026-10-24
|
|
67
|
+
|
|
68
|
+
- **The refusal log.** Every refused claim is logged: author, statement, codes, messages. A later accepted claim by
|
|
69
|
+
the same author that says the same thing (same node, or ≥ 30% shared content words within 24 hours) marks the
|
|
70
|
+
refusal fixed. Append-only, with its own hash chain (`verify_refusals()`); the record's chain is untouched.
|
|
71
|
+
- API: `refusals()`, `refusal_report()`.
|
|
72
|
+
- CLI: `hypgraph refusals [--author …]`. MCP: `refusal_log`. HTTP: `GET /api/graph/refusals`.
|
|
73
|
+
- Atlas: an "Overclaims caught" card in the Work view.
|
|
74
|
+
- **`hypgraph check report.md`** lints a write-up against the record (`Graph.check_text`; MCP `check_report`; HTTP
|
|
75
|
+
`POST /api/graph/check`). Exits 1 on errors (`--strict`: warnings too).
|
|
76
|
+
- Errors: citations of withdrawn nodes, settled language about unchecked, contested or at-risk work, unknown
|
|
77
|
+
codes, and unbacked never / no effect / significantly.
|
|
78
|
+
- Warnings: numbers no result contains or implies, omitted disputes, superseded citations, uncited causal
|
|
79
|
+
language.
|
|
80
|
+
- Calibrated on 24 real PegasusDMZ write-ups against its live record. That fixed negations ("cannot be proven"),
|
|
81
|
+
quoted passages under correction, instructions ("never use the eval set"), p-values given in the sentence, and
|
|
82
|
+
"results in" as a noun phrase.
|
|
83
|
+
- An absolute whose statement gives its n ("no leaks in 50 prompts", "nothing in 50 of 50") is scoped to what was
|
|
84
|
+
seen and accepted; its standing still carries the bound. Without n it is refused, as before.
|
|
85
|
+
- Spec draft 3 (§8 refusal log, §9 checking a write-up).
|
|
86
|
+
|
|
87
|
+
## 0.2.0 — 2026-10-24
|
|
88
|
+
|
|
89
|
+
**Refusal, remastered.** The claim checks now do the arithmetic the writer skipped, and every refusal says what the
|
|
90
|
+
count actually supports and offers the honest sentence.
|
|
91
|
+
|
|
92
|
+
- **The arithmetic of never.** "Never" / "always" / "eliminates" / "100%" need a count of what they're about with
|
|
93
|
+
k = 0 or n (`ABSOLUTE_WITHOUT_COUNT`, `ABSOLUTE_UNRELATED_COUNT`). That count needs a 95% bound under 5%
|
|
94
|
+
(`ABSOLUTE_UNDERPOWERED`: "0 of 3 only rules out more than 63%"), and the statement has to show its denominator
|
|
95
|
+
(`ABSOLUTE_HIDES_DENOMINATOR`). The bounds are exact at k = 0 (1 − 0.05^(1/n), the rule of three) and Wilson
|
|
96
|
+
otherwise.
|
|
97
|
+
- **Exposure.** A claim can say how many uses, users or units it applies to (`exposure`, `exposure_unit`). Refusals
|
|
98
|
+
and the claim's standing then state how many failures the bound leaves unruled out: "up to 58,155 of 1,000,000".
|
|
99
|
+
- **New rules:** `COMPARATIVE_WITHOUT_COMPARISON`, `SIGNIFICANCE_WITHOUT_TEST`, `SIGNIFICANCE_NOT_SHOWN` (the
|
|
100
|
+
record runs a two-proportion test on bound counts itself), `CAUSAL_WITHOUT_INTERVENTION`, and
|
|
101
|
+
`EXCLUSION_WITHOUT_POWER` for "no effect" however it is filed, with the smallest effect the sample could have
|
|
102
|
+
detected.
|
|
103
|
+
- **True numbers pass.** Differences, ratios, percentages and relative changes computed from bound measurements are
|
|
104
|
+
accepted ("2.8 points", "81.2% vs 78.4%", "+3.6%"). Statistical quantities must be written to one decimal place, so
|
|
105
|
+
"5 points" can't borrow an interval's end.
|
|
106
|
+
- **Refusals agents can act on:** a stable code on every line, and `GraphError.problems` with `code`, `message`,
|
|
107
|
+
`fix` and `words`.
|
|
108
|
+
- **Blast radius.** `withdraw()`, and a review that makes a node fall, return `blast_radius`: what rests on it, by
|
|
109
|
+
type, with claims and decisions named (and spend, if metered). The CLI and MCP print it.
|
|
110
|
+
- **`hypgraph bound K N --exposure X`** and the MCP tool `bound`: what a count supports, before anyone writes "never".
|
|
111
|
+
- A claim's standing carries `bounds`, and `test` for "significantly" claims. Spec draft 2 (§7 rewritten).
|
|
112
|
+
- Credits: made by Nicolas Houghtaling at VoodooMods LLC (README, NOTICE, CITATION.cff, package metadata, site).
|
|
113
|
+
|
|
114
|
+
## 0.1.0 — 2026-10-24
|
|
115
|
+
|
|
116
|
+
First release on PyPI.
|
|
117
|
+
|
|
118
|
+
- **Writes cost what they touch.** A write no longer copies the whole in-memory snapshot. Tables are shallow
|
|
119
|
+
copies, and a node's list is copied only when the write appends to it. Derived standing is kept for every node the
|
|
120
|
+
write can't affect (`derive.affected_by`), so the first full read after a write no longer re-derives the graph.
|
|
121
|
+
At 10,000 nodes: building the graph took 77 s instead of 133 s, a full read after a write 0.02 s instead of
|
|
122
|
+
0.17 s, and a write at 5,000 nodes 5.8 ms instead of 12 ms. A randomized suite checks the carried standing
|
|
123
|
+
against a full rebuild after every kind of write.
|
|
124
|
+
- New indexes for display codes and the rate limit (`nodes(inv, type)`, `nodes(inv, code)`, `events(actor, kind,
|
|
125
|
+
at)`). Created on open; existing records just gain them.
|
|
126
|
+
- Positioning: the evidence layer for AI research agents. README and site lead with the MCP server and the Agent
|
|
127
|
+
Skill; a new engineering guide (`/engineers/`) replaces the human guide; the eval-report example replaces the
|
|
128
|
+
classroom one.
|
|
129
|
+
|
|
130
|
+
### Extracted from PegasusDMZ
|
|
131
|
+
|
|
132
|
+
Extracted from the PegasusDMZ research graph and verified against it: on a copy of Pegasus's live
|
|
133
|
+
graph (1,357 events, 790 nodes in 5 investigations), the library reproduces the same chain head, every node's
|
|
134
|
+
standing, the work queues and the next-experiment rankings.
|
|
135
|
+
|
|
136
|
+
- **Engine** (stdlib only): typed nodes and edges, append-only SQLite with a SHA-256 event chain and `verify()`,
|
|
137
|
+
standing derived on read, claim checks on write, review pinned to versions, independence and evidence profile,
|
|
138
|
+
leases, next experiments, work map, digest, report.
|
|
139
|
+
- **Policy**: reviewers, instrument, operator, importer and system are the host's to set (they were hardcoded in
|
|
140
|
+
Pegasus). Optional `spend` hook for cost. Injectable `clock`; only the importer may set a write's time.
|
|
141
|
+
- **Bundles** (`hypgraph/1-bundle`): every event and body as the exact hashed string, so they can be verified in any
|
|
142
|
+
language. Scoped exports redact events outside the investigation and say so. A complete bundle replays row for row.
|
|
143
|
+
- **CLI**: `init`, `add`, `link`, `review`, `revise`, `withdraw`, `ls`, `show --why/--impact/--history`, `next`, `work`,
|
|
144
|
+
`report`, `export`, `import`, `verify`, `demo`, `schema`, `serve`, `mcp`, `skill`.
|
|
145
|
+
- **MCP server** (FastMCP, `hypgraph[mcp]`): 17 tools, 4 resources, a `method` prompt. Writes as one fixed author.
|
|
146
|
+
- **Agent skill**: `SKILL.md` ships in the package; `hypgraph skill --install`.
|
|
147
|
+
- **Atlas**: the framework-free explorer, with an HTTP source and a bundle source (it verifies the chain in the
|
|
148
|
+
browser). Cytoscape is vendored.
|
|
149
|
+
- **Demo**: Broad Street, 1854 — a teaching reconstruction with three refusals built into the story.
|
|
150
|
+
- Fixed while extracting it: a report listed stale-reviewed claims under the wrong key; claim measurements now accept
|
|
151
|
+
result codes (RS3) and store ids.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: hypgraph
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.4.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/
|
|
@@ -132,6 +132,25 @@ Nothing in the record is ever *set* as known. How well each claim is known is **
|
|
|
132
132
|
Every write is an event in a **SHA-256 hash chain**. A record can be handed to a reviewer, a regulator or another
|
|
133
133
|
team, and they can verify it without trusting you.
|
|
134
134
|
|
|
135
|
+
## One record, five disciplines
|
|
136
|
+
|
|
137
|
+
The rules above are the scientific case written as code. A **profile** says what a domain means by evidence,
|
|
138
|
+
acceptance and done — and the record enforces it, so it never depends on a prompt being followed. Pin one on the
|
|
139
|
+
investigation (`"profile": "software@1"`); without one, the record behaves exactly as before.
|
|
140
|
+
|
|
141
|
+
| profile | an order is done when… | the record refuses | the investigation is done when |
|
|
142
|
+
|---|---|---|---|
|
|
143
|
+
| `scientific@1` | a checked claim answers the question | numbers no result accounts for, "never" without the count, "significant" without the test | every question is settled |
|
|
144
|
+
| `software@1` | **the instrument ran the tests** (`tests_pass`) and a claim states it | *"it passes"* without an instrument-recorded run | every requirement's claim rests on a passing run |
|
|
145
|
+
| `trading@1` | a backtest is **out of sample and after costs** (`backtested_oos`) | a backtest without the costs it charged; *"edge"* without both | a sized paper position is a decision based on the claim |
|
|
146
|
+
| `knowledge@1` | the claim **cites a source node** the record holds (`sourced`) | a factual claim with no source | every claim cites a source |
|
|
147
|
+
| `optimization@1` | a result carries **objective, feasible, and a bound or gap** (`feasible_bounded`) | an objective without feasibility; *"optimal"* without a bound | a feasible incumbent with a bound exists |
|
|
148
|
+
|
|
149
|
+
Profiles are versioned and frozen: a record written under `trading@1` means the same thing in a year, and a changed
|
|
150
|
+
rule is `@2`. `completion(inv)` reports each criterion; the briefing names the profile and where it stands;
|
|
151
|
+
`hypgraph serve` exposes `/api/graph/completion` and `/api/graph/profiles`. Adding a discipline is one `Profile` —
|
|
152
|
+
vocabulary, default predicates, domain predicates, refusals, completion — and the rest of the record is unchanged.
|
|
153
|
+
|
|
135
154
|
## Connect your agent
|
|
136
155
|
|
|
137
156
|
```bash
|
|
@@ -100,6 +100,25 @@ Nothing in the record is ever *set* as known. How well each claim is known is **
|
|
|
100
100
|
Every write is an event in a **SHA-256 hash chain**. A record can be handed to a reviewer, a regulator or another
|
|
101
101
|
team, and they can verify it without trusting you.
|
|
102
102
|
|
|
103
|
+
## One record, five disciplines
|
|
104
|
+
|
|
105
|
+
The rules above are the scientific case written as code. A **profile** says what a domain means by evidence,
|
|
106
|
+
acceptance and done — and the record enforces it, so it never depends on a prompt being followed. Pin one on the
|
|
107
|
+
investigation (`"profile": "software@1"`); without one, the record behaves exactly as before.
|
|
108
|
+
|
|
109
|
+
| profile | an order is done when… | the record refuses | the investigation is done when |
|
|
110
|
+
|---|---|---|---|
|
|
111
|
+
| `scientific@1` | a checked claim answers the question | numbers no result accounts for, "never" without the count, "significant" without the test | every question is settled |
|
|
112
|
+
| `software@1` | **the instrument ran the tests** (`tests_pass`) and a claim states it | *"it passes"* without an instrument-recorded run | every requirement's claim rests on a passing run |
|
|
113
|
+
| `trading@1` | a backtest is **out of sample and after costs** (`backtested_oos`) | a backtest without the costs it charged; *"edge"* without both | a sized paper position is a decision based on the claim |
|
|
114
|
+
| `knowledge@1` | the claim **cites a source node** the record holds (`sourced`) | a factual claim with no source | every claim cites a source |
|
|
115
|
+
| `optimization@1` | a result carries **objective, feasible, and a bound or gap** (`feasible_bounded`) | an objective without feasibility; *"optimal"* without a bound | a feasible incumbent with a bound exists |
|
|
116
|
+
|
|
117
|
+
Profiles are versioned and frozen: a record written under `trading@1` means the same thing in a year, and a changed
|
|
118
|
+
rule is `@2`. `completion(inv)` reports each criterion; the briefing names the profile and where it stands;
|
|
119
|
+
`hypgraph serve` exposes `/api/graph/completion` and `/api/graph/profiles`. Adding a discipline is one `Profile` —
|
|
120
|
+
vocabulary, default predicates, domain predicates, refusals, completion — and the rest of the record is unchanged.
|
|
121
|
+
|
|
103
122
|
## Connect your agent
|
|
104
123
|
|
|
105
124
|
```bash
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# ADR-001 — Writes over HTTP are bound to tokens, and hosts can reserve their own names
|
|
2
|
+
|
|
3
|
+
**Date** 2026-10-25 · **Status** accepted · **Where** `server.py`, `policy.py`, `cli.py`
|
|
4
|
+
|
|
5
|
+
## Context
|
|
6
|
+
|
|
7
|
+
`hypgraph serve --writable` took `author` from the request body and authenticated nobody. The MCP server fixes
|
|
8
|
+
its author at start (`--as`), so an agent on MCP can't impersonate; over HTTP anyone who could reach the port
|
|
9
|
+
could write as any non-reserved author. For hypswarm that included **`harness`** — the orchestrator that owns
|
|
10
|
+
every order, may cancel and rework them, and settles accepted work — because `Policy.reserved` knew only the
|
|
11
|
+
engine's four names (instrument, operator, importer, system).
|
|
12
|
+
|
|
13
|
+
The principle at stake: the record is the authority, and authority starts with knowing who is writing.
|
|
14
|
+
|
|
15
|
+
## Decision
|
|
16
|
+
|
|
17
|
+
1. **`Policy.extra_reserved`**: a host may add names to the reserved set (hypswarm adds `harness`). Everything
|
|
18
|
+
that consults `policy.reserved` — the HTTP write path, the MCP `--as` check, the rate limiter, the fixed-record
|
|
19
|
+
guard — sees them. Default empty: existing policies are unchanged.
|
|
20
|
+
2. **Bearer tokens on the write route.** `serve --token SECRET=a,b` binds a token to authors; `SECRET=*` (or a
|
|
21
|
+
bare secret) means any *non-reserved* author; `--token-file` and `$HYPGRAPH_TOKEN` are the same thing in other
|
|
22
|
+
places. With any token configured, a write without a known token is **401** (`WWW-Authenticate: Bearer`), a
|
|
23
|
+
write as an author the token isn't bound to is **403**, and a reserved name is accepted only from a token that
|
|
24
|
+
names it explicitly. Secrets are compared with `hmac.compare_digest`; a secret under 16 characters is refused
|
|
25
|
+
at parse time. Reads stay open (the Atlas needs them; a server exposed beyond localhost still belongs behind a
|
|
26
|
+
reverse proxy for reads).
|
|
27
|
+
3. **No tokens → exactly today's behaviour**: reserved names refused, everyone else taken at their word.
|
|
28
|
+
|
|
29
|
+
## Alternatives considered
|
|
30
|
+
|
|
31
|
+
- Make `harness` one of the engine's fixed roles: it is a hypswarm concept; the engine shouldn't know it.
|
|
32
|
+
`extra_reserved` lets any host reserve what it needs.
|
|
33
|
+
- Per-request signatures (HMAC over the body): stronger against replay, but every client would need the
|
|
34
|
+
signing code, and the threat here is identity, not tampering on a localhost link. Tokens over TLS (or a
|
|
35
|
+
reverse proxy) cover the exposure the server is documented for.
|
|
36
|
+
- Authenticating reads too: left to the proxy layer for now; a `--private` flag is an easy follow-up.
|
|
37
|
+
|
|
38
|
+
## Consequences
|
|
39
|
+
|
|
40
|
+
- hypswarm's `HttpRecord(token=…)` sends the bearer; its one client writes as the harness and every seat, so its
|
|
41
|
+
token is bound to all of them (`SECRET=harness,analyst,…`). An outside seat (a person on MCP, another agent)
|
|
42
|
+
gets a token bound to its own name and cannot issue, cancel or settle orders.
|
|
43
|
+
- `AuthError` (hypswarm) distinguishes a refused identity from a refused write.
|
|
44
|
+
- Tests: `tests/test_server_auth.py` (401 / 403 / reserved / case folding / no-token path unchanged / parsing);
|
|
45
|
+
hypswarm `tests/test_auth.py` (a swarm runs on its token; outsider can't be the harness).
|
|
46
|
+
- The hypgraph suite grew from 91 to 108 tests; wall time 11.4 s → 14.6 s (the new tests start real servers).
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# ADR-002 — Governance profiles: what a domain means by evidence, acceptance and done, pinned and versioned
|
|
2
|
+
|
|
3
|
+
**Date** 2026-10-25 · **Status** accepted · **Where** `profiles.py`, hooks in `schema`, `coord`, `graph`, `server`, `mcp`
|
|
4
|
+
|
|
5
|
+
## Context
|
|
6
|
+
|
|
7
|
+
The engine's rules — claims bound to measured results, k/n for absolutes, a reviewer's verdict to settle a question
|
|
8
|
+
— are the scientific case written as code. A software team needs "it passes" to mean *the instrument ran the
|
|
9
|
+
tests*; a trading desk needs "edge" to mean *out of sample, after costs*; a research assistant needs every factual
|
|
10
|
+
claim to cite what was read; an optimisation run needs "optimal" to come with a bound. Each is a different answer to
|
|
11
|
+
the same three questions: what counts as evidence for a claim, when is an order's work accepted, and when is the
|
|
12
|
+
investigation done. Those answers belong in the record, not in prompts (the harmony study measured that rules in
|
|
13
|
+
prompts are followed inconsistently; rules the record enforces are followed always).
|
|
14
|
+
|
|
15
|
+
## Decision
|
|
16
|
+
|
|
17
|
+
A **profile** is a named, versioned, frozen set of: vocabulary (shown, not enforced); default predicates per target
|
|
18
|
+
type; domain predicates the record can check (`tests_pass`, `backtested_oos`, `sourced`, `feasible_bounded`);
|
|
19
|
+
write-time validators on claims and results (`PASS_WITHOUT_INSTRUMENT_RUN`, `EDGE_WITHOUT_OOS_COSTS`,
|
|
20
|
+
`BACKTEST_WITHOUT_COSTS`, `CLAIM_WITHOUT_SOURCE`, `OPTIMAL_WITHOUT_BOUND`, `OBJECTIVE_WITHOUT_FEASIBILITY`);
|
|
21
|
+
completion criteria derived from the record (`questions_settled`, `requirements_verified`, `position_recorded`,
|
|
22
|
+
`all_sourced`, `incumbent_feasible`); and suggested seat templates. Five ship: `scientific@1` (the default — an
|
|
23
|
+
investigation with no profile behaves exactly as before), `software@1`, `trading@1`, `knowledge@1`,
|
|
24
|
+
`optimization@1`.
|
|
25
|
+
|
|
26
|
+
An investigation **pins** its profile (`fields.profile = "software@1"`; an unknown id is refused at creation).
|
|
27
|
+
Rules never change under a version — a changed rule is `@2` — so a record written under `trading@1` means the same
|
|
28
|
+
thing in a year. `issue_work` takes the profile's default predicates; `check_work` evaluates the domain predicates
|
|
29
|
+
with the same lease-window rule as the built-ins; `create` adds the profile's refusals to the claim checks and
|
|
30
|
+
refuses results the profile rejects (curators excepted, as for claim checks); `completion(inv)` reports the
|
|
31
|
+
criteria; the briefing's MISSION names the profile and the criteria's state; the server has `/completion` and
|
|
32
|
+
`/profiles`; the MCP server has `completion`. A cited source now counts as a claim's evidence (knowledge profile).
|
|
33
|
+
|
|
34
|
+
## Alternatives considered
|
|
35
|
+
|
|
36
|
+
- Per-host subclasses of `Graph`: rules would live in code outside the record and couldn't be pinned or read back.
|
|
37
|
+
- Prompts per domain only: the measured failure mode (see context).
|
|
38
|
+
- One mutable profile per name: a record written under last month's rules would silently mean something else.
|
|
39
|
+
|
|
40
|
+
## Consequences
|
|
41
|
+
|
|
42
|
+
- Tests (`tests/test_profiles.py`): unknown profile refused; no profile = today's predicates and criteria; software —
|
|
43
|
+
the tester's own "positive" result does not meet `tests_pass`, the instrument's replicating lab run does, "passes"
|
|
44
|
+
is refused without it, completion needs instrument evidence; trading — a costless backtest result is refused, an
|
|
45
|
+
in-sample edge is refused, out-of-sample + fees + a reviewed claim + a sized decision completes; optimisation —
|
|
46
|
+
objective without feasibility refused, "optimal" without a bound refused; knowledge — unsourced claim refused,
|
|
47
|
+
cited claim accepted and completes; server routes. 119 tests pass.
|
|
48
|
+
- hypswarm binds rosters and toolkits to these ids (hypswarm ADR-008).
|
|
49
|
+
- Open: a `@2` of any profile needs a migration note in CHANGELOG; validators use the same clause-level negation
|
|
50
|
+
as the claim checks (`language.asserted`), so "no edge was found" is not refused.
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
# HypGraph, read fresh: what it is, what to fix, what it could become
|
|
2
|
+
|
|
3
|
+
*An assessment written on 2026-10-24 after reading the engine, the checks, the coordination layer, the agents'
|
|
4
|
+
instructions, and what the agents actually did in the two pilots. Every number here comes from those pilot
|
|
5
|
+
records; each is marked with where it came from.*
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## 1. What HypGraph is
|
|
10
|
+
|
|
11
|
+
HypGraph is a record that agents write into and cannot flatter. Three things make it different from a database
|
|
12
|
+
with a schema, and they are the three things to protect:
|
|
13
|
+
|
|
14
|
+
1. **Standing is derived, never set.** Nobody, human or agent, can mark a claim "established". Review state,
|
|
15
|
+
independence of support, fallen premises and evidence strength are recomputed from the record every time it is
|
|
16
|
+
read. This is the part most people will miss and the part that matters most: it means the record can be
|
|
17
|
+
trusted by someone who doesn't trust its authors.
|
|
18
|
+
2. **Refusal does the arithmetic.** A claim that says "never" from 0 of 50 is refused with the bound (5.8 %), the
|
|
19
|
+
trials needed (2,995), the exposure consequence (58,155 of a million) and the honest sentence. The agent can
|
|
20
|
+
repair in one step. Nothing else I know of does this at write time.
|
|
21
|
+
3. **Every write is hash-chained**, so the record is checkable without trusting the host.
|
|
22
|
+
|
|
23
|
+
The coordination layer added this week makes a fourth claim: that the record can compile each agent's context and
|
|
24
|
+
accept each agent's work, so a team coordinates through the record instead of through a transcript.
|
|
25
|
+
|
|
26
|
+
## 2. What is good
|
|
27
|
+
|
|
28
|
+
- The derived-standing engine is sound. On Pegasus's live record (790 nodes) it reproduces the old engine's
|
|
29
|
+
standing exactly, and the incremental snapshot keeps writes at milliseconds.
|
|
30
|
+
- The refusal rules are the right rules. Each exists because an agent made that mistake, and the set
|
|
31
|
+
(absolute / comparative / significance / causal / exclusion / unbound number) covers the overclaims that appear
|
|
32
|
+
in practice.
|
|
33
|
+
- The final reports produced under the record condition are the best reports I have seen an agent team write.
|
|
34
|
+
F1-902-C's report: every number traceable to a code, the trap named and checked, a caveat that no individual
|
|
35
|
+
subset clears 5 %, and the honest conclusion that A is *not* shown better. That is the product.
|
|
36
|
+
- The record condition was the only one that never fell for a trap across pilot 2 (0 of 4; chat 2, Pegasus-today
|
|
37
|
+
1, record-without-gates 1).
|
|
38
|
+
- The preregistration discipline is real: hashes, a lock, logged deviations, pilot data excluded. Keep it.
|
|
39
|
+
|
|
40
|
+
## 3. What to fix before showing the world
|
|
41
|
+
|
|
42
|
+
Ranked by how much they matter, with the evidence.
|
|
43
|
+
|
|
44
|
+
### 3.1 The checker refuses honest negations (a bug in the flagship feature)
|
|
45
|
+
|
|
46
|
+
`checks.py` listens for "significantly" and runs the test on the bound counts, but it does not read the
|
|
47
|
+
sentence. So:
|
|
48
|
+
|
|
49
|
+
```
|
|
50
|
+
REFUSED: "A is not significantly more accurate than B (812 of 1000 vs 800 of 1000)." -> SIGNIFICANCE_NOT_SHOWN
|
|
51
|
+
REFUSED: "A is significantly more accurate than B (812 of 1000 vs 800 of 1000)." -> SIGNIFICANCE_NOT_SHOWN
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
The honest statement, the one the refusal message itself asks for ("say the difference and that it isn't
|
|
55
|
+
significant"), is refused with the same code as the overclaim. In pilot 2, F1-903-C's analyst wrote "Trap check:
|
|
56
|
+
the wording 'whether A is really better than B' is a false premise" and was refused three times. The report
|
|
57
|
+
linter (`report_check._asserted`) already handles negation at sentence level; the claim checker must do the same
|
|
58
|
+
for every word list, not only significance ("not caused by", "no evidence that it never…").
|
|
59
|
+
|
|
60
|
+
### 3.2 Refuse less, repair more: bind the numbers the record already holds
|
|
61
|
+
|
|
62
|
+
In pilot 2's record runs, **106 numbers were refused as unbound; 61 of them already sat in a result value in the
|
|
63
|
+
same record**, and most of the rest were rates of bound counts (0.828010 is 337 of 407). The agent had done the
|
|
64
|
+
work and registered it; it had not filled in the `measurements` list. The record can do that itself: when a
|
|
65
|
+
statement's numbers all resolve against the author's own results in this investigation, bind them and accept,
|
|
66
|
+
noting the bindings it added. Refuse only what it cannot find. This turns the biggest friction (63 of 91
|
|
67
|
+
refusals in pilot 1) into a non-event, and it is deterministic.
|
|
68
|
+
|
|
69
|
+
### 3.3 Tell every agent when it is done
|
|
70
|
+
|
|
71
|
+
In F1-902-C, **8 of 9 sub-agent units ran to the 14-turn cap** and were returned on their behalf; 26 claims were
|
|
72
|
+
accepted for a 4-question task. Nobody told the analyst that `claim_made` was already MET after its third write.
|
|
73
|
+
`check_work` exists but only the lead calls it. After every write by an assignee, the record should evaluate the
|
|
74
|
+
order's predicates and say so in the reply: *"T3: claim_made MET — you can return now."* Done-ness is a derived
|
|
75
|
+
property like everything else; surface it where the work happens. This is the cheapest cost fix available: most of
|
|
76
|
+
C's 4.7× cost is sub-agents grinding past done.
|
|
77
|
+
|
|
78
|
+
### 3.4 The briefing is a claim dump; it should be a question board
|
|
79
|
+
|
|
80
|
+
F1-902-C's briefing was 5,666 characters, of which STANDING was 3,313: twenty-six claims in a flat list, most
|
|
81
|
+
"unchecked · no live support", eight of them restating the same subset numbers. And FRONTIER listed "CLn needs a
|
|
82
|
+
review" for every unchecked claim, so the lead issued six review orders in ten. The orchestrator's unit of work is
|
|
83
|
+
the **question**, not the claim. The briefing should show, per question: unanswered → answered (by CLx) →
|
|
84
|
+
checked (by whom) → settled; and a sufficiency rule: a question with one checked answering claim is done. The
|
|
85
|
+
lead should see the finish line.
|
|
86
|
+
|
|
87
|
+
### 3.5 Results duplicate inside the record
|
|
88
|
+
|
|
89
|
+
RS4, RS7, RS9, RS14, RS16 in F1-902-C all say "code +0.027, math 0.0, reading −0.0049". Artifacts are
|
|
90
|
+
content-addressed; results are not. A write that restates an existing result's values (same keys, same numbers
|
|
91
|
+
within rounding) should be refused with "this restates RS4: link to it", or linked automatically as a
|
|
92
|
+
`replicates` with `same_code`. The orchestrator's ALREADY KNOWN list showed the duplicates and the agents
|
|
93
|
+
re-derived anyway.
|
|
94
|
+
|
|
95
|
+
### 3.6 Automate the mechanical half of the lead
|
|
96
|
+
|
|
97
|
+
In F7-900-B the lead made 28 calls; in C runs the lead's `check_work` + `accept_work` calls were 13 of 28, 11 of
|
|
98
|
+
19, and so on. None of those needed a model: when every predicate is met, acceptance is a rule. Accept
|
|
99
|
+
automatically; bring the lead in only for NOT MET, disputes and the report.
|
|
100
|
+
|
|
101
|
+
### 3.7 Smaller frictions seen in the logs
|
|
102
|
+
|
|
103
|
+
- `title: say it in a full sentence` refuses a three-character title. Minimum lengths should apply to text
|
|
104
|
+
fields, not to names.
|
|
105
|
+
- `ABSOLUTE_WITHOUT_COUNT` fired on "every site_b_fixed value equals site_b / 10" when the author had 68 of 68
|
|
106
|
+
in the same sentence; the count check should accept "k of n" in the statement as a bound when the result
|
|
107
|
+
carries it.
|
|
108
|
+
- `register_run` requires `result_summary` to be a sentence of ten characters; fine, but the error says "needs
|
|
109
|
+
summary", not that.
|
|
110
|
+
|
|
111
|
+
### 3.8 Positioning
|
|
112
|
+
|
|
113
|
+
Keep the site honest to what is measured. "The evidence layer for AI research agents" is earned. "Harmony is
|
|
114
|
+
cheap" is not, yet: in pilot 2 the record condition cost 4.7× chat per run. Until the fixes above are measured,
|
|
115
|
+
the coordination layer stays unreleased and the site says nothing about cost.
|
|
116
|
+
|
|
117
|
+
## 4. Orchestrator guidance: the record is the orchestrator
|
|
118
|
+
|
|
119
|
+
The pilots show something the plan only half-said. Most of what an orchestrator does is mechanical:
|
|
120
|
+
|
|
121
|
+
| Orchestrator action | Needs judgement? | Pilot evidence |
|
|
122
|
+
|---|---|---|
|
|
123
|
+
| What is open | no: the question board | FRONTIER already computes it |
|
|
124
|
+
| Who is on what | no: leases | duplicates were refused correctly every time |
|
|
125
|
+
| Is an order done | no: predicates | `check_work` was 25–40 % of lead calls |
|
|
126
|
+
| Accept done work | no: a rule | `accept_work` was another 20–30 % |
|
|
127
|
+
| What to stop when a premise falls | no: blast radius | `cancel_moot` worked in F7 |
|
|
128
|
+
| Write the next order's objective | partly | the lead copied the question text |
|
|
129
|
+
| Decide between rival approaches, judge a NOT MET, write the report | **yes** | the lead's real work |
|
|
130
|
+
|
|
131
|
+
So the design: a deterministic scheduler issues default orders from the question board (one per open question,
|
|
132
|
+
to the role that fits, with the default predicates), accepts them when met, cancels them when moot, and escalates
|
|
133
|
+
to a judgement model only when something is NOT MET twice, when two claims conflict, or when the frontier is
|
|
134
|
+
empty and the report is due. The orchestrator model's context becomes a few hundred tokens of exceptions, not
|
|
135
|
+
5,000 tokens of standing. This is also the correct seed of hypswarm (§7).
|
|
136
|
+
|
|
137
|
+
What the briefing should carry, in order (stable first, for the cache):
|
|
138
|
+
1. mission and success test;
|
|
139
|
+
2. the question board, with each question's status and the claim that answers it;
|
|
140
|
+
3. exceptions: NOT MET returns, disputes, moot orders, budget;
|
|
141
|
+
4. since-last delta.
|
|
142
|
+
|
|
143
|
+
Everything else (the full standing list, the frontier of experiments) is available on request, not sent by default.
|
|
144
|
+
|
|
145
|
+
## 5. Keeping agents true, cheaply
|
|
146
|
+
|
|
147
|
+
The gates are free: they are deterministic and run at write time. **The cost is retries**, and retries have three
|
|
148
|
+
causes seen in the logs: the record refusing honest sentences (§3.1), refusing numbers it already holds (§3.2),
|
|
149
|
+
and nobody saying "done" (§3.3). Fix those and the cost of truth is close to zero; what remains is the cost of
|
|
150
|
+
the honest version itself, which is the point.
|
|
151
|
+
|
|
152
|
+
Two cheap things the refusal log makes possible that nobody else can offer:
|
|
153
|
+
|
|
154
|
+
- **An honesty metric per agent and per model, with no judge model.** Refusals per claim and the fix rate are
|
|
155
|
+
deterministic numbers the record already keeps. In pilot 2, DeepSeek-V4.1-Flash had 91 refusals and 79 fixes
|
|
156
|
+
(87 %) under pilot 1's rules. Run the same task suite through several models and the record gives a leaderboard
|
|
157
|
+
of *who overclaims and who repairs*, for cents, reproducibly. That is a benchmark the community does not have,
|
|
158
|
+
and HypGraph can publish it as a by-product of its own tests.
|
|
159
|
+
- **Exposure makes "never" cost what it costs.** The `exposure` field turns a bound into a consequence ("up to
|
|
160
|
+
58,155 of a million not ruled out"). Carry it one step further: a *decision* node that rests on a claim can
|
|
161
|
+
declare its stake (users, dollars, deployments), and the record reports, per premise, what is at risk if it
|
|
162
|
+
falls. Blast radius already reports dollars of work; it can report value at stake. "Never when it's 1 in
|
|
163
|
+
1,000" then has a price tag before anyone writes it.
|
|
164
|
+
|
|
165
|
+
## 6. The idea you are close to
|
|
166
|
+
|
|
167
|
+
**Stateless agents over a stateful record.** Pegasus's own ledger says where the money goes: 100 input tokens
|
|
168
|
+
per output token, 92 % of it re-read from cache, 34,865 tokens per call. The transcript is the state, and every
|
|
169
|
+
call re-reads it. HypGraph makes the state live in the record and compiles each call's context from it:
|
|
170
|
+
deterministic, small, cache-stable, and auditable (the briefing carries its own hash). Taken seriously:
|
|
171
|
+
|
|
172
|
+
- an agent call is `model(compile(record, role, order))`; transcripts are disposable;
|
|
173
|
+
- a team is a set of stateless workers pulling orders from the record's question board and writing results back;
|
|
174
|
+
- "coordination" is the record's scheduler, and the only model calls are work and judgement;
|
|
175
|
+
- the whole run is reproducible from the record and the seeds, and verifiable by hash.
|
|
176
|
+
|
|
177
|
+
That is not a feature of HypGraph; it is a different way to run agent teams, and HypGraph is the only piece that
|
|
178
|
+
makes it possible, because it is the only shared state that refuses overclaims and derives standing. The pilot's
|
|
179
|
+
reports are the first evidence it produces better output. Whether it produces it cheaper depends entirely on
|
|
180
|
+
§3.2–3.6, which is why they come first.
|
|
181
|
+
|
|
182
|
+
## 7. hypswarm
|
|
183
|
+
|
|
184
|
+
hypswarm is that scheduler, as a harness: workers, a question board, orders, predicates, cascade, budget, and a
|
|
185
|
+
judgement model at the exceptions. The study runner's condition C is already its embryo (`study_runner.run_C`
|
|
186
|
+
+ `_run_order`); hypswarm is that loop extracted, made parallel, and given a model-agnostic worker interface.
|
|
187
|
+
|
|
188
|
+
- **Research tasks** map directly: question → hypothesis → experiment → run → result → claim → review.
|
|
189
|
+
- **Building tasks** map with one change: the CI runner is the `instrument`. "The change makes the tests pass"
|
|
190
|
+
is a claim with a k/n measurement (tests passed of tests run) bound to a result the instrument filed, so it is
|
|
191
|
+
lab-recorded, not agent-reported. A requirement is a question; a design choice is a decision `based_on` the
|
|
192
|
+
claims that justify it, flagged REVISIT when one falls; a regression is a withdrawal with a blast radius. The
|
|
193
|
+
schema needs no new node types, only a `code` artifact convention (commit sha as the artifact hash).
|
|
194
|
+
- **Order of work:** (1) the §3 fixes in HypGraph, measured on the same two families; (2) extract the scheduler;
|
|
195
|
+
(3) a worker protocol (order text in, writes out, return note); (4) parallel workers with leases; (5) the
|
|
196
|
+
building adapter with CI as instrument. The harmony study's confirmatory run is then the first hypswarm result.
|
|
197
|
+
- **Positioning:** HypGraph is the record; hypswarm is the way to run a team on it. HypGraph stays independent
|
|
198
|
+
and usable alone (MCP, CLI, Python); hypswarm depends on HypGraph, never the reverse.
|
|
199
|
+
|
|
200
|
+
## 8. What not to do
|
|
201
|
+
|
|
202
|
+
- Don't publish the coordination layer, or say "cheaper", before §3 is fixed and the study rerun.
|
|
203
|
+
- Don't let the record become a chat: the 26-claim run shows what happens when every thought becomes a claim.
|
|
204
|
+
Sufficiency and deduplication are part of the design, not polish.
|
|
205
|
+
- Don't add a judge model to the gates. Everything that keeps agents true here is deterministic; that is what
|
|
206
|
+
makes it cheap and makes the honesty metric credible.
|
|
@@ -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.
|
|
19
|
+
__version__ = "0.4.0"
|
|
20
20
|
|
|
21
21
|
from .bundle import verify_bundle # noqa: E402
|
|
22
22
|
from .graph import Author, Graph, GraphError, file_sha256 # noqa: E402
|