opencode-sdlc-plugin 0.1.0

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 (42) hide show
  1. package/README.md +60 -0
  2. package/agents/design-facilitator.md +8 -0
  3. package/agents/domain.md +9 -0
  4. package/agents/exploration.md +8 -0
  5. package/agents/green.md +9 -0
  6. package/agents/marvin.md +15 -0
  7. package/agents/model-checker.md +9 -0
  8. package/agents/red.md +9 -0
  9. package/commands/sdlc-adr.md +37 -0
  10. package/commands/sdlc-design.md +88 -0
  11. package/commands/sdlc-domain-audit.md +32 -0
  12. package/commands/sdlc-plan.md +63 -0
  13. package/commands/sdlc-pr.md +43 -0
  14. package/commands/sdlc-recall.md +18 -0
  15. package/commands/sdlc-remember.md +19 -0
  16. package/commands/sdlc-review.md +192 -0
  17. package/commands/sdlc-setup.md +50 -0
  18. package/commands/sdlc-start.md +34 -0
  19. package/commands/sdlc-work.md +118 -0
  20. package/config/presets/event-modeling.json +12 -0
  21. package/config/presets/traditional.json +12 -0
  22. package/config/schemas/sdlc.schema.json +48 -0
  23. package/dist/cli/index.d.ts +1 -0
  24. package/dist/cli/index.js +703 -0
  25. package/dist/cli/index.js.map +1 -0
  26. package/dist/index.d.ts +2 -0
  27. package/dist/index.js +474 -0
  28. package/dist/index.js.map +1 -0
  29. package/dist/plugin/index.d.ts +5 -0
  30. package/dist/plugin/index.js +476 -0
  31. package/dist/plugin/index.js.map +1 -0
  32. package/package.json +56 -0
  33. package/skills/adr-policy.md +21 -0
  34. package/skills/atomic-design.md +39 -0
  35. package/skills/debugging-protocol.md +47 -0
  36. package/skills/event-modeling.md +40 -0
  37. package/skills/git-spice.md +44 -0
  38. package/skills/github-issues.md +44 -0
  39. package/skills/memory-protocol.md +41 -0
  40. package/skills/orchestration.md +118 -0
  41. package/skills/skill-enforcement.md +56 -0
  42. package/skills/tdd-constraints.md +63 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/plugin/hooks/session-hooks.ts","../src/plugin/utils/file-patterns.ts","../src/plugin/hooks/tool-hooks.ts","../src/plugin/hooks/compaction-hook.ts","../src/plugin/tools/get-context.ts","../src/plugin/tools/get-state.ts","../src/plugin/tools/update-state.ts","../src/plugin/tools/load-skill.ts","../src/plugin/utils/package-paths.ts","../src/plugin/tools/party-review.ts","../src/plugin/tools/review-store.ts","../src/plugin/tools/index.ts","../src/plugin/state/sdlc-tracker.ts","../src/shared/constants.ts","../src/plugin/utils/config-loader.ts","../src/shared/schemas.ts","../src/plugin/index.ts"],"sourcesContent":["import type { SdlcTracker } from \"../state/sdlc-tracker.js\";\n\ninterface SessionEvent {\n type?: string;\n}\n\nexport function createSessionHooks(_tracker: SdlcTracker): ({ event }: { event: SessionEvent }) => Promise<void> {\n return ({ event }: { event: SessionEvent }): Promise<void> => {\n if (event.type === \"session.created\") {\n return Promise.resolve();\n }\n if (event.type === \"session.idle\") {\n return Promise.resolve();\n }\n return Promise.resolve();\n };\n}\n","import picomatch from \"picomatch\";\n\nexport function matchesAnyPattern(filePath: string, patterns: string[]): boolean {\n if (patterns.length === 0) return false;\n const matcher = picomatch(patterns, { dot: true });\n return matcher(filePath);\n}\n","import type { SdlcConfig } from \"../../shared/types.js\";\nimport type { SdlcTracker } from \"../state/sdlc-tracker.js\";\nimport { matchesAnyPattern } from \"../utils/file-patterns.js\";\n\ninterface BeforeHookInput {\n tool: string;\n sessionID: string;\n callID: string;\n}\n\ninterface BeforeHookOutput {\n args: unknown;\n}\n\ninterface AfterHookInput {\n tool: string;\n sessionID: string;\n callID: string;\n}\n\ninterface AfterHookOutput {\n title: string;\n output: string;\n metadata: unknown;\n}\n\ninterface EditArgs {\n filePath?: string;\n}\n\ninterface WriteArgs {\n filePath?: string;\n}\n\ninterface UpdateStateArgs {\n currentPhase?: \"idle\" | \"red\" | \"domain-after-red\" | \"green\" | \"domain-after-green\";\n}\n\nconst VALID_TRANSITIONS: Record<string, string[]> = {\n idle: [\"red\"],\n red: [\"domain-after-red\"],\n \"domain-after-red\": [\"green\"],\n green: [\"domain-after-green\"],\n \"domain-after-green\": [\"red\", \"idle\"],\n};\n\nexport function createToolHooks(tracker: SdlcTracker, config: SdlcConfig): {\n before: (input: BeforeHookInput, output: BeforeHookOutput) => Promise<void>;\n after: (input: AfterHookInput, output: AfterHookOutput) => Promise<void>;\n} {\n return {\n before: async (input: BeforeHookInput, output: BeforeHookOutput): Promise<void> => {\n if (input.tool === \"sdlc_update_state\") {\n const args = output.args as UpdateStateArgs;\n if (args.currentPhase) {\n const current = tracker.getState().currentPhase;\n const allowed = VALID_TRANSITIONS[current] ?? [];\n if (!allowed.includes(args.currentPhase)) {\n throw new Error(\n `Invalid TDD transition: ${current} -> ${args.currentPhase}. ` +\n `Allowed transitions: ${allowed.join(\", \")}. ` +\n `Follow RED → DOMAIN → GREEN → DOMAIN → REFACTOR.`\n );\n }\n }\n }\n\n if (input.tool === \"edit\" || input.tool === \"write\") {\n const state = tracker.getState();\n const args = output.args as EditArgs | WriteArgs;\n const filePath = args.filePath ?? \"\";\n if (filePath.length === 0) return;\n\n const allowedPatterns = getAllowedPatterns(config, state.currentPhase);\n\n if (allowedPatterns.length > 0 && !matchesAnyPattern(filePath, allowedPatterns)) {\n throw new Error(\n `File ownership violation in phase '${state.currentPhase}'. ` +\n `Allowed patterns: ${allowedPatterns.join(\", \")}. ` +\n `Attempted: ${filePath}. Delegate to the correct agent.`\n );\n }\n }\n },\n\n after: async (_input: AfterHookInput, _output: AfterHookOutput): Promise<void> => {\n return;\n },\n };\n}\n\nfunction getAllowedPatterns(\n config: SdlcConfig,\n phase: \"idle\" | \"red\" | \"domain-after-red\" | \"green\" | \"domain-after-green\"\n): string[] {\n const patterns = config.languages.flatMap((language) => {\n if (phase === \"red\") return language.testPatterns;\n if (phase === \"green\") return language.productionPatterns;\n if (phase === \"domain-after-red\" || phase === \"domain-after-green\") return language.typePatterns;\n return [];\n });\n return patterns.filter(Boolean);\n}\n","import type { SdlcTracker } from \"../state/sdlc-tracker.js\";\n\nexport function createCompactionHook(tracker: SdlcTracker): () => Promise<void> {\n return async () => {\n await tracker.persist();\n };\n}\n","import type { PluginInput, ToolDefinition } from \"@opencode-ai/plugin\";\nimport { tool } from \"@opencode-ai/plugin\";\nimport type { SdlcConfig } from \"../../shared/types.js\";\n\nexport function createGetContextTool(ctx: PluginInput, config: SdlcConfig): ToolDefinition {\n return tool({\n description: \"Get SDLC plugin context and config.\",\n args: {},\n execute: () => {\n return Promise.resolve(\n JSON.stringify(\n {\n root: ctx.directory,\n config,\n },\n null,\n 2\n )\n );\n },\n });\n}\n","import { tool } from \"@opencode-ai/plugin\";\nimport type { ToolDefinition } from \"@opencode-ai/plugin\";\nimport type { SdlcTracker } from \"../state/sdlc-tracker.js\";\n\nexport function createGetStateTool(tracker: SdlcTracker): ToolDefinition {\n return tool({\n description: \"Get the current SDLC TDD state.\",\n args: {},\n execute: () => {\n return Promise.resolve(JSON.stringify(tracker.getState(), null, 2));\n },\n });\n}\n","import { tool, type ToolDefinition } from \"@opencode-ai/plugin\";\nimport type { SdlcTracker } from \"../state/sdlc-tracker.js\";\nimport type { SdlcState } from \"../../shared/types.js\";\n\nexport function createUpdateStateTool(tracker: SdlcTracker): ToolDefinition {\n return tool({\n description: \"Update SDLC TDD state.\",\n args: {\n currentPhase: tool.schema\n .enum([\"idle\", \"red\", \"domain-after-red\", \"green\", \"domain-after-green\"])\n .optional(),\n currentIssue: tool.schema.string().optional(),\n currentTest: tool.schema.string().optional(),\n currentTestFile: tool.schema.string().optional(),\n },\n execute: async (args: Partial<SdlcState>) => {\n tracker.updateState(args);\n await tracker.persist();\n return JSON.stringify(tracker.getState(), null, 2);\n },\n });\n}\n","import { readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport type { PluginInput, ToolDefinition } from \"@opencode-ai/plugin\";\nimport { tool } from \"@opencode-ai/plugin\";\nimport { getPluginSkillsDir } from \"../utils/package-paths.js\";\n\nexport function createLoadSkillTool(ctx: PluginInput): ToolDefinition {\n return tool({\n description: \"Load SDLC skill markdown by name.\",\n args: {\n skills: tool.schema.array(tool.schema.string()).min(1),\n },\n execute: async ({ skills }: { skills: string[] }) => {\n const skillContents: Record<string, string> = {};\n const pluginSkillsDir = getPluginSkillsDir();\n const localDir = join(ctx.directory, \"skills\");\n\n for (const skill of skills) {\n const fileName = `${skill}.md`;\n const candidatePaths = [join(localDir, fileName), join(pluginSkillsDir, fileName)];\n let content = \"\";\n for (const path of candidatePaths) {\n try {\n content = await readFile(path, \"utf-8\");\n break;\n } catch {\n continue;\n }\n }\n if (!content) {\n content = `Skill not found: ${skill}`;\n }\n skillContents[skill] = content;\n }\n\n return JSON.stringify(skillContents, null, 2);\n },\n });\n}\n","import { existsSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\nexport function getPackageRoot(): string {\n const currentFileDir = dirname(fileURLToPath(import.meta.url));\n\n const bundledRoot = join(currentFileDir, \"..\", \"..\", \"..\");\n if (existsSync(join(bundledRoot, \"package.json\"))) {\n return bundledRoot;\n }\n\n const devRoot = join(currentFileDir, \"..\", \"..\", \"..\", \"..\");\n if (existsSync(join(devRoot, \"package.json\"))) {\n return devRoot;\n }\n\n return bundledRoot;\n}\n\nexport function getPluginSkillsDir(): string {\n return join(getPackageRoot(), \"skills\");\n}\n","import { randomUUID } from \"node:crypto\";\nimport { tool, type ToolDefinition } from \"@opencode-ai/plugin\";\nimport type { PartyReviewSession, PartyReviewFinding } from \"../../shared/types.js\";\n\ninterface PartyReviewState {\n session: PartyReviewSession | null;\n}\n\nconst state: PartyReviewState = { session: null };\n\nexport function createPartyReviewTool(): ToolDefinition {\n return tool({\n description: \"Run SDLC party review discussion for findings.\",\n args: {\n action: tool.schema.enum([\"start\", \"next\", \"decide\", \"end\"]),\n findings: tool.schema\n .array(\n tool.schema.object({\n id: tool.schema.string(),\n title: tool.schema.string(),\n severity: tool.schema.enum([\"high\", \"medium\", \"low\"]),\n category: tool.schema.enum([\"logic\", \"security\", \"performance\", \"ux\", \"testing\", \"domain\"]),\n })\n )\n .optional(),\n sessionId: tool.schema.string().optional(),\n findingId: tool.schema.string().optional(),\n decision: tool.schema.enum([\"accept\", \"defer\", \"reject\"]).optional(),\n reason: tool.schema.string().optional(),\n },\n execute: async (args: {\n action: \"start\" | \"next\" | \"decide\" | \"end\";\n findings?: PartyReviewFinding[];\n sessionId?: string;\n findingId?: string;\n decision?: \"accept\" | \"defer\" | \"reject\";\n reason?: string;\n }) => {\n if (args.action === \"start\") {\n const findings = args.findings;\n if (!findings || findings.length === 0) {\n return JSON.stringify({ error: \"findings required\" });\n }\n const sessionId = randomUUID();\n state.session = {\n sessionId,\n findings,\n currentIndex: 0,\n decisions: [],\n };\n return JSON.stringify({ sessionId, current: findings[0] }, null, 2);\n }\n\n const session = state.session;\n if (!session || (args.sessionId !== undefined && args.sessionId !== session.sessionId)) {\n return JSON.stringify({ error: \"session not found\" });\n }\n\n if (args.action === \"next\") {\n const nextIndex = session.currentIndex + 1;\n if (nextIndex >= session.findings.length) {\n return JSON.stringify({ sessionId: session.sessionId, current: null }, null, 2);\n }\n session.currentIndex = nextIndex;\n const current = session.findings[session.currentIndex];\n return JSON.stringify({ sessionId: session.sessionId, current }, null, 2);\n }\n\n if (args.action === \"decide\") {\n if (args.findingId === undefined || args.decision === undefined) {\n return JSON.stringify({ error: \"findingId and decision required\" });\n }\n session.decisions.push({\n findingId: args.findingId,\n decision: args.decision,\n reason: args.reason,\n });\n return JSON.stringify({ sessionId: session.sessionId, decisions: session.decisions }, null, 2);\n }\n\n if (args.action === \"end\") {\n const summary = session;\n state.session = null;\n return JSON.stringify({ summary }, null, 2);\n }\n\n return JSON.stringify({ error: \"unknown action\" });\n },\n });\n}\n","import { mkdir, writeFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { randomUUID } from \"node:crypto\";\nimport type { PluginInput, ToolDefinition } from \"@opencode-ai/plugin\";\nimport { tool } from \"@opencode-ai/plugin\";\n\ninterface ReviewSession {\n id: string;\n folder: string;\n createdAt: string;\n}\n\nconst sessions = new Map<string, ReviewSession>();\n\nexport function createReviewStoreTool(ctx: PluginInput): ToolDefinition {\n return tool({\n description: \"Create and persist SDLC review artifacts under .opencode/reviews.\",\n args: {\n action: tool.schema.enum([\"start\", \"write\", \"end\"]),\n reviewId: tool.schema.string().optional(),\n issueId: tool.schema.string().optional(),\n filename: tool.schema.string().optional(),\n content: tool.schema.any().optional(),\n },\n execute: async (args: {\n action: \"start\" | \"write\" | \"end\";\n reviewId?: string;\n issueId?: string;\n filename?: string;\n content?: unknown;\n }) => {\n const reviewsRoot = join(ctx.directory, \".opencode\", \"reviews\");\n await mkdir(reviewsRoot, { recursive: true });\n\n if (args.action === \"start\") {\n const id = randomUUID();\n const timestamp = new Date().toISOString().replace(/[:.]/g, \"-\");\n const suffix = args.issueId !== undefined && args.issueId !== \"\" ? `-${args.issueId}` : \"\";\n const folder = join(reviewsRoot, `${timestamp}${suffix}`);\n await mkdir(folder, { recursive: true });\n const session: ReviewSession = {\n id,\n folder,\n createdAt: new Date().toISOString(),\n };\n sessions.set(id, session);\n return JSON.stringify({ reviewId: id, folder }, null, 2);\n }\n\n if (args.action !== \"write\" && args.action !== \"end\") {\n return JSON.stringify({ error: \"unknown action\" });\n }\n\n const reviewId = args.reviewId;\n if (reviewId === undefined || !sessions.has(reviewId)) {\n return JSON.stringify({ error: \"review session not found\" });\n }\n\n const session = sessions.get(reviewId);\n if (!session) {\n return JSON.stringify({ error: \"review session missing\" });\n }\n\n if (args.action === \"write\") {\n if (args.filename === undefined) {\n return JSON.stringify({ error: \"filename required\" });\n }\n const content =\n typeof args.content === \"string\" ? args.content : JSON.stringify(args.content ?? {}, null, 2);\n const filePath = join(session.folder, args.filename);\n await writeFile(filePath, content, \"utf-8\");\n return JSON.stringify({ reviewId: session.id, path: filePath }, null, 2);\n }\n\n if (args.action === \"end\") {\n sessions.delete(session.id);\n return JSON.stringify({ reviewId: session.id, folder: session.folder, closed: true }, null, 2);\n }\n\n return JSON.stringify({ error: \"unknown action\" });\n },\n });\n}\n","import type { PluginInput, ToolDefinition } from \"@opencode-ai/plugin\";\nimport type { SdlcConfig } from \"../../shared/types.js\";\nimport type { SdlcTracker } from \"../state/sdlc-tracker.js\";\nimport { createGetContextTool } from \"./get-context.js\";\nimport { createGetStateTool } from \"./get-state.js\";\nimport { createUpdateStateTool } from \"./update-state.js\";\nimport { createLoadSkillTool } from \"./load-skill.js\";\nimport { createPartyReviewTool } from \"./party-review.js\";\nimport { createReviewStoreTool } from \"./review-store.js\";\n\nexport function createTools(\n ctx: PluginInput,\n tracker: SdlcTracker,\n config: SdlcConfig\n): Record<string, ToolDefinition> {\n return {\n sdlc_get_context: createGetContextTool(ctx, config),\n sdlc_get_state: createGetStateTool(tracker),\n sdlc_update_state: createUpdateStateTool(tracker),\n sdlc_load_skill: createLoadSkillTool(ctx),\n sdlc_party_review: createPartyReviewTool(),\n sdlc_review_store: createReviewStoreTool(ctx),\n };\n}\n","import { existsSync } from \"node:fs\";\nimport { mkdir, readFile, writeFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { STATE_FILE_NAME } from \"../../shared/constants.js\";\nimport type { SdlcState } from \"../../shared/types.js\";\n\nexport class SdlcTracker {\n private state: SdlcState = {\n currentPhase: \"idle\",\n lastUpdated: new Date().toISOString(),\n };\n\n constructor(private directory: string) {}\n\n async initialize(): Promise<void> {\n const statePath = join(this.directory, \".opencode\", STATE_FILE_NAME);\n if (existsSync(statePath)) {\n const raw = await readFile(statePath, \"utf-8\");\n this.state = JSON.parse(raw) as SdlcState;\n } else {\n await this.persist();\n }\n }\n\n getState(): SdlcState {\n return this.state;\n }\n\n updateState(patch: Partial<SdlcState>): SdlcState {\n this.state = {\n ...this.state,\n ...patch,\n lastUpdated: new Date().toISOString(),\n };\n return this.state;\n }\n\n async persist(): Promise<void> {\n const stateDir = join(this.directory, \".opencode\");\n const statePath = join(stateDir, STATE_FILE_NAME);\n if (!existsSync(stateDir)) {\n await mkdir(stateDir, { recursive: true });\n }\n await writeFile(statePath, JSON.stringify(this.state, null, 2));\n }\n}\n","import { homedir } from \"node:os\";\nimport { join } from \"node:path\";\n\nexport const VERSION = \"0.1.0\";\nexport const DISPLAY_NAME = \"OpenCode SDLC Plugin\";\nexport const TAGLINE = \"Agentic SDLC workflow with discovery, ADRs, and TDD\";\n\nexport const PACKAGE_NAME = \"sdlc-plugin\";\n\nexport const GLOBAL_CONFIG_DIR = join(homedir(), \".config\", \"opencode\");\nexport const LOCAL_CONFIG_DIR_NAME = \".opencode\";\n\nexport const CONFIG_FILE_NAME = \"sdlc.json\";\nexport const STATE_FILE_NAME = \"sdlc-state.json\";\nexport const OPENCODE_CONFIG_NAME = \"opencode.json\";\nexport const OMO_CONFIG_NAME = \"oh-my-opencode.json\";\nexport const COMMAND_DIR_NAME = \"command\";\n\nexport const DEFAULT_AGENT_MODEL = \"anthropic/claude-sonnet-4-5-thinking\";\n\nexport const CONFIG_PATHS = {\n globalConfigDir: GLOBAL_CONFIG_DIR,\n globalSdlcConfig: join(GLOBAL_CONFIG_DIR, CONFIG_FILE_NAME),\n globalOpencodeConfig: join(GLOBAL_CONFIG_DIR, OPENCODE_CONFIG_NAME),\n globalOhMyOpencodeConfig: join(GLOBAL_CONFIG_DIR, OMO_CONFIG_NAME),\n commandsDir: join(GLOBAL_CONFIG_DIR, COMMAND_DIR_NAME),\n};\n","import { existsSync, readFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { CONFIG_FILE_NAME, CONFIG_PATHS } from \"../../shared/constants.js\";\nimport { sdlcConfigSchema } from \"../../shared/schemas.js\";\nimport type { SdlcConfig } from \"../../shared/types.js\";\n\nexport function loadSdlcConfig(directory: string): SdlcConfig {\n const localPath = join(directory, \".opencode\", CONFIG_FILE_NAME);\n const globalPath = join(CONFIG_PATHS.globalConfigDir, CONFIG_FILE_NAME);\n\n const configPath = existsSync(localPath) ? localPath : globalPath;\n\n if (!existsSync(configPath)) {\n return {\n version: \"0.0.0\",\n mode: \"event-modeling\",\n git: { workflow: \"standard\", worktrees: false, requireClean: false },\n features: { atomicDesign: true, gitSpice: false },\n github: {},\n languages: [\n {\n name: \"typescript\",\n testPatterns: [\"**/*.test.ts\", \"**/*.spec.ts\"],\n productionPatterns: [\"src/**/*.ts\"],\n typePatterns: [\"src/**/*types.ts\", \"src/**/*types/*.ts\"],\n },\n ],\n };\n }\n\n const raw = readFileSync(configPath, \"utf-8\");\n const parsed = JSON.parse(raw) as SdlcConfig;\n return sdlcConfigSchema.parse(parsed);\n}\n","import { z } from \"zod\";\n\nexport const languageConfigSchema = z.object({\n name: z.string().min(1),\n testPatterns: z.array(z.string()).min(1),\n productionPatterns: z.array(z.string()).min(1),\n typePatterns: z.array(z.string()).min(1),\n});\n\nexport const sdlcConfigSchema = z.object({\n version: z.string(),\n mode: z.enum([\"event-modeling\", \"traditional\"]),\n git: z.object({\n workflow: z.enum([\"git-spice\", \"standard\"]),\n worktrees: z.boolean(),\n requireClean: z.boolean(),\n }),\n features: z.object({\n atomicDesign: z.boolean(),\n gitSpice: z.boolean(),\n }),\n github: z.object({\n owner: z.string().optional(),\n project: z.number().optional(),\n }),\n languages: z.array(languageConfigSchema).min(1),\n});\n\nexport type SdlcConfigSchema = z.infer<typeof sdlcConfigSchema>;\n","import type { Plugin } from \"@opencode-ai/plugin\";\nimport { createSessionHooks } from \"./hooks/session-hooks.js\";\nimport { createToolHooks } from \"./hooks/tool-hooks.js\";\nimport { createCompactionHook } from \"./hooks/compaction-hook.js\";\nimport { createTools } from \"./tools/index.js\";\nimport { SdlcTracker } from \"./state/sdlc-tracker.js\";\nimport { loadSdlcConfig } from \"./utils/config-loader.js\";\n\nexport const SdlcPlugin: Plugin = async (ctx) => {\n const config = loadSdlcConfig(ctx.directory);\n const tracker = new SdlcTracker(ctx.directory);\n await tracker.initialize();\n\n const tools = createTools(ctx, tracker, config);\n const sessionHooks = createSessionHooks(tracker);\n const toolHooks = createToolHooks(tracker, config);\n const compactionHook = createCompactionHook(tracker);\n\n return {\n tool: tools,\n event: sessionHooks,\n \"tool.execute.before\": toolHooks.before,\n \"tool.execute.after\": toolHooks.after,\n \"experimental.session.compacting\": compactionHook,\n };\n};\n\nexport default SdlcPlugin;\n"],"mappings":";AAMO,SAAS,mBAAmB,UAA8E;AAC/G,SAAO,CAAC,EAAE,MAAM,MAA8C;AAC5D,QAAI,MAAM,SAAS,mBAAmB;AACpC,aAAO,QAAQ,QAAQ;AAAA,IACzB;AACA,QAAI,MAAM,SAAS,gBAAgB;AACjC,aAAO,QAAQ,QAAQ;AAAA,IACzB;AACA,WAAO,QAAQ,QAAQ;AAAA,EACzB;AACF;;;AChBA,OAAO,eAAe;AAEf,SAAS,kBAAkB,UAAkB,UAA6B;AAC/E,MAAI,SAAS,WAAW,EAAG,QAAO;AAClC,QAAM,UAAU,UAAU,UAAU,EAAE,KAAK,KAAK,CAAC;AACjD,SAAO,QAAQ,QAAQ;AACzB;;;ACgCA,IAAM,oBAA8C;AAAA,EAClD,MAAM,CAAC,KAAK;AAAA,EACZ,KAAK,CAAC,kBAAkB;AAAA,EACxB,oBAAoB,CAAC,OAAO;AAAA,EAC5B,OAAO,CAAC,oBAAoB;AAAA,EAC5B,sBAAsB,CAAC,OAAO,MAAM;AACtC;AAEO,SAAS,gBAAgB,SAAsB,QAGpD;AACA,SAAO;AAAA,IACL,QAAQ,OAAO,OAAwB,WAA4C;AACjF,UAAI,MAAM,SAAS,qBAAqB;AACtC,cAAM,OAAO,OAAO;AACpB,YAAI,KAAK,cAAc;AACrB,gBAAM,UAAU,QAAQ,SAAS,EAAE;AACnC,gBAAM,UAAU,kBAAkB,OAAO,KAAK,CAAC;AAC/C,cAAI,CAAC,QAAQ,SAAS,KAAK,YAAY,GAAG;AACxC,kBAAM,IAAI;AAAA,cACR,2BAA2B,OAAO,OAAO,KAAK,YAAY,0BAChC,QAAQ,KAAK,IAAI,CAAC;AAAA,YAE9C;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAEA,UAAI,MAAM,SAAS,UAAU,MAAM,SAAS,SAAS;AACnD,cAAMA,SAAQ,QAAQ,SAAS;AAC/B,cAAM,OAAO,OAAO;AACpB,cAAM,WAAW,KAAK,YAAY;AAClC,YAAI,SAAS,WAAW,EAAG;AAE3B,cAAM,kBAAkB,mBAAmB,QAAQA,OAAM,YAAY;AAErE,YAAI,gBAAgB,SAAS,KAAK,CAAC,kBAAkB,UAAU,eAAe,GAAG;AAC/E,gBAAM,IAAI;AAAA,YACR,sCAAsCA,OAAM,YAAY,wBACjC,gBAAgB,KAAK,IAAI,CAAC,gBACjC,QAAQ;AAAA,UAC1B;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,IAEA,OAAO,OAAO,QAAwB,YAA4C;AAChF;AAAA,IACF;AAAA,EACF;AACF;AAEA,SAAS,mBACP,QACA,OACU;AACV,QAAM,WAAW,OAAO,UAAU,QAAQ,CAAC,aAAa;AACtD,QAAI,UAAU,MAAO,QAAO,SAAS;AACrC,QAAI,UAAU,QAAS,QAAO,SAAS;AACvC,QAAI,UAAU,sBAAsB,UAAU,qBAAsB,QAAO,SAAS;AACpF,WAAO,CAAC;AAAA,EACV,CAAC;AACD,SAAO,SAAS,OAAO,OAAO;AAChC;;;ACpGO,SAAS,qBAAqB,SAA2C;AAC9E,SAAO,YAAY;AACjB,UAAM,QAAQ,QAAQ;AAAA,EACxB;AACF;;;ACLA,SAAS,YAAY;AAGd,SAAS,qBAAqB,KAAkB,QAAoC;AACzF,SAAO,KAAK;AAAA,IACV,aAAa;AAAA,IACb,MAAM,CAAC;AAAA,IACP,SAAS,MAAM;AACb,aAAO,QAAQ;AAAA,QACb,KAAK;AAAA,UACH;AAAA,YACE,MAAM,IAAI;AAAA,YACV;AAAA,UACF;AAAA,UACA;AAAA,UACA;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF,CAAC;AACH;;;ACrBA,SAAS,QAAAC,aAAY;AAId,SAAS,mBAAmB,SAAsC;AACvE,SAAOA,MAAK;AAAA,IACV,aAAa;AAAA,IACb,MAAM,CAAC;AAAA,IACP,SAAS,MAAM;AACb,aAAO,QAAQ,QAAQ,KAAK,UAAU,QAAQ,SAAS,GAAG,MAAM,CAAC,CAAC;AAAA,IACpE;AAAA,EACF,CAAC;AACH;;;ACZA,SAAS,QAAAC,aAAiC;AAInC,SAAS,sBAAsB,SAAsC;AAC1E,SAAOA,MAAK;AAAA,IACV,aAAa;AAAA,IACb,MAAM;AAAA,MACJ,cAAcA,MAAK,OAChB,KAAK,CAAC,QAAQ,OAAO,oBAAoB,SAAS,oBAAoB,CAAC,EACvE,SAAS;AAAA,MACZ,cAAcA,MAAK,OAAO,OAAO,EAAE,SAAS;AAAA,MAC5C,aAAaA,MAAK,OAAO,OAAO,EAAE,SAAS;AAAA,MAC3C,iBAAiBA,MAAK,OAAO,OAAO,EAAE,SAAS;AAAA,IACjD;AAAA,IACA,SAAS,OAAO,SAA6B;AAC3C,cAAQ,YAAY,IAAI;AACxB,YAAM,QAAQ,QAAQ;AACtB,aAAO,KAAK,UAAU,QAAQ,SAAS,GAAG,MAAM,CAAC;AAAA,IACnD;AAAA,EACF,CAAC;AACH;;;ACrBA,SAAS,gBAAgB;AACzB,SAAS,QAAAC,aAAY;AAErB,SAAS,QAAAC,aAAY;;;ACHrB,SAAS,kBAAkB;AAC3B,SAAS,SAAS,YAAY;AAC9B,SAAS,qBAAqB;AAEvB,SAAS,iBAAyB;AACvC,QAAM,iBAAiB,QAAQ,cAAc,YAAY,GAAG,CAAC;AAE7D,QAAM,cAAc,KAAK,gBAAgB,MAAM,MAAM,IAAI;AACzD,MAAI,WAAW,KAAK,aAAa,cAAc,CAAC,GAAG;AACjD,WAAO;AAAA,EACT;AAEA,QAAM,UAAU,KAAK,gBAAgB,MAAM,MAAM,MAAM,IAAI;AAC3D,MAAI,WAAW,KAAK,SAAS,cAAc,CAAC,GAAG;AAC7C,WAAO;AAAA,EACT;AAEA,SAAO;AACT;AAEO,SAAS,qBAA6B;AAC3C,SAAO,KAAK,eAAe,GAAG,QAAQ;AACxC;;;ADhBO,SAAS,oBAAoB,KAAkC;AACpE,SAAOC,MAAK;AAAA,IACV,aAAa;AAAA,IACb,MAAM;AAAA,MACJ,QAAQA,MAAK,OAAO,MAAMA,MAAK,OAAO,OAAO,CAAC,EAAE,IAAI,CAAC;AAAA,IACvD;AAAA,IACA,SAAS,OAAO,EAAE,OAAO,MAA4B;AACnD,YAAM,gBAAwC,CAAC;AAC/C,YAAM,kBAAkB,mBAAmB;AAC3C,YAAM,WAAWC,MAAK,IAAI,WAAW,QAAQ;AAE7C,iBAAW,SAAS,QAAQ;AAC1B,cAAM,WAAW,GAAG,KAAK;AACzB,cAAM,iBAAiB,CAACA,MAAK,UAAU,QAAQ,GAAGA,MAAK,iBAAiB,QAAQ,CAAC;AACjF,YAAI,UAAU;AACd,mBAAW,QAAQ,gBAAgB;AACjC,cAAI;AACF,sBAAU,MAAM,SAAS,MAAM,OAAO;AACtC;AAAA,UACF,QAAQ;AACN;AAAA,UACF;AAAA,QACF;AACA,YAAI,CAAC,SAAS;AACZ,oBAAU,oBAAoB,KAAK;AAAA,QACrC;AACA,sBAAc,KAAK,IAAI;AAAA,MACzB;AAEA,aAAO,KAAK,UAAU,eAAe,MAAM,CAAC;AAAA,IAC9C;AAAA,EACF,CAAC;AACH;;;AEtCA,SAAS,kBAAkB;AAC3B,SAAS,QAAAC,aAAiC;AAO1C,IAAM,QAA0B,EAAE,SAAS,KAAK;AAEzC,SAAS,wBAAwC;AACtD,SAAOA,MAAK;AAAA,IACV,aAAa;AAAA,IACb,MAAM;AAAA,MACJ,QAAQA,MAAK,OAAO,KAAK,CAAC,SAAS,QAAQ,UAAU,KAAK,CAAC;AAAA,MAC3D,UAAUA,MAAK,OACZ;AAAA,QACCA,MAAK,OAAO,OAAO;AAAA,UACjB,IAAIA,MAAK,OAAO,OAAO;AAAA,UACvB,OAAOA,MAAK,OAAO,OAAO;AAAA,UAC1B,UAAUA,MAAK,OAAO,KAAK,CAAC,QAAQ,UAAU,KAAK,CAAC;AAAA,UACpD,UAAUA,MAAK,OAAO,KAAK,CAAC,SAAS,YAAY,eAAe,MAAM,WAAW,QAAQ,CAAC;AAAA,QAC5F,CAAC;AAAA,MACH,EACC,SAAS;AAAA,MACZ,WAAWA,MAAK,OAAO,OAAO,EAAE,SAAS;AAAA,MACzC,WAAWA,MAAK,OAAO,OAAO,EAAE,SAAS;AAAA,MACzC,UAAUA,MAAK,OAAO,KAAK,CAAC,UAAU,SAAS,QAAQ,CAAC,EAAE,SAAS;AAAA,MACnE,QAAQA,MAAK,OAAO,OAAO,EAAE,SAAS;AAAA,IACxC;AAAA,IACA,SAAS,OAAO,SAOV;AACJ,UAAI,KAAK,WAAW,SAAS;AAC3B,cAAM,WAAW,KAAK;AACtB,YAAI,CAAC,YAAY,SAAS,WAAW,GAAG;AACtC,iBAAO,KAAK,UAAU,EAAE,OAAO,oBAAoB,CAAC;AAAA,QACtD;AACA,cAAM,YAAY,WAAW;AAC7B,cAAM,UAAU;AAAA,UACd;AAAA,UACA;AAAA,UACA,cAAc;AAAA,UACd,WAAW,CAAC;AAAA,QACd;AACA,eAAO,KAAK,UAAU,EAAE,WAAW,SAAS,SAAS,CAAC,EAAE,GAAG,MAAM,CAAC;AAAA,MACpE;AAEA,YAAM,UAAU,MAAM;AACtB,UAAI,CAAC,WAAY,KAAK,cAAc,UAAa,KAAK,cAAc,QAAQ,WAAY;AACtF,eAAO,KAAK,UAAU,EAAE,OAAO,oBAAoB,CAAC;AAAA,MACtD;AAEA,UAAI,KAAK,WAAW,QAAQ;AAC1B,cAAM,YAAY,QAAQ,eAAe;AACzC,YAAI,aAAa,QAAQ,SAAS,QAAQ;AACxC,iBAAO,KAAK,UAAU,EAAE,WAAW,QAAQ,WAAW,SAAS,KAAK,GAAG,MAAM,CAAC;AAAA,QAChF;AACA,gBAAQ,eAAe;AACvB,cAAM,UAAU,QAAQ,SAAS,QAAQ,YAAY;AACrD,eAAO,KAAK,UAAU,EAAE,WAAW,QAAQ,WAAW,QAAQ,GAAG,MAAM,CAAC;AAAA,MAC1E;AAEA,UAAI,KAAK,WAAW,UAAU;AAC5B,YAAI,KAAK,cAAc,UAAa,KAAK,aAAa,QAAW;AAC/D,iBAAO,KAAK,UAAU,EAAE,OAAO,kCAAkC,CAAC;AAAA,QACpE;AACA,gBAAQ,UAAU,KAAK;AAAA,UACrB,WAAW,KAAK;AAAA,UAChB,UAAU,KAAK;AAAA,UACf,QAAQ,KAAK;AAAA,QACf,CAAC;AACD,eAAO,KAAK,UAAU,EAAE,WAAW,QAAQ,WAAW,WAAW,QAAQ,UAAU,GAAG,MAAM,CAAC;AAAA,MAC/F;AAEA,UAAI,KAAK,WAAW,OAAO;AACzB,cAAM,UAAU;AAChB,cAAM,UAAU;AAChB,eAAO,KAAK,UAAU,EAAE,QAAQ,GAAG,MAAM,CAAC;AAAA,MAC5C;AAEA,aAAO,KAAK,UAAU,EAAE,OAAO,iBAAiB,CAAC;AAAA,IACnD;AAAA,EACF,CAAC;AACH;;;ACzFA,SAAS,OAAO,iBAAiB;AACjC,SAAS,QAAAC,aAAY;AACrB,SAAS,cAAAC,mBAAkB;AAE3B,SAAS,QAAAC,aAAY;AAQrB,IAAM,WAAW,oBAAI,IAA2B;AAEzC,SAAS,sBAAsB,KAAkC;AACtE,SAAOA,MAAK;AAAA,IACV,aAAa;AAAA,IACb,MAAM;AAAA,MACJ,QAAQA,MAAK,OAAO,KAAK,CAAC,SAAS,SAAS,KAAK,CAAC;AAAA,MAClD,UAAUA,MAAK,OAAO,OAAO,EAAE,SAAS;AAAA,MACxC,SAASA,MAAK,OAAO,OAAO,EAAE,SAAS;AAAA,MACvC,UAAUA,MAAK,OAAO,OAAO,EAAE,SAAS;AAAA,MACxC,SAASA,MAAK,OAAO,IAAI,EAAE,SAAS;AAAA,IACtC;AAAA,IACA,SAAS,OAAO,SAMV;AACJ,YAAM,cAAcF,MAAK,IAAI,WAAW,aAAa,SAAS;AAC9D,YAAM,MAAM,aAAa,EAAE,WAAW,KAAK,CAAC;AAE5C,UAAI,KAAK,WAAW,SAAS;AAC3B,cAAM,KAAKC,YAAW;AACtB,cAAM,aAAY,oBAAI,KAAK,GAAE,YAAY,EAAE,QAAQ,SAAS,GAAG;AAC/D,cAAM,SAAS,KAAK,YAAY,UAAa,KAAK,YAAY,KAAK,IAAI,KAAK,OAAO,KAAK;AACxF,cAAM,SAASD,MAAK,aAAa,GAAG,SAAS,GAAG,MAAM,EAAE;AACxD,cAAM,MAAM,QAAQ,EAAE,WAAW,KAAK,CAAC;AACvC,cAAMG,WAAyB;AAAA,UAC7B;AAAA,UACA;AAAA,UACA,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,QACpC;AACA,iBAAS,IAAI,IAAIA,QAAO;AACxB,eAAO,KAAK,UAAU,EAAE,UAAU,IAAI,OAAO,GAAG,MAAM,CAAC;AAAA,MACzD;AAEA,UAAI,KAAK,WAAW,WAAW,KAAK,WAAW,OAAO;AACpD,eAAO,KAAK,UAAU,EAAE,OAAO,iBAAiB,CAAC;AAAA,MACnD;AAEA,YAAM,WAAW,KAAK;AACtB,UAAI,aAAa,UAAa,CAAC,SAAS,IAAI,QAAQ,GAAG;AACrD,eAAO,KAAK,UAAU,EAAE,OAAO,2BAA2B,CAAC;AAAA,MAC7D;AAEA,YAAM,UAAU,SAAS,IAAI,QAAQ;AACrC,UAAI,CAAC,SAAS;AACZ,eAAO,KAAK,UAAU,EAAE,OAAO,yBAAyB,CAAC;AAAA,MAC3D;AAEA,UAAI,KAAK,WAAW,SAAS;AAC3B,YAAI,KAAK,aAAa,QAAW;AAC/B,iBAAO,KAAK,UAAU,EAAE,OAAO,oBAAoB,CAAC;AAAA,QACtD;AACA,cAAM,UACJ,OAAO,KAAK,YAAY,WAAW,KAAK,UAAU,KAAK,UAAU,KAAK,WAAW,CAAC,GAAG,MAAM,CAAC;AAC9F,cAAM,WAAWH,MAAK,QAAQ,QAAQ,KAAK,QAAQ;AACnD,cAAM,UAAU,UAAU,SAAS,OAAO;AAC1C,eAAO,KAAK,UAAU,EAAE,UAAU,QAAQ,IAAI,MAAM,SAAS,GAAG,MAAM,CAAC;AAAA,MACzE;AAEA,UAAI,KAAK,WAAW,OAAO;AACzB,iBAAS,OAAO,QAAQ,EAAE;AAC1B,eAAO,KAAK,UAAU,EAAE,UAAU,QAAQ,IAAI,QAAQ,QAAQ,QAAQ,QAAQ,KAAK,GAAG,MAAM,CAAC;AAAA,MAC/F;AAEA,aAAO,KAAK,UAAU,EAAE,OAAO,iBAAiB,CAAC;AAAA,IACnD;AAAA,EACF,CAAC;AACH;;;ACxEO,SAAS,YACd,KACA,SACA,QACgC;AAChC,SAAO;AAAA,IACL,kBAAkB,qBAAqB,KAAK,MAAM;AAAA,IAClD,gBAAgB,mBAAmB,OAAO;AAAA,IAC1C,mBAAmB,sBAAsB,OAAO;AAAA,IAChD,iBAAiB,oBAAoB,GAAG;AAAA,IACxC,mBAAmB,sBAAsB;AAAA,IACzC,mBAAmB,sBAAsB,GAAG;AAAA,EAC9C;AACF;;;ACvBA,SAAS,cAAAI,mBAAkB;AAC3B,SAAS,SAAAC,QAAO,YAAAC,WAAU,aAAAC,kBAAiB;AAC3C,SAAS,QAAAC,aAAY;;;ACFrB,SAAS,eAAe;AACxB,SAAS,QAAAC,aAAY;AAQd,IAAM,oBAAoBC,MAAK,QAAQ,GAAG,WAAW,UAAU;AAG/D,IAAM,mBAAmB;AACzB,IAAM,kBAAkB;AACxB,IAAM,uBAAuB;AAC7B,IAAM,kBAAkB;AACxB,IAAM,mBAAmB;AAIzB,IAAM,eAAe;AAAA,EAC1B,iBAAiB;AAAA,EACjB,kBAAkBC,MAAK,mBAAmB,gBAAgB;AAAA,EAC1D,sBAAsBA,MAAK,mBAAmB,oBAAoB;AAAA,EAClE,0BAA0BA,MAAK,mBAAmB,eAAe;AAAA,EACjE,aAAaA,MAAK,mBAAmB,gBAAgB;AACvD;;;ADpBO,IAAM,cAAN,MAAkB;AAAA,EAMvB,YAAoB,WAAmB;AAAnB;AAAA,EAAoB;AAAA,EALhC,QAAmB;AAAA,IACzB,cAAc;AAAA,IACd,cAAa,oBAAI,KAAK,GAAE,YAAY;AAAA,EACtC;AAAA,EAIA,MAAM,aAA4B;AAChC,UAAM,YAAYC,MAAK,KAAK,WAAW,aAAa,eAAe;AACnE,QAAIC,YAAW,SAAS,GAAG;AACzB,YAAM,MAAM,MAAMC,UAAS,WAAW,OAAO;AAC7C,WAAK,QAAQ,KAAK,MAAM,GAAG;AAAA,IAC7B,OAAO;AACL,YAAM,KAAK,QAAQ;AAAA,IACrB;AAAA,EACF;AAAA,EAEA,WAAsB;AACpB,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,YAAY,OAAsC;AAChD,SAAK,QAAQ;AAAA,MACX,GAAG,KAAK;AAAA,MACR,GAAG;AAAA,MACH,cAAa,oBAAI,KAAK,GAAE,YAAY;AAAA,IACtC;AACA,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,MAAM,UAAyB;AAC7B,UAAM,WAAWF,MAAK,KAAK,WAAW,WAAW;AACjD,UAAM,YAAYA,MAAK,UAAU,eAAe;AAChD,QAAI,CAACC,YAAW,QAAQ,GAAG;AACzB,YAAME,OAAM,UAAU,EAAE,WAAW,KAAK,CAAC;AAAA,IAC3C;AACA,UAAMC,WAAU,WAAW,KAAK,UAAU,KAAK,OAAO,MAAM,CAAC,CAAC;AAAA,EAChE;AACF;;;AE7CA,SAAS,cAAAC,aAAY,oBAAoB;AACzC,SAAS,QAAAC,aAAY;;;ACDrB,SAAS,SAAS;AAEX,IAAM,uBAAuB,EAAE,OAAO;AAAA,EAC3C,MAAM,EAAE,OAAO,EAAE,IAAI,CAAC;AAAA,EACtB,cAAc,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,IAAI,CAAC;AAAA,EACvC,oBAAoB,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,IAAI,CAAC;AAAA,EAC7C,cAAc,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,IAAI,CAAC;AACzC,CAAC;AAEM,IAAM,mBAAmB,EAAE,OAAO;AAAA,EACvC,SAAS,EAAE,OAAO;AAAA,EAClB,MAAM,EAAE,KAAK,CAAC,kBAAkB,aAAa,CAAC;AAAA,EAC9C,KAAK,EAAE,OAAO;AAAA,IACZ,UAAU,EAAE,KAAK,CAAC,aAAa,UAAU,CAAC;AAAA,IAC1C,WAAW,EAAE,QAAQ;AAAA,IACrB,cAAc,EAAE,QAAQ;AAAA,EAC1B,CAAC;AAAA,EACD,UAAU,EAAE,OAAO;AAAA,IACjB,cAAc,EAAE,QAAQ;AAAA,IACxB,UAAU,EAAE,QAAQ;AAAA,EACtB,CAAC;AAAA,EACD,QAAQ,EAAE,OAAO;AAAA,IACf,OAAO,EAAE,OAAO,EAAE,SAAS;AAAA,IAC3B,SAAS,EAAE,OAAO,EAAE,SAAS;AAAA,EAC/B,CAAC;AAAA,EACD,WAAW,EAAE,MAAM,oBAAoB,EAAE,IAAI,CAAC;AAChD,CAAC;;;ADpBM,SAAS,eAAe,WAA+B;AAC5D,QAAM,YAAYC,MAAK,WAAW,aAAa,gBAAgB;AAC/D,QAAM,aAAaA,MAAK,aAAa,iBAAiB,gBAAgB;AAEtE,QAAM,aAAaC,YAAW,SAAS,IAAI,YAAY;AAEvD,MAAI,CAACA,YAAW,UAAU,GAAG;AAC3B,WAAO;AAAA,MACL,SAAS;AAAA,MACT,MAAM;AAAA,MACN,KAAK,EAAE,UAAU,YAAY,WAAW,OAAO,cAAc,MAAM;AAAA,MACnE,UAAU,EAAE,cAAc,MAAM,UAAU,MAAM;AAAA,MAChD,QAAQ,CAAC;AAAA,MACT,WAAW;AAAA,QACT;AAAA,UACE,MAAM;AAAA,UACN,cAAc,CAAC,gBAAgB,cAAc;AAAA,UAC7C,oBAAoB,CAAC,aAAa;AAAA,UAClC,cAAc,CAAC,oBAAoB,oBAAoB;AAAA,QACzD;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,QAAM,MAAM,aAAa,YAAY,OAAO;AAC5C,QAAM,SAAS,KAAK,MAAM,GAAG;AAC7B,SAAO,iBAAiB,MAAM,MAAM;AACtC;;;AEzBO,IAAM,aAAqB,OAAO,QAAQ;AAC/C,QAAM,SAAS,eAAe,IAAI,SAAS;AAC3C,QAAM,UAAU,IAAI,YAAY,IAAI,SAAS;AAC7C,QAAM,QAAQ,WAAW;AAEzB,QAAM,QAAQ,YAAY,KAAK,SAAS,MAAM;AAC9C,QAAM,eAAe,mBAAmB,OAAO;AAC/C,QAAM,YAAY,gBAAgB,SAAS,MAAM;AACjD,QAAM,iBAAiB,qBAAqB,OAAO;AAEnD,SAAO;AAAA,IACL,MAAM;AAAA,IACN,OAAO;AAAA,IACP,uBAAuB,UAAU;AAAA,IACjC,sBAAsB,UAAU;AAAA,IAChC,mCAAmC;AAAA,EACrC;AACF;","names":["state","tool","tool","join","tool","tool","join","tool","join","randomUUID","tool","session","existsSync","mkdir","readFile","writeFile","join","join","join","join","join","existsSync","readFile","mkdir","writeFile","existsSync","join","join","existsSync"]}
