sdd-tool 1.0.1 → 1.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 -21
- package/README.md +490 -471
- package/bin/sdd.js +2 -2
- package/dist/cli/index.js +1219 -443
- package/dist/cli/index.js.map +1 -1
- package/dist/index.js.map +1 -1
- package/package.json +79 -81
- package/templates/agents.md +62 -62
- package/templates/constitution.md +43 -43
- package/templates/git/.gitattributes.sdd +39 -0
- package/templates/git/.gitignore.sdd +44 -0
- package/templates/git/.gitmessage +20 -0
- package/templates/git/commitlint.config.js +122 -0
- package/templates/github/branch-protection.md +194 -0
- package/templates/github/workflows/sdd-labeler.yml +125 -0
- package/templates/github/workflows/sdd-validate.yml +85 -0
- package/templates/proposal.md +71 -71
- package/templates/spec.md +27 -27
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/types/index.ts","../src/errors/codes.ts","../src/errors/messages.ts","../src/errors/base.ts"],"sourcesContent":["/**\r\n * 공통 타입 정의\r\n */\r\n\r\n// ============================================================\r\n// 스펙 관련 타입\r\n// ============================================================\r\n\r\n/**\r\n * 스펙 문서 구조\r\n */\r\nexport interface Spec {\r\n id: string;\r\n title: string;\r\n status: SpecStatus;\r\n requirements: Requirement[];\r\n scenarios: Scenario[];\r\n dependencies: string[];\r\n metadata: SpecMetadata;\r\n}\r\n\r\nexport type SpecStatus = 'draft' | 'approved' | 'implemented';\r\n\r\nexport interface SpecMetadata {\r\n created?: string;\r\n updated?: string;\r\n author?: string;\r\n}\r\n\r\n/**\r\n * 요구사항 (RFC 2119)\r\n */\r\nexport interface Requirement {\r\n id: string;\r\n level: RequirementLevel;\r\n description: string;\r\n}\r\n\r\nexport type RequirementLevel = 'SHALL' | 'MUST' | 'SHOULD' | 'MAY';\r\n\r\n/**\r\n * 시나리오 (GIVEN-WHEN-THEN)\r\n */\r\nexport interface Scenario {\r\n name: string;\r\n given: string[];\r\n when: string;\r\n then: string[];\r\n}\r\n\r\n// ============================================================\r\n// Constitution 관련 타입\r\n// ============================================================\r\n\r\n/**\r\n * Constitution 원칙\r\n */\r\nexport interface Principle {\r\n id: string;\r\n title: string;\r\n description: string;\r\n level: PrincipleLevel;\r\n}\r\n\r\nexport type PrincipleLevel = 'core' | 'technical' | 'forbidden';\r\n\r\nexport interface Constitution {\r\n projectName: string;\r\n principles: Principle[];\r\n technicalStack?: string[];\r\n constraints?: string[];\r\n}\r\n\r\n// ============================================================\r\n// 변경 워크플로우 관련 타입\r\n// ============================================================\r\n\r\n/**\r\n * 변경 제안\r\n */\r\nexport interface Proposal {\r\n id: string;\r\n title: string;\r\n rationale: string;\r\n affectedSpecs: string[];\r\n deltas: Delta[];\r\n status: ProposalStatus;\r\n createdAt: string;\r\n}\r\n\r\nexport type ProposalStatus = 'draft' | 'review' | 'approved' | 'applied' | 'archived';\r\n\r\n/**\r\n * 델타 (변경사항)\r\n */\r\nexport interface Delta {\r\n type: DeltaType;\r\n target: string;\r\n before?: string;\r\n after?: string;\r\n}\r\n\r\nexport type DeltaType = 'ADDED' | 'MODIFIED' | 'REMOVED';\r\n\r\n// ============================================================\r\n// 검증 관련 타입\r\n// ============================================================\r\n\r\n/**\r\n * 검증 결과\r\n */\r\nexport interface ValidationResult {\r\n valid: boolean;\r\n errors: SpecValidationError[];\r\n warnings: SpecValidationWarning[];\r\n}\r\n\r\nexport interface SpecValidationError {\r\n code: string;\r\n message: string;\r\n location?: Location;\r\n}\r\n\r\nexport interface SpecValidationWarning {\r\n code: string;\r\n message: string;\r\n location?: Location;\r\n}\r\n\r\nexport interface Location {\r\n file?: string;\r\n line?: number;\r\n column?: number;\r\n}\r\n\r\n// ============================================================\r\n// 분석 관련 타입\r\n// ============================================================\r\n\r\n/**\r\n * 분석 결과\r\n */\r\nexport interface AnalysisResult {\r\n scale: Scale;\r\n recommendation: WorkflowRecommendation;\r\n confidence: number;\r\n rationale: string;\r\n alternatives: string[];\r\n}\r\n\r\nexport type Scale = 'small' | 'medium' | 'large';\r\nexport type WorkflowRecommendation = 'direct' | 'change' | 'new';\r\n\r\n// ============================================================\r\n// 유틸리티 타입\r\n// ============================================================\r\n\r\n/**\r\n * Result 타입 (에러 처리용)\r\n */\r\nexport type Result<T, E = Error> =\r\n | { success: true; data: T }\r\n | { success: false; error: E };\r\n\r\n/**\r\n * 성공 결과 생성 헬퍼\r\n */\r\nexport function success<T>(data: T): Result<T, never> {\r\n return { success: true, data };\r\n}\r\n\r\n/**\r\n * 실패 결과 생성 헬퍼\r\n */\r\nexport function failure<E>(error: E): Result<never, E> {\r\n return { success: false, error };\r\n}\r\n","/**\r\n * 에러 코드 정의\r\n */\r\n\r\n/**\r\n * CLI 종료 코드\r\n */\r\nexport const ExitCode = {\r\n SUCCESS: 0,\r\n GENERAL_ERROR: 1,\r\n VALIDATION_FAILED: 2,\r\n CONSTITUTION_VIOLATION: 3,\r\n FILE_SYSTEM_ERROR: 4,\r\n USER_CANCELLED: 5,\r\n INIT_ERROR: 6,\r\n VALIDATION_ERROR: 7,\r\n} as const;\r\n\r\nexport type ExitCode = (typeof ExitCode)[keyof typeof ExitCode];\r\n\r\n/**\r\n * 에러 코드\r\n */\r\nexport const ErrorCode = {\r\n // 일반 에러 (E0xx)\r\n UNKNOWN: 'E001',\r\n INVALID_ARGUMENT: 'E002',\r\n NOT_INITIALIZED: 'E003',\r\n\r\n // 파일 시스템 에러 (E1xx)\r\n FILE_NOT_FOUND: 'E101',\r\n FILE_READ_ERROR: 'E102',\r\n FILE_WRITE_ERROR: 'E103',\r\n DIRECTORY_NOT_FOUND: 'E104',\r\n DIRECTORY_EXISTS: 'E105',\r\n\r\n // 스펙 검증 에러 (E2xx)\r\n SPEC_PARSE_ERROR: 'E201',\r\n SPEC_INVALID_FORMAT: 'E202',\r\n SPEC_MISSING_REQUIRED: 'E203',\r\n RFC2119_VIOLATION: 'E204',\r\n GWT_INVALID_FORMAT: 'E205',\r\n\r\n // Constitution 에러 (E3xx)\r\n CONSTITUTION_NOT_FOUND: 'E301',\r\n CONSTITUTION_PARSE_ERROR: 'E302',\r\n CONSTITUTION_VIOLATION: 'E303',\r\n CONSTITUTION_VERSION_MISMATCH: 'E304',\r\n\r\n // 변경 워크플로우 에러 (E4xx)\r\n PROPOSAL_NOT_FOUND: 'E401',\r\n PROPOSAL_INVALID: 'E402',\r\n DELTA_CONFLICT: 'E403',\r\n ARCHIVE_FAILED: 'E404',\r\n\r\n // 분석 에러 (E5xx)\r\n ANALYSIS_FAILED: 'E501',\r\n INSUFFICIENT_DATA: 'E502',\r\n} as const;\r\n\r\nexport type ErrorCode = (typeof ErrorCode)[keyof typeof ErrorCode];\r\n","/**\r\n * 에러 메시지 정의\r\n */\r\nimport { ErrorCode } from './codes.js';\r\n\r\n/**\r\n * 에러 코드별 메시지 템플릿\r\n */\r\nexport const ErrorMessages: Record<ErrorCode, string> = {\r\n // 일반 에러\r\n [ErrorCode.UNKNOWN]: '알 수 없는 오류가 발생했습니다',\r\n [ErrorCode.INVALID_ARGUMENT]: '잘못된 인자입니다: {0}',\r\n [ErrorCode.NOT_INITIALIZED]: 'SDD 프로젝트가 초기화되지 않았습니다. `sdd init`을 먼저 실행하세요',\r\n\r\n // 파일 시스템 에러\r\n [ErrorCode.FILE_NOT_FOUND]: '파일을 찾을 수 없습니다: {0}',\r\n [ErrorCode.FILE_READ_ERROR]: '파일 읽기 실패: {0}',\r\n [ErrorCode.FILE_WRITE_ERROR]: '파일 쓰기 실패: {0}',\r\n [ErrorCode.DIRECTORY_NOT_FOUND]: '디렉토리를 찾을 수 없습니다: {0}',\r\n [ErrorCode.DIRECTORY_EXISTS]: '디렉토리가 이미 존재합니다: {0}',\r\n\r\n // 스펙 검증 에러\r\n [ErrorCode.SPEC_PARSE_ERROR]: '스펙 파싱 실패: {0}',\r\n [ErrorCode.SPEC_INVALID_FORMAT]: '잘못된 스펙 형식: {0}',\r\n [ErrorCode.SPEC_MISSING_REQUIRED]: '필수 필드 누락: {0}',\r\n [ErrorCode.RFC2119_VIOLATION]: 'RFC 2119 형식 위반: {0}',\r\n [ErrorCode.GWT_INVALID_FORMAT]: 'GIVEN-WHEN-THEN 형식 위반: {0}',\r\n\r\n // Constitution 에러\r\n [ErrorCode.CONSTITUTION_NOT_FOUND]: 'constitution.md를 찾을 수 없습니다',\r\n [ErrorCode.CONSTITUTION_PARSE_ERROR]: 'Constitution 파싱 실패: {0}',\r\n [ErrorCode.CONSTITUTION_VIOLATION]: 'Constitution 원칙 위반: {0}',\r\n [ErrorCode.CONSTITUTION_VERSION_MISMATCH]: 'Constitution 버전 불일치: {0}',\r\n\r\n // 변경 워크플로우 에러\r\n [ErrorCode.PROPOSAL_NOT_FOUND]: '제안서를 찾을 수 없습니다: {0}',\r\n [ErrorCode.PROPOSAL_INVALID]: '잘못된 제안서 형식: {0}',\r\n [ErrorCode.DELTA_CONFLICT]: '델타 충돌: {0}',\r\n [ErrorCode.ARCHIVE_FAILED]: '아카이브 실패: {0}',\r\n\r\n // 분석 에러\r\n [ErrorCode.ANALYSIS_FAILED]: '분석 실패: {0}',\r\n [ErrorCode.INSUFFICIENT_DATA]: '분석에 필요한 데이터 부족: {0}',\r\n};\r\n\r\n/**\r\n * 메시지 템플릿에 인자를 적용\r\n */\r\nexport function formatMessage(code: ErrorCode, ...args: string[]): string {\r\n let message = ErrorMessages[code];\r\n args.forEach((arg, index) => {\r\n message = message.replace(`{${index}}`, arg);\r\n });\r\n return message;\r\n}\r\n","/**\r\n * 에러 기본 클래스\r\n */\r\nimport { ErrorCode, ExitCode } from './codes.js';\r\nimport { formatMessage } from './messages.js';\r\n\r\n/**\r\n * SDD 도구의 기본 에러 클래스\r\n */\r\nexport class SddError extends Error {\r\n readonly code: ErrorCode;\r\n readonly exitCode: ExitCode;\r\n\r\n constructor(\r\n code: ErrorCode,\r\n message?: string,\r\n exitCode: ExitCode = ExitCode.GENERAL_ERROR\r\n ) {\r\n super(message ?? formatMessage(code));\r\n this.name = 'SddError';\r\n this.code = code;\r\n this.exitCode = exitCode;\r\n Error.captureStackTrace?.(this, this.constructor);\r\n }\r\n\r\n /**\r\n * 사용자 친화적 메시지\r\n */\r\n toUserMessage(): string {\r\n return `[${this.code}] ${this.message}`;\r\n }\r\n}\r\n\r\n/**\r\n * 파일 시스템 에러\r\n */\r\nexport class FileSystemError extends SddError {\r\n readonly path: string;\r\n\r\n constructor(code: ErrorCode, path: string) {\r\n super(code, formatMessage(code, path), ExitCode.FILE_SYSTEM_ERROR);\r\n this.name = 'FileSystemError';\r\n this.path = path;\r\n }\r\n}\r\n\r\n/**\r\n * 스펙 검증 에러\r\n */\r\nexport class ValidationError extends SddError {\r\n readonly details: string;\r\n\r\n constructor(code: ErrorCode, details: string) {\r\n super(code, formatMessage(code, details), ExitCode.VALIDATION_FAILED);\r\n this.name = 'ValidationError';\r\n this.details = details;\r\n }\r\n}\r\n\r\n/**\r\n * Constitution 위반 에러\r\n */\r\nexport class ConstitutionError extends SddError {\r\n readonly principle: string;\r\n\r\n constructor(principle: string) {\r\n super(\r\n ErrorCode.CONSTITUTION_VIOLATION,\r\n formatMessage(ErrorCode.CONSTITUTION_VIOLATION, principle),\r\n ExitCode.CONSTITUTION_VIOLATION\r\n );\r\n this.name = 'ConstitutionError';\r\n this.principle = principle;\r\n }\r\n}\r\n\r\n/**\r\n * 사용자 취소 에러\r\n */\r\nexport class UserCancelledError extends SddError {\r\n constructor(message = '사용자가 작업을 취소했습니다') {\r\n super(ErrorCode.UNKNOWN, message, ExitCode.USER_CANCELLED);\r\n this.name = 'UserCancelledError';\r\n }\r\n}\r\n\r\n/**\r\n * 변경 워크플로우 에러\r\n */\r\nexport class ChangeError extends SddError {\r\n constructor(message: string) {\r\n super(ErrorCode.UNKNOWN, message, ExitCode.GENERAL_ERROR);\r\n this.name = 'ChangeError';\r\n }\r\n}\r\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/types/index.ts","../src/errors/codes.ts","../src/errors/messages.ts","../src/errors/base.ts"],"sourcesContent":["/**\n * 공통 타입 정의\n */\n\n// ============================================================\n// 스펙 관련 타입\n// ============================================================\n\n/**\n * 스펙 문서 구조\n */\nexport interface Spec {\n id: string;\n title: string;\n status: SpecStatus;\n requirements: Requirement[];\n scenarios: Scenario[];\n dependencies: string[];\n metadata: SpecMetadata;\n}\n\nexport type SpecStatus = 'draft' | 'approved' | 'implemented';\n\nexport interface SpecMetadata {\n created?: string;\n updated?: string;\n author?: string;\n}\n\n/**\n * 요구사항 (RFC 2119)\n */\nexport interface Requirement {\n id: string;\n level: RequirementLevel;\n description: string;\n}\n\nexport type RequirementLevel = 'SHALL' | 'MUST' | 'SHOULD' | 'MAY';\n\n/**\n * 시나리오 (GIVEN-WHEN-THEN)\n */\nexport interface Scenario {\n name: string;\n given: string[];\n when: string;\n then: string[];\n}\n\n// ============================================================\n// Constitution 관련 타입\n// ============================================================\n\n/**\n * Constitution 원칙\n */\nexport interface Principle {\n id: string;\n title: string;\n description: string;\n level: PrincipleLevel;\n}\n\nexport type PrincipleLevel = 'core' | 'technical' | 'forbidden';\n\nexport interface Constitution {\n projectName: string;\n principles: Principle[];\n technicalStack?: string[];\n constraints?: string[];\n}\n\n// ============================================================\n// 변경 워크플로우 관련 타입\n// ============================================================\n\n/**\n * 변경 제안\n */\nexport interface Proposal {\n id: string;\n title: string;\n rationale: string;\n affectedSpecs: string[];\n deltas: Delta[];\n status: ProposalStatus;\n createdAt: string;\n}\n\nexport type ProposalStatus = 'draft' | 'review' | 'approved' | 'applied' | 'archived';\n\n/**\n * 델타 (변경사항)\n */\nexport interface Delta {\n type: DeltaType;\n target: string;\n before?: string;\n after?: string;\n}\n\nexport type DeltaType = 'ADDED' | 'MODIFIED' | 'REMOVED';\n\n// ============================================================\n// 검증 관련 타입\n// ============================================================\n\n/**\n * 검증 결과\n */\nexport interface ValidationResult {\n valid: boolean;\n errors: SpecValidationError[];\n warnings: SpecValidationWarning[];\n}\n\nexport interface SpecValidationError {\n code: string;\n message: string;\n location?: Location;\n}\n\nexport interface SpecValidationWarning {\n code: string;\n message: string;\n location?: Location;\n}\n\nexport interface Location {\n file?: string;\n line?: number;\n column?: number;\n}\n\n// ============================================================\n// 분석 관련 타입\n// ============================================================\n\n/**\n * 분석 결과\n */\nexport interface AnalysisResult {\n scale: Scale;\n recommendation: WorkflowRecommendation;\n confidence: number;\n rationale: string;\n alternatives: string[];\n}\n\nexport type Scale = 'small' | 'medium' | 'large';\nexport type WorkflowRecommendation = 'direct' | 'change' | 'new';\n\n// ============================================================\n// 유틸리티 타입\n// ============================================================\n\n/**\n * Result 타입 (에러 처리용)\n */\nexport type Result<T, E = Error> =\n | { success: true; data: T }\n | { success: false; error: E };\n\n/**\n * 성공 결과 생성 헬퍼\n */\nexport function success<T>(data: T): Result<T, never> {\n return { success: true, data };\n}\n\n/**\n * 실패 결과 생성 헬퍼\n */\nexport function failure<E>(error: E): Result<never, E> {\n return { success: false, error };\n}\n","/**\n * 에러 코드 정의\n */\n\n/**\n * CLI 종료 코드\n */\nexport const ExitCode = {\n SUCCESS: 0,\n GENERAL_ERROR: 1,\n VALIDATION_FAILED: 2,\n CONSTITUTION_VIOLATION: 3,\n FILE_SYSTEM_ERROR: 4,\n USER_CANCELLED: 5,\n INIT_ERROR: 6,\n VALIDATION_ERROR: 7,\n} as const;\n\nexport type ExitCode = (typeof ExitCode)[keyof typeof ExitCode];\n\n/**\n * 에러 코드\n */\nexport const ErrorCode = {\n // 일반 에러 (E0xx)\n UNKNOWN: 'E001',\n INVALID_ARGUMENT: 'E002',\n NOT_INITIALIZED: 'E003',\n\n // 파일 시스템 에러 (E1xx)\n FILE_NOT_FOUND: 'E101',\n FILE_READ_ERROR: 'E102',\n FILE_WRITE_ERROR: 'E103',\n DIRECTORY_NOT_FOUND: 'E104',\n DIRECTORY_EXISTS: 'E105',\n\n // 스펙 검증 에러 (E2xx)\n SPEC_PARSE_ERROR: 'E201',\n SPEC_INVALID_FORMAT: 'E202',\n SPEC_MISSING_REQUIRED: 'E203',\n RFC2119_VIOLATION: 'E204',\n GWT_INVALID_FORMAT: 'E205',\n\n // Constitution 에러 (E3xx)\n CONSTITUTION_NOT_FOUND: 'E301',\n CONSTITUTION_PARSE_ERROR: 'E302',\n CONSTITUTION_VIOLATION: 'E303',\n CONSTITUTION_VERSION_MISMATCH: 'E304',\n\n // 변경 워크플로우 에러 (E4xx)\n PROPOSAL_NOT_FOUND: 'E401',\n PROPOSAL_INVALID: 'E402',\n DELTA_CONFLICT: 'E403',\n ARCHIVE_FAILED: 'E404',\n\n // 분석 에러 (E5xx)\n ANALYSIS_FAILED: 'E501',\n INSUFFICIENT_DATA: 'E502',\n} as const;\n\nexport type ErrorCode = (typeof ErrorCode)[keyof typeof ErrorCode];\n","/**\n * 에러 메시지 정의\n */\nimport { ErrorCode } from './codes.js';\n\n/**\n * 에러 코드별 메시지 템플릿\n */\nexport const ErrorMessages: Record<ErrorCode, string> = {\n // 일반 에러\n [ErrorCode.UNKNOWN]: '알 수 없는 오류가 발생했습니다',\n [ErrorCode.INVALID_ARGUMENT]: '잘못된 인자입니다: {0}',\n [ErrorCode.NOT_INITIALIZED]: 'SDD 프로젝트가 초기화되지 않았습니다. `sdd init`을 먼저 실행하세요',\n\n // 파일 시스템 에러\n [ErrorCode.FILE_NOT_FOUND]: '파일을 찾을 수 없습니다: {0}',\n [ErrorCode.FILE_READ_ERROR]: '파일 읽기 실패: {0}',\n [ErrorCode.FILE_WRITE_ERROR]: '파일 쓰기 실패: {0}',\n [ErrorCode.DIRECTORY_NOT_FOUND]: '디렉토리를 찾을 수 없습니다: {0}',\n [ErrorCode.DIRECTORY_EXISTS]: '디렉토리가 이미 존재합니다: {0}',\n\n // 스펙 검증 에러\n [ErrorCode.SPEC_PARSE_ERROR]: '스펙 파싱 실패: {0}',\n [ErrorCode.SPEC_INVALID_FORMAT]: '잘못된 스펙 형식: {0}',\n [ErrorCode.SPEC_MISSING_REQUIRED]: '필수 필드 누락: {0}',\n [ErrorCode.RFC2119_VIOLATION]: 'RFC 2119 형식 위반: {0}',\n [ErrorCode.GWT_INVALID_FORMAT]: 'GIVEN-WHEN-THEN 형식 위반: {0}',\n\n // Constitution 에러\n [ErrorCode.CONSTITUTION_NOT_FOUND]: 'constitution.md를 찾을 수 없습니다',\n [ErrorCode.CONSTITUTION_PARSE_ERROR]: 'Constitution 파싱 실패: {0}',\n [ErrorCode.CONSTITUTION_VIOLATION]: 'Constitution 원칙 위반: {0}',\n [ErrorCode.CONSTITUTION_VERSION_MISMATCH]: 'Constitution 버전 불일치: {0}',\n\n // 변경 워크플로우 에러\n [ErrorCode.PROPOSAL_NOT_FOUND]: '제안서를 찾을 수 없습니다: {0}',\n [ErrorCode.PROPOSAL_INVALID]: '잘못된 제안서 형식: {0}',\n [ErrorCode.DELTA_CONFLICT]: '델타 충돌: {0}',\n [ErrorCode.ARCHIVE_FAILED]: '아카이브 실패: {0}',\n\n // 분석 에러\n [ErrorCode.ANALYSIS_FAILED]: '분석 실패: {0}',\n [ErrorCode.INSUFFICIENT_DATA]: '분석에 필요한 데이터 부족: {0}',\n};\n\n/**\n * 메시지 템플릿에 인자를 적용\n */\nexport function formatMessage(code: ErrorCode, ...args: string[]): string {\n let message = ErrorMessages[code];\n args.forEach((arg, index) => {\n message = message.replace(`{${index}}`, arg);\n });\n return message;\n}\n","/**\n * 에러 기본 클래스\n */\nimport { ErrorCode, ExitCode } from './codes.js';\nimport { formatMessage } from './messages.js';\n\n/**\n * SDD 도구의 기본 에러 클래스\n */\nexport class SddError extends Error {\n readonly code: ErrorCode;\n readonly exitCode: ExitCode;\n\n constructor(\n code: ErrorCode,\n message?: string,\n exitCode: ExitCode = ExitCode.GENERAL_ERROR\n ) {\n super(message ?? formatMessage(code));\n this.name = 'SddError';\n this.code = code;\n this.exitCode = exitCode;\n Error.captureStackTrace?.(this, this.constructor);\n }\n\n /**\n * 사용자 친화적 메시지\n */\n toUserMessage(): string {\n return `[${this.code}] ${this.message}`;\n }\n}\n\n/**\n * 파일 시스템 에러\n */\nexport class FileSystemError extends SddError {\n readonly path: string;\n\n constructor(code: ErrorCode, path: string) {\n super(code, formatMessage(code, path), ExitCode.FILE_SYSTEM_ERROR);\n this.name = 'FileSystemError';\n this.path = path;\n }\n}\n\n/**\n * 스펙 검증 에러\n */\nexport class ValidationError extends SddError {\n readonly details: string;\n\n constructor(code: ErrorCode, details: string) {\n super(code, formatMessage(code, details), ExitCode.VALIDATION_FAILED);\n this.name = 'ValidationError';\n this.details = details;\n }\n}\n\n/**\n * Constitution 위반 에러\n */\nexport class ConstitutionError extends SddError {\n readonly principle: string;\n\n constructor(principle: string) {\n super(\n ErrorCode.CONSTITUTION_VIOLATION,\n formatMessage(ErrorCode.CONSTITUTION_VIOLATION, principle),\n ExitCode.CONSTITUTION_VIOLATION\n );\n this.name = 'ConstitutionError';\n this.principle = principle;\n }\n}\n\n/**\n * 사용자 취소 에러\n */\nexport class UserCancelledError extends SddError {\n constructor(message = '사용자가 작업을 취소했습니다') {\n super(ErrorCode.UNKNOWN, message, ExitCode.USER_CANCELLED);\n this.name = 'UserCancelledError';\n }\n}\n\n/**\n * 변경 워크플로우 에러\n */\nexport class ChangeError extends SddError {\n constructor(message: string) {\n super(ErrorCode.UNKNOWN, message, ExitCode.GENERAL_ERROR);\n this.name = 'ChangeError';\n }\n}\n"],"mappings":";AAuKO,SAAS,QAAW,MAA2B;AACpD,SAAO,EAAE,SAAS,MAAM,KAAK;AAC/B;AAKO,SAAS,QAAW,OAA4B;AACrD,SAAO,EAAE,SAAS,OAAO,MAAM;AACjC;;;ACzKO,IAAM,WAAW;AAAA,EACtB,SAAS;AAAA,EACT,eAAe;AAAA,EACf,mBAAmB;AAAA,EACnB,wBAAwB;AAAA,EACxB,mBAAmB;AAAA,EACnB,gBAAgB;AAAA,EAChB,YAAY;AAAA,EACZ,kBAAkB;AACpB;AAOO,IAAM,YAAY;AAAA;AAAA,EAEvB,SAAS;AAAA,EACT,kBAAkB;AAAA,EAClB,iBAAiB;AAAA;AAAA,EAGjB,gBAAgB;AAAA,EAChB,iBAAiB;AAAA,EACjB,kBAAkB;AAAA,EAClB,qBAAqB;AAAA,EACrB,kBAAkB;AAAA;AAAA,EAGlB,kBAAkB;AAAA,EAClB,qBAAqB;AAAA,EACrB,uBAAuB;AAAA,EACvB,mBAAmB;AAAA,EACnB,oBAAoB;AAAA;AAAA,EAGpB,wBAAwB;AAAA,EACxB,0BAA0B;AAAA,EAC1B,wBAAwB;AAAA,EACxB,+BAA+B;AAAA;AAAA,EAG/B,oBAAoB;AAAA,EACpB,kBAAkB;AAAA,EAClB,gBAAgB;AAAA,EAChB,gBAAgB;AAAA;AAAA,EAGhB,iBAAiB;AAAA,EACjB,mBAAmB;AACrB;;;AClDO,IAAM,gBAA2C;AAAA;AAAA,EAEtD,CAAC,UAAU,OAAO,GAAG;AAAA,EACrB,CAAC,UAAU,gBAAgB,GAAG;AAAA,EAC9B,CAAC,UAAU,eAAe,GAAG;AAAA;AAAA,EAG7B,CAAC,UAAU,cAAc,GAAG;AAAA,EAC5B,CAAC,UAAU,eAAe,GAAG;AAAA,EAC7B,CAAC,UAAU,gBAAgB,GAAG;AAAA,EAC9B,CAAC,UAAU,mBAAmB,GAAG;AAAA,EACjC,CAAC,UAAU,gBAAgB,GAAG;AAAA;AAAA,EAG9B,CAAC,UAAU,gBAAgB,GAAG;AAAA,EAC9B,CAAC,UAAU,mBAAmB,GAAG;AAAA,EACjC,CAAC,UAAU,qBAAqB,GAAG;AAAA,EACnC,CAAC,UAAU,iBAAiB,GAAG;AAAA,EAC/B,CAAC,UAAU,kBAAkB,GAAG;AAAA;AAAA,EAGhC,CAAC,UAAU,sBAAsB,GAAG;AAAA,EACpC,CAAC,UAAU,wBAAwB,GAAG;AAAA,EACtC,CAAC,UAAU,sBAAsB,GAAG;AAAA,EACpC,CAAC,UAAU,6BAA6B,GAAG;AAAA;AAAA,EAG3C,CAAC,UAAU,kBAAkB,GAAG;AAAA,EAChC,CAAC,UAAU,gBAAgB,GAAG;AAAA,EAC9B,CAAC,UAAU,cAAc,GAAG;AAAA,EAC5B,CAAC,UAAU,cAAc,GAAG;AAAA;AAAA,EAG5B,CAAC,UAAU,eAAe,GAAG;AAAA,EAC7B,CAAC,UAAU,iBAAiB,GAAG;AACjC;AAKO,SAAS,cAAc,SAAoB,MAAwB;AACxE,MAAI,UAAU,cAAc,IAAI;AAChC,OAAK,QAAQ,CAAC,KAAK,UAAU;AAC3B,cAAU,QAAQ,QAAQ,IAAI,KAAK,KAAK,GAAG;AAAA,EAC7C,CAAC;AACD,SAAO;AACT;;;AC7CO,IAAM,WAAN,cAAuB,MAAM;AAAA,EACzB;AAAA,EACA;AAAA,EAET,YACE,MACA,SACA,WAAqB,SAAS,eAC9B;AACA,UAAM,WAAW,cAAc,IAAI,CAAC;AACpC,SAAK,OAAO;AACZ,SAAK,OAAO;AACZ,SAAK,WAAW;AAChB,UAAM,oBAAoB,MAAM,KAAK,WAAW;AAAA,EAClD;AAAA;AAAA;AAAA;AAAA,EAKA,gBAAwB;AACtB,WAAO,IAAI,KAAK,IAAI,KAAK,KAAK,OAAO;AAAA,EACvC;AACF;AAKO,IAAM,kBAAN,cAA8B,SAAS;AAAA,EACnC;AAAA,EAET,YAAY,MAAiB,MAAc;AACzC,UAAM,MAAM,cAAc,MAAM,IAAI,GAAG,SAAS,iBAAiB;AACjE,SAAK,OAAO;AACZ,SAAK,OAAO;AAAA,EACd;AACF;AAKO,IAAM,kBAAN,cAA8B,SAAS;AAAA,EACnC;AAAA,EAET,YAAY,MAAiB,SAAiB;AAC5C,UAAM,MAAM,cAAc,MAAM,OAAO,GAAG,SAAS,iBAAiB;AACpE,SAAK,OAAO;AACZ,SAAK,UAAU;AAAA,EACjB;AACF;AAKO,IAAM,oBAAN,cAAgC,SAAS;AAAA,EACrC;AAAA,EAET,YAAY,WAAmB;AAC7B;AAAA,MACE,UAAU;AAAA,MACV,cAAc,UAAU,wBAAwB,SAAS;AAAA,MACzD,SAAS;AAAA,IACX;AACA,SAAK,OAAO;AACZ,SAAK,YAAY;AAAA,EACnB;AACF;AAKO,IAAM,qBAAN,cAAiC,SAAS;AAAA,EAC/C,YAAY,UAAU,oFAAmB;AACvC,UAAM,UAAU,SAAS,SAAS,SAAS,cAAc;AACzD,SAAK,OAAO;AAAA,EACd;AACF;AAKO,IAAM,cAAN,cAA0B,SAAS;AAAA,EACxC,YAAY,SAAiB;AAC3B,UAAM,UAAU,SAAS,SAAS,SAAS,aAAa;AACxD,SAAK,OAAO;AAAA,EACd;AACF;","names":[]}
|
package/package.json
CHANGED
|
@@ -1,81 +1,79 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "sdd-tool",
|
|
3
|
-
"version": "1.0
|
|
4
|
-
"description": "Unified Spec-Driven Development CLI - AI-first specification workflow",
|
|
5
|
-
"type": "module",
|
|
6
|
-
"bin": {
|
|
7
|
-
"sdd": "bin/sdd.js"
|
|
8
|
-
},
|
|
9
|
-
"main": "./dist/index.js",
|
|
10
|
-
"types": "./dist/index.d.ts",
|
|
11
|
-
"exports": {
|
|
12
|
-
".": {
|
|
13
|
-
"types": "./dist/index.d.ts",
|
|
14
|
-
"import": "./dist/index.js"
|
|
15
|
-
}
|
|
16
|
-
},
|
|
17
|
-
"
|
|
18
|
-
"
|
|
19
|
-
"
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
"
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
"
|
|
28
|
-
"
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
"
|
|
32
|
-
"
|
|
33
|
-
},
|
|
34
|
-
"
|
|
35
|
-
|
|
36
|
-
"
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
"
|
|
41
|
-
"
|
|
42
|
-
"
|
|
43
|
-
"
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
"
|
|
50
|
-
"
|
|
51
|
-
"
|
|
52
|
-
"
|
|
53
|
-
"
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
"
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
"
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
"
|
|
64
|
-
"
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
"
|
|
71
|
-
"
|
|
72
|
-
"
|
|
73
|
-
"
|
|
74
|
-
"
|
|
75
|
-
"
|
|
76
|
-
"
|
|
77
|
-
"
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
"license": "MIT"
|
|
81
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "sdd-tool",
|
|
3
|
+
"version": "1.1.0",
|
|
4
|
+
"description": "Unified Spec-Driven Development CLI - AI-first specification workflow",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"sdd": "bin/sdd.js"
|
|
8
|
+
},
|
|
9
|
+
"main": "./dist/index.js",
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"exports": {
|
|
12
|
+
".": {
|
|
13
|
+
"types": "./dist/index.d.ts",
|
|
14
|
+
"import": "./dist/index.js"
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
"repository": {
|
|
18
|
+
"type": "git",
|
|
19
|
+
"url": "git+https://github.com/JakeB-5/sdd-tool.git"
|
|
20
|
+
},
|
|
21
|
+
"homepage": "https://github.com/JakeB-5/sdd-tool#readme",
|
|
22
|
+
"bugs": {
|
|
23
|
+
"url": "https://github.com/JakeB-5/sdd-tool/issues"
|
|
24
|
+
},
|
|
25
|
+
"author": "JakeB-5",
|
|
26
|
+
"dependencies": {
|
|
27
|
+
"chalk": "^5.3.0",
|
|
28
|
+
"chokidar": "^5.0.0",
|
|
29
|
+
"commander": "^12.1.0",
|
|
30
|
+
"glob": "^11.0.0",
|
|
31
|
+
"gray-matter": "^4.0.3",
|
|
32
|
+
"zod": "^3.23.8"
|
|
33
|
+
},
|
|
34
|
+
"devDependencies": {
|
|
35
|
+
"@eslint/js": "^9.16.0",
|
|
36
|
+
"@types/node": "^20.17.10",
|
|
37
|
+
"@vitest/coverage-v8": "^2.1.8",
|
|
38
|
+
"eslint": "^9.16.0",
|
|
39
|
+
"tsup": "^8.3.5",
|
|
40
|
+
"typescript": "^5.7.2",
|
|
41
|
+
"typescript-eslint": "^8.18.0",
|
|
42
|
+
"vitepress": "^1.5.0",
|
|
43
|
+
"vitest": "^2.1.8"
|
|
44
|
+
},
|
|
45
|
+
"engines": {
|
|
46
|
+
"node": ">=20.0.0"
|
|
47
|
+
},
|
|
48
|
+
"files": [
|
|
49
|
+
"dist",
|
|
50
|
+
"bin",
|
|
51
|
+
"templates",
|
|
52
|
+
"README.md",
|
|
53
|
+
"LICENSE"
|
|
54
|
+
],
|
|
55
|
+
"keywords": [
|
|
56
|
+
"sdd",
|
|
57
|
+
"spec-driven-development",
|
|
58
|
+
"specification",
|
|
59
|
+
"cli",
|
|
60
|
+
"ai",
|
|
61
|
+
"workflow",
|
|
62
|
+
"rfc2119",
|
|
63
|
+
"given-when-then",
|
|
64
|
+
"bdd"
|
|
65
|
+
],
|
|
66
|
+
"license": "MIT",
|
|
67
|
+
"scripts": {
|
|
68
|
+
"build": "tsup",
|
|
69
|
+
"dev": "tsup --watch",
|
|
70
|
+
"test": "vitest",
|
|
71
|
+
"test:run": "vitest run",
|
|
72
|
+
"test:coverage": "vitest run --coverage",
|
|
73
|
+
"lint": "eslint src/",
|
|
74
|
+
"typecheck": "tsc --noEmit",
|
|
75
|
+
"docs:dev": "vitepress dev docs",
|
|
76
|
+
"docs:build": "vitepress build docs",
|
|
77
|
+
"docs:preview": "vitepress preview docs"
|
|
78
|
+
}
|
|
79
|
+
}
|
package/templates/agents.md
CHANGED
|
@@ -1,62 +1,62 @@
|
|
|
1
|
-
# AGENTS.md
|
|
2
|
-
|
|
3
|
-
> AI 에이전트 워크플로우 지침서
|
|
4
|
-
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
## 프로젝트 개요
|
|
8
|
-
|
|
9
|
-
**프로젝트**: {{PROJECT_NAME}}
|
|
10
|
-
**설명**: {{PROJECT_DESCRIPTION}}
|
|
11
|
-
|
|
12
|
-
---
|
|
13
|
-
|
|
14
|
-
## 디렉토리 구조
|
|
15
|
-
|
|
16
|
-
```
|
|
17
|
-
.sdd/
|
|
18
|
-
├── constitution.md # 프로젝트 헌법
|
|
19
|
-
├── specs/ # 스펙 문서
|
|
20
|
-
│ └── <feature>/
|
|
21
|
-
│ └── spec.md
|
|
22
|
-
├── changes/ # 변경 제안
|
|
23
|
-
│ └── <id>/
|
|
24
|
-
│ ├── proposal.md
|
|
25
|
-
│ └── delta.md
|
|
26
|
-
└── templates/ # 템플릿
|
|
27
|
-
```
|
|
28
|
-
|
|
29
|
-
---
|
|
30
|
-
|
|
31
|
-
## 워크플로우
|
|
32
|
-
|
|
33
|
-
### 신규 기능
|
|
34
|
-
|
|
35
|
-
1. `/sdd:new` - 스펙 초안 작성
|
|
36
|
-
2. `/sdd:plan` - 구현 계획 수립
|
|
37
|
-
3. `/sdd:tasks` - 작업 분해
|
|
38
|
-
4. 구현 및 테스트
|
|
39
|
-
5. 리뷰 및 머지
|
|
40
|
-
|
|
41
|
-
### 변경 제안
|
|
42
|
-
|
|
43
|
-
1. `/sdd:change` - 제안서 작성
|
|
44
|
-
2. `/sdd:impact` - 영향도 분석
|
|
45
|
-
3. 리뷰 및 승인
|
|
46
|
-
4. `/sdd:apply` - 변경 적용
|
|
47
|
-
5. `/sdd:archive` - 아카이브
|
|
48
|
-
|
|
49
|
-
---
|
|
50
|
-
|
|
51
|
-
## 컨벤션
|
|
52
|
-
|
|
53
|
-
- 모든 스펙은 RFC 2119 키워드 사용
|
|
54
|
-
- 모든 요구사항은 GIVEN-WHEN-THEN 시나리오 포함
|
|
55
|
-
- 변경 시 반드시 영향도 분석 수행
|
|
56
|
-
|
|
57
|
-
---
|
|
58
|
-
|
|
59
|
-
## 참조
|
|
60
|
-
|
|
61
|
-
- [Constitution](./constitution.md)
|
|
62
|
-
- [Specs](./specs/)
|
|
1
|
+
# AGENTS.md
|
|
2
|
+
|
|
3
|
+
> AI 에이전트 워크플로우 지침서
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 프로젝트 개요
|
|
8
|
+
|
|
9
|
+
**프로젝트**: {{PROJECT_NAME}}
|
|
10
|
+
**설명**: {{PROJECT_DESCRIPTION}}
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## 디렉토리 구조
|
|
15
|
+
|
|
16
|
+
```
|
|
17
|
+
.sdd/
|
|
18
|
+
├── constitution.md # 프로젝트 헌법
|
|
19
|
+
├── specs/ # 스펙 문서
|
|
20
|
+
│ └── <feature>/
|
|
21
|
+
│ └── spec.md
|
|
22
|
+
├── changes/ # 변경 제안
|
|
23
|
+
│ └── <id>/
|
|
24
|
+
│ ├── proposal.md
|
|
25
|
+
│ └── delta.md
|
|
26
|
+
└── templates/ # 템플릿
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## 워크플로우
|
|
32
|
+
|
|
33
|
+
### 신규 기능
|
|
34
|
+
|
|
35
|
+
1. `/sdd:new` - 스펙 초안 작성
|
|
36
|
+
2. `/sdd:plan` - 구현 계획 수립
|
|
37
|
+
3. `/sdd:tasks` - 작업 분해
|
|
38
|
+
4. 구현 및 테스트
|
|
39
|
+
5. 리뷰 및 머지
|
|
40
|
+
|
|
41
|
+
### 변경 제안
|
|
42
|
+
|
|
43
|
+
1. `/sdd:change` - 제안서 작성
|
|
44
|
+
2. `/sdd:impact` - 영향도 분석
|
|
45
|
+
3. 리뷰 및 승인
|
|
46
|
+
4. `/sdd:apply` - 변경 적용
|
|
47
|
+
5. `/sdd:archive` - 아카이브
|
|
48
|
+
|
|
49
|
+
---
|
|
50
|
+
|
|
51
|
+
## 컨벤션
|
|
52
|
+
|
|
53
|
+
- 모든 스펙은 RFC 2119 키워드 사용
|
|
54
|
+
- 모든 요구사항은 GIVEN-WHEN-THEN 시나리오 포함
|
|
55
|
+
- 변경 시 반드시 영향도 분석 수행
|
|
56
|
+
|
|
57
|
+
---
|
|
58
|
+
|
|
59
|
+
## 참조
|
|
60
|
+
|
|
61
|
+
- [Constitution](./constitution.md)
|
|
62
|
+
- [Specs](./specs/)
|
|
@@ -1,43 +1,43 @@
|
|
|
1
|
-
# Constitution: {{PROJECT_NAME}}
|
|
2
|
-
|
|
3
|
-
> 프로젝트의 근본 원칙과 제약 조건
|
|
4
|
-
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
## 핵심 원칙
|
|
8
|
-
|
|
9
|
-
### 1. 명세 우선 (Spec First)
|
|
10
|
-
|
|
11
|
-
코드보다 명세가 먼저다. 모든 구현은 승인된 명세에 기반한다.
|
|
12
|
-
|
|
13
|
-
### 2. 명확성 (Clarity)
|
|
14
|
-
|
|
15
|
-
모호함을 피하고 RFC 2119 키워드를 사용하여 요구사항을 명확히 한다.
|
|
16
|
-
|
|
17
|
-
### 3. 검증 가능성 (Verifiability)
|
|
18
|
-
|
|
19
|
-
모든 요구사항은 GIVEN-WHEN-THEN 시나리오로 검증 가능해야 한다.
|
|
20
|
-
|
|
21
|
-
---
|
|
22
|
-
|
|
23
|
-
## 기술 스택
|
|
24
|
-
|
|
25
|
-
- 언어: {{LANGUAGE}}
|
|
26
|
-
- 런타임: {{RUNTIME}}
|
|
27
|
-
- 테스트: {{TEST_FRAMEWORK}}
|
|
28
|
-
|
|
29
|
-
---
|
|
30
|
-
|
|
31
|
-
## 금지 사항
|
|
32
|
-
|
|
33
|
-
- 승인되지 않은 의존성 추가 금지
|
|
34
|
-
- 명세 없는 기능 구현 금지
|
|
35
|
-
- 테스트 없는 코드 머지 금지
|
|
36
|
-
|
|
37
|
-
---
|
|
38
|
-
|
|
39
|
-
## 변경 기록
|
|
40
|
-
|
|
41
|
-
| 날짜 | 변경 내용 | 작성자 |
|
|
42
|
-
|------|----------|--------|
|
|
43
|
-
| {{DATE}} | 초기 작성 | - |
|
|
1
|
+
# Constitution: {{PROJECT_NAME}}
|
|
2
|
+
|
|
3
|
+
> 프로젝트의 근본 원칙과 제약 조건
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 핵심 원칙
|
|
8
|
+
|
|
9
|
+
### 1. 명세 우선 (Spec First)
|
|
10
|
+
|
|
11
|
+
코드보다 명세가 먼저다. 모든 구현은 승인된 명세에 기반한다.
|
|
12
|
+
|
|
13
|
+
### 2. 명확성 (Clarity)
|
|
14
|
+
|
|
15
|
+
모호함을 피하고 RFC 2119 키워드를 사용하여 요구사항을 명확히 한다.
|
|
16
|
+
|
|
17
|
+
### 3. 검증 가능성 (Verifiability)
|
|
18
|
+
|
|
19
|
+
모든 요구사항은 GIVEN-WHEN-THEN 시나리오로 검증 가능해야 한다.
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## 기술 스택
|
|
24
|
+
|
|
25
|
+
- 언어: {{LANGUAGE}}
|
|
26
|
+
- 런타임: {{RUNTIME}}
|
|
27
|
+
- 테스트: {{TEST_FRAMEWORK}}
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## 금지 사항
|
|
32
|
+
|
|
33
|
+
- 승인되지 않은 의존성 추가 금지
|
|
34
|
+
- 명세 없는 기능 구현 금지
|
|
35
|
+
- 테스트 없는 코드 머지 금지
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
## 변경 기록
|
|
40
|
+
|
|
41
|
+
| 날짜 | 변경 내용 | 작성자 |
|
|
42
|
+
|------|----------|--------|
|
|
43
|
+
| {{DATE}} | 초기 작성 | - |
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# SDD Tool - .gitattributes 템플릿
|
|
2
|
+
# 이 파일의 내용을 프로젝트 .gitattributes에 추가하세요
|
|
3
|
+
|
|
4
|
+
# ===================
|
|
5
|
+
# 스펙 파일 설정
|
|
6
|
+
# ===================
|
|
7
|
+
|
|
8
|
+
# 스펙 파일은 항상 LF 사용 (크로스 플랫폼 일관성)
|
|
9
|
+
.sdd/**/*.md text eol=lf
|
|
10
|
+
.sdd/**/*.yml text eol=lf
|
|
11
|
+
.sdd/**/*.yaml text eol=lf
|
|
12
|
+
.sdd/**/*.json text eol=lf
|
|
13
|
+
|
|
14
|
+
# Constitution 파일
|
|
15
|
+
.sdd/constitution.md text eol=lf
|
|
16
|
+
|
|
17
|
+
# ===================
|
|
18
|
+
# 머지 전략
|
|
19
|
+
# ===================
|
|
20
|
+
|
|
21
|
+
# 스펙 파일 충돌 시 수동 해결 (union 머지 사용 안 함)
|
|
22
|
+
.sdd/specs/** merge=binary
|
|
23
|
+
|
|
24
|
+
# Constitution 충돌 시 수동 해결
|
|
25
|
+
.sdd/constitution.md merge=binary
|
|
26
|
+
|
|
27
|
+
# ===================
|
|
28
|
+
# Diff 설정
|
|
29
|
+
# ===================
|
|
30
|
+
|
|
31
|
+
# 마크다운 파일은 단어 단위 diff
|
|
32
|
+
.sdd/**/*.md diff=markdown
|
|
33
|
+
|
|
34
|
+
# ===================
|
|
35
|
+
# 언어 통계
|
|
36
|
+
# ===================
|
|
37
|
+
|
|
38
|
+
# 스펙 문서는 문서로 분류
|
|
39
|
+
.sdd/**/*.md linguist-documentation
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# SDD Tool - .gitignore 템플릿
|
|
2
|
+
# 이 파일의 내용을 프로젝트 .gitignore에 추가하세요
|
|
3
|
+
|
|
4
|
+
# ===================
|
|
5
|
+
# SDD 캐시 및 임시 파일
|
|
6
|
+
# ===================
|
|
7
|
+
|
|
8
|
+
# 인덱스 캐시 (재생성 가능)
|
|
9
|
+
.sdd/index.json
|
|
10
|
+
.sdd/.cache/
|
|
11
|
+
|
|
12
|
+
# 로컬 설정 (개인 환경)
|
|
13
|
+
.sdd/local.yml
|
|
14
|
+
|
|
15
|
+
# 생성된 리포트
|
|
16
|
+
.sdd/reports/
|
|
17
|
+
|
|
18
|
+
# 임시 파일
|
|
19
|
+
.sdd/**/*.tmp
|
|
20
|
+
.sdd/**/*.bak
|
|
21
|
+
|
|
22
|
+
# ===================
|
|
23
|
+
# 로컬 작업 파일
|
|
24
|
+
# ===================
|
|
25
|
+
|
|
26
|
+
# 로컬 태스크 추적
|
|
27
|
+
.tasks/
|
|
28
|
+
|
|
29
|
+
# ===================
|
|
30
|
+
# IDE/에디터
|
|
31
|
+
# ===================
|
|
32
|
+
|
|
33
|
+
.vscode/
|
|
34
|
+
.idea/
|
|
35
|
+
*.swp
|
|
36
|
+
*.swo
|
|
37
|
+
*~
|
|
38
|
+
|
|
39
|
+
# ===================
|
|
40
|
+
# OS 파일
|
|
41
|
+
# ===================
|
|
42
|
+
|
|
43
|
+
.DS_Store
|
|
44
|
+
Thumbs.db
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# <type>(<scope>): <subject>
|
|
2
|
+
# |<---- 50자 이내로 작성하세요 ---->|
|
|
3
|
+
#
|
|
4
|
+
# 스펙 타입: spec, spec-update, spec-status, plan, tasks, constitution, sdd-config
|
|
5
|
+
# 일반 타입: feat, fix, docs, style, refactor, test, chore
|
|
6
|
+
#
|
|
7
|
+
# 스코프 예시:
|
|
8
|
+
# spec(auth): ... - 도메인 전체
|
|
9
|
+
# spec(auth/user-login): ... - 특정 스펙
|
|
10
|
+
# spec(auth,billing): ... - 다중 도메인
|
|
11
|
+
# constitution: ... - 스코프 없음
|
|
12
|
+
|
|
13
|
+
# 본문 (선택사항, 72자 줄바꿈)
|
|
14
|
+
# |<---- 72자 이내로 작성하세요 ---->|
|
|
15
|
+
|
|
16
|
+
# Footer (선택사항)
|
|
17
|
+
# Refs: #이슈번호
|
|
18
|
+
# Breaking-Spec: 영향받는-스펙
|
|
19
|
+
# Depends-On: 의존-스펙
|
|
20
|
+
# Reviewed-By: @리뷰어
|