# SAD Impact Detection

Single source of truth for "does this change affect `docs/sad.md`?" Consumed by `/tas-plan`, `/tas-dev`, `/tas-bug`, `/tas-fix`, `/tas-debug`.

## When to read this file

- `/tas-plan` Step 5 — fill `## SAD Impact Matrix` in Feature-Technical file
- `/tas-bug` analyze step — fill `## SAD Impact Matrix` in Bug file
- `/tas-dev` Step 5 / `/tas-bug` post-fix — check `sad_impact` flag, auto-invoke `/tas-sad` if true
- `/tas-fix` / `/tas-debug` — run grep heuristic (Quick Heuristic section below); if hit → stop + escalate

## 8 Trigger Categories

Each category covers a class of changes that requires a SAD section update + Changelog entry. Mark `Detected: Yes` if any signal in the category applies.

| # | Category | Signals to detect | SAD section(s) | ADR-worthy? |
|---|----------|------------------|----------------|-------------|
| 1 | **Tech Stack** | New runtime library (package.json / *.csproj / requirements.txt add), new SaaS runtime dep (Stripe, Auth0, Sendgrid), DB engine swap or new DB instance, license-risk dep (GPL/AGPL) | §4 Technology Baseline (4.2 Stack / 4.3 Dependencies) | If swap or vendor lock-in |
| 2 | **System Boundary** | New actor / user role / service account, new external system, new egress target (3rd-party API / domain), new webhook (in or out) | §5 System Context, §9 Integration | If new trust boundary |
| 3 | **Container / Topology** | New service / cache (Redis, Memcached) / queue (Kafka, SQS, RabbitMQ) / scheduled job / file storage (S3, blob), monolith → microservice split, stateful service where was stateless | §6 Container View, §7 Module & Component | Yes for split / stateful shift |
| 4 | **Data Architecture** | New table / schema, new column on PII-classified table, retention or archival policy change, sharding / partitioning change, new column-level encryption | §8 Data Architecture & ERD | If data classification shifts |
| 5 | **API Contract** | New API style (add GraphQL alongside REST), API major-version bump (breaking), auth-scheme change on existing endpoint, new rate-limit / throttling rule, pagination convention change | §9.1 API Design Principles | If breaking or style change |
| 6 | **Security** | New auth mechanism / token type, RBAC / permission-model change, new secret (API key / cert) — beyond generic ENV, new encryption requirement (KMS, at-rest), new network zone / VPC / subnet, new inbound port or egress firewall rule, new compliance scope (GDPR / PCI / SOC2 expand), new audit-log event class | §10 Security Architecture | Yes for auth / compliance changes |
| 7 | **NFR / Ops** | New SLO / SLA target, new observability target (metric / dashboard / alert), new circuit breaker / retry / timeout policy, sync → async conversion, DR change (RPO / RTO) | §11 NFR Strategies | If SLO commits |
| 8 | **Deployment** | New region / AZ, new environment tier (UAT, sandbox), CI/CD pipeline gate change, orchestration change (K8s namespace, ECS task), new CDN config, new production ENV var (≠ dev-only config) | §12 Deployment Topology | If env-tier or pipeline change |

> ADR-worthy = decision is cross-cutting and irreversible. Log to `Architecture Decisions` table with `ADR Candidate: Yes`. ADR creation stays **human-triggered** (`/tas-adr`).

## Quick Heuristic (for `/tas-fix`, `/tas-debug`)

Lightweight commands skip the matrix. Run grep over the **diff** of staged / changed files.

> **Diff-qualifier rule (kills false positives):** a signal counts only when it is on an **added or modified** diff line matching the qualifier — never mere presence of a file in a matched directory. A one-line fix that happens to touch a file already containing `EXPOSE`, or edits a comment in a `migrations/` file, does **not** trip the heuristic.

