triflux 10.9.21 → 10.9.23

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.
Files changed (100) hide show
  1. package/.claude-plugin/marketplace.json +34 -0
  2. package/.claude-plugin/plugin.json +22 -0
  3. package/config/mcp-registry.json +29 -0
  4. package/hub/account-broker.mjs +6 -4
  5. package/hub/cli-adapter-base.mjs +14 -14
  6. package/hub/lib/env-detect.mjs +47 -20
  7. package/hub/server.mjs +17 -15
  8. package/hub/team/headless.mjs +10 -0
  9. package/hub/team/swarm-hypervisor.mjs +2 -2
  10. package/hub/workers/delegator-mcp.mjs +129 -1
  11. package/hud/constants.mjs +24 -13
  12. package/hud/renderers.mjs +2 -1
  13. package/package.json +62 -21
  14. package/scripts/__tests__/keyword-detector.test.mjs +4 -4
  15. package/scripts/__tests__/release-governance.test.mjs +148 -0
  16. package/scripts/doctor-diagnose.mjs +6 -7
  17. package/scripts/lib/cross-review-utils.mjs +2 -2
  18. package/scripts/lib/mcp-filter.mjs +12 -24
  19. package/scripts/release/bump-version.mjs +77 -0
  20. package/scripts/release/check-sync.mjs +51 -0
  21. package/scripts/release/lib.mjs +303 -0
  22. package/scripts/release/prepare.mjs +85 -0
  23. package/scripts/release/publish.mjs +87 -0
  24. package/scripts/release/verify.mjs +81 -0
  25. package/scripts/release/version-manifest.json +26 -0
  26. package/scripts/remote-spawn.mjs +3 -3
  27. package/scripts/setup.mjs +18 -15
  28. package/scripts/tfx-route.sh +64 -8
  29. package/tui/codex-profile.mjs +457 -0
  30. package/tui/core.mjs +266 -0
  31. package/tui/doctor.mjs +375 -0
  32. package/tui/gemini-profile.mjs +299 -0
  33. package/tui/monitor-data.mjs +152 -0
  34. package/tui/monitor.mjs +339 -0
  35. package/tui/setup.mjs +598 -0
  36. package/CLAUDE.md +0 -212
  37. package/references/hosts.json +0 -46
  38. package/skills/tfx-workspace/async-tests/run-tests.sh +0 -203
  39. package/skills/tfx-workspace/evals/evals.json +0 -79
  40. package/skills/tfx-workspace/iteration-1/benchmark.json +0 -524
  41. package/skills/tfx-workspace/iteration-1/codex-gemini-remap/eval_metadata.json +0 -11
  42. package/skills/tfx-workspace/iteration-1/codex-gemini-remap/old_skill/grading.json +0 -25
  43. package/skills/tfx-workspace/iteration-1/codex-gemini-remap/old_skill/outputs/analysis.md +0 -154
  44. package/skills/tfx-workspace/iteration-1/codex-gemini-remap/old_skill/timing.json +0 -5
  45. package/skills/tfx-workspace/iteration-1/codex-gemini-remap/with_skill/grading.json +0 -25
  46. package/skills/tfx-workspace/iteration-1/codex-gemini-remap/with_skill/outputs/analysis.md +0 -126
  47. package/skills/tfx-workspace/iteration-1/codex-gemini-remap/with_skill/timing.json +0 -5
  48. package/skills/tfx-workspace/iteration-1/doctor-diagnosis/eval_metadata.json +0 -11
  49. package/skills/tfx-workspace/iteration-1/doctor-diagnosis/old_skill/grading.json +0 -25
  50. package/skills/tfx-workspace/iteration-1/doctor-diagnosis/old_skill/outputs/analysis.md +0 -119
  51. package/skills/tfx-workspace/iteration-1/doctor-diagnosis/old_skill/timing.json +0 -5
  52. package/skills/tfx-workspace/iteration-1/doctor-diagnosis/with_skill/grading.json +0 -25
  53. package/skills/tfx-workspace/iteration-1/doctor-diagnosis/with_skill/outputs/analysis.md +0 -115
  54. package/skills/tfx-workspace/iteration-1/doctor-diagnosis/with_skill/timing.json +0 -5
  55. package/skills/tfx-workspace/iteration-1/hub-start-sequence/eval_metadata.json +0 -10
  56. package/skills/tfx-workspace/iteration-1/hub-start-sequence/old_skill/grading.json +0 -20
  57. package/skills/tfx-workspace/iteration-1/hub-start-sequence/old_skill/outputs/analysis.md +0 -86
  58. package/skills/tfx-workspace/iteration-1/hub-start-sequence/old_skill/timing.json +0 -5
  59. package/skills/tfx-workspace/iteration-1/hub-start-sequence/with_skill/grading.json +0 -20
  60. package/skills/tfx-workspace/iteration-1/hub-start-sequence/with_skill/outputs/analysis.md +0 -81
  61. package/skills/tfx-workspace/iteration-1/hub-start-sequence/with_skill/timing.json +0 -5
  62. package/skills/tfx-workspace/iteration-1/multi-team-creation/eval_metadata.json +0 -12
  63. package/skills/tfx-workspace/iteration-1/multi-team-creation/old_skill/grading.json +0 -30
  64. package/skills/tfx-workspace/iteration-1/multi-team-creation/old_skill/outputs/analysis.md +0 -316
  65. package/skills/tfx-workspace/iteration-1/multi-team-creation/old_skill/timing.json +0 -5
  66. package/skills/tfx-workspace/iteration-1/multi-team-creation/with_skill/grading.json +0 -30
  67. package/skills/tfx-workspace/iteration-1/multi-team-creation/with_skill/outputs/analysis.md +0 -352
  68. package/skills/tfx-workspace/iteration-1/multi-team-creation/with_skill/timing.json +0 -5
  69. package/skills/tfx-workspace/iteration-1/review.html +0 -1325
  70. package/skills/tfx-workspace/iteration-1/routing-implement-shortcut/eval_metadata.json +0 -12
  71. package/skills/tfx-workspace/iteration-1/routing-implement-shortcut/old_skill/grading.json +0 -30
  72. package/skills/tfx-workspace/iteration-1/routing-implement-shortcut/old_skill/outputs/analysis.md +0 -97
  73. package/skills/tfx-workspace/iteration-1/routing-implement-shortcut/old_skill/timing.json +0 -5
  74. package/skills/tfx-workspace/iteration-1/routing-implement-shortcut/with_skill/grading.json +0 -30
  75. package/skills/tfx-workspace/iteration-1/routing-implement-shortcut/with_skill/outputs/analysis.md +0 -94
  76. package/skills/tfx-workspace/iteration-1/routing-implement-shortcut/with_skill/timing.json +0 -5
  77. package/skills/tfx-workspace/iteration-1/routing-multi-task-triage/eval_metadata.json +0 -12
  78. package/skills/tfx-workspace/iteration-1/routing-multi-task-triage/old_skill/grading.json +0 -30
  79. package/skills/tfx-workspace/iteration-1/routing-multi-task-triage/old_skill/outputs/analysis.md +0 -209
  80. package/skills/tfx-workspace/iteration-1/routing-multi-task-triage/old_skill/timing.json +0 -5
  81. package/skills/tfx-workspace/iteration-1/routing-multi-task-triage/with_skill/grading.json +0 -30
  82. package/skills/tfx-workspace/iteration-1/routing-multi-task-triage/with_skill/outputs/analysis.md +0 -193
  83. package/skills/tfx-workspace/iteration-1/routing-multi-task-triage/with_skill/timing.json +0 -5
  84. package/skills/tfx-workspace/iteration-2/benchmark.json +0 -144
  85. package/skills/tfx-workspace/iteration-2/multi-team-creation-refactored/eval_metadata.json +0 -13
  86. package/skills/tfx-workspace/iteration-2/multi-team-creation-refactored/old_skill/grading.json +0 -35
  87. package/skills/tfx-workspace/iteration-2/multi-team-creation-refactored/old_skill/outputs/analysis.md +0 -382
  88. package/skills/tfx-workspace/iteration-2/multi-team-creation-refactored/old_skill/timing.json +0 -5
  89. package/skills/tfx-workspace/iteration-2/multi-team-creation-refactored/with_skill/grading.json +0 -35
  90. package/skills/tfx-workspace/iteration-2/multi-team-creation-refactored/with_skill/outputs/analysis.md +0 -333
  91. package/skills/tfx-workspace/iteration-2/multi-team-creation-refactored/with_skill/timing.json +0 -5
  92. package/skills/tfx-workspace/iteration-2/review.html +0 -1325
  93. package/skills/tfx-workspace/skill-snapshot/tfx-auto/SKILL.md +0 -217
  94. package/skills/tfx-workspace/skill-snapshot/tfx-auto-codex/SKILL.md +0 -77
  95. package/skills/tfx-workspace/skill-snapshot/tfx-codex/SKILL.md +0 -65
  96. package/skills/tfx-workspace/skill-snapshot/tfx-doctor/SKILL.md +0 -94
  97. package/skills/tfx-workspace/skill-snapshot/tfx-gemini/SKILL.md +0 -82
  98. package/skills/tfx-workspace/skill-snapshot/tfx-hub/SKILL.md +0 -133
  99. package/skills/tfx-workspace/skill-snapshot/tfx-multi/SKILL.md +0 -426
  100. package/skills/tfx-workspace/skill-snapshot/tfx-setup/SKILL.md +0 -101
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "triflux",
3
- "version": "10.9.21",
3
+ "version": "10.9.23",
4
4
  "description": "CLI-first multi-model orchestrator for Claude Code — route tasks to Codex, Gemini, and Claude",
