@braingrid/cli 0.2.41 → 0.2.42

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/CHANGELOG.md CHANGED
@@ -7,6 +7,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.2.42] - 2026-02-17
11
+
12
+ ### Added
13
+
14
+ - **SessionStart and TaskCompleted hook installation** — `braingrid setup claude-code` now installs two additional hook scripts: `check-stale-build-sentinel.sh` (SessionStart) for cleaning up stale build sentinels, and `task-completed-validate.sh` (TaskCompleted) for commit validation before marking tasks complete
15
+ - **Sync script updated** — `sync-claude-code-to-braingrid.sh` now syncs 16 files (up from 14), including the two new hook scripts
16
+
10
17
  ## [0.2.41] - 2026-02-17
11
18
 
12
19
  ### Fixed
package/dist/cli.js CHANGED
@@ -222,7 +222,7 @@ async function axiosWithRetry(config2, options) {
222
222
 
223
223
  // src/build-config.ts
224
224
  var BUILD_ENV = true ? "production" : process.env.NODE_ENV === "test" ? "development" : "production";
225
- var CLI_VERSION = true ? "0.2.41" : "0.0.0-test";
225
+ var CLI_VERSION = true ? "0.2.42" : "0.0.0-test";
226
226
  var PRODUCTION_CONFIG = {
227
227
  apiUrl: "https://app.braingrid.ai",
228
228
  workosAuthUrl: "https://auth.braingrid.ai",
@@ -2679,7 +2679,7 @@ async function copyBraingridReadme(targetPath = ".braingrid/README.md") {
2679
2679
  return false;
2680
2680
  }
2681
2681
  }
2682
- async function updateClaudeSettings(settingsPath = ".claude/settings.json", scriptPath2 = ".claude/statusline.sh", hookScriptPath = ".claude/hooks/sync-braingrid-task.sh", createHookScriptPath = ".claude/hooks/create-braingrid-task.sh", verifyHookScriptPath = ".claude/hooks/verify-acceptance-criteria.sh", postTaskUpdatePromptPath = ".claude/hooks/post-task-update-prompt.sh", preTaskCreatePath = ".claude/hooks/pre-task-create-naming.sh", preTaskUpdatePath = ".claude/hooks/pre-task-update-instructions.sh") {
2682
+ async function updateClaudeSettings(settingsPath = ".claude/settings.json", scriptPath2 = ".claude/statusline.sh", hookScriptPath = ".claude/hooks/sync-braingrid-task.sh", createHookScriptPath = ".claude/hooks/create-braingrid-task.sh", verifyHookScriptPath = ".claude/hooks/verify-acceptance-criteria.sh", postTaskUpdatePromptPath = ".claude/hooks/post-task-update-prompt.sh", preTaskCreatePath = ".claude/hooks/pre-task-create-naming.sh", preTaskUpdatePath = ".claude/hooks/pre-task-update-instructions.sh", sessionStartPath = ".claude/hooks/check-stale-build-sentinel.sh", taskCompletedPath = ".claude/hooks/task-completed-validate.sh") {
2683
2683
  try {
2684
2684
  let settings = {};
2685
2685
  try {
@@ -2782,11 +2782,39 @@ async function updateClaudeSettings(settingsPath = ".claude/settings.json", scri
2782
2782
  (entry) => entry.hooks?.some((h) => h.command?.includes("verify-acceptance-criteria"))
2783
2783
  );
2784
2784
  const mergedStop = hasVerifyHook ? existingStop : [...existingStop, ourStopHookEntry];
2785
+ const ourSessionStartEntry = {
2786
+ hooks: [
2787
+ {
2788
+ type: "command",
2789
+ command: sessionStartPath
2790
+ }
2791
+ ]
2792
+ };
2793
+ const existingSessionStart = Array.isArray(existingHooks.SessionStart) ? existingHooks.SessionStart : [];
2794
+ const hasSessionStartHook = existingSessionStart.some(
2795
+ (entry) => entry.hooks?.some((h) => h.command?.includes("check-stale-build-sentinel"))
2796
+ );
2797
+ const mergedSessionStart = hasSessionStartHook ? existingSessionStart : [...existingSessionStart, ourSessionStartEntry];
2798
+ const ourTaskCompletedEntry = {
2799
+ hooks: [
2800
+ {
2801
+ type: "command",
2802
+ command: taskCompletedPath
2803
+ }
2804
+ ]
2805
+ };
2806
+ const existingTaskCompleted = Array.isArray(existingHooks.TaskCompleted) ? existingHooks.TaskCompleted : [];
2807
+ const hasTaskCompletedHook = existingTaskCompleted.some(
2808
+ (entry) => entry.hooks?.some((h) => h.command?.includes("task-completed-validate"))
2809
+ );
2810
+ const mergedTaskCompleted = hasTaskCompletedHook ? existingTaskCompleted : [...existingTaskCompleted, ourTaskCompletedEntry];
2785
2811
  settings.hooks = {
2786
2812
  ...existingHooks,
2787
2813
  PreToolUse: mergedPreToolUse,
2788
2814
  PostToolUse: mergedPostToolUse,
2789
- Stop: mergedStop
2815
+ Stop: mergedStop,
2816
+ SessionStart: mergedSessionStart,
2817
+ TaskCompleted: mergedTaskCompleted
2790
2818
  };
2791
2819
  const parentDir = path2.dirname(settingsPath);
2792
2820
  await fs2.mkdir(parentDir, { recursive: true });
@@ -3645,8 +3673,34 @@ async function handleSetupClaudeCode(opts) {
3645
3673
  error instanceof Error ? error.message : String(error)
3646
3674
  );
3647
3675
  }
3676
+ let sessionStartInstalled = false;
3677
+ try {
3678
+ const sessionStartContent = await fetchFileFromGitHub(
3679
+ "claude-code/hooks/check-stale-build-sentinel.sh"
3680
+ );
3681
+ await installHookScript(sessionStartContent, ".claude/hooks/check-stale-build-sentinel.sh");
3682
+ sessionStartInstalled = true;
3683
+ } catch (error) {
3684
+ console.error(
3685
+ chalk8.yellow("\u26A0\uFE0F Failed to install session-start hook:"),
3686
+ error instanceof Error ? error.message : String(error)
3687
+ );
3688
+ }
3689
+ let taskCompletedInstalled = false;
3690
+ try {
3691
+ const taskCompletedContent = await fetchFileFromGitHub(
3692
+ "claude-code/hooks/task-completed-validate.sh"
3693
+ );
3694
+ await installHookScript(taskCompletedContent, ".claude/hooks/task-completed-validate.sh");
3695
+ taskCompletedInstalled = true;
3696
+ } catch (error) {
3697
+ console.error(
3698
+ chalk8.yellow("\u26A0\uFE0F Failed to install task-completed hook:"),
3699
+ error instanceof Error ? error.message : String(error)
3700
+ );
3701
+ }
3648
3702
  const statusLineMessage = statusLineInstalled ? chalk8.dim(" Status line: .claude/statusline.sh\n") : "";
3649
- const hooksMessage = (syncHookInstalled ? chalk8.dim(" Hook script: .claude/hooks/sync-braingrid-task.sh\n") : "") + (createHookInstalled ? chalk8.dim(" Hook script: .claude/hooks/create-braingrid-task.sh\n") : "") + (verifyHookInstalled ? chalk8.dim(" Hook script: .claude/hooks/verify-acceptance-criteria.sh\n") : "") + (preTaskCreateInstalled ? chalk8.dim(" Hook script: .claude/hooks/pre-task-create-naming.sh\n") : "") + (preTaskUpdateInstalled ? chalk8.dim(" Hook script: .claude/hooks/pre-task-update-instructions.sh\n") : "") + (postTaskUpdateInstalled ? chalk8.dim(" Hook script: .claude/hooks/post-task-update-prompt.sh\n") : "");
3703
+ const hooksMessage = (syncHookInstalled ? chalk8.dim(" Hook script: .claude/hooks/sync-braingrid-task.sh\n") : "") + (createHookInstalled ? chalk8.dim(" Hook script: .claude/hooks/create-braingrid-task.sh\n") : "") + (verifyHookInstalled ? chalk8.dim(" Hook script: .claude/hooks/verify-acceptance-criteria.sh\n") : "") + (preTaskCreateInstalled ? chalk8.dim(" Hook script: .claude/hooks/pre-task-create-naming.sh\n") : "") + (preTaskUpdateInstalled ? chalk8.dim(" Hook script: .claude/hooks/pre-task-update-instructions.sh\n") : "") + (postTaskUpdateInstalled ? chalk8.dim(" Hook script: .claude/hooks/post-task-update-prompt.sh\n") : "") + (sessionStartInstalled ? chalk8.dim(" Hook script: .claude/hooks/check-stale-build-sentinel.sh\n") : "") + (taskCompletedInstalled ? chalk8.dim(" Hook script: .claude/hooks/task-completed-validate.sh\n") : "");
3650
3704
  return {
3651
3705
  success: true,
3652
3706
  message: buildSuccessMessage(config2, displayPerDir, statusLineMessage + hooksMessage)