oh-my-customcodex 0.5.1 → 0.5.2
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 +2 -2
- package/dist/cli/index.js +168 -13
- package/dist/index.js +150 -8
- package/package.json +1 -1
- package/templates/.claude/agents/qa-engineer.md +7 -0
- package/templates/.claude/hooks/hooks.json +28 -0
- package/templates/.claude/hooks/scripts/agent-capability-precheck.sh +99 -0
- package/templates/.claude/hooks/scripts/agent-mode-guard.sh +14 -3
- package/templates/.claude/hooks/scripts/git-delegation-guard.sh +14 -5
- package/templates/.claude/hooks/scripts/plugin-cache-check.sh +42 -0
- package/templates/.claude/hooks/scripts/session-reflection.sh +106 -0
- package/templates/.claude/output-styles/korean-engineer.md +4 -0
- package/templates/.claude/rules/MUST-agent-identification.md +50 -22
- package/templates/.claude/rules/MUST-agent-teams.md +6 -2
- package/templates/.claude/rules/MUST-completion-verification.md +11 -0
- package/templates/.claude/rules/MUST-continuous-improvement.md +15 -1
- package/templates/.claude/rules/MUST-intent-transparency.md +29 -0
- package/templates/.claude/rules/MUST-language-policy.md +7 -0
- package/templates/.claude/rules/MUST-orchestrator-coordination.md +62 -0
- package/templates/.claude/rules/MUST-tool-identification.md +19 -0
- package/templates/.claude/rules/SHOULD-memory-integration.md +7 -2
- package/templates/.claude/skills/systematic-debugging/SKILL.md +44 -0
- package/templates/.claude/skills/systematic-debugging/phases/amplification-detection.md +25 -0
- package/templates/.claude/skills/systematic-debugging/phases/fault-injection.md +31 -0
- package/templates/.claude/skills/systematic-debugging/phases/retry-cache-timeout-audit.md +27 -0
- package/templates/.claude/skills/systematic-debugging/phases/timeline-correlation.md +26 -0
- package/templates/.claude/statusline.sh +40 -9
- package/templates/AGENTS.md.en +1 -1
- package/templates/AGENTS.md.ko +1 -1
- package/templates/CLAUDE.md +1 -1
- package/templates/CLAUDE.md.en +1 -1
- package/templates/CLAUDE.md.ko +1 -1
- package/templates/README.md +4 -4
- package/templates/guides/agent-teams/troubleshooting.md +53 -0
- package/templates/guides/autonomous-challenge-lessons/README.md +43 -0
- package/templates/guides/claude-code/15-version-compatibility.md +51 -0
- package/templates/guides/claude-code-tracking.md +51 -0
- package/templates/guides/index.yaml +12 -0
- package/templates/manifest.json +3 -3
- package/templates/tests/tsconfig.json +7 -0
package/README.md
CHANGED
|
@@ -228,7 +228,7 @@ Key rules: R010 (orchestrator never writes files), R009 (parallel execution mand
|
|
|
228
228
|
|
|
229
229
|
---
|
|
230
230
|
|
|
231
|
-
### Guides (
|
|
231
|
+
### Guides (50)
|
|
232
232
|
|
|
233
233
|
Reference documentation covering best practices, architecture decisions, and integration patterns. Located in `guides/` at project root, covering topics from agent design to CI/CD to observability.
|
|
234
234
|
|
|
@@ -288,7 +288,7 @@ your-project/
|
|
|
288
288
|
│ └── ontology/ # Knowledge graph for RAG
|
|
289
289
|
├── .agents/
|
|
290
290
|
│ └── skills/ # 123 installed skill modules
|
|
291
|
-
└── guides/ #
|
|
291
|
+
└── guides/ # 50 reference documents
|
|
292
292
|
```
|
|
293
293
|
|
|
294
294
|
### Source Repository And Compatibility Surfaces
|
package/dist/cli/index.js
CHANGED
|
@@ -3091,7 +3091,7 @@ var init_package = __esm(() => {
|
|
|
3091
3091
|
workspaces: [
|
|
3092
3092
|
"packages/*"
|
|
3093
3093
|
],
|
|
3094
|
-
version: "0.5.
|
|
3094
|
+
version: "0.5.2",
|
|
3095
3095
|
requiresCC: ">=2.1.121",
|
|
3096
3096
|
claudeCode: {
|
|
3097
3097
|
minimumVersion: "2.1.121",
|
|
@@ -26977,6 +26977,7 @@ init_lockfile();
|
|
|
26977
26977
|
init_logger();
|
|
26978
26978
|
import { execSync as execSync4 } from "node:child_process";
|
|
26979
26979
|
import { platform as platform2 } from "node:os";
|
|
26980
|
+
var MINIMUM_OMX_VERSION = "0.18.0";
|
|
26980
26981
|
var defaultDeps2 = {
|
|
26981
26982
|
exec: execSync4,
|
|
26982
26983
|
getPlatform: platform2
|
|
@@ -27000,11 +27001,116 @@ function getOmxVersion(deps = defaultDeps2) {
|
|
|
27000
27001
|
return null;
|
|
27001
27002
|
}
|
|
27002
27003
|
}
|
|
27004
|
+
function parseOmxVersion(versionOutput) {
|
|
27005
|
+
if (!versionOutput) {
|
|
27006
|
+
return null;
|
|
27007
|
+
}
|
|
27008
|
+
const match = versionOutput.match(/\bv?(\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?)\b/);
|
|
27009
|
+
return match ? match[1] : null;
|
|
27010
|
+
}
|
|
27011
|
+
function parseVersionParts(version) {
|
|
27012
|
+
const [withoutBuild] = version.split("+");
|
|
27013
|
+
const [coreText, prerelease = null] = withoutBuild.split("-", 2);
|
|
27014
|
+
const coreParts = coreText.split(".").map((part) => Number.parseInt(part, 10));
|
|
27015
|
+
return {
|
|
27016
|
+
core: [coreParts[0] ?? 0, coreParts[1] ?? 0, coreParts[2] ?? 0],
|
|
27017
|
+
prerelease
|
|
27018
|
+
};
|
|
27019
|
+
}
|
|
27020
|
+
function compareOmxVersions(left, right) {
|
|
27021
|
+
const a = parseVersionParts(left);
|
|
27022
|
+
const b = parseVersionParts(right);
|
|
27023
|
+
for (let index = 0;index < 3; index += 1) {
|
|
27024
|
+
const diff = a.core[index] - b.core[index];
|
|
27025
|
+
if (diff !== 0) {
|
|
27026
|
+
return diff > 0 ? 1 : -1;
|
|
27027
|
+
}
|
|
27028
|
+
}
|
|
27029
|
+
if (a.prerelease === b.prerelease) {
|
|
27030
|
+
return 0;
|
|
27031
|
+
}
|
|
27032
|
+
if (a.prerelease === null) {
|
|
27033
|
+
return 1;
|
|
27034
|
+
}
|
|
27035
|
+
if (b.prerelease === null) {
|
|
27036
|
+
return -1;
|
|
27037
|
+
}
|
|
27038
|
+
return a.prerelease.localeCompare(b.prerelease, undefined, { numeric: true });
|
|
27039
|
+
}
|
|
27040
|
+
function hasOmxApiCommand(deps = defaultDeps2) {
|
|
27041
|
+
try {
|
|
27042
|
+
deps.exec("omx api --help", {
|
|
27043
|
+
encoding: "utf-8",
|
|
27044
|
+
stdio: "pipe",
|
|
27045
|
+
timeout: 3000
|
|
27046
|
+
});
|
|
27047
|
+
return true;
|
|
27048
|
+
} catch {
|
|
27049
|
+
return false;
|
|
27050
|
+
}
|
|
27051
|
+
}
|
|
27052
|
+
function assessOmxInstallation(deps = defaultDeps2) {
|
|
27053
|
+
if (!isOmxInstalled(deps)) {
|
|
27054
|
+
return {
|
|
27055
|
+
status: "missing",
|
|
27056
|
+
installed: false,
|
|
27057
|
+
version: null,
|
|
27058
|
+
parsedVersion: null,
|
|
27059
|
+
minimumVersion: MINIMUM_OMX_VERSION,
|
|
27060
|
+
hasApiCommand: false
|
|
27061
|
+
};
|
|
27062
|
+
}
|
|
27063
|
+
const version = getOmxVersion(deps);
|
|
27064
|
+
const parsedVersion = parseOmxVersion(version);
|
|
27065
|
+
if (parsedVersion && compareOmxVersions(parsedVersion, MINIMUM_OMX_VERSION) < 0) {
|
|
27066
|
+
return {
|
|
27067
|
+
status: "stale",
|
|
27068
|
+
installed: true,
|
|
27069
|
+
version,
|
|
27070
|
+
parsedVersion,
|
|
27071
|
+
minimumVersion: MINIMUM_OMX_VERSION,
|
|
27072
|
+
hasApiCommand: false
|
|
27073
|
+
};
|
|
27074
|
+
}
|
|
27075
|
+
const hasApi = hasOmxApiCommand(deps);
|
|
27076
|
+
if (parsedVersion && !hasApi) {
|
|
27077
|
+
return {
|
|
27078
|
+
status: "api-missing",
|
|
27079
|
+
installed: true,
|
|
27080
|
+
version,
|
|
27081
|
+
parsedVersion,
|
|
27082
|
+
minimumVersion: MINIMUM_OMX_VERSION,
|
|
27083
|
+
hasApiCommand: false
|
|
27084
|
+
};
|
|
27085
|
+
}
|
|
27086
|
+
if (!parsedVersion && !hasApi) {
|
|
27087
|
+
return {
|
|
27088
|
+
status: "unknown-version",
|
|
27089
|
+
installed: true,
|
|
27090
|
+
version,
|
|
27091
|
+
parsedVersion: null,
|
|
27092
|
+
minimumVersion: MINIMUM_OMX_VERSION,
|
|
27093
|
+
hasApiCommand: false
|
|
27094
|
+
};
|
|
27095
|
+
}
|
|
27096
|
+
return {
|
|
27097
|
+
status: "ready",
|
|
27098
|
+
installed: true,
|
|
27099
|
+
version,
|
|
27100
|
+
parsedVersion,
|
|
27101
|
+
minimumVersion: MINIMUM_OMX_VERSION,
|
|
27102
|
+
hasApiCommand: hasApi
|
|
27103
|
+
};
|
|
27104
|
+
}
|
|
27105
|
+
function isOmxReady(deps = defaultDeps2) {
|
|
27106
|
+
return assessOmxInstallation(deps).status === "ready";
|
|
27107
|
+
}
|
|
27003
27108
|
function installOmx(deps = defaultDeps2) {
|
|
27004
27109
|
if (process.env.CI || false || false) {
|
|
27005
27110
|
return false;
|
|
27006
27111
|
}
|
|
27007
|
-
|
|
27112
|
+
const current = assessOmxInstallation(deps);
|
|
27113
|
+
if (current.status === "ready") {
|
|
27008
27114
|
info("install.omx_already");
|
|
27009
27115
|
return true;
|
|
27010
27116
|
}
|
|
@@ -27015,11 +27121,11 @@ function installOmx(deps = defaultDeps2) {
|
|
|
27015
27121
|
}
|
|
27016
27122
|
try {
|
|
27017
27123
|
info("install.omx_installing");
|
|
27018
|
-
deps.exec("npm install -g oh-my-codex", {
|
|
27124
|
+
deps.exec("npm install -g oh-my-codex@latest", {
|
|
27019
27125
|
stdio: "inherit",
|
|
27020
27126
|
timeout: 120000
|
|
27021
27127
|
});
|
|
27022
|
-
return
|
|
27128
|
+
return isOmxReady(deps);
|
|
27023
27129
|
} catch (err) {
|
|
27024
27130
|
const message = err instanceof Error ? err.message : String(err);
|
|
27025
27131
|
warn("install.omx_install_failed", { error: message });
|
|
@@ -27428,7 +27534,8 @@ async function checkCodex() {
|
|
|
27428
27534
|
};
|
|
27429
27535
|
}
|
|
27430
27536
|
async function checkOmx() {
|
|
27431
|
-
|
|
27537
|
+
const omx = assessOmxInstallation();
|
|
27538
|
+
if (omx.status === "missing") {
|
|
27432
27539
|
return {
|
|
27433
27540
|
name: "OMX",
|
|
27434
27541
|
status: "warn",
|
|
@@ -27436,11 +27543,34 @@ async function checkOmx() {
|
|
|
27436
27543
|
fixable: true
|
|
27437
27544
|
};
|
|
27438
27545
|
}
|
|
27439
|
-
|
|
27546
|
+
if (omx.status === "stale") {
|
|
27547
|
+
return {
|
|
27548
|
+
name: "OMX",
|
|
27549
|
+
status: "warn",
|
|
27550
|
+
message: `OMX stale (${omx.version ?? "unknown version"}) — requires oh-my-codex v${MINIMUM_OMX_VERSION}+ with omx api`,
|
|
27551
|
+
fixable: true
|
|
27552
|
+
};
|
|
27553
|
+
}
|
|
27554
|
+
if (omx.status === "api-missing") {
|
|
27555
|
+
return {
|
|
27556
|
+
name: "OMX",
|
|
27557
|
+
status: "warn",
|
|
27558
|
+
message: `OMX missing required omx api command (${omx.version ?? "unknown version"}) — install oh-my-codex v${MINIMUM_OMX_VERSION}+`,
|
|
27559
|
+
fixable: true
|
|
27560
|
+
};
|
|
27561
|
+
}
|
|
27562
|
+
if (omx.status === "unknown-version") {
|
|
27563
|
+
return {
|
|
27564
|
+
name: "OMX",
|
|
27565
|
+
status: "warn",
|
|
27566
|
+
message: `OMX version could not be verified — requires oh-my-codex v${MINIMUM_OMX_VERSION}+ with omx api`,
|
|
27567
|
+
fixable: true
|
|
27568
|
+
};
|
|
27569
|
+
}
|
|
27440
27570
|
return {
|
|
27441
27571
|
name: "OMX",
|
|
27442
27572
|
status: "pass",
|
|
27443
|
-
message: `OMX OK (${version ?? "unknown version"})`,
|
|
27573
|
+
message: `OMX OK (${omx.version ?? "unknown version"}, omx api available)`,
|
|
27444
27574
|
fixable: false
|
|
27445
27575
|
};
|
|
27446
27576
|
}
|
|
@@ -27557,7 +27687,7 @@ async function fixSingleIssue(check, targetDir, rootDir = ".codex") {
|
|
|
27557
27687
|
async function fixIssues(checks, targetDir, rootDir = ".codex") {
|
|
27558
27688
|
const fixedChecks = [];
|
|
27559
27689
|
for (const check of checks) {
|
|
27560
|
-
if (check.status
|
|
27690
|
+
if (check.status === "pass" || !check.fixable) {
|
|
27561
27691
|
fixedChecks.push(check);
|
|
27562
27692
|
continue;
|
|
27563
27693
|
}
|
|
@@ -27717,7 +27847,7 @@ async function doctorCommand(options = {}) {
|
|
|
27717
27847
|
const checksWithUpdate = await runAllChecks(targetDir, layout, packageVersion, options.updates ?? false);
|
|
27718
27848
|
let checks = checksWithUpdate;
|
|
27719
27849
|
if (options.fix) {
|
|
27720
|
-
const hasFixableIssues = checksWithUpdate.some((c) => c.status
|
|
27850
|
+
const hasFixableIssues = checksWithUpdate.some((c) => c.status !== "pass" && c.fixable);
|
|
27721
27851
|
if (hasFixableIssues) {
|
|
27722
27852
|
console.log(i18n.t("cli.doctor.applyingFixes"));
|
|
27723
27853
|
console.log("");
|
|
@@ -28306,6 +28436,22 @@ async function installStatusline(targetDir, options, _result) {
|
|
|
28306
28436
|
await fs2.chmod(destPath, 493);
|
|
28307
28437
|
debug("install.statusline_installed", {});
|
|
28308
28438
|
}
|
|
28439
|
+
async function installTestsConfig(targetDir, options, _result) {
|
|
28440
|
+
const srcPath = resolveTemplatePath(join7("tests", "tsconfig.json"));
|
|
28441
|
+
const destPath = join7(targetDir, "tests", "tsconfig.json");
|
|
28442
|
+
if (!await fileExists(srcPath)) {
|
|
28443
|
+
debug("install.tests_config_not_found", { path: srcPath });
|
|
28444
|
+
return;
|
|
28445
|
+
}
|
|
28446
|
+
if (await fileExists(destPath)) {
|
|
28447
|
+
if (!options.force && !options.backup) {
|
|
28448
|
+
debug("install.tests_config_skipped", { reason: "exists" });
|
|
28449
|
+
return;
|
|
28450
|
+
}
|
|
28451
|
+
}
|
|
28452
|
+
await copyFile(srcPath, destPath);
|
|
28453
|
+
debug("install.tests_config_installed", {});
|
|
28454
|
+
}
|
|
28309
28455
|
async function installSettingsLocal(targetDir, result) {
|
|
28310
28456
|
const layout = getProviderLayout();
|
|
28311
28457
|
const settingsPath = join7(targetDir, layout.rootDir, "settings.local.json");
|
|
@@ -28382,13 +28528,15 @@ function installCodexIfNeeded(result) {
|
|
|
28382
28528
|
}
|
|
28383
28529
|
}
|
|
28384
28530
|
function installOmxIfNeeded(result) {
|
|
28385
|
-
|
|
28531
|
+
const omx = assessOmxInstallation();
|
|
28532
|
+
if (omx.status !== "ready") {
|
|
28386
28533
|
info("install.omx_installing");
|
|
28387
28534
|
const omxInstalled = installOmx();
|
|
28388
28535
|
if (omxInstalled) {
|
|
28389
28536
|
info("install.omx_success");
|
|
28390
28537
|
} else {
|
|
28391
|
-
|
|
28538
|
+
const versionDetail = omx.version ? ` (found ${omx.version})` : "";
|
|
28539
|
+
result.warnings.push(`OMX installation/upgrade failed${versionDetail} — install oh-my-codex >= v${MINIMUM_OMX_VERSION} manually: npm install -g oh-my-codex@latest`);
|
|
28392
28540
|
}
|
|
28393
28541
|
} else {
|
|
28394
28542
|
info("install.omx_already");
|
|
@@ -28404,6 +28552,7 @@ async function install(options) {
|
|
|
28404
28552
|
await verifyTemplateDirectory();
|
|
28405
28553
|
await installAllComponents(options.targetDir, options, result);
|
|
28406
28554
|
await installStatusline(options.targetDir, options, result);
|
|
28555
|
+
await installTestsConfig(options.targetDir, options, result);
|
|
28407
28556
|
await installSettingsLocal(options.targetDir, result);
|
|
28408
28557
|
await installEntryDocWithTracking(options.targetDir, options, result);
|
|
28409
28558
|
if (preservation) {
|
|
@@ -31529,9 +31678,15 @@ function checkAndInstallCodexAfterUpdate() {
|
|
|
31529
31678
|
}
|
|
31530
31679
|
}
|
|
31531
31680
|
function checkAndInstallOmxAfterUpdate() {
|
|
31532
|
-
|
|
31681
|
+
const omx = assessOmxInstallation();
|
|
31682
|
+
if (omx.status !== "ready") {
|
|
31533
31683
|
warn("update.omx_missing");
|
|
31534
|
-
|
|
31684
|
+
if (omx.status === "missing") {
|
|
31685
|
+
console.log(i18n.t("cli.update.omxMissing"));
|
|
31686
|
+
} else {
|
|
31687
|
+
const versionDetail = omx.version ? ` (${omx.version})` : "";
|
|
31688
|
+
console.log(`OMX${versionDetail} does not meet the oh-my-codex v${MINIMUM_OMX_VERSION} baseline. Attempting upgrade...`);
|
|
31689
|
+
}
|
|
31535
31690
|
const omxInstalled = installOmx();
|
|
31536
31691
|
if (omxInstalled) {
|
|
31537
31692
|
console.log(i18n.t("cli.update.omxInstalled"));
|
package/dist/index.js
CHANGED
|
@@ -1569,6 +1569,7 @@ init_lockfile();
|
|
|
1569
1569
|
init_logger();
|
|
1570
1570
|
import { execSync as execSync2 } from "node:child_process";
|
|
1571
1571
|
import { platform as platform2 } from "node:os";
|
|
1572
|
+
var MINIMUM_OMX_VERSION = "0.18.0";
|
|
1572
1573
|
var defaultDeps2 = {
|
|
1573
1574
|
exec: execSync2,
|
|
1574
1575
|
getPlatform: platform2
|
|
@@ -1581,11 +1582,127 @@ function isOmxInstalled(deps = defaultDeps2) {
|
|
|
1581
1582
|
return false;
|
|
1582
1583
|
}
|
|
1583
1584
|
}
|
|
1585
|
+
function getOmxVersion(deps = defaultDeps2) {
|
|
1586
|
+
try {
|
|
1587
|
+
return deps.exec("omx --version", {
|
|
1588
|
+
encoding: "utf-8",
|
|
1589
|
+
stdio: "pipe",
|
|
1590
|
+
timeout: 3000
|
|
1591
|
+
}).trim();
|
|
1592
|
+
} catch {
|
|
1593
|
+
return null;
|
|
1594
|
+
}
|
|
1595
|
+
}
|
|
1596
|
+
function parseOmxVersion(versionOutput) {
|
|
1597
|
+
if (!versionOutput) {
|
|
1598
|
+
return null;
|
|
1599
|
+
}
|
|
1600
|
+
const match = versionOutput.match(/\bv?(\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?)\b/);
|
|
1601
|
+
return match ? match[1] : null;
|
|
1602
|
+
}
|
|
1603
|
+
function parseVersionParts(version) {
|
|
1604
|
+
const [withoutBuild] = version.split("+");
|
|
1605
|
+
const [coreText, prerelease = null] = withoutBuild.split("-", 2);
|
|
1606
|
+
const coreParts = coreText.split(".").map((part) => Number.parseInt(part, 10));
|
|
1607
|
+
return {
|
|
1608
|
+
core: [coreParts[0] ?? 0, coreParts[1] ?? 0, coreParts[2] ?? 0],
|
|
1609
|
+
prerelease
|
|
1610
|
+
};
|
|
1611
|
+
}
|
|
1612
|
+
function compareOmxVersions(left, right) {
|
|
1613
|
+
const a = parseVersionParts(left);
|
|
1614
|
+
const b = parseVersionParts(right);
|
|
1615
|
+
for (let index = 0;index < 3; index += 1) {
|
|
1616
|
+
const diff = a.core[index] - b.core[index];
|
|
1617
|
+
if (diff !== 0) {
|
|
1618
|
+
return diff > 0 ? 1 : -1;
|
|
1619
|
+
}
|
|
1620
|
+
}
|
|
1621
|
+
if (a.prerelease === b.prerelease) {
|
|
1622
|
+
return 0;
|
|
1623
|
+
}
|
|
1624
|
+
if (a.prerelease === null) {
|
|
1625
|
+
return 1;
|
|
1626
|
+
}
|
|
1627
|
+
if (b.prerelease === null) {
|
|
1628
|
+
return -1;
|
|
1629
|
+
}
|
|
1630
|
+
return a.prerelease.localeCompare(b.prerelease, undefined, { numeric: true });
|
|
1631
|
+
}
|
|
1632
|
+
function hasOmxApiCommand(deps = defaultDeps2) {
|
|
1633
|
+
try {
|
|
1634
|
+
deps.exec("omx api --help", {
|
|
1635
|
+
encoding: "utf-8",
|
|
1636
|
+
stdio: "pipe",
|
|
1637
|
+
timeout: 3000
|
|
1638
|
+
});
|
|
1639
|
+
return true;
|
|
1640
|
+
} catch {
|
|
1641
|
+
return false;
|
|
1642
|
+
}
|
|
1643
|
+
}
|
|
1644
|
+
function assessOmxInstallation(deps = defaultDeps2) {
|
|
1645
|
+
if (!isOmxInstalled(deps)) {
|
|
1646
|
+
return {
|
|
1647
|
+
status: "missing",
|
|
1648
|
+
installed: false,
|
|
1649
|
+
version: null,
|
|
1650
|
+
parsedVersion: null,
|
|
1651
|
+
minimumVersion: MINIMUM_OMX_VERSION,
|
|
1652
|
+
hasApiCommand: false
|
|
1653
|
+
};
|
|
1654
|
+
}
|
|
1655
|
+
const version = getOmxVersion(deps);
|
|
1656
|
+
const parsedVersion = parseOmxVersion(version);
|
|
1657
|
+
if (parsedVersion && compareOmxVersions(parsedVersion, MINIMUM_OMX_VERSION) < 0) {
|
|
1658
|
+
return {
|
|
1659
|
+
status: "stale",
|
|
1660
|
+
installed: true,
|
|
1661
|
+
version,
|
|
1662
|
+
parsedVersion,
|
|
1663
|
+
minimumVersion: MINIMUM_OMX_VERSION,
|
|
1664
|
+
hasApiCommand: false
|
|
1665
|
+
};
|
|
1666
|
+
}
|
|
1667
|
+
const hasApi = hasOmxApiCommand(deps);
|
|
1668
|
+
if (parsedVersion && !hasApi) {
|
|
1669
|
+
return {
|
|
1670
|
+
status: "api-missing",
|
|
1671
|
+
installed: true,
|
|
1672
|
+
version,
|
|
1673
|
+
parsedVersion,
|
|
1674
|
+
minimumVersion: MINIMUM_OMX_VERSION,
|
|
1675
|
+
hasApiCommand: false
|
|
1676
|
+
};
|
|
1677
|
+
}
|
|
1678
|
+
if (!parsedVersion && !hasApi) {
|
|
1679
|
+
return {
|
|
1680
|
+
status: "unknown-version",
|
|
1681
|
+
installed: true,
|
|
1682
|
+
version,
|
|
1683
|
+
parsedVersion: null,
|
|
1684
|
+
minimumVersion: MINIMUM_OMX_VERSION,
|
|
1685
|
+
hasApiCommand: false
|
|
1686
|
+
};
|
|
1687
|
+
}
|
|
1688
|
+
return {
|
|
1689
|
+
status: "ready",
|
|
1690
|
+
installed: true,
|
|
1691
|
+
version,
|
|
1692
|
+
parsedVersion,
|
|
1693
|
+
minimumVersion: MINIMUM_OMX_VERSION,
|
|
1694
|
+
hasApiCommand: hasApi
|
|
1695
|
+
};
|
|
1696
|
+
}
|
|
1697
|
+
function isOmxReady(deps = defaultDeps2) {
|
|
1698
|
+
return assessOmxInstallation(deps).status === "ready";
|
|
1699
|
+
}
|
|
1584
1700
|
function installOmx(deps = defaultDeps2) {
|
|
1585
1701
|
if (process.env.CI || false || false) {
|
|
1586
1702
|
return false;
|
|
1587
1703
|
}
|
|
1588
|
-
|
|
1704
|
+
const current = assessOmxInstallation(deps);
|
|
1705
|
+
if (current.status === "ready") {
|
|
1589
1706
|
info("install.omx_already");
|
|
1590
1707
|
return true;
|
|
1591
1708
|
}
|
|
@@ -1596,11 +1713,11 @@ function installOmx(deps = defaultDeps2) {
|
|
|
1596
1713
|
}
|
|
1597
1714
|
try {
|
|
1598
1715
|
info("install.omx_installing");
|
|
1599
|
-
deps.exec("npm install -g oh-my-codex", {
|
|
1716
|
+
deps.exec("npm install -g oh-my-codex@latest", {
|
|
1600
1717
|
stdio: "inherit",
|
|
1601
1718
|
timeout: 120000
|
|
1602
1719
|
});
|
|
1603
|
-
return
|
|
1720
|
+
return isOmxReady(deps);
|
|
1604
1721
|
} catch (err) {
|
|
1605
1722
|
const message = err instanceof Error ? err.message : String(err);
|
|
1606
1723
|
warn("install.omx_install_failed", { error: message });
|
|
@@ -1796,6 +1913,22 @@ async function installStatusline(targetDir, options, _result) {
|
|
|
1796
1913
|
await fs.chmod(destPath, 493);
|
|
1797
1914
|
debug("install.statusline_installed", {});
|
|
1798
1915
|
}
|
|
1916
|
+
async function installTestsConfig(targetDir, options, _result) {
|
|
1917
|
+
const srcPath = resolveTemplatePath(join5("tests", "tsconfig.json"));
|
|
1918
|
+
const destPath = join5(targetDir, "tests", "tsconfig.json");
|
|
1919
|
+
if (!await fileExists(srcPath)) {
|
|
1920
|
+
debug("install.tests_config_not_found", { path: srcPath });
|
|
1921
|
+
return;
|
|
1922
|
+
}
|
|
1923
|
+
if (await fileExists(destPath)) {
|
|
1924
|
+
if (!options.force && !options.backup) {
|
|
1925
|
+
debug("install.tests_config_skipped", { reason: "exists" });
|
|
1926
|
+
return;
|
|
1927
|
+
}
|
|
1928
|
+
}
|
|
1929
|
+
await copyFile(srcPath, destPath);
|
|
1930
|
+
debug("install.tests_config_installed", {});
|
|
1931
|
+
}
|
|
1799
1932
|
async function installSettingsLocal(targetDir, result) {
|
|
1800
1933
|
const layout = getProviderLayout();
|
|
1801
1934
|
const settingsPath = join5(targetDir, layout.rootDir, "settings.local.json");
|
|
@@ -1872,13 +2005,15 @@ function installCodexIfNeeded(result) {
|
|
|
1872
2005
|
}
|
|
1873
2006
|
}
|
|
1874
2007
|
function installOmxIfNeeded(result) {
|
|
1875
|
-
|
|
2008
|
+
const omx = assessOmxInstallation();
|
|
2009
|
+
if (omx.status !== "ready") {
|
|
1876
2010
|
info("install.omx_installing");
|
|
1877
2011
|
const omxInstalled = installOmx();
|
|
1878
2012
|
if (omxInstalled) {
|
|
1879
2013
|
info("install.omx_success");
|
|
1880
2014
|
} else {
|
|
1881
|
-
|
|
2015
|
+
const versionDetail = omx.version ? ` (found ${omx.version})` : "";
|
|
2016
|
+
result.warnings.push(`OMX installation/upgrade failed${versionDetail} — install oh-my-codex >= v${MINIMUM_OMX_VERSION} manually: npm install -g oh-my-codex@latest`);
|
|
1882
2017
|
}
|
|
1883
2018
|
} else {
|
|
1884
2019
|
info("install.omx_already");
|
|
@@ -1894,6 +2029,7 @@ async function install(options) {
|
|
|
1894
2029
|
await verifyTemplateDirectory();
|
|
1895
2030
|
await installAllComponents(options.targetDir, options, result);
|
|
1896
2031
|
await installStatusline(options.targetDir, options, result);
|
|
2032
|
+
await installTestsConfig(options.targetDir, options, result);
|
|
1897
2033
|
await installSettingsLocal(options.targetDir, result);
|
|
1898
2034
|
await installEntryDocWithTracking(options.targetDir, options, result);
|
|
1899
2035
|
if (preservation) {
|
|
@@ -2180,7 +2316,7 @@ var package_default = {
|
|
|
2180
2316
|
workspaces: [
|
|
2181
2317
|
"packages/*"
|
|
2182
2318
|
],
|
|
2183
|
-
version: "0.5.
|
|
2319
|
+
version: "0.5.2",
|
|
2184
2320
|
requiresCC: ">=2.1.121",
|
|
2185
2321
|
claudeCode: {
|
|
2186
2322
|
minimumVersion: "2.1.121",
|
|
@@ -5124,9 +5260,15 @@ function checkAndInstallCodexAfterUpdate() {
|
|
|
5124
5260
|
}
|
|
5125
5261
|
}
|
|
5126
5262
|
function checkAndInstallOmxAfterUpdate() {
|
|
5127
|
-
|
|
5263
|
+
const omx = assessOmxInstallation();
|
|
5264
|
+
if (omx.status !== "ready") {
|
|
5128
5265
|
warn("update.omx_missing");
|
|
5129
|
-
|
|
5266
|
+
if (omx.status === "missing") {
|
|
5267
|
+
console.log(i18n.t("cli.update.omxMissing"));
|
|
5268
|
+
} else {
|
|
5269
|
+
const versionDetail = omx.version ? ` (${omx.version})` : "";
|
|
5270
|
+
console.log(`OMX${versionDetail} does not meet the oh-my-codex v${MINIMUM_OMX_VERSION} baseline. Attempting upgrade...`);
|
|
5271
|
+
}
|
|
5130
5272
|
const omxInstalled = installOmx();
|
|
5131
5273
|
if (omxInstalled) {
|
|
5132
5274
|
console.log(i18n.t("cli.update.omxInstalled"));
|
package/package.json
CHANGED
|
@@ -31,6 +31,13 @@ You are a QA execution specialist that runs tests, identifies defects, and valid
|
|
|
31
31
|
|
|
32
32
|
Jest, Vitest, pytest, go test, JUnit, Playwright, Cypress
|
|
33
33
|
|
|
34
|
+
## Evidence Requirements
|
|
35
|
+
|
|
36
|
+
- Before citing selectors, test IDs, CLI flags, mappings, function names, or config keys, read or grep the target code and quote the exact identifier.
|
|
37
|
+
- Do not invent `data-testid`, route, mapping, or flag names from memory.
|
|
38
|
+
- UI verification requires browser or screenshot evidence when a renderer is available; typecheck alone is not sufficient for visual completion.
|
|
39
|
+
- If only indirect evidence is available, label it as indirect and state the missing direct check.
|
|
40
|
+
|
|
34
41
|
## Collaboration
|
|
35
42
|
|
|
36
43
|
Receives from: qa-writer (test cases), qa-planner (priorities). Outputs to: dev-lead (defects), qa-writer (results).
|
|
@@ -129,6 +129,10 @@
|
|
|
129
129
|
"type": "command",
|
|
130
130
|
"command": "bash .codex/hooks/scripts/agent-mode-guard.sh"
|
|
131
131
|
},
|
|
132
|
+
{
|
|
133
|
+
"type": "command",
|
|
134
|
+
"command": "bash .codex/hooks/scripts/agent-capability-precheck.sh"
|
|
135
|
+
},
|
|
132
136
|
{
|
|
133
137
|
"type": "command",
|
|
134
138
|
"command": "#!/bin/bash\ninput=$(cat)\nagent_type=$(echo \"$input\" | jq -r '.tool_input.subagent_type // \"unknown\"')\nmodel=$(echo \"$input\" | jq -r '.tool_input.model // \"inherit\"')\ndesc=$(echo \"$input\" | jq -r '.tool_input.description // \"\"' | head -c 40)\nresume=$(echo \"$input\" | jq -r '.tool_input.resume // empty')\nif [ -n \"$resume\" ]; then\n echo \"─── [Resume] ${agent_type}:${model} | ${desc} ───\" >&2\nelse\n echo \"─── [Spawn] ${agent_type}:${model} | ${desc} ───\" >&2\nfi\necho \"$input\""
|
|
@@ -199,6 +203,16 @@
|
|
|
199
203
|
}
|
|
200
204
|
],
|
|
201
205
|
"description": "Auto-detect and fix previous session issues at start (#838)"
|
|
206
|
+
},
|
|
207
|
+
{
|
|
208
|
+
"matcher": "*",
|
|
209
|
+
"hooks": [
|
|
210
|
+
{
|
|
211
|
+
"type": "command",
|
|
212
|
+
"command": "bash .codex/hooks/scripts/plugin-cache-check.sh"
|
|
213
|
+
}
|
|
214
|
+
],
|
|
215
|
+
"description": "Advisory check for plugin cache directories missing node_modules (#1366)"
|
|
202
216
|
}
|
|
203
217
|
],
|
|
204
218
|
"UserPromptSubmit": [
|
|
@@ -255,6 +269,10 @@
|
|
|
255
269
|
"type": "command",
|
|
256
270
|
"command": "bash .codex/hooks/scripts/auto-continue-guard.sh"
|
|
257
271
|
},
|
|
272
|
+
{
|
|
273
|
+
"type": "command",
|
|
274
|
+
"command": "bash .codex/hooks/scripts/session-reflection.sh"
|
|
275
|
+
},
|
|
258
276
|
{
|
|
259
277
|
"type": "prompt",
|
|
260
278
|
"prompt": "A background subagent just completed. Check if there are pending workflow steps that depend on this result. If the previous subagent FAILED, do NOT auto-continue — report the failure and wait for user input. If the previous step succeeded and there are pending steps, proceed automatically. If no pending steps, report results and wait. Safety: The file /tmp/.codex-loop-count-$PPID tracks auto-continue count. After 3 consecutive auto-continues without user interaction, pause and ask the user before proceeding."
|
|
@@ -555,6 +573,16 @@
|
|
|
555
573
|
],
|
|
556
574
|
"description": "Batch-save agent outcomes to eval-core DB on session end (advisory, exit 0)"
|
|
557
575
|
},
|
|
576
|
+
{
|
|
577
|
+
"matcher": "*",
|
|
578
|
+
"hooks": [
|
|
579
|
+
{
|
|
580
|
+
"type": "command",
|
|
581
|
+
"command": "bash .codex/hooks/scripts/session-reflection.sh"
|
|
582
|
+
}
|
|
583
|
+
],
|
|
584
|
+
"description": "Capture session-end reflection from transcript, background_tasks, and session_crons (advisory, exit 0)"
|
|
585
|
+
},
|
|
558
586
|
{
|
|
559
587
|
"matcher": "*",
|
|
560
588
|
"hooks": [
|