hypgraph 0.7.28__tar.gz → 0.8.1__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.7.28 → hypgraph-0.8.1}/CHANGELOG.md +59 -0
- {hypgraph-0.7.28 → hypgraph-0.8.1}/PKG-INFO +1 -1
- {hypgraph-0.7.28 → hypgraph-0.8.1}/docs/PLAN.md +1 -1
- {hypgraph-0.7.28 → hypgraph-0.8.1}/docs/RELEASE-READINESS.md +36 -0
- {hypgraph-0.7.28 → hypgraph-0.8.1}/docs/spec.md +59 -3
- {hypgraph-0.7.28 → hypgraph-0.8.1}/src/hypgraph/__init__.py +1 -1
- hypgraph-0.8.1/src/hypgraph/assertions.py +440 -0
- {hypgraph-0.7.28 → hypgraph-0.8.1}/src/hypgraph/bundle.py +15 -3
- {hypgraph-0.7.28 → hypgraph-0.8.1}/src/hypgraph/checks.py +163 -9
- {hypgraph-0.7.28 → hypgraph-0.8.1}/src/hypgraph/derive.py +22 -1
- {hypgraph-0.7.28 → hypgraph-0.8.1}/src/hypgraph/graph.py +11 -2
- {hypgraph-0.7.28 → hypgraph-0.8.1}/src/hypgraph/mcp.py +7 -2
- {hypgraph-0.7.28 → hypgraph-0.8.1}/src/hypgraph/plan.py +1 -1
- {hypgraph-0.7.28 → hypgraph-0.8.1}/src/hypgraph/profiles.py +1 -0
- {hypgraph-0.7.28 → hypgraph-0.8.1}/src/hypgraph/refusals.py +20 -13
- {hypgraph-0.7.28 → hypgraph-0.8.1}/src/hypgraph/schema.py +2 -0
- {hypgraph-0.7.28 → hypgraph-0.8.1}/src/hypgraph/skill/SKILL.md +11 -0
- {hypgraph-0.7.28 → hypgraph-0.8.1}/src/hypgraph/stats.py +8 -0
- {hypgraph-0.7.28 → hypgraph-0.8.1}/src/hypgraph/ui/hypgraph.i18n.js +12 -0
- {hypgraph-0.7.28 → hypgraph-0.8.1}/src/hypgraph/ui/hypgraph.js +12 -2
- hypgraph-0.8.1/tests/test_assertions.py +509 -0
- hypgraph-0.8.1/tests/test_typed_audits.py +166 -0
- {hypgraph-0.7.28 → hypgraph-0.8.1}/.gitignore +0 -0
- {hypgraph-0.7.28 → hypgraph-0.8.1}/AGENTS.md +0 -0
- {hypgraph-0.7.28 → hypgraph-0.8.1}/CITATION.cff +0 -0
- {hypgraph-0.7.28 → hypgraph-0.8.1}/DISCLAIMER.md +0 -0
- {hypgraph-0.7.28 → hypgraph-0.8.1}/LICENSE +0 -0
- {hypgraph-0.7.28 → hypgraph-0.8.1}/NOTICE +0 -0
- {hypgraph-0.7.28 → hypgraph-0.8.1}/README.md +0 -0
- {hypgraph-0.7.28 → hypgraph-0.8.1}/docs/decisions/ADR-001-token-bound-authors.md +0 -0
- {hypgraph-0.7.28 → hypgraph-0.8.1}/docs/decisions/ADR-002-governance-profiles.md +0 -0
- {hypgraph-0.7.28 → hypgraph-0.8.1}/docs/profile-workflows-plan.md +0 -0
- {hypgraph-0.7.28 → hypgraph-0.8.1}/docs/review-2026-10-24.md +0 -0
- {hypgraph-0.7.28 → hypgraph-0.8.1}/docs/site-plan.md +0 -0
- {hypgraph-0.7.28 → hypgraph-0.8.1}/docs/ui-plan.md +0 -0
- {hypgraph-0.7.28 → hypgraph-0.8.1}/docs/verification.md +0 -0
- {hypgraph-0.7.28 → hypgraph-0.8.1}/docs/workflows/README.md +0 -0
- {hypgraph-0.7.28 → hypgraph-0.8.1}/docs/workflows/knowledge.md +0 -0
- {hypgraph-0.7.28 → hypgraph-0.8.1}/docs/workflows/optimization.md +0 -0
- {hypgraph-0.7.28 → hypgraph-0.8.1}/docs/workflows/scientific.md +0 -0
- {hypgraph-0.7.28 → hypgraph-0.8.1}/docs/workflows/software.md +0 -0
- {hypgraph-0.7.28 → hypgraph-0.8.1}/docs/workflows/trading.md +0 -0
- {hypgraph-0.7.28 → hypgraph-0.8.1}/examples/frameworks/README.md +0 -0
- {hypgraph-0.7.28 → hypgraph-0.8.1}/pyproject.toml +0 -0
- {hypgraph-0.7.28 → hypgraph-0.8.1}/src/hypgraph/__main__.py +0 -0
- {hypgraph-0.7.28 → hypgraph-0.8.1}/src/hypgraph/blind.py +0 -0
- {hypgraph-0.7.28 → hypgraph-0.8.1}/src/hypgraph/cli.py +0 -0
- {hypgraph-0.7.28 → hypgraph-0.8.1}/src/hypgraph/coord.py +0 -0
- {hypgraph-0.7.28 → hypgraph-0.8.1}/src/hypgraph/demos/__init__.py +0 -0
- {hypgraph-0.7.28 → hypgraph-0.8.1}/src/hypgraph/demos/broad_street.py +0 -0
- {hypgraph-0.7.28 → hypgraph-0.8.1}/src/hypgraph/demos/linked.py +0 -0
- {hypgraph-0.7.28 → hypgraph-0.8.1}/src/hypgraph/language.py +0 -0
- {hypgraph-0.7.28 → hypgraph-0.8.1}/src/hypgraph/policy.py +0 -0
- {hypgraph-0.7.28 → hypgraph-0.8.1}/src/hypgraph/references.py +0 -0
- {hypgraph-0.7.28 → hypgraph-0.8.1}/src/hypgraph/report_check.py +0 -0
- {hypgraph-0.7.28 → hypgraph-0.8.1}/src/hypgraph/server.py +0 -0
- {hypgraph-0.7.28 → hypgraph-0.8.1}/src/hypgraph/store.py +0 -0
- {hypgraph-0.7.28 → hypgraph-0.8.1}/src/hypgraph/ui/__init__.py +0 -0
- {hypgraph-0.7.28 → hypgraph-0.8.1}/src/hypgraph/ui/atlas.css +0 -0
- {hypgraph-0.7.28 → hypgraph-0.8.1}/src/hypgraph/ui/atlas.js +0 -0
- {hypgraph-0.7.28 → hypgraph-0.8.1}/src/hypgraph/ui/hypgraph.css +0 -0
- {hypgraph-0.7.28 → hypgraph-0.8.1}/src/hypgraph/ui/hypgraph.svg +0 -0
- {hypgraph-0.7.28 → hypgraph-0.8.1}/src/hypgraph/ui/index.html +0 -0
- {hypgraph-0.7.28 → hypgraph-0.8.1}/src/hypgraph/ui/vendor/LICENSES.md +0 -0
- {hypgraph-0.7.28 → hypgraph-0.8.1}/src/hypgraph/ui/vendor/cose-base.js +0 -0
- {hypgraph-0.7.28 → hypgraph-0.8.1}/src/hypgraph/ui/vendor/cytoscape-fcose.js +0 -0
- {hypgraph-0.7.28 → hypgraph-0.8.1}/src/hypgraph/ui/vendor/cytoscape.min.js +0 -0
- {hypgraph-0.7.28 → hypgraph-0.8.1}/src/hypgraph/ui/vendor/layout-base.js +0 -0
- {hypgraph-0.7.28 → hypgraph-0.8.1}/src/hypgraph/workflow.py +0 -0
- {hypgraph-0.7.28 → hypgraph-0.8.1}/tests/test_accept_work_kind.py +0 -0
- {hypgraph-0.7.28 → hypgraph-0.8.1}/tests/test_anchoring.py +0 -0
- {hypgraph-0.7.28 → hypgraph-0.8.1}/tests/test_blind.py +0 -0
- {hypgraph-0.7.28 → hypgraph-0.8.1}/tests/test_blind_oracles.py +0 -0
- {hypgraph-0.7.28 → hypgraph-0.8.1}/tests/test_borrowed_words.py +0 -0
- {hypgraph-0.7.28 → hypgraph-0.8.1}/tests/test_bound_support.py +0 -0
- {hypgraph-0.7.28 → hypgraph-0.8.1}/tests/test_bundle_telemetry.py +0 -0
- {hypgraph-0.7.28 → hypgraph-0.8.1}/tests/test_cancel_releases_lease.py +0 -0
- {hypgraph-0.7.28 → hypgraph-0.8.1}/tests/test_cited_and_failed_support.py +0 -0
- {hypgraph-0.7.28 → hypgraph-0.8.1}/tests/test_contradictions.py +0 -0
- {hypgraph-0.7.28 → hypgraph-0.8.1}/tests/test_coord.py +0 -0
- {hypgraph-0.7.28 → hypgraph-0.8.1}/tests/test_counts_that_bear.py +0 -0
- {hypgraph-0.7.28 → hypgraph-0.8.1}/tests/test_d10.py +0 -0
- {hypgraph-0.7.28 → hypgraph-0.8.1}/tests/test_direction_and_units.py +0 -0
- {hypgraph-0.7.28 → hypgraph-0.8.1}/tests/test_engine.py +0 -0
- {hypgraph-0.7.28 → hypgraph-0.8.1}/tests/test_engine_fixes.py +0 -0
- {hypgraph-0.7.28 → hypgraph-0.8.1}/tests/test_figure_said_twice.py +0 -0
- {hypgraph-0.7.28 → hypgraph-0.8.1}/tests/test_framework_examples.py +0 -0
- {hypgraph-0.7.28 → hypgraph-0.8.1}/tests/test_i18n.py +0 -0
- {hypgraph-0.7.28 → hypgraph-0.8.1}/tests/test_incremental.py +0 -0
- {hypgraph-0.7.28 → hypgraph-0.8.1}/tests/test_link_translate.py +0 -0
- {hypgraph-0.7.28 → hypgraph-0.8.1}/tests/test_linked_records.py +0 -0
- {hypgraph-0.7.28 → hypgraph-0.8.1}/tests/test_log_and_check.py +0 -0
- {hypgraph-0.7.28 → hypgraph-0.8.1}/tests/test_measure_questions.py +0 -0
- {hypgraph-0.7.28 → hypgraph-0.8.1}/tests/test_opposed_answers.py +0 -0
- {hypgraph-0.7.28 → hypgraph-0.8.1}/tests/test_option_lead.py +0 -0
- {hypgraph-0.7.28 → hypgraph-0.8.1}/tests/test_order_detail.py +0 -0
- {hypgraph-0.7.28 → hypgraph-0.8.1}/tests/test_profiles.py +0 -0
- {hypgraph-0.7.28 → hypgraph-0.8.1}/tests/test_profiles_041.py +0 -0
- {hypgraph-0.7.28 → hypgraph-0.8.1}/tests/test_quantifiers_and_identity.py +0 -0
- {hypgraph-0.7.28 → hypgraph-0.8.1}/tests/test_questions_not_assertions.py +0 -0
- {hypgraph-0.7.28 → hypgraph-0.8.1}/tests/test_references.py +0 -0
- {hypgraph-0.7.28 → hypgraph-0.8.1}/tests/test_refusal_friction.py +0 -0
- {hypgraph-0.7.28 → hypgraph-0.8.1}/tests/test_refusal_results.py +0 -0
- {hypgraph-0.7.28 → hypgraph-0.8.1}/tests/test_refusals.py +0 -0
- {hypgraph-0.7.28 → hypgraph-0.8.1}/tests/test_relation_words.py +0 -0
- {hypgraph-0.7.28 → hypgraph-0.8.1}/tests/test_report_answers.py +0 -0
- {hypgraph-0.7.28 → hypgraph-0.8.1}/tests/test_rerunnable.py +0 -0
- {hypgraph-0.7.28 → hypgraph-0.8.1}/tests/test_restates_scale.py +0 -0
- {hypgraph-0.7.28 → hypgraph-0.8.1}/tests/test_server_auth.py +0 -0
- {hypgraph-0.7.28 → hypgraph-0.8.1}/tests/test_server_hosts.py +0 -0
- {hypgraph-0.7.28 → hypgraph-0.8.1}/tests/test_shape_refusals.py +0 -0
- {hypgraph-0.7.28 → hypgraph-0.8.1}/tests/test_stats_not_backtests.py +0 -0
- {hypgraph-0.7.28 → hypgraph-0.8.1}/tests/test_stats_values.py +0 -0
- {hypgraph-0.7.28 → hypgraph-0.8.1}/tests/test_surfaces.py +0 -0
- {hypgraph-0.7.28 → hypgraph-0.8.1}/tests/test_telemetry_stream.py +0 -0
- {hypgraph-0.7.28 → hypgraph-0.8.1}/tests/test_trust_boundary.py +0 -0
- {hypgraph-0.7.28 → hypgraph-0.8.1}/tests/test_ui_app.py +0 -0
- {hypgraph-0.7.28 → hypgraph-0.8.1}/tests/test_ui_engine.py +0 -0
- {hypgraph-0.7.28 → hypgraph-0.8.1}/tests/test_uncorrected_effect.py +0 -0
- {hypgraph-0.7.28 → hypgraph-0.8.1}/tests/test_unnamed_inputs.py +0 -0
- {hypgraph-0.7.28 → hypgraph-0.8.1}/tests/test_verify_complete.py +0 -0
- {hypgraph-0.7.28 → hypgraph-0.8.1}/tests/test_verify_lifecycle.py +0 -0
- {hypgraph-0.7.28 → hypgraph-0.8.1}/tests/test_verify_scope.py +0 -0
- {hypgraph-0.7.28 → hypgraph-0.8.1}/tests/test_verify_scoped_views.py +0 -0
- {hypgraph-0.7.28 → hypgraph-0.8.1}/tests/test_verify_trust.py +0 -0
- {hypgraph-0.7.28 → hypgraph-0.8.1}/tests/test_verify_views.py +0 -0
- {hypgraph-0.7.28 → hypgraph-0.8.1}/tests/test_versions_not_figures.py +0 -0
- {hypgraph-0.7.28 → hypgraph-0.8.1}/tests/test_vocabulary_friction.py +0 -0
- {hypgraph-0.7.28 → hypgraph-0.8.1}/tests/test_what_a_count_is_of.py +0 -0
- {hypgraph-0.7.28 → hypgraph-0.8.1}/tests/test_workflows.py +0 -0
|
@@ -1,5 +1,64 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.8.1 — 2026-11-01: exact figures, units within their kind
|
|
4
|
+
|
|
5
|
+
An independent audit of 0.8.0 found two defects in the typed checks, both confirmed on the published wheel.
|
|
6
|
+
|
|
7
|
+
- **Exact figures (HG-080-01).** Containment of two conditions was decided by probing at each figure ± 1 and the
|
|
8
|
+
midpoints, in floats. Above 2**53 a figure + 1 is the figure, so x > 1e18 looked inside x <= 1e18, and a count of 0
|
|
9
|
+
above 1e18 supported "none below 1e18". Containment is now decided on the pieces the two figures cut the line into,
|
|
10
|
+
with no arithmetic on them, and figures keep their exact value (10**18 + 1 is not 1e18; it renders as itself).
|
|
11
|
+
- **Units within their kind (HG-080-02).** The unit table's kind was dropped, so `lb` (mass) matched `GBP` and
|
|
12
|
+
`sterling` (currency) through the shared name "pound". A unit is now its (kind, unit) readings: `lb` = `lbs` and
|
|
13
|
+
`GBP` = `sterling` still, never across kinds, and an ambiguous `pound` matches only another `pound`; the refusal says
|
|
14
|
+
what it could be and asks for `lb` or `GBP`.
|
|
15
|
+
- **`exactly` decided from bounds.** It was left unresolved unless its set was the counted one or its complement:
|
|
16
|
+
4 of 4 above F now contradicts "exactly 4 below F". Over one population every verdict now equals enumeration of the
|
|
17
|
+
consistent worlds (sound and complete), and the test checks that.
|
|
18
|
+
- **An extreme stated as a value is two atoms.** In a typed investigation "the longest of the 4 routes is 26 km"
|
|
19
|
+
needs both "none above 26" and "some at 26 or more"; one of them is refused (`ASSERTION_MISSING`). An extreme stated
|
|
20
|
+
as a bound ("the slowest took at least 40 minutes") needs one.
|
|
21
|
+
- Tests: containment against exact rational probes over large, adjacent, subnormal and signed-zero figures; the audit's
|
|
22
|
+
cases through `_decide` and the write gate; units; extremes. The audit's own test file passes (13 of 13).
|
|
23
|
+
|
|
24
|
+
## 0.8.0 — 2026-11-01: typed claim assertions
|
|
25
|
+
|
|
26
|
+
Eight independent audits (HG-020 → HG-028) found the same class of failure, each time in a new wording: to decide
|
|
27
|
+
whether a count backs or contradicts a claim, the checks read words — the result's key and the claimant's
|
|
28
|
+
measurement name for what was counted, the statement for what is asserted and which clause a count belongs to — and
|
|
29
|
+
the claimant writes most of those words. Each fix narrowed one wording; the next audit found another. 0.8.0 stops
|
|
30
|
+
inferring that structure from words.
|
|
31
|
+
|
|
32
|
+
- **Typed counts.** A count may say what it counted: `population` (a path, `route/passenger` lies within `route`),
|
|
33
|
+
`property` and `unit`, beside `k`, `n`, `figure` and `op`. The result's author writes them; the instrument, on its
|
|
34
|
+
own results.
|
|
35
|
+
- **Typed assertions.** A claim may carry `asserts`, atoms `{quantifier none | all | some | exactly, population,
|
|
36
|
+
property, op, figure, unit, n, k, measurement}`. Each is decided against its bound count by sets on the number line
|
|
37
|
+
and population paths (`src/hypgraph/assertions.py`): supported, contradicted, or unresolved with the field that
|
|
38
|
+
blocked it. No words are read, so a true atom can't lend anything to a false one (HG-028-01) and "all 4 routes"
|
|
39
|
+
meets its counterexample however the set is enumerated (HG-028-02). New codes `ASSERTION_CONTRADICTED` (tracked in
|
|
40
|
+
conduct like `COUNT_CONTRADICTS`, `by_assertion`) and `ASSERTION_UNRESOLVED`.
|
|
41
|
+
- **Typed investigations.** `typed_claims: true` on an investigation (or a profile's `typed_claims`) makes atoms the
|
|
42
|
+
check: a statement that asserts an absolute, an extreme or a count needs an atom for each part that does
|
|
43
|
+
(`ASSERTION_MISSING`, with atoms drafted from the statement and its typed counts — never trusted, checked once
|
|
44
|
+
written), and the word interpretation stands down there: measurement names and keys aren't read for what was
|
|
45
|
+
counted, and the absolute / counterexample / extreme checks don't run. Numbers in the statement must still be bound;
|
|
46
|
+
every other check runs as before.
|
|
47
|
+
- **Standing.** A claim's state carries `assertions` (each atom rendered as the sentence it asserts, with its verdict
|
|
48
|
+
against the count as it stands now), `assertion_contradicted` when a count revised later makes an atom false (the
|
|
49
|
+
claim joins the revalidation queue), and `checked_by`: `typed`, `wording` or `none`. Bundles carry the verdicts, and
|
|
50
|
+
the verifier checks them against the rows. The Atlas claim drawer shows the atoms as the headline and the author's
|
|
51
|
+
sentence beneath, labelled as prose.
|
|
52
|
+
- **A count is whole, for everyone** (HG-028-03). `k` and `n` must be whole numbers (an int or an integral float),
|
|
53
|
+
finite, `0 ≤ k ≤ n`, `n ≥ 1`, on creation and on revision (`VALUE_NOT_A_COUNT`); counts used to be truncated, so 0.9
|
|
54
|
+
of 4 read as 0 of 4 and backed "none". A typed count must be complete (`VALUE_TYPE_INVALID`).
|
|
55
|
+
- **The word checks are frozen.** Outside a typed investigation they run as in 0.7.28 and are documented as heuristics;
|
|
56
|
+
HG-028-01 and -02 remain limits of untyped mode. Replaying the 1,900 recorded adversarial entries changes none, and
|
|
57
|
+
every trial's standing is the same.
|
|
58
|
+
- Tests: `tests/test_assertions.py` (the interval logic checked against enumeration over every op and quantifier, paths,
|
|
59
|
+
units, the gate, standing, bundles, the draft) and `tests/test_typed_audits.py` (92 attack sentences from the audits
|
|
60
|
+
and their holdouts, around fixed atoms: none changes a verdict).
|
|
61
|
+
|
|
3
62
|
## 0.7.28 — 2026-11-01: a figure said twice, a comparison in another tense
|
|
4
63
|
|
|
5
64
|
Fixes from an independent audit of 0.7.27 (HG-027-01, -02) and from paraphrases written after the first fix; each case
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: hypgraph
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.8.1
|
|
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/
|
|
@@ -109,7 +109,7 @@ claim's derived standing.
|
|
|
109
109
|
Multi-writer sync between graphs (bundles cover sharing), authentication (the host's job; the HTTP server binds to
|
|
110
110
|
loopback and is read-only unless started with `--writable`), and a hosted service.
|
|
111
111
|
|
|
112
|
-
## Status at 0.
|
|
112
|
+
## Status at 0.8.1 (2026-11-01)
|
|
113
113
|
|
|
114
114
|
All seven phases are done: the library, bundles, the server and UI, the MCP server, the website, Pegasus running on
|
|
115
115
|
the package, and releases to PyPI from tags with trusted publishing. What came after the plan, by release, is in
|
|
@@ -213,6 +213,42 @@ was taken from a changelog without being checked against the code.*
|
|
|
213
213
|
> checked against a counterexample. This is still word matching; the typed claim layer the audits recommend is not
|
|
214
214
|
> built. Released as 0.7.28.
|
|
215
215
|
|
|
216
|
+
> **Audit of 0.7.28 (2026-11-01): the class, not the symptom.** A ninth independent audit named three defects, all
|
|
217
|
+
> reproduced on the PyPI 0.7.28 wheel (9 of 12 reproducer cases failed, the 3 controls passed): a true absolute about
|
|
218
|
+
> one thing still lent its words to a false one about another in the same statement (HG-028-01); an enumerated "all 4
|
|
219
|
+
> routes" skipped the counterexample check (HG-028-02); and fractional counts were truncated, so 0.9 of 4 read as 0 of
|
|
220
|
+
> 4 (HG-028-03). The first two are the class every audit since HG-020 found: the checks infer from the claimant's
|
|
221
|
+
> words what a count measured, what a claim asserts and which clause a count belongs to. That is now addressed
|
|
222
|
+
> structurally rather than per wording: counts carry types (population, property, unit), claims carry typed atoms, and
|
|
223
|
+
> an atom is decided against its count by interval logic and population paths, reading no words
|
|
224
|
+
> (`src/hypgraph/assertions.py`). The audit's typed-predicate recommendation is the design. Fractional and impossible
|
|
225
|
+
> counts are refused for everyone (`VALUE_NOT_A_COUNT`).
|
|
226
|
+
>
|
|
227
|
+
> **Where that stands.** Typed checking is opt-in per investigation (`typed_claims`), additive to `hypgraph/1`.
|
|
228
|
+
> Inside it, the audits' 92 attack sentences around fixed atoms change no verdict, and the interval logic is checked
|
|
229
|
+
> against enumeration for every op and quantifier. Outside it the word checks are frozen at 0.7.28 and labelled
|
|
230
|
+
> heuristic: HG-028-01 and -02 are known limits of untyped mode, closed only by typed mode. Typed checking covers
|
|
231
|
+
> count-based assertions (none / all / some / exactly, and extremes as pairs); comparisons between two measured arms
|
|
232
|
+
> and significance are still word-checked. In typed mode the prose remains the author's: a sentence that asserts
|
|
233
|
+
> more than its atoms is refused (`ASSERTION_MISSING`), but a detection miss leaves prose unverified rather than
|
|
234
|
+
> verified, and the record shows the atoms, not the sentence, as what it checked. Replaying the 1,900 recorded
|
|
235
|
+
> adversarial entries changes none. #102 is merged with green CI (17 of 17 checks). Released as 0.8.0.
|
|
236
|
+
|
|
237
|
+
> **Audit of 0.8.0 (2026-11-01).** The first audit of the typed layer found its architecture sound (GO for a
|
|
238
|
+
> controlled typed-claims pilot) and two narrow defects in its helpers, both reproduced on the published wheel (its
|
|
239
|
+
> test file: 9 failed, the 4 controls passed; the wheel's SHA-256 matched the audit's). Containment was probed in
|
|
240
|
+
> floats at figure ± 1, which above 2**53 is the figure itself, so opposite conditions at 1e18 looked equal and an
|
|
241
|
+
> unsupported "none below 1e18" was supported (HG-080-01). And units dropped their kind, so `lb` matched `GBP` through
|
|
242
|
+
> the shared name "pound" (HG-080-02). Containment is now decided exactly on the pieces of the line, with figures kept
|
|
243
|
+
> as given; a unit is its (kind, unit) readings. Two related gaps closed with them: `exactly` was left open unless its
|
|
244
|
+
> set was the counted one (now decided from bounds, and every verdict equals enumeration over one population), and an
|
|
245
|
+
> extreme stated as a value now needs both its atoms.
|
|
246
|
+
>
|
|
247
|
+
> **Where that stands.** The boundary the audit names stays: prose is matched to atoms by reading words, so a missed
|
|
248
|
+
> part leaves prose unverified, never an atom verified; integrations should consume `asserts` and their verdicts, not
|
|
249
|
+
> the statement. Untyped mode keeps its documented limits. #104 is merged with green CI (17 of 17 checks). Released as
|
|
250
|
+
> 0.8.1.
|
|
251
|
+
|
|
216
252
|
## Recommendation: CONDITIONAL GO
|
|
217
253
|
|
|
218
254
|
HypGraph is ready for a public developer preview once #59, #60 and #61 are merged with green CI and released as one
|
|
@@ -20,10 +20,10 @@ correction is a new row, never an edited one.
|
|
|
20
20
|
|
|
21
21
|
| type | code | fields (\* required) | what it is |
|
|
22
22
|
|---|---|---|---|
|
|
23
|
-
| `investigation` | INV | **title**\*, **objective**\*, success_criteria, scope, state, reviewers, constants, strict_claims, keywords, projects, doi, note, legacy_case | The study: an objective, its scope, who reviews it. Every other node belongs to one. |
|
|
23
|
+
| `investigation` | INV | **title**\*, **objective**\*, success_criteria, scope, state, reviewers, constants, strict_claims, typed_claims, keywords, projects, doi, note, legacy_case | The study: an objective, its scope, who reviews it. Every other node belongs to one. |
|
|
24
24
|
| `question` | Q | **text**\*, why | Something you want to know. |
|
|
25
25
|
| `hypothesis` | H | **statement**\*, assumptions, **predictions**\*, distinguishing, open_questions | A possible answer, with the predictions that would show it wrong. |
|
|
26
|
-
| `claim` | CL | **statement**\*, scope, limitations, kind, measurements, evidence_note, exposure, exposure_unit, legacy | What you assert is known, with its scope and its numbers bound to results. |
|
|
26
|
+
| `claim` | CL | **statement**\*, scope, limitations, kind, measurements, asserts, evidence_note, exposure, exposure_unit, legacy | What you assert is known, with its scope and its numbers bound to results. |
|
|
27
27
|
| `experiment` | X | **aim**\*, **protocol**\*, controls, **success_criteria**\*, method, budget, power_check, cost_minutes, seed | A planned test: aim, protocol, controls, success criteria, and what each hypothesis expects. |
|
|
28
28
|
| `run` | RUN | **kind**\*, job_id, name, state, code, inputs, outputs, args, config, seed, env, started, finished, exit_code, log_sha256, note | One execution: code, inputs and outputs hashed, seed, state. `kind=lab` only from an instrument. |
|
|
29
29
|
| `result` | RS | **summary**\*, kind, outcome, values, expected, limitations, power, evidence_note, legacy | What a run (or an observation, or a citation) found: values, outcome, power. |
|
|
@@ -59,6 +59,21 @@ correction is a new row, never an edited one.
|
|
|
59
59
|
Field kinds and lengths: `hypgraph schema --json` (or `/schema/hypgraph-1.json` on the site). A claim's
|
|
60
60
|
`measurements` are `{name, value | k & n | lo & hi, result: <result id>, key: <field of that result's values>}`.
|
|
61
61
|
|
|
62
|
+
**Counts and typed counts.** A result value with `k` or `n` is a count: `k` of `n`, both whole numbers (an int, or a
|
|
63
|
+
float with no fraction), finite, `0 ≤ k ≤ n`, `n ≥ 1`. It may say what it compared: `figure` and `op` (one of `<` `<=`
|
|
64
|
+
`=` `!=` `>=` `>`). A **typed count** also says what it counted: `population`, a path such as `route/passenger` (lower
|
|
65
|
+
case; `a/b` lies within `a`), `property`, an id (`length`), and optionally `unit`. `{"k": 1, "n": 4, "figure": 26,
|
|
66
|
+
"op": ">", "population": "route", "property": "length", "unit": "km"}` is 1 of 4 routes with length > 26 km. The
|
|
67
|
+
types are the result's author's; on an instrument-filed result they are the instrument's.
|
|
68
|
+
|
|
69
|
+
**Typed assertions (`asserts`).** A claim may state what it asserts as atoms, each checked against a typed count
|
|
70
|
+
(§7): `{quantifier, population, property, op, figure, unit?, n?, k?, measurement}`, where `quantifier` is `none`
|
|
71
|
+
(nothing in the population meets `property op figure`), `all` (everything does), `some` (at least one does) or
|
|
72
|
+
`exactly` (`k` of them do; `k` required), `n` is the population's size as the claim states it, and `measurement` is the
|
|
73
|
+
0-based index of the claim's measurement whose count decides it. An extreme is two atoms: "the longest route is 26 km"
|
|
74
|
+
is `none` `>` 26 and `some` `>=` 26. An investigation with `typed_claims: true` (or a profile that sets it) checks its
|
|
75
|
+
claims this way.
|
|
76
|
+
|
|
62
77
|
Verdicts: positive `checked`, `pass`, `reproduced`, `replicated`, `separate_implementation`, `generalizes`; negative
|
|
63
78
|
`fail`, `not_reproduced`, `not_replicated`, `does_not_generalize`; and `objection`, `resolved`, `inconclusive`,
|
|
64
79
|
`comment`.
|
|
@@ -169,7 +184,8 @@ published and signed, and what each check does and doesn't show: [verification.m
|
|
|
169
184
|
verifier must check every fact in it that the rows fix: which investigations it covers (the scope's, or every
|
|
170
185
|
investigation node), which investigations the list shows (each once), which nodes each investigation's graph shows
|
|
171
186
|
(all of them, unless capped at 5,000) and which live (unretracted) links among them, each node's `type`, `code`, `inv`,
|
|
172
|
-
`by`, `at`, `v`, `title`, `kind` and `state.lifecycle`,
|
|
187
|
+
`by`, `at`, `v`, `title`, `kind` and `state.lifecycle`, each typed assertion's verdict (`state.assertions`, a function
|
|
188
|
+
of the claim's and its results' latest rows), and each link's `id`, ends, versions, `rel`, `data`, `at`,
|
|
173
189
|
`by` and `why`. Every one of these must be **present**, not only equal where present: a viewer fills a missing fact
|
|
174
190
|
with a default, and a withdrawn claim without its lifecycle would read as active. The lifecycle is derived from the
|
|
175
191
|
verified rows (withdrawn when a withdrawal exists; superseded when a live `supersedes` or `corrects` replacement is
|
|
@@ -212,6 +228,11 @@ Implementations must derive these, never store them:
|
|
|
212
228
|
- A replication edge on the run raises the profile according to its `differs`.
|
|
213
229
|
- A result of `kind=cited` is external only if it `cites` a source node.
|
|
214
230
|
- **basis_changed** (decisions): a `based_on` edge whose target's version has moved past the pinned `dst_v`.
|
|
231
|
+
- **assertions** (claims with `asserts`): each atom with its verdict against its count as the record holds it now
|
|
232
|
+
(§7, *Typed claims*) and its rendered sentence ("no route/passenger (of 4) has length > 26 km"). The rendered atoms
|
|
233
|
+
are what the record verified; the statement is the author's prose. **assertion_contradicted**: the atoms a count
|
|
234
|
+
revised since the claim was written now makes false. **checked_by**: `typed` when the claim's investigation checks
|
|
235
|
+
typed atoms, `wording` when the word checks applied, `none` with `strict_claims: false`.
|
|
215
236
|
- **written blind** (results): a work order with `blind: true` opens a window at its creation event and closes it at
|
|
216
237
|
the first release (return or cancel) or withdrawal of any order in its rework chain. A result its assignee
|
|
217
238
|
created inside the window, and has not revised since it closed, is written blind under that order, provided the
|
|
@@ -227,6 +248,9 @@ Implementations must derive these, never store them:
|
|
|
227
248
|
- Only the instrument files a `kind=lab` run, and only the instrument records what that run `produced`.
|
|
228
249
|
- Claims must pass the checks in §7, unless written by the operator or importer, or in an investigation with
|
|
229
250
|
`strict_claims: false`.
|
|
251
|
+
- A result's counts must be counts (`VALUE_NOT_A_NUMBER`, `VALUE_NOT_A_COUNT`), and a typed count must be complete
|
|
252
|
+
(`VALUE_TYPE_INVALID`: `population` a path, `property` an id, `op` one of the six, `figure` a number) — on creation
|
|
253
|
+
and on revision.
|
|
230
254
|
- Nobody officially reviews their own node.
|
|
231
255
|
- Writes into an `archived` or `published` investigation are refused (reserved authors excepted).
|
|
232
256
|
- Only the importer may set a write's time. Everyone else's comes from the writer's clock.
|
|
@@ -264,6 +288,38 @@ smallest detectable difference uses 80% power at two-sided α = 0.05.
|
|
|
264
288
|
| 10 | `EXCLUSION_WITHOUT_POWER` | `kind: exclusion`, or wording that says an effect is absent (no effect, no difference, makes no difference, does not affect, rules out, ineffective, …) in a finding, without a supporting result with `power: demonstrated` or one produced by a run of an experiment with a `power_check`. With two counts, the message gives the smallest detectable difference. |
|
|
265
289
|
| 11 | `UNCORRECTED_EFFECT` | a finding asserts an effect (changes, lowers, differs, affects, significant, …) on an outcome, while a live result in the investigation holds that outcome's corrected p-value (a field named with holm / bonferroni / fdr / adjusted / corrected …) at or above 0.05, or a count of 0 outcomes surviving correction (`n_holm_sig`), and the effect word is neither qualified within 20 words as uncorrected (uncorrected, unadjusted, nominally, without correction, …) nor names the correction with a corrected value bound as a measurement. A family-wide value (`min_adjusted_p`) applies when the claim binds a nominal p < 0.05. Thresholds (`bonferroni_alpha_threshold`) are not evidence. Honest forms: bind the corrected p and say "not significant after correction", or file `kind: lead`. |
|
|
266
290
|
|
|
291
|
+
**Typed claims.** An atom (§2) is decided by its bound count alone; no words are read. Let S_e = {x : x op_e f_e} (what
|
|
292
|
+
was counted, k of n inside it, n − k outside) and S_a = {x : x op_a f_a} (what is asserted); P_e and P_a the
|
|
293
|
+
populations. The property must equal the count's and the unit match it: spellings of one unit are one unit within one
|
|
294
|
+
kind of unit (`lb` = `lbs`, `GBP` = `sterling`, never `lb` = `GBP`), a spelling that could be two kinds (`pound`:
|
|
295
|
+
mass or currency) matches only another that could be the same two, and nothing is converted. A stated `n` must equal
|
|
296
|
+
the count's. Figures are compared exactly, as given (an int or a float, at any magnitude), on the pieces of the line
|
|
297
|
+
the two figures cut it into — never by arithmetic on them.
|
|
298
|
+
|
|
299
|
+
- `none` S_a: **supported** when a side of the count with 0 inside it contains S_a and P_a lies within P_e;
|
|
300
|
+
**contradicted** when a side with more than 0 lies inside S_a and P_e lies within P_a.
|
|
301
|
+
- `some` S_a: supported when a side with more than 0 lies inside S_a and P_e within P_a; contradicted when a side with
|
|
302
|
+
0 contains S_a and P_a lies within P_e.
|
|
303
|
+
- `all` S_a is `none` of the complement of S_a.
|
|
304
|
+
- `exactly` k needs the same population. A side of the count lying inside S_a puts at least its count in S_a; a side
|
|
305
|
+
containing S_a, at most its count. k at both bounds is **supported**, k outside them **contradicted**.
|
|
306
|
+
|
|
307
|
+
Over one population these verdicts are complete as well as sound: supported or contradicted exactly when every set of
|
|
308
|
+
values consistent with the count agrees.
|
|
309
|
+
- Anything else is **unresolved**, and names the field that blocked it.
|
|
310
|
+
|
|
311
|
+
| Code | Refused when |
|
|
312
|
+
|---|---|
|
|
313
|
+
| `ASSERTION_CONTRADICTED` | an atom is false by its count. The refusal log tracks it like a count contradiction (§8). |
|
|
314
|
+
| `ASSERTION_UNRESOLVED` | an atom its count can't settle: another property or unit, a population neither within nor containing the count's, a condition the count's doesn't decide, an untyped count, a malformed atom. |
|
|
315
|
+
| `ASSERTION_MISSING` | in a `typed_claims` investigation, the statement's parts that assert an absolute, an extreme or a count need more atoms than the claim has: one each, and two for an extreme stated as a value ("the longest is 26 km": none above, some at or above). Detection reads words only to ask for atoms; a missed word leaves prose unverified, never an atom verified. The refusal proposes atoms drafted from the statement and the claim's typed counts, which are checked like any other once written. |
|
|
316
|
+
|
|
317
|
+
Atoms are checked in every investigation that has them. In a `typed_claims` investigation the word interpretation
|
|
318
|
+
stands down: a measurement's name and key are not read for what was counted, and rule 5 (absolutes, with the
|
|
319
|
+
counterexample, extreme and unreached-figure checks behind it) does not run. Every other rule runs as before. Outside
|
|
320
|
+
one, rule 5 and those checks are heuristics, frozen as of 0.7.28: they read a claim's words for what a count measured,
|
|
321
|
+
what the claim asserts and which clause a count belongs to, and the claimant writes those words.
|
|
322
|
+
|
|
267
323
|
**Exposure.** A claim may set `exposure` (how many uses, users or units it will be applied to) and `exposure_unit`.
|
|
268
324
|
Absolute refusals then state how many failures the bound leaves unruled out at that scale. An accepted claim's
|
|
269
325
|
standing carries `bounds` (per count: k, n, rate, lo, hi and, with exposure, `unruled_out`), its sentence reads
|
|
@@ -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.8.1"
|
|
20
20
|
|
|
21
21
|
from .bundle import anchored, verify_bundle # noqa: E402
|
|
22
22
|
from .graph import Author, Graph, GraphError, file_sha256 # noqa: E402
|