refactor: SSA-based pattern registry architecture#14
Conversation
Add internal/ssa package providing SSA program building and value tracing utilities for the new pattern-based architecture. Key components: - builder.go: Wraps buildssa.Analyzer for SSA program construction - tracer.go: Provides value tracing through Phi nodes, Store instructions, closures, and MakeClosure operations The tracer supports: - Finding closures from SSA values (MakeClosure, Phi, Call returns, etc.) - Checking if closures capture context variables via FreeVars - Tracing through factory function returns - Store/address matching for field and index access Based on patterns from zerologlintctx with improvements for goroutinectx. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add internal/patterns package defining the pattern abstraction layer for context propagation checking. Pattern interface: - Pattern: For CallExpr-based checks (errgroup, waitgroup, etc.) - GoStmtPattern: For go statement checks Implemented patterns: - ClosureCapturesCtx: Checks closure captures outer context Used by: errgroup.Group.Go, sync.WaitGroup.Go, conc.Pool.Go - CallbackReceivesCtx: Checks callback receives context as parameter Used by: gotask.DoAllFnsSettled, ants.PoolWithFuncGeneric - ShouldCallDeriver: Checks callback calls deriver function Used by: goroutine-derive, gotask task functions - GoStmtCapturesCtx: Checks go statement captures context - GoStmtCallsDeriver: Checks go statement calls deriver CheckContext provides: - analysis.Pass for type information - SSA Program for dataflow analysis - Tracer for value tracing 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add internal/registry package for declarative API registration with pattern association. API struct defines: - Pkg: Package path (e.g., "golang.org/x/sync/errgroup") - Type: Receiver type name (empty for package functions) - Name: Method or function name - Kind: KindMethod or KindFunc - CallbackArgIdx: Index of callback argument Registry provides: - Register(pattern, ...apis): Associate pattern with multiple APIs - Match(pass, call): Find matching API and extract callback argument - Entries(): List all registered API/pattern pairs FullName() returns human-readable API names: - Methods: "errgroup.Group.Go" - Functions: "gotask.Do" 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add internal/checker package providing the unified checker that ties together SSA analysis, patterns, and registry. Checker struct orchestrates: - Registry for API matching - GoStmtPatterns for go statement checking - SSA Program for dataflow analysis - Ignore directive handling Run() method: - Builds function scopes with context parameters - Uses inspector.WithStack for AST traversal - Dispatches to patterns based on node type apis.go provides default API registrations: - errgroup.Group.Go, TryGo - sync.WaitGroup.Go - sourcegraph/conc pool APIs (Pool, WaitGroup, ContextPool, etc.) - gotask Do*, DoAsync functions This checker is not yet integrated into analyzer.go. The old checkers remain in use until integration is complete. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
実装メモSSA Tracer について
Pattern インターフェース設計type Pattern interface {
Name() string
Check(cctx *CheckContext, call *ast.CallExpr, callbackArg ast.Expr) bool
Message(apiName string, ctxName string) string
}
type GoStmtPattern interface {
Name() string
CheckGoStmt(cctx *CheckContext, stmt *ast.GoStmt) bool
Message(ctxName string) string
}CallExpr と GoStmt で別インターフェースにした理由:
Registry の API マッチングtype API struct {
Pkg string // "golang.org/x/sync/errgroup"
Type string // "Group" (empty for package functions)
Name string // "Go"
Kind APIKind // KindMethod or KindFunc
CallbackArgIdx int // 0 (callback is first argument)
}
次のステップ
|
既知の制限事項と今後の改善現時点の制限
SSA で解決できる可能性があるもの
テスト戦略統合時は以下の順序で進める予定:
|
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #14 +/- ##
==========================================
+ Coverage 81.29% 82.73% +1.43%
==========================================
Files 19 26 +7
Lines 1358 1772 +414
==========================================
+ Hits 1104 1466 +362
- Misses 137 194 +57
+ Partials 117 112 -5
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
Add buildssa.Analyzer to Requires list to enable SSA-based analysis. The SSA program is built but currently unused while we work on achieving detection parity with AST-based checkers. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Previously, patterns returned true (OK) when SSA analysis couldn't find the enclosing function or closure, causing false negatives. Now they always fall back to AST-based checking for reliable detection. Changes: - ClosureCapturesCtx: Fall back to AST when SSA fails at any stage - GoStmtCapturesCtx: Fall back to AST when SSA fails at any stage - CallbackReceivesCtx: Remove unused SSA code (was already AST-based) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Implementation Status UpdateCurrent State (Phase 1: Foundation)The SSA infrastructure is now built and integrated:
What Works Now
Why Full Migration is DeferredThe old AST-based checkers in
The new SSA patterns' AST fallback only handles direct FuncLit cases. Full migration requires either:
Next Steps (Phase 2)Option A: SSA Enhancement
Option B: AST Delegation
Option A is cleaner architecturally, Option B is faster to implement. Files Changed |
Improvements to SSA infrastructure for future pattern integration: 1. findSSAValue now handles multiple expression types: - FuncLit: finds MakeClosure instructions - Ident: traces variable declarations to find assigned values - CallExpr: finds SSA Call instructions - SelectorExpr: finds FieldAddr/Field instructions - IndexExpr: finds IndexAddr/Index/Lookup instructions 2. GetContextVars now includes FreeVars: - Captures context variables from enclosing scopes - Essential for nested closure analysis 3. findEnclosingFunc uses syntax range: - Uses full AST syntax range for position checking - Handles cases where GoStmt position precedes FuncLit position Note: These improvements prepare the infrastructure for future migration to SSA-based patterns. Current analyzer still uses AST-based checkers. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Latest Update: SSA Infrastructure EnhancementAdded improvements to the SSA infrastructure to prepare for future pattern-based migration: Changes in Latest Commit1. Enhanced
2. Enhanced
3. Fixed
Current State
Why Migration is Not Activated YetAfter extensive testing, the SSA-based patterns have fundamental differences from AST-based checking:
RecommendationThis PR provides solid SSA infrastructure. The actual migration should be:
|
This commit switches context capture detection from AST-based to SSA-based analysis using FreeVars. Key improvements: - Add ClosureCapturesContext to check FreeVars for context/carrier types - Add FindFuncLit to locate SSA function for FuncLit AST nodes - Fix isContextType to unwrap pointer types (SSA uses *context.Context) - Support carrier types in SSA-based detection Behavioral changes: - Context used in nested closures (defer, IIFE) is now correctly detected - Former LIMITATION cases now pass: ctx in deferred closures, recovery closures, and IIFE are properly recognized as using context Test updates: - Update test cases from [LIMITATION]/[BAD] to [GOOD] for nested closure ctx - Update deriver test cases to [PARTIAL] where ctx capture works but deriver calls in nested closures are not yet traced 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit adds SSA-based deriver function detection that: - Traverses into immediately-invoked function expressions (IIFE) - Distinguishes between regular calls and defer statements - Reports a special error message when deriver is only in defer Key changes: - Add CheckDeriverCalls to SSA tracer with DeriverResult struct - Update GoStmtPattern interface to return GoStmtResult with DeferOnly flag - Add DeferMessage method for defer-specific error messages - Former PARTIAL test cases now pass as GOOD (SSA detects IIFE correctly) Behavioral changes: - Deriver calls in IIFE are now correctly detected - Deriver calls only in defer will report: "goroutine calls X in defer, but it should be called at goroutine start" TODO: Add test case for defer-only scenario 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
🔄 セッション引き継ぎメモ完了した作業
残タスク
関連ファイル
|
defer-only テストケース追加完了追加内容テストケース (
メタテストJSON (3ファイル)
defer 専用メッセージ
|
- Add ArgIsDeriverCall pattern for DoAsync ctx argument checking - Register DoAll/DoAllSettled/DoRace with ShouldCallDeriver (trace through NewTask) - Register DoAllFns/DoAllFnsSettled/DoRaceFns as variadic APIs - Register Task.DoAsync/CancelableTask.DoAsync with ArgIsDeriverCall - Add Variadic flag to registry.API for variable callback arguments - Add MatchesFunc() to deriver.Matcher for direct function matching - Enhance ShouldCallDeriver with NewTask tracing and slice detection - Add variadic expansion detection (tasks...) with "variadic argument" message - Add ordinal formatting (2nd, 3rd) for argument position messages - Fix report position for method chains using selector position - Remove legacy checkers: errgroup, waitgroup, goroutine, goroutinederive, gotask - Add defer-only test cases for goroutinederive 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Session 7: gotask Migration CompleteSummarygotask checker を unified registry pattern に移行完了。全テスト通過。 ChangesNew Pattern:
|
- Create util.go with shared utilities: - funcLitHasContextParam, funcLitUsesContext - extractCallFunc, argUsesContext - findFuncLitAssignment, findFuncLitInAssignment - factoryReturnsContextUsingFunc, returnedValueUsesContext - Prefix pattern-specific helpers to avoid name collisions: - closure_captures_ctx.go: closureCheckFromSSA, closureCheckFactoryCall, etc. - gostmt.go: goStmtCheckFromSSA, goStmtCheckHigherOrder, goStmtFindFuncDecl, etc. - should_call_deriver.go: deriverFindFuncLitAssignmentBefore, etc. - arg_is_deriver_call.go: argDeriverSplitAPIName - Remove duplicate implementations, reducing code by ~230 lines 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Remove duplicate isContextType implementations (patterns, ssa) → Use single typeutil.IsContextType everywhere - Unify funcTypeHasContextParam for FuncLit and FuncDecl → Base function accepts *ast.FuncType - Consolidate findFuncLitAssignment variants → Single function with optional beforePos parameter - Unify factory returns context check logic → blockReturnsContextUsingFunc as common base Result: -95 lines of duplicated code 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
重複コード統合 (e81a031)前回のプレフィックス追加に加えて、実際の重複コードを統合しました。 統合内容
結果
|
…ntext package - Integrate spawner checker into internal/checker - Uses SSA-based ClosureCapturesCtx pattern - Removed internal/checkers/spawner package - Remove internal/context package (now dead code) - All 4 files: context.go, checker.go, finder.go, scope.go - AST-based context checking fully replaced by SSA This completes the SSA unification - all checkers now use SSA-based analysis through the patterns package. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
SSA統合完了 (dd85fea)Phase 1: spawner の unified checker 移行
Phase 2: AST-based context パッケージ削除全てデッドコードになったため削除:
結果
|
- Convert package-level functions to CheckContext methods: - funcTypeHasContextParam, funcLitHasContextParam - FuncLitUsesContext, extractCallFunc, argUsesContext - FindFuncLitAssignment, findFuncLitInAssignment - blockReturnsContextUsingFunc, factoryReturnsContextUsingFunc - returnedValueUsesContext - Reorganize files: - context.go: CheckContext and all its methods - patterns.go: Pattern and GoStmtPattern interfaces only - Update all call sites in pattern implementations 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Create internal/context/context.go with CheckContext and methods - Export all methods used by patterns package - Add type alias in patterns.go for backward compatibility - Update all pattern implementations to use exported method names 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Replace all patterns.CheckContext usages with context.CheckContext to eliminate the type alias and use direct imports consistently. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Move internal/checker/* to internal/ (package internal) - Move internal/checkers/spawnerlabel/ to internal/spawnerlabel/ - Remove redundant checker/checkers directory nesting - Update imports in top-level analyzer.go 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Session 7: Package ReorganizationChanges
Current StructureAll tests passing ✅ |
Package-level Unexported Functions
|
統合可能な重複関数1. FuncSpec + parseFunc + matchesSpec (deriver ↔ spawner)完全重複:
類似:
統合案: // internal/funcspec/funcspec.go
type Spec struct {
PkgPath string
TypeName string
FuncName string
}
func Parse(s string) Spec
func (s Spec) Matches(fn *types.Func) bool2. extractFunc / ExtractCallFunc / GetFuncFromCall3箇所で類似実装:
全て 統合案: 優先度
統合する? |
- Remove CallbackReceivesCtx (dead code, ants support deferred) - Fix HasPrefix bug: conc/pool was incorrectly matching conc - Add MatchPkg to typeutil for proper version suffix handling (/v2, /v3) - Add conc test fixtures to verify generic type support (ResultPool[T], etc.) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
追加変更 (96dc772)削除
バグ修正
追加
|
Rewrites spawnerlabel checker to use SSA analysis for detecting spawn calls in nested closures, IIFEs, and higher-order function returns. Changes: - Add SSA Program to spawnerlabel Checker struct - Implement findSpawnCallSSA() for SSA-based traversal - Add checkReturnedFuncForSpawn() for higher-order return tracking - Add FindFuncDecl() to internal/ssa for FuncDecl lookup - Fix generic function handling using fn.Origin() - Fix variadic function argument handling (slice of functions) - Move SSA build to main run() function for shared use Resolved limitations: - Nested FuncLit spawn now detected (badNestedFuncLitSpawn) - IIFE spawn now detected (badIIFEWithSpawn) - Defer IIFE spawn now detected (badDeferSpawnNestedScope) New limitation: - Unreachable code after panic not detected (SSA eliminates it) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
SSA-based spawnerlabel ImplementationThis commit implements SSA-based spawn detection for the spawnerlabel checker, resolving several previous limitations. Key ChangesCore Implementation:
Bug Fixes:
Resolved Limitations
New Limitation
Test ResultsAll tests pass including metatest validation. |
- Add `-conc` analyzer flag to enable/disable conc checker - Add support for conc/iter APIs: ForEach, ForEachIdx, Map, MapErr - Add support for iter.Iterator and iter.Mapper types - Add support for conc/stream.Stream.Go - Remove dead AST fallback code from spawnerlabel checker - Update documentation 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
進捗と引き継ぎ完了したこと
次のタスク: Registry リファクタリング現在の問題:
提案する設計変更: // 現状
reg.Register(pattern, api1, api2, ...) // 1 Pattern → N APIs
// 変更後
reg.Register(api, patterns...) // 1 API → N Patternsこれにより:
を独立した概念として分離し、API ごとに必要なチェックを組み合わせられる。 例:
変更対象ファイル
|
Refactor the Pattern interface to use a cleaner signature: - Pattern.Check(cctx, callbackArg, taskArg) instead of 5 arguments Introduce clear type hierarchy with *Config suffix for static configs: - TaskConstructorConfig: defines how tasks are constructed (NewTask etc.) - TaskArgumentConfig: combines Constructor + Idx (argument position) - TaskArgument: combines Call (dynamic) + Config (static) This separates static API-level config from dynamic per-call info: - Static: TaskArgumentConfig (from registry.API definition) - Dynamic: TaskArgument.Call (the actual call expression) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Pattern Interface Refactoring DesignProblemCurrent
The name Solution: Wrapper Pattern with Separated InterfacesSplit into purpose-specific interfaces: // For errgroup.Go, DoAllFns - checks the callback argument directly
type CallArgPattern interface {
Name() string
Check(cctx *context.CheckContext, arg ast.Expr) bool
Message(apiName, ctxName string) string
}
// For task.DoAsync - traces receiver back to constructor
type TaskSourcePattern interface {
Name() string
Check(tcctx *TaskCheckContext, call *ast.CallExpr) bool
Message(apiName, ctxName string) string
}
type TaskCheckContext struct {
*context.CheckContext
Constructor *TaskConstructorConfig // How to trace back (e.g., NewTask)
}Key Simplifications
Runner Wrappertype PatternRunner interface {
Run(cctx *CheckContext, call *ast.CallExpr, api *API) (ok bool, msg string)
}
// Wraps CallArgPattern
type callArgRunner struct { pattern CallArgPattern }
// Wraps TaskSourcePattern
type taskSourceRunner struct { pattern TaskSourcePattern }This eliminates type assertions while maintaining type safety. |
…askSourcePattern Separated pattern interfaces by use case for cleaner semantics: - CallArgPattern: for patterns that check callback arguments directly (errgroup.Go, DoAllFns, DoAll with task tracing) - TaskSourcePattern: for patterns that trace task receivers back to constructors (task.DoAsync where task is always the method receiver) - GoStmtPattern.CheckGoStmt renamed to Check for consistency Key changes: - Removed TaskArgumentConfig, TaskArgument, TaskReceiverIdx (simplified) - Added TaskCheckContext embedding CheckContext + Constructor - Registry now has separate RegisterCallArg and RegisterTaskSource methods - API.TaskArgConfig replaced with API.TaskConstructor (simpler) - MatchFunc now returns *API instead of *Entry This fixes the semantic issue where `callbackArg` contained `ctx` for DoAsync, which was misleading. Now DoAsync uses TaskSourcePattern with proper semantics. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Remove API struct and APIKind enum from registry package - Use funcspec.Spec directly in CallArgEntry and TaskSourceEntry - Add FullName() method to funcspec.Spec for message formatting - Update Spec.Matches() to use typeutil.MatchPkg for version suffix support - Simplify registry matching logic using ExtractFunc + Spec.Matches - Add FuncMatch struct for spawnerlabel detection - Add CheckerName() method to all pattern interfaces - Consolidate SSA helpers (ExtractCalledFunc, ExtractIIFE, HasFuncArgs) - Add ShortPkgName helper to typeutil package - Merge detector.go into checker.go in spawnerlabel package 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
API Struct Refactoring CompleteReplaced Key ChangesRemoved:
Added:
Simplified:
StatsNet reduction of ~360 lines while maintaining all functionality. |
…creation
Each Register function now creates its own patterns internally,
removing the need to pass pattern instances from the caller.
Before:
errgroupPatterns := []patterns.CallArgPattern{...}
internal.RegisterErrgroupAPIs(reg, enabled, errgroupPatterns)
After:
internal.RegisterErrgroupAPIs(reg, enabled)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Remaining Refactoring Tasks1. Split
|
Split the 855-line context.go into 5 focused files: - context.go (79 lines): Struct + core helpers - capture.go (196 lines): Context capture detection - assignment.go (137 lines): Assignment tracking - factory.go (210 lines): Factory/return analysis - composite.go (260 lines): Composite type access 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
context.go ファイル分割完了855行あった
Next: |
…runASTChecks - Rename internal/analyzer.go to internal/runner.go for clarity - Move contextScope to internal/context/scope.go as exported Scope type - Inline runASTChecks into analyzer.go's run function - Remove duplicate buildFuncScopes, findContextScope, findEnclosingScope 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Session 7: Analyzer File CleanupChanges Made
File Structure AfterRemaining TODOs
|
…all APIs - Create deriver.Matcher once in analyzer.go, pass to internal functions - Rename matcher to derivers for readability (derivers.SatisfiesAnyGroup) - Remove enabled bool parameters from internal register functions - Apply goroutine-deriver check to errgroup/waitgroup/conc APIs (these spawn goroutines, so deriver check is appropriate) - Add buildCallArgPatterns helper for consistent pattern creation 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Session 7 (continued): API Registration CleanupChanges Made
File Changes |
- Merge RegisterGoroutinePattern and RegisterGoroutineDerivePattern - Now consistent with other Register*APIs functions 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Coverage Analysis: High Priority ImprovementsCurrent overall coverage: 86.0% Top 5 Priorities (based on detection accuracy impact)
RationaleAll 5 are core detection logic paths that directly affect false negatives. Low coverage here means potential missed detections in real codebases. Excluded from priority:
|
- Add variable factory patterns with context parameters - Add index expression tests for slice function access - Add pointer dereference DoAsync tests for gotask - Improve coverage for checkFromAST (60% → 86.7%) - Improve coverage for findConstructorCall (42.9% → 57.1%) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
Add tests for: - Map index expression with string key (covers token.STRING) - Struct field selector patterns - Triple higher-order factory chains (go fn()()()) - Package-level factory functions - Factory from parameter limitation - Returned value from external func These tests improve coverage for: - IndexExprCapturesContext - SelectorExprCapturesContext - funcLitOfLiteralKey - FactoryCallReturnsContextUsingFunc - IdentFactoryReturnsContextUsingFunc 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add tests for: - IIFE containing spawn call (SSA traces into IIFE) - Nested IIFE containing spawn call These tests verify that the spawnerlabel checker correctly detects spawn calls inside immediately invoked function expressions. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
|
Closing to reorganize commits into a cleaner PR |
Summary
This PR introduces the foundation for a new SSA-based pattern registry architecture (Issue #12).
Changes
Architecture Overview
Pattern Classification
Status
The old
internal/checkers/remains in use. Integration will be done in follow-up commits after verification.Why SSA?
Current AST-based approach has limitations:
SSA enables proper dataflow analysis for these cases.
Test plan
🤖 Generated with Claude Code