| Signal | Where | Diff qualifier (must be an added/changed line) | Category hit |
|--------|-------|------------------------------------------------|--------------|
| New dependency | `package.json`, `*.csproj`, `requirements.txt`, `go.mod`, `Cargo.toml` | `+` line in the deps/packages section | 1 Tech Stack |
| New ENV var | `.env*`, `*.env.example`, `appsettings*.json` | `+` line adding a new key | 6 / 8 |
| Dockerfile change | `Dockerfile*`, `docker-compose*.yml` | `+` line with `EXPOSE` / `ENV` / new service | 3 / 6 / 8 |
| Migration / schema | `migrations/**`, `*.sql`, EF migration files | `+` line adding/altering a table/column/index (not a comment-only edit) | 4 Data |
| Infra-as-code | `terraform/**`, `*.tf`, `cdk/**`, `pulumi/**`, `k8s/**`, `helm/**` | `+` line adding/changing a resource | 8 Deployment |
| CI config | `.github/workflows/**`, `azure-pipelines*.yml`, `.gitlab-ci.yml` | `+` line adding/changing a job/step/gate | 8 Deployment |
| New top-level dir under apps/services root | `apps/{new}`, `services/{new}` | a newly added directory | 3 Container |
| **New egress / boundary** *(content grep — catches in-source changes the file patterns miss)* | any source file | `+` line adding an outbound URL literal (`https?://…`), a new `fetch(`/`HttpClient`/axios base URL to a new host, or a new webhook | 2 System Boundary |
| **New auth / security** *(content grep)* | any source file | `+` line adding `[Authorize]`/auth middleware, a new JWT/`bcrypt`/crypto call, a new role/permission string, or a new secret read | 6 Security |

**On a qualified hit — outcome depends on the caller's target:**
- **Feature target** (caller has a Feature ID in context, e.g. `/tas-debug TAS-042`): auto-invoke `/tas-sad "Feature-{NNN}: {signal hit}"` and verify the Changelog ref — do **not** bounce to `/tas-bug`.
- **Standalone target** (no Feature — `/tas-fix`, or `/tas-debug` on a bare dir): STOP and escalate to `/tas-bug` (which owns the SAD matrix + Changelog audit for untracked fixes).

## Matrix Template (paste into Feature-Technical / Bug files)

```markdown
## SAD Impact Matrix
> Fill per `.tas/rules/common/sad-impact.md`. Set frontmatter `sad_impact: true` if any row Detected: Yes.

| # | Category | Detected | SAD Section | Change Summary | ADR Candidate |
|---|----------|----------|-------------|----------------|---------------|
| 1 | Tech Stack | No | — | — | No |
| 2 | System Boundary | No | — | — | No |
| 3 | Container / Topology | No | — | — | No |
| 4 | Data Architecture | No | — | — | No |
| 5 | API Contract | No | — | — | No |
| 6 | Security | No | — | — | No |
| 7 | NFR / Ops | No | — | — | No |
| 8 | Deployment | No | — | — | No |
```

## Auto-invoke `/tas-sad` rules

When `sad_impact: true` in working file:

| Caller | When to invoke | Description argument | Changelog ref |
|--------|---------------|---------------------|---------------|
| `/tas-dev` Step 5 | After post-impl review passes | `"Feature-{NNN}: {summary aggregated from matrix Yes rows}"` | `Feature-{NNN}` |
| `/tas-bug` Status=Committed | After post-fix review passes | `"Bug-{NNN}: {summary}"` | `Bug-{NNN}` |
| Autonomous mode | Pass `--autonomous=true` flag through | Same as above | Same |

`/tas-sad` UPDATE mode writes Changelog entry to `docs/sad.md`. Caller verifies entry exists before marking Done.

## Done Gate

Used by `/tas-dev` Step 6 and `/tas-bug` Done transition:

```
if working_file.frontmatter.sad_impact == true:
  grep docs/sad.md changelog for {Feature-ID | Bug-ID}
  if no match → BLOCK Done, surface: "SAD updated but Changelog missing ref to {ID}"
```
