ai-ops-compiler 0.1.2 → 0.1.3

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/dist/index.d.ts CHANGED
@@ -229,7 +229,7 @@ declare const TOOL_OUTPUT_MAP: {
229
229
  readonly mode: "multi-file";
230
230
  readonly rulesDir: ".claude/rules";
231
231
  readonly fileExtension: ".md";
232
- readonly contextStrategy: "path-scoped";
232
+ readonly contextStrategy: "hybrid";
233
233
  };
234
234
  readonly codex: {
235
235
  readonly mode: "multi-file";
@@ -262,11 +262,11 @@ type WorkspaceMapping = {
262
262
  path: string;
263
263
  ruleIds: readonly string[];
264
264
  };
265
- declare const renderClaudeCodeRule: (rule: Rule, scopedGlobs?: readonly string[]) => string;
265
+ declare const renderClaudeCodeRule: (rule: Rule) => string;
266
266
  type ClaudeCodeRenderResult = {
267
267
  tool: 'claude-code';
268
268
  files: {
269
- fileName: string;
269
+ relativePath: string;
270
270
  content: string;
271
271
  }[];
272
272
  };
package/dist/index.js CHANGED
@@ -86,6 +86,9 @@ var loadPresets = (presetsPath) => {
86
86
  return parseRawPresets(data);
87
87
  };
88
88
 
89
+ // src/renderer.ts
90
+ import { join } from "path";
91
+
89
92
  // src/tool-output.ts
90
93
  var GLOBAL_CATEGORIES = ["persona", "communication", "philosophy", "convention", "standard"];
91
94
  var CLAUDE_CODE_PATH_GLOBS = {
@@ -113,8 +116,8 @@ var TOOL_OUTPUT_MAP = {
113
116
  mode: "multi-file",
114
117
  rulesDir: ".claude/rules",
115
118
  fileExtension: ".md",
116
- contextStrategy: "path-scoped"
117
- // paths: frontmatter
119
+ // single: path-scoped (paths: frontmatter) / monorepo: hierarchical ({workspace}/CLAUDE.md)
120
+ contextStrategy: "hybrid"
118
121
  },
119
122
  codex: {
120
123
  mode: "multi-file",
@@ -192,15 +195,8 @@ paths:
192
195
  ${lines}
193
196
  ---`;
194
197
  };
195
- var buildScopedGlobs = (rule, workspaceMappings) => {
196
- const baseGlobs = CLAUDE_CODE_PATH_GLOBS[rule.id];
197
- if (!baseGlobs) return void 0;
198
- const relevant = workspaceMappings.filter((ws) => ws.ruleIds.includes(rule.id));
199
- if (relevant.length === 0) return baseGlobs;
200
- return relevant.flatMap((ws) => baseGlobs.map((g) => `${ws.path}/${g}`));
201
- };
202
- var renderClaudeCodeRule = (rule, scopedGlobs) => {
203
- const globs = scopedGlobs ?? CLAUDE_CODE_PATH_GLOBS[rule.id];
198
+ var renderClaudeCodeRule = (rule) => {
199
+ const globs = CLAUDE_CODE_PATH_GLOBS[rule.id];
204
200
  if (!isGlobalRule(rule) && globs !== void 0) {
205
201
  return `${renderFrontmatter(globs)}
206
202
 
@@ -209,19 +205,34 @@ ${renderRuleToMarkdown(rule)}`;
209
205
  return renderRuleToMarkdown(rule);
210
206
  };
211
207
  var renderForTool = (toolId, rules, workspaceMappings) => {
212
- const { global, domain } = partitionRules(rules);
213
208
  const config = TOOL_OUTPUT_MAP[toolId];
214
209
  if (toolId === "claude-code") {
215
- const { fileExtension } = config;
216
- const files = rules.map((rule) => {
217
- const scopedGlobs = workspaceMappings ? buildScopedGlobs(rule, workspaceMappings) : void 0;
218
- return {
219
- fileName: `${rule.id}${fileExtension}`,
220
- content: renderClaudeCodeRule(rule, scopedGlobs)
221
- };
222
- });
223
- return { tool: "claude-code", files };
210
+ const { rulesDir, fileExtension } = config;
211
+ if (!workspaceMappings || workspaceMappings.length === 0) {
212
+ const files = rules.map((rule) => ({
213
+ relativePath: join(rulesDir, `${rule.id}${fileExtension}`),
214
+ content: renderClaudeCodeRule(rule)
215
+ }));
216
+ return { tool: "claude-code", files };
217
+ }
218
+ const { global: global2, domain: domain2 } = partitionRules(rules);
219
+ const globalFiles = global2.map((rule) => ({
220
+ relativePath: join(rulesDir, `${rule.id}${fileExtension}`),
221
+ content: renderRuleToMarkdown(rule)
222
+ // global은 frontmatter 불필요
223
+ }));
224
+ const workspaceFiles = [];
225
+ for (const ws of workspaceMappings) {
226
+ const wsRules = domain2.filter((r) => ws.ruleIds.includes(r.id));
227
+ if (wsRules.length === 0) continue;
228
+ workspaceFiles.push({
229
+ relativePath: join(ws.path, "CLAUDE.md"),
230
+ content: renderRulesToMarkdown(wsRules)
231
+ });
232
+ }
233
+ return { tool: "claude-code", files: [...globalFiles, ...workspaceFiles] };
224
234
  }
235
+ const { global, domain } = partitionRules(rules);
225
236
  const rootContent = renderRulesToMarkdown(global);
226
237
  const domainContent = renderRulesToMarkdown(domain);
227
238
  if (toolId === "codex") {
@@ -278,11 +289,11 @@ var stripManagedHeader = (content) => {
278
289
 
279
290
  // src/manifest-io.ts
280
291
  import { mkdirSync, readFileSync as readFileSync3, writeFileSync } from "fs";
281
- import { dirname, join } from "path";
292
+ import { dirname, join as join2 } from "path";
282
293
  var MANIFEST_FILENAME = ".ai-ops-manifest.json";
283
294
  var parseManifest = (json) => ManifestSchema.parse(JSON.parse(json));
284
295
  var serializeManifest = (manifest) => JSON.stringify(manifest, null, 2) + "\n";
285
- var resolveManifestPath = (basePath) => join(basePath, MANIFEST_FILENAME);
296
+ var resolveManifestPath = (basePath) => join2(basePath, MANIFEST_FILENAME);
286
297
  var readManifest = (manifestPath) => {
287
298
  let raw;
288
299
  try {
@@ -310,13 +321,12 @@ var computeDiff = (params) => {
310
321
  };
311
322
 
312
323
  // src/install-plan.ts
313
- import { join as join2 } from "path";
324
+ import { join as join3 } from "path";
314
325
  var buildInstallPlan = (params) => {
315
326
  const { toolId, renderResult, meta } = params;
316
327
  if (toolId === "claude-code" && renderResult.tool === "claude-code") {
317
- const { rulesDir } = TOOL_OUTPUT_MAP["claude-code"];
318
- return renderResult.files.map(({ fileName, content }) => ({
319
- relativePath: join2(rulesDir, fileName),
328
+ return renderResult.files.map(({ relativePath, content }) => ({
329
+ relativePath,
320
330
  content: wrapWithHeader(content, meta)
321
331
  }));
322
332
  }
@@ -325,13 +335,13 @@ var buildInstallPlan = (params) => {
325
335
  const actions = [];
326
336
  if (renderResult.rootContent) {
327
337
  actions.push({
328
- relativePath: join2(config.dir, config.rootFileName),
338
+ relativePath: join3(config.dir, config.rootFileName),
329
339
  content: wrapWithHeader(renderResult.rootContent, meta)
330
340
  });
331
341
  }
332
342
  if (renderResult.domainContent) {
333
343
  actions.push({
334
- relativePath: join2(config.dir, config.domainFileName),
344
+ relativePath: join3(config.dir, config.domainFileName),
335
345
  content: wrapWithHeader(renderResult.domainContent, meta)
336
346
  });
337
347
  }
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/schemas/rule.schema.ts","../src/schemas/preset.schema.ts","../src/schemas/manifest.schema.ts","../src/loader.ts","../src/tool-output.ts","../src/renderer.ts","../src/source-hash.ts","../src/managed-header.ts","../src/manifest-io.ts","../src/diff.ts","../src/install-plan.ts","../src/paths.ts"],"sourcesContent":["/**\n * Rule = SSOT의 최소 지식 단위. 하나의 코딩 컨벤션/아키텍처 규칙을 YAML로 구조화한 것.\n */\nimport { z } from 'zod';\n\nexport const DecisionTableEntrySchema = z\n .object({\n when: z.string().min(1),\n then: z.string().min(1),\n /** 조건부 규칙에서 회피해야 할 패턴 */\n avoid: z.string().min(1).optional(),\n })\n .strict();\n\nexport const RuleContentSchema = z\n .object({\n /** Anti-pattern 규칙 ('하지 마라'). guidelines보다 항상 상단 렌더링 */\n constraints: z.array(z.string().min(1)),\n /** Positive 규칙 ('해라') */\n guidelines: z.array(z.string().min(1)),\n /** 조건부 규칙. when→then→avoid 구조 */\n decision_table: z.array(DecisionTableEntrySchema).optional(),\n })\n .strict();\n\nexport const RuleSchema = z\n .object({\n id: z.string().regex(/^[a-z0-9]+(-[a-z0-9]+)*$/, 'id must be kebab-case'),\n category: z.string().min(1),\n tags: z.array(z.string().min(1)),\n /** 0-100. 높을수록 생성 파일 상단 배치 (U-shaped attention 최적화) */\n priority: z.number().int().min(0).max(100),\n content: RuleContentSchema,\n })\n .strict();\n\nexport type DecisionTableEntry = z.infer<typeof DecisionTableEntrySchema>;\nexport type RuleContent = z.infer<typeof RuleContentSchema>;\nexport type Rule = z.infer<typeof RuleSchema>;\n","import { z } from 'zod';\n\nexport const PresetSchema = z\n .object({\n id: z\n .string()\n .regex(/^[a-z][a-z0-9-]*$/)\n .min(1),\n description: z.string().min(1),\n rules: z.array(z.string().min(1)).min(1),\n })\n .strict();\n\nexport type Preset = z.infer<typeof PresetSchema>;\n","/**\n * Manifest = 설치 추적 메타데이터. CLI가 이전 설치 상태를 기억하기 위한 JSON.\n */\nimport { z } from 'zod';\n\nexport const SCOPES = {\n PROJECT: 'project',\n GLOBAL: 'global',\n} as const;\n\n/** 모노레포 워크스페이스별 preset + rules 추적 */\nconst WorkspaceEntrySchema = z\n .object({\n preset: z.string().min(1),\n rules: z.array(z.string().min(1)),\n })\n .strict();\n\nexport type WorkspaceEntry = z.infer<typeof WorkspaceEntrySchema>;\n\nexport const ManifestSchema = z\n .object({\n tools: z.array(z.string().min(1)).min(1),\n scope: z.enum(['project', 'global']),\n /** 비모노레포 단일 preset */\n preset: z.string().min(1).optional(),\n /** 모노레포: workspace path → { preset, rules } */\n workspaces: z.record(z.string(), WorkspaceEntrySchema).optional(),\n installed_rules: z.array(z.string().min(1)),\n /** SSOT 데이터 파일들의 deterministic SHA-256 해시 (6자리 hex). diff/update 판단 기준 */\n sourceHash: z.string().regex(/^[a-f0-9]{6}$/, 'sourceHash must be 6 lowercase hex chars'),\n generatedAt: z.string().datetime({ offset: true }),\n })\n .strict();\n\nexport type Manifest = z.infer<typeof ManifestSchema>;\n","import { readFileSync, readdirSync } from 'node:fs';\nimport { resolve } from 'node:path';\nimport { parse } from 'yaml';\nimport { RuleSchema, PresetSchema } from './schemas/index.js';\nimport type { Rule, Preset } from './schemas/index.js';\n\n// priority 내림차순 정렬 (높을수록 상단 → U-shaped attention)\nexport const sortRulesByPriority = (rules: readonly Rule[]): Rule[] =>\n [...rules].sort((a, b) => b.priority - a.priority);\n\n// presets.yaml의 Record<id, {description, rules}> → Preset[] 변환\nexport const parseRawPresets = (raw: Record<string, { description: string; rules: string[] }>): Preset[] =>\n Object.entries(raw).map(([id, value]) => PresetSchema.parse({ id, ...value }));\n\n// TUI 세부조정: 사용자가 해제한 rule ID 목록을 제외 (순서 유지)\nexport const excludeRules = (rules: readonly Rule[], excludeIds: readonly string[]): Rule[] => {\n const excludeSet = new Set(excludeIds);\n return rules.filter((r) => !excludeSet.has(r.id));\n};\n\n// preset.rules ID 목록으로 allRules에서 필터링 + priority 정렬, 누락 시 throw\nexport const resolvePresetRules = (preset: Preset, allRules: readonly Rule[]): Rule[] => {\n const resolved = preset.rules.map((ruleId) => {\n const found = allRules.find((r) => r.id === ruleId);\n if (!found) throw new Error(`Rule not found: ${ruleId}`);\n return found;\n });\n return sortRulesByPriority(resolved);\n};\n\nexport const loadRuleFile = (filePath: string): Rule => {\n const raw = readFileSync(filePath, 'utf-8');\n return RuleSchema.parse(parse(raw));\n};\n\n// readdirSync + .yaml 필터 + sort\nexport const loadAllRules = (rulesDir: string): Rule[] => {\n const files = readdirSync(rulesDir)\n .filter((f) => f.endsWith('.yaml'))\n .sort();\n return files.map((f) => loadRuleFile(resolve(rulesDir, f)));\n};\n\nexport const loadPresets = (presetsPath: string): Preset[] => {\n const raw = readFileSync(presetsPath, 'utf-8');\n const data = parse(raw) as Record<string, { description: string; rules: string[] }>;\n return parseRawPresets(data);\n};\n","// Global 성격의 category (항상 로딩, frontmatter 없음)\nexport const GLOBAL_CATEGORIES = ['persona', 'communication', 'philosophy', 'convention', 'standard'] as const;\n\n// Claude Code paths: frontmatter용 Rule ID → glob 매핑\n// src/ 없이 루트를 src처럼 쓰는 React/Next.js 프로젝트 고려\n// 매핑에 없는 domain 룰 → frontmatter 없이 항상 로딩 (안전 fallback)\nexport const CLAUDE_CODE_PATH_GLOBS: Readonly<Record<string, readonly string[]>> = {\n typescript: ['**/*.ts', '**/*.tsx'],\n 'react-typescript': ['**/*.tsx', '**/*.jsx'],\n nextjs: ['**/app/**', 'next.config.*', '**/middleware.ts'],\n nestjs: ['**/*.module.ts', '**/*.controller.ts', '**/*.service.ts'],\n 'nestjs-graphql': ['**/*.resolver.ts'],\n graphql: ['**/*.graphql', '**/*.gql'],\n 'prisma-postgresql': ['prisma/**', '**/*.prisma'],\n 'shadcn-ui': ['**/components/ui/**'],\n flutter: ['lib/**/*.dart'],\n python: ['**/*.py'],\n fastapi: ['**/routers/**', '**/main.py'],\n sqlalchemy: ['**/models/**/*.py', 'alembic/**'],\n 'data-pipeline-python': ['**/pipelines/**', '**/etl/**'],\n 'ai-llm-python': ['**/agents/**', '**/chains/**'],\n 'libs-frontend-web': ['**/*.tsx', '**/*.ts'],\n 'libs-frontend-app': ['lib/**/*.dart'],\n 'libs-backend-ts': ['**/*.ts'],\n 'libs-backend-python': ['**/*.py'],\n};\n\nexport const TOOL_OUTPUT_MAP = {\n 'claude-code': {\n mode: 'multi-file' as const,\n rulesDir: '.claude/rules',\n fileExtension: '.md',\n contextStrategy: 'path-scoped' as const, // paths: frontmatter\n },\n codex: {\n mode: 'multi-file' as const,\n dir: '.codex',\n rootFileName: 'AGENTS.md', // global 룰\n domainFileName: 'AGENTS.override.md', // domain 룰 (하위 폴더)\n contextStrategy: 'hierarchical' as const, // 루트 + 하위 폴더 JIT\n },\n gemini: {\n mode: 'multi-file' as const,\n dir: '.gemini',\n rootFileName: 'GEMINI.md', // global 룰\n domainFileName: 'GEMINI.md', // domain 룰 (하위 폴더)\n contextStrategy: 'hierarchical' as const, // 루트 + 하위 폴더 JIT\n },\n} as const;\n\nexport type ToolId = keyof typeof TOOL_OUTPUT_MAP;\n","import type { Rule, DecisionTableEntry } from './schemas/index.js';\nimport { GLOBAL_CATEGORIES, CLAUDE_CODE_PATH_GLOBS, TOOL_OUTPUT_MAP } from './tool-output.js';\nimport type { ToolId } from './tool-output.js';\n\n// \"react-typescript\" → \"React Typescript\"\nexport const ruleIdToTitle = (id: string): string =>\n id\n .split('-')\n .map((word) => word.charAt(0).toUpperCase() + word.slice(1))\n .join(' ');\n\n// DecisionTableEntry[] → Markdown 테이블 (pipe 문자 &#124; escape)\nexport const renderDecisionTable = (entries: readonly DecisionTableEntry[]): string => {\n const escape = (s: string) => s.replace(/\\|/g, '&#124;');\n const hasAvoid = entries.some((e) => e.avoid !== undefined);\n\n const header = hasAvoid ? '| When | Then | Avoid |\\n|------|------|-------|' : '| When | Then |\\n|------|------|';\n\n const rows = entries.map((e) => {\n const when = escape(e.when);\n const then = escape(e.then);\n if (hasAvoid) {\n const avoid = e.avoid ? escape(e.avoid) : '';\n return `| ${when} | ${then} | ${avoid} |`;\n }\n return `| ${when} | ${then} |`;\n });\n\n return [header, ...rows].join('\\n');\n};\n\n// 단일 Rule → Markdown (빈 섹션 생략)\nexport const renderRuleToMarkdown = (rule: Rule): string => {\n const sections: string[] = [`# ${ruleIdToTitle(rule.id)}`];\n\n if (rule.content.constraints.length > 0) {\n sections.push('## Constraints');\n sections.push(rule.content.constraints.map((c) => `- ${c}`).join('\\n'));\n }\n\n if (rule.content.guidelines.length > 0) {\n sections.push('## Guidelines');\n sections.push(rule.content.guidelines.map((g) => `- ${g}`).join('\\n'));\n }\n\n if (rule.content.decision_table && rule.content.decision_table.length > 0) {\n sections.push('## Decision Table');\n sections.push(renderDecisionTable(rule.content.decision_table));\n }\n\n return sections.join('\\n\\n');\n};\n\n// Rule[] → 단일 Markdown (--- separator, single-file 모드용)\nexport const renderRulesToMarkdown = (rules: readonly Rule[]): string =>\n rules.map(renderRuleToMarkdown).join('\\n\\n---\\n\\n');\n\n// Rule이 global 카테고리에 속하는지 판별\nexport const isGlobalRule = (rule: Rule): boolean => (GLOBAL_CATEGORIES as readonly string[]).includes(rule.category);\n\n// Rule[] → { global, domain } 분리\nexport const partitionRules = (rules: readonly Rule[]): { global: Rule[]; domain: Rule[] } => {\n const global: Rule[] = [];\n const domain: Rule[] = [];\n for (const rule of rules) {\n if (isGlobalRule(rule)) {\n global.push(rule);\n } else {\n domain.push(rule);\n }\n }\n return { global, domain };\n};\n\n// glob 배열 → YAML frontmatter 블록\nexport const renderFrontmatter = (paths: readonly string[]): string => {\n const lines = paths.map((p) => ` - \"${p}\"`).join('\\n');\n return `---\\npaths:\\n${lines}\\n---`;\n};\n\n// 모노레포에서 rule이 포함된 워크스페이스별 scoped glob 생성\n// e.g. typescript rule + ['backend-ts', 'web'] → ['backend-ts/**/*.ts', 'web/**/*.ts', ...]\nexport type WorkspaceMapping = {\n path: string;\n ruleIds: readonly string[];\n};\n\nconst buildScopedGlobs = (rule: Rule, workspaceMappings: readonly WorkspaceMapping[]): readonly string[] | undefined => {\n const baseGlobs = CLAUDE_CODE_PATH_GLOBS[rule.id];\n if (!baseGlobs) return undefined;\n\n const relevant = workspaceMappings.filter((ws) => ws.ruleIds.includes(rule.id));\n if (relevant.length === 0) return baseGlobs;\n\n return relevant.flatMap((ws) => baseGlobs.map((g) => `${ws.path}/${g}`));\n};\n\n// 단일 Rule → Claude Code용 Markdown\n// domain 룰이면서 glob 매핑이 있으면 paths: frontmatter 추가\n// global 룰 또는 매핑 없는 domain 룰 → frontmatter 없음 (안전 fallback)\nexport const renderClaudeCodeRule = (rule: Rule, scopedGlobs?: readonly string[]): string => {\n const globs = scopedGlobs ?? CLAUDE_CODE_PATH_GLOBS[rule.id];\n if (!isGlobalRule(rule) && globs !== undefined) {\n return `${renderFrontmatter(globs)}\\n\\n${renderRuleToMarkdown(rule)}`;\n }\n return renderRuleToMarkdown(rule);\n};\n\n// 도구별 렌더링 결과 타입 (tagged union)\nexport type ClaudeCodeRenderResult = {\n tool: 'claude-code';\n files: { fileName: string; content: string }[];\n};\n\nexport type CodexRenderResult = {\n tool: 'codex';\n rootContent: string;\n domainContent: string;\n};\n\nexport type GeminiRenderResult = {\n tool: 'gemini';\n rootContent: string;\n domainContent: string;\n};\n\nexport type ToolRenderResult = ClaudeCodeRenderResult | CodexRenderResult | GeminiRenderResult;\n\n// CLI 진입점: toolId + rules → 도구별 렌더링 결과\n// workspaceMappings 전달 시 claude-code frontmatter에 workspace-prefixed glob 생성\nexport const renderForTool = (\n toolId: ToolId,\n rules: readonly Rule[],\n workspaceMappings?: readonly WorkspaceMapping[],\n): ToolRenderResult => {\n const { global, domain } = partitionRules(rules);\n const config = TOOL_OUTPUT_MAP[toolId];\n\n if (toolId === 'claude-code') {\n const { fileExtension } = config as (typeof TOOL_OUTPUT_MAP)['claude-code'];\n const files = rules.map((rule) => {\n const scopedGlobs = workspaceMappings ? buildScopedGlobs(rule, workspaceMappings) : undefined;\n return {\n fileName: `${rule.id}${fileExtension}`,\n content: renderClaudeCodeRule(rule, scopedGlobs),\n };\n });\n return { tool: 'claude-code', files };\n }\n\n const rootContent = renderRulesToMarkdown(global);\n const domainContent = renderRulesToMarkdown(domain);\n\n if (toolId === 'codex') {\n return { tool: 'codex', rootContent, domainContent };\n }\n\n // gemini\n return { tool: 'gemini', rootContent, domainContent };\n};\n","import { createHash } from 'node:crypto';\nimport { readFileSync, readdirSync } from 'node:fs';\nimport { resolve } from 'node:path';\nimport { ManifestSchema } from './schemas/index.js';\nimport type { Manifest } from './schemas/index.js';\n\n// 문자열 배열 → SHA-256 → 6-hex (caller가 정렬 책임)\nexport const computeHash = (contents: readonly string[]): string =>\n createHash('sha256').update(contents.join('')).digest('hex').slice(0, 6);\n\n// rulesDir 내 YAML 파일들을 alphabetical 정렬 후 해싱\nexport const computeSourceHash = (rulesDir: string): string => {\n const files = readdirSync(rulesDir)\n .filter((f) => f.endsWith('.yaml'))\n .sort();\n const contents = files.map((f) => readFileSync(resolve(rulesDir, f), 'utf-8'));\n return computeHash(contents);\n};\n\n// Manifest Builder (Pure, 단 generatedAt에 현재 시각 사용)\nexport const buildManifest = (params: {\n tools: readonly string[];\n scope: 'project' | 'global';\n preset?: string;\n workspaces?: Record<string, { preset: string; rules: string[] }>;\n installedRules: readonly string[];\n sourceHash: string;\n}): Manifest =>\n ManifestSchema.parse({\n tools: [...params.tools],\n scope: params.scope,\n preset: params.preset,\n workspaces: params.workspaces,\n installed_rules: [...params.installedRules],\n sourceHash: params.sourceHash,\n generatedAt: new Date().toISOString(),\n });\n","const MANAGED_MARKER = '<!-- managed by ai-ops -->';\nconst META_PATTERN = /^<!-- sourceHash: ([a-f0-9]{6}) \\| generatedAt: (.+) -->$/;\n\nexport const wrapWithHeader = (content: string, meta: { sourceHash: string; generatedAt: string }): string => {\n const metaLine = `<!-- sourceHash: ${meta.sourceHash} | generatedAt: ${meta.generatedAt} -->`;\n return `${MANAGED_MARKER}\\n${metaLine}\\n\\n${content}`;\n};\n\nexport const isManagedFile = (content: string): boolean => content.startsWith(MANAGED_MARKER);\n\nexport const parseManagedHeader = (content: string): { sourceHash: string; generatedAt: string } | null => {\n if (!isManagedFile(content)) return null;\n\n const lines = content.split('\\n');\n const metaLine = lines[1] ?? '';\n const match = META_PATTERN.exec(metaLine);\n if (!match) return null;\n\n return { sourceHash: match[1], generatedAt: match[2] };\n};\n\nexport const stripManagedHeader = (content: string): string => {\n if (!isManagedFile(content)) return content;\n\n const lines = content.split('\\n');\n // marker line + meta line + blank line = 3 lines\n const stripped = lines.slice(3).join('\\n');\n return stripped;\n};\n","import { mkdirSync, readFileSync, writeFileSync } from 'node:fs';\nimport { dirname, join } from 'node:path';\nimport { ManifestSchema } from './schemas/index.js';\nimport type { Manifest } from './schemas/index.js';\n\nexport const MANIFEST_FILENAME = '.ai-ops-manifest.json';\n\n// Pure\nexport const parseManifest = (json: string): Manifest => ManifestSchema.parse(JSON.parse(json));\n\nexport const serializeManifest = (manifest: Manifest): string => JSON.stringify(manifest, null, 2) + '\\n';\n\n// I/O\nexport const resolveManifestPath = (basePath: string): string => join(basePath, MANIFEST_FILENAME);\n\nexport const readManifest = (manifestPath: string): Manifest | null => {\n let raw: string;\n try {\n raw = readFileSync(manifestPath, 'utf-8');\n } catch {\n return null;\n }\n return parseManifest(raw);\n};\n\nexport const writeManifest = (manifestPath: string, manifest: Manifest): void => {\n mkdirSync(dirname(manifestPath), { recursive: true });\n writeFileSync(manifestPath, serializeManifest(manifest), 'utf-8');\n};\n","import type { Manifest } from './schemas/index.js';\n\nexport type DiffResult = {\n status: 'up-to-date' | 'changed';\n added: readonly string[];\n removed: readonly string[];\n sourceChanged: boolean;\n};\n\nexport const computeDiff = (params: {\n previous: Manifest;\n currentRules: readonly string[];\n currentSourceHash: string;\n}): DiffResult => {\n const { previous, currentRules, currentSourceHash } = params;\n\n const previousSet = new Set(previous.installed_rules);\n const currentSet = new Set(currentRules);\n\n const added = currentRules.filter((id) => !previousSet.has(id));\n const removed = previous.installed_rules.filter((id) => !currentSet.has(id));\n const sourceChanged = previous.sourceHash !== currentSourceHash;\n\n const status = added.length > 0 || removed.length > 0 || sourceChanged ? 'changed' : 'up-to-date';\n\n return { status, added, removed, sourceChanged };\n};\n","import { join } from 'node:path';\nimport { wrapWithHeader } from './managed-header.js';\nimport { TOOL_OUTPUT_MAP } from './tool-output.js';\nimport type { ToolId } from './tool-output.js';\nimport type { ToolRenderResult } from './renderer.js';\n\nexport type FileAction = {\n relativePath: string;\n content: string;\n};\n\nexport const buildInstallPlan = (params: {\n toolId: ToolId;\n renderResult: ToolRenderResult;\n meta: { sourceHash: string; generatedAt: string };\n}): readonly FileAction[] => {\n const { toolId, renderResult, meta } = params;\n\n if (toolId === 'claude-code' && renderResult.tool === 'claude-code') {\n const { rulesDir } = TOOL_OUTPUT_MAP['claude-code'];\n return renderResult.files.map(({ fileName, content }) => ({\n relativePath: join(rulesDir, fileName),\n content: wrapWithHeader(content, meta),\n }));\n }\n\n if (\n (toolId === 'codex' && renderResult.tool === 'codex') ||\n (toolId === 'gemini' && renderResult.tool === 'gemini')\n ) {\n const config = TOOL_OUTPUT_MAP[toolId];\n const actions: FileAction[] = [];\n\n if (renderResult.rootContent) {\n actions.push({\n relativePath: join(config.dir, config.rootFileName),\n content: wrapWithHeader(renderResult.rootContent, meta),\n });\n }\n\n if (renderResult.domainContent) {\n actions.push({\n relativePath: join(config.dir, config.domainFileName),\n content: wrapWithHeader(renderResult.domainContent, meta),\n });\n }\n\n return actions;\n }\n\n return [];\n};\n","import { dirname, resolve } from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\n// dist/index.js 위치 기준 → 상위(패키지 루트) → data/\n// src/에서 실행 시: src/../data = data/ ✅\n// dist/에서 실행 시: dist/../data = data/ ✅\nconst __dirname = dirname(fileURLToPath(import.meta.url));\n\nexport const COMPILER_DATA_DIR = resolve(__dirname, '..', 'data');\n"],"mappings":"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","names":["z","z","readFileSync","readdirSync","resolve","readdirSync","readFileSync","resolve","readFileSync","readFileSync","join","join","dirname","resolve"]}
1
+ {"version":3,"sources":["../src/schemas/rule.schema.ts","../src/schemas/preset.schema.ts","../src/schemas/manifest.schema.ts","../src/loader.ts","../src/renderer.ts","../src/tool-output.ts","../src/source-hash.ts","../src/managed-header.ts","../src/manifest-io.ts","../src/diff.ts","../src/install-plan.ts","../src/paths.ts"],"sourcesContent":["/**\n * Rule = SSOT의 최소 지식 단위. 하나의 코딩 컨벤션/아키텍처 규칙을 YAML로 구조화한 것.\n */\nimport { z } from 'zod';\n\nexport const DecisionTableEntrySchema = z\n .object({\n when: z.string().min(1),\n then: z.string().min(1),\n /** 조건부 규칙에서 회피해야 할 패턴 */\n avoid: z.string().min(1).optional(),\n })\n .strict();\n\nexport const RuleContentSchema = z\n .object({\n /** Anti-pattern 규칙 ('하지 마라'). guidelines보다 항상 상단 렌더링 */\n constraints: z.array(z.string().min(1)),\n /** Positive 규칙 ('해라') */\n guidelines: z.array(z.string().min(1)),\n /** 조건부 규칙. when→then→avoid 구조 */\n decision_table: z.array(DecisionTableEntrySchema).optional(),\n })\n .strict();\n\nexport const RuleSchema = z\n .object({\n id: z.string().regex(/^[a-z0-9]+(-[a-z0-9]+)*$/, 'id must be kebab-case'),\n category: z.string().min(1),\n tags: z.array(z.string().min(1)),\n /** 0-100. 높을수록 생성 파일 상단 배치 (U-shaped attention 최적화) */\n priority: z.number().int().min(0).max(100),\n content: RuleContentSchema,\n })\n .strict();\n\nexport type DecisionTableEntry = z.infer<typeof DecisionTableEntrySchema>;\nexport type RuleContent = z.infer<typeof RuleContentSchema>;\nexport type Rule = z.infer<typeof RuleSchema>;\n","import { z } from 'zod';\n\nexport const PresetSchema = z\n .object({\n id: z\n .string()\n .regex(/^[a-z][a-z0-9-]*$/)\n .min(1),\n description: z.string().min(1),\n rules: z.array(z.string().min(1)).min(1),\n })\n .strict();\n\nexport type Preset = z.infer<typeof PresetSchema>;\n","/**\n * Manifest = 설치 추적 메타데이터. CLI가 이전 설치 상태를 기억하기 위한 JSON.\n */\nimport { z } from 'zod';\n\nexport const SCOPES = {\n PROJECT: 'project',\n GLOBAL: 'global',\n} as const;\n\n/** 모노레포 워크스페이스별 preset + rules 추적 */\nconst WorkspaceEntrySchema = z\n .object({\n preset: z.string().min(1),\n rules: z.array(z.string().min(1)),\n })\n .strict();\n\nexport type WorkspaceEntry = z.infer<typeof WorkspaceEntrySchema>;\n\nexport const ManifestSchema = z\n .object({\n tools: z.array(z.string().min(1)).min(1),\n scope: z.enum(['project', 'global']),\n /** 비모노레포 단일 preset */\n preset: z.string().min(1).optional(),\n /** 모노레포: workspace path → { preset, rules } */\n workspaces: z.record(z.string(), WorkspaceEntrySchema).optional(),\n installed_rules: z.array(z.string().min(1)),\n /** SSOT 데이터 파일들의 deterministic SHA-256 해시 (6자리 hex). diff/update 판단 기준 */\n sourceHash: z.string().regex(/^[a-f0-9]{6}$/, 'sourceHash must be 6 lowercase hex chars'),\n generatedAt: z.string().datetime({ offset: true }),\n })\n .strict();\n\nexport type Manifest = z.infer<typeof ManifestSchema>;\n","import { readFileSync, readdirSync } from 'node:fs';\nimport { resolve } from 'node:path';\nimport { parse } from 'yaml';\nimport { RuleSchema, PresetSchema } from './schemas/index.js';\nimport type { Rule, Preset } from './schemas/index.js';\n\n// priority 내림차순 정렬 (높을수록 상단 → U-shaped attention)\nexport const sortRulesByPriority = (rules: readonly Rule[]): Rule[] =>\n [...rules].sort((a, b) => b.priority - a.priority);\n\n// presets.yaml의 Record<id, {description, rules}> → Preset[] 변환\nexport const parseRawPresets = (raw: Record<string, { description: string; rules: string[] }>): Preset[] =>\n Object.entries(raw).map(([id, value]) => PresetSchema.parse({ id, ...value }));\n\n// TUI 세부조정: 사용자가 해제한 rule ID 목록을 제외 (순서 유지)\nexport const excludeRules = (rules: readonly Rule[], excludeIds: readonly string[]): Rule[] => {\n const excludeSet = new Set(excludeIds);\n return rules.filter((r) => !excludeSet.has(r.id));\n};\n\n// preset.rules ID 목록으로 allRules에서 필터링 + priority 정렬, 누락 시 throw\nexport const resolvePresetRules = (preset: Preset, allRules: readonly Rule[]): Rule[] => {\n const resolved = preset.rules.map((ruleId) => {\n const found = allRules.find((r) => r.id === ruleId);\n if (!found) throw new Error(`Rule not found: ${ruleId}`);\n return found;\n });\n return sortRulesByPriority(resolved);\n};\n\nexport const loadRuleFile = (filePath: string): Rule => {\n const raw = readFileSync(filePath, 'utf-8');\n return RuleSchema.parse(parse(raw));\n};\n\n// readdirSync + .yaml 필터 + sort\nexport const loadAllRules = (rulesDir: string): Rule[] => {\n const files = readdirSync(rulesDir)\n .filter((f) => f.endsWith('.yaml'))\n .sort();\n return files.map((f) => loadRuleFile(resolve(rulesDir, f)));\n};\n\nexport const loadPresets = (presetsPath: string): Preset[] => {\n const raw = readFileSync(presetsPath, 'utf-8');\n const data = parse(raw) as Record<string, { description: string; rules: string[] }>;\n return parseRawPresets(data);\n};\n","import { join } from 'node:path';\nimport type { Rule, DecisionTableEntry } from './schemas/index.js';\nimport { GLOBAL_CATEGORIES, CLAUDE_CODE_PATH_GLOBS, TOOL_OUTPUT_MAP } from './tool-output.js';\nimport type { ToolId } from './tool-output.js';\n\n// \"react-typescript\" → \"React Typescript\"\nexport const ruleIdToTitle = (id: string): string =>\n id\n .split('-')\n .map((word) => word.charAt(0).toUpperCase() + word.slice(1))\n .join(' ');\n\n// DecisionTableEntry[] → Markdown 테이블 (pipe 문자 &#124; escape)\nexport const renderDecisionTable = (entries: readonly DecisionTableEntry[]): string => {\n const escape = (s: string) => s.replace(/\\|/g, '&#124;');\n const hasAvoid = entries.some((e) => e.avoid !== undefined);\n\n const header = hasAvoid ? '| When | Then | Avoid |\\n|------|------|-------|' : '| When | Then |\\n|------|------|';\n\n const rows = entries.map((e) => {\n const when = escape(e.when);\n const then = escape(e.then);\n if (hasAvoid) {\n const avoid = e.avoid ? escape(e.avoid) : '';\n return `| ${when} | ${then} | ${avoid} |`;\n }\n return `| ${when} | ${then} |`;\n });\n\n return [header, ...rows].join('\\n');\n};\n\n// 단일 Rule → Markdown (빈 섹션 생략)\nexport const renderRuleToMarkdown = (rule: Rule): string => {\n const sections: string[] = [`# ${ruleIdToTitle(rule.id)}`];\n\n if (rule.content.constraints.length > 0) {\n sections.push('## Constraints');\n sections.push(rule.content.constraints.map((c) => `- ${c}`).join('\\n'));\n }\n\n if (rule.content.guidelines.length > 0) {\n sections.push('## Guidelines');\n sections.push(rule.content.guidelines.map((g) => `- ${g}`).join('\\n'));\n }\n\n if (rule.content.decision_table && rule.content.decision_table.length > 0) {\n sections.push('## Decision Table');\n sections.push(renderDecisionTable(rule.content.decision_table));\n }\n\n return sections.join('\\n\\n');\n};\n\n// Rule[] → 단일 Markdown (--- separator, single-file 모드용)\nexport const renderRulesToMarkdown = (rules: readonly Rule[]): string =>\n rules.map(renderRuleToMarkdown).join('\\n\\n---\\n\\n');\n\n// Rule이 global 카테고리에 속하는지 판별\nexport const isGlobalRule = (rule: Rule): boolean => (GLOBAL_CATEGORIES as readonly string[]).includes(rule.category);\n\n// Rule[] → { global, domain } 분리\nexport const partitionRules = (rules: readonly Rule[]): { global: Rule[]; domain: Rule[] } => {\n const global: Rule[] = [];\n const domain: Rule[] = [];\n for (const rule of rules) {\n if (isGlobalRule(rule)) {\n global.push(rule);\n } else {\n domain.push(rule);\n }\n }\n return { global, domain };\n};\n\n// glob 배열 → YAML frontmatter 블록\nexport const renderFrontmatter = (paths: readonly string[]): string => {\n const lines = paths.map((p) => ` - \"${p}\"`).join('\\n');\n return `---\\npaths:\\n${lines}\\n---`;\n};\n\nexport type WorkspaceMapping = {\n path: string;\n ruleIds: readonly string[];\n};\n\n// 단일 Rule → Claude Code용 Markdown\n// domain 룰이면서 glob 매핑이 있으면 paths: frontmatter 추가 (단일 프로젝트 전용)\n// global 룰 또는 매핑 없는 domain 룰 → frontmatter 없음\nexport const renderClaudeCodeRule = (rule: Rule): string => {\n const globs = CLAUDE_CODE_PATH_GLOBS[rule.id];\n if (!isGlobalRule(rule) && globs !== undefined) {\n return `${renderFrontmatter(globs)}\\n\\n${renderRuleToMarkdown(rule)}`;\n }\n return renderRuleToMarkdown(rule);\n};\n\n// 도구별 렌더링 결과 타입 (tagged union)\nexport type ClaudeCodeRenderResult = {\n tool: 'claude-code';\n files: { relativePath: string; content: string }[];\n};\n\nexport type CodexRenderResult = {\n tool: 'codex';\n rootContent: string;\n domainContent: string;\n};\n\nexport type GeminiRenderResult = {\n tool: 'gemini';\n rootContent: string;\n domainContent: string;\n};\n\nexport type ToolRenderResult = ClaudeCodeRenderResult | CodexRenderResult | GeminiRenderResult;\n\n// CLI 진입점: toolId + rules → 도구별 렌더링 결과\nexport const renderForTool = (\n toolId: ToolId,\n rules: readonly Rule[],\n workspaceMappings?: readonly WorkspaceMapping[],\n): ToolRenderResult => {\n const config = TOOL_OUTPUT_MAP[toolId];\n\n if (toolId === 'claude-code') {\n const { rulesDir, fileExtension } = config as (typeof TOOL_OUTPUT_MAP)['claude-code'];\n\n if (!workspaceMappings || workspaceMappings.length === 0) {\n // 단일 프로젝트: domain 룰에 paths: frontmatter (path-scoped)\n const files = rules.map((rule) => ({\n relativePath: join(rulesDir, `${rule.id}${fileExtension}`),\n content: renderClaudeCodeRule(rule),\n }));\n return { tool: 'claude-code', files };\n }\n\n // 모노레포: global → .claude/rules/, domain → {workspace}/CLAUDE.md (진짜 지연 로딩)\n const { global, domain } = partitionRules(rules);\n\n const globalFiles = global.map((rule) => ({\n relativePath: join(rulesDir, `${rule.id}${fileExtension}`),\n content: renderRuleToMarkdown(rule), // global은 frontmatter 불필요\n }));\n\n const workspaceFiles: { relativePath: string; content: string }[] = [];\n for (const ws of workspaceMappings) {\n const wsRules = domain.filter((r) => ws.ruleIds.includes(r.id));\n if (wsRules.length === 0) continue;\n workspaceFiles.push({\n relativePath: join(ws.path, 'CLAUDE.md'),\n content: renderRulesToMarkdown(wsRules),\n });\n }\n\n return { tool: 'claude-code', files: [...globalFiles, ...workspaceFiles] };\n }\n\n const { global, domain } = partitionRules(rules);\n const rootContent = renderRulesToMarkdown(global);\n const domainContent = renderRulesToMarkdown(domain);\n\n if (toolId === 'codex') {\n return { tool: 'codex', rootContent, domainContent };\n }\n\n // gemini\n return { tool: 'gemini', rootContent, domainContent };\n};\n","// Global 성격의 category (항상 로딩, frontmatter 없음)\nexport const GLOBAL_CATEGORIES = ['persona', 'communication', 'philosophy', 'convention', 'standard'] as const;\n\n// Claude Code paths: frontmatter용 Rule ID → glob 매핑\n// src/ 없이 루트를 src처럼 쓰는 React/Next.js 프로젝트 고려\n// 매핑에 없는 domain 룰 → frontmatter 없이 항상 로딩 (안전 fallback)\nexport const CLAUDE_CODE_PATH_GLOBS: Readonly<Record<string, readonly string[]>> = {\n typescript: ['**/*.ts', '**/*.tsx'],\n 'react-typescript': ['**/*.tsx', '**/*.jsx'],\n nextjs: ['**/app/**', 'next.config.*', '**/middleware.ts'],\n nestjs: ['**/*.module.ts', '**/*.controller.ts', '**/*.service.ts'],\n 'nestjs-graphql': ['**/*.resolver.ts'],\n graphql: ['**/*.graphql', '**/*.gql'],\n 'prisma-postgresql': ['prisma/**', '**/*.prisma'],\n 'shadcn-ui': ['**/components/ui/**'],\n flutter: ['lib/**/*.dart'],\n python: ['**/*.py'],\n fastapi: ['**/routers/**', '**/main.py'],\n sqlalchemy: ['**/models/**/*.py', 'alembic/**'],\n 'data-pipeline-python': ['**/pipelines/**', '**/etl/**'],\n 'ai-llm-python': ['**/agents/**', '**/chains/**'],\n 'libs-frontend-web': ['**/*.tsx', '**/*.ts'],\n 'libs-frontend-app': ['lib/**/*.dart'],\n 'libs-backend-ts': ['**/*.ts'],\n 'libs-backend-python': ['**/*.py'],\n};\n\nexport const TOOL_OUTPUT_MAP = {\n 'claude-code': {\n mode: 'multi-file' as const,\n rulesDir: '.claude/rules',\n fileExtension: '.md',\n // single: path-scoped (paths: frontmatter) / monorepo: hierarchical ({workspace}/CLAUDE.md)\n contextStrategy: 'hybrid' as const,\n },\n codex: {\n mode: 'multi-file' as const,\n dir: '.codex',\n rootFileName: 'AGENTS.md', // global 룰\n domainFileName: 'AGENTS.override.md', // domain 룰 (하위 폴더)\n contextStrategy: 'hierarchical' as const, // 루트 + 하위 폴더 JIT\n },\n gemini: {\n mode: 'multi-file' as const,\n dir: '.gemini',\n rootFileName: 'GEMINI.md', // global 룰\n domainFileName: 'GEMINI.md', // domain 룰 (하위 폴더)\n contextStrategy: 'hierarchical' as const, // 루트 + 하위 폴더 JIT\n },\n} as const;\n\nexport type ToolId = keyof typeof TOOL_OUTPUT_MAP;\n","import { createHash } from 'node:crypto';\nimport { readFileSync, readdirSync } from 'node:fs';\nimport { resolve } from 'node:path';\nimport { ManifestSchema } from './schemas/index.js';\nimport type { Manifest } from './schemas/index.js';\n\n// 문자열 배열 → SHA-256 → 6-hex (caller가 정렬 책임)\nexport const computeHash = (contents: readonly string[]): string =>\n createHash('sha256').update(contents.join('')).digest('hex').slice(0, 6);\n\n// rulesDir 내 YAML 파일들을 alphabetical 정렬 후 해싱\nexport const computeSourceHash = (rulesDir: string): string => {\n const files = readdirSync(rulesDir)\n .filter((f) => f.endsWith('.yaml'))\n .sort();\n const contents = files.map((f) => readFileSync(resolve(rulesDir, f), 'utf-8'));\n return computeHash(contents);\n};\n\n// Manifest Builder (Pure, 단 generatedAt에 현재 시각 사용)\nexport const buildManifest = (params: {\n tools: readonly string[];\n scope: 'project' | 'global';\n preset?: string;\n workspaces?: Record<string, { preset: string; rules: string[] }>;\n installedRules: readonly string[];\n sourceHash: string;\n}): Manifest =>\n ManifestSchema.parse({\n tools: [...params.tools],\n scope: params.scope,\n preset: params.preset,\n workspaces: params.workspaces,\n installed_rules: [...params.installedRules],\n sourceHash: params.sourceHash,\n generatedAt: new Date().toISOString(),\n });\n","const MANAGED_MARKER = '<!-- managed by ai-ops -->';\nconst META_PATTERN = /^<!-- sourceHash: ([a-f0-9]{6}) \\| generatedAt: (.+) -->$/;\n\nexport const wrapWithHeader = (content: string, meta: { sourceHash: string; generatedAt: string }): string => {\n const metaLine = `<!-- sourceHash: ${meta.sourceHash} | generatedAt: ${meta.generatedAt} -->`;\n return `${MANAGED_MARKER}\\n${metaLine}\\n\\n${content}`;\n};\n\nexport const isManagedFile = (content: string): boolean => content.startsWith(MANAGED_MARKER);\n\nexport const parseManagedHeader = (content: string): { sourceHash: string; generatedAt: string } | null => {\n if (!isManagedFile(content)) return null;\n\n const lines = content.split('\\n');\n const metaLine = lines[1] ?? '';\n const match = META_PATTERN.exec(metaLine);\n if (!match) return null;\n\n return { sourceHash: match[1], generatedAt: match[2] };\n};\n\nexport const stripManagedHeader = (content: string): string => {\n if (!isManagedFile(content)) return content;\n\n const lines = content.split('\\n');\n // marker line + meta line + blank line = 3 lines\n const stripped = lines.slice(3).join('\\n');\n return stripped;\n};\n","import { mkdirSync, readFileSync, writeFileSync } from 'node:fs';\nimport { dirname, join } from 'node:path';\nimport { ManifestSchema } from './schemas/index.js';\nimport type { Manifest } from './schemas/index.js';\n\nexport const MANIFEST_FILENAME = '.ai-ops-manifest.json';\n\n// Pure\nexport const parseManifest = (json: string): Manifest => ManifestSchema.parse(JSON.parse(json));\n\nexport const serializeManifest = (manifest: Manifest): string => JSON.stringify(manifest, null, 2) + '\\n';\n\n// I/O\nexport const resolveManifestPath = (basePath: string): string => join(basePath, MANIFEST_FILENAME);\n\nexport const readManifest = (manifestPath: string): Manifest | null => {\n let raw: string;\n try {\n raw = readFileSync(manifestPath, 'utf-8');\n } catch {\n return null;\n }\n return parseManifest(raw);\n};\n\nexport const writeManifest = (manifestPath: string, manifest: Manifest): void => {\n mkdirSync(dirname(manifestPath), { recursive: true });\n writeFileSync(manifestPath, serializeManifest(manifest), 'utf-8');\n};\n","import type { Manifest } from './schemas/index.js';\n\nexport type DiffResult = {\n status: 'up-to-date' | 'changed';\n added: readonly string[];\n removed: readonly string[];\n sourceChanged: boolean;\n};\n\nexport const computeDiff = (params: {\n previous: Manifest;\n currentRules: readonly string[];\n currentSourceHash: string;\n}): DiffResult => {\n const { previous, currentRules, currentSourceHash } = params;\n\n const previousSet = new Set(previous.installed_rules);\n const currentSet = new Set(currentRules);\n\n const added = currentRules.filter((id) => !previousSet.has(id));\n const removed = previous.installed_rules.filter((id) => !currentSet.has(id));\n const sourceChanged = previous.sourceHash !== currentSourceHash;\n\n const status = added.length > 0 || removed.length > 0 || sourceChanged ? 'changed' : 'up-to-date';\n\n return { status, added, removed, sourceChanged };\n};\n","import { join } from 'node:path';\nimport { wrapWithHeader } from './managed-header.js';\nimport { TOOL_OUTPUT_MAP } from './tool-output.js';\nimport type { ToolId } from './tool-output.js';\nimport type { ToolRenderResult } from './renderer.js';\n\nexport type FileAction = {\n relativePath: string;\n content: string;\n};\n\nexport const buildInstallPlan = (params: {\n toolId: ToolId;\n renderResult: ToolRenderResult;\n meta: { sourceHash: string; generatedAt: string };\n}): readonly FileAction[] => {\n const { toolId, renderResult, meta } = params;\n\n if (toolId === 'claude-code' && renderResult.tool === 'claude-code') {\n return renderResult.files.map(({ relativePath, content }) => ({\n relativePath,\n content: wrapWithHeader(content, meta),\n }));\n }\n\n if (\n (toolId === 'codex' && renderResult.tool === 'codex') ||\n (toolId === 'gemini' && renderResult.tool === 'gemini')\n ) {\n const config = TOOL_OUTPUT_MAP[toolId];\n const actions: FileAction[] = [];\n\n if (renderResult.rootContent) {\n actions.push({\n relativePath: join(config.dir, config.rootFileName),\n content: wrapWithHeader(renderResult.rootContent, meta),\n });\n }\n\n if (renderResult.domainContent) {\n actions.push({\n relativePath: join(config.dir, config.domainFileName),\n content: wrapWithHeader(renderResult.domainContent, meta),\n });\n }\n\n return actions;\n }\n\n return [];\n};\n","import { dirname, resolve } from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\n// dist/index.js 위치 기준 → 상위(패키지 루트) → data/\n// src/에서 실행 시: src/../data = data/ ✅\n// dist/에서 실행 시: dist/../data = data/ ✅\nconst __dirname = dirname(fileURLToPath(import.meta.url));\n\nexport const COMPILER_DATA_DIR = resolve(__dirname, '..', 'data');\n"],"mappings":"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","names":["z","z","global","domain","readFileSync","readdirSync","resolve","readdirSync","readFileSync","resolve","readFileSync","join","join","readFileSync","join","join","dirname","resolve"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ai-ops-compiler",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
4
4
  "description": "Compiler and rule management core for ai-ops scaffolding tools",
5
5
  "license": "MIT",
6
6
  "type": "module",