@wizdear/atlas-code 0.2.4 → 0.2.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (115) hide show
  1. package/README.md +1 -1
  2. package/dist/agent-factory.d.ts +10 -5
  3. package/dist/agent-factory.d.ts.map +1 -1
  4. package/dist/agent-factory.js +50 -13
  5. package/dist/agent-factory.js.map +1 -1
  6. package/dist/cli.d.ts +7 -1
  7. package/dist/cli.d.ts.map +1 -1
  8. package/dist/cli.js +72 -16
  9. package/dist/cli.js.map +1 -1
  10. package/dist/discovery.d.ts +9 -2
  11. package/dist/discovery.d.ts.map +1 -1
  12. package/dist/discovery.js +4 -5
  13. package/dist/discovery.js.map +1 -1
  14. package/dist/extension.d.ts +9 -2
  15. package/dist/extension.d.ts.map +1 -1
  16. package/dist/extension.js +1103 -381
  17. package/dist/extension.js.map +1 -1
  18. package/dist/gate.d.ts +1 -1
  19. package/dist/gate.d.ts.map +1 -1
  20. package/dist/gate.js.map +1 -1
  21. package/dist/index.d.ts +1 -1
  22. package/dist/index.d.ts.map +1 -1
  23. package/dist/index.js +1 -1
  24. package/dist/index.js.map +1 -1
  25. package/dist/orchestrator.d.ts +0 -4
  26. package/dist/orchestrator.d.ts.map +1 -1
  27. package/dist/orchestrator.js +0 -2
  28. package/dist/orchestrator.js.map +1 -1
  29. package/dist/pipeline-editor.d.ts +2 -0
  30. package/dist/pipeline-editor.d.ts.map +1 -1
  31. package/dist/pipeline-editor.js +36 -5
  32. package/dist/pipeline-editor.js.map +1 -1
  33. package/dist/pipeline.d.ts +2 -10
  34. package/dist/pipeline.d.ts.map +1 -1
  35. package/dist/pipeline.js +4 -6
  36. package/dist/pipeline.js.map +1 -1
  37. package/dist/planner.d.ts +9 -2
  38. package/dist/planner.d.ts.map +1 -1
  39. package/dist/planner.js +15 -11
  40. package/dist/planner.js.map +1 -1
  41. package/dist/roles/architect.d.ts +1 -1
  42. package/dist/roles/architect.d.ts.map +1 -1
  43. package/dist/roles/architect.js +1 -1
  44. package/dist/roles/architect.js.map +1 -1
  45. package/dist/roles/cicd.d.ts +1 -1
  46. package/dist/roles/cicd.d.ts.map +1 -1
  47. package/dist/roles/cicd.js +5 -0
  48. package/dist/roles/cicd.js.map +1 -1
  49. package/dist/roles/documenter.d.ts +1 -1
  50. package/dist/roles/documenter.d.ts.map +1 -1
  51. package/dist/roles/documenter.js +11 -0
  52. package/dist/roles/documenter.js.map +1 -1
  53. package/dist/roles/index.d.ts +1 -0
  54. package/dist/roles/index.d.ts.map +1 -1
  55. package/dist/roles/index.js +3 -0
  56. package/dist/roles/index.js.map +1 -1
  57. package/dist/roles/recover.d.ts +5 -0
  58. package/dist/roles/recover.d.ts.map +1 -0
  59. package/dist/roles/recover.js +82 -0
  60. package/dist/roles/recover.js.map +1 -0
  61. package/dist/roles/reviewer.d.ts +1 -1
  62. package/dist/roles/reviewer.d.ts.map +1 -1
  63. package/dist/roles/reviewer.js +7 -1
  64. package/dist/roles/reviewer.js.map +1 -1
  65. package/dist/roles/standards-enricher.d.ts +1 -1
  66. package/dist/roles/standards-enricher.d.ts.map +1 -1
  67. package/dist/roles/standards-enricher.js +8 -0
  68. package/dist/roles/standards-enricher.js.map +1 -1
  69. package/dist/roles/tester.d.ts +1 -1
  70. package/dist/roles/tester.d.ts.map +1 -1
  71. package/dist/roles/tester.js +7 -0
  72. package/dist/roles/tester.js.map +1 -1
  73. package/dist/router.d.ts.map +1 -1
  74. package/dist/router.js +6 -6
  75. package/dist/router.js.map +1 -1
  76. package/dist/standards.d.ts +37 -11
  77. package/dist/standards.d.ts.map +1 -1
  78. package/dist/standards.js +71 -89
  79. package/dist/standards.js.map +1 -1
  80. package/dist/step-executor.d.ts +15 -2
  81. package/dist/step-executor.d.ts.map +1 -1
  82. package/dist/step-executor.js +138 -30
  83. package/dist/step-executor.js.map +1 -1
  84. package/dist/store.d.ts +3 -10
  85. package/dist/store.d.ts.map +1 -1
  86. package/dist/store.js +45 -57
  87. package/dist/store.js.map +1 -1
  88. package/dist/system-architect.d.ts +9 -2
  89. package/dist/system-architect.d.ts.map +1 -1
  90. package/dist/system-architect.js +6 -10
  91. package/dist/system-architect.js.map +1 -1
  92. package/dist/telegram/bridge.d.ts +39 -0
  93. package/dist/telegram/bridge.d.ts.map +1 -0
  94. package/dist/telegram/bridge.js +380 -0
  95. package/dist/telegram/bridge.js.map +1 -0
  96. package/dist/telegram/formatter.d.ts +15 -0
  97. package/dist/telegram/formatter.d.ts.map +1 -0
  98. package/dist/telegram/formatter.js +86 -0
  99. package/dist/telegram/formatter.js.map +1 -0
  100. package/dist/telegram/renderer.d.ts +45 -0
  101. package/dist/telegram/renderer.d.ts.map +1 -0
  102. package/dist/telegram/renderer.js +150 -0
  103. package/dist/telegram/renderer.js.map +1 -0
  104. package/dist/telegram/telegram-api.d.ts +84 -0
  105. package/dist/telegram/telegram-api.d.ts.map +1 -0
  106. package/dist/telegram/telegram-api.js +134 -0
  107. package/dist/telegram/telegram-api.js.map +1 -0
  108. package/dist/types.d.ts +10 -1
  109. package/dist/types.d.ts.map +1 -1
  110. package/dist/types.js.map +1 -1
  111. package/dist/ui.d.ts +1 -1
  112. package/dist/ui.d.ts.map +1 -1
  113. package/dist/ui.js +2 -0
  114. package/dist/ui.js.map +1 -1
  115. package/package.json +1 -1
package/README.md CHANGED
@@ -18,7 +18,7 @@ Given a natural-language requirement, vibe decomposes it into features, assigns
18
18
  One command installs everything — pi-coding-agent, atlas-code, and configures the extension:
19
19
 
20
20
  ```bash
21
- npx @wizdear/atlas-code setup
21
+
22
22
  ```
23
23
 
24
24
  Then navigate to your project and start pi:
@@ -1,8 +1,15 @@
1
1
  import { Agent, type AgentEvent, type AgentMessage, type AgentTool } from "@mariozechner/pi-agent-core";
2
2
  import type { Message, Model } from "@mariozechner/pi-ai";
3
3
  import type { AgentRole, VibeConfig } from "./types.js";
4
+ /**
5
+ * Roles that receive project-context.md automatically via system prompt.
6
+ * Excluded roles:
7
+ * - projectAnalyzer: generates project-context.md; injecting it would bias re-analysis
8
+ * - cicd: executes git commands only; no project awareness needed
9
+ */
10
+ export declare const PROJECT_CONTEXT_ROLES: ReadonlySet<AgentRole>;
4
11
  /** Tool set category. */
5
- export type ToolSet = "readonly" | "analysis" | "implementation" | "design" | "infrastructure";
12
+ export type ToolSet = "readonly" | "analysis" | "implementation" | "design" | "infrastructure" | "none";
6
13
  /** Tool set mapping per role. */
7
14
  export declare const ROLE_TOOL_SETS: Record<AgentRole, ToolSet>;
8
15
  /**
@@ -11,9 +18,9 @@ export declare const ROLE_TOOL_SETS: Record<AgentRole, ToolSet>;
11
18
  export declare function getToolsForRole(role: AgentRole, cwd: string): AgentTool<any>[];
12
19
  /**
13
20
  * Assembles the system prompt.
14
- * Order: basePrompt → Organization Standards → Feature Context → Available Skills → Project Context
21
+ * Order: basePrompt → Organization Standards → Feature Context → Project Context
15
22
  */
16
- export declare function buildSystemPrompt(basePrompt: string, standardsPrompt: string, featureContext?: string, availableSkills?: string, projectContext?: string): string;
23
+ export declare function buildSystemPrompt(basePrompt: string, standardsPrompt: string, featureContext?: string, projectContext?: string): string;
17
24
  /** Dynamic API key lookup function. Used for expirable auth such as OAuth tokens. */
18
25
  export type GetApiKeyFn = (provider: string) => Promise<string | undefined> | string | undefined;
19
26
  /** createRoleAgent options. */
@@ -28,8 +35,6 @@ export interface CreateRoleAgentOptions {
28
35
  getApiKey?: GetApiKeyFn;
29
36
  /** Previous conversation history. Injected as Agent's initial messages when provided (for checkpoint restoration). */
30
37
  initialMessages?: AgentMessage[];
31
- /** Lightweight skill index (name+description+path). Agents load full content via read tool when needed. */
32
- availableSkills?: string;
33
38
  /** Project context (from project-context.md). Injected into system prompt for project awareness. */
34
39
  projectContext?: string;
35
40
  }
