ai-ops-cli 0.1.13 → 0.1.14
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/bin/index.js +164 -66
- package/dist/bin/index.js.map +1 -1
- package/package.json +1 -1
package/dist/bin/index.js
CHANGED
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
import { Command } from "commander";
|
|
5
5
|
|
|
6
6
|
// src/commands/init.ts
|
|
7
|
-
import * as
|
|
8
|
-
import { join as
|
|
7
|
+
import * as p3 from "@clack/prompts";
|
|
8
|
+
import { join as join9 } from "path";
|
|
9
9
|
|
|
10
10
|
// src/core/schemas/rule.schema.ts
|
|
11
11
|
import { z } from "zod";
|
|
@@ -42,6 +42,10 @@ var PresetSchema = z2.object({
|
|
|
42
42
|
|
|
43
43
|
// src/core/schemas/manifest.schema.ts
|
|
44
44
|
import { z as z3 } from "zod";
|
|
45
|
+
var SettingsConfigSchema = z3.object({
|
|
46
|
+
claude: z3.array(z3.string().min(1)).optional(),
|
|
47
|
+
gemini: z3.array(z3.string().min(1)).optional()
|
|
48
|
+
}).strict();
|
|
45
49
|
var WorkspaceEntrySchema = z3.object({
|
|
46
50
|
preset: z3.string().min(1),
|
|
47
51
|
rules: z3.array(z3.string().min(1))
|
|
@@ -58,6 +62,8 @@ var ManifestSchema = z3.object({
|
|
|
58
62
|
installed_files: z3.array(z3.string().min(1)).optional(),
|
|
59
63
|
/** non-managed 파일에 섹션을 append한 경우 추적 (uninstall 시 섹션만 제거) */
|
|
60
64
|
appended_files: z3.array(z3.string().min(1)).optional(),
|
|
65
|
+
/** init 시 선택된 settings 항목 — update 시 재생성에 사용 */
|
|
66
|
+
settings: SettingsConfigSchema.optional(),
|
|
61
67
|
/** SSOT 데이터 파일들의 deterministic SHA-256 해시 (6자리 hex). diff/update 판단 기준 */
|
|
62
68
|
sourceHash: z3.string().regex(/^[a-f0-9]{6}$/, "sourceHash must be 6 lowercase hex chars"),
|
|
63
69
|
generatedAt: z3.string().datetime({ offset: true })
|
|
@@ -231,7 +237,7 @@ var partitionRules = (rules) => {
|
|
|
231
237
|
return { global, domain };
|
|
232
238
|
};
|
|
233
239
|
var renderFrontmatter = (paths) => {
|
|
234
|
-
const lines = paths.map((
|
|
240
|
+
const lines = paths.map((p7) => ` - "${p7}"`).join("\n");
|
|
235
241
|
return `---
|
|
236
242
|
paths:
|
|
237
243
|
${lines}
|
|
@@ -301,6 +307,10 @@ var buildManifest = (params) => ManifestSchema.parse({
|
|
|
301
307
|
installed_rules: [...params.installedRules],
|
|
302
308
|
installed_files: params.installedFiles ? [...params.installedFiles] : void 0,
|
|
303
309
|
appended_files: params.appendedFiles && params.appendedFiles.length > 0 ? [...params.appendedFiles] : void 0,
|
|
310
|
+
settings: params.settings ? {
|
|
311
|
+
claude: params.settings.claude ? [...params.settings.claude] : void 0,
|
|
312
|
+
gemini: params.settings.gemini ? [...params.settings.gemini] : void 0
|
|
313
|
+
} : void 0,
|
|
304
314
|
sourceHash: params.sourceHash,
|
|
305
315
|
generatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
306
316
|
});
|
|
@@ -384,7 +394,7 @@ var computeDiff = (params) => {
|
|
|
384
394
|
|
|
385
395
|
// src/core/install-plan.ts
|
|
386
396
|
import { join as join3 } from "path";
|
|
387
|
-
var CODEX_PLAN_SECTION = "\n\n---\n\n## Plan\n\
|
|
397
|
+
var CODEX_PLAN_SECTION = "\n\n---\n\n## Plan Snapshot\n\nBefore implementation, save the latest `<proposed_plan>` to `.codex/plans/YYYYMMDD_<topic>.md` (`<topic>` = kebab-case title, fallback `task`).\nEnsure `.codex/plans` exists; if the filename exists, append `-v2`, `-v3`, ...\nDo not start any mutating implementation step until this file is written.";
|
|
388
398
|
var buildInstallPlan = (params) => {
|
|
389
399
|
const { toolId, renderResult, meta } = params;
|
|
390
400
|
if (toolId === "claude-code" && renderResult.tool === "claude-code") {
|
|
@@ -623,6 +633,75 @@ var installGeminiSettings = (basePath, selectedValues) => {
|
|
|
623
633
|
writeFileSync3(settingsPath, JSON.stringify(merged, null, 2) + "\n", "utf-8");
|
|
624
634
|
};
|
|
625
635
|
|
|
636
|
+
// src/lib/claude-settings.ts
|
|
637
|
+
import * as p2 from "@clack/prompts";
|
|
638
|
+
import { existsSync as existsSync4, mkdirSync as mkdirSync4, readFileSync as readFileSync6, writeFileSync as writeFileSync4 } from "fs";
|
|
639
|
+
import { join as join8 } from "path";
|
|
640
|
+
var SETTING_GROUPS2 = [
|
|
641
|
+
{
|
|
642
|
+
value: "model",
|
|
643
|
+
label: "Model \u2014 Plan \uBAA8\uB4DC \uBAA8\uB378",
|
|
644
|
+
hint: "model: opusplan \u2014 Plan \uBAA8\uB4DC\uC5D0\uC11C Opus \uBAA8\uB378 \uC0AC\uC6A9",
|
|
645
|
+
patch: { model: "opusplan" }
|
|
646
|
+
},
|
|
647
|
+
{
|
|
648
|
+
value: "plansDirectory",
|
|
649
|
+
label: "Plans Directory \u2014 \uACC4\uD68D \uD30C\uC77C \uC800\uC7A5 \uACBD\uB85C",
|
|
650
|
+
hint: "plansDirectory: ./.claude/plans \u2014 \uACC4\uD68D \uD30C\uC77C\uC744 .claude/plans\uC5D0 \uC800\uC7A5",
|
|
651
|
+
patch: { plansDirectory: "./.claude/plans" }
|
|
652
|
+
}
|
|
653
|
+
];
|
|
654
|
+
var deepMerge2 = (base, patch) => {
|
|
655
|
+
const result = { ...base };
|
|
656
|
+
for (const [key, value] of Object.entries(patch)) {
|
|
657
|
+
if (value !== null && typeof value === "object" && !Array.isArray(value) && typeof result[key] === "object" && result[key] !== null) {
|
|
658
|
+
result[key] = deepMerge2(result[key], value);
|
|
659
|
+
} else {
|
|
660
|
+
result[key] = value;
|
|
661
|
+
}
|
|
662
|
+
}
|
|
663
|
+
return result;
|
|
664
|
+
};
|
|
665
|
+
var promptClaudeSettings = async () => {
|
|
666
|
+
const wantSettings = await p2.confirm({
|
|
667
|
+
message: "Claude Code \uC124\uC815 \uD30C\uC77C(.claude/settings.local.json)\uC744 \uC124\uCE58\uD558\uC2DC\uACA0\uC2B5\uB2C8\uAE4C?",
|
|
668
|
+
initialValue: true
|
|
669
|
+
});
|
|
670
|
+
if (p2.isCancel(wantSettings) || !wantSettings) return null;
|
|
671
|
+
const selected = await p2.multiselect({
|
|
672
|
+
message: "\uC124\uCE58\uD560 \uC124\uC815 \uD56D\uBAA9\uC744 \uC120\uD0DD\uD558\uC138\uC694 (\uC2A4\uD398\uC774\uC2A4\uB85C \uD1A0\uAE00)",
|
|
673
|
+
options: SETTING_GROUPS2.map((g) => ({
|
|
674
|
+
value: g.value,
|
|
675
|
+
label: g.label,
|
|
676
|
+
hint: g.hint
|
|
677
|
+
})),
|
|
678
|
+
initialValues: SETTING_GROUPS2.map((g) => g.value),
|
|
679
|
+
required: false
|
|
680
|
+
});
|
|
681
|
+
if (p2.isCancel(selected)) return null;
|
|
682
|
+
return selected;
|
|
683
|
+
};
|
|
684
|
+
var installClaudeSettings = (basePath, selectedValues) => {
|
|
685
|
+
if (selectedValues.length === 0) return;
|
|
686
|
+
const settingsDir = join8(basePath, ".claude");
|
|
687
|
+
const settingsPath = join8(settingsDir, "settings.local.json");
|
|
688
|
+
let existing = {};
|
|
689
|
+
if (existsSync4(settingsPath)) {
|
|
690
|
+
try {
|
|
691
|
+
existing = JSON.parse(readFileSync6(settingsPath, "utf-8"));
|
|
692
|
+
} catch {
|
|
693
|
+
}
|
|
694
|
+
}
|
|
695
|
+
let merged = existing;
|
|
696
|
+
for (const val of selectedValues) {
|
|
697
|
+
const group = SETTING_GROUPS2.find((g) => g.value === val);
|
|
698
|
+
if (!group) continue;
|
|
699
|
+
merged = deepMerge2(merged, group.patch);
|
|
700
|
+
}
|
|
701
|
+
mkdirSync4(settingsDir, { recursive: true });
|
|
702
|
+
writeFileSync4(settingsPath, JSON.stringify(merged, null, 2) + "\n", "utf-8");
|
|
703
|
+
};
|
|
704
|
+
|
|
626
705
|
// src/commands/init.ts
|
|
627
706
|
var TOOL_OPTIONS = [
|
|
628
707
|
{ value: "claude-code", label: "Claude Code" },
|
|
@@ -638,7 +717,7 @@ var deduplicateRules = (rules) => {
|
|
|
638
717
|
});
|
|
639
718
|
};
|
|
640
719
|
var selectPresetAndFineTune = async (workspaceName, presets, allRules) => {
|
|
641
|
-
const preset = await
|
|
720
|
+
const preset = await p3.select({
|
|
642
721
|
message: `[${workspaceName}] \uD504\uB9AC\uC14B\uC744 \uC120\uD0DD\uD558\uC138\uC694`,
|
|
643
722
|
options: presets.map((pr) => ({
|
|
644
723
|
value: pr,
|
|
@@ -646,25 +725,25 @@ var selectPresetAndFineTune = async (workspaceName, presets, allRules) => {
|
|
|
646
725
|
hint: pr.description
|
|
647
726
|
}))
|
|
648
727
|
});
|
|
649
|
-
if (
|
|
728
|
+
if (p3.isCancel(preset)) return null;
|
|
650
729
|
const presetRuleGroups = resolvePresetRuleGroups(preset, allRules);
|
|
651
730
|
const globalGroups = presetRuleGroups.filter((group) => group.rules.every(isGlobalRule));
|
|
652
731
|
const domainGroups = presetRuleGroups.filter((group) => !group.rules.every(isGlobalRule));
|
|
653
732
|
const globalGroupIds = globalGroups.map((group) => group.id);
|
|
654
733
|
const globalRules = globalGroupIds.length > 0 ? resolvePresetRules({ ...preset, rules: globalGroupIds }, allRules) : [];
|
|
655
734
|
if (globalRules.length > 0) {
|
|
656
|
-
|
|
735
|
+
p3.note(globalRules.map((r) => ` \u2713 ${r.id}`).join("\n"), `[${workspaceName}] \uAE30\uBCF8 \uADDC\uCE59 (\uC7A0\uAE08)`);
|
|
657
736
|
}
|
|
658
737
|
if (domainGroups.length === 0) {
|
|
659
738
|
return { workspace: workspaceName, preset, finalRules: resolvePresetRules(preset, allRules) };
|
|
660
739
|
}
|
|
661
|
-
const selectedDomain = await
|
|
740
|
+
const selectedDomain = await p3.multiselect({
|
|
662
741
|
message: `[${workspaceName}] \uB3C4\uBA54\uC778 \uADDC\uCE59 \uC120\uD0DD (\uD574\uC81C\uD558\uC5EC \uC81C\uC678)`,
|
|
663
742
|
options: domainGroups.map((group) => ({ value: group.id, label: group.id })),
|
|
664
743
|
initialValues: domainGroups.map((group) => group.id),
|
|
665
744
|
required: false
|
|
666
745
|
});
|
|
667
|
-
if (
|
|
746
|
+
if (p3.isCancel(selectedDomain)) return null;
|
|
668
747
|
const selectedLogicalRuleIds = [...globalGroupIds, ...selectedDomain];
|
|
669
748
|
return {
|
|
670
749
|
workspace: workspaceName,
|
|
@@ -680,7 +759,7 @@ var installHierarchicalMonorepo = (toolId, mappings, basePath, meta) => {
|
|
|
680
759
|
const { global } = partitionRules(allRules);
|
|
681
760
|
if (global.length > 0) {
|
|
682
761
|
const rootAction = {
|
|
683
|
-
relativePath:
|
|
762
|
+
relativePath: join9(config.dir, config.rootFileName),
|
|
684
763
|
content: wrapWithHeader(renderRulesToMarkdown(global), meta)
|
|
685
764
|
};
|
|
686
765
|
const r = installFiles(basePath, [rootAction], meta);
|
|
@@ -691,7 +770,7 @@ var installHierarchicalMonorepo = (toolId, mappings, basePath, meta) => {
|
|
|
691
770
|
const { domain } = partitionRules(mapping.finalRules);
|
|
692
771
|
if (domain.length === 0) continue;
|
|
693
772
|
const domainAction = {
|
|
694
|
-
relativePath:
|
|
773
|
+
relativePath: join9(mapping.workspace, config.domainFileName),
|
|
695
774
|
content: wrapWithHeader(renderRulesToMarkdown(domain), meta)
|
|
696
775
|
};
|
|
697
776
|
const r = installFiles(basePath, [domainAction], meta);
|
|
@@ -714,22 +793,22 @@ var installClaudeCodeMonorepo = (mappings, basePath, meta) => {
|
|
|
714
793
|
var initCommand = async () => {
|
|
715
794
|
const basePath = resolveBasePath();
|
|
716
795
|
const rulesDir = resolveRulesDir();
|
|
717
|
-
|
|
718
|
-
const selectedTools = await
|
|
796
|
+
p3.intro("ai-ops init");
|
|
797
|
+
const selectedTools = await p3.multiselect({
|
|
719
798
|
message: "AI \uB3C4\uAD6C\uB97C \uC120\uD0DD\uD558\uC138\uC694",
|
|
720
799
|
options: TOOL_OPTIONS,
|
|
721
800
|
required: true
|
|
722
801
|
});
|
|
723
|
-
if (
|
|
724
|
-
|
|
802
|
+
if (p3.isCancel(selectedTools)) {
|
|
803
|
+
p3.cancel("\uCDE8\uC18C\uB428");
|
|
725
804
|
process.exit(0);
|
|
726
805
|
}
|
|
727
|
-
const isMonorepo = await
|
|
806
|
+
const isMonorepo = await p3.confirm({
|
|
728
807
|
message: "\uBAA8\uB178\uB808\uD3EC \uD504\uB85C\uC81D\uD2B8\uC785\uB2C8\uAE4C?",
|
|
729
808
|
initialValue: false
|
|
730
809
|
});
|
|
731
|
-
if (
|
|
732
|
-
|
|
810
|
+
if (p3.isCancel(isMonorepo)) {
|
|
811
|
+
p3.cancel("\uCDE8\uC18C\uB428");
|
|
733
812
|
process.exit(0);
|
|
734
813
|
}
|
|
735
814
|
const allRules = loadAllRules(rulesDir);
|
|
@@ -739,32 +818,33 @@ var initCommand = async () => {
|
|
|
739
818
|
if (!isMonorepo) {
|
|
740
819
|
const mapping = await selectPresetAndFineTune(".", presets, allRules);
|
|
741
820
|
if (!mapping) {
|
|
742
|
-
|
|
821
|
+
p3.cancel("\uCDE8\uC18C\uB428");
|
|
743
822
|
process.exit(0);
|
|
744
823
|
}
|
|
745
824
|
mappings.push(mapping);
|
|
746
825
|
} else {
|
|
747
826
|
const candidates = listWorkspaceCandidates(basePath);
|
|
748
|
-
const selectedWorkspaces = await
|
|
827
|
+
const selectedWorkspaces = await p3.multiselect({
|
|
749
828
|
message: "\uC6CC\uD06C\uC2A4\uD398\uC774\uC2A4\uB97C \uC120\uD0DD\uD558\uC138\uC694",
|
|
750
829
|
options: candidates.map((c) => ({ value: c, label: c })),
|
|
751
830
|
required: true
|
|
752
831
|
});
|
|
753
|
-
if (
|
|
754
|
-
|
|
832
|
+
if (p3.isCancel(selectedWorkspaces)) {
|
|
833
|
+
p3.cancel("\uCDE8\uC18C\uB428");
|
|
755
834
|
process.exit(0);
|
|
756
835
|
}
|
|
757
836
|
for (const ws of selectedWorkspaces) {
|
|
758
837
|
const mapping = await selectPresetAndFineTune(ws, presets, allRules);
|
|
759
838
|
if (!mapping) {
|
|
760
|
-
|
|
839
|
+
p3.cancel("\uCDE8\uC18C\uB428");
|
|
761
840
|
process.exit(0);
|
|
762
841
|
}
|
|
763
842
|
mappings.push(mapping);
|
|
764
843
|
}
|
|
765
844
|
}
|
|
766
845
|
const geminiSettingValues = selectedTools.includes("gemini") ? await promptGeminiSettings() : null;
|
|
767
|
-
const
|
|
846
|
+
const claudeSettingValues = selectedTools.includes("claude-code") ? await promptClaudeSettings() : null;
|
|
847
|
+
const s = p3.spinner();
|
|
768
848
|
s.start("\uADDC\uCE59 \uC124\uCE58 \uC911...");
|
|
769
849
|
const meta = { sourceHash, generatedAt: (/* @__PURE__ */ new Date()).toISOString() };
|
|
770
850
|
const allInstalledFiles = [];
|
|
@@ -792,6 +872,10 @@ var initCommand = async () => {
|
|
|
792
872
|
installGeminiSettings(basePath, geminiSettingValues);
|
|
793
873
|
allInstalledFiles.push(".gemini/settings.json");
|
|
794
874
|
}
|
|
875
|
+
if (claudeSettingValues && claudeSettingValues.length > 0) {
|
|
876
|
+
installClaudeSettings(basePath, claudeSettingValues);
|
|
877
|
+
allInstalledFiles.push(".claude/settings.local.json");
|
|
878
|
+
}
|
|
795
879
|
s.stop("\uADDC\uCE59 \uC124\uCE58 \uC644\uB8CC");
|
|
796
880
|
const allInstalledRuleIds = deduplicateRules(mappings.flatMap((m) => m.finalRules)).map((r) => r.id);
|
|
797
881
|
const workspacesRecord = isMonorepo ? Object.fromEntries(
|
|
@@ -805,27 +889,31 @@ var initCommand = async () => {
|
|
|
805
889
|
installedRules: allInstalledRuleIds,
|
|
806
890
|
installedFiles: allInstalledFiles,
|
|
807
891
|
appendedFiles: allAppended,
|
|
892
|
+
settings: claudeSettingValues || geminiSettingValues ? {
|
|
893
|
+
claude: claudeSettingValues ? [...claudeSettingValues] : void 0,
|
|
894
|
+
gemini: geminiSettingValues ? [...geminiSettingValues] : void 0
|
|
895
|
+
} : void 0,
|
|
808
896
|
sourceHash
|
|
809
897
|
});
|
|
810
898
|
writeManifest(resolveManifestPath(basePath), manifest);
|
|
811
899
|
if (allAppended.length > 0) {
|
|
812
|
-
|
|
900
|
+
p3.log.info(`\uAE30\uC874 \uD30C\uC77C\uC5D0 \uC139\uC158 \uCD94\uAC00\uB428 (\uB0B4\uC6A9 \uBCF4\uC874):
|
|
813
901
|
${allAppended.map((f) => ` ${f}`).join("\n")}`);
|
|
814
902
|
}
|
|
815
|
-
|
|
816
|
-
|
|
903
|
+
p3.log.success(`\uC124\uCE58\uB41C \uADDC\uCE59: ${allInstalledRuleIds.length}\uAC1C`);
|
|
904
|
+
p3.outro("ai-ops init \uC644\uB8CC");
|
|
817
905
|
};
|
|
818
906
|
|
|
819
907
|
// src/commands/update.ts
|
|
820
|
-
import * as
|
|
821
|
-
import { join as
|
|
908
|
+
import * as p4 from "@clack/prompts";
|
|
909
|
+
import { join as join10 } from "path";
|
|
822
910
|
var updateCommand = async (opts) => {
|
|
823
911
|
const basePath = resolveBasePath();
|
|
824
912
|
const manifestPath = resolveManifestPath(basePath);
|
|
825
|
-
|
|
913
|
+
p4.intro("ai-ops update");
|
|
826
914
|
const manifest = readManifest(manifestPath);
|
|
827
915
|
if (!manifest) {
|
|
828
|
-
|
|
916
|
+
p4.log.error("manifest\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4. \uBA3C\uC800 ai-ops init\uC744 \uC2E4\uD589\uD558\uC138\uC694.");
|
|
829
917
|
process.exit(1);
|
|
830
918
|
}
|
|
831
919
|
const rulesDir = resolveRulesDir();
|
|
@@ -836,11 +924,11 @@ var updateCommand = async (opts) => {
|
|
|
836
924
|
currentSourceHash: sourceHash
|
|
837
925
|
});
|
|
838
926
|
if (diffResult.status === "up-to-date" && !opts.force) {
|
|
839
|
-
|
|
840
|
-
|
|
927
|
+
p4.log.info("\uBCC0\uACBD \uC0AC\uD56D\uC774 \uC5C6\uC2B5\uB2C8\uB2E4.");
|
|
928
|
+
p4.outro("ai-ops update \uC644\uB8CC");
|
|
841
929
|
return;
|
|
842
930
|
}
|
|
843
|
-
const s =
|
|
931
|
+
const s = p4.spinner();
|
|
844
932
|
s.start("\uADDC\uCE59 \uAC31\uC2E0 \uC911...");
|
|
845
933
|
const allRules = loadAllRules(rulesDir);
|
|
846
934
|
const meta = { sourceHash, generatedAt: (/* @__PURE__ */ new Date()).toISOString() };
|
|
@@ -869,7 +957,7 @@ var updateCommand = async (opts) => {
|
|
|
869
957
|
const { global } = partitionRules(allRulesToInstall);
|
|
870
958
|
if (global.length > 0) {
|
|
871
959
|
const rootAction = {
|
|
872
|
-
relativePath:
|
|
960
|
+
relativePath: join10(config.dir, config.rootFileName),
|
|
873
961
|
content: wrapWithHeader(renderRulesToMarkdown(global), meta)
|
|
874
962
|
};
|
|
875
963
|
const r = installFiles(basePath, [rootAction], meta);
|
|
@@ -882,7 +970,7 @@ var updateCommand = async (opts) => {
|
|
|
882
970
|
const { domain } = partitionRules(wsRules);
|
|
883
971
|
if (domain.length === 0) continue;
|
|
884
972
|
const domainAction = {
|
|
885
|
-
relativePath:
|
|
973
|
+
relativePath: join10(ws, config.domainFileName),
|
|
886
974
|
content: wrapWithHeader(renderRulesToMarkdown(domain), meta)
|
|
887
975
|
};
|
|
888
976
|
const r = installFiles(basePath, [domainAction], meta);
|
|
@@ -903,6 +991,12 @@ var updateCommand = async (opts) => {
|
|
|
903
991
|
allAppended.push(...r.appended);
|
|
904
992
|
}
|
|
905
993
|
}
|
|
994
|
+
if (manifest.settings?.claude) {
|
|
995
|
+
installClaudeSettings(basePath, manifest.settings.claude);
|
|
996
|
+
}
|
|
997
|
+
if (manifest.settings?.gemini) {
|
|
998
|
+
installGeminiSettings(basePath, manifest.settings.gemini);
|
|
999
|
+
}
|
|
906
1000
|
const newManifest = buildManifest({
|
|
907
1001
|
tools: manifest.tools,
|
|
908
1002
|
scope: manifest.scope,
|
|
@@ -911,21 +1005,25 @@ var updateCommand = async (opts) => {
|
|
|
911
1005
|
installedRules: manifest.installed_rules,
|
|
912
1006
|
installedFiles: allInstalledFiles.length > 0 ? allInstalledFiles : manifest.installed_files,
|
|
913
1007
|
appendedFiles: allAppended.length > 0 ? allAppended : manifest.appended_files,
|
|
1008
|
+
settings: manifest.settings ? {
|
|
1009
|
+
claude: manifest.settings.claude,
|
|
1010
|
+
gemini: manifest.settings.gemini
|
|
1011
|
+
} : void 0,
|
|
914
1012
|
sourceHash
|
|
915
1013
|
});
|
|
916
1014
|
writeManifest(manifestPath, newManifest);
|
|
917
1015
|
s.stop("\uADDC\uCE59 \uAC31\uC2E0 \uC644\uB8CC");
|
|
918
|
-
|
|
1016
|
+
p4.outro("ai-ops update \uC644\uB8CC");
|
|
919
1017
|
};
|
|
920
1018
|
|
|
921
1019
|
// src/commands/diff.ts
|
|
922
|
-
import * as
|
|
1020
|
+
import * as p5 from "@clack/prompts";
|
|
923
1021
|
var diffCommand = async () => {
|
|
924
1022
|
const basePath = resolveBasePath();
|
|
925
|
-
|
|
1023
|
+
p5.intro("ai-ops diff");
|
|
926
1024
|
const manifest = readManifest(resolveManifestPath(basePath));
|
|
927
1025
|
if (!manifest) {
|
|
928
|
-
|
|
1026
|
+
p5.log.error("manifest\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4. \uBA3C\uC800 ai-ops init\uC744 \uC2E4\uD589\uD558\uC138\uC694.");
|
|
929
1027
|
process.exit(1);
|
|
930
1028
|
}
|
|
931
1029
|
const sourceHash = computeSourceHash(resolveRulesDir());
|
|
@@ -935,27 +1033,27 @@ var diffCommand = async () => {
|
|
|
935
1033
|
currentSourceHash: sourceHash
|
|
936
1034
|
});
|
|
937
1035
|
if (result.status === "up-to-date") {
|
|
938
|
-
|
|
1036
|
+
p5.log.success("\uBCC0\uACBD \uC0AC\uD56D \uC5C6\uC74C. \uCD5C\uC2E0 \uC0C1\uD0DC\uC785\uB2C8\uB2E4.");
|
|
939
1037
|
} else {
|
|
940
1038
|
if (result.sourceChanged) {
|
|
941
|
-
|
|
1039
|
+
p5.log.warn(`\uC18C\uC2A4 \uBCC0\uACBD \uAC10\uC9C0: ${manifest.sourceHash} \u2192 ${sourceHash}`);
|
|
942
1040
|
}
|
|
943
1041
|
if (result.added.length > 0) {
|
|
944
|
-
|
|
1042
|
+
p5.log.info(`\uCD94\uAC00\uB41C \uADDC\uCE59: ${result.added.join(", ")}`);
|
|
945
1043
|
}
|
|
946
1044
|
if (result.removed.length > 0) {
|
|
947
|
-
|
|
1045
|
+
p5.log.info(`\uC81C\uAC70\uB41C \uADDC\uCE59: ${result.removed.join(", ")}`);
|
|
948
1046
|
}
|
|
949
1047
|
}
|
|
950
|
-
|
|
1048
|
+
p5.outro("ai-ops diff \uC644\uB8CC");
|
|
951
1049
|
};
|
|
952
1050
|
|
|
953
1051
|
// src/commands/uninstall.ts
|
|
954
|
-
import * as
|
|
1052
|
+
import * as p6 from "@clack/prompts";
|
|
955
1053
|
import { rmSync as rmSync2 } from "fs";
|
|
956
1054
|
|
|
957
1055
|
// src/lib/uninstall.ts
|
|
958
|
-
import { existsSync as
|
|
1056
|
+
import { existsSync as existsSync5, readFileSync as readFileSync7, rmSync, readdirSync as readdirSync4, writeFileSync as writeFileSync5 } from "fs";
|
|
959
1057
|
import { resolve as resolve6, dirname as dirname4 } from "path";
|
|
960
1058
|
var removeFiles = (basePath, relativePaths) => {
|
|
961
1059
|
const deleted = [];
|
|
@@ -964,15 +1062,15 @@ var removeFiles = (basePath, relativePaths) => {
|
|
|
964
1062
|
const notFound = [];
|
|
965
1063
|
for (const rel of relativePaths) {
|
|
966
1064
|
const absPath = resolve6(basePath, rel);
|
|
967
|
-
if (!
|
|
1065
|
+
if (!existsSync5(absPath)) {
|
|
968
1066
|
notFound.push(rel);
|
|
969
1067
|
continue;
|
|
970
1068
|
}
|
|
971
|
-
const content =
|
|
1069
|
+
const content = readFileSync7(absPath, "utf-8");
|
|
972
1070
|
if (!isManagedFile(content)) {
|
|
973
1071
|
if (hasAiOpsSection(content)) {
|
|
974
1072
|
const stripped = stripAiOpsSection(content);
|
|
975
|
-
|
|
1073
|
+
writeFileSync5(absPath, stripped, "utf-8");
|
|
976
1074
|
cleaned.push(rel);
|
|
977
1075
|
} else {
|
|
978
1076
|
skipped.push(rel);
|
|
@@ -988,7 +1086,7 @@ var cleanEmptyDirs = (basePath, dirs) => {
|
|
|
988
1086
|
const removed = [];
|
|
989
1087
|
for (const dir of dirs) {
|
|
990
1088
|
const absDir = resolve6(basePath, dir);
|
|
991
|
-
if (!
|
|
1089
|
+
if (!existsSync5(absDir)) continue;
|
|
992
1090
|
try {
|
|
993
1091
|
const entries = readdirSync4(absDir);
|
|
994
1092
|
if (entries.length === 0) {
|
|
@@ -1015,10 +1113,10 @@ var collectManagedDirs = (relativePaths) => {
|
|
|
1015
1113
|
var uninstallCommand = async () => {
|
|
1016
1114
|
const basePath = resolveBasePath();
|
|
1017
1115
|
const manifestPath = resolveManifestPath(basePath);
|
|
1018
|
-
|
|
1116
|
+
p6.intro("ai-ops uninstall");
|
|
1019
1117
|
const manifest = readManifest(manifestPath);
|
|
1020
1118
|
if (!manifest) {
|
|
1021
|
-
|
|
1119
|
+
p6.log.error("manifest\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4. \uBA3C\uC800 ai-ops init\uC744 \uC2E4\uD589\uD558\uC138\uC694.");
|
|
1022
1120
|
process.exit(1);
|
|
1023
1121
|
}
|
|
1024
1122
|
const targetFiles = [
|
|
@@ -1026,18 +1124,18 @@ var uninstallCommand = async () => {
|
|
|
1026
1124
|
...manifest.appended_files ?? []
|
|
1027
1125
|
];
|
|
1028
1126
|
if (targetFiles.length === 0) {
|
|
1029
|
-
|
|
1030
|
-
|
|
1127
|
+
p6.log.warn("\uC0AD\uC81C\uD560 \uD30C\uC77C\uC774 \uC5C6\uC2B5\uB2C8\uB2E4.");
|
|
1128
|
+
p6.outro("ai-ops uninstall \uC644\uB8CC");
|
|
1031
1129
|
return;
|
|
1032
1130
|
}
|
|
1033
|
-
|
|
1131
|
+
p6.log.info(`\uC0AD\uC81C \uB300\uC0C1 \uD30C\uC77C (${targetFiles.length}\uAC1C):
|
|
1034
1132
|
${targetFiles.map((f) => ` ${f}`).join("\n")}`);
|
|
1035
|
-
const confirmed = await
|
|
1133
|
+
const confirmed = await p6.confirm({
|
|
1036
1134
|
message: "\uC704 \uD30C\uC77C\uACFC manifest\uB97C \uBAA8\uB450 \uC0AD\uC81C\uD558\uC2DC\uACA0\uC2B5\uB2C8\uAE4C?",
|
|
1037
1135
|
initialValue: false
|
|
1038
1136
|
});
|
|
1039
|
-
if (
|
|
1040
|
-
|
|
1137
|
+
if (p6.isCancel(confirmed) || !confirmed) {
|
|
1138
|
+
p6.cancel("\uCDE8\uC18C\uB428");
|
|
1041
1139
|
process.exit(0);
|
|
1042
1140
|
}
|
|
1043
1141
|
const result = removeFiles(basePath, targetFiles);
|
|
@@ -1045,31 +1143,31 @@ ${targetFiles.map((f) => ` ${f}`).join("\n")}`);
|
|
|
1045
1143
|
const removedDirs = cleanEmptyDirs(basePath, dirs);
|
|
1046
1144
|
rmSync2(manifestPath, { force: true });
|
|
1047
1145
|
if (result.deleted.length > 0) {
|
|
1048
|
-
|
|
1146
|
+
p6.log.success(`\uC0AD\uC81C \uC644\uB8CC (${result.deleted.length}\uAC1C):
|
|
1049
1147
|
${result.deleted.map((f) => ` ${f}`).join("\n")}`);
|
|
1050
1148
|
}
|
|
1051
1149
|
if (result.cleaned.length > 0) {
|
|
1052
|
-
|
|
1150
|
+
p6.log.success(
|
|
1053
1151
|
`\uC139\uC158 \uC81C\uAC70 \uC644\uB8CC (\uC0AC\uC6A9\uC790 \uB0B4\uC6A9 \uBCF4\uC874, ${result.cleaned.length}\uAC1C):
|
|
1054
1152
|
${result.cleaned.map((f) => ` ${f}`).join("\n")}`
|
|
1055
1153
|
);
|
|
1056
1154
|
}
|
|
1057
1155
|
if (result.skipped.length > 0) {
|
|
1058
|
-
|
|
1156
|
+
p6.log.warn(
|
|
1059
1157
|
`\uAC74\uB108\uB700 (non-managed \uD30C\uC77C \uBCF4\uD638, ${result.skipped.length}\uAC1C):
|
|
1060
1158
|
${result.skipped.map((f) => ` ${f}`).join("\n")}`
|
|
1061
1159
|
);
|
|
1062
1160
|
}
|
|
1063
1161
|
if (result.notFound.length > 0) {
|
|
1064
|
-
|
|
1162
|
+
p6.log.info(`\uC774\uBBF8 \uC5C6\uC74C (${result.notFound.length}\uAC1C):
|
|
1065
1163
|
${result.notFound.map((f) => ` ${f}`).join("\n")}`);
|
|
1066
1164
|
}
|
|
1067
1165
|
if (removedDirs.length > 0) {
|
|
1068
|
-
|
|
1166
|
+
p6.log.info(`\uBE48 \uB514\uB809\uD1A0\uB9AC \uC815\uB9AC (${removedDirs.length}\uAC1C):
|
|
1069
1167
|
${removedDirs.map((d) => ` ${d}`).join("\n")}`);
|
|
1070
1168
|
}
|
|
1071
|
-
|
|
1072
|
-
|
|
1169
|
+
p6.log.success(`manifest \uC0AD\uC81C: ${MANIFEST_FILENAME}`);
|
|
1170
|
+
p6.outro("ai-ops uninstall \uC644\uB8CC");
|
|
1073
1171
|
};
|
|
1074
1172
|
|
|
1075
1173
|
// src/bin/index.ts
|
package/dist/bin/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/bin/index.ts","../../src/commands/init.ts","../../src/core/schemas/rule.schema.ts","../../src/core/schemas/preset.schema.ts","../../src/core/schemas/manifest.schema.ts","../../src/core/loader.ts","../../src/core/renderer.ts","../../src/core/tool-output.ts","../../src/core/source-hash.ts","../../src/core/managed-header.ts","../../src/core/manifest-io.ts","../../src/core/diff.ts","../../src/core/install-plan.ts","../../src/core/uninstall-plan.ts","../../src/core/paths.ts","../../src/lib/paths.ts","../../src/lib/workspace.ts","../../src/lib/install.ts","../../src/lib/gemini-settings.ts","../../src/commands/update.ts","../../src/commands/diff.ts","../../src/commands/uninstall.ts","../../src/lib/uninstall.ts"],"sourcesContent":["import { Command } from 'commander';\nimport { initCommand } from '../commands/init.js';\nimport { updateCommand } from '../commands/update.js';\nimport { diffCommand } from '../commands/diff.js';\nimport { uninstallCommand } from '../commands/uninstall.js';\n\nconst program = new Command();\n\nconst ensureNoDeprecatedScopeFlag = (argv: readonly string[]): void => {\n if (argv.some((arg) => arg === '--scope' || arg.startsWith('--scope='))) {\n console.error('`--scope` is no longer supported. ai-ops is now project-only.');\n process.exit(1);\n }\n};\n\nprogram.name('ai-ops').description('AI 에이전트 규칙 스캐폴더').version('0.1.0');\n\nprogram\n .command('init')\n .description('AI 규칙 초기 설치')\n .action(() => initCommand());\n\nprogram\n .command('update')\n .description('기존 manifest 기반 규칙 갱신')\n .option('--force', '변경 없어도 강제 재설치', false)\n .action((opts: { force: boolean }) => updateCommand(opts));\n\nprogram\n .command('diff')\n .description('설치된 규칙과 최신 소스 비교')\n .action(() => diffCommand());\n\nprogram\n .command('uninstall')\n .description('설치된 규칙 파일 및 manifest 제거')\n .action(() => uninstallCommand());\n\nensureNoDeprecatedScopeFlag(process.argv);\nprogram.parse();\n","import * as p from '@clack/prompts';\nimport { join } from 'node:path';\nimport type { Rule, Preset, ToolId, WorkspaceMapping } from '@/core/index.js';\nimport {\n loadAllRules,\n loadPresets,\n resolvePresetRules,\n resolvePresetRuleGroups,\n isGlobalRule,\n partitionRules,\n renderForTool,\n renderRulesToMarkdown,\n buildInstallPlan,\n buildManifest,\n computeSourceHash,\n resolveManifestPath,\n writeManifest,\n wrapWithHeader,\n TOOL_OUTPUT_MAP,\n} from '@/core/index.js';\nimport type { FileAction } from '@/core/index.js';\nimport { resolveBasePath, resolveRulesDir, resolvePresetsPath } from '../lib/paths.js';\nimport { listWorkspaceCandidates } from '../lib/workspace.js';\nimport { installFiles } from '../lib/install.js';\nimport { promptGeminiSettings, installGeminiSettings } from '../lib/gemini-settings.js';\n\ntype WorkspacePresetMapping = {\n workspace: string;\n preset: Preset;\n finalRules: Rule[];\n};\n\ntype InstallStats = { written: string[]; appended: string[] };\n\nconst TOOL_OPTIONS = [\n { value: 'claude-code' as ToolId, label: 'Claude Code' },\n { value: 'codex' as ToolId, label: 'Codex' },\n { value: 'gemini' as ToolId, label: 'Gemini CLI' },\n];\n\nconst deduplicateRules = (rules: readonly Rule[]): Rule[] => {\n const seen = new Set<string>();\n return rules.filter((r) => {\n if (seen.has(r.id)) return false;\n seen.add(r.id);\n return true;\n });\n};\n\nconst selectPresetAndFineTune = async (\n workspaceName: string,\n presets: readonly Preset[],\n allRules: readonly Rule[],\n): Promise<WorkspacePresetMapping | null> => {\n const preset = await p.select<Preset>({\n message: `[${workspaceName}] 프리셋을 선택하세요`,\n options: presets.map((pr) => ({\n value: pr,\n label: pr.id,\n hint: pr.description,\n })),\n });\n if (p.isCancel(preset)) return null;\n\n const presetRuleGroups = resolvePresetRuleGroups(preset, allRules);\n const globalGroups = presetRuleGroups.filter((group) => group.rules.every(isGlobalRule));\n const domainGroups = presetRuleGroups.filter((group) => !group.rules.every(isGlobalRule));\n const globalGroupIds = globalGroups.map((group) => group.id);\n const globalRules =\n globalGroupIds.length > 0 ? resolvePresetRules({ ...preset, rules: globalGroupIds }, allRules) : [];\n\n // Global rules: locked (항상 포함)\n if (globalRules.length > 0) {\n p.note(globalRules.map((r) => ` ✓ ${r.id}`).join('\\n'), `[${workspaceName}] 기본 규칙 (잠금)`);\n }\n\n if (domainGroups.length === 0) {\n return { workspace: workspaceName, preset, finalRules: resolvePresetRules(preset, allRules) };\n }\n\n // Domain rules: 제외 가능\n const selectedDomain = await p.multiselect<string>({\n message: `[${workspaceName}] 도메인 규칙 선택 (해제하여 제외)`,\n options: domainGroups.map((group) => ({ value: group.id, label: group.id })),\n initialValues: domainGroups.map((group) => group.id),\n required: false,\n });\n if (p.isCancel(selectedDomain)) return null;\n\n const selectedLogicalRuleIds = [...globalGroupIds, ...(selectedDomain as string[])];\n return {\n workspace: workspaceName,\n preset,\n finalRules: resolvePresetRules({ ...preset, rules: selectedLogicalRuleIds }, allRules),\n };\n};\n\nconst installHierarchicalMonorepo = (\n toolId: 'codex' | 'gemini',\n mappings: readonly WorkspacePresetMapping[],\n basePath: string,\n meta: { sourceHash: string; generatedAt: string },\n): InstallStats => {\n const config = TOOL_OUTPUT_MAP[toolId];\n const written: string[] = [];\n const appended: string[] = [];\n\n const allRules = deduplicateRules(mappings.flatMap((m) => m.finalRules));\n const { global } = partitionRules(allRules);\n\n if (global.length > 0) {\n const rootAction: FileAction = {\n relativePath: join(config.dir, config.rootFileName),\n content: wrapWithHeader(renderRulesToMarkdown(global), meta),\n };\n const r = installFiles(basePath, [rootAction], meta);\n written.push(...r.written);\n appended.push(...r.appended);\n }\n\n for (const mapping of mappings) {\n const { domain } = partitionRules(mapping.finalRules);\n if (domain.length === 0) continue;\n\n const domainAction: FileAction = {\n relativePath: join(mapping.workspace, config.domainFileName),\n content: wrapWithHeader(renderRulesToMarkdown(domain), meta),\n };\n const r = installFiles(basePath, [domainAction], meta);\n written.push(...r.written);\n appended.push(...r.appended);\n }\n\n return { written, appended };\n};\n\nconst installClaudeCodeMonorepo = (\n mappings: readonly WorkspacePresetMapping[],\n basePath: string,\n meta: { sourceHash: string; generatedAt: string },\n): InstallStats => {\n const allRules = deduplicateRules(mappings.flatMap((m) => m.finalRules));\n const workspaceMappings: WorkspaceMapping[] = mappings.map((m) => ({\n path: m.workspace,\n ruleIds: m.finalRules.map((r) => r.id),\n }));\n const renderResult = renderForTool('claude-code', allRules, workspaceMappings);\n const actions = buildInstallPlan({ toolId: 'claude-code', renderResult, meta });\n const r = installFiles(basePath, actions, meta);\n return { written: r.written, appended: r.appended };\n};\n\nexport const initCommand = async (): Promise<void> => {\n const basePath = resolveBasePath();\n const rulesDir = resolveRulesDir();\n\n p.intro('ai-ops init');\n\n // 1. AI 도구 다중 선택\n const selectedTools = await p.multiselect<ToolId>({\n message: 'AI 도구를 선택하세요',\n options: TOOL_OPTIONS,\n required: true,\n });\n if (p.isCancel(selectedTools)) {\n p.cancel('취소됨');\n process.exit(0);\n }\n\n // 2. 모노레포 여부\n const isMonorepo = await p.confirm({\n message: '모노레포 프로젝트입니까?',\n initialValue: false,\n });\n if (p.isCancel(isMonorepo)) {\n p.cancel('취소됨');\n process.exit(0);\n }\n\n // 3. 데이터 로드\n const allRules = loadAllRules(rulesDir);\n const presets = loadPresets(resolvePresetsPath());\n const sourceHash = computeSourceHash(rulesDir);\n\n // 4. 워크스페이스별 preset 선택 + fine-tune\n const mappings: WorkspacePresetMapping[] = [];\n\n if (!isMonorepo) {\n const mapping = await selectPresetAndFineTune('.', presets, allRules);\n if (!mapping) {\n p.cancel('취소됨');\n process.exit(0);\n }\n mappings.push(mapping);\n } else {\n const candidates = listWorkspaceCandidates(basePath);\n const selectedWorkspaces = await p.multiselect<string>({\n message: '워크스페이스를 선택하세요',\n options: candidates.map((c) => ({ value: c, label: c })),\n required: true,\n });\n if (p.isCancel(selectedWorkspaces)) {\n p.cancel('취소됨');\n process.exit(0);\n }\n\n for (const ws of selectedWorkspaces as string[]) {\n const mapping = await selectPresetAndFineTune(ws, presets, allRules);\n if (!mapping) {\n p.cancel('취소됨');\n process.exit(0);\n }\n mappings.push(mapping);\n }\n }\n\n // 4.5. Gemini 설정 (gemini 선택 시)\n const geminiSettingValues: readonly string[] | null = (selectedTools as ToolId[]).includes('gemini')\n ? await promptGeminiSettings()\n : null;\n\n // 5. 설치\n const s = p.spinner();\n s.start('규칙 설치 중...');\n\n const meta = { sourceHash, generatedAt: new Date().toISOString() };\n const allInstalledFiles: string[] = [];\n const allAppended: string[] = [];\n\n for (const toolId of selectedTools as ToolId[]) {\n if (isMonorepo) {\n if (toolId === 'claude-code') {\n const stats = installClaudeCodeMonorepo(mappings, basePath, meta);\n allInstalledFiles.push(...stats.written);\n allAppended.push(...stats.appended);\n } else {\n const stats = installHierarchicalMonorepo(toolId, mappings, basePath, meta);\n allInstalledFiles.push(...stats.written);\n allAppended.push(...stats.appended);\n }\n } else {\n const renderResult = renderForTool(toolId, mappings[0].finalRules);\n const actions = buildInstallPlan({ toolId, renderResult, meta });\n const result = installFiles(basePath, actions, meta);\n allInstalledFiles.push(...result.written);\n allAppended.push(...result.appended);\n }\n }\n\n if (geminiSettingValues && geminiSettingValues.length > 0) {\n installGeminiSettings(basePath, geminiSettingValues);\n allInstalledFiles.push('.gemini/settings.json');\n }\n\n s.stop('규칙 설치 완료');\n\n // 6. Manifest 저장\n const allInstalledRuleIds = deduplicateRules(mappings.flatMap((m) => m.finalRules)).map((r) => r.id);\n\n const workspacesRecord = isMonorepo\n ? Object.fromEntries(\n mappings.map((m) => [m.workspace, { preset: m.preset.id, rules: m.finalRules.map((r) => r.id) }]),\n )\n : undefined;\n\n const manifest = buildManifest({\n tools: selectedTools as string[],\n scope: 'project',\n preset: !isMonorepo ? mappings[0].preset.id : undefined,\n workspaces: workspacesRecord,\n installedRules: allInstalledRuleIds,\n installedFiles: allInstalledFiles,\n appendedFiles: allAppended,\n sourceHash,\n });\n writeManifest(resolveManifestPath(basePath), manifest);\n\n // 7. 결과 요약\n if (allAppended.length > 0) {\n p.log.info(`기존 파일에 섹션 추가됨 (내용 보존):\\n${allAppended.map((f) => ` ${f}`).join('\\n')}`);\n }\n p.log.success(`설치된 규칙: ${allInstalledRuleIds.length}개`);\n p.outro('ai-ops init 완료');\n};\n","/**\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} 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.literal('project'),\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 /** 실제 디스크에 쓰여진 파일 상대 경로 목록 (uninstall용). 기존 manifest 호환성 위해 optional */\n installed_files: z.array(z.string().min(1)).optional(),\n /** non-managed 파일에 섹션을 append한 경우 추적 (uninstall 시 섹션만 제거) */\n appended_files: z.array(z.string().min(1)).optional(),\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\ntype PresetRuleBundles = Readonly<Record<string, Readonly<Record<string, readonly string[]>>>>;\n\nexport const PRESET_RULE_BUNDLES: PresetRuleBundles = {\n 'frontend-web': {\n graphql: ['graphql-core', 'graphql-client-web'],\n },\n 'frontend-app': {\n graphql: ['graphql-core', 'graphql-client-app'],\n },\n 'backend-ts': {\n graphql: ['graphql-core', 'graphql-server'],\n },\n} as const;\n\nexport type PresetRuleGroup = {\n id: string;\n rules: Rule[];\n};\n\n// priority 내림차순 정렬 (높을수록 상단 → U-shaped attention)\nexport const sortRulesByPriority = (rules: readonly Rule[]): Rule[] =>\n [...rules].sort((a, b) => b.priority - a.priority);\n\nconst deduplicateRulesById = (rules: readonly Rule[]): Rule[] => {\n const seen = new Set<string>();\n return rules.filter((rule) => {\n if (seen.has(rule.id)) return false;\n seen.add(rule.id);\n return true;\n });\n};\n\nconst resolveBundledRuleIds = (presetId: string, logicalRuleId: string): readonly string[] => {\n const presetBundles = PRESET_RULE_BUNDLES[presetId];\n if (!presetBundles) return [logicalRuleId];\n return presetBundles[logicalRuleId] ?? [logicalRuleId];\n};\n\nconst resolveRuleById = (ruleId: string, allRules: readonly Rule[], context?: string): Rule => {\n const found = allRules.find((rule) => rule.id === ruleId);\n if (!found) {\n const suffix = context ? ` (from ${context})` : '';\n throw new Error(`Rule not found: ${ruleId}${suffix}`);\n }\n return found;\n};\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\nexport const resolvePresetRuleGroups = (preset: Preset, allRules: readonly Rule[]): PresetRuleGroup[] =>\n preset.rules.map((logicalRuleId) => {\n const bundledRuleIds = resolveBundledRuleIds(preset.id, logicalRuleId);\n const rules = bundledRuleIds.map((ruleId) => resolveRuleById(ruleId, allRules, `${preset.id}:${logicalRuleId}`));\n return { id: logicalRuleId, rules };\n });\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 포함) 목록을 실제 rule로 확장 + priority 정렬, 누락 시 throw\nexport const resolvePresetRules = (preset: Preset, allRules: readonly Rule[]): Rule[] => {\n const groups = resolvePresetRuleGroups(preset, allRules);\n const resolved = deduplicateRulesById(groups.flatMap((group) => group.rules));\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 문자 | escape)\nexport const renderDecisionTable = (entries: readonly DecisionTableEntry[]): string => {\n const escape = (s: string) => s.replace(/\\|/g, '|');\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-core': ['**/*.graphql', '**/*.gql'],\n 'graphql-client-web': ['**/*.graphql', '**/*.gql', '**/*.tsx', '**/*.ts'],\n 'graphql-client-app': ['**/*.graphql', '**/*.gql', 'lib/**/*.dart'],\n 'graphql-server': ['**/*.graphql', '**/*.gql', '**/*.resolver.ts'],\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: '',\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';\n preset?: string;\n workspaces?: Record<string, { preset: string; rules: string[] }>;\n installedRules: readonly string[];\n installedFiles?: readonly string[];\n appendedFiles?: 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 installed_files: params.installedFiles ? [...params.installedFiles] : undefined,\n appended_files: params.appendedFiles && params.appendedFiles.length > 0 ? [...params.appendedFiles] : undefined,\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\nconst SECTION_START = '<!-- ai-ops:start -->';\nconst SECTION_END = '<!-- ai-ops:end -->';\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\nexport const wrapWithSection = (content: string, meta: { sourceHash: string; generatedAt: string }): string => {\n const metaLine = `<!-- sourceHash: ${meta.sourceHash} | generatedAt: ${meta.generatedAt} -->`;\n return `${SECTION_START}\\n${metaLine}\\n\\n${content}\\n${SECTION_END}`;\n};\n\nexport const hasAiOpsSection = (content: string): boolean =>\n content.includes(SECTION_START) && content.includes(SECTION_END);\n\nexport const stripAiOpsSection = (content: string): string => {\n const startIdx = content.indexOf(SECTION_START);\n const endIdx = content.indexOf(SECTION_END);\n if (startIdx === -1 || endIdx === -1) return content;\n\n const before = content.slice(0, startIdx).trimEnd();\n const after = content.slice(endIdx + SECTION_END.length).trimStart();\n return before + (after ? '\\n\\n' + after : '') + '\\n';\n};\n\nexport const replaceAiOpsSection = (existing: string, newSection: string): string => {\n const startIdx = existing.indexOf(SECTION_START);\n const endIdx = existing.indexOf(SECTION_END);\n if (startIdx === -1 || endIdx === -1) return existing;\n\n const before = existing.slice(0, startIdx).trimEnd();\n const after = existing.slice(endIdx + SECTION_END.length).trimStart();\n return before + '\\n\\n' + newSection + (after ? '\\n\\n' + after : '') + '\\n';\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\n// Codex has no settings.json — plan directory convention must live in AGENTS.md\nconst CODEX_PLAN_SECTION =\n '\\n\\n---\\n\\n## Plan\\n\\nSave plans to `.codex/plans/<timestamp>-<topic>.md` when creating or updating plans in plan mode.';\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 const rootContent = toolId === 'codex' ? renderResult.rootContent + CODEX_PLAN_SECTION : renderResult.rootContent;\n actions.push({\n relativePath: join(config.dir, config.rootFileName),\n content: wrapWithHeader(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 { join } from 'node:path';\nimport { TOOL_OUTPUT_MAP } from './tool-output.js';\nimport type { Manifest } from './schemas/index.js';\n\n/**\n * manifest에 installed_files가 없는 구버전 manifest를 위한 fallback.\n * manifest의 tools/workspaces/installed_rules 정보를 기반으로\n * 실제 설치됐을 파일 경로를 역산한다.\n */\nexport const inferInstalledFiles = (manifest: Manifest): string[] => {\n const files: string[] = [];\n const isMonorepo = manifest.workspaces !== undefined;\n\n for (const toolId of manifest.tools) {\n if (toolId === 'claude-code') {\n // claude-code: .claude/rules/{ruleId}.md\n const config = TOOL_OUTPUT_MAP['claude-code'];\n for (const ruleId of manifest.installed_rules) {\n files.push(join(config.rulesDir, `${ruleId}${config.fileExtension}`));\n }\n } else if (toolId === 'codex') {\n const config = TOOL_OUTPUT_MAP['codex'];\n if (!isMonorepo) {\n // 비모노: .codex/AGENTS.md + .codex/AGENTS.override.md (domain 있으면)\n files.push(join(config.dir, config.rootFileName));\n files.push(join(config.dir, config.domainFileName));\n } else {\n // 모노: .codex/AGENTS.md (global) + {workspace}/AGENTS.override.md (domain)\n files.push(join(config.dir, config.rootFileName));\n for (const ws of Object.keys(manifest.workspaces ?? {})) {\n files.push(join(ws, config.domainFileName));\n }\n }\n } else if (toolId === 'gemini') {\n const config = TOOL_OUTPUT_MAP['gemini'];\n if (!isMonorepo) {\n // 비모노: .gemini/GEMINI.md\n files.push(join(config.dir, config.rootFileName));\n } else {\n // 모노: .gemini/GEMINI.md (global) + {workspace}/GEMINI.md (domain)\n files.push(join(config.dir, config.rootFileName));\n for (const ws of Object.keys(manifest.workspaces ?? {})) {\n files.push(join(ws, config.domainFileName));\n }\n }\n }\n }\n\n // 중복 제거 (codex 비모노에서 rootFileName === domainFileName인 경우 대비)\n return [...new Set(files)];\n};\n","import { dirname, resolve } from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\n// src/core/* 또는 dist/bin/index.js 기준에서도 공통으로 패키지 루트/data를 가리키도록 계산\n// src/core/paths.ts → ../../data = apps/cli/data\n// dist/bin/index.js (bundle) → ../../data = apps/cli/data\nconst __dirname = dirname(fileURLToPath(import.meta.url));\n\nexport const COMPILER_DATA_DIR = resolve(__dirname, '..', '..', 'data');\n","import { join } from 'node:path';\nimport { COMPILER_DATA_DIR } from '@/core/index.js';\n\nexport const resolveCompilerDataDir = (): string => COMPILER_DATA_DIR;\n\nexport const resolveRulesDir = (): string => join(COMPILER_DATA_DIR, 'rules');\n\nexport const resolvePresetsPath = (): string => join(COMPILER_DATA_DIR, 'presets.yaml');\n\n// project-only 설치 기준 디렉토리\nexport const resolveBasePath = (): string => process.cwd();\n","import { existsSync, readdirSync, statSync } from 'node:fs';\nimport { join, resolve } from 'node:path';\n\nconst EXCLUDE_DIRS = new Set(['node_modules', '.git', 'dist', 'build', '.next', '.turbo', '.cache', 'coverage']);\n\nconst isVisibleDir = (basePath: string, name: string): boolean => {\n if (name.startsWith('.') || EXCLUDE_DIRS.has(name)) return false;\n return statSync(resolve(basePath, name)).isDirectory();\n};\n\n// Project manifest files that indicate a workspace root\nconst PROJECT_MANIFESTS = [\n 'package.json', // Node.js / JS / TS\n 'pubspec.yaml', // Flutter / Dart\n 'pyproject.toml', // Python (modern)\n 'setup.py', // Python (legacy)\n 'Cargo.toml', // Rust\n 'go.mod', // Go\n];\n\nconst isWorkspaceRoot = (dirPath: string): boolean => PROJECT_MANIFESTS.some((f) => existsSync(join(dirPath, f)));\n\n// 프로젝트 매니페스트 파일 존재 여부로 워크스페이스 판별:\n// 1. top-level dir에 매니페스트 → 그 자체가 워크스페이스 (e.g. backend-ts, mobile, web)\n// 2. top-level dir에 매니페스트 없고 자식에 있음 → 자식을 후보로 (e.g. apps/web, packages/ui)\n// 3. 매니페스트 없는 경우 → 1-depth 그대로\nexport const listWorkspaceCandidates = (basePath: string): string[] => {\n const topLevel = readdirSync(basePath).filter((name) => isVisibleDir(basePath, name));\n\n const candidates: string[] = [];\n for (const dir of topLevel) {\n const subPath = resolve(basePath, dir);\n if (isWorkspaceRoot(subPath)) {\n candidates.push(dir);\n } else {\n const children = readdirSync(subPath).filter((name) => isVisibleDir(subPath, name));\n const wsChildren = children.filter((name) => isWorkspaceRoot(resolve(subPath, name)));\n if (wsChildren.length > 0) {\n for (const child of wsChildren) {\n candidates.push(join(dir, child));\n }\n } else {\n candidates.push(dir);\n }\n }\n }\n\n return candidates.sort();\n};\n","import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';\nimport { dirname, resolve } from 'node:path';\nimport {\n isManagedFile,\n hasAiOpsSection,\n wrapWithSection,\n replaceAiOpsSection,\n stripManagedHeader,\n} from '@/core/index.js';\nimport type { FileAction } from '@/core/index.js';\n\nexport type InstallResult = {\n written: string[];\n appended: string[]; // 기존 non-managed 파일에 섹션 추가됨\n skipped: string[]; // 더 이상 발생하지 않음 (하위 호환용)\n};\n\nexport const installFiles = (\n basePath: string,\n actions: readonly FileAction[],\n meta: { sourceHash: string; generatedAt: string },\n): InstallResult => {\n const written: string[] = [];\n const appended: string[] = [];\n const skipped: string[] = [];\n\n for (const action of actions) {\n const absPath = resolve(basePath, action.relativePath);\n\n if (existsSync(absPath)) {\n const existing = readFileSync(absPath, 'utf-8');\n\n if (isManagedFile(existing)) {\n writeFileSync(absPath, action.content, 'utf-8');\n written.push(action.relativePath);\n } else if (hasAiOpsSection(existing)) {\n // 이전에 append된 파일 → 섹션만 교체\n const sectionContent = wrapWithSection(stripManagedHeader(action.content), meta);\n const updated = replaceAiOpsSection(existing, sectionContent);\n writeFileSync(absPath, updated, 'utf-8');\n appended.push(action.relativePath);\n } else {\n // non-managed, 섹션 없음 → 최초 append\n const sectionContent = wrapWithSection(stripManagedHeader(action.content), meta);\n const updated = existing.trimEnd() + '\\n\\n' + sectionContent + '\\n';\n writeFileSync(absPath, updated, 'utf-8');\n appended.push(action.relativePath);\n }\n } else {\n mkdirSync(dirname(absPath), { recursive: true });\n writeFileSync(absPath, action.content, 'utf-8');\n written.push(action.relativePath);\n }\n }\n\n return { written, appended, skipped };\n};\n","import * as p from '@clack/prompts';\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';\nimport { join } from 'node:path';\n\ntype GeminiSettings = {\n ui?: { showLineNumbers?: boolean };\n general?: {\n plan?: { directory?: string; modelRouting?: boolean };\n sessionRetention?: { maxAge?: string };\n };\n experimental?: { jitContext?: boolean; plan?: boolean };\n};\n\ntype SettingGroup = {\n value: string;\n label: string;\n hint: string;\n patch: GeminiSettings;\n};\n\nconst SETTING_GROUPS: readonly SettingGroup[] = [\n {\n value: 'ui',\n label: 'UI — 줄 번호 숨기기',\n hint: 'ui.showLineNumbers: false — 코드 복사 시 줄 번호가 포함되지 않도록 비활성화',\n patch: { ui: { showLineNumbers: false } },\n },\n {\n value: 'plan',\n label: 'Plan — 계획 파일 저장 및 모델 라우팅',\n hint: 'general.plan.directory: .gemini/plans, modelRouting: true — AI 계획을 파일로 저장하고 태스크별 최적 모델 자동 선택',\n patch: { general: { plan: { directory: '.gemini/plans', modelRouting: true } } },\n },\n {\n value: 'sessionRetention',\n label: 'Session Retention — 세션 30일 보존',\n hint: 'general.sessionRetention.maxAge: 30d — 이전 대화 컨텍스트를 30일간 유지',\n patch: { general: { sessionRetention: { maxAge: '30d' } } },\n },\n {\n value: 'experimental',\n label: 'Experimental — JIT 컨텍스트 + Plan 기능',\n hint: 'experimental.jitContext: true, plan: true — 서브디렉토리 컨텍스트 지연 로딩 및 계획 기능 실험적 활성화',\n patch: { experimental: { jitContext: true, plan: true } },\n },\n];\n\nconst deepMerge = (base: Record<string, unknown>, patch: Record<string, unknown>): Record<string, unknown> => {\n const result = { ...base };\n for (const [key, value] of Object.entries(patch)) {\n if (\n value !== null &&\n typeof value === 'object' &&\n !Array.isArray(value) &&\n typeof result[key] === 'object' &&\n result[key] !== null\n ) {\n result[key] = deepMerge(result[key] as Record<string, unknown>, value as Record<string, unknown>);\n } else {\n result[key] = value;\n }\n }\n return result;\n};\n\n// null → 건너뜀 (취소 또는 \"No\"), string[] → 선택된 항목\nexport const promptGeminiSettings = async (): Promise<readonly string[] | null> => {\n const wantSettings = await p.confirm({\n message: 'Gemini CLI 설정 파일(.gemini/settings.json)을 설치하시겠습니까?',\n initialValue: true,\n });\n if (p.isCancel(wantSettings) || !wantSettings) return null;\n\n const selected = await p.multiselect<string>({\n message: '설치할 설정 항목을 선택하세요 (스페이스로 토글)',\n options: SETTING_GROUPS.map((g) => ({\n value: g.value,\n label: g.label,\n hint: g.hint,\n })),\n initialValues: SETTING_GROUPS.map((g) => g.value),\n required: false,\n });\n if (p.isCancel(selected)) return null;\n return selected as string[];\n};\n\nexport const installGeminiSettings = (basePath: string, selectedValues: readonly string[]): void => {\n if (selectedValues.length === 0) return;\n\n const settingsDir = join(basePath, '.gemini');\n const settingsPath = join(settingsDir, 'settings.json');\n\n let existing: GeminiSettings = {};\n if (existsSync(settingsPath)) {\n try {\n existing = JSON.parse(readFileSync(settingsPath, 'utf-8')) as GeminiSettings;\n } catch {\n // parse 실패 시 덮어쓰기\n }\n }\n\n let merged: GeminiSettings = existing;\n for (const val of selectedValues) {\n const group = SETTING_GROUPS.find((g) => g.value === val);\n if (!group) continue;\n merged = deepMerge(merged as Record<string, unknown>, group.patch as Record<string, unknown>) as GeminiSettings;\n }\n\n mkdirSync(settingsDir, { recursive: true });\n writeFileSync(settingsPath, JSON.stringify(merged, null, 2) + '\\n', 'utf-8');\n};\n","import * as p from '@clack/prompts';\nimport type { ToolId } from '@/core/index.js';\nimport {\n readManifest,\n resolveManifestPath,\n loadAllRules,\n renderForTool,\n buildInstallPlan,\n buildManifest,\n writeManifest,\n computeSourceHash,\n computeDiff,\n partitionRules,\n renderRulesToMarkdown,\n wrapWithHeader,\n TOOL_OUTPUT_MAP,\n} from '@/core/index.js';\nimport type { FileAction } from '@/core/index.js';\nimport { join } from 'node:path';\nimport { resolveBasePath, resolveRulesDir } from '../lib/paths.js';\nimport { installFiles } from '../lib/install.js';\n\nexport const updateCommand = async (opts: { force: boolean }): Promise<void> => {\n const basePath = resolveBasePath();\n const manifestPath = resolveManifestPath(basePath);\n\n p.intro('ai-ops update');\n\n const manifest = readManifest(manifestPath);\n if (!manifest) {\n p.log.error('manifest가 없습니다. 먼저 ai-ops init을 실행하세요.');\n process.exit(1);\n }\n\n const rulesDir = resolveRulesDir();\n const sourceHash = computeSourceHash(rulesDir);\n\n const diffResult = computeDiff({\n previous: manifest,\n currentRules: manifest.installed_rules,\n currentSourceHash: sourceHash,\n });\n\n if (diffResult.status === 'up-to-date' && !opts.force) {\n p.log.info('변경 사항이 없습니다.');\n p.outro('ai-ops update 완료');\n return;\n }\n\n const s = p.spinner();\n s.start('규칙 갱신 중...');\n\n const allRules = loadAllRules(rulesDir);\n const meta = { sourceHash, generatedAt: new Date().toISOString() };\n const allInstalledFiles: string[] = [];\n const allAppended: string[] = [];\n\n if (manifest.workspaces) {\n // 모노레포: workspaces 기반 재설치\n const workspaceEntries = Object.entries(manifest.workspaces);\n\n for (const toolIdStr of manifest.tools) {\n const toolId = toolIdStr as ToolId;\n\n if (toolId === 'claude-code') {\n const allInstalledRuleSet = new Set(manifest.installed_rules);\n const rulesToInstall = allRules.filter((r) => allInstalledRuleSet.has(r.id));\n const workspaceMappings = workspaceEntries.map(([path, entry]) => ({\n path,\n ruleIds: entry.rules,\n }));\n const renderResult = renderForTool('claude-code', rulesToInstall, workspaceMappings);\n const actions = buildInstallPlan({ toolId: 'claude-code', renderResult, meta });\n const r = installFiles(basePath, actions, meta);\n allInstalledFiles.push(...r.written);\n allAppended.push(...r.appended);\n } else {\n // codex/gemini: global → 루트, domain → 워크스페이스별\n const config = TOOL_OUTPUT_MAP[toolId];\n\n const allInstalledRuleSet = new Set(manifest.installed_rules);\n const allRulesToInstall = allRules.filter((r) => allInstalledRuleSet.has(r.id));\n const { global } = partitionRules(allRulesToInstall);\n\n if (global.length > 0) {\n const rootAction: FileAction = {\n relativePath: join(config.dir, config.rootFileName),\n content: wrapWithHeader(renderRulesToMarkdown(global), meta),\n };\n const r = installFiles(basePath, [rootAction], meta);\n allInstalledFiles.push(...r.written);\n allAppended.push(...r.appended);\n }\n\n for (const [ws, entry] of workspaceEntries) {\n const wsRuleSet = new Set(entry.rules);\n const wsRules = allRules.filter((r) => wsRuleSet.has(r.id));\n const { domain } = partitionRules(wsRules);\n if (domain.length === 0) continue;\n\n const domainAction: FileAction = {\n relativePath: join(ws, config.domainFileName),\n content: wrapWithHeader(renderRulesToMarkdown(domain), meta),\n };\n const r = installFiles(basePath, [domainAction], meta);\n allInstalledFiles.push(...r.written);\n allAppended.push(...r.appended);\n }\n }\n }\n } else {\n // 단일 프로젝트: installed_rules 기반 재설치\n const installedRuleSet = new Set(manifest.installed_rules);\n const rulesToInstall = allRules.filter((r) => installedRuleSet.has(r.id));\n\n for (const toolIdStr of manifest.tools) {\n const toolId = toolIdStr as ToolId;\n const renderResult = renderForTool(toolId, rulesToInstall);\n const actions = buildInstallPlan({ toolId, renderResult, meta });\n const r = installFiles(basePath, actions, meta);\n allInstalledFiles.push(...r.written);\n allAppended.push(...r.appended);\n }\n }\n\n const newManifest = buildManifest({\n tools: manifest.tools,\n scope: manifest.scope,\n preset: manifest.preset,\n workspaces: manifest.workspaces,\n installedRules: manifest.installed_rules,\n installedFiles: allInstalledFiles.length > 0 ? allInstalledFiles : manifest.installed_files,\n appendedFiles: allAppended.length > 0 ? allAppended : manifest.appended_files,\n sourceHash,\n });\n writeManifest(manifestPath, newManifest);\n\n s.stop('규칙 갱신 완료');\n p.outro('ai-ops update 완료');\n};\n","import * as p from '@clack/prompts';\nimport { readManifest, resolveManifestPath, computeSourceHash, computeDiff } from '@/core/index.js';\nimport { resolveBasePath, resolveRulesDir } from '../lib/paths.js';\n\nexport const diffCommand = async (): Promise<void> => {\n const basePath = resolveBasePath();\n\n p.intro('ai-ops diff');\n\n const manifest = readManifest(resolveManifestPath(basePath));\n if (!manifest) {\n p.log.error('manifest가 없습니다. 먼저 ai-ops init을 실행하세요.');\n process.exit(1);\n }\n\n const sourceHash = computeSourceHash(resolveRulesDir());\n\n const result = computeDiff({\n previous: manifest,\n currentRules: manifest.installed_rules,\n currentSourceHash: sourceHash,\n });\n\n if (result.status === 'up-to-date') {\n p.log.success('변경 사항 없음. 최신 상태입니다.');\n } else {\n if (result.sourceChanged) {\n p.log.warn(`소스 변경 감지: ${manifest.sourceHash} → ${sourceHash}`);\n }\n if (result.added.length > 0) {\n p.log.info(`추가된 규칙: ${result.added.join(', ')}`);\n }\n if (result.removed.length > 0) {\n p.log.info(`제거된 규칙: ${result.removed.join(', ')}`);\n }\n }\n\n p.outro('ai-ops diff 완료');\n};\n","import * as p from '@clack/prompts';\nimport { rmSync } from 'node:fs';\nimport { readManifest, resolveManifestPath, inferInstalledFiles, MANIFEST_FILENAME } from '@/core/index.js';\nimport { resolveBasePath } from '../lib/paths.js';\nimport { removeFiles, cleanEmptyDirs, collectManagedDirs } from '../lib/uninstall.js';\n\nexport const uninstallCommand = async (): Promise<void> => {\n const basePath = resolveBasePath();\n const manifestPath = resolveManifestPath(basePath);\n\n p.intro('ai-ops uninstall');\n\n // 1. manifest 읽기\n const manifest = readManifest(manifestPath);\n if (!manifest) {\n p.log.error('manifest가 없습니다. 먼저 ai-ops init을 실행하세요.');\n process.exit(1);\n }\n\n // 2. 삭제 대상 결정 (managed 파일 + append된 파일)\n const targetFiles = [\n ...(manifest.installed_files ?? inferInstalledFiles(manifest)),\n ...(manifest.appended_files ?? []),\n ];\n\n if (targetFiles.length === 0) {\n p.log.warn('삭제할 파일이 없습니다.');\n p.outro('ai-ops uninstall 완료');\n return;\n }\n\n // 3. 삭제 대상 목록 출력\n p.log.info(`삭제 대상 파일 (${targetFiles.length}개):\\n${targetFiles.map((f) => ` ${f}`).join('\\n')}`);\n\n // 4. confirm\n const confirmed = await p.confirm({\n message: '위 파일과 manifest를 모두 삭제하시겠습니까?',\n initialValue: false,\n });\n if (p.isCancel(confirmed) || !confirmed) {\n p.cancel('취소됨');\n process.exit(0);\n }\n\n // 5. 파일 삭제\n const result = removeFiles(basePath, targetFiles);\n\n // 6. 빈 디렉토리 정리\n const dirs = collectManagedDirs(targetFiles);\n const removedDirs = cleanEmptyDirs(basePath, dirs);\n\n // 7. manifest 삭제\n rmSync(manifestPath, { force: true });\n\n // 8. 결과 요약\n if (result.deleted.length > 0) {\n p.log.success(`삭제 완료 (${result.deleted.length}개):\\n${result.deleted.map((f) => ` ${f}`).join('\\n')}`);\n }\n if (result.cleaned.length > 0) {\n p.log.success(\n `섹션 제거 완료 (사용자 내용 보존, ${result.cleaned.length}개):\\n${result.cleaned.map((f) => ` ${f}`).join('\\n')}`,\n );\n }\n if (result.skipped.length > 0) {\n p.log.warn(\n `건너뜀 (non-managed 파일 보호, ${result.skipped.length}개):\\n${result.skipped.map((f) => ` ${f}`).join('\\n')}`,\n );\n }\n if (result.notFound.length > 0) {\n p.log.info(`이미 없음 (${result.notFound.length}개):\\n${result.notFound.map((f) => ` ${f}`).join('\\n')}`);\n }\n if (removedDirs.length > 0) {\n p.log.info(`빈 디렉토리 정리 (${removedDirs.length}개):\\n${removedDirs.map((d) => ` ${d}`).join('\\n')}`);\n }\n\n p.log.success(`manifest 삭제: ${MANIFEST_FILENAME}`);\n p.outro('ai-ops uninstall 완료');\n};\n","import { existsSync, readFileSync, rmSync, readdirSync, writeFileSync } from 'node:fs';\nimport { resolve, dirname } from 'node:path';\nimport { isManagedFile, hasAiOpsSection, stripAiOpsSection } from '@/core/index.js';\n\nexport type UninstallResult = {\n deleted: string[];\n cleaned: string[]; // 섹션만 제거된 파일 (append 되었던 파일)\n skipped: string[]; // non-managed 파일 (사용자 파일 보호)\n notFound: string[]; // 이미 삭제됨\n};\n\nexport const removeFiles = (basePath: string, relativePaths: readonly string[]): UninstallResult => {\n const deleted: string[] = [];\n const cleaned: string[] = [];\n const skipped: string[] = [];\n const notFound: string[] = [];\n\n for (const rel of relativePaths) {\n const absPath = resolve(basePath, rel);\n\n if (!existsSync(absPath)) {\n notFound.push(rel);\n continue;\n }\n\n const content = readFileSync(absPath, 'utf-8');\n\n if (!isManagedFile(content)) {\n if (hasAiOpsSection(content)) {\n // append된 파일 → 섹션만 제거, 사용자 콘텐츠 보존\n const stripped = stripAiOpsSection(content);\n writeFileSync(absPath, stripped, 'utf-8');\n cleaned.push(rel);\n } else {\n skipped.push(rel);\n }\n continue;\n }\n\n rmSync(absPath);\n deleted.push(rel);\n }\n\n return { deleted, cleaned, skipped, notFound };\n};\n\n/** 대상 디렉토리가 비어 있으면 삭제하고, 삭제한 경로 배열 반환 */\nexport const cleanEmptyDirs = (basePath: string, dirs: readonly string[]): string[] => {\n const removed: string[] = [];\n\n for (const dir of dirs) {\n const absDir = resolve(basePath, dir);\n if (!existsSync(absDir)) continue;\n\n try {\n const entries = readdirSync(absDir);\n if (entries.length === 0) {\n rmSync(absDir, { recursive: true });\n removed.push(dir);\n }\n } catch {\n // 삭제 실패는 무시\n }\n }\n\n return removed;\n};\n\n/** manifest의 installed_files에서 정리 대상 디렉토리 목록 추출 */\nexport const collectManagedDirs = (relativePaths: readonly string[]): string[] => {\n const dirs = new Set<string>();\n for (const rel of relativePaths) {\n const dir = dirname(rel);\n if (dir !== '.') {\n dirs.add(dir);\n }\n }\n return [...dirs];\n};\n"],"mappings":"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","names":["p","join","z","z","z","p","global","domain","readFileSync","readdirSync","resolve","readdirSync","readFileSync","resolve","readFileSync","join","join","readFileSync","join","join","join","join","dirname","resolve","join","join","readdirSync","join","resolve","existsSync","mkdirSync","readFileSync","writeFileSync","dirname","resolve","resolve","existsSync","readFileSync","writeFileSync","mkdirSync","dirname","existsSync","mkdirSync","readFileSync","writeFileSync","join","join","r","p","join","r","join","p","p","rmSync","existsSync","readFileSync","readdirSync","writeFileSync","resolve","dirname","resolve","existsSync","readFileSync","writeFileSync","readdirSync","dirname","rmSync"]}
|
|
1
|
+
{"version":3,"sources":["../../src/bin/index.ts","../../src/commands/init.ts","../../src/core/schemas/rule.schema.ts","../../src/core/schemas/preset.schema.ts","../../src/core/schemas/manifest.schema.ts","../../src/core/loader.ts","../../src/core/renderer.ts","../../src/core/tool-output.ts","../../src/core/source-hash.ts","../../src/core/managed-header.ts","../../src/core/manifest-io.ts","../../src/core/diff.ts","../../src/core/install-plan.ts","../../src/core/uninstall-plan.ts","../../src/core/paths.ts","../../src/lib/paths.ts","../../src/lib/workspace.ts","../../src/lib/install.ts","../../src/lib/gemini-settings.ts","../../src/lib/claude-settings.ts","../../src/commands/update.ts","../../src/commands/diff.ts","../../src/commands/uninstall.ts","../../src/lib/uninstall.ts"],"sourcesContent":["import { Command } from 'commander';\nimport { initCommand } from '../commands/init.js';\nimport { updateCommand } from '../commands/update.js';\nimport { diffCommand } from '../commands/diff.js';\nimport { uninstallCommand } from '../commands/uninstall.js';\n\nconst program = new Command();\n\nconst ensureNoDeprecatedScopeFlag = (argv: readonly string[]): void => {\n if (argv.some((arg) => arg === '--scope' || arg.startsWith('--scope='))) {\n console.error('`--scope` is no longer supported. ai-ops is now project-only.');\n process.exit(1);\n }\n};\n\nprogram.name('ai-ops').description('AI 에이전트 규칙 스캐폴더').version('0.1.0');\n\nprogram\n .command('init')\n .description('AI 규칙 초기 설치')\n .action(() => initCommand());\n\nprogram\n .command('update')\n .description('기존 manifest 기반 규칙 갱신')\n .option('--force', '변경 없어도 강제 재설치', false)\n .action((opts: { force: boolean }) => updateCommand(opts));\n\nprogram\n .command('diff')\n .description('설치된 규칙과 최신 소스 비교')\n .action(() => diffCommand());\n\nprogram\n .command('uninstall')\n .description('설치된 규칙 파일 및 manifest 제거')\n .action(() => uninstallCommand());\n\nensureNoDeprecatedScopeFlag(process.argv);\nprogram.parse();\n","import * as p from '@clack/prompts';\nimport { join } from 'node:path';\nimport type { Rule, Preset, ToolId, WorkspaceMapping } from '@/core/index.js';\nimport {\n loadAllRules,\n loadPresets,\n resolvePresetRules,\n resolvePresetRuleGroups,\n isGlobalRule,\n partitionRules,\n renderForTool,\n renderRulesToMarkdown,\n buildInstallPlan,\n buildManifest,\n computeSourceHash,\n resolveManifestPath,\n writeManifest,\n wrapWithHeader,\n TOOL_OUTPUT_MAP,\n} from '@/core/index.js';\nimport type { FileAction } from '@/core/index.js';\nimport { resolveBasePath, resolveRulesDir, resolvePresetsPath } from '../lib/paths.js';\nimport { listWorkspaceCandidates } from '../lib/workspace.js';\nimport { installFiles } from '../lib/install.js';\nimport { promptGeminiSettings, installGeminiSettings } from '../lib/gemini-settings.js';\nimport { promptClaudeSettings, installClaudeSettings } from '../lib/claude-settings.js';\n\ntype WorkspacePresetMapping = {\n workspace: string;\n preset: Preset;\n finalRules: Rule[];\n};\n\ntype InstallStats = { written: string[]; appended: string[] };\n\nconst TOOL_OPTIONS = [\n { value: 'claude-code' as ToolId, label: 'Claude Code' },\n { value: 'codex' as ToolId, label: 'Codex' },\n { value: 'gemini' as ToolId, label: 'Gemini CLI' },\n];\n\nconst deduplicateRules = (rules: readonly Rule[]): Rule[] => {\n const seen = new Set<string>();\n return rules.filter((r) => {\n if (seen.has(r.id)) return false;\n seen.add(r.id);\n return true;\n });\n};\n\nconst selectPresetAndFineTune = async (\n workspaceName: string,\n presets: readonly Preset[],\n allRules: readonly Rule[],\n): Promise<WorkspacePresetMapping | null> => {\n const preset = await p.select<Preset>({\n message: `[${workspaceName}] 프리셋을 선택하세요`,\n options: presets.map((pr) => ({\n value: pr,\n label: pr.id,\n hint: pr.description,\n })),\n });\n if (p.isCancel(preset)) return null;\n\n const presetRuleGroups = resolvePresetRuleGroups(preset, allRules);\n const globalGroups = presetRuleGroups.filter((group) => group.rules.every(isGlobalRule));\n const domainGroups = presetRuleGroups.filter((group) => !group.rules.every(isGlobalRule));\n const globalGroupIds = globalGroups.map((group) => group.id);\n const globalRules =\n globalGroupIds.length > 0 ? resolvePresetRules({ ...preset, rules: globalGroupIds }, allRules) : [];\n\n // Global rules: locked (항상 포함)\n if (globalRules.length > 0) {\n p.note(globalRules.map((r) => ` ✓ ${r.id}`).join('\\n'), `[${workspaceName}] 기본 규칙 (잠금)`);\n }\n\n if (domainGroups.length === 0) {\n return { workspace: workspaceName, preset, finalRules: resolvePresetRules(preset, allRules) };\n }\n\n // Domain rules: 제외 가능\n const selectedDomain = await p.multiselect<string>({\n message: `[${workspaceName}] 도메인 규칙 선택 (해제하여 제외)`,\n options: domainGroups.map((group) => ({ value: group.id, label: group.id })),\n initialValues: domainGroups.map((group) => group.id),\n required: false,\n });\n if (p.isCancel(selectedDomain)) return null;\n\n const selectedLogicalRuleIds = [...globalGroupIds, ...(selectedDomain as string[])];\n return {\n workspace: workspaceName,\n preset,\n finalRules: resolvePresetRules({ ...preset, rules: selectedLogicalRuleIds }, allRules),\n };\n};\n\nconst installHierarchicalMonorepo = (\n toolId: 'codex' | 'gemini',\n mappings: readonly WorkspacePresetMapping[],\n basePath: string,\n meta: { sourceHash: string; generatedAt: string },\n): InstallStats => {\n const config = TOOL_OUTPUT_MAP[toolId];\n const written: string[] = [];\n const appended: string[] = [];\n\n const allRules = deduplicateRules(mappings.flatMap((m) => m.finalRules));\n const { global } = partitionRules(allRules);\n\n if (global.length > 0) {\n const rootAction: FileAction = {\n relativePath: join(config.dir, config.rootFileName),\n content: wrapWithHeader(renderRulesToMarkdown(global), meta),\n };\n const r = installFiles(basePath, [rootAction], meta);\n written.push(...r.written);\n appended.push(...r.appended);\n }\n\n for (const mapping of mappings) {\n const { domain } = partitionRules(mapping.finalRules);\n if (domain.length === 0) continue;\n\n const domainAction: FileAction = {\n relativePath: join(mapping.workspace, config.domainFileName),\n content: wrapWithHeader(renderRulesToMarkdown(domain), meta),\n };\n const r = installFiles(basePath, [domainAction], meta);\n written.push(...r.written);\n appended.push(...r.appended);\n }\n\n return { written, appended };\n};\n\nconst installClaudeCodeMonorepo = (\n mappings: readonly WorkspacePresetMapping[],\n basePath: string,\n meta: { sourceHash: string; generatedAt: string },\n): InstallStats => {\n const allRules = deduplicateRules(mappings.flatMap((m) => m.finalRules));\n const workspaceMappings: WorkspaceMapping[] = mappings.map((m) => ({\n path: m.workspace,\n ruleIds: m.finalRules.map((r) => r.id),\n }));\n const renderResult = renderForTool('claude-code', allRules, workspaceMappings);\n const actions = buildInstallPlan({ toolId: 'claude-code', renderResult, meta });\n const r = installFiles(basePath, actions, meta);\n return { written: r.written, appended: r.appended };\n};\n\nexport const initCommand = async (): Promise<void> => {\n const basePath = resolveBasePath();\n const rulesDir = resolveRulesDir();\n\n p.intro('ai-ops init');\n\n // 1. AI 도구 다중 선택\n const selectedTools = await p.multiselect<ToolId>({\n message: 'AI 도구를 선택하세요',\n options: TOOL_OPTIONS,\n required: true,\n });\n if (p.isCancel(selectedTools)) {\n p.cancel('취소됨');\n process.exit(0);\n }\n\n // 2. 모노레포 여부\n const isMonorepo = await p.confirm({\n message: '모노레포 프로젝트입니까?',\n initialValue: false,\n });\n if (p.isCancel(isMonorepo)) {\n p.cancel('취소됨');\n process.exit(0);\n }\n\n // 3. 데이터 로드\n const allRules = loadAllRules(rulesDir);\n const presets = loadPresets(resolvePresetsPath());\n const sourceHash = computeSourceHash(rulesDir);\n\n // 4. 워크스페이스별 preset 선택 + fine-tune\n const mappings: WorkspacePresetMapping[] = [];\n\n if (!isMonorepo) {\n const mapping = await selectPresetAndFineTune('.', presets, allRules);\n if (!mapping) {\n p.cancel('취소됨');\n process.exit(0);\n }\n mappings.push(mapping);\n } else {\n const candidates = listWorkspaceCandidates(basePath);\n const selectedWorkspaces = await p.multiselect<string>({\n message: '워크스페이스를 선택하세요',\n options: candidates.map((c) => ({ value: c, label: c })),\n required: true,\n });\n if (p.isCancel(selectedWorkspaces)) {\n p.cancel('취소됨');\n process.exit(0);\n }\n\n for (const ws of selectedWorkspaces as string[]) {\n const mapping = await selectPresetAndFineTune(ws, presets, allRules);\n if (!mapping) {\n p.cancel('취소됨');\n process.exit(0);\n }\n mappings.push(mapping);\n }\n }\n\n // 4.5. Gemini 설정 (gemini 선택 시)\n const geminiSettingValues: readonly string[] | null = (selectedTools as ToolId[]).includes('gemini')\n ? await promptGeminiSettings()\n : null;\n\n // 4.6. Claude 설정 (claude-code 선택 시)\n const claudeSettingValues: readonly string[] | null = (selectedTools as ToolId[]).includes('claude-code')\n ? await promptClaudeSettings()\n : null;\n\n // 5. 설치\n const s = p.spinner();\n s.start('규칙 설치 중...');\n\n const meta = { sourceHash, generatedAt: new Date().toISOString() };\n const allInstalledFiles: string[] = [];\n const allAppended: string[] = [];\n\n for (const toolId of selectedTools as ToolId[]) {\n if (isMonorepo) {\n if (toolId === 'claude-code') {\n const stats = installClaudeCodeMonorepo(mappings, basePath, meta);\n allInstalledFiles.push(...stats.written);\n allAppended.push(...stats.appended);\n } else {\n const stats = installHierarchicalMonorepo(toolId, mappings, basePath, meta);\n allInstalledFiles.push(...stats.written);\n allAppended.push(...stats.appended);\n }\n } else {\n const renderResult = renderForTool(toolId, mappings[0].finalRules);\n const actions = buildInstallPlan({ toolId, renderResult, meta });\n const result = installFiles(basePath, actions, meta);\n allInstalledFiles.push(...result.written);\n allAppended.push(...result.appended);\n }\n }\n\n if (geminiSettingValues && geminiSettingValues.length > 0) {\n installGeminiSettings(basePath, geminiSettingValues);\n allInstalledFiles.push('.gemini/settings.json');\n }\n\n if (claudeSettingValues && claudeSettingValues.length > 0) {\n installClaudeSettings(basePath, claudeSettingValues);\n allInstalledFiles.push('.claude/settings.local.json');\n }\n\n s.stop('규칙 설치 완료');\n\n // 6. Manifest 저장\n const allInstalledRuleIds = deduplicateRules(mappings.flatMap((m) => m.finalRules)).map((r) => r.id);\n\n const workspacesRecord = isMonorepo\n ? Object.fromEntries(\n mappings.map((m) => [m.workspace, { preset: m.preset.id, rules: m.finalRules.map((r) => r.id) }]),\n )\n : undefined;\n\n const manifest = buildManifest({\n tools: selectedTools as string[],\n scope: 'project',\n preset: !isMonorepo ? mappings[0].preset.id : undefined,\n workspaces: workspacesRecord,\n installedRules: allInstalledRuleIds,\n installedFiles: allInstalledFiles,\n appendedFiles: allAppended,\n settings:\n claudeSettingValues || geminiSettingValues\n ? {\n claude: claudeSettingValues ? [...claudeSettingValues] : undefined,\n gemini: geminiSettingValues ? [...geminiSettingValues] : undefined,\n }\n : undefined,\n sourceHash,\n });\n writeManifest(resolveManifestPath(basePath), manifest);\n\n // 7. 결과 요약\n if (allAppended.length > 0) {\n p.log.info(`기존 파일에 섹션 추가됨 (내용 보존):\\n${allAppended.map((f) => ` ${f}`).join('\\n')}`);\n }\n p.log.success(`설치된 규칙: ${allInstalledRuleIds.length}개`);\n p.outro('ai-ops init 완료');\n};\n","/**\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} as const;\n\n/** init/update 시 선택된 settings 항목 추적 */\nconst SettingsConfigSchema = z\n .object({\n claude: z.array(z.string().min(1)).optional(),\n gemini: z.array(z.string().min(1)).optional(),\n })\n .strict();\n\nexport type SettingsConfig = z.infer<typeof SettingsConfigSchema>;\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.literal('project'),\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 /** 실제 디스크에 쓰여진 파일 상대 경로 목록 (uninstall용). 기존 manifest 호환성 위해 optional */\n installed_files: z.array(z.string().min(1)).optional(),\n /** non-managed 파일에 섹션을 append한 경우 추적 (uninstall 시 섹션만 제거) */\n appended_files: z.array(z.string().min(1)).optional(),\n /** init 시 선택된 settings 항목 — update 시 재생성에 사용 */\n settings: SettingsConfigSchema.optional(),\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\ntype PresetRuleBundles = Readonly<Record<string, Readonly<Record<string, readonly string[]>>>>;\n\nexport const PRESET_RULE_BUNDLES: PresetRuleBundles = {\n 'frontend-web': {\n graphql: ['graphql-core', 'graphql-client-web'],\n },\n 'frontend-app': {\n graphql: ['graphql-core', 'graphql-client-app'],\n },\n 'backend-ts': {\n graphql: ['graphql-core', 'graphql-server'],\n },\n} as const;\n\nexport type PresetRuleGroup = {\n id: string;\n rules: Rule[];\n};\n\n// priority 내림차순 정렬 (높을수록 상단 → U-shaped attention)\nexport const sortRulesByPriority = (rules: readonly Rule[]): Rule[] =>\n [...rules].sort((a, b) => b.priority - a.priority);\n\nconst deduplicateRulesById = (rules: readonly Rule[]): Rule[] => {\n const seen = new Set<string>();\n return rules.filter((rule) => {\n if (seen.has(rule.id)) return false;\n seen.add(rule.id);\n return true;\n });\n};\n\nconst resolveBundledRuleIds = (presetId: string, logicalRuleId: string): readonly string[] => {\n const presetBundles = PRESET_RULE_BUNDLES[presetId];\n if (!presetBundles) return [logicalRuleId];\n return presetBundles[logicalRuleId] ?? [logicalRuleId];\n};\n\nconst resolveRuleById = (ruleId: string, allRules: readonly Rule[], context?: string): Rule => {\n const found = allRules.find((rule) => rule.id === ruleId);\n if (!found) {\n const suffix = context ? ` (from ${context})` : '';\n throw new Error(`Rule not found: ${ruleId}${suffix}`);\n }\n return found;\n};\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\nexport const resolvePresetRuleGroups = (preset: Preset, allRules: readonly Rule[]): PresetRuleGroup[] =>\n preset.rules.map((logicalRuleId) => {\n const bundledRuleIds = resolveBundledRuleIds(preset.id, logicalRuleId);\n const rules = bundledRuleIds.map((ruleId) => resolveRuleById(ruleId, allRules, `${preset.id}:${logicalRuleId}`));\n return { id: logicalRuleId, rules };\n });\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 포함) 목록을 실제 rule로 확장 + priority 정렬, 누락 시 throw\nexport const resolvePresetRules = (preset: Preset, allRules: readonly Rule[]): Rule[] => {\n const groups = resolvePresetRuleGroups(preset, allRules);\n const resolved = deduplicateRulesById(groups.flatMap((group) => group.rules));\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 문자 | escape)\nexport const renderDecisionTable = (entries: readonly DecisionTableEntry[]): string => {\n const escape = (s: string) => s.replace(/\\|/g, '|');\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-core': ['**/*.graphql', '**/*.gql'],\n 'graphql-client-web': ['**/*.graphql', '**/*.gql', '**/*.tsx', '**/*.ts'],\n 'graphql-client-app': ['**/*.graphql', '**/*.gql', 'lib/**/*.dart'],\n 'graphql-server': ['**/*.graphql', '**/*.gql', '**/*.resolver.ts'],\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: '',\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';\n preset?: string;\n workspaces?: Record<string, { preset: string; rules: string[] }>;\n installedRules: readonly string[];\n installedFiles?: readonly string[];\n appendedFiles?: readonly string[];\n settings?: { claude?: readonly string[]; gemini?: 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 installed_files: params.installedFiles ? [...params.installedFiles] : undefined,\n appended_files: params.appendedFiles && params.appendedFiles.length > 0 ? [...params.appendedFiles] : undefined,\n settings: params.settings\n ? {\n claude: params.settings.claude ? [...params.settings.claude] : undefined,\n gemini: params.settings.gemini ? [...params.settings.gemini] : undefined,\n }\n : undefined,\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\nconst SECTION_START = '<!-- ai-ops:start -->';\nconst SECTION_END = '<!-- ai-ops:end -->';\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\nexport const wrapWithSection = (content: string, meta: { sourceHash: string; generatedAt: string }): string => {\n const metaLine = `<!-- sourceHash: ${meta.sourceHash} | generatedAt: ${meta.generatedAt} -->`;\n return `${SECTION_START}\\n${metaLine}\\n\\n${content}\\n${SECTION_END}`;\n};\n\nexport const hasAiOpsSection = (content: string): boolean =>\n content.includes(SECTION_START) && content.includes(SECTION_END);\n\nexport const stripAiOpsSection = (content: string): string => {\n const startIdx = content.indexOf(SECTION_START);\n const endIdx = content.indexOf(SECTION_END);\n if (startIdx === -1 || endIdx === -1) return content;\n\n const before = content.slice(0, startIdx).trimEnd();\n const after = content.slice(endIdx + SECTION_END.length).trimStart();\n return before + (after ? '\\n\\n' + after : '') + '\\n';\n};\n\nexport const replaceAiOpsSection = (existing: string, newSection: string): string => {\n const startIdx = existing.indexOf(SECTION_START);\n const endIdx = existing.indexOf(SECTION_END);\n if (startIdx === -1 || endIdx === -1) return existing;\n\n const before = existing.slice(0, startIdx).trimEnd();\n const after = existing.slice(endIdx + SECTION_END.length).trimStart();\n return before + '\\n\\n' + newSection + (after ? '\\n\\n' + after : '') + '\\n';\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\n// Codex has no settings.json — plan directory convention must live in AGENTS.md\nconst CODEX_PLAN_SECTION =\n '\\n\\n---\\n\\n## Plan Snapshot\\n\\n' +\n 'Before implementation, save the latest `<proposed_plan>` to `.codex/plans/YYYYMMDD_<topic>.md` (`<topic>` = kebab-case title, fallback `task`).\\n' +\n 'Ensure `.codex/plans` exists; if the filename exists, append `-v2`, `-v3`, ...\\n' +\n 'Do not start any mutating implementation step until this file is written.';\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 const rootContent = toolId === 'codex' ? renderResult.rootContent + CODEX_PLAN_SECTION : renderResult.rootContent;\n actions.push({\n relativePath: join(config.dir, config.rootFileName),\n content: wrapWithHeader(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 { join } from 'node:path';\nimport { TOOL_OUTPUT_MAP } from './tool-output.js';\nimport type { Manifest } from './schemas/index.js';\n\n/**\n * manifest에 installed_files가 없는 구버전 manifest를 위한 fallback.\n * manifest의 tools/workspaces/installed_rules 정보를 기반으로\n * 실제 설치됐을 파일 경로를 역산한다.\n */\nexport const inferInstalledFiles = (manifest: Manifest): string[] => {\n const files: string[] = [];\n const isMonorepo = manifest.workspaces !== undefined;\n\n for (const toolId of manifest.tools) {\n if (toolId === 'claude-code') {\n // claude-code: .claude/rules/{ruleId}.md\n const config = TOOL_OUTPUT_MAP['claude-code'];\n for (const ruleId of manifest.installed_rules) {\n files.push(join(config.rulesDir, `${ruleId}${config.fileExtension}`));\n }\n } else if (toolId === 'codex') {\n const config = TOOL_OUTPUT_MAP['codex'];\n if (!isMonorepo) {\n // 비모노: .codex/AGENTS.md + .codex/AGENTS.override.md (domain 있으면)\n files.push(join(config.dir, config.rootFileName));\n files.push(join(config.dir, config.domainFileName));\n } else {\n // 모노: .codex/AGENTS.md (global) + {workspace}/AGENTS.override.md (domain)\n files.push(join(config.dir, config.rootFileName));\n for (const ws of Object.keys(manifest.workspaces ?? {})) {\n files.push(join(ws, config.domainFileName));\n }\n }\n } else if (toolId === 'gemini') {\n const config = TOOL_OUTPUT_MAP['gemini'];\n if (!isMonorepo) {\n // 비모노: .gemini/GEMINI.md\n files.push(join(config.dir, config.rootFileName));\n } else {\n // 모노: .gemini/GEMINI.md (global) + {workspace}/GEMINI.md (domain)\n files.push(join(config.dir, config.rootFileName));\n for (const ws of Object.keys(manifest.workspaces ?? {})) {\n files.push(join(ws, config.domainFileName));\n }\n }\n }\n }\n\n // 중복 제거 (codex 비모노에서 rootFileName === domainFileName인 경우 대비)\n return [...new Set(files)];\n};\n","import { dirname, resolve } from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\n// src/core/* 또는 dist/bin/index.js 기준에서도 공통으로 패키지 루트/data를 가리키도록 계산\n// src/core/paths.ts → ../../data = apps/cli/data\n// dist/bin/index.js (bundle) → ../../data = apps/cli/data\nconst __dirname = dirname(fileURLToPath(import.meta.url));\n\nexport const COMPILER_DATA_DIR = resolve(__dirname, '..', '..', 'data');\n","import { join } from 'node:path';\nimport { COMPILER_DATA_DIR } from '@/core/index.js';\n\nexport const resolveCompilerDataDir = (): string => COMPILER_DATA_DIR;\n\nexport const resolveRulesDir = (): string => join(COMPILER_DATA_DIR, 'rules');\n\nexport const resolvePresetsPath = (): string => join(COMPILER_DATA_DIR, 'presets.yaml');\n\n// project-only 설치 기준 디렉토리\nexport const resolveBasePath = (): string => process.cwd();\n","import { existsSync, readdirSync, statSync } from 'node:fs';\nimport { join, resolve } from 'node:path';\n\nconst EXCLUDE_DIRS = new Set(['node_modules', '.git', 'dist', 'build', '.next', '.turbo', '.cache', 'coverage']);\n\nconst isVisibleDir = (basePath: string, name: string): boolean => {\n if (name.startsWith('.') || EXCLUDE_DIRS.has(name)) return false;\n return statSync(resolve(basePath, name)).isDirectory();\n};\n\n// Project manifest files that indicate a workspace root\nconst PROJECT_MANIFESTS = [\n 'package.json', // Node.js / JS / TS\n 'pubspec.yaml', // Flutter / Dart\n 'pyproject.toml', // Python (modern)\n 'setup.py', // Python (legacy)\n 'Cargo.toml', // Rust\n 'go.mod', // Go\n];\n\nconst isWorkspaceRoot = (dirPath: string): boolean => PROJECT_MANIFESTS.some((f) => existsSync(join(dirPath, f)));\n\n// 프로젝트 매니페스트 파일 존재 여부로 워크스페이스 판별:\n// 1. top-level dir에 매니페스트 → 그 자체가 워크스페이스 (e.g. backend-ts, mobile, web)\n// 2. top-level dir에 매니페스트 없고 자식에 있음 → 자식을 후보로 (e.g. apps/web, packages/ui)\n// 3. 매니페스트 없는 경우 → 1-depth 그대로\nexport const listWorkspaceCandidates = (basePath: string): string[] => {\n const topLevel = readdirSync(basePath).filter((name) => isVisibleDir(basePath, name));\n\n const candidates: string[] = [];\n for (const dir of topLevel) {\n const subPath = resolve(basePath, dir);\n if (isWorkspaceRoot(subPath)) {\n candidates.push(dir);\n } else {\n const children = readdirSync(subPath).filter((name) => isVisibleDir(subPath, name));\n const wsChildren = children.filter((name) => isWorkspaceRoot(resolve(subPath, name)));\n if (wsChildren.length > 0) {\n for (const child of wsChildren) {\n candidates.push(join(dir, child));\n }\n } else {\n candidates.push(dir);\n }\n }\n }\n\n return candidates.sort();\n};\n","import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';\nimport { dirname, resolve } from 'node:path';\nimport {\n isManagedFile,\n hasAiOpsSection,\n wrapWithSection,\n replaceAiOpsSection,\n stripManagedHeader,\n} from '@/core/index.js';\nimport type { FileAction } from '@/core/index.js';\n\nexport type InstallResult = {\n written: string[];\n appended: string[]; // 기존 non-managed 파일에 섹션 추가됨\n skipped: string[]; // 더 이상 발생하지 않음 (하위 호환용)\n};\n\nexport const installFiles = (\n basePath: string,\n actions: readonly FileAction[],\n meta: { sourceHash: string; generatedAt: string },\n): InstallResult => {\n const written: string[] = [];\n const appended: string[] = [];\n const skipped: string[] = [];\n\n for (const action of actions) {\n const absPath = resolve(basePath, action.relativePath);\n\n if (existsSync(absPath)) {\n const existing = readFileSync(absPath, 'utf-8');\n\n if (isManagedFile(existing)) {\n writeFileSync(absPath, action.content, 'utf-8');\n written.push(action.relativePath);\n } else if (hasAiOpsSection(existing)) {\n // 이전에 append된 파일 → 섹션만 교체\n const sectionContent = wrapWithSection(stripManagedHeader(action.content), meta);\n const updated = replaceAiOpsSection(existing, sectionContent);\n writeFileSync(absPath, updated, 'utf-8');\n appended.push(action.relativePath);\n } else {\n // non-managed, 섹션 없음 → 최초 append\n const sectionContent = wrapWithSection(stripManagedHeader(action.content), meta);\n const updated = existing.trimEnd() + '\\n\\n' + sectionContent + '\\n';\n writeFileSync(absPath, updated, 'utf-8');\n appended.push(action.relativePath);\n }\n } else {\n mkdirSync(dirname(absPath), { recursive: true });\n writeFileSync(absPath, action.content, 'utf-8');\n written.push(action.relativePath);\n }\n }\n\n return { written, appended, skipped };\n};\n","import * as p from '@clack/prompts';\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';\nimport { join } from 'node:path';\n\ntype GeminiSettings = {\n ui?: { showLineNumbers?: boolean };\n general?: {\n plan?: { directory?: string; modelRouting?: boolean };\n sessionRetention?: { maxAge?: string };\n };\n experimental?: { jitContext?: boolean; plan?: boolean };\n};\n\ntype SettingGroup = {\n value: string;\n label: string;\n hint: string;\n patch: GeminiSettings;\n};\n\nconst SETTING_GROUPS: readonly SettingGroup[] = [\n {\n value: 'ui',\n label: 'UI — 줄 번호 숨기기',\n hint: 'ui.showLineNumbers: false — 코드 복사 시 줄 번호가 포함되지 않도록 비활성화',\n patch: { ui: { showLineNumbers: false } },\n },\n {\n value: 'plan',\n label: 'Plan — 계획 파일 저장 및 모델 라우팅',\n hint: 'general.plan.directory: .gemini/plans, modelRouting: true — AI 계획을 파일로 저장하고 태스크별 최적 모델 자동 선택',\n patch: { general: { plan: { directory: '.gemini/plans', modelRouting: true } } },\n },\n {\n value: 'sessionRetention',\n label: 'Session Retention — 세션 30일 보존',\n hint: 'general.sessionRetention.maxAge: 30d — 이전 대화 컨텍스트를 30일간 유지',\n patch: { general: { sessionRetention: { maxAge: '30d' } } },\n },\n {\n value: 'experimental',\n label: 'Experimental — JIT 컨텍스트 + Plan 기능',\n hint: 'experimental.jitContext: true, plan: true — 서브디렉토리 컨텍스트 지연 로딩 및 계획 기능 실험적 활성화',\n patch: { experimental: { jitContext: true, plan: true } },\n },\n];\n\nconst deepMerge = (base: Record<string, unknown>, patch: Record<string, unknown>): Record<string, unknown> => {\n const result = { ...base };\n for (const [key, value] of Object.entries(patch)) {\n if (\n value !== null &&\n typeof value === 'object' &&\n !Array.isArray(value) &&\n typeof result[key] === 'object' &&\n result[key] !== null\n ) {\n result[key] = deepMerge(result[key] as Record<string, unknown>, value as Record<string, unknown>);\n } else {\n result[key] = value;\n }\n }\n return result;\n};\n\n// null → 건너뜀 (취소 또는 \"No\"), string[] → 선택된 항목\nexport const promptGeminiSettings = async (): Promise<readonly string[] | null> => {\n const wantSettings = await p.confirm({\n message: 'Gemini CLI 설정 파일(.gemini/settings.json)을 설치하시겠습니까?',\n initialValue: true,\n });\n if (p.isCancel(wantSettings) || !wantSettings) return null;\n\n const selected = await p.multiselect<string>({\n message: '설치할 설정 항목을 선택하세요 (스페이스로 토글)',\n options: SETTING_GROUPS.map((g) => ({\n value: g.value,\n label: g.label,\n hint: g.hint,\n })),\n initialValues: SETTING_GROUPS.map((g) => g.value),\n required: false,\n });\n if (p.isCancel(selected)) return null;\n return selected as string[];\n};\n\nexport const installGeminiSettings = (basePath: string, selectedValues: readonly string[]): void => {\n if (selectedValues.length === 0) return;\n\n const settingsDir = join(basePath, '.gemini');\n const settingsPath = join(settingsDir, 'settings.json');\n\n let existing: GeminiSettings = {};\n if (existsSync(settingsPath)) {\n try {\n existing = JSON.parse(readFileSync(settingsPath, 'utf-8')) as GeminiSettings;\n } catch {\n // parse 실패 시 덮어쓰기\n }\n }\n\n let merged: GeminiSettings = existing;\n for (const val of selectedValues) {\n const group = SETTING_GROUPS.find((g) => g.value === val);\n if (!group) continue;\n merged = deepMerge(merged as Record<string, unknown>, group.patch as Record<string, unknown>) as GeminiSettings;\n }\n\n mkdirSync(settingsDir, { recursive: true });\n writeFileSync(settingsPath, JSON.stringify(merged, null, 2) + '\\n', 'utf-8');\n};\n","import * as p from '@clack/prompts';\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';\nimport { join } from 'node:path';\n\ntype ClaudeSettings = Record<string, unknown>;\n\ntype SettingGroup = {\n value: string;\n label: string;\n hint: string;\n patch: ClaudeSettings;\n};\n\nconst SETTING_GROUPS: readonly SettingGroup[] = [\n {\n value: 'model',\n label: 'Model — Plan 모드 모델',\n hint: 'model: opusplan — Plan 모드에서 Opus 모델 사용',\n patch: { model: 'opusplan' },\n },\n {\n value: 'plansDirectory',\n label: 'Plans Directory — 계획 파일 저장 경로',\n hint: 'plansDirectory: ./.claude/plans — 계획 파일을 .claude/plans에 저장',\n patch: { plansDirectory: './.claude/plans' },\n },\n] as const;\n\nconst deepMerge = (base: Record<string, unknown>, patch: Record<string, unknown>): Record<string, unknown> => {\n const result = { ...base };\n for (const [key, value] of Object.entries(patch)) {\n if (\n value !== null &&\n typeof value === 'object' &&\n !Array.isArray(value) &&\n typeof result[key] === 'object' &&\n result[key] !== null\n ) {\n result[key] = deepMerge(result[key] as Record<string, unknown>, value as Record<string, unknown>);\n } else {\n result[key] = value;\n }\n }\n return result;\n};\n\n// null → 건너뜀 (취소 또는 \"No\"), string[] → 선택된 항목\nexport const promptClaudeSettings = async (): Promise<readonly string[] | null> => {\n const wantSettings = await p.confirm({\n message: 'Claude Code 설정 파일(.claude/settings.local.json)을 설치하시겠습니까?',\n initialValue: true,\n });\n if (p.isCancel(wantSettings) || !wantSettings) return null;\n\n const selected = await p.multiselect<string>({\n message: '설치할 설정 항목을 선택하세요 (스페이스로 토글)',\n options: SETTING_GROUPS.map((g) => ({\n value: g.value,\n label: g.label,\n hint: g.hint,\n })),\n initialValues: SETTING_GROUPS.map((g) => g.value),\n required: false,\n });\n if (p.isCancel(selected)) return null;\n return selected as string[];\n};\n\nexport const installClaudeSettings = (basePath: string, selectedValues: readonly string[]): void => {\n if (selectedValues.length === 0) return;\n\n const settingsDir = join(basePath, '.claude');\n const settingsPath = join(settingsDir, 'settings.local.json');\n\n let existing: ClaudeSettings = {};\n if (existsSync(settingsPath)) {\n try {\n existing = JSON.parse(readFileSync(settingsPath, 'utf-8')) as ClaudeSettings;\n } catch {\n // parse 실패 시 덮어쓰기\n }\n }\n\n let merged: ClaudeSettings = existing;\n for (const val of selectedValues) {\n const group = SETTING_GROUPS.find((g) => g.value === val);\n if (!group) continue;\n merged = deepMerge(merged, group.patch);\n }\n\n mkdirSync(settingsDir, { recursive: true });\n writeFileSync(settingsPath, JSON.stringify(merged, null, 2) + '\\n', 'utf-8');\n};\n","import * as p from '@clack/prompts';\nimport type { ToolId } from '@/core/index.js';\nimport {\n readManifest,\n resolveManifestPath,\n loadAllRules,\n renderForTool,\n buildInstallPlan,\n buildManifest,\n writeManifest,\n computeSourceHash,\n computeDiff,\n partitionRules,\n renderRulesToMarkdown,\n wrapWithHeader,\n TOOL_OUTPUT_MAP,\n} from '@/core/index.js';\nimport type { FileAction } from '@/core/index.js';\nimport { join } from 'node:path';\nimport { resolveBasePath, resolveRulesDir } from '../lib/paths.js';\nimport { installFiles } from '../lib/install.js';\nimport { installClaudeSettings } from '../lib/claude-settings.js';\nimport { installGeminiSettings } from '../lib/gemini-settings.js';\n\nexport const updateCommand = async (opts: { force: boolean }): Promise<void> => {\n const basePath = resolveBasePath();\n const manifestPath = resolveManifestPath(basePath);\n\n p.intro('ai-ops update');\n\n const manifest = readManifest(manifestPath);\n if (!manifest) {\n p.log.error('manifest가 없습니다. 먼저 ai-ops init을 실행하세요.');\n process.exit(1);\n }\n\n const rulesDir = resolveRulesDir();\n const sourceHash = computeSourceHash(rulesDir);\n\n const diffResult = computeDiff({\n previous: manifest,\n currentRules: manifest.installed_rules,\n currentSourceHash: sourceHash,\n });\n\n if (diffResult.status === 'up-to-date' && !opts.force) {\n p.log.info('변경 사항이 없습니다.');\n p.outro('ai-ops update 완료');\n return;\n }\n\n const s = p.spinner();\n s.start('규칙 갱신 중...');\n\n const allRules = loadAllRules(rulesDir);\n const meta = { sourceHash, generatedAt: new Date().toISOString() };\n const allInstalledFiles: string[] = [];\n const allAppended: string[] = [];\n\n if (manifest.workspaces) {\n // 모노레포: workspaces 기반 재설치\n const workspaceEntries = Object.entries(manifest.workspaces);\n\n for (const toolIdStr of manifest.tools) {\n const toolId = toolIdStr as ToolId;\n\n if (toolId === 'claude-code') {\n const allInstalledRuleSet = new Set(manifest.installed_rules);\n const rulesToInstall = allRules.filter((r) => allInstalledRuleSet.has(r.id));\n const workspaceMappings = workspaceEntries.map(([path, entry]) => ({\n path,\n ruleIds: entry.rules,\n }));\n const renderResult = renderForTool('claude-code', rulesToInstall, workspaceMappings);\n const actions = buildInstallPlan({ toolId: 'claude-code', renderResult, meta });\n const r = installFiles(basePath, actions, meta);\n allInstalledFiles.push(...r.written);\n allAppended.push(...r.appended);\n } else {\n // codex/gemini: global → 루트, domain → 워크스페이스별\n const config = TOOL_OUTPUT_MAP[toolId];\n\n const allInstalledRuleSet = new Set(manifest.installed_rules);\n const allRulesToInstall = allRules.filter((r) => allInstalledRuleSet.has(r.id));\n const { global } = partitionRules(allRulesToInstall);\n\n if (global.length > 0) {\n const rootAction: FileAction = {\n relativePath: join(config.dir, config.rootFileName),\n content: wrapWithHeader(renderRulesToMarkdown(global), meta),\n };\n const r = installFiles(basePath, [rootAction], meta);\n allInstalledFiles.push(...r.written);\n allAppended.push(...r.appended);\n }\n\n for (const [ws, entry] of workspaceEntries) {\n const wsRuleSet = new Set(entry.rules);\n const wsRules = allRules.filter((r) => wsRuleSet.has(r.id));\n const { domain } = partitionRules(wsRules);\n if (domain.length === 0) continue;\n\n const domainAction: FileAction = {\n relativePath: join(ws, config.domainFileName),\n content: wrapWithHeader(renderRulesToMarkdown(domain), meta),\n };\n const r = installFiles(basePath, [domainAction], meta);\n allInstalledFiles.push(...r.written);\n allAppended.push(...r.appended);\n }\n }\n }\n } else {\n // 단일 프로젝트: installed_rules 기반 재설치\n const installedRuleSet = new Set(manifest.installed_rules);\n const rulesToInstall = allRules.filter((r) => installedRuleSet.has(r.id));\n\n for (const toolIdStr of manifest.tools) {\n const toolId = toolIdStr as ToolId;\n const renderResult = renderForTool(toolId, rulesToInstall);\n const actions = buildInstallPlan({ toolId, renderResult, meta });\n const r = installFiles(basePath, actions, meta);\n allInstalledFiles.push(...r.written);\n allAppended.push(...r.appended);\n }\n }\n\n if (manifest.settings?.claude) {\n installClaudeSettings(basePath, manifest.settings.claude);\n }\n\n if (manifest.settings?.gemini) {\n installGeminiSettings(basePath, manifest.settings.gemini);\n }\n\n const newManifest = buildManifest({\n tools: manifest.tools,\n scope: manifest.scope,\n preset: manifest.preset,\n workspaces: manifest.workspaces,\n installedRules: manifest.installed_rules,\n installedFiles: allInstalledFiles.length > 0 ? allInstalledFiles : manifest.installed_files,\n appendedFiles: allAppended.length > 0 ? allAppended : manifest.appended_files,\n settings: manifest.settings\n ? {\n claude: manifest.settings.claude,\n gemini: manifest.settings.gemini,\n }\n : undefined,\n sourceHash,\n });\n writeManifest(manifestPath, newManifest);\n\n s.stop('규칙 갱신 완료');\n p.outro('ai-ops update 완료');\n};\n","import * as p from '@clack/prompts';\nimport { readManifest, resolveManifestPath, computeSourceHash, computeDiff } from '@/core/index.js';\nimport { resolveBasePath, resolveRulesDir } from '../lib/paths.js';\n\nexport const diffCommand = async (): Promise<void> => {\n const basePath = resolveBasePath();\n\n p.intro('ai-ops diff');\n\n const manifest = readManifest(resolveManifestPath(basePath));\n if (!manifest) {\n p.log.error('manifest가 없습니다. 먼저 ai-ops init을 실행하세요.');\n process.exit(1);\n }\n\n const sourceHash = computeSourceHash(resolveRulesDir());\n\n const result = computeDiff({\n previous: manifest,\n currentRules: manifest.installed_rules,\n currentSourceHash: sourceHash,\n });\n\n if (result.status === 'up-to-date') {\n p.log.success('변경 사항 없음. 최신 상태입니다.');\n } else {\n if (result.sourceChanged) {\n p.log.warn(`소스 변경 감지: ${manifest.sourceHash} → ${sourceHash}`);\n }\n if (result.added.length > 0) {\n p.log.info(`추가된 규칙: ${result.added.join(', ')}`);\n }\n if (result.removed.length > 0) {\n p.log.info(`제거된 규칙: ${result.removed.join(', ')}`);\n }\n }\n\n p.outro('ai-ops diff 완료');\n};\n","import * as p from '@clack/prompts';\nimport { rmSync } from 'node:fs';\nimport { readManifest, resolveManifestPath, inferInstalledFiles, MANIFEST_FILENAME } from '@/core/index.js';\nimport { resolveBasePath } from '../lib/paths.js';\nimport { removeFiles, cleanEmptyDirs, collectManagedDirs } from '../lib/uninstall.js';\n\nexport const uninstallCommand = async (): Promise<void> => {\n const basePath = resolveBasePath();\n const manifestPath = resolveManifestPath(basePath);\n\n p.intro('ai-ops uninstall');\n\n // 1. manifest 읽기\n const manifest = readManifest(manifestPath);\n if (!manifest) {\n p.log.error('manifest가 없습니다. 먼저 ai-ops init을 실행하세요.');\n process.exit(1);\n }\n\n // 2. 삭제 대상 결정 (managed 파일 + append된 파일)\n const targetFiles = [\n ...(manifest.installed_files ?? inferInstalledFiles(manifest)),\n ...(manifest.appended_files ?? []),\n ];\n\n if (targetFiles.length === 0) {\n p.log.warn('삭제할 파일이 없습니다.');\n p.outro('ai-ops uninstall 완료');\n return;\n }\n\n // 3. 삭제 대상 목록 출력\n p.log.info(`삭제 대상 파일 (${targetFiles.length}개):\\n${targetFiles.map((f) => ` ${f}`).join('\\n')}`);\n\n // 4. confirm\n const confirmed = await p.confirm({\n message: '위 파일과 manifest를 모두 삭제하시겠습니까?',\n initialValue: false,\n });\n if (p.isCancel(confirmed) || !confirmed) {\n p.cancel('취소됨');\n process.exit(0);\n }\n\n // 5. 파일 삭제\n const result = removeFiles(basePath, targetFiles);\n\n // 6. 빈 디렉토리 정리\n const dirs = collectManagedDirs(targetFiles);\n const removedDirs = cleanEmptyDirs(basePath, dirs);\n\n // 7. manifest 삭제\n rmSync(manifestPath, { force: true });\n\n // 8. 결과 요약\n if (result.deleted.length > 0) {\n p.log.success(`삭제 완료 (${result.deleted.length}개):\\n${result.deleted.map((f) => ` ${f}`).join('\\n')}`);\n }\n if (result.cleaned.length > 0) {\n p.log.success(\n `섹션 제거 완료 (사용자 내용 보존, ${result.cleaned.length}개):\\n${result.cleaned.map((f) => ` ${f}`).join('\\n')}`,\n );\n }\n if (result.skipped.length > 0) {\n p.log.warn(\n `건너뜀 (non-managed 파일 보호, ${result.skipped.length}개):\\n${result.skipped.map((f) => ` ${f}`).join('\\n')}`,\n );\n }\n if (result.notFound.length > 0) {\n p.log.info(`이미 없음 (${result.notFound.length}개):\\n${result.notFound.map((f) => ` ${f}`).join('\\n')}`);\n }\n if (removedDirs.length > 0) {\n p.log.info(`빈 디렉토리 정리 (${removedDirs.length}개):\\n${removedDirs.map((d) => ` ${d}`).join('\\n')}`);\n }\n\n p.log.success(`manifest 삭제: ${MANIFEST_FILENAME}`);\n p.outro('ai-ops uninstall 완료');\n};\n","import { existsSync, readFileSync, rmSync, readdirSync, writeFileSync } from 'node:fs';\nimport { resolve, dirname } from 'node:path';\nimport { isManagedFile, hasAiOpsSection, stripAiOpsSection } from '@/core/index.js';\n\nexport type UninstallResult = {\n deleted: string[];\n cleaned: string[]; // 섹션만 제거된 파일 (append 되었던 파일)\n skipped: string[]; // non-managed 파일 (사용자 파일 보호)\n notFound: string[]; // 이미 삭제됨\n};\n\nexport const removeFiles = (basePath: string, relativePaths: readonly string[]): UninstallResult => {\n const deleted: string[] = [];\n const cleaned: string[] = [];\n const skipped: string[] = [];\n const notFound: string[] = [];\n\n for (const rel of relativePaths) {\n const absPath = resolve(basePath, rel);\n\n if (!existsSync(absPath)) {\n notFound.push(rel);\n continue;\n }\n\n const content = readFileSync(absPath, 'utf-8');\n\n if (!isManagedFile(content)) {\n if (hasAiOpsSection(content)) {\n // append된 파일 → 섹션만 제거, 사용자 콘텐츠 보존\n const stripped = stripAiOpsSection(content);\n writeFileSync(absPath, stripped, 'utf-8');\n cleaned.push(rel);\n } else {\n skipped.push(rel);\n }\n continue;\n }\n\n rmSync(absPath);\n deleted.push(rel);\n }\n\n return { deleted, cleaned, skipped, notFound };\n};\n\n/** 대상 디렉토리가 비어 있으면 삭제하고, 삭제한 경로 배열 반환 */\nexport const cleanEmptyDirs = (basePath: string, dirs: readonly string[]): string[] => {\n const removed: string[] = [];\n\n for (const dir of dirs) {\n const absDir = resolve(basePath, dir);\n if (!existsSync(absDir)) continue;\n\n try {\n const entries = readdirSync(absDir);\n if (entries.length === 0) {\n rmSync(absDir, { recursive: true });\n removed.push(dir);\n }\n } catch {\n // 삭제 실패는 무시\n }\n }\n\n return removed;\n};\n\n/** manifest의 installed_files에서 정리 대상 디렉토리 목록 추출 */\nexport const collectManagedDirs = (relativePaths: readonly string[]): string[] => {\n const dirs = new Set<string>();\n for (const rel of relativePaths) {\n const dir = dirname(rel);\n if (dir !== '.') {\n dirs.add(dir);\n }\n }\n return [...dirs];\n};\n"],"mappings":"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","names":["p","join","z","z","z","p","global","domain","readFileSync","readdirSync","resolve","readdirSync","readFileSync","resolve","readFileSync","join","join","readFileSync","join","join","join","join","dirname","resolve","join","join","readdirSync","join","resolve","existsSync","mkdirSync","readFileSync","writeFileSync","dirname","resolve","resolve","existsSync","readFileSync","writeFileSync","mkdirSync","dirname","existsSync","mkdirSync","readFileSync","writeFileSync","join","p","existsSync","mkdirSync","readFileSync","writeFileSync","join","SETTING_GROUPS","deepMerge","join","r","p","join","r","join","p","p","rmSync","existsSync","readFileSync","readdirSync","writeFileSync","resolve","dirname","resolve","existsSync","readFileSync","writeFileSync","readdirSync","dirname","rmSync"]}
|