Master Plan: Get Clustrix Production-Ready
Status: Planning · Opened: 2026-08-17 · Target: v0.2.0 (honest beta) → v1.0.0 (production)
This is the umbrella issue for taking Clustrix from its current state to a package that does what it advertises, is tested against real infrastructure, and has been adversarially reviewed. It is grounded in a five-track audit performed 2026-08-17 covering the full source tree, the entire test suite (actually executed), all 29 open issues, all documentation, and a security review of the working tree and git history.
Every claim below is cited to file:line or to verbatim command output. Where something could not be verified it is marked UNVERIFIED rather than assumed.
1. Executive summary: what is actually true today
| Question |
Audited answer |
| Does the advertised feature set work? |
Partially. SSH is solid. SLURM/SGE/Kubernetes are partial. PBS is broken. The entire cloud path has never executed successfully. |
| Is it tested? |
No, in the way that matters. CI runs 15 of 2,280 tests (~0.7%). When the full suite is actually run: 127 failed, 1738 passed, 26 skipped, 8 errors. |
| Is the coverage number real? |
No. Issues #61/#86/#98–#106 all reason from "74%". Measured full-suite coverage is ~56.14%; CI reports 8.21%; the committed artifact says 5.69%. Four different numbers, none of which was the planning input. |
| Can a new contributor run the tests? |
No. The documented pip install -e ".[dev]" produces an environment where pytest cannot start. |
| Is it safe to run the tests? |
No. The documented unit-test command provisions real, billable AWS EKS clusters. |
| Any leaked secrets? |
Not on GitHub. Issue #107 was a false positive. Two real HF tokens exist in local-only git objects and should be rotated. |
| Biggest security defect? |
Unauthenticated pickle deserialization of remote data — remote-to-local RCE. No issue existed for it. |
The single most important structural finding
Roughly every "completed" item in this project is half done in the same specific way: the scaffolding landed, the seam did not.
- Closure variables are detected and injected as parameters (
function_flattening.py:623,654-695) — but never passed at the call site (:749-751).
- The REPL limitation is documented (
README.md:554) — but the code still fails opaquely (utils.py:118-119).
- Kubernetes provisioners exist for all six targets — but GCP's
_assign_iam_role() assigns nothing (kubernetes/gcp_provisioner.py:356) and Azure's _create_service_principal() creates nothing (kubernetes/azure_provisioner.py:331).
- AWS cleanup scripts exist — but have no dry-run, confirmation, or scoping (
grep -rn "dry_run\|confirm\|input(" scripts/aws/*.py → 0 hits).
- The cloud executor serializes
{"function": ...} (utils.py:151) and deserializes func_data['func'] (executor_cloud.py:390) — a guaranteed KeyError on the first real invocation.
That last one is diagnostic. It is not a regression; it is unconditional. Its survival proves the path was never executed. This is what heavy mocking produces: coverage rises while every integration seam stays untested. The fix is not "more tests" — it is tests that actually execute.
2. Root causes (fix these, not the symptoms)
RC1 — Tests mock the thing under test. 60 of 240 test files, 2,513 occurrences of unittest.mock|MagicMock|@patch|monkeypatch. Representative: tests/test_executor_schedulers.py:73-131 stubs execute_remote_command to return "Submitted batch job 12345", then asserts job_id == "12345" — it tests a regex against a string the test itself supplied. No SLURM is involved. This directly violates the project's own rule: "Do not use mock services for anything ever."
RC2 — Production code is mock-aware. clustrix/executor_scheduler_status.py:89 imports unittest.mock and branches on isinstance(self.connection_manager.ssh_client, Mock), with the comment "Use robust checking only if we have a real SSH connection (not unit tests)". The shipped code path _check_slurm_job_status_robust is structurally unreachable from any unit test. Separately, clustrix/notebook_magic_mocks.py ships fake widgets (_MockDropdown, observe(): pass) imported by six production modules.
RC3 — CI does not run the tests. tests.yml and fast_ci.yml both run only tests/unit/ = 5 files, 391 LOC, 15 tests. real-world-tests.yml has all three jobs gated if: false. real_world_tests.yml sets continue-on-error: true, as does the mypy step in tests.yml. ~99.3% of the suite never executes in CI, which is why all 127 failures are invisible.
RC4 — Planning ran against stale snapshots. #102 targets "notebook_magic.py, 1,236 statements"; that file is now 90 lines split across nine modules. #104 targets "executor.py, 511 lines"; that is now a 39-line re-export shim (executor.py:19-26). The work items were decomposed from one snapshot and the code was refactored underneath them.
RC5 — Failure is silent by default. 40+ except Exception: → pass/return None sites. executor_kubernetes.py:304-308 returns "completed" on any API exception. config.py:206 swallows all cloud-dependency install errors during __init__. Errors surface as wrong results rather than as errors.
RC6 — Local work never reached the remote. master is 30 commits ahead of origin/master (git rev-list --left-right --count origin/master...master → 0 30). All 30 implement issues #99–#106. quality_gates.yml is committed locally but returns HTTP 404 on GitHub — it has never run.
3. Backend reality check
| Backend |
Status |
Evidence |
| ssh |
COMPLETE |
Most mature path; real runner writes result.pkl (utils.py:1330-1452) |
| slurm |
PARTIAL |
Env-setup failures downgraded to logger.warning (executor_schedulers.py:105-116); status checker branches on Mock (executor_scheduler_status.py:89-105) |
| sge |
PARTIAL |
Implemented (executor_schedulers.py:200-240); fragile positional job-ID parse (:243) |
| kubernetes |
PARTIAL |
Results via stdout + ast.literal_eval (executor_kubernetes.py:339) — non-literal returns silently degrade to str; any API error returns "completed" (:304-308) |
| local |
PARTIAL |
Auto-parallel injects _parallel_{var} into kwargs (decorator.py:778) that user functions cannot accept; the resulting TypeError is swallowed (:708-716) |
| pbs |
BROKEN |
Script runs python execute_function.py (utils.py:1226) — that file is never created anywhere in the package. Also never calls setup_remote_environment (executor_schedulers.py:157-198) yet sources a venv. |
| cloud: lambda |
BROKEN |
Producer/consumer key mismatch → guaranteed KeyError (utils.py:151 vs executor_cloud.py:390) |
| cloud: aws/azure/gcp/hf |
STUB |
Dispatch requires create_instance (executor_cloud.py:222); classes define create_ec2_instance/create_vm/create_compute_instance/create_space → NotImplementedError (:234) |
Additionally, three providers return fabricated hostnames from get_cluster_config() error branches — placeholder.gcp.com (cloud_providers/gcp.py:544), placeholder.azure.com (azure.py:669), placeholder.lambdalabs.com (lambda_cloud.py:327,338) — which executor_cloud.py:260 then attempts to SSH into.
4. New capability: HuggingFace Jobs as the integration-test substrate
Verified working today against the contextlab org (academia plan). A real container ran and returned:
CLUSTRIX_HF_OK 3.12.14 x86_64
Available flavors: cpu-basic, cpu-upgrade, cpu-xl, t4-small, t4-medium, l4x1, l4x4, l40sx1, l40sx4, l40sx8, a10g-small, a10g-large, a10g-largex2, a10g-largex4, a100-large, h100, h100x8.
Why this matters. The reason the cloud path stayed broken for months is that verifying it meant provisioning, IAM, billing, and teardown — so nobody did, and a first-line KeyError went unnoticed. HF Jobs collapses that loop to one CLI call and a few cents, with no cluster reservation, no VPN, no institutional SSH credentials. That makes it a far more reliable CI substrate than the Dartmouth hosts the current real-world tests depend on (ndoli.dartmouth.edu, tensor01.dartmouth.edu), whose scheduled workflow has failed on all of its last 60 runs.
Note also that clustrix currently targets the wrong HF primitive. cloud_providers/huggingface_spaces.py targets Spaces — long-lived web apps. Jobs is exactly clustrix's model: hand over a container, run a function, collect a result, exit. An HF Jobs backend is both easier to implement correctly and immediately useful as test infrastructure.
Cost guardrail: anything CI-facing must pin --flavor cpu-basic with an explicit --timeout. GPU flavors stay manual and opt-in. h100x8 on the academia plan is real money.
5. Plan of record
Phases are ordered by dependency. Phase 0 must complete first — until then, running the test suite is unsafe and measuring anything is meaningless.
Phase 0 — Stop the bleeding (safety + ability to measure)
Nothing else can be trusted until these land.
- Contain the billable-test landmine
- Make the dev environment installable and the suite runnable
- Security hardening + token rotation + secret scanning
- Reconcile the 30 unpushed commits
Phase 1 — Establish ground truth
- Make CI actually run the suite
- Fix the 127 failures and 8 collection errors
- Set an honest, measured coverage baseline and a gate that means something
Phase 2 — De-mock
- Remove mock-awareness from shipped code
- Replace assertion-free mock tests with tests that execute
- Land the HF Jobs backend and adopt it as the default integration substrate
Phase 3 — Fix the core
- Cloud execution path and the provider interface
- PBS backend
- Local auto-parallelization
- The pickle trust model and SSH host-key verification
Phase 4 — Pay down architecture debt
- Delete ~5,100 lines of orphaned modules
- Replace silent-failure handling; fix resource leaks
Phase 5 — Make the docs true
- Fix every broken README example; unify versions
- Rewrite
CLAUDE.md and MIGRATION.md against the real module layout
Phase 6 — Red team
- Adversarial review of serialization, credentials, injection, and the remote trust boundary
Phase 7 — Release
- Cut an honest
v0.2.0; define v1.0 exit criteria
6. Exit criteria for v1.0
A release is production-ready when all of the following hold:
pip install -e ".[dev]" on a clean machine, followed by the documented test command, runs the suite to completion — with zero network calls to billable services.
- CI executes >95% of the test suite on every PR, with
continue-on-error removed everywhere.
- Zero failing tests. Zero collection errors.
unittest.mock appears zero times in clustrix/ (shipped code).
- Every backend claimed in
README.md has a test that actually executed it end to end, with a dated CI run link as evidence.
- Coverage is measured, published, and gated at a threshold the project actually meets.
- Every code example in
README.md is executed by a doc test in CI.
- A single source of truth for the version; all four current locations agree.
- Secret scanning + push protection enabled; no plaintext credential ever written world-readable.
- The remote→local trust boundary is documented and either authenticated or explicitly opt-in.
7. Audit provenance
Five parallel audits, 2026-08-17, all read-only:
| Track |
Method |
Headline |
| Source tree |
Full AST import graph over clustrix/ |
4 of 8 backends broken/stub; ~5,100 orphaned lines |
| Test suite |
Suite actually executed in a purpose-built venv |
127 failed, 1738 passed, 26 skipped, 8 errors in 134.78s |
| Issues |
All 29 open issues + comments, cross-checked against code |
9 closable, 12 with stale bodies |
| Docs |
Every README claim verified against source |
All 4 cloud config examples raise on line 1 |
| Security |
Working tree + 555-commit history + gh api |
#107 false positive; pickle RCE is the real issue |
Known limits of this audit. The full-suite coverage figure (56.14%) is from combined worker data at 98% completion — the run reproducibly hangs in a real AWS retry loop (kubernetes/aws_provisioner.py:763,771), so it is a slight underestimate. PyPI publication status was not checked. Issue #87 (AWS EKS Service Control Policy) could not be verified from code as it is an AWS Organizations-level condition.
Sub-issues are linked below. Each carries its own evidence, acceptance criteria, and verification command.
8. Sub-issue roadmap
Phase 0 — Stop the bleeding (do these first; nothing else is trustworthy until they land)
Phase 1 — Establish ground truth
Phase 2 — De-mock
Phase 3 — Fix the core
Phase 4 — Architecture debt
Phase 5 — Make the docs true
Phase 6 — Red team
Phase 7 — Release
9. Suggested order of attack
#109 first, alone. It is the only issue where not acting has an ongoing cost — anyone running the documented test command with AWS credentials is billing EKS right now.
Then #110 → #114 → #113: make the suite runnable, make it green, then turn CI on. Turning CI on before #114 makes master permanently red, and the temptation will be to re-add continue-on-error, which is how this situation arose.
#116 before #117. While production code still branches on isinstance(..., Mock), you can delete a thousand mock assertions and still be exercising the wrong code path.
#122 before #115. Deleting dead code moves the coverage number without writing a test; re-baselining first means measuring a denominator you are about to change.
#118 early — it unblocks honest testing for #119, #120, and #126.
10. Issue triage performed alongside this plan
Of the 29 previously-open issues: 9 closed, 8 updated with corrected bodies.
| Action |
Issues |
| Closed — false positive |
#107 (scanner matched AWS's own doc placeholder) |
| Closed — completed |
#85 (SGE is fully implemented), #82, #72 |
| Closed — superseded / duplicate |
#61 (dup of #98), #86 (dup of #99+#102) |
| Closed — archival, no deliverable |
#92, #93, #94 |
| Updated — stale body corrected |
#66, #68, #88, #89, #90, #91, #95 |
Master Plan: Get Clustrix Production-Ready
Status: Planning · Opened: 2026-08-17 · Target: v0.2.0 (honest beta) → v1.0.0 (production)
This is the umbrella issue for taking Clustrix from its current state to a package that does what it advertises, is tested against real infrastructure, and has been adversarially reviewed. It is grounded in a five-track audit performed 2026-08-17 covering the full source tree, the entire test suite (actually executed), all 29 open issues, all documentation, and a security review of the working tree and git history.
Every claim below is cited to
file:lineor to verbatim command output. Where something could not be verified it is marked UNVERIFIED rather than assumed.1. Executive summary: what is actually true today
pip install -e ".[dev]"produces an environment where pytest cannot start.The single most important structural finding
Roughly every "completed" item in this project is half done in the same specific way: the scaffolding landed, the seam did not.
function_flattening.py:623,654-695) — but never passed at the call site (:749-751).README.md:554) — but the code still fails opaquely (utils.py:118-119)._assign_iam_role()assigns nothing (kubernetes/gcp_provisioner.py:356) and Azure's_create_service_principal()creates nothing (kubernetes/azure_provisioner.py:331).grep -rn "dry_run\|confirm\|input(" scripts/aws/*.py→ 0 hits).{"function": ...}(utils.py:151) and deserializesfunc_data['func'](executor_cloud.py:390) — a guaranteedKeyErroron the first real invocation.That last one is diagnostic. It is not a regression; it is unconditional. Its survival proves the path was never executed. This is what heavy mocking produces: coverage rises while every integration seam stays untested. The fix is not "more tests" — it is tests that actually execute.
2. Root causes (fix these, not the symptoms)
RC1 — Tests mock the thing under test. 60 of 240 test files, 2,513 occurrences of
unittest.mock|MagicMock|@patch|monkeypatch. Representative:tests/test_executor_schedulers.py:73-131stubsexecute_remote_commandto return"Submitted batch job 12345", then assertsjob_id == "12345"— it tests a regex against a string the test itself supplied. No SLURM is involved. This directly violates the project's own rule: "Do not use mock services for anything ever."RC2 — Production code is mock-aware.
clustrix/executor_scheduler_status.py:89importsunittest.mockand branches onisinstance(self.connection_manager.ssh_client, Mock), with the comment "Use robust checking only if we have a real SSH connection (not unit tests)". The shipped code path_check_slurm_job_status_robustis structurally unreachable from any unit test. Separately,clustrix/notebook_magic_mocks.pyships fake widgets (_MockDropdown,observe(): pass) imported by six production modules.RC3 — CI does not run the tests.
tests.ymlandfast_ci.ymlboth run onlytests/unit/= 5 files, 391 LOC, 15 tests.real-world-tests.ymlhas all three jobs gatedif: false.real_world_tests.ymlsetscontinue-on-error: true, as does the mypy step intests.yml. ~99.3% of the suite never executes in CI, which is why all 127 failures are invisible.RC4 — Planning ran against stale snapshots. #102 targets "
notebook_magic.py, 1,236 statements"; that file is now 90 lines split across nine modules. #104 targets "executor.py, 511 lines"; that is now a 39-line re-export shim (executor.py:19-26). The work items were decomposed from one snapshot and the code was refactored underneath them.RC5 — Failure is silent by default. 40+
except Exception:→pass/return Nonesites.executor_kubernetes.py:304-308returns"completed"on any API exception.config.py:206swallows all cloud-dependency install errors during__init__. Errors surface as wrong results rather than as errors.RC6 — Local work never reached the remote.
masteris 30 commits ahead oforigin/master(git rev-list --left-right --count origin/master...master→0 30). All 30 implement issues #99–#106.quality_gates.ymlis committed locally but returns HTTP 404 on GitHub — it has never run.3. Backend reality check
result.pkl(utils.py:1330-1452)logger.warning(executor_schedulers.py:105-116); status checker branches onMock(executor_scheduler_status.py:89-105)executor_schedulers.py:200-240); fragile positional job-ID parse (:243)ast.literal_eval(executor_kubernetes.py:339) — non-literal returns silently degrade tostr; any API error returns"completed"(:304-308)_parallel_{var}into kwargs (decorator.py:778) that user functions cannot accept; the resultingTypeErroris swallowed (:708-716)python execute_function.py(utils.py:1226) — that file is never created anywhere in the package. Also never callssetup_remote_environment(executor_schedulers.py:157-198) yet sources a venv.KeyError(utils.py:151vsexecutor_cloud.py:390)create_instance(executor_cloud.py:222); classes definecreate_ec2_instance/create_vm/create_compute_instance/create_space→NotImplementedError(:234)Additionally, three providers return fabricated hostnames from
get_cluster_config()error branches —placeholder.gcp.com(cloud_providers/gcp.py:544),placeholder.azure.com(azure.py:669),placeholder.lambdalabs.com(lambda_cloud.py:327,338) — whichexecutor_cloud.py:260then attempts to SSH into.4. New capability: HuggingFace Jobs as the integration-test substrate
Verified working today against the
contextlaborg (academia plan). A real container ran and returned:Available flavors:
cpu-basic, cpu-upgrade, cpu-xl, t4-small, t4-medium, l4x1, l4x4, l40sx1, l40sx4, l40sx8, a10g-small, a10g-large, a10g-largex2, a10g-largex4, a100-large, h100, h100x8.Why this matters. The reason the cloud path stayed broken for months is that verifying it meant provisioning, IAM, billing, and teardown — so nobody did, and a first-line
KeyErrorwent unnoticed. HF Jobs collapses that loop to one CLI call and a few cents, with no cluster reservation, no VPN, no institutional SSH credentials. That makes it a far more reliable CI substrate than the Dartmouth hosts the current real-world tests depend on (ndoli.dartmouth.edu,tensor01.dartmouth.edu), whose scheduled workflow has failed on all of its last 60 runs.Note also that clustrix currently targets the wrong HF primitive.
cloud_providers/huggingface_spaces.pytargets Spaces — long-lived web apps. Jobs is exactly clustrix's model: hand over a container, run a function, collect a result, exit. An HF Jobs backend is both easier to implement correctly and immediately useful as test infrastructure.Cost guardrail: anything CI-facing must pin
--flavor cpu-basicwith an explicit--timeout. GPU flavors stay manual and opt-in.h100x8on the academia plan is real money.5. Plan of record
Phases are ordered by dependency. Phase 0 must complete first — until then, running the test suite is unsafe and measuring anything is meaningless.
Phase 0 — Stop the bleeding (safety + ability to measure)
Nothing else can be trusted until these land.
Phase 1 — Establish ground truth
Phase 2 — De-mock
Phase 3 — Fix the core
Phase 4 — Pay down architecture debt
Phase 5 — Make the docs true
CLAUDE.mdandMIGRATION.mdagainst the real module layoutPhase 6 — Red team
Phase 7 — Release
v0.2.0; define v1.0 exit criteria6. Exit criteria for v1.0
A release is production-ready when all of the following hold:
pip install -e ".[dev]"on a clean machine, followed by the documented test command, runs the suite to completion — with zero network calls to billable services.continue-on-errorremoved everywhere.unittest.mockappears zero times inclustrix/(shipped code).README.mdhas a test that actually executed it end to end, with a dated CI run link as evidence.README.mdis executed by a doc test in CI.7. Audit provenance
Five parallel audits, 2026-08-17, all read-only:
clustrix/127 failed, 1738 passed, 26 skipped, 8 errors in 134.78sgh apiKnown limits of this audit. The full-suite coverage figure (56.14%) is from combined worker data at 98% completion — the run reproducibly hangs in a real AWS retry loop (
kubernetes/aws_provisioner.py:763,771), so it is a slight underestimate. PyPI publication status was not checked. Issue #87 (AWS EKS Service Control Policy) could not be verified from code as it is an AWS Organizations-level condition.Sub-issues are linked below. Each carries its own evidence, acceptance criteria, and verification command.
8. Sub-issue roadmap
Phase 0 — Stop the bleeding (do these first; nothing else is trustworthy until they land)
tests/integration/is unmarked, so the documented unit-test command provisions billable AWS EKS clusterspip install -e ".[dev]"produces an environment where pytest cannot startquality_gates.ymlhas never runPhase 1 — Establish ground truth
Phase 2 — De-mock
isinstance(..., Mock))Phase 3 — Fix the core
KeyError, provider interface mismatch, placeholder hostnamesPhase 4 — Architecture debt
Phase 5 — Make the docs true
CLAUDE.mdagainst the real architecture; resolve the 3-way mocking-policy contradictionPhase 6 — Red team
Phase 7 — Release
9. Suggested order of attack
#109 first, alone. It is the only issue where not acting has an ongoing cost — anyone running the documented test command with AWS credentials is billing EKS right now.
Then #110 → #114 → #113: make the suite runnable, make it green, then turn CI on. Turning CI on before #114 makes
masterpermanently red, and the temptation will be to re-addcontinue-on-error, which is how this situation arose.#116 before #117. While production code still branches on
isinstance(..., Mock), you can delete a thousand mock assertions and still be exercising the wrong code path.#122 before #115. Deleting dead code moves the coverage number without writing a test; re-baselining first means measuring a denominator you are about to change.
#118 early — it unblocks honest testing for #119, #120, and #126.
10. Issue triage performed alongside this plan
Of the 29 previously-open issues: 9 closed, 8 updated with corrected bodies.