foveance 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (111) hide show
  1. foveance-0.1.0/.dockerignore +18 -0
  2. foveance-0.1.0/.gitattributes +13 -0
  3. foveance-0.1.0/.github/ISSUE_TEMPLATE/bug_report.md +27 -0
  4. foveance-0.1.0/.github/ISSUE_TEMPLATE/feature_request.md +21 -0
  5. foveance-0.1.0/.github/PULL_REQUEST_TEMPLATE.md +17 -0
  6. foveance-0.1.0/.github/workflows/ci.yml +31 -0
  7. foveance-0.1.0/.github/workflows/release.yml +30 -0
  8. foveance-0.1.0/.gitignore +28 -0
  9. foveance-0.1.0/.pre-commit-config.yaml +19 -0
  10. foveance-0.1.0/CHANGELOG.md +57 -0
  11. foveance-0.1.0/CITATION.cff +30 -0
  12. foveance-0.1.0/CODE_OF_CONDUCT.md +24 -0
  13. foveance-0.1.0/CONTRIBUTING.md +34 -0
  14. foveance-0.1.0/Dockerfile +16 -0
  15. foveance-0.1.0/LICENSE +15 -0
  16. foveance-0.1.0/Makefile +40 -0
  17. foveance-0.1.0/PKG-INFO +352 -0
  18. foveance-0.1.0/README.md +297 -0
  19. foveance-0.1.0/SECURITY.md +23 -0
  20. foveance-0.1.0/assets/baseline_comparison.png +0 -0
  21. foveance-0.1.0/assets/baseline_trajectory.png +0 -0
  22. foveance-0.1.0/assets/demo.gif +0 -0
  23. foveance-0.1.0/assets/demo_anytool.gif +0 -0
  24. foveance-0.1.0/assets/demo_comparison.gif +0 -0
  25. foveance-0.1.0/assets/logo-dark.png +0 -0
  26. foveance-0.1.0/assets/logo-dark.svg +971 -0
  27. foveance-0.1.0/assets/logo-mark.png +0 -0
  28. foveance-0.1.0/assets/logo-mark.svg +581 -0
  29. foveance-0.1.0/assets/logo.png +0 -0
  30. foveance-0.1.0/assets/logo.svg +971 -0
  31. foveance-0.1.0/bench/analyze.py +240 -0
  32. foveance-0.1.0/bench/analyze_A.py +88 -0
  33. foveance-0.1.0/bench/compare_baselines.py +131 -0
  34. foveance-0.1.0/bench/fetch_longbench.py +82 -0
  35. foveance-0.1.0/bench/make_pareto.py +100 -0
  36. foveance-0.1.0/bench/merge_results.py +41 -0
  37. foveance-0.1.0/bench/overhead.py +52 -0
  38. foveance-0.1.0/bench/plot_baselines.py +69 -0
  39. foveance-0.1.0/bench/plots/baseline_comparison.png +0 -0
  40. foveance-0.1.0/bench/plots/baseline_trajectory.png +0 -0
  41. foveance-0.1.0/bench/plots/drift_sweep_ntFalse.png +0 -0
  42. foveance-0.1.0/bench/plots/drift_sweep_ntTrue.png +0 -0
  43. foveance-0.1.0/bench/plots/efficiency.png +0 -0
  44. foveance-0.1.0/bench/plots/greedy_gap.png +0 -0
  45. foveance-0.1.0/bench/plots/pareto_frontier.png +0 -0
  46. foveance-0.1.0/bench/plots/pareto_gemma2_2b.png +0 -0
  47. foveance-0.1.0/bench/plots/pareto_llama3.2_1b.png +0 -0
  48. foveance-0.1.0/bench/plots/pareto_qwen2.5_1.5b.png +0 -0
  49. foveance-0.1.0/bench/plots/savings_vs_full.png +0 -0
  50. foveance-0.1.0/bench/plots/tok_per_correct.png +0 -0
  51. foveance-0.1.0/bench/plots.py +186 -0
  52. foveance-0.1.0/bench/report.md +72 -0
  53. foveance-0.1.0/bench/results/ablations.csv +23 -0
  54. foveance-0.1.0/bench/results/by_seed.csv +271 -0
  55. foveance-0.1.0/bench/results/drift_twin_audit.json +11 -0
  56. foveance-0.1.0/bench/results/greedy_gap.csv +801 -0
  57. foveance-0.1.0/bench/results/headline.json +122 -0
  58. foveance-0.1.0/bench/results/pareto.csv +55 -0
  59. foveance-0.1.0/bench/results/per_turn.csv +1801 -0
  60. foveance-0.1.0/bench/results/summary.csv +55 -0
  61. foveance-0.1.0/bench/results_baselines/drift_twin_audit.json +11 -0
  62. foveance-0.1.0/bench/results_baselines/llama_trajectory.csv +19 -0
  63. foveance-0.1.0/bench/results_baselines/single_shot.csv +22 -0
  64. foveance-0.1.0/bench/results_pareto_run.err +0 -0
  65. foveance-0.1.0/bench/run_bench.py +327 -0
  66. foveance-0.1.0/bench/tasks.py +216 -0
  67. foveance-0.1.0/data/longbench/sample.jsonl +2 -0
  68. foveance-0.1.0/docs/NOVELTY.md +65 -0
  69. foveance-0.1.0/docs/architecture.md +41 -0
  70. foveance-0.1.0/docs/baselines.md +33 -0
  71. foveance-0.1.0/docs/limitations.md +63 -0
  72. foveance-0.1.0/docs/theory.md +45 -0
  73. foveance-0.1.0/docs/usage.md +159 -0
  74. foveance-0.1.0/examples/langchain_demo.py +42 -0
  75. foveance-0.1.0/examples/wrap_ollama.py +42 -0
  76. foveance-0.1.0/examples/wrap_openai.py +45 -0
  77. foveance-0.1.0/mkdocs.yml +18 -0
  78. foveance-0.1.0/npm/README.md +54 -0
  79. foveance-0.1.0/npm/bin/foveance-proxy.js +50 -0
  80. foveance-0.1.0/npm/package.json +38 -0
  81. foveance-0.1.0/pyproject.toml +73 -0
  82. foveance-0.1.0/scripts/make_comparison_gifs.py +163 -0
  83. foveance-0.1.0/scripts/make_demo_gif.py +95 -0
  84. foveance-0.1.0/scripts/make_logo.py +96 -0
  85. foveance-0.1.0/scripts/run_everything.sh +54 -0
  86. foveance-0.1.0/scripts/run_full6_monitor.ps1 +53 -0
  87. foveance-0.1.0/scripts/run_offline_demo.sh +16 -0
  88. foveance-0.1.0/src/foveance/__init__.py +38 -0
  89. foveance-0.1.0/src/foveance/allocator.py +159 -0
  90. foveance-0.1.0/src/foveance/baselines.py +156 -0
  91. foveance-0.1.0/src/foveance/cli.py +297 -0
  92. foveance-0.1.0/src/foveance/compressors.py +95 -0
  93. foveance-0.1.0/src/foveance/controller.py +182 -0
  94. foveance-0.1.0/src/foveance/embedders.py +104 -0
  95. foveance-0.1.0/src/foveance/learned.py +126 -0
  96. foveance-0.1.0/src/foveance/llm.py +132 -0
  97. foveance-0.1.0/src/foveance/metrics.py +112 -0
  98. foveance-0.1.0/src/foveance/predictor.py +147 -0
  99. foveance-0.1.0/src/foveance/proxy.py +605 -0
  100. foveance-0.1.0/src/foveance/py.typed +0 -0
  101. foveance-0.1.0/src/foveance/store.py +118 -0
  102. foveance-0.1.0/tests/test_allocator.py +91 -0
  103. foveance-0.1.0/tests/test_baselines_extra.py +42 -0
  104. foveance-0.1.0/tests/test_controller.py +136 -0
  105. foveance-0.1.0/tests/test_integration.py +51 -0
  106. foveance-0.1.0/tests/test_modules.py +253 -0
  107. foveance-0.1.0/tests/test_predictor.py +112 -0
  108. foveance-0.1.0/tests/test_property.py +70 -0
  109. foveance-0.1.0/tests/test_proxy_integration.py +244 -0
  110. foveance-0.1.0/tests/test_store.py +96 -0
  111. foveance-0.1.0/tests/test_wrap_and_dashboard.py +136 -0
