@ai-sdlc/orchestrator 0.2.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -55,6 +55,6 @@ export declare function scanPipelineAdapters(options: ScanOptions): Promise<Scan
55
55
  * Requires `GITHUB_REPOSITORY_OWNER` and `GITHUB_REPOSITORY` env vars.
56
56
  */
57
57
  export declare function createPipelineCIAdapter(): CIPipeline;
58
- export { createGitHubCIPipeline, createDockerSandbox, createLinearIssueTracker, resolveSecret, createGitLabSourceControl, createGitLabCIPipeline, createJiraIssueTracker, createWebhookServer, createGitHubWebhookProvider, verifyGitHubSignature, createGitLabWebhookProvider, verifyGitLabToken, createJiraWebhookProvider, createLinearWebhookProvider, verifyLinearSignature, createAdapterRegistry, validateAdapterMetadata, parseMetadataYaml, scanLocalAdapters, createStubCodeAnalysis, createStubMessenger, createStubDeploymentTarget, createStubGitLabCI, createStubGitLabSource, createStubJira, createStubBitbucket, createStubSonarQube, createStubSemgrep, createInMemoryAuditSink, createFileSink, createEnvSecretStore, createInMemoryMemoryStore, createInProcessEventBus, createStubSandbox, createWebhookBridge, parseGitAdapterRef, buildRawUrl, createGitAdapterFetcher, createStubGitAdapterFetcher, resolveGitAdapter, } from '@ai-sdlc/reference';
59
- export type { AdapterRegistry, AdapterMetadata, AdapterStability, AdapterFactory, MetadataValidationResult, ScanOptions, ScanResult, WebhookBridge, WebhookTransformer, GitAdapterReference, GitAdapterFetcher, GitResolveResult, CIPipeline, CodeAnalysis, Messenger, DeploymentTarget, EventBus, IssueTracker, LinearClientLike, IssueComment, AdapterInterfaces, EventStream, IssueFilter, CommitStatus, TestResults, CoverageReport, Finding, SeveritySummary, DeploymentStatus, StubCodeAnalysisConfig, StubCodeAnalysisAdapter, NotificationLogEntry, StubMessengerAdapter, StubDeploymentTargetAdapter, StubGitLabCIAdapter, StubGitLabSourceAdapter, StubJiraAdapter, StubBitbucketAdapter, StubSonarQubeConfig, StubSonarQubeAdapter, StubSemgrepConfig, StubSemgrepAdapter, AuditSink, AuditLog, InMemoryAuditSink, SecretStore, Sandbox, MemoryStore, InMemoryMemoryStore, InProcessEventBus, DockerSandboxConfig, BuildStatus, GitLabConfig, JiraConfig, WebhookServer, WebhookServerConfig, WebhookProviderConfig, GitHubWebhookConfig, GitHubWebhookBridges, GitLabWebhookConfig, JiraWebhookConfig, LinearWebhookConfig, } from '@ai-sdlc/reference';
58
+ export { createGitHubCIPipeline, createDockerSandbox, createLinearIssueTracker, resolveSecret, createGitLabSourceControl, createGitLabCIPipeline, createJiraIssueTracker, createBacklogMdIssueTracker, createWebhookServer, createGitHubWebhookProvider, verifyGitHubSignature, createGitLabWebhookProvider, verifyGitLabToken, createJiraWebhookProvider, createLinearWebhookProvider, verifyLinearSignature, createAdapterRegistry, validateAdapterMetadata, parseMetadataYaml, scanLocalAdapters, createStubCodeAnalysis, createStubMessenger, createStubDeploymentTarget, createStubGitLabCI, createStubGitLabSource, createStubJira, createStubBitbucket, createStubSonarQube, createStubSemgrep, createInMemoryAuditSink, createFileSink, createEnvSecretStore, createInMemoryMemoryStore, createInProcessEventBus, createStubSandbox, createWebhookBridge, parseGitAdapterRef, buildRawUrl, createGitAdapterFetcher, createStubGitAdapterFetcher, resolveGitAdapter, } from '@ai-sdlc/reference';
59
+ export type { AdapterRegistry, AdapterMetadata, AdapterStability, AdapterFactory, MetadataValidationResult, ScanOptions, ScanResult, WebhookBridge, WebhookTransformer, GitAdapterReference, GitAdapterFetcher, GitResolveResult, CIPipeline, CodeAnalysis, Messenger, DeploymentTarget, EventBus, IssueTracker, LinearClientLike, IssueComment, AdapterInterfaces, EventStream, IssueFilter, CommitStatus, TestResults, CoverageReport, Finding, SeveritySummary, DeploymentStatus, StubCodeAnalysisConfig, StubCodeAnalysisAdapter, NotificationLogEntry, StubMessengerAdapter, StubDeploymentTargetAdapter, StubGitLabCIAdapter, StubGitLabSourceAdapter, StubJiraAdapter, StubBitbucketAdapter, StubSonarQubeConfig, StubSonarQubeAdapter, StubSemgrepConfig, StubSemgrepAdapter, AuditSink, AuditLog, InMemoryAuditSink, SecretStore, Sandbox, MemoryStore, InMemoryMemoryStore, InProcessEventBus, DockerSandboxConfig, BuildStatus, GitLabConfig, JiraConfig, BacklogMdConfig, BacklogFs, WebhookServer, WebhookServerConfig, WebhookProviderConfig, GitHubWebhookConfig, GitHubWebhookBridges, GitLabWebhookConfig, JiraWebhookConfig, LinearWebhookConfig, } from '@ai-sdlc/reference';
60
60
  //# sourceMappingURL=adapters.d.ts.map
