Jaunt
Writing Specs

Spec Writing Tips

Practical patterns for getting better output from smaller specs.

You don't "use Jaunt" once. You live in a loop: write spec -> build -> review -> tighten spec -> rebuild.

Vague vs. Precise Docstrings

Bad (vague):

@jaunt.magic()
def parse_user_agent(ua: str) -> dict:
    """Parse a user agent string."""
    raise RuntimeError("spec stub (generated at build time)")

Better (contract):

@jaunt.magic()
def parse_user_agent(ua: str) -> dict[str, str]:
    """
    Parse a user agent string into a small, stable dict.

    Contract:
    - Return keys: "browser", "os".
    - If unknown, use "unknown" (do not raise).
    - Input may be empty or junk; treat as unknown.
    """
    raise RuntimeError("spec stub (generated at build time)")

Use prompt= When The Docstring Isn’t Enough

If a constraint is non-negotiable, say it twice:

@jaunt.magic(prompt="Use only the standard library. Do not import third-party deps.")
def stable_hash(text: str) -> str:
    """Return a stable hex sha256 of UTF-8 text."""
    raise RuntimeError("spec stub (generated at build time)")

Don’t Edit Generated Files

Generated output is disposable. Specs are the product.

If you need a behavior change, change the spec and rebuild so your intent is versioned.

When Not To Use Jaunt

Jaunt is best for glue code and boring-but-correct utilities (parsers, validators, formatters).

Avoid it (for now) for:

  • performance-critical hot paths
  • complex stateful systems with tight invariants
  • code that depends on exact library versions or fragile runtime behavior

Next: Guides.

On this page