← spectastic Examples
Worked example · architectural guardrails · engineering governance

Priya's PR

An agent-authored PR adds a nightly job that writes to the positions table directly — bypassing the adapter that emits the audit events. The code is clean, the tests pass, a reviewer new to the team approves it. A two-year-old ADR forbade exactly this; its author had left; nobody current remembered. The ADR was in the repository. It was never surfaced. This example records that decision as data — scope, enforcement, posture, reason — and lets the guardrail, not anyone's memory, catch the PR: once at design, once at merge, with no model on the verdict path.1

1That is the point of spec-driven development, and of spectastic in particular: a decision is an artifact — written once, in the design that made it, with a stable id — and everything downstream references it rather than re-deriving it. Remembering is a human skill; referencing is a tool's. ADR-0007 isn't a memo in a wiki; it is 002-downstream-consumers/D-007, addressable by coordinate from the spec, the plan, the verdict, and the reviewer.

Architectural guardrails Java · hexagonal Killed twice Full lifecycle · real build · CI gate No model on the verdict Standard profile Owner-aware
▷  Show me Read the decision →
Why it's a governance problem, not a review problem

The scenario is Theo Valmis's, from Architectural Guardrails for AI-Generated Code. He names the failure architectural drift — code that individually looks fine but collectively pulls the codebase away from where the team agreed it should go — and makes two claims that bite. First, an instruction file like CLAUDE.md is the right instinct at the wrong resolution: free text with no precedence, no lifecycle, no enforcement. Second, a second model reviewing the PR cannot fix this, because it shares the first model's blind spot — “two probabilistic passes over the same blind spot are not one deterministic pass with sight.” What's needed is a decision that is retrievable by path, injected before writing, and enforced by a script — not an agent, not retrieval-as-verdict, not AI-reviews-AI. spectastic's own principle P-8 says the same thing: guarantees live in the kernel or CI.

The distance

A securities position keeper — seven features, scaffolded by spectastic init --profile standard and driven through the whole lifecycle — spec → design → tasks → implement → verify — onto a real two-service Gradle build. The decision that matters was born in feature 2 as the answer to a requirement, not as governance ceremony: what guarantees every position change emits an event? Then five features and two and a half years go by without anyone mentioning it.

05 Feb 2024 · 001-position-core
Ports-and-adapters; a JDK-only domain. Positions are idempotent on tradeId.
11 Mar 2024 · 002-downstream-consumers
ADR-0007 is written. Risk and P&L need a PositionChanged event on every move, so FR-004 requires a single emitter — and the design records D-007: only the persistence adapter touches the data store. An ArchUnit fitness function ships with it; a DB grant (D-008) is the operational backstop.
20 May 2024 · 003-jdbc-persistence
Real SQL arrives. ADR-0007 is amended with a Semgrep content rule for the case a type-graph rule can't see.
Three merges that never mention it — 004-query-endpoint (Aug 2024) · 005-instrument-refdata (Nov 2024) · 006-health-check (Feb 2025). The author moves on.
13 Sep 2026 · 007-reconciliation
“Add a nightly job that corrects positions from the custodian file.” The naive implementation writes corrected quantities straight into positions — fast, clean, and exactly what ADR-0007 forbids. This is the request that tests whether the guardrail still holds.

The 2024–25 dates are narrated (docs/timeline.md); the build-out is real git history — every bundle, the Gradle build, the CI gate and every command output are committed.

The decision — recorded as data

A Nygard card with prose Context / Decision / Consequences is a decision log. What makes it a governance record is the structured half: a scope a tool can retrieve by, a posture that says block or warn, enforcement rule-ids that join a detector's finding back to the decision, and a reason that lives once — here — and is never re-typed into the enforcer's own message channel, where it would drift. And, since the amendment below, a resource: the store the decision governs, by coordinate, and the one project that owns it.

block

D-007 · ADR-0007 — only the persistence adapter touches the data store

