adr-aware
Ensures Architecture Decision Records (ADRs) are automatically considered when AI agents create or modify code. This skill provides proactive ADR awareness versus reactive checking (which is handled b
SKILL.md.claude/skills/adr-aware/SKILL.md
GitHubadr-aware
Last Reviewed: 2026-05-16 Reviewed By: ai-procedure-quality-r1 (Phase 2b Wave 2b-A) Exemplar rationale: This skill prescribes a context-loading discipline, not a build/deploy procedure — no artifact to rebuild and compare. Quarterly manual review of the mapping table is the right cadence.
Purpose
Ensures Architecture Decision Records (ADRs) are automatically considered when AI agents create or modify code. This skill provides proactive ADR awareness versus reactive checking (which is handled by adr-check).
Philosophy:
adr-aware(this skill) = BEFORE - Load relevant ADRs when starting workadr-check= AFTER - Validate completed work against every ADR that applies (mapping + a pass over the whole index)
Always-Apply Rules
Rule 1: Resource-Type to ADR Mapping
When creating or modifying these resource types, automatically load the specified ADRs:
| Resource Type | Detection Pattern | Required ADRs |
|---|---|---|
| API Endpoint | *Endpoints.cs, *Handler.cs, Program.cs routes |
ADR-001, ADR-008, ADR-010 |
| AI Endpoint/Service | Api/Ai/*, *DocumentIntelligence*, *Analysis*, *Ai* |
ADR-013, ADR-015, ADR-016, ADR-018, ADR-019, ADR-020 |
| Authorization | *Authorization*.cs, *Filter.cs, *Policy*.cs |
ADR-003, ADR-008, ADR-028 |
| Auth Library / Client Bootstrap | @spaarke/auth/**, *authInit*.ts, useAuth consumers, initAuth() callers, authenticatedFetch callers |
ADR-028 |
| Caching | *Cache*.cs, IDistributedCache, IMemoryCache |
ADR-009 |
Dataverse write path (plugin proposal; record create/update path; Create*Wizard services; rule a record must satisfy on save) |
*Plugin.cs (prohibited), *Wizard/*Service.ts, RecordCreationService, *Resolver.cs writers |
ADR-002 |
| Graph/SPE Integration | *Spe*.cs, *Graph*.cs, *Drive*.cs, GraphClientFactory.cs |
ADR-007, ADR-028 |
| PCF Control | *.tsx in pcf/, ControlManifest.Input.xml |
ADR-006, ADR-011, ADR-012, ADR-021, ADR-028 (for any PCF calling BFF) |
| Webresource | *.js in webresources/ |
ADR-006 |
| DI Registration | Program.cs DI section, Add* extension methods |
ADR-010 |
| Background Worker | *Worker.cs, *Service.cs implementing BackgroundService; IJobHandler; IScheduledJob; a Functions project |
ADR-052 (where it runs), ADR-004 (queue), ADR-036 (schedule) |
| Job Status/Persistence | *JobStatus*, JobOutcome, JobContract |
ADR-004, ADR-017, ADR-020 |
| Feature Flags / Kill Switches | *Feature*, FeatureFlag, IOptions* gates |
ADR-018 |
| API Errors / ProblemDetails | ProblemDetails, Results.Problem, IResult error helpers |
ADR-019 |
| Versioning | v1/, ApiVersion, contracts/DTO versioning |
ADR-020 |
| Storage/Documents | *Store*.cs, *Document*.cs, *File*.cs |
ADR-005, ADR-007 |
Rule 2: Automatic Context Loading (Two-Tier Strategy)
When a task or prompt involves creating/modifying files matching the patterns above:
BEFORE writing any code:
1. IDENTIFY resource types from task/file patterns
2. LOOKUP applicable ADRs from mapping table (Rule 1)
3. LOAD Tier 1 context (concise, AI-optimized):
a. LOAD .claude/constraints/{domain}.md for MUST/MUST NOT rules
- API work → .claude/constraints/api.md
- PCF work → .claude/constraints/pcf.md
- Dataverse write path / record invariants / any plugin proposal → .claude/constraints/plugins.md
- Auth work → .claude/constraints/auth.md
- Caching work → .claude/constraints/data.md
- AI work → .claude/constraints/ai.md
- Testing → .claude/constraints/testing.md
b. LOAD .claude/adr/ADR-XXX.md for each applicable ADR
- These are 100-150 line concise versions
- Focus on constraints, not full rationale
c. LOAD .claude/patterns/{domain}/*.md for implementation pointers (When to use, canonical files to read, constraints, key rules)
- API patterns → .claude/patterns/api/
- Auth patterns → .claude/patterns/auth/
- PCF patterns → .claude/patterns/pcf/
- Dataverse patterns → .claude/patterns/dataverse/
4. IF more context needed (rare):
→ READ docs/adr/ADR-XXX-*.md for full rationale and history
5. APPLY constraints during implementation
Resource Type to Context Files Mapping
| Resource Type | Constraints File | Pattern Directory | ADRs |
|---|---|---|---|
| API Endpoint | .claude/constraints/api.md |
.claude/patterns/api/ |
ADR-001, 008, 010 |
| PCF Control | .claude/constraints/pcf.md |
.claude/patterns/pcf/ |
ADR-006, 011, 012, 021 |
| Dataverse write path (record create/update, invariants; plugins prohibited) | .claude/constraints/plugins.md |
.claude/patterns/dataverse/ |
ADR-002 |
| Auth/OAuth | .claude/constraints/auth.md |
.claude/patterns/auth/ (incl. spaarke-sso-binding.md) |
ADR-003, 008, 028 (canonical) |
| Caching | .claude/constraints/data.md |
.claude/patterns/caching/ |
ADR-009 |
| AI Features | .claude/constraints/ai.md |
.claude/patterns/ai/ |
ADR-013, 014, 015, 016 |
| Background Jobs | .claude/constraints/jobs.md |
— | ADR-052, 004, 036, 017 |
| Testing | .claude/constraints/testing.md |
.claude/patterns/testing/ |
ADR-022 |
Rule 3: ADR Constraint Comments
When writing code affected by ADRs, include a brief ADR reference comment:
// ✅ DO: Reference ADRs in significant architectural code
public static class NavMapEndpoints
{
/// <summary>
/// ADR Compliance:
/// - ADR-001: Minimal API (no controllers)
/// - ADR-008: Endpoint-level authorization
/// - ADR-009: Redis-first caching (L1 exception for metadata)
/// </summary>
public static void MapNavMapEndpoints(this WebApplication app) { }
}
// ❌ DON'T: Clutter every method - only significant decisions
public string FormatDate(DateTime dt) => dt.ToString("yyyy-MM-dd"); // No ADR ref needed
Rule 4: ADR Violation Prevention
If about to write code that violates an ADR:
IF detected violation pattern:
1. STOP before writing
2. NOTIFY user with:
🔔 **ADR Conflict Detected**
**ADR**: {ADR-XXX} - {Title}
**Constraint**: {Specific rule being violated}
**Intended Code**: {What you were about to write}
**Compliant Alternative**: {What to write instead}
Proceed with compliant alternative? (y/n)
3. AWAIT confirmation before continuing
ADR Quick Reference
Reference this table for common constraints. The source of truth is:
- Concise ADRs:
.claude/adr/(AI-optimized, 100-150 lines each) - Full ADRs:
docs/adr/INDEX.md(complete with history and rationale)
| ADR | Title | Key Constraint | Violation Pattern |
|---|---|---|---|
| ADR-001 | Minimal API (BFF runtime) | BFF endpoints in Minimal API; no Functions / Durable Task inside the BFF. Where background work runs → ADR-052 (inside the BFF: queue → ADR-004, schedule → ADR-036) | [Function]/[FunctionName]/[HttpTrigger] inside Sprk.Bff.Api; Functions or DurableTask packages in the BFF csproj |
| ADR-002 | No Plugins + Server-Side Write Path | No plugins at all; each record invariant has one BFF owner; client previews only; security fails closed | Any IPlugin; applyFieldMappings/stamping only in a wizard then Xrm.WebApi create; NULL security flag treated as not-secure |
| ADR-003 | Authorization Seams | Two seams only: UAC + Storage | Multiple IAuthorizationXxx interfaces |
| ADR-004 | Async Job Contract | Uniform job processing | Ad-hoc Task.Run for async work |
| ADR-005 | Flat Storage | No folder hierarchies in SPE | CreateFolder, nested paths |
| ADR-006 | PCF over Webresources | No new JS webresources | New .js in webresources/ |
| ADR-007 | SpeFileStore Facade | No Graph types above facade | Microsoft.Graph in API controllers |
| ADR-008 | Endpoint Filters | No global auth middleware | app.UseAuthorization() for resources |
| ADR-009 | Redis-First | No hybrid L1+L2 without proof | IMemoryCache cross-request |
| ADR-010 | DI Minimalism | Feature modules; ~15 Program.cs lines is a target | Interface for single implementation |
| ADR-011 | Dataset PCF | PCF for data grids | Native subgrid with custom actions |
| ADR-012 | Shared Components | Reuse @spaarke/ui-components | Duplicate component implementations |
| ADR-013 | AI Architecture | No hidden/orphaned AI elements | Undocumented AI endpoints/jobs |
| ADR-014 | AI Caching | Define cache reuse policy | Ad-hoc caching per endpoint |
| ADR-015 | AI Data Governance | Minimize/secure AI data flows | Logging prompts/PII, unclear retention |
| ADR-016 | AI Backpressure | Rate limits + bounded concurrency | Unbounded fanout / no throttling |
| ADR-017 | Job Status | Persist job status contract | Fire-and-forget without status |
| ADR-018 | Feature Flags | Kill switches for risky features | No gating for AI/expensive features |
| ADR-019 | API Errors | ProblemDetails standards | Ad-hoc error payloads/status codes |
| ADR-020 | Versioning | Version APIs/jobs/contracts | Breaking changes without version bump |
| ADR-021 | Fluent UI v9 Design | Use Fluent v9; dark mode; tokens | Hard-coded colors, Fluent v8 imports |
| ADR-022 | PCF Platform Libraries | PCF uses React 16/17 (platform); Code Pages use React 19 (bundled) | createRoot in PCF; useId() in PCF |
| ADR-026 | Code Page Build Standard | Vite + vite-plugin-singlefile + React 19 |
Webpack/CRA for new Code Pages; no viteSingleFile |
| ADR-027 | Subscription Isolation | One Azure subscription per CUSTOMER (amended 2026-09-28) + declarative per-scope resource groups; unmanaged solutions in every environment (amended 2026-06-02) | Two customers in one subscription; a shared App Service Plan across customers (impossible cross-subscription); ad-hoc/manually-created resource groups; enforcing managed solutions — that mandate is suspended, not active |
| ADR-028 | Spaarke Auth Architecture (v2) | useAuth() + authenticatedFetch; MI (UAMI) for app-only outbound; MI-FIC client assertion or KV certificate for confidential clients / OBO (A4); HMAC webhooks; tenant-specific authority |
Raw fetch(... Authorization: Bearer ...), tokenBridge, window.__SPAARKE_BFF_TOKEN__, 6-strategy cascade, ClientSecretCredential for app-only when MI available, .WithClientSecret(...) on BFF-identity clients (A4; transitional sites covered by E-3), per-request CCA construction, /common or /organizations authority |
Integration with Other Skills
design-to-spec
- Phase 2 (Context) should invoke ADR lookup using the mapping table
- Generated CLAUDE.md should list applicable ADRs
task-create
- Task
<constraints>should include ADR references - Task
<files>should include ADRs to read
code-review
- Should reference this skill for ADR-specific checks
- Violations should cite specific ADR numbers
adr-check
- This skill prevents violations; adr-check validates afterward
- Both should use the same ADR quick reference
Examples
Example 1: Creating a new API endpoint
Task: "Create a new endpoint to get document metadata"
adr-aware activates:
Detected: API Endpoint creation
Loading ADRs: ADR-001, ADR-008, ADR-010
Key constraints:
- ADR-001: Use Minimal API pattern (MapGet/MapPost), not controllers
- ADR-008: Add endpoint filter for authorization, not global middleware
- ADR-010: Inject concrete SpeFileStore, not interface
Generated code includes:
// ADR-001: Minimal API pattern
app.MapGet("/api/documents/{id}/metadata", GetDocumentMetadataAsync)
.AddEndpointFilter<DocumentAuthorizationFilter>() // ADR-008
.WithName("GetDocumentMetadata");
Example 2: Creating a PCF control
Task: "Create a document viewer PCF control"
adr-aware activates:
Detected: PCF Control creation
Loading ADRs: ADR-006, ADR-011, ADR-012, ADR-021
Key constraints:
- ADR-006: Use PCF, not webresource (already doing this ✅)
- ADR-011: Use Dataset PCF for list views
- ADR-012: Import from @spaarke/ui-components for shared components
- ADR-021: Use Fluent v9, semantic tokens, dark mode support
Generated code includes:
// ADR-012: Use shared component library
import { DocumentCard, StatusBadge } from "@spaarke/ui-components";
// ADR-021: Fluent v9 components and tokens
import { Button, tokens, makeStyles } from "@fluentui/react-components";
import { DocumentAdd20Regular } from "@fluentui/react-icons";
const useStyles = makeStyles({
container: {
backgroundColor: tokens.colorNeutralBackground1, // ADR-021: semantic tokens
color: tokens.colorNeutralForeground1,
},
});
Example 3: Prevented violation
Task: "Add caching to the document service"
adr-aware detects:
About to use IMemoryCache for cross-request caching...
🔔 **ADR Conflict Detected**
**ADR**: ADR-009 - Redis-first caching
**Constraint**: No hybrid L1+L2 cache; use IDistributedCache for cross-request
**Intended Code**: `_memoryCache.Set(key, value, TimeSpan.FromMinutes(5))`
**Compliant Alternative**: `await _distributedCache.SetStringAsync(key, json, options)`
Proceed with compliant alternative? (y/n)
Validation
Run /adr-check after completing tasks to verify no violations were introduced.
Failure Modes & Recovery
| Failure | Cause | Prevention / Recovery |
|---|---|---|
Agent creates code that violates an ADR despite adr-aware being always-apply |
Mapping table didn't trigger (resource type not recognized) OR agent loaded the ADR but ignored its constraint | Add the missed resource type to the mapping table (Rule 1) so future loads cover it. Run /adr-check to retroactively catch the violation. |
| Two mapping tables disagree on which ADRs apply to a resource | Rule 1 (resource-type → ADR) and "Resource Type to Context Files Mapping" tables drift apart | Reconcile against current .claude/adr/ inventory + ADR-jobs ADR coverage. The two tables should agree on jobs.md and other constraint files. |
| Renamed skill referenced inline still appears in old form | Skill rename (e.g., design-to-project → design-to-spec) propagated to root CLAUDE.md but not here |
Run Find-SkillReferenceDrift.ps1 (Phase 4a) before claiming "all references updated." Update inline references in lockstep with skill renames. |
| ADR-jobs (or another newer ADR) added but not in this skill's mapping | ADR creation skipped the propagation step in ai-procedure-maintenance |
Run /ai-procedure-maintenance checklist when adding a new ADR — it explicitly updates the resource-type mapping in this skill. |
Last updated 2026-05-16 by ai-procedure-quality-r1 Phase 2b Wave 2b-A.