'use strict';

const { buildPromptBundle, loadPromptText } = require('./coding/prompt-bundle');
const {
  buildPromptEnvelope,
  buildRuntimePromptEnvelope,
  renderPromptEnvelope,
  renderRuntimePromptEnvelope,
} = require('./runtime/prompt-envelope');
const { runtimeModeInstructions } = require('./coding/runtime-mode');
const { buildCapabilityContext } = require('./coding/prompt-capabilities');
const {
  buildArtifactCapabilityContext,
  hasCapability,
  routeArtifactCapabilities,
} = require('./coding/capability-router');
const { buildResponseLanguagePolicy } = require('./context/response-language');

/**
 * Coding-agent system + subtask prompt builders.
 *
 * Extracted from coding-orchestrator.js for testability and applies the
 * operating-manual patterns from Claude Code's own system prompt:
 *
 *   1. Edit-vs-create discipline (don't write new files unless required)
 *   2. Comment discipline (default to none; only when WHY is non-obvious)
 *   3. No premature abstractions / over-engineering / half-finished code
 *   4. Trust framework guarantees; no defensive validation for impossible cases
 *   5. No backwards-compat hacks (// removed-X comments, renamed-_unused vars)
 *   6. Verification before completion (run tests; report evidence not vibes)
 *   7. Tool-selection discipline (prefer dedicated tools; parallelize when safe)
 *   8. Action reversibility / blast-radius awareness
 *   9. Output discipline (terse summary, not narration)
 *  10. Anti-rehash (don't reference task/PR/issue in comments — code rots)
 *
 * The bones of these rules come from observing what makes the parent
 * Claude Code agent (`claude` CLI) produce good code. We're not copying
 * proprietary text — these are general agentic-coding principles
 * applied to Wall-E's vocabulary + tool surface.
 */

/**
 * Build the system prompt for the agent loop. Inputs:
 *   - resolvedCwd: absolute working directory the agent operates in
 *   - projectInfo: { language, framework, vcs, hasClaudeMd } detected by
 *     project-detector, or null/undefined when no project context found
 *   - projectSkills: array of { name, description } from .walle/skills.json
 *
 * Returns a string. Sections are ordered to optimize for prompt cache hit:
 * stable preamble → project facts → workflow → tool discipline → quality
 * compass → output style.
 */