Grounding
· KB-0001@2026-09-13
Status
accepted · review by 2027-03-11
Scope
src/**/persistence/**
xyz.briancorbin.pk.hex.persistence..
Resource
spectastic://briancorbin/position-keeper-guardrails/datastore/positions
owner briancorbin/position-keeper-guardrails · direct writes allowed in src/**/persistence/**
Enforcement
archunit only_the_persistence_adapter_touches_data_access_apissemgrep no_sql_write_to_positions_outside_adapter
Reason
Every position change must emit PositionChanged so Risk, P&L, and the audit trail stay consistent; a direct write to the position store bypasses the emission and the audit hooks that live in the adapter.
Decision
Only xyz.briancorbin.pk.hex.persistence may reach the data-access APIs or write the positions store.
warn

D-008 · DB-grant backstop for the positions table

Grounding
Status
accepted
Scope
db/**
Enforcement
none, with reason — a database GRANT restricts writes on positions to the adapter's role. Operational; no static check exists, so it is recorded as unenforceable rather than pretended.
Reason
Even if a static rule is evaded, the database itself refuses a write to positions from any role but the adapter's.

Two accepted decisions, one honest gap. D-008 carries no executable check and says so — which is what lets the coverage report count it as excused rather than silently uncovered.

specs/002-downstream-consumers/design.html — the record as authored
<spec-decision id="D-007" grounding="verified" status="accepted" posture="block" review-by="2027-03-11"> <spec-scope> <spec-path>src/**/persistence/**</spec-path> <spec-module>xyz.briancorbin.pk.hex.persistence..</spec-module> <spec-resource coordinate="spectastic://briancorbin/position-keeper-guardrails/datastore/positions" owner="briancorbin/position-keeper-guardrails" allowed-in="src/**/persistence/**"></spec-resource> </spec-scope> <spec-enforcement> <spec-rule tool="archunit" id="only_the_persistence_adapter_touches_data_access_apis" run="./gradlew test --tests *DataAccessRulesTest"></spec-rule> <spec-rule tool="semgrep" id="no_sql_write_to_positions_outside_adapter" pattern="UPDATE\s+positions" allowed-in="src/**/persistence/**"></spec-rule> </spec-enforcement> <spec-reason>Every position change must emit PositionChanged so Risk, P&L, and the audit trail stay consistent; a direct write to the position store bypasses the emission and the audit hooks that live in the adapter.</spec-reason> <h4>D-007 · ADR-0007 — only the persistence adapter touches the data store</h4> <p>…Context / Decision / Consequences prose, as any Nygard card…</p> </spec-decision>

→ A decision-well-formed rule in spectastic validate rejects an illegal status or posture, an accepted blocking decision with no scope, and an enforcement that is neither ≥1 rule nor exactly one none with a reason. Absent metadata leaves an older card exactly as it was. A sibling rule, resource-scope-well-formed, rejects a malformed coordinate, an ill-formed owner, or an owner that disagrees with the coordinate's own authority. The decision is addressable: spectastic://briancorbin/position-keeper-guardrails/decision/002-downstream-consumers/D-007.

Show me

The same reconciliation request, routed four ways. Pick a route and watch which stage the change reaches — and where it dies. The outputs are the real commands' real output against the committed repo.

Route the change

adrs --for
retrieve · aid
validate
design gate
verdict
merge gate
--explain --teach
teach · advisory

Two gates, one aid. Retrieval and injection help the agent get it right; the design constraint and the merge verdict are the guarantee — scripts that run and stop, reconstructable from disk, with no model anywhere on the path. The gate's answer is identical whether or not the agent read what was injected.

Killed twice

The layer is six stages — author → register → retrieve → inject → gate → teach — and the PR dies at two independent points. Both are deterministic. The second one also tells the author exactly why, and where to go instead.

1

Retrieval surfaces the decision — by path, to a log

Before writing, the agent (or the human) asks which decisions govern the paths about to change. The answer is a glob match over every active decision's scope — no embeddings, no ranking, the same paths always return the same decisions — and it writes a retrieval log so the plan's view can be diffed against the merge's.

$ spectastic adrs --for src/main/java/xyz/briancorbin/pk/hex/persistence/CustodianSnapshotReader.java
002-downstream-consumers/D-007  [block]  archunit:only_the_persistence_adapter_touches_data_access_apis, semgrep:no_sql_write_to_positions_outside_adapter
  governs: src/main/java/xyz/briancorbin/pk/hex/persistence/CustodianSnapshotReader.java
Wrote .spectastic/adr-retrieval.json

The same block — id, coordinate, reason — is injected into the design and tasks prompts, fenced as data to account for, never an instruction the tool obeys. It's an aid: an advisory prompt cannot be a guarantee, so nothing downstream assumes it was read.

2

Death at design — the plan constraint

A draft design's project-structure tree is its declared surface. If that surface touches a path governed by an accepted decision from another spec, the design must acknowledge it — by coordinate — or spectastic validate fails at the standard profile and up. spectastic has no diff at design time, only prose; this is a nudge where the PR should die in the happy path, and it binds forward-only (a new decision never retroactively fails the ninety-seven designs that shipped before it).

$ spectastic validate 'specs/**/*.html'  # the 007 design touches src/**/persistence/** and says nothing about D-007
specs/007-reconciliation/design.html
  1:1  error  this plan's surface touches "src/**/persistence/**", governed by decision
             002-downstream-consumers/D-007, which it does not acknowledge  plan-constraint
        → Acknowledge the decision by referencing 002-downstream-consumers/D-007 (its coordinate tail)
           in this design, or narrow the project-structure tree so it does not touch that path.
