hypgraph 0.8.4__tar.gz → 0.8.6__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.8.4 → hypgraph-0.8.6}/CHANGELOG.md +29 -0
- {hypgraph-0.8.4 → hypgraph-0.8.6}/PKG-INFO +1 -1
- {hypgraph-0.8.4 → hypgraph-0.8.6}/docs/PLAN.md +1 -1
- {hypgraph-0.8.4 → hypgraph-0.8.6}/docs/RELEASE-READINESS.md +13 -0
- {hypgraph-0.8.4 → hypgraph-0.8.6}/src/hypgraph/__init__.py +1 -1
- {hypgraph-0.8.4 → hypgraph-0.8.6}/src/hypgraph/checks.py +27 -4
- {hypgraph-0.8.4 → hypgraph-0.8.6}/src/hypgraph/report_check.py +26 -3
- hypgraph-0.8.6/tests/test_report_significance_denied.py +62 -0
- hypgraph-0.8.6/tests/test_statement_is_a_question.py +51 -0
- hypgraph-0.8.6/tests/test_statement_slots.py +82 -0
- {hypgraph-0.8.4 → hypgraph-0.8.6}/tests/test_versions_not_figures.py +8 -0
- {hypgraph-0.8.4 → hypgraph-0.8.6}/.gitignore +0 -0
- {hypgraph-0.8.4 → hypgraph-0.8.6}/AGENTS.md +0 -0
- {hypgraph-0.8.4 → hypgraph-0.8.6}/CITATION.cff +0 -0
- {hypgraph-0.8.4 → hypgraph-0.8.6}/DISCLAIMER.md +0 -0
- {hypgraph-0.8.4 → hypgraph-0.8.6}/LICENSE +0 -0
- {hypgraph-0.8.4 → hypgraph-0.8.6}/NOTICE +0 -0
- {hypgraph-0.8.4 → hypgraph-0.8.6}/README.md +0 -0
- {hypgraph-0.8.4 → hypgraph-0.8.6}/docs/decisions/ADR-001-token-bound-authors.md +0 -0
- {hypgraph-0.8.4 → hypgraph-0.8.6}/docs/decisions/ADR-002-governance-profiles.md +0 -0
- {hypgraph-0.8.4 → hypgraph-0.8.6}/docs/profile-workflows-plan.md +0 -0
- {hypgraph-0.8.4 → hypgraph-0.8.6}/docs/review-2026-10-24.md +0 -0
- {hypgraph-0.8.4 → hypgraph-0.8.6}/docs/site-plan.md +0 -0
- {hypgraph-0.8.4 → hypgraph-0.8.6}/docs/spec.md +0 -0
- {hypgraph-0.8.4 → hypgraph-0.8.6}/docs/ui-plan.md +0 -0
- {hypgraph-0.8.4 → hypgraph-0.8.6}/docs/verification.md +0 -0
- {hypgraph-0.8.4 → hypgraph-0.8.6}/docs/workflows/README.md +0 -0
- {hypgraph-0.8.4 → hypgraph-0.8.6}/docs/workflows/knowledge.md +0 -0
- {hypgraph-0.8.4 → hypgraph-0.8.6}/docs/workflows/optimization.md +0 -0
- {hypgraph-0.8.4 → hypgraph-0.8.6}/docs/workflows/scientific.md +0 -0
- {hypgraph-0.8.4 → hypgraph-0.8.6}/docs/workflows/software.md +0 -0
- {hypgraph-0.8.4 → hypgraph-0.8.6}/docs/workflows/trading.md +0 -0
- {hypgraph-0.8.4 → hypgraph-0.8.6}/examples/frameworks/README.md +0 -0
- {hypgraph-0.8.4 → hypgraph-0.8.6}/pyproject.toml +0 -0
- {hypgraph-0.8.4 → hypgraph-0.8.6}/src/hypgraph/__main__.py +0 -0
- {hypgraph-0.8.4 → hypgraph-0.8.6}/src/hypgraph/assertions.py +0 -0
- {hypgraph-0.8.4 → hypgraph-0.8.6}/src/hypgraph/blind.py +0 -0
- {hypgraph-0.8.4 → hypgraph-0.8.6}/src/hypgraph/bundle.py +0 -0
- {hypgraph-0.8.4 → hypgraph-0.8.6}/src/hypgraph/cli.py +0 -0
- {hypgraph-0.8.4 → hypgraph-0.8.6}/src/hypgraph/coord.py +0 -0
- {hypgraph-0.8.4 → hypgraph-0.8.6}/src/hypgraph/demos/__init__.py +0 -0
- {hypgraph-0.8.4 → hypgraph-0.8.6}/src/hypgraph/demos/broad_street.py +0 -0
- {hypgraph-0.8.4 → hypgraph-0.8.6}/src/hypgraph/demos/dispute.py +0 -0
- {hypgraph-0.8.4 → hypgraph-0.8.6}/src/hypgraph/demos/linked.py +0 -0
- {hypgraph-0.8.4 → hypgraph-0.8.6}/src/hypgraph/derive.py +0 -0
- {hypgraph-0.8.4 → hypgraph-0.8.6}/src/hypgraph/graph.py +0 -0
- {hypgraph-0.8.4 → hypgraph-0.8.6}/src/hypgraph/language.py +0 -0
- {hypgraph-0.8.4 → hypgraph-0.8.6}/src/hypgraph/mcp.py +0 -0
- {hypgraph-0.8.4 → hypgraph-0.8.6}/src/hypgraph/plan.py +0 -0
- {hypgraph-0.8.4 → hypgraph-0.8.6}/src/hypgraph/policy.py +0 -0
- {hypgraph-0.8.4 → hypgraph-0.8.6}/src/hypgraph/profiles.py +0 -0
- {hypgraph-0.8.4 → hypgraph-0.8.6}/src/hypgraph/references.py +0 -0
- {hypgraph-0.8.4 → hypgraph-0.8.6}/src/hypgraph/refusals.py +0 -0
- {hypgraph-0.8.4 → hypgraph-0.8.6}/src/hypgraph/schema.py +0 -0
- {hypgraph-0.8.4 → hypgraph-0.8.6}/src/hypgraph/server.py +0 -0
- {hypgraph-0.8.4 → hypgraph-0.8.6}/src/hypgraph/skill/SKILL.md +0 -0
- {hypgraph-0.8.4 → hypgraph-0.8.6}/src/hypgraph/stats.py +0 -0
- {hypgraph-0.8.4 → hypgraph-0.8.6}/src/hypgraph/store.py +0 -0
- {hypgraph-0.8.4 → hypgraph-0.8.6}/src/hypgraph/ui/__init__.py +0 -0
- {hypgraph-0.8.4 → hypgraph-0.8.6}/src/hypgraph/ui/atlas.css +0 -0
- {hypgraph-0.8.4 → hypgraph-0.8.6}/src/hypgraph/ui/atlas.js +0 -0
- {hypgraph-0.8.4 → hypgraph-0.8.6}/src/hypgraph/ui/hypgraph.css +0 -0
- {hypgraph-0.8.4 → hypgraph-0.8.6}/src/hypgraph/ui/hypgraph.i18n.js +0 -0
- {hypgraph-0.8.4 → hypgraph-0.8.6}/src/hypgraph/ui/hypgraph.js +0 -0
- {hypgraph-0.8.4 → hypgraph-0.8.6}/src/hypgraph/ui/hypgraph.svg +0 -0
- {hypgraph-0.8.4 → hypgraph-0.8.6}/src/hypgraph/ui/index.html +0 -0
- {hypgraph-0.8.4 → hypgraph-0.8.6}/src/hypgraph/ui/vendor/LICENSES.md +0 -0
- {hypgraph-0.8.4 → hypgraph-0.8.6}/src/hypgraph/ui/vendor/cose-base.js +0 -0
- {hypgraph-0.8.4 → hypgraph-0.8.6}/src/hypgraph/ui/vendor/cytoscape-fcose.js +0 -0
- {hypgraph-0.8.4 → hypgraph-0.8.6}/src/hypgraph/ui/vendor/cytoscape.min.js +0 -0
- {hypgraph-0.8.4 → hypgraph-0.8.6}/src/hypgraph/ui/vendor/layout-base.js +0 -0
- {hypgraph-0.8.4 → hypgraph-0.8.6}/src/hypgraph/workflow.py +0 -0
- {hypgraph-0.8.4 → hypgraph-0.8.6}/tests/test_accept_work_kind.py +0 -0
- {hypgraph-0.8.4 → hypgraph-0.8.6}/tests/test_anchoring.py +0 -0
- {hypgraph-0.8.4 → hypgraph-0.8.6}/tests/test_assertions.py +0 -0
- {hypgraph-0.8.4 → hypgraph-0.8.6}/tests/test_blind.py +0 -0
- {hypgraph-0.8.4 → hypgraph-0.8.6}/tests/test_blind_oracles.py +0 -0
- {hypgraph-0.8.4 → hypgraph-0.8.6}/tests/test_borrowed_words.py +0 -0
- {hypgraph-0.8.4 → hypgraph-0.8.6}/tests/test_bound_support.py +0 -0
- {hypgraph-0.8.4 → hypgraph-0.8.6}/tests/test_bundle_telemetry.py +0 -0
- {hypgraph-0.8.4 → hypgraph-0.8.6}/tests/test_cancel_releases_lease.py +0 -0
- {hypgraph-0.8.4 → hypgraph-0.8.6}/tests/test_cited_and_failed_support.py +0 -0
- {hypgraph-0.8.4 → hypgraph-0.8.6}/tests/test_contradictions.py +0 -0
- {hypgraph-0.8.4 → hypgraph-0.8.6}/tests/test_coord.py +0 -0
- {hypgraph-0.8.4 → hypgraph-0.8.6}/tests/test_counts_that_bear.py +0 -0
- {hypgraph-0.8.4 → hypgraph-0.8.6}/tests/test_d10.py +0 -0
- {hypgraph-0.8.4 → hypgraph-0.8.6}/tests/test_demo_dispute.py +0 -0
- {hypgraph-0.8.4 → hypgraph-0.8.6}/tests/test_direction_and_units.py +0 -0
- {hypgraph-0.8.4 → hypgraph-0.8.6}/tests/test_engine.py +0 -0
- {hypgraph-0.8.4 → hypgraph-0.8.6}/tests/test_engine_fixes.py +0 -0
- {hypgraph-0.8.4 → hypgraph-0.8.6}/tests/test_figure_said_twice.py +0 -0
- {hypgraph-0.8.4 → hypgraph-0.8.6}/tests/test_framework_examples.py +0 -0
- {hypgraph-0.8.4 → hypgraph-0.8.6}/tests/test_i18n.py +0 -0
- {hypgraph-0.8.4 → hypgraph-0.8.6}/tests/test_incremental.py +0 -0
- {hypgraph-0.8.4 → hypgraph-0.8.6}/tests/test_link_translate.py +0 -0
- {hypgraph-0.8.4 → hypgraph-0.8.6}/tests/test_linked_records.py +0 -0
- {hypgraph-0.8.4 → hypgraph-0.8.6}/tests/test_log_and_check.py +0 -0
- {hypgraph-0.8.4 → hypgraph-0.8.6}/tests/test_measure_questions.py +0 -0
- {hypgraph-0.8.4 → hypgraph-0.8.6}/tests/test_next_order.py +0 -0
- {hypgraph-0.8.4 → hypgraph-0.8.6}/tests/test_opposed_answers.py +0 -0
- {hypgraph-0.8.4 → hypgraph-0.8.6}/tests/test_option_lead.py +0 -0
- {hypgraph-0.8.4 → hypgraph-0.8.6}/tests/test_order_detail.py +0 -0
- {hypgraph-0.8.4 → hypgraph-0.8.6}/tests/test_profiles.py +0 -0
- {hypgraph-0.8.4 → hypgraph-0.8.6}/tests/test_profiles_041.py +0 -0
- {hypgraph-0.8.4 → hypgraph-0.8.6}/tests/test_quantifiers_and_identity.py +0 -0
- {hypgraph-0.8.4 → hypgraph-0.8.6}/tests/test_questions_not_assertions.py +0 -0
- {hypgraph-0.8.4 → hypgraph-0.8.6}/tests/test_quoted_counterexample.py +0 -0
- {hypgraph-0.8.4 → hypgraph-0.8.6}/tests/test_references.py +0 -0
- {hypgraph-0.8.4 → hypgraph-0.8.6}/tests/test_refusal_friction.py +0 -0
- {hypgraph-0.8.4 → hypgraph-0.8.6}/tests/test_refusal_results.py +0 -0
- {hypgraph-0.8.4 → hypgraph-0.8.6}/tests/test_refusals.py +0 -0
- {hypgraph-0.8.4 → hypgraph-0.8.6}/tests/test_relation_words.py +0 -0
- {hypgraph-0.8.4 → hypgraph-0.8.6}/tests/test_report_answers.py +0 -0
- {hypgraph-0.8.4 → hypgraph-0.8.6}/tests/test_rerunnable.py +0 -0
- {hypgraph-0.8.4 → hypgraph-0.8.6}/tests/test_restates_scale.py +0 -0
- {hypgraph-0.8.4 → hypgraph-0.8.6}/tests/test_server_auth.py +0 -0
- {hypgraph-0.8.4 → hypgraph-0.8.6}/tests/test_server_hosts.py +0 -0
- {hypgraph-0.8.4 → hypgraph-0.8.6}/tests/test_shape_refusals.py +0 -0
- {hypgraph-0.8.4 → hypgraph-0.8.6}/tests/test_stats_not_backtests.py +0 -0
- {hypgraph-0.8.4 → hypgraph-0.8.6}/tests/test_stats_values.py +0 -0
- {hypgraph-0.8.4 → hypgraph-0.8.6}/tests/test_surfaces.py +0 -0
- {hypgraph-0.8.4 → hypgraph-0.8.6}/tests/test_telemetry_stream.py +0 -0
- {hypgraph-0.8.4 → hypgraph-0.8.6}/tests/test_trust_boundary.py +0 -0
- {hypgraph-0.8.4 → hypgraph-0.8.6}/tests/test_typed_audits.py +0 -0
- {hypgraph-0.8.4 → hypgraph-0.8.6}/tests/test_ui_app.py +0 -0
- {hypgraph-0.8.4 → hypgraph-0.8.6}/tests/test_ui_engine.py +0 -0
- {hypgraph-0.8.4 → hypgraph-0.8.6}/tests/test_ui_sources_focus.py +0 -0
- {hypgraph-0.8.4 → hypgraph-0.8.6}/tests/test_uncorrected_effect.py +0 -0
- {hypgraph-0.8.4 → hypgraph-0.8.6}/tests/test_unnamed_inputs.py +0 -0
- {hypgraph-0.8.4 → hypgraph-0.8.6}/tests/test_verify_complete.py +0 -0
- {hypgraph-0.8.4 → hypgraph-0.8.6}/tests/test_verify_lifecycle.py +0 -0
- {hypgraph-0.8.4 → hypgraph-0.8.6}/tests/test_verify_scope.py +0 -0
- {hypgraph-0.8.4 → hypgraph-0.8.6}/tests/test_verify_scoped_views.py +0 -0
- {hypgraph-0.8.4 → hypgraph-0.8.6}/tests/test_verify_trust.py +0 -0
- {hypgraph-0.8.4 → hypgraph-0.8.6}/tests/test_verify_views.py +0 -0
- {hypgraph-0.8.4 → hypgraph-0.8.6}/tests/test_vocabulary_friction.py +0 -0
- {hypgraph-0.8.4 → hypgraph-0.8.6}/tests/test_what_a_count_is_of.py +0 -0
- {hypgraph-0.8.4 → hypgraph-0.8.6}/tests/test_workflows.py +0 -0
|
@@ -1,5 +1,34 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## Unreleased
|
|
4
|
+
|
|
5
|
+
## 0.8.6 — 2026-11-07: a placeholder is not a statement
|
|
6
|
+
|
|
7
|
+
- **A figure's name is not the figure.** The slot check (`STATEMENT_EMPTY`) now refuses `$mean_tutored`,
|
|
8
|
+
`$cost_per_change$`, `<claim_id>`, and a bare name shaped like a figure standing where the figure belongs ("a
|
|
9
|
+
p-value steps_k_p", "before costs of cum_rule_before"). Over every BC-250 challenge record (1,535 claims) 13 were
|
|
10
|
+
written this way and reviewers checked three of them, one with a note listing the numbers the claim left out. A
|
|
11
|
+
name beside its value passes: "17.13 % (oos_return)", "oos_return = 0.17", "a mean_diff of 1.7"; a column named
|
|
12
|
+
`steps_k` is a name, not a slot.
|
|
13
|
+
- **A claim that is a question says nothing.** A statement ending in a question mark is refused as `STATEMENT_EMPTY`.
|
|
14
|
+
On a BC-250 run a seat wrote the question's own text as a claim superseding its right answer, and the reviewer
|
|
15
|
+
checked it, so the question settled on a question. A question followed by its answer passes as before.
|
|
16
|
+
|
|
17
|
+
## 0.8.5 — 2026-11-06: fewer false refusals
|
|
18
|
+
|
|
19
|
+
- A date a source writes as an ordinal is in the source: "the 14th of June 1887" accounts for "14 June 1887". It was refused as an unbound number, and a seat ended up with a claim saying the bridge opened "on a date".
|
|
20
|
+
- A statement with an unfilled slot is refused as STATEMENT_EMPTY: a template's `{date}`, or a variable's name where its value belongs (`accuracy = A_easy_acc`). Inline code is not read for this.
|
|
21
|
+
- **A report that denies significance isn't refused for it.** `REPORT_SIGNIFICANCE_UNBACKED` is a warning, not an
|
|
22
|
+
error, when the sentence denies the test: emphasis ("*not* significantly"), "no statistically significant difference",
|
|
23
|
+
"does not support a statistically significant advantage". Before, only the bare "not significant" counted, so an
|
|
24
|
+
honest negative was refused and small models gave up on the report. A sentence that also asserts significance
|
|
25
|
+
("not only significantly", "B is not significantly cheaper, but A is significantly better") stays an error.
|
|
26
|
+
- **A named p-value carries the test.** A result whose values name one (`p`, `p_value`, `pvalue`, `p_exact`, …) backs a
|
|
27
|
+
significance word, and so does a claim whose statement gives a p-value or that rests on such a result. Before, only a
|
|
28
|
+
value with a `p` field did, so citing the claim that held the test was refused.
|
|
29
|
+
- **A word and a figure say something.** `STATEMENT_EMPTY` no longer fires on "A's accuracy is 0.814."; placeholders
|
|
30
|
+
still do, with a number beside them or not.
|
|
31
|
+
|
|
3
32
|
## 0.8.4 — 2026-11-04: sources in the sidebar; a focus on one node's part of the graph
|
|
4
33
|
|
|
5
34
|
- **A Sources view in the Explorer's sidebar.** Everything an investigation cites, in one place: outside literature
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: hypgraph
|
|
3
|
-
Version: 0.8.
|
|
3
|
+
Version: 0.8.6
|
|
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.8.
|
|
112
|
+
## Status at 0.8.6 (2026-11-07)
|
|
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
|
|
@@ -261,6 +261,19 @@ was taken from a changelog without being checked against the code.*
|
|
|
261
261
|
> with two or more of them when the exporting and verifying processes hashed strings differently. The list now follows
|
|
262
262
|
> the order the hypotheses were added. #109 is merged with green CI. Released as 0.8.3.
|
|
263
263
|
|
|
264
|
+
> **After 0.8.5 (2026-11-07).** Checks only, no change to the bundle format: two ways a claim said nothing and got
|
|
265
|
+
> checked on the BC-250 sweeps. A statement ending in a question mark is refused (a seat wrote the question's own text
|
|
266
|
+
> as a claim superseding its right answer, and the question settled on a question); a figure's name standing where the
|
|
267
|
+
> figure belongs is refused (`$mean_tutored`, `steps_k_p`, `cum_rule_before` — 13 such claims over 1,535, three of
|
|
268
|
+
> them checked), while a name beside its value passes. Tests: `tests/test_statement_slots.py`,
|
|
269
|
+
> `tests/test_statement_is_a_question.py`. #115 and #116 are merged with green CI. Released as 0.8.6.
|
|
270
|
+
|
|
271
|
+
> **After 0.8.4 (2026-11-06).** Checks only, no change to the bundle format: false refusals found running HypSwarm on a
|
|
272
|
+
> small local model. A report that denies significance is warned, not refused; a named p-value carries the test; a word
|
|
273
|
+
> and a figure are a statement, and an unfilled slot isn't; an ordinal in a source accounts for the number. Tests:
|
|
274
|
+
> `tests/test_report_significance_denied.py`, `tests/test_statement_slots.py`, `tests/test_versions_not_figures.py`.
|
|
275
|
+
> #113 is merged with green CI. Released as 0.8.5.
|
|
276
|
+
|
|
264
277
|
> **After 0.8.3 (2026-11-04).** Explorer only, no change to the engine, the checks or the bundle format: a Sources view
|
|
265
278
|
> (what an investigation cites, with what the record did and did not check about each) and a focus on one node's part
|
|
266
279
|
> of the graph, carried in the link. The focus is computed in the browser from the record's own edges;
|
|
@@ -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.8.
|
|
19
|
+
__version__ = "0.8.6"
|
|
20
20
|
|
|
21
21
|
from .bundle import anchored, verify_bundle # noqa: E402
|
|
22
22
|
from .graph import Author, Graph, GraphError, file_sha256 # noqa: E402
|
|
@@ -4,7 +4,7 @@ and each refusal does the arithmetic the writer skipped, then offers the honest
|
|
|
4
4
|
|
|
5
5
|
code refused when
|
|
6
6
|
─────────────────────────────────────────────────────────────────────────────────────────────────────────────
|
|
7
|
-
STATEMENT_EMPTY the statement says nothing ("Placeholder.", "TBD", one word)
|
|
7
|
+
STATEMENT_EMPTY the statement says nothing ("Placeholder.", "TBD", one word, a question)
|
|
8
8
|
SCOPE_MISSING a finding or exclusion doesn't say under which conditions it holds
|
|
9
9
|
EVIDENCE_MISSING nothing supports it
|
|
10
10
|
MEASUREMENT_MALFORMED a measurement doesn't name its result and field
|
|
@@ -1598,6 +1598,15 @@ def _exclusion(s: Snap, stmt: str, kind: str, support: list[str], bound: list) -
|
|
|
1598
1598
|
"effect", words=words)]
|
|
1599
1599
|
|
|
1600
1600
|
|
|
1601
|
+
_ORDINAL = re.compile(r"\b(\d+)(?:st|nd|rd|th)\b", re.I)
|
|
1602
|
+
# a value not filled in: a template's {date} / $mean_tutored / $cost_per_change$ / <claim_id>, a variable's name where
|
|
1603
|
+
# its value belongs ("accuracy = A_easy_acc"), or a figure's name standing in the sentence as if it were the figure
|
|
1604
|
+
# ("a p-value steps_k_p", "before costs of cum_rule_before"; BC-250 sweeps 2026-11-05..07: 13 of 1,535 claims, three
|
|
1605
|
+
# of them checked by reviewers whose notes listed the numbers the claim left out). A name beside its value is not a
|
|
1606
|
+
# slot: "17.13 % (oos_return)", "oos_return = 0.17", "a mean_diff of 1.7"; a column named steps_k is a name
|
|
1607
|
+
_FIGURE_SUFFIX = r"p|pvalue|p_value|diff|before|after|return|mean|value|low|high|ci|count|ratio|gain|sd|se"
|
|
1608
|
+
_SLOT = re.compile(r"\{\s*[A-Za-z_][\w.]*\s*\}|\$\{?[A-Za-z_]\w*\}?\$?|<[A-Za-z_]\w*>|=\s*[A-Za-z]+_[A-Za-z0-9_]*\b(?!\s*\()"
|
|
1609
|
+
rf"|(?<![\w`(])[A-Za-z]+(?:_[A-Za-z]+)*_(?:{_FIGURE_SUFFIX})\b(?!\s*(?:[=:≈(\d]|is|was|of|at)\s*[-+−]?\d)(?!\s*\))")
|
|
1601
1610
|
_PLACEHOLDER = re.compile(r"^\W*(?:(?:placeholder|tbd|todo|tba|n/?a|none|wip|xxx|test|claim|statement|pending|"
|
|
1602
1611
|
r"to be (?:determined|confirmed|added)|lorem ipsum)\W*)+$", re.I)
|
|
1603
1612
|
|
|
@@ -1776,13 +1785,26 @@ def claim_issues(s: Snap, body: dict, support: list[str], inv: str) -> list[Prob
|
|
|
1776
1785
|
if invb.get("strict_claims") is False:
|
|
1777
1786
|
return []
|
|
1778
1787
|
problems: list[Problem] = []
|
|
1779
|
-
|
|
1780
|
-
|
|
1788
|
+
words = len(re.findall(r"[^\W\d_]{3,}", stmt))
|
|
1789
|
+
if _PLACEHOLDER.match(_NUM.sub("", stmt)) or words < (1 if _NUM.search(stmt) else 2):
|
|
1790
|
+
# a claim written to clear a gate (studies/challenges E2: "Placeholder.", contested and left in the record);
|
|
1791
|
+
# a word and a figure do say something: "A's accuracy is 0.814."
|
|
1781
1792
|
problems.append(Problem("STATEMENT_EMPTY", "the statement says nothing: write the finding itself — what was "
|
|
1782
1793
|
"measured, on what, and what it came to"))
|
|
1783
1794
|
if kind in ("finding", "exclusion") and len(scope.strip()) < 10:
|
|
1784
1795
|
problems.append(Problem("SCOPE_MISSING", "scope: say under which conditions this holds (the data, method, "
|
|
1785
1796
|
"sample) — at least a sentence"))
|
|
1797
|
+
slot = _SLOT.search(re.sub(r"`[^`]*`", " ", stmt))
|
|
1798
|
+
if slot:
|
|
1799
|
+
# refused the date, a seat wrote "opened on {date}", and a later version "on a date" was checked as the answer
|
|
1800
|
+
problems.append(Problem("STATEMENT_EMPTY", f"the statement has an unfilled slot ({slot.group(0).strip()}): "
|
|
1801
|
+
"write the value itself", words=[slot.group(0).strip()]))
|
|
1802
|
+
if stmt.rstrip().rstrip("'\")").endswith("?"):
|
|
1803
|
+
# a seat wrote the question's own text as the claim, as superseding its right answer, and the reviewer checked
|
|
1804
|
+
# it ("the test failures confirm the claim"): the right answer was buried under a question mark (BC-250,
|
|
1805
|
+
# 2026-11-07, E1). A question followed by its answer still ends in a sentence, and passes
|
|
1806
|
+
problems.append(Problem("STATEMENT_EMPTY", "the statement is a question: write the answer to it — what was "
|
|
1807
|
+
"found, on what, and what it came to"))
|
|
1786
1808
|
if kind == "convention" and L.HEDGE.search(stmt):
|
|
1787
1809
|
problems.append(Problem("CONVENTION_HEDGED", "a convention states agreed notation; a hedged interpretation "
|
|
1788
1810
|
"(could / suggests / consistent with) is a finding or a lead"))
|
|
@@ -1799,7 +1821,8 @@ def claim_issues(s: Snap, body: dict, support: list[str], inv: str) -> list[Prob
|
|
|
1799
1821
|
[float(c) for c in (invb.get("constants") or []) if isinstance(c, (int, float))]
|
|
1800
1822
|
for src in support: # a cited source's own text accounts for the numbers in it
|
|
1801
1823
|
sb = s.nodes[src]["body"] if s.nodes[src]["type"] == "source" else {}
|
|
1802
|
-
|
|
1824
|
+
said = " ".join(str(sb.get(k) or "") for k in ("passage", "citation", "title"))
|
|
1825
|
+
allowed += [v for v, *_ in numbers(_ORDINAL.sub(r"\1", said))] # "the 14th of June" accounts for "14 June"
|
|
1803
1826
|
if _CONVENTIONS.search(clean): # "95% interval", "α 0.05", "80% power" are conventions
|
|
1804
1827
|
allowed += [95.0, 99.0, 90.0, 80.0, 0.05, 0.01]
|
|
1805
1828
|
loose = [p for p in numbers(clean) if not _matches(p, allowed) and not _matches_stat(p, stat)]
|
|
@@ -92,6 +92,28 @@ def _asserted(pattern: re.Pattern, text: str) -> list[str]:
|
|
|
92
92
|
return [m.group(0).lower() for m in pattern.finditer(text) if not _NEGATOR.search(text[:m.start()])]
|
|
93
93
|
|
|
94
94
|
|
|
95
|
+
_P_KEY = re.compile(r"p(?:[_-]?val(?:ue)?|_[a-z0-9_]+)?", re.I)
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
def _carries_test(s: D.Snap, nid: str) -> bool:
|
|
99
|
+
"""Does this node hold a test: a two-sample count the record worked out, a value with a p, a value named as one
|
|
100
|
+
(p_value, p_exact, pvalue), or, for a claim, its own statement's p-value or any such result it rests on?"""
|
|
101
|
+
def holds(n: str) -> bool:
|
|
102
|
+
vals = s.nodes[n]["body"].get("values") or {}
|
|
103
|
+
return bool(D.state(s, n).get("test")) or any(
|
|
104
|
+
_P_KEY.fullmatch(str(k)) or (isinstance(v, dict) and "p" in v) for k, v in vals.items())
|
|
105
|
+
if holds(nid):
|
|
106
|
+
return True
|
|
107
|
+
n = s.nodes[nid]
|
|
108
|
+
if n["type"] != "claim":
|
|
109
|
+
return False
|
|
110
|
+
if _P_VALUE.search(n["body"].get("statement") or ""):
|
|
111
|
+
return True
|
|
112
|
+
bound = [m.get("result") for m in n["body"].get("measurements") or [] if isinstance(m, dict)]
|
|
113
|
+
rests = [e["dst"] for e in s.out.get(nid, []) if e["rel"] == "derived_from"]
|
|
114
|
+
return any(holds(r) for r in [*bound, *rests] if r in s.nodes)
|
|
115
|
+
|
|
116
|
+
|
|
95
117
|
def _blank(m: re.Match) -> str:
|
|
96
118
|
return re.sub(r"[^\n]", " ", m.group(0))
|
|
97
119
|
|
|
@@ -286,9 +308,10 @@ def check(g: "Graph", text: str, inv: str = "") -> dict:
|
|
|
286
308
|
f"'{causal[0]}' is causal and no claim is cited — cite the claim backed by an experiment, or say "
|
|
287
309
|
"'is associated with'.")
|
|
288
310
|
sig = L.found(L.SIGNIFICANCE, own)
|
|
289
|
-
if sig and not _P_VALUE.search(sent) and not any(
|
|
290
|
-
|
|
291
|
-
|
|
311
|
+
if sig and not _P_VALUE.search(sent) and not any(_carries_test(s, c) for c in cited):
|
|
312
|
+
# the sentence denies the test rather than claims it: emphasis ("*not* significantly") is no assertion
|
|
313
|
+
plain = re.sub(r"\bnot\s+(?:only|just|merely)\b", "", re.sub(r"[*_]", "", own), flags=re.I)
|
|
314
|
+
negated = bool(L.denied(L.SIGNIFICANCE, plain)) and not L.asserted(L.SIGNIFICANCE, plain)
|
|
292
315
|
add(ln, "warning" if negated else "error", "REPORT_SIGNIFICANCE_UNBACKED", sent,
|
|
293
316
|
f"'{sig[0]}' — cite the claim or result that carries the test.")
|
|
294
317
|
_check_answers(s, text or "", invs, by_code, add, counted)
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
"""0.8.5: a report that says a difference was NOT significant isn't claiming a test passed, and a claim resting on a
|
|
2
|
+
named p-value carries its test. From gpt-oss runs on a small box: leads wrote "*not* significantly" and were refused
|
|
3
|
+
until they gave up, so two of six runs ended with no interpretation."""
|
|
4
|
+
import pytest
|
|
5
|
+
|
|
6
|
+
from hypgraph import Graph, Policy
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def _record(values):
|
|
10
|
+
g = Graph(policy=Policy(reviewers={"critic"}))
|
|
11
|
+
inv = g.create(author="h", type="investigation", fields={"title": "Does A beat B.", "objective": "Compare A and B on the same items."})["id"]
|
|
12
|
+
q = g.create(author="h", type="question", inv=inv, code="Q2",
|
|
13
|
+
fields={"text": "Is A significantly more accurate than B (two-sided, 0.05)?"})["id"]
|
|
14
|
+
r = g.create(author="stats", type="run", inv=inv, fields={"kind": "agent", "name": "mcnemar", "state": "succeeded"})
|
|
15
|
+
rs = g.create(author="stats", type="result", inv=inv, fields={"summary": "McNemar test on the same 1,000 items.", "values": values},
|
|
16
|
+
links=[{"rel": "produced", "from": r["id"]}])
|
|
17
|
+
c = g.create(author="stats", type="claim", inv=inv,
|
|
18
|
+
fields={"statement": "The McNemar test on the 1,000 shared items gave the value in the result.",
|
|
19
|
+
"scope": "The 1,000 shared items."},
|
|
20
|
+
links=[{"rel": "answers", "to": q}, {"rel": "derived_from", "to": rs["id"]}])
|
|
21
|
+
return g, inv, c["code"], rs["code"]
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def _sig(g, text, inv):
|
|
25
|
+
return [f["level"] for f in g.check_text(text, inv)["findings"] if f["code"] == "REPORT_SIGNIFICANCE_UNBACKED"]
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
@pytest.mark.parametrize("sentence", [
|
|
29
|
+
"Model A is *not* significantly more accurate than model B.",
|
|
30
|
+
"Model A is **not** significantly more accurate than model B.",
|
|
31
|
+
"There is no statistically significant difference between A and B.",
|
|
32
|
+
"The evidence does not support a statistically significant advantage for A.",
|
|
33
|
+
"The test did not reach statistical significance, so A is not significantly better.",
|
|
34
|
+
])
|
|
35
|
+
def test_a_denial_is_a_warning_not_a_refusal(sentence):
|
|
36
|
+
g, inv, _, _ = _record({"chi2": {"value": 3.0}})
|
|
37
|
+
assert _sig(g, sentence, inv) in (["warning"], [])
|
|
38
|
+
assert g.check_text(sentence, inv)["errors"] == 0
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
@pytest.mark.parametrize("sentence", [
|
|
42
|
+
"A is significantly more accurate than B.",
|
|
43
|
+
"A is not only significantly more accurate than B, it is cheaper.",
|
|
44
|
+
"A is not worse, and it is significantly more accurate than B.",
|
|
45
|
+
"B is not significantly cheaper, but A is significantly more accurate.",
|
|
46
|
+
])
|
|
47
|
+
def test_an_assertion_is_still_refused(sentence):
|
|
48
|
+
g, inv, _, _ = _record({"chi2": {"value": 3.0}})
|
|
49
|
+
assert _sig(g, sentence, inv) == ["error"]
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
@pytest.mark.parametrize("key", ["p", "p_value", "pvalue", "p-value", "p_exact", "p_two"])
|
|
53
|
+
def test_a_named_p_value_carries_the_test(key):
|
|
54
|
+
g, inv, cl, rs = _record({key: {"value": 0.03}})
|
|
55
|
+
assert _sig(g, f"A is significantly more accurate than B ({rs}).", inv) == [] # the result itself
|
|
56
|
+
assert _sig(g, f"A is significantly more accurate than B ({cl}).", inv) == [] # the claim that rests on it
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def test_a_claim_without_a_test_does_not_carry_one():
|
|
60
|
+
g, inv, cl, rs = _record({"pct_a": {"value": 90.0}, "pairs": {"value": 322}, "chi2": {"value": 3.0}})
|
|
61
|
+
assert _sig(g, f"A is significantly more accurate than B ({cl}).", inv) == ["error"]
|
|
62
|
+
assert _sig(g, f"A is significantly more accurate than B ({rs}).", inv) == ["error"]
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"""A claim that is a question says nothing. On a BC-250 run of the bug-fix challenge (2026-11-07) a seat wrote the
|
|
2
|
+
question's own text as a claim, "Which tests in test_semver.py fail on the original semver.py, and what causes each
|
|
3
|
+
failure?", linked it as superseding its right answer, and the reviewer checked it: the question settled on a question."""
|
|
4
|
+
from __future__ import annotations
|
|
5
|
+
|
|
6
|
+
import pytest
|
|
7
|
+
|
|
8
|
+
from hypgraph import Graph, GraphError, Policy
|
|
9
|
+
|
|
10
|
+
QUESTION = "Which tests in test_semver.py fail on the original semver.py, and what causes each failure?"
|
|
11
|
+
ANSWER = ("test_minor_numeric, test_prerelease_before_release and test_newest fail on the original semver.py, because "
|
|
12
|
+
"compare() orders numeric parts as strings.")
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def _record():
|
|
16
|
+
g = Graph(policy=Policy(reviewers={"critic"}))
|
|
17
|
+
inv = g.create(author="a", type="investigation", fields={
|
|
18
|
+
"title": "semver", "objective": "Fix the version comparison.", "profile": "software@2"})["id"]
|
|
19
|
+
q = g.create(author="a", type="question", inv=inv, fields={"text": QUESTION})["id"]
|
|
20
|
+
run = g.create(author="a", type="run", inv=inv, fields={"kind": "agent", "name": "pytest on the original",
|
|
21
|
+
"state": "succeeded", "config": {"source": "pytest -q _base"}})["id"]
|
|
22
|
+
res = g.create(author="a", type="result", inv=inv, fields={
|
|
23
|
+
"summary": "Three of six tests fail on the original.", "values": {"tests_passed": {"k": 3, "n": 6}}},
|
|
24
|
+
links=[{"rel": "produced", "from": run}])["id"]
|
|
25
|
+
return g, inv, q, res
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def _claim(g, inv, q, res, statement):
|
|
29
|
+
return g.create(author="a", type="claim", inv=inv, fields={
|
|
30
|
+
"statement": statement, "scope": "The six tests in test_semver.py, run on the kept copy of semver.py."},
|
|
31
|
+
links=[{"rel": "answers", "to": q}, {"rel": "supports", "from": res, "why": "the run shows which tests fail"}])
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
@pytest.mark.parametrize("statement", [QUESTION, "Does the original fail test_newest?", "Which tests fail? "])
|
|
35
|
+
def test_a_claim_that_is_a_question_is_refused(statement):
|
|
36
|
+
g, inv, q, res = _record()
|
|
37
|
+
with pytest.raises(GraphError, match="STATEMENT_EMPTY") as e:
|
|
38
|
+
_claim(g, inv, q, res, statement)
|
|
39
|
+
assert "is a question" in str(e.value)
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
@pytest.mark.parametrize("statement", [ANSWER, f"Which tests fail on the original semver.py? {ANSWER}", "Why? Because compare() orders numeric parts as strings."])
|
|
43
|
+
def test_an_answer_passes_with_or_without_the_question_before_it(statement):
|
|
44
|
+
g, inv, q, res = _record()
|
|
45
|
+
assert _claim(g, inv, q, res, statement)["id"]
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def test_the_refusal_names_what_to_write():
|
|
49
|
+
g, inv, q, res = _record()
|
|
50
|
+
with pytest.raises(GraphError, match="write the answer to it"):
|
|
51
|
+
_claim(g, inv, q, res, QUESTION)
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
"""A number a source writes as an ordinal is in the source, and a statement with a slot in it says nothing. Found on a
|
|
2
|
+
BC-250 run of the knowledge challenge: the passage said "the 14th of June 1887", "14 June 1887" was refused as unbound
|
|
3
|
+
12 times, the seat wrote "opened on {date}", then "opened on a date", and that was checked as the answer."""
|
|
4
|
+
from __future__ import annotations
|
|
5
|
+
|
|
6
|
+
import pytest
|
|
7
|
+
|
|
8
|
+
from hypgraph import Graph, GraphError, Policy
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def _record():
|
|
12
|
+
g = Graph(policy=Policy(reviewers={"critic"}))
|
|
13
|
+
inv = g.create(author="a", type="investigation", fields={
|
|
14
|
+
"title": "The footbridge", "objective": "When did the footbridge open?", "profile": "knowledge@2"})["id"]
|
|
15
|
+
src = g.create(author="a", type="source", inv=inv, fields={
|
|
16
|
+
"url": "file:archive/minutes.md", "kind": "primary", "retrieved": "2026-11-05",
|
|
17
|
+
"citation": "Council minutes, 2 May",
|
|
18
|
+
"passage": "Resolved that the bridge be opened to the public on Tuesday the 14th of June 1887."})["id"]
|
|
19
|
+
return g, inv, src
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def _claim(g, inv, src, statement):
|
|
23
|
+
return g.create(author="a", type="claim", inv=inv, fields={
|
|
24
|
+
"statement": statement, "scope": "The council minutes of the town, read in full."},
|
|
25
|
+
links=[{"rel": "cites", "to": src}, {"rel": "supports", "from": src, "why": "the minutes name the day it opened"}])
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
@pytest.mark.parametrize("statement", ["The footbridge opened to the public on 14 June 1887.",
|
|
29
|
+
"The footbridge opened to the public on the 14th of June 1887."])
|
|
30
|
+
def test_a_date_written_as_an_ordinal_is_in_the_source(statement):
|
|
31
|
+
g, inv, src = _record()
|
|
32
|
+
assert _claim(g, inv, src, statement)["id"]
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def test_a_number_the_source_doesnt_have_stays_unbound():
|
|
36
|
+
g, inv, src = _record()
|
|
37
|
+
with pytest.raises(GraphError, match="UNBOUND_NUMBER"):
|
|
38
|
+
_claim(g, inv, src, "The footbridge opened to the public on 15 June 1887.")
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
@pytest.mark.parametrize("statement", [
|
|
42
|
+
"The footbridge opened to the public on {date}.",
|
|
43
|
+
"The footbridge opened to the public on { date }.",
|
|
44
|
+
"Model A easy accuracy = A_easy_acc on the items.",
|
|
45
|
+
"The strategy with fast window {fast_window} returned the most.",
|
|
46
|
+
# BC-250 sweeps (2026-11-06/07): $name, $name$, and a figure's name in the sentence — three of these were checked
|
|
47
|
+
"The mean gain from test 1 to test 2 was $mean_tutored for tutored pupils.",
|
|
48
|
+
"The rule returned less after paying $cost_per_change$ per position change.",
|
|
49
|
+
"The rule returned ${cost} after costs.",
|
|
50
|
+
"The only outcome that differed is steps_k, with a p-value steps_k_p.",
|
|
51
|
+
"The rule achieved a cumulative return before costs of cum_rule_before.",
|
|
52
|
+
"Over the calls of the fixed sample_three, duplicate_count returned a repeated winner.",
|
|
53
|
+
"The claim <claim_id> answers the question about the footbridge.",
|
|
54
|
+
])
|
|
55
|
+
def test_a_statement_with_a_slot_is_refused(statement):
|
|
56
|
+
g, inv, src = _record()
|
|
57
|
+
with pytest.raises(GraphError, match="STATEMENT_EMPTY") as e:
|
|
58
|
+
_claim(g, inv, src, statement)
|
|
59
|
+
assert "unfilled slot" in str(e.value)
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
@pytest.mark.parametrize("statement", [
|
|
63
|
+
"The minutes set the option `retry = max_tries` for the footbridge.",
|
|
64
|
+
"The function returned `{date}` for the footbridge.",
|
|
65
|
+
"The footbridge opened in the summer, as the minutes say.",
|
|
66
|
+
"The minutes say steps_k differs between the arms for the footbridge.",
|
|
67
|
+
])
|
|
68
|
+
def test_code_and_plain_sentences_are_not_slots(statement):
|
|
69
|
+
g, inv, src = _record()
|
|
70
|
+
assert _claim(g, inv, src, statement)["id"]
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
@pytest.mark.parametrize("statement", [
|
|
74
|
+
"The out-of-sample return is 17.13 % (oos_return), versus -17.08 % (buy_and_hold_return).",
|
|
75
|
+
"oos_return = 0.1713 and bh_return: -0.1708 out of sample.",
|
|
76
|
+
"A mean_diff of 1.7 points, with a p_value of 0.33.",
|
|
77
|
+
"The bridge cost $4,210 according to the minutes.",
|
|
78
|
+
"steps_k_p is 0.012 and steps_k_diff was -0.8 steps.",
|
|
79
|
+
])
|
|
80
|
+
def test_a_name_beside_its_figure_is_not_a_slot(statement):
|
|
81
|
+
from hypgraph.checks import _SLOT
|
|
82
|
+
assert not _SLOT.search(statement), _SLOT.search(statement)
|
|
@@ -76,3 +76,11 @@ def test_a_statement_that_says_nothing_is_refused(tmp_path):
|
|
|
76
76
|
for i, stmt in enumerate(("Placeholder.", "Placeholder claim.", "TBD — pending.", "To be determined.", "1234567890 ...")):
|
|
77
77
|
assert "STATEMENT_EMPTY" in _claim_error(tmp_path / f"{i}.hypgraph", stmt), stmt
|
|
78
78
|
assert _claim_error(tmp_path / "real.hypgraph", "parse_duration truncates rather than rounds.") == ""
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def test_a_word_and_a_figure_say_something(tmp_path):
|
|
82
|
+
"""From gpt-oss runs: "A's accuracy is 0.814." has one word of three letters, and was refused as saying nothing."""
|
|
83
|
+
for i, stmt in enumerate(("A's accuracy is 0.814.", "Accuracy: 81.4 %.")):
|
|
84
|
+
assert "STATEMENT_EMPTY" not in _claim_error(tmp_path / f"{i}.hypgraph", stmt), stmt
|
|
85
|
+
for i, stmt in enumerate(("TBD 12.", "Placeholder 3.", "Placeholder 3 — pending.", "See RS1.", "12.")):
|
|
86
|
+
assert _claim_error(tmp_path / f"e{i}.hypgraph", stmt), stmt # some are too short to reach this check
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|