hybrid-recursive-ladder 0.0.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.
- hybrid_recursive_ladder-0.0.6/.gitignore +34 -0
- hybrid_recursive_ladder-0.0.6/.zenodo.json +37 -0
- hybrid_recursive_ladder-0.0.6/CHANGELOG.md +175 -0
- hybrid_recursive_ladder-0.0.6/CHANGELOG.zh-CN.md +154 -0
- hybrid_recursive_ladder-0.0.6/CITATION.cff +28 -0
- hybrid_recursive_ladder-0.0.6/CONTRIBUTING.md +120 -0
- hybrid_recursive_ladder-0.0.6/CONTRIBUTING.zh-CN.md +114 -0
- hybrid_recursive_ladder-0.0.6/LICENSE +21 -0
- hybrid_recursive_ladder-0.0.6/LICENSE.zh-CN.md +19 -0
- hybrid_recursive_ladder-0.0.6/PKG-INFO +478 -0
- hybrid_recursive_ladder-0.0.6/README.ar.md +210 -0
- hybrid_recursive_ladder-0.0.6/README.de.md +210 -0
- hybrid_recursive_ladder-0.0.6/README.es.md +210 -0
- hybrid_recursive_ladder-0.0.6/README.fr.md +210 -0
- hybrid_recursive_ladder-0.0.6/README.hi.md +210 -0
- hybrid_recursive_ladder-0.0.6/README.ja.md +210 -0
- hybrid_recursive_ladder-0.0.6/README.ko.md +210 -0
- hybrid_recursive_ladder-0.0.6/README.md +405 -0
- hybrid_recursive_ladder-0.0.6/README.pt-BR.md +210 -0
- hybrid_recursive_ladder-0.0.6/README.ru.md +210 -0
- hybrid_recursive_ladder-0.0.6/README.zh-CN.md +337 -0
- hybrid_recursive_ladder-0.0.6/docs/README.md +46 -0
- hybrid_recursive_ladder-0.0.6/docs/README.zh-CN.md +45 -0
- hybrid_recursive_ladder-0.0.6/docs/algorithm.md +392 -0
- hybrid_recursive_ladder-0.0.6/docs/algorithm.zh-CN.md +288 -0
- hybrid_recursive_ladder-0.0.6/docs/api.md +313 -0
- hybrid_recursive_ladder-0.0.6/docs/api.zh-CN.md +311 -0
- hybrid_recursive_ladder-0.0.6/docs/architecture.md +253 -0
- hybrid_recursive_ladder-0.0.6/docs/architecture.zh-CN.md +244 -0
- hybrid_recursive_ladder-0.0.6/docs/articles/why-per-bucket-queries-are-slow.md +228 -0
- hybrid_recursive_ladder-0.0.6/docs/articles/why-per-bucket-queries-are-slow.zh-CN.md +171 -0
- hybrid_recursive_ladder-0.0.6/docs/assets/architecture.png +0 -0
- hybrid_recursive_ladder-0.0.6/docs/assets/architecture.svg +99 -0
- hybrid_recursive_ladder-0.0.6/docs/assets/architecture.zh-CN.png +0 -0
- hybrid_recursive_ladder-0.0.6/docs/assets/architecture.zh-CN.svg +99 -0
- hybrid_recursive_ladder-0.0.6/docs/assets/decomposition.png +0 -0
- hybrid_recursive_ladder-0.0.6/docs/assets/decomposition.svg +68 -0
- hybrid_recursive_ladder-0.0.6/docs/assets/decomposition.zh-CN.png +0 -0
- hybrid_recursive_ladder-0.0.6/docs/assets/decomposition.zh-CN.svg +68 -0
- hybrid_recursive_ladder-0.0.6/docs/assets/hero.ar.png +0 -0
- hybrid_recursive_ladder-0.0.6/docs/assets/hero.ar.svg +99 -0
- hybrid_recursive_ladder-0.0.6/docs/assets/hero.de.png +0 -0
- hybrid_recursive_ladder-0.0.6/docs/assets/hero.de.svg +99 -0
- hybrid_recursive_ladder-0.0.6/docs/assets/hero.es.png +0 -0
- hybrid_recursive_ladder-0.0.6/docs/assets/hero.es.svg +99 -0
- hybrid_recursive_ladder-0.0.6/docs/assets/hero.fr.png +0 -0
- hybrid_recursive_ladder-0.0.6/docs/assets/hero.fr.svg +99 -0
- hybrid_recursive_ladder-0.0.6/docs/assets/hero.hi.png +0 -0
- hybrid_recursive_ladder-0.0.6/docs/assets/hero.hi.svg +99 -0
- hybrid_recursive_ladder-0.0.6/docs/assets/hero.ja.png +0 -0
- hybrid_recursive_ladder-0.0.6/docs/assets/hero.ja.svg +99 -0
- hybrid_recursive_ladder-0.0.6/docs/assets/hero.ko.png +0 -0
- hybrid_recursive_ladder-0.0.6/docs/assets/hero.ko.svg +99 -0
- hybrid_recursive_ladder-0.0.6/docs/assets/hero.png +0 -0
- hybrid_recursive_ladder-0.0.6/docs/assets/hero.pt-BR.png +0 -0
- hybrid_recursive_ladder-0.0.6/docs/assets/hero.pt-BR.svg +99 -0
- hybrid_recursive_ladder-0.0.6/docs/assets/hero.ru.png +0 -0
- hybrid_recursive_ladder-0.0.6/docs/assets/hero.ru.svg +99 -0
- hybrid_recursive_ladder-0.0.6/docs/assets/hero.svg +99 -0
- hybrid_recursive_ladder-0.0.6/docs/assets/hero.zh-CN.png +0 -0
- hybrid_recursive_ladder-0.0.6/docs/assets/hero.zh-CN.svg +99 -0
- hybrid_recursive_ladder-0.0.6/docs/benchmarks.md +117 -0
- hybrid_recursive_ladder-0.0.6/docs/benchmarks.zh-CN.md +102 -0
- hybrid_recursive_ladder-0.0.6/docs/defensive-publication.md +246 -0
- hybrid_recursive_ladder-0.0.6/docs/defensive-publication.zh-CN.md +213 -0
- hybrid_recursive_ladder-0.0.6/docs/i18n.js +916 -0
- hybrid_recursive_ladder-0.0.6/docs/index.html +297 -0
- hybrid_recursive_ladder-0.0.6/docs/prior-art-matrix.csv +13 -0
- hybrid_recursive_ladder-0.0.6/docs/prior-art-matrix.zh-CN.csv +13 -0
- hybrid_recursive_ladder-0.0.6/docs/prior-art-search.zh-CN.md +322 -0
- hybrid_recursive_ladder-0.0.6/docs/publishing.md +122 -0
- hybrid_recursive_ladder-0.0.6/docs/related-work.md +198 -0
- hybrid_recursive_ladder-0.0.6/docs/related-work.zh-CN.md +108 -0
- hybrid_recursive_ladder-0.0.6/docs/robots.txt +3 -0
- hybrid_recursive_ladder-0.0.6/docs/sitemap.xml +9 -0
- hybrid_recursive_ladder-0.0.6/examples/benchmark.py +73 -0
- hybrid_recursive_ladder-0.0.6/examples/fastapi_app.py +21 -0
- hybrid_recursive_ladder-0.0.6/examples/mixed_read.py +61 -0
- hybrid_recursive_ladder-0.0.6/examples/quickstart.py +39 -0
- hybrid_recursive_ladder-0.0.6/examples/thingsboard.py +85 -0
- hybrid_recursive_ladder-0.0.6/pyproject.toml +114 -0
- hybrid_recursive_ladder-0.0.6/skills/README.md +61 -0
- hybrid_recursive_ladder-0.0.6/skills/README.zh-CN.md +60 -0
- hybrid_recursive_ladder-0.0.6/skills/hybrid-recursive-ladder/SKILL.md +183 -0
- hybrid_recursive_ladder-0.0.6/skills/hybrid-recursive-ladder/SKILL.zh-CN.md +172 -0
- hybrid_recursive_ladder-0.0.6/skills/hybrid-recursive-ladder/reference.md +105 -0
- hybrid_recursive_ladder-0.0.6/skills/hybrid-recursive-ladder/reference.zh-CN.md +105 -0
- hybrid_recursive_ladder-0.0.6/src/hybrid_ladder/__init__.py +109 -0
- hybrid_recursive_ladder-0.0.6/src/hybrid_ladder/api.py +392 -0
- hybrid_recursive_ladder-0.0.6/src/hybrid_ladder/cli.py +483 -0
- hybrid_recursive_ladder-0.0.6/src/hybrid_ladder/core.py +300 -0
- hybrid_recursive_ladder-0.0.6/src/hybrid_ladder/demo.py +60 -0
- hybrid_recursive_ladder-0.0.6/src/hybrid_ladder/engine.py +688 -0
- hybrid_recursive_ladder-0.0.6/src/hybrid_ladder/errors.py +24 -0
- hybrid_recursive_ladder-0.0.6/src/hybrid_ladder/mcp_server.py +215 -0
- hybrid_recursive_ladder-0.0.6/src/hybrid_ladder/models.py +255 -0
- hybrid_recursive_ladder-0.0.6/src/hybrid_ladder/protocols.py +115 -0
- hybrid_recursive_ladder-0.0.6/src/hybrid_ladder/py.typed +0 -0
- hybrid_recursive_ladder-0.0.6/src/hybrid_ladder/runtime.py +72 -0
- hybrid_recursive_ladder-0.0.6/src/hybrid_ladder/sources/__init__.py +7 -0
- hybrid_recursive_ladder-0.0.6/src/hybrid_ladder/sources/memory.py +87 -0
- hybrid_recursive_ladder-0.0.6/src/hybrid_ladder/sources/thingsboard.py +230 -0
- hybrid_recursive_ladder-0.0.6/src/hybrid_ladder/stores/__init__.py +15 -0
- hybrid_recursive_ladder-0.0.6/src/hybrid_ladder/stores/memory.py +99 -0
- hybrid_recursive_ladder-0.0.6/src/hybrid_ladder/stores/postgres.py +437 -0
- hybrid_recursive_ladder-0.0.6/src/hybrid_ladder/tasks.py +203 -0
- hybrid_recursive_ladder-0.0.6/tests/conftest.py +34 -0
- hybrid_recursive_ladder-0.0.6/tests/helpers.py +39 -0
- hybrid_recursive_ladder-0.0.6/tests/test_api.py +198 -0
- hybrid_recursive_ladder-0.0.6/tests/test_cli.py +121 -0
- hybrid_recursive_ladder-0.0.6/tests/test_core.py +208 -0
- hybrid_recursive_ladder-0.0.6/tests/test_engine.py +253 -0
- hybrid_recursive_ladder-0.0.6/tests/test_mcp.py +116 -0
- hybrid_recursive_ladder-0.0.6/tests/test_mixed.py +146 -0
- hybrid_recursive_ladder-0.0.6/tests/test_postgres_integration.py +109 -0
- hybrid_recursive_ladder-0.0.6/tests/test_tasks.py +118 -0
- hybrid_recursive_ladder-0.0.6/tests/test_thingsboard.py +156 -0
- hybrid_recursive_ladder-0.0.6/tests/test_verify_repair.py +154 -0
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*.egg-info/
|
|
5
|
+
.eggs/
|
|
6
|
+
build/
|
|
7
|
+
dist/
|
|
8
|
+
.venv/
|
|
9
|
+
.venv-*/
|
|
10
|
+
venv/
|
|
11
|
+
env/
|
|
12
|
+
|
|
13
|
+
# Tooling
|
|
14
|
+
.pytest_cache/
|
|
15
|
+
.ruff_cache/
|
|
16
|
+
.mypy_cache/
|
|
17
|
+
.coverage
|
|
18
|
+
.coverage.*
|
|
19
|
+
htmlcov/
|
|
20
|
+
coverage.xml
|
|
21
|
+
|
|
22
|
+
# Editors / OS
|
|
23
|
+
.idea/
|
|
24
|
+
.vscode/
|
|
25
|
+
.DS_Store
|
|
26
|
+
Thumbs.db
|
|
27
|
+
|
|
28
|
+
# Local configuration and data
|
|
29
|
+
.env
|
|
30
|
+
.env.*
|
|
31
|
+
*.local
|
|
32
|
+
data/
|
|
33
|
+
*.db
|
|
34
|
+
*.sqlite3
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
{
|
|
2
|
+
"title": "Hybrid Recursive Ladder: Query Planning for Bucket-Limited Time-Series APIs",
|
|
3
|
+
"description": "<p>A query-planning method for long-range time-series aggregation over APIs with a hard per-request bucket limit. The range is decomposed into complete calendar units; each maximal contiguous run sharing a fetch level is fetched once at the next finer aggregation and folded locally; optional coverage tracking fetches only uncovered sub-ranges.</p><p>This release is a public disclosure of the method and its formal properties. It is a composition of calendar mixed-radix decomposition, canonical interval decomposition, roll-up and multi-resolution aggregation. The code is released under the MIT License.</p>",
|
|
4
|
+
"creators": [
|
|
5
|
+
{
|
|
6
|
+
"name": "MagicSquarekey",
|
|
7
|
+
"affiliation": "Independent"
|
|
8
|
+
}
|
|
9
|
+
],
|
|
10
|
+
"license": "MIT",
|
|
11
|
+
"upload_type": "software",
|
|
12
|
+
"access_right": "open",
|
|
13
|
+
"publication_date": "2026-10-27",
|
|
14
|
+
"version": "0.0.6",
|
|
15
|
+
"keywords": [
|
|
16
|
+
"time series",
|
|
17
|
+
"aggregation",
|
|
18
|
+
"query planning",
|
|
19
|
+
"downsampling",
|
|
20
|
+
"multi-resolution",
|
|
21
|
+
"ThingsBoard",
|
|
22
|
+
"observability"
|
|
23
|
+
],
|
|
24
|
+
"related_identifiers": [
|
|
25
|
+
{
|
|
26
|
+
"identifier": "https://github.com/MagicSquarekey/hybrid_recursive_ladder_algorithm",
|
|
27
|
+
"relation": "isSupplementTo",
|
|
28
|
+
"scheme": "url"
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
"identifier": "https://github.com/MagicSquarekey/hybrid_recursive_ladder_algorithm/blob/main/docs/defensive-publication.md",
|
|
32
|
+
"relation": "isDocumentedBy",
|
|
33
|
+
"scheme": "url"
|
|
34
|
+
}
|
|
35
|
+
],
|
|
36
|
+
"notes": "Public disclosure / prior art for the Hybrid Recursive Ladder query-planning method."
|
|
37
|
+
}
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
**语言 / Languages:** [English](CHANGELOG.md) · [简体中文](CHANGELOG.zh-CN.md)
|
|
4
|
+
|
|
5
|
+
All notable changes to this project are documented here. The format follows
|
|
6
|
+
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and the project uses
|
|
7
|
+
[Semantic Versioning](https://semver.org/spec/v2.0.0.html) from 0.0.1 onward.
|
|
8
|
+
|
|
9
|
+
## [0.0.6] — 2026-10-27
|
|
10
|
+
|
|
11
|
+
Documentation and site release. No algorithm, API, wire-format or storage
|
|
12
|
+
changes.
|
|
13
|
+
|
|
14
|
+
### Added
|
|
15
|
+
|
|
16
|
+
* Zenodo archive and DOI: [10.5281/zenodo.23683292](https://doi.org/10.5281/zenodo.23683292).
|
|
17
|
+
* Chinese versions for every document in the repository. All 14 prose documents
|
|
18
|
+
now have a `.zh-CN.md` mirror — including the API reference, architecture,
|
|
19
|
+
benchmarks, changelog, contributing guide and the agent skill — and the
|
|
20
|
+
prior-art matrix has a Chinese CSV.
|
|
21
|
+
* `docs/README.md` / `docs/README.zh-CN.md`: a documentation index for every
|
|
22
|
+
document, project-level file and diagram in both languages.
|
|
23
|
+
* `tools/check_docs_i18n.py`: fails CI when a document lacks a Chinese mirror,
|
|
24
|
+
a diagram lacks `zh-CN` SVG/PNG assets, or a new document is not registered.
|
|
25
|
+
* An 11-language switcher on the documentation site, with `?lang=` deep links,
|
|
26
|
+
a saved preference, translated metadata and right-to-left layout for Arabic.
|
|
27
|
+
|
|
28
|
+
### Changed
|
|
29
|
+
|
|
30
|
+
* Every document carries an English / 简体中文 switch at the top.
|
|
31
|
+
* Chinese documents use the Chinese diagrams; other languages keep the English
|
|
32
|
+
or their localized hero image.
|
|
33
|
+
* On the site, Chinese mode links to the Chinese editions of the algorithm,
|
|
34
|
+
prior-art, article and disclosure pages.
|
|
35
|
+
* Install snippets, badges, API examples and metadata now reference `0.0.6`.
|
|
36
|
+
|
|
37
|
+
### Fixed
|
|
38
|
+
|
|
39
|
+
* The benchmark table on the landing page no longer collapses: the badge rule
|
|
40
|
+
is scoped to cards and wide tables scroll horizontally.
|
|
41
|
+
* Numeric ranges and arrows keep left-to-right order in the Arabic RTL layout.
|
|
42
|
+
|
|
43
|
+
## [0.0.5] — 2026-10-26
|
|
44
|
+
|
|
45
|
+
### Added
|
|
46
|
+
|
|
47
|
+
* MCP tool annotations on all four tools: a human-readable `title` plus
|
|
48
|
+
`readOnlyHint`, `destructiveHint`, `idempotentHint` and `openWorldHint`.
|
|
49
|
+
Clients can now tell that `ladder_meta` and `ladder_decompose` are local and
|
|
50
|
+
side-effect free, that `ladder_sum` can write to the local store through
|
|
51
|
+
`materialize=True`, and that `ladder_verify` reaches the source.
|
|
52
|
+
* Per-language README diagrams. `docs/assets/hero.<lang>.png` ships for every
|
|
53
|
+
translated README, and `decomposition`/`architecture` are also localized for
|
|
54
|
+
Chinese. `tools/localize_assets.py` regenerates them from the English SVGs.
|
|
55
|
+
|
|
56
|
+
### Fixed
|
|
57
|
+
|
|
58
|
+
* `tests/test_mcp.py` now accepts the `(content, structured)` return value of
|
|
59
|
+
`call_tool` in current MCP SDK releases; the previous assertions failed on
|
|
60
|
+
`mcp` 1.27 and later.
|
|
61
|
+
|
|
62
|
+
## [0.0.4] — 2026-10-22
|
|
63
|
+
|
|
64
|
+
Documentation release. No code or algorithm changes. Reworks the READMEs and
|
|
65
|
+
adds diagrams.
|
|
66
|
+
|
|
67
|
+
### Added
|
|
68
|
+
|
|
69
|
+
* Zenodo archive and DOI: [10.5281/zenodo.23557574](https://doi.org/10.5281/zenodo.23557574).
|
|
70
|
+
|
|
71
|
+
### Changed
|
|
72
|
+
|
|
73
|
+
* Reworked `README.md` and `README.zh-CN.md` into a single narrative with
|
|
74
|
+
diagrams for the before/after comparison, calendar decomposition and
|
|
75
|
+
local-first read path.
|
|
76
|
+
* Added the hero diagram and DOI/website badges to the other language READMEs.
|
|
77
|
+
* Bumped the package version to `0.0.4`.
|
|
78
|
+
|
|
79
|
+
## [0.0.3] — 2026-10-22
|
|
80
|
+
|
|
81
|
+
Archival release. No code or algorithm changes. This release triggers Zenodo's
|
|
82
|
+
GitHub integration so the public disclosure receives a DOI.
|
|
83
|
+
|
|
84
|
+
### Added
|
|
85
|
+
|
|
86
|
+
* Zenodo archive and DOI: [10.5281/zenodo.23556606](https://doi.org/10.5281/zenodo.23556606).
|
|
87
|
+
|
|
88
|
+
### Changed
|
|
89
|
+
|
|
90
|
+
* Bumped the package version to `0.0.3` and updated citation, install and site
|
|
91
|
+
metadata for the archival release.
|
|
92
|
+
|
|
93
|
+
## [0.0.2] — 2026-10-22
|
|
94
|
+
|
|
95
|
+
Documentation and public-disclosure release. No algorithm semantics changed.
|
|
96
|
+
|
|
97
|
+
### Added
|
|
98
|
+
|
|
99
|
+
* `docs/defensive-publication.md`: a public disclosure of the method and its
|
|
100
|
+
formal properties as prior art.
|
|
101
|
+
* `CITATION.cff` and `.zenodo.json`: citation and archive metadata.
|
|
102
|
+
* `docs/articles/why-per-bucket-queries-are-slow.md` and its Chinese mirror: a
|
|
103
|
+
technical article with the production benchmark and prior-art framing.
|
|
104
|
+
* `docs/index.html`: a static landing page for GitHub Pages.
|
|
105
|
+
* `docs/publishing.md`: release, Zenodo, PyPI and distribution checklist.
|
|
106
|
+
* `docs/related-work.md` and `docs/related-work.zh-CN.md`: prior-art
|
|
107
|
+
comparison, historical algorithms and a defensible novelty statement.
|
|
108
|
+
* `docs/prior-art-search.zh-CN.md` and `docs/prior-art-matrix.csv`: a
|
|
109
|
+
repeatable prior-art/patent search plan and recording template.
|
|
110
|
+
* Formal refinement-locality, segment-count and request-count propositions in
|
|
111
|
+
the algorithm specs.
|
|
112
|
+
|
|
113
|
+
### Changed
|
|
114
|
+
|
|
115
|
+
* Repositioned the project as a query-planning method for bucket-limited
|
|
116
|
+
time-series APIs (README, algorithm spec, package description).
|
|
117
|
+
* Bumped the package version to `0.0.2` for the public-disclosure release.
|
|
118
|
+
|
|
119
|
+
## [0.0.1] — 2026-10-22
|
|
120
|
+
|
|
121
|
+
First standalone open-source release, extracted from AutoTestHub.
|
|
122
|
+
|
|
123
|
+
### Added
|
|
124
|
+
|
|
125
|
+
* Pure decomposition core (`month → day → hour → minute`) with configurable
|
|
126
|
+
finest level, IANA timezone support and a strict tiling invariant.
|
|
127
|
+
* `LadderEngine` with source-only, local-only and local-first mixed reads.
|
|
128
|
+
* Local materialization with coverage tracking, a 5-minute grace period and
|
|
129
|
+
rewrite-safe coverage invalidation.
|
|
130
|
+
* Segment-level verification with point-level drilling (`added`, `removed`,
|
|
131
|
+
`changed`) and repair from the authoritative source.
|
|
132
|
+
* `TimeSeriesSource` and `PointStore` protocols; adapters for ThingsBoard,
|
|
133
|
+
PostgreSQL, and in-memory use.
|
|
134
|
+
* PostgreSQL schema with monthly partitions, idempotent upserts, batched range
|
|
135
|
+
sums and coverage tables (`hl_readings`, `hl_coverage`).
|
|
136
|
+
* ThingsBoard adapter handling the 500-bucket limit, mid-bucket timestamps,
|
|
137
|
+
inclusive `endTs`, token refresh and error translation.
|
|
138
|
+
* `hybrid-ladder` CLI: `decompose`, `demo`, `sum`, `verify`, `repair`,
|
|
139
|
+
`materialize`, `serve`, `mcp`, `version`.
|
|
140
|
+
* FastAPI app with async tasks, progress, cancellation, synchronous variants
|
|
141
|
+
and the `{"code":0,"data":...}` envelope.
|
|
142
|
+
* MCP server with `ladder_meta`, `ladder_decompose`, `ladder_sum` and
|
|
143
|
+
`ladder_verify` (supports MCP 1.x and 2.x).
|
|
144
|
+
* Agent skill package under `skills/hybrid-recursive-ladder/`.
|
|
145
|
+
* Deterministic demo data and an end-to-end `hybrid-ladder demo`.
|
|
146
|
+
* 90+ tests covering decomposition, folding, mixed reads, materialization,
|
|
147
|
+
verification, repair, tasks, API, CLI, MCP, ThingsBoard and PostgreSQL.
|
|
148
|
+
|
|
149
|
+
### Fixed (relative to the original AutoTestHub implementation)
|
|
150
|
+
|
|
151
|
+
* **Multi-level fetch grouping.** Fetch runs are grouped by fetch level +
|
|
152
|
+
contiguity instead of adjacency only. The original fetched a whole
|
|
153
|
+
multi-level range at the coarsest level, which assigned a full day's value to
|
|
154
|
+
the first hour and lost the remaining hours/minutes.
|
|
155
|
+
Regression: `tests/test_engine.py::test_multilevel_query_is_exact`.
|
|
156
|
+
* **Raw chunk boundary.** Bisection now uses `[a, mid)` and `[mid, b)` under the
|
|
157
|
+
exclusive-end contract. The original used `mid + 1`, dropping a point that
|
|
158
|
+
landed exactly on the split boundary.
|
|
159
|
+
Regression: `tests/test_engine.py::test_raw_split_keeps_boundary_point`.
|
|
160
|
+
|
|
161
|
+
### Changed
|
|
162
|
+
|
|
163
|
+
* PostgreSQL tables are namespaced (`namespace`, `entity`, `name`) and use a
|
|
164
|
+
configurable `table_prefix` instead of AutoTestHub's
|
|
165
|
+
`connection_id/device_id/device`.
|
|
166
|
+
* `TaskRegistry` is reusable (multiple instances, TTL, max tasks) instead of a
|
|
167
|
+
module-level singleton.
|
|
168
|
+
* The MCP tool layer and HTTP layer share one `runtime.engine_from_env()`.
|
|
169
|
+
|
|
170
|
+
### Known limitations
|
|
171
|
+
|
|
172
|
+
* Only the `sum` rule is implemented. `avg` and `meter_delta` need additional
|
|
173
|
+
aggregation semantics.
|
|
174
|
+
* In-process task results are lost on restart (data is not).
|
|
175
|
+
* The original AutoTestHub `device_id` migration is not automatic.
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
# 变更日志
|
|
2
|
+
|
|
3
|
+
**语言 / Languages:** [English](CHANGELOG.md) · [简体中文](CHANGELOG.zh-CN.md)
|
|
4
|
+
|
|
5
|
+
本文件记录项目的所有重要变更。格式遵循
|
|
6
|
+
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/),项目从 0.0.1 起使用
|
|
7
|
+
[语义化版本](https://semver.org/spec/v2.0.0.html)。
|
|
8
|
+
|
|
9
|
+
## [0.0.6] — 2026-10-27
|
|
10
|
+
|
|
11
|
+
文档与站点发布。没有算法、API、线格式或存储变更。
|
|
12
|
+
|
|
13
|
+
### 新增
|
|
14
|
+
|
|
15
|
+
* Zenodo 归档与 DOI:[10.5281/zenodo.23683292](https://doi.org/10.5281/zenodo.23683292)。
|
|
16
|
+
* 仓库内每份文档都有中文版。14 份说明文档全部有 `.zh-CN.md` 镜像,包括 API
|
|
17
|
+
参考、架构、基准、变更日志、贡献指南和智能体技能;先例矩阵也提供了中文
|
|
18
|
+
CSV。
|
|
19
|
+
* `docs/README.md` / `docs/README.zh-CN.md`:中英双语的文档索引,覆盖所有
|
|
20
|
+
文档、项目级文件和示意图。
|
|
21
|
+
* `tools/check_docs_i18n.py`:文档缺中文镜像、示意图缺 `zh-CN` SVG/PNG,
|
|
22
|
+
或新文档未登记时,CI 直接失败。
|
|
23
|
+
* 文档站点支持 11 种语言切换:`?lang=` 深链、偏好记忆、标题/描述翻译,
|
|
24
|
+
阿拉伯语使用从右到左布局。
|
|
25
|
+
|
|
26
|
+
### 变更
|
|
27
|
+
|
|
28
|
+
* 每份文档顶部都有 English / 简体中文 切换。
|
|
29
|
+
* 中文文档使用中文示意图;其他语言保留英文图或各自的 hero 图。
|
|
30
|
+
* 站点中文模式下的算法、先例、文章和公开披露链接指向中文版。
|
|
31
|
+
* 安装命令、徽章、API 示例和元数据更新到 `0.0.6`。
|
|
32
|
+
|
|
33
|
+
### 修复
|
|
34
|
+
|
|
35
|
+
* 落地页基准表格不再被压扁:徽章样式限定在卡片内,宽表格可横向滚动。
|
|
36
|
+
* 阿拉伯语 RTL 布局下,数字区间和箭头保持从左到右的顺序。
|
|
37
|
+
|
|
38
|
+
## [0.0.5] — 2026-10-26
|
|
39
|
+
|
|
40
|
+
### 新增
|
|
41
|
+
|
|
42
|
+
* 四个 MCP 工具都加了工具注解:人类可读的 `title`,以及
|
|
43
|
+
`readOnlyHint`、`destructiveHint`、`idempotentHint`、`openWorldHint`。
|
|
44
|
+
客户端现在可以判断:`ladder_meta` 和 `ladder_decompose` 是本地、无副作用
|
|
45
|
+
的;`ladder_sum` 在 `materialize=True` 时可能写本地存储;`ladder_verify`
|
|
46
|
+
会访问数据源。
|
|
47
|
+
* 每种语言的 README 配图。每个翻译版 README 都有
|
|
48
|
+
`docs/assets/hero.<lang>.png`,`decomposition`/`architecture` 也提供了中文
|
|
49
|
+
版。`tools/localize_assets.py` 从英文 SVG 重新生成这些图。
|
|
50
|
+
|
|
51
|
+
### 修复
|
|
52
|
+
|
|
53
|
+
* `tests/test_mcp.py` 现在接受当前 MCP SDK 版本中 `call_tool` 返回的
|
|
54
|
+
`(content, structured)`;此前的断言在 `mcp` 1.27 及更高版本上失败。
|
|
55
|
+
|
|
56
|
+
## [0.0.4] — 2026-10-22
|
|
57
|
+
|
|
58
|
+
文档发布。没有代码或算法变更。重写 README 并增加示意图。
|
|
59
|
+
|
|
60
|
+
### 新增
|
|
61
|
+
|
|
62
|
+
* Zenodo 归档与 DOI:[10.5281/zenodo.23557574](https://doi.org/10.5281/zenodo.23557574)。
|
|
63
|
+
|
|
64
|
+
### 变更
|
|
65
|
+
|
|
66
|
+
* 把 `README.md` 与 `README.zh-CN.md` 重写为单一叙事,并加入前后对比、日历
|
|
67
|
+
分解和本地优先读路径的示意图。
|
|
68
|
+
* 给其他语言 README 加入 hero 图和 DOI/网站徽章。
|
|
69
|
+
* 包版本升到 `0.0.4`。
|
|
70
|
+
|
|
71
|
+
## [0.0.3] — 2026-10-22
|
|
72
|
+
|
|
73
|
+
归档发布。没有代码或算法变更。此发布触发 Zenodo 的 GitHub 集成,使公开披露
|
|
74
|
+
获得 DOI。
|
|
75
|
+
|
|
76
|
+
### 新增
|
|
77
|
+
|
|
78
|
+
* Zenodo 归档与 DOI:[10.5281/zenodo.23556606](https://doi.org/10.5281/zenodo.23556606)。
|
|
79
|
+
|
|
80
|
+
### 变更
|
|
81
|
+
|
|
82
|
+
* 包版本升到 `0.0.3`,并更新引用、安装和站点元数据。
|
|
83
|
+
|
|
84
|
+
## [0.0.2] — 2026-10-22
|
|
85
|
+
|
|
86
|
+
文档与公开披露发布。算法语义未变。
|
|
87
|
+
|
|
88
|
+
### 新增
|
|
89
|
+
|
|
90
|
+
* `docs/defensive-publication.md`:方法及其形式化性质的公开披露,作为现有技术。
|
|
91
|
+
* `CITATION.cff` 与 `.zenodo.json`:引用与归档元数据。
|
|
92
|
+
* `docs/articles/why-per-bucket-queries-are-slow.md` 及其中文版:带生产基准和
|
|
93
|
+
现有技术定位的技术文章。
|
|
94
|
+
* `docs/index.html`:GitHub Pages 静态落地页。
|
|
95
|
+
* `docs/publishing.md`:发布、Zenodo、PyPI 与传播清单。
|
|
96
|
+
* `docs/related-work.md` 与 `docs/related-work.zh-CN.md`:现有技术对比、历史
|
|
97
|
+
算法和可辩护的新颖性陈述。
|
|
98
|
+
* `docs/prior-art-search.zh-CN.md` 与 `docs/prior-art-matrix.csv`:可重复的
|
|
99
|
+
现有技术/专利检索计划和记录模板。
|
|
100
|
+
* 算法规范中的形式化细化局部性、段数和请求数命题。
|
|
101
|
+
|
|
102
|
+
### 变更
|
|
103
|
+
|
|
104
|
+
* 把项目重新定位为面向桶数受限时序 API 的查询规划方法(README、算法规范、
|
|
105
|
+
包描述)。
|
|
106
|
+
* 包版本升到 `0.0.2`,用于公开披露发布。
|
|
107
|
+
|
|
108
|
+
## [0.0.1] — 2026-10-22
|
|
109
|
+
|
|
110
|
+
首个独立开源版本,从 AutoTestHub 抽离。
|
|
111
|
+
|
|
112
|
+
### 新增
|
|
113
|
+
|
|
114
|
+
* 纯分解核心(`month → day → hour → minute`),可配置最细层、IANA 时区支持和
|
|
115
|
+
严格的铺满不变量。
|
|
116
|
+
* `LadderEngine`:纯源、纯本地和本地优先混合读。
|
|
117
|
+
* 本地固化,带覆盖跟踪、5 分钟宽限期和重写安全的覆盖失效。
|
|
118
|
+
* 段级校验与点级展开(`added`、`removed`、`changed`),以及从权威数据源修复。
|
|
119
|
+
* `TimeSeriesSource` 与 `PointStore` 协议;ThingsBoard、PostgreSQL 和内存适配器。
|
|
120
|
+
* PostgreSQL 表结构:月分区、幂等 upsert、批量区间求和和覆盖表
|
|
121
|
+
(`hl_readings`、`hl_coverage`)。
|
|
122
|
+
* ThingsBoard 适配器:500 桶上限、半桶时间戳、包含端点的 `endTs`、token 刷新
|
|
123
|
+
和错误翻译。
|
|
124
|
+
* `hybrid-ladder` CLI:`decompose`、`demo`、`sum`、`verify`、`repair`、
|
|
125
|
+
`materialize`、`serve`、`mcp`、`version`。
|
|
126
|
+
* FastAPI 应用:异步任务、进度、取消、同步变体和 `{"code":0,"data":...}` 信封。
|
|
127
|
+
* MCP server:`ladder_meta`、`ladder_decompose`、`ladder_sum`、`ladder_verify`
|
|
128
|
+
(支持 MCP 1.x 与 2.x)。
|
|
129
|
+
* `skills/hybrid-recursive-ladder/` 下的 Agent 技能包。
|
|
130
|
+
* 确定性演示数据和端到端 `hybrid-ladder demo`。
|
|
131
|
+
* 90+ 个测试,覆盖分解、折叠、混合读、固化、校验、修复、任务、API、CLI、
|
|
132
|
+
MCP、ThingsBoard 和 PostgreSQL。
|
|
133
|
+
|
|
134
|
+
### 修复(相对原 AutoTestHub 实现)
|
|
135
|
+
|
|
136
|
+
* **多层级取数分组。** 取数 run 按取数层级 + 连续性分组,而不是只按相邻分组。
|
|
137
|
+
原实现把整个多层级区间按最粗层取数,把一整天的值赋给第一个小时,并丢掉其余
|
|
138
|
+
小时/分钟。回归测试:`tests/test_engine.py::test_multilevel_query_is_exact`。
|
|
139
|
+
* **原始点分块边界。** 在左闭右开契约下,二分改为 `[a, mid)` 与 `[mid, b)`。
|
|
140
|
+
原实现用 `mid + 1`,会丢掉正好落在分块边界上的点。回归测试:
|
|
141
|
+
`tests/test_engine.py::test_raw_split_keeps_boundary_point`。
|
|
142
|
+
|
|
143
|
+
### 变更
|
|
144
|
+
|
|
145
|
+
* PostgreSQL 表使用命名空间(`namespace`、`entity`、`name`),并支持可配置的
|
|
146
|
+
`table_prefix`,替代 AutoTestHub 的 `connection_id/device_id/device`。
|
|
147
|
+
* `TaskRegistry` 可复用(多实例、TTL、最大任务数),不再是模块级单例。
|
|
148
|
+
* MCP 工具层与 HTTP 层共享一个 `runtime.engine_from_env()`。
|
|
149
|
+
|
|
150
|
+
### 已知限制
|
|
151
|
+
|
|
152
|
+
* 只实现 `sum` 规则。`avg` 和 `meter_delta` 需要额外的聚合语义。
|
|
153
|
+
* 进程内任务结果在重启后丢失(数据不丢)。
|
|
154
|
+
* 原 AutoTestHub 的 `device_id` 迁移不是自动的。
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
cff-version: 1.2.0
|
|
2
|
+
message: "If you use this software, please cite it using the metadata below."
|
|
3
|
+
title: "Hybrid Recursive Ladder: Query Planning for Bucket-Limited Time-Series APIs"
|
|
4
|
+
abstract: >-
|
|
5
|
+
A query-planning method for long-range time-series aggregation over APIs with
|
|
6
|
+
a hard per-request bucket limit. The range is decomposed into complete
|
|
7
|
+
calendar units; each maximal contiguous run sharing a fetch level is fetched
|
|
8
|
+
once at the next finer aggregation and folded locally; optional coverage
|
|
9
|
+
tracking fetches only uncovered sub-ranges. The method is a composition of
|
|
10
|
+
calendar mixed-radix decomposition, canonical interval decomposition, roll-up
|
|
11
|
+
and multi-resolution aggregation.
|
|
12
|
+
authors:
|
|
13
|
+
- family-names: "MagicSquarekey"
|
|
14
|
+
alias: "MagicSquarekey"
|
|
15
|
+
version: "0.0.6"
|
|
16
|
+
doi: "10.5281/zenodo.23683292"
|
|
17
|
+
date-released: "2026-10-27"
|
|
18
|
+
license: "MIT"
|
|
19
|
+
repository-code: "https://github.com/MagicSquarekey/hybrid_recursive_ladder_algorithm"
|
|
20
|
+
url: "https://github.com/MagicSquarekey/hybrid_recursive_ladder_algorithm"
|
|
21
|
+
keywords:
|
|
22
|
+
- "time series"
|
|
23
|
+
- "aggregation"
|
|
24
|
+
- "query planning"
|
|
25
|
+
- "downsampling"
|
|
26
|
+
- "multi-resolution"
|
|
27
|
+
- "ThingsBoard"
|
|
28
|
+
- "observability"
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
# Contributing
|
|
2
|
+
|
|
3
|
+
**语言 / Languages:** [English](CONTRIBUTING.md) · [简体中文](CONTRIBUTING.zh-CN.md)
|
|
4
|
+
|
|
5
|
+
Thanks for considering a contribution. This project values correctness and
|
|
6
|
+
clarity over feature count: the algorithm's guarantees are the product.
|
|
7
|
+
|
|
8
|
+
## Development setup
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
git clone https://github.com/MagicSquarekey/hybrid_recursive_ladder_algorithm.git
|
|
12
|
+
cd hybrid_recursive_ladder_algorithm
|
|
13
|
+
python -m venv .venv
|
|
14
|
+
source .venv/bin/activate # Windows: .venv\Scripts\activate
|
|
15
|
+
pip install -e ".[dev]"
|
|
16
|
+
ruff check .
|
|
17
|
+
pytest
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
Optional PostgreSQL integration tests:
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
export HL_TEST_PG_DSN='postgresql://user:pass@127.0.0.1:5432/testdb'
|
|
24
|
+
pytest -m integration
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
The integration test uses a unique `namespace` and the `hl_test_` table prefix;
|
|
28
|
+
it cleans its rows after each test.
|
|
29
|
+
|
|
30
|
+
## What to run before opening a PR
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
ruff check .
|
|
34
|
+
pytest
|
|
35
|
+
python examples/benchmark.py # segment/request counts should stay stable
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
If you change algorithm semantics, update `docs/algorithm.md`,
|
|
39
|
+
`docs/algorithm.zh-CN.md` and the relevant test in the same PR.
|
|
40
|
+
|
|
41
|
+
## Commit messages
|
|
42
|
+
|
|
43
|
+
Conventional Commits are preferred:
|
|
44
|
+
|
|
45
|
+
```
|
|
46
|
+
feat(engine): add max/min folding
|
|
47
|
+
fix(core): keep boundary point on raw bisection
|
|
48
|
+
docs(api): document sync endpoints
|
|
49
|
+
test(mixed): cover grace-period clamping
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Keep a commit focused. A bug fix should include a regression test that fails
|
|
53
|
+
before the fix.
|
|
54
|
+
|
|
55
|
+
## Adding a source adapter
|
|
56
|
+
|
|
57
|
+
1. Implement `interval_agg` and `raw_series` from
|
|
58
|
+
`hybrid_ladder.protocols.TimeSeriesSource`.
|
|
59
|
+
2. Return `{bucket_start_ms: value}` from `interval_agg`; normalize any
|
|
60
|
+
mid-bucket timestamps your source uses.
|
|
61
|
+
3. Enforce `[start, end)` and ascending order in `raw_series`; return at most
|
|
62
|
+
`limit` points.
|
|
63
|
+
4. Keep credentials out of logs and error messages.
|
|
64
|
+
5. Add tests with `httpx.MockTransport` (for HTTP sources) or a deterministic
|
|
65
|
+
fixture. Cover: bucket normalization, chunking, auth, error translation and
|
|
66
|
+
the exclusive end.
|
|
67
|
+
|
|
68
|
+
## Adding a store adapter
|
|
69
|
+
|
|
70
|
+
1. Implement the seven methods from `hybrid_ladder.protocols.PointStore`.
|
|
71
|
+
2. Return `(None, 0)` for an empty range and `(0.0, n)` for a zero-valued
|
|
72
|
+
range. This distinction is a core guarantee.
|
|
73
|
+
3. Make `upsert_points` idempotent on `(entity, key, ts)`.
|
|
74
|
+
4. `clear_coverage` must remove overlapping coverage rows before a rewrite.
|
|
75
|
+
5. `series` may paginate internally; `max_points` is a page size, not a cap.
|
|
76
|
+
6. Add an opt-in integration test gated by an environment variable.
|
|
77
|
+
|
|
78
|
+
## Code style
|
|
79
|
+
|
|
80
|
+
* Python 3.10+, type hints on public functions.
|
|
81
|
+
* Line length 100, `ruff` with the configured rule set.
|
|
82
|
+
* The core (`core.py`) must remain free of I/O and third-party dependencies.
|
|
83
|
+
* Prefer explicit names over abbreviations; comments should explain
|
|
84
|
+
constraints, not restate code.
|
|
85
|
+
|
|
86
|
+
## Documentation
|
|
87
|
+
|
|
88
|
+
* Every prose document ships with a `.zh-CN.md` mirror; every diagram ships
|
|
89
|
+
with a `zh-CN` SVG and PNG. Run `python tools/check_docs_i18n.py` (also
|
|
90
|
+
enforced in CI) before opening a PR.
|
|
91
|
+
* English is the primary README; keep `README.zh-CN.md` in sync when behavior
|
|
92
|
+
changes.
|
|
93
|
+
* API changes require an update to `docs/api.md` and `docs/api.zh-CN.md`.
|
|
94
|
+
* Add benchmarks only with methodology and caveats; never present a
|
|
95
|
+
single-machine number as a guarantee.
|
|
96
|
+
* README diagrams are language-specific: `docs/assets/<name>.<lang>.png` is
|
|
97
|
+
rendered from the English `docs/assets/<name>.svg` by
|
|
98
|
+
`python tools/localize_assets.py`. After editing an SVG or a translation,
|
|
99
|
+
re-run it; `--check` reports strings that have no translation yet.
|
|
100
|
+
|
|
101
|
+
## Release process
|
|
102
|
+
|
|
103
|
+
1. Update `CHANGELOG.md` and the version in `pyproject.toml`.
|
|
104
|
+
2. Run `ruff check .`, `pytest`, and `python -m build`.
|
|
105
|
+
3. Commit, tag (`vX.Y.Z`), and push the tag. The `release.yml` workflow builds
|
|
106
|
+
the distributions and creates the GitHub release.
|
|
107
|
+
4. If PyPI publishing is enabled, use trusted publishing with the `pypi`
|
|
108
|
+
environment.
|
|
109
|
+
|
|
110
|
+
## Reporting issues
|
|
111
|
+
|
|
112
|
+
Please include:
|
|
113
|
+
|
|
114
|
+
* the range and `finest` level,
|
|
115
|
+
* the source type and adapter version,
|
|
116
|
+
* the expected and actual totals/segment counts,
|
|
117
|
+
* whether the local store was involved (`source` / `source_counts`),
|
|
118
|
+
* a minimal reproduction when possible.
|
|
119
|
+
|
|
120
|
+
Never include credentials or production data in an issue.
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
# 贡献指南
|
|
2
|
+
|
|
3
|
+
**语言 / Languages:** [English](CONTRIBUTING.md) · [简体中文](CONTRIBUTING.zh-CN.md)
|
|
4
|
+
|
|
5
|
+
感谢你考虑贡献。这个项目更看重正确性和清晰度,而不是功能数量:算法的保证就是
|
|
6
|
+
产品本身。
|
|
7
|
+
|
|
8
|
+
## 开发环境
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
git clone https://github.com/MagicSquarekey/hybrid_recursive_ladder_algorithm.git
|
|
12
|
+
cd hybrid_recursive_ladder_algorithm
|
|
13
|
+
python -m venv .venv
|
|
14
|
+
source .venv/bin/activate # Windows: .venv\Scripts\activate
|
|
15
|
+
pip install -e ".[dev]"
|
|
16
|
+
ruff check .
|
|
17
|
+
pytest
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
可选的 PostgreSQL 集成测试:
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
export HL_TEST_PG_DSN='postgresql://user:pass@127.0.0.1:5432/testdb'
|
|
24
|
+
pytest -m integration
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
集成测试使用唯一的 `namespace` 和 `hl_test_` 表前缀;每个测试后会清理自己的行。
|
|
28
|
+
|
|
29
|
+
## 开 PR 前要跑什么
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
ruff check .
|
|
33
|
+
pytest
|
|
34
|
+
python examples/benchmark.py # 段数/请求数应保持稳定
|
|
35
|
+
python tools/check_docs_i18n.py # 每份文档/示意图都要有中文版
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
如果改动了算法语义,请在同一个 PR 中更新 `docs/algorithm.md`、
|
|
39
|
+
`docs/algorithm.zh-CN.md` 和相关测试。
|
|
40
|
+
|
|
41
|
+
## 提交信息
|
|
42
|
+
|
|
43
|
+
推荐使用 Conventional Commits:
|
|
44
|
+
|
|
45
|
+
```
|
|
46
|
+
feat(engine): add max/min folding
|
|
47
|
+
fix(core): keep boundary point on raw bisection
|
|
48
|
+
docs(api): document sync endpoints
|
|
49
|
+
test(mixed): cover grace-period clamping
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
保持每次提交聚焦。Bug 修复应包含一个在修复前会失败的回归测试。
|
|
53
|
+
|
|
54
|
+
## 新增数据源适配器
|
|
55
|
+
|
|
56
|
+
1. 实现 `hybrid_ladder.protocols.TimeSeriesSource` 的 `interval_agg` 和
|
|
57
|
+
`raw_series`。
|
|
58
|
+
2. `interval_agg` 返回 `{bucket_start_ms: value}`;如果你的数据源使用半桶时间
|
|
59
|
+
戳,归一化它。
|
|
60
|
+
3. `raw_series` 强制 `[start, end)` 和升序;最多返回 `limit` 个点。
|
|
61
|
+
4. 不要把凭据写进日志或错误信息。
|
|
62
|
+
5. 用 `httpx.MockTransport`(HTTP 数据源)或确定性 fixture 加测试。覆盖:桶
|
|
63
|
+
归一化、分块、认证、错误翻译和排除端点。
|
|
64
|
+
|
|
65
|
+
## 新增存储适配器
|
|
66
|
+
|
|
67
|
+
1. 实现 `hybrid_ladder.protocols.PointStore` 的七个方法。
|
|
68
|
+
2. 空区间返回 `(None, 0)`,零值区间返回 `(0.0, n)`。这个区分是核心保证。
|
|
69
|
+
3. 让 `upsert_points` 在 `(entity, key, ts)` 上幂等。
|
|
70
|
+
4. `clear_coverage` 必须在重写前删除重叠的覆盖行。
|
|
71
|
+
5. `series` 可以在内部翻页;`max_points` 是页大小,不是上限。
|
|
72
|
+
6. 加一个由环境变量控制的选择性集成测试。
|
|
73
|
+
|
|
74
|
+
## 代码风格
|
|
75
|
+
|
|
76
|
+
* Python 3.10+,公开函数加类型标注。
|
|
77
|
+
* 行宽 100,使用配置好的 `ruff` 规则。
|
|
78
|
+
* 核心(`core.py`)必须保持无 I/O、无第三方依赖。
|
|
79
|
+
* 优先使用明确的命名而不是缩写;注释应解释约束,而不是复述代码。
|
|
80
|
+
|
|
81
|
+
## 文档
|
|
82
|
+
|
|
83
|
+
* 英文是主要 README;行为变化时同步更新 `README.zh-CN.md`。
|
|
84
|
+
* **每一份说明文档都必须有中文版**:英文文件 `foo.md` 配套 `foo.zh-CN.md`;
|
|
85
|
+
中文文件也要在顶部放语言切换链接。
|
|
86
|
+
* **每一张示意图都必须有中文版**:`docs/assets/<name>.svg` 配套
|
|
87
|
+
`<name>.zh-CN.svg` 和 `<name>.zh-CN.png`。README 图由
|
|
88
|
+
`python tools/localize_assets.py` 从英文 SVG 生成;改完 SVG 或翻译后重跑,
|
|
89
|
+
`--check` 会报告还没有翻译的字符串。
|
|
90
|
+
* API 变化需要同时更新 `docs/api.md`、`docs/api.zh-CN.md` 和
|
|
91
|
+
`CHANGELOG.md`。
|
|
92
|
+
* 基准数据必须附方法和注意事项;不要把单机数字说成保证。
|
|
93
|
+
* 提交前运行 `python tools/check_docs_i18n.py`(CI 也会跑)。
|
|
94
|
+
|
|
95
|
+
## 发布流程
|
|
96
|
+
|
|
97
|
+
1. 更新 `CHANGELOG.md`、`CHANGELOG.zh-CN.md` 和 `pyproject.toml` 中的版本。
|
|
98
|
+
2. 运行 `ruff check .`、`pytest`、`python examples/benchmark.py` 和
|
|
99
|
+
`python tools/check_docs_i18n.py`。
|
|
100
|
+
3. 提交、打 tag(`vX.Y.Z`)、推 tag。`release.yml` 工作流会构建分发包并创建
|
|
101
|
+
GitHub Release。
|
|
102
|
+
4. 如果启用了 PyPI 发布,使用 `pypi` 环境和 trusted publishing。
|
|
103
|
+
|
|
104
|
+
## 报告问题
|
|
105
|
+
|
|
106
|
+
请包含:
|
|
107
|
+
|
|
108
|
+
* 区间和 `finest` 层级;
|
|
109
|
+
* 数据源类型和适配器版本;
|
|
110
|
+
* 预期与实际合计/段数;
|
|
111
|
+
* 是否涉及本地存储(`source` / `source_counts`);
|
|
112
|
+
* 尽可能提供最小复现。
|
|
113
|
+
|
|
114
|
+
永远不要在 issue 中包含凭据或生产数据。
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 MagicSquarekey
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|