@@ -0,0 +1,5 @@
1
+ import { Plugin } from '@opencode-ai/plugin';
2
+
3
+ declare const SdlcPlugin: Plugin;
4
+
5
+ export { SdlcPlugin, SdlcPlugin as default };
@@ -0,0 +1,476 @@
1
+ // src/plugin/hooks/session-hooks.ts
2
+ function createSessionHooks(_tracker) {
3
+ return ({ event }) => {
4
+ if (event.type === "session.created") {
5
+ return Promise.resolve();
6
+ }
7
+ if (event.type === "session.idle") {
8
+ return Promise.resolve();
9
+ }
10
+ return Promise.resolve();
11
+ };
12
+ }
13
+
14
+ // src/plugin/utils/file-patterns.ts
15
+ import picomatch from "picomatch";
16
+ function matchesAnyPattern(filePath, patterns) {
17
+ if (patterns.length === 0) return false;
18
+ const matcher = picomatch(patterns, { dot: true });
19
+ return matcher(filePath);
20
+ }
21
+
22
+ // src/plugin/hooks/tool-hooks.ts
23
+ var VALID_TRANSITIONS = {
24
+ idle: ["red"],
25
+ red: ["domain-after-red"],
26
+ "domain-after-red": ["green"],
27
+ green: ["domain-after-green"],
28
+ "domain-after-green": ["red", "idle"]
29
+ };
30
+ function createToolHooks(tracker, config) {
31
+ return {
32
+ before: async (input, output) => {
33
+ if (input.tool === "sdlc_update_state") {
34
+ const args = output.args;
35
+ if (args.currentPhase) {
36
+ const current = tracker.getState().currentPhase;
37
+ const allowed = VALID_TRANSITIONS[current] ?? [];
38
+ if (!allowed.includes(args.currentPhase)) {
39
+ throw new Error(
40
+ `Invalid TDD transition: ${current} -> ${args.currentPhase}. Allowed transitions: ${allowed.join(", ")}. Follow RED \u2192 DOMAIN \u2192 GREEN \u2192 DOMAIN \u2192 REFACTOR.`
41
+ );
42
+ }
43
+ }
44
+ }
45
+ if (input.tool === "edit" || input.tool === "write") {
46
+ const state2 = tracker.getState();
47
+ const args = output.args;
48
+ const filePath = args.filePath ?? "";
49
+ if (filePath.length === 0) return;
50
+ const allowedPatterns = getAllowedPatterns(config, state2.currentPhase);
51
+ if (allowedPatterns.length > 0 && !matchesAnyPattern(filePath, allowedPatterns)) {
52
+ throw new Error(
53
+ `File ownership violation in phase '${state2.currentPhase}'. Allowed patterns: ${allowedPatterns.join(", ")}. Attempted: ${filePath}. Delegate to the correct agent.`
54
+ );
55
+ }
56
+ }
57
+ },
58
+ after: async (_input, _output) => {
59
+ return;
60
+ }
61
+ };
62
+ }
63
+ function getAllowedPatterns(config, phase) {
64
+ const patterns = config.languages.flatMap((language) => {
65
+ if (phase === "red") return language.testPatterns;
66
+ if (phase === "green") return language.productionPatterns;
67
+ if (phase === "domain-after-red" || phase === "domain-after-green") return language.typePatterns;
68
+ return [];
69
+ });
70
+ return patterns.filter(Boolean);
71
+ }
72
+
73
+ // src/plugin/hooks/compaction-hook.ts
74
+ function createCompactionHook(tracker) {
75
+ return async () => {
76
+ await tracker.persist();
77
+ };
78
+ }
79
+
80
+ // src/plugin/tools/get-context.ts
81
+ import { tool } from "@opencode-ai/plugin";
82
+ function createGetContextTool(ctx, config) {
83
+ return tool({
84
+ description: "Get SDLC plugin context and config.",
85
+ args: {},
86
+ execute: () => {
87
+ return Promise.resolve(
88
+ JSON.stringify(
89
+ {
90
+ root: ctx.directory,
91
+ config
92
+ },
93
+ null,
94
+ 2
95
+ )
96
+ );
97
+ }
98
+ });
99
+ }
100
+
101
+ // src/plugin/tools/get-state.ts
102
+ import { tool as tool2 } from "@opencode-ai/plugin";
103
+ function createGetStateTool(tracker) {
104
+ return tool2({
105
+ description: "Get the current SDLC TDD state.",
106
+ args: {},
107
+ execute: () => {
108
+ return Promise.resolve(JSON.stringify(tracker.getState(), null, 2));
109
+ }
110
+ });
111
+ }
112
+
113
+ // src/plugin/tools/update-state.ts
114
+ import { tool as tool3 } from "@opencode-ai/plugin";
115
+ function createUpdateStateTool(tracker) {
116
+ return tool3({
117
+ description: "Update SDLC TDD state.",
118
+ args: {
119
+ currentPhase: tool3.schema.enum(["idle", "red", "domain-after-red", "green", "domain-after-green"]).optional(),
120
+ currentIssue: tool3.schema.string().optional(),
121
+ currentTest: tool3.schema.string().optional(),
122
+ currentTestFile: tool3.schema.string().optional()
123
+ },
124
+ execute: async (args) => {
125
+ tracker.updateState(args);
126
+ await tracker.persist();
127
+ return JSON.stringify(tracker.getState(), null, 2);
128
+ }
129
+ });
130
+ }
131
+
132
+ // src/plugin/tools/load-skill.ts
133
+ import { readFile } from "fs/promises";
134
+ import { join as join2 } from "path";
135
+ import { tool as tool4 } from "@opencode-ai/plugin";
136
+
137
+ // src/plugin/utils/package-paths.ts
138
+ import { existsSync } from "fs";
139
+ import { dirname, join } from "path";
140
+ import { fileURLToPath } from "url";
141
+ function getPackageRoot() {
142
+ const currentFileDir = dirname(fileURLToPath(import.meta.url));
143
+ const bundledRoot = join(currentFileDir, "..", "..", "..");
144
+ if (existsSync(join(bundledRoot, "package.json"))) {
145
+ return bundledRoot;
146
+ }
147
+ const devRoot = join(currentFileDir, "..", "..", "..", "..");
148
+ if (existsSync(join(devRoot, "package.json"))) {
149
+ return devRoot;
150
+ }
151
+ return bundledRoot;
152
+ }
153
+ function getPluginSkillsDir() {
154
+ return join(getPackageRoot(), "skills");
155
+ }
156
+
157
+ // src/plugin/tools/load-skill.ts
158
+ function createLoadSkillTool(ctx) {
159
+ return tool4({
160
+ description: "Load SDLC skill markdown by name.",
161
+ args: {
162
+ skills: tool4.schema.array(tool4.schema.string()).min(1)
163
+ },
164
+ execute: async ({ skills }) => {
165
+ const skillContents = {};
166
+ const pluginSkillsDir = getPluginSkillsDir();
167
+ const localDir = join2(ctx.directory, "skills");
168
+ for (const skill of skills) {
169
+ const fileName = `${skill}.md`;
170
+ const candidatePaths = [join2(localDir, fileName), join2(pluginSkillsDir, fileName)];
171
+ let content = "";
172
+ for (const path of candidatePaths) {
173
+ try {
174
+ content = await readFile(path, "utf-8");
175
+ break;
176
+ } catch {
177
+ continue;
178
+ }
179
+ }
180
+ if (!content) {
181
+ content = `Skill not found: ${skill}`;
182
+ }
183
+ skillContents[skill] = content;
184
+ }
185
+ return JSON.stringify(skillContents, null, 2);
186
+ }
187
+ });
188
+ }
189
+
190
+ // src/plugin/tools/party-review.ts
191
+ import { randomUUID } from "crypto";
192
+ import { tool as tool5 } from "@opencode-ai/plugin";
193
+ var state = { session: null };
194
+ function createPartyReviewTool() {
195
+ return tool5({
196
+ description: "Run SDLC party review discussion for findings.",
197
+ args: {
198
+ action: tool5.schema.enum(["start", "next", "decide", "end"]),
199
+ findings: tool5.schema.array(
200
+ tool5.schema.object({
201
+ id: tool5.schema.string(),
202
+ title: tool5.schema.string(),
203
+ severity: tool5.schema.enum(["high", "medium", "low"]),
204
+ category: tool5.schema.enum(["logic", "security", "performance", "ux", "testing", "domain"])
205
+ })
206
+ ).optional(),
207
+ sessionId: tool5.schema.string().optional(),
208
+ findingId: tool5.schema.string().optional(),
209
+ decision: tool5.schema.enum(["accept", "defer", "reject"]).optional(),
210
+ reason: tool5.schema.string().optional()
211
+ },
212
+ execute: async (args) => {
213
+ if (args.action === "start") {
214
+ const findings = args.findings;
215
+ if (!findings || findings.length === 0) {
216
+ return JSON.stringify({ error: "findings required" });
217
+ }
218
+ const sessionId = randomUUID();
219
+ state.session = {
220
+ sessionId,
221
+ findings,
222
+ currentIndex: 0,
223
+ decisions: []
224
+ };
225
+ return JSON.stringify({ sessionId, current: findings[0] }, null, 2);
226
+ }
227
+ const session = state.session;
228
+ if (!session || args.sessionId !== void 0 && args.sessionId !== session.sessionId) {
229
+ return JSON.stringify({ error: "session not found" });
230
+ }
231
+ if (args.action === "next") {
232
+ const nextIndex = session.currentIndex + 1;
233
+ if (nextIndex >= session.findings.length) {
234
+ return JSON.stringify({ sessionId: session.sessionId, current: null }, null, 2);
235
+ }
236
+ session.currentIndex = nextIndex;
237
+ const current = session.findings[session.currentIndex];
238
+ return JSON.stringify({ sessionId: session.sessionId, current }, null, 2);
239
+ }
240
+ if (args.action === "decide") {
241
+ if (args.findingId === void 0 || args.decision === void 0) {
242
+ return JSON.stringify({ error: "findingId and decision required" });
243
+ }
244
+ session.decisions.push({
245
+ findingId: args.findingId,
246
+ decision: args.decision,
247
+ reason: args.reason
248
+ });
249
+ return JSON.stringify({ sessionId: session.sessionId, decisions: session.decisions }, null, 2);
250
+ }
251
+ if (args.action === "end") {
252
+ const summary = session;
253
+ state.session = null;
254
+ return JSON.stringify({ summary }, null, 2);
255
+ }
256
+ return JSON.stringify({ error: "unknown action" });
257
+ }
258
+ });
259
+ }
260
+
261
+ // src/plugin/tools/review-store.ts
262
+ import { mkdir, writeFile } from "fs/promises";
263
+ import { join as join3 } from "path";
264
+ import { randomUUID as randomUUID2 } from "crypto";
265
+ import { tool as tool6 } from "@opencode-ai/plugin";
266
+ var sessions = /* @__PURE__ */ new Map();
267
+ function createReviewStoreTool(ctx) {
268
+ return tool6({
269
+ description: "Create and persist SDLC review artifacts under .opencode/reviews.",
270
+ args: {
271
+ action: tool6.schema.enum(["start", "write", "end"]),
272
+ reviewId: tool6.schema.string().optional(),
273
+ issueId: tool6.schema.string().optional(),
274
+ filename: tool6.schema.string().optional(),
275
+ content: tool6.schema.any().optional()
276
+ },
277
+ execute: async (args) => {
278
+ const reviewsRoot = join3(ctx.directory, ".opencode", "reviews");
279
+ await mkdir(reviewsRoot, { recursive: true });
280
+ if (args.action === "start") {
281
+ const id = randomUUID2();
282
+ const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
283
+ const suffix = args.issueId !== void 0 && args.issueId !== "" ? `-${args.issueId}` : "";
284
+ const folder = join3(reviewsRoot, `${timestamp}${suffix}`);
285
+ await mkdir(folder, { recursive: true });
286
+ const session2 = {
287
+ id,
288
+ folder,
289
+ createdAt: (/* @__PURE__ */ new Date()).toISOString()
290
+ };
291
+ sessions.set(id, session2);
292
+ return JSON.stringify({ reviewId: id, folder }, null, 2);
293
+ }
294
+ if (args.action !== "write" && args.action !== "end") {
295
+ return JSON.stringify({ error: "unknown action" });
296
+ }
297
+ const reviewId = args.reviewId;
298
+ if (reviewId === void 0 || !sessions.has(reviewId)) {
299
+ return JSON.stringify({ error: "review session not found" });
300
+ }
301
+ const session = sessions.get(reviewId);
302
+ if (!session) {
303
+ return JSON.stringify({ error: "review session missing" });
304
+ }
305
+ if (args.action === "write") {
306
+ if (args.filename === void 0) {
307
+ return JSON.stringify({ error: "filename required" });
308
+ }
309
+ const content = typeof args.content === "string" ? args.content : JSON.stringify(args.content ?? {}, null, 2);
310
+ const filePath = join3(session.folder, args.filename);
311
+ await writeFile(filePath, content, "utf-8");
312
+ return JSON.stringify({ reviewId: session.id, path: filePath }, null, 2);
313
+ }
314
+ if (args.action === "end") {
315
+ sessions.delete(session.id);
316
+ return JSON.stringify({ reviewId: session.id, folder: session.folder, closed: true }, null, 2);
317
+ }
318
+ return JSON.stringify({ error: "unknown action" });
319
+ }
320
+ });
321
+ }
322
+
323
+ // src/plugin/tools/index.ts
324
+ function createTools(ctx, tracker, config) {
325
+ return {
326
+ sdlc_get_context: createGetContextTool(ctx, config),
327
+ sdlc_get_state: createGetStateTool(tracker),
328
+ sdlc_update_state: createUpdateStateTool(tracker),
329
+ sdlc_load_skill: createLoadSkillTool(ctx),
330
+ sdlc_party_review: createPartyReviewTool(),
331
+ sdlc_review_store: createReviewStoreTool(ctx)
332
+ };
333
+ }
334
+
335
+ // src/plugin/state/sdlc-tracker.ts
336
+ import { existsSync as existsSync2 } from "fs";
337
+ import { mkdir as mkdir2, readFile as readFile2, writeFile as writeFile2 } from "fs/promises";
338
+ import { join as join5 } from "path";
339
+
340
+ // src/shared/constants.ts
341
+ import { homedir } from "os";
342
+ import { join as join4 } from "path";
343
+ var GLOBAL_CONFIG_DIR = join4(homedir(), ".config", "opencode");
344
+ var CONFIG_FILE_NAME = "sdlc.json";
345
+ var STATE_FILE_NAME = "sdlc-state.json";
346
+ var OPENCODE_CONFIG_NAME = "opencode.json";
347
+ var OMO_CONFIG_NAME = "oh-my-opencode.json";
348
+ var COMMAND_DIR_NAME = "command";
349
+ var CONFIG_PATHS = {
350
+ globalConfigDir: GLOBAL_CONFIG_DIR,
351
+ globalSdlcConfig: join4(GLOBAL_CONFIG_DIR, CONFIG_FILE_NAME),
352
+ globalOpencodeConfig: join4(GLOBAL_CONFIG_DIR, OPENCODE_CONFIG_NAME),
353
+ globalOhMyOpencodeConfig: join4(GLOBAL_CONFIG_DIR, OMO_CONFIG_NAME),
354
+ commandsDir: join4(GLOBAL_CONFIG_DIR, COMMAND_DIR_NAME)
355
+ };
356
+
357
+ // src/plugin/state/sdlc-tracker.ts
358
+ var SdlcTracker = class {
359
+ constructor(directory) {
360
+ this.directory = directory;
361
+ }
362
+ state = {
363
+ currentPhase: "idle",
364
+ lastUpdated: (/* @__PURE__ */ new Date()).toISOString()
365
+ };
366
+ async initialize() {
367
+ const statePath = join5(this.directory, ".opencode", STATE_FILE_NAME);
368
+ if (existsSync2(statePath)) {
369
+ const raw = await readFile2(statePath, "utf-8");
370
+ this.state = JSON.parse(raw);
371
+ } else {
372
+ await this.persist();
373
+ }
374
+ }
375
+ getState() {
376
+ return this.state;
377
+ }
378
+ updateState(patch) {
379
+ this.state = {
380
+ ...this.state,
381
+ ...patch,
382
+ lastUpdated: (/* @__PURE__ */ new Date()).toISOString()
383
+ };
384
+ return this.state;
385
+ }
386
+ async persist() {
387
+ const stateDir = join5(this.directory, ".opencode");
388
+ const statePath = join5(stateDir, STATE_FILE_NAME);
389
+ if (!existsSync2(stateDir)) {
390
+ await mkdir2(stateDir, { recursive: true });
391
+ }
392
+ await writeFile2(statePath, JSON.stringify(this.state, null, 2));
393
+ }
394
+ };
395
+
396
+ // src/plugin/utils/config-loader.ts
397
+ import { existsSync as existsSync3, readFileSync } from "fs";
398
+ import { join as join6 } from "path";
399
+
400
+ // src/shared/schemas.ts
401
+ import { z } from "zod";
402
+ var languageConfigSchema = z.object({
403
+ name: z.string().min(1),
404
+ testPatterns: z.array(z.string()).min(1),
405
+ productionPatterns: z.array(z.string()).min(1),
406
+ typePatterns: z.array(z.string()).min(1)
407
+ });
408
+ var sdlcConfigSchema = z.object({
409
+ version: z.string(),
410
+ mode: z.enum(["event-modeling", "traditional"]),
411
+ git: z.object({
412
+ workflow: z.enum(["git-spice", "standard"]),
413
+ worktrees: z.boolean(),
414
+ requireClean: z.boolean()
415
+ }),
416
+ features: z.object({
417
+ atomicDesign: z.boolean(),
418
+ gitSpice: z.boolean()
419
+ }),
420
+ github: z.object({
421
+ owner: z.string().optional(),
422
+ project: z.number().optional()
423
+ }),
424
+ languages: z.array(languageConfigSchema).min(1)
425
+ });
426
+
427
+ // src/plugin/utils/config-loader.ts
428
+ function loadSdlcConfig(directory) {
429
+ const localPath = join6(directory, ".opencode", CONFIG_FILE_NAME);
430
+ const globalPath = join6(CONFIG_PATHS.globalConfigDir, CONFIG_FILE_NAME);
431
+ const configPath = existsSync3(localPath) ? localPath : globalPath;
432
+ if (!existsSync3(configPath)) {
433
+ return {
434
+ version: "0.0.0",
435
+ mode: "event-modeling",
436
+ git: { workflow: "standard", worktrees: false, requireClean: false },
437
+ features: { atomicDesign: true, gitSpice: false },
438
+ github: {},
439
+ languages: [
440
+ {
441
+ name: "typescript",
442
+ testPatterns: ["**/*.test.ts", "**/*.spec.ts"],
443
+ productionPatterns: ["src/**/*.ts"],
444
+ typePatterns: ["src/**/*types.ts", "src/**/*types/*.ts"]
445
+ }
446
+ ]
447
+ };
448
+ }
449
+ const raw = readFileSync(configPath, "utf-8");
450
+ const parsed = JSON.parse(raw);
451
+ return sdlcConfigSchema.parse(parsed);
452
+ }
453
+
454
+ // src/plugin/index.ts
455
+ var SdlcPlugin = async (ctx) => {
456
+ const config = loadSdlcConfig(ctx.directory);
457
+ const tracker = new SdlcTracker(ctx.directory);
458
+ await tracker.initialize();
459
+ const tools = createTools(ctx, tracker, config);
460
+ const sessionHooks = createSessionHooks(tracker);
461
+ const toolHooks = createToolHooks(tracker, config);
462
+ const compactionHook = createCompactionHook(tracker);
463
+ return {
464
+ tool: tools,
465
+ event: sessionHooks,
466
+ "tool.execute.before": toolHooks.before,
467
+ "tool.execute.after": toolHooks.after,
468
+ "experimental.session.compacting": compactionHook
469
+ };
470
+ };
471
+ var plugin_default = SdlcPlugin;
472
+ export {
473
+ SdlcPlugin,
474
+ plugin_default as default
475
+ };
476
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/plugin/hooks/session-hooks.ts","../../src/plugin/utils/file-patterns.ts","../../src/plugin/hooks/tool-hooks.ts","../../src/plugin/hooks/compaction-hook.ts","../../src/plugin/tools/get-context.ts","../../src/plugin/tools/get-state.ts","../../src/plugin/tools/update-state.ts","../../src/plugin/tools/load-skill.ts","../../src/plugin/utils/package-paths.ts","../../src/plugin/tools/party-review.ts","../../src/plugin/tools/review-store.ts","../../src/plugin/tools/index.ts","../../src/plugin/state/sdlc-tracker.ts","../../src/shared/constants.ts","../../src/plugin/utils/config-loader.ts","../../src/shared/schemas.ts","../../src/plugin/index.ts"],"sourcesContent":["import type { SdlcTracker } from \"../state/sdlc-tracker.js\";\n\ninterface SessionEvent {\n type?: string;\n}\n\nexport function createSessionHooks(_tracker: SdlcTracker): ({ event }: { event: SessionEvent }) => Promise<void> {\n return ({ event }: { event: SessionEvent }): Promise<void> => {\n if (event.type === \"session.created\") {\n return Promise.resolve();\n }\n if (event.type === \"session.idle\") {\n return Promise.resolve();\n }\n return Promise.resolve();\n };\n}\n","import picomatch from \"picomatch\";\n\nexport function matchesAnyPattern(filePath: string, patterns: string[]): boolean {\n if (patterns.length === 0) return false;\n const matcher = picomatch(patterns, { dot: true });\n return matcher(filePath);\n}\n","import type { SdlcConfig } from \"../../shared/types.js\";\nimport type { SdlcTracker } from \"../state/sdlc-tracker.js\";\nimport { matchesAnyPattern } from \"../utils/file-patterns.js\";\n\ninterface BeforeHookInput {\n tool: string;\n sessionID: string;\n callID: string;\n}\n\ninterface BeforeHookOutput {\n args: unknown;\n}\n\ninterface AfterHookInput {\n tool: string;\n sessionID: string;\n callID: string;\n}\n\ninterface AfterHookOutput {\n title: string;\n output: string;\n metadata: unknown;\n}\n\ninterface EditArgs {\n filePath?: string;\n}\n\ninterface WriteArgs {\n filePath?: string;\n}\n\ninterface UpdateStateArgs {\n currentPhase?: \"idle\" | \"red\" | \"domain-after-red\" | \"green\" | \"domain-after-green\";\n}\n\nconst VALID_TRANSITIONS: Record<string, string[]> = {\n idle: [\"red\"],\n red: [\"domain-after-red\"],\n \"domain-after-red\": [\"green\"],\n green: [\"domain-after-green\"],\n \"domain-after-green\": [\"red\", \"idle\"],\n};\n\nexport function createToolHooks(tracker: SdlcTracker, config: SdlcConfig): {\n before: (input: BeforeHookInput, output: BeforeHookOutput) => Promise<void>;\n after: (input: AfterHookInput, output: AfterHookOutput) => Promise<void>;\n} {\n return {\n before: async (input: BeforeHookInput, output: BeforeHookOutput): Promise<void> => {\n if (input.tool === \"sdlc_update_state\") {\n const args = output.args as UpdateStateArgs;\n if (args.currentPhase) {\n const current = tracker.getState().currentPhase;\n const allowed = VALID_TRANSITIONS[current] ?? [];\n if (!allowed.includes(args.currentPhase)) {\n throw new Error(\n `Invalid TDD transition: ${current} -> ${args.currentPhase}. ` +\n `Allowed transitions: ${allowed.join(\", \")}. ` +\n `Follow RED → DOMAIN → GREEN → DOMAIN → REFACTOR.`\n );\n }\n }\n }\n\n if (input.tool === \"edit\" || input.tool === \"write\") {\n const state = tracker.getState();\n const args = output.args as EditArgs | WriteArgs;\n const filePath = args.filePath ?? \"\";\n if (filePath.length === 0) return;\n\n const allowedPatterns = getAllowedPatterns(config, state.currentPhase);\n\n if (allowedPatterns.length > 0 && !matchesAnyPattern(filePath, allowedPatterns)) {\n throw new Error(\n `File ownership violation in phase '${state.currentPhase}'. ` +\n `Allowed patterns: ${allowedPatterns.join(\", \")}. ` +\n `Attempted: ${filePath}. Delegate to the correct agent.`\n );\n }\n }\n },\n\n after: async (_input: AfterHookInput, _output: AfterHookOutput): Promise<void> => {\n return;\n },\n };\n}\n\nfunction getAllowedPatterns(\n config: SdlcConfig,\n phase: \"idle\" | \"red\" | \"domain-after-red\" | \"green\" | \"domain-after-green\"\n): string[] {\n const patterns = config.languages.flatMap((language) => {\n if (phase === \"red\") return language.testPatterns;\n if (phase === \"green\") return language.productionPatterns;\n if (phase === \"domain-after-red\" || phase === \"domain-after-green\") return language.typePatterns;\n return [];\n });\n return patterns.filter(Boolean);\n}\n","import type { SdlcTracker } from \"../state/sdlc-tracker.js\";\n\nexport function createCompactionHook(tracker: SdlcTracker): () => Promise<void> {\n return async () => {\n await tracker.persist();\n };\n}\n","import type { PluginInput, ToolDefinition } from \"@opencode-ai/plugin\";\nimport { tool } from \"@opencode-ai/plugin\";\nimport type { SdlcConfig } from \"../../shared/types.js\";\n\nexport function createGetContextTool(ctx: PluginInput, config: SdlcConfig): ToolDefinition {\n return tool({\n description: \"Get SDLC plugin context and config.\",\n args: {},\n execute: () => {\n return Promise.resolve(\n JSON.stringify(\n {\n root: ctx.directory,\n config,\n },\n null,\n 2\n )\n );\n },\n });\n}\n","import { tool } from \"@opencode-ai/plugin\";\nimport type { ToolDefinition } from \"@opencode-ai/plugin\";\nimport type { SdlcTracker } from \"../state/sdlc-tracker.js\";\n\nexport function createGetStateTool(tracker: SdlcTracker): ToolDefinition {\n return tool({\n description: \"Get the current SDLC TDD state.\",\n args: {},\n execute: () => {\n return Promise.resolve(JSON.stringify(tracker.getState(), null, 2));\n },\n });\n}\n","import { tool, type ToolDefinition } from \"@opencode-ai/plugin\";\nimport type { SdlcTracker } from \"../state/sdlc-tracker.js\";\nimport type { SdlcState } from \"../../shared/types.js\";\n\nexport function createUpdateStateTool(tracker: SdlcTracker): ToolDefinition {\n return tool({\n description: \"Update SDLC TDD state.\",\n args: {\n currentPhase: tool.schema\n .enum([\"idle\", \"red\", \"domain-after-red\", \"green\", \"domain-after-green\"])\n .optional(),\n currentIssue: tool.schema.string().optional(),\n currentTest: tool.schema.string().optional(),\n currentTestFile: tool.schema.string().optional(),\n },\n execute: async (args: Partial<SdlcState>) => {\n tracker.updateState(args);\n await tracker.persist();\n return JSON.stringify(tracker.getState(), null, 2);\n },\n });\n}\n","import { readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport type { PluginInput, ToolDefinition } from \"@opencode-ai/plugin\";\nimport { tool } from \"@opencode-ai/plugin\";\nimport { getPluginSkillsDir } from \"../utils/package-paths.js\";\n\nexport function createLoadSkillTool(ctx: PluginInput): ToolDefinition {\n return tool({\n description: \"Load SDLC skill markdown by name.\",\n args: {\n skills: tool.schema.array(tool.schema.string()).min(1),\n },\n execute: async ({ skills }: { skills: string[] }) => {\n const skillContents: Record<string, string> = {};\n const pluginSkillsDir = getPluginSkillsDir();\n const localDir = join(ctx.directory, \"skills\");\n\n for (const skill of skills) {\n const fileName = `${skill}.md`;\n const candidatePaths = [join(localDir, fileName), join(pluginSkillsDir, fileName)];\n let content = \"\";\n for (const path of candidatePaths) {\n try {\n content = await readFile(path, \"utf-8\");\n break;\n } catch {\n continue;\n }\n }\n if (!content) {\n content = `Skill not found: ${skill}`;\n }\n skillContents[skill] = content;\n }\n\n return JSON.stringify(skillContents, null, 2);\n },\n });\n}\n","import { existsSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\nexport function getPackageRoot(): string {\n const currentFileDir = dirname(fileURLToPath(import.meta.url));\n\n const bundledRoot = join(currentFileDir, \"..\", \"..\", \"..\");\n if (existsSync(join(bundledRoot, \"package.json\"))) {\n return bundledRoot;\n }\n\n const devRoot = join(currentFileDir, \"..\", \"..\", \"..\", \"..\");\n if (existsSync(join(devRoot, \"package.json\"))) {\n return devRoot;\n }\n\n return bundledRoot;\n}\n\nexport function getPluginSkillsDir(): string {\n return join(getPackageRoot(), \"skills\");\n}\n","import { randomUUID } from \"node:crypto\";\nimport { tool, type ToolDefinition } from \"@opencode-ai/plugin\";\nimport type { PartyReviewSession, PartyReviewFinding } from \"../../shared/types.js\";\n\ninterface PartyReviewState {\n session: PartyReviewSession | null;\n}\n\nconst state: PartyReviewState = { session: null };\n\nexport function createPartyReviewTool(): ToolDefinition {\n return tool({\n description: \"Run SDLC party review discussion for findings.\",\n args: {\n action: tool.schema.enum([\"start\", \"next\", \"decide\", \"end\"]),\n findings: tool.schema\n .array(\n tool.schema.object({\n id: tool.schema.string(),\n title: tool.schema.string(),\n severity: tool.schema.enum([\"high\", \"medium\", \"low\"]),\n category: tool.schema.enum([\"logic\", \"security\", \"performance\", \"ux\", \"testing\", \"domain\"]),\n })\n )\n .optional(),\n sessionId: tool.schema.string().optional(),\n findingId: tool.schema.string().optional(),\n decision: tool.schema.enum([\"accept\", \"defer\", \"reject\"]).optional(),\n reason: tool.schema.string().optional(),\n },\n execute: async (args: {\n action: \"start\" | \"next\" | \"decide\" | \"end\";\n findings?: PartyReviewFinding[];\n sessionId?: string;\n findingId?: string;\n decision?: \"accept\" | \"defer\" | \"reject\";\n reason?: string;\n }) => {\n if (args.action === \"start\") {\n const findings = args.findings;\n if (!findings || findings.length === 0) {\n return JSON.stringify({ error: \"findings required\" });\n }\n const sessionId = randomUUID();\n state.session = {\n sessionId,\n findings,\n currentIndex: 0,\n decisions: [],\n };\n return JSON.stringify({ sessionId, current: findings[0] }, null, 2);\n }\n\n const session = state.session;\n if (!session || (args.sessionId !== undefined && args.sessionId !== session.sessionId)) {\n return JSON.stringify({ error: \"session not found\" });\n }\n\n if (args.action === \"next\") {\n const nextIndex = session.currentIndex + 1;\n if (nextIndex >= session.findings.length) {\n return JSON.stringify({ sessionId: session.sessionId, current: null }, null, 2);\n }\n session.currentIndex = nextIndex;\n const current = session.findings[session.currentIndex];\n return JSON.stringify({ sessionId: session.sessionId, current }, null, 2);\n }\n\n if (args.action === \"decide\") {\n if (args.findingId === undefined || args.decision === undefined) {\n return JSON.stringify({ error: \"findingId and decision required\" });\n }\n session.decisions.push({\n findingId: args.findingId,\n decision: args.decision,\n reason: args.reason,\n });\n return JSON.stringify({ sessionId: session.sessionId, decisions: session.decisions }, null, 2);\n }\n\n if (args.action === \"end\") {\n const summary = session;\n state.session = null;\n return JSON.stringify({ summary }, null, 2);\n }\n\n return JSON.stringify({ error: \"unknown action\" });\n },\n });\n}\n","import { mkdir, writeFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { randomUUID } from \"node:crypto\";\nimport type { PluginInput, ToolDefinition } from \"@opencode-ai/plugin\";\nimport { tool } from \"@opencode-ai/plugin\";\n\ninterface ReviewSession {\n id: string;\n folder: string;\n createdAt: string;\n}\n\nconst sessions = new Map<string, ReviewSession>();\n\nexport function createReviewStoreTool(ctx: PluginInput): ToolDefinition {\n return tool({\n description: \"Create and persist SDLC review artifacts under .opencode/reviews.\",\n args: {\n action: tool.schema.enum([\"start\", \"write\", \"end\"]),\n reviewId: tool.schema.string().optional(),\n issueId: tool.schema.string().optional(),\n filename: tool.schema.string().optional(),\n content: tool.schema.any().optional(),\n },\n execute: async (args: {\n action: \"start\" | \"write\" | \"end\";\n reviewId?: string;\n issueId?: string;\n filename?: string;\n content?: unknown;\n }) => {\n const reviewsRoot = join(ctx.directory, \".opencode\", \"reviews\");\n await mkdir(reviewsRoot, { recursive: true });\n\n if (args.action === \"start\") {\n const id = randomUUID();\n const timestamp = new Date().toISOString().replace(/[:.]/g, \"-\");\n const suffix = args.issueId !== undefined && args.issueId !== \"\" ? `-${args.issueId}` : \"\";\n const folder = join(reviewsRoot, `${timestamp}${suffix}`);\n await mkdir(folder, { recursive: true });\n const session: ReviewSession = {\n id,\n folder,\n createdAt: new Date().toISOString(),\n };\n sessions.set(id, session);\n return JSON.stringify({ reviewId: id, folder }, null, 2);\n }\n\n if (args.action !== \"write\" && args.action !== \"end\") {\n return JSON.stringify({ error: \"unknown action\" });\n }\n\n const reviewId = args.reviewId;\n if (reviewId === undefined || !sessions.has(reviewId)) {\n return JSON.stringify({ error: \"review session not found\" });\n }\n\n const session = sessions.get(reviewId);\n if (!session) {\n return JSON.stringify({ error: \"review session missing\" });\n }\n\n if (args.action === \"write\") {\n if (args.filename === undefined) {\n return JSON.stringify({ error: \"filename required\" });\n }\n const content =\n typeof args.content === \"string\" ? args.content : JSON.stringify(args.content ?? {}, null, 2);\n const filePath = join(session.folder, args.filename);\n await writeFile(filePath, content, \"utf-8\");\n return JSON.stringify({ reviewId: session.id, path: filePath }, null, 2);\n }\n\n if (args.action === \"end\") {\n sessions.delete(session.id);\n return JSON.stringify({ reviewId: session.id, folder: session.folder, closed: true }, null, 2);\n }\n\n return JSON.stringify({ error: \"unknown action\" });\n },\n });\n}\n","import type { PluginInput, ToolDefinition } from \"@opencode-ai/plugin\";\nimport type { SdlcConfig } from \"../../shared/types.js\";\nimport type { SdlcTracker } from \"../state/sdlc-tracker.js\";\nimport { createGetContextTool } from \"./get-context.js\";\nimport { createGetStateTool } from \"./get-state.js\";\nimport { createUpdateStateTool } from \"./update-state.js\";\nimport { createLoadSkillTool } from \"./load-skill.js\";\nimport { createPartyReviewTool } from \"./party-review.js\";\nimport { createReviewStoreTool } from \"./review-store.js\";\n\nexport function createTools(\n ctx: PluginInput,\n tracker: SdlcTracker,\n config: SdlcConfig\n): Record<string, ToolDefinition> {\n return {\n sdlc_get_context: createGetContextTool(ctx, config),\n sdlc_get_state: createGetStateTool(tracker),\n sdlc_update_state: createUpdateStateTool(tracker),\n sdlc_load_skill: createLoadSkillTool(ctx),\n sdlc_party_review: createPartyReviewTool(),\n sdlc_review_store: createReviewStoreTool(ctx),\n };\n}\n","import { existsSync } from \"node:fs\";\nimport { mkdir, readFile, writeFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { STATE_FILE_NAME } from \"../../shared/constants.js\";\nimport type { SdlcState } from \"../../shared/types.js\";\n\nexport class SdlcTracker {\n private state: SdlcState = {\n currentPhase: \"idle\",\n lastUpdated: new Date().toISOString(),\n };\n\n constructor(private directory: string) {}\n\n async initialize(): Promise<void> {\n const statePath = join(this.directory, \".opencode\", STATE_FILE_NAME);\n if (existsSync(statePath)) {\n const raw = await readFile(statePath, \"utf-8\");\n this.state = JSON.parse(raw) as SdlcState;\n } else {\n await this.persist();\n }\n }\n\n getState(): SdlcState {\n return this.state;\n }\n\n updateState(patch: Partial<SdlcState>): SdlcState {\n this.state = {\n ...this.state,\n ...patch,\n lastUpdated: new Date().toISOString(),\n };\n return this.state;\n }\n\n async persist(): Promise<void> {\n const stateDir = join(this.directory, \".opencode\");\n const statePath = join(stateDir, STATE_FILE_NAME);\n if (!existsSync(stateDir)) {\n await mkdir(stateDir, { recursive: true });\n }\n await writeFile(statePath, JSON.stringify(this.state, null, 2));\n }\n}\n","import { homedir } from \"node:os\";\nimport { join } from \"node:path\";\n\nexport const VERSION = \"0.1.0\";\nexport const DISPLAY_NAME = \"OpenCode SDLC Plugin\";\nexport const TAGLINE = \"Agentic SDLC workflow with discovery, ADRs, and TDD\";\n\nexport const PACKAGE_NAME = \"sdlc-plugin\";\n\nexport const GLOBAL_CONFIG_DIR = join(homedir(), \".config\", \"opencode\");\nexport const LOCAL_CONFIG_DIR_NAME = \".opencode\";\n\nexport const CONFIG_FILE_NAME = \"sdlc.json\";\nexport const STATE_FILE_NAME = \"sdlc-state.json\";\nexport const OPENCODE_CONFIG_NAME = \"opencode.json\";\nexport const OMO_CONFIG_NAME = \"oh-my-opencode.json\";\nexport const COMMAND_DIR_NAME = \"command\";\n\nexport const DEFAULT_AGENT_MODEL = \"anthropic/claude-sonnet-4-5-thinking\";\n\nexport const CONFIG_PATHS = {\n globalConfigDir: GLOBAL_CONFIG_DIR,\n globalSdlcConfig: join(GLOBAL_CONFIG_DIR, CONFIG_FILE_NAME),\n globalOpencodeConfig: join(GLOBAL_CONFIG_DIR, OPENCODE_CONFIG_NAME),\n globalOhMyOpencodeConfig: join(GLOBAL_CONFIG_DIR, OMO_CONFIG_NAME),\n commandsDir: join(GLOBAL_CONFIG_DIR, COMMAND_DIR_NAME),\n};\n","import { existsSync, readFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { CONFIG_FILE_NAME, CONFIG_PATHS } from \"../../shared/constants.js\";\nimport { sdlcConfigSchema } from \"../../shared/schemas.js\";\nimport type { SdlcConfig } from \"../../shared/types.js\";\n\nexport function loadSdlcConfig(directory: string): SdlcConfig {\n const localPath = join(directory, \".opencode\", CONFIG_FILE_NAME);\n const globalPath = join(CONFIG_PATHS.globalConfigDir, CONFIG_FILE_NAME);\n\n const configPath = existsSync(localPath) ? localPath : globalPath;\n\n if (!existsSync(configPath)) {\n return {\n version: \"0.0.0\",\n mode: \"event-modeling\",\n git: { workflow: \"standard\", worktrees: false, requireClean: false },\n features: { atomicDesign: true, gitSpice: false },\n github: {},\n languages: [\n {\n name: \"typescript\",\n testPatterns: [\"**/*.test.ts\", \"**/*.spec.ts\"],\n productionPatterns: [\"src/**/*.ts\"],\n typePatterns: [\"src/**/*types.ts\", \"src/**/*types/*.ts\"],\n },\n ],\n };\n }\n\n const raw = readFileSync(configPath, \"utf-8\");\n const parsed = JSON.parse(raw) as SdlcConfig;\n return sdlcConfigSchema.parse(parsed);\n}\n","import { z } from \"zod\";\n\nexport const languageConfigSchema = z.object({\n name: z.string().min(1),\n testPatterns: z.array(z.string()).min(1),\n productionPatterns: z.array(z.string()).min(1),\n typePatterns: z.array(z.string()).min(1),\n});\n\nexport const sdlcConfigSchema = z.object({\n version: z.string(),\n mode: z.enum([\"event-modeling\", \"traditional\"]),\n git: z.object({\n workflow: z.enum([\"git-spice\", \"standard\"]),\n worktrees: z.boolean(),\n requireClean: z.boolean(),\n }),\n features: z.object({\n atomicDesign: z.boolean(),\n gitSpice: z.boolean(),\n }),\n github: z.object({\n owner: z.string().optional(),\n project: z.number().optional(),\n }),\n languages: z.array(languageConfigSchema).min(1),\n});\n\nexport type SdlcConfigSchema = z.infer<typeof sdlcConfigSchema>;\n","import type { Plugin } from \"@opencode-ai/plugin\";\nimport { createSessionHooks } from \"./hooks/session-hooks.js\";\nimport { createToolHooks } from \"./hooks/tool-hooks.js\";\nimport { createCompactionHook } from \"./hooks/compaction-hook.js\";\nimport { createTools } from \"./tools/index.js\";\nimport { SdlcTracker } from \"./state/sdlc-tracker.js\";\nimport { loadSdlcConfig } from \"./utils/config-loader.js\";\n\nexport const SdlcPlugin: Plugin = async (ctx) => {\n const config = loadSdlcConfig(ctx.directory);\n const tracker = new SdlcTracker(ctx.directory);\n await tracker.initialize();\n\n const tools = createTools(ctx, tracker, config);\n const sessionHooks = createSessionHooks(tracker);\n const toolHooks = createToolHooks(tracker, config);\n const compactionHook = createCompactionHook(tracker);\n\n return {\n tool: tools,\n event: sessionHooks,\n \"tool.execute.before\": toolHooks.before,\n \"tool.execute.after\": toolHooks.after,\n \"experimental.session.compacting\": compactionHook,\n };\n};\n\nexport default SdlcPlugin;\n"],"mappings":"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","names":["state","tool","tool","join","tool","tool","join","tool","join","randomUUID","tool","session","existsSync","mkdir","readFile","writeFile","join","join","join","join","join","existsSync","readFile","mkdir","writeFile","existsSync","join","join","existsSync"]}