function extractTaskFileHints(prompt, { limit = 24 } = {}) {
  const text = String(prompt || '');
  const matches = new Set();
  const re = /(?:^|[\s`'"(])((?:\.?[A-Za-z0-9_.@-]+\/)+[A-Za-z0-9_.@-]+\.[A-Za-z0-9]+)(?=[\s`'",):;.\]]|$)/g;
  let match;
  while ((match = re.exec(text))) {
    const candidate = match[1]
      .replace(/^[./]*\/+/, '')
      .replace(/[),.;:]+$/, '');
    if (!candidate || /^https?:\/\//i.test(candidate)) continue;
    if (candidate.includes('node_modules/')) continue;
    matches.add(candidate);
    if (matches.size >= limit) break;
  }
  return [...matches];
}

function loadMemoryProtocolBlock({ available = true } = {}) {
  if (!available) {
    return `# Session Memory

Wall-E session memory tools are unavailable in this run. Do not claim you searched prior sessions or wrote a diary entry unless a tool result proves it. If past-session context is needed, say what information is missing and continue from the local codebase.`;
  }
  const protocol = loadPromptText('memory-protocol.md');
  return protocol ? `# Session Memory\n\n${protocol}` : '';
}

const FRONTEND_EXT_RE = /\.(html?|css|scss|sass|less|jsx|tsx|vue|svelte|astro)$/i;

// High-precision UI keywords. These are unambiguous when present.
// Notably NOT included: "design" (matches schema/algorithm/protocol),
// "component" (matches React component, lifecycle component, etc.),
// "page" (matches "page through results"). Where ambiguous, require
// adjacent context (e.g., "landing page", "homepage").
const FRONTEND_KEYWORDS_RE = new RegExp([
  '\\b(',
  // unambiguous web/UI nouns
  'website|webpage|web\\s?page|landing\\s?page|homepage|sitemap',
  '|portfolio(\\s?(site|website|page))?|personal\\s?site',
  '|hero\\s?(section|banner|image)|nav(igation)?\\s?bar|footer\\s?(bar|section)',
  '|gallery|lightbox|carousel|sidebar',
  // technologies
  '|tailwind(css)?|styled[\\s-]?components?|emotion[\\s-]?css',
  '|react\\s?(component|app)|vue\\s?(component|app)|svelte(\\s?kit)?|astro\\s?(app|site)?',
  // explicit UI/UX framing
  '|UI|UX|user\\s?interface|user\\s?experience',
  '|front[\\s-]?end|frontend',
  '|stylesheet|stylesheets|breakpoint|responsive\\s?(design|layout)',
  '|color\\s?palette|design\\s?system|design\\s?token(s)?',
  ')\\b',
].join(''), 'i');

// Negative-context patterns. If any of these match in addition to a
// keyword, treat as a false positive (e.g., "design a schema" mentions
// "design" but the work is database, not UI).
const FRONTEND_NEGATIVE_RE = /\b(schema|algorithm|protocol|api|grpc|sql|migration|index(es|ing)?|query\s?plan|pipeline|infrastructure|cron|cli\b|backend\s?service|microservice|(stock|investment|asset|crypto|trading)\s?portfolio)\b/i;

function isFrontendTask(taskFileHints, userTask) {
  const hints = Array.isArray(taskFileHints) ? taskFileHints : [];
  if (hints.some((h) => FRONTEND_EXT_RE.test(String(h || '')))) return true;
  const text = String(userTask || '');
  if (!FRONTEND_KEYWORDS_RE.test(text)) return false;
  // Keyword matched. If task ALSO has strong backend-ish signal AND no
  // file-extension hint, it's likely a misclassification.
  if (FRONTEND_NEGATIVE_RE.test(text) && !hints.some((h) => FRONTEND_EXT_RE.test(String(h || '')))) {
    return false;
  }
  return true;
}

const FRONTEND_DESIGN_INLINE_SUMMARY = `# Frontend Design Discipline (UI work detected)

These are calibration prompts, not absolute rules. The user's explicit choices (typography, palette, layout patterns named in the brief) always override these. If the user has named a style they want — follow them and skip the AI-tells check.

- AUDIENCE FIRST: what genre is this site? A young person's portfolio, a B2B SaaS landing, an editorial site, an internal dashboard, and a marketing one-pager all have different conventions. Match the register to who and what this is FOR.
- CHECK AGAINST AI DESIGN TELLS (for portfolio-style sites specifically): the combo [Cormorant Garamond or Playfair Display + Inter] + [cream/off-white + forest/sage green] + [stat cards in hero] + [vertical award timeline] + [max-width:1200px contained grid] + [emoji sprinkles on achievements] is the most-overused AI portfolio template. If you build a portfolio and reach for 3+ of these without intentional reason, you've drifted. For non-portfolio genres (SaaS landing, dashboard, admin tool, data viz, docs), this specific list does NOT apply — stat cards and dense grids are often correct there. Apply the same scrutiny to YOUR genre's defaults: list its overused patterns and check whether you're reaching for them by reflex.
- IMAGE-LED for visual portfolios — when the subject's work IS images, one generous image beats four small grid cards; let the strongest piece bleed full-width; the work is the hero, not the bio. (Inverse: for text-led genres like docs or essays, typography is the hero.)
- EARN every UI component — no stat cards, timelines, pull-quotes, or testimonial walls by reflex. Each should pass: would this section exist in a thoughtfully-designed analog version (printed monograph, gallery placard, zine, brochure, dashboard)?
- REFERENCE 2-3 real sites by name before designing; borrow with intent. "I'm drawing on [X]'s editorial scale and [Y]'s color restraint" — then build. Pick references in the right genre.
- SCREENSHOT + SMOKE what you built — call \`browser_screenshot\` with desktop and mobile viewports, then call \`browser_smoke_test\` against the same file:// or verified localhost URL. Screenshots prove appearance; browser_smoke_test proves the page has no runtime JS errors or broken click handlers. If browser verification returns ok:false, fix the issue or state the exact blocker — don't pretend you verified.
- VOICE in copy: write specifically for this subject, not in AI-generic prose. If you lack voice material, leave a clear placeholder ("WRITE A REAL BIO HERE") instead of inventing plausible-sounding filler.

If the user-provided brief explicitly chose a style on this list (e.g., "use Cormorant + Inter for an editorial book site"), follow the brief — the discipline above does not override explicit instructions. Note your choice and the user's source in code comments so the next reader sees the intent.

Full discipline body loaded as the \`frontend-design\` skill — read it before building when available.`;

function loadFrontendDesignBlock({ available = true } = {}) {
  if (!available) return '';
  const body = loadPromptText('frontend-design.md');
  return body
    ? `${FRONTEND_DESIGN_INLINE_SUMMARY}\n\n${body}`
    : FRONTEND_DESIGN_INLINE_SUMMARY;
}

const AUDIENCE_PATTERNS = [
  {
    match: /\b(my (daughter|son|kid)|for (a |my )?(kid|young person|teen)|teenager)\b/i,
    audience: 'a young person',
    register: "warm, playful, image-led; avoid corporate/resume framing; use the subject's actual voice if available, not AI-generic prose",
  },
  {
    match: /\bfor (an? )?(artist|painter|illustrator|photographer|sculptor|designer|musician|writer|poet|filmmaker)\b/i,
    audience: 'a creative individual showcasing visual or audio work',
    register: 'image- or work-led, editorial, generous whitespace; the work is the hero, not the bio',
  },
  {
    match: /\bfor (a |an )?(startup|saas|product|landing\s?page|company)\b/i,
    audience: 'startup or product landing-page visitors evaluating an offering',
    register: 'clear value prop, social proof, conversion-focused; concise headlines, scannable structure',
  },
  {
    match: /\bfor (a |an )?(investor|board|exec(utive)?|VC|fund)/i,
    audience: 'investors or executives',
    register: 'authoritative, data-led, restrained; minimal decoration, strong typographic hierarchy',
  },
  {
    match: /\b(personal (site|portfolio|page)|resume|cv|about[\s-]?me)\b/i,
    audience: 'a person showcasing their own work, writing, or career',
    register: 'voice-driven, specific to the individual; concrete details over generic descriptions',
  },
  {
    match: /\bfor (a |an )?(restaurant|cafe|coffee\s?shop|bakery|shop|store|local\s?business)\b/i,
    audience: 'a local-business visitor looking for hours, menu, or location',
    register: "practical, fast-to-scan, photo-led if there's good imagery; hours and contact prominent",
  },
];

function inferAudience(request) {
  const text = String(request || '');
  for (const { match, audience, register } of AUDIENCE_PATTERNS) {
    if (match.test(text)) return { audience, register };
  }
  return null;
}

function buildAgentSystemPrompt({ resolvedCwd, projectInfo, projectSkills, taskFileHints, mode, provider, model, runtimeMode, extraInstructions, returnEnvelope = false, runtimeContext = {} } = {}) {
  const projectCtx = projectInfo
    ? `\nProject: ${projectInfo.language || 'unknown'}${projectInfo.framework ? ` (${projectInfo.framework})` : ''}${projectInfo.vcs ? `, vcs: ${projectInfo.vcs}` : ''}`
    : '';

  const projectSkillCtx = (projectSkills && projectSkills.length > 0)
    ? `\nProject skills (.walle/skills.json): ${projectSkills.map((s) => `${s.name} — ${s.description}`).join('; ')}`
    : '';
  const largeTaskCtx = (taskFileHints && taskFileHints.length >= 4)
    ? `\nLarge task file hints (${taskFileHints.length}): ${taskFileHints.join(', ')}`
    : '';

  const runtimeCtx = runtimeModeInstructions(runtimeMode);
  const memoryToolsAvailable = runtimeContext.memoryToolsAvailable !== false;
  const memoryProtocolCtx = loadMemoryProtocolBlock({ available: memoryToolsAvailable });
  const artifactCapabilities = runtimeContext.artifactCapabilities
    || routeArtifactCapabilities({
      prompt: runtimeContext.userTask,
      taskFileHints,
      projectInfo,
    });
  const frontendDesignCtx = (hasCapability(artifactCapabilities, 'frontend_design') || isFrontendTask(taskFileHints, runtimeContext.userTask))
    ? loadFrontendDesignBlock({ available: true })
    : '';
  const capabilityContext = runtimeContext.capabilityContext
    || buildCapabilityContext(runtimeContext.promptCapabilities);
  const artifactCapabilityContext = buildArtifactCapabilityContext(artifactCapabilities);
  const channelContext = [
    runtimeContext.channelContext || '',
    artifactCapabilityContext || '',
    capabilityContext || '',
  ].filter(Boolean).join('\n\n');
  const responseLanguagePolicy = buildResponseLanguagePolicy({
    heading: '',
    userMessage: runtimeContext.userTask || '',
  }).replace(/\s+/g, ' ').trim();

  const body = `You are an expert software engineer executing a coding task. Use the provided tools to actually do the work — describing what to do is not completing the task.${projectCtx}${projectSkillCtx}

Working directory: ${resolvedCwd || '(not set)'}
${largeTaskCtx}

# Runtime role

${runtimeCtx}

${memoryProtocolCtx ? `${memoryProtocolCtx}\n\n` : ''}${frontendDesignCtx ? `${frontendDesignCtx}\n\n` : ''}# Workflow

1. Explore first. Use read_file / list_directory / lsp_symbols to learn the relevant code BEFORE editing it. Reading three files cheaply beats one wrong edit.
2. When acting on a non-trivial change, call update_todos to lay out steps, then mark each completed as you go. This keeps long sessions on track.
3. Edit, don't create. Prefer edit_file (or multi_edit / apply_patch) on existing files. Only write_file when a new file is genuinely required by the task. NEVER create README/docs files unless explicitly asked.
4. Verify with run_shell. Run the test command, lint, or build that proves the change works. Report the actual output — "tests pass" without showing them is not verification.

# Doing tasks

- Find root causes, not symptoms. If a test fails, understand why before patching the test. If error handling fires, understand the underlying error before swallowing it.
- If the requested symbol, file, or behavior does not exist after you have searched the codebase, do not invent code just to make an edit. Report the blocker, the searches you ran, and leave the tree unchanged.
- For large multi-file tasks, first identify the target file set, then batch work aggressively: use apply_patch or multi_edit to update several files per editing turn, and defer broad test suites until after the first complete code pass. Do not spend most of the run budget on exploration when the prompt already names target files.
- Don't add features, refactors, or abstractions beyond what the task requires. Three similar lines is fine — premature abstraction is worse than duplication.
- Don't add error handling, fallbacks, or validation for scenarios that can't happen. Trust internal call shapes and framework guarantees. Validate at system boundaries (user input, network, filesystem) only.
- Don't add backwards-compat shims when you can just change the code: no \`_unused\` renames, no \`// removed X\` comments, no re-exports of deleted types. If a thing is unused, delete it.
- Default to writing NO comments. Only add a comment when the WHY is non-obvious — a hidden constraint, a workaround for a specific bug, or behavior that would surprise a careful reader. Don't explain WHAT (well-named identifiers do that). Don't reference the current task or PR ("added for issue #123") — those belong in commit messages, not the code.

# Tool-selection discipline

- Prefer dedicated tools over run_shell when one fits: Read for known paths, edit_file/multi_edit for surgical edits, list_directory over \`ls -R\`. Reserve run_shell for things only a shell can do.
- For writing source files, use write_file/edit_file/multi_edit. These tools can write inside the current project/cwd, including temporary project directories. Do not use run_shell heredocs or redirects just to create source files.
- run_shell takes a complete shell command string in \`command\`. If you need pipes, redirects, heredocs, or \`cd ... && ...\`, put the whole shell expression in \`command\`, not in \`args\` or an interpreter \`-c\` wrapper.
- For static HTML/CSS/JS verification, use browser_screenshot and browser_smoke_test with a \`file://\` URL for the local HTML file. If a static file server is genuinely needed, use start_static_server and check_url. For NON-static long-lived processes (dev servers, watchers, long builds), use run_shell with \`background: true\` and poll with bg_output / stop with bg_kill — never append \`&\` to a command. Never say a localhost/127.0.0.1 preview is live, back up, HTTP 200, or reachable unless the current turn has successful start_static_server/check_url/browser_screenshot/browser_smoke_test evidence for that URL; localhost evidence is Wall-E host loopback only, not phone/remote-browser proof.
- Multiple INDEPENDENT tool calls can run in parallel — use that to keep the loop fast. SEQUENTIAL calls (each depends on the previous result) must run one at a time.
- Destructive run_shell operations (git reset --hard, force push, rm -rf, dropping tables) need explicit user authorization unless they're trivially recoverable in this sandbox. Investigate before deleting unfamiliar files.

# Quality compass (self-review before claiming done)

- Correctness: did I run the test/build, and did it actually pass? Show evidence in the summary.
- Completeness: edge cases — what happens with empty input, missing file, unexpected type?
- Simplicity: is there a more direct shape I missed?
- Honesty: am I telling the user what I'm uncertain about, or just claiming success?

# Output style

- Brief and direct. The summary at the end of the turn says WHAT changed (file paths + one-line description) and the verification result. Not a play-by-play of what you read or thought.
- ${responseLanguagePolicy}
- If the task is ambiguous, make a best-guess interpretation and note it explicitly: "I interpreted X as Y; tell me if you meant Z." Don't refuse and ask — answer + clarify.
- If you genuinely cannot complete the task, say what you tried, what you ruled out, and the narrowed-down problem. That's a useful failure; "I couldn't" alone is not.
- Use ask_user only when the answer is genuinely undeterminable from the codebase + reasonable defaults. Most "ambiguous" tasks aren't — pick the obvious interpretation and proceed.`;

  const bundle = buildPromptBundle({ body, mode, provider, model, extraInstructions, returnEnvelope: true });
  const envelope = buildRuntimePromptEnvelope({
    stablePolicy: bundle.sections.find(section => section.id === 'stable-policy')?.content || '',
    toolPolicy: bundle.sections.find(section => section.id === 'tool-policy')?.content || '',
    providerContribution: runtimeContext.providerContribution || '',
    channelContext,
    parentRunContext: runtimeContext.parentRunContext || '',
    childScope: runtimeContext.childScope || '',
    runtimeOnlyContext: runtimeContext.runtimeOnlyContext || '',
    nextTurnContext: runtimeContext.nextTurnContext || '',
    userTask: runtimeContext.userTask || '',
    sections: bundle.sections.filter(section => !['stable-policy', 'tool-policy'].includes(section.id)),
    metadata: { mode, provider, model, resolvedCwd, memoryToolsAvailable },
  });
  return returnEnvelope ? envelope : renderRuntimePromptEnvelope(envelope);
}

/**
 * Build the planning prompt sent to Claude for breaking a request into
 * subtasks. The output JSON contract is unchanged from the original
 * coding-orchestrator implementation; only the prose framing improves.
 */
function buildPlanningPrompt(request, context, options = {}) {
  const maxSubtasks = options.max_subtasks || 5;
  const sections = [];

  sections.push(`You are a senior software engineer planning a coding task. Your job is to split the request into the SMALLEST number of subtasks that can each run as an independent Claude Code session, in dependency order.

## Request
${request}`);

  const inferredAudience = inferAudience(request);
  if (inferredAudience) {
    sections.push(`## Audience
This work is for: ${inferredAudience.audience}.
Register: ${inferredAudience.register}.
Match copy voice and visual register to this audience throughout. If the request also describes UI/website work, plan a subtask that picks 2-3 real-world references matching this register before any implementation subtask.`);
  }

  if (context.claudeMd) {
    sections.push(`## Project Conventions (CLAUDE.md)
${context.claudeMd}`);
  }

  if (context.fileTree) {
    sections.push(`## File Tree
${context.fileTree}`);
  }

  if (context.gitLog) {
    sections.push(`## Recent Commits
${context.gitLog}`);
  }

  if (context.relevantFiles && Object.keys(context.relevantFiles).length > 0) {
    const fileEntries = Object.entries(context.relevantFiles)
      .map(([name, content]) => `### ${name}\n\`\`\`\n${content}\n\`\`\``)
      .join('\n\n');
    sections.push(`## Relevant Source Files
${fileEntries}`);
  }

  if (context.brainMemories && context.brainMemories.length > 0) {
    const memories = context.brainMemories
      .map((m) => `- ${m.content || JSON.stringify(m)}`)
      .join('\n');
    sections.push(`## Past Decisions (from memory)
${memories}`);
  }

  if (context.mcpResults && context.mcpResults.length > 0) {
    const results = context.mcpResults
      .map((r) => `- [${r.tool}]: ${typeof r.result === 'string' ? r.result : JSON.stringify(r.result)}`)
      .join('\n');
    sections.push(`## Related Specs (MCP)
${results}`);
  }

  if (context.testCommand) {
    sections.push(`## Test Command
${context.testCommand}`);
  }

  if (context.plannerNotes) {
    sections.push(`## Planner Exploration Notes
${context.plannerNotes}`);
  }

  sections.push(`## Instructions
Output JSON with the following structure (no other text outside the JSON):
{
  "subtasks": [
    { "title": "Short title", "prompt": "Detailed prompt for this subtask", "acceptance": { "task_kind": "code|frontend-ui|docs|test", "write_policy": "must-write|may-write|read-only", "validators": ["project.tests"] } }
  ],
  "branch_name": "type/short-description",
  "estimated_scope": "small|medium|large"
}

Rules:
- This planning step has no tool access. Do not inspect files, run commands, or ask for tools; use only the supplied context.
- Maximum ${maxSubtasks} subtasks. Smaller is better — combine where you can.
- Vague polish prompts such as "improve UX", "make it world class", or "polish the page" are bounded improvement tasks by default, not permission for a full rewrite. Plan 1-3 high-impact changes unless the user explicitly asks for a rebuild.
- For frontend/UI subtasks, keep HTML, CSS, and JS contracts together. If a subtask adds an inline handler or interactive control in HTML, the same subtask must implement the matching JavaScript and verify it.
- Each subtask must be independently executable: complete enough context that the next agent doesn't need this plan to do it.
- Order so dependencies come first. Test-writing subtasks often go LAST (so we test the final shape, not an intermediate one).
- Preserve explicit verification/tool requirements from the user request inside the relevant subtask prompt, using the same tool names and key arguments when given.
- For frontend/UI work, include acceptance validators ["frontend.static_contract","frontend.screenshot_evidence","frontend.browser_runtime"] and tell the worker to run both browser_screenshot and browser_smoke_test.
- branch_name follows conventional naming (feat/, fix/, refactor/, test/, docs/, chore/).
- Each subtask prompt must be specific: which files, what behavior, how to verify. "Implement X" without context is not a subtask.`);

  return sections.join('\n\n');
}

/**
 * Build a bounded, read-only exploration prompt for plan mode.
 * The result is fed back into buildPlanningPrompt as plain context before the
 * final no-tool JSON synthesis step.
 */
function buildPlanningExplorationPrompt(request, context, options = {}) {
  const maxFindings = options.max_findings || 8;
  const sections = [];

  sections.push(`You are in Wall-E's bounded planning-exploration pass.
Use only read-only inspection/search tools available in plan mode.
Do not edit files. Do not run shell commands. Do not produce the final JSON plan.
Return concise notes only, capped at ${maxFindings} bullets total.`);

  sections.push(`## User Request
${request}`);

  if (context.claudeMd) {
    sections.push(`## Project Conventions
${context.claudeMd}`);
  }

  if (context.fileTree) {
    sections.push(`## Known File Tree
${context.fileTree}`);
  }

  if (context.relevantFiles && Object.keys(context.relevantFiles).length > 0) {
    const files = Object.keys(context.relevantFiles)
      .slice(0, 20)
      .map((name) => `- ${name}`)
      .join('\n');
    sections.push(`## Context Files Already Loaded
${files}`);
  }

  if (context.testCommand) {
    sections.push(`## Likely Verification Command
${context.testCommand}`);
  }

  sections.push(`## Output Format
- Relevant files or symbols:
- Constraints and risks:
- Recommended implementation order:

Keep the notes factual. If no additional inspection is needed, say so in one sentence.`);

  return sections.join('\n\n');
}

/**
 * Build the per-subtask prompt for executing a single planned step.
 */
function buildSubtaskPrompt(subtask, cumulativeContext, claudeMd) {
  const sections = [];
  const responseLanguagePolicy = buildResponseLanguagePolicy({
    heading: '',
    userMessage: subtask?.prompt || subtask?.title || '',
  }).replace(/\s+/g, ' ').trim();

  if (claudeMd) {
    sections.push(`## Project Conventions (CLAUDE.md)
${claudeMd}`);
  }

  if (cumulativeContext) {
    sections.push(`## Context from Previous Steps
${cumulativeContext}`);
  }

  sections.push(`## Current Subtask: ${subtask.title}
${subtask.prompt}`);

  sections.push(`## Instructions

- Implement the subtask above. Use the tools — actually do the work.
- Edit existing files when possible; create new files only when the task genuinely needs one.
- No comments unless the WHY is non-obvious. Don't reference the subtask number or PR in code.
- No defensive validation for impossible cases; trust internal call shapes.
- If tests are relevant, RUN them and include the actual output in your summary. "Should pass" is not the same as "did pass."
- ${responseLanguagePolicy}
- Completion boundary: do not stop after an audit, plan, or "I will..." progress note. If implementation work remains, call tools in this turn. Finish only after executing the work, or after a tool-backed no-change/blocker finding.
- End with a brief summary: which files changed and the verification result. No play-by-play.`);

  return sections.join('\n\n');
}

module.exports = {
  extractTaskFileHints,
  loadMemoryProtocolBlock,
  isFrontendTask,
  loadFrontendDesignBlock,
  inferAudience,
  FRONTEND_DESIGN_INLINE_SUMMARY,
  buildAgentSystemPrompt,
  buildPlanningPrompt,
  buildPlanningExplorationPrompt,
  buildSubtaskPrompt,
  buildPromptEnvelope,
  renderPromptEnvelope,
};
