Jaunt
Reference

Upgrading

Per-version migration notes. Version churn lives only here.

The rest of the reference is versionless. This page collects what changes between releases and what you have to do about it. For the complete log, see the GitHub releases.

Compatibility promise: patch releases (1.3.0 → 1.3.1) do not normally invalidate built modules. The exception is a correctness repair for artifacts whose provenance was previously marked fresh incorrectly; that safety migration is called out explicitly below.

1.7.14

Jaunt-managed PyPI and npm skills now live under .jaunt/skills; .agents/skills is reserved for project-authored overrides. Preview the mechanical migration, then apply it from a clean worktree:

jaunt skill migrate
jaunt skill migrate --apply

The migration recognizes Jaunt's Python and npm provenance frontmatter, leaves manual skills untouched, deduplicates byte-identical destinations, and refuses conflicting destinations. Jaunt also adds the narrow .gitignore rules needed to track .jaunt/skills while keeping other .jaunt runtime state ignored.

Skill activation defaults to relevant. Jaunt uses each request's imports and dependency context, keeps unscoped manual project skills active, and partitions the generation cache on the selected set. Use [skills] activation = "all" for the old all-skills behavior, or configure always and exclude by skill name.

Targeted TypeScript builds now recompose an existing implementation without a model call when current compiler and consumer validation prove that structural staleness came only from compatible environment provenance. For an explicit preview/apply workflow, jaunt migrate --language ts also accepts repeatable --target ts:<module-id> flags and limits its write set to those modules.

This is a Python-only patch. Keep @usejaunt/ts at 0.1.3; no npm upgrade is needed.

1.7.13 / @usejaunt/ts 0.1.3

Installed skill content and installed-toolchain identity (runner, Vitest, and fast-check) no longer gate committed TypeScript battery freshness; only contract inputs and ownership/tamper signals (provenance, tier, source, and body_digest) do: a tampered body, wrong tier, wrong source path, or unparseable provenance still fails check. From this release on, the installed fast-check version is not a freshness input at all. A battery stamped by an older Jaunt whose contract fields still match is re-stamped for free by the next jaunt test --language ts, with no model call and no API key — but only if the installed fast-check version is also unchanged since that battery was stamped. The pre-split property digest embedded the version, so Jaunt recognizes such a header by recomputing the old composition against the currently installed version; if fast-check was upgraded too, the committed digest cannot be reconstructed and those batteries regenerate once, with a model call. Nothing is falsely declared fresh — the mismatch simply falls through to regeneration. So to take the free migration, upgrade Jaunt first, run jaunt test --language ts to re-stamp, and bump fast-check afterwards; the re-stamped header no longer carries the version, so later fast-check bumps cost nothing. jaunt check now agrees with jaunt test: it reports non-gating divergence as an advisory on the diagnostic instead of failing the gate. This covers TypeScript test batteries; module sidecars still hash skill content into their generation fingerprint, so a regenerated or edited skill can still make jaunt check exit 4 for every TypeScript module. That repair is free, though: jaunt build re-stamps those modules with no model call.

jaunt status no longer reports environment-only battery drift, even informationally, because it and check share one diagnostic implementation. Repo-map drift is the inverse precedent: status notes it while build and check ignore it.

This removes skills and toolchain identity as causes of staleness, but it does not promise that upgrading across releases needs no regeneration. A repo whose artifacts were stamped by an older Jaunt can still see genuine contract-field drift in fixture_fingerprint, prompt_fingerprint, target_api_digest, or imported_type_context_fingerprint for reasons unrelated to this fix — and the pre-split fast-check case above is one more instance of the same point. That drift requires regeneration.

@usejaunt/ts 0.1.3 also narrows TypeScript module structural freshness to the resolved declaration surface. Package-manager metadata, lockfile-only changes, and manifest dependencies that the module never resolves remain provenance, but no longer force a rebuild. Changes to declarations that the module imports still invalidate it.

Upgrade both packages for the complete fix:

uv add --dev 'jaunt==1.7.13'
npm install -D @usejaunt/ts@^0.1.3 'typescript@^5.9' vitest fast-check @types/node