1 error, 0 warnings
3

Death at merge — the verdict

Skip spec and design entirely; commit PositionReconciliationJob straight to a branch. The merge gate judges the actual diff against the decisions governing it and composes a verdict — {decision, rule, reason, file:line, source → target, cause} — persisted as plain JSON that reconstructs from the changed file and the decision record. Exit 1. The verdict kernel's transitive imports carry zero child-process modules: running a foreign command is not something it can do.

$ spectastic verdict --changed docs/priya-pr/PositionReconciliationJob.java
VIOLATION 002-downstream-consumers/D-007 [no_sql_write_to_positions_outside_adapter] at docs/priya-pr/PositionReconciliationJob.java:20
  docs/priya-pr/PositionReconciliationJob.java → UPDATE\s+positions
  Every position change must emit PositionChanged so Risk, P&L, and the audit trail stay consistent; a direct
  write to the position store bypasses the emission and the audit hooks that live in the adapter.
Scope: repo-local — evaluated 2 decisions from this checkout. A decision not present in this checkout is not evaluated.
Wrote .spectastic/verdict.json
exit 1
.spectastic/verdict.json — the artifact any CI or any tool's hook can read
{ "at": "2026-09-13T20:25:32.587Z", "scope": "repo-local", "decisionsEvaluated": 2, "changed": ["docs/priya-pr/PositionReconciliationJob.java"], "violations": [{ "decisionId": "D-007", "specId": "002-downstream-consumers", "ruleId": "no_sql_write_to_positions_outside_adapter", "reason": "Every position change must emit PositionChanged so Risk, P&L, and the audit trail stay consistent; …", "file": "docs/priya-pr/PositionReconciliationJob.java", "line": 20, "detector": "content", "cause": "path", "source": "docs/priya-pr/PositionReconciliationJob.java", "target": "UPDATE\\s+positions" }] }
4

A failure teaches — the explanation, then one question

A terse VIOLATION line tells a reviewer what fired; it still sends them off to read the ADR. --explain renders each violation to the clarity floor of a triage card — the offending code in context, the decision made readable, the sanctioned path — composed entirely from the decision record and the changed file. --teach adds one Socratic question templated from the decision's reason, and never proposes a fix. Both are output-only: the exit code and the artifact are byte-identical with or without them.

$ spectastic verdict --changed docs/priya-pr/PositionReconciliationJob.java --explain --teach
VIOLATION 002-downstream-consumers/D-007 … (as above)
 
Explanation (advisory — the decision and the code, so you can act):
 
── D-007 · ADR-0007 — only the persistence adapter touches the data store ──
  Rule no_sql_write_to_positions_outside_adapter · docs/priya-pr/PositionReconciliationJob.java:20
 
  Offending — the change the gate flagged:
