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.
Files changed (130) hide show
  1. {hypgraph-0.7.28 → hypgraph-0.8.1}/CHANGELOG.md +59 -0
  2. {hypgraph-0.7.28 → hypgraph-0.8.1}/PKG-INFO +1 -1
  3. {hypgraph-0.7.28 → hypgraph-0.8.1}/docs/PLAN.md +1 -1
  4. {hypgraph-0.7.28 → hypgraph-0.8.1}/docs/RELEASE-READINESS.md +36 -0
  5. {hypgraph-0.7.28 → hypgraph-0.8.1}/docs/spec.md +59 -3
  6. {hypgraph-0.7.28 → hypgraph-0.8.1}/src/hypgraph/__init__.py +1 -1
  7. hypgraph-0.8.1/src/hypgraph/assertions.py +440 -0
  8. {hypgraph-0.7.28 → hypgraph-0.8.1}/src/hypgraph/bundle.py +15 -3
  9. {hypgraph-0.7.28 → hypgraph-0.8.1}/src/hypgraph/checks.py +163 -9
  10. {hypgraph-0.7.28 → hypgraph-0.8.1}/src/hypgraph/derive.py +22 -1
  11. {hypgraph-0.7.28 → hypgraph-0.8.1}/src/hypgraph/graph.py +11 -2
  12. {hypgraph-0.7.28 → hypgraph-0.8.1}/src/hypgraph/mcp.py +7 -2
  13. {hypgraph-0.7.28 → hypgraph-0.8.1}/src/hypgraph/plan.py +1 -1
  14. {hypgraph-0.7.28 → hypgraph-0.8.1}/src/hypgraph/profiles.py +1 -0
  15. {hypgraph-0.7.28 → hypgraph-0.8.1}/src/hypgraph/refusals.py +20 -13
  16. {hypgraph-0.7.28 → hypgraph-0.8.1}/src/hypgraph/schema.py +2 -0
  17. {hypgraph-0.7.28 → hypgraph-0.8.1}/src/hypgraph/skill/SKILL.md +11 -0
  18. {hypgraph-0.7.28 → hypgraph-0.8.1}/src/hypgraph/stats.py +8 -0
  19. {hypgraph-0.7.28 → hypgraph-0.8.1}/src/hypgraph/ui/hypgraph.i18n.js +12 -0
  20. {hypgraph-0.7.28 → hypgraph-0.8.1}/src/hypgraph/ui/hypgraph.js +12 -2
  21. hypgraph-0.8.1/tests/test_assertions.py +509 -0
  22. hypgraph-0.8.1/tests/test_typed_audits.py +166 -0
  23. {hypgraph-0.7.28 → hypgraph-0.8.1}/.gitignore +0 -0
  24. {hypgraph-0.7.28 → hypgraph-0.8.1}/AGENTS.md +0 -0
  25. {hypgraph-0.7.28 → hypgraph-0.8.1}/CITATION.cff +0 -0
  26. {hypgraph-0.7.28 → hypgraph-0.8.1}/DISCLAIMER.md +0 -0
  27. {hypgraph-0.7.28 → hypgraph-0.8.1}/LICENSE +0 -0
  28. {hypgraph-0.7.28 → hypgraph-0.8.1}/NOTICE +0 -0
  29. {hypgraph-0.7.28 → hypgraph-0.8.1}/README.md +0 -0
  30. {hypgraph-0.7.28 → hypgraph-0.8.1}/docs/decisions/ADR-001-token-bound-authors.md +0 -0
  31. {hypgraph-0.7.28 → hypgraph-0.8.1}/docs/decisions/ADR-002-governance-profiles.md +0 -0
  32. {hypgraph-0.7.28 → hypgraph-0.8.1}/docs/profile-workflows-plan.md +0 -0
  33. {hypgraph-0.7.28 → hypgraph-0.8.1}/docs/review-2026-10-24.md +0 -0
  34. {hypgraph-0.7.28 → hypgraph-0.8.1}/docs/site-plan.md +0 -0
  35. {hypgraph-0.7.28 → hypgraph-0.8.1}/docs/ui-plan.md +0 -0
  36. {hypgraph-0.7.28 → hypgraph-0.8.1}/docs/verification.md +0 -0
  37. {hypgraph-0.7.28 → hypgraph-0.8.1}/docs/workflows/README.md +0 -0
  38. {hypgraph-0.7.28 → hypgraph-0.8.1}/docs/workflows/knowledge.md +0 -0
  39. {hypgraph-0.7.28 → hypgraph-0.8.1}/docs/workflows/optimization.md +0 -0
  40. {hypgraph-0.7.28 → hypgraph-0.8.1}/docs/workflows/scientific.md +0 -0
  41. {hypgraph-0.7.28 → hypgraph-0.8.1}/docs/workflows/software.md +0 -0
  42. {hypgraph-0.7.28 → hypgraph-0.8.1}/docs/workflows/trading.md +0 -0
  43. {hypgraph-0.7.28 → hypgraph-0.8.1}/examples/frameworks/README.md +0 -0
  44. {hypgraph-0.7.28 → hypgraph-0.8.1}/pyproject.toml +0 -0
  45. {hypgraph-0.7.28 → hypgraph-0.8.1}/src/hypgraph/__main__.py +0 -0
  46. {hypgraph-0.7.28 → hypgraph-0.8.1}/src/hypgraph/blind.py +0 -0
  47. {hypgraph-0.7.28 → hypgraph-0.8.1}/src/hypgraph/cli.py +0 -0
  48. {hypgraph-0.7.28 → hypgraph-0.8.1}/src/hypgraph/coord.py +0 -0
  49. {hypgraph-0.7.28 → hypgraph-0.8.1}/src/hypgraph/demos/__init__.py +0 -0
  50. {hypgraph-0.7.28 → hypgraph-0.8.1}/src/hypgraph/demos/broad_street.py +0 -0
  51. {hypgraph-0.7.28 → hypgraph-0.8.1}/src/hypgraph/demos/linked.py +0 -0
  52. {hypgraph-0.7.28 → hypgraph-0.8.1}/src/hypgraph/language.py +0 -0
  53. {hypgraph-0.7.28 → hypgraph-0.8.1}/src/hypgraph/policy.py +0 -0
  54. {hypgraph-0.7.28 → hypgraph-0.8.1}/src/hypgraph/references.py +0 -0
  55. {hypgraph-0.7.28 → hypgraph-0.8.1}/src/hypgraph/report_check.py +0 -0
  56. {hypgraph-0.7.28 → hypgraph-0.8.1}/src/hypgraph/server.py +0 -0
  57. {hypgraph-0.7.28 → hypgraph-0.8.1}/src/hypgraph/store.py +0 -0
  58. {hypgraph-0.7.28 → hypgraph-0.8.1}/src/hypgraph/ui/__init__.py +0 -0
  59. {hypgraph-0.7.28 → hypgraph-0.8.1}/src/hypgraph/ui/atlas.css +0 -0
  60. {hypgraph-0.7.28 → hypgraph-0.8.1}/src/hypgraph/ui/atlas.js +0 -0
  61. {hypgraph-0.7.28 → hypgraph-0.8.1}/src/hypgraph/ui/hypgraph.css +0 -0
  62. {hypgraph-0.7.28 → hypgraph-0.8.1}/src/hypgraph/ui/hypgraph.svg +0 -0
  63. {hypgraph-0.7.28 → hypgraph-0.8.1}/src/hypgraph/ui/index.html +0 -0
  64. {hypgraph-0.7.28 → hypgraph-0.8.1}/src/hypgraph/ui/vendor/LICENSES.md +0 -0
  65. {hypgraph-0.7.28 → hypgraph-0.8.1}/src/hypgraph/ui/vendor/cose-base.js +0 -0
  66. {hypgraph-0.7.28 → hypgraph-0.8.1}/src/hypgraph/ui/vendor/cytoscape-fcose.js +0 -0
  67. {hypgraph-0.7.28 → hypgraph-0.8.1}/src/hypgraph/ui/vendor/cytoscape.min.js +0 -0
  68. {hypgraph-0.7.28 → hypgraph-0.8.1}/src/hypgraph/ui/vendor/layout-base.js +0 -0
  69. {hypgraph-0.7.28 → hypgraph-0.8.1}/src/hypgraph/workflow.py +0 -0
  70. {hypgraph-0.7.28 → hypgraph-0.8.1}/tests/test_accept_work_kind.py +0 -0
  71. {hypgraph-0.7.28 → hypgraph-0.8.1}/tests/test_anchoring.py +0 -0
  72. {hypgraph-0.7.28 → hypgraph-0.8.1}/tests/test_blind.py +0 -0
  73. {hypgraph-0.7.28 → hypgraph-0.8.1}/tests/test_blind_oracles.py +0 -0
  74. {hypgraph-0.7.28 → hypgraph-0.8.1}/tests/test_borrowed_words.py +0 -0
  75. {hypgraph-0.7.28 → hypgraph-0.8.1}/tests/test_bound_support.py +0 -0
  76. {hypgraph-0.7.28 → hypgraph-0.8.1}/tests/test_bundle_telemetry.py +0 -0
  77. {hypgraph-0.7.28 → hypgraph-0.8.1}/tests/test_cancel_releases_lease.py +0 -0
  78. {hypgraph-0.7.28 → hypgraph-0.8.1}/tests/test_cited_and_failed_support.py +0 -0
  79. {hypgraph-0.7.28 → hypgraph-0.8.1}/tests/test_contradictions.py +0 -0
  80. {hypgraph-0.7.28 → hypgraph-0.8.1}/tests/test_coord.py +0 -0
  81. {hypgraph-0.7.28 → hypgraph-0.8.1}/tests/test_counts_that_bear.py +0 -0
  82. {hypgraph-0.7.28 → hypgraph-0.8.1}/tests/test_d10.py +0 -0
  83. {hypgraph-0.7.28 → hypgraph-0.8.1}/tests/test_direction_and_units.py +0 -0
  84. {hypgraph-0.7.28 → hypgraph-0.8.1}/tests/test_engine.py +0 -0
  85. {hypgraph-0.7.28 → hypgraph-0.8.1}/tests/test_engine_fixes.py +0 -0
  86. {hypgraph-0.7.28 → hypgraph-0.8.1}/tests/test_figure_said_twice.py +0 -0
  87. {hypgraph-0.7.28 → hypgraph-0.8.1}/tests/test_framework_examples.py +0 -0
  88. {hypgraph-0.7.28 → hypgraph-0.8.1}/tests/test_i18n.py +0 -0
  89. {hypgraph-0.7.28 → hypgraph-0.8.1}/tests/test_incremental.py +0 -0
  90. {hypgraph-0.7.28 → hypgraph-0.8.1}/tests/test_link_translate.py +0 -0
  91. {hypgraph-0.7.28 → hypgraph-0.8.1}/tests/test_linked_records.py +0 -0
  92. {hypgraph-0.7.28 → hypgraph-0.8.1}/tests/test_log_and_check.py +0 -0
  93. {hypgraph-0.7.28 → hypgraph-0.8.1}/tests/test_measure_questions.py +0 -0
  94. {hypgraph-0.7.28 → hypgraph-0.8.1}/tests/test_opposed_answers.py +0 -0
  95. {hypgraph-0.7.28 → hypgraph-0.8.1}/tests/test_option_lead.py +0 -0
  96. {hypgraph-0.7.28 → hypgraph-0.8.1}/tests/test_order_detail.py +0 -0
  97. {hypgraph-0.7.28 → hypgraph-0.8.1}/tests/test_profiles.py +0 -0
  98. {hypgraph-0.7.28 → hypgraph-0.8.1}/tests/test_profiles_041.py +0 -0
  99. {hypgraph-0.7.28 → hypgraph-0.8.1}/tests/test_quantifiers_and_identity.py +0 -0
  100. {hypgraph-0.7.28 → hypgraph-0.8.1}/tests/test_questions_not_assertions.py +0 -0
  101. {hypgraph-0.7.28 → hypgraph-0.8.1}/tests/test_references.py +0 -0
  102. {hypgraph-0.7.28 → hypgraph-0.8.1}/tests/test_refusal_friction.py +0 -0
  103. {hypgraph-0.7.28 → hypgraph-0.8.1}/tests/test_refusal_results.py +0 -0
  104. {hypgraph-0.7.28 → hypgraph-0.8.1}/tests/test_refusals.py +0 -0
  105. {hypgraph-0.7.28 → hypgraph-0.8.1}/tests/test_relation_words.py +0 -0
  106. {hypgraph-0.7.28 → hypgraph-0.8.1}/tests/test_report_answers.py +0 -0
  107. {hypgraph-0.7.28 → hypgraph-0.8.1}/tests/test_rerunnable.py +0 -0
  108. {hypgraph-0.7.28 → hypgraph-0.8.1}/tests/test_restates_scale.py +0 -0
  109. {hypgraph-0.7.28 → hypgraph-0.8.1}/tests/test_server_auth.py +0 -0
  110. {hypgraph-0.7.28 → hypgraph-0.8.1}/tests/test_server_hosts.py +0 -0
  111. {hypgraph-0.7.28 → hypgraph-0.8.1}/tests/test_shape_refusals.py +0 -0
  112. {hypgraph-0.7.28 → hypgraph-0.8.1}/tests/test_stats_not_backtests.py +0 -0
  113. {hypgraph-0.7.28 → hypgraph-0.8.1}/tests/test_stats_values.py +0 -0
  114. {hypgraph-0.7.28 → hypgraph-0.8.1}/tests/test_surfaces.py +0 -0
  115. {hypgraph-0.7.28 → hypgraph-0.8.1}/tests/test_telemetry_stream.py +0 -0
  116. {hypgraph-0.7.28 → hypgraph-0.8.1}/tests/test_trust_boundary.py +0 -0
  117. {hypgraph-0.7.28 → hypgraph-0.8.1}/tests/test_ui_app.py +0 -0
  118. {hypgraph-0.7.28 → hypgraph-0.8.1}/tests/test_ui_engine.py +0 -0
  119. {hypgraph-0.7.28 → hypgraph-0.8.1}/tests/test_uncorrected_effect.py +0 -0
  120. {hypgraph-0.7.28 → hypgraph-0.8.1}/tests/test_unnamed_inputs.py +0 -0
  121. {hypgraph-0.7.28 → hypgraph-0.8.1}/tests/test_verify_complete.py +0 -0
  122. {hypgraph-0.7.28 → hypgraph-0.8.1}/tests/test_verify_lifecycle.py +0 -0
  123. {hypgraph-0.7.28 → hypgraph-0.8.1}/tests/test_verify_scope.py +0 -0
  124. {hypgraph-0.7.28 → hypgraph-0.8.1}/tests/test_verify_scoped_views.py +0 -0
  125. {hypgraph-0.7.28 → hypgraph-0.8.1}/tests/test_verify_trust.py +0 -0
  126. {hypgraph-0.7.28 → hypgraph-0.8.1}/tests/test_verify_views.py +0 -0
  127. {hypgraph-0.7.28 → hypgraph-0.8.1}/tests/test_versions_not_figures.py +0 -0
  128. {hypgraph-0.7.28 → hypgraph-0.8.1}/tests/test_vocabulary_friction.py +0 -0
  129. {hypgraph-0.7.28 → hypgraph-0.8.1}/tests/test_what_a_count_is_of.py +0 -0
  130. {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.7.28
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.7.28 (2026-11-01)
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`, and each link's `id`, ends, versions, `rel`, `data`, `at`,
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.7.28"
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