DEV Community

Ali Abbas
Ali Abbas

Posted on

Stop Repeating Yourself: How to Automate Architectural Context in GitHub PRs

We've all been there. You're reviewing a pull request from a junior developer, and for what feels like the tenth time this month, you're typing out the same comment:

"Hey, we don't use console.log in production code—please use our structured logger."

The dev apologizes, updates the code, and you approve the PR. Two weeks later, a different developer makes the exact same mistake. Rinse and repeat.

Sound familiar?

The Real Problem: The Documentation-Implementation Gap

Here's the thing: your team's architectural decisions live in documents that nobody reads, while the actual work happens in code.

You probably have an Architecture Decision Record (ADR) somewhere that clearly states: "We use Winston for structured logging, not console.log." It's documented. It's in Confluence. It might even be in your repository's /docs folder.

But let's be honest—when was the last time a developer actively searched through ADRs before writing code?

The problem isn't your team. The problem is expecting humans to remember and enforce dozens of architectural constraints manually. That's not scalable, and it leads to:

  • Review fatigue: Senior devs waste time repeating the same feedback
  • Inconsistent codebases: Some violations slip through when reviewers are tired
  • Slower onboarding: New team members learn by making mistakes instead of prevention
  • Context switching: Developers have to context-switch between code and documentation

What if there was a better way?

The Solution: Context-as-Code

Instead of keeping architectural decisions in separate documentation, what if we could encode them directly into our development workflow?

This is the concept of "Context-as-Code"—taking your team's architectural decisions and automating their enforcement at the exact moment they matter: during pull requests.

Think of it like this: instead of a senior developer manually checking every PR for violations, you create automated rules that check for you. The PR author gets immediate feedback, learns the constraint, and your reviewers can focus on actual architecture and logic instead of style guide enforcement.

Enter Decision Guardian

Decision Guardian is a GitHub Action that bridges this gap. It automatically surfaces architectural decisions and critical context when Pull Requests modify protected files. Instead of relying on tribal knowledge, Decision Guardian proactively alerts teams when changes touch sensitive code.

Here's what makes it powerful:

  • Automated context surfacing: Automatically posts PR comments when protected files change
  • Markdown-based decisions: Write decisions in simple markdown format
  • Flexible file matching: Supports glob patterns and advanced rule evaluation
  • Non-blocking: Configurable to either block merges or just warn
  • Zero external calls: Runs entirely within your GitHub Actions runner—no data leaves GitHub

Let's dive into what this looks like in practice.

The Cool Stuff: Deep Dive into Features

Simple File-Based Decisions

The core concept is beautifully simple: you write architectural decisions in markdown and link them to file patterns. When someone opens a PR that touches those files, they automatically see the context.

Here's a basic example for protecting your database configuration:

<!-- DECISION-DB-001 -->
## Decision: Connection Pool Size

**Status**: Active  
**Date**: 2024-01-15  
**Severity**: Critical

**Files**:
- `src/db/pool.ts`
- `config/database.yml`

### Context

Pool size fixed at 20 connections to prevent exhaustion.

Tested with production load (5K req/s). Higher values caused
connection leaks under sustained traffic.

**Do not modify without load testing.**

---
Enter fullscreen mode Exit fullscreen mode

That's it! When someone modifies src/db/pool.ts or config/database.yml, this decision automatically appears as a comment on their PR.

Advanced Rules with Regex

For more sophisticated scenarios, you can embed JSON-based rules directly in your markdown to detect patterns in code:

<!-- DECISION-SEC-001 -->
## Decision: No Hardcoded Credentials

**Status**: Active  
**Date**: 2024-02-01  
**Severity**: Critical

