Skip to main content

libspec

CI/CD Documentation PyPI version Python versions License

an ounce of spec is worth a pound of tokens

libspec is a Specification Management System in Python. Similar in spirit to object-relation mapping (ORM), libspec uses an Object Specification Mapping to compile logical requirements into structured database snapshots. Instead of generating SQL, it tracks how requirements evolve over time.

By diff'ing snapshots and using a Model Context Protocol (MCP) server, it provides a centralized context layer for local coding agents to trace specs directly to generated code. The developer workflow is incremental and exploratory, less like gambling and more like delegating.

the general idea

Example Spec

Here is the specification spec/err.py used to establish fundamental code quality, error handling, and robustness constraints across the entire project via multiple inheritance:

from libspec import Ctx, Feature, Requirement


# The Err docstrings are compiled into specification snapshots and 
# injected as prompt context for LLM code generation.
class Err(Ctx):
    """
    It is important that error handling be done excellently.

    If a function can fail, then it needs to do so in the most elegant way
    possible. Error reporting, handling, exceptions and all aspects of failure
    must be taken to extreme. It should be possible to understand the program
    by reading the error messages.

    When an error occurs there should be a story about the failure at each step
    of the way. What went wrong and why.
    """


class BoilerPlate(Ctx):
    """
    If you can see a way to reduce boiler plate, then do it.
    """


class FunctionLines(Ctx):
    """
    Try to keep functions under 20 lines.
    """


class Indentation(Ctx):
    """
    Try to keep indentation under 4 levels.
    """


class PreCondition(Ctx):
    """
    Functions should validate preconditions at their entry point.

    Instead of using `assert` statements (which can be disabled globally),
    raise explicit, descriptive exceptions (e.g., ValueError, TypeError, or
    custom domain exceptions) to robustly reject malformed input.
    """


class GlobalMutableState(Ctx):
    """
    Broadly you should avoid global mutable state.
    """


class PostCondition(Ctx):
    """
    Before a function returns, it should verify postconditions to ensure
    invariant properties hold true.

    Raise explicit, descriptive exceptions (such as RuntimeError or domain
    exceptions) rather than using `assert` statements to handle post-execution
    verification failures.
    """


# Composite specification aggregating precondition, postcondition, and global state avoidance guidelines.
class DefensiveProgramming(PreCondition, PostCondition, GlobalMutableState):
    pass


class Refactor(BoilerPlate, FunctionLines, Indentation):
    """
    Always keep an eye out for ways to generalize a function if it's utility
    might be helpful to other functions.

    Classes should be implemented in their own files with filename being the
    classname with correct naming convention
    """


class Robustness(DefensiveProgramming):
    """
    Always prioritize library-provided constructors for complex objects. Ensure
    all components are fully initialized before calling any state- mutating
    methods. Assume private internal state is uninitialized until the official
    constructor has returned. When extending library components, prioritize
    composition (pointers) over embedding by value to avoid risky state-copying
    bugs.

    Use dependency injection for system level objects for composability and to
    make testing easier.
    """


# Use multiple inheritance to endow Feature and Requirement specs with
# disciplined error handling guidance from above.
class Feat(Err, Refactor, Robustness, Feature):
    pass


class Req(Err, Refactor, Robustness, Requirement):
    pass

The Object Model

Each class declares a specification fragment that is optionally a Jinja2 template string. More about that later...

Inheritance

Inheritance means "does this and more." The inherited superclass docstrings are normative, but the compiled XML preserves them as <inherits><ref>...</ref></inherits> references instead of prepending their prose into the child docstring. Renderers such as libspec diff can expand those refs when a review needs the inherited context.

Mixins

Mixins help get around the diamond problem. (TODO: write more about this)

Versioning

Note that the versioning of libspec is still being hammered out. Currently, the version of libspec appears in the generated XML (libspec-version field). But, how diffs will be performed on different versions is unexplored.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

libspec-10.2.0.tar.gz (88.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

libspec-10.2.0-py3-none-any.whl (80.4 kB view details)

Uploaded Python 3

File details

Details for the file libspec-10.2.0.tar.gz.

File metadata

  • Download URL: libspec-10.2.0.tar.gz
  • Upload date:
  • Size: 88.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.21 {"installer":{"name":"uv","version":"0.11.21","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Debian GNU/Linux","version":"13","id":"trixie","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for libspec-10.2.0.tar.gz
Algorithm Hash digest
SHA256 3fa8f5f4697c1014d25d64c5ebf95b222fd065586501e5230dda016a3f2017c7
MD5 40ffd37a1a1e41d2e421fcceb1378649
BLAKE2b-256 23fc95c8917cbbb6a283086a1f9085e6d8a543c6df84cd050a50fb86ffb96e3a

See more details on using hashes here.

File details

Details for the file libspec-10.2.0-py3-none-any.whl.

File metadata

  • Download URL: libspec-10.2.0-py3-none-any.whl
  • Upload date:
  • Size: 80.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.21 {"installer":{"name":"uv","version":"0.11.21","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Debian GNU/Linux","version":"13","id":"trixie","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for libspec-10.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 38f603de2367b744bb884e6695bf79498aa0cdc832966c7557fbe3fd182594e3
MD5 a7d6b220558ed45e4255e140447431ce
BLAKE2b-256 85d9c22bc82e201b7529e7a8e27dfaa9d48c59afc394221a4874d438c8a0bac7

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page