Stack-Aware AI: When Your Go Patterns Go Rogue in TypeScript Land
When your AI starts suggesting `goroutines` for a `React` component, you know you have a problem. This post details our solution to keep AI code patterns relevant to the target tech stack.
Building an AI-assisted development environment is a journey of continuous refinement. We want our AI to be a co-pilot, not a confused back-seat driver. Recently, we hit a snag that's probably familiar to anyone working with multi-language codebases and LLMs: cross-stack pattern pollution.
Our system, designed to enrich notes and load "project wisdom" for AI-driven feature planning, was getting a little too enthusiastic. It was pulling Go-specific code patterns from our CodeMCP (Code Monoculture Patterns) repository and injecting them into contexts explicitly focused on TypeScript/Next.js feature development.
Imagine asking for help with a new React component, and your AI assistant starts suggesting optimal ways to handle goroutine synchronization or manage go.mod dependencies. It's not just confusing; it's noise, it wastes precious AI tokens, and it adds significant cognitive load. This session was all about teaching our AI to stay in its lane.
The Problem: AI Getting Lost in Translation
Our setup leverages a repository of curated code patterns, CodeMCP, to provide context and examples to the LLM. This is fantastic for guiding the AI towards idiomatic solutions. The issue arose because, when generating plans or enriching notes for a TypeScript-centric feature, the system wasn't adequately filtering these patterns. It was blindly pulling all relevant patterns, regardless of the target language, leading to a frustrating blend of Go and TypeScript suggestions.
For example, when planning a new feature for our Next.js frontend, the generated implementation prompt would sometimes include advice like:
// Example of a Go pattern mistakenly injected
func processUserRequest(ctx context.Context, req *UserRequest) (*UserResponse, error) {
// Implement Go-specific logic here
// e.g., using goroutines for concurrent tasks
// or interacting with a Go-based ORM
}
...right alongside perfectly valid TypeScript/tRPC patterns. This clearly wasn't going to fly.
The Solution: Introducing Stack-Aware Filtering
The fix was straightforward in concept: before loading any code patterns for enrichment or workflow wisdom, we needed to detect the target technology stack and filter the available patterns accordingly.
Here's how we implemented it:
1. detectTargetStackFromContent()
We added a new utility function to src/server/services/stack-detector.ts. This function takes a chunk of freeform text (like a feature description, a project note, or a user prompt) and tries to infer the primary technology stack based on keywords.
// src/server/services/stack-detector.ts
type TechStack = 'TypeScript' | 'Go' | 'Unknown';
export function detectTargetStackFromContent(content: string): TechStack {
const lowerContent = content.toLowerCase();
// Prioritize more specific keywords or frameworks
if (/(react|next\.js|typescript|ts|trpc|prisma|javascript|node\.js)/.test(lowerContent)) {
return 'TypeScript';
}
if (/(goroutine|go\.mod|golang|go lang|gin framework|fiber framework)/.test(lowerContent)) {
return 'Go';
}
// Add more stacks as needed (e.g., Python, Rust, Java)
return 'Unknown';
}
This simple regex-based approach is surprisingly effective for our use case. It's not foolproof, but it's a significant improvement over no detection at all.
2. filterReposByTargetStack()
Next, we created a generic helper to filter repositories (or any collection of patterns) based on a detected target stack. This function ensures that only patterns relevant to the inferred stack are considered.
// src/server/services/stack-detector.ts (simplified example)
interface CodePatternRepository {
id: string;
stack: TechStack; // Each repo is tagged with its primary stack
patterns: string[];
}
export function filterReposByTargetStack(
repos: CodePatternRepository[],
targetStack: TechStack
): CodePatternRepository[] {
if (targetStack === 'Unknown') {
// If we can't detect a target, maybe return all or none,
// depending on desired fallback behavior. For now, let's return all.
return repos;
}
return repos.filter(repo => repo.stack === targetStack);
}
3. Integration Points
With these building blocks in place, we integrated the filtering logic into the core parts of our system:
src/server/services/note-enrichment.ts: When a single note is being enriched (e.g., a user writing a new feature idea), we now first detect the target stack from the note's content. Then, we filter theCodeMCPpatterns before feeding them to the LLM.src/server/services/workflow-engine.ts(loadProjectWisdom()): For broader project context, we detect the target stack from the 5 most recent project notes. This gives us a good aggregate sense of the current project's focus, and we apply the same filtering before loading the project's wisdom.
The impact was immediate and satisfying. Our typechecks are clean, and the PoC report has been updated to reflect this crucial fix. No more goroutines showing up in our React plans!
Lessons Learned (The "Pain Log" Revisited)
While this session itself was smooth, it's always good to reflect on persistent lessons:
- Schema Migrations are Sacred (Especially with
pgvector): This is a recurring drumbeat. NEVER usenpx prisma db pushordb push --accept-data-losson production, especially if you're usingpgvectorfor embeddings. It will drop yourembedding vector(1536)columns, leading to data loss and a very bad day. Always, always use a controlled migration script like our./scripts/db-migrate-safe.shthat generates and applies proper SQL migrations. Data integrity is paramount, and a quick-fixdb pushcan be a landmine. - External API Credits are a Real Constraint: The Anthropic API being out of credits halted our Synthesis review steps. It's a stark reminder that even with robust internal systems, external dependencies (and their financial limits) can become critical bottlenecks. Keeping an eye on usage and topping up credits proactively is a mundane but essential operational task.
What's Next? The Road Ahead
With the stack filtering fix implemented and verified, the immediate next steps are clear:
- Commit and Push: Get this crucial fix into
main. - Deploy to Production:
bashThis will bring the new stack-aware filtering logic to our live environment.
cd /opt/nyxcore && \ git pull && \ docker compose -f docker-compose.production.yml build --no-cache app && \ docker compose -f docker-compose.production.yml up -d app - Re-enrich the Project-Onboarding Note: This is the real test. We'll re-run the enrichment process on our key project notes, ensuring that the Go patterns are now correctly filtered out.
- Create New Action Points: From this cleaner, more relevant enrichment, we'll generate fresh action points.
- Create & Run New Workflow: With accurate action points, we can build and execute a new, more focused workflow.
- Top Up Anthropic Credits: Resolve the external API credit issue so our Synthesis review steps can function flawlessly.
- Start Implementing: With a clean slate, accurate context, and a fully operational AI co-pilot, the real building can begin.
This session was a great example of how small, targeted architectural improvements can have a massive impact on the quality and usability of an AI-powered developer tool. Context is king, and ensuring our AI understands the current tech stack is fundamental to its effectiveness.
{
"thingsDone": [
"Added detectTargetStackFromContent() to src/server/services/stack-detector.ts for technology keyword scanning.",
"Added filterReposByTargetStack() to src/server/services/stack-detector.ts to filter code pattern repositories by detected language stack.",
"Updated src/server/services/note-enrichment.ts to detect target stack from note content and filter mismatched code patterns.",
"Updated src/server/services/workflow-engine.ts loadProjectWisdom() to detect target stack from recent project notes and apply filtering.",
"Updated docs/reports/2026-03-15-image-to-implementation-pipeline-poc.md section 4.3 to document the cross-stack issue and its fix."
],
"pains": [
"Prior session pain: Accidental pgvector embedding column loss due to incorrect 'db push' usage on production; emphasized using safe migration scripts.",
"Anthropic API out of credits, preventing Synthesis review steps from functioning."
],
"successes": [
"Successfully implemented cross-stack code pattern filtering.",
"All typechecks are clean after implementation.",
"Proof-of-concept report updated with the fix details.",
"Improved relevance and quality of AI-generated code patterns and suggestions."
],
"techStack": [
"TypeScript",
"Next.js",
"Go",
"tRPC",
"Prisma",
"PostgreSQL",
"pgvector",
"Docker",
"Git",
"Anthropic API",
"LLM (Large Language Model)"
]
}