5
5
  "type": "module",
6
6
  "bin": {
@@ -13,26 +13,75 @@
13
13
  "tfx-doctor-tui": "bin/tfx-doctor-tui.mjs",
14
14
  "tfx-setup-tui": "bin/tfx-setup-tui.mjs"
15
15
  },
16
- "engines": {
17
- "node": ">=18.0.0"
18
- },
19
- "dependencies": {
20
- "@triflux/core": "10.0.1",
21
- "@triflux/remote": "^10.0.0-alpha.1"
22
- },
23
16
  "files": [
24
17
  "bin",
18
+ "tui",
19
+ "hub",
20
+ "config",
25
21
  "skills",
22
+ "!skills/tfx-workspace",
23
+ "!**/failure-reports",
24
+ "scripts",
26
25
  "hooks",
27
26
  "hud",
28
- "scripts",
29
- "hub",
30
27
  "mesh",
31
- "references",
32
- "CLAUDE.md",
28
+ ".claude-plugin",
33
29
  "README.md",
30
+ "README.ko.md",
34
31
  "LICENSE"
35
32
  ],
33
+ "workspaces": [
34
+ "packages/core",
35
+ "packages/remote",
36
+ "packages/triflux"
37
+ ],
38
+ "scripts": {
39
+ "pack": "node scripts/pack.mjs all",
40
+ "pack:core": "node scripts/pack.mjs core",
41
+ "pack:remote": "node scripts/pack.mjs remote",
42
+ "setup": "node scripts/setup.mjs",
43
+ "preinstall": "node scripts/preinstall.mjs",
44
+ "postinstall": "node scripts/setup.mjs",
45
+ "lint": "biome check bin config hooks hub hud mesh scripts tests .claude-plugin .github package.json package-lock.json biome.json",
46
+ "lint:fix": "biome check --write bin config hooks hub hud mesh scripts tests .claude-plugin .github package.json package-lock.json biome.json",
47
+ "health": "npm test && npm run lint",
48
+ "test": "node scripts/test-lock.mjs --test --test-force-exit --test-concurrency=8 \"tests/**/*.test.mjs\" \"scripts/__tests__/**/*.test.mjs\"",
49
+ "test:unit": "node scripts/test-lock.mjs --test --test-force-exit --test-concurrency=8 tests/unit/**/*.test.mjs",
50
+ "test:integration": "node scripts/test-lock.mjs --test --test-force-exit --test-concurrency=8 tests/integration/**/*.test.mjs",
51
+ "test:route-smoke": "node scripts/test-lock.mjs --test scripts/test-tfx-route-no-claude-native.mjs",
52
+ "test:contract": "node scripts/test-lock.mjs --test --test-force-exit --test-concurrency=8 tests/contract/**/*.test.mjs",
53
+ "test:coverage": "node --experimental-test-coverage --test-coverage-lines=60 --test-coverage-functions=60 --test --test-force-exit --test-concurrency=8 \"tests/**/*.test.mjs\"",
54
+ "gen:skill-docs": "node scripts/gen-skill-docs.mjs",
55
+ "gen:skill-manifest": "node scripts/gen-skill-manifest.mjs",
56
+ "release:check-sync": "node scripts/release/check-sync.mjs",
57
+ "release:check-sync:fix": "node scripts/release/check-sync.mjs --fix",
58
+ "release:bump": "node scripts/release/bump-version.mjs",
59
+ "release:prepare": "node scripts/release/prepare.mjs",
60
+ "release:publish": "node scripts/release/publish.mjs",
61
+ "release:verify": "node scripts/release/verify.mjs"
62
+ },
63
+ "engines": {
64
+ "node": ">=18.0.0"
65
+ },
66
+ "repository": {
67
+ "type": "git",
68
+ "url": "git+https://github.com/tellang/triflux.git"
69
+ },
70
+ "homepage": "https://github.com/tellang/triflux#readme",
71
+ "author": "tellang",
72
+ "license": "MIT",
73
+ "dependencies": {
74
+ "@modelcontextprotocol/sdk": "^1.27.1",
75
+ "better-sqlite3": "^12.6.2",
76
+ "pino": "^10.3.1",
77
+ "pino-pretty": "^13.1.3",
78
+ "systray2": "^2.1.4",
79
+ "zod": "^4.0.0"
80
+ },
81
+ "devDependencies": {
82
+ "@biomejs/biome": "^2.0.0",
83
+ "knip": "^6.3.0"
84
+ },
36
85
  "keywords": [
37
86
  "claude-code",
38
87
  "plugin",
@@ -43,13 +92,5 @@
43
92
  "multi-model",
44
93
  "triflux",
45
94
  "tfx"
46
- ],
47
- "author": "tellang",
48
- "license": "MIT",
49
- "homepage": "https://github.com/tellang/triflux#readme",
50
- "repository": {
51
- "type": "git",
52
- "url": "git+https://github.com/tellang/triflux.git",
53
- "directory": "packages/triflux"
54
- }
95
+ ]
55
96
  }
