@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.
package/bin/multiagent-safety.js
CHANGED
|
@@ -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
|
|
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
|
|
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 '${
|
|
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
|
@@ -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
|