diff --git a/evidence/indexer-255-limit-sizing-20261030/README.md b/evidence/indexer-255-limit-sizing-20261030/README.md new file mode 100644 index 00000000..dcdc58b7 --- /dev/null +++ b/evidence/indexer-255-limit-sizing-20261030/README.md @@ -0,0 +1,28 @@ +# Issue #255 — avoid redundant size serialization after the item limit + +[Result table and limits](results/report.md) · [Frozen protocol](plan/protocol.md) · [Independent audit](results/independent-review.json) + +This distinct five-line runtime optimization passes its bounded CPU-retrieval campaign. It is not acceptance of the earlier resource-cache candidate, a retrieval-accuracy gain, or closure of #255. Historical FAIL/INCONCLUSIVE evidence remains unchanged. + +## Replay and inspection + +The candidate snapshot and tests are retained under [patch/](patch/README.md). The [frozen runner](validator/evaluate.py) and its adjacent [freeze receipt](validator/candidate-runner-freeze.json) describe exact baseline/candidate pins. `plan/protocol.md` preserves the original `proposed-protocol.md` bytes; that original filename appears in the freeze receipt. + +Inspect the archived evidence without executing retrieval: + +```bash +python evidence/indexer-255-limit-sizing-20261030/validator/verify_raw.py +``` + +The deterministic gzip/tar archive retains every original raw file, including240 completed-arm receipts,120 paired groups, original output captures, source identities, run order, environment and summary. [Raw-file manifest](results/raw-files.json) records decompressed exact byte counts and hashes. The verifier does not extract or execute archive members. The independent audit is a post-run supplement, not the prospective validator; its original local helper was not portable and is not represented as a reusable production tool. + +To reproduce the experiment only with appropriate CPU-execution authorization, reconstruct the two pinned worktrees, use the same recorded Python/dependencies, and invoke: + +```bash +python evidence/indexer-255-limit-sizing-20261030/validator/evaluate.py \ + --baseline "$BASELINE_ROOT" --candidate "$CANDIDATE_ROOT" --output "$NEW_OUTPUT_DIR" +``` + +`NEW_OUTPUT_DIR` must not exist. Keep the frozen receipt adjacent to the runner. Worktrees must be at the exact recorded commits; the runner asserts pins, source/corpus equality, output equality and unchanged source. The original run is complete; this command is reproducibility documentation, not permission to repeat until PASS. No source/control defaults carry campaign thresholds. + +The runner's generic exception wrapper records `INCONCLUSIVE`; an output-parity assertion failure must instead be interpreted as a correctness **FAIL/blocker**, not measurement noise. No exception or mismatch occurred in the retained run. diff --git a/evidence/indexer-255-limit-sizing-20261030/patch/README.md b/evidence/indexer-255-limit-sizing-20261030/patch/README.md new file mode 100644 index 00000000..05355b15 --- /dev/null +++ b/evidence/indexer-255-limit-sizing-20261030/patch/README.md @@ -0,0 +1,6 @@ +# Frozen candidate + +Baseline: `f93df0548a26714f6514337a8525c7c14108acad`. +Candidate: `9f7862a9f8619dd68ac59f12736f6b50da10d9e8`. + +`candidate.patch` is the exact baseline-to-candidate source/test diff. `candidate.bundle` retains that one commit with baseline prerequisite. No ranking, corpus or default interface change is included. Publication commits additionally package evidence and inventory registration; they are not substituted for the frozen measured source revision. diff --git a/evidence/indexer-255-limit-sizing-20261030/patch/candidate.bundle b/evidence/indexer-255-limit-sizing-20261030/patch/candidate.bundle new file mode 100644 index 00000000..806be22a Binary files /dev/null and b/evidence/indexer-255-limit-sizing-20261030/patch/candidate.bundle differ diff --git a/evidence/indexer-255-limit-sizing-20261030/patch/candidate.patch b/evidence/indexer-255-limit-sizing-20261030/patch/candidate.patch new file mode 100644 index 00000000..f4d63744 --- /dev/null +++ b/evidence/indexer-255-limit-sizing-20261030/patch/candidate.patch @@ -0,0 +1,121 @@ +diff --git a/src/inferrsi/knowledge_operations.py b/src/inferrsi/knowledge_operations.py +index 1c78418f..d5748c46 100644 +--- a/src/inferrsi/knowledge_operations.py ++++ b/src/inferrsi/knowledge_operations.py +@@ -566,6 +566,11 @@ class KnowledgeReader: + + def select(reference: str, bundle: Bundle, view: dict) -> None: + nonlocal used, context_used ++ # Normal Bundle views were serialized while computing their revision. ++ # Preserve custom subclasses' serialization/error behavior below. ++ if type(bundle) is Bundle and len(selected) >= limit: ++ omitted.append({"id": reference, "reason": "output_limit"}) ++ return + size = len(_json(view)) + if len(selected) >= limit or (max_bytes is not None and used + size > max_bytes): + omitted.append({"id": reference, "reason": "output_limit"}) +diff --git a/tests/test_collect_limit_serialization.py b/tests/test_collect_limit_serialization.py +new file mode 100644 +index 00000000..00153e5f +--- /dev/null ++++ b/tests/test_collect_limit_serialization.py +@@ -0,0 +1,99 @@ ++"""Count saturation skips only redundant normal-view payload sizing.""" ++import pytest ++ ++from inferrsi import knowledge_operations as operations ++from inferrsi.knowledge_operations import Bundle, KnowledgeReader ++ ++ ++class CustomBundle(Bundle): ++ pass ++ ++ ++class InvalidViewBundle(Bundle): ++ def view(self, *, material=False): ++ return {**super().view(material=material), "custom": object()} ++ ++ ++def bundle(identity, cls=Bundle): ++ return cls({ ++ "id": identity, "kind": "knowledge", "entrypoint": "entry.md", ++ "sources": [{"type": "unknown"}], "applicability": {}, "state": "test", ++ "limitations": [], "attribution": "test", "required_resources": ["entry.md"], ++ }, {"entry.md": identity.encode()}, {}) ++ ++ ++class FixtureReader(KnowledgeReader): ++ def __init__(self, bundles): ++ super().__init__() ++ self.bundles = {item.metadata["id"]: item for item in bundles} ++ self.reads = [] ++ ++ def records(self): ++ return {identity: {} for identity in self.bundles} ++ ++ def _read(self, qualified, revision): ++ self.reads.append(qualified) ++ return self.bundles[qualified.partition(":")[2]] ++ ++ ++def size_calls(monkeypatch): ++ original, seen = operations._json, [] ++ ++ def observe(value): ++ if isinstance(value, dict) and "authority" in value and "ref" in value: ++ seen.append(value["id"]) ++ return original(value) ++ ++ monkeypatch.setattr(operations, "_json", observe) ++ return seen ++ ++ ++@pytest.mark.parametrize("material", [False, True]) ++def test_saturated_count_omits_without_sizing_but_reads_every_bundle(monkeypatch, material): ++ reader = FixtureReader([bundle(name) for name in ("a", "b", "c")]) ++ seen = size_calls(monkeypatch) ++ result = reader.collect(limit=1, material=material) ++ assert seen == ["a"] ++ assert reader.reads == ["package:a", "package:b", "package:c"] ++ assert result["omissions"] == [ ++ {"id": "package:b", "reason": "output_limit"}, ++ {"id": "package:c", "reason": "output_limit"}, ++ ] ++ assert result["material_bytes"] == len(operations._json(result["items"][0])) ++ ++ ++@pytest.mark.parametrize("max_bytes", [None, 1, 100000]) ++@pytest.mark.parametrize("material", [False, True]) ++def test_custom_subclass_fallback_is_identical_to_normal_views(max_bytes, material): ++ normal = FixtureReader([bundle(n) for n in ("a", "b", "c")]) ++ legacy = FixtureReader([bundle(n, CustomBundle) for n in ("a", "b", "c")]) ++ options = dict(limit=1, max_bytes=max_bytes, material=material, context_bytes=100) ++ assert normal.collect(**options) == legacy.collect(**options) ++ ++ ++def test_byte_budget_rejections_still_size_every_unsaturated_item(monkeypatch): ++ reader = FixtureReader([bundle(n) for n in ("a", "b", "c")]) ++ seen = size_calls(monkeypatch) ++ result = reader.collect(limit=1, max_bytes=1) ++ assert seen == ["a", "b", "c"] ++ assert result["no_match"] and len(result["omissions"]) == 3 ++ ++ ++def test_invalid_custom_view_still_raises_after_count_limit(): ++ reader = FixtureReader([bundle("a"), bundle("b", InvalidViewBundle)]) ++ with pytest.raises(TypeError, match="not JSON serializable"): ++ reader.collect(limit=1) ++ ++ ++def test_invalid_normal_resource_is_reported_even_after_count_limit(): ++ invalid = bundle("b") ++ invalid.content["../escape"] = b"unsafe" ++ result = FixtureReader([bundle("a"), invalid]).collect(limit=1) ++ assert result["omissions"][0]["reason"] == "invalid" ++ assert "Unsafe bundle path" in result["omissions"][0]["detail"] ++ ++ ++@pytest.mark.parametrize("limit", [0, None, -1, True]) ++def test_invalid_limits_still_rejected(limit): ++ with pytest.raises(ValueError, match="positive integer"): ++ FixtureReader([bundle("a")]).collect(limit=limit) diff --git a/evidence/indexer-255-limit-sizing-20261030/plan/protocol.md b/evidence/indexer-255-limit-sizing-20261030/plan/protocol.md new file mode 100644 index 00000000..411abede --- /dev/null +++ b/evidence/indexer-255-limit-sizing-20261030/plan/protocol.md @@ -0,0 +1,44 @@ +# Issue #255: defer serialization of already-limit-omitted views (proposal) + +Status: prospectively accepted by coordinator before candidate/measurements, with independent reviewer conservative subclass guard. Baseline f93df0548a26714f6514337a8525c7c14108acad. Plane: harness. Historical cache v1 FAIL and confirmation uncertainty remain unchanged; this is a distinct, smaller optimization, not another attempt on that cache. + +## Hypothesis and scope + +`KnowledgeReader.collect.select` calls `len(_json(view))` before checking `len(selected) >= limit`. Once the item count is full, that byte size cannot alter the `output_limit` omission. Move only the full-count check before serialization for exact type(bundle) is Bundle; subclasses retain the original serialization/error path. Leave byte-budget checks after serialization. Do not skip `_read`, `Bundle.view`, identity/revision/resource validation, filters, ranking, query processing, omitted-item ordering, or context selection. No memo/cache, source/corpus edits or ranking changes. + +For N calls to select and no max_bytes, view-size JSON serialization reduces from N to min(N,limit). With max_bytes, only calls after count saturation are removed; byte-budget-excluded candidates before saturation still undergo exact size calculation. Manifest and complete-resource hashing remain O(N*resource_bytes); no claim of removing that dominant work. + +## Before performance execution + +Independent source/protocol review; synthetic call-count and full JSON parity tests, including default, relevance, explicit order, aliases/revisions, material, context, exact/undersized byte budgets, invalid resources after count saturation, mutable inputs, filters and no match. Invalid limit values (0, None, negative, bool) retain their existing rejection. Supported normal Bundle outputs already serialize their metadata/resources/dependencies into the revision before select; custom overridden view behavior must be considered explicitly rather than hidden. + +Freeze candidate commit, runner hash, exact cases and installed/import-path proof before timing. Run existing relevant software tests. No semantic heldout evaluation or new labels. Any correctness discrepancy stops before performance. Independent resource/output audit uses saved captures only. + +## Fixed workload + +All arms use same Python, source imports pinned to each worktree, identical packaged corpus, no filters unless stated, limit=5, max_bytes=None, material=False. + +1. Primary: reused-reader default Collect(query=''); one warmup then one call per sample. This broad, bounded enumeration is the direct targeted operation, not a claim about every query. +2. Secondary: reused-reader Collect(query='', relevance='memory', context_bytes=262144); one warmup then one call. +3. Secondary: fresh-process CLI default Collect(query='', limit=5), full parent-observed startup/stdout capture. +4. Untouched guard: fresh-process CLI catalog search(query='cgroupv2', limit=5), same exact command/API mapping as old study. + +Exact CLI argv: [PYTHON, '-m', 'inferrsi', 'collect', '', '--limit', '5', '--json'] and [PYTHON, '-m', 'inferrsi', 'knowledge', 'search', 'cgroupv2', '--limit', '5', '--json']. Each child gets only PATH=os.defpath, PYTHONPATH=/src, PYTHONDONTWRITEBYTECODE=1; cwd is its matching arm root. Freeze runner manifest before candidate measurements. Both arms serialize identical results; retain complete correctness output once per path plus every timing sample digest/bytes. + +## One study only + +120 paired groups, balanced AB/BA shuffled with random.Random(25530), path order fixed 1→4. Sequential isolated arm subprocesses, no concurrent heavy work. Capture wall nanoseconds and process CPU nanoseconds for API; child CPU user/system from os.wait4/rusage-compatible subprocess accounting for CLI plus wall time. Record monotonic chronology, arm order, source/corpus hashes before/after, load averages as contextual metadata. CPU and load evidence can narrow attribution but cannot waive a wall-time failure. Fresh process is not cold filesystem cache. + +No trimming, pooling with old studies, retries to obtain PASS or tuning after outcomes. Exactly one execution after freeze. Missing/changed-source samples → INCONCLUSIVE; preserve partial data, no replacement. + +## Prospective gates (proposal requiring coordinator acceptance) + +- All output/resource/contract parity gates must pass. +- Primary median within-pair latency reduction >=5%, bootstrap95% lower bound >0. This practical threshold is specific to this smaller eliminated-serialization hypothesis, not relaxation of historical cache gates. +- Secondary each p50 regression <=10%, p95 regression <=20%; nearest-rank p95. Additionally upper95% bootstrap bound on each secondary p50 regression <=10% to exclude the median uncertainty that prevented previous acceptance. Point-limit failure → FAIL; point gates pass but confidence bound exceeds limit → INCONCLUSIVE (not PASS). +- 10,000 paired-group bootstrap resamples, seed25531, percentile2.5/97.5; no arm-independent resampling. Ratios of resampled medians for secondary p50. p95 confidence intervals descriptive, never SLO claim. +- Any source/corpus/parity/correctness failure blocks promotion regardless of speed. No ranking accuracy gain inferred; #255 accuracy remains independently open. + +## Deliverable / stopping condition + +One table with primary/secondary wall and CPU metrics, exact counts, bootstrap uncertainty, output parity and deterministic serialization counts. If practical gain is absent or any gate fails/inconclusive, retain evidence and stop this candidate without another confirmation. If all pass, seek current-head independent review and publication approval; no automatic tracker closure. No model/service/hardware calls or remote writes in this preparation. diff --git a/evidence/indexer-255-limit-sizing-20261030/plan/publication-integrity.json b/evidence/indexer-255-limit-sizing-20261030/plan/publication-integrity.json new file mode 100644 index 00000000..3e56f0d2 --- /dev/null +++ b/evidence/indexer-255-limit-sizing-20261030/plan/publication-integrity.json @@ -0,0 +1,17 @@ +{ + "README.md": "dfcb9cc72c7ed9e06b94cbc848fb3870697cd35860e66add1b9dd8d75bef188d", + "patch/README.md": "a229382547bd8da466b069c332614df34f077bb5f0fcfe9ab6a9d634f0a64844", + "patch/candidate.bundle": "bebda54d45d8a33fd1bf61a72025f57f7fbb28de0e25185c4711046b91423b83", + "patch/candidate.patch": "f9fbd04c05742e4e927df44344a87eb56b5af82a37627ba1ea8099f4b7f3aaef", + "plan/protocol.md": "d577712b231be4bf33e66d401da22d50a38b01951707dae7a65b8d9c2dfc6a44", + "results/affected-tests.txt": "b446d144969edc0fcfad2fec5a9766269f4423b8a1587b18ca27baf67617c82b", + "results/independent-review.json": "66b17170a7d968f950ef2ad969734ccfae4c55f78bd7705930e1b9f350f97e76", + "results/lint.txt": "82b3e6a6c090a57601d22943bd23fca9218d1031dbe5a7b754092f9a156b4f18", + "results/raw-files.json": "5895b8827f4db31aaa887c294942f0107338d528388857e5b9983b95e60ee637", + "results/raw-study.tar.gz": "50f1055d01a6f1305ef34c798a68fdf5334fc1b0033b0fc7808f11b443f89dea", + "results/report.md": "c70e5e2cb216a49467306859044d9ee9dfe3522a8e60c9919378cc6e87fa1c69", + "results/summary.json": "45888c28f57685aa91315811a04facf743a2e111a329cf62467b85f61528c3d8", + "validator/candidate-runner-freeze.json": "c118d40b587195b1a4a471dd2c75b63321b0c89e6661b40855d9b906f06a926d", + "validator/evaluate.py": "fe46d6fdfecccd5ce3fe8ac517aa8db39dc7c7dacf1aae775b62a7f3b5cc9760", + "validator/verify_raw.py": "ca9951697caf851a0c9facc49d3f4bd560f376647fcd2c976270ad2002dcd5f6" +} diff --git a/evidence/indexer-255-limit-sizing-20261030/results/affected-tests.txt b/evidence/indexer-255-limit-sizing-20261030/results/affected-tests.txt new file mode 100644 index 00000000..88356b2f --- /dev/null +++ b/evidence/indexer-255-limit-sizing-20261030/results/affected-tests.txt @@ -0,0 +1,3 @@ +............................................................ss.......... [ 62%] +........................................... [100%] +113 passed, 2 skipped in 53.73s diff --git a/evidence/indexer-255-limit-sizing-20261030/results/independent-review.json b/evidence/indexer-255-limit-sizing-20261030/results/independent-review.json new file mode 100644 index 00000000..022a1a00 --- /dev/null +++ b/evidence/indexer-255-limit-sizing-20261030/results/independent-review.json @@ -0,0 +1,128 @@ +{ + "reviewed_at_utc": "2026-10-30T08:30:47.957157+00:00", + "scope": "Independent saved-output/source/arithmetic audit only; no retrieval or timing rerun. Exact reader.read/indexed_skill required-resource verification.", + "baseline": "f93df0548a26714f6514337a8525c7c14108acad", + "candidate": "9f7862a9f8619dd68ac59f12736f6b50da10d9e8", + "runner_sha256": "fe46d6fdfecccd5ce3fe8ac517aa8db39dc7c7dacf1aae775b62a7f3b5cc9760", + "paired_groups": 120, + "arm_receipts": 240, + "mode_comparisons": 480, + "output_parity": true, + "source_before_after_and_current_identical": true, + "bootstrap_recomputed": true, + "metrics": { + "context_api": { + "paired_median_gain_percent": 7.098877743926381, + "paired_gain_95ci": [ + 4.048262810162958, + 10.614829211904599 + ], + "p50_change_percent": -5.763618073452181, + "p95_change_percent": -32.9411077361231, + "p50_change_95ci": [ + -8.949749849290267, + -2.725503643668059 + ], + "p95_change_95ci": [ + -50.601304184113104, + -12.990828764875516 + ] + }, + "default_api": { + "paired_median_gain_percent": 9.43424477752091, + "paired_gain_95ci": [ + 4.603267611296492, + 13.337351437091183 + ], + "p50_change_percent": -6.205209666429812, + "p95_change_percent": -23.826233930620834, + "p50_change_95ci": [ + -9.786019053699235, + -3.0363831683991815 + ], + "p95_change_95ci": [ + -43.36007076233995, + 1.860914709383743 + ] + }, + "default_cli": { + "paired_median_gain_percent": 3.974159412973369, + "paired_gain_95ci": [ + 1.4083114467975126, + 8.746270620946916 + ], + "p50_change_percent": -3.563052589953841, + "p95_change_percent": 2.957726056732457, + "p50_change_95ci": [ + -7.671345176007338, + 2.268486090834343 + ], + "p95_change_95ci": [ + -16.703171909592108, + 17.294299031876182 + ] + }, + "search_cli": { + "paired_median_gain_percent": -0.5137363838687043, + "paired_gain_95ci": [ + -5.567556545513452, + 3.5983360196163208 + ], + "p50_change_percent": 0.5069227477990879, + "p95_change_percent": 8.991532975478789, + "p50_change_95ci": [ + -5.60419094777459, + 4.633352077175856 + ], + "p95_change_95ci": [ + -42.024943749883306, + 32.84556993923775 + ] + } + }, + "required_resource_checks": [ + { + "ref": "package:inferrsi.ascend.skills.torchnpu_pinned_host_memory_lifecycle", + "required_count": 2, + "emitted_count": 2, + "bytes": 19652, + "revision_match": true + }, + { + "ref": "package:inferrsi.ascend.skills.torchnpu_device_memory_lifecycle", + "required_count": 2, + "emitted_count": 2, + "bytes": 17459, + "revision_match": true + }, + { + "ref": "package:inferrsi.common.skills.host_memory_management", + "required_count": 10, + "emitted_count": 10, + "bytes": 69776, + "revision_match": true + }, + { + "ref": "package:inferrsi.common.skills.audit_llama_runtime_state", + "required_count": 2, + "emitted_count": 2, + "bytes": 24572, + "revision_match": true + }, + { + "ref": "package:inferrsi.common.skills.cgroup_resource_controls", + "required_count": 1, + "emitted_count": 1, + "bytes": 7348, + "revision_match": true + } + ], + "context_bytes": 138807, + "timing_gate": "PASS", + "limits": [ + "One host and frozen workloads, not a universal speed claim.", + "Search CLI p95 point regression about 8.99%; its 95% CI extends above 20%, but preregistered secondary uncertainty gate covered p50 only.", + "No ranking or semantic accuracy improvement established; #255 accuracy objective remains open.", + "Old failed experiments remain distinct and unchanged." + ] +} diff --git a/evidence/indexer-255-limit-sizing-20261030/results/lint.txt b/evidence/indexer-255-limit-sizing-20261030/results/lint.txt new file mode 100644 index 00000000..1f5f344d --- /dev/null +++ b/evidence/indexer-255-limit-sizing-20261030/results/lint.txt @@ -0,0 +1 @@ +All checks passed! diff --git a/evidence/indexer-255-limit-sizing-20261030/results/raw-files.json b/evidence/indexer-255-limit-sizing-20261030/results/raw-files.json new file mode 100644 index 00000000..8452bf5f --- /dev/null +++ b/evidence/indexer-255-limit-sizing-20261030/results/raw-files.json @@ -0,0 +1,1001 @@ +{ + "archive_sha256": "50f1055d01a6f1305ef34c798a68fdf5334fc1b0033b0fc7808f11b443f89dea", + "files": { + "A-capture.json.gz": { + "sha256": "d8c69921ed459a04439a933d125c409a2b09da4c010a6469d0d86551e419c7f4", + "bytes": 253021 + }, + "B-capture.json.gz": { + "sha256": "d8c69921ed459a04439a933d125c409a2b09da4c010a6469d0d86551e419c7f4", + "bytes": 253021 + }, + "environment.json": { + "sha256": "4012e16b40ff82ef16210cd5f938cf1f7c2f75ab9a83b45ef24397552997531d", + "bytes": 738 + }, + "group-000-A.json": { + "sha256": "3ad731c179a4d16a63c3de7467b7bd95b4843e3503d06101850272f4c2077d7c", + "bytes": 1029919 + }, + "group-000-B.json": { + "sha256": "a47f3accafeae332bb57c81c29e786ca8354f6aa8a0d79cc05f5291a0d8cf4a4", + "bytes": 1029912 + }, + "group-001-A.json": { + "sha256": "cc82097f616e2c17b3e6becf820dc95fea875379f6d0223c7793588034b34dec", + "bytes": 1240 + }, + "group-001-B.json": { + "sha256": "531dee4c720e2a8442641631f6523d524ee65894ac73565f84044915b109a5f8", + "bytes": 1249 + }, + "group-002-A.json": { + "sha256": "974f3c077203c28cc02983ca78cae188b016143f7322938771ef894ecff63506", + "bytes": 1249 + }, + "group-002-B.json": { + "sha256": "594f0de5da3522175b4804831f1743e33ffbcb607c71267382b74d12a190b909", + "bytes": 1241 + }, + "group-003-A.json": { + "sha256": "a62cda4116b4a8390b1efc8f9d4a2544b6f5c14b5d3ad2c10246b8736e40f344", + "bytes": 1246 + }, + "group-003-B.json": { + "sha256": "dc488f238efcfde9467e15a3e8ace8825c9a2bf7e7934efc1d2ad6dccefb785f", + "bytes": 1245 + }, + "group-004-A.json": { + "sha256": "bc40d7567ffb903c41266b7bd9a5420cbdaf588e2d57df9bbfeaf98aa2168be3", + "bytes": 1246 + }, + "group-004-B.json": { + "sha256": "408c9177fdb11017d95b6510f46930735995bb17ef3111cf7a9e70d8acf7af88", + "bytes": 1246 + }, + "group-005-A.json": { + "sha256": "7c54a5a717b9e1d1b39026cfa3991f95b7d48627876140a4179bfb41af123c84", + "bytes": 1237 + }, + "group-005-B.json": { + "sha256": "5bc60d03846d95655b7d53e01bb90bbb6682238083acd808e370b42c060ab4f1", + "bytes": 1232 + }, + "group-006-A.json": { + "sha256": "a4f899c914d02f998f5a672b324699e5d1ea7bb787b8ff2cf1b09ea074363dc0", + "bytes": 1230 + }, + "group-006-B.json": { + "sha256": "80475d9523627c3ec74691860795f47f2d7b4456cd3032211534440733a0b819", + "bytes": 1234 + }, + "group-007-A.json": { + "sha256": "82e81824038da95289f0b694f4aa28b3fd2ceddcd7fe38be9b9cb158b47c3bad", + "bytes": 1240 + }, + "group-007-B.json": { + "sha256": "f3b0d70c4cba7f564a040fa104ac3f1eb274cf1e3f38a13f4d6e066daae049aa", + "bytes": 1242 + }, + "group-008-A.json": { + "sha256": "22f79f102d6e40734681f668c5ccab6a5c022b82bf73bad6a6ca4afd670ff61e", + "bytes": 1234 + }, + "group-008-B.json": { + "sha256": "cecf36fb2e95bdadd9a8fb5a8a2cdee020d4a1770534c1c35a1592f6abb9cb5a", + "bytes": 1228 + }, + "group-009-A.json": { + "sha256": "b2868f349416dba0b5a150f2a3840df20641a3480c184138427c863d46cf2088", + "bytes": 1233 + }, + "group-009-B.json": { + "sha256": "323aa7964ae84b47d7cfb5f33910cb208833a70b078caaf63cfd82898a004f25", + "bytes": 1240 + }, + "group-010-A.json": { + "sha256": "7189884ee69f1cfad5d3bec31a579e1ef4ed0b4f3a02b42d2bf3314bbf84ba29", + "bytes": 1238 + }, + "group-010-B.json": { + "sha256": "a26ad00ccb5c418906a0b0782d6f4fa4dc4428621cb217ba2b27931750c2e2eb", + "bytes": 1243 + }, + "group-011-A.json": { + "sha256": "b28c663691fc1bc94a707e2cc540929ffb3d25eef19c165dea201438a8702318", + "bytes": 1233 + }, + "group-011-B.json": { + "sha256": "32e0482faa3217e31b3cb87dd3159c68ed69e85a40d66a2e73af5269d48ad024", + "bytes": 1234 + }, + "group-012-A.json": { + "sha256": "32aa994897739712d45195192e9549963cf6f6f2b3291d01af4708ec1a0f3996", + "bytes": 1232 + }, + "group-012-B.json": { + "sha256": "178a1d79219484b812db957d7fb25e2c4785ef9752823b73d110b421d55bec29", + "bytes": 1241 + }, + "group-013-A.json": { + "sha256": "58cd72719be556ef7545ff46101609874a618a332934e1e96e3605614bc37bb0", + "bytes": 1234 + }, + "group-013-B.json": { + "sha256": "b9b63df2f6d68bf60330c8cd41d3fbb194826d7b4f600d090149287f0fe3737d", + "bytes": 1216 + }, + "group-014-A.json": { + "sha256": "6697ca3d97e1019dda33bc899285840448c7c8db7eca619739f4b85137cd58ff", + "bytes": 1234 + }, + "group-014-B.json": { + "sha256": "938c943148b3b410998be5e548d2a1c6a221e3c55f0440eda8c5a0b6a06f18ed", + "bytes": 1242 + }, + "group-015-A.json": { + "sha256": "3c19aa59d916ddcaeb4b564a178b7c401d6fac44e1409c62c41100aee01e3321", + "bytes": 1237 + }, + "group-015-B.json": { + "sha256": "e1cca4594fe6b20a1728e321da65c74694850e16d246112d569ef40737a72842", + "bytes": 1239 + }, + "group-016-A.json": { + "sha256": "c3a0095fac0d55e3d9ad4891a7abd03f7a5af005b7320e31aba1f1958ced9f48", + "bytes": 1233 + }, + "group-016-B.json": { + "sha256": "b85c9e6c916de59272c2a5fa2e98b8a175e2fa24c70905f3fed621dcdeb905df", + "bytes": 1235 + }, + "group-017-A.json": { + "sha256": "ed415bf13fcae54a5ea168716f56d749c20b1d157965f8d83c5962259fdec92e", + "bytes": 1238 + }, + "group-017-B.json": { + "sha256": "0bb34ebce9389d9585ba606cdeccda4633af56db09813b062503702a00760d4a", + "bytes": 1237 + }, + "group-018-A.json": { + "sha256": "2d34a8df05eb583473f2bccc23e9c70bc26aaebf19c5ebc8be21e397957a4431", + "bytes": 1234 + }, + "group-018-B.json": { + "sha256": "9dbcb2604b0cb4d3eff3bf5f1d7a743587a73bb43894bd55a7b3e0e3594a45a8", + "bytes": 1231 + }, + "group-019-A.json": { + "sha256": "15fc13dd354dabd088f287236794cb875330c3a8936ed1bb9dda10443ad1b822", + "bytes": 1239 + }, + "group-019-B.json": { + "sha256": "5ec9ec1245ae47a6e504947f19575ab0b217e9174afe31d6ff770bbc07f9091e", + "bytes": 1221 + }, + "group-020-A.json": { + "sha256": "0a3228da08c5c52f1546183ef4bd718ae4fdab5d1a2561607c0c786cc1683d92", + "bytes": 1237 + }, + "group-020-B.json": { + "sha256": "9d77f3611c95b67f016c60e6a2ecd865759addb4061fe543b756a7c1d064f18b", + "bytes": 1243 + }, + "group-021-A.json": { + "sha256": "282aa3b5df4c96d56a4ab7243ab5d7ee7085e2f34b705fdd5b0fedea66c513dd", + "bytes": 1225 + }, + "group-021-B.json": { + "sha256": "cf790c2ddd5582c3ad531121c6f75b08128559aad88f419aaa6c7be497e0eb08", + "bytes": 1203 + }, + "group-022-A.json": { + "sha256": "ba1b68951e94a9b9cd8808df5a3fe0965fef0f42d9d82a956f211e41aaa4e0ba", + "bytes": 1194 + }, + "group-022-B.json": { + "sha256": "2494d843cb53cb6fbe4d7620bc462f6153d1d53503d32ac4c3401a749cd53b57", + "bytes": 1209 + }, + "group-023-A.json": { + "sha256": "afc3cd0beee3a86cb02670335281fb8a92a394fad4508687ff26230afe10ef1a", + "bytes": 1205 + }, + "group-023-B.json": { + "sha256": "7cb98f87f6fddd1707d7bd24599fb64da8423146f73b232d52d945a520ae71ed", + "bytes": 1206 + }, + "group-024-A.json": { + "sha256": "50576a287f41178bf6e695fba2af9b057fb5b9a75095ee4f7e5d697da6296799", + "bytes": 1204 + }, + "group-024-B.json": { + "sha256": "24c0fd2ab056da37d1ee55e0851a77e642e35cdcac27e11fa003fd9dfafe8f4a", + "bytes": 1204 + }, + "group-025-A.json": { + "sha256": "087479c9bf5383cc670a20de24e02ec7d7061be2291e494867f191de6f1ed8f9", + "bytes": 1203 + }, + "group-025-B.json": { + "sha256": "6cd299448b976d5dfa4ce8efcac5ec00a591187edabd0310fcf79a9918999cf5", + "bytes": 1204 + }, + "group-026-A.json": { + "sha256": "c97bc69507ea116de54d69a41348882c4e65e32f631578b74b9c1e69e39fc401", + "bytes": 1208 + }, + "group-026-B.json": { + "sha256": "f08dbab585740219138714121e4c51d8f1a2a01ff06946bcf050aa7b0af44b99", + "bytes": 1204 + }, + "group-027-A.json": { + "sha256": "989c5521336423287a6869152e474e9e6588ada4afa85b0fe52f11f262a06b0e", + "bytes": 1203 + }, + "group-027-B.json": { + "sha256": "af93daa22baebcdf39b39273ae7d05fdda00206c49d2f940cd452e4e6ef7a068", + "bytes": 1224 + }, + "group-028-A.json": { + "sha256": "817c6c26b0e970a758212993ef610466b3c35670383e835fcc4bc305568c8ee3", + "bytes": 1242 + }, + "group-028-B.json": { + "sha256": "00e4a67fe3b93955120bef404677556bd538c9c01b70b0b39a9fa10bf27cde88", + "bytes": 1242 + }, + "group-029-A.json": { + "sha256": "87909615004023bd08b2625b24ff0161326a7c582e23a8f32de94e3d706975e8", + "bytes": 1247 + }, + "group-029-B.json": { + "sha256": "22d40275e0c9a6e6af34a651bad864f5056a9b8db5616ea6626ef4c1dcfa44f7", + "bytes": 1246 + }, + "group-030-A.json": { + "sha256": "83c0e77107663c030acaf6a5a86b1ed8e2c101a27b1ac5c7c82ee0975664469f", + "bytes": 1227 + }, + "group-030-B.json": { + "sha256": "b86e93e41065d21c996d918269f4e4552c1a8ef40c469c04fea7b0041ce56d44", + "bytes": 1233 + }, + "group-031-A.json": { + "sha256": "a35060342bbfdff3ecf058e7c69936f7082823c530cbd3f9bb207186ecc91213", + "bytes": 1242 + }, + "group-031-B.json": { + "sha256": "f6b4fdffd3be7eaa10b71977a399452e0603006ebfe8d104f119f16d625994e8", + "bytes": 1239 + }, + "group-032-A.json": { + "sha256": "a2ab7060e8189505f7c207ba984936329036fe7c0661ced4c61ffe6901f44d1c", + "bytes": 1243 + }, + "group-032-B.json": { + "sha256": "62e49c5543189c2ccd2585e2c2afc8b2832b56f7f90ef06587dc191da384b751", + "bytes": 1238 + }, + "group-033-A.json": { + "sha256": "3405b92800ecbde5f1e7c070e6d29c053434f09ff24f0c12d0e9d4de46d1a2a5", + "bytes": 1240 + }, + "group-033-B.json": { + "sha256": "7f5169f8e01d5f5cf18269d4b1dabb58fc254deb02e28d5002214ca3539b07d2", + "bytes": 1238 + }, + "group-034-A.json": { + "sha256": "d724aea26652daa9271d243862c5ff85339f1b68076e9530798fc49df3cd76c4", + "bytes": 1242 + }, + "group-034-B.json": { + "sha256": "f135c026dfce4ce420697ad064bc357087870cf6d49de419de84d026eece3cc5", + "bytes": 1242 + }, + "group-035-A.json": { + "sha256": "bf62660c812e937211dd814ab83ea41bcf23bd848555836da98f35ccf1d41332", + "bytes": 1225 + }, + "group-035-B.json": { + "sha256": "e6a8e0aafada211d396ef4526766c6a23e360914cf29b66d3c1d6ce2accf1bc7", + "bytes": 1230 + }, + "group-036-A.json": { + "sha256": "f350d6960df019bc1693db79e01ae371d3a35aafd3b6a03d60557f358ce5c1ed", + "bytes": 1218 + }, + "group-036-B.json": { + "sha256": "d34f8fd4e0a687e9a66933b8ee88815c6406745562f71e6f7e19f060cb481966", + "bytes": 1240 + }, + "group-037-A.json": { + "sha256": "7f48d06e52cba2c5d0f6193796f8b732e793a9ee88dafd16fb9730274d11e87e", + "bytes": 1239 + }, + "group-037-B.json": { + "sha256": "b000d0033da6f99b163ce649d9e9e61d94c7c79b38140464695a0da626736d28", + "bytes": 1231 + }, + "group-038-A.json": { + "sha256": "50d4660c645bdf47e60258491453a91586a98d454741efaa94d80680f814aa76", + "bytes": 1228 + }, + "group-038-B.json": { + "sha256": "db12592be3f88fe3f11f30352c83a1d758e24dc9d0af6bd029140bc5b7097709", + "bytes": 1224 + }, + "group-039-A.json": { + "sha256": "96c7c68efea33f213853f65f2af98533ee6f2a54deae7aa91c7e1703c88d55fc", + "bytes": 1247 + }, + "group-039-B.json": { + "sha256": "0f51bdc1fa3e9cc9b7f5933a2842b0a5a46da834976c3e78c2fcca98b660998d", + "bytes": 1244 + }, + "group-040-A.json": { + "sha256": "2cc60d172f5319523c4a01e07fe136a71039eafc33b54cb41b23a2dd184d1b9a", + "bytes": 1239 + }, + "group-040-B.json": { + "sha256": "57834230b9c050b31220e9b564137f98a939c00cd83c20c0b3af4dd8fe7efb3e", + "bytes": 1245 + }, + "group-041-A.json": { + "sha256": "8e6102aef41b0c4122af667eb3d2b3187e87ed78167ab1053cd8442683e4aee6", + "bytes": 1247 + }, + "group-041-B.json": { + "sha256": "431a4f7b953f3b707019672c7d45f65cdb1c7c0ee0eb87346ad809d9149d74c2", + "bytes": 1246 + }, + "group-042-A.json": { + "sha256": "3a0ba97598a4f516d0acd8dafae8ca783a4a48ad9d20550c0b8d6f4c6fe11a99", + "bytes": 1227 + }, + "group-042-B.json": { + "sha256": "3833dbe9b632ae3aac1c2fa9832eb8a04b20b7eafd157caebd6c4306f66b5fd5", + "bytes": 1232 + }, + "group-043-A.json": { + "sha256": "e85e27a5e3f3e58e1fa8c070913575a0e3f521e98522c4cbef818b8dde6e251d", + "bytes": 1236 + }, + "group-043-B.json": { + "sha256": "321ac1fb908913257e3ff2dc7f348add07bb2905ed64dc54bef1a3a032d30075", + "bytes": 1237 + }, + "group-044-A.json": { + "sha256": "5afa3d434f00eadd4555b9573854f881b98ad317a32cf7a3855aebe0dc2cf1c9", + "bytes": 1228 + }, + "group-044-B.json": { + "sha256": "db16a1e0fe953c1442320d34104cf749d4d9736d96c03902c8761b96362a6289", + "bytes": 1236 + }, + "group-045-A.json": { + "sha256": "b07232670abc403191107d56c0f409da9660d8e3bc7447ae3cd6132e421497c9", + "bytes": 1241 + }, + "group-045-B.json": { + "sha256": "4e876b8e67cbf06a0b07b49e85814984f0405be2cac7748bd18e101b224a7d1b", + "bytes": 1235 + }, + "group-046-A.json": { + "sha256": "7812b8f4dad657a3e291fc2368ce4fd4273f17441e0c183afeb336984cd6b868", + "bytes": 1240 + }, + "group-046-B.json": { + "sha256": "5cc5db23db006fd1d6fcfeed3d2ad79bdfe4c0e676aae76f8ede0cfd1f15d7cb", + "bytes": 1231 + }, + "group-047-A.json": { + "sha256": "87a5467d63e8d3088b4110787f7874f85763b6387b1f87108f3e9140dc706def", + "bytes": 1237 + }, + "group-047-B.json": { + "sha256": "c269a01b87f71a7cbdbac7e8ca37ee7ec8cfdf9bf23e43d61483e3e7a74594ab", + "bytes": 1235 + }, + "group-048-A.json": { + "sha256": "fa20b7433ec26c89618fae02d673fbc24b107b34bbebe697bef4537882799874", + "bytes": 1238 + }, + "group-048-B.json": { + "sha256": "32de3e813e6ec66eef18897a55db9128d77c59dee6a53ac8ea50ddc1815c959f", + "bytes": 1228 + }, + "group-049-A.json": { + "sha256": "8e278d5237c32912cac08c768e17d923ed5d566e9de30c39d6a81a13d75672c3", + "bytes": 1223 + }, + "group-049-B.json": { + "sha256": "e7f2b9aaf90d05a286269a3cc5ef64405e50c6280823f50f4ab67ae493c4cc03", + "bytes": 1230 + }, + "group-050-A.json": { + "sha256": "a9f79cdcae576b0649393d8908e13f19d6c0cc0a8bb4d4e27c7fa4eae0653ae0", + "bytes": 1234 + }, + "group-050-B.json": { + "sha256": "f8df325f8d9ac0383acb894378a1ca5d4ced1c585fff27414b54017b3d51415d", + "bytes": 1240 + }, + "group-051-A.json": { + "sha256": "024acb4acc01a8dd68332c527fa33e28de8623924743bfd1cc1f4880a804826d", + "bytes": 1241 + }, + "group-051-B.json": { + "sha256": "8ecbaaa789924ee47d480d5941f340d03358f3de4bf76e38f7cc035121fa8349", + "bytes": 1240 + }, + "group-052-A.json": { + "sha256": "a2e09e4e8eebd68848cd823f6ad79d92fb9d19516f971498b925d16de04d6130", + "bytes": 1239 + }, + "group-052-B.json": { + "sha256": "bb1d74b75b76659d13c5bdd5597a7400f496363080984556879ada1c20d2577e", + "bytes": 1246 + }, + "group-053-A.json": { + "sha256": "3719784961a9aeb86d00e266e90fc24d1fadc9359e1568878f8197e1fb0d8d89", + "bytes": 1245 + }, + "group-053-B.json": { + "sha256": "f261c9704c968777a97e1c451f32747ad08d8dad80aa1b9281b674d7c375b3e6", + "bytes": 1242 + }, + "group-054-A.json": { + "sha256": "8bea77052fbb9da90acde51b48843c912acda984dcbd6e7c1356d43a81af4d1e", + "bytes": 1237 + }, + "group-054-B.json": { + "sha256": "0a81dc8fbef9a1df28759e701306cbd82600b5dd62c5084e1f10fd4b04ae5b17", + "bytes": 1241 + }, + "group-055-A.json": { + "sha256": "7ec1bcf77629b1931a37c8418e5d1c7a96f04d405090212604080400b25bf876", + "bytes": 1245 + }, + "group-055-B.json": { + "sha256": "194b2902c335f3ab5a8974d6a91b341cc976b2d297bfe7c2fdb35a19896c023c", + "bytes": 1237 + }, + "group-056-A.json": { + "sha256": "d193ac8c7e320a9aec203e2b23185c2d5a74098c398d4d166b7ff7f96d11880e", + "bytes": 1248 + }, + "group-056-B.json": { + "sha256": "f3ca24317633dbe68e10d98b622befa0ded4fe8c31ab930d6facb3d67b4e2232", + "bytes": 1234 + }, + "group-057-A.json": { + "sha256": "3d467d5f8b4bba625fbd32bf77dbb67a4f50fcbed7c41435adde2e8060615b74", + "bytes": 1238 + }, + "group-057-B.json": { + "sha256": "643f42fc89979bcd61cfb84b6a7156632b774e6f944a2cf6338f2c58bf62d221", + "bytes": 1243 + }, + "group-058-A.json": { + "sha256": "31cf34ab8f039e66aec1fca86cd32d437b6905201aa515e327cd2d01db6d63cd", + "bytes": 1235 + }, + "group-058-B.json": { + "sha256": "39ddf928a1389bbf5a2619a3912d73db50406573e62150213beccb3855c1e31c", + "bytes": 1228 + }, + "group-059-A.json": { + "sha256": "6957465efe092753b19388bbeaf5be961a7e608e3fe16de4c6f67bcba6990d6d", + "bytes": 1240 + }, + "group-059-B.json": { + "sha256": "17bb8d5dcad0ee3ea75f0da7d13225446a5ddc09e0bf601dd3e0f3ef4cb552b5", + "bytes": 1240 + }, + "group-060-A.json": { + "sha256": "e703216df9e02c238870c7dc7632f0dc8926898de5d817be68976bce73e0ee79", + "bytes": 1244 + }, + "group-060-B.json": { + "sha256": "ceb24cc27c49a1c7c1db5a357a44f49ddb433d4596dcaea335744d06cb33d17a", + "bytes": 1239 + }, + "group-061-A.json": { + "sha256": "a070f488226385cc531d4e302446b45470d30ad778ccce6d0df3a88f5ca1d5ad", + "bytes": 1232 + }, + "group-061-B.json": { + "sha256": "7b3e6101bc2770b2e93295d049a27f44a0d8a73e90e90bf0d228d92c2cdb1561", + "bytes": 1242 + }, + "group-062-A.json": { + "sha256": "cb7b36578e923945813c76e1f71e4cf31fe3d6fc584bef549fd53ef8ffde6eea", + "bytes": 1226 + }, + "group-062-B.json": { + "sha256": "4b7ac4397d2b26175a108e6045c0ce1ef6c19a6bf6276edd23e36cf7bfd132b8", + "bytes": 1238 + }, + "group-063-A.json": { + "sha256": "7beefb3c7b336c5b3e1999219746b9788c48094b976f5b461f9795bbc0f07d88", + "bytes": 1234 + }, + "group-063-B.json": { + "sha256": "8762fc1a1f61a40ed7e47d8792524f47fb1d33b6f6f18e715ac3427852375d66", + "bytes": 1236 + }, + "group-064-A.json": { + "sha256": "4fb6296c103d8fa6b039b277d2d586a73621d9745a96ff904e8f5f543590e71f", + "bytes": 1232 + }, + "group-064-B.json": { + "sha256": "b8ab7040ff8f6e3dc4c7041d076f75538b6fe72b3f252e123046d635e167c917", + "bytes": 1240 + }, + "group-065-A.json": { + "sha256": "507c38d0b2e34f7837bed24702891e6f8f6553d6ef8875a3788411975525fa76", + "bytes": 1206 + }, + "group-065-B.json": { + "sha256": "759713c3766b9efd040b8455688724e43b0b08d259ad44c814e73fd78db52477", + "bytes": 1242 + }, + "group-066-A.json": { + "sha256": "5a69df58d1e54397b900d7c8a7806a5caaa11256bb5f5f988ef6989b8ddf0be2", + "bytes": 1236 + }, + "group-066-B.json": { + "sha256": "a431986decb5b548cc53eeda00075b4607e6abfc39a868b4b5c00eda697aa290", + "bytes": 1238 + }, + "group-067-A.json": { + "sha256": "7dca436e0708e89f9ed5692b48b30974dde74e4d76b065b6ed8e7b21d2bd6707", + "bytes": 1215 + }, + "group-067-B.json": { + "sha256": "d2ae5ef4e095f2771d5dd0d95924445dc7bfa27343e4031bd0046c06d3d14b91", + "bytes": 1228 + }, + "group-068-A.json": { + "sha256": "c1c0c5134e3c05a2d6e4fde5d4fcbf09ed7b4f843dce3e651347161091f6f748", + "bytes": 1245 + }, + "group-068-B.json": { + "sha256": "da3517a5cec56a0fc3e1f828d2b4b32ccc68e0ff42a0aca6582beaa9d97286cc", + "bytes": 1240 + }, + "group-069-A.json": { + "sha256": "545ef9c61aeb5a5d51e70f7f56b344aeddabaa58c035f1d2f1e8f9a0ebe3ef4a", + "bytes": 1228 + }, + "group-069-B.json": { + "sha256": "66a5f4d1ac2600864ea47cd587149a66aa47617a2ced181160e5ab709b8a3440", + "bytes": 1244 + }, + "group-070-A.json": { + "sha256": "0e624931273d8593ed12a0cba44aee8b65a98c9d71813f8992ac22b7eee69cb2", + "bytes": 1236 + }, + "group-070-B.json": { + "sha256": "e565e18c1ae772292f4bd6b85a4db41f76dbf860544171d16e87c26cb6eb3819", + "bytes": 1234 + }, + "group-071-A.json": { + "sha256": "9c876e3b182ed50075192b9060be6bc32a04312d12bfab77bc035ba3362e69bb", + "bytes": 1248 + }, + "group-071-B.json": { + "sha256": "be52c801060f699f44f4c93110b2fb6cc8131a1fcc078f254a8c3c32822db64f", + "bytes": 1200 + }, + "group-072-A.json": { + "sha256": "1297c7aa4741326ee43a67a3e6abfdb201685d6c45160de169613a0324981a28", + "bytes": 1240 + }, + "group-072-B.json": { + "sha256": "c16dcec8f691535dca8aa01a0cd4b59e54306aa83f6646efcae3992ca7e96023", + "bytes": 1238 + }, + "group-073-A.json": { + "sha256": "7e5bcfacbed9232c7affd35417f160a7b30a3f6149c551dd3904096a48747488", + "bytes": 1240 + }, + "group-073-B.json": { + "sha256": "ffc7d5275e94e8d207258c34938109b78ebd6d1b77911c4e08ae9b4874dcb132", + "bytes": 1235 + }, + "group-074-A.json": { + "sha256": "a046517214ae37a748930a08a004d8f711f9c99e4677d293d0f53244928de8da", + "bytes": 1241 + }, + "group-074-B.json": { + "sha256": "b7885b25c78e5f692bc4a8fe10cdbee720efa5e3eccccf1b9d393f1997f9e8da", + "bytes": 1236 + }, + "group-075-A.json": { + "sha256": "41986c9c13c095a3bcca864061d3b4a0eab8da2ce8ffa47053169edccd377ea9", + "bytes": 1241 + }, + "group-075-B.json": { + "sha256": "c275a76e5d65e26d90f1d6a2e77f6db9a112e5569e2b5559606dedc2cd10f0c7", + "bytes": 1245 + }, + "group-076-A.json": { + "sha256": "84b18db8acc1ce17bf2ba0842e4d2747849d781701258279f14046cac8c4eb16", + "bytes": 1235 + }, + "group-076-B.json": { + "sha256": "65a08d5861e029f21810871ca8af36998f2fa0eb915ba0ca1fe6cbc60afd60a8", + "bytes": 1244 + }, + "group-077-A.json": { + "sha256": "57227fb7bc3a31a897ef141e2aa27e031d0eb89cae6f5d34d4616505533d26a9", + "bytes": 1240 + }, + "group-077-B.json": { + "sha256": "e18327dacfb49143c86873a6f039e0f6644329cd9e02dfeb9a3924237473fb51", + "bytes": 1228 + }, + "group-078-A.json": { + "sha256": "9912c9626c76e02c14fc22af6123c0dc150ed42bed5ec943fb72500c8b291c70", + "bytes": 1244 + }, + "group-078-B.json": { + "sha256": "5ddff3005a3d437028d7a7c74e13dc4f529cc43c22e5d9eb0597c95788149526", + "bytes": 1230 + }, + "group-079-A.json": { + "sha256": "0ec3f2228f33313e055c653446523724406a4fd83c93db431ad1a096e36f0d20", + "bytes": 1244 + }, + "group-079-B.json": { + "sha256": "45cac740a0dd4a6e9ac712281481afe300b458f634790f7be059196a13ed06ce", + "bytes": 1240 + }, + "group-080-A.json": { + "sha256": "d5da93908342f7b504a637580a537f3bdff54c13b750cd0fb7e83c30fd5315d6", + "bytes": 1237 + }, + "group-080-B.json": { + "sha256": "e70b5cbb136db91cbee8a4b99c1be85bc4be97d97e3aba6f3f0a5986d900d5aa", + "bytes": 1236 + }, + "group-081-A.json": { + "sha256": "cd3199fa13132389aa9af3c1dad45981cf2f10acb59f37c37bbf80c707d776ee", + "bytes": 1236 + }, + "group-081-B.json": { + "sha256": "983b523cf1d1584ccaf47f2f76365d2cffdd8eb1df240eb1259e8dc5ac527cf5", + "bytes": 1242 + }, + "group-082-A.json": { + "sha256": "ef8fbbd7765da88e235aeea8c3f89f939be895115e4bde28610397cca9dbf130", + "bytes": 1238 + }, + "group-082-B.json": { + "sha256": "53866250ad65fec7f249bd74711ac957f09309126fd2248a948e49d435ac2c15", + "bytes": 1226 + }, + "group-083-A.json": { + "sha256": "47c0c8467fbbf3435e9f61a7851f5ffebf8fb0c5f2ad158f52b28ce454e53768", + "bytes": 1222 + }, + "group-083-B.json": { + "sha256": "a1e297f299948de774a72dec1c1e68f33c4b05d801d18f971456e68c52284e68", + "bytes": 1221 + }, + "group-084-A.json": { + "sha256": "81b810f283c60d2e29cfc168587182275fc87a71533261eb8a88dfcd37807d45", + "bytes": 1226 + }, + "group-084-B.json": { + "sha256": "fd2ba8125bfa96b9683a01df06f27d52329691cdd06d48a074aa9e500aa39259", + "bytes": 1226 + }, + "group-085-A.json": { + "sha256": "0beca3a0abadc90607d58fdf771ad7095275acaac3f3556592efb91dac996eb6", + "bytes": 1223 + }, + "group-085-B.json": { + "sha256": "7270f36a2487f0c72c3b36ce665f0e952597ed30ce381d5cb17c8aa8181ab05f", + "bytes": 1234 + }, + "group-086-A.json": { + "sha256": "f0fc1fbddb1cf6b7b369d2f81945bb76a536dc41b66304e2901e168f8e9f56a7", + "bytes": 1242 + }, + "group-086-B.json": { + "sha256": "353e6586b81b40195c929eb2c68b161549d2597e419e19214684881bd7fb379e", + "bytes": 1244 + }, + "group-087-A.json": { + "sha256": "51113cd1b672de2084faa80b60ac356ad0261f0aa0633c8b5002da94aff59102", + "bytes": 1246 + }, + "group-087-B.json": { + "sha256": "0791fcf38499813d8b8e7cbd28ec7723bd1d313ea343ab7bb422c0fd256152d4", + "bytes": 1246 + }, + "group-088-A.json": { + "sha256": "da0f8e5da7e016b172223e9812a89af319ee9a736b12a8fb1d68d09d1ee594b8", + "bytes": 1232 + }, + "group-088-B.json": { + "sha256": "c3b0710a142872530e3dcb842bcc7b85cc24255053238ef54febab4b32a7d11d", + "bytes": 1243 + }, + "group-089-A.json": { + "sha256": "f7c84c6681c06e6c3a703b5b1a584175f0afdc1ffd6e47508abfe1312dd9c73c", + "bytes": 1239 + }, + "group-089-B.json": { + "sha256": "1bfcb141e2f69910ad0d128d9d4813328aa9a22f4f28e86646a9624d030c56d0", + "bytes": 1236 + }, + "group-090-A.json": { + "sha256": "b307c05b89ad43228b62faed5c6b237c7959402b4d66f1c77932b0245093e1d7", + "bytes": 1247 + }, + "group-090-B.json": { + "sha256": "fcd94edbcf6a2e0ac908c19719149ddcfd09af21f1d3be24dc906b678468ec7c", + "bytes": 1248 + }, + "group-091-A.json": { + "sha256": "287b278437ef0eb0a3b9b8c1f3152616da38c5829730971fdd82c9d11ae6fd8c", + "bytes": 1241 + }, + "group-091-B.json": { + "sha256": "47869f2c3fbd0db7c03c5f15269924969e7a07880a3cac1370d5e7c539e752ad", + "bytes": 1233 + }, + "group-092-A.json": { + "sha256": "2e60b4088956904233f2946e0ec708a0ea32a419676c58de366959746165a71c", + "bytes": 1242 + }, + "group-092-B.json": { + "sha256": "14b5f7c3954100123e47509bb25d9191deb376a6768679fd1d2e0e33612bf5a4", + "bytes": 1238 + }, + "group-093-A.json": { + "sha256": "e842e4fa7a81bb48aeea3cf9b08fd45b49ae707a0ed4df236315036c1b68a6e7", + "bytes": 1227 + }, + "group-093-B.json": { + "sha256": "df77dfb9d64a8bbbcb1e871f6605fda500c83b00d75e04f14281e62229acad83", + "bytes": 1238 + }, + "group-094-A.json": { + "sha256": "b94aa15d5afe9421ad7fc3353d3772f6b98461310812f299b3e823bcbb0c15b5", + "bytes": 1244 + }, + "group-094-B.json": { + "sha256": "775a527eb4fae8630afa69fdc7a2ffaa285384ec5c0c4d328b386dd12f713868", + "bytes": 1246 + }, + "group-095-A.json": { + "sha256": "c69656a410a6a64303a12d3aeac0974deb939d33a5b9f1bb4e00d5dd79172ba4", + "bytes": 1238 + }, + "group-095-B.json": { + "sha256": "bcd927b37e6e6ac38acf2a7a31f08ae73d179def2fa603c024ce0c2c5404ddff", + "bytes": 1235 + }, + "group-096-A.json": { + "sha256": "13eb3f83f0b39273d8ca3caf39a720ce18fde6e90aa95241b0d302e479e7744d", + "bytes": 1236 + }, + "group-096-B.json": { + "sha256": "9d14acb9fefdc6f9730f81e5de797bd747de373b2651591dbded47e3e1bd68f4", + "bytes": 1234 + }, + "group-097-A.json": { + "sha256": "31327ed1caec6b2a73404974a19a8fe0bec539adbee0dd26768fc8419d060b6b", + "bytes": 1240 + }, + "group-097-B.json": { + "sha256": "11a9fbd33b4751e08f88c4e0c92c8e5b1f6576d8ee9b440835b813726aedd15e", + "bytes": 1235 + }, + "group-098-A.json": { + "sha256": "7b544db63177c53c089dba6f38b6e005e2344284e9c6f5845f58a770bc0564f4", + "bytes": 1245 + }, + "group-098-B.json": { + "sha256": "91ce419f976d511b7e8f5c59a9a3cda7fdc706ca69e44d04598b90f7e178c234", + "bytes": 1236 + }, + "group-099-A.json": { + "sha256": "8bdef0dae2cad469270916a223afd3e4c88c45596d262710849d4968b0806247", + "bytes": 1231 + }, + "group-099-B.json": { + "sha256": "ba0720ad8f2d4e7a8d8498c4baa94c98ca1c3f4892e781909d2213e0b0378a88", + "bytes": 1227 + }, + "group-100-A.json": { + "sha256": "e8fa91774bf3c9cd616585560c5d07801d7925eb4934c49fafa18fbec927e6e6", + "bytes": 1245 + }, + "group-100-B.json": { + "sha256": "be4703a2c531d31df42affbd78b5af3a7a37bac7946ba2145dad7920e19c352b", + "bytes": 1242 + }, + "group-101-A.json": { + "sha256": "e92c0e7d1179505600ec911347de2a4d3236f45063ceb928fc5598d6c3321e23", + "bytes": 1244 + }, + "group-101-B.json": { + "sha256": "b427f4adbe80d4c1de6097b630d4eaa4d94c5d8388d5298889e001826b47b470", + "bytes": 1241 + }, + "group-102-A.json": { + "sha256": "dc5fe4143beab07c535cd98d71391ce1f052b2d732981115181bb7d42bf9bb70", + "bytes": 1241 + }, + "group-102-B.json": { + "sha256": "ca2543d7dd912ffea92cc7a76e303d806a1444502d665a6d2ca050a0e56b82a3", + "bytes": 1249 + }, + "group-103-A.json": { + "sha256": "d37d0cc70fabb5731c658df8d379e4cc1f45939ac14e212d1202c474cecb84dd", + "bytes": 1243 + }, + "group-103-B.json": { + "sha256": "fd235972fa562e7562d06aca4ef2a0d00c06781264634950ecbfa620602ad0b3", + "bytes": 1244 + }, + "group-104-A.json": { + "sha256": "cf3e68c28b8b2f614f50eee8d6d246c1d19f170b4217faee4ec5c16df32682f0", + "bytes": 1232 + }, + "group-104-B.json": { + "sha256": "468bfeceac322aad8b83b164f6a8dc8794758b04fbd548c380b5db034b397835", + "bytes": 1234 + }, + "group-105-A.json": { + "sha256": "90e1d3208295c0342951ed5152be9e2704f6d8134a408cb45075a9bf6787ebb9", + "bytes": 1234 + }, + "group-105-B.json": { + "sha256": "3ecbfa47a14ea9b7cb117fc63d2212fdbf03d5883d097b419ab03c477ca5c48e", + "bytes": 1232 + }, + "group-106-A.json": { + "sha256": "6a0fbec1c48fe34f3f9ee6aa3bd7da62bf83f883619ae93731fac39a16f858d2", + "bytes": 1234 + }, + "group-106-B.json": { + "sha256": "b2de0d49bd64eb47312b50f9c3667074afb93b56f821ab69849caa2d44bca3bb", + "bytes": 1232 + }, + "group-107-A.json": { + "sha256": "0b2b64347ffe464d5b718b2b89df9827d400cf29aa77c9a3efce9ca66e054c4f", + "bytes": 1234 + }, + "group-107-B.json": { + "sha256": "ca20ac86efcf87d127a8000478afc463d9e0699ede9313fae9d569d876c10caa", + "bytes": 1240 + }, + "group-108-A.json": { + "sha256": "be68e38556631aa84ce74b336a5dad046d5a65b84a4c1c2e436c08158260676e", + "bytes": 1239 + }, + "group-108-B.json": { + "sha256": "a05ea28dd34593141ab4e74d6597576515e51c25efa4b266b851044156afd538", + "bytes": 1240 + }, + "group-109-A.json": { + "sha256": "85136d03962f294184e1fd5604b096cf54a445e9130b2e13a86d3dc6f07a966a", + "bytes": 1244 + }, + "group-109-B.json": { + "sha256": "4773c948338e066870c1338d25e25902a8e981d48e9d80f70739a7a0c74259b4", + "bytes": 1220 + }, + "group-110-A.json": { + "sha256": "a02d3f286dc7b5a645752f801b7d9737ba40da7ea5f291862652093daebc0231", + "bytes": 1232 + }, + "group-110-B.json": { + "sha256": "9f3cade6eeb3fa5999d0f26bcda53f3178c70ae0637d32edcabe7fae73411fea", + "bytes": 1231 + }, + "group-111-A.json": { + "sha256": "05f94be5130d141675d715eb6d70ed3189850389154b7c68c799ec4baf2ad0ac", + "bytes": 1240 + }, + "group-111-B.json": { + "sha256": "605bdc9729903167a2ad90b3d4a3564488feff9fb37c129cb6154d3016514829", + "bytes": 1238 + }, + "group-112-A.json": { + "sha256": "74e8dccd05650a3c7052b4f17c543bbeedfdff4a8ed5891796b8f99e3dbfb633", + "bytes": 1240 + }, + "group-112-B.json": { + "sha256": "56ecb0087f3cedf159d9f010ed0d643821cdeb465df0956e9554507a87730c62", + "bytes": 1240 + }, + "group-113-A.json": { + "sha256": "b0293c057f39bc271355317f84d21e05d15134ccc7830519f4e028192fa8f936", + "bytes": 1241 + }, + "group-113-B.json": { + "sha256": "72c80ae2f80b1b100f2209ed76b34da581ccbf617bc7c8c4967184a0349d64f0", + "bytes": 1236 + }, + "group-114-A.json": { + "sha256": "c1d702e6fc6a1d12e941bd0921112bba8853377e576a9b67b9d9698497dc2bf1", + "bytes": 1244 + }, + "group-114-B.json": { + "sha256": "18f89fa5307608b90aa51f273b8d68e451975eeb45d70ec8172a207e52fe7647", + "bytes": 1242 + }, + "group-115-A.json": { + "sha256": "aef2248fe719979ddd24749150762dcbb06f2e61e481a2d0cc0f773a49cb25a3", + "bytes": 1236 + }, + "group-115-B.json": { + "sha256": "238f8a48d8a4c7f083ff0883e5f3a1bf07500d912f3c33987fa5c5467cd3f74b", + "bytes": 1243 + }, + "group-116-A.json": { + "sha256": "38b07ccb6d5f0e63cac87515233ce30c1cc722bd6411d7eb7f74c05839c801ae", + "bytes": 1239 + }, + "group-116-B.json": { + "sha256": "663a3212bc652eb3f9a71435aef84fda35e9d17a6e14fad57f1237f5fcffa72a", + "bytes": 1245 + }, + "group-117-A.json": { + "sha256": "57b1548b47e20570ce3ba65da2eb5c6b180f236908dbae69f7a672fe6673e631", + "bytes": 1249 + }, + "group-117-B.json": { + "sha256": "038060b23f013adb5fafef4afa6b75c487d0c2909d506579f2d1b20cd524b0a6", + "bytes": 1246 + }, + "group-118-A.json": { + "sha256": "86671b3ef48d67d826a059d02b4476b8eceddb3034153853e44e1bdde4c379c7", + "bytes": 1248 + }, + "group-118-B.json": { + "sha256": "dfe35e4ee097657a6b0e56c7eaf5e5edd12faf133781a1a61d4a8573f3bfee09", + "bytes": 1244 + }, + "group-119-A.json": { + "sha256": "428d43e07342c0725c63e9e3cad520c736f4f05b3f0cbfa5e04dd7fe99c9f86f", + "bytes": 1244 + }, + "group-119-B.json": { + "sha256": "4b8830caee6b89e849d39da6578218ceba710f7545b067f9ce746870c7d382d1", + "bytes": 1244 + }, + "groups.jsonl": { + "sha256": "7172f5be1075cf9d3eb5557e19aa98cdf76ef9bfc34fd2b999f0d0d77418bba5", + "bytes": 297493 + }, + "identities-after.json": { + "sha256": "d7d1dd6a429eda4d60aab282090f571f810c954f39434ff4dee7c886d47d905f", + "bytes": 266491 + }, + "identities-before.json": { + "sha256": "d7d1dd6a429eda4d60aab282090f571f810c954f39434ff4dee7c886d47d905f", + "bytes": 266491 + }, + "order.json": { + "sha256": "38cf0ac759c1bed20a459af232c6660e07d636253c01f950b0de858b2524092e", + "bytes": 601 + }, + "runner.sha256": { + "sha256": "3d7fa805ae800e7f24abda2a7f591c692b112749ae5f4255d15552648e481275", + "bytes": 65 + }, + "summary.json": { + "sha256": "45888c28f57685aa91315811a04facf743a2e111a329cf62467b85f61528c3d8", + "bytes": 2056 + } + } +} diff --git a/evidence/indexer-255-limit-sizing-20261030/results/raw-study.tar.gz b/evidence/indexer-255-limit-sizing-20261030/results/raw-study.tar.gz new file mode 100644 index 00000000..89406c23 Binary files /dev/null and b/evidence/indexer-255-limit-sizing-20261030/results/raw-study.tar.gz differ diff --git a/evidence/indexer-255-limit-sizing-20261030/results/report.md b/evidence/indexer-255-limit-sizing-20261030/results/report.md new file mode 100644 index 00000000..6bd04854 --- /dev/null +++ b/evidence/indexer-255-limit-sizing-20261030/results/report.md @@ -0,0 +1,46 @@ +# Indexer limit-saturated serialization study — Issue #255 + +**PASS for this bounded CPU retrieval campaign under its prospectively frozen protocol, including independent saved-output/resource audit.** + +This candidate is distinct from the rejected historical resource memo. It removes only redundant view-size serialization after the item count is full for exact normal Bundle instances. Subclasses retain the prior serialization/error behavior. All reads, full resource validation, ranking, filters, query checks and omission order still run. This does not improve retrieval accuracy or close #255. + +## Controlled result + +| Path | A p50 ms | B p50 ms | p50 change | A p95 ms | B p95 ms | p95 change | A/B CPU p50 ms | n/arm | +| --- | ---: | ---: | ---: | ---: | ---: | ---: | ---: | ---: | +| context_api | 709.98 | 669.06 | -5.764% | 1334.15 | 894.67 | -32.941% | 709.81/669.01 | 120 | +| default_api | 830.52 | 778.98 | -6.205% | 1495.02 | 1138.81 | -23.826% | 829.67/778.88 | 120 | +| default_cli | 1123.31 | 1083.29 | -3.563% | 1575.09 | 1621.67 | +2.958% | 1122.36/1081.72 | 120 | +| search_cli | 209.69 | 210.75 | +0.507% | 349.68 | 381.13 | +8.992% | 209.07/208.56 | 120 | + +Primary statistic is the median of within-pair reductions, **9.434%**, percentile-bootstrap95%CI **4.603–13.337%**; it differs from the ratio of marginal p50s. Frozen threshold≥5% with lowerCI>0 passes. Secondary p50≤10%/p95≤20% point guards and p50 upper95%CI≤10% all pass. + +Untouched search CLI p95 uncertainty remains wide (−42.025%…+32.846%). This sampled tail is not a production SLO or proof of absence of any tail regression. Its point guard passes; the p95 interval was prospectively descriptive. API process CPU and CLI child CPU track median wall time closely here; this observation does not retroactively explain or waive the historical CLI failure. + +## Reproducibility and preserved history + +- Baseline `f93df0548a26714f6514337a8525c7c14108acad`; candidate `9f7862a9f8619dd68ac59f12736f6b50da10d9e8`; tree `261645a7adc0ac097281096df6752ef7fec394f8`. +- Protocol SHA256 `d577712b231be4bf33e66d401da22d50a38b01951707dae7a65b8d9c2dfc6a44`; runner `fe46d6fdfecccd5ce3fe8ac517aa8db39dc7c7dacf1aae775b62a7f3b5cc9760`. +- One execution,120 balanced randomized AB/BA pairs (seed25530), paired bootstrap10,000 resamples (seed25531). Started2026-10-30T08:08:51Z, terminal~08:29Z. No samples removed, pooled or repeated; no interim outcome-based stop. +- Fixed queries: primary default Collect(query="",limit=5), context Collect(relevance="memory",limit=5,context_bytes=262144), matching full default CLI, untouched catalog CLI(query="cgroupv2",limit=5). API reused-reader warmup and fullCLI startup policies are in frozen protocol. Fresh process is not cold filesystem cache. +- Exact source/corpus identities before/after match. All480 paired path outputs have matching SHA256/bytes; default API and CLI outputs also match each arm. Full first-pair captures and all completed-arm receipts retained. +- Historical resource-cache v1 FAIL, separate confirmation uncertainty, accuracyv2/v3 FAIL and cue-study negative evidence remain unchanged. No old sealed heldout was accessed or evaluated. + +## Deterministic correctness and limits + +- Synthetic counter test reduces view-size serializations3→1 atlimit1; all3 bundles still read. Byte-budget-only omissions still size every item until count saturation. +- Invalid normal resource after saturation still reports invalid; custom nonserializable subclass view still raises TypeError after saturation. Invalid0/None/negative/bool limits still rejected. +- Initial focused source tests79 passed/2Windows skips (81 selected), Ruff passed. Broader affected suite:113 passed,2 Windows-only skips in53.73s, including operations,store,CLI,selection and new sizing tests; no full-suite claim. Full repository src/tests/tools Ruff passes. +- Dominant scan/full-resource hashing work remains O(N+B_total), where B_total sums bytes hashed over all candidates (shared resource bytes may be hashed repeatedly); this is a small CPU retrieval improvement on the specified workloads, not service/model/hardware benefit. No peak-memory measurement or accuracy gain claim. +- Current evidence supports considering this small runtime change for scoped review, not closing the accuracy half of #255. Independent saved-output audit verified120groups,240arm receipts,480paired mode comparisons, exact bootstrap recomputation, unchanged source and5contexts/17required resources with exact bytes/hash/revision (138807bytes total). See `independent-review.json`. + +## Efficiency versus accuracy tracker + +| Axis | Evidence | Status | +| --- | --- | --- | +| This bounded efficiency change | Primary paired reduction9.434%, CI4.603–13.337%; exact output/resource parity | PASS for frozen workload; review/publication separate | +| Retrieval accuracy improvement | No ranker/corpus/query changes; paired results unchanged in this study | Not established; remains open | +| Historical accuracyv2 / v3 | Hit4/6→5/6 but MRR0.5833→0.5417 /0.5333 on their older pinned corpus | Both FAIL; no heldout evaluation | +| Historical cue feasibility | Blind preparationINCONCLUSIVE; covered synthetic cue MRR29/36→29/36 | No demonstrated improvement | + +The [earlier consolidated table](../../indexer-255-covered-cue-20261030/results/consolidated-results.md) retains all historical baselines and uncertainty. Its numbers are not new measurements on this baseline. No knowledge-corpus quality or #255 closure is inferred from this performance PASS. diff --git a/evidence/indexer-255-limit-sizing-20261030/results/summary.json b/evidence/indexer-255-limit-sizing-20261030/results/summary.json new file mode 100644 index 00000000..e0aed82a --- /dev/null +++ b/evidence/indexer-255-limit-sizing-20261030/results/summary.json @@ -0,0 +1 @@ +{"note":"Timing only; independent correctness/resource gates also required.","paths":{"context_api":{"A_cpu_p50_ms":709.8120665,"A_p50_ms":709.9819155,"A_p95_ms":1334.153874,"B_cpu_p50_ms":669.0094645,"B_p50_ms":669.0612695,"B_p95_ms":894.668809,"n":120,"p50_change_95ci":[-8.949749849290267,-2.725503643668059],"p50_change_percent":-5.763618073452181,"p95_change_95ci":[-50.601304184113104,-12.990828764875516],"p95_change_percent":-32.9411077361231,"paired_gain_95ci":[4.048262810162958,10.614829211904599],"paired_median_gain_percent":7.098877743926381},"default_api":{"A_cpu_p50_ms":829.67028,"A_p50_ms":830.518625,"A_p95_ms":1495.022365,"B_cpu_p50_ms":778.8755135,"B_p50_ms":778.983203,"B_p95_ms":1138.814839,"n":120,"p50_change_95ci":[-9.786019053699235,-3.0363831683991815],"p50_change_percent":-6.205209666429812,"p95_change_95ci":[-43.36007076233995,1.860914709383743],"p95_change_percent":-23.826233930620834,"paired_gain_95ci":[4.603267611296492,13.337351437091183],"paired_median_gain_percent":9.43424477752091},"default_cli":{"A_cpu_p50_ms":1122.362,"A_p50_ms":1123.3137735,"A_p95_ms":1575.085593,"B_cpu_p50_ms":1081.723,"B_p50_ms":1083.289513,"B_p95_ms":1621.67231,"n":120,"p50_change_95ci":[-7.671345176007338,2.268486090834343],"p50_change_percent":-3.563052589953841,"p95_change_95ci":[-16.703171909592108,17.294299031876182],"p95_change_percent":2.957726056732457,"paired_gain_95ci":[1.4083114467975126,8.746270620946916],"paired_median_gain_percent":3.974159412973369},"search_cli":{"A_cpu_p50_ms":209.072,"A_p50_ms":209.6859935,"A_p95_ms":349.684354,"B_cpu_p50_ms":208.561,"B_p50_ms":210.7489395,"B_p95_ms":381.126338,"n":120,"p50_change_95ci":[-5.60419094777459,4.633352077175856],"p50_change_percent":0.5069227477990879,"p95_change_95ci":[-42.024943749883306,32.84556993923775],"p95_change_percent":8.991532975478789,"paired_gain_95ci":[-5.567556545513452,3.5983360196163208],"paired_median_gain_percent":-0.5137363838687043}},"primary_pass":true,"secondary_points_pass":true,"secondary_uncertainty_pass":true,"timing_verdict":"PASS"} \ No newline at end of file diff --git a/evidence/indexer-255-limit-sizing-20261030/validator/candidate-runner-freeze.json b/evidence/indexer-255-limit-sizing-20261030/validator/candidate-runner-freeze.json new file mode 100644 index 00000000..7767c80d --- /dev/null +++ b/evidence/indexer-255-limit-sizing-20261030/validator/candidate-runner-freeze.json @@ -0,0 +1,12 @@ +{ + "baseline": "f93df0548a26714f6514337a8525c7c14108acad", + "candidate": "9f7862a9f8619dd68ac59f12736f6b50da10d9e8", + "tree": "261645a7adc0ac097281096df6752ef7fec394f8", + "frozen_at_utc": "2026-10-30T08:05:56.584717+00:00", + "files": { + "proposed-protocol.md": "d577712b231be4bf33e66d401da22d50a38b01951707dae7a65b8d9c2dfc6a44", + "evaluate.py": "fe46d6fdfecccd5ce3fe8ac517aa8db39dc7c7dacf1aae775b62a7f3b5cc9760", + "knowledge_operations.py": "6332118c0c505144c36ac29c35b4e56b1797d290550cc5dadbb921336367f84a", + "test_collect_limit_serialization.py": "7a94b70ee1abe4acc2d1dc78ae9d69aa15777e6d521e7ce249d61bba01e18416" + } +} diff --git a/evidence/indexer-255-limit-sizing-20261030/validator/evaluate.py b/evidence/indexer-255-limit-sizing-20261030/validator/evaluate.py new file mode 100644 index 00000000..d1438d7e --- /dev/null +++ b/evidence/indexer-255-limit-sizing-20261030/validator/evaluate.py @@ -0,0 +1,220 @@ +"""One frozen paired study; this file does not modify either source tree.""" +import argparse +import gzip +import hashlib +import json +import math +import os +import platform +import random +import resource +import statistics +import subprocess +import sys +import time +from pathlib import Path + +MODES = ("default_api", "context_api", "default_cli", "search_cli") + + +def encode(value): + return json.dumps(value, sort_keys=True, ensure_ascii=False, separators=(",", ":")).encode() + + +def digest(value): + return hashlib.sha256(value).hexdigest() + + +def env(root): + return {"PATH": os.defpath, "PYTHONPATH": str(root / "src"), + "PYTHONDONTWRITEBYTECODE": "1"} + + +def identity(root): + source = {} + for path in sorted((root / "src").rglob("*")): + if path.is_file() and "__pycache__" not in path.parts: + source[path.relative_to(root).as_posix()] = digest(path.read_bytes()) + corpus = {key: val for key, val in source.items() if key.startswith("src/inferrsi/data/")} + revision = subprocess.check_output(["git", "-C", str(root), "rev-parse", "HEAD"], + text=True).strip() + return {"revision": revision, "source_sha256": digest(encode(source)), + "corpus_sha256": digest(encode(corpus)), "source_files": source} + + +def cli(root, mode): + args = [sys.executable, "-m", "inferrsi"] + if mode == "search_cli": + args += ["knowledge", "search", "cgroupv2", "--limit", "5", "--json"] + else: + args += ["collect", "", "--limit", "5", "--json"] + usage = resource.getrusage(resource.RUSAGE_CHILDREN) + cpu0 = usage.ru_utime + usage.ru_stime + start = time.perf_counter_ns() + completed = subprocess.run(args, cwd=root, env=env(root), capture_output=True, + check=True, timeout=180) + elapsed = time.perf_counter_ns() - start + usage = resource.getrusage(resource.RUSAGE_CHILDREN) + cpu = round((usage.ru_utime + usage.ru_stime - cpu0) * 1e9) + decode_start = time.perf_counter_ns() + value = json.loads(completed.stdout) + decode_ns = time.perf_counter_ns() - decode_start + return value, {"wall_ns": elapsed, "cpu_ns": cpu, "decode_ns": decode_ns, + "stdout_bytes": len(completed.stdout)} + + +def worker(root, capture): + sys.path.insert(0, str(root / "src")) + from inferrsi import knowledge_operations + from inferrsi.knowledge_operations import KnowledgeReader + assert Path(knowledge_operations.__file__).resolve().is_relative_to(root / "src") + rows, captures = {}, {} + for mode in MODES: + before = time.monotonic_ns() + load = os.getloadavg() + if mode.endswith("_api"): + reader = KnowledgeReader() + options = {"query": "", "limit": 5} + if mode == "context_api": + options.update(relevance="memory", context_bytes=262144) + reader.collect(**options) + start_cpu = time.process_time_ns() + start = time.perf_counter_ns() + value = reader.collect(**options) + stats = {"wall_ns": time.perf_counter_ns() - start, + "cpu_ns": time.process_time_ns() - start_cpu} + else: + value, stats = cli(root, mode) + payload = encode(value) + rows[mode] = {**stats, "monotonic_start_ns": before, "loadavg": load, + "output_sha256": digest(payload), "output_bytes": len(payload)} + if capture: + captures[mode] = value + assert rows["default_api"]["output_sha256"] == rows["default_cli"]["output_sha256"] + return {"rows": rows, "captures": captures, + "module_path_relative": str(Path(knowledge_operations.__file__).relative_to(root)), + "module_sha256": digest(Path(knowledge_operations.__file__).read_bytes())} + + +def percentile(values, q): + return sorted(values)[max(0, math.ceil(len(values) * q) - 1)] + + +def summary(groups): + rng = random.Random(25531) + indices = [[rng.randrange(len(groups)) for _ in groups] for _ in range(10000)] + result = {} + for mode in MODES: + a = [g["A"]["rows"][mode]["wall_ns"] for g in groups] + b = [g["B"]["rows"][mode]["wall_ns"] for g in groups] + paired_gain = [100 * (x - y) / x for x, y in zip(a, b)] + gains = [statistics.median([paired_gain[i] for i in ix]) for ix in indices] + medchanges, tailchanges = [], [] + for ix in indices: + aa, bb = [a[i] for i in ix], [b[i] for i in ix] + medchanges.append(100 * (statistics.median(bb) / statistics.median(aa) - 1)) + tailchanges.append(100 * (percentile(bb, .95) / percentile(aa, .95) - 1)) + row = { + "n": len(groups), "A_p50_ms": statistics.median(a) / 1e6, + "B_p50_ms": statistics.median(b) / 1e6, + "A_p95_ms": percentile(a, .95) / 1e6, "B_p95_ms": percentile(b, .95) / 1e6, + "paired_median_gain_percent": statistics.median(paired_gain), + "paired_gain_95ci": [percentile(gains, .025), percentile(gains, .975)], + "p50_change_percent": 100 * (statistics.median(b) / statistics.median(a) - 1), + "p95_change_percent": 100 * (percentile(b, .95) / percentile(a, .95) - 1), + "p50_change_95ci": [percentile(medchanges, .025), percentile(medchanges, .975)], + "p95_change_95ci": [percentile(tailchanges, .025), percentile(tailchanges, .975)], + } + for arm in ("A", "B"): + cpu = [g[arm]["rows"][mode]["cpu_ns"] for g in groups] + row[arm + "_cpu_p50_ms"] = statistics.median(cpu) / 1e6 + result[mode] = row + primary = result["default_api"] + primary_pass = (primary["paired_median_gain_percent"] >= 5 + and primary["paired_gain_95ci"][0] > 0) + point_pass = all(r["p50_change_percent"] <= 10 and r["p95_change_percent"] <= 20 + for key, r in result.items() if key != "default_api") + uncertainty_pass = all(r["p50_change_95ci"][1] <= 10 + for key, r in result.items() if key != "default_api") + verdict = "FAIL" if not primary_pass or not point_pass else ( + "PASS" if uncertainty_pass else "INCONCLUSIVE") + return {"paths": result, "primary_pass": primary_pass, + "secondary_points_pass": point_pass, "secondary_uncertainty_pass": uncertainty_pass, + "timing_verdict": verdict, + "note": "Timing only; independent correctness/resource gates also required."} + + +def run(args): + roots = {"A": Path(args.baseline).resolve(), "B": Path(args.candidate).resolve()} + output = Path(args.output).resolve() + output.mkdir(exist_ok=False) + freeze = json.loads(Path(__file__).with_name("candidate-runner-freeze.json").read_text()) + assert digest(Path(__file__).read_bytes()) == freeze["files"]["evaluate.py"] + identities = {arm: identity(root) for arm, root in roots.items()} + assert identities["A"]["revision"] == freeze["baseline"] + assert identities["B"]["revision"] == freeze["candidate"] + (output / "environment.json").write_bytes(encode({ + "python": sys.version, "platform": platform.system(), + "release": platform.release(), "machine": platform.machine(), + "cpu_count": os.cpu_count(), "freeze": freeze, + })) + assert identities["A"]["corpus_sha256"] == identities["B"]["corpus_sha256"] + (output / "identities-before.json").write_bytes(encode(identities)) + (output / "runner.sha256").write_text(digest(Path(__file__).read_bytes()) + "\n") + groups = [] + order = ["AB"] * 60 + ["BA"] * 60 + random.Random(25530).shuffle(order) + (output / "order.json").write_bytes(encode(order)) + for number, arms in enumerate(order): + group = {"group": number, "order": arms} + for arm in arms: + command = [sys.executable, str(Path(__file__).resolve()), "--worker", + str(roots[arm])] + if number == 0: + command.append("--capture") + proc = subprocess.run(command, cwd=roots[arm], env=env(roots[arm]), + capture_output=True, check=True, timeout=900) + result = json.loads(proc.stdout) + # Retain each completed arm before the other arm can fail. + (output / f"group-{number:03d}-{arm}.json").write_bytes(encode(result)) + captures = result.pop("captures") + if captures: + (output / (arm + "-capture.json.gz")).write_bytes( + gzip.compress(encode(captures), mtime=0)) + group[arm] = result + for mode in MODES: + assert group["A"]["rows"][mode]["output_sha256"] == ( + group["B"]["rows"][mode]["output_sha256"]), (number, mode) + groups.append(group) + with (output / "groups.jsonl").open("ab") as stream: + stream.write(encode(group) + b"\n") + print(f"{number + 1}/120 paired groups retained", flush=True) + after = {arm: identity(root) for arm, root in roots.items()} + (output / "identities-after.json").write_bytes(encode(after)) + assert identities == after + (output / "summary.json").write_bytes(encode(summary(groups))) + + +if __name__ == "__main__": + parser = argparse.ArgumentParser() + parser.add_argument("--worker") + parser.add_argument("--capture", action="store_true") + parser.add_argument("--baseline") + parser.add_argument("--candidate") + parser.add_argument("--output") + args = parser.parse_args() + if args.worker: + print(encode(worker(Path(args.worker).resolve(), args.capture)).decode()) + else: + try: + run(args) + except Exception as exc: + output = Path(args.output).resolve() + if output.is_dir(): + failure = {"verdict": "INCONCLUSIVE", "error_type": type(exc).__name__, + "detail": str(exc), "no_resume": True} + if isinstance(exc, (subprocess.CalledProcessError, subprocess.TimeoutExpired)): + failure["stdout"] = (exc.stdout or b"").decode("utf-8", "replace") + failure["stderr"] = (exc.stderr or b"").decode("utf-8", "replace") + (output / "failure.json").write_bytes(encode(failure)) + raise diff --git a/evidence/indexer-255-limit-sizing-20261030/validator/verify_raw.py b/evidence/indexer-255-limit-sizing-20261030/validator/verify_raw.py new file mode 100644 index 00000000..0e6d2b4b --- /dev/null +++ b/evidence/indexer-255-limit-sizing-20261030/validator/verify_raw.py @@ -0,0 +1,28 @@ +"""Verify saved archive members without extracting or executing them.""" +import hashlib +import json +import tarfile +from pathlib import Path + + +def main(): + root = Path(__file__).resolve().parents[1] + manifest = json.loads((root / "results/raw-files.json").read_text()) + path = root / "results/raw-study.tar.gz" + assert hashlib.sha256(path.read_bytes()).hexdigest() == manifest["archive_sha256"] + seen = set() + with tarfile.open(path, "r:gz") as archive: + for member in archive.getmembers(): + assert member.isfile() and member.name in manifest["files"] + assert member.name not in seen + seen.add(member.name) + data = archive.extractfile(member).read() + expected = manifest["files"][member.name] + assert len(data) == expected["bytes"] + assert hashlib.sha256(data).hexdigest() == expected["sha256"] + assert seen == set(manifest["files"]) + print(f"Verified {len(seen)} original raw files") + + +if __name__ == "__main__": + main() diff --git a/src/inferrsi/knowledge_operations.py b/src/inferrsi/knowledge_operations.py index d776964d..8a9d8d05 100644 --- a/src/inferrsi/knowledge_operations.py +++ b/src/inferrsi/knowledge_operations.py @@ -571,6 +571,11 @@ def matches(metadata: dict, authority: str) -> bool: def select(reference: str, bundle: Bundle, view: dict) -> None: nonlocal used, context_used + # Normal Bundle views were serialized while computing their revision. + # Preserve custom subclasses' serialization/error behavior below. + if type(bundle) is Bundle and len(selected) >= limit: + omitted.append({"id": reference, "reason": "output_limit"}) + return size = len(_json(view)) if len(selected) >= limit or (max_bytes is not None and used + size > max_bytes): omitted.append({"id": reference, "reason": "output_limit"}) diff --git a/tests/test_collect_limit_serialization.py b/tests/test_collect_limit_serialization.py new file mode 100644 index 00000000..00153e5f --- /dev/null +++ b/tests/test_collect_limit_serialization.py @@ -0,0 +1,99 @@ +"""Count saturation skips only redundant normal-view payload sizing.""" +import pytest + +from inferrsi import knowledge_operations as operations +from inferrsi.knowledge_operations import Bundle, KnowledgeReader + + +class CustomBundle(Bundle): + pass + + +class InvalidViewBundle(Bundle): + def view(self, *, material=False): + return {**super().view(material=material), "custom": object()} + + +def bundle(identity, cls=Bundle): + return cls({ + "id": identity, "kind": "knowledge", "entrypoint": "entry.md", + "sources": [{"type": "unknown"}], "applicability": {}, "state": "test", + "limitations": [], "attribution": "test", "required_resources": ["entry.md"], + }, {"entry.md": identity.encode()}, {}) + + +class FixtureReader(KnowledgeReader): + def __init__(self, bundles): + super().__init__() + self.bundles = {item.metadata["id"]: item for item in bundles} + self.reads = [] + + def records(self): + return {identity: {} for identity in self.bundles} + + def _read(self, qualified, revision): + self.reads.append(qualified) + return self.bundles[qualified.partition(":")[2]] + + +def size_calls(monkeypatch): + original, seen = operations._json, [] + + def observe(value): + if isinstance(value, dict) and "authority" in value and "ref" in value: + seen.append(value["id"]) + return original(value) + + monkeypatch.setattr(operations, "_json", observe) + return seen + + +@pytest.mark.parametrize("material", [False, True]) +def test_saturated_count_omits_without_sizing_but_reads_every_bundle(monkeypatch, material): + reader = FixtureReader([bundle(name) for name in ("a", "b", "c")]) + seen = size_calls(monkeypatch) + result = reader.collect(limit=1, material=material) + assert seen == ["a"] + assert reader.reads == ["package:a", "package:b", "package:c"] + assert result["omissions"] == [ + {"id": "package:b", "reason": "output_limit"}, + {"id": "package:c", "reason": "output_limit"}, + ] + assert result["material_bytes"] == len(operations._json(result["items"][0])) + + +@pytest.mark.parametrize("max_bytes", [None, 1, 100000]) +@pytest.mark.parametrize("material", [False, True]) +def test_custom_subclass_fallback_is_identical_to_normal_views(max_bytes, material): + normal = FixtureReader([bundle(n) for n in ("a", "b", "c")]) + legacy = FixtureReader([bundle(n, CustomBundle) for n in ("a", "b", "c")]) + options = dict(limit=1, max_bytes=max_bytes, material=material, context_bytes=100) + assert normal.collect(**options) == legacy.collect(**options) + + +def test_byte_budget_rejections_still_size_every_unsaturated_item(monkeypatch): + reader = FixtureReader([bundle(n) for n in ("a", "b", "c")]) + seen = size_calls(monkeypatch) + result = reader.collect(limit=1, max_bytes=1) + assert seen == ["a", "b", "c"] + assert result["no_match"] and len(result["omissions"]) == 3 + + +def test_invalid_custom_view_still_raises_after_count_limit(): + reader = FixtureReader([bundle("a"), bundle("b", InvalidViewBundle)]) + with pytest.raises(TypeError, match="not JSON serializable"): + reader.collect(limit=1) + + +def test_invalid_normal_resource_is_reported_even_after_count_limit(): + invalid = bundle("b") + invalid.content["../escape"] = b"unsafe" + result = FixtureReader([bundle("a"), invalid]).collect(limit=1) + assert result["omissions"][0]["reason"] == "invalid" + assert "Unsafe bundle path" in result["omissions"][0]["detail"] + + +@pytest.mark.parametrize("limit", [0, None, -1, True]) +def test_invalid_limits_still_rejected(limit): + with pytest.raises(ValueError, match="positive integer"): + FixtureReader([bundle("a")]).collect(limit=limit) diff --git a/tests/test_evidence_inventory.py b/tests/test_evidence_inventory.py index 22764106..560f4bdf 100644 --- a/tests/test_evidence_inventory.py +++ b/tests/test_evidence_inventory.py @@ -145,6 +145,6 @@ def test_checked_in_inventory(): repo = Path(__file__).resolve().parents[1] result = validate_inventory(repo) assert result["errors"] == [] - assert len(result["bundles"]) == 15 - assert result["checked_hashes"] == 321 + assert len(result["bundles"]) == 16 + assert result["checked_hashes"] == 336 assert result["unavailable"] # Historical raw artifacts are not in this checkout. diff --git a/tools/evidence_inventory.json b/tools/evidence_inventory.json index e3dcd9ef..27e75253 100644 --- a/tools/evidence_inventory.json +++ b/tools/evidence_inventory.json @@ -1,6 +1,10 @@ { "version": 1, "bundles": { + "indexer-255-limit-sizing-20261030": { + "kind": "campaign", + "manifests": [{"path": "plan/publication-integrity.json", "schema": "bundle-sha256"}] + }, "indexer-255-raw-string-20261030": { "kind": "campaign", "manifests": [{"path": "plan/integrity.json", "schema": "bundle-sha256"}]