jettypod 4.4.77 → 4.4.79
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/jettypod.js
CHANGED
|
@@ -705,6 +705,77 @@ async function generateClaude(options = {}) {
|
|
|
705
705
|
console.log('📝 CLAUDE.md generated');
|
|
706
706
|
}
|
|
707
707
|
|
|
708
|
+
// Ensure Claude Code hooks are up to date (called on every jettypod launch)
|
|
709
|
+
function ensureClaudeHooks() {
|
|
710
|
+
// Create .claude directory if needed
|
|
711
|
+
if (!fs.existsSync('.claude')) {
|
|
712
|
+
fs.mkdirSync('.claude', { recursive: true });
|
|
713
|
+
}
|
|
714
|
+
|
|
715
|
+
const claudeSettingsPath = path.join('.claude', 'settings.json');
|
|
716
|
+
|
|
717
|
+
// Required hooks configuration - always ensure these are present
|
|
718
|
+
const requiredHooks = {
|
|
719
|
+
Edit: [
|
|
720
|
+
'.jettypod/hooks/global-guardrails.js',
|
|
721
|
+
'.jettypod/hooks/protect-claude-md.js'
|
|
722
|
+
],
|
|
723
|
+
Write: [
|
|
724
|
+
'.jettypod/hooks/global-guardrails.js',
|
|
725
|
+
'.jettypod/hooks/protect-claude-md.js'
|
|
726
|
+
],
|
|
727
|
+
Bash: [
|
|
728
|
+
'.jettypod/hooks/global-guardrails.js',
|
|
729
|
+
'.jettypod/hooks/enforce-skill-activation.js'
|
|
730
|
+
]
|
|
731
|
+
};
|
|
732
|
+
|
|
733
|
+
// Load existing settings or create empty structure
|
|
734
|
+
let claudeSettings = { hooks: { PreToolUse: [] } };
|
|
735
|
+
if (fs.existsSync(claudeSettingsPath)) {
|
|
736
|
+
try {
|
|
737
|
+
claudeSettings = JSON.parse(fs.readFileSync(claudeSettingsPath, 'utf-8'));
|
|
738
|
+
if (!claudeSettings.hooks) claudeSettings.hooks = {};
|
|
739
|
+
if (!claudeSettings.hooks.PreToolUse) claudeSettings.hooks.PreToolUse = [];
|
|
740
|
+
} catch {
|
|
741
|
+
// Invalid JSON, start fresh
|
|
742
|
+
claudeSettings = { hooks: { PreToolUse: [] } };
|
|
743
|
+
}
|
|
744
|
+
}
|
|
745
|
+
|
|
746
|
+
// Ensure required hooks are present for each matcher
|
|
747
|
+
let hooksUpdated = false;
|
|
748
|
+
for (const [matcher, requiredCommands] of Object.entries(requiredHooks)) {
|
|
749
|
+
// Find existing entry for this matcher
|
|
750
|
+
let matcherEntry = claudeSettings.hooks.PreToolUse.find(e => e.matcher === matcher);
|
|
751
|
+
|
|
752
|
+
if (!matcherEntry) {
|
|
753
|
+
// Create new entry for this matcher
|
|
754
|
+
matcherEntry = { matcher, hooks: [] };
|
|
755
|
+
claudeSettings.hooks.PreToolUse.push(matcherEntry);
|
|
756
|
+
hooksUpdated = true;
|
|
757
|
+
}
|
|
758
|
+
|
|
759
|
+
// Ensure each required command is present
|
|
760
|
+
for (const command of requiredCommands) {
|
|
761
|
+
const hasCommand = matcherEntry.hooks.some(h => h.command === command);
|
|
762
|
+
if (!hasCommand) {
|
|
763
|
+
// Add required hook at the beginning (guardrails should run first)
|
|
764
|
+
matcherEntry.hooks.unshift({ type: 'command', command });
|
|
765
|
+
hooksUpdated = true;
|
|
766
|
+
}
|
|
767
|
+
}
|
|
768
|
+
}
|
|
769
|
+
|
|
770
|
+
// Write updated settings
|
|
771
|
+
fs.writeFileSync(claudeSettingsPath, JSON.stringify(claudeSettings, null, 2));
|
|
772
|
+
if (hooksUpdated) {
|
|
773
|
+
console.log('⚙️ Claude Code hooks updated');
|
|
774
|
+
}
|
|
775
|
+
|
|
776
|
+
return hooksUpdated;
|
|
777
|
+
}
|
|
778
|
+
|
|
708
779
|
// Initialize project (used by both 'jettypod init' and 'jettypod' with no args)
|
|
709
780
|
async function initializeProject() {
|
|
710
781
|
const { showLogo } = require('./lib/terminal-logo');
|
|
@@ -805,74 +876,11 @@ async function initializeProject() {
|
|
|
805
876
|
fs.chmodSync(guardrailsHookDest, 0o755);
|
|
806
877
|
}
|
|
807
878
|
|
|
808
|
-
// Create Claude Code settings
|
|
809
|
-
if (!fs.existsSync('.claude')) {
|
|
810
|
-
fs.mkdirSync('.claude', { recursive: true });
|
|
811
|
-
}
|
|
812
|
-
|
|
813
879
|
// Ensure .claude/session.md is gitignored and untracked
|
|
814
880
|
ensureJettypodGitignores();
|
|
815
881
|
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
// Required hooks configuration - always ensure these are present
|
|
819
|
-
const requiredHooks = {
|
|
820
|
-
Edit: [
|
|
821
|
-
'.jettypod/hooks/global-guardrails.js',
|
|
822
|
-
'.jettypod/hooks/protect-claude-md.js'
|
|
823
|
-
],
|
|
824
|
-
Write: [
|
|
825
|
-
'.jettypod/hooks/global-guardrails.js',
|
|
826
|
-
'.jettypod/hooks/protect-claude-md.js'
|
|
827
|
-
],
|
|
828
|
-
Bash: [
|
|
829
|
-
'.jettypod/hooks/global-guardrails.js',
|
|
830
|
-
'.jettypod/hooks/enforce-skill-activation.js'
|
|
831
|
-
]
|
|
832
|
-
};
|
|
833
|
-
|
|
834
|
-
// Load existing settings or create empty structure
|
|
835
|
-
let claudeSettings = { hooks: { PreToolUse: [] } };
|
|
836
|
-
if (fs.existsSync(claudeSettingsPath)) {
|
|
837
|
-
try {
|
|
838
|
-
claudeSettings = JSON.parse(fs.readFileSync(claudeSettingsPath, 'utf-8'));
|
|
839
|
-
if (!claudeSettings.hooks) claudeSettings.hooks = {};
|
|
840
|
-
if (!claudeSettings.hooks.PreToolUse) claudeSettings.hooks.PreToolUse = [];
|
|
841
|
-
} catch {
|
|
842
|
-
// Invalid JSON, start fresh
|
|
843
|
-
claudeSettings = { hooks: { PreToolUse: [] } };
|
|
844
|
-
}
|
|
845
|
-
}
|
|
846
|
-
|
|
847
|
-
// Ensure required hooks are present for each matcher
|
|
848
|
-
let hooksUpdated = false;
|
|
849
|
-
for (const [matcher, requiredCommands] of Object.entries(requiredHooks)) {
|
|
850
|
-
// Find existing entry for this matcher
|
|
851
|
-
let matcherEntry = claudeSettings.hooks.PreToolUse.find(e => e.matcher === matcher);
|
|
852
|
-
|
|
853
|
-
if (!matcherEntry) {
|
|
854
|
-
// Create new entry for this matcher
|
|
855
|
-
matcherEntry = { matcher, hooks: [] };
|
|
856
|
-
claudeSettings.hooks.PreToolUse.push(matcherEntry);
|
|
857
|
-
hooksUpdated = true;
|
|
858
|
-
}
|
|
859
|
-
|
|
860
|
-
// Ensure each required command is present
|
|
861
|
-
for (const command of requiredCommands) {
|
|
862
|
-
const hasCommand = matcherEntry.hooks.some(h => h.command === command);
|
|
863
|
-
if (!hasCommand) {
|
|
864
|
-
// Add required hook at the beginning (guardrails should run first)
|
|
865
|
-
matcherEntry.hooks.unshift({ type: 'command', command });
|
|
866
|
-
hooksUpdated = true;
|
|
867
|
-
}
|
|
868
|
-
}
|
|
869
|
-
}
|
|
870
|
-
|
|
871
|
-
// Write updated settings
|
|
872
|
-
fs.writeFileSync(claudeSettingsPath, JSON.stringify(claudeSettings, null, 2));
|
|
873
|
-
if (hooksUpdated) {
|
|
874
|
-
console.log('⚙️ Claude Code hooks updated');
|
|
875
|
-
}
|
|
882
|
+
// Ensure Claude Code hooks are up to date
|
|
883
|
+
ensureClaudeHooks();
|
|
876
884
|
|
|
877
885
|
// Copy skills directory
|
|
878
886
|
// Allow tests to override skills source directory
|
|
@@ -1163,8 +1171,11 @@ switch (command) {
|
|
|
1163
1171
|
const updateCommand = require('./lib/update-command');
|
|
1164
1172
|
const success = await updateCommand.runUpdate();
|
|
1165
1173
|
|
|
1166
|
-
// Always refresh skills in current project after update attempt
|
|
1174
|
+
// Always refresh skills and hooks in current project after update attempt
|
|
1167
1175
|
if (fs.existsSync('.jettypod')) {
|
|
1176
|
+
// Update Claude Code hooks first
|
|
1177
|
+
ensureClaudeHooks();
|
|
1178
|
+
|
|
1168
1179
|
console.log('');
|
|
1169
1180
|
console.log('🔄 Refreshing skills in current project...');
|
|
1170
1181
|
|
|
@@ -2099,6 +2110,9 @@ switch (command) {
|
|
|
2099
2110
|
const currentConfig = config.read();
|
|
2100
2111
|
await generateClaude();
|
|
2101
2112
|
|
|
2113
|
+
// Ensure Claude Code hooks are up to date on every launch
|
|
2114
|
+
ensureClaudeHooks();
|
|
2115
|
+
|
|
2102
2116
|
// Launch dashboard
|
|
2103
2117
|
const dashboardPath = path.join(__dirname, 'apps', 'dashboard');
|
|
2104
2118
|
const BASE_PORT = 3456;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: chore-planning
|
|
3
|
-
description: Guide standalone chore planning with automatic type classification
|
|
3
|
+
description: Guide standalone chore planning with automatic type classification and routing to chore-mode. Use when the implementation approach is obvious - refactoring, bug fixes, infrastructure, or simple enhancements where there's no UX decision to make. Key question - "Does this need UX exploration?" No → chore-planning. Yes → feature-planning instead.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Chore Planning Skill
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: feature-planning
|
|
3
|
-
description: Guide feature planning with UX approach exploration and BDD scenario generation. Use when user
|
|
3
|
+
description: Guide feature planning with UX approach exploration and BDD scenario generation. Use when implementing NEW user-facing behavior that requires UX decisions (multiple valid approaches to discuss). NOT for simple/obvious changes like copy tweaks, styling fixes, or adding straightforward functionality. Key question - "Does this need UX exploration?" Yes → feature-planning.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Feature Planning Skill
|