1.7.12

Vitest projects using the jsdom environment can pin the protected runner again. Jaunt no longer applies its generated-code CommonJS loader policy as a hard gate to third-party package source. Unsupported loader flows do not discard other static imports from the same file. Jaunt still follows manifest dependencies and pins every resolved package's full runtime identity through the final command boundary.

This is a Python-only patch. Keep @usejaunt/ts at 0.1.2; no npm upgrade is needed. Errors raised before a normal TypeScript check report now appear in the top-level diagnostics array from standalone and mixed check --json commands.

1.7.11 / @usejaunt/ts 0.1.2

TypeScript batteries whose only mismatches are target_api_digest and battery_fingerprint no longer require a model call merely to refresh their stamps. Use the committed battery as the proof:

jaunt build --language ts --no-semantic-gate
jaunt test --language ts --no-build
jaunt check --language ts

The test command typechecks and runs the old body against the current target, then reheaders it when green. Do not use --no-run for this recovery: without runtime verification Jaunt regenerates rather than trusting the old body. A successful reheader can land even when a sibling battery exhausts its attempts. Target-API drift may also change the embedded prompt or runner fingerprint; those combinations use the same safety-first verification path rather than forcing generation. The protected scanner accepts a computed record key only when it can prove a unique same-file const string-literal binding, while forbidden loader properties and unknown dynamic keys remain fail-closed.

Legacy batteries created before fixture_fingerprint was recorded can use this verification path when the current request has no fixture. Jaunt proves the missing field means an empty fixture, then typechecks and executes the unchanged body under the current runner before reheadering it. A newly added or changed real fixture remains a content change and regenerates normally.

Regenerated implementations now have an additional pre-commit gate: compatible committed Jaunt batteries for the target run against the candidate overlay. Native project tests remain a separate repository gate. TypeScript test --instruction values reach both battery tiers but stay invocation-only; persistent [build].instructions remain provenance-bearing.

When generation exhausts its candidate budget, inspect the exact saved source and JSON metadata under .jaunt/typescript/rejected-tests/. The structured diagnostic is JAUNT_TS_TEST_GENERATION_EXHAUSTED; a later successful run removes the matching record. A prompt-only fingerprint change preserves that diagnostic; changing the test contract or target API resets it.

Jaunt 1.7.11 requires the matching protected-runner capability from @usejaunt/ts 0.1.2. Upgrade the project-local worker so Vitest config snapshots stay available to imports without becoming standalone typecheck roots:

npm install -D @usejaunt/ts@^0.1.2 'typescript@^5.9' vitest fast-check @types/node

No contract-IR migration is required for this release.

This release also broadens the local tool identity used by TypeScript builds and tests: Jaunt now fingerprints all shipped files and the full parsed manifests of the protected runner, compiler, Vitest, and statically imported Vitest-config packages, including their declared and statically loaded runtime dependency closure. The config scan includes hoisted undeclared loads, require.resolve(), legal comment trivia, and imports inside executable template expressions; it captures static join/resolve config paths and rejects indirect or computed module loads it cannot prove safe. A proven createRequire loader, factory, or Node module namespace cannot be exported across captured config files; keep the static package load in the same helper so its provenance remains auditable. Existing artifacts may therefore show one toolchain, runner, or Vitest transition after upgrading even when their behavior is unchanged. The buildtest --no-buildcheck sequence above validates and reheaders those committed artifacts without a model call; --no-semantic-gate makes the model-free intent explicit for the build step.

Contract mutation scoring now runs from a disposable workspace. On supported Linux hosts Jaunt adds a namespace boundary; all hosts apply Node's filesystem permissions. Trusted runner hosts may start infrastructure children such as Vitest 3's esbuild service, but the preloaded guard removes that permission from generated battery workers. Battery code cannot create processes or read or write outside the isolated workspace. External dependency links are materialized into that workspace instead of granting access to their package-store parent; any link that still escapes the copy fails before the runner starts. Mutation timeouts and runner failures are excluded and leave the strength report incomplete rather than increasing its score. This changes no committed contract format.

Codex plan-level usage limits still fail immediately unless you opt in to waiting. Set a project default or override it for one command:

[codex]
quota_wait_minutes = 15
jaunt build --quota-wait 15
jaunt test --quota-wait 15

The wait budget is one command-wide total shared by modules, batteries, and mixed targets. Concurrent waits reserve from that total before sleeping. The bounded exponential backoff does not consume generation attempts. Vitest startup failures now retain a bounded message and stack so runner installation or configuration problems are actionable; failures from executed held-out cases remain redacted.

1.7.10 / @usejaunt/ts 0.1.1

Tagged-template text no longer participates in the TypeScript semantic environment. A change inside a gql document or another tagged string in a transitive import therefore leaves governed modules and generated batteries fresh when their type contract is unchanged. Expressions inside ${...} and ordinary untagged template literals remain structural inputs.

Existing 0.1.0 artifacts whose import closure contains tagged templates may show one toolchain transition after upgrading. Preview it with jaunt migrate --language ts --json; when the tagged-template normalization is the only change, the current compiler can validate it as free-recompose without a model call.

1.7.9 / @usejaunt/ts 0.1.0

@usejaunt/ts 0.1.0 is the first release on npm's latest channel. Pair it with Jaunt 1.7.9 or later:

npm install -D @usejaunt/ts@^0.1.0 'typescript@^5.9' vitest fast-check @types/node

The supported host ranges remain Node 20 through 24 and TypeScript 5.8 through 6.x. An unchanged alpha.7 workspace can reuse its implementation even when the older sidecar's aggregate semantic-environment digest no longer matches. Preview the recovery first:

jaunt migrate --language ts --json
jaunt migrate --language ts --target ts:src/example --json
jaunt migrate --language ts --target ts:src/example --apply
jaunt migrate --language ts --apply
jaunt test --language ts --no-build
jaunt check --language ts

Apply only when every affected module is free-recompose and requires_rebuild is empty. The migration validates the saved implementation against the current compiler, static policy, public API, and consumer closure, then carries the old-to-new API proof into the separate battery command. It makes no model calls. Contract changes, changed symbol/options/dependency payloads, and compiler-overlay failures remain rebuilds. Use repeatable --target flags when you want to validate and land the recovery incrementally without writing unrelated module artifacts.

New sidecars store package- and workspace-scoped semantic-environment digests. Whole lockfiles still trigger ordinary structural analysis, but unrelated lockfile entries no longer define compatibility. Resolved declaration files and project metadata do, and status/migration JSON reports their added, removed, and changed records when the previous sidecar has the same evidence.

The root package.json#packageManager field is tooling provenance rather than semantic contract. Adding or changing it still makes the structural record visible, under an exact tooling:packageManager:<path> identifier, but it does not invalidate the resolved declaration compatibility digest.

This pair also fixes alpha.7's test-candidate retry gap. Live candidates now pass through the same full-project overlay and dynamic-loader checks as cached responses. A rejected attempt consumes the remaining per-battery retry budget and the runner's exact diagnostic is included in batteries[].retry_reasons. If a combined overlay still exposes a cross-battery conflict, Jaunt isolates, runs, and commits a compatible subset while leaving the conflicting paths uncommitted and returning exit 3. Typecheck messages are bounded to 2,000 characters without exposing executed derived-test detail. Validator- or subset-rejected cache entries are evicted, while a concurrently replaced entry is retained.

Long TypeScript runs now honor explicit plain progress in both TypeScript-only and mixed workspaces. --progress plain --json prints the active module or battery, the battery tier, retry phases, and completion counts to stderr; stdout remains a single JSON object. Jaunt also retries the known Codex capacity response twice without spending the candidate attempt budget. If capacity stays exhausted, the command returns the failed module or battery in its normal structured report and keeps outcomes from requests that already finished. Mixed build JSON retains TypeScript candidate_outcomes at the top level and under targets.ts.

jaunt doctor --json now identifies the running Jaunt entrypoint and module, Python executable, distribution or editable source, nearest uv.lock, and the lock's Jaunt requirement. It warns when the active version differs from the lock, which catches a broad uv sync replacing an editable checkout before a long validation run.

The npm package is stable, but the worker boundary still identifies itself as jaunt-ts/1-draft.3. That protocol is versioned for matching Jaunt Python and npm releases; it is not yet a compatibility promise for third-party protocol clients. Refresh the companion plugin to Codex 1.1.6 or Claude Code 1.2.6 for matching stable-target guidance, then start a new host session.

1.7.8

Pair Jaunt 1.7.8 with @usejaunt/ts 0.1.0-alpha.7. Strict TypeScript projects can keep noUnusedParameters enabled during full or targeted sync. Jaunt ignores TS6133 only for parameters in canonical jaunt.magic() marker bodies, including dependency-closure specs; unused parameters in @jauntPreserve and other handwritten bodies remain errors. Mixed-workspace jaunt instructions output now labels its Python freshness snapshot separately and directs agents to jaunt status --language ts for authoritative TypeScript freshness. TypeScript battery generation now honors the test job limit and durably stages validated responses after a combined compiler preflight. Alpha.7 did not attach the project-overlay validator to live model attempts, so compiler and dynamic-loader failures could escape the retry loop and reject the complete set at the final gate. Upgrade to Jaunt 1.7.9 for the corrected retry and partial-landing behavior.

1.7.7

Pair Jaunt 1.7.7 with @usejaunt/ts 0.1.0-alpha.6. This hotfix preserves the bounded 1.7.6 compiler workflow while restoring full status and check coverage for handwritten consumers. Scoped candidate validation now follows reverse consumers only from modules that actually change, so an unrelated pre-existing error below an unchanged dependency does not reject the target. Strict API mirrors also remove imports shadowed by value parameters in public typeof declarations.

1.7.6

Pair Jaunt 1.7.6 with @usejaunt/ts 0.1.0-alpha.5. Existing alpha.4 implementations with valid semantic-environment proof recompose through the current worker without a model call; matching Vitest batteries are reheadered and rerun. If the saved proof is missing or the dependency contract changed, status reports the normal rebuild reason instead.

  • Final TypeScript conformance failures now consume the remaining per-module attempt budget. Build JSON reports candidate_outcomes, and cost accounting records each attempt instead of one aggregate call.
  • Strict API mirrors drop implementation-only imports. Status and sync validate bounded dependency batches and release compiler program state between batches.
  • Large projects can set [target.ts].worker_heap_mb. Jaunt passes the limit directly to Node, distinguishes heap OOMs from timeouts and missing tooling, and never replays a deterministic OOM.
  • Paid Codex subprocesses ignore user Codex configuration on current CLIs, so unrelated hooks, plugins, and MCP tools do not inflate generation context.
  • Refresh the companion plugins to Codex 1.1.4 or Claude Code 1.2.4, then start a new host session. Loaded sessions keep their old skill and hook snapshot.

1.7.0

Jaunt 1.7 adds the first alpha TypeScript target. The Python package is now 1.7.0; the project-local worker and marker package use their own prerelease version under @usejaunt/ts.

  • Existing Python projects do not need a migration. Version-1 jaunt.toml files and generated Python artifacts keep their current layout. The release does not intentionally stale an otherwise fresh Python module; upgrade and run jaunt check as usual.

  • A TypeScript target uses version-2 configuration. Install the Python CLI, then add the worker, a supported compiler, and the protected test runtime to the package named by tool_owner:

    npm install -D @usejaunt/ts@next 'typescript@^5.9' vitest fast-check @types/node

    The worker supports Node 20 through 24 and TypeScript 5.8 through 6.x. Start with the TypeScript target guide, then run jaunt sync --language ts before the first model-backed build.

  • Adding TypeScript to a version-1 Python project is mechanical. Preview jaunt migrate --config-v2, review the version-2 target layout, and apply it with jaunt migrate --config-v2 --apply. The migration moves Python-specific settings under [target.py] without changing their loaded values or calling a model.

  • Alpha artifact formats can still change. Preview upgrades with jaunt migrate --language ts. Compatible mirrors, facades, placeholders, sidecars, and fingerprints are repaired deterministically; an incompatible protocol, IR, route, or contract change is reported as model-rebuild rather than guessed.

  • Mixed workspaces operate on both targets by default. Use --language py or --language ts to narrow a command. TypeScript target IDs are qualified as ts:path/to/spec#symbol; existing dotted Python IDs keep their meaning.

