xtrm-tools 2.1.30 → 2.3.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.
@@ -0,0 +1,51 @@
1
+ #!/usr/bin/env node
2
+ // branch-state.mjs — UserPromptSubmit hook
3
+ // Re-injects current git branch and active beads claim at each prompt.
4
+ // Keeps the agent oriented after /compact or long sessions.
5
+ // Output: { hookSpecificOutput: { additionalSystemPrompt } }
6
+
7
+ import { execSync } from 'node:child_process';
8
+ import { readFileSync, existsSync } from 'node:fs';
9
+ import { join } from 'node:path';
10
+
11
+ function readInput() {
12
+ try { return JSON.parse(readFileSync(0, 'utf-8')); } catch { return null; }
13
+ }
14
+
15
+ function getBranch(cwd) {
16
+ try {
17
+ return execSync('git branch --show-current', {
18
+ encoding: 'utf8', cwd,
19
+ stdio: ['pipe', 'pipe', 'pipe'], timeout: 3000,
20
+ }).trim() || null;
21
+ } catch { return null; }
22
+ }
23
+
24
+ function getSessionClaim(sessionId, cwd) {
25
+ try {
26
+ const out = execSync(`bd kv get "claimed:${sessionId}"`, {
27
+ encoding: 'utf8', cwd,
28
+ stdio: ['pipe', 'pipe', 'pipe'], timeout: 3000,
29
+ }).trim();
30
+ return out || null;
31
+ } catch { return null; }
32
+ }
33
+
34
+ const input = readInput();
35
+ if (!input) process.exit(0);
36
+
37
+ const cwd = input.cwd || process.cwd();
38
+ const sessionId = input.session_id ?? input.sessionId;
39
+ const branch = getBranch(cwd);
40
+ const isBeads = existsSync(join(cwd, '.beads'));
41
+ const claim = isBeads && sessionId ? getSessionClaim(sessionId, cwd) : null;
42
+
43
+ if (!branch && !claim) process.exit(0);
44
+
45
+ const context = `[Context: branch=${branch ?? 'unknown'}${claim ? ', claim=' + claim : ''}]`;
46
+
47
+ process.stdout.write(JSON.stringify({
48
+ hookSpecificOutput: { additionalSystemPrompt: context },
49
+ }));
50
+ process.stdout.write('\n');
51
+ process.exit(0);
@@ -59,11 +59,13 @@ const explicitlyProtectedTarget = protectedBranches
59
59
  .some((b) => lastToken === b || lastToken.endsWith(`:${b}`));
60
60
  if (explicitlyProtectedTarget) process.exit(0);
61
61
 
62
- process.stdout.write(
63
- `✅ Pushed '${branch}'. Next workflow steps:\n\n` +
64
- ' 1. gh pr create --fill\n' +
65
- ' 2. gh pr merge --squash\n' +
66
- ' 3. git checkout main && git reset --hard origin/main\n\n' +
67
- 'Before/after merge, ensure beads state is updated (e.g. bd close <id>).\n',
68
- );
62
+ process.stdout.write(JSON.stringify({
63
+ additionalContext:
64
+ `✅ Pushed '${branch}'. Next steps:\n` +
65
+ ' 1. gh pr create --fill\n' +
66
+ ' 2. gh pr merge --squash\n' +
67
+ ' 3. git checkout main && git reset --hard origin/main\n' +
68
+ 'Ensure beads state is updated (e.g. bd close <id>).',
69
+ }));
70
+ process.stdout.write('\n');
69
71
  process.exit(0);
@@ -37,10 +37,11 @@ const hookEventName = input.hook_event_name ?? 'PreToolUse';
37
37
 
38
38
  function deny(reason) {
39
39
  process.stdout.write(JSON.stringify({
40
- systemMessage: reason,
40
+ decision: 'block',
41
+ reason,
41
42
  }));
42
43
  process.stdout.write('\n');
43
- process.exit(2);
44
+ process.exit(0);
44
45
  }
45
46
 
46
47
  const WRITE_TOOLS = new Set([
@@ -55,8 +56,9 @@ const WRITE_TOOLS = new Set([
55
56
  ]);
56
57
 
57
58
  if (WRITE_TOOLS.has(tool)) {
58
- deny(`⛔ On '${branch}' — checkout a feature branch first.\n`
59
- + ' git checkout -b feature/<name>\n');
59
+ deny(`⛔ On '${branch}' — start on a feature branch and claim an issue.\n`
60
+ + ' git checkout -b feature/<name>\n'
61
+ + ' bd update <id> --claim\n');
60
62
  }
61
63
 
62
64
  const WORKFLOW =
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "xtrm-tools",
3
- "version": "2.1.30",
3
+ "version": "2.3.0",
4
4
  "description": "Claude Code tools installer (skills, hooks, MCP servers)",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -1,3 +1,8 @@
1
+ ---
2
+ name: using-tdd-guard
3
+ description: TDD Guard enforces Test-Driven Development workflow in Claude Code. Blocks implementation code until failing tests are written.
4
+ ---
5
+
1
6
  # Using TDD Guard
2
7
 
3
8
  **TDD Guard** enforces Test-Driven Development workflow in Claude Code. It blocks implementation code until failing tests are written.