Skip to content

Repository Scripts

Python 3.11+ command-line utilities that validate repository structure and create new ventures/products from templates. All scripts use only the Python standard library — no external dependencies are required to run them, except the gimp_*.py brand-asset tools below, which are the one deliberate exception (see Brand-asset tools).

Validation scripts

Run all of them at once with:

python scripts/check.py
Script Purpose
check.py Runs every validator below in a predictable order; nonzero exit on any failure.
validate_repository.py Checks required root files, directories, entry points, templates, ADRs, and scans for filler text or duplicate IDs.
validate_links.py Checks relative Markdown links resolve to real files/directories.
validate_metadata.py Checks YAML front matter on authoritative Markdown documents against the metadata standard.
validate_registries.py Checks JSON syntax and required fields in portfolio/*.json and venture/product/component JSON records.

Creation scripts

Script Purpose
create_venture.py Scaffolds a new venture from ventures/_template/.
create_product.py Retired 2026-07-27 (see ADR-0017) — its template source, ventures/<slug>/products/_template/, no longer exists in any venture. Kept for its test coverage/history, not for use; a product is now created entirely in its venture's implementation repository.
create_implementation_repository.py Scaffolds a new venture implementation repository from templates/implementation-repository/, per ADR-0014. Writes outside this repository; does not run git init or create a remote.

All three refuse to overwrite existing paths, reject unsafe slugs, and only update a registry file when explicitly asked with a flag. Run any of them with --help for full usage.

Brand-asset tools

Script Purpose
_gimp_common.py Shared helper: locates a gimp-console executable and runs a Python-Fu script in headless GIMP 3, returning its stdout. Not a CLI itself.
gimp_trace_mark.py Crops a region of a raster image, selects a color, and traces it to a vector-path SVG (plug-in-sel2path).
gimp_render_svg.py Rasterizes an SVG to a transparent PNG at a given width/height, via GIMP's librsvg-backed SVG loader.
gimp_compose_badge.py Composites a mark SVG onto a solid-color rectangle (e.g. a favicon-style navy square with a centered white mark).

Run any of them with --help for full usage. All three formalize the ad hoc GIMP batch scripting used to produce Devonshire Digital LLC's candidate "D" mark (see docs/company/brand-assets.md and the corresponding entry under work/), so the same steps can be re-run for future brand assets (e.g. Devonside Labs') without re-deriving the GIMP 3 Python API from scratch.

Dependency note (per ../docs/standards/dependency-and-tooling-standard.md): these three scripts require GIMP 3 to be installed locally (they shell out to gimp-console; no Python package is added). This is a minor, easily-reversible tooling dependency — scoped to brand-asset production, not to validation or scaffolding — so it's justified here rather than via a separate ADR. _gimp_common.find_gimp_console() checks the GIMP_CONSOLE environment variable, then PATH, then common Windows install locations; set GIMP_CONSOLE explicitly if GIMP is installed somewhere nonstandard.

GIMP 3's gimp-console does not reliably self-terminate after a batch script finishes (observed on Windows even without the -i interactive flag and with stdin closed). _gimp_common.run_gimp_python() works around this by streaming output for a completion sentinel and then killing the process itself, rather than waiting for it to exit on its own — do not replace this with a plain subprocess.run(...) call, which would block for the full timeout on every invocation.

gimp_compose_badge.py's default centering only works for a square (1:1) mark SVG. Its no-args default requests a square --mark-size (60% of canvas height, both dimensions equal) and centers assuming that full square gets filled. For a non-square mark (e.g. b3-mark-white.svg's 885:758 viewBox), GIMP's keep-ratio loader letterboxes the actual content inside that square — the rendered ink ends up smaller than requested and off-center (observed: top-anchored, leaving a big gap at the bottom) — which is exactly the "too small and shifted north" defect found and fixed in the B3 badge (see ventures/digital-products/docs/brand-assets.md's 2026-07-17 entry). For any non-square mark, don't rely on the defaults: render the mark once at a size where width/height are left to auto-match its true aspect (e.g. via gimp_render_svg.py --height N), measure that PNG's transparent-pixel bounding box to get the content's real margin fractions within its own render box, then solve for an explicit --mark-size/--offset pair that lands the rendered ink (not the nominal box) centered on the target canvas.

Finding GIMP/Inkscape on this machine: neither installer adds itself to PATH, so where gimp, where inkscape, or shutil.which(...) will report nothing even when both are installed — that is not evidence they're missing. Confirm the real state by running python scripts/_gimp_common.py directly (it prints the resolved gimp-console path and GIMP's version) or by checking the paths below, before concluding a render step needs to be skipped:

  • GIMP 3.2: C:\Program Files\GIMP 3\bin\gimp-console-3.2.exe (this is exactly _gimp_common._CANDIDATE_WINDOWS_GLOBS[0], so find_gimp_console() resolves it with no extra configuration).
  • Inkscape: C:\Program Files\Inkscape\bin\inkscape.exe. No script here drives Inkscape (it's the Founder's interactive editor of choice for master/export SVGs); its path is noted here only so a future automation need doesn't start from "is it even installed?".

Conventions

  • Exit code 0 means success; any nonzero exit code means at least one check failed. check.py prints a summary of which validator failed.
  • Scripts avoid network access and avoid mutating files outside the paths the user explicitly requested.
  • See ../tests/README.md for how these scripts are tested.

Report an issue about this page