1.6.3

  • Removing a magic or generated-test spec now rebuilds its module instead of re-stamping the old body. This prevents deleted implementations and pytest functions from surviving as dead generated text.
  • Generated artifacts last stamped by 1.0.0rc7 through 1.6.2 rebuild once on upgrade because those releases could overwrite the evidence needed to detect an earlier removal-only re-stamp. This is an intentional safety exception to the usual patch-release freshness promise.
  • Context-only rebuilds stay local, while removal and public-API changes still propagate to affected dependents. Pure fingerprint changes and semantically equivalent prose edits retain the free re-stamp path.

1.6.2

  • A single jaunt.toml can now route modules across several packages and mixed flat/src layouts. source_roots and test_roots accept globs; unmatched globs fail during config loading.
  • Generated implementations, stubs, tests, contract batteries, ty checks, and dependency validation follow each module's nearest owning pyproject.toml. Root-level status, check, clean, watch, and daemon jobs cover the full workspace.
  • Run jaunt migrate --merge-projects to prove that existing child projects can be consolidated without changing module names, digests, fingerprints, or artifact paths. Add --apply after reviewing the plan.
  • The semantic gate now defaults to gpt-5.6-luna at medium reasoning. Semantic gate settings remain outside generation fingerprints, so this does not stale generated modules.

1.5.1

Patch release from the sixth adoption-feedback wave, focused on uv workspaces. No generated body changes, and the one restale it causes costs nothing to clear.

  • Modules read stale (fingerprint) after the upgrade — the next build re-stamps them all for free. The build prompt's import rule changed, and the prompt is a fingerprint input, so every built module reports stale once. Their spec sources are unchanged, so jaunt build resolves each through the re-stamp path: it writes the new fingerprint over the existing body with no semantic-gate call and no gpt-5.6-sol call. jaunt check counts fingerprint staleness as drift and exits 4 until you run that one build and commit the re-stamped headers. --json lists the modules under refrozen.
  • Specs that span source roots now stop at a config error instead of building into the wrong package. Under 1.5.0, a multi-root project (source_roots with more than one entry) routed every generated file to the first existing root, which quietly broke packages under the others — status and check read through the same wrong path, so the tree looked fresh while runtime was broken. 1.5.1 makes that a hard config error (exit 2) on build, check, status, and migrate: it fires when governed specs span more than one root, or when they all live under a root that is not the first existing one (the message tells you to reorder). The adopter-verified fix is one jaunt project per package: put a jaunt.toml with source_roots = ["."] at each package's import root and run jaunt from there. Nested default roots (["src", "."]) with specs under src/ resolve by longest path and pass untouched.
  • Generated code may import third-party packages plainly. The build prompt now sanctions the standard library and any installed distribution that the spec module imports or the owning package declares — imported from its real module, not smuggled in through a duck-typed stand-in or a dynamic import. Paired with it, the undeclared-import validator resolves declared dependencies from the pyproject that owns the spec's source file, not just the config-root one. A workspace dependency declared in its own package's pyproject now passes without an entry in build.generated_import_allowlist; see the allowlist.

1.5