@@ -34,7 +34,7 @@ const { extractPrompt, sanitizeForKeywordDetection } = detectorModule;
34
34
 
35
35
  function loadCompiledRules() {
36
36
  const rules = loadRules(rulesPath);
37
- assert.equal(rules.length, 32);
37
+ assert.ok(rules.length >= 32);
38
38
  return compileRules(rules);
39
39
  }
40
40
 
@@ -108,8 +108,8 @@ test("sanitizeForKeywordDetection: 코드블록/URL/파일경로/XML 태그 제
108
108
 
109
109
  test("loadRules: 유효한 JSON 로드", () => {
110
110
  const rules = loadRules(rulesPath);
111
- assert.equal(rules.length, 32);
112
- assert.equal(rules.filter((rule) => rule.skill).length, 18);
111
+ assert.ok(rules.length >= 32);
112
+ assert.ok(rules.filter((rule) => rule.skill).length >= 18);
113
113
  assert.equal(rules.filter((rule) => rule.mcp_route).length, 10);
114
114
  });
115
115
 
@@ -130,7 +130,7 @@ test("loadRules: 잘못된 파일 처리", () => {
130
130
  test("compileRules: 정규식 컴파일 성공", () => {
131
131
  const rules = loadRules(rulesPath);
132
132
  const compiled = compileRules(rules);
133
- assert.equal(compiled.length, 32);
133
+ assert.equal(compiled.length, rules.length);
134
134
  for (const rule of compiled) {
135
135
  assert.ok(Array.isArray(rule.compiledPatterns));
136
136
  assert.ok(rule.compiledPatterns.length > 0);
@@ -0,0 +1,148 @@
1
+ import assert from "node:assert/strict";
2
+ import { mkdirSync, mkdtempSync, readFileSync, rmSync } from "node:fs";
3
+ import { tmpdir } from "node:os";
4
+ import { join } from "node:path";
5
+ import { describe, it } from "node:test";
6
+
7
+ import { bumpVersion } from "../release/bump-version.mjs";
8
+ import { assertVersionSync, writeJson } from "../release/lib.mjs";
9
+ import { prepareRelease } from "../release/prepare.mjs";
10
+ import { publishRelease } from "../release/publish.mjs";
11
+ import { verifyRelease } from "../release/verify.mjs";
12
+
13
+ function makeRepo() {
14
+ const root = mkdtempSync(join(tmpdir(), "tfx-release-"));
15
+ mkdirSync(join(root, "scripts", "release"), { recursive: true });
16
+ mkdirSync(join(root, ".claude-plugin"), { recursive: true });
17
+ mkdirSync(join(root, "packages", "triflux"), { recursive: true });
18
+ mkdirSync(join(root, ".omx", "plans"), { recursive: true });
19
+
20
+ writeJson(join(root, "package.json"), { name: "triflux", version: "1.2.3" });
21
+ writeJson(join(root, "packages", "triflux", "package.json"), {
22
+ name: "triflux",
23
+ version: "1.2.0",
24
+ });
25
+ writeJson(join(root, ".claude-plugin", "plugin.json"), {
26
+ name: "triflux",
27
+ version: "1.1.0",
28
+ });
29
+ writeJson(join(root, ".claude-plugin", "marketplace.json"), {
30
+ version: "1.2.0",
31
+ plugins: [{ name: "triflux", version: "1.0.0" }],
32
+ });
33
+ writeJson(join(root, "package-lock.json"), {
34
+ name: "triflux",
35
+ version: "1.2.0",
36
+ packages: {
37
+ "": {
38
+ version: "1.0.0",
39
+ },
40
+ },
41
+ });
42
+ writeJson(join(root, "scripts", "release", "version-manifest.json"), {
43
+ canonicalFile: "package.json",
44
+ canonicalPath: ["version"],
45
+ targets: [
46
+ { file: "package.json", paths: [["version"]] },
47
+ { file: "packages/triflux/package.json", paths: [["version"]] },
48
+ { file: ".claude-plugin/plugin.json", paths: [["version"]] },
49
+ {
50
+ file: ".claude-plugin/marketplace.json",
51
+ paths: [["version"], ["plugins", 0, "version"]],
52
+ },
53
+ {
54
+ file: "package-lock.json",
55
+ paths: [["version"], ["packages", "", "version"]],
56
+ },
57
+ ],
58
+ });
59
+ return root;
60
+ }
61
+
62
+ describe("release governance scripts", () => {
63
+ it("assertVersionSync detects mismatches and fixes them", () => {
64
+ const root = makeRepo();
65
+ try {
66
+ const before = assertVersionSync({ rootDir: root });
67
+ assert.equal(before.ok, false);
68
+ assert.ok(before.mismatches.length >= 4);
69
+
70
+ const after = assertVersionSync({ rootDir: root, fix: true });
71
+ assert.equal(after.ok, true);
72
+ assert.deepEqual(
73
+ JSON.parse(readFileSync(join(root, ".claude-plugin", "plugin.json"))),
74
+ { name: "triflux", version: "1.2.3" },
75
+ );
76
+ } finally {
77
+ rmSync(root, { recursive: true, force: true });
78
+ }
79
+ });
80
+
81
+ it("bumpVersion writes canonical version and syncs targets", async () => {
82
+ const root = makeRepo();
83
+ try {
84
+ const result = await bumpVersion({
85
+ rootDir: root,
86
+ nextVersion: "2.0.0",
87
+ write: true,
88
+ });
89
+ assert.equal(result.ok, true);
90
+ assert.equal(
91
+ JSON.parse(readFileSync(join(root, "package.json"), "utf8")).version,
92
+ "2.0.0",
93
+ );
94
+ assert.equal(
95
+ JSON.parse(
96
+ readFileSync(
97
+ join(root, "packages", "triflux", "package.json"),
98
+ "utf8",
99
+ ),
100
+ ).version,
101
+ "2.0.0",
102
+ );
103
+ } finally {
104
+ rmSync(root, { recursive: true, force: true });
105
+ }
106
+ });
107
+
108
+ it("prepare/publish/verify support dry-run planning", async () => {
109
+ const root = makeRepo();
110
+ try {
111
+ assertVersionSync({ rootDir: root, fix: true });
112
+ const execStub = (command, args) => {
113
+ if (command === "git" && args[0] === "status") return "";
114
+ if (command === "git" && args[0] === "describe") return "v1.2.2";
115
+ if (command === "git" && args[0] === "log")
116
+ return "abc1234 feat: sample\n";
117
+ return "";
118
+ };
119
+
120
+ const prepare = await prepareRelease({
121
+ rootDir: root,
122
+ version: "1.2.3",
123
+ allowDirty: true,
124
+ dryRun: true,
125
+ execFileSyncFn: execStub,
126
+ });
127
+ assert.equal(prepare.ok, true);
128
+ assert.equal(prepare.commands.length, 3);
129
+
130
+ const publish = await publishRelease({
131
+ rootDir: root,
132
+ version: "1.2.3",
133
+ dryRun: true,
134
+ });
135
+ assert.equal(publish.steps.length >= 3, true);
136
+
137
+ const verify = await verifyRelease({
138
+ rootDir: root,
139
+ version: "1.2.3",
140
+ dryRun: true,
141
+ });
142
+ assert.equal(verify.ok, true);
143
+ assert.equal(verify.checks[1].name, "npm-view");
144
+ } finally {
145
+ rmSync(root, { recursive: true, force: true });
146
+ }
147
+ });
148
+ });
@@ -139,14 +139,13 @@ function collectSystemInfo() {
139
139
  freeMemMB: Math.round(freemem() / 1024 / 1024),
140
140
  };
141
141
 
142
- // Windows Terminal version
142
+ // Windows Terminal version (wt.exe --version은 GUI 다이얼로그를 띄우므로 AppxPackage로 조회)
143
143
  try {
144
- const wtVer = execSync("wt.exe --version 2>&1", {
145
- encoding: "utf8",
146
- timeout: 5000,
147
- windowsHide: true,
148
- }).trim();
149
- info.wtVersion = wtVer;
144
+ const wtVer = execSync(
145
+ 'powershell.exe -NoProfile -NoLogo -Command "(Get-AppxPackage Microsoft.WindowsTerminal).Version"',
146
+ { encoding: "utf8", timeout: 5000, windowsHide: true },
147
+ ).trim();
148
+ info.wtVersion = wtVer || "not found";
150
149
  } catch {
151
150
  info.wtVersion = "not found";
152
151
  }
@@ -1,7 +1,7 @@
1
1
  import { join } from "node:path";
2
2
 
3
3
  export const SESSION_TTL_SEC = 30 * 60;
4
- export const STATE_REL_PATH = join(".omc", "state", "cross-review.json");
4
+ export const STATE_REL_PATH = join(".triflux", "state", "cross-review.json");
5
5
 
6
6
  export function readStdin() {
7
7
  return new Promise((resolve) => {
@@ -39,7 +39,7 @@ export function shouldTrackPath(filePath) {
39
39
  if (typeof filePath !== "string" || !filePath.trim()) return false;
40
40
 
41
41
  const lower = filePath.toLowerCase();
42
- if (lower.startsWith(".omc/") || lower.startsWith(".claude/")) return false;
42
+ if (lower.startsWith(".triflux/") || lower.startsWith(".omc/") || lower.startsWith(".claude/")) return false;
43
43
  if (lower === "package-lock.json" || lower.endsWith("/package-lock.json"))
44
44
  return false;
45
45
  if (/\.(md|lock|yml|yaml)$/i.test(lower)) return false;
@@ -36,28 +36,12 @@ const PROFILE_DEFINITIONS = Object.freeze({
36
36
  }),
37
37
  }),
38
38
  executor: Object.freeze({
39
- description: "구현 워커용. 문서/검색/브라우징 보조 MCP 허용",
40
- allowedServers: Object.freeze([
41
- "context7",
42
- "playwright",
43
- "brave-search",
44
- "tavily",
45
- "exa",
46
- ]),
39
+ description: "구현 워커용. 문서 조회 전용 MCP 허용 (검색/브라우징은 Codex stall 유발)",
40
+ allowedServers: Object.freeze(["context7"]),
47
41
  alwaysOnServers: Object.freeze(["context7"]),
48
- maxSearchServers: 2,
42
+ maxSearchServers: 0,
49
43
  allowedToolsByServer: Object.freeze({
50
44
  context7: Object.freeze(["resolve-library-id", "query-docs"]),
51
- "brave-search": Object.freeze(["brave_web_search", "brave_news_search"]),
52
- exa: Object.freeze(["web_search_exa", "get_code_context_exa"]),
53
- tavily: Object.freeze(["tavily_search", "tavily_extract"]),
54
- playwright: Object.freeze([
55
- "browser_navigate",
56
- "browser_navigate_back",
57
- "browser_snapshot",
58
- "browser_take_screenshot",
59
- "browser_wait_for",
60
- ]),
61
45
  }),
62
46
  }),
63
47
  designer: Object.freeze({
@@ -672,18 +656,22 @@ export function getCodexMcpConfig(options = {}) {
672
656
  const targetServers = registeredServers;
673
657
 
674
658
  if (resolvedProfile === "none") {
675
- // Codex 0.115+: transport 없는 서버에 enabled=false 보내면 "invalid transport" 에러.
676
- // 비허용 서버는 override에서 제외하고, 허용 서버만 명시적으로 설정한다.
677
- return { mcp_servers: {} };
659
+ // 등록된 서버를 전부 enabled=false 비활성화.
660
+ // 미등록 서버에 보내면 "invalid transport" 에러지만, registeredServers는 등록 확인 완료.
661
+ const config = { mcp_servers: {} };
662
+ for (const server of targetServers) {
663
+ config.mcp_servers[server] = { enabled: false };
664
+ }
665
+ return config;
678
666
  }
679
667
 
680
668
  const config = { mcp_servers: {} };
681
669
  const allowedToolsByServer =
682
670
  getProfileDefinition(resolvedProfile).allowedToolsByServer;
683
671
  for (const server of targetServers) {
684
- // Codex 0.115+: transport 없는 서버에 enabled=false를 보내면 "invalid transport" 에러.
685
- // 비허용 서버는 override에서 제외한다 (Codex 기본 설정이 유지됨).
686
672
  if (!allowedServers.has(server)) {
673
+ // 비허용 서버는 명시적으로 비활성화하여 MCP 시작 자체를 방지.
674
+ config.mcp_servers[server] = { enabled: false };
687
675
  continue;
688
676
  }
689
677
 
@@ -0,0 +1,77 @@
1
+ #!/usr/bin/env node
2
+ import { join } from "node:path";
3
+ import { fileURLToPath } from "node:url";
4
+ import {
5
+ assertVersionSync,
6
+ isSemver,
7
+ parseArgs,
8
+ ROOT,
9
+ readJson,
10
+ syncVersionTargets,
11
+ writeJson,
12
+ } from "./lib.mjs";
13
+
14
+ export async function bumpVersion({
15
+ nextVersion,
16
+ rootDir = ROOT,
17
+ write = false,
18
+ } = {}) {
19
+ if (!isSemver(nextVersion)) {
20
+ throw new Error(`Invalid semver version: ${nextVersion}`);
21
+ }
22
+
23
+ const packagePath = join(rootDir, "package.json");
24
+ const packageJson = readJson(packagePath);
25
+ const previousVersion = packageJson.version;
26
+ packageJson.version = nextVersion;
27
+
28
+ if (write) {
29
+ writeJson(packagePath, packageJson);
30
+ const syncedFiles = syncVersionTargets({
31
+ rootDir,
32
+ expectedVersion: nextVersion,
33
+ });
34
+ const post = assertVersionSync({ rootDir, expectedVersion: nextVersion });
35
+ return {
36
+ ok: post.ok,
37
+ previousVersion,
38
+ nextVersion,
39
+ updatedFiles: ["package.json", ...syncedFiles],
40
+ targets: post.targets,
41
+ };
42
+ }
43
+
44
+ const preview = assertVersionSync({
45
+ rootDir,
46
+ expectedVersion: nextVersion,
47
+ });
48
+ return {
49
+ ok: true,
50
+ previousVersion,
51
+ nextVersion,
52
+ updatedFiles: ["package.json"],
53
+ targets: preview.targets.map((target) => ({
54
+ ...target,
55
+ expected: nextVersion,
56
+ inSync: target.file === "package.json",
57
+ })),
58
+ };
59
+ }
60
+
61
+ if (process.argv[1] && fileURLToPath(import.meta.url) === process.argv[1]) {
62
+ const args = parseArgs(process.argv.slice(2));
63
+ const nextVersion = args.next || args.version;
64
+ const result = await bumpVersion({
65
+ nextVersion,
66
+ rootDir: args.root,
67
+ write: Boolean(args.write),
68
+ });
69
+ if (args.json) {
70
+ console.log(JSON.stringify(result, null, 2));
71
+ } else {
72
+ console.log(
73
+ `${args.write ? "Bumped" : "Planned"} version ${result.previousVersion} -> ${result.nextVersion}`,
74
+ );
75
+ console.log(`Updated files: ${result.updatedFiles.join(", ")}`);
76
+ }
77
+ }
@@ -0,0 +1,51 @@
1
+ #!/usr/bin/env node
2
+ import { fileURLToPath } from "node:url";
3
+
4
+ import { assertVersionSync, formatPathSegments, parseArgs } from "./lib.mjs";
5
+
6
+ export { assertVersionSync } from "./lib.mjs";
7
+
8
+ function toJson(result) {
9
+ return {
10
+ ok: result.ok,
11
+ rootVersion: result.rootVersion,
12
+ fixedFiles: result.fixedFiles,
13
+ mismatches: result.mismatches.map((target) => ({
14
+ file: target.file,
15
+ path: formatPathSegments(target.path),
16
+ found: target.found ?? null,
17
+ expected: target.expected,
18
+ missing: target.missing,
19
+ })),
20
+ };
21
+ }
22
+
23
+ function printHuman(result) {
24
+ if (result.ok) {
25
+ console.log(`Version sync OK (${result.rootVersion})`);
26
+ return;
27
+ }
28
+ console.log(`Version sync mismatch (${result.rootVersion})`);
29
+ for (const target of result.mismatches) {
30
+ console.log(
31
+ `- ${target.file} :: ${formatPathSegments(target.path)} => found=${target.found ?? "missing"}, expected=${target.expected}`,
32
+ );
33
+ }
34
+ if (result.fixedFiles.length) {
35
+ console.log(`Fixed files: ${result.fixedFiles.join(", ")}`);
36
+ }
37
+ }
38
+
39
+ if (process.argv[1] && fileURLToPath(import.meta.url) === process.argv[1]) {
40
+ const args = parseArgs(process.argv.slice(2));
41
+ const result = assertVersionSync({
42
+ rootDir: args.root,
43
+ fix: Boolean(args.fix),
44
+ });
45
+ if (args.json) {
46
+ console.log(JSON.stringify(toJson(result), null, 2));
47
+ } else {
48
+ printHuman(result);
49
+ }
50
+ process.exitCode = result.ok ? 0 : 1;
51
+ }