Skip to main content

日本語 | 中文 | Español | Français | हिन्दी | Italiano | Português (BR)

prompt-craft

CI MIT License Python 3.11+

Say what the picture must contain. Check that it does. Refuse when it doesn't.

A generative image pipeline will happily hand you a hero with the wrong face, the wrong palette and none of the faction's markings — and report success, because nothing looked. prompt-craft replaces the opaque prose prompt with a typed contract of depictable claims, uses that same list twice — once to write the prompt, once to check the pixels — and blocks the asset when a required claim is not there.

   CONTRACT  ──atoms──▶  SYNTHESIZE  ──prompt──▶  GENERATE
   typed, depictable     every token traces      diffusion + control
        │                to an atom                     │
        │ the same atoms                                │ pixels
        └──────────────────────▶  GATE  ◀───────────────┘
                    a DIFFERENT model family checks the
                    contract against the image, cheapest
                    tier deciding first
                         │                    │
                       PASS                FAIL / UNCERTAIN
                         ▼                    ▼
                    BIND to canon      REPAIR ladder, or a
                  (only when every     human checkpoint when
                   required atom       the gate is unsure
                   actually passed)

The one idea: the contract's atom list is the same list used twice. Writing the prompt and checking the result read from one source, so the thing you asked for is the thing that gets verified. That is what closes the loop an opaque prompt leaves open.

Install

pip install prompt-crafter
pcraft --help
npm install -g @mcptoolshop/prompt-crafter   # the same command, as a launcher

The distribution is prompt-crafter because pcraft and prompt-craft are both taken on PyPI; the import package and the command stay pcraft. The npm package is a launcher, not a port — reimplementing a threshold in a second language is how a threshold drifts, so it forwards to the Python that holds the truth and inherits its exit code.

For development:

pip install -e ".[dev]"

The core is GPU-free and runs anywhere — the whole test suite executes against a mock generator and verifier, which is what proves the plugin boundary actually holds. The [image] extra (torch/diffusers) and [synth] extra (DSPy + a hosted LM) wire the real generator, verifiers and synthesizer. Neither is needed to run, test, or evaluate the core.

pcraft demo              # the whole loop end-to-end, no GPU, deterministic stubs
pcraft gate <image>      # check an image against a contract
pcraft replay <record>   # re-read a bound asset's provenance receipt

What a contract looks like

Not a prose prompt. A list of atomic, depictable, individually checkable claims:

  • must_have — a garment, a palette, a silhouette, a sigil. Each carries a check_type (which gate tier verifies it), a severity, and optionally a depends_on edge so a claim is only meaningful when its parent passed. There is no point verifying the colour of an axe that is not there.
  • must_not — anti-constraints, verified as absence on the pixels. Not a negative prompt: negative prompts leave residual features and fall to paraphrase.
  • identity_ref — a reference plate. Identity is conditioning, not tokens. Anatomical text makes a diffusion model render a specimen; a reference image binds the specific face.

Contracts inherit — a character extends a faction — and inheritance is fail-closed: a child may raise a requirement, never relax or silently drop one it inherited.

The gate

Three tiers, cheapest deciding first, escalating only when a cheap answer is unclear. A dependency-ordered pass means a failed parent marks its children N/A rather than scoring nonsense.

The verifier is always a different model family from the generator, enforced by a guard that refuses to run otherwise. A model is a poor judge of its own output, and that is the least speculative part of this design.

Exit codes distinguish four different things, because a caller reading one number needs to tell them apart:

exit meaning
0 the gate ran and every required atom passed
1 bad arguments or a malformed contract
2 it ran, and a required atom failed
3 it ran, and the result is unconfirmed — the human band
4 it could not run — no readable input, or no required tier available

That last row is the one that matters. "I could not check" and "I checked and it is bad" are different facts, and collapsing them is a documented source of real harm — it is why browsers soft-fail certificate revocation, and why monitoring standards have carried a distinct unknown verdict since the 1990s. Every gate transcript also reports how many required tiers actually executed, independently of the verdict, so a gate that quietly stopped checking cannot read as a pass.

CLIPScore is not used as the gate metric. It behaves as a bag of concepts — blind to which attribute belongs to which object, to counts, and to relations. It is documented as known-broken in the verifier interface so nobody reintroduces it.

Honest status

v0.2.0 — the core is real; the GPU path has never run here.

Core 105 tests passing, GPU-free, deterministic. verify runs the suite, the suite again under -O, and a package build
Predicates the eleven compound decision points in core/ are mutation-tested — 20 of 21 mutants killed, and the survivor is named rather than hidden
Coverage 81% overall; GPU-bound generator and verifier adapters are the untested remainder
The [image] path never executed on this machine. bind --no-mock refuses with a missing-dependency error. Everything below the plugin boundary is unproven by measurement
Thresholds the sprite sub-gate's floor and variance limits are hardcoded defaults with no recorded calibration — no holdout, no citation. Treat them as placeholders
Real canon the shipped example contract is a generic invention, not any real project's canon. Binding real canon is a deliberate, human decision

