oh-my-customcode 0.47.1 → 0.48.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -13,7 +13,7 @@
13
13
 
14
14
  **[한국어 문서 (Korean)](./README_ko.md)**
15
15
 
16
- 45 agents. 83 skills. 21 rules. One command.
16
+ 45 agents. 84 skills. 21 rules. One command.
17
17
 
18
18
  ```bash
19
19
  npm install -g oh-my-customcode && cd your-project && omcustom init
@@ -138,7 +138,7 @@ Each agent declares its tools, model, memory scope, and limitations in YAML fron
138
138
 
139
139
  ---
140
140
 
141
- ### Skills (83)
141
+ ### Skills (84)
142
142
 
143
143
  | Category | Count | Includes |
144
144
  |----------|-------|----------|
@@ -272,7 +272,7 @@ your-project/
272
272
  ├── CLAUDE.md # Entry point
273
273
  ├── .claude/
274
274
  │ ├── agents/ # 45 agent definitions
275
- │ ├── skills/ # 83 skill modules
275
+ │ ├── skills/ # 84 skill modules
276
276
  │ ├── rules/ # 21 governance rules (R000-R021)
277
277
  │ ├── hooks/ # 15 lifecycle hook scripts
278
278
  │ ├── schemas/ # Tool input validation schemas
package/dist/cli/index.js CHANGED
@@ -9323,7 +9323,7 @@ var init_package = __esm(() => {
9323
9323
  package_default = {
9324
9324
  name: "oh-my-customcode",
9325
9325
  workspaces: ["packages/*"],
9326
- version: "0.47.1",
9326
+ version: "0.48.0",
9327
9327
  description: "Batteries-included agent harness for Claude Code",
9328
9328
  type: "module",
9329
9329
  bin: {
@@ -29784,6 +29784,7 @@ function runForeground(projectRoot, port, buildDirOpts) {
29784
29784
  init_package();
29785
29785
 
29786
29786
  // src/core/updater.ts
29787
+ init_package();
29787
29788
  init_fs();
29788
29789
  import { join as join14 } from "node:path";
29789
29790
 
@@ -30093,12 +30094,28 @@ async function runFullUpdatePostProcessing(options, result, config) {
30093
30094
  });
30094
30095
  }
30095
30096
  }
30097
+ function compareSemver2(a, b) {
30098
+ const pa = a.split(".").map(Number);
30099
+ const pb = b.split(".").map(Number);
30100
+ for (let i = 0;i < 3; i++) {
30101
+ const diff = (pa[i] ?? 0) - (pb[i] ?? 0);
30102
+ if (diff !== 0)
30103
+ return diff;
30104
+ }
30105
+ return 0;
30106
+ }
30096
30107
  async function update(options) {
30097
30108
  const result = createUpdateResult();
30098
30109
  try {
30099
30110
  info("update.start", { targetDir: options.targetDir });
30100
30111
  const config = await loadConfig(options.targetDir);
30101
30112
  result.previousVersion = config.version;
30113
+ const cliVersion = package_default.version;
30114
+ if (result.previousVersion !== "0.0.0" && compareSemver2(result.previousVersion, cliVersion) > 0) {
30115
+ result.success = false;
30116
+ result.error = `Downgrade prevented: project has v${result.previousVersion} but CLI is v${cliVersion}. Update the CLI first: npm install -g oh-my-customcode@latest`;
30117
+ return result;
30118
+ }
30102
30119
  const targetPkgPath = join14(options.targetDir, "package.json");
30103
30120
  if (await fileExists(targetPkgPath)) {
30104
30121
  const targetPkg = await readJsonFile(targetPkgPath);
@@ -30449,8 +30466,8 @@ async function updateAllProjects(options) {
30449
30466
  };
30450
30467
  const result = await update(updateOptions);
30451
30468
  if (result.success) {
30452
- const from = project.version ?? "unknown";
30453
- const to = currentVersion;
30469
+ const from = result.previousVersion || project.version || "unknown";
30470
+ const to = result.newVersion || currentVersion;
30454
30471
  console.log(i18n.t("cli.update.allProjectUpdated", { from, to }));
30455
30472
  updatedCount++;
30456
30473
  } else {
package/dist/index.js CHANGED
@@ -1637,8 +1637,98 @@ async function detectProvider(_options = {}) {
1637
1637
  };
1638
1638
  }
1639
1639
  // src/core/updater.ts
1640
- init_fs();
1641
1640
  import { join as join6 } from "node:path";
1641
+ // package.json
1642
+ var package_default = {
1643
+ name: "oh-my-customcode",
1644
+ workspaces: ["packages/*"],
1645
+ version: "0.48.0",
1646
+ description: "Batteries-included agent harness for Claude Code",
1647
+ type: "module",
1648
+ bin: {
1649
+ omcustom: "./dist/cli/index.js"
1650
+ },
1651
+ main: "./dist/index.js",
1652
+ types: "./dist/index.d.ts",
1653
+ exports: {
1654
+ ".": {
1655
+ import: "./dist/index.js",
1656
+ types: "./dist/index.d.ts"
1657
+ }
1658
+ },
1659
+ files: [
1660
+ "dist",
1661
+ "templates"
1662
+ ],
1663
+ publishConfig: {
1664
+ access: "public",
1665
+ registry: "https://registry.npmjs.org/"
1666
+ },
1667
+ scripts: {
1668
+ dev: "bun run src/cli/index.ts",
1669
+ build: "bun build src/cli/index.ts --outdir dist/cli --target node && bun build src/index.ts --outdir dist --target node && bun run scripts/sync-source-lockfile.ts",
1670
+ test: "bun test",
1671
+ "test:unit": "bun test tests/unit",
1672
+ "test:integration": "bun test tests/integration",
1673
+ "test:e2e": "bun test tests/e2e",
1674
+ "test:coverage": "bun test --coverage",
1675
+ lint: "biome check src/ tests/ scripts/",
1676
+ "lint:fix": "biome check --write src/ tests/ scripts/",
1677
+ format: "biome format --write src/ tests/ scripts/",
1678
+ typecheck: "tsc --noEmit",
1679
+ "docs:dev": "vitepress dev docs",
1680
+ "docs:build": "vitepress build docs",
1681
+ prepare: "sh scripts/setup-hooks.sh || true",
1682
+ "setup:hooks": "sh scripts/setup-hooks.sh",
1683
+ prepublishOnly: "bun run build && bun run test"
1684
+ },
1685
+ dependencies: {
1686
+ "@clack/prompts": "^1.1.0",
1687
+ "@inquirer/prompts": "^8.3.2",
1688
+ commander: "^14.0.2",
1689
+ i18next: "^25.8.0",
1690
+ yaml: "^2.8.2"
1691
+ },
1692
+ devDependencies: {
1693
+ "@anthropic-ai/sdk": "^0.78.0",
1694
+ "@biomejs/biome": "^2.3.12",
1695
+ "@types/bun": "^1.3.6",
1696
+ "@types/js-yaml": "^4.0.9",
1697
+ "@types/nodemailer": "^7.0.9",
1698
+ "js-yaml": "^4.1.0",
1699
+ nodemailer: "^8.0.1",
1700
+ typescript: "^5.7.3",
1701
+ vitepress: "^1.6.4"
1702
+ },
1703
+ keywords: [
1704
+ "claude",
1705
+ "claude-code",
1706
+ "openai",
1707
+ "ai",
1708
+ "agent",
1709
+ "cli"
1710
+ ],
1711
+ author: "baekenough",
1712
+ license: "MIT",
1713
+ repository: {
1714
+ type: "git",
1715
+ url: "git+https://github.com/baekenough/oh-my-customcode.git"
1716
+ },
1717
+ bugs: {
1718
+ url: "https://github.com/baekenough/oh-my-customcode/issues"
1719
+ },
1720
+ homepage: "https://github.com/baekenough/oh-my-customcode#readme",
1721
+ engines: {
1722
+ node: ">=18.0.0"
1723
+ },
1724
+ overrides: {
1725
+ rollup: "^4.59.0",
1726
+ esbuild: "^0.25.0"
1727
+ }
1728
+ };
1729
+
1730
+ // src/core/updater.ts
1731
+ init_fs();
1642
1732
 
1643
1733
  // src/core/entry-merger.ts
1644
1734
  var MANAGED_START = "<!-- omcustom:start -->";
@@ -1946,12 +2036,28 @@ async function runFullUpdatePostProcessing(options, result, config) {
1946
2036
  });
1947
2037
  }
1948
2038
  }
2039
+ function compareSemver(a, b) {
2040
+ const pa = a.split(".").map(Number);
2041
+ const pb = b.split(".").map(Number);
2042
+ for (let i = 0;i < 3; i++) {
2043
+ const diff = (pa[i] ?? 0) - (pb[i] ?? 0);
2044
+ if (diff !== 0)
2045
+ return diff;
2046
+ }
2047
+ return 0;
2048
+ }
1949
2049
  async function update(options) {
1950
2050
  const result = createUpdateResult();
1951
2051
  try {
1952
2052
  info("update.start", { targetDir: options.targetDir });
1953
2053
  const config = await loadConfig(options.targetDir);
1954
2054
  result.previousVersion = config.version;
2055
+ const cliVersion = package_default.version;
2056
+ if (result.previousVersion !== "0.0.0" && compareSemver(result.previousVersion, cliVersion) > 0) {
2057
+ result.success = false;
2058
+ result.error = `Downgrade prevented: project has v${result.previousVersion} but CLI is v${cliVersion}. Update the CLI first: npm install -g oh-my-customcode@latest`;
2059
+ return result;
2060
+ }
1955
2061
  const targetPkgPath = join6(options.targetDir, "package.json");
1956
2062
  if (await fileExists(targetPkgPath)) {
1957
2063
  const targetPkg = await readJsonFile(targetPkgPath);
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "oh-my-customcode",
3
3
  "workspaces": ["packages/*"],
4
- "version": "0.47.1",
4
+ "version": "0.48.0",
5
5
  "description": "Batteries-included agent harness for Claude Code",
6
6
  "type": "module",
7
7
  "bin": {
@@ -139,7 +139,7 @@
139
139
  },
140
140
  {
141
141
  "type": "command",
142
- "command": "count_file=\"/tmp/.claude-loop-count-$PPID\"; if [ -f \"$count_file\" ]; then last_mod=$(stat -f%m \"$count_file\" 2>/dev/null || echo 0); now=$(date +%s); if [ $((now - last_mod)) -gt 60 ]; then echo 0 > \"$count_file\"; fi; fi; count=$(cat \"$count_file\" 2>/dev/null || echo 0); count=$((count + 1)); echo \"$count\" > \"$count_file\"; if [ \"$count\" -ge 4 ]; then echo '[AutoContinue] SAFETY: auto-continue limit (3) reached. Pausing.' >&2; fi; cat"
142
+ "command": "count_file=\"/tmp/.claude-loop-count-$PPID\"; if [ -f \"$count_file\" ]; then last_mod=$(stat -c%Y \"$count_file\" 2>/dev/null || stat -f%m \"$count_file\" 2>/dev/null || echo 0); now=$(date +%s); if [ $((now - last_mod)) -gt 60 ]; then echo 0 > \"$count_file\"; fi; fi; count=$(cat \"$count_file\" 2>/dev/null || echo 0); count=$((count + 1)); echo \"$count\" > \"$count_file\"; if [ \"$count\" -ge 4 ]; then echo '[AutoContinue] SAFETY: auto-continue limit (3) reached. Pausing.' >&2; fi; cat"
143
143
  },
144
144
  {
145
145
  "type": "prompt",
@@ -0,0 +1,96 @@
1
+ ---
2
+ name: deep-verify
3
+ description: Multi-angle release quality verification using parallel expert review teams
4
+ scope: core
5
+ version: 1.0.0
6
+ user-invocable: true
7
+ effort: high
8
+ ---
9
+
10
+ # /deep-verify — Multi-Angle Release Quality Verification
11
+
12
+ ## Purpose
13
+
14
+ Performs deep cross-iterative verification of code changes before release, using multiple independent review perspectives to catch issues that single-pass review misses.
15
+
16
+ ## Usage
17
+
18
+ ```
19
+ /deep-verify [branch|PR]
20
+ ```
21
+
22
+ If no argument, verifies current branch against its base (usually `develop`).
23
+
24
+ ## Workflow
25
+
26
+ ### Round 1: Baseline Assessment
27
+ - Gather the full diff (`git diff develop...HEAD`)
28
+ - Run test suite, lint, and type check
29
+ - Collect results as baseline
30
+
31
+ ### Round 2: Parallel Expert Review (4 agents)
32
+ Spawn 4 parallel review agents, each with a different focus:
33
+
34
+ 1. **Correctness Reviewer** — Logic errors, edge cases, off-by-one, null handling
35
+ 2. **Security Reviewer** — Injection, auth bypass, data exposure, OWASP top 10
36
+ 3. **Performance Reviewer** — O(n^2) loops, unbounded queries, memory leaks, missing indexes
37
+ 4. **Integration Reviewer** — API contract breaks, migration safety, cross-module side effects
38
+
39
+ Each agent receives the full diff and returns findings as structured JSON:
40
+ ```json
41
+ {
42
+ "severity": "HIGH|MEDIUM|LOW",
43
+ "file": "path/to/file",
44
+ "line": 42,
45
+ "finding": "description",
46
+ "suggestion": "fix suggestion"
47
+ }
48
+ ```
49
+
50
+ ### Round 3: Cross-Verification
51
+ - Merge all findings from Round 2
52
+ - Deduplicate (same file+line+similar finding = 1 entry)
53
+ - For each HIGH finding: spawn a verification agent to confirm or dismiss as FALSE POSITIVE
54
+ - Evidence-based: each confirmation must include proof (e.g., `toQuery()` output, test result)
55
+
56
+ ### Round 4: FALSE POSITIVE Filter
57
+ - Remove confirmed false positives with evidence
58
+ - Remaining findings are CONFIRMED issues
59
+
60
+ ### Round 5: Fix Application
61
+ - For each CONFIRMED HIGH/MEDIUM finding: spawn fix agent
62
+ - Run tests after fixes
63
+ - If tests fail: revert fix, report as "needs manual review"
64
+
65
+ ### Round 6: Final Verification
66
+ - Re-run full test suite
67
+ - Re-run lint and type check
68
+ - Generate summary report
69
+
70
+ ## Output Format
71
+
72
+ ```
73
+ ╔══════════════════════════════════════════════════════╗
74
+ ║ Deep Verification Report ║
75
+ ╠══════════════════════════════════════════════════════╣
76
+ ║ Branch: {branch} ║
77
+ ║ Commits: {count} ║
78
+ ║ Files changed: {count} ║
79
+ ╠══════════════════════════════════════════════════════╣
80
+ ║ Findings: ║
81
+ ║ HIGH: {n} ({confirmed} confirmed, {fp} FP) ║
82
+ ║ MEDIUM: {n} ({confirmed} confirmed, {fp} FP) ║
83
+ ║ LOW: {n} ║
84
+ ╠══════════════════════════════════════════════════════╣
85
+ ║ Fixes Applied: {n} ║
86
+ ║ Tests: {pass}/{total} passing ║
87
+ ║ Verdict: READY / NEEDS REVIEW / BLOCKED ║
88
+ ╚══════════════════════════════════════════════════════╝
89
+ ```
90
+
91
+ ## Notes
92
+
93
+ - Round 2 agents use `model: sonnet` for cost efficiency
94
+ - Round 3 verification agents use `model: opus` for reasoning depth
95
+ - FALSE POSITIVE filtering is critical — previous releases showed 80%+ FP rate on automated review
96
+ - This skill replaces ad-hoc cross-verification with a repeatable process
@@ -120,6 +120,7 @@ oh-my-customcode로 구동됩니다.
120
120
  | `/optimize-report` | 최적화 리포트 생성 |
121
121
  | `/research` | 10-team 병렬 딥 분석 및 교차 검증 |
122
122
  | `/deep-plan` | 연구 검증 기반 계획 수립 (research → plan → verify) |
123
+ | `/deep-verify` | 다중 관점 릴리즈 품질 검증 |
123
124
  | `/omcustom:sauron-watch` | 전체 R017 검증 |
124
125
  | `/structured-dev-cycle` | 6단계 구조적 개발 사이클 (Plan → Verify → Implement → Verify → Compound → Done) |
125
126
  | `/omcustom:loop` | 백그라운드 에이전트 자동 계속 실행 |
@@ -134,7 +135,7 @@ project/
134
135
  +-- CLAUDE.md # 진입점
135
136
  +-- .claude/
136
137
  | +-- agents/ # 서브에이전트 정의 (45 파일)
137
- | +-- skills/ # 스킬 (83 디렉토리)
138
+ | +-- skills/ # 스킬 (84 디렉토리)
138
139
  | +-- rules/ # 전역 규칙 (R000-R021)
139
140
  | +-- hooks/ # 훅 스크립트 (보안, 검증, HUD)
140
141
  | +-- contexts/ # 컨텍스트 파일 (ecomode)
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "0.47.1",
2
+ "version": "0.48.0",
3
3
  "lastUpdated": "2026-03-16T00:00:00.000Z",
4
4
  "components": [
5
5
  {
@@ -18,7 +18,7 @@
18
18
  "name": "skills",
19
19
  "path": ".claude/skills",
20
20
  "description": "Reusable skill modules (includes slash commands)",
21
- "files": 83
21
+ "files": 84
22
22
  },
23
23
  {
24
24
  "name": "guides",