.specify/memory/constitution.md
Spec Kit (the specify-cli package and its bundled assets) is a local, offline-capable
developer CLI that bootstraps and operates Spec-Driven Development workflows for AI coding
agents. These principles are derived from the patterns the codebase already enforces. They
are binding on all changes — including the specify bundle subcommand and any future
command group, integration, extension, preset, or workflow.
The codebase follows a strict, registry-driven, layered architecture, and all changes MUST preserve it.
commands/, */_commands.py); business logic lives in plain, importable
modules with no @app.command() decorators. New features MUST keep orchestration logic
testable independently of Typer.MarkdownIntegration, TomlIntegration, YamlIntegration,
SkillsIntegration) and declare the required class attributes (key, config,
registrar_config, and context_file where applicable). Extending IntegrationBase
directly is permitted only when no base class fits, and the deviation MUST be justified.INTEGRATION_REGISTRY via _register_builtins()), with imports and registrations
kept in alphabetical order. Duplicate keys MUST fail loudly rather than silently override._-prefixed and MUST
NOT be imported across package boundaries. Every new module begins with
from __future__ import annotations and uses modern type syntax (dict[str, Any],
str | None); legacy Dict/List/Optional forms are rejected.kiro_cli/, key = "kiro-cli"). For CLI-backed integrations the key MUST
match the executable name so shutil.which(key) resolves.Rationale: A registry-plus-base-class architecture is what lets dozens of integrations, extensions, and workflows coexist with minimal coupling. Drift here multiplies maintenance cost and breaks the "add one subclass, register once, ship a test" contract.
Every behavioral change MUST be accompanied by automated tests, and the suite is a hard gate.
pytest across a matrix of ubuntu + windows × Python 3.11,
3.12, and 3.13. Changes MUST pass on every cell of that matrix.CommandRegistrar config entry where required, and ship a dedicated
tests/integrations/test_integration_<key>.py (hyphens in the key become underscores in the
filename). These are enforced by parametrized tests (e.g. test_registry.py) and MUST NOT
be weakened.test_* / Test*
naming the project configures, run under --strict-markers, and isolate state with
tmp_path, monkeypatch, and the autouse auth-isolation fixture. Platform-specific tests
MUST be guarded (e.g. @requires_bash) rather than left to fail.Rationale: The breadth of supported agents and the offline/air-gapped guarantees can only be sustained by exhaustive, parametrized tests. The parity and security suites are what stop a single new integration from regressing the whole matrix.
The CLI presents one coherent surface; every command group MUST feel like the others.
list, add/install, remove, search, info, update, plus enable/disable and
set-priority where relevant. New verbs MUST NOT be invented when an existing one fits, and
any genuinely new verb MUST be justified.<group> catalog list|add|remove, back it with a priority-ordered source stack (lower number
= higher precedence) plus per-source install policy (install-allowed vs discovery-only),
and fall back to a built-in default stack when no project config is present.typer.Typer(...) instances
attached via app.add_typer(child, name="..."), preferably through a modular
register(app) function imported in __init__.py. Nesting MUST stay within ~2–3 levels.[green]✓[/green] success, [red]Error:[/red] + non-zero exit on
failure, actionable remediation in messages). Where a --json flag is offered, valid JSON
goes to stdout and all other logging is redirected to stderr.docs/reference/.Rationale: Predictability is the product. Users learn one set of verbs, one catalog model,
and one output grammar, then apply them to every group — including specify bundle.
Spec Kit is a local CLI; responsiveness, offline operability, and graceful degradation are the performance contract.
specify init and core scaffolding MUST work fully offline using bundled core_pack
assets. Asset resolution MUST prefer bundled assets, then a source checkout, before ever
reaching the network.--help) stay fast.Rationale: Developers run this tool in air-gapped, enterprise, and flaky-network environments. Offline-first behavior and idempotent, hash-tracked file operations are what make it safe and fast to run repeatedly.
The project guards its dependency surface and its on-disk footprint deliberately.
Path.relative_to checks) and reject traversal
payloads; symlink escapes MUST be refused.raise ... from exc to preserve causes. I/O
that can legitimately fail MUST degrade gracefully rather than emit a raw traceback.Rationale: A lean, pinned dependency set and hardened, idempotent file handling are what keep the tool trustworthy in enterprise and air-gapped contexts and cheap to maintain.
.editorconfig rules (LF endings, final newline, no trailing
whitespace, 4-space Python / 2-space YAML-JSON-Markdown), ruff check src/, and
markdownlint-cli2 MUST pass.<type>/<number>-<short-slug> (or <type>/<short-slug> with no
issue), with <type> ∈ {feat, fix, docs, community, chore}.ruff, pytest (full matrix), markdown lint, and CodeQL;
add/extend tests for new behavior; update user-facing docs (README.md, docs/,
spec-driven.md) when behavior changes; and disclose any AI assistance used.This constitution supersedes ad-hoc convention where they conflict; the existing codebase patterns it codifies remain authoritative references.
## Constitution Check section of the
plan template MUST be evaluated against these principles, and /speckit.analyze treats
conflicts with a MUST as CRITICAL. Violations are resolved by changing the spec, plan, or
tasks — not by diluting a principle.Version: 1.0.0 | Ratified: 2026-06-19 | Last Amended: 2026-06-19