Spectio — development environment, automation and testing¶
Status: draft v0.1 · 2026-10-25 · author: Thomas Weber (with Claude) Companion docs:
schedulers-and-monitoring.md: what is tested against SLURM and Kubernetes.architecture-plugins-and-packaging.md: packages, plugin conformance suites, deployments.admin-and-operations.md: backup compatibility tests.docs/playbooks/next-phase.md: the order in which this is built.
0. Decisions in brief¶
-
Agents check their own work against real tools.
- Every behaviour Spectio relies on is tested against the real tool at a pinned version: Nextflow, Snakemake and its executor plugins, Slurm, Kubernetes and Kueue.
- Mocks are for unit tests only.
- Real outputs are recorded as golden fixtures, with the tool version in the file name.
-
Local clusters, no real HPC needed for development.
- SLURM runs in Docker with sind (Slurm 25.11 and 26.05 images; slurmdbd; slurmrestd with JWT; node power-cycle simulation; GitHub Action; MCP server; no privileged containers needed; LGPL-3.0, used as a tool, not linked).
- Kubernetes runs in kind with Kueue installed.
-
Scenarios are isolated and run in parallel. Each has its own Compose project, port range, Docker network, sind realm or kind cluster, and data directory. Agents in parallel worktrees never collide.
-
One bootstrap script everywhere.
dev/bootstrap.shinstalls the pinned toolchain fromdev/versions.envin:- the Claude Code cloud environment setup script, cached when it finishes in about 5 minutes;
- CI;
- a developer laptop.
dev/doctor.shproves each tool works. -
Dev previews without a server; a public instance only later, on EMBL Kubernetes (revised 2026-10-26, §7). There is no staging VM, and the institute network is behind a VPN that GitHub cannot reach.
- Every PR, validated wave and release is published as its own static preview on Cloudflare Pages. Nothing is overwritten, and a
/versionspage lists them all. - The full stack runs on demand in GitHub Codespaces, from a link on each PR.
- The cost is 0 € within the free quotas.
- The public instance for users comes at the beta, on EMBL's Kubernetes, deployed like depictio's.
- Every PR, validated wave and release is published as its own static preview on Cloudflare Pages. Nothing is overwritten, and a
-
Claude is part of the development loop, inside guard rails:
- project agents and skills in
.claude/; - PR review by those agents in GitHub Actions;
- auto-fix of CI failures on PRs;
- scheduled routines for drift checks.
Humans merge.
- project agents and skills in
1. Toolchain (pinned in dev/versions.env)¶
| Tool | Pin (initial) | How it is installed | Used for |
|---|---|---|---|
| Python | 3.13 (uv-managed; embeds SQLite ≥ 3.51.3) | uv python install |
server, CLI, runner, tests |
| uv | latest at bootstrap time, then pinned | official installer | everything Python |
| Node.js | 22 LTS | distro or nvm |
UI build, Playwright, mermaid-cli |
| Java | 21 (Temurin) | distro package or SDKMAN | Nextflow |
| Nextflow | 26.10.x and 25.10.x (two versions, both tested) | release launcher from GitHub releases, NXF_VER pinned [to be validated: asset names and whether the cloud allowlist reaches get.nextflow.io / www.nextflow.io] |
fixture and nf-core runs |
| Snakemake | 9.x + snakemake-executor-plugin-slurm, -kubernetes, -kueue, plus snakemake-logger-plugin-spectio (ours) |
uv tool install with --with plugins, or a pixi environment |
fixture runs |
| sind | latest release, pinned | release binary [to be validated: install method, see gsi-hpc.github.io/sind] | SLURM clusters |
| kind, kubectl, helm | pinned releases | release binaries | Kubernetes clusters, chart tests |
| Kueue | pinned manifest version | kubectl apply --server-side -f |
queueing scenarios |
| Playwright | pinned, Chromium | npm i -D playwright; Chromium is pre-installed in some environments |
e2e tests, board rendering |
| mermaid-cli, mkdocs-material | pinned | npx, uvx |
docs CI |
| Apptainer | optional, later | distro package | Apptainer-only HPC scenarios |
Checks.
-
dev/doctor.shprints each tool and version, then runs one smoke test per layer:docker run --rm hello-world;sindcreate, thensbatch --wrap hostnamewith--wait;kind create cluster, then a Job, then delete;nextflow run tests/fixtures/workflows/nf-toy -profile local;snakemake -n -s tests/fixtures/workflows/smk-toy/Snakefile;- Playwright opening
about:blank.
-
It exits non-zero on the first failure, naming the tool.
2. Where agents work¶
| Place | What it is good for | Limits to design around |
|---|---|---|
| Claude Code on the user's machine (terminal, desktop) | interactive work, plugins (superpowers, Karpathy guidelines, frontend-design) installed normally | the user's machine resources |
Cloud sessions (claude.ai/code, claude --cloud) |
parallel autonomous tasks, one per branch; Docker is available | setup script cached only if it finishes in about 5 min; commands time out at 2 min by default (10 max, then moved to the background, up to 30 more min; BASH_DEFAULT_TIMEOUT_MS raises it); outbound network through an allowlist proxy (Trusted, Custom or Full); plugins are not loaded, so the skills are vendored in .claude/skills/; VM memory limits; idle VMs are reclaimed (cloud environments, cloud sessions) |
| GitHub Actions | PR gates, nightly matrix, preview deploys, Claude PR review | runner time and memory |
| Cloudflare Pages | one static preview per PR, wave and release (docs, boards, later the UI with a mocked API) | static only; public unless Cloudflare Access is on |
| GitHub Codespaces | the full stack on demand for Thomas, one per branch | about 60 h a month of a 2-core machine in the free quota; stops when idle |
Cloud environment settings (claude.ai/code → environment):
- Network: Custom, with the default list plus the hosts Nextflow, nf-core and the container registries need. The list is to be confirmed by spike D2:
www.nextflow.io,get.nextflow.io,registry.nextflow.io,quay.io,ghcr.io,community.wave.seqera.io,conda.anaconda.org,prefix.dev. - Environment variables:
BASH_DEFAULT_TIMEOUT_MS=600000,BASH_MAX_TIMEOUT_MS=1800000,CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1(optional). - Setup script:
bash dev/bootstrap.sh --ci(toolchain and pre-pulled images only). - SessionStart hook: in
.claude/settings.json, starts nothing heavy by default. Scenarios start their own clusters.
3. Fixture workflows (tests/fixtures/workflows/)¶
Tiny, deterministic, shell-only tasks (seconds each), with explicit stages so gates can be exercised:
| Fixture | Engine | What it exercises |
|---|---|---|
nf-toy |
Nextflow DSL2 | 3 stages (A → gate → B → C), ext.when stage stop and -resume; params fail=oom\|timeout\|exit\|flaky, fanout=N, array=true; publishDir outputs, a MultiQC-like JSON and a per-sample TSV for checks |
smk-toy |
Snakemake | the same stages with --until and --forcerun; a checkpoint that changes the DAG; rule resources for SLURM; the same failure parameters |
nf-core/demo (real) |
Nextflow | -profile test,docker on the local executor and on kind; a real MultiQC report for review views |
nf-core/rnaseq test profile (real, nightly) |
Nextflow | full gate scenario "Mapping QC" from checking-scenarios.md, on kind |
Failure injection.
- OOM: a task allocates more memory than requested. SLURM then reports
OUT_OF_MEMORY, Kubernetes reportsOOMKilled. - Timeout:
sleepbeyond the time limit. - Flaky: fails when
task.attempt == 1. - Node failure: sind power-cycles a worker during a running job.
- Preemption: a higher-priority partition and QoS in the sind cluster.
4. Local clusters¶
4.1 SLURM with sind¶
| Profile | Topology | Used for |
|---|---|---|
slurm-mini |
controller + 1 worker, no accounting | head job, squeue --json, cancel, reconcile |
slurm-site |
controller, db (slurmdbd), 3 workers in partitions htc, bigmem, gpu (fake GRES), users with association limits, a maintenance reservation |
pending reasons, sacct outcomes, fairshare, limits, pre-flight, failure classes |
slurm-rest |
slurm-site + api node (slurmrestd, JWT, 26.05) |
slurmrestd transport and data_parser negotiation |
slurm-versions |
slurm-site on 25.11 and 26.05 |
version matrix |
The runner runs on the sind submitter node as an unprivileged user, exactly as on a login node. Fixture workflows are mounted into it. Nextflow and Snakemake run inside the submitter node, using the cluster's sbatch.
4.2 Kubernetes with kind¶
| Profile | Setup | Used for |
|---|---|---|
k8s-mini |
kind, 1 node, a namespace with a ResourceQuota, a namespaced runner Role (see schedulers-and-monitoring.md §4) |
watch API, pod reasons, OOMKilled, logs |
k8s-kueue |
kind with 2 workers, Kueue with a ClusterQueue and a LocalQueue, the visibility API |
queue positions, admission, preemption |
k8s-rwx |
k8s-mini + an RWX storage class (NFS provisioner) |
Nextflow k8s executor with a shared work directory |
Whether kind runs inside a Claude Code cloud session (kind needs privileged node containers) is the first thing spike D2 answers. If it does not, Kubernetes scenarios run in CI and on the user's machine only.
5. Isolated, parallel scenarios¶
-
One command per scenario.
dev/scenario.py up <scenario> [--id <n>]creates:- Docker network
spx-<id>; - Compose project
spx-<id>with ports20000 + 100·id + k; - data directory
.scenarios/<id>/; - sind realm
spx-<id>or kind clusterspx-<id>.
It prints a JSON with every URL and credential.
downremoves all of it. - Docker network
-
Scenarios are YAML (
tests/scenarios/*.yaml): deployment (bundle / compose), scheduler profile, engine and version, fixture and parameters, gate script (who decides what, when), and expected events and states. - The matrix is engine {nextflow 25.10, 26.10; snakemake 9} × scheduler {local, slurm-mini, slurm-site, k8s-mini, k8s-kueue} × deployment {bundle, compose} × scenario {happy, gate-approve, gate-exclude-and-resume, oom-retry-suggestion, runner-offline-mid-run, restore-during-idle, multi-user-permissions}. A PR runs a smoke subset, the full matrix runs nightly.
- Parallelism is capped by memory, checked against free RAM before
up. One Claude agent per worktree and scenario ID, so agents working in parallel never share state.
6. Test tiers¶
| Tier | What | Runs on | Gates |
|---|---|---|---|
| 0 · static | ruff, ty or mypy, import-linter (dependency rules), eslint, OpenAPI diff, docs build, Mermaid | every push | PR |
| 1 · unit and contract | pure logic; plugin conformance suites (spectio_sdk.testing); golden fixtures for the Tower protocol, Snakemake logger events, squeue / sacct JSON and Kubernetes objects |
every push, seconds | PR |
| 2 · component | server with SQLite, fake runner, recorded engine event streams replayed; API tests with RFC 9457 errors, If-Match, idempotency |
every push, < 2 min | PR |
| 3 · integration | real engines on slurm-mini and k8s-mini; backup → restore → migrate; bundle → Compose hand-over |
PR (smoke subset), < 15 min | PR |
| 4 · end-to-end | Playwright against the bundle and Compose: launch, watch, review a gate, relaunch, admin pages, phone viewport | PR (smoke), nightly (full) | PR (smoke) |
| 5 · matrix and compatibility | the full scenario matrix; cross-version backup restore (previous release → current); depictio hand-off with a depictio container | nightly / weekly | release |
| 6 · preview and instance | static preview: links and media checked on the deployed URL. Public instance, from the beta: deploy + Playwright smoke over its URL; inbound webhook round trip | after merge | release |
Visual review. Playwright saves screenshots of the real pages named after the canvas boards (RunDetail, ReviewQueue…). A report puts them side by side with the renders of design/ui-canvas. This is a review aid for the ux-reviewer agent and for humans, not a pixel-diff gate.
7. Dev previews and the public instance¶
Context.
- No staging VM: Thomas has no VM of his own.
- No institute host: the institute's machines are behind a VPN that GitHub cannot reach.
- Cost: it must stay as close to zero as possible.
The earlier design (a tailnet VM behind Tailscale Funnel) is replaced; see the decision log of 2026-10-26.
7.1 Static previews on Cloudflare Pages (now)¶
- What is published. The built docs site, which already contains the progress pages, figures, casts and board screenshots. Once the UI exists, its build in mock mode is published too (§7.3).
-
How.
previews.ymlbuilds the site in GitHub Actions, then uploads it withwrangler pages deploy(direct upload).- Cloudflare never reads the repository, so a private repository is not an issue.
- The secrets
CLOUDFLARE_API_TOKENandCLOUDFLARE_ACCOUNT_IDlive in the GitHub environmentpreviews, which onlypreviews.ymluses.
-
Versions side by side, nothing overwritten (Cloudflare docs):
- each deployment gets its own hash URL (
<hash>.spectio.pages.dev), which stays reachable; - each branch gets an alias that follows its latest deployment (
<branch>.spectio.pages.dev).
- each deployment gets its own hash URL (
-
Which branch each kind of preview is deployed under:
Event Branch a PR pr-<n>a validated wave wave-<id>, for examplewave-w2a release v<X-Y-Z>mainthe production URL -
The
/versionspage. It is generated at every deploy from the Cloudflare deployments API (tools/previews/versions_page.py) and lists every preview with its date, branch, commit, PR and link. It is the "versions step by step" view. -
Privacy.
- Previews are public by default. Cloudflare Access can restrict them to Thomas.
- Media are rendered with fixture names (
documentation-system.md§5.5).
-
Limits (free plan): 500 builds a month, 20 000 files and 25 MiB per file (limits). Whether direct uploads count as builds is [to be validated]. The site is far below both limits.
- Without the secrets, the workflow skips the deploy, with a notice, and still builds.
7.2 The full stack on demand in GitHub Codespaces (from D3)¶
- The dev container (
.devcontainer/) installs the pinned toolchain (§1): uv, Python, Java 21, Nextflow, Snakemake, Node and Playwright, plus Docker-in-Docker for sind and kind. - Forwarded ports: the docs site on 8000, and, once it exists, Spectio on 8080 with a seeded demo.
- Opening it. Each PR comment from
previews.ymlcarries an "Open in Codespaces" link for its branch (https://codespaces.new/weber8thomas/spectio/tree/<branch>?quickstart=1). Thomas opens it when he wants to try the real thing. - Lifetime. The codespace stops when idle, and nothing runs when nobody looks.
- Cost: GitHub Free includes 120 hours and 15 GB a month, and 2-core machines count double (billing). Without a payment method, usage stops at the quota instead of being billed.
- Showing it to someone. A forwarded port can be made public (
https://<codespace>-<port>.app.github.dev), with no sign-in (ports). Use this only for short demos, with demo mode on.
7.3 The UI in mock mode (from the first UI milestone)¶
The front-end has a build flag that replaces the API with fixtures generated from the OpenAPI and the demo dataset (MSW). That build is static, so every UI iteration can be published on Cloudflare Pages and compared side by side with no backend at all. The real backend stays covered by tiers 2–4 and by Codespaces.
7.4 The public instance (from the public beta)¶
- Where. On EMBL's Kubernetes, with the Helm chart, as depictio does: a self-hosted runner inside EMBL,
workflow_dispatchonly, behind a GitHub environment with a required reviewer. - What is not copied from depictio (
docs/reviews/R8b-depictio-tooling.md, DEP-T-032):--insecure-skip-tls-verifyand values files kept on the runner's disk. - Before it exists: nothing public runs Spectio's backend. Inbound webhook tests run in CI against a local instance.
8. Claude in the development loop¶
| Mechanism | Use in Spectio | Reference |
|---|---|---|
Project memory CLAUDE.md |
project rules, phase, commands | memory |
Subagents .claude/agents/ |
eight reviewers and builders (spec, facts, constraints, security, UX, depictio liaison, tests, infra) | sub-agents |
Skills .claude/skills/ |
workflow skills (review-round, apply-findings, verify-claims, render-board, spike) + vendored superpowers and Karpathy guidelines |
skills, .claude/skills/THIRD_PARTY.md |
| Worktrees | one agent and scenario per worktree (isolation: worktree for implementer agents later) |
sub-agents docs |
| Cloud sessions in parallel | independent spikes and review rounds, each on its own branch | cloud sessions |
| Auto-fix pull requests | Claude watches CI and review comments on a PR and pushes fixes (needs the Claude GitHub App) | same page, "Auto-fix" |
| GitHub Actions with Claude | PR review by spec-reviewer on docs/**, security-reviewer on auth, tokens, plugins and runner paths |
GitHub Actions |
| Routines | weekly depictio-liaison drift check; weekly nf-core release check against templates and checking-scenarios.md; nightly verify-claims on specs whose upstream released |
routines |
| Agent teams (experimental) | large review rounds where reviewers discuss findings | agent teams |
| sind's MCP server | agents create and break SLURM clusters through tools instead of shell | sind README |
| Playwright | e2e tests, and agents looking at the UI they built | — |
Guard rails.
- Agents work on branches and open PRs.
- CI tiers 0–4 must pass.
- A human merges.
- Reviewers are read-only.
- No secrets in the repository or in shared environment variables.
- Deploy credentials (Cloudflare now, EMBL later) stay in GitHub environments, never in repository-level secrets (R8b DEP-T-007).
9. First steps (playbook phase D)¶
- D1: validate
.claude/(agents load, skills appear in/), and add the docs CI. -
D2 spike (the cloud environment):
- does Docker, sind and kind each work in a cloud session?
- which domains Nextflow, nf-core and the registries need;
- can the setup script stay under 5 minutes?
-
D3: write
dev/versions.env,dev/bootstrap.shanddev/doctor.sh, and run them green in a cloud session, in CI and locally. - D4: build the fixture workflows and record the first golden fixtures (Tower protocol payloads, Snakemake logger events,
squeue/sacctJSON from sind). - D5: dev previews: the Cloudflare Pages deploy with the
/versionspage, and the Codespaces dev container (§7).
10. Pipeline test corpus¶
10.1 Synthetic scenario pipelines (tests/pipelines/synthetic/)¶
Two twin pipelines, one written for each engine:
What they share:
- the same three stages (
qc→ gate →align→ gate →quant); - the same task bodies (
bin/synth.py, deterministic and seeded); - the same 12-sample samplesheet (three groups, one low-depth outlier, S03);
- the same failure injection (
exit,oom,oom_once,oom_real,timeout,flaky), targeted at one process or rule and, optionally, one sample.
Both engines produce byte-identical results (the counts matrix compared with diff).
Gate stops use exactly what Spectio generates:
- Nextflow: a config setting
ext.when = falseon later stages (conf/stop_after_qc.config), then-resume. - Snakemake:
--until qc_reportor--until align_done, then a plain rerun.
Scenarios are in scenarios.yaml. run_scenarios.py runs them and checks:
- exit codes;
- expected and forbidden outputs;
- content checks;
- per-process counts of completed and failed tasks, exit codes and attempts, read from the Nextflow trace or the Snakemake log;
- cached tasks after
-resume.
| Scenario | What it proves |
|---|---|
happy |
65 tasks, all outputs |
gate_qc_then_resume, gate_align_then_resume |
stop at a gate with the generated config, resume with cached work |
exclude_sample_and_resume |
samplesheet v2 without the outlier; downstream recomputed without it |
flaky_retry |
failure on attempt 1, success on retry |
oom_once_retry |
exit 137 once, success with more memory on attempt 2 |
oom_fatal, timeout_fatal |
failure after 3 attempts with the right exit codes (137, 143 / 124) |
tool_error_then_fixed_resume |
a non-retried tool error, then a resume after the fix |
dynamic_fanout |
chunk count decided at run time (Nextflow dynamic channel, Snakemake checkpoint): 45 ALIGN tasks |
fanout_medium |
180 ALIGN tasks (PR) |
fanout_stress |
about 12 000 ALIGN tasks (nightly) |
Verified runs on 2026-10-26 (this session, local executor, 2 CPUs); see docs/research/spike-synthetic-pipelines-2026-10-26.md and the step page F2:
| Engine | Result |
|---|---|
| Nextflow 26.10.3 | 11 / 11 pass |
| Nextflow 25.10.9 | 11 / 11 pass (after retrying time-limit kills that carry no exit code) |
| Snakemake 9.27.1 | 11 / 11 pass. oom_once_retry hit a known engine fault in 4 of its 18 executions; the faulty run is repeated once and reported as PASS* |
Known engine faults. These are listed in scenarios.yaml under engine_faults, each with the log pattern that identifies it. A failed scenario that matches one is repeated once, from scratch, and reported as PASS*. Any other failure fails the build.
Profiles for the same pipelines on other executors:
- Nextflow
-profile slurm, which includes job arrays for ALIGN; - Nextflow
-profile k8s, which adds thespectio.io/run-idpod label; - Snakemake
--workflow-profile profiles/slurm.
These run against sind and kind in T3 and T4.
10.2 Real pipelines (tests/pipelines/real/corpus.yaml)¶
Step page: F3. Real pipelines run with their own test datasets. They are chosen to cover the scenario classes of checking-scenarios.md §1. Sources: docs/research/corpus-and-ci-2026-10-26.md.
| Source | PR tier | Nightly tier |
|---|---|---|
nf-core (-profile test,docker, data from nf-core/test-datasets) |
demo, rnaseq, viralrecon, methylseq, molkart | fetchngs, sarek, scrnaseq, mhcquant, differentialabundance, mag, ampliseq, taxprofiler (mcmicro: manual) |
Snakemake Workflow Catalog (.test/ directory, --sdm conda) |
rna-seq-star-deseq2, dna-seq-gatk-variant-calling, ms-proteomics (dry-run only, as upstream) | rna-seq-kallisto-sleuth, dna-seq-varlociraptor, single-cell-rna-seq, chipseq, cyrcular-calling, ONT-AmpSeq |
run_corpus.pyruns one entry, a tier or everything, and writesresult.jsonper pipeline.- The same entries are reused later: once the server exists, they are launched through Spectio (runner → engine), and the checks move from exit codes to Spectio's own run states, gates and evidence.
- Constraints:
- mag 5.5.0 and ampliseq 3.0.0 need Nextflow ≥ 26.04, so the 25.10 leg skips them;
- private-repository GitHub runners have 2 CPU / 8 GB, so nf-core runs get
process.resourceLimitsfromrunner_limits.private; - the heaviest entries are nightly only.
11. CI workflows¶
| Workflow | Trigger | What it runs |
|---|---|---|
docs.yml |
PR and push touching docs/ |
strict MkDocs build, Mermaid render |
pipelines-synthetic.yml |
PR, main, nightly | synthetic scenarios × {Nextflow 26.10.3, 25.10.9, Snakemake 9.27.1}; stress scenario nightly; artifacts with reports, logs, traces |
pipelines-real.yml |
PR touching the corpus, nightly, manual | matrix generated from corpus.yaml: nf-core with nf-core/setup-nextflow@v3, the catalog with snakemake/snakemake-github-action@v2 on the workflow's own .test |
pipelines-slurm.yml (T3) |
PR touching runner code, nightly | GSI-HPC/sind-action@v2 cluster, synthetic scenarios with the SLURM profiles. Needs cgroup v2 Docker, which GitHub runners have; this cloud session has cgroup v1, so not here |
pipelines-k8s.yml (T4) |
nightly | helm/kind-action@v1 + Kueue, synthetic scenarios with the k8s profile, nf-core/demo |
release-please.yml |
push to main | release PR with version bump and changelog (§12) |
previews.yml |
PR, push to main, v* tags, wave approvals, manual |
build the docs site, deploy it to Cloudflare Pages under its own branch alias, regenerate /versions, comment the preview and Codespaces links on the PR (§7) |
12. Versioning and releases¶
- Commit and PR titles: Conventional Commits (
feat:,fix:,docs:,test:,ci:,chore:). The PR title becomes the squash commit, so the title is what is checked. - Release PR.
release-pleasekeeps one open onmain, with the next version and a conciseCHANGELOG.mdsection grouped by type. Each line links the PR and its commit. - Releasing. Merging the release PR tags
vX.Y.Z, creates the GitHub release, and triggers the image, Helm chart and PyPI builds. - One version train for the core (
spectio,spectio-server, HelmappVersion), kept in step with thelinked-versionsplugin once the Python packages exist.spectio-sdkfollows its own semver (architecture-plugins-and-packaging.md§4). For nowrelease-type: simpleversions the repository as a whole. - Image tags (
docker/metadata-action@v6):X.Y.ZandX.Yon releases,sha-<7>on every build,edgeon main,pr-<n>on previews. -
Versions you can see:
GET /api/v1/versionreturnsversion,git_sha,build_date,schema_revisionanddeployment;- the UI footer shows the version and links to its changelog entry;
- every preview and instance shows a "vX.Y.Z+sha" banner;
spectio --versionprints the client version and warns when the server differs.
-
Pre-1.0 policy: minor versions may break the API, and the changelog says so. From 1.0, semver applies to the public API and the plugin SDK.
-
The version follows the importance of the change, automatically (
release-please-config.json):Merged since the last release Next version (while < 1.0) only docs,test,ci,chore,refactorno release at least one fixorperfpatch: 0.3.1 → 0.3.2 at least one featminor: 0.3.1 → 0.4.0 a breaking change ( feat!:or aBREAKING CHANGE:footer)minor too ( bump-minor-pre-major), never 1.0.0- Design phase:
featandfixare kept for product code. Tooling (tools/,tests/, workflows) useschore,testorci. Docs, specs and research usedocs. So no release is cut before the walking skeleton, which is planned as0.1.0. - Docs and tests do not cut releases. They are hidden from the generated
CHANGELOG.md, because the curated changelog (documentation-system.md§6) covers docs. Whether a visible changelog section alone makes a commit releasable is [to be validated] with a dry run (release-please release-pr --dry-run). - 1.0.0 is never automatic. release-please only reaches it when
release-as: 1.0.0is set in the config (release-please manifest docs). A guard (release-guard.yml) also fails any release PR at ≥ 1.0.0 unless the repository variableALLOW_V1istrue. Thomas sets that variable once the 1.0 gate (§14) is met.
- Design phase:
13. Instance verification and access¶
Dev previews (now).
-
After each deploy,
previews.ymlfetches the deployed URL and checks:- the home page and
/versionsanswer; - the build's commit SHA is in the page footer;
- a sample of internal links resolves.
- the home page and
-
The preview and Codespaces links are posted on the PR.
The public instance (from the beta, §7.4). Every deploy is verified through its public URL:
- Version:
/health/readyand/api/v1/version, whosegit_shamust match the deployed commit. -
Playwright smoke test (T6):
- sign-in by magic link (Mailpit in the test profile);
- opening a run;
- opening a gate and approving it on a synthetic run;
- the phone viewport.
-
Share-link round trip: create a link, open it in a fresh browser context, check its scope, revoke it, and check that it now fails.
Access without accounts.
- Share links. On the public instance, demos and outside reviewers use scoped share links (
authentication-and-access.md§2) instead of shared passwords. - Demo mode. Visitors without a link see read-only demo data.
- Nightly reset. The demo data is reset every night from a known backup, which also tests restore.
14. Release stages and the 1.0 gate¶
Spectio stays in 0.x until it has been checked, in a fairly robust way, against several use cases and by several users. Each stage has an entry condition, and the docs say which stage a version belongs to: the changelog block's admonition and a badge on the landing page.
| Stage | Versions | Who uses it | Entry condition |
|---|---|---|---|
| Design | none | Thomas and the agents | — |
| Walking skeleton | 0.1.x | Thomas, on the synthetic pipelines | GO gate passed (pipeline W4); one run crosses every layer once (launch, observe, gate, resume, hand-off) |
| Private alpha | 0.2 – 0.4 | 3 to 5 design-partner groups at EMBL (docs/research/adoption-and-positioning-2026-10-26.md) |
install in under 30 min from the docs alone; real corpus green nightly; backup and restore tested; R5 security findings closed |
| Public beta | 0.5 – 0.9 | anyone, with a public demo instance | 2 weeks without a P0/P1 bug at the partners; upgrade tested across 3 consecutive minors; every guide has a cast or screenshots |
| 1.0 | 1.0.0 | stable for institutional installs | the 1.0 gate below, checked by a review step (R-v1, added to the pipeline when the beta starts) and decided by Thomas |
The 1.0 gate (all of them):
- Use cases. At least one real pipeline from each scenario class of
checking-scenarios.md§1 runs through Spectio, with a gate decided by a person other than its author. - Users and sites. At least 3 groups, 2 of them outside Thomas's own team, and 10 or more active users over 8 consecutive weeks. At least one site other than EMBL [to be validated: realistic target].
- Engines and schedulers. Nextflow and Snakemake on SLURM and on Kubernetes in daily use, plus the local runner.
- Tests. The synthetic suite is green on every PR, and the real corpus is green nightly for 4 consecutive weeks. The auth matrix (
authentication-and-access.md§6) and the Playwright suite are green. - Operations. An upgrade path is tested across at least 3 minors with backup, restore and migration. No open P0 or P1 bug. A documented support channel answers within a week.
- Contracts. The OpenAPI and the plugin SDK are frozen, with a deprecation policy. The data model has a migration test for every revision.
- Docs. Install, user, admin and operator guides, the reference (API, CLI, configuration), and a curated changelog for every 0.x version.