package/dist/adapters.js CHANGED
@@ -14,6 +14,8 @@ createStubCodeAnalysis, createStubMessenger, createStubDeploymentTarget, createS
14
14
  createInMemoryAuditSink, createFileSink, createAuditLog, createEnvSecretStore, createInMemoryMemoryStore, createInProcessEventBus, createStubSandbox,
15
15
  // Docker sandbox
16
16
  createDockerSandbox,
17
+ // Backlog.md adapter
18
+ createBacklogMdIssueTracker,
17
19
  // Webhook bridge (used in function body)
18
20
  createWebhookBridge,
19
21
  // Git resolver (used in function bodies)
@@ -45,6 +47,7 @@ export function createPipelineAdapterRegistry() {
45
47
  registry.register(stubMeta('bitbucket-stub', 'Bitbucket', 'SourceControl', 'bitbucket'), () => createStubBitbucket());
46
48
  registry.register(stubMeta('sonarqube-stub', 'SonarQube', 'CodeAnalysis', 'sonarqube'), () => createStubSonarQube());
47
49
  registry.register(stubMeta('semgrep-stub', 'Semgrep', 'CodeAnalysis', 'semgrep'), () => createStubSemgrep());
50
+ registry.register(stubMeta('backlog-md', 'Backlog.md', 'IssueTracker', 'backlog-md'), () => createBacklogMdIssueTracker({ backlogDir: process.env.AI_SDLC_BACKLOG_DIR ?? './backlog' }));
48
51
  // Infrastructure adapter stubs
49
52
  registry.register(stubMeta('memory-audit-sink', 'In-Memory Audit Sink', 'AuditSink@v1', 'memory'), () => createInMemoryAuditSink());
50
53
  // file-audit-sink is registered metadata-only; the actual file path is
@@ -143,6 +146,8 @@ export {
143
146
  createGitHubCIPipeline, createDockerSandbox, createLinearIssueTracker, resolveSecret,
144
147
  // Production adapters
145
148
  createGitLabSourceControl, createGitLabCIPipeline, createJiraIssueTracker,
149
+ // Backlog.md adapter
150
+ createBacklogMdIssueTracker,
146
151
  // Webhook server
147
152
  createWebhookServer,
148
153
  // Webhook providers
@@ -2,8 +2,10 @@
2
2
  * ai-sdlc init — initialize a project with AI-SDLC config files.
3
3
  */
4
4
  import { Command } from 'commander';
5
- import { existsSync, mkdirSync, writeFileSync } from 'node:fs';
6
- import { join } from 'node:path';
5
+ import { existsSync, mkdirSync, writeFileSync, readFileSync, appendFileSync } from 'node:fs';
6
+ import { join, basename } from 'node:path';
7
+ import { detectAgents, installMcpServer } from './mcp-setup.js';
8
+ import { detectWorkspace, generateWorkspaceYaml } from './workspace-detect.js';
7
9
  const PIPELINE_YAML = `apiVersion: ai-sdlc.io/v1alpha1
8
10
  kind: Pipeline
9
11
  metadata:
@@ -132,23 +134,42 @@ spec:
132
134
  action: demote-one-level
133
135
  cooldown: 2w
134
136
  `;
135
- export const initCommand = new Command('init')
136
- .description('Initialize AI-SDLC configuration in the current project')
137
- .option('--dry-run', 'Show what would be created without writing files')
138
- .option('-d, --dir <path>', 'Config directory name', '.ai-sdlc')
139
- .action(async (opts) => {
140
- const configDir = join(process.cwd(), opts.dir ?? '.ai-sdlc');
137
+ const GITIGNORE_ENTRIES = [
138
+ '# AI-SDLC runtime artifacts',
139
+ '.ai-sdlc/state.db',
140
+ '.ai-sdlc/state/',
141
+ '.ai-sdlc/audit.jsonl',
142
+ ];
143
+ /** Ensure .gitignore includes AI-SDLC runtime artifact entries. */
144
+ function ensureGitignore(projectDir, dryRun, prefix = '') {
145
+ const gitignorePath = join(projectDir, '.gitignore');
146
+ const existing = existsSync(gitignorePath) ? readFileSync(gitignorePath, 'utf-8') : '';
147
+ const missing = GITIGNORE_ENTRIES.filter((entry) => !existing.includes(entry));
148
+ if (missing.length === 0)
149
+ return;
150
+ if (dryRun) {
151
+ console.log(`${prefix} Would update .gitignore`);
152
+ return;
153
+ }
154
+ const block = '\n' + missing.join('\n') + '\n';
155
+ appendFileSync(gitignorePath, block, 'utf-8');
156
+ console.log(`${prefix} updated .gitignore`);
157
+ }
158
+ /** Initialize a single project directory with AI-SDLC config files. */
159
+ function initProject(projectDir, configDirName, dryRun, prefix = '') {
160
+ const configDir = join(projectDir, configDirName);
141
161
  const files = [
142
162
  { name: 'pipeline.yaml', content: PIPELINE_YAML },
143
163
  { name: 'agent-role.yaml', content: AGENT_ROLE_YAML },
144
164
  { name: 'quality-gate.yaml', content: QUALITY_GATE_YAML },
145
165
  { name: 'autonomy-policy.yaml', content: AUTONOMY_POLICY_YAML },
146
166
  ];
147
- if (opts.dryRun) {
148
- console.log(`Would create ${configDir}/`);
167
+ if (dryRun) {
168
+ console.log(`${prefix}Would create ${configDir}/`);
149
169
  for (const f of files) {
150
- console.log(` ${f.name}`);
170
+ console.log(`${prefix} ${f.name}`);
151
171
  }
172
+ ensureGitignore(projectDir, true, prefix);
152
173
  return;
153
174
  }
154
175
  if (!existsSync(configDir)) {
@@ -157,20 +178,90 @@ export const initCommand = new Command('init')
157
178
  for (const f of files) {
158
179
  const path = join(configDir, f.name);
159
180
  if (existsSync(path)) {
160
- console.log(` skip ${f.name} (already exists)`);
181
+ console.log(`${prefix} skip ${f.name} (already exists)`);
161
182
  }
162
183
  else {
163
184
  writeFileSync(path, f.content, 'utf-8');
164
- console.log(` created ${f.name}`);
185
+ console.log(`${prefix} created ${f.name}`);
165
186
  }
166
187
  }
167
- // Create state directory for SQLite store
168
- const stateDir = join(configDir, 'state');
169
- if (!existsSync(stateDir)) {
170
- mkdirSync(stateDir, { recursive: true });
171
- console.log(` created state/`);
188
+ ensureGitignore(projectDir, false, prefix);
189
+ }
190
+ /** Initialize the workspace root with workspace.yaml. */
191
+ function initWorkspaceRoot(workspacePath, repos, configDirName, dryRun) {
192
+ const configDir = join(workspacePath, configDirName);
193
+ const workspaceFile = join(configDir, 'workspace.yaml');
194
+ const workspaceName = basename(workspacePath);
195
+ const yaml = generateWorkspaceYaml(workspaceName, repos);
196
+ if (dryRun) {
197
+ console.log(`Would create ${configDir}/`);
198
+ console.log(` workspace.yaml`);
199
+ return;
200
+ }
201
+ if (!existsSync(configDir)) {
202
+ mkdirSync(configDir, { recursive: true });
203
+ }
204
+ if (existsSync(workspaceFile)) {
205
+ console.log(` skip workspace.yaml (already exists)`);
206
+ }
207
+ else {
208
+ writeFileSync(workspaceFile, yaml, 'utf-8');
209
+ console.log(` created workspace.yaml`);
210
+ }
211
+ }
212
+ export const initCommand = new Command('init')
213
+ .description('Initialize AI-SDLC configuration in the current project')
214
+ .option('--dry-run', 'Show what would be created without writing files')
215
+ .option('--skip-mcp', 'Skip MCP server auto-configuration')
216
+ .option('-d, --dir <path>', 'Config directory name', '.ai-sdlc')
217
+ .action(async (opts) => {
218
+ const projectDir = process.cwd();
219
+ const configDirName = opts.dir ?? '.ai-sdlc';
220
+ const dryRun = !!opts.dryRun;
221
+ // Detect workspace (multi-repo parent directory)
222
+ const workspace = detectWorkspace(projectDir);
223
+ if (workspace.isWorkspace) {
224
+ console.log(`Workspace detected with ${workspace.repos.length} repositories:`);
225
+ for (const repo of workspace.repos) {
226
+ console.log(` ${repo.name} (${repo.path})`);
227
+ }
228
+ console.log('');
229
+ // Initialize workspace root with workspace.yaml
230
+ initWorkspaceRoot(projectDir, workspace.repos, configDirName, dryRun);
231
+ // Cascade into each child repo
232
+ for (const repo of workspace.repos) {
233
+ console.log(`\n${repo.name}/`);
234
+ initProject(repo.absPath, configDirName, dryRun, ' ');
235
+ }
236
+ // MCP setup at workspace root (serves all repos)
237
+ if (!opts.skipMcp) {
238
+ const agents = detectAgents(projectDir, { isWorkspace: true });
239
+ console.log(`\nMCP server setup (workspace root):`);
240
+ console.log(` detected ${agents.map((a) => a.name).join(', ')}`);
241
+ for (const agent of agents) {
242
+ const status = installMcpServer(projectDir, agent, dryRun);
243
+ const pad = status === 'merged' ? ' ' : '';
244
+ console.log(` ${status}${pad} ${agent.configPath} (${agent.name})`);
245
+ }
246
+ }
247
+ console.log(`\nAI-SDLC workspace initialized in ${projectDir}/`);
248
+ console.log(`Run 'ai-sdlc health' to verify your configuration.`);
249
+ }
250
+ else {
251
+ // Single-repo mode (original behavior)
252
+ initProject(projectDir, configDirName, dryRun);
253
+ if (!opts.skipMcp) {
254
+ const agents = detectAgents(projectDir);
255
+ console.log(`\nMCP server setup:`);
256
+ console.log(` detected ${agents.map((a) => a.name).join(', ')}`);
257
+ for (const agent of agents) {
258
+ const status = installMcpServer(projectDir, agent, dryRun);
259
+ const pad = status === 'merged' ? ' ' : '';
260
+ console.log(` ${status}${pad} ${agent.configPath} (${agent.name})`);
261
+ }
262
+ }
263
+ console.log(`\nAI-SDLC config initialized in ${join(projectDir, configDirName)}/`);
264
+ console.log(`Run 'ai-sdlc health' to verify your configuration.`);
172
265
  }
173
- console.log(`\nAI-SDLC config initialized in ${configDir}/`);
174
- console.log(`Run 'ai-sdlc health' to verify your configuration.`);
175
266
  });
176
267
  //# sourceMappingURL=init.js.map
@@ -0,0 +1,16 @@
1
+ /**
2
+ * MCP server setup — detect coding agents and install MCP config.
3
+ */
4
+ export interface DetectedAgent {
5
+ name: string;
6
+ configPath: string;
7
+ configKey: string;
8
+ serverEntry: Record<string, unknown>;
9
+ }
10
+ export interface DetectAgentsOptions {
11
+ /** When true, adds AI_SDLC_WORKSPACE env to server entries. */
12
+ isWorkspace?: boolean;
13
+ }
14
+ export declare function detectAgents(projectDir: string, options?: DetectAgentsOptions): DetectedAgent[];
15
+ export declare function installMcpServer(projectDir: string, agent: DetectedAgent, dryRun: boolean): 'created' | 'merged' | 'skipped';
16
+ //# sourceMappingURL=mcp-setup.d.ts.map
@@ -0,0 +1,131 @@
1
+ /**
2
+ * MCP server setup — detect coding agents and install MCP config.
3
+ */
4
+ import { existsSync, readFileSync, mkdirSync, writeFileSync } from 'node:fs';
5
+ import { join, dirname } from 'node:path';
6
+ import { execSync } from 'node:child_process';
7
+ function standardEntry(env) {
8
+ const entry = {
9
+ command: 'npx',
10
+ args: ['-y', '@ai-sdlc/mcp-advisor'],
11
+ };
12
+ if (env)
13
+ entry.env = env;
14
+ return entry;
15
+ }
16
+ function vscodeEntry(env) {
17
+ const entry = {
18
+ type: 'stdio',
19
+ command: 'npx',
20
+ args: ['-y', '@ai-sdlc/mcp-advisor'],
21
+ };
22
+ if (env)
23
+ entry.env = env;
24
+ return entry;
25
+ }
26
+ const AGENT_SPECS = [
27
+ {
28
+ name: 'Claude Code',
29
+ configPath: '.mcp.json',
30
+ configKey: 'mcpServers',
31
+ entryFn: standardEntry,
32
+ binary: 'claude',
33
+ alwaysDetect: true,
34
+ },
35
+ {
36
+ name: 'Cursor',
37
+ configPath: '.cursor/mcp.json',
38
+ configKey: 'mcpServers',
39
+ entryFn: standardEntry,
40
+ configDir: '.cursor',
41
+ binary: 'cursor',
42
+ },
43
+ {
44
+ name: 'VS Code',
45
+ configPath: '.vscode/mcp.json',
46
+ configKey: 'servers',
47
+ entryFn: vscodeEntry,
48
+ configDir: '.vscode',
49
+ binary: 'code',
50
+ },
51
+ {
52
+ name: 'Windsurf',
53
+ configPath: '.windsurf/mcp.json',
54
+ configKey: 'mcpServers',
55
+ entryFn: standardEntry,
56
+ configDir: '.windsurf',
57
+ binary: 'windsurf',
58
+ },
59
+ ];
60
+ function hasBinary(name) {
61
+ try {
62
+ execSync(`which ${name}`, { stdio: 'ignore' });
63
+ return true;
64
+ }
65
+ catch {
66
+ return false;
67
+ }
68
+ }
69
+ export function detectAgents(projectDir, options) {
70
+ const detected = [];
71
+ const env = options?.isWorkspace ? { AI_SDLC_WORKSPACE: '.' } : undefined;
72
+ for (const spec of AGENT_SPECS) {
73
+ if (spec.alwaysDetect) {
74
+ detected.push({
75
+ name: spec.name,
76
+ configPath: spec.configPath,
77
+ configKey: spec.configKey,
78
+ serverEntry: spec.entryFn(env),
79
+ });
80
+ continue;
81
+ }
82
+ const hasDir = spec.configDir ? existsSync(join(projectDir, spec.configDir)) : false;
83
+ const hasBin = spec.binary ? hasBinary(spec.binary) : false;
84
+ if (hasDir || hasBin) {
85
+ detected.push({
86
+ name: spec.name,
87
+ configPath: spec.configPath,
88
+ configKey: spec.configKey,
89
+ serverEntry: spec.entryFn(env),
90
+ });
91
+ }
92
+ }
93
+ return detected;
94
+ }
95
+ export function installMcpServer(projectDir, agent, dryRun) {
96
+ const fullPath = join(projectDir, agent.configPath);
97
+ if (existsSync(fullPath)) {
98
+ let existing;
99
+ try {
100
+ existing = JSON.parse(readFileSync(fullPath, 'utf-8'));
101
+ }
102
+ catch {
103
+ // If the file is malformed JSON, treat as new
104
+ existing = {};
105
+ }
106
+ const section = (existing[agent.configKey] ?? {});
107
+ if (section['ai-sdlc']) {
108
+ return 'skipped';
109
+ }
110
+ if (!dryRun) {
111
+ section['ai-sdlc'] = agent.serverEntry;
112
+ existing[agent.configKey] = section;
113
+ writeFileSync(fullPath, JSON.stringify(existing, null, 2) + '\n', 'utf-8');
114
+ }
115
+ return 'merged';
116
+ }
117
+ if (!dryRun) {
118
+ const dir = dirname(fullPath);
119
+ if (!existsSync(dir)) {
120
+ mkdirSync(dir, { recursive: true });
121
+ }
122
+ const config = {
123
+ [agent.configKey]: {
124
+ 'ai-sdlc': agent.serverEntry,
125
+ },
126
+ };
127
+ writeFileSync(fullPath, JSON.stringify(config, null, 2) + '\n', 'utf-8');
128
+ }
129
+ return 'created';
130
+ }
131
+ //# sourceMappingURL=mcp-setup.js.map
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Workspace detection — identify multi-repo workspaces and child repositories.
3
+ */
4
+ export interface WorkspaceRepo {
5
+ name: string;
6
+ path: string;
7
+ absPath: string;
8
+ }
9
+ export interface WorkspaceInfo {
10
+ isWorkspace: boolean;
11
+ workspacePath: string;
12
+ repos: WorkspaceRepo[];
13
+ }
14
+ /**
15
+ * Detect if a directory is a multi-repo workspace root.
16
+ * A workspace root is a directory that:
17
+ * 1. Is NOT itself a git repository
18
+ * 2. Contains at least 2 child directories that ARE git repositories
19
+ */
20
+ export declare function detectWorkspace(dir: string): WorkspaceInfo;
21
+ export declare function generateWorkspaceYaml(workspaceName: string, repos: WorkspaceRepo[]): string;
22
+ //# sourceMappingURL=workspace-detect.d.ts.map
@@ -0,0 +1,65 @@
1
+ /**
2
+ * Workspace detection — identify multi-repo workspaces and child repositories.
3
+ */
4
+ import { existsSync, readdirSync, statSync } from 'node:fs';
5
+ import { join, resolve } from 'node:path';
6
+ /**
7
+ * Detect if a directory is a multi-repo workspace root.
8
+ * A workspace root is a directory that:
9
+ * 1. Is NOT itself a git repository
10
+ * 2. Contains at least 2 child directories that ARE git repositories
11
+ */
12
+ export function detectWorkspace(dir) {
13
+ const absDir = resolve(dir);
14
+ const isGitRepo = existsSync(join(absDir, '.git'));
15
+ if (isGitRepo) {
16
+ return { isWorkspace: false, workspacePath: absDir, repos: [] };
17
+ }
18
+ const repos = [];
19
+ let entries;
20
+ try {
21
+ entries = readdirSync(absDir);
22
+ }
23
+ catch {
24
+ return { isWorkspace: false, workspacePath: absDir, repos: [] };
25
+ }
26
+ for (const entry of entries) {
27
+ if (entry.startsWith('.'))
28
+ continue;
29
+ const childPath = join(absDir, entry);
30
+ try {
31
+ if (!statSync(childPath).isDirectory())
32
+ continue;
33
+ }
34
+ catch {
35
+ continue;
36
+ }
37
+ if (existsSync(join(childPath, '.git'))) {
38
+ repos.push({
39
+ name: entry,
40
+ path: `./${entry}`,
41
+ absPath: childPath,
42
+ });
43
+ }
44
+ }
45
+ return {
46
+ isWorkspace: repos.length >= 2,
47
+ workspacePath: absDir,
48
+ repos,
49
+ };
50
+ }
51
+ const WORKSPACE_YAML_TEMPLATE = (name, repos) => {
52
+ const repoEntries = repos.map((r) => ` - name: ${r.name}\n path: ${r.path}`).join('\n');
53
+ return `apiVersion: ai-sdlc.io/v1alpha1
54
+ kind: Workspace
55
+ metadata:
56
+ name: ${name}
57
+ spec:
58
+ repos:
59
+ ${repoEntries}
60
+ `;
61
+ };
62
+ export function generateWorkspaceYaml(workspaceName, repos) {
63
+ return WORKSPACE_YAML_TEMPLATE(workspaceName, repos);
64
+ }
65
+ //# sourceMappingURL=workspace-detect.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ai-sdlc/orchestrator",
3
- "version": "0.2.0",
3
+ "version": "0.4.0",
4
4
  "description": "AI-SDLC Orchestrator — long-running runtime that drives issues through the complete SDLC with AI agents",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
@@ -45,7 +45,7 @@
45
45
  "better-sqlite3": "^11.0.0",
46
46
  "commander": "^12.0.0",
47
47
  "yaml": "^2.7.0",
48
- "@ai-sdlc/reference": "0.2.0"
48
+ "@ai-sdlc/reference": "0.4.0"
49
49
  },
50
50
  "devDependencies": {
51
51
  "@types/better-sqlite3": "^7.6.0",