vibe-commander 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.
- package/LICENSE +21 -0
- package/dist/adapters/cli/commands/context-resolver.d.ts +29 -0
- package/dist/adapters/cli/commands/context-resolver.js +93 -0
- package/dist/adapters/cli/commands/context.d.ts +26 -0
- package/dist/adapters/cli/commands/context.js +39 -0
- package/dist/adapters/cli/commands/git-helpers.d.ts +43 -0
- package/dist/adapters/cli/commands/git-helpers.js +99 -0
- package/dist/adapters/cli/commands/init-helpers.d.ts +30 -0
- package/dist/adapters/cli/commands/init-helpers.js +112 -0
- package/dist/adapters/cli/commands/init-interactive.d.ts +25 -0
- package/dist/adapters/cli/commands/init-interactive.js +143 -0
- package/dist/adapters/cli/commands/init.d.ts +25 -0
- package/dist/adapters/cli/commands/init.js +73 -0
- package/dist/adapters/cli/commands/io-helpers.d.ts +45 -0
- package/dist/adapters/cli/commands/io-helpers.js +144 -0
- package/dist/adapters/cli/commands/list-units.d.ts +39 -0
- package/dist/adapters/cli/commands/list-units.js +92 -0
- package/dist/adapters/cli/commands/prompt-helpers.d.ts +36 -0
- package/dist/adapters/cli/commands/prompt-helpers.js +113 -0
- package/dist/adapters/cli/commands/set-unit.d.ts +44 -0
- package/dist/adapters/cli/commands/set-unit.js +90 -0
- package/dist/adapters/cli/commands/skill-install.d.ts +31 -0
- package/dist/adapters/cli/commands/skill-install.js +85 -0
- package/dist/adapters/cli/commands/state-helpers.d.ts +28 -0
- package/dist/adapters/cli/commands/state-helpers.js +55 -0
- package/dist/adapters/cli/commands/update-commit.d.ts +42 -0
- package/dist/adapters/cli/commands/update-commit.js +180 -0
- package/dist/adapters/cli/commands/validate.d.ts +40 -0
- package/dist/adapters/cli/commands/validate.js +219 -0
- package/dist/adapters/cli/formatters-list.d.ts +36 -0
- package/dist/adapters/cli/formatters-list.js +106 -0
- package/dist/adapters/cli/formatters-unit.d.ts +44 -0
- package/dist/adapters/cli/formatters-unit.js +287 -0
- package/dist/adapters/cli/formatters.d.ts +2 -0
- package/dist/adapters/cli/formatters.js +3 -0
- package/dist/adapters/cli/index.d.ts +17 -0
- package/dist/adapters/cli/index.js +60 -0
- package/dist/adapters/cli/output.d.ts +58 -0
- package/dist/adapters/cli/output.js +159 -0
- package/dist/adapters/cli/router.d.ts +99 -0
- package/dist/adapters/cli/router.js +419 -0
- package/dist/adapters/cli/scanner.d.ts +19 -0
- package/dist/adapters/cli/scanner.js +227 -0
- package/dist/adapters/pipe/stdin-reader.d.ts +23 -0
- package/dist/adapters/pipe/stdin-reader.js +56 -0
- package/dist/config/loader.d.ts +27 -0
- package/dist/config/loader.js +84 -0
- package/dist/config/resolver.d.ts +71 -0
- package/dist/config/resolver.js +124 -0
- package/dist/config/schema.d.ts +205 -0
- package/dist/config/schema.js +186 -0
- package/dist/core/parsers/backlog-parser.d.ts +25 -0
- package/dist/core/parsers/backlog-parser.js +255 -0
- package/dist/core/parsers/dep-line-parser.d.ts +36 -0
- package/dist/core/parsers/dep-line-parser.js +176 -0
- package/dist/core/parsers/dependency-extractor.d.ts +64 -0
- package/dist/core/parsers/dependency-extractor.js +193 -0
- package/dist/core/parsers/index.d.ts +20 -0
- package/dist/core/parsers/index.js +20 -0
- package/dist/core/parsers/md-utils.d.ts +81 -0
- package/dist/core/parsers/md-utils.js +144 -0
- package/dist/core/parsers/metadata-parser.d.ts +49 -0
- package/dist/core/parsers/metadata-parser.js +133 -0
- package/dist/core/parsers/pairing-question-extractor.d.ts +42 -0
- package/dist/core/parsers/pairing-question-extractor.js +146 -0
- package/dist/core/parsers/plan-parser-helpers.d.ts +61 -0
- package/dist/core/parsers/plan-parser-helpers.js +90 -0
- package/dist/core/parsers/plan-parser.d.ts +55 -0
- package/dist/core/parsers/plan-parser.js +69 -0
- package/dist/core/parsers/title-extractor.d.ts +36 -0
- package/dist/core/parsers/title-extractor.js +101 -0
- package/dist/core/renderers/index.d.ts +15 -0
- package/dist/core/renderers/index.js +18 -0
- package/dist/core/renderers/interpolate.d.ts +92 -0
- package/dist/core/renderers/interpolate.js +117 -0
- package/dist/core/renderers/marker-utils.d.ts +60 -0
- package/dist/core/renderers/marker-utils.js +85 -0
- package/dist/core/renderers/section-renderer.d.ts +31 -0
- package/dist/core/renderers/section-renderer.js +171 -0
- package/dist/core/renderers/section-updater.d.ts +72 -0
- package/dist/core/renderers/section-updater.js +175 -0
- package/dist/core/renderers/template-engine.d.ts +69 -0
- package/dist/core/renderers/template-engine.js +92 -0
- package/dist/core/renderers/updater-helpers.d.ts +45 -0
- package/dist/core/renderers/updater-helpers.js +83 -0
- package/dist/core/resolvers/commit-filter.d.ts +84 -0
- package/dist/core/resolvers/commit-filter.js +95 -0
- package/dist/core/resolvers/config-generator.d.ts +32 -0
- package/dist/core/resolvers/config-generator.js +112 -0
- package/dist/core/resolvers/config-merger.d.ts +26 -0
- package/dist/core/resolvers/config-merger.js +89 -0
- package/dist/core/resolvers/config-validator.d.ts +42 -0
- package/dist/core/resolvers/config-validator.js +61 -0
- package/dist/core/resolvers/dep-commit-resolver.d.ts +63 -0
- package/dist/core/resolvers/dep-commit-resolver.js +158 -0
- package/dist/core/resolvers/dep-doc-resolver.d.ts +70 -0
- package/dist/core/resolvers/dep-doc-resolver.js +84 -0
- package/dist/core/resolvers/index.d.ts +15 -0
- package/dist/core/resolvers/index.js +12 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +8 -0
- package/dist/types/config.d.ts +10 -0
- package/dist/types/config.js +10 -0
- package/dist/types/context.d.ts +55 -0
- package/dist/types/context.js +10 -0
- package/dist/types/index.d.ts +15 -0
- package/dist/types/index.js +10 -0
- package/dist/types/init.d.ts +56 -0
- package/dist/types/init.js +10 -0
- package/dist/types/tool-result.d.ts +75 -0
- package/dist/types/tool-result.js +40 -0
- package/dist/types/unit.d.ts +118 -0
- package/dist/types/unit.js +10 -0
- package/package.json +71 -0
- package/skills/claude/SKILL.md +375 -0
- package/skills/common/cli-reference.md +251 -0
- package/skills/cursor/SKILL.md +353 -0
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 의존성 추출기 — Layer 1 순수 함수
|
|
3
|
+
*
|
|
4
|
+
* 계획서 마크다운에서 의존 유닛 정보를 추출한다.
|
|
5
|
+
* `dependsSource` 설정에 따라 section, frontmatter, metadata-table 소스를 지원하고,
|
|
6
|
+
* Fallback 체인으로 부분 실패에 대응한다.
|
|
7
|
+
*
|
|
8
|
+
* Fallback 체인: 설정 소스 → 메타데이터 테이블 → 본문 정규식 스캔
|
|
9
|
+
*
|
|
10
|
+
* PRD §8.1 계획서 파싱:
|
|
11
|
+
* dependsSource: "section" → dependsSectionName 헤더 아래 **유닛ID** / [유닛ID] 수집
|
|
12
|
+
* dependsSource: "frontmatter" → YAML frontmatter의 depends 배열
|
|
13
|
+
* dependsSource: "metadata-table" → 메타데이터 테이블의 dependsField 값
|
|
14
|
+
*
|
|
15
|
+
* @module
|
|
16
|
+
*/
|
|
17
|
+
import type { DepInfo, PlanParsingConfig, ToolResult } from '../../types/index.js';
|
|
18
|
+
import type { ParsedDependencyResult } from './dep-line-parser.js';
|
|
19
|
+
/**
|
|
20
|
+
* 계획서에서 의존 유닛 정보를 추출한다
|
|
21
|
+
*
|
|
22
|
+
* `dependsSource` 설정값에 따라 추출 전략을 선택하고,
|
|
23
|
+
* 실패 시 Fallback 체인으로 다음 전략을 자동 시도한다.
|
|
24
|
+
*
|
|
25
|
+
* Fallback 순서:
|
|
26
|
+
* 1. 설정된 소스 (planParsing.dependsSource)
|
|
27
|
+
* 2. 메타데이터 테이블 스캔 (설정 소스가 metadata-table이 아닌 경우)
|
|
28
|
+
* 3. 본문 정규식 전체 스캔 (idPattern이 있을 때만)
|
|
29
|
+
*
|
|
30
|
+
* @param content - 계획서 마크다운 전체 내용
|
|
31
|
+
* @param config - 계획서 파싱 설정 (dependsSource, dependsSectionName, metadataTable)
|
|
32
|
+
* @param idPattern - 유닛 ID 매칭 정규식 패턴 (선택). 섹션 내 ID 필터링과 본문 스캔에 사용
|
|
33
|
+
* @returns 추출된 의존 유닛 정보 배열을 포함한 ToolResult. 의존성이 없으면 빈 배열(success: true)
|
|
34
|
+
*
|
|
35
|
+
* @example
|
|
36
|
+
* ```typescript
|
|
37
|
+
* const content = '## 이전 작업에서 가져올 것\n- **U-002[Mvp]**: 공유 타입';
|
|
38
|
+
* const config: PlanParsingConfig = {
|
|
39
|
+
* titleSource: 'h1',
|
|
40
|
+
* dependsSource: 'section',
|
|
41
|
+
* dependsSectionName: '이전 작업에서 가져올 것',
|
|
42
|
+
* pairingQuestionSection: '페어링 질문',
|
|
43
|
+
* metadataTable: { idField: 'Unit ID', phaseField: 'Phase', dependsField: '의존성' },
|
|
44
|
+
* };
|
|
45
|
+
* const result = extractDependencies(content, config, 'U-\\d+(?:\\[.*?\\])?');
|
|
46
|
+
* if (result.success) {
|
|
47
|
+
* // result.data → [{ unitId: 'U-002[Mvp]', description: '공유 타입' }]
|
|
48
|
+
* }
|
|
49
|
+
* ```
|
|
50
|
+
*/
|
|
51
|
+
export declare function extractDependencies(content: string, config: PlanParsingConfig, idPattern?: string): ToolResult<DepInfo[]>;
|
|
52
|
+
/**
|
|
53
|
+
* 계획서에서 의존 유닛 정보와 비유닛 컨텍스트 항목을 함께 추출한다
|
|
54
|
+
*
|
|
55
|
+
* `extractDependencies`와 동일한 Fallback 체인을 적용하되,
|
|
56
|
+
* 섹션 소스에서 발견된 비유닛 컨텍스트 항목(contextNotes)도 함께 반환한다.
|
|
57
|
+
*
|
|
58
|
+
* @param content - 계획서 마크다운 전체 내용
|
|
59
|
+
* @param config - 계획서 파싱 설정
|
|
60
|
+
* @param idPattern - 유닛 ID 매칭 정규식 패턴 (선택)
|
|
61
|
+
* @returns 유닛 의존성과 비유닛 컨텍스트 항목을 포함한 ToolResult
|
|
62
|
+
*/
|
|
63
|
+
export declare function extractDependenciesWithNotes(content: string, config: PlanParsingConfig, idPattern?: string): ToolResult<ParsedDependencyResult>;
|
|
64
|
+
//# sourceMappingURL=dependency-extractor.d.ts.map
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 의존성 추출기 — Layer 1 순수 함수
|
|
3
|
+
*
|
|
4
|
+
* 계획서 마크다운에서 의존 유닛 정보를 추출한다.
|
|
5
|
+
* `dependsSource` 설정에 따라 section, frontmatter, metadata-table 소스를 지원하고,
|
|
6
|
+
* Fallback 체인으로 부분 실패에 대응한다.
|
|
7
|
+
*
|
|
8
|
+
* Fallback 체인: 설정 소스 → 메타데이터 테이블 → 본문 정규식 스캔
|
|
9
|
+
*
|
|
10
|
+
* PRD §8.1 계획서 파싱:
|
|
11
|
+
* dependsSource: "section" → dependsSectionName 헤더 아래 **유닛ID** / [유닛ID] 수집
|
|
12
|
+
* dependsSource: "frontmatter" → YAML frontmatter의 depends 배열
|
|
13
|
+
* dependsSource: "metadata-table" → 메타데이터 테이블의 dependsField 값
|
|
14
|
+
*
|
|
15
|
+
* @module
|
|
16
|
+
*/
|
|
17
|
+
import { ok } from '../../types/index.js';
|
|
18
|
+
import { parseMetadataTable } from './metadata-parser.js';
|
|
19
|
+
import { FRONTMATTER_RE, findSectionLines, deduplicateBy, normalizeLineEndings, isNoneDependency, } from './md-utils.js';
|
|
20
|
+
import { parseDependencyLines } from './dep-line-parser.js';
|
|
21
|
+
/**
|
|
22
|
+
* 계획서에서 의존 유닛 정보를 추출한다
|
|
23
|
+
*
|
|
24
|
+
* `dependsSource` 설정값에 따라 추출 전략을 선택하고,
|
|
25
|
+
* 실패 시 Fallback 체인으로 다음 전략을 자동 시도한다.
|
|
26
|
+
*
|
|
27
|
+
* Fallback 순서:
|
|
28
|
+
* 1. 설정된 소스 (planParsing.dependsSource)
|
|
29
|
+
* 2. 메타데이터 테이블 스캔 (설정 소스가 metadata-table이 아닌 경우)
|
|
30
|
+
* 3. 본문 정규식 전체 스캔 (idPattern이 있을 때만)
|
|
31
|
+
*
|
|
32
|
+
* @param content - 계획서 마크다운 전체 내용
|
|
33
|
+
* @param config - 계획서 파싱 설정 (dependsSource, dependsSectionName, metadataTable)
|
|
34
|
+
* @param idPattern - 유닛 ID 매칭 정규식 패턴 (선택). 섹션 내 ID 필터링과 본문 스캔에 사용
|
|
35
|
+
* @returns 추출된 의존 유닛 정보 배열을 포함한 ToolResult. 의존성이 없으면 빈 배열(success: true)
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* ```typescript
|
|
39
|
+
* const content = '## 이전 작업에서 가져올 것\n- **U-002[Mvp]**: 공유 타입';
|
|
40
|
+
* const config: PlanParsingConfig = {
|
|
41
|
+
* titleSource: 'h1',
|
|
42
|
+
* dependsSource: 'section',
|
|
43
|
+
* dependsSectionName: '이전 작업에서 가져올 것',
|
|
44
|
+
* pairingQuestionSection: '페어링 질문',
|
|
45
|
+
* metadataTable: { idField: 'Unit ID', phaseField: 'Phase', dependsField: '의존성' },
|
|
46
|
+
* };
|
|
47
|
+
* const result = extractDependencies(content, config, 'U-\\d+(?:\\[.*?\\])?');
|
|
48
|
+
* if (result.success) {
|
|
49
|
+
* // result.data → [{ unitId: 'U-002[Mvp]', description: '공유 타입' }]
|
|
50
|
+
* }
|
|
51
|
+
* ```
|
|
52
|
+
*/
|
|
53
|
+
export function extractDependencies(content, config, idPattern) {
|
|
54
|
+
const result = extractDependenciesWithNotes(content, config, idPattern);
|
|
55
|
+
if (!result.success)
|
|
56
|
+
return result;
|
|
57
|
+
return ok(result.data.deps);
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* 계획서에서 의존 유닛 정보와 비유닛 컨텍스트 항목을 함께 추출한다
|
|
61
|
+
*
|
|
62
|
+
* `extractDependencies`와 동일한 Fallback 체인을 적용하되,
|
|
63
|
+
* 섹션 소스에서 발견된 비유닛 컨텍스트 항목(contextNotes)도 함께 반환한다.
|
|
64
|
+
*
|
|
65
|
+
* @param content - 계획서 마크다운 전체 내용
|
|
66
|
+
* @param config - 계획서 파싱 설정
|
|
67
|
+
* @param idPattern - 유닛 ID 매칭 정규식 패턴 (선택)
|
|
68
|
+
* @returns 유닛 의존성과 비유닛 컨텍스트 항목을 포함한 ToolResult
|
|
69
|
+
*/
|
|
70
|
+
export function extractDependenciesWithNotes(content, config, idPattern) {
|
|
71
|
+
const normalized = normalizeLineEndings(content);
|
|
72
|
+
// 1. 설정된 소스로 시도
|
|
73
|
+
const primary = extractBySource(normalized, config, idPattern);
|
|
74
|
+
if (primary.deps.length > 0) {
|
|
75
|
+
return ok({
|
|
76
|
+
deps: deduplicateBy(primary.deps, (d) => d.unitId),
|
|
77
|
+
contextNotes: primary.contextNotes,
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
// 2. Fallback: 메타데이터 테이블 (설정 소스가 metadata-table이면 이미 시도했으므로 건너뜀)
|
|
81
|
+
if (config.dependsSource !== 'metadata-table') {
|
|
82
|
+
const fromTableResult = parseMetadataTable(normalized, config.metadataTable);
|
|
83
|
+
const fromTable = fromTableResult.success
|
|
84
|
+
? fromTableResult.data.depends.map((unitId) => ({ unitId, description: '' }))
|
|
85
|
+
: [];
|
|
86
|
+
if (fromTable.length > 0) {
|
|
87
|
+
return ok({
|
|
88
|
+
deps: deduplicateBy(fromTable, (d) => d.unitId),
|
|
89
|
+
contextNotes: primary.contextNotes,
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
// 3. Fallback: 본문 정규식 스캔 (idPattern이 있을 때만)
|
|
94
|
+
if (idPattern) {
|
|
95
|
+
const fromScan = extractFromBodyScan(normalized, idPattern);
|
|
96
|
+
if (fromScan.length > 0) {
|
|
97
|
+
return ok({
|
|
98
|
+
deps: deduplicateBy(fromScan, (d) => d.unitId),
|
|
99
|
+
contextNotes: primary.contextNotes,
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
return ok({ deps: [], contextNotes: primary.contextNotes });
|
|
104
|
+
}
|
|
105
|
+
// ── 소스별 추출 전략 ──
|
|
106
|
+
/**
|
|
107
|
+
* 설정된 소스에 따라 적절한 추출 전략을 선택한다
|
|
108
|
+
*/
|
|
109
|
+
function extractBySource(content, config, idPattern) {
|
|
110
|
+
switch (config.dependsSource) {
|
|
111
|
+
case 'section':
|
|
112
|
+
return config.dependsSectionName
|
|
113
|
+
? extractFromSection(content, config.dependsSectionName, idPattern)
|
|
114
|
+
: { deps: [], contextNotes: [] };
|
|
115
|
+
case 'frontmatter':
|
|
116
|
+
return { deps: extractFromFrontmatter(content), contextNotes: [] };
|
|
117
|
+
case 'metadata-table':
|
|
118
|
+
return { deps: extractFromMetadataTable(content, config.metadataTable), contextNotes: [] };
|
|
119
|
+
default:
|
|
120
|
+
return { deps: [], contextNotes: [] };
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
/** 섹션 기반으로 의존성과 비유닛 컨텍스트 항목을 추출한다 */
|
|
124
|
+
function extractFromSection(content, sectionName, idPattern) {
|
|
125
|
+
const sectionLines = findSectionLines(content, sectionName, { allowBoldMarker: true });
|
|
126
|
+
if (sectionLines.length === 0)
|
|
127
|
+
return { deps: [], contextNotes: [] };
|
|
128
|
+
return parseDependencyLines(sectionLines, idPattern);
|
|
129
|
+
}
|
|
130
|
+
/** YAML frontmatter의 depends 필드에서 의존성을 추출한다 (배열/콤마/단일값) */
|
|
131
|
+
function extractFromFrontmatter(content) {
|
|
132
|
+
const fmMatch = content.match(FRONTMATTER_RE);
|
|
133
|
+
if (!fmMatch?.[1])
|
|
134
|
+
return [];
|
|
135
|
+
const fmContent = fmMatch[1];
|
|
136
|
+
const lines = fmContent.split('\n');
|
|
137
|
+
for (const line of lines) {
|
|
138
|
+
const trimmed = line.trim();
|
|
139
|
+
// depends: ... 패턴 매칭 (대소문자 무시)
|
|
140
|
+
const kvMatch = trimmed.match(/^depends\s*:\s*(.+)$/i);
|
|
141
|
+
if (!kvMatch?.[1])
|
|
142
|
+
continue;
|
|
143
|
+
let value = kvMatch[1].trim();
|
|
144
|
+
// YAML 인라인 배열 형식: [U-117, U-116]
|
|
145
|
+
if (value.startsWith('[') && value.endsWith(']')) {
|
|
146
|
+
value = value.slice(1, -1);
|
|
147
|
+
}
|
|
148
|
+
// 따옴표 제거 (YAML 문자열)
|
|
149
|
+
if ((value.startsWith('"') && value.endsWith('"')) ||
|
|
150
|
+
(value.startsWith("'") && value.endsWith("'"))) {
|
|
151
|
+
value = value.slice(1, -1);
|
|
152
|
+
}
|
|
153
|
+
return value
|
|
154
|
+
.split(',')
|
|
155
|
+
.map((s) => s.trim())
|
|
156
|
+
.filter((s) => !isNoneDependency(s))
|
|
157
|
+
.map((unitId) => ({
|
|
158
|
+
unitId,
|
|
159
|
+
description: '',
|
|
160
|
+
}));
|
|
161
|
+
}
|
|
162
|
+
return [];
|
|
163
|
+
}
|
|
164
|
+
/** 메타데이터 테이블에서 의존성을 추출한다 */
|
|
165
|
+
function extractFromMetadataTable(content, tableConfig) {
|
|
166
|
+
const tableResult = parseMetadataTable(content, tableConfig);
|
|
167
|
+
if (!tableResult.success)
|
|
168
|
+
return [];
|
|
169
|
+
return tableResult.data.depends.map((unitId) => ({
|
|
170
|
+
unitId,
|
|
171
|
+
description: '',
|
|
172
|
+
}));
|
|
173
|
+
}
|
|
174
|
+
/** 본문 전체에서 ID 패턴으로 의존성을 스캔한다 (Fallback 최후 수단) */
|
|
175
|
+
function extractFromBodyScan(content, idPattern) {
|
|
176
|
+
try {
|
|
177
|
+
const regex = new RegExp(idPattern, 'g');
|
|
178
|
+
const matches = content.match(regex);
|
|
179
|
+
if (!matches)
|
|
180
|
+
return [];
|
|
181
|
+
// 중복 제거
|
|
182
|
+
const unique = [...new Set(matches)];
|
|
183
|
+
return unique.map((unitId) => ({
|
|
184
|
+
unitId,
|
|
185
|
+
description: '',
|
|
186
|
+
}));
|
|
187
|
+
}
|
|
188
|
+
catch {
|
|
189
|
+
// 잘못된 정규식 — 빈 배열 반환 (Graceful Degradation)
|
|
190
|
+
return [];
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
//# sourceMappingURL=dependency-extractor.js.map
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Core 파서 — 공개 API barrel export
|
|
3
|
+
*
|
|
4
|
+
* 계획서/백로그 마크다운 파싱 함수의 진입점.
|
|
5
|
+
* 내부 구현 상세는 노출하지 않는다.
|
|
6
|
+
*
|
|
7
|
+
* @module
|
|
8
|
+
*/
|
|
9
|
+
export { parseUnitPlan } from './plan-parser.js';
|
|
10
|
+
export type { ParseUnitPlanResult } from './plan-parser.js';
|
|
11
|
+
export { parseBacklog } from './backlog-parser.js';
|
|
12
|
+
export { extractTitle } from './title-extractor.js';
|
|
13
|
+
export { parseMetadataTable } from './metadata-parser.js';
|
|
14
|
+
export type { MetadataTableResult } from './metadata-parser.js';
|
|
15
|
+
export { extractDependencies, extractDependenciesWithNotes } from './dependency-extractor.js';
|
|
16
|
+
export type { ParsedDependencyResult } from './dep-line-parser.js';
|
|
17
|
+
export { extractPairingQuestions } from './pairing-question-extractor.js';
|
|
18
|
+
export { findSectionLines, escapeRegex, safeRegex, normalizeLineEndings, stripCR, getHeadingPrefix, isSameLevelHeading, deduplicateBy, FRONTMATTER_RE, HEADING_RE, } from './md-utils.js';
|
|
19
|
+
export type { FindSectionOptions } from './md-utils.js';
|
|
20
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Core 파서 — 공개 API barrel export
|
|
3
|
+
*
|
|
4
|
+
* 계획서/백로그 마크다운 파싱 함수의 진입점.
|
|
5
|
+
* 내부 구현 상세는 노출하지 않는다.
|
|
6
|
+
*
|
|
7
|
+
* @module
|
|
8
|
+
*/
|
|
9
|
+
// 통합 파서 (메인 엔트리포인트)
|
|
10
|
+
export { parseUnitPlan } from './plan-parser.js';
|
|
11
|
+
// 백로그 파서
|
|
12
|
+
export { parseBacklog } from './backlog-parser.js';
|
|
13
|
+
// 개별 추출기 (필요 시 단독 사용)
|
|
14
|
+
export { extractTitle } from './title-extractor.js';
|
|
15
|
+
export { parseMetadataTable } from './metadata-parser.js';
|
|
16
|
+
export { extractDependencies, extractDependenciesWithNotes } from './dependency-extractor.js';
|
|
17
|
+
export { extractPairingQuestions } from './pairing-question-extractor.js';
|
|
18
|
+
// 공통 유틸 (다른 Core 모듈에서 사용)
|
|
19
|
+
export { findSectionLines, escapeRegex, safeRegex, normalizeLineEndings, stripCR, getHeadingPrefix, isSameLevelHeading, deduplicateBy, FRONTMATTER_RE, HEADING_RE, } from './md-utils.js';
|
|
20
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 마크다운 파싱 공통 유틸리티 — Layer 1 순수 함수
|
|
3
|
+
*
|
|
4
|
+
* 여러 파서에서 공유하는 정규식 상수와 헬퍼 함수 모음.
|
|
5
|
+
* 섹션 탐색, 정규식 유틸, 라인 처리 등.
|
|
6
|
+
*
|
|
7
|
+
* @module
|
|
8
|
+
*/
|
|
9
|
+
/** Frontmatter 블록 패턴: ---로 감싸진 YAML 영역 */
|
|
10
|
+
export declare const FRONTMATTER_RE: RegExp;
|
|
11
|
+
/** 마크다운 헤딩 패턴: # ~ ###### 레벨 */
|
|
12
|
+
export declare const HEADING_RE: RegExp;
|
|
13
|
+
/** 볼드 마커 패턴: **섹션명** (콜론/대시 허용) */
|
|
14
|
+
export declare const BOLD_MARKER_RE: RegExp;
|
|
15
|
+
/**
|
|
16
|
+
* 섹션 탐색 옵션
|
|
17
|
+
*/
|
|
18
|
+
export interface FindSectionOptions {
|
|
19
|
+
/** 볼드 마커(**섹션명**) 시작도 허용 (기본: false) */
|
|
20
|
+
allowBoldMarker?: boolean;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* 섹션명에 해당하는 콘텐츠 라인들을 추출한다
|
|
24
|
+
*
|
|
25
|
+
* 헤딩(##, ### 등)에서 sectionName을 포함하는 섹션을 찾고,
|
|
26
|
+
* 동일/상위 레벨의 다음 헤딩까지의 라인을 수집한다.
|
|
27
|
+
*
|
|
28
|
+
* @param content - 마크다운 전체 내용
|
|
29
|
+
* @param sectionName - 찾을 섹션명 (includes 매칭)
|
|
30
|
+
* @param options - 탐색 옵션 (볼드 마커 허용 등)
|
|
31
|
+
* @returns 섹션 내 라인 배열
|
|
32
|
+
*/
|
|
33
|
+
export declare function findSectionLines(content: string, sectionName: string, options?: FindSectionOptions): string[];
|
|
34
|
+
/**
|
|
35
|
+
* 정규식 특수문자를 이스케이프한다
|
|
36
|
+
*/
|
|
37
|
+
export declare function escapeRegex(str: string): string;
|
|
38
|
+
/**
|
|
39
|
+
* 정규식 문자열을 안전하게 RegExp로 변환한다
|
|
40
|
+
*/
|
|
41
|
+
export declare function safeRegex(pattern: string): RegExp | null;
|
|
42
|
+
/**
|
|
43
|
+
* 콘텐츠의 줄바꿈을 LF로 정규화한다
|
|
44
|
+
*
|
|
45
|
+
* Windows CRLF(\r\n)를 LF(\n)로 변환.
|
|
46
|
+
* 각 파서의 진입점에서 한 번 호출하면 내부 로직에서 \r 걱정 불필요.
|
|
47
|
+
* \r\n이 없으면 원본 그대로 반환하여 성능 영향 최소화.
|
|
48
|
+
*/
|
|
49
|
+
export declare function normalizeLineEndings(content: string): string;
|
|
50
|
+
/**
|
|
51
|
+
* 라인 끝의 캐리지 리턴(\r)을 제거한다
|
|
52
|
+
*/
|
|
53
|
+
export declare function stripCR(line: string): string;
|
|
54
|
+
/**
|
|
55
|
+
* 섹션 헤더의 헤딩 레벨 프리픽스를 추출한다
|
|
56
|
+
*
|
|
57
|
+
* @example
|
|
58
|
+
* getHeadingPrefix('# 유닛 구현') // → '#'
|
|
59
|
+
* getHeadingPrefix('## 작업 백로그') // → '##'
|
|
60
|
+
* getHeadingPrefix('plain text') // → null
|
|
61
|
+
*/
|
|
62
|
+
export declare function getHeadingPrefix(sectionHeader: string): string | null;
|
|
63
|
+
/**
|
|
64
|
+
* 라인이 주어진 헤딩과 동급인지 확인한다
|
|
65
|
+
*
|
|
66
|
+
* 헤딩 레벨이 동일한 경우만 true.
|
|
67
|
+
* 예: headingPrefix='#'일 때 '# foo' → true, '## foo' → false
|
|
68
|
+
*/
|
|
69
|
+
export declare function isSameLevelHeading(line: string, headingPrefix: string | null): boolean;
|
|
70
|
+
/**
|
|
71
|
+
* 값이 "의존성 없음"을 나타내는지 판단한다
|
|
72
|
+
*
|
|
73
|
+
* 대소문자 무관으로 "None", "-", 빈 문자열 등을 인식.
|
|
74
|
+
* 모든 파서에서 재사용하여 일관된 None 필터링 보장.
|
|
75
|
+
*/
|
|
76
|
+
export declare function isNoneDependency(value: string): boolean;
|
|
77
|
+
/**
|
|
78
|
+
* 배열에서 키 기준 중복을 제거한다 (첫 등장 유지)
|
|
79
|
+
*/
|
|
80
|
+
export declare function deduplicateBy<T>(items: T[], keyFn: (item: T) => string): T[];
|
|
81
|
+
//# sourceMappingURL=md-utils.d.ts.map
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 마크다운 파싱 공통 유틸리티 — Layer 1 순수 함수
|
|
3
|
+
*
|
|
4
|
+
* 여러 파서에서 공유하는 정규식 상수와 헬퍼 함수 모음.
|
|
5
|
+
* 섹션 탐색, 정규식 유틸, 라인 처리 등.
|
|
6
|
+
*
|
|
7
|
+
* @module
|
|
8
|
+
*/
|
|
9
|
+
/** Frontmatter 블록 패턴: ---로 감싸진 YAML 영역 */
|
|
10
|
+
export const FRONTMATTER_RE = /^---\r?\n([\s\S]*?)\r?\n---/;
|
|
11
|
+
/** 마크다운 헤딩 패턴: # ~ ###### 레벨 */
|
|
12
|
+
export const HEADING_RE = /^(#{1,6})\s+(.+)$/;
|
|
13
|
+
/** 볼드 마커 패턴: **섹션명** (콜론/대시 허용) */
|
|
14
|
+
export const BOLD_MARKER_RE = /^\*\*[^*]+\*\*\s*[:\-—]?\s*$/;
|
|
15
|
+
/**
|
|
16
|
+
* 섹션명에 해당하는 콘텐츠 라인들을 추출한다
|
|
17
|
+
*
|
|
18
|
+
* 헤딩(##, ### 등)에서 sectionName을 포함하는 섹션을 찾고,
|
|
19
|
+
* 동일/상위 레벨의 다음 헤딩까지의 라인을 수집한다.
|
|
20
|
+
*
|
|
21
|
+
* @param content - 마크다운 전체 내용
|
|
22
|
+
* @param sectionName - 찾을 섹션명 (includes 매칭)
|
|
23
|
+
* @param options - 탐색 옵션 (볼드 마커 허용 등)
|
|
24
|
+
* @returns 섹션 내 라인 배열
|
|
25
|
+
*/
|
|
26
|
+
export function findSectionLines(content, sectionName, options = {}) {
|
|
27
|
+
const { allowBoldMarker = false } = options;
|
|
28
|
+
const lines = content.split('\n');
|
|
29
|
+
let inSection = false;
|
|
30
|
+
let sectionHeadingLevel = 0;
|
|
31
|
+
const result = [];
|
|
32
|
+
for (const line of lines) {
|
|
33
|
+
const trimmed = line.trim();
|
|
34
|
+
const headingMatch = trimmed.match(HEADING_RE);
|
|
35
|
+
if (inSection) {
|
|
36
|
+
if (headingMatch) {
|
|
37
|
+
const level = (headingMatch[1] ?? '').length;
|
|
38
|
+
if (sectionHeadingLevel > 0 && level <= sectionHeadingLevel)
|
|
39
|
+
break;
|
|
40
|
+
if (sectionHeadingLevel === 0)
|
|
41
|
+
break;
|
|
42
|
+
}
|
|
43
|
+
if (allowBoldMarker && sectionHeadingLevel === 0 && BOLD_MARKER_RE.test(trimmed)) {
|
|
44
|
+
break;
|
|
45
|
+
}
|
|
46
|
+
result.push(line);
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
if (headingMatch?.[2]?.includes(sectionName)) {
|
|
50
|
+
inSection = true;
|
|
51
|
+
sectionHeadingLevel = (headingMatch[1] ?? '').length;
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
54
|
+
if (allowBoldMarker && trimmed.includes(`**${sectionName}**`)) {
|
|
55
|
+
inSection = true;
|
|
56
|
+
sectionHeadingLevel = 0;
|
|
57
|
+
continue;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return result;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* 정규식 특수문자를 이스케이프한다
|
|
65
|
+
*/
|
|
66
|
+
export function escapeRegex(str) {
|
|
67
|
+
return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* 정규식 문자열을 안전하게 RegExp로 변환한다
|
|
71
|
+
*/
|
|
72
|
+
export function safeRegex(pattern) {
|
|
73
|
+
try {
|
|
74
|
+
return new RegExp(pattern);
|
|
75
|
+
}
|
|
76
|
+
catch {
|
|
77
|
+
return null;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* 콘텐츠의 줄바꿈을 LF로 정규화한다
|
|
82
|
+
*
|
|
83
|
+
* Windows CRLF(\r\n)를 LF(\n)로 변환.
|
|
84
|
+
* 각 파서의 진입점에서 한 번 호출하면 내부 로직에서 \r 걱정 불필요.
|
|
85
|
+
* \r\n이 없으면 원본 그대로 반환하여 성능 영향 최소화.
|
|
86
|
+
*/
|
|
87
|
+
export function normalizeLineEndings(content) {
|
|
88
|
+
return content.includes('\r') ? content.replace(/\r\n/g, '\n') : content;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* 라인 끝의 캐리지 리턴(\r)을 제거한다
|
|
92
|
+
*/
|
|
93
|
+
export function stripCR(line) {
|
|
94
|
+
return line.endsWith('\r') ? line.slice(0, -1) : line;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* 섹션 헤더의 헤딩 레벨 프리픽스를 추출한다
|
|
98
|
+
*
|
|
99
|
+
* @example
|
|
100
|
+
* getHeadingPrefix('# 유닛 구현') // → '#'
|
|
101
|
+
* getHeadingPrefix('## 작업 백로그') // → '##'
|
|
102
|
+
* getHeadingPrefix('plain text') // → null
|
|
103
|
+
*/
|
|
104
|
+
export function getHeadingPrefix(sectionHeader) {
|
|
105
|
+
const match = sectionHeader.trim().match(/^(#{1,6})\s/);
|
|
106
|
+
return match?.[1] ?? null;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* 라인이 주어진 헤딩과 동급인지 확인한다
|
|
110
|
+
*
|
|
111
|
+
* 헤딩 레벨이 동일한 경우만 true.
|
|
112
|
+
* 예: headingPrefix='#'일 때 '# foo' → true, '## foo' → false
|
|
113
|
+
*/
|
|
114
|
+
export function isSameLevelHeading(line, headingPrefix) {
|
|
115
|
+
if (!headingPrefix)
|
|
116
|
+
return false;
|
|
117
|
+
const trimmed = stripCR(line).trim();
|
|
118
|
+
// 동일 레벨: prefix + 공백으로 시작하되, 더 깊은 레벨(prefix + #)은 제외
|
|
119
|
+
return trimmed.startsWith(headingPrefix + ' ') && !trimmed.startsWith(headingPrefix + '#');
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* 값이 "의존성 없음"을 나타내는지 판단한다
|
|
123
|
+
*
|
|
124
|
+
* 대소문자 무관으로 "None", "-", 빈 문자열 등을 인식.
|
|
125
|
+
* 모든 파서에서 재사용하여 일관된 None 필터링 보장.
|
|
126
|
+
*/
|
|
127
|
+
export function isNoneDependency(value) {
|
|
128
|
+
const normalized = value.trim().toLowerCase();
|
|
129
|
+
return normalized === '' || normalized === 'none' || normalized === '-' || normalized === '없음';
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* 배열에서 키 기준 중복을 제거한다 (첫 등장 유지)
|
|
133
|
+
*/
|
|
134
|
+
export function deduplicateBy(items, keyFn) {
|
|
135
|
+
const seen = new Set();
|
|
136
|
+
return items.filter((item) => {
|
|
137
|
+
const key = keyFn(item);
|
|
138
|
+
if (seen.has(key))
|
|
139
|
+
return false;
|
|
140
|
+
seen.add(key);
|
|
141
|
+
return true;
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
//# sourceMappingURL=md-utils.js.map
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 메타데이터 테이블 파서 — Layer 1 순수 함수
|
|
3
|
+
*
|
|
4
|
+
* 계획서 마크다운의 메타데이터 테이블(2-column key-value)에서
|
|
5
|
+
* 유닛 메타정보를 추출한다.
|
|
6
|
+
*
|
|
7
|
+
* 설정의 `metadataTable` 필드명으로 시맨틱 키(unitId, phase, depends)에 매핑.
|
|
8
|
+
* 테이블이 없으면 모든 필드가 null인 결과 반환 (Graceful Degradation).
|
|
9
|
+
*
|
|
10
|
+
* @module
|
|
11
|
+
*/
|
|
12
|
+
import type { MetadataTableConfig, ToolResult } from '../../types/index.js';
|
|
13
|
+
/**
|
|
14
|
+
* 메타데이터 테이블 파싱 결과
|
|
15
|
+
*
|
|
16
|
+
* 설정 필드명으로 매핑된 시맨틱 키와 원본 key-value 맵을 제공.
|
|
17
|
+
*/
|
|
18
|
+
export interface MetadataTableResult {
|
|
19
|
+
/** Unit ID (tableConfig.idField 키로 찾은 값) */
|
|
20
|
+
unitId?: string;
|
|
21
|
+
/** Phase (tableConfig.phaseField 키로 찾은 값) */
|
|
22
|
+
phase?: string;
|
|
23
|
+
/** 의존성 ID 목록 (tableConfig.dependsField 키로 찾은 값을 콤마로 분리) */
|
|
24
|
+
depends: string[];
|
|
25
|
+
/** 원본 key-value 맵 (테이블의 모든 항목) */
|
|
26
|
+
raw: Record<string, string>;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* 마크다운 2-column 테이블에서 메타데이터를 파싱한다
|
|
30
|
+
*
|
|
31
|
+
* 첫 번째 2-column 테이블을 찾아 key-value 쌍으로 추출하고,
|
|
32
|
+
* 설정의 필드명으로 시맨틱 키(unitId, phase, depends)에 매핑한다.
|
|
33
|
+
*
|
|
34
|
+
* @param content - 마크다운 전체 내용
|
|
35
|
+
* @param tableConfig - 메타데이터 테이블 필드명 매핑 설정
|
|
36
|
+
* @returns 파싱된 메타데이터 결과를 포함한 ToolResult
|
|
37
|
+
*
|
|
38
|
+
* @example
|
|
39
|
+
* ```typescript
|
|
40
|
+
* const content = '| 항목 | 내용 |\n|---|---|\n| Unit ID | U-005 |\n| Phase | MVP |';
|
|
41
|
+
* const config = { idField: 'Unit ID', phaseField: 'Phase', dependsField: '의존성' };
|
|
42
|
+
* const result = parseMetadataTable(content, config);
|
|
43
|
+
* if (result.success) {
|
|
44
|
+
* // result.data.unitId === 'U-005'
|
|
45
|
+
* }
|
|
46
|
+
* ```
|
|
47
|
+
*/
|
|
48
|
+
export declare function parseMetadataTable(content: string, tableConfig: MetadataTableConfig): ToolResult<MetadataTableResult>;
|
|
49
|
+
//# sourceMappingURL=metadata-parser.d.ts.map
|