Minor release that closes the adoption-feedback backlog: a codex advisories channel, jaunt migrate, an orphaned-artifact gate, and clearer status labels. No built module restales on the upgrade.

  • Nothing restales when you upgrade. The advisories prompt instruction lives in backend code, outside the generation fingerprint, so it cannot invalidate a built module. _STUB_FORMAT_VERSION is unchanged, so committed .pyi stubs stay fresh. Upgrade, run jaunt status, and every module reports fresh.
  • jaunt check now blocks on orphaned artifacts. An orphan is a generated module, .pyi stub, or contract battery whose spec no longer exists. check exits 4 and names the fix. On upgrade this fires only if you already have orphans on disk from a deleted or renamed spec. Clear them once with jaunt clean --orphans (preview with --dry-run), or restore the spec. Hand-authored files are never candidates: only files carrying a jaunt provenance header, plus the .contract.json sidecar next to an orphaned module, can be classified.
  • jaunt migrate retires two upgrade chores. It rewrites legacy raise RuntimeError("spec stub") bodies to ... and re-stamps the header so the change costs no model call, and it re-emits .pyi stubs left stale by a past _STUB_FORMAT_VERSION bump. It plans by default and prints what it would change; pass --apply to write. This closes the 1.4.2 caveat where jaunt check stayed red until you ran a full jaunt build.
  • Advisories are additive. Codex ends its final message with any logical issues it noticed while implementing: a spec ambiguity, a spec that contradicts a dependency's documented API, or a suspected bug in code it read. Fresh builds and test runs print them, --json carries an advisories map, and jaunt log replays them. They never touch digests, staleness, or exit codes.
  • The context_stats skills key is renamed. skills_workspace becomes skills_workspace_seeded to say what it measures: the bytes of skill files seeded on disk and available to the agent, not bytes the agent read. The old skills_workspace key stays as a --json alias for this release.
  • Two new status labels. A module the next build resolves through the free re-stamp path now reads stale (re-stamp: free) instead of stale (structural), and a module-origin spec with no artifact yet is flagged newly governed by module scan before you spend anything.
  • Docs and the jaunt init scaffold lead with ... again. 1.4.2 had switched the example stub body to raise NotImplementedError to satisfy strict type checkers; ... reads plainer, never runs, and carries no runtime risk, so it is the default once more. All stub forms still digest identically. If ty or Pyright flags ... under a concrete return annotation, raise NotImplementedError works just as well and switching between the two never restales a module.

1.4.2

