agent-hive 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/README.md +95 -0
  2. package/dist/cli.d.ts +3 -0
  3. package/dist/cli.js +61 -0
  4. package/dist/cli.js.map +1 -0
  5. package/dist/commands/get.d.ts +2 -0
  6. package/dist/commands/get.js +39 -0
  7. package/dist/commands/get.js.map +1 -0
  8. package/dist/commands/init.d.ts +2 -0
  9. package/dist/commands/init.js +64 -0
  10. package/dist/commands/init.js.map +1 -0
  11. package/dist/config.d.ts +15 -0
  12. package/dist/config.js +52 -0
  13. package/dist/config.js.map +1 -0
  14. package/dist/core/errors.d.ts +14 -0
  15. package/dist/core/errors.js +27 -0
  16. package/dist/core/errors.js.map +1 -0
  17. package/dist/core/logger.d.ts +7 -0
  18. package/dist/core/logger.js +37 -0
  19. package/dist/core/logger.js.map +1 -0
  20. package/dist/core/session-spawner.d.ts +9 -0
  21. package/dist/core/session-spawner.js +73 -0
  22. package/dist/core/session-spawner.js.map +1 -0
  23. package/dist/github/issues.d.ts +26 -0
  24. package/dist/github/issues.js +115 -0
  25. package/dist/github/issues.js.map +1 -0
  26. package/dist/github/pr.d.ts +24 -0
  27. package/dist/github/pr.js +92 -0
  28. package/dist/github/pr.js.map +1 -0
  29. package/dist/obsidian/session-log.d.ts +14 -0
  30. package/dist/obsidian/session-log.js +62 -0
  31. package/dist/obsidian/session-log.js.map +1 -0
  32. package/dist/obsidian/sot-sync.d.ts +11 -0
  33. package/dist/obsidian/sot-sync.js +72 -0
  34. package/dist/obsidian/sot-sync.js.map +1 -0
  35. package/dist/obsidian/vault-init.d.ts +3 -0
  36. package/dist/obsidian/vault-init.js +44 -0
  37. package/dist/obsidian/vault-init.js.map +1 -0
  38. package/dist/prompts/lead.md +57 -0
  39. package/dist/prompts/reviewer.md +67 -0
  40. package/dist/prompts/worker.md +68 -0
  41. package/package.json +54 -0
