Skip to content

refactor(core): deepen architecture — rules registry, enricher pipeline, export composition#62

Merged
ryanbas21 merged 1 commit into
mainfrom
refactor/deepen-core-architecture
May 15, 2026
Merged

refactor(core): deepen architecture — rules registry, enricher pipeline, export composition#62
ryanbas21 merged 1 commit into
mainfrom
refactor/deepen-core-architecture

Conversation

@ryanbas21
Copy link
Copy Markdown
Owner

Summary

  • Diagnosis rules registry: Extract 7 collect* functions from 846-line monolith into diagnosis/rules/ modules with FlowRule type and array-based registry. Adding a diagnostic = one file + one array entry.
  • Simplify EventStore interface: Remove setLastOidcEventId method — tracking now happens automatically in updateSummary. All adapters get OIDC event linking for free.
  • Export composition into core: Move exportAsJson/exportAsMarkdown from standalone into devtools-core/src/export/. Eliminates duplicated redact→diagnose→render recipe across 3 call sites.
  • Enricher pipeline: Replace hardcoded detector merge in enrichWithOidcSemantics with OidcEnricher type + enrichers array. Adding a detector = one function + one entry.
  • Narrow barrel: Remove 14 internal-only symbols from public barrel. ~20 organized exports vs 30+ flat.

Test plan

  • All 575 tests pass (pnpm test)
  • Typecheck passes (only pre-existing errors in unrelated eslint-plugin-treeshake)
  • Lint passes — all pre-commit hooks green (eslint, prettier, syncpack)
  • pnpm --filter @wolfcola/devtools-core build succeeds
  • Verify extension loads in Chrome and diagnoses a flow correctly
  • Verify standalone MCP tools (export-json, export-markdown) work

🤖 Generated with Claude Code

Copy link
Copy Markdown
Contributor

@pullfrog pullfrog Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note

Clean refactor. One behavioral change to be aware of: client_id= was removed from the inline-params check in par.ts — this is a correct bugfix per RFC 9126.

TL;DR — Extracts 7 diagnosis rules into a registry, replaces the ad-hoc enricher merge with a pipeline, moves export helpers into core, simplifies the EventStore interface, and narrows the barrel. ~800 lines changed, ~800 removed. Zero behavioral regressions.

Key changes

  • Rules registryFlowRule[] array replaces 7 hardcoded collect* calls in runFlowRules. Adding a diagnostic is one file + one array entry.
  • Enricher pipelineOidcEnricher type + enrichers array replaces the object-spread merge in enrichWithOidcSemantics.
  • Export composition into core — 3 call-sites (extension panel, standalone IPC, MCP tools) now import exportAsJson/exportAsMarkdown from @wolfcola/devtools-core instead of duplicating the redact→diagnose→render recipe.
  • EventStore interface simplificationsetLastOidcEventId removed. updateSummary now auto-tracks lastOidcEventId via event.oidcSemantics. All adapters get OIDC causal linking for free.
  • Barrel narrowed — 14 internal symbols removed from public index. Reorganized into labeled sections.
  • par.ts bugfixclient_id= removed from inline-params-with-request_uri check. RFC 9126 requires client_id alongside request_uri, so flagging it was a false positive.

Summary | 19 files | 1 commit | base: mainrefactor/deepen-core-architecture


Rules registry

Before: 7 collect* functions defined inline in a 774-line diagnosis engine module
After: Each rule is a separate file in diagnosis/rules/, registered in a FlowRule[] array

The extraction is pure — no behavior changed in any rule. The mergeByDedupKey helper stays in diagnosis-engine.ts since it's the engine's concern, not a per-rule concern. The FlowRule type signature is (events: readonly AuthEvent[]) => IssueCandidate[], which is exactly what each extracted function already was.

diagnosis-engine.ts · rules/types.ts · rules/index.ts


Enricher pipeline

Before: Three inline variables (semantics, dpop, par) merged via ad-hoc object spread with a cast
After: OidcEnricher type with enrichers.reduce, same contract

The OidcEnricher type matches the existing convention of the file — the import()-style inline type for OidcConfig is already used in enrichWithOidcSemantics itself, so this is consistent.

message-handler.ts


Export composition

Before: panel.ts, ipc-bridge.ts, and mcp/tools.ts each implemented redact→diagnose→render inline
After: exportAsJson and exportAsMarkdown live in @wolfcola/devtools-core, all three callers import from there

The standalone export-helpers.ts module is gone — its contents are now in packages/devtools-core/src/export/export-transforms.ts. The envelope construction (version, exportedAt, redacted) is centralized.

export-transforms.ts · panel.ts · ipc-bridge.ts


EventStore simplification

Before: setLastOidcEventId in interface, manual yield* store.setLastOidcEventId(id) in handler
After: updateSummary auto-tracks lastOidcEventId — no interface method, no manual calls

This is a textbook "don't ask for state you can derive" improvement. The lastOidcEventId was always derivable from the event being appended; the manual call was a leaky abstraction that every adapter implementor had to remember.

event-store.service.ts · message-handler.ts · event-store-chrome.ts

Pullfrog  | View workflow run𝕏

…ne, export composition

Five architectural improvements to devtools-core:

1. Extract diagnosis rules into registry (diagnosis/rules/)
   - 846-line monolith → 160-line engine + 7 focused rule modules
   - FlowRule type defines internal seam; flowRules array is the registry
   - Adding a diagnostic category = one file + one array entry

2. Simplify EventStore interface
   - Remove setLastOidcEventId from service shape
   - Track lastOidcEventId in updateSummary alongside lastSdkEventId
   - Every adapter gets OIDC tracking automatically via append

3. Move export composition into core
   - exportAsJson/exportAsMarkdown now in devtools-core/src/export/
   - Delete standalone export-helpers.ts; all consumers import from core
   - Eliminates duplicated redact→diagnose→render recipe

4. Refactor detector pipeline with enricher pattern
   - OidcEnricher type + enrichers array replaces hardcoded merge
   - annotateOidc stays as base gate; DPoP/PAR are enrichers
   - Adding a detector = one function + one array entry

5. Narrow barrel exports
   - Remove 14 internal-only symbols from public barrel
   - ~20 organized exports vs 30+ flat exports

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@ryanbas21 ryanbas21 force-pushed the refactor/deepen-core-architecture branch from 48f3203 to aa938a3 Compare May 15, 2026 19:19
Copy link
Copy Markdown
Contributor

@pullfrog pullfrog Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No new issues. Reviewed the following changes:

  • Added .changeset/fix-par-inline-params.md documenting the PAR bugfix
  • Added test coverage verifying client_id alone with request_uri does not trigger the inline-params false positive

Pullfrog  | View workflow run𝕏

@ryanbas21 ryanbas21 merged commit 906d9cc into main May 15, 2026
1 check passed
@ryanbas21 ryanbas21 deleted the refactor/deepen-core-architecture branch May 15, 2026 19:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant