@imdeadpool/guardex 6.0.1 → 6.1.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.
@@ -54,6 +54,7 @@ const TEMPLATE_FILES = [
54
54
  'githooks/pre-commit',
55
55
  'githooks/pre-push',
56
56
  'githooks/post-merge',
57
+ 'githooks/post-checkout',
57
58
  'codex/skills/guardex/SKILL.md',
58
59
  'codex/skills/guardex-merge-skills-to-dev/SKILL.md',
59
60
  'claude/commands/guardex.md',
@@ -97,6 +98,7 @@ const EXECUTABLE_RELATIVE_PATHS = new Set([
97
98
  '.githooks/pre-commit',
98
99
  '.githooks/pre-push',
99
100
  '.githooks/post-merge',
101
+ '.githooks/post-checkout',
100
102
  ]);
101
103
 
102
104
  const CRITICAL_GUARDRAIL_PATHS = new Set([
@@ -104,6 +106,7 @@ const CRITICAL_GUARDRAIL_PATHS = new Set([
104
106
  '.githooks/pre-commit',
105
107
  '.githooks/pre-push',
106
108
  '.githooks/post-merge',
109
+ '.githooks/post-checkout',
107
110
  'scripts/agent-branch-start.sh',
108
111
  'scripts/agent-branch-finish.sh',
109
112
  'scripts/agent-worktree-prune.sh',
@@ -131,6 +134,7 @@ const MANAGED_GITIGNORE_PATHS = [
131
134
  '.githooks/pre-commit',
132
135
  '.githooks/pre-push',
133
136
  '.githooks/post-merge',
137
+ '.githooks/post-checkout',
134
138
  'oh-my-codex/',
135
139
  '.codex/skills/guardex/SKILL.md',
136
140
  '.codex/skills/guardex-merge-skills-to-dev/SKILL.md',
@@ -203,6 +207,15 @@ const CLI_COMMAND_DESCRIPTIONS = [
203
207
  ['help', 'Show this help output'],
204
208
  ['version', 'Print GuardeX version'],
205
209
  ];
210
+ const CORE_COMMAND_NAMES = new Set([
211
+ 'setup',
212
+ 'doctor',
213
+ 'status',
214
+ 'finish',
215
+ 'cleanup',
216
+ 'sync',
217
+ 'scan',
218
+ ]);
206
219
  const AGENT_BOT_DESCRIPTIONS = [
207
220
  ['review', 'Start PR monitor + codex-agent review flow (default interval: 30s)'],
208
221
  ['agents', 'Start/stop both review and cleanup bots for this repo'],
@@ -351,12 +364,15 @@ function statusDot(status) {
351
364
  return colorize('●', '33'); // yellow for degraded/unknown
352
365
  }
353
366
 
354
- function commandCatalogLines(indent = ' ') {
355
- const maxCommandLength = CLI_COMMAND_DESCRIPTIONS.reduce(
367
+ function commandCatalogLines(indent = ' ', { coreOnly = false } = {}) {
368
+ const entries = coreOnly
369
+ ? CLI_COMMAND_DESCRIPTIONS.filter(([name]) => CORE_COMMAND_NAMES.has(name))
370
+ : CLI_COMMAND_DESCRIPTIONS;
371
+ const maxCommandLength = entries.reduce(
356
372
  (max, [command]) => Math.max(max, command.length),
357
373
  0,
358
374
  );
359
- return CLI_COMMAND_DESCRIPTIONS.map(
375
+ return entries.map(
360
376
  ([command, description]) => `${indent}${command.padEnd(maxCommandLength + 2)}${description}`,
361
377
  );
362
378
  }
@@ -373,7 +389,7 @@ function agentBotCatalogLines(indent = ' ') {
373
389
 
374
390
  function printToolLogsSummary() {
375
391
  const usageLine = ` $ ${SHORT_TOOL_NAME} <command> [options]`;
376
- const commandDetails = commandCatalogLines(' ');
392
+ const commandDetails = commandCatalogLines(' ', { coreOnly: true });
377
393
  const agentBotDetails = agentBotCatalogLines(' ');
378
394
 
379
395
  if (!supportsAnsiColors()) {
@@ -418,7 +434,7 @@ function printToolLogsSummary() {
418
434
  }
419
435
  console.log(` ${pipe}${line.slice(2)}`);
420
436
  }
421
- console.log(` ${corner}─ ${colorize(`Try '${TOOL_NAME} doctor' for one-step repair + verification.`, '2')}`);
437
+ console.log(` ${corner}─ ${colorize(`Try '${SHORT_TOOL_NAME} doctor' to repair drift, or '${SHORT_TOOL_NAME} help' for the full command list.`, '2')}`);
422
438
  }
423
439
 
424
440
  function usage(options = {}) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@imdeadpool/guardex",
3
- "version": "6.0.1",
3
+ "version": "6.1.0",
4
4
  "description": "GuardeX: the Guardian T-Rex for your repo, with hardened multi-agent git guardrails.",
5
5
  "license": "MIT",
6
6
  "preferGlobal": true,
@@ -11,6 +11,7 @@
11
11
  - If ownership is unclear or overlaps, stop that edit, post a blocker comment, and let the leader/integrator reassign scope.
12
12
  - For git isolation, each agent must start on a dedicated branch via `scripts/agent-branch-start.sh "<task-or-plan>" "<agent-name>"`.
13
13
  - In-place branch mode is disallowed: never switch the active local/base checkout to an agent branch.
14
+ - Primary-checkout immutability: agents MUST NOT run `git checkout <branch>` on any repo's primary working tree, including nested repos inside the parent workspace (e.g. tool repos nested under the product repo). Keep each repo's primary checkout on its base/protected branch; use `git worktree add` for feature work. The `.githooks/post-checkout` hook auto-reverts primary-checkout branch switches when an agent session is detected; bypass only with `GUARDEX_ALLOW_PRIMARY_BRANCH_SWITCH=1` when truly intentional.
14
15
  - Treat the base branch (`main` or the user's current local base branch) as read-only while the agent branch is active.
15
16
  - Agent completion defaults to `scripts/codex-agent.sh`, which auto-finishes the branch (auto-commit changed files, push/create PR, attempt merge, and pull the local base branch after merge).
16
17
  - OMX completion policy: when a task is done, the agent must commit the task changes, push the agent branch, and create/update a PR for those changes (via `codex-agent` or `agent-branch-finish`).
@@ -0,0 +1,68 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ # post-checkout <prev_head> <new_head> <branch_checkout_flag>
5
+ branch_checkout="${3:-0}"
6
+ [[ "$branch_checkout" == "1" ]] || exit 0
7
+
8
+ if [[ "${GUARDEX_ALLOW_PRIMARY_BRANCH_SWITCH:-0}" == "1" ]]; then
9
+ exit 0
10
+ fi
11
+
12
+ # Skip in secondary worktrees — only the primary checkout is guarded.
13
+ git_dir_abs="$(cd "$(git rev-parse --git-dir)" && pwd -P)"
14
+ common_dir_abs="$(cd "$(git rev-parse --git-common-dir)" && pwd -P)"
15
+ if [[ "$git_dir_abs" != "$common_dir_abs" ]]; then
16
+ exit 0
17
+ fi
18
+
19
+ new_branch="$(git rev-parse --abbrev-ref HEAD 2>/dev/null || true)"
20
+ # Parse the latest reflog entry; post-checkout writes "checkout: moving from <prev> to <new>".
21
+ prev_branch="$(git reflog -1 HEAD 2>/dev/null | sed -n 's/.*checkout: moving from \([^ ]*\) to .*/\1/p' || true)"
22
+
23
+ [[ -n "$prev_branch" && -n "$new_branch" && "$prev_branch" != "$new_branch" ]] || exit 0
24
+
25
+ protected_raw="${GUARDEX_PROTECTED_BRANCHES:-$(git config --get multiagent.protectedBranches || true)}"
26
+ [[ -n "$protected_raw" ]] || protected_raw="dev main master"
27
+ protected_raw="${protected_raw//,/ }"
28
+
29
+ is_protected() {
30
+ local branch="$1"
31
+ for p in $protected_raw; do
32
+ [[ "$branch" == "$p" ]] && return 0
33
+ done
34
+ return 1
35
+ }
36
+
37
+ # Only guard when moving AWAY from a protected primary branch.
38
+ is_protected "$prev_branch" || exit 0
39
+
40
+ is_agent=0
41
+ if [[ -n "${CLAUDECODE:-}" \
42
+ || -n "${CLAUDE_CODE_SESSION_ID:-}" \
43
+ || -n "${CODEX_THREAD_ID:-}" \
44
+ || -n "${OMX_SESSION_ID:-}" \
45
+ || "${CODEX_CI:-0}" == "1" ]]; then
46
+ is_agent=1
47
+ fi
48
+
49
+ echo "" >&2
50
+ echo "[agent-primary-branch-guard] Primary checkout switched branches." >&2
51
+ echo "[agent-primary-branch-guard] from: $prev_branch (protected)" >&2
52
+ echo "[agent-primary-branch-guard] to: $new_branch" >&2
53
+ echo "[agent-primary-branch-guard] The primary working tree must stay on its base/protected branch." >&2
54
+ echo "[agent-primary-branch-guard] Use 'git worktree add' (or scripts/agent-branch-start.sh) for feature work." >&2
55
+
56
+ if [[ "$is_agent" == "1" ]]; then
57
+ echo "[agent-primary-branch-guard] Agent session detected — reverting to '$prev_branch'." >&2
58
+ echo "[agent-primary-branch-guard] Bypass with GUARDEX_ALLOW_PRIMARY_BRANCH_SWITCH=1 if truly intentional." >&2
59
+ if git diff --quiet && git diff --cached --quiet; then
60
+ GUARDEX_ALLOW_PRIMARY_BRANCH_SWITCH=1 git checkout "$prev_branch" >/dev/null 2>&1 || true
61
+ echo "[agent-primary-branch-guard] Reverted to '$prev_branch'." >&2
62
+ else
63
+ echo "[agent-primary-branch-guard] Working tree dirty — auto-revert skipped." >&2
64
+ echo "[agent-primary-branch-guard] Fix manually: git stash && git checkout $prev_branch" >&2
65
+ fi
66
+ else
67
+ echo "[agent-primary-branch-guard] Bypass with GUARDEX_ALLOW_PRIMARY_BRANCH_SWITCH=1 if intentional." >&2
68
+ fi