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 +3 -3
- package/dist/cli/index.js +20 -3
- package/dist/index.js +107 -1
- package/package.json +1 -1
- package/templates/.claude/hooks/hooks.json +1 -1
- package/templates/.claude/skills/deep-verify/SKILL.md +96 -0
- package/templates/CLAUDE.md +2 -1
- package/templates/manifest.json +2 -2
package/README.md
CHANGED
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
|
|
14
14
|
**[한국어 문서 (Korean)](./README_ko.md)**
|
|
15
15
|
|
|
16
|
-
45 agents.
|
|
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 (
|
|
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/ #
|
|
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.
|
|
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
|
|
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
|
@@ -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
|
package/templates/CLAUDE.md
CHANGED
|
@@ -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/ # 스킬 (
|
|
138
|
+
| +-- skills/ # 스킬 (84 디렉토리)
|
|
138
139
|
| +-- rules/ # 전역 규칙 (R000-R021)
|
|
139
140
|
| +-- hooks/ # 훅 스크립트 (보안, 검증, HUD)
|
|
140
141
|
| +-- contexts/ # 컨텍스트 파일 (ecomode)
|
package/templates/manifest.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "0.
|
|
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":
|
|
21
|
+
"files": 84
|
|
22
22
|
},
|
|
23
23
|
{
|
|
24
24
|
"name": "guides",
|