@@ -1 +1 @@
1
- {"version":3,"file":"agent-factory.d.ts","sourceRoot":"","sources":["../src/agent-factory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,KAAK,UAAU,EAAE,KAAK,YAAY,EAAE,KAAK,SAAS,EAAE,MAAM,6BAA6B,CAAC;AACxG,OAAO,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AAU1D,OAAO,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAIxD,yBAAyB;AACzB,MAAM,MAAM,OAAO,GAAG,UAAU,GAAG,UAAU,GAAG,gBAAgB,GAAG,QAAQ,GAAG,gBAAgB,CAAC;AAE/F,iCAAiC;AACjC,eAAO,MAAM,cAAc,EAAE,MAAM,CAAC,SAAS,EAAE,OAAO,CAcrD,CAAC;AAEF;;GAEG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,SAAS,EAAE,GAAG,EAAE,MAAM,GAAG,SAAS,CAAC,GAAG,CAAC,EAAE,CAc9E;AAID;;;GAGG;AACH,wBAAgB,iBAAiB,CAChC,UAAU,EAAE,MAAM,EAClB,eAAe,EAAE,MAAM,EACvB,cAAc,CAAC,EAAE,MAAM,EACvB,eAAe,CAAC,EAAE,MAAM,EACxB,cAAc,CAAC,EAAE,MAAM,GACrB,MAAM,CAoBR;AAID,qFAAqF;AACrF,MAAM,MAAM,WAAW,GAAG,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,GAAG,MAAM,GAAG,SAAS,CAAC;AAEjG,+BAA+B;AAC/B,MAAM,WAAW,sBAAsB;IACtC,IAAI,EAAE,SAAS,CAAC;IAChB,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,UAAU,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC;IACnB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,CAAC;IACtC,SAAS,CAAC,EAAE,WAAW,CAAC;IACxB,sHAAsH;IACtH,eAAe,CAAC,EAAE,YAAY,EAAE,CAAC;IACjC,2GAA2G;IAC3G,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,oGAAoG;IACpG,cAAc,CAAC,EAAE,MAAM,CAAC;CACxB;AAED;;;;;;GAMG;AACH,wBAAsB,eAAe,CAAC,OAAO,EAAE,sBAAsB,GAAG,OAAO,CAAC,KAAK,CAAC,CAqDrF;AAMD;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAiCpD;AAID,wBAAwB;AACxB,MAAM,WAAW,eAAe;IAC/B,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,CAAC;CACtC;AAED;;GAEG;AACH,wBAAsB,QAAQ,CAAC,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,eAAe,GAAG,OAAO,CAAC,MAAM,CAAC,CAqBvG;AAED,gDAAgD;AAChD,MAAM,WAAW,cAAc;IAC9B,0CAA0C;IAC1C,IAAI,EAAE,MAAM,CAAC;IACb,qDAAqD;IACrD,QAAQ,EAAE,YAAY,EAAE,CAAC;CACzB;AAED;;;GAGG;AACH,wBAAsB,mBAAmB,CACxC,KAAK,EAAE,KAAK,EACZ,MAAM,EAAE,MAAM,EACd,OAAO,CAAC,EAAE,eAAe,GACvB,OAAO,CAAC,cAAc,CAAC,CAsBzB;AAED;;;GAGG;AACH,wBAAgB,0BAA0B,CAAC,QAAQ,EAAE,YAAY,EAAE,GAAG,OAAO,EAAE,CAI9E;AAED;;GAEG;AACH,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,YAAY,EAAE,GAAG,MAAM,CAgBzE","sourcesContent":["import { Agent, type AgentEvent, type AgentMessage, type AgentTool } from \"@mariozechner/pi-agent-core\";\nimport type { Message, Model } from \"@mariozechner/pi-ai\";\nimport {\n\tcreateBashTool,\n\tcreateCodingTools,\n\tcreateReadOnlyTools,\n\tcreateReadTool,\n\tcreateWriteTool,\n} from \"@mariozechner/pi-coding-agent\";\nimport { createCompactionTransform } from \"./compaction.js\";\nimport { formatStandardsPrompt, loadStandardsForRole } from \"./standards.js\";\nimport type { AgentRole, VibeConfig } from \"./types.js\";\n\n// ─── Tool Set Mapping ────────────────────────────────────────────────────────\n\n/** Tool set category. */\nexport type ToolSet = \"readonly\" | \"analysis\" | \"implementation\" | \"design\" | \"infrastructure\";\n\n/** Tool set mapping per role. */\nexport const ROLE_TOOL_SETS: Record<AgentRole, ToolSet> = {\n\tplanner: \"readonly\",\n\tanalyzer: \"readonly\",\n\treviewer: \"readonly\",\n\tdiagnostician: \"analysis\",\n\tdeveloper: \"implementation\",\n\ttester: \"implementation\",\n\tarchitect: \"design\",\n\tcicd: \"infrastructure\",\n\tdiscovery: \"readonly\",\n\tprojectAnalyzer: \"analysis\",\n\tdocumenter: \"implementation\",\n\tstandardsEnricher: \"readonly\",\n\tsystemArchitect: \"design\",\n};\n\n/**\n * Returns the tool list for a given role.\n */\nexport function getToolsForRole(role: AgentRole, cwd: string): AgentTool<any>[] {\n\tconst toolSet = ROLE_TOOL_SETS[role];\n\tswitch (toolSet) {\n\t\tcase \"readonly\":\n\t\t\treturn createReadOnlyTools(cwd);\n\t\tcase \"analysis\":\n\t\t\treturn [createReadTool(cwd), createBashTool(cwd)];\n\t\tcase \"implementation\":\n\t\t\treturn createCodingTools(cwd);\n\t\tcase \"design\":\n\t\t\treturn [createReadTool(cwd), createWriteTool(cwd)];\n\t\tcase \"infrastructure\":\n\t\t\treturn [createBashTool(cwd)];\n\t}\n}\n\n// ─── System Prompt Builder ───────────────────────────────────────────────────\n\n/**\n * Assembles the system prompt.\n * Order: basePrompt → Organization Standards → Feature Context → Available Skills → Project Context\n */\nexport function buildSystemPrompt(\n\tbasePrompt: string,\n\tstandardsPrompt: string,\n\tfeatureContext?: string,\n\tavailableSkills?: string,\n\tprojectContext?: string,\n): string {\n\tconst parts = [basePrompt];\n\n\tif (standardsPrompt) {\n\t\tparts.push(standardsPrompt);\n\t}\n\n\tif (featureContext) {\n\t\tparts.push(featureContext);\n\t}\n\n\tif (availableSkills) {\n\t\tparts.push(availableSkills);\n\t}\n\n\tif (projectContext) {\n\t\tparts.push(`## Project Context\\n\\n${projectContext}`);\n\t}\n\n\treturn parts.join(\"\\n\\n\");\n}\n\n// ─── Agent Factory ───────────────────────────────────────────────────────────\n\n/** Dynamic API key lookup function. Used for expirable auth such as OAuth tokens. */\nexport type GetApiKeyFn = (provider: string) => Promise<string | undefined> | string | undefined;\n\n/** createRoleAgent options. */\nexport interface CreateRoleAgentOptions {\n\trole: AgentRole;\n\tsystemPrompt: string;\n\tconfig: VibeConfig;\n\tprojectRoot: string;\n\tmodel?: Model<any>;\n\tfeatureContext?: string;\n\tonEvent?: (event: AgentEvent) => void;\n\tgetApiKey?: GetApiKeyFn;\n\t/** Previous conversation history. Injected as Agent's initial messages when provided (for checkpoint restoration). */\n\tinitialMessages?: AgentMessage[];\n\t/** Lightweight skill index (name+description+path). Agents load full content via read tool when needed. */\n\tavailableSkills?: string;\n\t/** Project context (from project-context.md). Injected into system prompt for project awareness. */\n\tprojectContext?: string;\n}\n\n/**\n * Creates a role-configured Agent instance.\n *\n * 1. Loads role-specific standards and injects into system prompt\n * 2. Configures role-specific tool set\n * 3. Sets the model (uses default if not specified)\n */\nexport async function createRoleAgent(options: CreateRoleAgentOptions): Promise<Agent> {\n\tconst {\n\t\trole,\n\t\tsystemPrompt,\n\t\tconfig,\n\t\tprojectRoot,\n\t\tmodel,\n\t\tfeatureContext,\n\t\tonEvent,\n\t\tgetApiKey,\n\t\tinitialMessages,\n\t\tavailableSkills,\n\t\tprojectContext,\n\t} = options;\n\n\t// Load and format standards\n\tconst standardsContent = await loadStandardsForRole(role, config, projectRoot);\n\tconst standardsPrompt = formatStandardsPrompt(standardsContent);\n\n\t// Assemble system prompt\n\tconst fullSystemPrompt = buildSystemPrompt(\n\t\tsystemPrompt,\n\t\tstandardsPrompt,\n\t\tfeatureContext,\n\t\tavailableSkills,\n\t\tprojectContext,\n\t);\n\n\t// Determine tool set\n\tconst tools = getToolsForRole(role, projectRoot);\n\n\t// Configure compaction transform\n\tconst compactionTransform =\n\t\tconfig.compaction.enabled && model ? createCompactionTransform(model, config.compaction, getApiKey) : undefined;\n\n\t// Create Agent\n\tconst agent = new Agent({\n\t\tinitialState: {\n\t\t\tsystemPrompt: fullSystemPrompt,\n\t\t\ttools,\n\t\t\t...(model ? { model } : {}),\n\t\t\t...(initialMessages && initialMessages.length > 0 ? { messages: initialMessages } : {}),\n\t\t},\n\t\tgetApiKey,\n\t\ttransformContext: compactionTransform,\n\t});\n\n\t// Subscribe to events\n\tif (onEvent) {\n\t\tagent.subscribe(onEvent);\n\t}\n\n\treturn agent;\n}\n\n// ─── Agent Runner ────────────────────────────────────────────────────────────\n\n// ─── Error Formatting ────────────────────────────────────────────────────────\n\n/**\n * Formats a raw agent error string into a human-readable message.\n * Handles JSON error objects from LLM providers (e.g., Anthropic API errors).\n * Falls back to the original string if parsing fails.\n */\nexport function formatAgentError(raw: string): string {\n\tconst trimmed = raw.trim();\n\tif (!trimmed.startsWith(\"{\")) {\n\t\treturn raw;\n\t}\n\n\ttry {\n\t\tconst parsed = JSON.parse(trimmed);\n\n\t\t// Anthropic-style: {\"type\":\"error\",\"error\":{\"type\":\"api_error\",\"message\":\"...\"},\"request_id\":\"...\"}\n\t\tif (parsed.error && typeof parsed.error === \"object\" && parsed.error.message) {\n\t\t\tconst parts: string[] = [parsed.error.message];\n\t\t\tif (parsed.error.type) {\n\t\t\t\tparts[0] = `${parsed.error.message} (${parsed.error.type})`;\n\t\t\t}\n\t\t\tif (parsed.request_id) {\n\t\t\t\tparts.push(`requestId=${parsed.request_id}`);\n\t\t\t}\n\t\t\tif (parsed.error.details) {\n\t\t\t\tparts.push(`details=${JSON.stringify(parsed.error.details)}`);\n\t\t\t}\n\t\t\treturn parts.join(\" | \");\n\t\t}\n\n\t\t// Generic: {\"message\":\"...\"}\n\t\tif (parsed.message && typeof parsed.message === \"string\") {\n\t\t\treturn parsed.message;\n\t\t}\n\n\t\treturn raw;\n\t} catch {\n\t\treturn raw;\n\t}\n}\n\n// ─── Agent Runner ────────────────────────────────────────────────────────────\n\n/** runAgent options. */\nexport interface RunAgentOptions {\n\tonEvent?: (event: AgentEvent) => void;\n}\n\n/**\n * Sends a prompt to the agent, waits for completion, and returns the final response text.\n */\nexport async function runAgent(agent: Agent, prompt: string, options?: RunAgentOptions): Promise<string> {\n\tlet unsubscribe: (() => void) | undefined;\n\tif (options?.onEvent) {\n\t\tunsubscribe = agent.subscribe(options.onEvent);\n\t}\n\n\ttry {\n\t\tawait agent.prompt(prompt);\n\t\tawait agent.waitForIdle();\n\n\t\t// Agent stores LLM errors in state.error without throwing.\n\t\t// Explicitly check and propagate the error here.\n\t\tif (agent.state.error) {\n\t\t\tconst formatted = formatAgentError(agent.state.error);\n\t\t\tthrow new Error(`Agent error: ${formatted}`, { cause: agent.state.error });\n\t\t}\n\n\t\treturn extractLastAssistantText(agent.state.messages);\n\t} finally {\n\t\tunsubscribe?.();\n\t}\n}\n\n/** runAgent execution result (with history). */\nexport interface RunAgentResult {\n\t/** Text of the last assistant message. */\n\ttext: string;\n\t/** Full conversation history (for checkpointing). */\n\tmessages: AgentMessage[];\n}\n\n/**\n * Runs the agent and returns response text with full message history.\n * Use this function when checkpointing is needed.\n */\nexport async function runAgentWithHistory(\n\tagent: Agent,\n\tprompt: string,\n\toptions?: RunAgentOptions,\n): Promise<RunAgentResult> {\n\tlet unsubscribe: (() => void) | undefined;\n\tif (options?.onEvent) {\n\t\tunsubscribe = agent.subscribe(options.onEvent);\n\t}\n\n\ttry {\n\t\tawait agent.prompt(prompt);\n\t\tawait agent.waitForIdle();\n\n\t\tif (agent.state.error) {\n\t\t\tconst formatted = formatAgentError(agent.state.error);\n\t\t\tthrow new Error(`Agent error: ${formatted}`, { cause: agent.state.error });\n\t\t}\n\n\t\treturn {\n\t\t\ttext: extractLastAssistantText(agent.state.messages),\n\t\t\tmessages: [...agent.state.messages],\n\t\t};\n\t} finally {\n\t\tunsubscribe?.();\n\t}\n}\n\n/**\n * Extracts LLM messages (user, assistant, toolResult) from an AgentMessage array.\n * Custom message types are excluded, ensuring JSON serializability.\n */\nexport function filterSerializableMessages(messages: AgentMessage[]): Message[] {\n\treturn messages.filter(\n\t\t(m): m is Message => \"role\" in m && (m.role === \"user\" || m.role === \"assistant\" || m.role === \"toolResult\"),\n\t);\n}\n\n/**\n * Extracts the text of the last assistant message from a message list.\n */\nexport function extractLastAssistantText(messages: AgentMessage[]): string {\n\tfor (let i = messages.length - 1; i >= 0; i--) {\n\t\tconst msg = messages[i];\n\t\tif (msg.role === \"assistant\") {\n\t\t\tconst textParts: string[] = [];\n\t\t\tif (Array.isArray(msg.content)) {\n\t\t\t\tfor (const block of msg.content) {\n\t\t\t\t\tif (\"text\" in block && block.type === \"text\") {\n\t\t\t\t\t\ttextParts.push(block.text);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn textParts.join(\"\");\n\t\t}\n\t}\n\treturn \"\";\n}\n"]}
1
+ {"version":3,"file":"agent-factory.d.ts","sourceRoot":"","sources":["../src/agent-factory.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,KAAK,EAAE,KAAK,UAAU,EAAE,KAAK,YAAY,EAAE,KAAK,SAAS,EAAE,MAAM,6BAA6B,CAAC;AACxG,OAAO,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AAU1D,OAAO,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAIxD;;;;;GAKG;AACH,eAAO,MAAM,qBAAqB,EAAE,WAAW,CAAC,SAAS,CAYvD,CAAC;AAaH,yBAAyB;AACzB,MAAM,MAAM,OAAO,GAAG,UAAU,GAAG,UAAU,GAAG,gBAAgB,GAAG,QAAQ,GAAG,gBAAgB,GAAG,MAAM,CAAC;AAExG,iCAAiC;AACjC,eAAO,MAAM,cAAc,EAAE,MAAM,CAAC,SAAS,EAAE,OAAO,CAerD,CAAC;AAEF;;GAEG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,SAAS,EAAE,GAAG,EAAE,MAAM,GAAG,SAAS,CAAC,GAAG,CAAC,EAAE,CAgB9E;AAID;;;GAGG;AACH,wBAAgB,iBAAiB,CAChC,UAAU,EAAE,MAAM,EAClB,eAAe,EAAE,MAAM,EACvB,cAAc,CAAC,EAAE,MAAM,EACvB,cAAc,CAAC,EAAE,MAAM,GACrB,MAAM,CAgBR;AAID,qFAAqF;AACrF,MAAM,MAAM,WAAW,GAAG,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,GAAG,MAAM,GAAG,SAAS,CAAC;AAEjG,+BAA+B;AAC/B,MAAM,WAAW,sBAAsB;IACtC,IAAI,EAAE,SAAS,CAAC;IAChB,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,UAAU,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC;IACnB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,CAAC;IACtC,SAAS,CAAC,EAAE,WAAW,CAAC;IACxB,sHAAsH;IACtH,eAAe,CAAC,EAAE,YAAY,EAAE,CAAC;IACjC,oGAAoG;IACpG,cAAc,CAAC,EAAE,MAAM,CAAC;CACxB;AAED;;;;;;GAMG;AACH,wBAAsB,eAAe,CAAC,OAAO,EAAE,sBAAsB,GAAG,OAAO,CAAC,KAAK,CAAC,CAsDrF;AAMD;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAiCpD;AAID,wBAAwB;AACxB,MAAM,WAAW,eAAe;IAC/B,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,CAAC;CACtC;AAED;;GAEG;AACH,wBAAsB,QAAQ,CAAC,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,eAAe,GAAG,OAAO,CAAC,MAAM,CAAC,CAqBvG;AAED,gDAAgD;AAChD,MAAM,WAAW,cAAc;IAC9B,0CAA0C;IAC1C,IAAI,EAAE,MAAM,CAAC;IACb,qDAAqD;IACrD,QAAQ,EAAE,YAAY,EAAE,CAAC;CACzB;AAED;;;GAGG;AACH,wBAAsB,mBAAmB,CACxC,KAAK,EAAE,KAAK,EACZ,MAAM,EAAE,MAAM,EACd,OAAO,CAAC,EAAE,eAAe,GACvB,OAAO,CAAC,cAAc,CAAC,CAsBzB;AAED;;;GAGG;AACH,wBAAgB,0BAA0B,CAAC,QAAQ,EAAE,YAAY,EAAE,GAAG,OAAO,EAAE,CAI9E;AAED;;GAEG;AACH,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,YAAY,EAAE,GAAG,MAAM,CAgBzE","sourcesContent":["import { readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nimport { Agent, type AgentEvent, type AgentMessage, type AgentTool } from \"@mariozechner/pi-agent-core\";\nimport type { Message, Model } from \"@mariozechner/pi-ai\";\nimport {\n\tcreateBashTool,\n\tcreateCodingTools,\n\tcreateReadOnlyTools,\n\tcreateReadTool,\n\tcreateWriteTool,\n} from \"@mariozechner/pi-coding-agent\";\nimport { createCompactionTransform } from \"./compaction.js\";\nimport { buildStandardsIndex, formatStandardsIndexPrompt } from \"./standards.js\";\nimport type { AgentRole, VibeConfig } from \"./types.js\";\n\n// ─── Project Context Auto-Load ───────────────────────────────────────────────\n\n/**\n * Roles that receive project-context.md automatically via system prompt.\n * Excluded roles:\n * - projectAnalyzer: generates project-context.md; injecting it would bias re-analysis\n * - cicd: executes git commands only; no project awareness needed\n */\nexport const PROJECT_CONTEXT_ROLES: ReadonlySet<AgentRole> = new Set<AgentRole>([\n\t\"discovery\",\n\t\"planner\",\n\t\"systemArchitect\",\n\t\"analyzer\",\n\t\"architect\",\n\t\"developer\",\n\t\"tester\",\n\t\"reviewer\",\n\t\"diagnostician\",\n\t\"documenter\",\n\t\"standardsEnricher\",\n]);\n\n/** Reads .vibe/project-context.md from projectRoot. Returns undefined if not found. */\nasync function autoLoadProjectContext(projectRoot: string): Promise<string | undefined> {\n\ttry {\n\t\treturn await readFile(join(projectRoot, \".vibe\", \"project-context.md\"), \"utf-8\");\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\n// ─── Tool Set Mapping ────────────────────────────────────────────────────────\n\n/** Tool set category. */\nexport type ToolSet = \"readonly\" | \"analysis\" | \"implementation\" | \"design\" | \"infrastructure\" | \"none\";\n\n/** Tool set mapping per role. */\nexport const ROLE_TOOL_SETS: Record<AgentRole, ToolSet> = {\n\tplanner: \"readonly\",\n\tanalyzer: \"readonly\",\n\treviewer: \"analysis\",\n\tdiagnostician: \"analysis\",\n\tdeveloper: \"implementation\",\n\ttester: \"implementation\",\n\tarchitect: \"design\",\n\tcicd: \"infrastructure\",\n\tdiscovery: \"readonly\",\n\tprojectAnalyzer: \"analysis\",\n\tdocumenter: \"implementation\",\n\tstandardsEnricher: \"none\",\n\tsystemArchitect: \"design\",\n\trecover: \"analysis\",\n};\n\n/**\n * Returns the tool list for a given role.\n */\nexport function getToolsForRole(role: AgentRole, cwd: string): AgentTool<any>[] {\n\tconst toolSet = ROLE_TOOL_SETS[role];\n\tswitch (toolSet) {\n\t\tcase \"readonly\":\n\t\t\treturn createReadOnlyTools(cwd);\n\t\tcase \"analysis\":\n\t\t\treturn [createReadTool(cwd), createBashTool(cwd)];\n\t\tcase \"implementation\":\n\t\t\treturn createCodingTools(cwd);\n\t\tcase \"design\":\n\t\t\treturn [createReadTool(cwd), createWriteTool(cwd)];\n\t\tcase \"infrastructure\":\n\t\t\treturn [createBashTool(cwd)];\n\t\tcase \"none\":\n\t\t\treturn [];\n\t}\n}\n\n// ─── System Prompt Builder ───────────────────────────────────────────────────\n\n/**\n * Assembles the system prompt.\n * Order: basePrompt → Organization Standards → Feature Context → Project Context\n */\nexport function buildSystemPrompt(\n\tbasePrompt: string,\n\tstandardsPrompt: string,\n\tfeatureContext?: string,\n\tprojectContext?: string,\n): string {\n\tconst parts = [basePrompt];\n\n\tif (standardsPrompt) {\n\t\tparts.push(standardsPrompt);\n\t}\n\n\tif (featureContext) {\n\t\tparts.push(featureContext);\n\t}\n\n\tif (projectContext) {\n\t\tparts.push(`## Project Context\\n\\n${projectContext}`);\n\t}\n\n\treturn parts.join(\"\\n\\n\");\n}\n\n// ─── Agent Factory ───────────────────────────────────────────────────────────\n\n/** Dynamic API key lookup function. Used for expirable auth such as OAuth tokens. */\nexport type GetApiKeyFn = (provider: string) => Promise<string | undefined> | string | undefined;\n\n/** createRoleAgent options. */\nexport interface CreateRoleAgentOptions {\n\trole: AgentRole;\n\tsystemPrompt: string;\n\tconfig: VibeConfig;\n\tprojectRoot: string;\n\tmodel?: Model<any>;\n\tfeatureContext?: string;\n\tonEvent?: (event: AgentEvent) => void;\n\tgetApiKey?: GetApiKeyFn;\n\t/** Previous conversation history. Injected as Agent's initial messages when provided (for checkpoint restoration). */\n\tinitialMessages?: AgentMessage[];\n\t/** Project context (from project-context.md). Injected into system prompt for project awareness. */\n\tprojectContext?: string;\n}\n\n/**\n * Creates a role-configured Agent instance.\n *\n * 1. Loads role-specific standards and injects into system prompt\n * 2. Configures role-specific tool set\n * 3. Sets the model (uses default if not specified)\n */\nexport async function createRoleAgent(options: CreateRoleAgentOptions): Promise<Agent> {\n\tconst {\n\t\trole,\n\t\tsystemPrompt,\n\t\tconfig,\n\t\tprojectRoot,\n\t\tmodel,\n\t\tfeatureContext,\n\t\tonEvent,\n\t\tgetApiKey,\n\t\tinitialMessages,\n\t\tprojectContext: explicitProjectContext,\n\t} = options;\n\n\t// Auto-load project-context.md for eligible roles when not explicitly provided\n\tconst projectContext =\n\t\texplicitProjectContext !== undefined\n\t\t\t? explicitProjectContext\n\t\t\t: PROJECT_CONTEXT_ROLES.has(role)\n\t\t\t\t? await autoLoadProjectContext(projectRoot)\n\t\t\t\t: undefined;\n\n\t// Build standards index (agents read full files on demand)\n\tconst { entries: standardsIndex } = await buildStandardsIndex(config, projectRoot);\n\tconst standardsPrompt = formatStandardsIndexPrompt(standardsIndex);\n\n\t// Assemble system prompt\n\tconst fullSystemPrompt = buildSystemPrompt(systemPrompt, standardsPrompt, featureContext, projectContext);\n\n\t// Determine tool set\n\tconst tools = getToolsForRole(role, projectRoot);\n\n\t// Configure compaction transform\n\tconst compactionTransform =\n\t\tconfig.compaction.enabled && model ? createCompactionTransform(model, config.compaction, getApiKey) : undefined;\n\n\t// Create Agent\n\tconst agent = new Agent({\n\t\tinitialState: {\n\t\t\tsystemPrompt: fullSystemPrompt,\n\t\t\ttools,\n\t\t\t...(model ? { model } : {}),\n\t\t\t...(initialMessages && initialMessages.length > 0 ? { messages: initialMessages } : {}),\n\t\t},\n\t\tgetApiKey,\n\t\ttransformContext: compactionTransform,\n\t});\n\n\t// Subscribe to events\n\tif (onEvent) {\n\t\tagent.subscribe(onEvent);\n\t}\n\n\treturn agent;\n}\n\n// ─── Agent Runner ────────────────────────────────────────────────────────────\n\n// ─── Error Formatting ────────────────────────────────────────────────────────\n\n/**\n * Formats a raw agent error string into a human-readable message.\n * Handles JSON error objects from LLM providers (e.g., Anthropic API errors).\n * Falls back to the original string if parsing fails.\n */\nexport function formatAgentError(raw: string): string {\n\tconst trimmed = raw.trim();\n\tif (!trimmed.startsWith(\"{\")) {\n\t\treturn raw;\n\t}\n\n\ttry {\n\t\tconst parsed = JSON.parse(trimmed);\n\n\t\t// Anthropic-style: {\"type\":\"error\",\"error\":{\"type\":\"api_error\",\"message\":\"...\"},\"request_id\":\"...\"}\n\t\tif (parsed.error && typeof parsed.error === \"object\" && parsed.error.message) {\n\t\t\tconst parts: string[] = [parsed.error.message];\n\t\t\tif (parsed.error.type) {\n\t\t\t\tparts[0] = `${parsed.error.message} (${parsed.error.type})`;\n\t\t\t}\n\t\t\tif (parsed.request_id) {\n\t\t\t\tparts.push(`requestId=${parsed.request_id}`);\n\t\t\t}\n\t\t\tif (parsed.error.details) {\n\t\t\t\tparts.push(`details=${JSON.stringify(parsed.error.details)}`);\n\t\t\t}\n\t\t\treturn parts.join(\" | \");\n\t\t}\n\n\t\t// Generic: {\"message\":\"...\"}\n\t\tif (parsed.message && typeof parsed.message === \"string\") {\n\t\t\treturn parsed.message;\n\t\t}\n\n\t\treturn raw;\n\t} catch {\n\t\treturn raw;\n\t}\n}\n\n// ─── Agent Runner ────────────────────────────────────────────────────────────\n\n/** runAgent options. */\nexport interface RunAgentOptions {\n\tonEvent?: (event: AgentEvent) => void;\n}\n\n/**\n * Sends a prompt to the agent, waits for completion, and returns the final response text.\n */\nexport async function runAgent(agent: Agent, prompt: string, options?: RunAgentOptions): Promise<string> {\n\tlet unsubscribe: (() => void) | undefined;\n\tif (options?.onEvent) {\n\t\tunsubscribe = agent.subscribe(options.onEvent);\n\t}\n\n\ttry {\n\t\tawait agent.prompt(prompt);\n\t\tawait agent.waitForIdle();\n\n\t\t// Agent stores LLM errors in state.error without throwing.\n\t\t// Explicitly check and propagate the error here.\n\t\tif (agent.state.error) {\n\t\t\tconst formatted = formatAgentError(agent.state.error);\n\t\t\tthrow new Error(`Agent error: ${formatted}`, { cause: agent.state.error });\n\t\t}\n\n\t\treturn extractLastAssistantText(agent.state.messages);\n\t} finally {\n\t\tunsubscribe?.();\n\t}\n}\n\n/** runAgent execution result (with history). */\nexport interface RunAgentResult {\n\t/** Text of the last assistant message. */\n\ttext: string;\n\t/** Full conversation history (for checkpointing). */\n\tmessages: AgentMessage[];\n}\n\n/**\n * Runs the agent and returns response text with full message history.\n * Use this function when checkpointing is needed.\n */\nexport async function runAgentWithHistory(\n\tagent: Agent,\n\tprompt: string,\n\toptions?: RunAgentOptions,\n): Promise<RunAgentResult> {\n\tlet unsubscribe: (() => void) | undefined;\n\tif (options?.onEvent) {\n\t\tunsubscribe = agent.subscribe(options.onEvent);\n\t}\n\n\ttry {\n\t\tawait agent.prompt(prompt);\n\t\tawait agent.waitForIdle();\n\n\t\tif (agent.state.error) {\n\t\t\tconst formatted = formatAgentError(agent.state.error);\n\t\t\tthrow new Error(`Agent error: ${formatted}`, { cause: agent.state.error });\n\t\t}\n\n\t\treturn {\n\t\t\ttext: extractLastAssistantText(agent.state.messages),\n\t\t\tmessages: [...agent.state.messages],\n\t\t};\n\t} finally {\n\t\tunsubscribe?.();\n\t}\n}\n\n/**\n * Extracts LLM messages (user, assistant, toolResult) from an AgentMessage array.\n * Custom message types are excluded, ensuring JSON serializability.\n */\nexport function filterSerializableMessages(messages: AgentMessage[]): Message[] {\n\treturn messages.filter(\n\t\t(m): m is Message => \"role\" in m && (m.role === \"user\" || m.role === \"assistant\" || m.role === \"toolResult\"),\n\t);\n}\n\n/**\n * Extracts the text of the last assistant message from a message list.\n */\nexport function extractLastAssistantText(messages: AgentMessage[]): string {\n\tfor (let i = messages.length - 1; i >= 0; i--) {\n\t\tconst msg = messages[i];\n\t\tif (msg.role === \"assistant\") {\n\t\t\tconst textParts: string[] = [];\n\t\t\tif (Array.isArray(msg.content)) {\n\t\t\t\tfor (const block of msg.content) {\n\t\t\t\t\tif (\"text\" in block && block.type === \"text\") {\n\t\t\t\t\t\ttextParts.push(block.text);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn textParts.join(\"\");\n\t\t}\n\t}\n\treturn \"\";\n}\n"]}
@@ -1,12 +1,43 @@
1
+ import { readFile } from "node:fs/promises";
2
+ import { join } from "node:path";
1
3
  import { Agent } from "@mariozechner/pi-agent-core";
2
4
  import { createBashTool, createCodingTools, createReadOnlyTools, createReadTool, createWriteTool, } from "@mariozechner/pi-coding-agent";
3
5
  import { createCompactionTransform } from "./compaction.js";
4
- import { formatStandardsPrompt, loadStandardsForRole } from "./standards.js";
6
+ import { buildStandardsIndex, formatStandardsIndexPrompt } from "./standards.js";
7
+ // ─── Project Context Auto-Load ───────────────────────────────────────────────
8
+ /**
9
+ * Roles that receive project-context.md automatically via system prompt.
10
+ * Excluded roles:
11
+ * - projectAnalyzer: generates project-context.md; injecting it would bias re-analysis
12
+ * - cicd: executes git commands only; no project awareness needed
13
+ */
14
+ export const PROJECT_CONTEXT_ROLES = new Set([
15
+ "discovery",
16
+ "planner",
17
+ "systemArchitect",
18
+ "analyzer",
19
+ "architect",
20
+ "developer",
21
+ "tester",
22
+ "reviewer",
23
+ "diagnostician",
24
+ "documenter",
25
+ "standardsEnricher",
26
+ ]);
27
+ /** Reads .vibe/project-context.md from projectRoot. Returns undefined if not found. */
28
+ async function autoLoadProjectContext(projectRoot) {
29
+ try {
30
+ return await readFile(join(projectRoot, ".vibe", "project-context.md"), "utf-8");
31
+ }
32
+ catch {
33
+ return undefined;
34
+ }
35
+ }
5
36
  /** Tool set mapping per role. */
6
37
  export const ROLE_TOOL_SETS = {
7
38
  planner: "readonly",
8
39
  analyzer: "readonly",
9
- reviewer: "readonly",
40
+ reviewer: "analysis",
10
41
  diagnostician: "analysis",
11
42
  developer: "implementation",
12
43
  tester: "implementation",
@@ -15,8 +46,9 @@ export const ROLE_TOOL_SETS = {
15
46
  discovery: "readonly",
16
47
  projectAnalyzer: "analysis",
17
48
  documenter: "implementation",
18
- standardsEnricher: "readonly",
49
+ standardsEnricher: "none",
19
50
  systemArchitect: "design",
51
+ recover: "analysis",
20
52
  };
21
53
  /**
22
54
  * Returns the tool list for a given role.
@@ -34,14 +66,16 @@ export function getToolsForRole(role, cwd) {
34
66
  return [createReadTool(cwd), createWriteTool(cwd)];
35
67
  case "infrastructure":
36
68
  return [createBashTool(cwd)];
69
+ case "none":
70
+ return [];
37
71
  }
38
72
  }
39
73
  // ─── System Prompt Builder ───────────────────────────────────────────────────
40
74
  /**
41
75
  * Assembles the system prompt.
42
- * Order: basePrompt → Organization Standards → Feature Context → Available Skills → Project Context
76
+ * Order: basePrompt → Organization Standards → Feature Context → Project Context
43
77
  */
44
- export function buildSystemPrompt(basePrompt, standardsPrompt, featureContext, availableSkills, projectContext) {
78
+ export function buildSystemPrompt(basePrompt, standardsPrompt, featureContext, projectContext) {
45
79
  const parts = [basePrompt];
46
80
  if (standardsPrompt) {
47
81
  parts.push(standardsPrompt);
@@ -49,9 +83,6 @@ export function buildSystemPrompt(basePrompt, standardsPrompt, featureContext, a
49
83
  if (featureContext) {
50
84
  parts.push(featureContext);
51
85
  }
52
- if (availableSkills) {
53
- parts.push(availableSkills);
54
- }
55
86
  if (projectContext) {
56
87
  parts.push(`## Project Context\n\n${projectContext}`);
57
88
  }
@@ -65,12 +96,18 @@ export function buildSystemPrompt(basePrompt, standardsPrompt, featureContext, a
65
96
  * 3. Sets the model (uses default if not specified)
66
97
  */
67
98
  export async function createRoleAgent(options) {
68
- const { role, systemPrompt, config, projectRoot, model, featureContext, onEvent, getApiKey, initialMessages, availableSkills, projectContext, } = options;
69
- // Load and format standards
70
- const standardsContent = await loadStandardsForRole(role, config, projectRoot);
71
- const standardsPrompt = formatStandardsPrompt(standardsContent);
99
+ const { role, systemPrompt, config, projectRoot, model, featureContext, onEvent, getApiKey, initialMessages, projectContext: explicitProjectContext, } = options;
100
+ // Auto-load project-context.md for eligible roles when not explicitly provided
101
+ const projectContext = explicitProjectContext !== undefined
102
+ ? explicitProjectContext
103
+ : PROJECT_CONTEXT_ROLES.has(role)
104
+ ? await autoLoadProjectContext(projectRoot)
105
+ : undefined;
106
+ // Build standards index (agents read full files on demand)
107
+ const { entries: standardsIndex } = await buildStandardsIndex(config, projectRoot);
108
+ const standardsPrompt = formatStandardsIndexPrompt(standardsIndex);
72
109
  // Assemble system prompt
73
- const fullSystemPrompt = buildSystemPrompt(systemPrompt, standardsPrompt, featureContext, availableSkills, projectContext);
110
+ const fullSystemPrompt = buildSystemPrompt(systemPrompt, standardsPrompt, featureContext, projectContext);
74
111
  // Determine tool set
75
112
  const tools = getToolsForRole(role, projectRoot);
76
113
  // Configure compaction transform
@@ -1 +1 @@
1
- {"version":3,"file":"agent-factory.js","sourceRoot":"","sources":["../src/agent-factory.ts"],"names":[],"mappings":"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","sourcesContent":["import { Agent, type AgentEvent, type AgentMessage, type AgentTool } from \"@mariozechner/pi-agent-core\";\nimport type { Message, Model } from \"@mariozechner/pi-ai\";\nimport {\n\tcreateBashTool,\n\tcreateCodingTools,\n\tcreateReadOnlyTools,\n\tcreateReadTool,\n\tcreateWriteTool,\n} from \"@mariozechner/pi-coding-agent\";\nimport { createCompactionTransform } from \"./compaction.js\";\nimport { formatStandardsPrompt, loadStandardsForRole } from \"./standards.js\";\nimport type { AgentRole, VibeConfig } from \"./types.js\";\n\n// ─── Tool Set Mapping ────────────────────────────────────────────────────────\n\n/** Tool set category. */\nexport type ToolSet = \"readonly\" | \"analysis\" | \"implementation\" | \"design\" | \"infrastructure\";\n\n/** Tool set mapping per role. */\nexport const ROLE_TOOL_SETS: Record<AgentRole, ToolSet> = {\n\tplanner: \"readonly\",\n\tanalyzer: \"readonly\",\n\treviewer: \"readonly\",\n\tdiagnostician: \"analysis\",\n\tdeveloper: \"implementation\",\n\ttester: \"implementation\",\n\tarchitect: \"design\",\n\tcicd: \"infrastructure\",\n\tdiscovery: \"readonly\",\n\tprojectAnalyzer: \"analysis\",\n\tdocumenter: \"implementation\",\n\tstandardsEnricher: \"readonly\",\n\tsystemArchitect: \"design\",\n};\n\n/**\n * Returns the tool list for a given role.\n */\nexport function getToolsForRole(role: AgentRole, cwd: string): AgentTool<any>[] {\n\tconst toolSet = ROLE_TOOL_SETS[role];\n\tswitch (toolSet) {\n\t\tcase \"readonly\":\n\t\t\treturn createReadOnlyTools(cwd);\n\t\tcase \"analysis\":\n\t\t\treturn [createReadTool(cwd), createBashTool(cwd)];\n\t\tcase \"implementation\":\n\t\t\treturn createCodingTools(cwd);\n\t\tcase \"design\":\n\t\t\treturn [createReadTool(cwd), createWriteTool(cwd)];\n\t\tcase \"infrastructure\":\n\t\t\treturn [createBashTool(cwd)];\n\t}\n}\n\n// ─── System Prompt Builder ───────────────────────────────────────────────────\n\n/**\n * Assembles the system prompt.\n * Order: basePrompt → Organization Standards → Feature Context → Available Skills → Project Context\n */\nexport function buildSystemPrompt(\n\tbasePrompt: string,\n\tstandardsPrompt: string,\n\tfeatureContext?: string,\n\tavailableSkills?: string,\n\tprojectContext?: string,\n): string {\n\tconst parts = [basePrompt];\n\n\tif (standardsPrompt) {\n\t\tparts.push(standardsPrompt);\n\t}\n\n\tif (featureContext) {\n\t\tparts.push(featureContext);\n\t}\n\n\tif (availableSkills) {\n\t\tparts.push(availableSkills);\n\t}\n\n\tif (projectContext) {\n\t\tparts.push(`## Project Context\\n\\n${projectContext}`);\n\t}\n\n\treturn parts.join(\"\\n\\n\");\n}\n\n// ─── Agent Factory ───────────────────────────────────────────────────────────\n\n/** Dynamic API key lookup function. Used for expirable auth such as OAuth tokens. */\nexport type GetApiKeyFn = (provider: string) => Promise<string | undefined> | string | undefined;\n\n/** createRoleAgent options. */\nexport interface CreateRoleAgentOptions {\n\trole: AgentRole;\n\tsystemPrompt: string;\n\tconfig: VibeConfig;\n\tprojectRoot: string;\n\tmodel?: Model<any>;\n\tfeatureContext?: string;\n\tonEvent?: (event: AgentEvent) => void;\n\tgetApiKey?: GetApiKeyFn;\n\t/** Previous conversation history. Injected as Agent's initial messages when provided (for checkpoint restoration). */\n\tinitialMessages?: AgentMessage[];\n\t/** Lightweight skill index (name+description+path). Agents load full content via read tool when needed. */\n\tavailableSkills?: string;\n\t/** Project context (from project-context.md). Injected into system prompt for project awareness. */\n\tprojectContext?: string;\n}\n\n/**\n * Creates a role-configured Agent instance.\n *\n * 1. Loads role-specific standards and injects into system prompt\n * 2. Configures role-specific tool set\n * 3. Sets the model (uses default if not specified)\n */\nexport async function createRoleAgent(options: CreateRoleAgentOptions): Promise<Agent> {\n\tconst {\n\t\trole,\n\t\tsystemPrompt,\n\t\tconfig,\n\t\tprojectRoot,\n\t\tmodel,\n\t\tfeatureContext,\n\t\tonEvent,\n\t\tgetApiKey,\n\t\tinitialMessages,\n\t\tavailableSkills,\n\t\tprojectContext,\n\t} = options;\n\n\t// Load and format standards\n\tconst standardsContent = await loadStandardsForRole(role, config, projectRoot);\n\tconst standardsPrompt = formatStandardsPrompt(standardsContent);\n\n\t// Assemble system prompt\n\tconst fullSystemPrompt = buildSystemPrompt(\n\t\tsystemPrompt,\n\t\tstandardsPrompt,\n\t\tfeatureContext,\n\t\tavailableSkills,\n\t\tprojectContext,\n\t);\n\n\t// Determine tool set\n\tconst tools = getToolsForRole(role, projectRoot);\n\n\t// Configure compaction transform\n\tconst compactionTransform =\n\t\tconfig.compaction.enabled && model ? createCompactionTransform(model, config.compaction, getApiKey) : undefined;\n\n\t// Create Agent\n\tconst agent = new Agent({\n\t\tinitialState: {\n\t\t\tsystemPrompt: fullSystemPrompt,\n\t\t\ttools,\n\t\t\t...(model ? { model } : {}),\n\t\t\t...(initialMessages && initialMessages.length > 0 ? { messages: initialMessages } : {}),\n\t\t},\n\t\tgetApiKey,\n\t\ttransformContext: compactionTransform,\n\t});\n\n\t// Subscribe to events\n\tif (onEvent) {\n\t\tagent.subscribe(onEvent);\n\t}\n\n\treturn agent;\n}\n\n// ─── Agent Runner ────────────────────────────────────────────────────────────\n\n// ─── Error Formatting ────────────────────────────────────────────────────────\n\n/**\n * Formats a raw agent error string into a human-readable message.\n * Handles JSON error objects from LLM providers (e.g., Anthropic API errors).\n * Falls back to the original string if parsing fails.\n */\nexport function formatAgentError(raw: string): string {\n\tconst trimmed = raw.trim();\n\tif (!trimmed.startsWith(\"{\")) {\n\t\treturn raw;\n\t}\n\n\ttry {\n\t\tconst parsed = JSON.parse(trimmed);\n\n\t\t// Anthropic-style: {\"type\":\"error\",\"error\":{\"type\":\"api_error\",\"message\":\"...\"},\"request_id\":\"...\"}\n\t\tif (parsed.error && typeof parsed.error === \"object\" && parsed.error.message) {\n\t\t\tconst parts: string[] = [parsed.error.message];\n\t\t\tif (parsed.error.type) {\n\t\t\t\tparts[0] = `${parsed.error.message} (${parsed.error.type})`;\n\t\t\t}\n\t\t\tif (parsed.request_id) {\n\t\t\t\tparts.push(`requestId=${parsed.request_id}`);\n\t\t\t}\n\t\t\tif (parsed.error.details) {\n\t\t\t\tparts.push(`details=${JSON.stringify(parsed.error.details)}`);\n\t\t\t}\n\t\t\treturn parts.join(\" | \");\n\t\t}\n\n\t\t// Generic: {\"message\":\"...\"}\n\t\tif (parsed.message && typeof parsed.message === \"string\") {\n\t\t\treturn parsed.message;\n\t\t}\n\n\t\treturn raw;\n\t} catch {\n\t\treturn raw;\n\t}\n}\n\n// ─── Agent Runner ────────────────────────────────────────────────────────────\n\n/** runAgent options. */\nexport interface RunAgentOptions {\n\tonEvent?: (event: AgentEvent) => void;\n}\n\n/**\n * Sends a prompt to the agent, waits for completion, and returns the final response text.\n */\nexport async function runAgent(agent: Agent, prompt: string, options?: RunAgentOptions): Promise<string> {\n\tlet unsubscribe: (() => void) | undefined;\n\tif (options?.onEvent) {\n\t\tunsubscribe = agent.subscribe(options.onEvent);\n\t}\n\n\ttry {\n\t\tawait agent.prompt(prompt);\n\t\tawait agent.waitForIdle();\n\n\t\t// Agent stores LLM errors in state.error without throwing.\n\t\t// Explicitly check and propagate the error here.\n\t\tif (agent.state.error) {\n\t\t\tconst formatted = formatAgentError(agent.state.error);\n\t\t\tthrow new Error(`Agent error: ${formatted}`, { cause: agent.state.error });\n\t\t}\n\n\t\treturn extractLastAssistantText(agent.state.messages);\n\t} finally {\n\t\tunsubscribe?.();\n\t}\n}\n\n/** runAgent execution result (with history). */\nexport interface RunAgentResult {\n\t/** Text of the last assistant message. */\n\ttext: string;\n\t/** Full conversation history (for checkpointing). */\n\tmessages: AgentMessage[];\n}\n\n/**\n * Runs the agent and returns response text with full message history.\n * Use this function when checkpointing is needed.\n */\nexport async function runAgentWithHistory(\n\tagent: Agent,\n\tprompt: string,\n\toptions?: RunAgentOptions,\n): Promise<RunAgentResult> {\n\tlet unsubscribe: (() => void) | undefined;\n\tif (options?.onEvent) {\n\t\tunsubscribe = agent.subscribe(options.onEvent);\n\t}\n\n\ttry {\n\t\tawait agent.prompt(prompt);\n\t\tawait agent.waitForIdle();\n\n\t\tif (agent.state.error) {\n\t\t\tconst formatted = formatAgentError(agent.state.error);\n\t\t\tthrow new Error(`Agent error: ${formatted}`, { cause: agent.state.error });\n\t\t}\n\n\t\treturn {\n\t\t\ttext: extractLastAssistantText(agent.state.messages),\n\t\t\tmessages: [...agent.state.messages],\n\t\t};\n\t} finally {\n\t\tunsubscribe?.();\n\t}\n}\n\n/**\n * Extracts LLM messages (user, assistant, toolResult) from an AgentMessage array.\n * Custom message types are excluded, ensuring JSON serializability.\n */\nexport function filterSerializableMessages(messages: AgentMessage[]): Message[] {\n\treturn messages.filter(\n\t\t(m): m is Message => \"role\" in m && (m.role === \"user\" || m.role === \"assistant\" || m.role === \"toolResult\"),\n\t);\n}\n\n/**\n * Extracts the text of the last assistant message from a message list.\n */\nexport function extractLastAssistantText(messages: AgentMessage[]): string {\n\tfor (let i = messages.length - 1; i >= 0; i--) {\n\t\tconst msg = messages[i];\n\t\tif (msg.role === \"assistant\") {\n\t\t\tconst textParts: string[] = [];\n\t\t\tif (Array.isArray(msg.content)) {\n\t\t\t\tfor (const block of msg.content) {\n\t\t\t\t\tif (\"text\" in block && block.type === \"text\") {\n\t\t\t\t\t\ttextParts.push(block.text);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn textParts.join(\"\");\n\t\t}\n\t}\n\treturn \"\";\n}\n"]}
1
+ {"version":3,"file":"agent-factory.js","sourceRoot":"","sources":["../src/agent-factory.ts"],"names":[],"mappings":"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","sourcesContent":["import { readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nimport { Agent, type AgentEvent, type AgentMessage, type AgentTool } from \"@mariozechner/pi-agent-core\";\nimport type { Message, Model } from \"@mariozechner/pi-ai\";\nimport {\n\tcreateBashTool,\n\tcreateCodingTools,\n\tcreateReadOnlyTools,\n\tcreateReadTool,\n\tcreateWriteTool,\n} from \"@mariozechner/pi-coding-agent\";\nimport { createCompactionTransform } from \"./compaction.js\";\nimport { buildStandardsIndex, formatStandardsIndexPrompt } from \"./standards.js\";\nimport type { AgentRole, VibeConfig } from \"./types.js\";\n\n// ─── Project Context Auto-Load ───────────────────────────────────────────────\n\n/**\n * Roles that receive project-context.md automatically via system prompt.\n * Excluded roles:\n * - projectAnalyzer: generates project-context.md; injecting it would bias re-analysis\n * - cicd: executes git commands only; no project awareness needed\n */\nexport const PROJECT_CONTEXT_ROLES: ReadonlySet<AgentRole> = new Set<AgentRole>([\n\t\"discovery\",\n\t\"planner\",\n\t\"systemArchitect\",\n\t\"analyzer\",\n\t\"architect\",\n\t\"developer\",\n\t\"tester\",\n\t\"reviewer\",\n\t\"diagnostician\",\n\t\"documenter\",\n\t\"standardsEnricher\",\n]);\n\n/** Reads .vibe/project-context.md from projectRoot. Returns undefined if not found. */\nasync function autoLoadProjectContext(projectRoot: string): Promise<string | undefined> {\n\ttry {\n\t\treturn await readFile(join(projectRoot, \".vibe\", \"project-context.md\"), \"utf-8\");\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\n// ─── Tool Set Mapping ────────────────────────────────────────────────────────\n\n/** Tool set category. */\nexport type ToolSet = \"readonly\" | \"analysis\" | \"implementation\" | \"design\" | \"infrastructure\" | \"none\";\n\n/** Tool set mapping per role. */\nexport const ROLE_TOOL_SETS: Record<AgentRole, ToolSet> = {\n\tplanner: \"readonly\",\n\tanalyzer: \"readonly\",\n\treviewer: \"analysis\",\n\tdiagnostician: \"analysis\",\n\tdeveloper: \"implementation\",\n\ttester: \"implementation\",\n\tarchitect: \"design\",\n\tcicd: \"infrastructure\",\n\tdiscovery: \"readonly\",\n\tprojectAnalyzer: \"analysis\",\n\tdocumenter: \"implementation\",\n\tstandardsEnricher: \"none\",\n\tsystemArchitect: \"design\",\n\trecover: \"analysis\",\n};\n\n/**\n * Returns the tool list for a given role.\n */\nexport function getToolsForRole(role: AgentRole, cwd: string): AgentTool<any>[] {\n\tconst toolSet = ROLE_TOOL_SETS[role];\n\tswitch (toolSet) {\n\t\tcase \"readonly\":\n\t\t\treturn createReadOnlyTools(cwd);\n\t\tcase \"analysis\":\n\t\t\treturn [createReadTool(cwd), createBashTool(cwd)];\n\t\tcase \"implementation\":\n\t\t\treturn createCodingTools(cwd);\n\t\tcase \"design\":\n\t\t\treturn [createReadTool(cwd), createWriteTool(cwd)];\n\t\tcase \"infrastructure\":\n\t\t\treturn [createBashTool(cwd)];\n\t\tcase \"none\":\n\t\t\treturn [];\n\t}\n}\n\n// ─── System Prompt Builder ───────────────────────────────────────────────────\n\n/**\n * Assembles the system prompt.\n * Order: basePrompt → Organization Standards → Feature Context → Project Context\n */\nexport function buildSystemPrompt(\n\tbasePrompt: string,\n\tstandardsPrompt: string,\n\tfeatureContext?: string,\n\tprojectContext?: string,\n): string {\n\tconst parts = [basePrompt];\n\n\tif (standardsPrompt) {\n\t\tparts.push(standardsPrompt);\n\t}\n\n\tif (featureContext) {\n\t\tparts.push(featureContext);\n\t}\n\n\tif (projectContext) {\n\t\tparts.push(`## Project Context\\n\\n${projectContext}`);\n\t}\n\n\treturn parts.join(\"\\n\\n\");\n}\n\n// ─── Agent Factory ───────────────────────────────────────────────────────────\n\n/** Dynamic API key lookup function. Used for expirable auth such as OAuth tokens. */\nexport type GetApiKeyFn = (provider: string) => Promise<string | undefined> | string | undefined;\n\n/** createRoleAgent options. */\nexport interface CreateRoleAgentOptions {\n\trole: AgentRole;\n\tsystemPrompt: string;\n\tconfig: VibeConfig;\n\tprojectRoot: string;\n\tmodel?: Model<any>;\n\tfeatureContext?: string;\n\tonEvent?: (event: AgentEvent) => void;\n\tgetApiKey?: GetApiKeyFn;\n\t/** Previous conversation history. Injected as Agent's initial messages when provided (for checkpoint restoration). */\n\tinitialMessages?: AgentMessage[];\n\t/** Project context (from project-context.md). Injected into system prompt for project awareness. */\n\tprojectContext?: string;\n}\n\n/**\n * Creates a role-configured Agent instance.\n *\n * 1. Loads role-specific standards and injects into system prompt\n * 2. Configures role-specific tool set\n * 3. Sets the model (uses default if not specified)\n */\nexport async function createRoleAgent(options: CreateRoleAgentOptions): Promise<Agent> {\n\tconst {\n\t\trole,\n\t\tsystemPrompt,\n\t\tconfig,\n\t\tprojectRoot,\n\t\tmodel,\n\t\tfeatureContext,\n\t\tonEvent,\n\t\tgetApiKey,\n\t\tinitialMessages,\n\t\tprojectContext: explicitProjectContext,\n\t} = options;\n\n\t// Auto-load project-context.md for eligible roles when not explicitly provided\n\tconst projectContext =\n\t\texplicitProjectContext !== undefined\n\t\t\t? explicitProjectContext\n\t\t\t: PROJECT_CONTEXT_ROLES.has(role)\n\t\t\t\t? await autoLoadProjectContext(projectRoot)\n\t\t\t\t: undefined;\n\n\t// Build standards index (agents read full files on demand)\n\tconst { entries: standardsIndex } = await buildStandardsIndex(config, projectRoot);\n\tconst standardsPrompt = formatStandardsIndexPrompt(standardsIndex);\n\n\t// Assemble system prompt\n\tconst fullSystemPrompt = buildSystemPrompt(systemPrompt, standardsPrompt, featureContext, projectContext);\n\n\t// Determine tool set\n\tconst tools = getToolsForRole(role, projectRoot);\n\n\t// Configure compaction transform\n\tconst compactionTransform =\n\t\tconfig.compaction.enabled && model ? createCompactionTransform(model, config.compaction, getApiKey) : undefined;\n\n\t// Create Agent\n\tconst agent = new Agent({\n\t\tinitialState: {\n\t\t\tsystemPrompt: fullSystemPrompt,\n\t\t\ttools,\n\t\t\t...(model ? { model } : {}),\n\t\t\t...(initialMessages && initialMessages.length > 0 ? { messages: initialMessages } : {}),\n\t\t},\n\t\tgetApiKey,\n\t\ttransformContext: compactionTransform,\n\t});\n\n\t// Subscribe to events\n\tif (onEvent) {\n\t\tagent.subscribe(onEvent);\n\t}\n\n\treturn agent;\n}\n\n// ─── Agent Runner ────────────────────────────────────────────────────────────\n\n// ─── Error Formatting ────────────────────────────────────────────────────────\n\n/**\n * Formats a raw agent error string into a human-readable message.\n * Handles JSON error objects from LLM providers (e.g., Anthropic API errors).\n * Falls back to the original string if parsing fails.\n */\nexport function formatAgentError(raw: string): string {\n\tconst trimmed = raw.trim();\n\tif (!trimmed.startsWith(\"{\")) {\n\t\treturn raw;\n\t}\n\n\ttry {\n\t\tconst parsed = JSON.parse(trimmed);\n\n\t\t// Anthropic-style: {\"type\":\"error\",\"error\":{\"type\":\"api_error\",\"message\":\"...\"},\"request_id\":\"...\"}\n\t\tif (parsed.error && typeof parsed.error === \"object\" && parsed.error.message) {\n\t\t\tconst parts: string[] = [parsed.error.message];\n\t\t\tif (parsed.error.type) {\n\t\t\t\tparts[0] = `${parsed.error.message} (${parsed.error.type})`;\n\t\t\t}\n\t\t\tif (parsed.request_id) {\n\t\t\t\tparts.push(`requestId=${parsed.request_id}`);\n\t\t\t}\n\t\t\tif (parsed.error.details) {\n\t\t\t\tparts.push(`details=${JSON.stringify(parsed.error.details)}`);\n\t\t\t}\n\t\t\treturn parts.join(\" | \");\n\t\t}\n\n\t\t// Generic: {\"message\":\"...\"}\n\t\tif (parsed.message && typeof parsed.message === \"string\") {\n\t\t\treturn parsed.message;\n\t\t}\n\n\t\treturn raw;\n\t} catch {\n\t\treturn raw;\n\t}\n}\n\n// ─── Agent Runner ────────────────────────────────────────────────────────────\n\n/** runAgent options. */\nexport interface RunAgentOptions {\n\tonEvent?: (event: AgentEvent) => void;\n}\n\n/**\n * Sends a prompt to the agent, waits for completion, and returns the final response text.\n */\nexport async function runAgent(agent: Agent, prompt: string, options?: RunAgentOptions): Promise<string> {\n\tlet unsubscribe: (() => void) | undefined;\n\tif (options?.onEvent) {\n\t\tunsubscribe = agent.subscribe(options.onEvent);\n\t}\n\n\ttry {\n\t\tawait agent.prompt(prompt);\n\t\tawait agent.waitForIdle();\n\n\t\t// Agent stores LLM errors in state.error without throwing.\n\t\t// Explicitly check and propagate the error here.\n\t\tif (agent.state.error) {\n\t\t\tconst formatted = formatAgentError(agent.state.error);\n\t\t\tthrow new Error(`Agent error: ${formatted}`, { cause: agent.state.error });\n\t\t}\n\n\t\treturn extractLastAssistantText(agent.state.messages);\n\t} finally {\n\t\tunsubscribe?.();\n\t}\n}\n\n/** runAgent execution result (with history). */\nexport interface RunAgentResult {\n\t/** Text of the last assistant message. */\n\ttext: string;\n\t/** Full conversation history (for checkpointing). */\n\tmessages: AgentMessage[];\n}\n\n/**\n * Runs the agent and returns response text with full message history.\n * Use this function when checkpointing is needed.\n */\nexport async function runAgentWithHistory(\n\tagent: Agent,\n\tprompt: string,\n\toptions?: RunAgentOptions,\n): Promise<RunAgentResult> {\n\tlet unsubscribe: (() => void) | undefined;\n\tif (options?.onEvent) {\n\t\tunsubscribe = agent.subscribe(options.onEvent);\n\t}\n\n\ttry {\n\t\tawait agent.prompt(prompt);\n\t\tawait agent.waitForIdle();\n\n\t\tif (agent.state.error) {\n\t\t\tconst formatted = formatAgentError(agent.state.error);\n\t\t\tthrow new Error(`Agent error: ${formatted}`, { cause: agent.state.error });\n\t\t}\n\n\t\treturn {\n\t\t\ttext: extractLastAssistantText(agent.state.messages),\n\t\t\tmessages: [...agent.state.messages],\n\t\t};\n\t} finally {\n\t\tunsubscribe?.();\n\t}\n}\n\n/**\n * Extracts LLM messages (user, assistant, toolResult) from an AgentMessage array.\n * Custom message types are excluded, ensuring JSON serializability.\n */\nexport function filterSerializableMessages(messages: AgentMessage[]): Message[] {\n\treturn messages.filter(\n\t\t(m): m is Message => \"role\" in m && (m.role === \"user\" || m.role === \"assistant\" || m.role === \"toolResult\"),\n\t);\n}\n\n/**\n * Extracts the text of the last assistant message from a message list.\n */\nexport function extractLastAssistantText(messages: AgentMessage[]): string {\n\tfor (let i = messages.length - 1; i >= 0; i--) {\n\t\tconst msg = messages[i];\n\t\tif (msg.role === \"assistant\") {\n\t\t\tconst textParts: string[] = [];\n\t\t\tif (Array.isArray(msg.content)) {\n\t\t\t\tfor (const block of msg.content) {\n\t\t\t\t\tif (\"text\" in block && block.type === \"text\") {\n\t\t\t\t\t\ttextParts.push(block.text);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn textParts.join(\"\");\n\t\t}\n\t}\n\treturn \"\";\n}\n"]}
package/dist/cli.d.ts CHANGED
@@ -39,11 +39,15 @@ export type VibeCommand = {
39
39
  type: "config";
40
40
  } | {
41
41
  type: "init";
42
+ } | {
43
+ type: "reset";
44
+ } | {
45
+ type: "recover";
42
46
  } | {
43
47
  type: "help";
44
48
  };
45
49
  /** Available subcommands */
46
- export declare const VIBE_SUBCOMMANDS: readonly ["new", "enhance", "fix", "refactor", "status", "pause", "resume", "steer", "log", "analyze", "config", "init"];
50
+ export declare const VIBE_SUBCOMMANDS: readonly ["new", "enhance", "fix", "refactor", "status", "pause", "resume", "steer", "log", "analyze", "config", "init", "reset", "recover"];
47
51
  /**
48
52
  * Parse /vibe command arguments.
49
53
  *
@@ -59,6 +63,8 @@ export declare const VIBE_SUBCOMMANDS: readonly ["new", "enhance", "fix", "refac
59
63
  * - /vibe log <featureId>
60
64
  * - /vibe config
61
65
  * - /vibe init
66
+ * - /vibe reset
67
+ * - /vibe recover
62
68
  */
63
69
  export declare function parseVibeCommand(args: string): VibeCommand;
64
70
  /** 14 standard file templates generated by /vibe init */
package/dist/cli.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAEA,0BAA0B;AAC1B,MAAM,MAAM,WAAW,GACpB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,GACrC;IAAE,IAAI,EAAE,KAAK,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,GACpC;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,GAC5D;IAAE,IAAI,EAAE,KAAK,CAAC;IAAC,WAAW,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,GACvD;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GACzD;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,GACtC;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,GACpC;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,GACtC;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GACtD;IAAE,IAAI,EAAE,KAAK,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,GAClC;IAAE,IAAI,EAAE,SAAS,CAAA;CAAE,GACnB;IAAE,IAAI,EAAE,QAAQ,CAAA;CAAE,GAClB;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAChB;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAEpB,4BAA4B;AAC5B,eAAO,MAAM,gBAAgB,0HAanB,CAAC;AAIX;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,CAqH1D;AA8CD,yDAAyD;AACzD,eAAO,MAAM,kBAAkB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAm5BrD,CAAC","sourcesContent":["// ─── Command Types ───────────────────────────────────────────────────────────\n\n/** Parsed vibe command */\nexport type VibeCommand =\n\t| { type: \"auto\"; requirement: string }\n\t| { type: \"new\"; requirement: string }\n\t| { type: \"enhance\"; featureId?: string; requirement: string }\n\t| { type: \"fix\"; description: string; issueRef?: string }\n\t| { type: \"refactor\"; featureId?: string; purpose: string }\n\t| { type: \"status\"; featureId?: string }\n\t| { type: \"pause\"; featureId: string }\n\t| { type: \"resume\"; featureId?: string }\n\t| { type: \"steer\"; featureId: string; feedback: string }\n\t| { type: \"log\"; featureId: string }\n\t| { type: \"analyze\" }\n\t| { type: \"config\" }\n\t| { type: \"init\" }\n\t| { type: \"help\" };\n\n/** Available subcommands */\nexport const VIBE_SUBCOMMANDS = [\n\t\"new\",\n\t\"enhance\",\n\t\"fix\",\n\t\"refactor\",\n\t\"status\",\n\t\"pause\",\n\t\"resume\",\n\t\"steer\",\n\t\"log\",\n\t\"analyze\",\n\t\"config\",\n\t\"init\",\n] as const;\n\n// ─── Parsing ─────────────────────────────────────────────────────────────────\n\n/**\n * Parse /vibe command arguments.\n *\n * Format:\n * - /vibe new \"requirement\"\n * - /vibe enhance <featureId> \"requirement\"\n * - /vibe fix \"description\" --issue N\n * - /vibe refactor <featureId> \"purpose\"\n * - /vibe status [featureId]\n * - /vibe pause <featureId>\n * - /vibe resume <featureId>\n * - /vibe steer <featureId> \"feedback\"\n * - /vibe log <featureId>\n * - /vibe config\n * - /vibe init\n */\nexport function parseVibeCommand(args: string): VibeCommand {\n\tconst trimmed = args.trim();\n\n\tif (!trimmed) {\n\t\treturn { type: \"help\" };\n\t}\n\n\tconst parts = splitArgs(trimmed);\n\tconst subcommand = parts[0];\n\n\tswitch (subcommand) {\n\t\tcase \"new\": {\n\t\t\tconst requirement = parts.slice(1).join(\" \");\n\t\t\tif (!requirement) {\n\t\t\t\tthrow new Error(\"Usage: /vibe new <requirement>\");\n\t\t\t}\n\t\t\treturn { type: \"new\", requirement };\n\t\t}\n\n\t\tcase \"enhance\": {\n\t\t\tif (parts.length < 2) {\n\t\t\t\tthrow new Error(\"Usage: /vibe enhance [featureId] <requirement>\");\n\t\t\t}\n\t\t\tif (isFeatureId(parts[1])) {\n\t\t\t\tconst featureId = parts[1];\n\t\t\t\tconst requirement = parts.slice(2).join(\" \");\n\t\t\t\tif (!requirement) {\n\t\t\t\t\tthrow new Error(\"Usage: /vibe enhance [featureId] <requirement>\");\n\t\t\t\t}\n\t\t\t\treturn { type: \"enhance\", featureId, requirement };\n\t\t\t}\n\t\t\tconst requirement = parts.slice(1).join(\" \");\n\t\t\treturn { type: \"enhance\", requirement };\n\t\t}\n\n\t\tcase \"fix\": {\n\t\t\tconst issueIdx = parts.indexOf(\"--issue\");\n\t\t\tlet issueRef: string | undefined;\n\t\t\tlet descParts: string[];\n\n\t\t\tif (issueIdx !== -1) {\n\t\t\t\tissueRef = parts[issueIdx + 1];\n\t\t\t\tdescParts = [...parts.slice(1, issueIdx), ...parts.slice(issueIdx + 2)];\n\t\t\t} else {\n\t\t\t\tdescParts = parts.slice(1);\n\t\t\t}\n\n\t\t\tconst description = descParts.join(\" \");\n\t\t\tif (!description) {\n\t\t\t\tthrow new Error(\"Usage: /vibe fix <description> [--issue N]\");\n\t\t\t}\n\t\t\treturn { type: \"fix\", description, issueRef };\n\t\t}\n\n\t\tcase \"refactor\": {\n\t\t\tif (parts.length < 2) {\n\t\t\t\tthrow new Error(\"Usage: /vibe refactor [featureId] <purpose>\");\n\t\t\t}\n\t\t\tif (isFeatureId(parts[1])) {\n\t\t\t\tconst featureId = parts[1];\n\t\t\t\tconst purpose = parts.slice(2).join(\" \");\n\t\t\t\tif (!purpose) {\n\t\t\t\t\tthrow new Error(\"Usage: /vibe refactor [featureId] <purpose>\");\n\t\t\t\t}\n\t\t\t\treturn { type: \"refactor\", featureId, purpose };\n\t\t\t}\n\t\t\tconst purpose = parts.slice(1).join(\" \");\n\t\t\treturn { type: \"refactor\", purpose };\n\t\t}\n\n\t\tcase \"status\": {\n\t\t\tconst featureId = parts[1];\n\t\t\treturn { type: \"status\", featureId };\n\t\t}\n\n\t\tcase \"pause\": {\n\t\t\tif (!parts[1]) {\n\t\t\t\tthrow new Error(\"Usage: /vibe pause <featureId>\");\n\t\t\t}\n\t\t\treturn { type: \"pause\", featureId: parts[1] };\n\t\t}\n\n\t\tcase \"resume\": {\n\t\t\treturn { type: \"resume\", featureId: parts[1] };\n\t\t}\n\n\t\tcase \"steer\": {\n\t\t\tif (parts.length < 3) {\n\t\t\t\tthrow new Error(\"Usage: /vibe steer <featureId> <feedback>\");\n\t\t\t}\n\t\t\tconst featureId = parts[1];\n\t\t\tconst feedback = parts.slice(2).join(\" \");\n\t\t\treturn { type: \"steer\", featureId, feedback };\n\t\t}\n\n\t\tcase \"log\": {\n\t\t\tif (!parts[1]) {\n\t\t\t\tthrow new Error(\"Usage: /vibe log <featureId>\");\n\t\t\t}\n\t\t\treturn { type: \"log\", featureId: parts[1] };\n\t\t}\n\n\t\tcase \"analyze\":\n\t\t\treturn { type: \"analyze\" };\n\n\t\tcase \"config\":\n\t\t\treturn { type: \"config\" };\n\n\t\tcase \"init\":\n\t\t\treturn { type: \"init\" };\n\n\t\tdefault: {\n\t\t\t// Text that is not a subcommand is treated as auto mode\n\t\t\tconst requirement = parts.join(\" \");\n\t\t\treturn { type: \"auto\", requirement };\n\t\t}\n\t}\n}\n\n/** featureId prefix list. Used to identify featureId tokens. */\nconst FEATURE_ID_PREFIXES = [\"feat-\", \"fix-\", \"enhance-\", \"refactor-\"];\n\n/** Check if a token is a featureId. */\nfunction isFeatureId(token: string): boolean {\n\treturn FEATURE_ID_PREFIXES.some((prefix) => token.startsWith(prefix));\n}\n\n/** Split by whitespace, preserving spaces inside quotes. */\nfunction splitArgs(input: string): string[] {\n\tconst result: string[] = [];\n\tlet current = \"\";\n\tlet inQuote = false;\n\tlet quoteChar = \"\";\n\n\tfor (const ch of input) {\n\t\tif (inQuote) {\n\t\t\tif (ch === quoteChar) {\n\t\t\t\tinQuote = false;\n\t\t\t} else {\n\t\t\t\tcurrent += ch;\n\t\t\t}\n\t\t} else if (ch === '\"' || ch === \"'\") {\n\t\t\tinQuote = true;\n\t\t\tquoteChar = ch;\n\t\t} else if (ch === \" \") {\n\t\t\tif (current) {\n\t\t\t\tresult.push(current);\n\t\t\t\tcurrent = \"\";\n\t\t\t}\n\t\t} else {\n\t\t\tcurrent += ch;\n\t\t}\n\t}\n\n\tif (current) {\n\t\tresult.push(current);\n\t}\n\n\treturn result;\n}\n\n// ─── Standard Templates ──────────────────────────────────────────────────────\n\n/** 14 standard file templates generated by /vibe init */\nexport const STANDARD_TEMPLATES: Record<string, string> = {\n\t\"coding-style.md\": `# Coding Style\n\n<!-- Customize: adjust these defaults to match your project's conventions. -->\n\n## Formatting\n\n- Use consistent indentation (tabs or spaces — pick one and enforce it)\n- Keep line length reasonable (80-120 characters)\n- Use trailing commas in multi-line structures for cleaner diffs\n\n## Naming\n\n- Files: follow the project's convention (e.g., kebab-case \\`user-service.ts\\`, snake_case \\`user_service.py\\`)\n- Classes/interfaces: PascalCase (\\`UserService\\`, \\`AuthProvider\\`)\n- Functions/variables: follow the language convention (e.g., camelCase for JS/TS/Java, snake_case for Python/Rust)\n- Constants: UPPER_SNAKE_CASE (\\`MAX_RETRIES\\`, \\`DEFAULT_TIMEOUT\\`)\n- Booleans: prefix with \\`is\\`, \\`has\\`, \\`can\\`, \\`should\\` (\\`isActive\\`, \\`hasPermission\\`)\n- No abbreviations unless universally understood (\\`id\\`, \\`url\\` are OK; \\`usr\\`, \\`cfg\\` are not)\n\n## Imports\n\n- Use standard module imports following the project's conventions\n- Group imports: external packages first, then internal modules, separated by a blank line\n`,\n\t\"coding-conventions.md\": `# Coding Conventions\n\n<!-- Customize: adjust these defaults to match your project's conventions. -->\n\n## Error Handling\n\n- Handle errors explicitly — no silent failures, no empty catch blocks\n- Use typed errors when the language supports it\n- Validate inputs at module boundaries (public APIs, request handlers)\n- Fail fast: detect invalid state early and report clearly\n\n## Dependency Injection\n\n- Business logic depends on interfaces (ports), never on concrete implementations (adapters)\n- Wire concrete adapters in a single composition root (factory function or module)\n- Swapping an adapter (e.g., in-memory → database) should require changing only the composition root\n\n## Comments\n\n- Documentation comments for all public APIs (e.g., JSDoc, docstrings, GoDoc)\n- Explain \"why\", not \"what\" — the code shows what, comments explain intent\n- No commented-out code in committed files\n\n## Constants\n\n- No magic numbers or strings — use named constants\n- Group related constants in a dedicated module or object\n\n## Functions\n\n- Keep functions small and focused — one responsibility per function\n- Explicit return types or type hints for public functions where the language supports it\n- No side effects in functions named as queries (get*, is*, has*)\n`,\n\t\"tech-stack.md\": `# Tech Stack\n\n<!-- This file is populated during project initialization or discovery. -->\n<!-- Update it when the tech stack changes. -->\n\n## Languages\n<!-- e.g., TypeScript 5.x, Python 3.12, Go 1.22 -->\n\n## Frameworks\n<!-- e.g., React 19, Express 5, FastAPI -->\n\n## Build Tools\n<!-- e.g., Vite, esbuild, webpack -->\n\n## Runtime\n<!-- e.g., Node.js 20, Deno, Bun -->\n\n## Package Manager\n<!-- e.g., npm, pnpm, yarn -->\n`,\n\t\"architecture-principles.md\": `# Architecture Principles\n\n<!-- Customize: adjust these defaults to match your project's architecture. -->\n\n## Separation of Concerns\n\n- Each module has a single, well-defined responsibility\n- UI, business logic, and data access are separate layers\n- Cross-cutting concerns (logging, auth) are injected, not hard-wired\n\n## Integration Boundary Principle\n\nAll external dependencies must be abstracted behind interfaces (ports) with swappable adapter implementations.\n\n### What counts as an external dependency\n\n- Data persistence (databases, file systems, localStorage)\n- Authentication / authorization providers\n- Third-party service calls (payment, email, SMS, push notifications)\n- File / media / blob storage\n- Time / scheduling / cron services\n- Message queues / event buses\n\n### Required pattern\n\n1. **Interface (port)**: an interface or abstract type defining the contract, using the project's language idiom (e.g., TypeScript interface, Python Protocol/ABC, Go interface). Named descriptively: \\`TodoRepository\\`, \\`AuthProvider\\`, \\`NotificationService\\`.\n2. **Mock/in-memory adapter**: a default implementation that works without any external system. Named with prefix: \\`InMemory*\\`, \\`Stub*\\`, \\`Console*\\`, \\`Fake*\\`.\n3. **Composition root**: a single location (factory function, module, or DI container) where concrete adapters are wired. Swapping an adapter means changing only this location.\n\n### Why\n\n- Apps work immediately with mock adapters — no infrastructure setup needed\n- Tests run without external dependencies\n- Real adapters can be swapped in later without touching business logic\n\n## Testability\n\n- Every component must be independently testable\n- Dependencies are injected, not instantiated internally\n- No global mutable state\n\n## Dependency Direction\n\n- Higher-level modules must not depend on lower-level implementation details\n- Depend on abstractions (interfaces), not concretions\n`,\n\t\"design-guide.md\": `# Design Guide\n\n<!-- Customize: adjust these defaults to match your project's design approach. -->\n\n## API Design\n\n- APIs expose clear contracts — input types, output types, error types\n- Use consistent naming: \\`getX\\`, \\`createX\\`, \\`updateX\\`, \\`deleteX\\`\n- Return typed results, not raw primitives where context matters\n- Document error conditions and edge cases in documentation comments\n\n## Data Modeling\n\n- Define explicit types for all domain entities — no implicit shapes\n- Nullable fields must be explicitly typed (e.g., \\`field: string | null\\` in TS, \\`Optional[str]\\` in Python)\n- Validate data at boundaries (API handlers, file reads, user input)\n- Separate internal models from external representations (DTOs)\n\n## Component Design\n\n- Prefer composition over inheritance\n- Keep interfaces small and focused (Interface Segregation)\n- Design for extension — new behavior via new implementations, not modification of existing code\n`,\n\t\"api-design.md\": `# API Design\n\n<!-- Customize: adjust these defaults to match your project's API conventions. -->\n\n## REST API\n\n- Resource-oriented URLs: \\`/users\\`, \\`/users/:id\\`, \\`/users/:id/posts\\`\n- Use standard HTTP methods: GET (read), POST (create), PUT/PATCH (update), DELETE (remove)\n- Consistent status codes: 200 (OK), 201 (Created), 400 (Bad Request), 404 (Not Found), 500 (Internal Error)\n- Return JSON with consistent envelope: \\`{ data, error, meta }\\`\n- Version APIs when breaking changes are unavoidable: \\`/api/v1/...\\`\n\n## Language-Specific API Conventions\n\n- Small, focused functions — one purpose per function\n- Explicit return types or type hints for all public functions\n- Avoid untyped or loosely-typed constructs (e.g., \\`any\\` in TS, \\`Any\\` in Python) — use narrow types\n- Use tagged unions, discriminated unions, or enums for complex state where the language supports it\n- Prefer async/await patterns for asynchronous operations\n`,\n\t\"testing-standards.md\": `# Testing Standards\n\n<!-- Customize: adjust these defaults to match your project's testing approach. -->\n\n## Test Layers\n\n| Layer | Role | Scope |\n|-------|------|-------|\n| **Unit** | Verify isolated module logic | Single function/class, all dependencies mocked |\n| **Integration** | Verify module wiring and interaction | Multiple modules, external boundaries mocked |\n| **E2E** | Verify end-to-end user workflow | Full application, real or simulated environment |\n\n## Change Type → Test Scope\n\n| What changed | Unit | Integration | E2E / Manual |\n|--------------|:----:|:-----------:|:------------:|\n| Internal logic (algorithm, validation) | Required | — | — |\n| Public API / interface signature | Required | Required if callers exist | — |\n| Module wiring (callbacks, DI, factory) | — | Required | — |\n| User-facing workflow | Required for logic | Required for wiring | Required |\n\n## Unit Test Rules\n\n- Test one module in isolation — mock all dependencies\n- Cover edge cases: empty input, invalid state, boundary values\n- Tests must be deterministic — no dependency on external state, time, or network\n- No meaningless tests that always pass\n\n## Integration Test Rules\n\n- Mock external boundaries (database, network, file system) but use real internal modules\n- Verify callback wiring: A creates B with callback → trigger callback → verify side effect\n- Verify argument passing and state flow across modules\n\n## E2E / Manual Verification\n\n- Required for TUI rendering, prompt effectiveness, cross-terminal behavior\n- Document what was checked and the result in test reports\n\n## Mock Adapters\n\n- All tests must use mock/in-memory adapters — never depend on real external systems\n- Mock adapters must faithfully implement the interface contract\n`,\n\t\"documentation.md\": `# Documentation\n\n<!-- Customize: adjust these defaults to match your project's documentation approach. -->\n\n## Code Documentation\n\n- Documentation comments for all public APIs (e.g., JSDoc, Python docstrings, GoDoc, Javadoc)\n- Include parameter descriptions, return types, and thrown errors/exceptions\n- Explain complex algorithms or non-obvious design decisions inline\n\n## README\n\nEvery project must have a README.md containing:\n- **Purpose**: what the project does and why\n- **Setup**: how to install and configure\n- **Usage**: how to run and use\n- **Architecture**: high-level overview of structure and key decisions\n- **Contributing**: how to develop and test\n\n## Commit Messages\n\n- Use conventional commits: \\`feat:\\`, \\`fix:\\`, \\`refactor:\\`, \\`docs:\\`, \\`test:\\`\n- First line: imperative mood, under 72 characters\n- Body: explain \"why\" when the change is non-obvious\n`,\n\t\"git-workflow.md\": `# Git Workflow\n\n<!-- Customize: adjust these defaults to match your project's Git workflow. -->\n\n## Branching\n\n- \\`main\\` (or \\`master\\`): stable, always deployable\n- Feature branches: \\`feat/description\\`, \\`fix/description\\`, \\`refactor/description\\`\n- Branch from the latest main, keep branches short-lived\n\n## Commits\n\n- Use conventional commits: \\`feat:\\`, \\`fix:\\`, \\`refactor:\\`, \\`docs:\\`, \\`test:\\`, \\`chore:\\`\n- Atomic commits: each commit is a single logical change\n- First line: imperative mood, under 72 characters\n\n## Merging\n\n- Merge feature branches with \\`--no-ff\\` to preserve branch history\n- Resolve conflicts in the feature branch before merging\n- Delete feature branches after merge (or keep for traceability — choose one convention)\n- Never force-push to shared branches\n`,\n\t\"security-policy.md\": `# Security Policy\n\n<!-- Customize: adjust these defaults to match your project's security requirements. -->\n\n## Secrets Management\n\n- No secrets, API keys, or credentials in source code or version control\n- Use environment variables or secret management services\n- Add sensitive file patterns to \\`.gitignore\\`\n\n## Input Validation\n\n- Validate all external input at system boundaries (API handlers, file reads, user input)\n- Sanitize data before rendering to prevent XSS\n- Use parameterized queries to prevent SQL injection\n\n## Authentication & Authorization\n\n- Use established libraries — do not implement custom crypto\n- Apply least privilege: grant minimum permissions required\n- Expire sessions and tokens with reasonable timeouts\n\n## Dependencies\n\n- Regularly scan dependencies for known vulnerabilities\n- Update vulnerable dependencies promptly\n- Evaluate new dependencies for security track record before adding\n`,\n\t\"dependency-policy.md\": `# Dependency Policy\n\n<!-- Customize: adjust these defaults to match your project's dependency approach. -->\n\n## Adding Dependencies\n\nBefore adding a dependency, evaluate:\n- **Necessity**: can this be implemented in a few lines without the dependency?\n- **Maintenance**: is the package actively maintained? When was the last release?\n- **Size**: what is the install size and dependency tree depth?\n- **License**: is the license compatible with your project?\n- **Security**: does it have known vulnerabilities?\n\nPrefer standard library / platform APIs over third-party packages when feasible.\n\n## Version Management\n\n- Pin exact versions or use lock files (\\`package-lock.json\\`, \\`pnpm-lock.yaml\\`)\n- Update dependencies regularly — do not let them go stale\n- Test after updating — run the full test suite before committing dependency updates\n`,\n\t\"performance-guidelines.md\": `# Performance Guidelines\n\n<!-- Customize: adjust these defaults to match your project's performance needs. -->\n\n## Principles\n\n- Do not optimize prematurely — write clear code first, optimize when measured\n- Profile before optimizing — identify actual bottlenecks, not guessed ones\n- Use async I/O where appropriate — avoid blocking the event loop or main thread with synchronous operations\n\n## Data Structures\n\n- Choose appropriate data structures for the access pattern (Map for lookups, Array for iteration)\n- Avoid unnecessary copying of large data structures\n\n## Resource Management\n\n- Close resources (file handles, connections, streams) when done\n- Use connection pooling for databases and HTTP clients\n- Set reasonable timeouts for all external calls\n`,\n\t\"accessibility.md\": `# Accessibility\n\n<!-- Customize: adjust these defaults if your project has a UI. -->\n<!-- If your project has no user-facing UI, this file can be left as-is. -->\n\n## Standards\n\n- Follow WCAG 2.1 Level AA guidelines for web applications\n- Use semantic HTML elements (\\`<button>\\`, \\`<nav>\\`, \\`<main>\\`, not \\`<div>\\` for everything)\n- Provide text alternatives for non-text content (images, icons)\n\n## Keyboard Navigation\n\n- All interactive elements must be keyboard-accessible\n- Focus order must follow a logical reading sequence\n- Visible focus indicators on all interactive elements\n\n## Screen Readers\n\n- Use ARIA attributes when semantic HTML is insufficient\n- Test with at least one screen reader\n\n## Visual Design\n\n- Minimum 4.5:1 contrast ratio for normal text\n- Do not convey information by color alone\n- Support user font size preferences\n`,\n\t\"observability.md\": `# Observability\n\n<!-- Customize: adjust these defaults to match your project's observability needs. -->\n\n## Logging\n\n- Use structured logging (JSON or key-value pairs) — not free-form text\n- Include context: timestamp, level, module, request ID where applicable\n- Log at appropriate levels: ERROR for failures, WARN for recoverable issues, INFO for state changes, DEBUG for troubleshooting\n\n## Metrics\n\n<!-- Define key metrics for your application. Examples: -->\n- Request latency (p50, p95, p99)\n- Error rate\n- Resource utilization (memory, CPU, connections)\n\n## Tracing\n\n- Propagate trace/correlation IDs across service boundaries\n- Instrument key operations: incoming requests, outgoing calls, database queries\n- Use consistent span naming conventions\n`,\n\t\"logging.md\": `# Logging\n\n<!-- Define your logging standards. -->\n\n## Principles\n<!-- Basic principles such as no direct console.* calls -->\n\n## Log Levels\n<!-- Criteria for debug, info, warn, error usage -->\n\n## Log Format\n<!-- Log format rules -->\n\n## Injection Pattern\n<!-- Logger injection approach (callbacks, DI, etc.) -->\n`,\n\t\".artifact-standards.md\": `# Artifact Standards\n\nStandards for all artifacts generated by agents under \\\\\\`.vibe/features/{featureId}/\\\\\\`.\n\n## Artifact List\n\n| File | Creator | Workflow | Required |\n|---|---|---|---|\n| \\\\\\`spec.md\\\\\\` | Planner | all | required |\n| \\\\\\`design.md\\\\\\` | Architect | all | required |\n| \\\\\\`impact-report.md\\\\\\` | Analyzer | enhancement, refactor | conditional |\n| \\\\\\`diagnosis.md\\\\\\` | Diagnostician | bugfix | conditional |\n| \\\\\\`review.md\\\\\\` | Reviewer | all | required |\n| \\\\\\`test-report.md\\\\\\` | Tester | all | required |\n| \\\\\\`regression-report.md\\\\\\` | Tester | enhancement, bugfix, refactor | conditional |\n| \\\\\\`retry-log.md\\\\\\` | Pipeline Engine | on retry | conditional |\n| \\\\\\`status.json\\\\\\` | Pipeline Engine / VibeStore | all | required |\n\n---\n\n## spec.md (Planner)\n\nDefines the purpose, scope, and requirements of a feature.\n\n### Required Sections\n\n\\\\\\`\\\\\\`\\\\\\`markdown\n# {featureId}: {Title}\n\n## Purpose\n\nDescribe the problem this feature solves and why it exists in 1-3 sentences.\n\n## Dependencies\n\n- \\\\\\\\\\\\\\`feat-xxx\\\\\\\\\\\\\\`: reason for dependency\n- (if none, write \"None\")\n\n## Requirements\n\n### {Requirement Group 1}\n\n- Describe as specific, verifiable items\n- Each item must be independently testable\n\n### {Requirement Group 2}\n\n- ...\n\n## Implementation Location\n\n- \\\\\\\\\\\\\\`src/xxx\\\\\\\\\\\\\\`: role description\n\n## Acceptance Criteria\n\n- List conditions that can be verified by tests\n- No vague expressions (e.g., \"should work well\")\n\\\\\\`\\\\\\`\\\\\\`\n\n### Rules\n\n- Describe **what** needs to be done, not **how** to implement it\n- Acceptance criteria must be directly convertible to test cases by the Tester\n- Dependencies must match the \\\\\\`dependencyGraph\\\\\\` in \\\\\\`plan.json\\\\\\`\n- File paths are relative to the package root\n\n---\n\n## design.md (Architect)\n\nConverts spec requirements into concrete technical design.\n\n### Required Sections\n\n\\\\\\`\\\\\\`\\\\\\`markdown\n# {featureId}: Design Document\n\n## Overview\n\nSummarize the core design direction in 1-3 sentences.\n\n## Dependencies\n\n- \\\\\\\\\\\\\\`./types\\\\\\\\\\\\\\`: types used\n- \\\\\\\\\\\\\\`./store\\\\\\\\\\\\\\`: modules used\n- (include external packages)\n\n## API Design\n\n### {Component/Class/Module}\n\n\\\\\\\\\\\\\\`\\\\\\\\\\\\\\`\\\\\\\\\\\\\\`\n// Public interface definition (signatures + documentation comments)\n\\\\\\\\\\\\\\`\\\\\\\\\\\\\\`\\\\\\\\\\\\\\`\n\n### {Additional Type Definitions}\n\n\\\\\\\\\\\\\\`\\\\\\\\\\\\\\`\\\\\\\\\\\\\\`\n// Types to add\n\\\\\\\\\\\\\\`\\\\\\\\\\\\\\`\\\\\\\\\\\\\\`\n\n## File Structure\n\n| File | Content |\n|---|---|\n| \\\\\\\\\\\\\\`src/xxx\\\\\\\\\\\\\\` | role description |\n| \\\\\\\\\\\\\\`test/xxx\\\\\\\\\\\\\\` | test description |\n\n## Design Decisions\n\n1. **Decision title**: chosen direction and rationale. If alternatives existed, explain why they were rejected.\n\n## Test Strategy\n\n- What level of testing is needed (unit/integration)\n- Mocking strategy\n- Edge case list\n\\\\\\`\\\\\\`\\\\\\`\n\n### Rules\n\n- API signatures must be specified as code in the project's language (natural language descriptions alone are insufficient)\n- File paths are relative to the package root\n- All requirements from spec.md must be reflected in the design\n- Clearly describe integration points with existing code\n\n---\n\n## impact-report.md (Analyzer)\n\nAnalyzes the impact of changes on the existing codebase. Generated for enhancement and refactor workflows.\n\n### Required Sections\n\n\\\\\\`\\\\\\`\\\\\\`markdown\n# {featureId}: Impact Report\n\n## Change Summary\n\nDescribe the purpose and scope of the change in 1-3 sentences.\n\n## Affected Files\n\n| File | Change Type | Impact | Description |\n|---|---|---|---|\n| \\\\\\\\\\\\\\`src/xxx\\\\\\\\\\\\\\` | modify | HIGH | public API signature change |\n| \\\\\\\\\\\\\\`src/yyy\\\\\\\\\\\\\\` | modify | LOW | import path change only |\n\nChange types: \\\\\\\\\\\\\\`create\\\\\\\\\\\\\\`, \\\\\\\\\\\\\\`modify\\\\\\\\\\\\\\`, \\\\\\\\\\\\\\`delete\\\\\\\\\\\\\\`\nImpact levels: \\\\\\\\\\\\\\`HIGH\\\\\\\\\\\\\\`, \\\\\\\\\\\\\\`MEDIUM\\\\\\\\\\\\\\`, \\\\\\\\\\\\\\`LOW\\\\\\\\\\\\\\`\n\n## Affected Tests\n\n| Test File | Impact Reason |\n|---|---|\n| \\\\\\\\\\\\\\`test/xxx\\\\\\\\\\\\\\` | directly tests the changed API |\n\n## Compatibility\n\n### Backward Compatibility\n\n- Whether existing API is preserved\n- List of breaking changes (if any)\n\n### Impact on Dependent Features\n\n- How this change affects other features\n\n## Risk Assessment\n\n| Risk | Level | Mitigation |\n|---|---|---|\n| {risk description} | HIGH/MEDIUM/LOW | {mitigation strategy} |\n\n## Recommendations\n\n- Regression test targets\n- Areas requiring additional review\n\\\\\\`\\\\\\`\\\\\\`\n\n### Rules\n\n- Read-only analysis. May suggest code modifications but must not modify code directly\n- List all affected files without omissions\n- Risk level must be one of \\\\\\`HIGH\\\\\\`, \\\\\\`MEDIUM\\\\\\`, \\\\\\`LOW\\\\\\`\n\n---\n\n## diagnosis.md (Diagnostician)\n\nAnalyzes bug causes and proposes fix strategies. Generated for bugfix workflows.\n\n### Required Sections\n\n\\\\\\`\\\\\\`\\\\\\`markdown\n# {featureId}: Diagnosis\n\n## Bug Summary\n\nDescribe reported symptoms in 1-3 sentences.\n\n## Reproduction Steps\n\n1. Step-by-step reproduction method\n2. ...\n\n## Reproduction Results\n\n- Expected behavior: ...\n- Actual behavior: ...\n- Error message/log (if available):\n\n\\\\\\\\\\\\\\`\\\\\\\\\\\\\\`\\\\\\\\\\\\\\`\nerror output\n\\\\\\\\\\\\\\`\\\\\\\\\\\\\\`\\\\\\\\\\\\\\`\n\n## Root Cause Analysis\n\n### Root Cause\n\nDescribe the cause concretely. Include code paths and line numbers.\n\n### Impact Scope\n\n- Other features/code affected by this bug\n\n## Fix Strategy\n\n### Recommended Fix\n\n- Files to modify and change details\n- Scope of changes (minimal invasiveness principle)\n\n### Alternatives (if any)\n\n- Alternatives and reasons for rejection\n\n## Risk Assessment\n\n| Risk | Level | Description |\n|---|---|---|\n| Side effects of fix | HIGH/MEDIUM/LOW | description |\n| Recurrence likelihood | HIGH/MEDIUM/LOW | description |\n\n## Recommended Regression Tests\n\n- Proposed test cases to verify this bug\n\\\\\\`\\\\\\`\\\\\\`\n\n### Rules\n\n- Read-only. Cannot modify code, but may run reproduction tests\n- Diagnosis must be based on code analysis, not speculation\n- Fix strategy must be specific enough for the Developer to implement directly\n\n---\n\n## review.md (Reviewer)\n\nVerifies the quality of implementation and tests, and issues approval/change request verdicts.\n\n### Required Sections\n\n\\\\\\`\\\\\\`\\\\\\`markdown\n# {featureId}: Review\n\n## Review Scope\n\n| File | Change |\n|---|---|\n| \\\\\\\\\\\\\\`src/xxx\\\\\\\\\\\\\\` | change summary |\n| \\\\\\\\\\\\\\`test/xxx\\\\\\\\\\\\\\` | change summary |\n\n## Checklist\n\n- [x] spec.md requirements met\n - [x] {specific item}\n- [x] design.md compliance\n - [x] {specific item}\n- [x] Type safety: no loosely-typed constructs\n- [x] Import conventions followed\n- [x] Project lint/check passes\n- [x] Tests pass ({N} tests)\n\n## Code Review\n\n### {Perspective 1} (e.g., architecture, error handling, performance)\n\nEvaluation content. Reference specific files/lines.\n\n### Improvements (non-blocking)\n\n- Items not requiring immediate fix but worth improving later\n\n### Issues (blocking) — only if present\n\n- Items that must be fixed. Specify file paths and concrete details.\n\n## Standards Compliance\n\n| Standard | Status | Notes |\n|---|---|---|\n| coding-style | PASS | |\n| coding-conventions | PASS | |\n| {standard name} | WARN/FAIL | {file path} - {violation details} |\n\nOverall: PASS / WARN / FAIL\n\n## Verdict: APPROVED / CHANGES_REQUESTED\n\n(If CHANGES_REQUESTED, refer to blocking issues list)\n\\\\\\`\\\\\\`\\\\\\`\n\n### Rules\n\n- Read-only. Cannot modify code\n- Standards Compliance is included only when loaded standards are available\n- If Overall is \\\\\\`FAIL\\\\\\`, verdict must be \\\\\\`CHANGES_REQUESTED\\\\\\`\n- If no blocking issues exist, verdict is \\\\\\`APPROVED\\\\\\`\n- Checklist items correspond 1:1 to acceptance criteria in spec.md\n\n---\n\n## test-report.md (Tester)\n\nRecords test execution results.\n\n### Required Sections\n\n\\\\\\`\\\\\\`\\\\\\`markdown\n# {featureId}: Test Report\n\n## Execution Environment\n\n- **Framework**: {test framework and version, e.g., Vitest, pytest, go test}\n- **Runner**: {command used to run tests}\n- **Working directory**: {project root or relevant subdirectory}\n\n## Result Summary\n\n| Item | Value |\n|---|---|\n| Test files | {N} passed ({N}) |\n| Test cases | {N} passed ({N}) |\n| Failures | {N} |\n| Duration | {N}ms |\n\n## Test Details\n\n### {describe block name} ({passed}/{total} passed)\n\n| Test | Result |\n|---|---|\n| {test name} | PASS |\n| {test name} | FAIL — {failure reason summary} |\n\n## Coverage Analysis\n\n- [x] {covered functionality}\n- [ ] {uncovered functionality} — {reason}\n\nEdge case coverage:\n- [x] {edge case}\n\n## Acceptance Criteria Fulfillment\n\n| Criterion | Status |\n|---|---|\n| {acceptance criterion from spec.md} | PASS/FAIL |\n\\\\\\`\\\\\\`\\\\\\`\n\n### Rules\n\n- Record actual execution results. No estimates\n- Failed tests must include failure reasons\n- Acceptance criteria table corresponds 1:1 to spec.md acceptance criteria\n- Explicitly note missing coverage areas\n\n---\n\n## regression-report.md (Tester)\n\nVerifies no regressions in existing functionality. Generated for enhancement, bugfix, and refactor workflows.\n\n### Required Sections\n\n\\\\\\`\\\\\\`\\\\\\`markdown\n# {featureId}: Regression Report\n\n## Target\n\n- **Changed feature**: {featureId}\n- **Reference**: impact-report.md / diagnosis.md\n\n## Execution Environment\n\n- **Framework**: {test framework and version}\n- **Working directory**: {project root or relevant subdirectory}\n\n## Regression Test Scope\n\n| Test File | Target Functionality | Selection Reason |\n|---|---|---|\n| \\\\\\\\\\\\\\`test/xxx\\\\\\\\\\\\\\` | {functionality} | identified as affected file in impact-report.md |\n\n## Results\n\n| Test File | Result | Failed Items |\n|---|---|---|\n| \\\\\\\\\\\\\\`test/xxx\\\\\\\\\\\\\\` | PASS | — |\n| \\\\\\\\\\\\\\`test/yyy\\\\\\\\\\\\\\` | FAIL | {test name}: {failure reason} |\n\n## New Regression Tests\n\nTests added due to the change:\n\n| Test File | Test Name | Verification Target |\n|---|---|---|\n| \\\\\\\\\\\\\\`test/xxx\\\\\\\\\\\\\\` | {test name} | {what it verifies} |\n\n## Verdict: PASS / FAIL\n\n(If FAIL, include failed tests and impact analysis)\n\\\\\\`\\\\\\`\\\\\\`\n\n### Rules\n\n- Determine test scope by referencing impact-report.md or diagnosis.md\n- Run both existing tests and new regression tests\n- Record actual execution results. No estimates\n\n---\n\n## retry-log.md (Pipeline Engine)\n\nRecords retry history. Automatically generated when retries occur due to test failures, review change requests, etc.\n\n### Required Sections\n\n\\\\\\`\\\\\\`\\\\\\`markdown\n# {featureId}: Retry Log\n\n## Retry History\n\n### Attempt {N} — {timestamp}\n\n- **Step**: {testing/reviewing/regression}\n- **Result**: FAIL\n- **Reason**: {failure cause summary}\n- **Action**: {changes made for the next attempt}\n\n### Attempt {N+1} — {timestamp}\n\n- **Step**: {step}\n- **Result**: PASS\n- **Reason**: —\n\n## Summary\n\n| Item | Value |\n|---|---|\n| Total attempts | {N} |\n| Final result | PASS/FAIL |\n| Max retry limit reached | Yes/No |\n\\\\\\`\\\\\\`\\\\\\`\n\n### Rules\n\n- Record each attempt in chronological order\n- Reference test-report.md or review.md for failure reasons\n- Indicate when max retry limit (from \\\\\\`config.json\\\\\\` retry settings) is reached\n\n---\n\n## status.json (Pipeline Engine / VibeStore)\n\nTracks the current state of a feature.\n\n### Format\n\n\\\\\\`\\\\\\`\\\\\\`json\n{\n \"status\": \"implementing\",\n \"updatedAt\": \"2026-03-05T16:35:00+09:00\",\n \"phase\": \"develop\",\n \"error\": null\n}\n\\\\\\`\\\\\\`\\\\\\`\n\n### Fields\n\n| Field | Type | Required | Description |\n|---|---|---|---|\n| \\\\\\`status\\\\\\` | \\\\\\`FeatureStatusValue\\\\\\` | required | \\\\\\`planned\\\\\\`, \\\\\\`designing\\\\\\`, \\\\\\`implementing\\\\\\`, \\\\\\`testing\\\\\\`, \\\\\\`reviewing\\\\\\`, \\\\\\`done\\\\\\`, \\\\\\`blocked\\\\\\`, \\\\\\`failed\\\\\\` |\n| \\\\\\`updatedAt\\\\\\` | \\\\\\`string\\\\\\` (ISO 8601) | required | timestamp of last status change |\n| \\\\\\`phase\\\\\\` | \\\\\\`string\\\\\\` | optional | current pipeline step (plan, design, develop, test, review, etc.) |\n| \\\\\\`error\\\\\\` | \\\\\\`string \\\\\\\\| null\\\\\\` | optional | failure/block reason |\n\n### Rules\n\n- Do not edit directly. Change only through \\\\\\`VibeStore.updateFeatureStatus()\\\\\\`\n- Only state transitions defined in \\\\\\`VALID_TRANSITIONS\\\\\\` are allowed\n- \\\\\\`updatedAt\\\\\\` must be in ISO 8601 format with UTC offset\n\n---\n\n## Common Rules\n\n1. **File paths**: use relative paths from the project root (e.g., \\\\\\`src/store\\\\\\`, \\\\\\`test/store\\\\\\`)\n2. **Writing style**: technical documentation style. Concise and direct. No emojis.\n3. **Code blocks**: language tag required (e.g., \\\\\\\\\\\\\\`\\\\\\\\\\\\\\`\\\\\\\\\\\\\\`python, \\\\\\\\\\\\\\`\\\\\\\\\\\\\\`\\\\\\\\\\\\\\`typescript, \\\\\\\\\\\\\\`\\\\\\\\\\\\\\`\\\\\\\\\\\\\\`json, \\\\\\\\\\\\\\`\\\\\\\\\\\\\\`\\\\\\\\\\\\\\`markdown)\n4. **Table alignment**: Markdown table separators use \\\\\\`|---|\\\\\\` format\n5. **Cross-references**: reference other artifacts by filename (e.g., \"see acceptance criteria in spec.md\")\n6. **Version control**: artifacts are tracked by git within the feature directory. Overwrite history is tracked via commit history.\n7. **Encoding**: UTF-8, LF line endings\n8. **Language**: all artifacts must be written in English. This includes headings, prose, table content, and technical descriptions.\n`,\n};\n"]}
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAEA,0BAA0B;AAC1B,MAAM,MAAM,WAAW,GACpB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,GACrC;IAAE,IAAI,EAAE,KAAK,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,GACpC;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,GAC5D;IAAE,IAAI,EAAE,KAAK,CAAC;IAAC,WAAW,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,GACvD;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GACzD;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,GACtC;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,GACpC;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,GACtC;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GACtD;IAAE,IAAI,EAAE,KAAK,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,GAClC;IAAE,IAAI,EAAE,SAAS,CAAA;CAAE,GACnB;IAAE,IAAI,EAAE,QAAQ,CAAA;CAAE,GAClB;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAChB;IAAE,IAAI,EAAE,OAAO,CAAA;CAAE,GACjB;IAAE,IAAI,EAAE,SAAS,CAAA;CAAE,GACnB;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAEpB,4BAA4B;AAC5B,eAAO,MAAM,gBAAgB,8IAenB,CAAC;AAIX;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,CA2H1D;AA8CD,yDAAyD;AACzD,eAAO,MAAM,kBAAkB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAm8BrD,CAAC","sourcesContent":["// ─── Command Types ───────────────────────────────────────────────────────────\n\n/** Parsed vibe command */\nexport type VibeCommand =\n\t| { type: \"auto\"; requirement: string }\n\t| { type: \"new\"; requirement: string }\n\t| { type: \"enhance\"; featureId?: string; requirement: string }\n\t| { type: \"fix\"; description: string; issueRef?: string }\n\t| { type: \"refactor\"; featureId?: string; purpose: string }\n\t| { type: \"status\"; featureId?: string }\n\t| { type: \"pause\"; featureId: string }\n\t| { type: \"resume\"; featureId?: string }\n\t| { type: \"steer\"; featureId: string; feedback: string }\n\t| { type: \"log\"; featureId: string }\n\t| { type: \"analyze\" }\n\t| { type: \"config\" }\n\t| { type: \"init\" }\n\t| { type: \"reset\" }\n\t| { type: \"recover\" }\n\t| { type: \"help\" };\n\n/** Available subcommands */\nexport const VIBE_SUBCOMMANDS = [\n\t\"new\",\n\t\"enhance\",\n\t\"fix\",\n\t\"refactor\",\n\t\"status\",\n\t\"pause\",\n\t\"resume\",\n\t\"steer\",\n\t\"log\",\n\t\"analyze\",\n\t\"config\",\n\t\"init\",\n\t\"reset\",\n\t\"recover\",\n] as const;\n\n// ─── Parsing ─────────────────────────────────────────────────────────────────\n\n/**\n * Parse /vibe command arguments.\n *\n * Format:\n * - /vibe new \"requirement\"\n * - /vibe enhance <featureId> \"requirement\"\n * - /vibe fix \"description\" --issue N\n * - /vibe refactor <featureId> \"purpose\"\n * - /vibe status [featureId]\n * - /vibe pause <featureId>\n * - /vibe resume <featureId>\n * - /vibe steer <featureId> \"feedback\"\n * - /vibe log <featureId>\n * - /vibe config\n * - /vibe init\n * - /vibe reset\n * - /vibe recover\n */\nexport function parseVibeCommand(args: string): VibeCommand {\n\tconst trimmed = args.trim();\n\n\tif (!trimmed) {\n\t\treturn { type: \"help\" };\n\t}\n\n\tconst parts = splitArgs(trimmed);\n\tconst subcommand = parts[0];\n\n\tswitch (subcommand) {\n\t\tcase \"new\": {\n\t\t\tconst requirement = parts.slice(1).join(\" \");\n\t\t\tif (!requirement) {\n\t\t\t\tthrow new Error(\"Usage: /vibe new <requirement>\");\n\t\t\t}\n\t\t\treturn { type: \"new\", requirement };\n\t\t}\n\n\t\tcase \"enhance\": {\n\t\t\tif (parts.length < 2) {\n\t\t\t\tthrow new Error(\"Usage: /vibe enhance [featureId] <requirement>\");\n\t\t\t}\n\t\t\tif (isFeatureId(parts[1])) {\n\t\t\t\tconst featureId = parts[1];\n\t\t\t\tconst requirement = parts.slice(2).join(\" \");\n\t\t\t\tif (!requirement) {\n\t\t\t\t\tthrow new Error(\"Usage: /vibe enhance [featureId] <requirement>\");\n\t\t\t\t}\n\t\t\t\treturn { type: \"enhance\", featureId, requirement };\n\t\t\t}\n\t\t\tconst requirement = parts.slice(1).join(\" \");\n\t\t\treturn { type: \"enhance\", requirement };\n\t\t}\n\n\t\tcase \"fix\": {\n\t\t\tconst issueIdx = parts.indexOf(\"--issue\");\n\t\t\tlet issueRef: string | undefined;\n\t\t\tlet descParts: string[];\n\n\t\t\tif (issueIdx !== -1) {\n\t\t\t\tissueRef = parts[issueIdx + 1];\n\t\t\t\tdescParts = [...parts.slice(1, issueIdx), ...parts.slice(issueIdx + 2)];\n\t\t\t} else {\n\t\t\t\tdescParts = parts.slice(1);\n\t\t\t}\n\n\t\t\tconst description = descParts.join(\" \");\n\t\t\tif (!description) {\n\t\t\t\tthrow new Error(\"Usage: /vibe fix <description> [--issue N]\");\n\t\t\t}\n\t\t\treturn { type: \"fix\", description, issueRef };\n\t\t}\n\n\t\tcase \"refactor\": {\n\t\t\tif (parts.length < 2) {\n\t\t\t\tthrow new Error(\"Usage: /vibe refactor [featureId] <purpose>\");\n\t\t\t}\n\t\t\tif (isFeatureId(parts[1])) {\n\t\t\t\tconst featureId = parts[1];\n\t\t\t\tconst purpose = parts.slice(2).join(\" \");\n\t\t\t\tif (!purpose) {\n\t\t\t\t\tthrow new Error(\"Usage: /vibe refactor [featureId] <purpose>\");\n\t\t\t\t}\n\t\t\t\treturn { type: \"refactor\", featureId, purpose };\n\t\t\t}\n\t\t\tconst purpose = parts.slice(1).join(\" \");\n\t\t\treturn { type: \"refactor\", purpose };\n\t\t}\n\n\t\tcase \"status\": {\n\t\t\tconst featureId = parts[1];\n\t\t\treturn { type: \"status\", featureId };\n\t\t}\n\n\t\tcase \"pause\": {\n\t\t\tif (!parts[1]) {\n\t\t\t\tthrow new Error(\"Usage: /vibe pause <featureId>\");\n\t\t\t}\n\t\t\treturn { type: \"pause\", featureId: parts[1] };\n\t\t}\n\n\t\tcase \"resume\": {\n\t\t\treturn { type: \"resume\", featureId: parts[1] };\n\t\t}\n\n\t\tcase \"steer\": {\n\t\t\tif (parts.length < 3) {\n\t\t\t\tthrow new Error(\"Usage: /vibe steer <featureId> <feedback>\");\n\t\t\t}\n\t\t\tconst featureId = parts[1];\n\t\t\tconst feedback = parts.slice(2).join(\" \");\n\t\t\treturn { type: \"steer\", featureId, feedback };\n\t\t}\n\n\t\tcase \"log\": {\n\t\t\tif (!parts[1]) {\n\t\t\t\tthrow new Error(\"Usage: /vibe log <featureId>\");\n\t\t\t}\n\t\t\treturn { type: \"log\", featureId: parts[1] };\n\t\t}\n\n\t\tcase \"analyze\":\n\t\t\treturn { type: \"analyze\" };\n\n\t\tcase \"config\":\n\t\t\treturn { type: \"config\" };\n\n\t\tcase \"init\":\n\t\t\treturn { type: \"init\" };\n\n\t\tcase \"reset\":\n\t\t\treturn { type: \"reset\" };\n\n\t\tcase \"recover\":\n\t\t\treturn { type: \"recover\" };\n\n\t\tdefault: {\n\t\t\t// Text that is not a subcommand is treated as auto mode\n\t\t\tconst requirement = parts.join(\" \");\n\t\t\treturn { type: \"auto\", requirement };\n\t\t}\n\t}\n}\n\n/** featureId prefix list. Used to identify featureId tokens. */\nconst FEATURE_ID_PREFIXES = [\"feat-\", \"fix-\", \"enhance-\", \"refactor-\"];\n\n/** Check if a token is a featureId. */\nfunction isFeatureId(token: string): boolean {\n\treturn FEATURE_ID_PREFIXES.some((prefix) => token.startsWith(prefix));\n}\n\n/** Split by whitespace, preserving spaces inside quotes. */\nfunction splitArgs(input: string): string[] {\n\tconst result: string[] = [];\n\tlet current = \"\";\n\tlet inQuote = false;\n\tlet quoteChar = \"\";\n\n\tfor (const ch of input) {\n\t\tif (inQuote) {\n\t\t\tif (ch === quoteChar) {\n\t\t\t\tinQuote = false;\n\t\t\t} else {\n\t\t\t\tcurrent += ch;\n\t\t\t}\n\t\t} else if (ch === '\"' || ch === \"'\") {\n\t\t\tinQuote = true;\n\t\t\tquoteChar = ch;\n\t\t} else if (ch === \" \") {\n\t\t\tif (current) {\n\t\t\t\tresult.push(current);\n\t\t\t\tcurrent = \"\";\n\t\t\t}\n\t\t} else {\n\t\t\tcurrent += ch;\n\t\t}\n\t}\n\n\tif (current) {\n\t\tresult.push(current);\n\t}\n\n\treturn result;\n}\n\n// ─── Standard Templates ──────────────────────────────────────────────────────\n\n/** 14 standard file templates generated by /vibe init */\nexport const STANDARD_TEMPLATES: Record<string, string> = {\n\t\"coding-style.md\": `---\ndescription: Naming conventions, formatting rules, import ordering\n---\n# Coding Style\n\n<!-- Customize: adjust these defaults to match your project's conventions. -->\n\n## Formatting\n\n- Use consistent indentation (tabs or spaces — pick one and enforce it)\n- Keep line length reasonable (80-120 characters)\n- Use trailing commas in multi-line structures for cleaner diffs\n\n## Naming\n\n- Files: follow the project's convention (e.g., kebab-case \\`user-service.ts\\`, snake_case \\`user_service.py\\`)\n- Classes/interfaces: PascalCase (\\`UserService\\`, \\`AuthProvider\\`)\n- Functions/variables: follow the language convention (e.g., camelCase for JS/TS/Java, snake_case for Python/Rust)\n- Constants: UPPER_SNAKE_CASE (\\`MAX_RETRIES\\`, \\`DEFAULT_TIMEOUT\\`)\n- Booleans: prefix with \\`is\\`, \\`has\\`, \\`can\\`, \\`should\\` (\\`isActive\\`, \\`hasPermission\\`)\n- No abbreviations unless universally understood (\\`id\\`, \\`url\\` are OK; \\`usr\\`, \\`cfg\\` are not)\n\n## Imports\n\n- Use standard module imports following the project's conventions\n- Group imports: external packages first, then internal modules, separated by a blank line\n`,\n\t\"coding-conventions.md\": `---\ndescription: Error handling, dependency injection, comments, constants, function design\n---\n# Coding Conventions\n\n<!-- Customize: adjust these defaults to match your project's conventions. -->\n\n## Error Handling\n\n- Handle errors explicitly — no silent failures, no empty catch blocks\n- Use typed errors when the language supports it\n- Validate inputs at module boundaries (public APIs, request handlers)\n- Fail fast: detect invalid state early and report clearly\n\n## Dependency Injection\n\n- Business logic depends on interfaces (ports), never on concrete implementations (adapters)\n- Wire concrete adapters in a single composition root (factory function or module)\n- Swapping an adapter (e.g., in-memory → database) should require changing only the composition root\n\n## Comments\n\n- Documentation comments for all public APIs (e.g., JSDoc, docstrings, GoDoc)\n- Explain \"why\", not \"what\" — the code shows what, comments explain intent\n- No commented-out code in committed files\n\n## Constants\n\n- No magic numbers or strings — use named constants\n- Group related constants in a dedicated module or object\n\n## Functions\n\n- Keep functions small and focused — one responsibility per function\n- Explicit return types or type hints for public functions where the language supports it\n- No side effects in functions named as queries (get*, is*, has*)\n`,\n\t\"tech-stack.md\": `---\ndescription: Languages, frameworks, build tools, runtime, package manager\n---\n# Tech Stack\n\n<!-- This file is populated during project initialization or discovery. -->\n<!-- Update it when the tech stack changes. -->\n\n## Languages\n<!-- e.g., TypeScript 5.x, Python 3.12, Go 1.22 -->\n\n## Frameworks\n<!-- e.g., React 19, Express 5, FastAPI -->\n\n## Build Tools\n<!-- e.g., Vite, esbuild, webpack -->\n\n## Runtime\n<!-- e.g., Node.js 20, Deno, Bun -->\n\n## Package Manager\n<!-- e.g., npm, pnpm, yarn -->\n`,\n\t\"architecture-principles.md\": `---\ndescription: Separation of concerns, integration boundaries, testability, dependency direction\n---\n# Architecture Principles\n\n<!-- Customize: adjust these defaults to match your project's architecture. -->\n\n## Separation of Concerns\n\n- Each module has a single, well-defined responsibility\n- UI, business logic, and data access are separate layers\n- Cross-cutting concerns (logging, auth) are injected, not hard-wired\n\n## Integration Boundary Principle\n\nAll external dependencies must be abstracted behind interfaces (ports) with swappable adapter implementations.\n\n### What counts as an external dependency\n\n- Data persistence (databases, file systems, localStorage)\n- Authentication / authorization providers\n- Third-party service calls (payment, email, SMS, push notifications)\n- File / media / blob storage\n- Time / scheduling / cron services\n- Message queues / event buses\n\n### Required pattern\n\n1. **Interface (port)**: an interface or abstract type defining the contract, using the project's language idiom (e.g., TypeScript interface, Python Protocol/ABC, Go interface). Named descriptively: \\`TodoRepository\\`, \\`AuthProvider\\`, \\`NotificationService\\`.\n2. **Mock/in-memory adapter**: a default implementation that works without any external system. Named with prefix: \\`InMemory*\\`, \\`Stub*\\`, \\`Console*\\`, \\`Fake*\\`.\n3. **Composition root**: a single location (factory function, module, or DI container) where concrete adapters are wired. Swapping an adapter means changing only this location.\n\n### Why\n\n- Apps work immediately with mock adapters — no infrastructure setup needed\n- Tests run without external dependencies\n- Real adapters can be swapped in later without touching business logic\n\n## Testability\n\n- Every component must be independently testable\n- Dependencies are injected, not instantiated internally\n- No global mutable state\n\n## Dependency Direction\n\n- Higher-level modules must not depend on lower-level implementation details\n- Depend on abstractions (interfaces), not concretions\n`,\n\t\"design-guide.md\": `---\ndescription: API design, data modeling, component design\n---\n# Design Guide\n\n<!-- Customize: adjust these defaults to match your project's design approach. -->\n\n## API Design\n\n- APIs expose clear contracts — input types, output types, error types\n- Use consistent naming: \\`getX\\`, \\`createX\\`, \\`updateX\\`, \\`deleteX\\`\n- Return typed results, not raw primitives where context matters\n- Document error conditions and edge cases in documentation comments\n\n## Data Modeling\n\n- Define explicit types for all domain entities — no implicit shapes\n- Nullable fields must be explicitly typed (e.g., \\`field: string | null\\` in TS, \\`Optional[str]\\` in Python)\n- Validate data at boundaries (API handlers, file reads, user input)\n- Separate internal models from external representations (DTOs)\n\n## Component Design\n\n- Prefer composition over inheritance\n- Keep interfaces small and focused (Interface Segregation)\n- Design for extension — new behavior via new implementations, not modification of existing code\n`,\n\t\"api-design.md\": `---\ndescription: REST API conventions, language-specific API patterns\n---\n# API Design\n\n<!-- Customize: adjust these defaults to match your project's API conventions. -->\n\n## REST API\n\n- Resource-oriented URLs: \\`/users\\`, \\`/users/:id\\`, \\`/users/:id/posts\\`\n- Use standard HTTP methods: GET (read), POST (create), PUT/PATCH (update), DELETE (remove)\n- Consistent status codes: 200 (OK), 201 (Created), 400 (Bad Request), 404 (Not Found), 500 (Internal Error)\n- Return JSON with consistent envelope: \\`{ data, error, meta }\\`\n- Version APIs when breaking changes are unavoidable: \\`/api/v1/...\\`\n\n## Language-Specific API Conventions\n\n- Small, focused functions — one purpose per function\n- Explicit return types or type hints for all public functions\n- Avoid untyped or loosely-typed constructs (e.g., \\`any\\` in TS, \\`Any\\` in Python) — use narrow types\n- Use tagged unions, discriminated unions, or enums for complex state where the language supports it\n- Prefer async/await patterns for asynchronous operations\n`,\n\t\"testing-standards.md\": `---\ndescription: Test layers, test scope by change type, unit/integration/E2E rules, mock adapters\n---\n# Testing Standards\n\n<!-- Customize: adjust these defaults to match your project's testing approach. -->\n\n## Test Layers\n\n| Layer | Role | Scope |\n|-------|------|-------|\n| **Unit** | Verify isolated module logic | Single function/class, all dependencies mocked |\n| **Integration** | Verify module wiring and interaction | Multiple modules, external boundaries mocked |\n| **E2E** | Verify end-to-end user workflow | Full application, real or simulated environment |\n\n## Change Type → Test Scope\n\n| What changed | Unit | Integration | E2E / Manual |\n|--------------|:----:|:-----------:|:------------:|\n| Internal logic (algorithm, validation) | Required | — | — |\n| Public API / interface signature | Required | Required if callers exist | — |\n| Module wiring (callbacks, DI, factory) | — | Required | — |\n| User-facing workflow | Required for logic | Required for wiring | Required |\n\n## Unit Test Rules\n\n- Test one module in isolation — mock all dependencies\n- Cover edge cases: empty input, invalid state, boundary values\n- Tests must be deterministic — no dependency on external state, time, or network\n- No meaningless tests that always pass\n\n## Integration Test Rules\n\n- Mock external boundaries (database, network, file system) but use real internal modules\n- Verify callback wiring: A creates B with callback → trigger callback → verify side effect\n- Verify argument passing and state flow across modules\n\n## E2E / Manual Verification\n\n- Required for TUI rendering, prompt effectiveness, cross-terminal behavior\n- Document what was checked and the result in test reports\n\n## Mock Adapters\n\n- All tests must use mock/in-memory adapters — never depend on real external systems\n- Mock adapters must faithfully implement the interface contract\n`,\n\t\"documentation.md\": `---\ndescription: Code documentation, README structure, commit messages\n---\n# Documentation\n\n<!-- Customize: adjust these defaults to match your project's documentation approach. -->\n\n## Code Documentation\n\n- Documentation comments for all public APIs (e.g., JSDoc, Python docstrings, GoDoc, Javadoc)\n- Include parameter descriptions, return types, and thrown errors/exceptions\n- Explain complex algorithms or non-obvious design decisions inline\n\n## README\n\nEvery project must have a README.md containing:\n- **Purpose**: what the project does and why\n- **Setup**: how to install and configure\n- **Usage**: how to run and use\n- **Architecture**: high-level overview of structure and key decisions\n- **Contributing**: how to develop and test\n\n## Commit Messages\n\n- Use conventional commits: \\`feat:\\`, \\`fix:\\`, \\`refactor:\\`, \\`docs:\\`, \\`test:\\`\n- First line: imperative mood, under 72 characters\n- Body: explain \"why\" when the change is non-obvious\n`,\n\t\"git-workflow.md\": `---\ndescription: Branching strategy, commit conventions, merging rules\n---\n# Git Workflow\n\n<!-- Customize: adjust these defaults to match your project's Git workflow. -->\n\n## Branching\n\n- \\`main\\` (or \\`master\\`): stable, always deployable\n- Feature branches: \\`feat/description\\`, \\`fix/description\\`, \\`refactor/description\\`\n- Branch from the latest main, keep branches short-lived\n\n## Commits\n\n- Use conventional commits: \\`feat:\\`, \\`fix:\\`, \\`refactor:\\`, \\`docs:\\`, \\`test:\\`, \\`chore:\\`\n- Atomic commits: each commit is a single logical change\n- First line: imperative mood, under 72 characters\n\n## Merging\n\n- Merge feature branches with \\`--no-ff\\` to preserve branch history\n- Resolve conflicts in the feature branch before merging\n- Delete feature branches after merge (or keep for traceability — choose one convention)\n- Never force-push to shared branches\n`,\n\t\"security-policy.md\": `---\ndescription: Secrets management, input validation, authentication, dependency security\n---\n# Security Policy\n\n<!-- Customize: adjust these defaults to match your project's security requirements. -->\n\n## Secrets Management\n\n- No secrets, API keys, or credentials in source code or version control\n- Use environment variables or secret management services\n- Add sensitive file patterns to \\`.gitignore\\`\n\n## Input Validation\n\n- Validate all external input at system boundaries (API handlers, file reads, user input)\n- Sanitize data before rendering to prevent XSS\n- Use parameterized queries to prevent SQL injection\n\n## Authentication & Authorization\n\n- Use established libraries — do not implement custom crypto\n- Apply least privilege: grant minimum permissions required\n- Expire sessions and tokens with reasonable timeouts\n\n## Dependencies\n\n- Regularly scan dependencies for known vulnerabilities\n- Update vulnerable dependencies promptly\n- Evaluate new dependencies for security track record before adding\n`,\n\t\"dependency-policy.md\": `---\ndescription: Dependency evaluation criteria, version management\n---\n# Dependency Policy\n\n<!-- Customize: adjust these defaults to match your project's dependency approach. -->\n\n## Adding Dependencies\n\nBefore adding a dependency, evaluate:\n- **Necessity**: can this be implemented in a few lines without the dependency?\n- **Maintenance**: is the package actively maintained? When was the last release?\n- **Size**: what is the install size and dependency tree depth?\n- **License**: is the license compatible with your project?\n- **Security**: does it have known vulnerabilities?\n\nPrefer standard library / platform APIs over third-party packages when feasible.\n\n## Version Management\n\n- Pin exact versions or use lock files (\\`package-lock.json\\`, \\`pnpm-lock.yaml\\`)\n- Update dependencies regularly — do not let them go stale\n- Test after updating — run the full test suite before committing dependency updates\n`,\n\t\"performance-guidelines.md\": `---\ndescription: Performance principles, data structures, resource management\n---\n# Performance Guidelines\n\n<!-- Customize: adjust these defaults to match your project's performance needs. -->\n\n## Principles\n\n- Do not optimize prematurely — write clear code first, optimize when measured\n- Profile before optimizing — identify actual bottlenecks, not guessed ones\n- Use async I/O where appropriate — avoid blocking the event loop or main thread with synchronous operations\n\n## Data Structures\n\n- Choose appropriate data structures for the access pattern (Map for lookups, Array for iteration)\n- Avoid unnecessary copying of large data structures\n\n## Resource Management\n\n- Close resources (file handles, connections, streams) when done\n- Use connection pooling for databases and HTTP clients\n- Set reasonable timeouts for all external calls\n`,\n\t\"accessibility.md\": `---\ndescription: WCAG compliance, keyboard navigation, screen readers, visual design\n---\n# Accessibility\n\n<!-- Customize: adjust these defaults if your project has a UI. -->\n<!-- If your project has no user-facing UI, this file can be left as-is. -->\n\n## Standards\n\n- Follow WCAG 2.1 Level AA guidelines for web applications\n- Use semantic HTML elements (\\`<button>\\`, \\`<nav>\\`, \\`<main>\\`, not \\`<div>\\` for everything)\n- Provide text alternatives for non-text content (images, icons)\n\n## Keyboard Navigation\n\n- All interactive elements must be keyboard-accessible\n- Focus order must follow a logical reading sequence\n- Visible focus indicators on all interactive elements\n\n## Screen Readers\n\n- Use ARIA attributes when semantic HTML is insufficient\n- Test with at least one screen reader\n\n## Visual Design\n\n- Minimum 4.5:1 contrast ratio for normal text\n- Do not convey information by color alone\n- Support user font size preferences\n`,\n\t\"observability.md\": `---\ndescription: Structured logging, metrics, distributed tracing\n---\n# Observability\n\n<!-- Customize: adjust these defaults to match your project's observability needs. -->\n\n## Logging\n\n- Use structured logging (JSON or key-value pairs) — not free-form text\n- Include context: timestamp, level, module, request ID where applicable\n- Log at appropriate levels: ERROR for failures, WARN for recoverable issues, INFO for state changes, DEBUG for troubleshooting\n\n## Metrics\n\n<!-- Define key metrics for your application. Examples: -->\n- Request latency (p50, p95, p99)\n- Error rate\n- Resource utilization (memory, CPU, connections)\n\n## Tracing\n\n- Propagate trace/correlation IDs across service boundaries\n- Instrument key operations: incoming requests, outgoing calls, database queries\n- Use consistent span naming conventions\n`,\n\t\"logging.md\": `---\ndescription: Logging principles, log levels, log format, logger injection\n---\n# Logging\n\n<!-- Define your logging standards. -->\n\n## Principles\n<!-- Basic principles such as no direct console.* calls -->\n\n## Log Levels\n<!-- Criteria for debug, info, warn, error usage -->\n\n## Log Format\n<!-- Log format rules -->\n\n## Injection Pattern\n<!-- Logger injection approach (callbacks, DI, etc.) -->\n`,\n\t\".artifact-standards.md\": `---\ndescription: Format and structure rules for all feature artifacts\n---\n# Artifact Standards\n\nStandards for all artifacts generated by agents under \\\\\\`.vibe/features/{featureId}/\\\\\\`.\n\n## Artifact List\n\n| File | Creator | Workflow | Required |\n|---|---|---|---|\n| \\\\\\`spec.md\\\\\\` | Planner | all | required |\n| \\\\\\`design.md\\\\\\` | Architect | all | required |\n| \\\\\\`impact-report.md\\\\\\` | Analyzer | enhancement, refactor | conditional |\n| \\\\\\`diagnosis.md\\\\\\` | Diagnostician | bugfix | conditional |\n| \\\\\\`review.md\\\\\\` | Reviewer | all | required |\n| \\\\\\`test-report.md\\\\\\` | Tester | all | required |\n| \\\\\\`regression-report.md\\\\\\` | Tester | enhancement, bugfix, refactor | conditional |\n| \\\\\\`retry-log.md\\\\\\` | Pipeline Engine | on retry | conditional |\n| \\\\\\`status.json\\\\\\` | Pipeline Engine / VibeStore | all | required |\n\n---\n\n## spec.md (Planner)\n\nDefines the purpose, scope, and requirements of a feature.\n\n### Required Sections\n\n\\\\\\`\\\\\\`\\\\\\`markdown\n# {featureId}: {Title}\n\n## Purpose\n\nDescribe the problem this feature solves and why it exists in 1-3 sentences.\n\n## Dependencies\n\n- \\\\\\\\\\\\\\`feat-xxx\\\\\\\\\\\\\\`: reason for dependency\n- (if none, write \"None\")\n\n## Requirements\n\n### {Requirement Group 1}\n\n- Describe as specific, verifiable items\n- Each item must be independently testable\n\n### {Requirement Group 2}\n\n- ...\n\n## Implementation Location\n\n- \\\\\\\\\\\\\\`src/xxx\\\\\\\\\\\\\\`: role description\n\n## Acceptance Criteria\n\n- List conditions that can be verified by tests\n- No vague expressions (e.g., \"should work well\")\n\\\\\\`\\\\\\`\\\\\\`\n\n### Rules\n\n- Describe **what** needs to be done, not **how** to implement it\n- Acceptance criteria must be directly convertible to test cases by the Tester\n- Dependencies must match the \\\\\\`dependencyGraph\\\\\\` in \\\\\\`plan.json\\\\\\`\n- File paths are relative to the package root\n\n---\n\n## design.md (Architect)\n\nConverts spec requirements into concrete technical design.\n\n### Required Sections\n\n\\\\\\`\\\\\\`\\\\\\`markdown\n# {featureId}: Design Document\n\n## Overview\n\nSummarize the core design direction in 1-3 sentences.\n\n## Dependencies\n\n- \\\\\\\\\\\\\\`./types\\\\\\\\\\\\\\`: types used\n- \\\\\\\\\\\\\\`./store\\\\\\\\\\\\\\`: modules used\n- (include external packages)\n\n## API Design\n\n### {Component/Class/Module}\n\n\\\\\\\\\\\\\\`\\\\\\\\\\\\\\`\\\\\\\\\\\\\\`\n// Public interface definition (signatures + documentation comments)\n\\\\\\\\\\\\\\`\\\\\\\\\\\\\\`\\\\\\\\\\\\\\`\n\n### {Additional Type Definitions}\n\n\\\\\\\\\\\\\\`\\\\\\\\\\\\\\`\\\\\\\\\\\\\\`\n// Types to add\n\\\\\\\\\\\\\\`\\\\\\\\\\\\\\`\\\\\\\\\\\\\\`\n\n## File Structure\n\n| File | Content |\n|---|---|\n| \\\\\\\\\\\\\\`src/xxx\\\\\\\\\\\\\\` | role description |\n| \\\\\\\\\\\\\\`test/xxx\\\\\\\\\\\\\\` | test description |\n\n## Design Decisions\n\n1. **Decision title**: chosen direction and rationale. If alternatives existed, explain why they were rejected.\n\n## Test Strategy\n\n- What level of testing is needed (unit/integration)\n- Mocking strategy\n- Edge case list\n\\\\\\`\\\\\\`\\\\\\`\n\n### Rules\n\n- API signatures must be specified as code in the project's language (natural language descriptions alone are insufficient)\n- File paths are relative to the package root\n- All requirements from spec.md must be reflected in the design\n- Clearly describe integration points with existing code\n\n---\n\n## impact-report.md (Analyzer)\n\nAnalyzes the impact of changes on the existing codebase. Generated for enhancement and refactor workflows.\n\n### Required Sections\n\n\\\\\\`\\\\\\`\\\\\\`markdown\n# {featureId}: Impact Report\n\n## Change Summary\n\nDescribe the purpose and scope of the change in 1-3 sentences.\n\n## Affected Files\n\n| File | Change Type | Impact | Description |\n|---|---|---|---|\n| \\\\\\\\\\\\\\`src/xxx\\\\\\\\\\\\\\` | modify | HIGH | public API signature change |\n| \\\\\\\\\\\\\\`src/yyy\\\\\\\\\\\\\\` | modify | LOW | import path change only |\n\nChange types: \\\\\\\\\\\\\\`create\\\\\\\\\\\\\\`, \\\\\\\\\\\\\\`modify\\\\\\\\\\\\\\`, \\\\\\\\\\\\\\`delete\\\\\\\\\\\\\\`\nImpact levels: \\\\\\\\\\\\\\`HIGH\\\\\\\\\\\\\\`, \\\\\\\\\\\\\\`MEDIUM\\\\\\\\\\\\\\`, \\\\\\\\\\\\\\`LOW\\\\\\\\\\\\\\`\n\n## Affected Tests\n\n| Test File | Impact Reason |\n|---|---|\n| \\\\\\\\\\\\\\`test/xxx\\\\\\\\\\\\\\` | directly tests the changed API |\n\n## Compatibility\n\n### Backward Compatibility\n\n- Whether existing API is preserved\n- List of breaking changes (if any)\n\n### Impact on Dependent Features\n\n- How this change affects other features\n\n## Risk Assessment\n\n| Risk | Level | Mitigation |\n|---|---|---|\n| {risk description} | HIGH/MEDIUM/LOW | {mitigation strategy} |\n\n## Recommendations\n\n- Regression test targets\n- Areas requiring additional review\n\\\\\\`\\\\\\`\\\\\\`\n\n### Rules\n\n- Read-only analysis. May suggest code modifications but must not modify code directly\n- List all affected files without omissions\n- Risk level must be one of \\\\\\`HIGH\\\\\\`, \\\\\\`MEDIUM\\\\\\`, \\\\\\`LOW\\\\\\`\n\n---\n\n## diagnosis.md (Diagnostician)\n\nAnalyzes bug causes and proposes fix strategies. Generated for bugfix workflows.\n\n### Required Sections\n\n\\\\\\`\\\\\\`\\\\\\`markdown\n# {featureId}: Diagnosis\n\n## Bug Summary\n\nDescribe reported symptoms in 1-3 sentences.\n\n## Reproduction Steps\n\n1. Step-by-step reproduction method\n2. ...\n\n## Reproduction Results\n\n- Expected behavior: ...\n- Actual behavior: ...\n- Error message/log (if available):\n\n\\\\\\\\\\\\\\`\\\\\\\\\\\\\\`\\\\\\\\\\\\\\`\nerror output\n\\\\\\\\\\\\\\`\\\\\\\\\\\\\\`\\\\\\\\\\\\\\`\n\n## Root Cause Analysis\n\n### Root Cause\n\nDescribe the cause concretely. Include code paths and line numbers.\n\n### Impact Scope\n\n- Other features/code affected by this bug\n\n## Fix Strategy\n\n### Recommended Fix\n\n- Files to modify and change details\n- Scope of changes (minimal invasiveness principle)\n\n### Alternatives (if any)\n\n- Alternatives and reasons for rejection\n\n## Risk Assessment\n\n| Risk | Level | Description |\n|---|---|---|\n| Side effects of fix | HIGH/MEDIUM/LOW | description |\n| Recurrence likelihood | HIGH/MEDIUM/LOW | description |\n\n## Recommended Regression Tests\n\n- Proposed test cases to verify this bug\n\\\\\\`\\\\\\`\\\\\\`\n\n### Rules\n\n- Read-only. Cannot modify code, but may run reproduction tests\n- Diagnosis must be based on code analysis, not speculation\n- Fix strategy must be specific enough for the Developer to implement directly\n\n---\n\n## review.md (Reviewer)\n\nVerifies the quality of implementation and tests, and issues approval/change request verdicts.\n\n### Required Sections\n\n\\\\\\`\\\\\\`\\\\\\`markdown\n# {featureId}: Review\n\n## Review Scope\n\n| File | Change |\n|---|---|\n| \\\\\\\\\\\\\\`src/xxx\\\\\\\\\\\\\\` | change summary |\n| \\\\\\\\\\\\\\`test/xxx\\\\\\\\\\\\\\` | change summary |\n\n## Checklist\n\n- [x] spec.md requirements met\n - [x] {specific item}\n- [x] design.md compliance\n - [x] {specific item}\n- [x] Type safety: no loosely-typed constructs\n- [x] Import conventions followed\n- [x] Project lint/check passes\n- [x] Tests pass ({N} tests)\n\n## Code Review\n\n### {Perspective 1} (e.g., architecture, error handling, performance)\n\nEvaluation content. Reference specific files/lines.\n\n### Improvements (non-blocking)\n\n- Items not requiring immediate fix but worth improving later\n\n### Issues (blocking) — only if present\n\n- Items that must be fixed. Specify file paths and concrete details.\n\n## Standards Compliance\n\n| Standard | Status | Notes |\n|---|---|---|\n| coding-style | PASS | |\n| coding-conventions | PASS | |\n| {standard name} | WARN/FAIL | {file path} - {violation details} |\n\nOverall: PASS / WARN / FAIL\n\n## Verdict: APPROVED / CHANGES_REQUESTED\n\n(If CHANGES_REQUESTED, refer to blocking issues list)\n\\\\\\`\\\\\\`\\\\\\`\n\n### Rules\n\n- Read-only. Cannot modify code\n- Standards Compliance is included only when loaded standards are available\n- If Overall is \\\\\\`FAIL\\\\\\`, verdict must be \\\\\\`CHANGES_REQUESTED\\\\\\`\n- If no blocking issues exist, verdict is \\\\\\`APPROVED\\\\\\`\n- Checklist items correspond 1:1 to acceptance criteria in spec.md\n\n---\n\n## test-report.md (Tester)\n\nRecords test execution results.\n\n### Required Sections\n\n\\\\\\`\\\\\\`\\\\\\`markdown\n# {featureId}: Test Report\n\n## Execution Environment\n\n- **Framework**: {test framework and version, e.g., Vitest, pytest, go test}\n- **Runner**: {command used to run tests}\n- **Working directory**: {project root or relevant subdirectory}\n\n## Result Summary\n\n| Item | Value |\n|---|---|\n| Test files | {N} passed ({N}) |\n| Test cases | {N} passed ({N}) |\n| Failures | {N} |\n| Duration | {N}ms |\n\n## Test Details\n\n### {describe block name} ({passed}/{total} passed)\n\n| Test | Result |\n|---|---|\n| {test name} | PASS |\n| {test name} | FAIL — {failure reason summary} |\n\n## Coverage Analysis\n\n- [x] {covered functionality}\n- [ ] {uncovered functionality} — {reason}\n\nEdge case coverage:\n- [x] {edge case}\n\n## Acceptance Criteria Fulfillment\n\n| Criterion | Status |\n|---|---|\n| {acceptance criterion from spec.md} | PASS/FAIL |\n\\\\\\`\\\\\\`\\\\\\`\n\n### Rules\n\n- Record actual execution results. No estimates\n- Failed tests must include failure reasons\n- Acceptance criteria table corresponds 1:1 to spec.md acceptance criteria\n- Explicitly note missing coverage areas\n\n---\n\n## regression-report.md (Tester)\n\nVerifies no regressions in existing functionality. Generated for enhancement, bugfix, and refactor workflows.\n\n### Required Sections\n\n\\\\\\`\\\\\\`\\\\\\`markdown\n# {featureId}: Regression Report\n\n## Target\n\n- **Changed feature**: {featureId}\n- **Reference**: impact-report.md / diagnosis.md\n\n## Execution Environment\n\n- **Framework**: {test framework and version}\n- **Working directory**: {project root or relevant subdirectory}\n\n## Regression Test Scope\n\n| Test File | Target Functionality | Selection Reason |\n|---|---|---|\n| \\\\\\\\\\\\\\`test/xxx\\\\\\\\\\\\\\` | {functionality} | identified as affected file in impact-report.md |\n\n## Results\n\n| Test File | Result | Failed Items |\n|---|---|---|\n| \\\\\\\\\\\\\\`test/xxx\\\\\\\\\\\\\\` | PASS | — |\n| \\\\\\\\\\\\\\`test/yyy\\\\\\\\\\\\\\` | FAIL | {test name}: {failure reason} |\n\n## New Regression Tests\n\nTests added due to the change:\n\n| Test File | Test Name | Verification Target |\n|---|---|---|\n| \\\\\\\\\\\\\\`test/xxx\\\\\\\\\\\\\\` | {test name} | {what it verifies} |\n\n## Verdict: PASS / FAIL\n\n(If FAIL, include failed tests and impact analysis)\n\\\\\\`\\\\\\`\\\\\\`\n\n### Rules\n\n- Determine test scope by referencing impact-report.md or diagnosis.md\n- Run both existing tests and new regression tests\n- Record actual execution results. No estimates\n\n---\n\n## retry-log.md (Pipeline Engine)\n\nRecords retry history. Automatically generated when retries occur due to test failures, review change requests, etc.\n\n### Required Sections\n\n\\\\\\`\\\\\\`\\\\\\`markdown\n# {featureId}: Retry Log\n\n## Retry History\n\n### Attempt {N} — {timestamp}\n\n- **Step**: {testing/reviewing/regression}\n- **Result**: FAIL\n- **Reason**: {failure cause summary}\n- **Action**: {changes made for the next attempt}\n\n### Attempt {N+1} — {timestamp}\n\n- **Step**: {step}\n- **Result**: PASS\n- **Reason**: —\n\n## Summary\n\n| Item | Value |\n|---|---|\n| Total attempts | {N} |\n| Final result | PASS/FAIL |\n| Max retry limit reached | Yes/No |\n\\\\\\`\\\\\\`\\\\\\`\n\n### Rules\n\n- Record each attempt in chronological order\n- Reference test-report.md or review.md for failure reasons\n- Indicate when max retry limit (from \\\\\\`config.json\\\\\\` retry settings) is reached\n\n---\n\n## status.json (Pipeline Engine / VibeStore)\n\nTracks the current state of a feature.\n\n### Format\n\n\\\\\\`\\\\\\`\\\\\\`json\n{\n \"status\": \"implementing\",\n \"updatedAt\": \"2026-03-05T16:35:00+09:00\",\n \"phase\": \"develop\",\n \"error\": null\n}\n\\\\\\`\\\\\\`\\\\\\`\n\n### Fields\n\n| Field | Type | Required | Description |\n|---|---|---|---|\n| \\\\\\`status\\\\\\` | \\\\\\`FeatureStatusValue\\\\\\` | required | \\\\\\`planned\\\\\\`, \\\\\\`designing\\\\\\`, \\\\\\`implementing\\\\\\`, \\\\\\`testing\\\\\\`, \\\\\\`reviewing\\\\\\`, \\\\\\`done\\\\\\`, \\\\\\`blocked\\\\\\`, \\\\\\`failed\\\\\\` |\n| \\\\\\`updatedAt\\\\\\` | \\\\\\`string\\\\\\` (ISO 8601) | required | timestamp of last status change |\n| \\\\\\`phase\\\\\\` | \\\\\\`string\\\\\\` | optional | current pipeline step (plan, design, develop, test, review, etc.) |\n| \\\\\\`error\\\\\\` | \\\\\\`string \\\\\\\\| null\\\\\\` | optional | failure/block reason |\n\n### Rules\n\n- Do not edit directly. Change only through \\\\\\`VibeStore.updateFeatureStatus()\\\\\\`\n- Only state transitions defined in \\\\\\`VALID_TRANSITIONS\\\\\\` are allowed\n- \\\\\\`updatedAt\\\\\\` must be in ISO 8601 format with UTC offset\n\n---\n\n## Common Rules\n\n1. **File paths**: use relative paths from the project root (e.g., \\\\\\`src/store\\\\\\`, \\\\\\`test/store\\\\\\`)\n2. **Writing style**: technical documentation style. Concise and direct. No emojis.\n3. **Code blocks**: language tag required (e.g., \\\\\\\\\\\\\\`\\\\\\\\\\\\\\`\\\\\\\\\\\\\\`python, \\\\\\\\\\\\\\`\\\\\\\\\\\\\\`\\\\\\\\\\\\\\`typescript, \\\\\\\\\\\\\\`\\\\\\\\\\\\\\`\\\\\\\\\\\\\\`json, \\\\\\\\\\\\\\`\\\\\\\\\\\\\\`\\\\\\\\\\\\\\`markdown)\n4. **Table alignment**: Markdown table separators use \\\\\\`|---|\\\\\\` format\n5. **Cross-references**: reference other artifacts by filename (e.g., \"see acceptance criteria in spec.md\")\n6. **Version control**: artifacts are tracked by git within the feature directory. Overwrite history is tracked via commit history.\n7. **Encoding**: UTF-8, LF line endings\n8. **Language**: all artifacts must be written in English. This includes headings, prose, table content, and technical descriptions.\n`,\n};\n"]}