17| public void reconcile(CustodianFile file) throws Exception {
18| for (CustodianRecord record : file.records()) {
19| try (PreparedStatement ps =
> 20| db.prepareStatement("UPDATE positions SET quantity = ? WHERE instrument = ?")) {
21| ps.setLong(1, record.quantity());
22| ps.setString(2, record.instrument());
23| ps.executeUpdate();
 
  Why it is a violation — the decision that governs this code:
    Every position change must emit PositionChanged so Risk, P&L, and the audit trail stay consistent; a direct write to
    the position store bypasses the emission and the audit hooks that live in the adapter.
 
    Context. Spec FR-004 requires a single emitter; the emission guarantee is only as strong as the boundary around
    the write. The domain reason is settlement consistency (KB-0001@2026-09-13): the book and its consumers must never
    diverge silently. Decision. Only xyz.briancorbin.pk.hex.persistence may reach the data-access APIs or write the
    positions store … Consequences. + Every position change provably emits the event; a new writer fails the gate.
    − Legitimate new persistence code lives in the adapter package or extends the scope through a recorded amendment.
    Open the full decision: specs/002-downstream-consumers/design.html#D-007
    (spectastic://briancorbin/position-keeper-guardrails/decision/002-downstream-consumers/D-007)
 
  Sanctioned path — where this pattern is permitted instead:
    src/**/persistence/**
 
Teaching follow-up (advisory — reason for yourself, this is not a fix):
  · Decision 002-downstream-consumers/D-007 exists so that: Every position change must emit PositionChanged … — this change
    has docs/priya-pr/PositionReconciliationJob.java reaching UPDATE\s+positions. What makes that necessary here,
    rather than the path the decision intends?

The reason appears in the ADR, in the verdict, in the explanation and in the question — and it is stored once. Delete it from the enforcer's .because() and nothing here changes.

And on GitHub, for real — the same PR, killed by the same two checks
Nightly reconciliation from the custodian EOD file #1 ↗ feat/nightly-reconciliation → main · open, never merged
✕gate24sthe managed gate, spectastic.yml — validate → enforce → merge verdict over merge-base..HEAD
✕gradle1m 21sthe project's own build — ./gradlew build fails on ADR-0007's ArchUnit rule; Semgrep finds the write; the verdict re-fires from the SARIF
✓guardrail-fires11sthe demonstrations as a CI assertion — the two intentional violations kept in the checkout still exit 1
✓spectastic2scode-scanning upload of the validate SARIF — green by design, and easy to misread beside the red gate
gate › Merge verdict for the changed paths
▸ Run BASE="$(git merge-base "origin/$BASE_REF" HEAD)"
VIOLATION 002-downstream-consumers/D-007 [no_sql_write_to_positions_outside_adapter] at src/main/java/xyz/briancorbin/pk/recon/PositionReconciliationJob.java:22
  src/main/java/xyz/briancorbin/pk/recon/PositionReconciliationJob.java → UPDATE\s+positions
  Every position change must emit PositionChanged so Risk, P&L, and the audit trail stay consistent; …
Scope: repo-local — evaluated 2 decisions from this checkout.
Error: Process completed with exit code 1.
 
gradle › ./gradlew build
DataAccessRulesTest > onlyThePersistenceAdapterTouchesDataAccessApis() FAILED
  Method <…PositionReconciliationJob.reconcile(CustodianFile)> calls method <java.sql.Connection.prepareStatement(String)> in (PositionReconciliationJob.java:22)

Nobody wrote the failing assertion for this PR. The gate is a workflow spectastic owns — installed by spectastic init --tools --ci github, pinned to the CLI version, reported as drifted by validate the moment it is edited — and the rule it applied was recorded in a design two and a half years earlier. The second check is ordinary: the repository's own build, running the fitness function that shipped with the decision. Two independent kills; both reconstructable from disk. Read the run ↗

The residual — detector and explainer, split

spectastic is a Node CLI. It does not reimplement ArchUnit or Semgrep, and it never executes them. For language-agnostic rules — a path boundary, a forbidden pattern — it runs its own deterministic content detector. For a type-graph rule it ingests the ecosystem enforcer's SARIF and joins the rule-id back to the decision. Either way spectastic owns the one thing no architecture-test tool provides: the composition rule-id ↔ decision-id ↔ reason ↔ location.

The sanctioned writer · silent

JdbcPositionRepositoryAdapter runs the identical UPDATE positions — and emits PositionChanged in the same transaction. It sits inside src/**/persistence/**, the rule's allowed-in, so the content detector says nothing.

$ spectastic verdict --changed src/…/persistence/JdbcPositionRepositoryAdapter.java
verdict: no governance violations in the changed paths.
Scope: repo-local — evaluated 2 decisions from this checkout.
exit 0
ArchUnit's finding · ingested, never run

The build runs the fitness function on the bypass branch and writes SARIF — ArchUnit ships no emitter, so the test does it. spectastic reads it, maps only_the_persistence_adapter_touches_data_access_apis to D-007, and composes the same reason — a second violation, from a detector spectastic didn't write.

$ spectastic verdict --changed docs/priya-pr/…Job.java --enforcer-output enforcement/archunit-results.sarif
VIOLATION 002-downstream-consumers/D-007 [no_sql_write_to_positions_outside_adapter] at …Job.java:20
VIOLATION 002-downstream-consumers/D-007 [only_the_persistence_adapter_touches_data_access_apis] at src/…/recon/…Job.java:22
… and :21, :23–26 — one result per data-access call
  …Job.java → only_the_persistence_adapter_touches_data_access_apis
  Every position change must emit PositionChanged so Risk, P&L, and the audit trail stay consistent; …
The blind spot, made visible — spectastic adrs --coverage
$ spectastic adrs --coverage
decision coverage: 1/2 active decisions carry an executable check (50%)
  excused (none-with-reason): 1  # D-008 — the DB grant, operational, honestly unenforceable
  uncovered: 0

This is the number that would have made “the ADR governing positions has no check” visible before the incident. It counts a wired rule-id, not a green run — present is not the same as live, and the report says so.

Ownership, not layering

Split the estate into services and the sharper version of Priya's PR appears: the reconciliation team builds the nightly job in their service, and writes the position store from a persistence adapter of their own — cleanly layered, ports-and-adapters by the book. A path glob has no grammar for this. src/**/persistence/** is satisfied; the write is still wrong, because of whose store it is.

So D-007 was amended to name the store it governs by coordinate and the one project that owns it. The verdict becomes owner-aware: the current project identity is resolved once at the CLI edge from spectastic.json and injected into the pure kernel as data. If it equals the owner, the path rule applies exactly as before — demos 1–7 reproduce byte-identically. If it is anything else — another project, no identity at all, a bare unqualified default — the allowed zone is empty, and every detected touch flags.

acme/reconciliation-service · not the owner

A second project — services/reconciliation-service/, a real Gradle subproject with its own spectastic.json — carrying a copy of D-007 and a textbook adapter that writes positions. Well layered; flagged.

$ spectastic verdict --changed src/main/java/acme/…/persistence/PositionRepositoryAdapter.java
VIOLATION 002-downstream-consumers/D-007 [no_sql_write_to_positions_outside_adapter] at …Adapter.java:21
  …Adapter.java → UPDATE\s+positions
exit 1
Same file, owner identity · silent

Flip spectastic.json to briancorbin/position-keeper-guardrails and nothing else. The identical file is inside the owner's allowed-in; the path rule applies; the adapter is sanctioned.

$ spectastic verdict --changed src/main/java/acme/…/persistence/PositionRepositoryAdapter.java
verdict: no governance violations in the changed paths.
exit 0

The verdict also says why. The owner comparison happens once, in the kernel, and is recorded on the violation as cause: "ownership" with the store's coordinate and owner — so the explanation and the teaching question read it rather than re-deriving it. A non-owner is no longer pointed at a "sanctioned path" (which is where the file already was); it is pointed at the authority.

$ spectastic verdict --changed src/main/java/acme/…/persistence/PositionRepositoryAdapter.java --explain --teach  # as acme/reconciliation-service
VIOLATION 002-downstream-consumers/D-007 … (as above)
 
── D-007 · ADR-0007 — only the persistence adapter touches the data store ──
  Offending … Why it is a violation … (the same composition as the single-repo case)
 
  Owned elsewhere — nowhere in this service; route the change through its owner:
    the store spectastic://briancorbin/position-keeper-guardrails/datastore/positions is owned by briancorbin/position-keeper-guardrails
 
Teaching follow-up (advisory — reason for yourself, this is not a fix):
  · The store spectastic://briancorbin/position-keeper-guardrails/datastore/positions is owned by briancorbin/position-keeper-guardrails, not this
    service — this change has …PositionRepositoryAdapter.java writing it directly. What makes holding this data here necessary,
    rather than routing the change through briancorbin/position-keeper-guardrails?
demonstrations/8-verdict.json — the violation, with its cause
{ "decisionId": "D-007", "specId": "002-downstream-consumers", "ruleId": "no_sql_write_to_positions_outside_adapter", "file": "src/main/java/acme/recon/hex/persistence/PositionRepositoryAdapter.java", "line": 21, "detector": "content", "cause": "ownership", "owner": "briancorbin/position-keeper-guardrails", "storeCoordinate": "spectastic://briancorbin/position-keeper-guardrails/datastore/positions" }

The reason text is the same in both directions — it was written for the single-repo case and still holds. Every violation on the owner side carries cause: "path" and renders exactly as before; a pre-existing artifact with no cause is read as path. That gap was found by dogfooding this page, triaged, and closed the same day.

The rubric, scored twice

Before building the layer, spectastic scored itself against Valmis's rubric under a harsh bar — a row is full only against a committed passing test — and came out 2 full · 5 partial · 3 does-not. The Priya PR would have passed. After seven specs and this example: 9 full · 1 partial · 0, with the one partial kept on purpose.

#Rubric itemWasNowEvidence
1Structured decision corpus — precedence, lifecycle, supersedespartialfullThe extended <spec-decision>; overlapping scopes without supersedes are reported, never silently resolved.
2Reliable retrieval — path-scoped, deterministic, loggeddoes notfulladrs --for + the retrieval log.
3Context injection before writingdoes notpartialReal, tested injection into design and tasks; at the code-writing moment it is an advisory nudge, because an advisory prompt cannot be a guarantee. Kept partial on purpose.
4Deterministic CI enforcement, decision-traceablepartialfullThe plan constraint and the merge verdict.
5Not an agentpartialfullA test asserts the verdict kernel imports zero child-process modules.
6Not RAG-as-verdictpartialfullA gate-independence test: injection never changes the verdict.
7Not AI-reviews-AIfullfullUnchanged — the critic recommends, the deterministic gate decides.
8Not vendor-lockedfullfullA Node CLI and plain JSON; AGENTS.md points at the commands and restates no ADR.
9Enforcement coverage is visibledoes notfulladrs --coverage.
10A failure teachespartialfullReason composition, --explain, --teach.

Items 9 and 10 are spectastic's additions to the rubric. Building the layer also taught two things the rubric doesn't name: a governance layer needs forward-only binding — a new decision binds work in flight, not history — and “a failure teaches” has two halves, the data and the rendering; full data behind a one-line render reads as done and is not.

What it can't see

A guardrail that overstates its reach is a guardrail nobody should trust. Three boundaries, recorded in the tool rather than in the marketing.

The verdict reads one checkout, and says so

A decision can now name a store in another service and its owner — but the verdict still reads only this checkout's specs/*/design.html. The consumer in demo 8 works because D-007 is copied into it; the federated read that would deliver the owner's decision into a consumer's CI is deferred to spectastic-mcp. And a "touch" is still whatever the content pattern matches: an API call, a topic subscription, a migration is not a SQL string. So a green verdict carries "scope": "repo-local" and the count of decisions it evaluated — a repo-local green, reconstructable as exactly that, never misread as an estate-wide guarantee.

Wrong service is a placement question, not an enforcement one

Database-per-service saves you from the wrong thing. A resource-scoped decision (and a per-service grant) stops Priya reaching into the position store; nothing stops her rebuilding its responsibility inside the repo her team knows — a parallel store that never touches the named one. That's a boundary duplication, not a bypass — Conway's Law operating as designed — and it is invisible to every mechanical check for a correct reason. spectastic keeps it where the industry does: a design-time, human-confirmed suggestion, never a merge gate.

Injection is an aid; the gate is the guarantee

The governing decisions are injected before writing — but a prompt is a channel the model may ignore, and spectastic has watched a weaker model ignore one. Injection improves the odds the gate stays quiet. The gate fires regardless, and a test proves its answer is the same whether or not the block was injected.

Also honest: the Java is now a real two-service Gradle build — 38 tests, green on main, red on the bypass branch — but the point is still not that a project compiles. It is that a decision recorded as data, two and a half years before a request that tests it, is surfaced and enforced deterministically; what remains narrated is only the calendar.

The artifacts

The position-keeper-guardrails repo, bundled here: seven spec bundles (spec · design · tasks · verify), one applied change proposal, the decision record, the sanctioned writer and the bypass, the enforcement rules, a second non-owner project built as a subproject, and the eight demonstrations with their committed output. Every artifact passes spectastic validate.

002 · the decision
Where ADR-0007 was born — FR-004, D-007 with scope / enforcement / reason, D-008 the excused backstop
007 · the request
The reconciliation spec and its happy-path design — the one that acknowledges D-007 and routes through the use case — plus the applied proposal that opened POST /corrections
↳ the bypass
Priya's PR — the direct UPDATE positions, next to the sanctioned writer it should have gone through
enforcement/
The detectors — the ArchUnit fitness function (in the build, writing its own SARIF), the Semgrep content rule, the real SARIF from the bypass branch
▷ demonstrations/
Eight behaviors, each reproducible from the repo root, with committed output — the eighth from a second, non-owner project · the whole repo on GitHub ↗
▷ ./gradlew build
Two services, 38 tests — green on main, red on the bypass branch · PR #1, open and failing ↗ · view the source on GitHub ↗

These are the real, rendered artifacts — the same files spectastic validate checks and the same repo the commands above ran against; the excerpts are drawn from them.

▷  Show me View source on GitHub ↗ ← All examples