triflux 10.4.0 → 10.7.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/.claude-plugin/marketplace.json +34 -0
- package/.claude-plugin/plugin.json +22 -0
- package/bin/tfx-doctor-tui.mjs +1 -1
- package/bin/tfx-doctor.mjs +6 -1
- package/bin/tfx-profile.mjs +1 -1
- package/bin/tfx-setup-tui.mjs +1 -1
- package/bin/tfx-setup.mjs +6 -1
- package/bin/triflux.mjs +2396 -1140
- package/config/mcp-registry.json +29 -0
- package/hooks/agent-route-guard.mjs +12 -8
- package/hooks/cross-review-tracker.mjs +21 -8
- package/hooks/error-context.mjs +19 -7
- package/hooks/hook-adaptive-collector.mjs +18 -16
- package/hooks/hook-manager.mjs +93 -32
- package/hooks/hook-orchestrator.mjs +108 -24
- package/hooks/hook-registry.json +267 -256
- package/hooks/keyword-rules.json +6 -10
- package/hooks/lib/resolve-root.mjs +1 -1
- package/hooks/mcp-config-watcher.mjs +6 -2
- package/hooks/pipeline-stop.mjs +3 -6
- package/hooks/safety-guard.mjs +99 -28
- package/hooks/session-start-fast.mjs +143 -0
- package/hooks/subagent-verifier.mjs +5 -4
- package/hub/account-broker.mjs +256 -60
- package/hub/adaptive-diagnostic.mjs +75 -48
- package/hub/adaptive-inject.mjs +96 -58
- package/hub/adaptive-memory.mjs +156 -42
- package/hub/adaptive.mjs +60 -31
- package/hub/assign-callbacks.mjs +163 -126
- package/hub/bridge.mjs +0 -1
- package/hub/cli-adapter-base.mjs +200 -48
- package/hub/codex-adapter.mjs +76 -96
- package/hub/codex-compat.mjs +3 -3
- package/hub/codex-preflight.mjs +63 -37
- package/hub/delegator/contracts.mjs +19 -23
- package/hub/delegator/index.mjs +14 -14
- package/hub/delegator/service.mjs +88 -64
- package/hub/delegator/tool-definitions.mjs +35 -35
- package/hub/fullcycle.mjs +33 -17
- package/hub/gemini-adapter.mjs +69 -94
- package/hub/hitl.mjs +202 -143
- package/hub/intent.mjs +161 -38
- package/hub/lib/cache-guard.mjs +43 -17
- package/hub/lib/mcp-response-cache.mjs +66 -32
- package/hub/lib/memory-store.mjs +285 -111
- package/hub/lib/path-utils.mjs +35 -37
- package/hub/lib/process-utils.mjs +106 -37
- package/hub/lib/spawn-trace.mjs +527 -0
- package/hub/lib/ssh-command.mjs +34 -4
- package/hub/lib/ssh-retry.mjs +5 -1
- package/hub/lib/uuidv7.mjs +4 -3
- package/hub/memory-doctor.mjs +266 -106
- package/hub/middleware/request-logger.mjs +61 -34
- package/hub/paths.mjs +9 -9
- package/hub/pipeline/gates/confidence.mjs +34 -15
- package/hub/pipeline/gates/consensus.mjs +27 -15
- package/hub/pipeline/gates/index.mjs +7 -3
- package/hub/pipeline/gates/selfcheck.mjs +57 -19
- package/hub/pipeline/index.mjs +77 -42
- package/hub/pipeline/state.mjs +10 -10
- package/hub/pipeline/transitions.mjs +40 -23
- package/hub/platform.mjs +57 -48
- package/hub/promote-penalties.mjs +25 -7
- package/hub/quality/deslop.mjs +70 -49
- package/hub/research.mjs +32 -25
- package/hub/router.mjs +924 -791
- package/hub/routing/complexity.mjs +132 -29
- package/hub/routing/index.mjs +17 -12
- package/hub/routing/q-learning.mjs +76 -28
- package/hub/server.mjs +4 -4
- package/hub/session-fingerprint.mjs +127 -61
- package/hub/state.mjs +84 -43
- package/hub/store-adapter.mjs +59 -26
- package/hub/store.mjs +356 -153
- package/hub/team/agent-map.json +22 -7
- package/hub/team/ansi.mjs +186 -122
- package/hub/team/backend.mjs +28 -10
- package/hub/team/cli/commands/attach.mjs +57 -37
- package/hub/team/cli/commands/control.mjs +29 -8
- package/hub/team/cli/commands/debug.mjs +95 -74
- package/hub/team/cli/commands/focus.mjs +80 -53
- package/hub/team/cli/commands/interrupt.mjs +18 -6
- package/hub/team/cli/commands/kill.mjs +16 -5
- package/hub/team/cli/commands/list.mjs +31 -24
- package/hub/team/cli/commands/send.mjs +19 -6
- package/hub/team/cli/commands/start/index.mjs +154 -31
- package/hub/team/cli/commands/start/parse-args.mjs +38 -11
- package/hub/team/cli/commands/start/start-headless.mjs +112 -36
- package/hub/team/cli/commands/start/start-in-process.mjs +50 -40
- package/hub/team/cli/commands/start/start-mux.mjs +122 -73
- package/hub/team/cli/commands/start/start-wt.mjs +86 -69
- package/hub/team/cli/commands/status.mjs +43 -14
- package/hub/team/cli/commands/stop.mjs +11 -4
- package/hub/team/cli/commands/task.mjs +8 -3
- package/hub/team/cli/commands/tasks.mjs +13 -13
- package/hub/team/cli/index.mjs +2 -2
- package/hub/team/cli/manifest.mjs +38 -8
- package/hub/team/cli/render.mjs +52 -30
- package/hub/team/cli/services/attach-fallback.mjs +74 -54
- package/hub/team/cli/services/hub-client.mjs +42 -14
- package/hub/team/cli/services/member-selector.mjs +37 -30
- package/hub/team/cli/services/native-control.mjs +143 -116
- package/hub/team/cli/services/runtime-mode.mjs +2 -1
- package/hub/team/cli/services/state-store.mjs +25 -8
- package/hub/team/cli/services/task-model.mjs +40 -30
- package/hub/team/conductor-mesh-bridge.mjs +24 -23
- package/hub/team/conductor.mjs +8 -4
- package/hub/team/dashboard-anchor.mjs +4 -5
- package/hub/team/dashboard-layout.mjs +3 -1
- package/hub/team/dashboard-open.mjs +41 -21
- package/hub/team/dashboard.mjs +76 -28
- package/hub/team/event-log.mjs +18 -10
- package/hub/team/handoff.mjs +31 -15
- package/hub/team/headless.mjs +2 -1
- package/hub/team/health-probe.mjs +69 -54
- package/hub/team/launcher-template.mjs +16 -13
- package/hub/team/native-supervisor.mjs +65 -21
- package/hub/team/native.mjs +74 -35
- package/hub/team/nativeProxy.mjs +184 -113
- package/hub/team/notify.mjs +120 -77
- package/hub/team/orchestrator.mjs +166 -161
- package/hub/team/pane.mjs +12 -7
- package/hub/team/process-cleanup.mjs +25 -16
- package/hub/team/psmux.mjs +491 -201
- package/hub/team/remote-probe.mjs +68 -52
- package/hub/team/remote-session.mjs +117 -59
- package/hub/team/remote-watcher.mjs +61 -33
- package/hub/team/routing.mjs +51 -25
- package/hub/team/runtime-strategy.mjs +3 -1
- package/hub/team/session.mjs +675 -611
- package/hub/team/shared.mjs +13 -13
- package/hub/team/staleState.mjs +72 -30
- package/hub/team/swarm-locks.mjs +15 -13
- package/hub/team/swarm-planner.mjs +32 -21
- package/hub/team/swarm-reconciler.mjs +48 -23
- package/hub/team/tui-lite.mjs +266 -68
- package/hub/team/tui-remote-adapter.mjs +14 -10
- package/hub/team/tui-viewer.mjs +99 -43
- package/hub/team/tui.mjs +708 -271
- package/hub/team/worktree-lifecycle.mjs +152 -58
- package/hub/team/wt-manager.mjs +24 -14
- package/hub/token-mode.mjs +71 -71
- package/hub/tray.mjs +411 -368
- package/hub/workers/claude-worker.mjs +162 -118
- package/hub/workers/codex-mcp.mjs +558 -507
- package/hub/workers/delegator-mcp.mjs +507 -333
- package/hub/workers/factory.mjs +21 -21
- package/hub/workers/gemini-worker.mjs +115 -84
- package/hub/workers/interface.mjs +6 -1
- package/hub/workers/worker-utils.mjs +21 -14
- package/hud/colors.mjs +27 -9
- package/hud/constants.mjs +162 -26
- package/hud/context-monitor.mjs +82 -41
- package/hud/hud-qos-status.mjs +129 -49
- package/hud/mission-board.mjs +6 -3
- package/hud/providers/claude.mjs +226 -115
- package/hud/providers/codex.mjs +62 -22
- package/hud/providers/gemini.mjs +168 -56
- package/hud/renderers.mjs +384 -119
- package/hud/terminal.mjs +101 -31
- package/hud/utils.mjs +78 -38
- package/mesh/index.mjs +11 -5
- package/mesh/mesh-budget.mjs +18 -9
- package/mesh/mesh-heartbeat.mjs +1 -1
- package/mesh/mesh-queue.mjs +3 -5
- package/mesh/mesh-router.mjs +5 -4
- package/package.json +56 -21
- package/scripts/__tests__/gen-skill-docs.test.mjs +36 -7
- package/scripts/__tests__/keyword-detector.test.mjs +77 -28
- package/scripts/__tests__/mcp-guard-engine.test.mjs +58 -20
- package/scripts/__tests__/remote-spawn-transfer.test.mjs +30 -19
- package/scripts/__tests__/remote-spawn.test.mjs +10 -4
- package/scripts/__tests__/session-start-fast.test.mjs +36 -0
- package/scripts/__tests__/skill-template.test.mjs +98 -50
- package/scripts/__tests__/smoke.test.mjs +1 -1
- package/scripts/__tests__/spawn-trace.test.mjs +102 -0
- package/scripts/__tests__/tfx-doctor-diagnose.test.mjs +48 -0
- package/scripts/cache-doctor.mjs +11 -4
- package/scripts/cache-warmup.mjs +96 -37
- package/scripts/claudemd-sync.mjs +27 -17
- package/scripts/codex-gateway-preflight.mjs +52 -37
- package/scripts/codex-mcp-gateway-sync.mjs +59 -39
- package/scripts/config-audit.mjs +232 -0
- package/scripts/convert-to-tmpl.mjs +54 -0
- package/scripts/cross-review-gate.mjs +35 -12
- package/scripts/cross-review-tracker.mjs +21 -8
- package/scripts/demo.mjs +35 -17
- package/scripts/doctor-diagnose.mjs +284 -0
- package/scripts/gen-skill-docs.mjs +7 -2
- package/scripts/gen-skill-manifest.mjs +2 -1
- package/scripts/headless-guard.mjs +86 -48
- package/scripts/hub-ensure.mjs +139 -120
- package/scripts/keyword-detector.mjs +293 -272
- package/scripts/keyword-rules-expander.mjs +538 -521
- package/scripts/lib/claudemd-scanner.mjs +6 -1
- package/scripts/lib/context.mjs +3 -3
- package/scripts/lib/cross-review-utils.mjs +6 -3
- package/scripts/lib/env-probe.mjs +47 -28
- package/scripts/lib/gemini-profiles.mjs +44 -10
- package/scripts/lib/handoff.mjs +33 -17
- package/scripts/lib/hook-utils.mjs +8 -6
- package/scripts/lib/keyword-rules.mjs +43 -19
- package/scripts/lib/logger.mjs +24 -24
- package/scripts/lib/mcp-filter.mjs +377 -239
- package/scripts/lib/mcp-guard-engine.mjs +194 -79
- package/scripts/lib/mcp-manifest.mjs +23 -13
- package/scripts/lib/mcp-server-catalog.mjs +355 -118
- package/scripts/lib/psmux-info.mjs +11 -6
- package/scripts/lib/remote-spawn-transfer.mjs +44 -14
- package/scripts/lib/skill-template.mjs +30 -7
- package/scripts/mcp-check.mjs +58 -39
- package/scripts/mcp-gateway-config.mjs +83 -39
- package/scripts/mcp-gateway-ensure.mjs +43 -35
- package/scripts/mcp-gateway-integration-test.mjs +70 -58
- package/scripts/mcp-gateway-start.mjs +126 -60
- package/scripts/mcp-gateway-verify.mjs +24 -22
- package/scripts/mcp-safety-guard.mjs +44 -11
- package/scripts/notion-read.mjs +669 -554
- package/scripts/pack.mjs +94 -89
- package/scripts/preflight-cache.mjs +27 -10
- package/scripts/preinstall.mjs +42 -13
- package/scripts/remote-spawn.mjs +309 -94
- package/scripts/run.cjs +8 -5
- package/scripts/session-spawn-helper.mjs +130 -39
- package/scripts/session-stale-cleanup.mjs +123 -0
- package/scripts/setup.mjs +941 -492
- package/scripts/test-lock.mjs +20 -7
- package/scripts/test-tfx-route-no-claude-native.mjs +61 -57
- package/scripts/tfx-batch-stats.mjs +117 -96
- package/scripts/tfx-gate-activate.mjs +11 -4
- package/scripts/tfx-route-post.mjs +87 -20
- package/scripts/tfx-route-worker.mjs +57 -51
- package/scripts/tfx-route.sh +41 -124
- package/scripts/tmp-cleanup.mjs +21 -7
- package/scripts/token-snapshot.mjs +204 -85
- package/skills/.omc/state/idle-notif-cooldown.json +1 -1
- package/skills/.omc/state/last-tool-error.json +1 -1
- package/skills/.omc/state/subagent-tracking.json +1 -1
- package/skills/_templates/base.md +1 -6
- package/skills/merge-worktree/SKILL.md.tmpl +144 -0
- package/skills/shared/telemetry-segment.md +6 -0
- package/skills/star-prompt/SKILL.md.tmpl +222 -0
- package/skills/tfx-analysis/SKILL.md.tmpl +107 -0
- package/skills/tfx-analysis/skill.json +1 -6
- package/skills/tfx-auto/SKILL.md +1 -0
- package/skills/{tfx-workspace/skill-snapshot/tfx-auto-codex/SKILL.md → tfx-auto-codex/SKILL.md.tmpl} +33 -4
- package/skills/tfx-auto-codex/skill.json +1 -3
- package/skills/tfx-autopilot/SKILL.md.tmpl +116 -0
- package/skills/tfx-autopilot/skill.json +1 -5
- package/skills/tfx-autoresearch/SKILL.md.tmpl +136 -0
- package/skills/tfx-autoroute/SKILL.md.tmpl +189 -0
- package/skills/tfx-autoroute/skill.json +1 -7
- package/skills/tfx-codex/SKILL.md +1 -0
- package/skills/tfx-codex/skill.json +1 -3
- package/skills/tfx-codex-swarm/SKILL.md.tmpl +16 -0
- package/skills/tfx-codex-swarm/evals/evals.json +1 -1
- package/skills/tfx-codex-swarm/skill.json +1 -4
- package/skills/tfx-codex-swarm-workspace/iteration-1/benchmark.json +54 -12
- package/skills/tfx-codex-swarm-workspace/iteration-1/full-swarm-all-prds/with_skill/grading.json +35 -7
- package/skills/tfx-codex-swarm-workspace/iteration-1/full-swarm-all-prds/without_skill/grading.json +35 -7
- package/skills/tfx-codex-swarm-workspace/iteration-1/implicit-swarm-no-keywords/with_skill/grading.json +25 -5
- package/skills/tfx-codex-swarm-workspace/iteration-1/implicit-swarm-no-keywords/without_skill/grading.json +25 -5
- package/skills/tfx-codex-swarm-workspace/iteration-1/selective-spawn-with-override/with_skill/grading.json +20 -4
- package/skills/tfx-codex-swarm-workspace/iteration-1/selective-spawn-with-override/without_skill/grading.json +16 -4
- package/skills/tfx-consensus/SKILL.md.tmpl +146 -0
- package/skills/tfx-debate/SKILL.md.tmpl +192 -0
- package/skills/tfx-debate/skill.json +1 -7
- package/skills/tfx-deep-analysis/SKILL.md.tmpl +228 -0
- package/skills/tfx-deep-analysis/skill.json +1 -5
- package/skills/tfx-deep-interview/SKILL.md.tmpl +203 -0
- package/skills/tfx-deep-plan/SKILL.md.tmpl +282 -0
- package/skills/tfx-deep-qa/SKILL.md.tmpl +165 -0
- package/skills/tfx-deep-qa/skill.json +1 -6
- package/skills/tfx-deep-research/SKILL.md.tmpl +217 -0
- package/skills/tfx-deep-review/SKILL.md.tmpl +179 -0
- package/skills/tfx-doctor/SKILL.md +21 -0
- package/skills/tfx-doctor/SKILL.md.tmpl +172 -0
- package/skills/tfx-doctor/skill.json +1 -3
- package/skills/tfx-find/SKILL.md +1 -0
- package/skills/tfx-forge/SKILL.md.tmpl +187 -0
- package/skills/tfx-fullcycle/SKILL.md.tmpl +286 -0
- package/skills/tfx-fullcycle/skill.json +1 -6
- package/skills/{tfx-workspace/skill-snapshot/tfx-gemini/SKILL.md → tfx-gemini/SKILL.md.tmpl} +16 -7
- package/skills/tfx-gemini/skill.json +1 -3
- package/skills/tfx-hooks/SKILL.md.tmpl +216 -0
- package/skills/tfx-hooks/skill.json +1 -3
- package/skills/tfx-hub/SKILL.md.tmpl +212 -0
- package/skills/tfx-hub/skill.json +1 -3
- package/skills/tfx-index/SKILL.md +1 -0
- package/skills/tfx-index/skill.json +1 -6
- package/skills/tfx-interview/SKILL.md.tmpl +285 -0
- package/skills/tfx-multi/SKILL.md.tmpl +183 -0
- package/skills/tfx-multi/skill.json +1 -3
- package/skills/tfx-panel/SKILL.md.tmpl +189 -0
- package/skills/tfx-panel/skill.json +1 -7
- package/skills/tfx-persist/SKILL.md.tmpl +270 -0
- package/skills/tfx-persist/skill.json +1 -7
- package/skills/tfx-plan/SKILL.md +1 -0
- package/skills/tfx-plan/skill.json +1 -6
- package/skills/tfx-profile/SKILL.md.tmpl +239 -0
- package/skills/tfx-profile/skill.json +1 -3
- package/skills/tfx-prune/SKILL.md.tmpl +200 -0
- package/skills/tfx-prune/skill.json +1 -7
- package/skills/tfx-psmux-rules/SKILL.md.tmpl +326 -0
- package/skills/tfx-psmux-rules/skill.json +1 -4
- package/skills/tfx-qa/SKILL.md +1 -0
- package/skills/tfx-qa/skill.json +1 -6
- package/skills/tfx-ralph/SKILL.md.tmpl +28 -0
- package/skills/tfx-ralph/skill.json +1 -4
- package/skills/tfx-remote-setup/SKILL.md.tmpl +576 -0
- package/skills/tfx-remote-setup/skill.json +1 -3
- package/skills/tfx-remote-spawn/SKILL.md.tmpl +263 -0
- package/skills/tfx-remote-spawn/references/hosts.json +16 -16
- package/skills/tfx-remote-spawn/skill.json +1 -4
- package/skills/tfx-research/SKILL.md +1 -0
- package/skills/tfx-review/SKILL.md +1 -0
- package/skills/tfx-review/skill.json +1 -6
- package/skills/tfx-setup/SKILL.md.tmpl +504 -0
- package/skills/tfx-setup/skill.json +1 -3
- package/skills/tfx-swarm/SKILL.md +22 -0
- package/skills/tfx-swarm/SKILL.md.tmpl +218 -0
- package/tui/codex-profile.mjs +457 -0
- package/tui/core.mjs +266 -0
- package/tui/doctor.mjs +375 -0
- package/tui/gemini-profile.mjs +299 -0
- package/tui/monitor-data.mjs +152 -0
- package/tui/monitor.mjs +339 -0
- package/tui/setup.mjs +533 -0
- package/CLAUDE.md +0 -193
- package/references/hosts.json +0 -33
- package/skills/tfx-workspace/async-tests/run-tests.sh +0 -203
- package/skills/tfx-workspace/evals/evals.json +0 -79
- package/skills/tfx-workspace/iteration-1/benchmark.json +0 -162
- package/skills/tfx-workspace/iteration-1/codex-gemini-remap/eval_metadata.json +0 -11
- package/skills/tfx-workspace/iteration-1/codex-gemini-remap/old_skill/grading.json +0 -9
- package/skills/tfx-workspace/iteration-1/codex-gemini-remap/old_skill/outputs/analysis.md +0 -154
- package/skills/tfx-workspace/iteration-1/codex-gemini-remap/old_skill/timing.json +0 -5
- package/skills/tfx-workspace/iteration-1/codex-gemini-remap/with_skill/grading.json +0 -9
- package/skills/tfx-workspace/iteration-1/codex-gemini-remap/with_skill/outputs/analysis.md +0 -126
- package/skills/tfx-workspace/iteration-1/codex-gemini-remap/with_skill/timing.json +0 -5
- package/skills/tfx-workspace/iteration-1/doctor-diagnosis/eval_metadata.json +0 -11
- package/skills/tfx-workspace/iteration-1/doctor-diagnosis/old_skill/grading.json +0 -9
- package/skills/tfx-workspace/iteration-1/doctor-diagnosis/old_skill/outputs/analysis.md +0 -119
- package/skills/tfx-workspace/iteration-1/doctor-diagnosis/old_skill/timing.json +0 -5
- package/skills/tfx-workspace/iteration-1/doctor-diagnosis/with_skill/grading.json +0 -9
- package/skills/tfx-workspace/iteration-1/doctor-diagnosis/with_skill/outputs/analysis.md +0 -115
- package/skills/tfx-workspace/iteration-1/doctor-diagnosis/with_skill/timing.json +0 -5
- package/skills/tfx-workspace/iteration-1/hub-start-sequence/eval_metadata.json +0 -10
- package/skills/tfx-workspace/iteration-1/hub-start-sequence/old_skill/grading.json +0 -8
- package/skills/tfx-workspace/iteration-1/hub-start-sequence/old_skill/outputs/analysis.md +0 -86
- package/skills/tfx-workspace/iteration-1/hub-start-sequence/old_skill/timing.json +0 -5
- package/skills/tfx-workspace/iteration-1/hub-start-sequence/with_skill/grading.json +0 -8
- package/skills/tfx-workspace/iteration-1/hub-start-sequence/with_skill/outputs/analysis.md +0 -81
- package/skills/tfx-workspace/iteration-1/hub-start-sequence/with_skill/timing.json +0 -5
- package/skills/tfx-workspace/iteration-1/multi-team-creation/eval_metadata.json +0 -12
- package/skills/tfx-workspace/iteration-1/multi-team-creation/old_skill/grading.json +0 -10
- package/skills/tfx-workspace/iteration-1/multi-team-creation/old_skill/outputs/analysis.md +0 -316
- package/skills/tfx-workspace/iteration-1/multi-team-creation/old_skill/timing.json +0 -5
- package/skills/tfx-workspace/iteration-1/multi-team-creation/with_skill/grading.json +0 -10
- package/skills/tfx-workspace/iteration-1/multi-team-creation/with_skill/outputs/analysis.md +0 -352
- package/skills/tfx-workspace/iteration-1/multi-team-creation/with_skill/timing.json +0 -5
- package/skills/tfx-workspace/iteration-1/review.html +0 -1325
- package/skills/tfx-workspace/iteration-1/routing-implement-shortcut/eval_metadata.json +0 -12
- package/skills/tfx-workspace/iteration-1/routing-implement-shortcut/old_skill/grading.json +0 -10
- package/skills/tfx-workspace/iteration-1/routing-implement-shortcut/old_skill/outputs/analysis.md +0 -97
- package/skills/tfx-workspace/iteration-1/routing-implement-shortcut/old_skill/timing.json +0 -5
- package/skills/tfx-workspace/iteration-1/routing-implement-shortcut/with_skill/grading.json +0 -10
- package/skills/tfx-workspace/iteration-1/routing-implement-shortcut/with_skill/outputs/analysis.md +0 -94
- package/skills/tfx-workspace/iteration-1/routing-implement-shortcut/with_skill/timing.json +0 -5
- package/skills/tfx-workspace/iteration-1/routing-multi-task-triage/eval_metadata.json +0 -12
- package/skills/tfx-workspace/iteration-1/routing-multi-task-triage/old_skill/grading.json +0 -10
- package/skills/tfx-workspace/iteration-1/routing-multi-task-triage/old_skill/outputs/analysis.md +0 -209
- package/skills/tfx-workspace/iteration-1/routing-multi-task-triage/old_skill/timing.json +0 -5
- package/skills/tfx-workspace/iteration-1/routing-multi-task-triage/with_skill/grading.json +0 -10
- package/skills/tfx-workspace/iteration-1/routing-multi-task-triage/with_skill/outputs/analysis.md +0 -193
- package/skills/tfx-workspace/iteration-1/routing-multi-task-triage/with_skill/timing.json +0 -5
- package/skills/tfx-workspace/iteration-2/benchmark.json +0 -62
- package/skills/tfx-workspace/iteration-2/multi-team-creation-refactored/eval_metadata.json +0 -13
- package/skills/tfx-workspace/iteration-2/multi-team-creation-refactored/old_skill/grading.json +0 -11
- package/skills/tfx-workspace/iteration-2/multi-team-creation-refactored/old_skill/outputs/analysis.md +0 -382
- package/skills/tfx-workspace/iteration-2/multi-team-creation-refactored/old_skill/timing.json +0 -5
- package/skills/tfx-workspace/iteration-2/multi-team-creation-refactored/with_skill/grading.json +0 -11
- package/skills/tfx-workspace/iteration-2/multi-team-creation-refactored/with_skill/outputs/analysis.md +0 -333
- package/skills/tfx-workspace/iteration-2/multi-team-creation-refactored/with_skill/timing.json +0 -5
- package/skills/tfx-workspace/iteration-2/review.html +0 -1325
- package/skills/tfx-workspace/skill-snapshot/tfx-auto/SKILL.md +0 -217
- package/skills/tfx-workspace/skill-snapshot/tfx-codex/SKILL.md +0 -65
- package/skills/tfx-workspace/skill-snapshot/tfx-doctor/SKILL.md +0 -94
- package/skills/tfx-workspace/skill-snapshot/tfx-hub/SKILL.md +0 -133
- package/skills/tfx-workspace/skill-snapshot/tfx-multi/SKILL.md +0 -426
- package/skills/tfx-workspace/skill-snapshot/tfx-setup/SKILL.md +0 -101
|
@@ -1,4 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
copyFileSync,
|
|
3
|
+
existsSync,
|
|
4
|
+
mkdirSync,
|
|
5
|
+
readFileSync,
|
|
6
|
+
writeFileSync,
|
|
7
|
+
} from "node:fs";
|
|
2
8
|
import { homedir } from "node:os";
|
|
3
9
|
import { basename, dirname, isAbsolute, join, resolve } from "node:path";
|
|
4
10
|
import { fileURLToPath } from "node:url";
|
|
@@ -43,13 +49,16 @@ function cloneDefaultRegistry() {
|
|
|
43
49
|
|
|
44
50
|
function expandHome(filePath) {
|
|
45
51
|
if (typeof filePath !== "string") return "";
|
|
46
|
-
if (!filePath.startsWith("~/") && !filePath.startsWith("~\\"))
|
|
52
|
+
if (!filePath.startsWith("~/") && !filePath.startsWith("~\\"))
|
|
53
|
+
return filePath;
|
|
47
54
|
return join(homedir(), filePath.slice(2));
|
|
48
55
|
}
|
|
49
56
|
|
|
50
57
|
function resolveFilePath(filePath) {
|
|
51
58
|
const expanded = expandHome(filePath);
|
|
52
|
-
return isAbsolute(expanded)
|
|
59
|
+
return isAbsolute(expanded)
|
|
60
|
+
? resolve(expanded)
|
|
61
|
+
: resolve(process.cwd(), expanded);
|
|
53
62
|
}
|
|
54
63
|
|
|
55
64
|
function normalizeForMatch(filePath) {
|
|
@@ -77,7 +86,11 @@ function ensureBackup(filePath) {
|
|
|
77
86
|
|
|
78
87
|
function isJsonMcpConfig(filePath) {
|
|
79
88
|
const name = pathBasename(filePath);
|
|
80
|
-
return
|
|
89
|
+
return (
|
|
90
|
+
name === "settings.json" ||
|
|
91
|
+
name === "settings.local.json" ||
|
|
92
|
+
name === ".mcp.json"
|
|
93
|
+
);
|
|
81
94
|
}
|
|
82
95
|
|
|
83
96
|
function isCodexConfig(filePath) {
|
|
@@ -90,9 +103,9 @@ function detectClient(filePath) {
|
|
|
90
103
|
if (normalized.endsWith("/.gemini/settings.json")) return "gemini";
|
|
91
104
|
if (normalized.endsWith("/.codex/config.toml")) return "codex";
|
|
92
105
|
if (
|
|
93
|
-
normalized.endsWith("/.claude/settings.json")
|
|
94
|
-
|
|
95
|
-
|
|
106
|
+
normalized.endsWith("/.claude/settings.json") ||
|
|
107
|
+
normalized.endsWith("/.claude/settings.local.json") ||
|
|
108
|
+
normalized.endsWith("/.mcp.json")
|
|
96
109
|
) {
|
|
97
110
|
return "claude";
|
|
98
111
|
}
|
|
@@ -104,16 +117,19 @@ function detectLabel(filePath) {
|
|
|
104
117
|
if (normalized.endsWith("/.gemini/settings.json")) return "Gemini";
|
|
105
118
|
if (normalized.endsWith("/.codex/config.toml")) return "Codex";
|
|
106
119
|
if (normalized.endsWith("/.claude/settings.json")) return "Claude User";
|
|
107
|
-
if (normalized.endsWith("/.claude/settings.local.json"))
|
|
120
|
+
if (normalized.endsWith("/.claude/settings.local.json"))
|
|
121
|
+
return "Claude Local";
|
|
108
122
|
if (normalized.endsWith("/.mcp.json")) return "Project MCP";
|
|
109
123
|
return basename(filePath);
|
|
110
124
|
}
|
|
111
125
|
|
|
112
126
|
function isPrimaryConfigTarget(filePath) {
|
|
113
127
|
const normalized = normalizeForMatch(filePath);
|
|
114
|
-
return
|
|
115
|
-
|
|
116
|
-
|
|
128
|
+
return (
|
|
129
|
+
normalized.endsWith("/.gemini/settings.json") ||
|
|
130
|
+
normalized.endsWith("/.codex/config.toml") ||
|
|
131
|
+
normalized.endsWith("/.mcp.json")
|
|
132
|
+
);
|
|
117
133
|
}
|
|
118
134
|
|
|
119
135
|
function normalizeUrl(value) {
|
|
@@ -192,15 +208,15 @@ function removeTomlSection(raw, sectionName) {
|
|
|
192
208
|
if (!skipping) output.push(line);
|
|
193
209
|
}
|
|
194
210
|
|
|
195
|
-
const cleaned = output
|
|
211
|
+
const cleaned = output
|
|
212
|
+
.join("\n")
|
|
213
|
+
.replace(/\n{3,}$/g, "\n\n")
|
|
214
|
+
.replace(/^\n+/, "");
|
|
196
215
|
return cleaned.length > 0 ? cleaned.replace(/\n{3,}/g, "\n\n") : "";
|
|
197
216
|
}
|
|
198
217
|
|
|
199
218
|
function upsertTomlUrlServer(raw, name, url) {
|
|
200
|
-
const section = [
|
|
201
|
-
`[mcp_servers.${name}]`,
|
|
202
|
-
`url = ${formatTomlString(url)}`,
|
|
203
|
-
];
|
|
219
|
+
const section = [`[mcp_servers.${name}]`, `url = ${formatTomlString(url)}`];
|
|
204
220
|
const withoutExisting = removeTomlSection(raw, name).trimEnd();
|
|
205
221
|
return withoutExisting.length > 0
|
|
206
222
|
? `${withoutExisting}\n\n${section.join("\n")}\n`
|
|
@@ -210,12 +226,19 @@ function upsertTomlUrlServer(raw, name, url) {
|
|
|
210
226
|
function getHubServerEntry(registry) {
|
|
211
227
|
const entries = Object.entries(registry?.servers || {});
|
|
212
228
|
if (entries.length === 0) {
|
|
213
|
-
return [
|
|
229
|
+
return [
|
|
230
|
+
"tfx-hub",
|
|
231
|
+
{
|
|
232
|
+
url: `${registry?.defaults?.hub_base || "http://127.0.0.1:27888"}${DEFAULT_HUB_PATH}`,
|
|
233
|
+
},
|
|
234
|
+
];
|
|
214
235
|
}
|
|
215
236
|
|
|
216
|
-
return
|
|
217
|
-
|
|
218
|
-
|
|
237
|
+
return (
|
|
238
|
+
entries.find(([name]) => name === "tfx-hub") ||
|
|
239
|
+
entries.find(([, config]) => config?.transport === "hub-url") ||
|
|
240
|
+
entries[0]
|
|
241
|
+
);
|
|
219
242
|
}
|
|
220
243
|
|
|
221
244
|
function _makeHubRuntimeConfig() {
|
|
@@ -224,7 +247,13 @@ function _makeHubRuntimeConfig() {
|
|
|
224
247
|
|
|
225
248
|
function serverTargets(serverConfig) {
|
|
226
249
|
if (Array.isArray(serverConfig?.targets) && serverConfig.targets.length > 0) {
|
|
227
|
-
return [
|
|
250
|
+
return [
|
|
251
|
+
...new Set(
|
|
252
|
+
serverConfig.targets
|
|
253
|
+
.map((value) => String(value).trim())
|
|
254
|
+
.filter(Boolean),
|
|
255
|
+
),
|
|
256
|
+
];
|
|
228
257
|
}
|
|
229
258
|
return ["claude", "gemini", "codex"];
|
|
230
259
|
}
|
|
@@ -234,9 +263,10 @@ function serverAppliesToClient(serverConfig, client) {
|
|
|
234
263
|
}
|
|
235
264
|
|
|
236
265
|
function buildDesiredServerRecord(name, serverConfig, filePath) {
|
|
237
|
-
const url =
|
|
238
|
-
|
|
239
|
-
|
|
266
|
+
const url =
|
|
267
|
+
serverConfig?.transport === "hub-url"
|
|
268
|
+
? resolveHubUrl()
|
|
269
|
+
: normalizeUrl(serverConfig?.url || "");
|
|
240
270
|
const basenameValue = pathBasename(filePath);
|
|
241
271
|
|
|
242
272
|
if (basenameValue === ".mcp.json") {
|
|
@@ -266,22 +296,30 @@ function scanJsonConfig(filePath) {
|
|
|
266
296
|
try {
|
|
267
297
|
const parsed = readJsonFile(filePath);
|
|
268
298
|
const mcpServers = parsed?.mcpServers;
|
|
269
|
-
const servers =
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
.
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
299
|
+
const servers =
|
|
300
|
+
!mcpServers || typeof mcpServers !== "object"
|
|
301
|
+
? []
|
|
302
|
+
: Object.entries(mcpServers)
|
|
303
|
+
.filter(
|
|
304
|
+
([name, config]) =>
|
|
305
|
+
typeof name === "string" &&
|
|
306
|
+
config &&
|
|
307
|
+
typeof config === "object",
|
|
308
|
+
)
|
|
309
|
+
.map(([name, config]) => ({
|
|
310
|
+
name: name.trim(),
|
|
311
|
+
url:
|
|
312
|
+
typeof config.url === "string" ? normalizeUrl(config.url) : "",
|
|
313
|
+
command: typeof config.command === "string" ? config.command : "",
|
|
314
|
+
type: typeof config.type === "string" ? config.type : "",
|
|
315
|
+
transport:
|
|
316
|
+
typeof config.url === "string" && config.url
|
|
317
|
+
? "url"
|
|
318
|
+
: typeof config.command === "string" && config.command
|
|
319
|
+
? "stdio"
|
|
320
|
+
: "unknown",
|
|
321
|
+
raw: config,
|
|
322
|
+
}));
|
|
285
323
|
|
|
286
324
|
return {
|
|
287
325
|
filePath,
|
|
@@ -325,11 +363,12 @@ function scanCodexConfig(filePath) {
|
|
|
325
363
|
name,
|
|
326
364
|
url: typeof config.url === "string" ? normalizeUrl(config.url) : "",
|
|
327
365
|
command: typeof config.command === "string" ? config.command : "",
|
|
328
|
-
transport:
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
366
|
+
transport:
|
|
367
|
+
typeof config.url === "string" && config.url
|
|
368
|
+
? "url"
|
|
369
|
+
: typeof config.command === "string" && config.command
|
|
370
|
+
? "stdio"
|
|
371
|
+
: "unknown",
|
|
333
372
|
raw: config,
|
|
334
373
|
}));
|
|
335
374
|
|
|
@@ -368,7 +407,11 @@ function updateJsonConfig(filePath, updates = [], removals = []) {
|
|
|
368
407
|
parsed = {};
|
|
369
408
|
}
|
|
370
409
|
|
|
371
|
-
if (
|
|
410
|
+
if (
|
|
411
|
+
!parsed.mcpServers ||
|
|
412
|
+
typeof parsed.mcpServers !== "object" ||
|
|
413
|
+
Array.isArray(parsed.mcpServers)
|
|
414
|
+
) {
|
|
372
415
|
parsed.mcpServers = {};
|
|
373
416
|
}
|
|
374
417
|
|
|
@@ -383,8 +426,12 @@ function updateJsonConfig(filePath, updates = [], removals = []) {
|
|
|
383
426
|
|
|
384
427
|
for (const update of updates) {
|
|
385
428
|
const current = parsed.mcpServers[update.name];
|
|
386
|
-
const nextConfig = {
|
|
387
|
-
|
|
429
|
+
const nextConfig = {
|
|
430
|
+
...(current && typeof current === "object" ? current : {}),
|
|
431
|
+
...update.config,
|
|
432
|
+
};
|
|
433
|
+
const changed =
|
|
434
|
+
JSON.stringify(current || null) !== JSON.stringify(nextConfig);
|
|
388
435
|
if (changed) {
|
|
389
436
|
parsed.mcpServers[update.name] = nextConfig;
|
|
390
437
|
modified = true;
|
|
@@ -412,7 +459,9 @@ function updateCodexConfig(filePath, updates = [], removals = []) {
|
|
|
412
459
|
}
|
|
413
460
|
|
|
414
461
|
const finalRaw = raw.trim().length > 0 ? `${raw.trimEnd()}\n` : "";
|
|
415
|
-
const previousRaw = existsSync(resolvedPath)
|
|
462
|
+
const previousRaw = existsSync(resolvedPath)
|
|
463
|
+
? readFileSync(resolvedPath, "utf8")
|
|
464
|
+
: "";
|
|
416
465
|
if (finalRaw === previousRaw) {
|
|
417
466
|
return { modified: false, filePath: resolvedPath };
|
|
418
467
|
}
|
|
@@ -460,7 +509,11 @@ export function validateRegistry(registry) {
|
|
|
460
509
|
errors.push("registry.defaults must be an object");
|
|
461
510
|
}
|
|
462
511
|
|
|
463
|
-
if (
|
|
512
|
+
if (
|
|
513
|
+
!registry.servers ||
|
|
514
|
+
typeof registry.servers !== "object" ||
|
|
515
|
+
Array.isArray(registry.servers)
|
|
516
|
+
) {
|
|
464
517
|
errors.push("registry.servers must be an object");
|
|
465
518
|
} else {
|
|
466
519
|
for (const [name, server] of Object.entries(registry.servers)) {
|
|
@@ -481,14 +534,23 @@ export function validateRegistry(registry) {
|
|
|
481
534
|
}
|
|
482
535
|
}
|
|
483
536
|
|
|
484
|
-
if (
|
|
537
|
+
if (
|
|
538
|
+
!registry.policies ||
|
|
539
|
+
typeof registry.policies !== "object" ||
|
|
540
|
+
Array.isArray(registry.policies)
|
|
541
|
+
) {
|
|
485
542
|
errors.push("registry.policies must be an object");
|
|
486
543
|
} else {
|
|
487
544
|
if (!Array.isArray(registry.policies.watched_paths)) {
|
|
488
545
|
errors.push("registry.policies.watched_paths must be an array");
|
|
489
546
|
}
|
|
490
|
-
if (
|
|
491
|
-
|
|
547
|
+
if (
|
|
548
|
+
registry.policies.stdio_action &&
|
|
549
|
+
!["replace-with-hub", "warn"].includes(registry.policies.stdio_action)
|
|
550
|
+
) {
|
|
551
|
+
errors.push(
|
|
552
|
+
"registry.policies.stdio_action must be replace-with-hub or warn",
|
|
553
|
+
);
|
|
492
554
|
}
|
|
493
555
|
}
|
|
494
556
|
|
|
@@ -578,7 +640,9 @@ export function listManagedConfigTargets(registry = loadRegistryOrDefault()) {
|
|
|
578
640
|
}
|
|
579
641
|
|
|
580
642
|
export function listPrimaryConfigTargets(registry = loadRegistryOrDefault()) {
|
|
581
|
-
return listManagedConfigTargets(registry).filter((target) =>
|
|
643
|
+
return listManagedConfigTargets(registry).filter((target) =>
|
|
644
|
+
isPrimaryConfigTarget(target.filePath),
|
|
645
|
+
);
|
|
582
646
|
}
|
|
583
647
|
|
|
584
648
|
export function scanManagedConfigs(registry = loadRegistryOrDefault()) {
|
|
@@ -590,17 +654,28 @@ export function scanManagedConfigs(registry = loadRegistryOrDefault()) {
|
|
|
590
654
|
|
|
591
655
|
export function inspectRegistryStatus(registry = loadRegistryOrDefault()) {
|
|
592
656
|
const configs = scanManagedConfigs(registry);
|
|
593
|
-
const primaryTargets = new Set(
|
|
657
|
+
const primaryTargets = new Set(
|
|
658
|
+
listPrimaryConfigTargets(registry).map((target) =>
|
|
659
|
+
normalizeForMatch(target.filePath),
|
|
660
|
+
),
|
|
661
|
+
);
|
|
594
662
|
const rows = [];
|
|
595
663
|
|
|
596
664
|
for (const config of configs) {
|
|
597
665
|
const isPrimary = primaryTargets.has(normalizeForMatch(config.filePath));
|
|
598
|
-
const managedServers = Object.entries(registry.servers || {})
|
|
599
|
-
|
|
666
|
+
const managedServers = Object.entries(registry.servers || {}).filter(
|
|
667
|
+
([, serverConfig]) =>
|
|
668
|
+
isPrimary && serverAppliesToClient(serverConfig, config.client),
|
|
669
|
+
);
|
|
600
670
|
|
|
601
671
|
for (const [name, serverConfig] of managedServers) {
|
|
602
|
-
const expectedUrl = buildDesiredServerRecord(
|
|
603
|
-
|
|
672
|
+
const expectedUrl = buildDesiredServerRecord(
|
|
673
|
+
name,
|
|
674
|
+
serverConfig,
|
|
675
|
+
config.filePath,
|
|
676
|
+
).config.url;
|
|
677
|
+
const actual =
|
|
678
|
+
config.servers.find((server) => server.name === name) || null;
|
|
604
679
|
let status = "missing";
|
|
605
680
|
|
|
606
681
|
if (!config.exists) {
|
|
@@ -658,7 +733,9 @@ export function scanForStdioServers(filePath) {
|
|
|
658
733
|
|
|
659
734
|
export function remediate(filePath, stdioServers, policy = {}) {
|
|
660
735
|
const resolvedPath = resolveFilePath(filePath);
|
|
661
|
-
const offenders = Array.isArray(stdioServers)
|
|
736
|
+
const offenders = Array.isArray(stdioServers)
|
|
737
|
+
? stdioServers.filter((server) => server?.name)
|
|
738
|
+
: [];
|
|
662
739
|
const action = policy?.stdio_action || "warn";
|
|
663
740
|
|
|
664
741
|
if (offenders.length === 0) {
|
|
@@ -724,7 +801,11 @@ export function remediate(filePath, stdioServers, policy = {}) {
|
|
|
724
801
|
if (action === "replace-with-hub") {
|
|
725
802
|
const registry = loadRegistryOrDefault();
|
|
726
803
|
const [hubServerName, hubServerConfig] = getHubServerEntry(registry);
|
|
727
|
-
const desired = buildDesiredServerRecord(
|
|
804
|
+
const desired = buildDesiredServerRecord(
|
|
805
|
+
hubServerName,
|
|
806
|
+
hubServerConfig,
|
|
807
|
+
resolvedPath,
|
|
808
|
+
);
|
|
728
809
|
replacement = { name: desired.name, ...desired.config };
|
|
729
810
|
updates.push(desired);
|
|
730
811
|
}
|
|
@@ -742,9 +823,13 @@ export function remediate(filePath, stdioServers, policy = {}) {
|
|
|
742
823
|
|
|
743
824
|
export function resolveHubUrl() {
|
|
744
825
|
const registryState = inspectRegistry();
|
|
745
|
-
const registry = registryState.valid
|
|
826
|
+
const registry = registryState.valid
|
|
827
|
+
? registryState.registry
|
|
828
|
+
: cloneDefaultRegistry();
|
|
746
829
|
const [, hubServer] = getHubServerEntry(registry);
|
|
747
|
-
const fallbackRaw =
|
|
830
|
+
const fallbackRaw =
|
|
831
|
+
hubServer?.url ||
|
|
832
|
+
`${registry?.defaults?.hub_base || "http://127.0.0.1:27888"}${DEFAULT_HUB_PATH}`;
|
|
748
833
|
|
|
749
834
|
let fallback;
|
|
750
835
|
try {
|
|
@@ -754,12 +839,16 @@ export function resolveHubUrl() {
|
|
|
754
839
|
}
|
|
755
840
|
|
|
756
841
|
const envPortRaw = Number(process.env.TFX_HUB_PORT || "");
|
|
757
|
-
const envPort =
|
|
842
|
+
const envPort =
|
|
843
|
+
Number.isFinite(envPortRaw) && envPortRaw > 0 ? envPortRaw : null;
|
|
758
844
|
const target = {
|
|
759
845
|
protocol: fallback.protocol || "http:",
|
|
760
846
|
host: fallback.hostname || "127.0.0.1",
|
|
761
847
|
port: envPort || Number(fallback.port || 27888),
|
|
762
|
-
pathname:
|
|
848
|
+
pathname:
|
|
849
|
+
fallback.pathname && fallback.pathname !== "/"
|
|
850
|
+
? fallback.pathname
|
|
851
|
+
: DEFAULT_HUB_PATH,
|
|
763
852
|
};
|
|
764
853
|
|
|
765
854
|
const hubPidPath = join(homedir(), ".claude", "cache", "tfx-hub", "hub.pid");
|
|
@@ -785,7 +874,9 @@ export function resolveHubUrl() {
|
|
|
785
874
|
|
|
786
875
|
export function isWatchedPath(filePath) {
|
|
787
876
|
const registryState = inspectRegistry();
|
|
788
|
-
const registry = registryState.valid
|
|
877
|
+
const registry = registryState.valid
|
|
878
|
+
? registryState.registry
|
|
879
|
+
: cloneDefaultRegistry();
|
|
789
880
|
const candidate = normalizeForMatch(filePath);
|
|
790
881
|
|
|
791
882
|
return (registry?.policies?.watched_paths || []).some((watchedPath) => {
|
|
@@ -802,7 +893,10 @@ export function isWatchedPath(filePath) {
|
|
|
802
893
|
return pathBasename(candidate) === trimmed.toLowerCase();
|
|
803
894
|
}
|
|
804
895
|
|
|
805
|
-
const suffix = trimmed
|
|
896
|
+
const suffix = trimmed
|
|
897
|
+
.replace(/^[.][\\/]/, "")
|
|
898
|
+
.replace(/\\/g, "/")
|
|
899
|
+
.toLowerCase();
|
|
806
900
|
return candidate.endsWith(`/${suffix}`);
|
|
807
901
|
});
|
|
808
902
|
}
|
|
@@ -814,16 +908,26 @@ export function addRegistryServer(name, url, options = {}) {
|
|
|
814
908
|
if (!normalizedUrl) throw new Error("server url is required");
|
|
815
909
|
|
|
816
910
|
const registryState = inspectRegistry();
|
|
817
|
-
const registry = registryState.valid
|
|
818
|
-
|
|
911
|
+
const registry = registryState.valid
|
|
912
|
+
? loadRegistry()
|
|
913
|
+
: cloneDefaultRegistry();
|
|
914
|
+
const transport =
|
|
915
|
+
options.transport || (trimmedName === "tfx-hub" ? "hub-url" : "url");
|
|
819
916
|
|
|
820
917
|
registry.servers[trimmedName] = {
|
|
821
918
|
transport,
|
|
822
919
|
url: normalizedUrl,
|
|
823
920
|
safe: options.safe ?? true,
|
|
824
|
-
targets:
|
|
825
|
-
|
|
826
|
-
|
|
921
|
+
targets:
|
|
922
|
+
Array.isArray(options.targets) && options.targets.length > 0
|
|
923
|
+
? [
|
|
924
|
+
...new Set(
|
|
925
|
+
options.targets
|
|
926
|
+
.map((value) => String(value).trim())
|
|
927
|
+
.filter(Boolean),
|
|
928
|
+
),
|
|
929
|
+
]
|
|
930
|
+
: ["claude", "gemini", "codex"],
|
|
827
931
|
description: options.description || `${trimmedName} MCP 서버`,
|
|
828
932
|
};
|
|
829
933
|
|
|
@@ -851,10 +955,13 @@ export function removeServerFromTargets(name, options = {}) {
|
|
|
851
955
|
const trimmedName = String(name || "").trim();
|
|
852
956
|
if (!trimmedName) throw new Error("server name is required");
|
|
853
957
|
|
|
854
|
-
const registry =
|
|
855
|
-
|
|
856
|
-
?
|
|
857
|
-
|
|
958
|
+
const registry =
|
|
959
|
+
options.registry ||
|
|
960
|
+
(inspectRegistry().valid ? loadRegistry() : cloneDefaultRegistry());
|
|
961
|
+
const targetsFilter =
|
|
962
|
+
Array.isArray(options.targets) && options.targets.length > 0
|
|
963
|
+
? new Set(options.targets)
|
|
964
|
+
: null;
|
|
858
965
|
const actions = [];
|
|
859
966
|
|
|
860
967
|
for (const target of listManagedConfigTargets(registry)) {
|
|
@@ -912,7 +1019,11 @@ export function syncRegistryTargets(options = {}) {
|
|
|
912
1019
|
}
|
|
913
1020
|
|
|
914
1021
|
if (snapshot.stdioServers.length > 0) {
|
|
915
|
-
const remediation = remediate(
|
|
1022
|
+
const remediation = remediate(
|
|
1023
|
+
target.filePath,
|
|
1024
|
+
snapshot.stdioServers,
|
|
1025
|
+
registry.policies,
|
|
1026
|
+
);
|
|
916
1027
|
actions.push({
|
|
917
1028
|
type: "remediate",
|
|
918
1029
|
filePath: target.filePath,
|
|
@@ -927,8 +1038,12 @@ export function syncRegistryTargets(options = {}) {
|
|
|
927
1038
|
|
|
928
1039
|
for (const target of listPrimaryConfigTargets(registry)) {
|
|
929
1040
|
const updates = Object.entries(registry.servers || {})
|
|
930
|
-
.filter(([, serverConfig]) =>
|
|
931
|
-
|
|
1041
|
+
.filter(([, serverConfig]) =>
|
|
1042
|
+
serverAppliesToClient(serverConfig, target.client),
|
|
1043
|
+
)
|
|
1044
|
+
.map(([name, serverConfig]) =>
|
|
1045
|
+
buildDesiredServerRecord(name, serverConfig, target.filePath),
|
|
1046
|
+
);
|
|
932
1047
|
|
|
933
1048
|
if (updates.length === 0) continue;
|
|
934
1049
|
|
|
@@ -2,33 +2,41 @@
|
|
|
2
2
|
// MCP 서버 활성화 매니페스트 — 단일 진실 소스.
|
|
3
3
|
// tfx-setup 위저드가 저장하고, gateway/filter가 참조한다.
|
|
4
4
|
|
|
5
|
-
import { existsSync, readFileSync, writeFileSync
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
5
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
6
|
+
import { homedir } from "node:os";
|
|
7
|
+
import { dirname, join } from "node:path";
|
|
8
8
|
|
|
9
|
-
export const MANIFEST_PATH = join(
|
|
9
|
+
export const MANIFEST_PATH = join(
|
|
10
|
+
homedir(),
|
|
11
|
+
".claude",
|
|
12
|
+
"cache",
|
|
13
|
+
"mcp-enabled.json",
|
|
14
|
+
);
|
|
10
15
|
|
|
11
16
|
/** API 키 불필요 — 항상 활성화 */
|
|
12
|
-
export const CORE_SERVERS = Object.freeze([
|
|
17
|
+
export const CORE_SERVERS = Object.freeze(["context7", "serena"]);
|
|
13
18
|
|
|
14
19
|
/** 검색 MCP — API 키 필요 */
|
|
15
20
|
export const SEARCH_SERVERS = Object.freeze([
|
|
16
|
-
{ name:
|
|
17
|
-
{ name:
|
|
18
|
-
{ name:
|
|
21
|
+
{ name: "brave-search", envVars: ["BRAVE_API_KEY"] },
|
|
22
|
+
{ name: "exa", envVars: ["EXA_API_KEY"] },
|
|
23
|
+
{ name: "tavily", envVars: ["TAVILY_API_KEY"] },
|
|
19
24
|
]);
|
|
20
25
|
|
|
21
26
|
/** 통합 MCP — API 키 + 추가 설정 필요 */
|
|
22
27
|
export const INTEGRATION_SERVERS = Object.freeze([
|
|
23
|
-
{
|
|
24
|
-
|
|
25
|
-
|
|
28
|
+
{
|
|
29
|
+
name: "jira",
|
|
30
|
+
envVars: ["JIRA_API_TOKEN", "JIRA_EMAIL", "JIRA_INSTANCE_URL"],
|
|
31
|
+
},
|
|
32
|
+
{ name: "notion", envVars: ["NOTION_TOKEN"] },
|
|
33
|
+
{ name: "notion-guest", envVars: ["NOTION_TOKEN"] },
|
|
26
34
|
]);
|
|
27
35
|
|
|
28
36
|
export function readManifest() {
|
|
29
37
|
if (!existsSync(MANIFEST_PATH)) return null;
|
|
30
38
|
try {
|
|
31
|
-
return JSON.parse(readFileSync(MANIFEST_PATH,
|
|
39
|
+
return JSON.parse(readFileSync(MANIFEST_PATH, "utf8"));
|
|
32
40
|
} catch {
|
|
33
41
|
return null;
|
|
34
42
|
}
|
|
@@ -56,7 +64,9 @@ export function filterByManifest(allServers) {
|
|
|
56
64
|
if (!manifest) return null;
|
|
57
65
|
const enabled = new Set(manifest.enabled || []);
|
|
58
66
|
for (const core of CORE_SERVERS) enabled.add(core);
|
|
59
|
-
return allServers.filter((s) =>
|
|
67
|
+
return allServers.filter((s) =>
|
|
68
|
+
enabled.has(typeof s === "string" ? s : s.name),
|
|
69
|
+
);
|
|
60
70
|
}
|
|
61
71
|
|
|
62
72
|
/**
|