Changelog
All notable user-visible changes to spoolctl are documented here.
Status: published, pre-1.0. The CLI surface can still move between minor versions, but the documented interface and guarantees are tested in this repository.
v0.4.11 — Packaging Blessed
spoolctl is installable from PyPI. No behavior change to any verb;
CONTRACT_VERSION remains 2, SCHEMA_VERSION remains 6, and runtime
dependencies remain empty.
- Packaging is blessed.
pip install spoolctl/uv tool install spoolctlare the supported installation paths; the README no longer disclaims them. - Removed references to a planned MCP server mode from the published contract
and documentation. The
contract_policystring incapabilities --jsonnow describes the v0.4.7 additions as readiness diagnostics for automated consumers, and thedoctordocumentation describes automated launchers generally. MCP server mode was evaluated and will not be built; the readiness and config surfaces it motivated stand on their own and are unchanged. - No verb, flag, schema, exit code, or database change.
v0.4.10 — The feedback Verb and the Operation Layer
Additive release. CONTRACT_VERSION remains 2, SCHEMA_VERSION remains 6,
and spoolctl still has zero runtime dependencies.
Version note: 0.4.10 sorts after 0.4.9. PEP 440 compares each component
numerically, so 10 > 9; only a lexical string sort would put it before.
- Added the
feedbackverb: one call returns whether a job isterminal, whether itsucceeded(tri-state,nullwhile in flight), itsexit_code,failure_reason,last_error,duration_seconds, the three counting fields (attempts,attempts_total,latest_attempt_no), aremediationcommand naming what to run next, and tails of both output streams. feedback --tail-bytes N(1..65536, default 2048) sizes each tail;--stream {stdout,stderr,both}narrows the human-readable rendering only, since the JSON payload always carries both streams.feedbackdistinguishes three stream situations that used to look alike: no attempt has run (path: null), the file was deleted or is unreadable (missing: true), and the attempt produced nothing (size_bytes: 0).- Completed the operation layer:
show,list,events,retry,cancel, andprunenow delegate to reusable operations inspoolctl/operations.py, joiningadd,wait,status,output,config-*, anddoctor. Consent stays in the CLI adapter; effect lives in the operation. Behavior is unchanged, proven by the differential signature matrix. workandevents --followare deliberately not lifted: one is a process with signal handlers and a process group, the other an open-ended stream against a terminal. Both reasons are recorded in the operations module.- Corrected the documented
failedjob state. It is reserved and never emitted: a failing job with retry budget left returns toqueued(reported asscheduledduring backoff) and becomesdeadwhen the budget is exhausted. The value itself is unchanged in the contract. - The
brieftoken budget stays at 700; the newfeedbackline was paid for by removing a duplicatedwaitclause and the self-describingcapabilities --jsonsurface enumeration.
v0.4.9 — Changelog and README Housekeeping
Housekeeping release. Zero runtime behavior change. CONTRACT_VERSION remains
2, SCHEMA_VERSION remains 6.
- Added curated public
CHANGELOG.mdcovering v0.1.0 through v0.4.9. - Added
docs/changelog.mdsymlink so the changelog renders in the mkdocs documentation site under Project. - Slimmed
README.mdfrom ~330 to ~240 lines: removed version-specific sections, compressed redundant FAQ entries and detail blocks, added docs cross-references. - Added changelog content gates to the test suite: version-ahead check and forward-language scan.
v0.4.8 — Documentation Section
Docs-only release. Zero runtime behavior change.
- Added 19-page documentation tree under
docs/: install, quickstart, concepts, guarantees, architecture, scheduling, execution, config, doctor, events, agent guide, JSON contract, comparison, landscape, FAQ, security, lineage, and project overview. - Added a stdlib-only generator (
scripts/build_docs.py) producing four reference pages (verbs, errors, limits, states) from the live contract.--checkmode gates CI against drift. - Added
mkdocs.ymlwith mkdocs-material theme.mkdocs-materialis an optional[docs]extra;pip install spoolctlremains stdlib-only. - Added a Documentation section to the README linking into
docs/.
v0.4.7 — MCP Readiness Prep
Additive readiness release. CONTRACT_VERSION remains 2, SCHEMA_VERSION
remains 6.
- Added project-local config resolution. Database path precedence is now
explicit:
--db>SPOOLCTL_DB>.spoolctl/config.jsondb_path>./.spoolctl/queue.dbrelative to the project directory. - Added
config-show: reports the effective config path, config validity, DB path, DB source, and precedence without opening or creating the database. - Added
config-validate [PATH]: validates optional project JSON config without opening or creating the database. Missing config is a valid optional state. - Added narrow
doctor: bounded readiness diagnostic checking config validity, DB path resolution, spool-directory writability, database existence, SQLite read/write open, schema version, and contract metadata. Readiness failures exit3with envelopeok:true,errors:[], anddata.ready:false. - Added contract completeness gates for verb tables, schema data, signature baselines, generated probes, and module-boundary coverage.
v0.4.6 — Operation-Layer Refactor
No-feature refactor release preparing the codebase for MCP server mode.
CONTRACT_VERSION remains 2, SCHEMA_VERSION remains 6.
- Extracted a reusable operation layer:
status,output,add, andwaitnow have typed operation inputs and direct tests independent of argparse. - Extracted focused modules:
errors.py,models.py,validation.py,operations.py, andcontract.py. Static tests enforce module boundaries. cli.pyremains the executable adapter: parser construction, envelope emission, rendering, stdout/stderr, and exit-code mapping.
v0.4.5 — Contract Conformance
Hardened the CLI contract. CONTRACT_VERSION bumped to 2. No v1
compatibility shim is planned before public release.
- Expanded
capabilities --jsoninto the probe source of truth: verbs, flags, positionals, malformed-input expectations, output modes, safety gates, idempotency behavior, schemas, code registry, environment variables, limits, scheduling, and execution semantics. - Hardened parser totality: disabled flag abbreviation, rejected inert flags,
made bare invocation an explicit error, diagnosed
addcommand-tail ambiguity, and converted numeric/path/env/duration/timestamp/enum failures into structured contract errors. - Added destructive gates:
prunerequires--yesunless--dry-run,cancel --runningrequires--yes,retry --forcefor running-job recovery. - Added
IDEMPOTENCY_CONFLICTfor active-key execution mismatch andIDEMPOTENCY_METADATA_DIFFERSfor metadata-only dedupe warnings. - Declared and tested output modes: envelope, frames (
events --follow --json), raw (output --raw), and human text. - Added
robot-docs guidewith JSON output and updated top-level help, brief text, and schemas.
Compatibility: fresh databases still use schema version 6.
CONTRACT_VERSION 2 removes accepted-but-unsafe or accepted-but-inert CLI
behaviors.
v0.4.2 — Failure Reason Enum
Made failures machine-classifiable. CONTRACT_VERSION remains 1.
- Added durable per-attempt
failure_reasonwith a stable enum:process_exit,timeout,spawn_failed,worker_crash,canceled, andunknown. - Added
job.last_failure_reasontoshow --json, derived from attempts using current-outcome semantics. Recovered jobs reportnull. - Updated
capabilities --jsonto publish thefailure_reasonsregistry andschema --jsonto validate nullable failure-reason fields.
Compatibility: schema version 6. Existing databases migrate forward. Migration
backfills obvious legacy states but maps ambiguous historical failed rows to
unknown.
v0.4.1 — Execution Fidelity
Completed the run primitive. CONTRACT_VERSION remains 1.
- Added per-job working directory with
add --cwd DIR. Resolved to an absolute path at submit time without symlink collapse; missing cwd at runtime is a normal spawn failure. - Added per-job environment overrides with repeatable
add --env K=V. Overrides augment the worker environment, allow empty values, and use last-wins semantics.add/listexpose env key names only;showis the explicit plaintext surface. - Split worker-crash accounting from job-owned failure retry accounting.
--max-retriesgoverns nonzero exits, timeouts, and spawn failures.--max-crashes Nbounds crash redelivery (default unbounded).
Compatibility: schema version 5. Existing databases migrate forward. Migration
backfills crashes from canonical abandoned attempts.
v0.4.0 — Scheduling-Lite and Lanes
Added scheduling and resource isolation. CONTRACT_VERSION remains 1.
- Added delayed submission:
add --after DURATIONandadd --at TIMESTAMP. Delayed jobs stayqueuedwith a futurenext_run_at; there is no new state. - Added submit-time priorities with
add --priority N. Claim order is nowpriority DESC, next_run_at ASC, id ASC. - Added named queues with
add --queue NAMEandwork --queue NAME. Default workers serve only thedefaultlane. - Added per-lane slot ceilings with
work --slots N, enforced inside the SQLite claim transaction. - Updated
list,show, andstatusto exposenext_run_at,priority,queue,scheduledcount, and per-queue counts. - Made
work --drainlane-aware: ignores other lanes and never-run user-delayed future rows while preserving retry-backoff draining.
Compatibility: schema version 4. Existing databases migrate forward.
v0.3.0 — Agent-Native Ergonomics
Differentiation begins. CONTRACT_VERSION remains 1.
- Added
brief: compact, token-budgeted usage doc for agent context injection. - Added
schema: formal JSON Schema export for the envelope, verb payloads, and event stream records. - Added idempotent submission with
add --key K: same key while queued/running is a no-op returning the existing id. - Added tags and notes:
add --tag KEY=VALUE,add --note STRING, filterable inlist --tag. - Added
events: read the append-only event log as a cursored one-shot, long-poll with--wait, or tail with--follow --jsonraw NDJSON.
Compatibility: schema version 3. Existing databases migrate forward.
v0.2.0 — Operational Completeness
Table-stakes completion of the CLI surface.
- Added
listandshow <id>with full attempt history from the event log. - Added
cancel <id>to dequeue a queued job;--runningkills the live process group. - Added
wait <id...>to block until jobs finish, with exit code reflecting outcome. Enables submit-many-then-wait as a parallelism primitive. - Added
work --drainto run until queue empty, then exit (cron/CI-friendly). - Added
pruneto delete old done jobs, events, and output files with age/state filters. - Added
--jsonon every read command and stable documented exit codes.
v0.1.0 — The Reliability Core
Initial release.
add,work,status,retry,output.- Atomic claiming via
BEGIN IMMEDIATE, confirmed-dead reaping with heartbeat and pid-reuse guard, exponential backoff, dead-letter state, per-job timeout with process-group kill, per-attempt captured output. - Full concurrency and SIGKILL test suite: no double execution, SIGKILL recovery, no false-positive reap of a live worker, timeout kill including grandchildren.
- Ships as a single file and as
pip install spoolctl. Python 3.10+, stdlib only, macOS and Linux.