@@ -0,0 +1,18 @@
1
+ .git
2
+ __pycache__/
3
+ *.py[cod]
4
+ .pytest_cache/
5
+ .mypy_cache/
6
+ .ruff_cache/
7
+ *.egg-info/
8
+ .coverage
9
+ htmlcov/
10
+ bench/results/
11
+ bench/results_real/
12
+ bench/results_mock/
13
+ bench/plots/
14
+ paper/
15
+ prompts/
16
+ CLAUDE.md
17
+ dist/
18
+ data/
@@ -0,0 +1,13 @@
1
+ # Normalize line endings: LF in the repo, native on checkout.
2
+ * text=auto eol=lf
3
+ *.png binary
4
+ *.pdf binary
5
+ *.docx binary
6
+ *.whl binary
7
+ *.gz binary
8
+
9
+ # Keep generated/vendored files out of language stats and diffs where noisy.
10
+ assets/* linguist-documentation
11
+ bench/report.md linguist-documentation
12
+ docs/* linguist-documentation
13
+ *.svg -diff
@@ -0,0 +1,27 @@
1
+ ---
2
+ name: Bug report
3
+ about: Something doesn't work as documented
4
+ title: "[bug] "
5
+ labels: bug
6
+ ---
7
+
8
+ **What happened**
9
+ A clear description of the bug.
10
+
11
+ **Reproduce**
12
+ Exact command(s) and the smallest input that triggers it:
13
+ ```bash
14
+ python bench/run_bench.py --backend mock ...
15
+ ```
16
+
17
+ **Expected**
18
+ What you expected instead.
19
+
20
+ **Environment**
21
+ - OS / Python version:
22
+ - Foveance version (`foveance version`):
23
+ - Extras installed (`[dev]`/`[bench]`/`[proxy]`/`[ml]`):
24
+ - If a benchmark issue: attach `bench/results/headline.json` and model/hardware details.
25
+
26
+ **Logs**
27
+ Paste relevant output (and `bench/results/drift_twin_audit.json` if arms behave unexpectedly).
@@ -0,0 +1,21 @@
1
+ ---
2
+ name: Feature request
3
+ about: Propose an addition (new policy, suite adapter, embedder, ...)
4
+ title: "[feat] "
5
+ labels: enhancement
6
+ ---
7
+
8
+ **Motivation**
9
+ What problem does this solve? Who benefits?
10
+
11
+ **Proposal**
12
+ What you'd add and where (e.g. a new arm in `foveance.baselines`, a `Suite` adapter in
13
+ `bench/tasks.py`, an `Embedder`).
14
+
15
+ **Novelty / positioning check**
16
+ Does this stay within the claim boundaries in `docs/NOVELTY.md`? If it adds a comparison
17
+ method, note the citation.
18
+
19
+ **Alternatives considered**
20
+
21
+ **Willing to submit a PR?** yes / no
@@ -0,0 +1,17 @@
1
+ # Pull request
2
+
3
+ ## What and why
4
+ <!-- One or two sentences on the change and the motivation. -->
5
+
6
+ ## Checklist
7
+ - [ ] `make lint` is clean (ruff + mypy)
8
+ - [ ] `make cov` keeps core coverage at or above 90%
9
+ - [ ] New behavior has tests; new policies are registered in `foveance.baselines.POLICIES`
10
+ - [ ] If the `reactive_afm` / `foveance` arms were touched, the drift-twin audit
11
+ (`bench/results/drift_twin_audit.json`) still reports `only_difference_is_drift: true`
12
+ - [ ] No fabricated benchmark numbers; any results come from a real run
13
+ - [ ] Docstrings on public API; type hints throughout
14
+ - [ ] Claims stay within the boundaries in `docs/NOVELTY.md`
15
+
16
+ ## Results / evidence
17
+ <!-- For perf or benchmark changes, paste the relevant CSV rows or the headline.json diff. -->
@@ -0,0 +1,31 @@
1
+ name: ci
2
+ on: [push, pull_request]
3
+ jobs:
4
+ test:
5
+ runs-on: ubuntu-latest
6
+ strategy:
7
+ matrix:
8
+ python-version: ["3.10", "3.11", "3.12", "3.13"]
9
+ steps:
10
+ - uses: actions/checkout@v4
11
+ - uses: actions/setup-python@v5
12
+ with: { python-version: "${{ matrix.python-version }}" }
13
+ - run: pip install -e ".[dev,bench,proxy]"
14
+ - name: lint
15
+ run: ruff check src tests bench
16
+ - name: type-check
17
+ run: mypy src
18
+ - name: tests + core coverage gate
19
+ run: |
20
+ pytest -q --cov=foveance.store --cov=foveance.predictor \
21
+ --cov=foveance.allocator --cov=foveance.controller \
22
+ --cov-report=term-missing --cov-fail-under=90
23
+ - name: offline benchmark smoke + analysis
24
+ run: |
25
+ python bench/run_bench.py --backend mock --models mock --suite synthetic \
26
+ --budgets 1000,2500 --tasks 4 --turns 30 --name-target false \
27
+ --fidelity-cost true --greedy-gap --ablations
28
+ python bench/analyze.py
29
+ python bench/plots.py
30
+ - name: cli smoke
31
+ run: foveance demo --budgets 1000,2500 --turns 18
@@ -0,0 +1,30 @@
1
+ name: release
2
+ on:
3
+ push:
4
+ tags: ["v*"]
5
+
6
+ jobs:
7
+ build:
8
+ runs-on: ubuntu-latest
9
+ steps:
10
+ - uses: actions/checkout@v4
11
+ - uses: actions/setup-python@v5
12
+ with: { python-version: "3.12" }
13
+ - run: pip install build twine
14
+ - run: python -m build
15
+ - run: twine check dist/*
16
+ - uses: actions/upload-artifact@v4
17
+ with: { name: dist, path: dist/* }
18
+
19
+ publish:
20
+ # Publishes to PyPI via Trusted Publishing (OIDC, no stored secrets).
21
+ # Configure the project on PyPI first, then this runs on every v* tag.
22
+ needs: build
23
+ runs-on: ubuntu-latest
24
+ environment: pypi
25
+ permissions:
26
+ id-token: write
27
+ steps:
28
+ - uses: actions/download-artifact@v4
29
+ with: { name: dist, path: dist }
30
+ - uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,28 @@
1
+ __pycache__/
2
+ *.py[cod]
3
+ .pytest_cache/
4
+ .mypy_cache/
5
+ .ruff_cache/
6
+ .hypothesis/
7
+ .coverage
8
+ htmlcov/
9
+ *.egg-info/
10
+ build/
11
+ dist/
12
+ .venv/
13
+ venv/
14
+ # generated artifacts (reproducible); the REAL benchmark evidence in bench/results/,
15
+ # bench/plots/, and bench/results_baselines/ is committed on purpose -- the docs and README
16
+ # promise every number traces to these files.
17
+ # The research manuscript and internal build specs are kept local, out of the public package.
18
+ paper/
19
+ prompts/
20
+ CLAUDE.md
21
+ bench/results_real/
22
+ bench/results_mock/
23
+ bench/results_*/
24
+ !bench/results_baselines/
25
+ bench/report_mock.md
26
+ data/
27
+ !data/longbench/sample.jsonl
28
+ .cache/
@@ -0,0 +1,19 @@
1
+ repos:
2
+ - repo: https://github.com/astral-sh/ruff-pre-commit
3
+ rev: v0.6.9
4
+ hooks:
5
+ - id: ruff
6
+ args: [--fix]
7
+ - repo: https://github.com/pre-commit/mirrors-mypy
8
+ rev: v1.11.2
9
+ hooks:
10
+ - id: mypy
11
+ files: ^src/
12
+ additional_dependencies: []
13
+ - repo: https://github.com/pre-commit/pre-commit-hooks
14
+ rev: v5.0.0
15
+ hooks:
16
+ - id: end-of-file-fixer
17
+ - id: trailing-whitespace
18
+ - id: check-yaml
19
+ - id: check-added-large-files
@@ -0,0 +1,57 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project are documented here. The format is based on
4
+ [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to
5
+ [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
+
7
+ ## [0.1.0] - 2026-06-22
8
+ ### Added
9
+ - `foveance wrap` — run any CLI/agent through the proxy with one command: starts the proxy,
10
+ sets `ANTHROPIC_BASE_URL`/`OPENAI_BASE_URL` for the child process only, launches the tool,
11
+ and prints a tokens-saved summary (with a ≈$ estimate at `--price-per-mtok`) on exit.
12
+ - Live dashboard at `GET /` and `/admin`: running tokens-saved counter, %, and $-equivalent,
13
+ polling `/admin/stats` (which now reports `est_tokens_before/after/saved`, `est_saved_pct`,
14
+ `est_usd_saved`, and `compressed_requests`).
15
+ - Prompt-cache-aware compression: blocks carrying Anthropic `cache_control` are never modified,
16
+ and `--cache-aware` additionally freezes everything at or before the last breakpoint so the
17
+ provider's prompt cache is never invalidated (cost arithmetic in `docs/limitations.md`).
18
+ - Structure-preserving in-place compression for agentic requests (Anthropic tool_use/tool_result,
19
+ OpenAI tool_calls, and the OpenAI Responses API used by Codex), protecting the most recent
20
+ `--agentic-protect-last` turns; verified live with Claude Code.
21
+ - Additional baseline arms `truncate` and `uniform` in the package and benchmark; single-shot
22
+ head-to-head probe (`bench/compare_baselines.py`) including real LLMLingua-2.
23
+ - Anticipatory predictor with a forward-drifting future-query posterior; `drift=0` recovers the
24
+ reactive (AFM) criterion.
25
+ - Multi-fidelity reversible store (POINTER/GIST/DIGEST/FULL) with content-hash-cached renders.
26
+ - Index allocator (Lagrangian/Whittle greedy on concave envelopes), exact DP oracle, and LP
27
+ bound, giving the `index <= OPT <= LP` sandwich.
28
+ - Compressors (heuristic + LLM), embedders (hashing/sentence-transformers/API), metrics, a
29
+ learned logistic future-relevance predictor, and an OpenAI-compatible reverse proxy.
30
+ - Baselines as first-class policy arms: `full`, `recency`, `reactive_afm`, `oracle`, optional
31
+ `llmlingua2`; a drift-twin audit proves `reactive_afm` and `foveance` differ only in drift.
32
+ - Benchmark harness (suites, budget sweep, bootstrap CIs, paired Wilcoxon, greedy-gap, drift /
33
+ predictor / retrieve / fidelity-cost ablations) with synthetic and LongBench/RULER/AppWorld/
34
+ OfficeBench adapters that skip gracefully when data is absent.
35
+ - Theory summary (`docs/theory.md`) backed by five theorems with full proofs in the accompanying manuscript.
36
+ - CLI (`foveance demo|proxy|bench|version`), examples, docs, and CI across Python 3.10-3.13.
37
+
38
+ ### Performance
39
+ - `index_allocate` reimplemented with a binary heap, attaining the documented
40
+ `O(sum_i L_i log sum_i L_i)` time (previously re-sorted the queue each iteration); allocates
41
+ 4000 items in tens of milliseconds. A reproducible overhead benchmark is in `bench/overhead.py`.
42
+
43
+ ### Fixed
44
+ - Proxy `/v1/chat/completions` route returned HTTP 422 because a stringized `Request`
45
+ annotation (from `from __future__ import annotations`) was not recognized by FastAPI; the
46
+ route now takes the JSON body as a dict and is covered by a real end-to-end HTTP test.
47
+
48
+ ### Testing & tooling
49
+ - Property-based tests (Hypothesis) for the allocator invariants: budget feasibility,
50
+ monotonicity, the one-item greedy bound, and the `IDX <= OPT <= LP` sandwich.
51
+ - End-to-end proxy integration test over real HTTP (threaded upstream + FastAPI TestClient).
52
+ - `py.typed` marker (PEP 561), `mkdocs.yml`, `Dockerfile`/`.dockerignore`, `.pre-commit-config.yaml`,
53
+ `CITATION.cff`, `CODE_OF_CONDUCT.md`, `SECURITY.md`, PR template, and a PyPI release workflow.
54
+
55
+ ### Notes
56
+ - Real-model results (Gemma/Qwen/Llama via Ollama) show budgeted policies reaching full-replay
57
+ accuracy at roughly 61-62% fewer tokens; see `bench/report.md`. No numbers are hand-entered.
@@ -0,0 +1,30 @@
1
+ cff-version: 1.2.0
2
+ message: "If you use Foveance, please cite the software and the accompanying paper."
3
+ title: "Foveance: Anticipatory Context Allocation for Long-Horizon LLM Agents"
4
+ abstract: >-
5
+ Foveance is a black-box, reversible, anticipatory context-allocation layer for long-horizon
6
+ LLM agents. It spends a fixed token budget across accumulated context held at multiple
7
+ fidelities, choosing each item's fidelity by its expected future relevance, backed by a
8
+ predictive trajectory rate-distortion theory.
9
+ type: software
10
+ authors:
11
+ - family-names: Maghsoodi
12
+ given-names: Abtin
13
+ version: 0.1.0
14
+ license: Apache-2.0
15
+ repository-code: "https://github.com/aimaghsoodi/foveance"
16
+ keywords:
17
+ - large-language-models
18
+ - agents
19
+ - context-compression
20
+ - rate-distortion
21
+ - kv-cache
22
+ preferred-citation:
23
+ type: article
24
+ title: >-
25
+ Foveance: A Predictive Rate-Distortion Theory of Anticipatory, Reversible Context
26
+ Compression for Black-Box LLM Agents
27
+ authors:
28
+ - family-names: Maghsoodi
29
+ given-names: Abtin
30
+ year: 2026
@@ -0,0 +1,24 @@
1
+ # Contributor Covenant Code of Conduct
2
+
3
+ ## Our pledge
4
+ We as members, contributors, and leaders pledge to make participation in our community a
5
+ harassment-free experience for everyone, regardless of age, body size, visible or invisible
6
+ disability, ethnicity, sex characteristics, gender identity and expression, level of
7
+ experience, education, socio-economic status, nationality, personal appearance, race, religion,
8
+ or sexual identity and orientation.
9
+
10
+ ## Our standards
11
+ Examples of behavior that contributes to a positive environment include using welcoming and
12
+ inclusive language, being respectful of differing viewpoints, gracefully accepting constructive
13
+ criticism, and focusing on what is best for the community. Unacceptable behavior includes
14
+ harassment, trolling, insulting or derogatory comments, and publishing others' private
15
+ information without permission.
16
+
17
+ ## Enforcement
18
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be reported to the
19
+ project maintainers. All complaints will be reviewed and investigated promptly and fairly.
20
+ Maintainers are obligated to respect the privacy and security of the reporter.
21
+
22
+ ## Attribution
23
+ This Code of Conduct is adapted from the [Contributor Covenant](https://www.contributor-covenant.org),
24
+ version 2.1.
@@ -0,0 +1,34 @@
1
+ # Contributing to Foveance
2
+
3
+ Thanks for your interest! Foveance aims to be a small, rigorous, reviewer-proof codebase.
4
+
5
+ ## Ground rules
6
+ - **Never fabricate benchmark numbers.** Every figure in the report traces to a CSV in
7
+ `bench/results/`. Unmeasured = `TODO`, not invented.
8
+ - **Keep the novelty boundary honest.** The multi-fidelity store under a budget is prior art
9
+ (AFM, ContextBudget, ACON, MemAct). Don't claim it. See [`docs/NOVELTY.md`](docs/NOVELTY.md).
10
+ - **Core stays dependency-free.** `store/predictor/allocator/controller` must run offline with no
11
+ third-party imports. ML/proxy/bench deps live behind extras.
12
+
13
+ ## Dev setup
14
+ ```bash
15
+ pip install -e ".[dev,bench]"
16
+ make test # pytest
17
+ make cov # coverage gate on core modules (target ≥90%)
18
+ make lint # ruff + mypy
19
+ ```
20
+
21
+ ## Before opening a PR
22
+ 1. `make lint` is clean (ruff + mypy).
23
+ 2. `make cov` keeps core coverage ≥90%.
24
+ 3. New behavior has tests; new policies are added to `foveance.baselines.POLICIES`.
25
+ 4. If you touch the `reactive_afm`/`foveance` arms, the drift-twin audit
26
+ (`bench/results/drift_twin_audit.json`) must still report `only_difference_is_drift: true`.
27
+ 5. Docstrings on public API; type hints throughout.
28
+
29
+ ## Commit style
30
+ Small, reviewable commits. If you work within the phased build, tag commits `[phase N]`.
31
+
32
+ ## Reporting issues
33
+ Use the templates in `.github/ISSUE_TEMPLATE/`. For benchmark discrepancies, include the exact
34
+ command, the `headline.json`, and your hardware/model versions.
@@ -0,0 +1,16 @@
1
+ # Reproducible Foveance environment (offline core + benchmark).
2
+ FROM python:3.12-slim
3
+
4
+ WORKDIR /app
5
+ COPY . /app
6
+
7
+ # Install the package with dev + bench extras; core itself is dependency-free.
8
+ RUN pip install --no-cache-dir -e ".[dev,bench]"
9
+
10
+ # Smoke test at build time so a broken image fails fast.
11
+ RUN pytest -q && foveance demo --budgets 1000,2500 --turns 18
12
+
13
+ # Default: run the offline benchmark + analysis + plots.
14
+ CMD ["bash", "-lc", "python bench/run_bench.py --backend mock --models mock --suite synthetic \
15
+ --budgets 600,1200,2500 --tasks 4 --turns 30 --greedy-gap --ablations && \
16
+ python bench/analyze.py && python bench/plots.py && cat bench/report.md"]
foveance-0.1.0/LICENSE ADDED
@@ -0,0 +1,15 @@
1
+ SPDX-License-Identifier: Apache-2.0
2
+
3
+ Copyright 2026 Abtin Maghsoodi
4
+
5
+ Licensed under the Apache License, Version 2.0 (the "License"); you may not use
6
+ this file except in compliance with the License. You may obtain a copy of the
7
+ License at: http://www.apache.org/licenses/LICENSE-2.0
8
+
9
+ Unless required by applicable law or agreed to in writing, software distributed
10
+ under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
11
+ CONDITIONS OF ANY KIND, either express or implied. See the License for the
12
+ specific language governing permissions and limitations under the License.
13
+
14
+ NOTE (Phase 5 / release): replace this stub with the full verbatim text of the
15
+ Apache License 2.0 from the URL above before publishing the repository.
@@ -0,0 +1,40 @@
1
+ .PHONY: install test cov lint bench demo repro clean
2
+
3
+ install:
4
+ pip install -e ".[dev,bench]"
5
+
6
+ # Full pytest suite (falls back to the seed script runner if pytest is absent).
7
+ test:
8
+ @python -m pytest -q 2>/dev/null || python tests/test_allocator.py
9
+
10
+ # Coverage gate on the core modules.
11
+ cov:
12
+ python -m pytest -q --cov=foveance.store --cov=foveance.predictor \
13
+ --cov=foveance.allocator --cov=foveance.controller --cov-report=term-missing
14
+
15
+ lint:
16
+ @ruff check src tests bench 2>/dev/null || echo "ruff not installed (pip install -e .[dev])"
17
+ @mypy src 2>/dev/null || echo "mypy not installed (pip install -e .[dev])"
18
+
19
+ # Offline benchmark (mock model) — CI-safe, no GPU/network.
20
+ demo:
21
+ foveance demo
22
+
23
+ bench:
24
+ python bench/run_bench.py --backend mock --models mock --suite synthetic \
25
+ --budgets 600,1200,1600,2500,4000 --tasks 6 --turns 40 --drift 0.7 \
26
+ --name-target false --fidelity-cost true --greedy-gap --ablations
27
+ python bench/analyze.py
28
+ python bench/plots.py
29
+
30
+ # Real benchmark example (needs Ollama running locally).
31
+ bench-real:
32
+ python bench/run_bench.py --backend ollama \
33
+ --models gemma2:9b,gemma2:2b,qwen2.5:7b,llama3.1:8b \
34
+ --budget 2400 --tasks 8 --turns 60 --drift 0.7
35
+
36
+ repro: test bench
37
+ @echo "Offline repro complete: CSVs in bench/results/, plots in bench/plots/, report in bench/report.md."
38
+
39
+ clean:
40
+ rm -rf **/__pycache__ .pytest_cache .mypy_cache .ruff_cache