{"version":3,"sources":["../src/config/loader.ts","../src/memlog/memlog.ts","../src/artifacts/writer.ts","../src/templates/spec-template.ts","../src/templates/story-template.ts","../src/agents/registry.ts"],"names":["resolve","existsSync","readFileSync","mkdirSync","writeFileSync"],"mappings":"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","file":"index.mjs","sourcesContent":["import { readFileSync, existsSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport { load } from \"js-yaml\";\n\nexport interface CodewrightConfig {\n  codewright_version: string;\n  project_name: string;\n  stack: string;\n  communication_language: string;\n  output_folder: string;\n  context_file: string;\n\n  // Auto-detected fields\n  framework?: string;\n  test_runner?: string;\n  lint_tools?: string[];\n  project_language?: string;\n  strict_mode?: boolean;\n}\n\nconst DEFAULTS: CodewrightConfig = {\n  codewright_version: \"0.1.0\",\n  project_name: \"\",\n  stack: \"node\",\n  communication_language: \"en\",\n  output_folder: \".codewright-output\",\n  context_file: \".codewright-output/project-context.md\",\n};\n\nfunction loadYaml(path: string): Record<string, unknown> {\n  if (!existsSync(path)) return {};\n  try {\n    const raw = readFileSync(path, \"utf-8\");\n    return (load(raw) as Record<string, unknown>) || {};\n  } catch {\n    return {};\n  }\n}\n\nfunction mergeConfigs(\n  ...sources: Record<string, unknown>[]\n): CodewrightConfig {\n  const merged: Record<string, unknown> = { ...DEFAULTS };\n  for (const src of sources) {\n    Object.assign(merged, src);\n  }\n  return merged as unknown as CodewrightConfig;\n}\n\nexport function loadConfig(cwd: string): CodewrightConfig {\n  const projectConfig = loadYaml(resolve(cwd, \".codewright\", \"config.yaml\"));\n  const userConfig = loadYaml(resolve(cwd, \".codewright\", \"config.user.yaml\"));\n  return mergeConfigs(projectConfig, userConfig);\n}\n\nexport function resolveOutputDir(cwd: string, config: CodewrightConfig): string {\n  return resolve(cwd, config.output_folder);\n}\n\nexport function resolveSpecDir(cwd: string, config: CodewrightConfig, slug: string): string {\n  return resolve(resolveOutputDir(cwd, config), \"specs\", `spec-${slug}`);\n}\n\n/** Resolve {template} variables in a string using the config */\nexport function resolveTemplates(input: string, config: CodewrightConfig): string {\n  const vars: Record<string, string> = {\n    \"project-root\": process.cwd(),\n    \"output-folder\": config.output_folder,\n    \"skills-dir\": \".agents/skills\",\n    \"config-dir\": \".codewright\",\n    \"project-name\": config.project_name || \"\",\n  };\n  return input.replace(/\\{(\\w[\\w-]*\\w|\\w)\\}/g, (_, key) => vars[key] || `{${key}}`);\n}\n","import { readFileSync, writeFileSync, existsSync, mkdirSync } from \"node:fs\";\nimport { dirname, resolve } from \"node:path\";\n\nexport interface MemlogEntry {\n  type:\n    | \"decision\"\n    | \"constraint\"\n    | \"capability\"\n    | \"assumption\"\n    | \"question\"\n    | \"direction\"\n    | \"note\"\n    | \"event\";\n  text: string;\n  by?: string;\n}\n\nexport interface MemlogData {\n  frontmatter: Record<string, string>;\n  entries: MemlogEntry[];\n}\n\nfunction frontmatterToString(fm: Record<string, string>): string {\n  const lines = [\"---\"];\n  for (const [k, v] of Object.entries(fm)) {\n    if (v) lines.push(`${k}: ${v}`);\n  }\n  lines.push(\"---\", \"\");\n  return lines.join(\"\\n\");\n}\n\nfunction frontmatterFromString(raw: string): { frontmatter: Record<string, string>; body: string } {\n  const frontmatter: Record<string, string> = {};\n  if (!raw.startsWith(\"---\")) return { frontmatter, body: raw };\n\n  const endIndex = raw.indexOf(\"---\", 3);\n  if (endIndex === -1) return { frontmatter, body: raw };\n\n  const fmBlock = raw.slice(3, endIndex).trim();\n  const body = raw.slice(endIndex + 3).trim();\n\n  for (const line of fmBlock.split(\"\\n\")) {\n    const colonIdx = line.indexOf(\":\");\n    if (colonIdx > 0) {\n      const key = line.slice(0, colonIdx).trim();\n      const value = line.slice(colonIdx + 1).trim();\n      frontmatter[key] = value;\n    }\n  }\n\n  return { frontmatter, body };\n}\n\nfunction entryToLine(entry: MemlogEntry): string {\n  const by = entry.by ? ` @${entry.by}` : \"\";\n  return `- (${entry.type}) ${entry.text}${by}`;\n}\n\nfunction lineToEntry(line: string): MemlogEntry | null {\n  const match = line.match(/^\\s*-\\s*\\((\\w+)\\)\\s+(.+)/);\n  if (!match) return null;\n  const type = match[1] as MemlogEntry[\"type\"];\n  const rest = match[2];\n  const byMatch = rest.match(/(.+?)\\s+@(\\S+)$/);\n  if (byMatch) {\n    return { type, text: byMatch[1].trim(), by: byMatch[2] };\n  }\n  return { type, text: rest.trim() };\n}\n\nfunction getPath(ws: string): string {\n  return resolve(ws, \".memlog.md\");\n}\n\nfunction ensureDir(fp: string) {\n  const dir = dirname(fp);\n  if (!existsSync(dir)) mkdirSync(dir, { recursive: true });\n}\n\nfunction init(workspace: string, fields: Record<string, string>) {\n  const fp = getPath(workspace);\n  ensureDir(fp);\n  const fm = frontmatterToString({ ...fields, updated: new Date().toISOString() });\n  // Use atomic write\n  const tmp = fp + \".tmp\";\n  writeFileSync(tmp, fm, \"utf-8\");\n  writeFileSync(fp, fm, \"utf-8\");\n}\n\nfunction append(workspace: string, entry: MemlogEntry) {\n  const fp = getPath(workspace);\n  ensureDir(fp);\n  const existing = existsSync(fp) ? readFileSync(fp, \"utf-8\") : \"\";\n\n  let frontmatter: Record<string, string> = {};\n  let body: string;\n\n  if (existing.startsWith(\"---\")) {\n    const parsed = frontmatterFromString(existing);\n    frontmatter = parsed.frontmatter;\n    body = parsed.body;\n  } else {\n    body = existing.trim();\n  }\n\n  frontmatter.updated = new Date().toISOString();\n  const newLine = entryToLine(entry);\n  const content = frontmatterToString(frontmatter) + (body ? body + \"\\n\" : \"\") + newLine + \"\\n\";\n\n  const tmp = fp + \".tmp\";\n  writeFileSync(tmp, content, \"utf-8\");\n  writeFileSync(fp, content, \"utf-8\");\n}\n\nfunction set(workspace: string, key: string, value: string) {\n  const fp = getPath(workspace);\n  ensureDir(fp);\n  const existing = existsSync(fp) ? readFileSync(fp, \"utf-8\") : \"\";\n  const { frontmatter, body } = frontmatterFromString(existing);\n  frontmatter[key] = value;\n  frontmatter.updated = new Date().toISOString();\n  const content = frontmatterToString(frontmatter) + (body || \"\");\n\n  const tmp = fp + \".tmp\";\n  writeFileSync(tmp, content, \"utf-8\");\n  writeFileSync(fp, content, \"utf-8\");\n}\n\nfunction read(workspace: string): MemlogData {\n  const fp = getPath(workspace);\n  if (!existsSync(fp)) return { frontmatter: {}, entries: [] };\n  const raw = readFileSync(fp, \"utf-8\");\n  const { frontmatter, body } = frontmatterFromString(raw);\n  const entries: MemlogEntry[] = [];\n  for (const line of body.split(\"\\n\")) {\n    const entry = lineToEntry(line);\n    if (entry) entries.push(entry);\n  }\n  return { frontmatter, entries };\n}\n\nexport function memlog() {\n  return { init, append, set, read };\n}\n","import { writeFileSync, mkdirSync, existsSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\n\nexport interface WriteOptions {\n  cwd: string;\n  outputFolder: string;\n  subpath: string;\n  filename: string;\n  content: string;\n}\n\nexport function writeArtifact(opts: WriteOptions): string {\n  const dir = resolve(opts.cwd, opts.outputFolder, opts.subpath);\n  if (!existsSync(dir)) mkdirSync(dir, { recursive: true });\n  const fp = resolve(dir, opts.filename);\n  writeFileSync(fp, opts.content, \"utf-8\");\n  return fp;\n}\n","export interface SpecTemplateOptions {\n  slug: string;\n  topic: string;\n  goal: string;\n  capabilities: Array<{ id: string; text: string }>;\n  constraints: string[];\n  decisions: string[];\n}\n\nexport function specTemplate(opts: SpecTemplateOptions): string {\n  const caps = opts.capabilities.length > 0\n    ? opts.capabilities.map((c) => `- **${c.id}**\\n  - **intent:** ${c.text}\\n  - **success:** {Testable or demonstrable criterion}`).join(\"\\n\")\n    : `- **CAP-1**\n  - **intent:** {What the system allows — WHAT, not HOW}\n  - **success:** {Testable or demonstrable criterion}`;\n\n  const constraints = opts.constraints.length > 0\n    ? opts.constraints.map((c) => `- ${c}`).join(\"\\n\")\n    : \"{Non-negotiable rules}\";\n\n  const decisions = opts.decisions.length > 0\n    ? opts.decisions.map((d) => `- ${d}`).join(\"\\n\")\n    : \"\";\n\n  return `---\nid: SPEC-${opts.slug}\ncompanions: []\nsources: []\n---\n\n# ${opts.topic}\n\n## Why\n${opts.goal || \"{Problem being solved. Business context.}\"}\n\n## Capabilities\n${caps}\n\n## Constraints\n${constraints}\n\n## Non-goals\n{What is NOT in scope}\n\n## Success signal\n{Concrete moment that proves it's done}\n${decisions ? `\\n## Architecture Decisions\\n${decisions}` : \"\"}\n`;\n}\n","export interface StoryTemplateOptions {\n  story_id: string;\n  story_title: string;\n  phase: string;\n  spec_name: string;\n}\n\nexport function storyTemplate(opts: StoryTemplateOptions): string {\n  return `---\nid: ${opts.story_id}\nstatus: pending # pending | in-progress | review | done\nbaseline_commit:\nphase: ${opts.phase}\nspec: ${opts.spec_name}\n---\n\n# ${opts.story_title}\n\n## Intent\nProblem: {what problem it solves}\nApproach: {how it will solve}\n\n## Boundaries & Constraints\n- Always: {always do}\n- Ask First: {ask before}\n- Never: {never do}\n\n## I/O & Edge-Case Matrix\n| # | Scenario | Input | Expected Output |\n|---|----------|-------|-----------------|\n| 1 | Success  |       |                 |\n| 2 |          |       |                 |\n\n## Code Map\n- {file} (CREATE | MODIFY | DELETE)\n\n## Tasks\n- [ ] Task 1\n  - [ ] Subtask 1.1\n  - [ ] Subtask 1.2\n- [ ] Task 2\n\n## Change Log\n`;\n}\n","export const AGENT_TARGETS = [\n  \"codex\",\n  \"claude\",\n  \"gemini\",\n  \"copilot\",\n  \"opencode\",\n  \"windsurf\",\n  \"cline\",\n  \"cursor\",\n] as const;\n\nexport type AgentTarget = (typeof AGENT_TARGETS)[number];\n\nexport type AgentAdapter = \"canonical\" | \"skill-wrapper\" | \"cursor-command\";\n\nexport interface AgentDefinition {\n  id: AgentTarget;\n  label: string;\n  adapter: AgentAdapter;\n  aliases: readonly string[];\n}\n\nexport const AGENT_DEFINITIONS: readonly AgentDefinition[] = [\n  { id: \"codex\", label: \"Codex\", adapter: \"canonical\", aliases: [\"openai-codex\"] },\n  { id: \"claude\", label: \"Claude Code\", adapter: \"skill-wrapper\", aliases: [\"claude-code\"] },\n  { id: \"gemini\", label: \"Gemini CLI\", adapter: \"canonical\", aliases: [\"gemini-cli\"] },\n  { id: \"copilot\", label: \"GitHub Copilot\", adapter: \"canonical\", aliases: [\"github-copilot\"] },\n  { id: \"opencode\", label: \"OpenCode\", adapter: \"canonical\", aliases: [\"open-code\"] },\n  { id: \"windsurf\", label: \"Windsurf\", adapter: \"canonical\", aliases: [\"cascade\"] },\n  { id: \"cline\", label: \"Cline\", adapter: \"skill-wrapper\", aliases: [] },\n  { id: \"cursor\", label: \"Cursor\", adapter: \"cursor-command\", aliases: [\"cursor-agent\"] },\n] as const;\n\nconst AGENT_LOOKUP = new Map<string, AgentTarget>();\nfor (const definition of AGENT_DEFINITIONS) {\n  AGENT_LOOKUP.set(definition.id, definition.id);\n  for (const alias of definition.aliases) AGENT_LOOKUP.set(alias, definition.id);\n}\n\nexport function getAgentDefinition(target: AgentTarget): AgentDefinition {\n  return AGENT_DEFINITIONS.find((definition) => definition.id === target)!;\n}\n\nexport function parseAgentTargets(value: string): AgentTarget[] {\n  const tokens = value.split(\",\").map((token) => token.trim().toLowerCase()).filter(Boolean);\n  if (tokens.length === 0) throw new Error(\"Agent selection cannot be empty. Use 'core' for the universal skill set.\");\n  if (tokens.includes(\"all\")) {\n    if (tokens.length !== 1) throw new Error(\"'all' cannot be combined with individual agents.\");\n    return [...AGENT_TARGETS];\n  }\n  if (tokens.includes(\"core\")) {\n    if (tokens.length !== 1) throw new Error(\"'core' cannot be combined with individual agents.\");\n    return [];\n  }\n\n  const selected: AgentTarget[] = [];\n  for (const token of tokens) {\n    const target = AGENT_LOOKUP.get(token);\n    if (!target) {\n      throw new Error(`Unknown agent '${token}'. Valid values: ${AGENT_TARGETS.join(\", \")}, all, core.`);\n    }\n    if (!selected.includes(target)) selected.push(target);\n  }\n  return selected;\n}\n\nexport function parseInteractiveAgentSelection(value: string): AgentTarget[] {\n  const answer = value.trim().toLowerCase();\n  if (!answer || answer === \"core\") return [];\n  if (answer === \"all\") return [...AGENT_TARGETS];\n\n  const tokens = answer.split(\",\").map((token) => token.trim()).filter(Boolean);\n  const normalized = tokens.map((token) => {\n    if (!/^\\d+$/.test(token)) return token;\n    const index = Number(token) - 1;\n    if (index < 0 || index >= AGENT_TARGETS.length) {\n      throw new Error(`Agent number '${token}' is outside the available range.`);\n    }\n    return AGENT_TARGETS[index];\n  });\n  return parseAgentTargets(normalized.join(\",\"));\n}\n\nexport function formatAgentMenu(): string {\n  const lines = [\"Select AI agents (comma-separated numbers, 'all', or Enter for core only):\"];\n  AGENT_DEFINITIONS.forEach((definition, index) => {\n    const mode = definition.adapter === \"canonical\" ? \"uses universal core\" : \"installs native adapter\";\n    lines.push(`  ${index + 1}. ${definition.label} — ${mode}`);\n  });\n  return lines.join(\"\\n\");\n}\n"]}