Skip to main content

Playbook: Adopt SicarioSpec in a Brownfield Repository

Scenario

You maintain a repository that already has governance: a project constitution, Spec Kit templates, and agent-instruction files such as CLAUDE.md. You want SicarioSpec's gate and evidence without losing a line of what you already wrote. This playbook walks the overlay-not-clobber contract end to end: preview with --dry-run, adopt for real, inspect what was merged and what was preserved, confirm the backups can never be committed, and re-run init to see that adoption converges to a no-op.

Intended reader: an engineer adopting SicarioSpec into an existing repository. No prior SicarioSpec experience is assumed beyond having the CLI installed.

Output conventions

Every quoted output block in this playbook carries a machine-readable marker declaring it verified or illustrative:

  • verified — captured from the reference run named in this page's front matter and re-executable as-is. The only rewrites applied are the documented normalizations listed in the marker: paths (the reference-run directory is shown as ~/refrun-rules/brownfield-app, and the SicarioSpec install location as <install-root>).
  • illustrative — representative of the shape you will see, visibly labeled as such, used where output contains environment-dependent values (absolute paths, backup timestamps, your specify version).

Every step in this playbook is a terminal interaction, captured as text per the terminal-text capture class. No step surfaces a graphical view, so this playbook carries no screenshots (stated per the visual-asset policy).

Prerequisites and starting state

  • Python 3.9+ and SicarioSpec 0.6.0. Commands below use the module form python3 -m sicario_cli.cli, which works on every install; if the sicario command is on your PATH, sicario init / sicario verify are equivalent.
  • git, and a POSIX shell (bash or zsh) on macOS or Linux. On Windows, use WSL; native path separators and prompts will differ.

The starting state is a git repository with pre-existing governance. To reconstruct it exactly, the reference run seeded a repository containing README.md, src/app.py, a .gitignore (__pycache__/, *.pyc), and these three governance files, all committed:

.specify/memory/constitution.md — the project's own constitution:

# payments-api Constitution

## Principle I — Boring Technology
We choose proven components over novel ones.

## Principle II — Reviewed Changes
Every change lands through a reviewed pull request.

.specify/templates/spec-template.md — the project's own minimal template:

# Feature Spec: [NAME]

## Problem

## Approach

## Rollout

and CLAUDE.md — agent instructions:

Prefer small, reviewable diffs. Never commit generated artifacts.

The remaining seed files (their content is not asserted by anything below):

printf '# payments-api\n' > README.md
mkdir -p src
printf 'def main():\n pass\n' > src/app.py
printf '__pycache__/\n*.pyc\n' > .gitignore

Steps

1. Preview the adoption with --dry-run

Always preview first. The dry run detects your existing governance, chooses a per-file plan, and writes nothing.

python3 -m sicario_cli.cli init . --profile public-core --dry-run

Illustrative output — excerpted; absolute paths and your specify version vary by environment.

Illustrative output (representative, not exact)
target ~/refrun-rules/brownfield-app
specify specify 0.11.8
integration claude
presets sicario-core, sicario-docs
detected existing governance: constitution=['.specify/memory/constitution.md']; templates=['.specify/templates/spec-template.md']; instructions=['CLAUDE.md']
mode: brownfield-safe (merge/overlay/preserve)
append ignore rule *.sicario-bak.* to ~/refrun-rules/brownfield-app/.gitignore
copy <install-root>/presets/sicario-core -> ~/refrun-rules/brownfield-app/.specify/presets/sicario-core
...
overlay ~/refrun-rules/brownfield-app/.specify/memory/constitution.md

SicarioSpec adoption report (dry-run preview — nothing written)
---------------------------------------------------------------
[merged-overlaid] ~/refrun-rules/brownfield-app/.gitignore — appended ignore rule *.sicario-bak.*
[created] ~/refrun-rules/brownfield-app/.specify/presets/sicario-core
[merged-overlaid] ~/refrun-rules/brownfield-app/.specify/templates/spec-template.md — appended overlay
[merged-overlaid] ~/refrun-rules/brownfield-app/.specify/memory/constitution.md — appended overlay
[merged-overlaid] ~/refrun-rules/brownfield-app/CLAUDE.md — appended overlay
...
summary: 33 created, 4 merged-overlaid
dry-run complete; no files written

Read the plan through the three per-file states:

  • created — the file does not exist in your repository; SicarioSpec will write it new. Nothing of yours is involved.
  • merged-overlaid — the file exists and SicarioSpec knows how to extend it additively: your content stays verbatim, a clearly delimited overlay block is appended, and a backup is taken first.
  • preserved — the file exists and SicarioSpec cannot safely merge it, so it is left untouched and reported. (You will see this state on re-runs in step 5; --force is the explicit opt-in to full overwrite instead, and it still takes backups first.)

Note the detection line: your constitution, your template, and CLAUDE.md were all found, and the mode switched to brownfield-safe (merge/overlay/preserve). In an empty directory the same command reports mode: greenfield (no existing governance detected).

