xtrm-tools 0.5.10 → 0.5.13
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 +4 -1
- package/README.md +28 -30
- package/cli/dist/index.cjs +1509 -2722
- package/cli/dist/index.cjs.map +1 -1
- package/cli/package.json +1 -1
- package/config/instructions/agents-top.md +87 -23
- package/config/instructions/claude-top.md +101 -23
- package/config/pi/extensions/beads/index.ts +3 -1
- package/config/pi/extensions/session-flow/index.ts +26 -90
- package/config/pi/extensions/xtrm-loader/index.ts +39 -2
- package/hooks/README.md +0 -14
- package/hooks/beads-gate-messages.mjs +8 -22
- package/hooks/gitnexus/gitnexus-hook.cjs +1 -1
- package/hooks/hooks.json +25 -27
- package/hooks/quality-check-env.mjs +79 -0
- package/hooks/quality-check.cjs +6 -6
- package/hooks/statusline.mjs +115 -0
- package/hooks/using-xtrm-reminder.mjs +35 -0
- package/package.json +1 -1
- package/skills/sync-docs-workspace/iteration-1/benchmark.json +293 -0
- package/skills/sync-docs-workspace/iteration-1/benchmark.md +13 -0
- package/skills/sync-docs-workspace/iteration-1/eval-doc-audit/eval_metadata.json +27 -0
- package/skills/sync-docs-workspace/iteration-1/eval-doc-audit/with_skill/outputs/result.md +210 -0
- package/skills/sync-docs-workspace/iteration-1/eval-doc-audit/with_skill/run-1/grading.json +28 -0
- package/skills/sync-docs-workspace/iteration-1/eval-doc-audit/with_skill/run-1/timing.json +1 -0
- package/skills/sync-docs-workspace/iteration-1/eval-doc-audit/without_skill/outputs/result.md +101 -0
- package/skills/sync-docs-workspace/iteration-1/eval-doc-audit/without_skill/run-1/grading.json +28 -0
- package/skills/sync-docs-workspace/iteration-1/eval-doc-audit/without_skill/run-1/timing.json +5 -0
- package/skills/sync-docs-workspace/iteration-1/eval-doc-audit/without_skill/timing.json +5 -0
- package/skills/sync-docs-workspace/iteration-1/eval-fix-mode/eval_metadata.json +27 -0
- package/skills/sync-docs-workspace/iteration-1/eval-fix-mode/with_skill/outputs/result.md +198 -0
- package/skills/sync-docs-workspace/iteration-1/eval-fix-mode/with_skill/run-1/grading.json +28 -0
- package/skills/sync-docs-workspace/iteration-1/eval-fix-mode/with_skill/run-1/timing.json +1 -0
- package/skills/sync-docs-workspace/iteration-1/eval-fix-mode/without_skill/outputs/result.md +94 -0
- package/skills/sync-docs-workspace/iteration-1/eval-fix-mode/without_skill/run-1/grading.json +28 -0
- package/skills/sync-docs-workspace/iteration-1/eval-fix-mode/without_skill/run-1/timing.json +1 -0
- package/skills/sync-docs-workspace/iteration-1/eval-sprint-closeout/eval_metadata.json +27 -0
- package/skills/sync-docs-workspace/iteration-1/eval-sprint-closeout/with_skill/outputs/result.md +237 -0
- package/skills/sync-docs-workspace/iteration-1/eval-sprint-closeout/with_skill/run-1/grading.json +28 -0
- package/skills/sync-docs-workspace/iteration-1/eval-sprint-closeout/with_skill/run-1/timing.json +1 -0
- package/skills/sync-docs-workspace/iteration-1/eval-sprint-closeout/without_skill/outputs/result.md +134 -0
- package/skills/sync-docs-workspace/iteration-1/eval-sprint-closeout/without_skill/run-1/grading.json +28 -0
- package/skills/sync-docs-workspace/iteration-1/eval-sprint-closeout/without_skill/run-1/timing.json +1 -0
- package/skills/sync-docs-workspace/iteration-2/benchmark.json +297 -0
- package/skills/sync-docs-workspace/iteration-2/benchmark.md +13 -0
- package/skills/sync-docs-workspace/iteration-2/eval-doc-audit/eval_metadata.json +27 -0
- package/skills/sync-docs-workspace/iteration-2/eval-doc-audit/with_skill/outputs/result.md +137 -0
- package/skills/sync-docs-workspace/iteration-2/eval-doc-audit/with_skill/run-1/grading.json +92 -0
- package/skills/sync-docs-workspace/iteration-2/eval-doc-audit/with_skill/run-1/timing.json +1 -0
- package/skills/sync-docs-workspace/iteration-2/eval-doc-audit/without_skill/outputs/result.md +134 -0
- package/skills/sync-docs-workspace/iteration-2/eval-doc-audit/without_skill/run-1/grading.json +86 -0
- package/skills/sync-docs-workspace/iteration-2/eval-doc-audit/without_skill/run-1/timing.json +1 -0
- package/skills/sync-docs-workspace/iteration-2/eval-fix-mode/eval_metadata.json +27 -0
- package/skills/sync-docs-workspace/iteration-2/eval-fix-mode/with_skill/outputs/result.md +193 -0
- package/skills/sync-docs-workspace/iteration-2/eval-fix-mode/with_skill/run-1/grading.json +72 -0
- package/skills/sync-docs-workspace/iteration-2/eval-fix-mode/with_skill/run-1/timing.json +1 -0
- package/skills/sync-docs-workspace/iteration-2/eval-fix-mode/without_skill/outputs/result.md +211 -0
- package/skills/sync-docs-workspace/iteration-2/eval-fix-mode/without_skill/run-1/grading.json +91 -0
- package/skills/sync-docs-workspace/iteration-2/eval-fix-mode/without_skill/run-1/timing.json +5 -0
- package/skills/sync-docs-workspace/iteration-2/eval-sprint-closeout/eval_metadata.json +27 -0
- package/skills/sync-docs-workspace/iteration-2/eval-sprint-closeout/with_skill/outputs/result.md +182 -0
- package/skills/sync-docs-workspace/iteration-2/eval-sprint-closeout/with_skill/run-1/grading.json +95 -0
- package/skills/sync-docs-workspace/iteration-2/eval-sprint-closeout/with_skill/run-1/timing.json +1 -0
- package/skills/sync-docs-workspace/iteration-2/eval-sprint-closeout/without_skill/outputs/result.md +222 -0
- package/skills/sync-docs-workspace/iteration-2/eval-sprint-closeout/without_skill/run-1/grading.json +88 -0
- package/skills/sync-docs-workspace/iteration-2/eval-sprint-closeout/without_skill/run-1/timing.json +5 -0
- package/skills/sync-docs-workspace/iteration-3/benchmark.json +298 -0
- package/skills/sync-docs-workspace/iteration-3/benchmark.md +13 -0
- package/skills/sync-docs-workspace/iteration-3/eval-doc-audit/eval_metadata.json +27 -0
- package/skills/sync-docs-workspace/iteration-3/eval-doc-audit/with_skill/outputs/result.md +125 -0
- package/skills/sync-docs-workspace/iteration-3/eval-doc-audit/with_skill/run-1/grading.json +97 -0
- package/skills/sync-docs-workspace/iteration-3/eval-doc-audit/with_skill/run-1/timing.json +5 -0
- package/skills/sync-docs-workspace/iteration-3/eval-doc-audit/without_skill/outputs/result.md +144 -0
- package/skills/sync-docs-workspace/iteration-3/eval-doc-audit/without_skill/run-1/grading.json +78 -0
- package/skills/sync-docs-workspace/iteration-3/eval-doc-audit/without_skill/run-1/timing.json +5 -0
- package/skills/sync-docs-workspace/iteration-3/eval-fix-mode/eval_metadata.json +27 -0
- package/skills/sync-docs-workspace/iteration-3/eval-fix-mode/with_skill/outputs/result.md +104 -0
- package/skills/sync-docs-workspace/iteration-3/eval-fix-mode/with_skill/run-1/grading.json +91 -0
- package/skills/sync-docs-workspace/iteration-3/eval-fix-mode/with_skill/run-1/timing.json +5 -0
- package/skills/sync-docs-workspace/iteration-3/eval-fix-mode/without_skill/outputs/result.md +79 -0
- package/skills/sync-docs-workspace/iteration-3/eval-fix-mode/without_skill/run-1/grading.json +82 -0
- package/skills/sync-docs-workspace/iteration-3/eval-fix-mode/without_skill/run-1/timing.json +5 -0
- package/skills/sync-docs-workspace/iteration-3/eval-sprint-closeout/eval_metadata.json +27 -0
- package/skills/sync-docs-workspace/iteration-3/eval-sprint-closeout/with_skill/outputs/phase1_context.json +302 -0
- package/skills/sync-docs-workspace/iteration-3/eval-sprint-closeout/with_skill/outputs/phase2_drift.txt +33 -0
- package/skills/sync-docs-workspace/iteration-3/eval-sprint-closeout/with_skill/outputs/phase3_analysis.json +114 -0
- package/skills/sync-docs-workspace/iteration-3/eval-sprint-closeout/with_skill/outputs/phase4_fix.txt +118 -0
- package/skills/sync-docs-workspace/iteration-3/eval-sprint-closeout/with_skill/outputs/phase5_validate.txt +38 -0
- package/skills/sync-docs-workspace/iteration-3/eval-sprint-closeout/with_skill/outputs/result.md +158 -0
- package/skills/sync-docs-workspace/iteration-3/eval-sprint-closeout/with_skill/run-1/grading.json +95 -0
- package/skills/sync-docs-workspace/iteration-3/eval-sprint-closeout/with_skill/run-1/timing.json +5 -0
- package/skills/sync-docs-workspace/iteration-3/eval-sprint-closeout/without_skill/outputs/result.md +71 -0
- package/skills/sync-docs-workspace/iteration-3/eval-sprint-closeout/without_skill/run-1/grading.json +90 -0
- package/skills/sync-docs-workspace/iteration-3/eval-sprint-closeout/without_skill/run-1/timing.json +5 -0
- package/skills/using-xtrm/SKILL.md +84 -205
- package/config/pi/extensions/bg-process/index.ts +0 -230
- package/config/pi/extensions/bg-process/package.json +0 -16
- package/config/pi/extensions/minimal-mode/index.ts +0 -201
- package/config/pi/extensions/minimal-mode/package.json +0 -16
- package/config/pi/extensions/todo/index.ts +0 -299
- package/config/pi/extensions/todo/package.json +0 -16
- package/hooks/agent_context.py +0 -105
- package/hooks/branch-state.mjs +0 -39
- package/hooks/guard-rules.mjs +0 -118
- package/hooks/main-guard-post-push.mjs +0 -71
- package/hooks/main-guard.mjs +0 -119
package/hooks/guard-rules.mjs
DELETED
|
@@ -1,118 +0,0 @@
|
|
|
1
|
-
// Canonical guard rule definitions shared across hooks, policies, and extensions.
|
|
2
|
-
// Pure data module: named exports only.
|
|
3
|
-
|
|
4
|
-
export const WRITE_TOOLS = [
|
|
5
|
-
'Edit',
|
|
6
|
-
'Write',
|
|
7
|
-
'MultiEdit',
|
|
8
|
-
'NotebookEdit',
|
|
9
|
-
'mcp__serena__rename_symbol',
|
|
10
|
-
'mcp__serena__replace_symbol_body',
|
|
11
|
-
'mcp__serena__insert_after_symbol',
|
|
12
|
-
'mcp__serena__insert_before_symbol',
|
|
13
|
-
];
|
|
14
|
-
|
|
15
|
-
export const DANGEROUS_BASH_PATTERNS = [
|
|
16
|
-
'sed\\s+-i',
|
|
17
|
-
'echo\\s+[^\\n]*>',
|
|
18
|
-
'printf\\s+[^\\n]*>',
|
|
19
|
-
'cat\\s+[^\\n]*>',
|
|
20
|
-
'tee\\b',
|
|
21
|
-
'(?:^|\\s)(?:vim|nano|vi)\\b',
|
|
22
|
-
'(?:^|\\s)mv\\b',
|
|
23
|
-
'(?:^|\\s)cp\\b',
|
|
24
|
-
'(?:^|\\s)rm\\b',
|
|
25
|
-
'(?:^|\\s)mkdir\\b',
|
|
26
|
-
'(?:^|\\s)touch\\b',
|
|
27
|
-
'(?:^|\\s)chmod\\b',
|
|
28
|
-
'(?:^|\\s)chown\\b',
|
|
29
|
-
'>>',
|
|
30
|
-
'(?:^|\\s)git\\s+add\\b',
|
|
31
|
-
'(?:^|\\s)git\\s+commit\\b',
|
|
32
|
-
'(?:^|\\s)git\\s+merge\\b',
|
|
33
|
-
'(?:^|\\s)git\\s+push\\b',
|
|
34
|
-
'(?:^|\\s)git\\s+reset\\b',
|
|
35
|
-
'(?:^|\\s)git\\s+checkout\\b',
|
|
36
|
-
'(?:^|\\s)git\\s+rebase\\b',
|
|
37
|
-
'(?:^|\\s)git\\s+stash\\b',
|
|
38
|
-
'(?:^|\\s)npm\\s+install\\b',
|
|
39
|
-
'(?:^|\\s)bun\\s+install\\b',
|
|
40
|
-
'(?:^|\\s)bun\\s+add\\b',
|
|
41
|
-
'(?:^|\\s)node\\s+(?:-e|--eval)\\b',
|
|
42
|
-
'(?:^|\\s)bun\\s+(?:-e|--eval)\\b',
|
|
43
|
-
'(?:^|\\s)python\\s+-c\\b',
|
|
44
|
-
'(?:^|\\s)perl\\s+-e\\b',
|
|
45
|
-
'(?:^|\\s)ruby\\s+-e\\b',
|
|
46
|
-
];
|
|
47
|
-
|
|
48
|
-
export const SAFE_BASH_PREFIXES = [
|
|
49
|
-
// Git read-only
|
|
50
|
-
'git status',
|
|
51
|
-
'git log',
|
|
52
|
-
'git diff',
|
|
53
|
-
'git show',
|
|
54
|
-
'git blame',
|
|
55
|
-
'git branch',
|
|
56
|
-
'git fetch',
|
|
57
|
-
'git remote',
|
|
58
|
-
'git config',
|
|
59
|
-
'git pull',
|
|
60
|
-
'git stash',
|
|
61
|
-
'git worktree',
|
|
62
|
-
'git checkout -b',
|
|
63
|
-
'git switch -c',
|
|
64
|
-
// Tools
|
|
65
|
-
'gh',
|
|
66
|
-
'bd',
|
|
67
|
-
'npx gitnexus',
|
|
68
|
-
'xtrm finish',
|
|
69
|
-
// Read-only filesystem
|
|
70
|
-
'cat',
|
|
71
|
-
'ls',
|
|
72
|
-
'head',
|
|
73
|
-
'tail',
|
|
74
|
-
'pwd',
|
|
75
|
-
'which',
|
|
76
|
-
'type',
|
|
77
|
-
'env',
|
|
78
|
-
'printenv',
|
|
79
|
-
'find',
|
|
80
|
-
'grep',
|
|
81
|
-
'rg',
|
|
82
|
-
'fd',
|
|
83
|
-
'wc',
|
|
84
|
-
'sort',
|
|
85
|
-
'uniq',
|
|
86
|
-
'cut',
|
|
87
|
-
'awk',
|
|
88
|
-
'jq',
|
|
89
|
-
'yq',
|
|
90
|
-
'bat',
|
|
91
|
-
'less',
|
|
92
|
-
'more',
|
|
93
|
-
'file',
|
|
94
|
-
'stat',
|
|
95
|
-
'du',
|
|
96
|
-
'tree',
|
|
97
|
-
// Allowed writes (specific paths)
|
|
98
|
-
'touch .beads/',
|
|
99
|
-
];
|
|
100
|
-
|
|
101
|
-
export const NATIVE_TEAM_TOOLS = [
|
|
102
|
-
'Task',
|
|
103
|
-
'TeamCreate',
|
|
104
|
-
'TeamDelete',
|
|
105
|
-
'SendMessage',
|
|
106
|
-
'TaskCreate',
|
|
107
|
-
'TaskUpdate',
|
|
108
|
-
'TaskList',
|
|
109
|
-
'TaskGet',
|
|
110
|
-
'TaskOutput',
|
|
111
|
-
'TaskStop',
|
|
112
|
-
];
|
|
113
|
-
|
|
114
|
-
export const INTERACTIVE_TOOLS = [
|
|
115
|
-
'AskUserQuestion',
|
|
116
|
-
'EnterPlanMode',
|
|
117
|
-
'EnterWorktree',
|
|
118
|
-
];
|
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
// Claude Code PostToolUse hook — after successful feature-branch push,
|
|
3
|
-
// inject next-step PR workflow guidance.
|
|
4
|
-
// Exit 0 in all paths (informational only).
|
|
5
|
-
//
|
|
6
|
-
// Installed by: xtrm install
|
|
7
|
-
|
|
8
|
-
import { execSync } from 'node:child_process';
|
|
9
|
-
import { readFileSync } from 'node:fs';
|
|
10
|
-
|
|
11
|
-
let input;
|
|
12
|
-
try {
|
|
13
|
-
input = JSON.parse(readFileSync(0, 'utf8'));
|
|
14
|
-
} catch {
|
|
15
|
-
process.exit(0);
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
if ((input.tool_name ?? '') !== 'Bash') process.exit(0);
|
|
19
|
-
const cmd = (input.tool_input?.command ?? '').trim().replace(/\s+/g, ' ');
|
|
20
|
-
if (!/^git\s+push\b/.test(cmd)) process.exit(0);
|
|
21
|
-
|
|
22
|
-
function commandSucceeded(payload) {
|
|
23
|
-
const tr = payload?.tool_response ?? payload?.tool_result ?? payload?.result;
|
|
24
|
-
if (!tr || typeof tr !== 'object') return true;
|
|
25
|
-
|
|
26
|
-
if (tr.success === false) return false;
|
|
27
|
-
if (tr.error) return false;
|
|
28
|
-
|
|
29
|
-
const numeric = [tr.exit_code, tr.exitCode, tr.status, tr.returncode]
|
|
30
|
-
.find((v) => Number.isInteger(v));
|
|
31
|
-
if (typeof numeric === 'number' && numeric !== 0) return false;
|
|
32
|
-
|
|
33
|
-
return true;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
if (!commandSucceeded(input)) process.exit(0);
|
|
37
|
-
|
|
38
|
-
const cwd = input.cwd || process.cwd();
|
|
39
|
-
let branch = '';
|
|
40
|
-
try {
|
|
41
|
-
branch = execSync('git branch --show-current', {
|
|
42
|
-
cwd,
|
|
43
|
-
encoding: 'utf8',
|
|
44
|
-
stdio: ['pipe', 'pipe', 'pipe'],
|
|
45
|
-
}).trim();
|
|
46
|
-
} catch {
|
|
47
|
-
process.exit(0);
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
const protectedBranches = process.env.MAIN_GUARD_PROTECTED_BRANCHES
|
|
51
|
-
? process.env.MAIN_GUARD_PROTECTED_BRANCHES.split(',').map((b) => b.trim()).filter(Boolean)
|
|
52
|
-
: ['main', 'master'];
|
|
53
|
-
|
|
54
|
-
if (!branch || protectedBranches.includes(branch)) process.exit(0);
|
|
55
|
-
|
|
56
|
-
const tokens = cmd.split(' ');
|
|
57
|
-
const lastToken = tokens[tokens.length - 1] ?? '';
|
|
58
|
-
const explicitlyProtectedTarget = protectedBranches
|
|
59
|
-
.some((b) => lastToken === b || lastToken.endsWith(`:${b}`));
|
|
60
|
-
if (explicitlyProtectedTarget) process.exit(0);
|
|
61
|
-
|
|
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');
|
|
71
|
-
process.exit(0);
|
package/hooks/main-guard.mjs
DELETED
|
@@ -1,119 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
// Claude Code PreToolUse hook — block writes and direct master pushes
|
|
3
|
-
// Exit 0: allow | Exit 2: block (message shown to user)
|
|
4
|
-
//
|
|
5
|
-
// Installed by: xtrm install
|
|
6
|
-
|
|
7
|
-
import { execSync } from 'node:child_process';
|
|
8
|
-
import { existsSync, readFileSync } from 'node:fs';
|
|
9
|
-
import { join } from 'node:path';
|
|
10
|
-
import { WRITE_TOOLS, SAFE_BASH_PREFIXES } from './guard-rules.mjs';
|
|
11
|
-
|
|
12
|
-
let branch = '';
|
|
13
|
-
try {
|
|
14
|
-
branch = execSync('git branch --show-current', {
|
|
15
|
-
encoding: 'utf8',
|
|
16
|
-
stdio: ['pipe', 'pipe', 'pipe'],
|
|
17
|
-
}).trim();
|
|
18
|
-
} catch {}
|
|
19
|
-
|
|
20
|
-
const protectedBranches = process.env.MAIN_GUARD_PROTECTED_BRANCHES
|
|
21
|
-
? process.env.MAIN_GUARD_PROTECTED_BRANCHES.split(',').map(b => b.trim()).filter(Boolean)
|
|
22
|
-
: ['main', 'master'];
|
|
23
|
-
|
|
24
|
-
if (!branch || !protectedBranches.includes(branch)) {
|
|
25
|
-
process.exit(0);
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
let input;
|
|
29
|
-
try {
|
|
30
|
-
input = JSON.parse(readFileSync(0, 'utf8'));
|
|
31
|
-
} catch {
|
|
32
|
-
process.exit(0);
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
const tool = input.tool_name ?? '';
|
|
36
|
-
const cwd = input.cwd || process.cwd();
|
|
37
|
-
|
|
38
|
-
function deny(reason) {
|
|
39
|
-
process.stdout.write(JSON.stringify({ decision: 'block', reason }));
|
|
40
|
-
process.stdout.write('\n');
|
|
41
|
-
process.exit(0);
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
function getSessionState(cwd) {
|
|
45
|
-
const statePath = join(cwd, '.xtrm-session-state.json');
|
|
46
|
-
if (!existsSync(statePath)) return null;
|
|
47
|
-
try {
|
|
48
|
-
return JSON.parse(readFileSync(statePath, 'utf8'));
|
|
49
|
-
} catch {
|
|
50
|
-
return null;
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
function normalizeGitCCommand(cmd) {
|
|
55
|
-
const match = cmd.match(/^git\s+-C\s+(?:"[^"]+"|'[^']+'|\S+)\s+(.+)$/);
|
|
56
|
-
if (match?.[1]) return `git ${match[1]}`;
|
|
57
|
-
return cmd;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
if (WRITE_TOOLS.includes(tool)) {
|
|
61
|
-
deny(`⛔ On '${branch}' — start on a feature branch and claim an issue.\n`
|
|
62
|
-
+ ' git checkout -b feature/<name> (or: git switch -c feature/<name>)\n'
|
|
63
|
-
+ ' bd update <id> --claim\n');
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
if (tool === 'Bash') {
|
|
67
|
-
const cmd = (input.tool_input?.command ?? '').trim().replace(/\s+/g, ' ');
|
|
68
|
-
const normalizedCmd = normalizeGitCCommand(cmd);
|
|
69
|
-
const state = getSessionState(cwd);
|
|
70
|
-
|
|
71
|
-
if (process.env.MAIN_GUARD_ALLOW_BASH === '1') {
|
|
72
|
-
process.exit(0);
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
if (/^gh\s+pr\s+merge\b/.test(cmd)) {
|
|
76
|
-
if (!/--squash\b/.test(cmd)) {
|
|
77
|
-
deny('⛔ Squash only: gh pr merge --squash\n'
|
|
78
|
-
+ ' (override: MAIN_GUARD_ALLOW_BASH=1 gh pr merge --merge)\n');
|
|
79
|
-
}
|
|
80
|
-
process.exit(0);
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
const SAFE_BASH_PATTERNS = [
|
|
84
|
-
...SAFE_BASH_PREFIXES.map(prefix => new RegExp(`^${prefix.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}\\b`)),
|
|
85
|
-
...protectedBranches.map(b => new RegExp(`^git\\s+reset\\s+--hard\\s+origin/${b}\\b`)),
|
|
86
|
-
];
|
|
87
|
-
|
|
88
|
-
if (SAFE_BASH_PATTERNS.some(p => p.test(cmd) || p.test(normalizedCmd))) {
|
|
89
|
-
process.exit(0);
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
if (/\bgit\s+commit\b/.test(normalizedCmd)) {
|
|
93
|
-
deny(`⛔ No commits on '${branch}' — use a feature branch/worktree.\n`
|
|
94
|
-
+ ' git checkout -b feature/<name>\n'
|
|
95
|
-
+ ' bd update <id> --claim\n');
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
if (/\bgit\s+push\b/.test(normalizedCmd)) {
|
|
99
|
-
const tokens = normalizedCmd.split(' ');
|
|
100
|
-
const lastToken = tokens[tokens.length - 1];
|
|
101
|
-
const explicitProtected = protectedBranches.some(b => lastToken === b || lastToken.endsWith(`:${b}`));
|
|
102
|
-
const impliedProtected = tokens.length <= 3 && protectedBranches.includes(branch);
|
|
103
|
-
if (explicitProtected || impliedProtected) {
|
|
104
|
-
deny(`⛔ No direct push to '${branch}' — push a feature branch and open a PR.\n`
|
|
105
|
-
+ ' git push -u origin <feature-branch> && gh pr create --fill\n');
|
|
106
|
-
}
|
|
107
|
-
process.exit(0);
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
const handoff = state?.worktreePath
|
|
111
|
-
? ` Active worktree session recorded: ${state.worktreePath}\n (Current workaround) use feature branch flow until worktree bug is fixed.\n`
|
|
112
|
-
: ' Exit: git checkout -b feature/<name> (or: git switch -c feature/<name>)\n Then: bd update <id> --claim\n';
|
|
113
|
-
|
|
114
|
-
deny(`⛔ Bash restricted on '${branch}'. Allowed: read-only commands, gh, bd, git checkout -b, git switch -c.\n`
|
|
115
|
-
+ handoff
|
|
116
|
-
+ ' Override: MAIN_GUARD_ALLOW_BASH=1 <cmd>\n');
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
process.exit(0);
|