Patch release from the fourth adoption-feedback wave. No built module is invalidated and re-emitting stubs makes no model calls — but note the CI caveat: the stub format version changed, so jaunt check reports committed stubs stale (exit 4) until you run jaunt build once and commit the re-emitted .pyi files.

  • importlib.reload() works on governed modules. Re-executing the same magic_module(__name__) call (same file, same line) is now treated as a reload: the prior registration is replaced instead of raising "already called". Reload-dependent test idioms (monkeypatch.setenv + reload) no longer force a module back to decorator style. A second call at a different line in the same module is still an error.
  • Scaffold and docs lead with raise NotImplementedError. Strict type checkers (ty, Pyright) reject a ... body under a concrete return annotation outside stub files. All stub forms digest identically, so switching your existing ... bodies over is free. (1.5 reverted the scaffold default back to ...; the type-checker note still holds, and either form works.)
  • Emitted .pyi stubs are lint-clean. The unused import jaunt is no longer copied from the spec; names inside string annotations ("Chunker | None") resolve like plain ones (from the generated module's imports, including if TYPE_CHECKING: blocks, with an Any fallback for optional-dependency guards); and when ruff is on PATH the emitted stub is formatted with it. You can drop per-file lint exemptions for jaunt stubs.
  • Refreeze no longer blanks tool_version. Re-stamped generated headers (the free path that resolves digest-scheme migrations and gate-equivalent edits) now record the jaunt version that wrote them, preserving provenance.

1.4.1

Patch release: three post-merge review fixes for magic_module. No built module is invalidated.

  • A handwritten helper reached first no longer runs raw stubs. In 1.4.0, if the first external access to a governed module was a handwritten helper (not a spec name), the helper's calls into sibling specs hit the pre-rebind stubs and silently returned stub results (None). Resolution now fires on the first access to any non-dunder attribute.
  • Circular imports are detected exactly. The mid-execution guard now keys on importlib's __spec__._initializing flag, so a circular importer probing the module — even after the last stub is defined — sees plain stubs instead of triggering eager resolution. The 1.4.0 known-limitation window is closed.
  • A stub shadowed by a later real definition is handwritten. The scan now classifies the last top-level def/class per name, matching Python's last-binding-wins semantics. If you relied on an early stub being governed despite a later real redefinition (unlikely), the real definition now wins.
  • Finalize errors exit structurally. A governed module that fails post-import finalize (for example a spec class with a custom metaclass) now reports as a discovery error (exit 2) instead of an uncaught traceback.

1.4.0

jaunt.magic_module(__name__) — module-level magic — becomes the primary authoring style. Nothing about decorator mode changes; the new call is additive.

  • Converting a decorated spec to magic_module is digest-neutral, as long as the stub body form is unchanged. The @jaunt.magic line never entered the digest, and a module-governed spec renders its signature through the same path a decorated one does, so dropping the decorator does not restale the module.
  • Rewriting raise RuntimeError("spec stub") to ... restales once. That older body is not a recognized stub form — in a governed module it would classify as handwritten, not a spec — so its text is part of the current digest. Standardizing on ... during conversion costs one rebuild per module.
  • Module-level kwargs restale their governed specs. A magic_module(prompt=…) default is part of every governed spec's contract, so adding or editing one restales the file, as any contract change should.
  • Eject, don't hand-strip, in a governed module. Removing a @jaunt.contract or @jaunt.magic marker by hand from a still-stub-shaped function inside a magic_module file silently flips that function to module-magic governance — the scan now picks it up. Use jaunt eject, which leaves committed real code that classifies as handwritten, instead of deleting the marker yourself.

1.3.1

Patch release from the second adoption-feedback wave.

  • Migrating inner @jaunt.magic to @jaunt.sig is free. (Corrected in 1.4.2 — this note originally said to budget one rebuild; adopter reports showed the rename resolves through the re-stamp path with zero model calls. jaunt status may label the module stale until the next jaunt build re-stamps it.)

  • [codex] fingerprint_cli_version now defaults to false. Embedding codex --version in the generation fingerprint coupled jaunt check to environments with the codex binary installed: a CI runner without it restaled a byte-identical tree. If you relied on CLI-version churn triggering rebuilds, set it back to true explicitly. Projects that built with the old default will see a one-time stale (fingerprint) on the next build after upgrading.

  • Fingerprint-only staleness is now labeled. status and check report stale (fingerprint) instead of stale (structural) when specs are byte-identical but the generation fingerprint differs, and print a hint when the cause is a missing codex binary with fingerprint_cli_version = true.

  • .pyi stubs no longer contain from __future__ import annotations. The emitter could place a future import mid-file (a syntax error for ruff and ty). Stale stubs re-emit on the next build; no action needed.

1.3.0

Adoption-feedback release: strict config, .pyi stubs, a CI-grade check, and the @jaunt.sig vocabulary.

  • Generated layout for top-level modules changed. A bare module timing under a source root now generates to __generated__/timing.py instead of the old timing/__generated__/__init__.py, which shadowed the module name. Package members (pkg.modpkg/__generated__/mod.py) are unchanged. If you have a top-level-module project, run jaunt clean && jaunt build once to migrate. See Output Locations.
  • Config validation is strict. Unknown sections and keys are now errors (exit 2) with a did-you-mean suggestion. Upgrading can surface a latent typo that was previously ignored and silently left a setting at its default. Fix the reported key. See Strict validation.
  • emit_stubs defaults on. Builds now write a .pyi beside each spec module, and a missing or stale stub marks the module stale. Set [build] emit_stubs = false to opt out. See .pyi stubs.
  • jaunt check gates magic drift. check now fails on an unbuilt or stale @jaunt.magic module, not just contract drift, so it is the single CI gate for both modes. Scope it with --contracts-only or --magic-only. See the CI guide.
  • @jaunt.sig for sealed methods. In a whole-class spec, mark a method @jaunt.sig to seal its signature (exact params, defaults, annotations, and return type enforced). See writing magic specs.
  • Repo-map drift is decoupled from magic freshness. status and check track treedocs.yaml drift separately; --magic-only skips it entirely.

1.2.0

  • The daemon parks green jobs by default. [daemon] auto_commit now defaults to false: a green job becomes a reviewable proposal you land with jaunt jobs land, rather than an automatic commit. This is the one behavior change existing daemon users feel. To restore the pre-1.2 auto-commit-on-green loop, set auto_commit = true. See the Background Daemon guide.

Next: back to CLI.

On this page