opencode-sdlc-plugin 0.1.0 → 0.2.1
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.
- package/README.md +1 -1
- package/dist/cli/index.js +31 -9
- package/dist/cli/index.js.map +1 -1
- package/dist/index.js +27 -25
- package/dist/index.js.map +1 -1
- package/dist/plugin/index.js +27 -25
- package/dist/plugin/index.js.map +1 -1
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@ An OpenCode plugin that enforces an event-modeling SDLC workflow: discovery →
|
|
|
4
4
|
|
|
5
5
|
## What This Plugin Provides
|
|
6
6
|
|
|
7
|
-
- **CLI installer** (`opencode-sdlc-plugin install`) that configures OpenCode, oh-my-opencode agents, and SDLC config.
|
|
7
|
+
- **CLI installer** (`opencode-sdlc-plugin install`) that configures OpenCode, oh-my-opencode agents, and SDLC config (auto-installs oh-my-opencode if missing).
|
|
8
8
|
- **OpenCode plugin tools** for context, state tracking, skills, party review, and review persistence.
|
|
9
9
|
- **Commands** (`/sdlc-*`) that encode your SDLC workflow.
|
|
10
10
|
- **Skills** for orchestration, TDD constraints, debugging, memory, event modeling, and ADR policy.
|
package/dist/cli/index.js
CHANGED
|
@@ -7,7 +7,7 @@ import kleur5 from "kleur";
|
|
|
7
7
|
// src/shared/constants.ts
|
|
8
8
|
import { homedir } from "os";
|
|
9
9
|
import { join } from "path";
|
|
10
|
-
var VERSION = "0.1
|
|
10
|
+
var VERSION = "0.2.1";
|
|
11
11
|
var DISPLAY_NAME = "OpenCode SDLC Plugin";
|
|
12
12
|
var TAGLINE = "Agentic SDLC workflow with discovery, ADRs, and TDD";
|
|
13
13
|
var GLOBAL_CONFIG_DIR = join(homedir(), ".config", "opencode");
|
|
@@ -27,6 +27,7 @@ var CONFIG_PATHS = {
|
|
|
27
27
|
// src/cli/commands/install.ts
|
|
28
28
|
import kleur2 from "kleur";
|
|
29
29
|
import ora from "ora";
|
|
30
|
+
import { join as join6 } from "path";
|
|
30
31
|
|
|
31
32
|
// src/cli/questions/install-prompts.ts
|
|
32
33
|
import { confirm, input, select } from "@inquirer/prompts";
|
|
@@ -311,7 +312,7 @@ function generateOhMyOpencodeConfig(answers, configDir) {
|
|
|
311
312
|
// src/cli/generators/opencode-config.ts
|
|
312
313
|
import { existsSync as existsSync2, readFileSync as readFileSync2 } from "fs";
|
|
313
314
|
import { join as join3 } from "path";
|
|
314
|
-
var REQUIRED_PLUGINS = ["sdlc-plugin/plugin", "oh-my-opencode"];
|
|
315
|
+
var REQUIRED_PLUGINS = ["opencode-sdlc-plugin/plugin", "oh-my-opencode"];
|
|
315
316
|
function generateOpencodeConfig(answers, configDir) {
|
|
316
317
|
const configPath = join3(configDir, "opencode.json");
|
|
317
318
|
const existing = existsSync2(configPath) ? JSON.parse(readFileSync2(configPath, "utf-8")) : {};
|
|
@@ -329,7 +330,7 @@ function generateOpencodeConfig(answers, configDir) {
|
|
|
329
330
|
};
|
|
330
331
|
}
|
|
331
332
|
function getRequiredPlugins(answers) {
|
|
332
|
-
const packages = ["sdlc-plugin", "oh-my-opencode"];
|
|
333
|
+
const packages = ["opencode-sdlc-plugin", "oh-my-opencode"];
|
|
333
334
|
if (answers.subscriptions.hasGoogle) packages.push("opencode-antigravity-auth");
|
|
334
335
|
if (answers.subscriptions.hasOpenAI) packages.push("opencode-openai-codex-auth");
|
|
335
336
|
return packages;
|
|
@@ -473,6 +474,9 @@ var FileManager = class {
|
|
|
473
474
|
}
|
|
474
475
|
return copiedFiles;
|
|
475
476
|
}
|
|
477
|
+
async installOhMyOpencode() {
|
|
478
|
+
await execAsync("npx -y oh-my-opencode@latest install", { timeout: 12e4 });
|
|
479
|
+
}
|
|
476
480
|
async installGitHubExtensions() {
|
|
477
481
|
const extensions = [
|
|
478
482
|
"jwilger/gh-issue-ext",
|
|
@@ -590,6 +594,9 @@ async function install(options) {
|
|
|
590
594
|
logger.banner();
|
|
591
595
|
const spinner = ora("Checking prerequisites...").start();
|
|
592
596
|
const prereqs = checkPrerequisites();
|
|
597
|
+
let fileManager = new FileManager(
|
|
598
|
+
resolveInstallLocation(options) === "local" ? join6(process.cwd(), ".opencode") : void 0
|
|
599
|
+
);
|
|
593
600
|
if (!prereqs.node.installed) {
|
|
594
601
|
spinner.fail("Node.js not found");
|
|
595
602
|
logger.error("Please install Node.js 20+ first: https://nodejs.org/");
|
|
@@ -601,9 +608,24 @@ async function install(options) {
|
|
|
601
608
|
process.exit(1);
|
|
602
609
|
}
|
|
603
610
|
if (!prereqs.ohMyOpencode.installed) {
|
|
604
|
-
spinner.
|
|
605
|
-
|
|
606
|
-
|
|
611
|
+
spinner.warn("oh-my-opencode not found - installing...");
|
|
612
|
+
const ohMyOpencodeSpinner = ora("Installing oh-my-opencode...").start();
|
|
613
|
+
try {
|
|
614
|
+
await fileManager.installOhMyOpencode();
|
|
615
|
+
const updatedPrereqs = checkPrerequisites();
|
|
616
|
+
if (!updatedPrereqs.ohMyOpencode.installed) {
|
|
617
|
+
ohMyOpencodeSpinner.fail("oh-my-opencode install did not register");
|
|
618
|
+
logger.error("Please install oh-my-opencode manually: https://github.com/khulnasoft/oh-my-opencode");
|
|
619
|
+
process.exit(1);
|
|
620
|
+
}
|
|
621
|
+
ohMyOpencodeSpinner.succeed("oh-my-opencode installed");
|
|
622
|
+
} catch (error) {
|
|
623
|
+
ohMyOpencodeSpinner.fail("Failed to install oh-my-opencode");
|
|
624
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
625
|
+
logger.error(`Installation error: ${message}`);
|
|
626
|
+
logger.error("Please install oh-my-opencode manually: https://github.com/khulnasoft/oh-my-opencode");
|
|
627
|
+
process.exit(1);
|
|
628
|
+
}
|
|
607
629
|
}
|
|
608
630
|
spinner.succeed("Prerequisites checked");
|
|
609
631
|
const subscriptions = await gatherSubscriptions();
|
|
@@ -623,7 +645,7 @@ async function install(options) {
|
|
|
623
645
|
});
|
|
624
646
|
const generator = new ConfigGenerator(answers);
|
|
625
647
|
const files = generator.generate();
|
|
626
|
-
|
|
648
|
+
fileManager = new FileManager(generator.getConfigDir());
|
|
627
649
|
const installSpinner = ora("Writing configuration...").start();
|
|
628
650
|
await fileManager.writeFiles(files);
|
|
629
651
|
installSpinner.succeed("Configuration written");
|
|
@@ -688,12 +710,12 @@ function upgrade(options) {
|
|
|
688
710
|
return;
|
|
689
711
|
}
|
|
690
712
|
logger.warn("Upgrade workflow not implemented yet.");
|
|
691
|
-
logger.info(kleur4.gray("Re-run sdlc-plugin install to regenerate configs."));
|
|
713
|
+
logger.info(kleur4.gray("Re-run opencode-sdlc-plugin install to regenerate configs."));
|
|
692
714
|
}
|
|
693
715
|
|
|
694
716
|
// src/cli/index.ts
|
|
695
717
|
var program = new Command();
|
|
696
|
-
program.name("sdlc-plugin").description(`${kleur5.cyan(DISPLAY_NAME)} - ${TAGLINE}`).version(VERSION);
|
|
718
|
+
program.name("opencode-sdlc-plugin").description(`${kleur5.cyan(DISPLAY_NAME)} - ${TAGLINE}`).version(VERSION);
|
|
697
719
|
program.command("install").description("Install and configure OpenCode SDLC plugin").option("-y, --yes", "Skip confirmation prompts", false).option("--global", "Install globally (default)", true).option("--local", "Install to current project only", false).option("--reconfigure", "Force full reconfiguration", false).action(async (options) => {
|
|
698
720
|
await install(options);
|
|
699
721
|
});
|
package/dist/cli/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/cli/index.ts","../../src/shared/constants.ts","../../src/cli/commands/install.ts","../../src/cli/questions/install-prompts.ts","../../src/cli/generators/config-generator.ts","../../src/cli/generators/sdlc-config.ts","../../src/cli/generators/omo-config.ts","../../src/cli/utils/persona-builder.ts","../../src/cli/generators/opencode-config.ts","../../src/cli/utils/file-manager.ts","../../src/cli/utils/prerequisites.ts","../../src/cli/utils/logger.ts","../../src/cli/commands/doctor.ts","../../src/cli/commands/upgrade.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport { Command } from \"commander\";\nimport kleur from \"kleur\";\nimport { DISPLAY_NAME, TAGLINE, VERSION } from \"../shared/constants.js\";\nimport { install } from \"./commands/install.js\";\nimport { doctor } from \"./commands/doctor.js\";\nimport { upgrade } from \"./commands/upgrade.js\";\n\nconst program = new Command();\n\nprogram\n .name(\"sdlc-plugin\")\n .description(`${kleur.cyan(DISPLAY_NAME)} - ${TAGLINE}`)\n .version(VERSION);\n\nprogram\n .command(\"install\")\n .description(\"Install and configure OpenCode SDLC plugin\")\n .option(\"-y, --yes\", \"Skip confirmation prompts\", false)\n .option(\"--global\", \"Install globally (default)\", true)\n .option(\"--local\", \"Install to current project only\", false)\n .option(\"--reconfigure\", \"Force full reconfiguration\", false)\n .action(async (options: { yes?: boolean; global?: boolean; local?: boolean; reconfigure?: boolean }) => {\n await install(options);\n });\n\nprogram\n .command(\"upgrade\")\n .description(\"Upgrade OpenCode SDLC plugin\")\n .option(\"--check\", \"Check for updates without installing\", false)\n .option(\"-y, --yes\", \"Skip confirmation prompts\", false)\n .action(upgrade);\n\nprogram\n .command(\"doctor\")\n .description(\"Diagnose and fix common setup issues\")\n .option(\"--fix\", \"Attempt to fix detected issues\", false)\n .action(doctor);\n\nprogram.parse();\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 kleur from \"kleur\";\nimport ora from \"ora\";\nimport type { InstallAnswers, InstallLocation } from \"../../shared/types.js\";\nimport { VERSION } from \"../../shared/constants.js\";\nimport {\n compileInstallAnswers,\n gatherGitHub,\n gatherLanguages,\n gatherMethodology,\n gatherModels,\n gatherSubscriptions,\n} from \"../questions/install-prompts.js\";\nimport { ConfigGenerator } from \"../generators/config-generator.js\";\nimport { FileManager } from \"../utils/file-manager.js\";\nimport { checkPrerequisites } from \"../utils/prerequisites.js\";\nimport { logger } from \"../utils/logger.js\";\n\ninterface InstallOptions {\n yes?: boolean;\n global?: boolean;\n local?: boolean;\n reconfigure?: boolean;\n}\n\nfunction resolveInstallLocation(options: InstallOptions): InstallLocation {\n if (options.local === true) return \"local\";\n return \"global\";\n}\n\nexport async function install(options: InstallOptions): Promise<void> {\n logger.banner();\n\n const spinner = ora(\"Checking prerequisites...\").start();\n const prereqs = checkPrerequisites();\n\n if (!prereqs.node.installed) {\n spinner.fail(\"Node.js not found\");\n logger.error(\"Please install Node.js 20+ first: https://nodejs.org/\");\n process.exit(1);\n }\n\n if (!prereqs.opencode.installed) {\n spinner.fail(\"OpenCode not found\");\n logger.error(\"Please install OpenCode first: https://opencode.ai/docs\");\n process.exit(1);\n }\n\n if (!prereqs.ohMyOpencode.installed) {\n spinner.fail(\"oh-my-opencode not found\");\n logger.error(\"Please install oh-my-opencode first: https://github.com/khulnasoft/oh-my-opencode\");\n process.exit(1);\n }\n\n spinner.succeed(\"Prerequisites checked\");\n\n const subscriptions = await gatherSubscriptions();\n const availableModels = prereqs.opencode.models.length > 0 ? prereqs.opencode.models : [\"anthropic/claude-sonnet-4-5-thinking\"];\n const models = await gatherModels(availableModels);\n const methodology = await gatherMethodology();\n const github = await gatherGitHub();\n const languages = await gatherLanguages();\n const installLocation = resolveInstallLocation(options);\n\n const answers: InstallAnswers = compileInstallAnswers({\n subscriptions,\n models,\n methodology,\n github,\n languages,\n installLocation,\n });\n\n const generator = new ConfigGenerator(answers);\n const files = generator.generate();\n\n const fileManager = new FileManager(generator.getConfigDir());\n\n const installSpinner = ora(\"Writing configuration...\").start();\n await fileManager.writeFiles(files);\n installSpinner.succeed(\"Configuration written\");\n\n const dependencySpinner = ora(\"Installing dependencies...\").start();\n const packages = generator.getRequiredPackages();\n await fileManager.installDependencies(packages);\n dependencySpinner.succeed(\"Dependencies installed\");\n\n const commandSpinner = ora(\"Installing commands...\").start();\n const copiedCommands = await fileManager.copyCommands();\n commandSpinner.succeed(`Installed ${copiedCommands.length} commands`);\n\n const ghSpinner = ora(\"Installing GitHub CLI extensions...\").start();\n const ghResult = await fileManager.installGitHubExtensions();\n if (ghResult.failed.length > 0) {\n ghSpinner.warn(\n `GitHub extensions: ${ghResult.installed.length} installed, ` +\n `${ghResult.skipped.length} skipped, ${ghResult.failed.length} failed`\n );\n for (const failure of ghResult.failed) {\n logger.warn(` Failed to install ${failure.name}: ${failure.error}`);\n }\n } else {\n ghSpinner.succeed(\n `GitHub extensions: ${ghResult.installed.length} installed, ${ghResult.skipped.length} already present`\n );\n }\n\n logger.successBanner(`SDLC PLUGIN ${VERSION} INSTALLED`);\n\n logger.info(\"Next steps:\");\n logger.info(kleur.gray(\" 1. Restart OpenCode\"));\n logger.info(kleur.gray(\" 2. Run /sdlc-setup in your project\"));\n logger.info(\"\");\n}\n","import { confirm, input, select } from \"@inquirer/prompts\";\nimport type { GitHubAnswers, InstallAnswers, LanguageConfig, MethodologyAnswers, ModelAnswers, SubscriptionAnswers } from \"../../shared/types.js\";\nimport { DEFAULT_AGENT_MODEL } from \"../../shared/constants.js\";\n\nexport async function gatherSubscriptions(): Promise<SubscriptionAnswers> {\n const hasClaude = await confirm({\n message: \"Do you have a Claude subscription?\",\n default: true,\n });\n const hasOpenAI = await confirm({\n message: \"Do you have an OpenAI subscription?\",\n default: true,\n });\n const hasGoogle = await confirm({\n message: \"Do you have a Google/Gemini subscription?\",\n default: false,\n });\n const hasGitHubCopilot = await confirm({\n message: \"Do you have GitHub Copilot?\",\n default: false,\n });\n\n return { hasClaude, hasOpenAI, hasGoogle, hasGitHubCopilot };\n}\n\nexport async function gatherModels(availableModels: string[]): Promise<ModelAnswers> {\n const modelChoice = async (message: string, defaultModel: string): Promise<string> => {\n const firstModel = availableModels[0];\n if (availableModels.length === 1) {\n return firstModel ?? defaultModel;\n }\n const selection = await select<string>({\n message,\n choices: availableModels.map((id) => ({ name: id, value: id })),\n default: firstModel ?? defaultModel,\n });\n return selection;\n };\n\n return {\n orchestrator: await modelChoice(\"Model for Marvin orchestrator\", DEFAULT_AGENT_MODEL),\n red: await modelChoice(\"Model for RED agent\", DEFAULT_AGENT_MODEL),\n green: await modelChoice(\"Model for GREEN agent\", DEFAULT_AGENT_MODEL),\n domain: await modelChoice(\"Model for DOMAIN agent\", DEFAULT_AGENT_MODEL),\n architect: await modelChoice(\"Model for ARCHITECT agent\", DEFAULT_AGENT_MODEL),\n discovery: await modelChoice(\"Model for DISCOVERY agent\", DEFAULT_AGENT_MODEL),\n exploration: await modelChoice(\"Model for EXPLORATION agent\", DEFAULT_AGENT_MODEL),\n workflowDesigner: await modelChoice(\"Model for WORKFLOW DESIGNER agent\", DEFAULT_AGENT_MODEL),\n gwt: await modelChoice(\"Model for GWT agent\", DEFAULT_AGENT_MODEL),\n modelChecker: await modelChoice(\"Model for MODEL CHECKER agent\", DEFAULT_AGENT_MODEL),\n codeReviewer: await modelChoice(\"Model for CODE REVIEWER agent\", DEFAULT_AGENT_MODEL),\n story: await modelChoice(\"Model for STORY agent\", DEFAULT_AGENT_MODEL),\n ux: await modelChoice(\"Model for UX agent\", DEFAULT_AGENT_MODEL),\n oracle: await modelChoice(\"Model for ORACLE agent\", DEFAULT_AGENT_MODEL),\n adr: await modelChoice(\"Model for ADR agent\", DEFAULT_AGENT_MODEL),\n designFacilitator: await modelChoice(\"Model for DESIGN FACILITATOR agent\", DEFAULT_AGENT_MODEL),\n fileUpdater: await modelChoice(\"Model for FILE UPDATER agent\", DEFAULT_AGENT_MODEL),\n };\n}\n\nexport async function gatherMethodology(): Promise<MethodologyAnswers> {\n const mode = await select<\"event-modeling\" | \"traditional\">({\n message: \"Which SDLC mode?\",\n choices: [\n { name: \"Event modeling\", value: \"event-modeling\" as const },\n { name: \"Traditional (PRD-driven)\", value: \"traditional\" as const },\n ],\n default: \"event-modeling\",\n });\n\n const gitWorkflow = await select<\"git-spice\" | \"standard\">({\n message: \"Preferred git workflow?\",\n choices: [\n { name: \"git-spice\", value: \"git-spice\" as const },\n { name: \"standard\", value: \"standard\" as const },\n ],\n default: \"git-spice\",\n });\n\n const requireClean = await confirm({\n message: \"Require clean working tree before starting work?\",\n default: true,\n });\n\n const worktrees = await confirm({\n message: \"Enable git worktrees for parallel issue work?\",\n default: false,\n });\n\n const atomicDesign = await confirm({\n message: \"Enable Atomic Design guidance for UI work?\",\n default: true,\n });\n\n const gitSpice = await confirm({\n message: \"Enable git-spice stacked PR workflow guidance?\",\n default: false,\n });\n\n return {\n mode,\n gitWorkflow,\n requireClean,\n worktrees,\n atomicDesign,\n gitSpice,\n };\n}\n\nexport async function gatherGitHub(): Promise<GitHubAnswers> {\n const owner = await input({\n message: \"GitHub owner/org (leave blank to skip)\",\n });\n\n const projectRaw = await input({\n message: \"GitHub project number (leave blank to skip)\",\n });\n\n const project = projectRaw ? Number(projectRaw) : undefined;\n\n return {\n owner: owner || undefined,\n project: Number.isFinite(project) ? project : undefined,\n };\n}\n\nexport async function gatherLanguages(): Promise<LanguageConfig[]> {\n const language = await select({\n message: \"Primary language?\",\n choices: [\n { name: \"TypeScript\", value: \"typescript\" },\n { name: \"JavaScript\", value: \"javascript\" },\n { name: \"Python\", value: \"python\" },\n { name: \"Rust\", value: \"rust\" },\n { name: \"Go\", value: \"go\" },\n { name: \"Other\", value: \"other\" },\n ],\n default: \"typescript\",\n });\n\n if (language === \"other\") {\n const name = await input({ message: \"Language name\" });\n const testPatterns = await input({ message: \"Test file glob patterns (comma-separated)\" });\n const productionPatterns = await input({\n message: \"Production code glob patterns (comma-separated)\",\n });\n const typePatterns = await input({ message: \"Domain/type file patterns (comma-separated)\" });\n\n return [\n {\n name: name || \"custom\",\n testPatterns: testPatterns.split(\",\").map((p) => p.trim()).filter(Boolean),\n productionPatterns: productionPatterns.split(\",\").map((p) => p.trim()).filter(Boolean),\n typePatterns: typePatterns.split(\",\").map((p) => p.trim()).filter(Boolean),\n },\n ];\n }\n\n return [getLanguageDefaults(language)];\n}\n\nfunction getLanguageDefaults(language: string): LanguageConfig {\n switch (language) {\n case \"typescript\":\n return {\n name: \"typescript\",\n testPatterns: [\"**/*.test.ts\", \"**/*.spec.ts\"],\n productionPatterns: [\"src/**/*.ts\"],\n typePatterns: [\"src/**/*types.ts\", \"src/**/*types/*.ts\"],\n };\n case \"javascript\":\n return {\n name: \"javascript\",\n testPatterns: [\"**/*.test.js\", \"**/*.spec.js\"],\n productionPatterns: [\"src/**/*.js\"],\n typePatterns: [\"src/**/*types.js\", \"src/**/*types/*.js\"],\n };\n case \"python\":\n return {\n name: \"python\",\n testPatterns: [\"tests/**/*.py\", \"**/test_*.py\"],\n productionPatterns: [\"src/**/*.py\"],\n typePatterns: [\"src/**/types.py\"],\n };\n case \"rust\":\n return {\n name: \"rust\",\n testPatterns: [\"tests/**/*.rs\", \"src/**/*.rs\"],\n productionPatterns: [\"src/**/*.rs\"],\n typePatterns: [\"src/**/types.rs\"],\n };\n case \"go\":\n return {\n name: \"go\",\n testPatterns: [\"**/*_test.go\"],\n productionPatterns: [\"**/*.go\"],\n typePatterns: [\"**/types/*.go\"],\n };\n default:\n return {\n name: language,\n testPatterns: [\"**/*test*\"],\n productionPatterns: [\"src/**/*\"],\n typePatterns: [\"src/**/*types*\"],\n };\n }\n}\n\nexport function compileInstallAnswers(answers: {\n subscriptions: SubscriptionAnswers;\n models: ModelAnswers;\n methodology: MethodologyAnswers;\n github: GitHubAnswers;\n languages: LanguageConfig[];\n installLocation: InstallAnswers[\"installLocation\"];\n}): InstallAnswers {\n return {\n subscriptions: answers.subscriptions,\n models: answers.models,\n methodology: answers.methodology,\n github: answers.github,\n languages: answers.languages,\n installLocation: answers.installLocation,\n };\n}\n","import { join } from \"node:path\";\nimport type { GeneratedFile, InstallAnswers } from \"../../shared/types.js\";\nimport { CONFIG_FILE_NAME, CONFIG_PATHS, OMO_CONFIG_NAME, OPENCODE_CONFIG_NAME } from \"../../shared/constants.js\";\nimport { generateSdlcConfig } from \"./sdlc-config.js\";\nimport { generateOhMyOpencodeConfig } from \"./omo-config.js\";\nimport { generateOpencodeConfig, getRequiredPlugins } from \"./opencode-config.js\";\n\nexport class ConfigGenerator {\n constructor(private answers: InstallAnswers) {}\n\n getConfigDir(): string {\n return this.answers.installLocation === \"local\"\n ? join(process.cwd(), \".opencode\")\n : CONFIG_PATHS.globalConfigDir;\n }\n\n getRequiredPackages(): string[] {\n return getRequiredPlugins(this.answers);\n }\n\n generate(): GeneratedFile[] {\n const configDir = this.getConfigDir();\n const sdlcConfig = generateSdlcConfig(this.answers);\n const omoConfig = generateOhMyOpencodeConfig(this.answers, configDir);\n const opencodeConfig = generateOpencodeConfig(this.answers, configDir);\n\n return [\n {\n path: join(configDir, CONFIG_FILE_NAME),\n content: JSON.stringify(sdlcConfig, null, 2),\n exists: false,\n },\n {\n path: join(configDir, OMO_CONFIG_NAME),\n content: JSON.stringify(omoConfig, null, 2),\n exists: false,\n },\n {\n path: join(configDir, OPENCODE_CONFIG_NAME),\n content: JSON.stringify(opencodeConfig, null, 2),\n exists: false,\n },\n {\n path: join(configDir, \"README.md\"),\n content: buildConfigReadme(configDir),\n exists: false,\n },\n ];\n }\n}\n\nfunction buildConfigReadme(configDir: string): string {\n return `# OpenCode SDLC Configuration\\n\\nThis folder is managed by the SDLC plugin installer.\\n\\n## Files\\n- ${CONFIG_FILE_NAME}: SDLC workflow configuration\\n- ${OMO_CONFIG_NAME}: oh-my-opencode agent definitions\\n- ${OPENCODE_CONFIG_NAME}: OpenCode plugin registration\\n\\n## Generated From\\n- Project: ${process.cwd()}\\n- Config directory: ${configDir}\\n`;\n}\n","import type { InstallAnswers, SdlcConfig } from \"../../shared/types.js\";\nimport { VERSION } from \"../../shared/constants.js\";\n\nexport function generateSdlcConfig(answers: InstallAnswers): SdlcConfig {\n return {\n version: VERSION,\n mode: answers.methodology.mode,\n git: {\n workflow: answers.methodology.gitWorkflow,\n worktrees: answers.methodology.worktrees,\n requireClean: answers.methodology.requireClean,\n },\n features: {\n atomicDesign: answers.methodology.atomicDesign,\n gitSpice: answers.methodology.gitSpice,\n },\n github: answers.github,\n languages: answers.languages,\n };\n}\n","import { existsSync, readFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport type { InstallAnswers, OhMyOpencodeConfig } from \"../../shared/types.js\";\nimport { OMO_CONFIG_NAME } from \"../../shared/constants.js\";\nimport { buildAgentSystems } from \"../utils/persona-builder.js\";\n\nexport function generateOhMyOpencodeConfig(\n answers: InstallAnswers,\n configDir: string\n): OhMyOpencodeConfig {\n const existingPath = join(configDir, OMO_CONFIG_NAME);\n const existing = existsSync(existingPath)\n ? (JSON.parse(readFileSync(existingPath, \"utf-8\")) as OhMyOpencodeConfig)\n : null;\n\n const agentSystems = buildAgentSystems(answers.models);\n\n return {\n agents: {\n ...(existing?.agents ?? {}),\n ...agentSystems,\n },\n };\n}\n","import type { ModelAnswers, OhMyOpencodeConfig } from \"../../shared/types.js\";\n\nconst baseInstructions = {\n red: \"You are the RED agent. Write ONE failing test with ONE assertion. Only edit test files.\",\n green:\n \"You are the GREEN agent. Make the failing test pass with minimal changes. Only edit production code files.\",\n domain:\n \"You are the DOMAIN agent. Enforce domain modeling: no primitive obsession, represent invalid state unrepresentable, parse don't validate. Only edit type definition files. You have VETO power.\",\n architect: \"You are the ARCHITECT agent. Review architecture and implementation feasibility. Read-only.\",\n discovery:\n \"You are the DISCOVERY agent. Facilitate domain discovery and capture domain language in event modeling docs.\",\n exploration:\n \"You are the EXPLORATION agent. Explore problem space, business case, and stakeholder goals before event modeling. Output discovery notes.\",\n workflowDesigner:\n \"You are the WORKFLOW DESIGNER agent. Run the 9-step event modeling workflow and capture slices.\",\n gwt: \"You are the GWT agent. Produce Given/When/Then scenarios for slices.\",\n modelChecker:\n \"You are the MODEL CHECKER agent. Validate event model completeness, slice coherence, and missing scenarios.\",\n codeReviewer:\n \"You are the CODE REVIEWER agent. Perform three-stage review: spec compliance, code quality, domain integrity. Read-only.\",\n story: \"You are the STORY agent. Assess business value and acceptance criteria alignment.\",\n ux: \"You are the UX agent. Review user experience, accessibility, and atomic design compliance.\",\n oracle: \"You are the ORACLE agent. Perform adversarial review to break assumptions and find edge cases. Read-only.\",\n adr: \"You are the ADR agent. Create ADRs only. Do not update ARCHITECTURE.md directly.\",\n designFacilitator:\n \"You are the DESIGN FACILITATOR agent. Synthesize ARCHITECTURE.md from ADRs and current decisions. Read-only unless editing ARCHITECTURE.md.\",\n fileUpdater: \"You are the FILE UPDATER agent. Edit configuration, docs, scripts. Do not edit code.\",\n};\n\nexport function buildAgentSystems(models: ModelAnswers): OhMyOpencodeConfig[\"agents\"] {\n return {\n marvin: {\n model: models.orchestrator,\n system:\n \"You are Marvin, the Paranoid Android. You are the SDLC orchestrator. Maintain a weary, sardonic tone while executing the SDLC process precisely. Always delegate implementation tasks to subagents.\",\n },\n red: { model: models.red, system: baseInstructions.red },\n green: { model: models.green, system: baseInstructions.green },\n domain: { model: models.domain, system: baseInstructions.domain },\n architect: { model: models.architect, system: baseInstructions.architect },\n discovery: { model: models.discovery, system: baseInstructions.discovery },\n exploration: { model: models.exploration, system: baseInstructions.exploration },\n workflowDesigner: { model: models.workflowDesigner, system: baseInstructions.workflowDesigner },\n gwt: { model: models.gwt, system: baseInstructions.gwt },\n modelChecker: { model: models.modelChecker, system: baseInstructions.modelChecker },\n codeReviewer: { model: models.codeReviewer, system: baseInstructions.codeReviewer },\n story: { model: models.story, system: baseInstructions.story },\n ux: { model: models.ux, system: baseInstructions.ux },\n oracle: { model: models.oracle, system: baseInstructions.oracle },\n adr: { model: models.adr, system: baseInstructions.adr },\n designFacilitator: { model: models.designFacilitator, system: baseInstructions.designFacilitator },\n fileUpdater: { model: models.fileUpdater, system: baseInstructions.fileUpdater },\n };\n}\n","import { existsSync, readFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport type { InstallAnswers, OpencodeConfig } from \"../../shared/types.js\";\n\nconst REQUIRED_PLUGINS = [\"sdlc-plugin/plugin\", \"oh-my-opencode\"];\n\nexport function generateOpencodeConfig(\n answers: InstallAnswers,\n configDir: string\n): OpencodeConfig {\n const configPath = join(configDir, \"opencode.json\");\n const existing = existsSync(configPath)\n ? (JSON.parse(readFileSync(configPath, \"utf-8\")) as OpencodeConfig)\n : {};\n\n const plugins = new Set<string>([...(existing.plugin ?? []), ...REQUIRED_PLUGINS]);\n\n if (answers.subscriptions.hasGoogle) {\n plugins.add(\"opencode-antigravity-auth\");\n }\n\n if (answers.subscriptions.hasOpenAI) {\n plugins.add(\"opencode-openai-codex-auth\");\n }\n\n return {\n ...existing,\n $schema: existing.$schema ?? \"https://opencode.ai/config.json\",\n plugin: Array.from(plugins),\n };\n}\n\nexport function getRequiredPlugins(answers: InstallAnswers): string[] {\n const packages = [\"sdlc-plugin\", \"oh-my-opencode\"];\n if (answers.subscriptions.hasGoogle) packages.push(\"opencode-antigravity-auth\");\n if (answers.subscriptions.hasOpenAI) packages.push(\"opencode-openai-codex-auth\");\n return packages;\n}\n","import { exec } from \"node:child_process\";\nimport { existsSync } from \"node:fs\";\nimport { copyFile, mkdir, readdir, writeFile } from \"node:fs/promises\";\nimport { dirname, join } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { promisify } from \"node:util\";\nimport { CONFIG_PATHS } from \"../../shared/constants.js\";\nimport type { GeneratedFile } from \"../../shared/types.js\";\n\nconst execAsync = promisify(exec);\n\nfunction getPackageRoot(): string {\n const currentFileDir = dirname(fileURLToPath(import.meta.url));\n\n const bundledRoot = join(currentFileDir, \"..\", \"..\");\n if (existsSync(join(bundledRoot, \"commands\"))) {\n return bundledRoot;\n }\n\n const devRoot = join(currentFileDir, \"..\", \"..\", \"..\");\n if (existsSync(join(devRoot, \"commands\"))) {\n return devRoot;\n }\n\n return bundledRoot;\n}\n\nexport interface GitHubExtensionFailure {\n name: string;\n error: string;\n}\n\nexport interface GitHubExtensionResult {\n installed: string[];\n skipped: string[];\n failed: GitHubExtensionFailure[];\n}\n\nexport class FileManager {\n private configDir: string;\n\n constructor(configDir?: string) {\n this.configDir = configDir ?? CONFIG_PATHS.globalConfigDir;\n }\n\n getConfigDir(): string {\n return this.configDir;\n }\n\n async ensureDir(dir: string): Promise<void> {\n if (!existsSync(dir)) {\n await mkdir(dir, { recursive: true });\n }\n }\n\n async writeFiles(files: GeneratedFile[]): Promise<void> {\n for (const file of files) {\n const dir = dirname(file.path);\n await this.ensureDir(dir);\n await writeFile(file.path, file.content, \"utf-8\");\n }\n }\n\n async installDependencies(packages: string[]): Promise<void> {\n if (packages.length === 0) return;\n\n await this.ensureDir(this.configDir);\n\n const packageJsonPath = join(this.configDir, \"package.json\");\n if (!existsSync(packageJsonPath)) {\n await writeFile(\n packageJsonPath,\n JSON.stringify(\n {\n name: \"opencode-config\",\n private: true,\n type: \"module\",\n },\n null,\n 2\n )\n );\n }\n\n await execAsync(`npm install ${packages.join(\" \")}`, {\n cwd: this.configDir,\n timeout: 120000,\n });\n }\n\n async copyCommands(): Promise<string[]> {\n const commandsDir = CONFIG_PATHS.commandsDir;\n await this.ensureDir(commandsDir);\n\n const packageRoot = getPackageRoot();\n const sourceCommandsDir = join(packageRoot, \"commands\");\n\n const copiedFiles: string[] = [];\n\n if (existsSync(sourceCommandsDir)) {\n const files = await readdir(sourceCommandsDir);\n for (const file of files) {\n if (file.endsWith(\".md\")) {\n const sourcePath = join(sourceCommandsDir, file);\n const destPath = join(commandsDir, file);\n await copyFile(sourcePath, destPath);\n copiedFiles.push(file);\n }\n }\n }\n\n return copiedFiles;\n }\n\n async installGitHubExtensions(): Promise<GitHubExtensionResult> {\n const extensions = [\n \"jwilger/gh-issue-ext\",\n \"jwilger/gh-project-ext\",\n \"agynio/gh-pr-review\",\n ];\n\n const result: GitHubExtensionResult = {\n installed: [],\n skipped: [],\n failed: [],\n };\n\n let installedExtensions: string[] = [];\n try {\n const { stdout } = await execAsync(\"gh extension list\", { timeout: 10000 });\n installedExtensions = stdout\n .split(\"\\n\")\n .map((line) => line.split(\"\\t\")[0])\n .filter((name): name is string => Boolean(name));\n } catch {\n installedExtensions = [];\n }\n\n for (const ext of extensions) {\n const extName = ext.split(\"/\")[1] ?? ext;\n\n if (installedExtensions.some((installed) => installed.includes(extName))) {\n result.skipped.push(ext);\n continue;\n }\n\n try {\n await execAsync(`gh extension install ${ext}`, { timeout: 60000 });\n result.installed.push(ext);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n result.failed.push({ name: ext, error: message });\n }\n }\n\n return result;\n }\n}\n","import { execSync } from \"node:child_process\";\n\ninterface PrereqResult {\n installed: boolean;\n version?: string;\n}\n\ninterface OpencodePrereq extends PrereqResult {\n models: string[];\n}\n\nexport interface Prerequisites {\n node: PrereqResult;\n opencode: OpencodePrereq;\n ohMyOpencode: PrereqResult;\n gh: PrereqResult;\n}\n\nfunction checkBinary(command: string): PrereqResult {\n try {\n const version = execSync(command, { encoding: \"utf-8\" }).trim();\n return { installed: true, version };\n } catch {\n return { installed: false };\n }\n}\n\nexport function checkPrerequisites(): Prerequisites {\n const node = checkBinary(\"node --version\");\n const opencode = checkBinary(\"opencode --version\");\n const ohMyOpencode = checkBinary(\"opencode --help | grep -q oh-my-opencode && echo installed\");\n const gh = checkBinary(\"gh --version\");\n\n const models = opencode.installed ? getOpencodeModels() : [];\n\n return {\n node,\n opencode: { ...opencode, models },\n ohMyOpencode,\n gh,\n };\n}\n\nfunction getOpencodeModels(): string[] {\n try {\n const output = execSync(\"opencode models --json\", { encoding: \"utf-8\" });\n const parsed = JSON.parse(output) as { id: string }[];\n return parsed.map((model) => model.id);\n } catch {\n return [];\n }\n}\n","import kleur from \"kleur\";\nimport { DISPLAY_NAME } from \"../../shared/constants.js\";\n\nconst writeLine = (message: string): void => {\n process.stdout.write(`${message}\\n`);\n};\n\nconst writeErrorLine = (message: string): void => {\n process.stderr.write(`${message}\\n`);\n};\n\nexport const logger = {\n banner(): void {\n writeLine(kleur.cyan().bold(`\\n${DISPLAY_NAME}`));\n writeLine(kleur.gray(\"====================================\\n\"));\n },\n section(title: string): void {\n writeLine(kleur.cyan(`\\n${title}`));\n },\n info(message: string): void {\n writeLine(kleur.gray(message));\n },\n warn(message: string): void {\n writeErrorLine(kleur.yellow(message));\n },\n error(message: string): void {\n writeErrorLine(kleur.red(message));\n },\n success(message: string): void {\n writeLine(kleur.green(message));\n },\n successBanner(message: string): void {\n writeLine(kleur.green().bold(`\\n${message}\\n`));\n },\n};\n","import kleur from \"kleur\";\nimport { logger } from \"../utils/logger.js\";\nimport { checkPrerequisites } from \"../utils/prerequisites.js\";\n\ninterface DoctorOptions {\n fix?: boolean;\n}\n\nexport function doctor(_options: DoctorOptions): void {\n logger.banner();\n\n const prereqs = checkPrerequisites();\n\n logger.section(\"Prerequisites\");\n const nodeVersion = prereqs.node.installed ? prereqs.node.version ?? \"unknown\" : \"missing\";\n const opencodeVersion = prereqs.opencode.installed ? prereqs.opencode.version ?? \"unknown\" : \"missing\";\n const ohMyOpencodeStatus = prereqs.ohMyOpencode.installed ? \"installed\" : \"missing\";\n const ghVersion = prereqs.gh.installed ? prereqs.gh.version ?? \"unknown\" : \"missing\";\n\n logger.info(kleur.gray(`Node.js: ${nodeVersion}`));\n logger.info(kleur.gray(`OpenCode: ${opencodeVersion}`));\n logger.info(kleur.gray(`oh-my-opencode: ${ohMyOpencodeStatus}`));\n logger.info(kleur.gray(`GitHub CLI: ${ghVersion}`));\n logger.info(\"\");\n\n if (!prereqs.node.installed || !prereqs.opencode.installed || !prereqs.ohMyOpencode.installed) {\n logger.warn(\"Missing required dependencies. Please install them and retry.\");\n }\n\n if (!prereqs.gh.installed) {\n logger.warn(\"GitHub CLI not installed. Install it from https://cli.github.com/\");\n }\n\n logger.info(\"Doctor completed. No automatic fixes implemented yet.\");\n}\n","import kleur from \"kleur\";\nimport { logger } from \"../utils/logger.js\";\n\ninterface UpgradeOptions {\n check?: boolean;\n yes?: boolean;\n}\n\nexport function upgrade(options: UpgradeOptions): void {\n logger.banner();\n\n if (options.check === true) {\n logger.info(\"Upgrade check not implemented yet.\");\n return;\n }\n\n logger.warn(\"Upgrade workflow not implemented yet.\");\n logger.info(kleur.gray(\"Re-run sdlc-plugin install to regenerate configs.\"));\n}\n"],"mappings":"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","names":["kleur","kleur","join","join","join","existsSync","readFileSync","join","join","existsSync","join","join","existsSync","kleur","kleur","kleur","kleur","kleur","kleur"]}
|
|
1
|
+
{"version":3,"sources":["../../src/cli/index.ts","../../src/shared/constants.ts","../../src/cli/commands/install.ts","../../src/cli/questions/install-prompts.ts","../../src/cli/generators/config-generator.ts","../../src/cli/generators/sdlc-config.ts","../../src/cli/generators/omo-config.ts","../../src/cli/utils/persona-builder.ts","../../src/cli/generators/opencode-config.ts","../../src/cli/utils/file-manager.ts","../../src/cli/utils/prerequisites.ts","../../src/cli/utils/logger.ts","../../src/cli/commands/doctor.ts","../../src/cli/commands/upgrade.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport { Command } from \"commander\";\nimport kleur from \"kleur\";\nimport { DISPLAY_NAME, TAGLINE, VERSION } from \"../shared/constants.js\";\nimport { install } from \"./commands/install.js\";\nimport { doctor } from \"./commands/doctor.js\";\nimport { upgrade } from \"./commands/upgrade.js\";\n\nconst program = new Command();\n\nprogram\n .name(\"opencode-sdlc-plugin\")\n .description(`${kleur.cyan(DISPLAY_NAME)} - ${TAGLINE}`)\n .version(VERSION);\n\nprogram\n .command(\"install\")\n .description(\"Install and configure OpenCode SDLC plugin\")\n .option(\"-y, --yes\", \"Skip confirmation prompts\", false)\n .option(\"--global\", \"Install globally (default)\", true)\n .option(\"--local\", \"Install to current project only\", false)\n .option(\"--reconfigure\", \"Force full reconfiguration\", false)\n .action(async (options: { yes?: boolean; global?: boolean; local?: boolean; reconfigure?: boolean }) => {\n await install(options);\n });\n\nprogram\n .command(\"upgrade\")\n .description(\"Upgrade OpenCode SDLC plugin\")\n .option(\"--check\", \"Check for updates without installing\", false)\n .option(\"-y, --yes\", \"Skip confirmation prompts\", false)\n .action(upgrade);\n\nprogram\n .command(\"doctor\")\n .description(\"Diagnose and fix common setup issues\")\n .option(\"--fix\", \"Attempt to fix detected issues\", false)\n .action(doctor);\n\nprogram.parse();\n","import { homedir } from \"node:os\";\nimport { join } from \"node:path\";\n\nexport const VERSION = \"0.2.1\";\nexport const DISPLAY_NAME = \"OpenCode SDLC Plugin\";\nexport const TAGLINE = \"Agentic SDLC workflow with discovery, ADRs, and TDD\";\n\nexport const PACKAGE_NAME = \"opencode-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 kleur from \"kleur\";\nimport ora from \"ora\";\nimport { join } from \"node:path\";\nimport type { InstallAnswers, InstallLocation } from \"../../shared/types.js\";\nimport { VERSION } from \"../../shared/constants.js\";\nimport {\n compileInstallAnswers,\n gatherGitHub,\n gatherLanguages,\n gatherMethodology,\n gatherModels,\n gatherSubscriptions,\n} from \"../questions/install-prompts.js\";\nimport { ConfigGenerator } from \"../generators/config-generator.js\";\nimport { FileManager } from \"../utils/file-manager.js\";\nimport { checkPrerequisites } from \"../utils/prerequisites.js\";\nimport { logger } from \"../utils/logger.js\";\n\ninterface InstallOptions {\n yes?: boolean;\n global?: boolean;\n local?: boolean;\n reconfigure?: boolean;\n}\n\nfunction resolveInstallLocation(options: InstallOptions): InstallLocation {\n if (options.local === true) return \"local\";\n return \"global\";\n}\n\nexport async function install(options: InstallOptions): Promise<void> {\n logger.banner();\n\n const spinner = ora(\"Checking prerequisites...\").start();\n const prereqs = checkPrerequisites();\n let fileManager = new FileManager(\n resolveInstallLocation(options) === \"local\" ? join(process.cwd(), \".opencode\") : undefined\n );\n\n if (!prereqs.node.installed) {\n spinner.fail(\"Node.js not found\");\n logger.error(\"Please install Node.js 20+ first: https://nodejs.org/\");\n process.exit(1);\n }\n\n if (!prereqs.opencode.installed) {\n spinner.fail(\"OpenCode not found\");\n logger.error(\"Please install OpenCode first: https://opencode.ai/docs\");\n process.exit(1);\n }\n\n if (!prereqs.ohMyOpencode.installed) {\n spinner.warn(\"oh-my-opencode not found - installing...\");\n const ohMyOpencodeSpinner = ora(\"Installing oh-my-opencode...\").start();\n try {\n await fileManager.installOhMyOpencode();\n const updatedPrereqs = checkPrerequisites();\n if (!updatedPrereqs.ohMyOpencode.installed) {\n ohMyOpencodeSpinner.fail(\"oh-my-opencode install did not register\");\n logger.error(\"Please install oh-my-opencode manually: https://github.com/khulnasoft/oh-my-opencode\");\n process.exit(1);\n }\n ohMyOpencodeSpinner.succeed(\"oh-my-opencode installed\");\n } catch (error) {\n ohMyOpencodeSpinner.fail(\"Failed to install oh-my-opencode\");\n const message = error instanceof Error ? error.message : String(error);\n logger.error(`Installation error: ${message}`);\n logger.error(\"Please install oh-my-opencode manually: https://github.com/khulnasoft/oh-my-opencode\");\n process.exit(1);\n }\n }\n\n spinner.succeed(\"Prerequisites checked\");\n\n const subscriptions = await gatherSubscriptions();\n const availableModels = prereqs.opencode.models.length > 0 ? prereqs.opencode.models : [\"anthropic/claude-sonnet-4-5-thinking\"];\n const models = await gatherModels(availableModels);\n const methodology = await gatherMethodology();\n const github = await gatherGitHub();\n const languages = await gatherLanguages();\n const installLocation = resolveInstallLocation(options);\n\n const answers: InstallAnswers = compileInstallAnswers({\n subscriptions,\n models,\n methodology,\n github,\n languages,\n installLocation,\n });\n\n const generator = new ConfigGenerator(answers);\n const files = generator.generate();\n\n fileManager = new FileManager(generator.getConfigDir());\n\n const installSpinner = ora(\"Writing configuration...\").start();\n await fileManager.writeFiles(files);\n installSpinner.succeed(\"Configuration written\");\n\n const dependencySpinner = ora(\"Installing dependencies...\").start();\n const packages = generator.getRequiredPackages();\n await fileManager.installDependencies(packages);\n dependencySpinner.succeed(\"Dependencies installed\");\n\n const commandSpinner = ora(\"Installing commands...\").start();\n const copiedCommands = await fileManager.copyCommands();\n commandSpinner.succeed(`Installed ${copiedCommands.length} commands`);\n\n const ghSpinner = ora(\"Installing GitHub CLI extensions...\").start();\n const ghResult = await fileManager.installGitHubExtensions();\n if (ghResult.failed.length > 0) {\n ghSpinner.warn(\n `GitHub extensions: ${ghResult.installed.length} installed, ` +\n `${ghResult.skipped.length} skipped, ${ghResult.failed.length} failed`\n );\n for (const failure of ghResult.failed) {\n logger.warn(` Failed to install ${failure.name}: ${failure.error}`);\n }\n } else {\n ghSpinner.succeed(\n `GitHub extensions: ${ghResult.installed.length} installed, ${ghResult.skipped.length} already present`\n );\n }\n\n logger.successBanner(`SDLC PLUGIN ${VERSION} INSTALLED`);\n\n logger.info(\"Next steps:\");\n logger.info(kleur.gray(\" 1. Restart OpenCode\"));\n logger.info(kleur.gray(\" 2. Run /sdlc-setup in your project\"));\n logger.info(\"\");\n}\n","import { confirm, input, select } from \"@inquirer/prompts\";\nimport type { GitHubAnswers, InstallAnswers, LanguageConfig, MethodologyAnswers, ModelAnswers, SubscriptionAnswers } from \"../../shared/types.js\";\nimport { DEFAULT_AGENT_MODEL } from \"../../shared/constants.js\";\n\nexport async function gatherSubscriptions(): Promise<SubscriptionAnswers> {\n const hasClaude = await confirm({\n message: \"Do you have a Claude subscription?\",\n default: true,\n });\n const hasOpenAI = await confirm({\n message: \"Do you have an OpenAI subscription?\",\n default: true,\n });\n const hasGoogle = await confirm({\n message: \"Do you have a Google/Gemini subscription?\",\n default: false,\n });\n const hasGitHubCopilot = await confirm({\n message: \"Do you have GitHub Copilot?\",\n default: false,\n });\n\n return { hasClaude, hasOpenAI, hasGoogle, hasGitHubCopilot };\n}\n\nexport async function gatherModels(availableModels: string[]): Promise<ModelAnswers> {\n const modelChoice = async (message: string, defaultModel: string): Promise<string> => {\n const firstModel = availableModels[0];\n if (availableModels.length === 1) {\n return firstModel ?? defaultModel;\n }\n const selection = await select<string>({\n message,\n choices: availableModels.map((id) => ({ name: id, value: id })),\n default: firstModel ?? defaultModel,\n });\n return selection;\n };\n\n return {\n orchestrator: await modelChoice(\"Model for Marvin orchestrator\", DEFAULT_AGENT_MODEL),\n red: await modelChoice(\"Model for RED agent\", DEFAULT_AGENT_MODEL),\n green: await modelChoice(\"Model for GREEN agent\", DEFAULT_AGENT_MODEL),\n domain: await modelChoice(\"Model for DOMAIN agent\", DEFAULT_AGENT_MODEL),\n architect: await modelChoice(\"Model for ARCHITECT agent\", DEFAULT_AGENT_MODEL),\n discovery: await modelChoice(\"Model for DISCOVERY agent\", DEFAULT_AGENT_MODEL),\n exploration: await modelChoice(\"Model for EXPLORATION agent\", DEFAULT_AGENT_MODEL),\n workflowDesigner: await modelChoice(\"Model for WORKFLOW DESIGNER agent\", DEFAULT_AGENT_MODEL),\n gwt: await modelChoice(\"Model for GWT agent\", DEFAULT_AGENT_MODEL),\n modelChecker: await modelChoice(\"Model for MODEL CHECKER agent\", DEFAULT_AGENT_MODEL),\n codeReviewer: await modelChoice(\"Model for CODE REVIEWER agent\", DEFAULT_AGENT_MODEL),\n story: await modelChoice(\"Model for STORY agent\", DEFAULT_AGENT_MODEL),\n ux: await modelChoice(\"Model for UX agent\", DEFAULT_AGENT_MODEL),\n oracle: await modelChoice(\"Model for ORACLE agent\", DEFAULT_AGENT_MODEL),\n adr: await modelChoice(\"Model for ADR agent\", DEFAULT_AGENT_MODEL),\n designFacilitator: await modelChoice(\"Model for DESIGN FACILITATOR agent\", DEFAULT_AGENT_MODEL),\n fileUpdater: await modelChoice(\"Model for FILE UPDATER agent\", DEFAULT_AGENT_MODEL),\n };\n}\n\nexport async function gatherMethodology(): Promise<MethodologyAnswers> {\n const mode = await select<\"event-modeling\" | \"traditional\">({\n message: \"Which SDLC mode?\",\n choices: [\n { name: \"Event modeling\", value: \"event-modeling\" as const },\n { name: \"Traditional (PRD-driven)\", value: \"traditional\" as const },\n ],\n default: \"event-modeling\",\n });\n\n const gitWorkflow = await select<\"git-spice\" | \"standard\">({\n message: \"Preferred git workflow?\",\n choices: [\n { name: \"git-spice\", value: \"git-spice\" as const },\n { name: \"standard\", value: \"standard\" as const },\n ],\n default: \"git-spice\",\n });\n\n const requireClean = await confirm({\n message: \"Require clean working tree before starting work?\",\n default: true,\n });\n\n const worktrees = await confirm({\n message: \"Enable git worktrees for parallel issue work?\",\n default: false,\n });\n\n const atomicDesign = await confirm({\n message: \"Enable Atomic Design guidance for UI work?\",\n default: true,\n });\n\n const gitSpice = await confirm({\n message: \"Enable git-spice stacked PR workflow guidance?\",\n default: false,\n });\n\n return {\n mode,\n gitWorkflow,\n requireClean,\n worktrees,\n atomicDesign,\n gitSpice,\n };\n}\n\nexport async function gatherGitHub(): Promise<GitHubAnswers> {\n const owner = await input({\n message: \"GitHub owner/org (leave blank to skip)\",\n });\n\n const projectRaw = await input({\n message: \"GitHub project number (leave blank to skip)\",\n });\n\n const project = projectRaw ? Number(projectRaw) : undefined;\n\n return {\n owner: owner || undefined,\n project: Number.isFinite(project) ? project : undefined,\n };\n}\n\nexport async function gatherLanguages(): Promise<LanguageConfig[]> {\n const language = await select({\n message: \"Primary language?\",\n choices: [\n { name: \"TypeScript\", value: \"typescript\" },\n { name: \"JavaScript\", value: \"javascript\" },\n { name: \"Python\", value: \"python\" },\n { name: \"Rust\", value: \"rust\" },\n { name: \"Go\", value: \"go\" },\n { name: \"Other\", value: \"other\" },\n ],\n default: \"typescript\",\n });\n\n if (language === \"other\") {\n const name = await input({ message: \"Language name\" });\n const testPatterns = await input({ message: \"Test file glob patterns (comma-separated)\" });\n const productionPatterns = await input({\n message: \"Production code glob patterns (comma-separated)\",\n });\n const typePatterns = await input({ message: \"Domain/type file patterns (comma-separated)\" });\n\n return [\n {\n name: name || \"custom\",\n testPatterns: testPatterns.split(\",\").map((p) => p.trim()).filter(Boolean),\n productionPatterns: productionPatterns.split(\",\").map((p) => p.trim()).filter(Boolean),\n typePatterns: typePatterns.split(\",\").map((p) => p.trim()).filter(Boolean),\n },\n ];\n }\n\n return [getLanguageDefaults(language)];\n}\n\nfunction getLanguageDefaults(language: string): LanguageConfig {\n switch (language) {\n case \"typescript\":\n return {\n name: \"typescript\",\n testPatterns: [\"**/*.test.ts\", \"**/*.spec.ts\"],\n productionPatterns: [\"src/**/*.ts\"],\n typePatterns: [\"src/**/*types.ts\", \"src/**/*types/*.ts\"],\n };\n case \"javascript\":\n return {\n name: \"javascript\",\n testPatterns: [\"**/*.test.js\", \"**/*.spec.js\"],\n productionPatterns: [\"src/**/*.js\"],\n typePatterns: [\"src/**/*types.js\", \"src/**/*types/*.js\"],\n };\n case \"python\":\n return {\n name: \"python\",\n testPatterns: [\"tests/**/*.py\", \"**/test_*.py\"],\n productionPatterns: [\"src/**/*.py\"],\n typePatterns: [\"src/**/types.py\"],\n };\n case \"rust\":\n return {\n name: \"rust\",\n testPatterns: [\"tests/**/*.rs\", \"src/**/*.rs\"],\n productionPatterns: [\"src/**/*.rs\"],\n typePatterns: [\"src/**/types.rs\"],\n };\n case \"go\":\n return {\n name: \"go\",\n testPatterns: [\"**/*_test.go\"],\n productionPatterns: [\"**/*.go\"],\n typePatterns: [\"**/types/*.go\"],\n };\n default:\n return {\n name: language,\n testPatterns: [\"**/*test*\"],\n productionPatterns: [\"src/**/*\"],\n typePatterns: [\"src/**/*types*\"],\n };\n }\n}\n\nexport function compileInstallAnswers(answers: {\n subscriptions: SubscriptionAnswers;\n models: ModelAnswers;\n methodology: MethodologyAnswers;\n github: GitHubAnswers;\n languages: LanguageConfig[];\n installLocation: InstallAnswers[\"installLocation\"];\n}): InstallAnswers {\n return {\n subscriptions: answers.subscriptions,\n models: answers.models,\n methodology: answers.methodology,\n github: answers.github,\n languages: answers.languages,\n installLocation: answers.installLocation,\n };\n}\n","import { join } from \"node:path\";\nimport type { GeneratedFile, InstallAnswers } from \"../../shared/types.js\";\nimport { CONFIG_FILE_NAME, CONFIG_PATHS, OMO_CONFIG_NAME, OPENCODE_CONFIG_NAME } from \"../../shared/constants.js\";\nimport { generateSdlcConfig } from \"./sdlc-config.js\";\nimport { generateOhMyOpencodeConfig } from \"./omo-config.js\";\nimport { generateOpencodeConfig, getRequiredPlugins } from \"./opencode-config.js\";\n\nexport class ConfigGenerator {\n constructor(private answers: InstallAnswers) {}\n\n getConfigDir(): string {\n return this.answers.installLocation === \"local\"\n ? join(process.cwd(), \".opencode\")\n : CONFIG_PATHS.globalConfigDir;\n }\n\n getRequiredPackages(): string[] {\n return getRequiredPlugins(this.answers);\n }\n\n generate(): GeneratedFile[] {\n const configDir = this.getConfigDir();\n const sdlcConfig = generateSdlcConfig(this.answers);\n const omoConfig = generateOhMyOpencodeConfig(this.answers, configDir);\n const opencodeConfig = generateOpencodeConfig(this.answers, configDir);\n\n return [\n {\n path: join(configDir, CONFIG_FILE_NAME),\n content: JSON.stringify(sdlcConfig, null, 2),\n exists: false,\n },\n {\n path: join(configDir, OMO_CONFIG_NAME),\n content: JSON.stringify(omoConfig, null, 2),\n exists: false,\n },\n {\n path: join(configDir, OPENCODE_CONFIG_NAME),\n content: JSON.stringify(opencodeConfig, null, 2),\n exists: false,\n },\n {\n path: join(configDir, \"README.md\"),\n content: buildConfigReadme(configDir),\n exists: false,\n },\n ];\n }\n}\n\nfunction buildConfigReadme(configDir: string): string {\n return `# OpenCode SDLC Configuration\\n\\nThis folder is managed by the SDLC plugin installer.\\n\\n## Files\\n- ${CONFIG_FILE_NAME}: SDLC workflow configuration\\n- ${OMO_CONFIG_NAME}: oh-my-opencode agent definitions\\n- ${OPENCODE_CONFIG_NAME}: OpenCode plugin registration\\n\\n## Generated From\\n- Project: ${process.cwd()}\\n- Config directory: ${configDir}\\n`;\n}\n","import type { InstallAnswers, SdlcConfig } from \"../../shared/types.js\";\nimport { VERSION } from \"../../shared/constants.js\";\n\nexport function generateSdlcConfig(answers: InstallAnswers): SdlcConfig {\n return {\n version: VERSION,\n mode: answers.methodology.mode,\n git: {\n workflow: answers.methodology.gitWorkflow,\n worktrees: answers.methodology.worktrees,\n requireClean: answers.methodology.requireClean,\n },\n features: {\n atomicDesign: answers.methodology.atomicDesign,\n gitSpice: answers.methodology.gitSpice,\n },\n github: answers.github,\n languages: answers.languages,\n };\n}\n","import { existsSync, readFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport type { InstallAnswers, OhMyOpencodeConfig } from \"../../shared/types.js\";\nimport { OMO_CONFIG_NAME } from \"../../shared/constants.js\";\nimport { buildAgentSystems } from \"../utils/persona-builder.js\";\n\nexport function generateOhMyOpencodeConfig(\n answers: InstallAnswers,\n configDir: string\n): OhMyOpencodeConfig {\n const existingPath = join(configDir, OMO_CONFIG_NAME);\n const existing = existsSync(existingPath)\n ? (JSON.parse(readFileSync(existingPath, \"utf-8\")) as OhMyOpencodeConfig)\n : null;\n\n const agentSystems = buildAgentSystems(answers.models);\n\n return {\n agents: {\n ...(existing?.agents ?? {}),\n ...agentSystems,\n },\n };\n}\n","import type { ModelAnswers, OhMyOpencodeConfig } from \"../../shared/types.js\";\n\nconst baseInstructions = {\n red: \"You are the RED agent. Write ONE failing test with ONE assertion. Only edit test files.\",\n green:\n \"You are the GREEN agent. Make the failing test pass with minimal changes. Only edit production code files.\",\n domain:\n \"You are the DOMAIN agent. Enforce domain modeling: no primitive obsession, represent invalid state unrepresentable, parse don't validate. Only edit type definition files. You have VETO power.\",\n architect: \"You are the ARCHITECT agent. Review architecture and implementation feasibility. Read-only.\",\n discovery:\n \"You are the DISCOVERY agent. Facilitate domain discovery and capture domain language in event modeling docs.\",\n exploration:\n \"You are the EXPLORATION agent. Explore problem space, business case, and stakeholder goals before event modeling. Output discovery notes.\",\n workflowDesigner:\n \"You are the WORKFLOW DESIGNER agent. Run the 9-step event modeling workflow and capture slices.\",\n gwt: \"You are the GWT agent. Produce Given/When/Then scenarios for slices.\",\n modelChecker:\n \"You are the MODEL CHECKER agent. Validate event model completeness, slice coherence, and missing scenarios.\",\n codeReviewer:\n \"You are the CODE REVIEWER agent. Perform three-stage review: spec compliance, code quality, domain integrity. Read-only.\",\n story: \"You are the STORY agent. Assess business value and acceptance criteria alignment.\",\n ux: \"You are the UX agent. Review user experience, accessibility, and atomic design compliance.\",\n oracle: \"You are the ORACLE agent. Perform adversarial review to break assumptions and find edge cases. Read-only.\",\n adr: \"You are the ADR agent. Create ADRs only. Do not update ARCHITECTURE.md directly.\",\n designFacilitator:\n \"You are the DESIGN FACILITATOR agent. Synthesize ARCHITECTURE.md from ADRs and current decisions. Read-only unless editing ARCHITECTURE.md.\",\n fileUpdater: \"You are the FILE UPDATER agent. Edit configuration, docs, scripts. Do not edit code.\",\n};\n\nexport function buildAgentSystems(models: ModelAnswers): OhMyOpencodeConfig[\"agents\"] {\n return {\n marvin: {\n model: models.orchestrator,\n system:\n \"You are Marvin, the Paranoid Android. You are the SDLC orchestrator. Maintain a weary, sardonic tone while executing the SDLC process precisely. Always delegate implementation tasks to subagents.\",\n },\n red: { model: models.red, system: baseInstructions.red },\n green: { model: models.green, system: baseInstructions.green },\n domain: { model: models.domain, system: baseInstructions.domain },\n architect: { model: models.architect, system: baseInstructions.architect },\n discovery: { model: models.discovery, system: baseInstructions.discovery },\n exploration: { model: models.exploration, system: baseInstructions.exploration },\n workflowDesigner: { model: models.workflowDesigner, system: baseInstructions.workflowDesigner },\n gwt: { model: models.gwt, system: baseInstructions.gwt },\n modelChecker: { model: models.modelChecker, system: baseInstructions.modelChecker },\n codeReviewer: { model: models.codeReviewer, system: baseInstructions.codeReviewer },\n story: { model: models.story, system: baseInstructions.story },\n ux: { model: models.ux, system: baseInstructions.ux },\n oracle: { model: models.oracle, system: baseInstructions.oracle },\n adr: { model: models.adr, system: baseInstructions.adr },\n designFacilitator: { model: models.designFacilitator, system: baseInstructions.designFacilitator },\n fileUpdater: { model: models.fileUpdater, system: baseInstructions.fileUpdater },\n };\n}\n","import { existsSync, readFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport type { InstallAnswers, OpencodeConfig } from \"../../shared/types.js\";\n\nconst REQUIRED_PLUGINS = [\"opencode-sdlc-plugin/plugin\", \"oh-my-opencode\"];\n\nexport function generateOpencodeConfig(\n answers: InstallAnswers,\n configDir: string\n): OpencodeConfig {\n const configPath = join(configDir, \"opencode.json\");\n const existing = existsSync(configPath)\n ? (JSON.parse(readFileSync(configPath, \"utf-8\")) as OpencodeConfig)\n : {};\n\n const plugins = new Set<string>([...(existing.plugin ?? []), ...REQUIRED_PLUGINS]);\n\n if (answers.subscriptions.hasGoogle) {\n plugins.add(\"opencode-antigravity-auth\");\n }\n\n if (answers.subscriptions.hasOpenAI) {\n plugins.add(\"opencode-openai-codex-auth\");\n }\n\n return {\n ...existing,\n $schema: existing.$schema ?? \"https://opencode.ai/config.json\",\n plugin: Array.from(plugins),\n };\n}\n\nexport function getRequiredPlugins(answers: InstallAnswers): string[] {\n const packages = [\"opencode-sdlc-plugin\", \"oh-my-opencode\"];\n if (answers.subscriptions.hasGoogle) packages.push(\"opencode-antigravity-auth\");\n if (answers.subscriptions.hasOpenAI) packages.push(\"opencode-openai-codex-auth\");\n return packages;\n}\n","import { exec } from \"node:child_process\";\nimport { existsSync } from \"node:fs\";\nimport { copyFile, mkdir, readdir, writeFile } from \"node:fs/promises\";\nimport { dirname, join } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { promisify } from \"node:util\";\nimport { CONFIG_PATHS } from \"../../shared/constants.js\";\nimport type { GeneratedFile } from \"../../shared/types.js\";\n\nconst execAsync = promisify(exec);\n\nfunction getPackageRoot(): string {\n const currentFileDir = dirname(fileURLToPath(import.meta.url));\n\n const bundledRoot = join(currentFileDir, \"..\", \"..\");\n if (existsSync(join(bundledRoot, \"commands\"))) {\n return bundledRoot;\n }\n\n const devRoot = join(currentFileDir, \"..\", \"..\", \"..\");\n if (existsSync(join(devRoot, \"commands\"))) {\n return devRoot;\n }\n\n return bundledRoot;\n}\n\nexport interface GitHubExtensionFailure {\n name: string;\n error: string;\n}\n\nexport interface GitHubExtensionResult {\n installed: string[];\n skipped: string[];\n failed: GitHubExtensionFailure[];\n}\n\nexport class FileManager {\n private configDir: string;\n\n constructor(configDir?: string) {\n this.configDir = configDir ?? CONFIG_PATHS.globalConfigDir;\n }\n\n getConfigDir(): string {\n return this.configDir;\n }\n\n async ensureDir(dir: string): Promise<void> {\n if (!existsSync(dir)) {\n await mkdir(dir, { recursive: true });\n }\n }\n\n async writeFiles(files: GeneratedFile[]): Promise<void> {\n for (const file of files) {\n const dir = dirname(file.path);\n await this.ensureDir(dir);\n await writeFile(file.path, file.content, \"utf-8\");\n }\n }\n\n async installDependencies(packages: string[]): Promise<void> {\n if (packages.length === 0) return;\n\n await this.ensureDir(this.configDir);\n\n const packageJsonPath = join(this.configDir, \"package.json\");\n if (!existsSync(packageJsonPath)) {\n await writeFile(\n packageJsonPath,\n JSON.stringify(\n {\n name: \"opencode-config\",\n private: true,\n type: \"module\",\n },\n null,\n 2\n )\n );\n }\n\n await execAsync(`npm install ${packages.join(\" \")}`, {\n cwd: this.configDir,\n timeout: 120000,\n });\n }\n\n async copyCommands(): Promise<string[]> {\n const commandsDir = CONFIG_PATHS.commandsDir;\n await this.ensureDir(commandsDir);\n\n const packageRoot = getPackageRoot();\n const sourceCommandsDir = join(packageRoot, \"commands\");\n\n const copiedFiles: string[] = [];\n\n if (existsSync(sourceCommandsDir)) {\n const files = await readdir(sourceCommandsDir);\n for (const file of files) {\n if (file.endsWith(\".md\")) {\n const sourcePath = join(sourceCommandsDir, file);\n const destPath = join(commandsDir, file);\n await copyFile(sourcePath, destPath);\n copiedFiles.push(file);\n }\n }\n }\n\n return copiedFiles;\n }\n\n async installOhMyOpencode(): Promise<void> {\n await execAsync(\"npx -y oh-my-opencode@latest install\", { timeout: 120000 });\n }\n\n async installGitHubExtensions(): Promise<GitHubExtensionResult> {\n const extensions = [\n \"jwilger/gh-issue-ext\",\n \"jwilger/gh-project-ext\",\n \"agynio/gh-pr-review\",\n ];\n\n const result: GitHubExtensionResult = {\n installed: [],\n skipped: [],\n failed: [],\n };\n\n let installedExtensions: string[] = [];\n try {\n const { stdout } = await execAsync(\"gh extension list\", { timeout: 10000 });\n installedExtensions = stdout\n .split(\"\\n\")\n .map((line) => line.split(\"\\t\")[0])\n .filter((name): name is string => Boolean(name));\n } catch {\n installedExtensions = [];\n }\n\n for (const ext of extensions) {\n const extName = ext.split(\"/\")[1] ?? ext;\n\n if (installedExtensions.some((installed) => installed.includes(extName))) {\n result.skipped.push(ext);\n continue;\n }\n\n try {\n await execAsync(`gh extension install ${ext}`, { timeout: 60000 });\n result.installed.push(ext);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n result.failed.push({ name: ext, error: message });\n }\n }\n\n return result;\n }\n}\n","import { execSync } from \"node:child_process\";\n\ninterface PrereqResult {\n installed: boolean;\n version?: string;\n}\n\ninterface OpencodePrereq extends PrereqResult {\n models: string[];\n}\n\nexport interface Prerequisites {\n node: PrereqResult;\n opencode: OpencodePrereq;\n ohMyOpencode: PrereqResult;\n gh: PrereqResult;\n}\n\nfunction checkBinary(command: string): PrereqResult {\n try {\n const version = execSync(command, { encoding: \"utf-8\" }).trim();\n return { installed: true, version };\n } catch {\n return { installed: false };\n }\n}\n\nexport function checkPrerequisites(): Prerequisites {\n const node = checkBinary(\"node --version\");\n const opencode = checkBinary(\"opencode --version\");\n const ohMyOpencode = checkBinary(\"opencode --help | grep -q oh-my-opencode && echo installed\");\n const gh = checkBinary(\"gh --version\");\n\n const models = opencode.installed ? getOpencodeModels() : [];\n\n return {\n node,\n opencode: { ...opencode, models },\n ohMyOpencode,\n gh,\n };\n}\n\nfunction getOpencodeModels(): string[] {\n try {\n const output = execSync(\"opencode models --json\", { encoding: \"utf-8\" });\n const parsed = JSON.parse(output) as { id: string }[];\n return parsed.map((model) => model.id);\n } catch {\n return [];\n }\n}\n","import kleur from \"kleur\";\nimport { DISPLAY_NAME } from \"../../shared/constants.js\";\n\nconst writeLine = (message: string): void => {\n process.stdout.write(`${message}\\n`);\n};\n\nconst writeErrorLine = (message: string): void => {\n process.stderr.write(`${message}\\n`);\n};\n\nexport const logger = {\n banner(): void {\n writeLine(kleur.cyan().bold(`\\n${DISPLAY_NAME}`));\n writeLine(kleur.gray(\"====================================\\n\"));\n },\n section(title: string): void {\n writeLine(kleur.cyan(`\\n${title}`));\n },\n info(message: string): void {\n writeLine(kleur.gray(message));\n },\n warn(message: string): void {\n writeErrorLine(kleur.yellow(message));\n },\n error(message: string): void {\n writeErrorLine(kleur.red(message));\n },\n success(message: string): void {\n writeLine(kleur.green(message));\n },\n successBanner(message: string): void {\n writeLine(kleur.green().bold(`\\n${message}\\n`));\n },\n};\n","import kleur from \"kleur\";\nimport { logger } from \"../utils/logger.js\";\nimport { checkPrerequisites } from \"../utils/prerequisites.js\";\n\ninterface DoctorOptions {\n fix?: boolean;\n}\n\nexport function doctor(_options: DoctorOptions): void {\n logger.banner();\n\n const prereqs = checkPrerequisites();\n\n logger.section(\"Prerequisites\");\n const nodeVersion = prereqs.node.installed ? prereqs.node.version ?? \"unknown\" : \"missing\";\n const opencodeVersion = prereqs.opencode.installed ? prereqs.opencode.version ?? \"unknown\" : \"missing\";\n const ohMyOpencodeStatus = prereqs.ohMyOpencode.installed ? \"installed\" : \"missing\";\n const ghVersion = prereqs.gh.installed ? prereqs.gh.version ?? \"unknown\" : \"missing\";\n\n logger.info(kleur.gray(`Node.js: ${nodeVersion}`));\n logger.info(kleur.gray(`OpenCode: ${opencodeVersion}`));\n logger.info(kleur.gray(`oh-my-opencode: ${ohMyOpencodeStatus}`));\n logger.info(kleur.gray(`GitHub CLI: ${ghVersion}`));\n logger.info(\"\");\n\n if (!prereqs.node.installed || !prereqs.opencode.installed || !prereqs.ohMyOpencode.installed) {\n logger.warn(\"Missing required dependencies. Please install them and retry.\");\n }\n\n if (!prereqs.gh.installed) {\n logger.warn(\"GitHub CLI not installed. Install it from https://cli.github.com/\");\n }\n\n logger.info(\"Doctor completed. No automatic fixes implemented yet.\");\n}\n","import kleur from \"kleur\";\nimport { logger } from \"../utils/logger.js\";\n\ninterface UpgradeOptions {\n check?: boolean;\n yes?: boolean;\n}\n\nexport function upgrade(options: UpgradeOptions): void {\n logger.banner();\n\n if (options.check === true) {\n logger.info(\"Upgrade check not implemented yet.\");\n return;\n }\n\n logger.warn(\"Upgrade workflow not implemented yet.\");\n logger.info(kleur.gray(\"Re-run opencode-sdlc-plugin install to regenerate configs.\"));\n}\n"],"mappings":"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","names":["kleur","kleur","join","join","join","join","existsSync","readFileSync","join","join","existsSync","join","join","existsSync","join","kleur","kleur","kleur","kleur","kleur","kleur"]}
|
package/dist/index.js
CHANGED
|
@@ -29,34 +29,36 @@ var VALID_TRANSITIONS = {
|
|
|
29
29
|
};
|
|
30
30
|
function createToolHooks(tracker, config) {
|
|
31
31
|
return {
|
|
32
|
-
before:
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
32
|
+
before: (input, output) => {
|
|
33
|
+
return Promise.resolve().then(() => {
|
|
34
|
+
if (input.tool === "sdlc_update_state") {
|
|
35
|
+
const args = output.args;
|
|
36
|
+
if (args.currentPhase) {
|
|
37
|
+
const current = tracker.getState().currentPhase;
|
|
38
|
+
const allowed = VALID_TRANSITIONS[current] ?? [];
|
|
39
|
+
if (!allowed.includes(args.currentPhase)) {
|
|
40
|
+
throw new Error(
|
|
41
|
+
`Invalid TDD transition: ${current} -> ${args.currentPhase}. Allowed transitions: ${allowed.join(", ")}. Follow RED \u2192 DOMAIN \u2192 GREEN \u2192 DOMAIN \u2192 REFACTOR.`
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
if (input.tool === "edit" || input.tool === "write") {
|
|
47
|
+
const state2 = tracker.getState();
|
|
48
|
+
const args = output.args;
|
|
49
|
+
const filePath = args.filePath ?? "";
|
|
50
|
+
if (filePath.length === 0) return;
|
|
51
|
+
const allowedPatterns = getAllowedPatterns(config, state2.currentPhase);
|
|
52
|
+
if (allowedPatterns.length > 0 && !matchesAnyPattern(filePath, allowedPatterns)) {
|
|
39
53
|
throw new Error(
|
|
40
|
-
`
|
|
54
|
+
`File ownership violation in phase '${state2.currentPhase}'. Allowed patterns: ${allowedPatterns.join(", ")}. Attempted: ${filePath}. Delegate to the correct agent.`
|
|
41
55
|
);
|
|
42
56
|
}
|
|
43
57
|
}
|
|
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
|
-
}
|
|
58
|
+
});
|
|
57
59
|
},
|
|
58
|
-
after:
|
|
59
|
-
return;
|
|
60
|
+
after: (_input, _output) => {
|
|
61
|
+
return Promise.resolve();
|
|
60
62
|
}
|
|
61
63
|
};
|
|
62
64
|
}
|
|
@@ -209,7 +211,7 @@ function createPartyReviewTool() {
|
|
|
209
211
|
decision: tool5.schema.enum(["accept", "defer", "reject"]).optional(),
|
|
210
212
|
reason: tool5.schema.string().optional()
|
|
211
213
|
},
|
|
212
|
-
execute: async (args) => {
|
|
214
|
+
execute: async (args) => Promise.resolve().then(() => {
|
|
213
215
|
if (args.action === "start") {
|
|
214
216
|
const findings = args.findings;
|
|
215
217
|
if (!findings || findings.length === 0) {
|
|
@@ -254,7 +256,7 @@ function createPartyReviewTool() {
|
|
|
254
256
|
return JSON.stringify({ summary }, null, 2);
|
|
255
257
|
}
|
|
256
258
|
return JSON.stringify({ error: "unknown action" });
|
|
257
|
-
}
|
|
259
|
+
})
|
|
258
260
|
});
|
|
259
261
|
}
|
|
260
262
|
|
package/dist/index.js.map
CHANGED
|
@@ -1 +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"]}
|
|
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: (input: BeforeHookInput, output: BeforeHookOutput): Promise<void> => {\n return Promise.resolve().then(() => {\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\n after: (_input: AfterHookInput, _output: AfterHookOutput): Promise<void> => {\n return Promise.resolve();\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 Promise.resolve().then(() => {\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.2.1\";\nexport const DISPLAY_NAME = \"OpenCode SDLC Plugin\";\nexport const TAGLINE = \"Agentic SDLC workflow with discovery, ADRs, and TDD\";\n\nexport const PACKAGE_NAME = \"opencode-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"]}
|
package/dist/plugin/index.js
CHANGED
|
@@ -29,34 +29,36 @@ var VALID_TRANSITIONS = {
|
|
|
29
29
|
};
|
|
30
30
|
function createToolHooks(tracker, config) {
|
|
31
31
|
return {
|
|
32
|
-
before:
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
32
|
+
before: (input, output) => {
|
|
33
|
+
return Promise.resolve().then(() => {
|
|
34
|
+
if (input.tool === "sdlc_update_state") {
|
|
35
|
+
const args = output.args;
|
|
36
|
+
if (args.currentPhase) {
|
|
37
|
+
const current = tracker.getState().currentPhase;
|
|
38
|
+
const allowed = VALID_TRANSITIONS[current] ?? [];
|
|
39
|
+
if (!allowed.includes(args.currentPhase)) {
|
|
40
|
+
throw new Error(
|
|
41
|
+
`Invalid TDD transition: ${current} -> ${args.currentPhase}. Allowed transitions: ${allowed.join(", ")}. Follow RED \u2192 DOMAIN \u2192 GREEN \u2192 DOMAIN \u2192 REFACTOR.`
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
if (input.tool === "edit" || input.tool === "write") {
|
|
47
|
+
const state2 = tracker.getState();
|
|
48
|
+
const args = output.args;
|
|
49
|
+
const filePath = args.filePath ?? "";
|
|
50
|
+
if (filePath.length === 0) return;
|
|
51
|
+
const allowedPatterns = getAllowedPatterns(config, state2.currentPhase);
|
|
52
|
+
if (allowedPatterns.length > 0 && !matchesAnyPattern(filePath, allowedPatterns)) {
|
|
39
53
|
throw new Error(
|
|
40
|
-
`
|
|
54
|
+
`File ownership violation in phase '${state2.currentPhase}'. Allowed patterns: ${allowedPatterns.join(", ")}. Attempted: ${filePath}. Delegate to the correct agent.`
|
|
41
55
|
);
|
|
42
56
|
}
|
|
43
57
|
}
|
|
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
|
-
}
|
|
58
|
+
});
|
|
57
59
|
},
|
|
58
|
-
after:
|
|
59
|
-
return;
|
|
60
|
+
after: (_input, _output) => {
|
|
61
|
+
return Promise.resolve();
|
|
60
62
|
}
|
|
61
63
|
};
|
|
62
64
|
}
|
|
@@ -209,7 +211,7 @@ function createPartyReviewTool() {
|
|
|
209
211
|
decision: tool5.schema.enum(["accept", "defer", "reject"]).optional(),
|
|
210
212
|
reason: tool5.schema.string().optional()
|
|
211
213
|
},
|
|
212
|
-
execute: async (args) => {
|
|
214
|
+
execute: async (args) => Promise.resolve().then(() => {
|
|
213
215
|
if (args.action === "start") {
|
|
214
216
|
const findings = args.findings;
|
|
215
217
|
if (!findings || findings.length === 0) {
|
|
@@ -254,7 +256,7 @@ function createPartyReviewTool() {
|
|
|
254
256
|
return JSON.stringify({ summary }, null, 2);
|
|
255
257
|
}
|
|
256
258
|
return JSON.stringify({ error: "unknown action" });
|
|
257
|
-
}
|
|
259
|
+
})
|
|
258
260
|
});
|
|
259
261
|
}
|
|
260
262
|
|
package/dist/plugin/index.js.map
CHANGED
|
@@ -1 +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;AAEA,IAAO,iBAAQ;","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"]}
|
|
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: (input: BeforeHookInput, output: BeforeHookOutput): Promise<void> => {\n return Promise.resolve().then(() => {\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\n after: (_input: AfterHookInput, _output: AfterHookOutput): Promise<void> => {\n return Promise.resolve();\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 Promise.resolve().then(() => {\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.2.1\";\nexport const DISPLAY_NAME = \"OpenCode SDLC Plugin\";\nexport const TAGLINE = \"Agentic SDLC workflow with discovery, ADRs, and TDD\";\n\nexport const PACKAGE_NAME = \"opencode-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"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "opencode-sdlc-plugin",
|
|
3
|
-
"version": "0.1
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"description": "OpenCode SDLC workflow plugin with event modeling, ADRs, and TDD orchestration",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -29,7 +29,8 @@
|
|
|
29
29
|
"test:watch": "vitest",
|
|
30
30
|
"test:coverage": "vitest run --coverage",
|
|
31
31
|
"test:integration": "vitest run --config vitest.integration.config.ts",
|
|
32
|
-
"test:coverage:integration": "vitest run --coverage --config vitest.integration.config.ts"
|
|
32
|
+
"test:coverage:integration": "vitest run --coverage --config vitest.integration.config.ts",
|
|
33
|
+
"prepublishOnly": "npm run build"
|
|
33
34
|
},
|
|
34
35
|
"dependencies": {
|
|
35
36
|
"@inquirer/prompts": "^7.1.0",
|