package/README.md ADDED
@@ -0,0 +1,95 @@
1
+ # claude-colony
2
+
3
+ **기존 Git 레포에 붙이는 AI 개발 파이프라인 서버.**
4
+
5
+ 서버를 띄우면 Claude 세션이 워커/리뷰어로 자율 동작하며
6
+ 이슈 관리 → 개발 → PR → 코드 리뷰 → 머지 요청까지 자동화합니다.
7
+ 머지는 반드시 유저가 직접 승인합니다.
8
+
9
+ ## 어떻게 동작하나
10
+
11
+ ```
12
+ npx claude-colony init --repo owner/repo --target-repo ./my-project --token ghp_xxx
13
+ npx claude-colony start
14
+ ```
15
+
16
+ ```
17
+ ┌─────────────────────────────────────────────────┐
18
+ │ claude-colony server │
19
+ │ │
20
+ │ ┌──────────┐ PR 생성 ┌──────────┐ │
21
+ │ │ 워커 │ ───────────→ │ 리뷰어 │ │
22
+ │ │ 세션 │ ←─────────── │ 세션 │ │
23
+ │ └──────────┘ 코멘트 핑퐁 └──────────┘ │
24
+ │ │ │ │
25
+ │ ▼ ▼ │
26
+ │ ┌──────────────────────────────────────┐ │
27
+ │ │ GitHub (Issues, PR, Webhook) │ │
28
+ │ └──────────────────────────────────────┘ │
29
+ │ │ │
30
+ │ ▼ │
31
+ │ ┌──────────────────────────────────────┐ │
32
+ │ │ Obsidian vault (선택) │ │
33
+ │ │ 작업 기록 축적 + SSoT 승격 │ │
34
+ │ └──────────────────────────────────────┘ │
35
+ │ │
36
+ └─────────────────────────────────────────────────┘
37
+
38
+
39
+ 유저가 최종 머지 승인
40
+ ```
41
+
42
+ ## 핵심 기능
43
+
44
+ - **워커 세션** — 브랜치별로 스폰, 코드 작성, PR 생성
45
+ - **리뷰어 세션** — PR 트리거로 자동 스폰, 코드 리뷰, 워커와 핑퐁
46
+ - **이슈 관리** — GitHub Issues 자동 생성/라벨링/close
47
+ - **장기 기억** — Obsidian vault에 작업 기록 축적, 컨텍스트 유실 방지
48
+ - **머지 보호** — init 시 브랜치 보호 규칙 자동 설정, AI가 머지 불가
49
+
50
+ ## 왜 쓰는가
51
+
52
+ | 문제 | claude-colony의 해결 |
53
+ |------|----------------------|
54
+ | AI가 코드 리뷰 없이 머지 | 워커-리뷰어 분리 + 유저 최종 승인 강제 |
55
+ | 새 세션이 이전 맥락을 모름 | 작업 기록서 + SSoT로 컨텍스트 복원 |
56
+ | 이슈/PR 수동 관리 | 자동 생성, 라벨링, 연결, close |
57
+ | AI 에이전트 설정이 복잡 | `npx claude-colony init` 한 줄로 끝 |
58
+
59
+ ## 빠른 시작
60
+
61
+ ```bash
62
+ # 1. 초기화 (config 생성 + GitHub 브랜치 보호 설정)
63
+ npx claude-colony init \
64
+ --repo owner/repo \
65
+ --target-repo /path/to/repo \
66
+ --token ghp_xxx
67
+
68
+ # 2. 서버 시작
69
+ npx claude-colony start
70
+ ```
71
+
72
+ ## 문서
73
+
74
+ - [설치 및 설정 가이드](docs/setup.md)
75
+ - [프로젝트 명세](claude-colony-SPEC.md)
76
+ - [코드 컨벤션](CONVENTIONS.md)
77
+
78
+ ## 프로젝트 구조
79
+
80
+ ```
81
+ src/
82
+ ├── cli.ts ← CLI 진입점 (init, start)
83
+ ├── index.ts ← 서버 진입점
84
+ ├── config.ts ← 설정 로드/검증
85
+ ├── commands/
86
+ │ └── init.ts ← init 명령어
87
+ ├── core/ ← 세션 스폰, 로거, 이벤트 감시
88
+ ├── github/ ← Webhook, Issues, PR
89
+ ├── obsidian/ ← Vault 초기화, 기록서, SSoT
90
+ └── prompts/ ← 워커/리뷰어 규칙 템플릿
91
+ ```
92
+
93
+ ## 라이센스
94
+
95
+ MIT
package/dist/cli.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=cli.d.ts.map
package/dist/cli.js ADDED
@@ -0,0 +1,61 @@
1
+ #!/usr/bin/env node
2
+ import { logger } from './core/logger.js';
3
+ import { ColonyError } from './core/errors.js';
4
+ const USAGE_TEXT = `Usage: claude-colony <command> [options]
5
+
6
+ Commands:
7
+ init Initialize a new colony project
8
+ get <issue> Fetch a GitHub issue and spawn a Worker+Reviewer team
9
+
10
+ Options:
11
+ --help Show this help message
12
+
13
+ Init options:
14
+ --repo <owner/repo> GitHub repository (required)
15
+ --target-repo <path> Path to local repository (required)
16
+ --base-branch <branch> Base branch name (default: main)
17
+ --obsidian-vault <path> Obsidian vault path (optional)
18
+
19
+ Get examples:
20
+ claude-colony get 42
21
+ claude-colony get #42
22
+ claude-colony get https://github.com/owner/repo/issues/42`;
23
+ function parseCommand(args) {
24
+ const positional = args.filter((a) => !a.startsWith('--'));
25
+ return positional[0];
26
+ }
27
+ function hasFlag(args, flag) {
28
+ return args.includes(flag);
29
+ }
30
+ async function run() {
31
+ const args = process.argv.slice(2);
32
+ if (hasFlag(args, '--help') || args.length === 0) {
33
+ logger.info(USAGE_TEXT);
34
+ return;
35
+ }
36
+ const command = parseCommand(args);
37
+ if (command === 'init') {
38
+ const { runInit } = await import('./commands/init.js');
39
+ await runInit(args);
40
+ return;
41
+ }
42
+ if (command === 'get') {
43
+ const { runGet } = await import('./commands/get.js');
44
+ const getArgs = args.filter((a) => a !== 'get');
45
+ await runGet(getArgs);
46
+ return;
47
+ }
48
+ logger.error(`Unknown command: ${command}`);
49
+ logger.info(USAGE_TEXT);
50
+ process.exit(1);
51
+ }
52
+ run().catch((err) => {
53
+ if (err instanceof ColonyError) {
54
+ logger.error(err.message, { code: err.code });
55
+ }
56
+ else {
57
+ logger.error('Fatal error', { error: String(err) });
58
+ }
59
+ process.exit(1);
60
+ });
61
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC1C,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAE/C,MAAM,UAAU,GAAG;;;;;;;;;;;;;;;;;;4DAkByC,CAAC;AAE7D,SAAS,YAAY,CAAC,IAAc;IAClC,MAAM,UAAU,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC;IAC3D,OAAO,UAAU,CAAC,CAAC,CAAC,CAAC;AACvB,CAAC;AAED,SAAS,OAAO,CAAC,IAAc,EAAE,IAAY;IAC3C,OAAO,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;AAC7B,CAAC;AAED,KAAK,UAAU,GAAG;IAChB,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAEnC,IAAI,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACjD,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QACxB,OAAO;IACT,CAAC;IAED,MAAM,OAAO,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;IAEnC,IAAI,OAAO,KAAK,MAAM,EAAE,CAAC;QACvB,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,MAAM,CAAC,oBAAoB,CAAC,CAAC;QACvD,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;QACpB,OAAO;IACT,CAAC;IAED,IAAI,OAAO,KAAK,KAAK,EAAE,CAAC;QACtB,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,MAAM,CAAC,mBAAmB,CAAC,CAAC;QACrD,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,KAAK,CAAC,CAAC;QAChD,MAAM,MAAM,CAAC,OAAO,CAAC,CAAC;QACtB,OAAO;IACT,CAAC;IAED,MAAM,CAAC,KAAK,CAAC,oBAAoB,OAAO,EAAE,CAAC,CAAC;IAC5C,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IACxB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;AAED,GAAG,EAAE,CAAC,KAAK,CAAC,CAAC,GAAY,EAAE,EAAE;IAC3B,IAAI,GAAG,YAAY,WAAW,EAAE,CAAC;QAC/B,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,EAAE,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC;IAChD,CAAC;SAAM,CAAC;QACN,MAAM,CAAC,KAAK,CAAC,aAAa,EAAE,EAAE,KAAK,EAAE,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IACtD,CAAC;IACD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare function runGet(args: string[]): Promise<void>;
2
+ //# sourceMappingURL=get.d.ts.map
@@ -0,0 +1,39 @@
1
+ import { loadConfig } from '../config.js';
2
+ import { GithubError } from '../core/errors.js';
3
+ import { logger } from '../core/logger.js';
4
+ import { spawnLeadSession } from '../core/session-spawner.js';
5
+ import { getIssue } from '../github/issues.js';
6
+ import { initVault } from '../obsidian/vault-init.js';
7
+ function parseIssueRef(input) {
8
+ const urlMatch = input.match(/github\.com\/[\w.-]+\/[\w.-]+\/issues\/(\d+)/);
9
+ if (urlMatch)
10
+ return urlMatch[1];
11
+ const shortMatch = input.match(/^[\w.-]+\/[\w.-]+#(\d+)$/);
12
+ if (shortMatch)
13
+ return shortMatch[1];
14
+ if (/^\d+$/.test(input))
15
+ return input;
16
+ if (/^#\d+$/.test(input))
17
+ return input.slice(1);
18
+ throw new GithubError(`Invalid issue reference: ${input}`);
19
+ }
20
+ export async function runGet(args) {
21
+ const issueRef = args.find((a) => !a.startsWith('--'));
22
+ if (!issueRef) {
23
+ throw new GithubError('Usage: claude-colony get <issue-number-or-url>');
24
+ }
25
+ const config = await loadConfig();
26
+ if (config.obsidian) {
27
+ await initVault(config);
28
+ }
29
+ const issueNumber = parseIssueRef(issueRef);
30
+ const issue = await getIssue(config, issueNumber);
31
+ logger.info(`Issue #${issue.number}: ${issue.title}`);
32
+ await spawnLeadSession({
33
+ config,
34
+ issueNumber: issue.number,
35
+ issueTitle: issue.title,
36
+ issueBody: issue.body,
37
+ });
38
+ }
39
+ //# sourceMappingURL=get.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get.js","sourceRoot":"","sources":["../../src/commands/get.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAC3C,OAAO,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AAC9D,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAC/C,OAAO,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AAEtD,SAAS,aAAa,CAAC,KAAa;IAClC,MAAM,QAAQ,GAAG,KAAK,CAAC,KAAK,CAAC,8CAA8C,CAAC,CAAC;IAC7E,IAAI,QAAQ;QAAE,OAAO,QAAQ,CAAC,CAAC,CAAC,CAAC;IAEjC,MAAM,UAAU,GAAG,KAAK,CAAC,KAAK,CAAC,0BAA0B,CAAC,CAAC;IAC3D,IAAI,UAAU;QAAE,OAAO,UAAU,CAAC,CAAC,CAAC,CAAC;IAErC,IAAI,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IACtC,IAAI,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAEhD,MAAM,IAAI,WAAW,CAAC,4BAA4B,KAAK,EAAE,CAAC,CAAC;AAC7D,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,MAAM,CAAC,IAAc;IACzC,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC;IACvD,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,MAAM,IAAI,WAAW,CAAC,gDAAgD,CAAC,CAAC;IAC1E,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,UAAU,EAAE,CAAC;IAElC,IAAI,MAAM,CAAC,QAAQ,EAAE,CAAC;QACpB,MAAM,SAAS,CAAC,MAAM,CAAC,CAAC;IAC1B,CAAC;IAED,MAAM,WAAW,GAAG,aAAa,CAAC,QAAQ,CAAC,CAAC;IAC5C,MAAM,KAAK,GAAG,MAAM,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IAElD,MAAM,CAAC,IAAI,CAAC,UAAU,KAAK,CAAC,MAAM,KAAK,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC;IAEtD,MAAM,gBAAgB,CAAC;QACrB,MAAM;QACN,WAAW,EAAE,KAAK,CAAC,MAAM;QACzB,UAAU,EAAE,KAAK,CAAC,KAAK;QACvB,SAAS,EAAE,KAAK,CAAC,IAAI;KACtB,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare function runInit(args: string[]): Promise<void>;
2
+ //# sourceMappingURL=init.d.ts.map
@@ -0,0 +1,64 @@
1
+ import { writeFile } from 'node:fs/promises';
2
+ import path from 'node:path';
3
+ import { ConfigError } from '../core/errors.js';
4
+ import { logger } from '../core/logger.js';
5
+ import { initVault } from '../obsidian/vault-init.js';
6
+ const DEFAULT_BASE_BRANCH = 'main';
7
+ function getArgValue(args, flag) {
8
+ const idx = args.indexOf(flag);
9
+ if (idx === -1 || idx + 1 >= args.length)
10
+ return undefined;
11
+ return args[idx + 1];
12
+ }
13
+ function parseInitArgs(args) {
14
+ const repo = getArgValue(args, '--repo');
15
+ const targetRepo = getArgValue(args, '--target-repo');
16
+ if (!repo)
17
+ throw new ConfigError('--repo is required (e.g., owner/repo)');
18
+ if (!targetRepo)
19
+ throw new ConfigError('--target-repo is required (e.g., /path/to/repo)');
20
+ return {
21
+ repo,
22
+ targetRepo,
23
+ baseBranch: getArgValue(args, '--base-branch') ?? DEFAULT_BASE_BRANCH,
24
+ obsidianVault: getArgValue(args, '--obsidian-vault') ?? '',
25
+ };
26
+ }
27
+ function buildConfigJson(options) {
28
+ const config = {
29
+ targetRepo: options.targetRepo,
30
+ github: {
31
+ repo: options.repo,
32
+ baseBranch: options.baseBranch,
33
+ },
34
+ };
35
+ if (options.obsidianVault) {
36
+ config.obsidian = {
37
+ vaultPath: options.obsidianVault,
38
+ };
39
+ }
40
+ return JSON.stringify(config, null, 2);
41
+ }
42
+ export async function runInit(args) {
43
+ const options = parseInitArgs(args);
44
+ const outputDir = process.cwd();
45
+ const configContent = buildConfigJson(options);
46
+ await writeFile(path.join(outputDir, 'colony.config.json'), configContent, 'utf-8');
47
+ logger.info('Created colony.config.json');
48
+ if (options.obsidianVault) {
49
+ const tempConfig = {
50
+ targetRepo: options.targetRepo,
51
+ github: { repo: options.repo, baseBranch: options.baseBranch },
52
+ obsidian: { vaultPath: options.obsidianVault },
53
+ };
54
+ await initVault(tempConfig);
55
+ logger.info('Obsidian vault initialized', { path: options.obsidianVault });
56
+ }
57
+ logger.info('Initialization complete', {
58
+ repo: options.repo,
59
+ targetRepo: options.targetRepo,
60
+ baseBranch: options.baseBranch,
61
+ obsidian: options.obsidianVault || 'disabled',
62
+ });
63
+ }
64
+ //# sourceMappingURL=init.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ export interface GithubConfig {
2
+ repo: string;
3
+ baseBranch: string;
4
+ }
5
+ export interface ObsidianConfig {
6
+ vaultPath: string;
7
+ }
8
+ export interface ColonyConfig {
9
+ targetRepo: string;
10
+ github: GithubConfig;
11
+ obsidian?: ObsidianConfig;
12
+ }
13
+ export { ConfigError } from './core/errors.js';
14
+ export declare function loadConfig(configDir?: string): Promise<ColonyConfig>;
15
+ //# sourceMappingURL=config.d.ts.map
package/dist/config.js ADDED
@@ -0,0 +1,52 @@
1
+ import { readFile } from 'node:fs/promises';
2
+ import path from 'node:path';
3
+ import dotenv from 'dotenv';
4
+ import { ConfigError } from './core/errors.js';
5
+ function loadEnv(configDir) {
6
+ dotenv.config({ path: path.join(configDir, '.env') });
7
+ }
8
+ async function loadConfigFile(configDir) {
9
+ const configPath = path.join(configDir, 'colony.config.json');
10
+ try {
11
+ const content = await readFile(configPath, 'utf-8');
12
+ return JSON.parse(content);
13
+ }
14
+ catch {
15
+ return {};
16
+ }
17
+ }
18
+ function validateConfig(config) {
19
+ if (!config.targetRepo) {
20
+ throw new ConfigError('targetRepo is required in colony.config.json');
21
+ }
22
+ if (!config.github.repo) {
23
+ throw new ConfigError('github.repo is required in colony.config.json');
24
+ }
25
+ if (config.obsidian && !config.obsidian.vaultPath) {
26
+ throw new ConfigError('obsidian.vaultPath is required when obsidian is configured');
27
+ }
28
+ }
29
+ export { ConfigError } from './core/errors.js';
30
+ export async function loadConfig(configDir) {
31
+ const dir = configDir ?? process.cwd();
32
+ loadEnv(dir);
33
+ const raw = await loadConfigFile(dir);
34
+ const config = {
35
+ targetRepo: raw.targetRepo ?? '',
36
+ github: {
37
+ repo: raw.github?.repo ?? '',
38
+ baseBranch: raw.github?.baseBranch ?? 'main',
39
+ },
40
+ };
41
+ if (raw.obsidian) {
42
+ if (raw.obsidian.vaultPath) {
43
+ config.obsidian = { vaultPath: raw.obsidian.vaultPath };
44
+ }
45
+ else {
46
+ throw new ConfigError('obsidian.vaultPath is required when obsidian is configured');
47
+ }
48
+ }
49
+ validateConfig(config);
50
+ return config;
51
+ }
52
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,OAAO,MAAM,MAAM,QAAQ,CAAC;AAE5B,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAuB/C,SAAS,OAAO,CAAC,SAAiB;IAChC,MAAM,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC;AACxD,CAAC;AAED,KAAK,UAAU,cAAc,CAAC,SAAiB;IAC7C,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,oBAAoB,CAAC,CAAC;IAC9D,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;QACpD,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAc,CAAC;IAC1C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED,SAAS,cAAc,CAAC,MAAoB;IAC1C,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC;QACvB,MAAM,IAAI,WAAW,CAAC,8CAA8C,CAAC,CAAC;IACxE,CAAC;IAED,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;QACxB,MAAM,IAAI,WAAW,CAAC,+CAA+C,CAAC,CAAC;IACzE,CAAC;IAED,IAAI,MAAM,CAAC,QAAQ,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,EAAE,CAAC;QAClD,MAAM,IAAI,WAAW,CAAC,4DAA4D,CAAC,CAAC;IACtF,CAAC;AACH,CAAC;AAED,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAE/C,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,SAAkB;IACjD,MAAM,GAAG,GAAG,SAAS,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;IAEvC,OAAO,CAAC,GAAG,CAAC,CAAC;IACb,MAAM,GAAG,GAAG,MAAM,cAAc,CAAC,GAAG,CAAC,CAAC;IAEtC,MAAM,MAAM,GAAiB;QAC3B,UAAU,EAAE,GAAG,CAAC,UAAU,IAAI,EAAE;QAChC,MAAM,EAAE;YACN,IAAI,EAAE,GAAG,CAAC,MAAM,EAAE,IAAI,IAAI,EAAE;YAC5B,UAAU,EAAE,GAAG,CAAC,MAAM,EAAE,UAAU,IAAI,MAAM;SAC7C;KACF,CAAC;IAEF,IAAI,GAAG,CAAC,QAAQ,EAAE,CAAC;QACjB,IAAI,GAAG,CAAC,QAAQ,CAAC,SAAS,EAAE,CAAC;YAC3B,MAAM,CAAC,QAAQ,GAAG,EAAE,SAAS,EAAE,GAAG,CAAC,QAAQ,CAAC,SAAS,EAAE,CAAC;QAC1D,CAAC;aAAM,CAAC;YACN,MAAM,IAAI,WAAW,CAAC,4DAA4D,CAAC,CAAC;QACtF,CAAC;IACH,CAAC;IAED,cAAc,CAAC,MAAM,CAAC,CAAC;IAEvB,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -0,0 +1,14 @@
1
+ export declare class ColonyError extends Error {
2
+ readonly code: string;
3
+ constructor(message: string, code: string);
4
+ }
5
+ export declare class ConfigError extends ColonyError {
6
+ constructor(message: string);
7
+ }
8
+ export declare class GithubError extends ColonyError {
9
+ constructor(message: string);
10
+ }
11
+ export declare class ObsidianError extends ColonyError {
12
+ constructor(message: string);
13
+ }
14
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1,27 @@
1
+ export class ColonyError extends Error {
2
+ code;
3
+ constructor(message, code) {
4
+ super(message);
5
+ this.code = code;
6
+ this.name = 'ColonyError';
7
+ }
8
+ }
9
+ export class ConfigError extends ColonyError {
10
+ constructor(message) {
11
+ super(message, 'CONFIG_ERROR');
12
+ this.name = 'ConfigError';
13
+ }
14
+ }
15
+ export class GithubError extends ColonyError {
16
+ constructor(message) {
17
+ super(message, 'GITHUB_ERROR');
18
+ this.name = 'GithubError';
19
+ }
20
+ }
21
+ export class ObsidianError extends ColonyError {
22
+ constructor(message) {
23
+ super(message, 'OBSIDIAN_ERROR');
24
+ this.name = 'ObsidianError';
25
+ }
26
+ }
27
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/core/errors.ts"],"names":[],"mappings":"AAAA,MAAM,OAAO,WAAY,SAAQ,KAAK;IAGlB;IAFlB,YACE,OAAe,EACC,IAAY;QAE5B,KAAK,CAAC,OAAO,CAAC,CAAC;QAFC,SAAI,GAAJ,IAAI,CAAQ;QAG5B,IAAI,CAAC,IAAI,GAAG,aAAa,CAAC;IAC5B,CAAC;CACF;AAED,MAAM,OAAO,WAAY,SAAQ,WAAW;IAC1C,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,EAAE,cAAc,CAAC,CAAC;QAC/B,IAAI,CAAC,IAAI,GAAG,aAAa,CAAC;IAC5B,CAAC;CACF;AAED,MAAM,OAAO,WAAY,SAAQ,WAAW;IAC1C,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,EAAE,cAAc,CAAC,CAAC;QAC/B,IAAI,CAAC,IAAI,GAAG,aAAa,CAAC;IAC5B,CAAC;CACF;AAED,MAAM,OAAO,aAAc,SAAQ,WAAW;IAC5C,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,EAAE,gBAAgB,CAAC,CAAC;QACjC,IAAI,CAAC,IAAI,GAAG,eAAe,CAAC;IAC9B,CAAC;CACF"}
@@ -0,0 +1,7 @@
1
+ export declare const logger: {
2
+ debug: (message: string, context?: Record<string, unknown>) => void;
3
+ info: (message: string, context?: Record<string, unknown>) => void;
4
+ warn: (message: string, context?: Record<string, unknown>) => void;
5
+ error: (message: string, context?: Record<string, unknown>) => void;
6
+ };
7
+ //# sourceMappingURL=logger.d.ts.map
@@ -0,0 +1,37 @@
1
+ const LOG_LEVEL_PRIORITY = {
2
+ debug: 0,
3
+ info: 1,
4
+ warn: 2,
5
+ error: 3,
6
+ };
7
+ function formatLog(entry) {
8
+ const ctx = entry.context ? ` ${JSON.stringify(entry.context)}` : '';
9
+ return `[${entry.timestamp}] [${entry.level.toUpperCase()}] ${entry.message}${ctx}`;
10
+ }
11
+ function createLogger(minLevel = 'info') {
12
+ function log(level, message, context) {
13
+ if (LOG_LEVEL_PRIORITY[level] < LOG_LEVEL_PRIORITY[minLevel])
14
+ return;
15
+ const entry = {
16
+ level,
17
+ message,
18
+ timestamp: new Date().toISOString(),
19
+ context,
20
+ };
21
+ const formatted = formatLog(entry);
22
+ if (level === 'error') {
23
+ process.stderr.write(formatted + '\n');
24
+ }
25
+ else {
26
+ process.stdout.write(formatted + '\n');
27
+ }
28
+ }
29
+ return {
30
+ debug: (message, context) => log('debug', message, context),
31
+ info: (message, context) => log('info', message, context),
32
+ warn: (message, context) => log('warn', message, context),
33
+ error: (message, context) => log('error', message, context),
34
+ };
35
+ }
36
+ export const logger = createLogger();
37
+ //# sourceMappingURL=logger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/core/logger.ts"],"names":[],"mappings":"AAEA,MAAM,kBAAkB,GAA6B;IACnD,KAAK,EAAE,CAAC;IACR,IAAI,EAAE,CAAC;IACP,IAAI,EAAE,CAAC;IACP,KAAK,EAAE,CAAC;CACT,CAAC;AASF,SAAS,SAAS,CAAC,KAAe;IAChC,MAAM,GAAG,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IACrE,OAAO,IAAI,KAAK,CAAC,SAAS,MAAM,KAAK,CAAC,KAAK,CAAC,WAAW,EAAE,KAAK,KAAK,CAAC,OAAO,GAAG,GAAG,EAAE,CAAC;AACtF,CAAC;AAED,SAAS,YAAY,CAAC,WAAqB,MAAM;IAM/C,SAAS,GAAG,CAAC,KAAe,EAAE,OAAe,EAAE,OAAiC;QAC9E,IAAI,kBAAkB,CAAC,KAAK,CAAC,GAAG,kBAAkB,CAAC,QAAQ,CAAC;YAAE,OAAO;QAErE,MAAM,KAAK,GAAa;YACtB,KAAK;YACL,OAAO;YACP,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;YACnC,OAAO;SACR,CAAC;QAEF,MAAM,SAAS,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC;QAEnC,IAAI,KAAK,KAAK,OAAO,EAAE,CAAC;YACtB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,SAAS,GAAG,IAAI,CAAC,CAAC;QACzC,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,SAAS,GAAG,IAAI,CAAC,CAAC;QACzC,CAAC;IACH,CAAC;IAED,OAAO;QACL,KAAK,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,CAAC,GAAG,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC;QAC3D,IAAI,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,CAAC,GAAG,CAAC,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC;QACzD,IAAI,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,CAAC,GAAG,CAAC,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC;QACzD,KAAK,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,CAAC,GAAG,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC;KAC5D,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,MAAM,MAAM,GAAG,YAAY,EAAE,CAAC"}
@@ -0,0 +1,9 @@
1
+ import type { ColonyConfig } from '../config.js';
2
+ export interface LeadSessionOptions {
3
+ config: ColonyConfig;
4
+ issueNumber: number;
5
+ issueTitle: string;
6
+ issueBody: string;
7
+ }
8
+ export declare function spawnLeadSession(options: LeadSessionOptions): Promise<void>;
9
+ //# sourceMappingURL=session-spawner.d.ts.map
@@ -0,0 +1,73 @@
1
+ import { spawn } from 'node:child_process';
2
+ import { readFile } from 'node:fs/promises';
3
+ import path from 'node:path';
4
+ import { logger } from './logger.js';
5
+ async function loadPromptFile(filename) {
6
+ const filePath = path.join(import.meta.dirname ?? '.', '..', 'prompts', filename);
7
+ return readFile(filePath, 'utf-8');
8
+ }
9
+ function renderTemplate(template, vars) {
10
+ let result = template;
11
+ for (const [key, value] of Object.entries(vars)) {
12
+ result = result.replaceAll(`{${key}}`, value);
13
+ }
14
+ return result;
15
+ }
16
+ function buildVaultSection(config) {
17
+ if (!config.obsidian) {
18
+ return 'Obsidian vault는 비활성화 상태입니다.';
19
+ }
20
+ return [
21
+ `Vault 경로: ${config.obsidian.vaultPath}`,
22
+ '- 작업 기록은 vault/sessions/ 에 저장한다.',
23
+ '- 컨벤션/패턴은 vault/context/CLAUDE.md 를 참조한다.',
24
+ '- 중요 결정사항은 [SSoT] 태그로 기록하여 승격 대상으로 표시한다.',
25
+ ].join('\n');
26
+ }
27
+ async function buildLeadPrompt(options) {
28
+ const [leadTemplate, workerRules, reviewerRules] = await Promise.all([
29
+ loadPromptFile('lead.md'),
30
+ loadPromptFile('worker.md'),
31
+ loadPromptFile('reviewer.md'),
32
+ ]);
33
+ return renderTemplate(leadTemplate, {
34
+ repo: options.config.github.repo,
35
+ 'target-repo': options.config.targetRepo,
36
+ 'base-branch': options.config.github.baseBranch,
37
+ 'issue-number': String(options.issueNumber),
38
+ 'issue-title': options.issueTitle,
39
+ 'issue-body': options.issueBody,
40
+ 'worker-rules': workerRules,
41
+ 'reviewer-rules': reviewerRules,
42
+ 'vault-section': buildVaultSection(options.config),
43
+ });
44
+ }
45
+ export async function spawnLeadSession(options) {
46
+ const prompt = await buildLeadPrompt(options);
47
+ logger.info('Spawning lead session...', {
48
+ issue: `#${options.issueNumber}`,
49
+ repo: options.config.github.repo,
50
+ });
51
+ return new Promise((resolve, reject) => {
52
+ const child = spawn('claude', ['-p', prompt], {
53
+ cwd: options.config.targetRepo,
54
+ stdio: 'inherit',
55
+ env: {
56
+ ...process.env,
57
+ CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS: '1',
58
+ },
59
+ });
60
+ child.on('error', (err) => {
61
+ reject(new Error(`Failed to spawn claude: ${err.message}`));
62
+ });
63
+ child.on('exit', (code) => {
64
+ if (code === 0) {
65
+ resolve();
66
+ }
67
+ else {
68
+ reject(new Error(`Lead session exited with code ${code}`));
69
+ }
70
+ });
71
+ });
72
+ }
73
+ //# sourceMappingURL=session-spawner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-spawner.js","sourceRoot":"","sources":["../../src/core/session-spawner.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,26 @@
1
+ import type { ColonyConfig } from '../config.js';
2
+ declare const IssueLabel: {
3
+ readonly Backlog: "backlog";
4
+ readonly InProgress: "in-progress";
5
+ readonly Blocked: "blocked";
6
+ };
7
+ type IssueLabel = (typeof IssueLabel)[keyof typeof IssueLabel];
8
+ export { IssueLabel };
9
+ export interface IssueInfo {
10
+ number: number;
11
+ title: string;
12
+ state: 'open' | 'closed';
13
+ labels: string[];
14
+ url: string;
15
+ }
16
+ export declare function getIssue(config: ColonyConfig, issueRef: string): Promise<IssueInfo & {
17
+ body: string;
18
+ }>;
19
+ export declare function createIssue(config: ColonyConfig, options: {
20
+ title: string;
21
+ body: string;
22
+ labels?: string[];
23
+ }): Promise<IssueInfo>;
24
+ export declare function updateLabel(config: ColonyConfig, issueNumber: number, label: IssueLabel): Promise<void>;
25
+ export declare function closeIssue(config: ColonyConfig, issueNumber: number): Promise<void>;
26
+ //# sourceMappingURL=issues.d.ts.map