**Rules**:
\`\`\`json
{
  "type": "file",
  "pattern": "src/**/*.{ts,js}",
  "exclude": "**/*.test.{ts,js}",
  "content_rules": [
    {
      "mode": "regex",
      "pattern": "(password|api[_-]?key|secret)\\s*[=:]\\s*['\"][^'\"]+['\"]",
      "flags": "i"
    }
  ]
}
\`\`\`

### Context

Detects hardcoded credentials. Use environment variables
or AWS Secrets Manager instead.

---
Enter fullscreen mode Exit fullscreen mode

This rule will trigger when someone adds code like const password = "secret123" in a JavaScript/TypeScript file.

JSONPath for Configuration Files

You can also use JSONPath to validate specific values in JSON files:

<!-- DECISION-API-002 -->
## Decision: API Rate Limit Configuration

**Status**: Active  
**Date**: 2024-03-10  
**Severity**: Warning

**Rules**:
\`\`\`json
{
  "type": "file",
  "pattern": "config/api.json",
  "content_rules": [
    {
      "mode": "json_path",
      "path": "$.rateLimit.maxRequests",
      "expected": 100
    }
  ]
}
\`\`\`

### Context

Rate limit must stay at 100 requests/minute. Changes can:
- Block legitimate users (too strict)
- Allow abuse (too loose)

Before modifying, test with production traffic patterns.

---
Enter fullscreen mode Exit fullscreen mode

Setting This Up (It's Easier Than You Think)

The beauty of Decision Guardian is its simplicity. No complex YAML configuration files—just markdown documents.

Step 1: Create Your Decisions File

Create .decispher/decisions.md in your repository:

<!-- DECISION-DB-001 -->
## Decision: Database Choice for Billing

**Status**: Active  
**Date**: 2024-03-15  
**Severity**: Critical

**Files**:
- `src/db/pool.ts`
- `config/database.{yml,yaml}`

### Context

We chose Postgres over MongoDB because billing requires ACID compliance.
MongoDB doesn't guarantee consistency for financial transactions.

**Alternatives rejected:**
- MongoDB: No ACID guarantees
- Redis: Added unnecessary complexity

**Related:**
- [Slack thread](https://your-workspace.slack.com/archives/...)
- [Architecture review](https://your-docs.com/...)

---
Enter fullscreen mode Exit fullscreen mode

Step 2: Add the GitHub Action

Create .github/workflows/decision-guardian.yml:

name: Decision Guardian

on:
  pull_request:

permissions:
  pull-requests: write
  contents: read

jobs:
  check:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - uses: DecispherHQ/decision-guardian@v1
        with:
          token: ${{ secrets.GITHUB_TOKEN }}
          decision_file: '.decispher/decisions.md'
          fail_on_critical: true
Enter fullscreen mode Exit fullscreen mode

Step 3: Test It Out

Create a test PR that modifies src/db/pool.ts and watch Decision Guardian automatically comment with the full context from DECISION-DB-001.

That's really it. No complex configuration files, no YAML sprawl—just markdown documents with your decisions.

What Makes This Different

You might be thinking: "Isn't this just like CODEOWNERS or linting?"

Not quite. Here's the key difference:

  • CODEOWNERS assigns reviewers but doesn't explain why review matters
  • Linting catches syntax errors but not architectural violations
  • Decision Guardian provides context at the exact moment it's needed

When someone modifies your database connection pool, they don't just get an error—they get the full story: what the decision was, why it was made, what was tested, and who to talk to if they really need to change it.

Real-World Scenarios

Here are some practical examples of decisions teams protect with Decision Guardian:

Security patterns:

  • No hardcoded credentials
  • Required authentication middleware
  • Specific encryption algorithms

Performance constraints:

  • Database connection pool limits
  • API rate limiting configurations
  • Cache invalidation strategies

Architecture boundaries:

  • Microservice communication patterns
  • Dependency injection requirements
  • Database access patterns

Business logic:

  • Payment processing flows
  • Data retention policies
  • Feature flag configurations

Real-World Impact

After implementing Decision Guardian, teams typically see:

  • Faster reviews: Senior developers spend less time on repetitive feedback
  • Better onboarding: New developers learn architectural constraints immediately
  • Consistent codebases: Violations get caught automatically, not sporadically
  • Living documentation: ADRs become actionable, not just informational
  • Knowledge preservation: Critical context survives even when team members leave

The real win isn't just catching violations—it's educating developers about why those violations matter. Each PR comment becomes a teaching moment.

Getting Started

The easiest way to start is to identify the top 3-5 architectural decisions you find yourself repeating in code reviews. Document them in markdown format, link them to the relevant files, and let Decision Guardian handle the rest.

Start small:

  1. Pick one decision that causes the most friction
  2. Document it in .decispher/decisions.md
  3. Add the GitHub Action
  4. Observe what happens over the next week

You can always expand from there.

Conclusion: Bridge the Gap

Decision Guardian represents a shift in how we think about documentation. Instead of static documents that live separately from our code, we can embed our architectural knowledge directly into the development workflow—right where developers need it.

This doesn't replace code review—it enhances it. Your senior developers can focus on architectural discussions, design patterns, and business logic instead of catching the same violations over and over.

If you're tired of repeating yourself in PR comments, give Decision Guardian a try. It's open source, free to use, and might just save your team hundreds of hours.

Resources


Have you tried automating architectural decisions in your workflow? What challenges have you faced with keeping documentation and code in sync? Let me know in the comments!

Top comments (0)