Rails Context Verification Skill
Purpose
Prevent "assumption bugs" by verifying codebase context before generating code. Never assume helper methods, authentication patterns, or namespace conventions exist - always verify first.
The Assumption Bug Pattern
Common Mistake:
❌ Agent assumes current_admin exists
Agent copies pattern from client → admin without verification
Result: undefined method 'current_admin' error
In admin header view
<%= current_admin.email %> # BREAKS - current_admin doesn't exist
Correct Approach:
✅ Agent verifies authentication helper FIRST
1. Search: rg "def current_" app/controllers/
2. Find: current_administrator (actual helper name)
3. Use verified helper
In admin header view
<%= current_administrator.email %> # WORKS - verified from codebase
Critical Rule
NEVER assume - ALWAYS verify:
-
Helper method names (current_user, current_admin, signed_in?, etc.)
-
Authentication patterns (Devise scope names)
-
Namespace conventions (admin vs client patterns)
-
Controller methods availability
-
View helper existence
-
Model method names
Pre-Implementation Verification Protocol
Step 1: Identify Context
Before generating ANY code, identify:
- Namespace Context:
What namespace am I working in?
- Admin namespace (app/controllers/admins/, app/views/admins/)
- Client namespace (app/controllers/clients/, app/views/clients/)
- API namespace (app/controllers/api/)
- Public namespace (app/controllers/)
- Authentication Context:
What authentication system is used here?
Search for Devise configuration:
rg "devise_for" config/routes.rb
Example output:
devise_for :users, path: 'clients'
devise_for :admins, path: 'admins'
devise_for :administrators
This tells you:
- User model → current_user, user_signed_in?
- Admin model → current_admin, admin_signed_in?
- Administrator model → current_administrator, administrator_signed_in?
- Controller Inheritance:
What base controller is used?
Admin controllers:
rg "class.*Controller.*ApplicationController" app/controllers/admins/
May show:
class Admins::BaseController < ApplicationController
class Admins::DashboardController < Admins::BaseController
Step 2: Verify Helper Methods
Before using ANY helper in views/controllers, verify it exists:
Authentication Helpers
Search for current_* helpers
rg "def current_" app/controllers/ app/helpers/
Common patterns:
- current_user (Devise for :users)
- current_admin (Devise for :admins)
- current_administrator (Devise for :administrators)
- current_account (custom helper)
- current_organization (custom helper)
Example Verification:
Task: Add user dropdown to admin header
Question: What is the authentication helper name?
Step 1: Search for authentication helper
$ rg "def current_" app/controllers/admins/ app/controllers/application_controller.rb
Output:
app/controllers/application_controller.rb: def current_administrator @current_administrator ||= Administrator.find_by(id: session[:admin_id]) end
Step 2: Use verified helper name
✅ Use: current_administrator
❌ Don't use: current_admin (assumption)
View Helpers
Search for custom view helpers
rg "def helper_name" app/helpers/
Example:
$ rg "def format_currency" app/helpers/
If found → safe to use
If not found → DON'T use (will cause NoMethodError)
Controller Methods
Check if controller method exists before calling from view
rg "def method_name" app/controllers/namespace/
Example: Verify @current_account is set
$ rg "@current_account\s*=" app/controllers/clients/
If found in before_action → safe to use in views
If not found → will be nil in views
Step 3: Extract Existing Patterns
Don't invent patterns - discover them:
Authentication Pattern Discovery
Find existing authentication usage in target namespace
rg "signed_in?" app/views/admins/ --type erb
Example output:
app/views/admins/dashboard/_header.html.erb: <% if administrator_signed_in? %>
Pattern discovered: administrator_signed_in? (not admin_signed_in?)
Use this pattern, not an assumed one
Authorization Pattern Discovery
Find existing authorization patterns
rg "authorize|policy|can?" app/controllers/admins/
Example output:
app/controllers/admins/users_controller.rb: before_action :require_super_admin
Pattern discovered: require_super_admin (not authorize :admin)
Use this pattern
Routing Pattern Discovery
Find existing route helper usage
rg "path|url" app/views/admins/ --type erb | head -20
Example output:
admins_dashboard_path destroy_admins_session_path new_admins_administrator_path
Pattern discovered: admins_ prefix for admin routes
Use: admins_users_path (not admin_users_path)
Step 4: Namespace-Specific Patterns
Different namespaces have different conventions:
Admin Namespace Patterns
Authentication
current_administrator # (not current_admin) administrator_signed_in?
Routes
admins_dashboard_path destroy_admins_session_path
Controllers
class Admins::UsersController < Admins::BaseController before_action :authenticate_administrator! end
Models
Administrator (not Admin)
Client Namespace Patterns
Authentication
current_user user_signed_in? current_account # If multi-tenancy
Routes
clients_dashboard_path destroy_clients_session_path
Controllers
class Clients::DashboardController < Clients::BaseController before_action :authenticate_user! before_action :set_account end
Verification Checklist (Before Code Generation)
For Views
-
Verify authentication helper name (rg "def current_" )
-
Verify signed_in? helper name (rg "signed_in?" )
-
Verify all instance variables are set in controller (rg "@variable_name\s*=" controller_file )
-
Verify all view helpers exist (rg "def helper_name" app/helpers/ )
-
Check route helper names (rails routes | grep namespace )
-
Verify model methods exist (rg "def method_name" app/models/ )
For Controllers
-
Verify authentication method (authenticate_user! vs authenticate_admin! )
-
Verify authorization method (Pundit, CanCanCan, custom)
-
Verify before_action callbacks exist
-
Verify model finder methods (find_by vs find)
-
Verify service object existence (rg "class ServiceName" )
For Services
-
Verify model associations (rg "has_many :association" model_file )
-
Verify model methods exist before calling
-
Verify background job classes exist (rg "class JobName" )
-
Verify mailer methods exist (rg "def mailer_method" app/mailers/ )
For Tests
-
Verify factory exists (rg "factory :model_name" spec/factories/ )
-
Verify test helper methods (rg "def helper" spec/support/ )
-
Verify shared examples exist (rg "shared_examples" spec/support/ )
Common Assumption Bugs & Prevention
Bug 1: Undefined Authentication Helper
Assumption:
<%# Agent assumes current_admin exists %> <%= current_admin.email %>
Prevention:
Verify first
$ rg "def current_" app/controllers/
Find actual helper name, then use it
<%= current_administrator.email %>
Bug 2: Wrong Devise Scope Name
Assumption:
Agent assumes admin_signed_in? exists
before_action :authenticate_admin!
Prevention:
Check routes.rb for devise_for declaration
$ rg "devise_for" config/routes.rb
Output: devise_for :administrators
Correct helper: authenticate_administrator!
Bug 3: Namespace Route Mismatch
Assumption:
<%# Agent assumes admin_users_path exists %> <%= link_to "Users", admin_users_path %>
Prevention:
Check existing route helper patterns
$ rg "_path" app/views/admins/ --type erb | head -5
Output: admins_users_path (note the 's' in admins)
Correct: admins_users_path
Bug 4: Undefined Instance Variable
Assumption:
<%# Agent assumes @current_account is set %> <%= @current_account.name %>
Prevention:
Check controller sets this variable
$ rg "@current_account\s*=" app/controllers/namespace/controller.rb
If not found → DON'T use in view
Add to controller first, or use different pattern
Bug 5: Undefined View Helper
Assumption:
<%# Agent assumes format_currency helper exists %> <%= format_currency(@amount) %>
Prevention:
Verify helper exists
$ rg "def format_currency" app/helpers/
If not found → define helper first, or use number_to_currency (Rails built-in)
Bug 6: Copying Patterns Across Namespaces
Assumption:
Agent copies client pattern to admin without verification
Client controller uses:
before_action :set_account
Agent assumes admin also has set_account
In admin controller:
before_action :set_account # BREAKS - admin doesn't have accounts
Prevention:
Check what before_actions exist in target namespace
$ rg "before_action" app/controllers/admins/base_controller.rb
Output shows actual available callbacks
Use only verified callbacks, don't copy blindly
Pattern Discovery Examples
Example 1: Adding User Dropdown to Admin Header
Task: Add admin user dropdown with logout link
Wrong Approach (Assumption):
<%# Assume current_admin and destroy_admin_session_path %> <% if admin_signed_in? %> <%= current_admin.email %> <%= link_to "Logout", destroy_admin_session_path %> <% end %>
Correct Approach (Verification):
Step 1: Verify authentication helper
$ rg "def current_" app/controllers/
Found: def current_administrator
Step 2: Verify signed_in? helper
$ rg "signed_in?" app/views/admins/
Found: administrator_signed_in?
Step 3: Verify logout route
$ rails routes | grep destroy.*session | grep admin
Found: destroy_admins_session_path
Step 4: Use verified helpers
<% if administrator_signed_in? %> <%= current_administrator.email %> <%= link_to "Logout", destroy_admins_session_path, method: :delete %> <% end %>
Example 2: Adding Authorization Check
Task: Restrict action to super admins
Wrong Approach (Assumption):
Assume authorize method exists
before_action :authorize_admin!
Correct Approach (Verification):
Step 1: Check existing authorization patterns
$ rg "before_action.*authorize|admin|permission" app/controllers/admins/
Found pattern:
before_action :require_super_admin
Step 2: Verify method exists
$ rg "def require_super_admin" app/controllers/
Found in: app/controllers/admins/base_controller.rb
Step 3: Use verified pattern
before_action :require_super_admin
Example 3: Adding Account-Scoped Query
Task: Show records for current account
Wrong Approach (Assumption):
Assume current_account exists
@records = current_account.records
Correct Approach (Verification):
Step 1: Check if multi-tenancy is used
$ rg "current_account" app/controllers/clients/
Step 2: Check how it's set
$ rg "def current_account|@current_account\s*=" app/controllers/
Step 3: If found, verify it's available in this controller
Step 4: If not found, check what scoping is used
If current_account exists:
@records = current_account.records
If not, check for other patterns:
@records = current_user.records # Or: @records = Record.all # If no scoping
Integration with Implementation Workflow
Before Delegating to Specialist
In implementation-executor.md Step 2.6 (Context Verification):
Step 2.6: Context Verification
Before delegating to specialist, VERIFY context:
-
Identify Namespace:
- Admin? Client? API? Public?
- Check file paths: app/controllers/[namespace]/
- Check view paths: app/views/[namespace]/
-
Search for Existing Patterns:
# Authentication helpers rg "def current_" app/controllers/ # signed_in? helpers rg "signed_in\?" app/views/[namespace]/ # Route patterns rails routes | grep [namespace] # before_actions rg "before_action" app/controllers/[namespace]/base_controller.rb
Extract Verified Names:
-
Authentication helper: [verified from search]
-
Routes prefix: [verified from search]
-
Authorization method: [verified from search]
Pass to Specialist: Include verified names in delegation message (see below)
Delegation Message Format
Add Context Verification Section:
**Context Verification:**
Namespace: [admin/clients/api/public]
Authentication helper: `current_administrator` (verified: app/controllers/application_controller.rb:42)
Signed-in helper: `administrator_signed_in?` (verified: app/views/admins/dashboard/_header.html.erb:12)
Route prefix: `admins_` (verified: rails routes | grep admins)
Authorization: `require_super_admin` (verified: app/controllers/admins/base_controller.rb:8)
Available instance variables: `@current_administrator` (set in before_action)
**CRITICAL:**
- DO NOT assume helper names - use ONLY the verified helpers above
- DO NOT copy patterns from other namespaces without verification
- DO NOT use helpers that aren't listed above (they don't exist)
- If you need a helper not listed, ask for it to be added first
Per-Feature Context Tracking
New in v1.1.0: Context verification results are now persisted per-feature in beads comments.
After completing verification for a feature, the implementation-executor records the verified context in the beads feature issue comment:
verified_context:
namespace: admin
auth_helper: current_administrator
signed_in_helper: administrator_signed_in?
route_prefix: admins_
authorization_methods:
- require_super_admin
- authenticate_administrator!
instance_variables:
- @current_administrator
verified_at: 2025-01-15T10:30:00Z
Benefits:
- Single verification for entire feature (not per-phase)
- All specialists reference same verified context
- Audit trail of what was verified and when
- Quality assurance - reviewers can verify correct usage
Usage:
When implementing any phase, check the feature beads comment for verified context and use only those exact helper/route names.
Common Violation Patterns to Avoid
Violation 1: Generic Name Assumption
# ❌ WRONG - Assuming generic "current_user"
if current_user.admin?
# code
end
# ✅ CORRECT - Use verified helper
# Verified: current_administrator (from rg search)
if current_administrator.super_admin?
# code
end
Violation 2: Cross-Namespace Pattern Copying
# ❌ WRONG - Copying client pattern to admin
# In app/controllers/clients/dashboard_controller.rb:
before_action :set_account
# In app/controllers/admins/dashboard_controller.rb:
before_action :set_account # FAILS - admins don't have accounts!
# ✅ CORRECT - Verify admin patterns separately
# Search: rg "before_action" app/controllers/admins/base_controller.rb
# Found: before_action :authenticate_administrator!
before_action :authenticate_administrator!
Violation 3: Route Helper Plurality Mismatch
# ❌ WRONG - Assuming singular prefix
link_to "Dashboard", admin_dashboard_path
# ✅ CORRECT - Verify actual route prefix
# Verified: rails routes | grep admin → shows "admins_" (plural)
link_to "Dashboard", admins_dashboard_path
Violation 4: Devise Scope Name Mismatch
# ❌ WRONG - Assuming scope matches model name
# Model: Administrator
# Assumption: admin_signed_in?
before_action :authenticate_admin! # FAILS!
# ✅ CORRECT - Check devise_for scope in routes.rb
# Found: devise_for :administrators
# Correct helpers: current_administrator, administrator_signed_in?
before_action :authenticate_administrator! # WORKS!
Violation 5: Undefined Instance Variable Usage
<%# ❌ WRONG - Using @current_account without verification %>
<%= @current_account.name %> # NIL ERROR if not set!
<%# ✅ CORRECT - Verify controller sets it first %>
<%# Search: rg "@current_account\s*=" app/controllers/admins/ %>
<%# Result: Not found in admin namespace %>
<%# Action: Use different pattern or add to controller first %>
<%= current_administrator.account&.name %>
Enforcement Mechanisms
PreToolUse Hook (verify-assumptions.sh)
The verify-assumptions.sh
hook runs before any code generation to enforce verification:
Checks:
- Context verification exists in beads feature comment
- Generated code uses only verified helpers
- No cross-namespace assumptions
- All route helpers match verified prefix
Blocks if:
- Context not verified (Step 2.6 not complete)
- Code uses unverified helpers (e.g., current_admin
when current_administrator
verified)
- Cross-namespace copying detected
Logs:
Violations are logged to .claude/assumption-violations.log
for review and learning.
Quality Gate Integration
The Chief Reviewer validates:
- All helpers used match verified context
- No assumption patterns in generated code
- Beads comment has verified context section
- Context verification timestamp exists
Remember
- Never assume - always verify helper names, routes, methods
- Search first, code second - discover patterns before applying them
- Namespace matters - admin ≠ client ≠ api (different patterns)
- Inheritance matters - check base controller for available methods
- Devise scope matters - :users ≠ :admins ≠ :administrators (different helpers)
- Verification is enforced - hooks will block unverified code generation
- Context is tracked - verified context persists in beads for entire feature
Quick Reference
Before using in code, verify:
What
How to Verify
Command
current_* helper
Search controllers
rg "def current_" app/controllers/
signed_in? helper
Search views
rg "signed_in\?" app/views/namespace/
Route helper
Check routes
rails routes | grep namespace
View helper
Search helpers
rg "def helper_name" app/helpers/
Instance variable
Check controller
rg "@variable\s*=" controller_file
before_action
Check base controller
rg "before_action" base_controller.rb
Model method
Search model
rg "def method_name" app/models/model.rb
Factory
Search factories
rg "factory :name" spec/factories/
Verification is not optional - it's mandatory.
Assumption bugs cause production errors. Take 2 minutes to verify, save hours of debugging.