@stanco323/oh-my-claude-code 4.10.3 ā 4.11.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 +2 -2
- package/.claude-plugin/plugin.json +1 -1
- package/README.md +65 -18
- package/bridge/cli.cjs +3030 -1784
- package/bridge/mcp-server.cjs +128 -98
- package/bridge/runtime-cli.cjs +174 -136
- package/bridge/team-bridge.cjs +102 -96
- package/bridge/team-mcp.cjs +40 -29
- package/bridge/team.js +102 -88
- package/dist/__tests__/auto-update.test.js +8 -9
- package/dist/__tests__/auto-update.test.js.map +1 -1
- package/dist/__tests__/cli-config-stop-callback.test.js +26 -0
- package/dist/__tests__/cli-config-stop-callback.test.js.map +1 -1
- package/dist/__tests__/config-dir.test.d.ts +2 -0
- package/dist/__tests__/config-dir.test.d.ts.map +1 -0
- package/dist/__tests__/config-dir.test.js +184 -0
- package/dist/__tests__/config-dir.test.js.map +1 -0
- package/dist/__tests__/delegation-enforcement-levels.test.js +45 -1
- package/dist/__tests__/delegation-enforcement-levels.test.js.map +1 -1
- package/dist/__tests__/doctor-conflicts.test.js +9 -7
- package/dist/__tests__/doctor-conflicts.test.js.map +1 -1
- package/dist/__tests__/hooks-command-escaping.test.js +17 -10
- package/dist/__tests__/hooks-command-escaping.test.js.map +1 -1
- package/dist/__tests__/hud/cli-diagnostic.test.js +1 -1
- package/dist/__tests__/hud/cli-diagnostic.test.js.map +1 -1
- package/dist/__tests__/hud/usage-api-lock.test.js +5 -5
- package/dist/__tests__/hud/usage-api-lock.test.js.map +1 -1
- package/dist/__tests__/hud/usage-api-stale.test.js +2 -2
- package/dist/__tests__/hud/usage-api-stale.test.js.map +1 -1
- package/dist/__tests__/hud/usage-api.test.js +98 -0
- package/dist/__tests__/hud/usage-api.test.js.map +1 -1
- package/dist/__tests__/hud-api-key-source.test.js +2 -2
- package/dist/__tests__/hud-api-key-source.test.js.map +1 -1
- package/dist/__tests__/hud-marketplace-resolution.test.js +3 -1
- package/dist/__tests__/hud-marketplace-resolution.test.js.map +1 -1
- package/dist/__tests__/hud-windows.test.js +7 -6
- package/dist/__tests__/hud-windows.test.js.map +1 -1
- package/dist/__tests__/installer-omc-reference.test.js +122 -6
- package/dist/__tests__/installer-omc-reference.test.js.map +1 -1
- package/dist/__tests__/installer.test.js +33 -9
- package/dist/__tests__/installer.test.js.map +1 -1
- package/dist/__tests__/omc-tools-server.test.js +5 -5
- package/dist/__tests__/pre-tool-enforcer.test.js +34 -14
- package/dist/__tests__/pre-tool-enforcer.test.js.map +1 -1
- package/dist/__tests__/preemptive-compaction-hook.test.d.ts +2 -0
- package/dist/__tests__/preemptive-compaction-hook.test.d.ts.map +1 -0
- package/dist/__tests__/preemptive-compaction-hook.test.js +163 -0
- package/dist/__tests__/preemptive-compaction-hook.test.js.map +1 -0
- package/dist/__tests__/purge-stale-cache.test.js +1 -1
- package/dist/__tests__/purge-stale-cache.test.js.map +1 -1
- package/dist/__tests__/release-generation.test.d.ts +2 -0
- package/dist/__tests__/release-generation.test.d.ts.map +1 -0
- package/dist/__tests__/release-generation.test.js +79 -0
- package/dist/__tests__/release-generation.test.js.map +1 -0
- package/dist/__tests__/runtime-guidance-plan-ralph.test.d.ts +2 -0
- package/dist/__tests__/runtime-guidance-plan-ralph.test.d.ts.map +1 -0
- package/dist/__tests__/runtime-guidance-plan-ralph.test.js +87 -0
- package/dist/__tests__/runtime-guidance-plan-ralph.test.js.map +1 -0
- package/dist/__tests__/session-history-search.test.js +31 -3
- package/dist/__tests__/session-history-search.test.js.map +1 -1
- package/dist/__tests__/setup-claude-md-script.test.js +9 -1
- package/dist/__tests__/setup-claude-md-script.test.js.map +1 -1
- package/dist/__tests__/setup-no-plugin-flag.test.d.ts +2 -0
- package/dist/__tests__/setup-no-plugin-flag.test.d.ts.map +1 -0
- package/dist/__tests__/setup-no-plugin-flag.test.js +15 -0
- package/dist/__tests__/setup-no-plugin-flag.test.js.map +1 -0
- package/dist/__tests__/shared-memory.test.js +40 -2
- package/dist/__tests__/shared-memory.test.js.map +1 -1
- package/dist/__tests__/skills.test.js +45 -1
- package/dist/__tests__/skills.test.js.map +1 -1
- package/dist/cli/__tests__/launch.test.js +48 -14
- package/dist/cli/__tests__/launch.test.js.map +1 -1
- package/dist/cli/commands/__tests__/team-role-shorthand.test.d.ts +2 -0
- package/dist/cli/commands/__tests__/team-role-shorthand.test.d.ts.map +1 -0
- package/dist/cli/commands/__tests__/team-role-shorthand.test.js +63 -0
- package/dist/cli/commands/__tests__/team-role-shorthand.test.js.map +1 -0
- package/dist/cli/commands/__tests__/team.test.js +21 -0
- package/dist/cli/commands/__tests__/team.test.js.map +1 -1
- package/dist/cli/commands/adapt.d.ts.map +1 -1
- package/dist/cli/commands/adapt.js.map +1 -1
- package/dist/cli/commands/doctor-conflicts.js +1 -1
- package/dist/cli/commands/doctor-conflicts.js.map +1 -1
- package/dist/cli/commands/team.d.ts.map +1 -1
- package/dist/cli/commands/team.js +30 -17
- package/dist/cli/commands/team.js.map +1 -1
- package/dist/cli/index.js +16 -7
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/launch.d.ts.map +1 -1
- package/dist/cli/launch.js +22 -14
- package/dist/cli/launch.js.map +1 -1
- package/dist/commands/index.js +1 -1
- package/dist/commands/index.js.map +1 -1
- package/dist/constants/names.d.ts +1 -0
- package/dist/constants/names.d.ts.map +1 -1
- package/dist/constants/names.js +1 -0
- package/dist/constants/names.js.map +1 -1
- package/dist/features/auto-update.d.ts.map +1 -1
- package/dist/features/auto-update.js +4 -4
- package/dist/features/auto-update.js.map +1 -1
- package/dist/features/background-agent/manager.js +1 -1
- package/dist/features/background-agent/manager.js.map +1 -1
- package/dist/features/builtin-skills/runtime-guidance.d.ts.map +1 -1
- package/dist/features/builtin-skills/runtime-guidance.js +35 -3
- package/dist/features/builtin-skills/runtime-guidance.js.map +1 -1
- package/dist/features/builtin-skills/skills.d.ts.map +1 -1
- package/dist/features/builtin-skills/skills.js +53 -1
- package/dist/features/builtin-skills/skills.js.map +1 -1
- package/dist/features/session-history-search/index.d.ts.map +1 -1
- package/dist/features/session-history-search/index.js +1 -4
- package/dist/features/session-history-search/index.js.map +1 -1
- package/dist/hooks/__tests__/bridge-routing.test.js +4 -0
- package/dist/hooks/__tests__/bridge-routing.test.js.map +1 -1
- package/dist/hooks/__tests__/bridge.test.js +42 -1
- package/dist/hooks/__tests__/bridge.test.js.map +1 -1
- package/dist/hooks/auto-slash-command/executor.js +2 -2
- package/dist/hooks/auto-slash-command/executor.js.map +1 -1
- package/dist/hooks/autopilot/enforcement.d.ts.map +1 -1
- package/dist/hooks/autopilot/enforcement.js +20 -4
- package/dist/hooks/autopilot/enforcement.js.map +1 -1
- package/dist/hooks/bridge.d.ts +15 -0
- package/dist/hooks/bridge.d.ts.map +1 -1
- package/dist/hooks/bridge.js +38 -1
- package/dist/hooks/bridge.js.map +1 -1
- package/dist/hooks/factcheck/__tests__/factcheck.test.js +6 -5
- package/dist/hooks/factcheck/__tests__/factcheck.test.js.map +1 -1
- package/dist/hooks/factcheck/config.d.ts +2 -2
- package/dist/hooks/factcheck/config.d.ts.map +1 -1
- package/dist/hooks/factcheck/config.js +6 -4
- package/dist/hooks/factcheck/config.js.map +1 -1
- package/dist/hooks/index.d.ts +1 -1
- package/dist/hooks/index.d.ts.map +1 -1
- package/dist/hooks/index.js +1 -1
- package/dist/hooks/index.js.map +1 -1
- package/dist/hooks/learner/auto-invoke.js +1 -1
- package/dist/hooks/learner/auto-invoke.js.map +1 -1
- package/dist/hooks/learner/config.js +1 -1
- package/dist/hooks/learner/config.js.map +1 -1
- package/dist/hooks/learner/constants.js +1 -1
- package/dist/hooks/learner/constants.js.map +1 -1
- package/dist/hooks/omc-orchestrator/constants.d.ts +1 -1
- package/dist/hooks/omc-orchestrator/constants.d.ts.map +1 -1
- package/dist/hooks/omc-orchestrator/constants.js +2 -2
- package/dist/hooks/omc-orchestrator/constants.js.map +1 -1
- package/dist/hooks/omc-orchestrator/index.d.ts.map +1 -1
- package/dist/hooks/omc-orchestrator/index.js +10 -7
- package/dist/hooks/omc-orchestrator/index.js.map +1 -1
- package/dist/hooks/permission-handler/index.js +1 -1
- package/dist/hooks/permission-handler/index.js.map +1 -1
- package/dist/hooks/persistent-mode/index.d.ts.map +1 -1
- package/dist/hooks/persistent-mode/index.js +21 -4
- package/dist/hooks/persistent-mode/index.js.map +1 -1
- package/dist/hooks/persistent-mode/stop-hook-blocking.test.js +91 -0
- package/dist/hooks/persistent-mode/stop-hook-blocking.test.js.map +1 -1
- package/dist/hooks/rules-injector/constants.d.ts +0 -2
- package/dist/hooks/rules-injector/constants.d.ts.map +1 -1
- package/dist/hooks/rules-injector/constants.js +0 -2
- package/dist/hooks/rules-injector/constants.js.map +1 -1
- package/dist/hooks/rules-injector/finder.d.ts +3 -3
- package/dist/hooks/rules-injector/finder.d.ts.map +1 -1
- package/dist/hooks/rules-injector/finder.js +7 -6
- package/dist/hooks/rules-injector/finder.js.map +1 -1
- package/dist/hooks/rules-injector/index.d.ts +1 -1
- package/dist/hooks/rules-injector/index.d.ts.map +1 -1
- package/dist/hooks/rules-injector/index.js +3 -6
- package/dist/hooks/rules-injector/index.js.map +1 -1
- package/dist/hooks/setup/__tests__/stdin-symlink.test.d.ts +2 -0
- package/dist/hooks/setup/__tests__/stdin-symlink.test.d.ts.map +1 -0
- package/dist/hooks/setup/__tests__/stdin-symlink.test.js +184 -0
- package/dist/hooks/setup/__tests__/stdin-symlink.test.js.map +1 -0
- package/dist/hooks/setup/index.d.ts +13 -0
- package/dist/hooks/setup/index.d.ts.map +1 -1
- package/dist/hooks/setup/index.js +100 -2
- package/dist/hooks/setup/index.js.map +1 -1
- package/dist/hooks/skill-bridge.cjs +19 -13
- package/dist/hooks/subagent-tracker/index.d.ts.map +1 -1
- package/dist/hooks/subagent-tracker/index.js +7 -3
- package/dist/hooks/subagent-tracker/index.js.map +1 -1
- package/dist/hooks/todo-continuation/index.js +1 -1
- package/dist/hooks/todo-continuation/index.js.map +1 -1
- package/dist/hooks/wiki/__tests__/ingest.test.d.ts +5 -0
- package/dist/hooks/wiki/__tests__/ingest.test.d.ts.map +1 -0
- package/dist/hooks/wiki/__tests__/ingest.test.js +180 -0
- package/dist/hooks/wiki/__tests__/ingest.test.js.map +1 -0
- package/dist/hooks/wiki/__tests__/lint.test.d.ts +5 -0
- package/dist/hooks/wiki/__tests__/lint.test.d.ts.map +1 -0
- package/dist/hooks/wiki/__tests__/lint.test.js +162 -0
- package/dist/hooks/wiki/__tests__/lint.test.js.map +1 -0
- package/dist/hooks/wiki/__tests__/query.test.d.ts +5 -0
- package/dist/hooks/wiki/__tests__/query.test.d.ts.map +1 -0
- package/dist/hooks/wiki/__tests__/query.test.js +119 -0
- package/dist/hooks/wiki/__tests__/query.test.js.map +1 -0
- package/dist/hooks/wiki/__tests__/session-hooks.test.d.ts +5 -0
- package/dist/hooks/wiki/__tests__/session-hooks.test.d.ts.map +1 -0
- package/dist/hooks/wiki/__tests__/session-hooks.test.js +40 -0
- package/dist/hooks/wiki/__tests__/session-hooks.test.js.map +1 -0
- package/dist/hooks/wiki/__tests__/storage.test.d.ts +5 -0
- package/dist/hooks/wiki/__tests__/storage.test.d.ts.map +1 -0
- package/dist/hooks/wiki/__tests__/storage.test.js +277 -0
- package/dist/hooks/wiki/__tests__/storage.test.js.map +1 -0
- package/dist/hooks/wiki/index.d.ts +13 -0
- package/dist/hooks/wiki/index.d.ts.map +1 -0
- package/dist/hooks/wiki/index.js +16 -0
- package/dist/hooks/wiki/index.js.map +1 -0
- package/dist/hooks/wiki/ingest.d.ts +20 -0
- package/dist/hooks/wiki/ingest.d.ts.map +1 -0
- package/dist/hooks/wiki/ingest.js +115 -0
- package/dist/hooks/wiki/ingest.js.map +1 -0
- package/dist/hooks/wiki/lint.d.ts +25 -0
- package/dist/hooks/wiki/lint.d.ts.map +1 -0
- package/dist/hooks/wiki/lint.js +166 -0
- package/dist/hooks/wiki/lint.js.map +1 -0
- package/dist/hooks/wiki/query.d.ts +27 -0
- package/dist/hooks/wiki/query.d.ts.map +1 -0
- package/dist/hooks/wiki/query.js +97 -0
- package/dist/hooks/wiki/query.js.map +1 -0
- package/dist/hooks/wiki/session-hooks.d.ts +42 -0
- package/dist/hooks/wiki/session-hooks.d.ts.map +1 -0
- package/dist/hooks/wiki/session-hooks.js +228 -0
- package/dist/hooks/wiki/session-hooks.js.map +1 -0
- package/dist/hooks/wiki/storage.d.ts +73 -0
- package/dist/hooks/wiki/storage.d.ts.map +1 -0
- package/dist/hooks/wiki/storage.js +343 -0
- package/dist/hooks/wiki/storage.js.map +1 -0
- package/dist/hooks/wiki/types.d.ts +136 -0
- package/dist/hooks/wiki/types.d.ts.map +1 -0
- package/dist/hooks/wiki/types.js +19 -0
- package/dist/hooks/wiki/types.js.map +1 -0
- package/dist/hud/custom-rate-provider.js +1 -1
- package/dist/hud/custom-rate-provider.js.map +1 -1
- package/dist/hud/elements/api-key-source.js +1 -1
- package/dist/hud/elements/api-key-source.js.map +1 -1
- package/dist/hud/index.js +1 -1
- package/dist/hud/index.js.map +1 -1
- package/dist/hud/state.js +1 -1
- package/dist/hud/state.js.map +1 -1
- package/dist/hud/usage-api.d.ts.map +1 -1
- package/dist/hud/usage-api.js +6 -2
- package/dist/hud/usage-api.js.map +1 -1
- package/dist/installer/__tests__/standalone-hook-reconcile.test.js +3 -0
- package/dist/installer/__tests__/standalone-hook-reconcile.test.js.map +1 -1
- package/dist/installer/hooks.d.ts +0 -2
- package/dist/installer/hooks.d.ts.map +1 -1
- package/dist/installer/hooks.js +1 -5
- package/dist/installer/hooks.js.map +1 -1
- package/dist/installer/index.d.ts +3 -0
- package/dist/installer/index.d.ts.map +1 -1
- package/dist/installer/index.js +176 -32
- package/dist/installer/index.js.map +1 -1
- package/dist/installer/mcp-registry.js +2 -2
- package/dist/installer/mcp-registry.js.map +1 -1
- package/dist/lib/release-generation.d.ts +20 -0
- package/dist/lib/release-generation.d.ts.map +1 -0
- package/dist/lib/release-generation.js +198 -0
- package/dist/lib/release-generation.js.map +1 -0
- package/dist/lib/shared-memory.d.ts +2 -1
- package/dist/lib/shared-memory.d.ts.map +1 -1
- package/dist/lib/shared-memory.js +4 -2
- package/dist/lib/shared-memory.js.map +1 -1
- package/dist/lib/worktree-paths.d.ts.map +1 -1
- package/dist/lib/worktree-paths.js +36 -10
- package/dist/lib/worktree-paths.js.map +1 -1
- package/dist/mcp/omc-tools-server.d.ts +2 -0
- package/dist/mcp/omc-tools-server.d.ts.map +1 -1
- package/dist/mcp/omc-tools-server.js +9 -2
- package/dist/mcp/omc-tools-server.js.map +1 -1
- package/dist/notifications/__tests__/config-merge.test.js +1 -1
- package/dist/notifications/__tests__/config-merge.test.js.map +1 -1
- package/dist/notifications/__tests__/profiles.test.js +1 -1
- package/dist/notifications/__tests__/profiles.test.js.map +1 -1
- package/dist/notifications/config.js +1 -1
- package/dist/notifications/config.js.map +1 -1
- package/dist/notifications/hook-config.js +1 -1
- package/dist/notifications/hook-config.js.map +1 -1
- package/dist/openclaw/__tests__/config.test.js +1 -1
- package/dist/openclaw/__tests__/config.test.js.map +1 -1
- package/dist/openclaw/config.js +1 -1
- package/dist/openclaw/config.js.map +1 -1
- package/dist/skills/__tests__/mingw-escape.test.js +1 -1
- package/dist/skills/__tests__/mingw-escape.test.js.map +1 -1
- package/dist/team/__tests__/api-interop.dispatch.test.js +2 -1
- package/dist/team/__tests__/api-interop.dispatch.test.js.map +1 -1
- package/dist/team/__tests__/bridge-integration.test.js +5 -3
- package/dist/team/__tests__/bridge-integration.test.js.map +1 -1
- package/dist/team/__tests__/edge-cases.test.js +6 -7
- package/dist/team/__tests__/edge-cases.test.js.map +1 -1
- package/dist/team/__tests__/inbox-outbox.test.js +2 -2
- package/dist/team/__tests__/inbox-outbox.test.js.map +1 -1
- package/dist/team/__tests__/message-router.test.js +6 -5
- package/dist/team/__tests__/message-router.test.js.map +1 -1
- package/dist/team/__tests__/outbox-reader.test.js +2 -2
- package/dist/team/__tests__/outbox-reader.test.js.map +1 -1
- package/dist/team/__tests__/runtime-v2.dispatch.test.js +4 -4
- package/dist/team/__tests__/runtime-v2.dispatch.test.js.map +1 -1
- package/dist/team/__tests__/shell-affinity.test.js +16 -0
- package/dist/team/__tests__/shell-affinity.test.js.map +1 -1
- package/dist/team/__tests__/team-registration.test.js +3 -2
- package/dist/team/__tests__/team-registration.test.js.map +1 -1
- package/dist/team/__tests__/team-status.test.js +3 -3
- package/dist/team/__tests__/team-status.test.js.map +1 -1
- package/dist/team/__tests__/tmux-session.test.js +6 -1
- package/dist/team/__tests__/tmux-session.test.js.map +1 -1
- package/dist/team/bridge-entry.js +1 -1
- package/dist/team/bridge-entry.js.map +1 -1
- package/dist/team/inbox-outbox.js +1 -1
- package/dist/team/inbox-outbox.js.map +1 -1
- package/dist/team/message-router.js +1 -1
- package/dist/team/message-router.js.map +1 -1
- package/dist/team/outbox-reader.js +1 -1
- package/dist/team/outbox-reader.js.map +1 -1
- package/dist/team/runtime-v2.d.ts.map +1 -1
- package/dist/team/runtime-v2.js +6 -17
- package/dist/team/runtime-v2.js.map +1 -1
- package/dist/team/task-file-ops.js +1 -1
- package/dist/team/task-file-ops.js.map +1 -1
- package/dist/team/team-registration.js +1 -1
- package/dist/team/team-registration.js.map +1 -1
- package/dist/team/team-status.js +1 -1
- package/dist/team/team-status.js.map +1 -1
- package/dist/team/tmux-session.d.ts +1 -1
- package/dist/team/tmux-session.d.ts.map +1 -1
- package/dist/team/tmux-session.js +39 -4
- package/dist/team/tmux-session.js.map +1 -1
- package/dist/team/unified-team.js +1 -1
- package/dist/team/unified-team.js.map +1 -1
- package/dist/tools/shared-memory-tools.d.ts.map +1 -1
- package/dist/tools/shared-memory-tools.js +2 -1
- package/dist/tools/shared-memory-tools.js.map +1 -1
- package/dist/tools/skills-tools.d.ts.map +1 -1
- package/dist/tools/skills-tools.js +3 -2
- package/dist/tools/skills-tools.js.map +1 -1
- package/dist/tools/wiki-tools.d.ts +74 -0
- package/dist/tools/wiki-tools.d.ts.map +1 -0
- package/dist/tools/wiki-tools.js +370 -0
- package/dist/tools/wiki-tools.js.map +1 -0
- package/dist/utils/config-dir.d.ts +21 -1
- package/dist/utils/config-dir.d.ts.map +1 -1
- package/dist/utils/config-dir.js +45 -4
- package/dist/utils/config-dir.js.map +1 -1
- package/dist/utils/paths.d.ts +0 -5
- package/dist/utils/paths.d.ts.map +1 -1
- package/dist/utils/paths.js +1 -8
- package/dist/utils/paths.js.map +1 -1
- package/docs/CLAUDE.md +1 -1
- package/hooks/hooks.json +15 -0
- package/package.json +1 -1
- package/scripts/cleanup-orphans.mjs +2 -2
- package/scripts/context-guard-stop.mjs +10 -4
- package/scripts/find-node.sh +13 -1
- package/scripts/keyword-detector.mjs +9 -2
- package/scripts/lib/config-dir.cjs +31 -0
- package/scripts/lib/config-dir.mjs +29 -0
- package/scripts/lib/config-dir.sh +18 -0
- package/scripts/lib/pre-tool-enforcer-preflight.mjs +63 -0
- package/scripts/persistent-mode.cjs +29 -6
- package/scripts/persistent-mode.mjs +24 -4
- package/scripts/plugin-setup.mjs +18 -7
- package/scripts/post-tool-verifier.mjs +200 -7
- package/scripts/pre-tool-enforcer.mjs +15 -56
- package/scripts/release.ts +158 -224
- package/scripts/session-start.mjs +6 -4
- package/scripts/session-summary.mjs +6 -1
- package/scripts/setup-claude-md.sh +4 -2
- package/scripts/setup-progress.sh +4 -1
- package/scripts/skill-injector.mjs +2 -1
- package/scripts/sync-version.sh +3 -3
- package/scripts/test-pr25.sh +9 -5
- package/scripts/uninstall.sh +5 -2
- package/scripts/wiki-pre-compact.mjs +17 -0
- package/scripts/wiki-session-end.mjs +17 -0
- package/scripts/wiki-session-start.mjs +17 -0
- package/skills/cancel/SKILL.md +4 -4
- package/skills/configure-notifications/SKILL.md +12 -12
- package/skills/hud/SKILL.md +4 -4
- package/skills/learner/SKILL.md +1 -1
- package/skills/omc-doctor/SKILL.md +25 -25
- package/skills/omc-setup/SKILL.md +1 -1
- package/skills/omc-setup/phases/02-configure.md +2 -2
- package/skills/omc-setup/phases/03-integrations.md +7 -7
- package/skills/omc-setup/phases/04-welcome.md +3 -3
- package/skills/ralph/SKILL.md +6 -2
- package/skills/skill/SKILL.md +9 -9
- package/skills/team/SKILL.md +1 -1
- package/skills/wiki/SKILL.md +67 -0
- package/templates/hooks/keyword-detector.mjs +4 -2
- package/templates/hooks/lib/config-dir.mjs +29 -0
- package/templates/hooks/persistent-mode.mjs +24 -4
- package/templates/hooks/session-start.mjs +7 -4
package/scripts/release.ts
CHANGED
|
@@ -3,7 +3,8 @@
|
|
|
3
3
|
* Release Automation Script
|
|
4
4
|
*
|
|
5
5
|
* Automates version bumping, changelog generation, and release notes creation.
|
|
6
|
-
* Uses
|
|
6
|
+
* Uses merged PR metadata when available so changelog content, PR counts,
|
|
7
|
+
* and contributors all reflect the same release dataset.
|
|
7
8
|
*
|
|
8
9
|
* Usage:
|
|
9
10
|
* npm run release -- patch # Bump patch version
|
|
@@ -18,10 +19,25 @@ import { join, resolve } from 'path';
|
|
|
18
19
|
import { execSync } from 'child_process';
|
|
19
20
|
import { fileURLToPath } from 'url';
|
|
20
21
|
import { dirname } from 'path';
|
|
22
|
+
import {
|
|
23
|
+
type ReleasePullRequest,
|
|
24
|
+
type ReleaseNoteEntry,
|
|
25
|
+
extractPullRequestNumbers,
|
|
26
|
+
isReleasePullRequest,
|
|
27
|
+
deriveContributorLogins,
|
|
28
|
+
buildReleaseNoteEntriesFromPullRequests,
|
|
29
|
+
categorizeReleaseNoteEntries,
|
|
30
|
+
generateChangelog,
|
|
31
|
+
generateReleaseBody,
|
|
32
|
+
} from '../src/lib/release-generation.ts';
|
|
21
33
|
|
|
22
34
|
const __filename = fileURLToPath(import.meta.url);
|
|
23
35
|
const __dirname = dirname(__filename);
|
|
24
36
|
const ROOT = resolve(__dirname, '..');
|
|
37
|
+
const DEFAULT_REPO_SLUG = 'Yeachan-Heo/oh-my-claudecode';
|
|
38
|
+
const REPO_SLUG = process.env.GITHUB_REPOSITORY || DEFAULT_REPO_SLUG;
|
|
39
|
+
const REPO_URL = `https://github.com/${REPO_SLUG}`;
|
|
40
|
+
const GITHUB_API_URL = process.env.GITHUB_API_URL || 'https://api.github.com';
|
|
25
41
|
|
|
26
42
|
// āā Colors āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
27
43
|
|
|
@@ -51,9 +67,16 @@ interface ParsedCommit {
|
|
|
51
67
|
raw: string;
|
|
52
68
|
}
|
|
53
69
|
|
|
54
|
-
interface
|
|
70
|
+
interface GitHubPullRequestResponse {
|
|
55
71
|
title: string;
|
|
56
|
-
|
|
72
|
+
user?: { login?: string | null } | null;
|
|
73
|
+
head?: { ref?: string | null } | null;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
interface GitHubCompareResponse {
|
|
77
|
+
commits?: Array<{
|
|
78
|
+
author?: { login?: string | null } | null;
|
|
79
|
+
}>;
|
|
57
80
|
}
|
|
58
81
|
|
|
59
82
|
// āā Version helpers āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
@@ -85,243 +108,123 @@ function bumpVersion(current: string, bump: string): string {
|
|
|
85
108
|
|
|
86
109
|
// āā Git helpers āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
87
110
|
|
|
88
|
-
function
|
|
111
|
+
function getGitLog(tag: string, format: string, flags: string[] = []): string[] {
|
|
89
112
|
const range = tag ? `${tag}..HEAD` : 'HEAD';
|
|
90
|
-
const
|
|
91
|
-
|
|
92
|
-
{ cwd: ROOT, encoding: 'utf-8' }
|
|
93
|
-
).trim();
|
|
113
|
+
const cmd = ['git', 'log', range, `--format=${JSON.stringify(format)}`, ...flags].join(' ');
|
|
114
|
+
const raw = execSync(cmd, { cwd: ROOT, encoding: 'utf-8' }).trim();
|
|
94
115
|
return raw ? raw.split('\n') : [];
|
|
95
116
|
}
|
|
96
117
|
|
|
97
|
-
function
|
|
98
|
-
|
|
99
|
-
const raw = execSync(
|
|
100
|
-
`git log ${range} --format="%s" --merges`,
|
|
101
|
-
{ cwd: ROOT, encoding: 'utf-8' }
|
|
102
|
-
).trim();
|
|
103
|
-
return raw ? raw.split('\n') : [];
|
|
118
|
+
function getCommitLinesSinceTag(tag: string): string[] {
|
|
119
|
+
return getGitLog(tag, '%H|%s');
|
|
104
120
|
}
|
|
105
121
|
|
|
106
|
-
function
|
|
107
|
-
|
|
108
|
-
const contributors = new Set<string>();
|
|
109
|
-
|
|
110
|
-
for (const msg of merges) {
|
|
111
|
-
const match = msg.match(/from\s+([^/]+)\//);
|
|
112
|
-
if (match && match[1]) {
|
|
113
|
-
const user = match[1].trim();
|
|
114
|
-
if (user && !user.startsWith('#')) {
|
|
115
|
-
contributors.add(user);
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
return [...contributors].sort();
|
|
122
|
+
function getNonMergeCommitLinesSinceTag(tag: string): string[] {
|
|
123
|
+
return getGitLog(tag, '%H|%s', ['--no-merges']);
|
|
121
124
|
}
|
|
122
125
|
|
|
123
|
-
function
|
|
124
|
-
|
|
125
|
-
return merges.filter(m => m.startsWith('Merge pull request')).length;
|
|
126
|
+
function getHeadSha(): string {
|
|
127
|
+
return execSync('git rev-parse HEAD', { cwd: ROOT, encoding: 'utf-8' }).trim();
|
|
126
128
|
}
|
|
127
129
|
|
|
128
|
-
// āā Commit parsing
|
|
129
|
-
|
|
130
|
-
const CONVENTIONAL_RE = /^(?<type>[a-z]+)(?:\((?<scope>[^)]*)\))?:\s*(?<desc>.+)$/;
|
|
130
|
+
// āā Commit / PR parsing āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
131
131
|
|
|
132
132
|
function parseCommit(line: string): ParsedCommit | null {
|
|
133
133
|
const [hash, ...rest] = line.split('|');
|
|
134
134
|
const raw = rest.join('|');
|
|
135
135
|
|
|
136
136
|
if (!raw) return null;
|
|
137
|
-
|
|
138
|
-
// Skip merge commits, chore(release) version bumps
|
|
139
137
|
if (raw.startsWith('Merge ')) return null;
|
|
140
138
|
if (raw.match(/^chore\(release\)/i)) return null;
|
|
141
139
|
|
|
142
|
-
const
|
|
143
|
-
if (!
|
|
140
|
+
const conventionalMatch = raw.match(/^(?<type>[a-z]+)(?:\((?<scope>[^)]*)\))?:\s*(?<desc>.+)$/);
|
|
141
|
+
if (!conventionalMatch?.groups) return null;
|
|
144
142
|
|
|
145
143
|
const prMatch = raw.match(/\(#(\d+)\)/);
|
|
146
144
|
|
|
147
145
|
return {
|
|
148
146
|
hash: hash.trim(),
|
|
149
|
-
type:
|
|
150
|
-
scope:
|
|
151
|
-
description:
|
|
147
|
+
type: conventionalMatch.groups.type,
|
|
148
|
+
scope: conventionalMatch.groups.scope || '',
|
|
149
|
+
description: conventionalMatch.groups.desc.replace(/\s*\(#\d+\)$/, '').trim(),
|
|
152
150
|
prNumber: prMatch ? prMatch[1] : null,
|
|
153
151
|
raw,
|
|
154
152
|
};
|
|
155
153
|
}
|
|
156
154
|
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
if (commit.type === 'feat') {
|
|
166
|
-
category = 'features';
|
|
167
|
-
} else if (commit.type === 'fix' && /^(security|deps)$/.test(commit.scope)) {
|
|
168
|
-
category = 'security';
|
|
169
|
-
} else if (commit.type === 'fix') {
|
|
170
|
-
category = 'fixes';
|
|
171
|
-
} else if (commit.type === 'refactor') {
|
|
172
|
-
category = 'refactoring';
|
|
173
|
-
} else if (commit.type === 'docs') {
|
|
174
|
-
category = 'docs';
|
|
175
|
-
} else if (commit.type === 'chore' && commit.scope === 'deps') {
|
|
176
|
-
category = 'security';
|
|
177
|
-
} else if (commit.type === 'perf') {
|
|
178
|
-
category = 'features';
|
|
179
|
-
} else {
|
|
180
|
-
// skip test, chore, ci, build, style
|
|
181
|
-
continue;
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
if (!categories.has(category)) categories.set(category, []);
|
|
185
|
-
categories.get(category)!.push(commit);
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
return categories;
|
|
155
|
+
function toReleaseNoteEntryFromCommit(commit: ParsedCommit): ReleaseNoteEntry {
|
|
156
|
+
return {
|
|
157
|
+
type: commit.type,
|
|
158
|
+
scope: commit.scope,
|
|
159
|
+
description: commit.description,
|
|
160
|
+
prNumber: commit.prNumber,
|
|
161
|
+
};
|
|
189
162
|
}
|
|
190
163
|
|
|
191
|
-
// āā Changelog generation āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
192
164
|
|
|
193
|
-
|
|
194
|
-
const scope = commit.scope ? `(${commit.scope})` : '';
|
|
195
|
-
const pr = commit.prNumber ? ` (#${commit.prNumber})` : '';
|
|
196
|
-
return `- **${commit.type}${scope}: ${commit.description}**${pr}`;
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
function generateTitle(categories: Map<string, ParsedCommit[]>): string {
|
|
200
|
-
const parts: string[] = [];
|
|
201
|
-
|
|
202
|
-
if (categories.has('features')) {
|
|
203
|
-
// Pick the most notable feature keywords
|
|
204
|
-
const feats = categories.get('features')!;
|
|
205
|
-
const keywords = feats
|
|
206
|
-
.slice(0, 3)
|
|
207
|
-
.map(f => {
|
|
208
|
-
// Extract key noun from description
|
|
209
|
-
const words = f.description.split(/\s+/);
|
|
210
|
-
return words.slice(0, 3).join(' ');
|
|
211
|
-
});
|
|
212
|
-
parts.push(...keywords);
|
|
213
|
-
}
|
|
214
|
-
if (categories.has('security')) parts.push('Security Hardening');
|
|
215
|
-
if (categories.has('fixes') && !parts.length) parts.push('Bug Fixes');
|
|
165
|
+
// āā GitHub metadata helpers āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
216
166
|
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
167
|
+
function getGitHubApiHeaders(): Record<string, string> {
|
|
168
|
+
const headers: Record<string, string> = {
|
|
169
|
+
Accept: 'application/vnd.github+json',
|
|
170
|
+
'User-Agent': 'oh-my-claudecode-release-script',
|
|
171
|
+
};
|
|
221
172
|
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
if (categories.has('features')) parts.push(`**${categories.get('features')!.length} new features**`);
|
|
225
|
-
if (categories.has('security')) parts.push(`**security hardening**`);
|
|
226
|
-
if (categories.has('fixes')) parts.push(`**${categories.get('fixes')!.length} bug fixes**`);
|
|
173
|
+
const token = process.env.GITHUB_TOKEN || process.env.GH_TOKEN;
|
|
174
|
+
if (token) headers.Authorization = `Bearer ${token}`;
|
|
227
175
|
|
|
228
|
-
|
|
229
|
-
return `Release with ${parts.join(', ')} across ${prCount}+ merged PRs.`;
|
|
176
|
+
return headers;
|
|
230
177
|
}
|
|
231
178
|
|
|
232
|
-
function
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
)
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
const sections: ChangelogSection[] = [];
|
|
241
|
-
|
|
242
|
-
// Highlights: top features + security
|
|
243
|
-
const highlights: string[] = [];
|
|
244
|
-
if (categories.has('features')) {
|
|
245
|
-
for (const f of categories.get('features')!.slice(0, 5)) {
|
|
246
|
-
highlights.push(formatEntry(f));
|
|
247
|
-
}
|
|
248
|
-
}
|
|
249
|
-
if (categories.has('security')) {
|
|
250
|
-
for (const s of categories.get('security')!.slice(0, 3)) {
|
|
251
|
-
highlights.push(formatEntry(s));
|
|
252
|
-
}
|
|
253
|
-
}
|
|
254
|
-
if (highlights.length) sections.push({ title: 'Highlights', entries: highlights });
|
|
255
|
-
|
|
256
|
-
// New Features
|
|
257
|
-
if (categories.has('features')) {
|
|
258
|
-
sections.push({ title: 'New Features', entries: categories.get('features')!.map(formatEntry) });
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
// Security & Hardening
|
|
262
|
-
if (categories.has('security')) {
|
|
263
|
-
sections.push({ title: 'Security & Hardening', entries: categories.get('security')!.map(formatEntry) });
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
// Bug Fixes
|
|
267
|
-
if (categories.has('fixes')) {
|
|
268
|
-
sections.push({ title: 'Bug Fixes', entries: categories.get('fixes')!.map(formatEntry) });
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
// Refactoring
|
|
272
|
-
if (categories.has('refactoring')) {
|
|
273
|
-
sections.push({ title: 'Refactoring', entries: categories.get('refactoring')!.map(formatEntry) });
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
// Documentation
|
|
277
|
-
if (categories.has('docs')) {
|
|
278
|
-
sections.push({ title: 'Documentation', entries: categories.get('docs')!.map(formatEntry) });
|
|
179
|
+
async function fetchJson<T>(url: string): Promise<T | null> {
|
|
180
|
+
try {
|
|
181
|
+
const response = await fetch(url, { headers: getGitHubApiHeaders() });
|
|
182
|
+
if (!response.ok) return null;
|
|
183
|
+
return await response.json() as T;
|
|
184
|
+
} catch {
|
|
185
|
+
return null;
|
|
279
186
|
}
|
|
187
|
+
}
|
|
280
188
|
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
189
|
+
function getRepoApiPath(): string {
|
|
190
|
+
return REPO_SLUG
|
|
191
|
+
.split('/')
|
|
192
|
+
.map(part => encodeURIComponent(part))
|
|
193
|
+
.join('/');
|
|
194
|
+
}
|
|
286
195
|
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
196
|
+
async function fetchPullRequestMetadata(prNumbers: string[]): Promise<ReleasePullRequest[]> {
|
|
197
|
+
const repoPath = getRepoApiPath();
|
|
198
|
+
const records = await Promise.all(prNumbers.map(async number => {
|
|
199
|
+
const data = await fetchJson<GitHubPullRequestResponse>(
|
|
200
|
+
`${GITHUB_API_URL}/repos/${repoPath}/pulls/${encodeURIComponent(number)}`
|
|
201
|
+
);
|
|
290
202
|
|
|
291
|
-
|
|
292
|
-
md += `\n### ${section.title}\n\n`;
|
|
293
|
-
md += section.entries.join('\n') + '\n';
|
|
294
|
-
}
|
|
203
|
+
if (!data) return null;
|
|
295
204
|
|
|
296
|
-
|
|
205
|
+
return {
|
|
206
|
+
number,
|
|
207
|
+
title: data.title,
|
|
208
|
+
author: data.user?.login ?? null,
|
|
209
|
+
headRefName: data.head?.ref ?? null,
|
|
210
|
+
} satisfies ReleasePullRequest;
|
|
211
|
+
}));
|
|
297
212
|
|
|
298
|
-
return
|
|
213
|
+
return records.filter((record): record is ReleasePullRequest => record !== null);
|
|
299
214
|
}
|
|
300
215
|
|
|
301
|
-
function
|
|
302
|
-
|
|
303
|
-
changelog: string,
|
|
304
|
-
contributors: string[],
|
|
305
|
-
prevTag: string,
|
|
306
|
-
): string {
|
|
307
|
-
let body = changelog;
|
|
308
|
-
|
|
309
|
-
body += `\n### Install / Update\n\n`;
|
|
310
|
-
body += '```bash\n';
|
|
311
|
-
body += `npm install -g oh-my-claude-sisyphus@${version}\n`;
|
|
312
|
-
body += '```\n\n';
|
|
313
|
-
body += 'Or reinstall the plugin:\n```bash\nclaude /install-plugin oh-my-claudecode\n```\n';
|
|
314
|
-
|
|
315
|
-
if (prevTag) {
|
|
316
|
-
body += `\n**Full Changelog**: https://github.com/Yeachan-Heo/oh-my-claudecode/compare/${prevTag}...v${version}\n`;
|
|
317
|
-
}
|
|
216
|
+
async function fetchCompareCommitAuthors(prevTag: string): Promise<string[]> {
|
|
217
|
+
if (!prevTag) return [];
|
|
318
218
|
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
219
|
+
const repoPath = getRepoApiPath();
|
|
220
|
+
const headRef = process.env.GITHUB_SHA || getHeadSha();
|
|
221
|
+
const data = await fetchJson<GitHubCompareResponse>(
|
|
222
|
+
`${GITHUB_API_URL}/repos/${repoPath}/compare/${encodeURIComponent(prevTag)}...${encodeURIComponent(headRef)}`
|
|
223
|
+
);
|
|
323
224
|
|
|
324
|
-
return
|
|
225
|
+
return (data?.commits ?? [])
|
|
226
|
+
.map(commit => commit.author?.login ?? null)
|
|
227
|
+
.filter((author): author is string => Boolean(author));
|
|
325
228
|
}
|
|
326
229
|
|
|
327
230
|
// āā Version file bumping āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
@@ -329,7 +232,6 @@ function generateReleaseBody(
|
|
|
329
232
|
function bumpVersionFiles(newVersion: string, dryRun: boolean): string[] {
|
|
330
233
|
const changes: string[] = [];
|
|
331
234
|
|
|
332
|
-
// 1. package.json
|
|
333
235
|
const pkgPath = join(ROOT, 'package.json');
|
|
334
236
|
const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8'));
|
|
335
237
|
if (pkg.version !== newVersion) {
|
|
@@ -338,7 +240,6 @@ function bumpVersionFiles(newVersion: string, dryRun: boolean): string[] {
|
|
|
338
240
|
changes.push(`package.json: ${pkg.version} ā ${newVersion}`);
|
|
339
241
|
}
|
|
340
242
|
|
|
341
|
-
// 2. .claude-plugin/plugin.json
|
|
342
243
|
const pluginPath = join(ROOT, '.claude-plugin/plugin.json');
|
|
343
244
|
if (existsSync(pluginPath)) {
|
|
344
245
|
const content = readFileSync(pluginPath, 'utf-8');
|
|
@@ -349,7 +250,6 @@ function bumpVersionFiles(newVersion: string, dryRun: boolean): string[] {
|
|
|
349
250
|
}
|
|
350
251
|
}
|
|
351
252
|
|
|
352
|
-
// 3. .claude-plugin/marketplace.json (has 2 version fields)
|
|
353
253
|
const marketPath = join(ROOT, '.claude-plugin/marketplace.json');
|
|
354
254
|
if (existsSync(marketPath)) {
|
|
355
255
|
const content = readFileSync(marketPath, 'utf-8');
|
|
@@ -360,7 +260,6 @@ function bumpVersionFiles(newVersion: string, dryRun: boolean): string[] {
|
|
|
360
260
|
}
|
|
361
261
|
}
|
|
362
262
|
|
|
363
|
-
// 4. docs/CLAUDE.md version marker
|
|
364
263
|
const claudeMdPath = join(ROOT, 'docs/CLAUDE.md');
|
|
365
264
|
if (existsSync(claudeMdPath)) {
|
|
366
265
|
const content = readFileSync(claudeMdPath, 'utf-8');
|
|
@@ -371,7 +270,6 @@ function bumpVersionFiles(newVersion: string, dryRun: boolean): string[] {
|
|
|
371
270
|
}
|
|
372
271
|
}
|
|
373
272
|
|
|
374
|
-
// 5. package-lock.json (via npm)
|
|
375
273
|
if (!dryRun) {
|
|
376
274
|
try {
|
|
377
275
|
execSync('npm install --package-lock-only --ignore-scripts 2>/dev/null', { cwd: ROOT });
|
|
@@ -386,9 +284,28 @@ function bumpVersionFiles(newVersion: string, dryRun: boolean): string[] {
|
|
|
386
284
|
return changes;
|
|
387
285
|
}
|
|
388
286
|
|
|
287
|
+
function buildFallbackPullRequests(prNumbers: string[], subjects: string[]): ReleasePullRequest[] {
|
|
288
|
+
return prNumbers.map(number => {
|
|
289
|
+
const subject = subjects.find(entry => entry.includes(`(#${number})`));
|
|
290
|
+
const mergeSubject = subjects.find(entry => entry.startsWith(`Merge pull request #${number} `));
|
|
291
|
+
const headRefMatch = mergeSubject?.match(/from\s+[^/]+\/(.+)$/);
|
|
292
|
+
|
|
293
|
+
return {
|
|
294
|
+
number,
|
|
295
|
+
title: subject ? subject.replace(/\s*\(#\d+\)$/, '').trim() : `PR #${number}`,
|
|
296
|
+
author: null,
|
|
297
|
+
headRefName: headRefMatch?.[1] ?? null,
|
|
298
|
+
} satisfies ReleasePullRequest;
|
|
299
|
+
});
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
function isMainModule(): boolean {
|
|
303
|
+
return process.argv[1] ? resolve(process.argv[1]) === __filename : false;
|
|
304
|
+
}
|
|
305
|
+
|
|
389
306
|
// āā Main āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
390
307
|
|
|
391
|
-
function main(): void {
|
|
308
|
+
async function main(): Promise<void> {
|
|
392
309
|
const args = process.argv.slice(2);
|
|
393
310
|
const dryRun = args.includes('--dry-run');
|
|
394
311
|
const help = args.includes('--help') || args.includes('-h');
|
|
@@ -409,7 +326,7 @@ ${clr('Examples:', c.cyan)}
|
|
|
409
326
|
|
|
410
327
|
${clr('What it does:', c.cyan)}
|
|
411
328
|
1. Bumps version in all 5 files (package.json, plugin.json, marketplace.json, docs/CLAUDE.md, lockfile)
|
|
412
|
-
2. Generates CHANGELOG.md from
|
|
329
|
+
2. Generates CHANGELOG.md from the merged PR set when metadata is available
|
|
413
330
|
3. Generates .github/release-body.md with contributor @mentions
|
|
414
331
|
4. Runs sync-metadata to update doc badges
|
|
415
332
|
|
|
@@ -435,31 +352,45 @@ ${clr('After running:', c.cyan)}
|
|
|
435
352
|
console.log(` Previous tag: ${clr(prevTag || '(none)', c.dim)}`);
|
|
436
353
|
if (dryRun) console.log(clr('\n DRY RUN ā no files will be modified\n', c.yellow));
|
|
437
354
|
|
|
438
|
-
|
|
439
|
-
const
|
|
440
|
-
const
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
355
|
+
const allCommitLines = getCommitLinesSinceTag(prevTag);
|
|
356
|
+
const allSubjects = allCommitLines.map(line => line.split('|').slice(1).join('|'));
|
|
357
|
+
const fallbackCommits = getNonMergeCommitLinesSinceTag(prevTag)
|
|
358
|
+
.map(parseCommit)
|
|
359
|
+
.filter((commit): commit is ParsedCommit => commit !== null);
|
|
360
|
+
|
|
361
|
+
const extractedPrNumbers = extractPullRequestNumbers(allSubjects);
|
|
362
|
+
const fetchedPullRequests = await fetchPullRequestMetadata(extractedPrNumbers);
|
|
363
|
+
const pullRequests = fetchedPullRequests.length > 0
|
|
364
|
+
? fetchedPullRequests
|
|
365
|
+
: buildFallbackPullRequests(extractedPrNumbers, allSubjects);
|
|
366
|
+
const userFacingPullRequests = pullRequests.filter(pr => !isReleasePullRequest(pr));
|
|
367
|
+
const compareCommitAuthors = fetchedPullRequests.length > 0 ? await fetchCompareCommitAuthors(prevTag) : [];
|
|
368
|
+
const contributors = deriveContributorLogins(userFacingPullRequests, compareCommitAuthors);
|
|
369
|
+
|
|
370
|
+
const usingPullRequests = fetchedPullRequests.length > 0;
|
|
371
|
+
const releaseEntries = usingPullRequests
|
|
372
|
+
? buildReleaseNoteEntriesFromPullRequests(userFacingPullRequests)
|
|
373
|
+
: fallbackCommits.map(toReleaseNoteEntryFromCommit);
|
|
374
|
+
const categories = categorizeReleaseNoteEntries(releaseEntries);
|
|
375
|
+
const prCount = userFacingPullRequests.length > 0 ? userFacingPullRequests.length : extractedPrNumbers.length;
|
|
376
|
+
|
|
377
|
+
console.log(clr('\nš Release Analysis', c.cyan));
|
|
378
|
+
console.log(` Total commits: ${allCommitLines.length}`);
|
|
379
|
+
console.log(` Extracted PRs: ${extractedPrNumbers.length}`);
|
|
380
|
+
console.log(` User-facing PRs: ${prCount}`);
|
|
381
|
+
console.log(` Metadata source: ${usingPullRequests ? 'GitHub PR metadata' : 'git fallback'}`);
|
|
449
382
|
console.log(` Contributors: ${contributors.join(', ') || '(none)'}`);
|
|
450
383
|
|
|
451
|
-
for (const [cat,
|
|
452
|
-
console.log(` ${cat}: ${
|
|
384
|
+
for (const [cat, entries] of categories) {
|
|
385
|
+
console.log(` ${cat}: ${entries.length}`);
|
|
453
386
|
}
|
|
454
387
|
|
|
455
|
-
// 2. Bump version files
|
|
456
388
|
console.log(clr('\nš¦ Version Bump', c.cyan));
|
|
457
389
|
const versionChanges = bumpVersionFiles(newVersion, dryRun);
|
|
458
390
|
for (const change of versionChanges) {
|
|
459
391
|
console.log(` ${clr('ā', c.green)} ${change}`);
|
|
460
392
|
}
|
|
461
393
|
|
|
462
|
-
// 3. Generate CHANGELOG
|
|
463
394
|
console.log(clr('\nš Changelog', c.cyan));
|
|
464
395
|
const changelog = generateChangelog(newVersion, categories, prCount);
|
|
465
396
|
if (!dryRun) {
|
|
@@ -472,9 +403,8 @@ ${clr('After running:', c.cyan)}
|
|
|
472
403
|
console.log(clr('--- End Preview ---\n', c.dim));
|
|
473
404
|
}
|
|
474
405
|
|
|
475
|
-
// 4. Generate release body
|
|
476
406
|
console.log(clr('\nš Release Body', c.cyan));
|
|
477
|
-
const releaseBody = generateReleaseBody(newVersion, changelog, contributors, prevTag);
|
|
407
|
+
const releaseBody = generateReleaseBody(newVersion, changelog, contributors, prevTag, REPO_URL);
|
|
478
408
|
const releaseBodyPath = join(ROOT, '.github/release-body.md');
|
|
479
409
|
if (!dryRun) {
|
|
480
410
|
writeFileSync(releaseBodyPath, releaseBody, 'utf-8');
|
|
@@ -483,7 +413,6 @@ ${clr('After running:', c.cyan)}
|
|
|
483
413
|
console.log(` ${clr('ā', c.yellow)} Would write .github/release-body.md`);
|
|
484
414
|
}
|
|
485
415
|
|
|
486
|
-
// 5. Run sync-metadata
|
|
487
416
|
console.log(clr('\nš Sync Metadata', c.cyan));
|
|
488
417
|
if (!dryRun) {
|
|
489
418
|
try {
|
|
@@ -495,17 +424,22 @@ ${clr('After running:', c.cyan)}
|
|
|
495
424
|
console.log(` ${clr('ā', c.yellow)} Would run sync-metadata`);
|
|
496
425
|
}
|
|
497
426
|
|
|
498
|
-
// 6. Next steps
|
|
499
427
|
console.log(clr('\nā
Done!', c.green));
|
|
500
428
|
if (!dryRun) {
|
|
501
429
|
console.log(clr('\nNext steps:', c.bold));
|
|
502
430
|
console.log(` 1. ${clr(`git add -A && git commit -m "chore(release): bump version to v${newVersion}"`, c.cyan)}`);
|
|
503
|
-
console.log(` 2. ${clr(
|
|
504
|
-
console.log(
|
|
505
|
-
console.log(` 4. ${clr(
|
|
431
|
+
console.log(` 2. ${clr('git push origin dev', c.cyan)}`);
|
|
432
|
+
console.log(' 3. Wait for CI green');
|
|
433
|
+
console.log(` 4. ${clr('git checkout main && git merge dev && git push origin main', c.cyan)}`);
|
|
506
434
|
console.log(` 5. ${clr(`git tag -a v${newVersion} -m "v${newVersion}" && git push origin v${newVersion}`, c.cyan)}`);
|
|
507
|
-
console.log(
|
|
435
|
+
console.log(' 6. release.yml handles npm publish + GitHub release automatically');
|
|
508
436
|
}
|
|
509
437
|
}
|
|
510
438
|
|
|
511
|
-
|
|
439
|
+
if (isMainModule()) {
|
|
440
|
+
void main().catch((error: unknown) => {
|
|
441
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
442
|
+
console.error(clr(`\nā ${message}`, c.red));
|
|
443
|
+
process.exit(1);
|
|
444
|
+
});
|
|
445
|
+
}
|
|
@@ -8,14 +8,14 @@
|
|
|
8
8
|
|
|
9
9
|
import { existsSync, readFileSync, readdirSync, rmSync, mkdirSync, writeFileSync, symlinkSync, lstatSync, readlinkSync, unlinkSync, renameSync } from 'fs';
|
|
10
10
|
import { join, dirname } from 'path';
|
|
11
|
-
import { homedir } from 'os';
|
|
12
11
|
import { fileURLToPath, pathToFileURL } from 'url';
|
|
12
|
+
import { getClaudeConfigDir } from './lib/config-dir.mjs';
|
|
13
13
|
|
|
14
14
|
const __filename = fileURLToPath(import.meta.url);
|
|
15
15
|
const __dirname = dirname(__filename);
|
|
16
16
|
|
|
17
17
|
/** Claude config directory (respects CLAUDE_CONFIG_DIR env var) */
|
|
18
|
-
const configDir =
|
|
18
|
+
const configDir = getClaudeConfigDir();
|
|
19
19
|
|
|
20
20
|
// Import timeout-protected stdin reader (prevents hangs on Linux/Windows, see issue #240, #524)
|
|
21
21
|
let readStdin;
|
|
@@ -482,8 +482,10 @@ Treat this as prior-session context only. Prioritize the user's newest request,
|
|
|
482
482
|
`);
|
|
483
483
|
}
|
|
484
484
|
|
|
485
|
-
// Check for incomplete todos (project-local only, not global
|
|
486
|
-
//
|
|
485
|
+
// Check for incomplete todos (project-local only, not global
|
|
486
|
+
// [$CLAUDE_CONFIG_DIR|~/.claude]/todos/)
|
|
487
|
+
// NOTE: We intentionally do NOT scan the global
|
|
488
|
+
// [$CLAUDE_CONFIG_DIR|~/.claude]/todos/ directory.
|
|
487
489
|
// That directory accumulates todo files from ALL past sessions across all
|
|
488
490
|
// projects, causing phantom task counts in fresh sessions (see issue #354).
|
|
489
491
|
const localTodoPaths = [
|
|
@@ -126,7 +126,12 @@ function readSummaryState(stateDir, sessionId) {
|
|
|
126
126
|
* Write summary state to disk (scoped by sessionId).
|
|
127
127
|
*/
|
|
128
128
|
function writeSummaryState(stateDir, sessionId, state) {
|
|
129
|
-
|
|
129
|
+
try {
|
|
130
|
+
mkdirSync(stateDir, { recursive: true });
|
|
131
|
+
} catch (err) {
|
|
132
|
+
// On Windows, concurrent hooks can throw EEXIST even with recursive:true
|
|
133
|
+
if (err?.code !== 'EEXIST') throw err;
|
|
134
|
+
}
|
|
130
135
|
const statePath = join(stateDir, `session-summary-${sessionId}.json`);
|
|
131
136
|
writeFileSync(statePath, JSON.stringify(state, null, 2));
|
|
132
137
|
}
|
|
@@ -13,13 +13,15 @@ INSTALL_STYLE="${2:-overwrite}"
|
|
|
13
13
|
DOWNLOAD_URL="https://raw.githubusercontent.com/Yeachan-Heo/oh-my-claudecode/main/docs/CLAUDE.md"
|
|
14
14
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
15
15
|
SCRIPT_PLUGIN_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)"
|
|
16
|
+
. "$SCRIPT_DIR/lib/config-dir.sh"
|
|
16
17
|
|
|
17
18
|
# Resolve active plugin root from installed_plugins.json.
|
|
18
19
|
# Handles stale CLAUDE_PLUGIN_ROOT when a session was started before a plugin
|
|
19
20
|
# update (e.g. 4.8.2 session invoking setup after updating to 4.9.0).
|
|
20
21
|
# Same pattern as run.cjs resolveTarget() fallback.
|
|
21
22
|
resolve_active_plugin_root() {
|
|
22
|
-
local config_dir
|
|
23
|
+
local config_dir
|
|
24
|
+
config_dir="$(resolve_claude_config_dir)"
|
|
23
25
|
local installed_plugins="${config_dir}/plugins/installed_plugins.json"
|
|
24
26
|
|
|
25
27
|
if [ -f "$installed_plugins" ] && command -v jq >/dev/null 2>&1; then
|
|
@@ -89,7 +91,7 @@ EOF
|
|
|
89
91
|
}
|
|
90
92
|
|
|
91
93
|
# Determine target path
|
|
92
|
-
CONFIG_DIR="$
|
|
94
|
+
CONFIG_DIR="$(resolve_claude_config_dir)"
|
|
93
95
|
if [ "$MODE" = "local" ]; then
|
|
94
96
|
mkdir -p .claude/skills/omc-reference
|
|
95
97
|
TARGET_PATH=".claude/CLAUDE.md"
|
|
@@ -8,8 +8,11 @@
|
|
|
8
8
|
|
|
9
9
|
set -euo pipefail
|
|
10
10
|
|
|
11
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
12
|
+
. "$SCRIPT_DIR/lib/config-dir.sh"
|
|
13
|
+
|
|
11
14
|
STATE_FILE=".omc/state/setup-state.json"
|
|
12
|
-
CONFIG_DIR="$
|
|
15
|
+
CONFIG_DIR="$(resolve_claude_config_dir)"
|
|
13
16
|
CONFIG_FILE="$CONFIG_DIR/.omc-config.json"
|
|
14
17
|
|
|
15
18
|
# Cross-platform ISO date to epoch conversion
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
import { existsSync, readdirSync, readFileSync, realpathSync } from 'fs';
|
|
14
14
|
import { join, basename } from 'path';
|
|
15
15
|
import { homedir } from 'os';
|
|
16
|
+
import { getClaudeConfigDir } from './lib/config-dir.mjs';
|
|
16
17
|
import { readStdin } from './lib/stdin.mjs';
|
|
17
18
|
import { createRequire } from 'module';
|
|
18
19
|
|
|
@@ -26,7 +27,7 @@ try {
|
|
|
26
27
|
}
|
|
27
28
|
|
|
28
29
|
// Constants (used by fallback)
|
|
29
|
-
const cfgDir =
|
|
30
|
+
const cfgDir = getClaudeConfigDir();
|
|
30
31
|
const USER_SKILLS_DIR = join(cfgDir, 'skills', 'omc-learned');
|
|
31
32
|
const GLOBAL_SKILLS_DIR = join(homedir(), '.omc', 'skills');
|
|
32
33
|
const PROJECT_SKILLS_SUBDIR = join('.omc', 'skills');
|