2. Adopt for real

python3 -m sicario_cli.cli init . --profile public-core

Illustrative output — final lines shown; the full report matches the dry-run plan.

Illustrative output (representative, not exact)
summary: 33 created, 4 merged-overlaid
SicarioSpec initialized at ~/refrun-rules/brownfield-app
Next: cd into the project and run `sicario verify`.

3. Inspect the overlay: your content is untouched above the markers

sed -n '1,16p' .specify/memory/constitution.md
Verified output
# payments-api Constitution

## Principle I — Boring Technology
We choose proven components over novel ones.

## Principle II — Reviewed Changes
Every change lands through a reviewed pull request.

<!-- BEGIN SICARIO-SPEC OVERLAY (additive; do not edit by hand) -->

## SicarioSpec Governance Overlay (Additive)

This section was appended by `sicario init`/`apply` as an ADDITIVE governance
overlay. Your existing constitution above is unchanged and remains authoritative.

This overlay is SUBORDINATE to the existing principles above and to `CLAUDE.md`. Where any conflict exists, the project's own principles and `mission.md` (or equivalent project-supremacy clause) WIN.

Your constitution is byte-for-byte intact above the BEGIN SICARIO-SPEC OVERLAY marker, and the overlay itself states that it is subordinate to your existing principles and to the instruction files it detected (CLAUDE.md here). The overlay ends with an <!-- END SICARIO-SPEC OVERLAY --> marker:

grep -n "SICARIO-SPEC OVERLAY" .specify/memory/constitution.md
Verified output
9:<!-- BEGIN SICARIO-SPEC OVERLAY (additive; do not edit by hand) -->
39:<!-- END SICARIO-SPEC OVERLAY -->

The same marker pair delimits the overlays appended to CLAUDE.md and .specify/templates/spec-template.md — run the same grep -n against each to see them.

4. Backups exist — and cannot be committed

Every merged file was backed up first, as a timestamped sibling:

ls .specify/memory/

Illustrative output — the UTC timestamp in the backup name is taken at run time.

Illustrative output (representative, not exact)
constitution.md
constitution.md.sicario-bak.20260728T204506Z

Backups are verbatim copies of your pre-existing files, which may contain things that were never meant to be committed. So before the first backup was taken, init appended an ignore rule to your .gitignore (your existing entries untouched):

cat .gitignore
Verified output
__pycache__/
*.pyc

# SicarioSpec timestamped backups (may contain pre-existing secrets)
*.sicario-bak.*

Confirm git actually ignores them — git check-ignore -v names the deciding rule, and no backup appears in git status:

git check-ignore -v .specify/memory/constitution.md.sicario-bak.*
git status --short | grep sicario-bak

Illustrative output — timestamped file name varies; the second command prints nothing (and exits 1) because no backup is unignored.

Illustrative output (representative, not exact)
.gitignore:5:*.sicario-bak.* .specify/memory/constitution.md.sicario-bak.20260728T204506Z

init is careful here: if your .gitignore already contains the rule it is left alone, and if a later negation (!something.sicario-bak...) re-includes backups, the rule is re-appended so the last matching pattern wins again.

5. Re-run to confirm adoption converges

Run the same init command again:

python3 -m sicario_cli.cli init . --profile public-core

Illustrative output — summary lines shown.

Illustrative output (representative, not exact)
gitignore already ignores *.sicario-bak.*
overlay already present in ~/refrun-rules/brownfield-app/.specify/templates/spec-template.md
...
summary: 2 merged-overlaid, 35 preserved

Nothing you own is touched again: files with the overlay marker report overlay already present, directories report skip existing, and generated files report preserve existing. One wrinkle, reported honestly because the reference run observed it: the second run appends the overlay marker block to plan-template.md and tasks-template.md — the two templates the first run created without markers — which is why this run still shows 2 merged-overlaid. From the second run onward the state is stable; a third run is a pure no-op:

Illustrative output — third run's summary line.

Illustrative output (representative, not exact)
summary: 37 preserved

No new backups are taken on a converged re-run.

6. Run the gate

python3 -m sicario_cli.cli verify .
Verified output
sicario verify passed

Exit code 0. The adopted repository passes because init created every document the shipped rules require (threat model, risk registers, data classification, control maps, and the rest) while preserving yours.

Success check

You are done when all of the following hold:

  1. python3 -m sicario_cli.cli verify . prints sicario verify passed and exits 0.
  2. git diff on .specify/memory/constitution.md, CLAUDE.md, and .specify/templates/spec-template.md shows only appended SICARIO-SPEC OVERLAY blocks (plus the .gitignore rule) — none of your original lines changed.
  3. git status --short | grep sicario-bak prints nothing: every backup exists on disk but is uncommittable.
  4. Re-running init reports preserved / overlay already present rather than taking new backups.

Further reading