Two claims that earlier versions of this document made and that measurement did not support, corrected here rather than quietly dropped:

  • The three-zone thresholds were described as calibrated against a human-labelled holdout. They are not. They are defaults.
  • The rule that a generative model is never its own gate was stated as though a study had established it. The supporting evidence is convergent rather than direct — discriminative yes/no polling is measurably more stable than open-ended captioning, models cannot reliably self-correct without external feedback, and self-recognition tracks self-preference bias. No single study runs the head-to-head. The rule is sound; the certainty was overstated.

Requirements

Python 3.11+ (CI runs 3.13)
Platforms pure Python, no compiled extensions in the core — developed on Windows 11, CI on ubuntu-latest
Dependencies the core needs only pydantic. GPU work lives behind optional extras

Trust and threat model

  • Data touched — contract JSON you point it at, the images you pass it, and provenance records written under the directory you name. Nothing else is read.
  • Data NOT touched — no credentials of any kind are read, stored or transmitted. No telemetry, analytics or usage counting: there is no opt-out because there is nothing to opt out of. The core imports no networking library at all.
  • Network egress — none from the core. The optional [image] and [synth] extras reach a model host by their nature; that is the only network path, and installing them is a choice.
  • Permissions — ordinary user permissions. No elevation, no service installation, no registry or system-settings writes.
  • The sharp edge, disclosed rather than claimed awayfile operations are not sandboxed. --records-dir and --db write wherever you point them, deliberately, because this is a local-first tool. Point them somewhere you intend.
  • Errors — deliberate refusals carry a code, a message and a hint, and raise rather than assert, so -O cannot delete them; the suite runs a second time under -O to prove it. Unexpected failures print a traceback only under --debug.

Support status

main is the only supported state. No release channel, no backport policy, no SLA. This is studio infrastructure published in the open, not a product with a support contract.

How the pieces are arranged

core/ is domain-agnostic and imports zero diffusion or torch symbols — a domain plugin exports exactly three things: a generator, a list of verifiers, and an encoder ruleset. Adding a new domain is a new sibling under domains/; nothing in core/ changes. The GPU-free suite is what keeps that claim honest.

src/pcraft/
  core/          contract · loop · gate · synth · optimize · receipt   (GPU-free)
  cli/           pcraft: synth | gate | bind | demo | replay | compile | sync-rules
  domains/       ── PLUGIN BOUNDARY ──
    image/       generators, the three verifier tiers, encoder rules, sprite subdomain

Encoder rules under domains/image/rules/ are generated from a verified recipe database, not hand-written, and carry a generation header. Every bound asset writes a replayable provenance receipt pinning the contract hash, the synthesizer artifact, the generator and seed, the verifier version, and the full per-atom gate transcript.

Design rationale, the standards this repo scores itself against, and the named undo for every irreversible action live in STANDARDS.md and COMPENSATORS.md.

License

MIT — see LICENSE. The licence of any model used through this tool is a separate question and is not covered by it.

Download files

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

Source Distribution

prompt_crafter-0.2.0.tar.gz (520.9 kB view details)

Uploaded Source

Built Distribution

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

prompt_crafter-0.2.0-py3-none-any.whl (167.4 kB view details)

Uploaded Python 3

File details

Details for the file prompt_crafter-0.2.0.tar.gz.

File metadata

  • Download URL: prompt_crafter-0.2.0.tar.gz
  • Upload date:
  • Size: 520.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for prompt_crafter-0.2.0.tar.gz
Algorithm Hash digest
SHA256 dc07ffc75a1fc4fe7ce1309acac68a8feddb8ecb4bbe211342f9468a713246ff
MD5 0704698c5cecb597265aab947912bcdb
BLAKE2b-256 6aea91d82ebefc22ca917bd3ae09e0a00053a78a757454ed75ae408267792434

See more details on using hashes here.

Provenance

The following attestation bundles were made for prompt_crafter-0.2.0.tar.gz:

Publisher: release.yml on mcp-tool-shop-org/prompt-craft

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file prompt_crafter-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: prompt_crafter-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 167.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for prompt_crafter-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 21a7789723584f415188b073cfacf43865135ea9d4c7f7d41d02c25403d50137
MD5 1dbcef7ed3665464f413fb97a67b1494
BLAKE2b-256 897a1faa0303b62cea392401027f8c78bb9f89b3ccc3fa8ce7d7c601c5e170c5

See more details on using hashes here.

Provenance

The following attestation bundles were made for prompt_crafter-0.2.0-py3-none-any.whl:

Publisher: release.yml on mcp-tool-shop-org/prompt-craft

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

0.4.0

2 files

0.3.0

2 files

0.2.1

2 files

This release

0.2.0 This release

2 files

Supported by

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