@imdeadpool/guardex 5.0.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/package.json ADDED
@@ -0,0 +1,68 @@
1
+ {
2
+ "name": "@imdeadpool/guardex",
3
+ "version": "5.0.0",
4
+ "description": "GuardeX: the Guardian T-Rex for your repo, with hardened multi-agent git guardrails.",
5
+ "license": "MIT",
6
+ "preferGlobal": true,
7
+ "bin": {
8
+ "guardex": "bin/multiagent-safety.js",
9
+ "gx": "bin/multiagent-safety.js",
10
+ "musafety": "bin/multiagent-safety.js",
11
+ "multiagent-safety": "bin/multiagent-safety.js"
12
+ },
13
+ "scripts": {
14
+ "test": "node --test test/*.test.js",
15
+ "agent:codex": "bash ./scripts/codex-agent.sh",
16
+ "agent:branch:start": "bash ./scripts/agent-branch-start.sh",
17
+ "agent:branch:finish": "bash ./scripts/agent-branch-finish.sh",
18
+ "agent:cleanup": "bash ./scripts/agent-worktree-prune.sh --base dev",
19
+ "agent:hooks:install": "bash ./scripts/install-agent-git-hooks.sh",
20
+ "agent:locks:claim": "python3 ./scripts/agent-file-locks.py claim",
21
+ "agent:locks:allow-delete": "python3 ./scripts/agent-file-locks.py allow-delete",
22
+ "agent:locks:release": "python3 ./scripts/agent-file-locks.py release",
23
+ "agent:locks:status": "python3 ./scripts/agent-file-locks.py status",
24
+ "agent:plan:init": "bash ./scripts/openspec/init-plan-workspace.sh",
25
+ "agent:protect:list": "gx protect list",
26
+ "agent:branch:sync": "gx sync",
27
+ "agent:branch:sync:check": "gx sync --check",
28
+ "agent:safety:setup": "gx setup",
29
+ "agent:safety:scan": "gx scan",
30
+ "agent:safety:fix": "gx fix",
31
+ "agent:safety:doctor": "gx doctor"
32
+ },
33
+ "engines": {
34
+ "node": ">=18"
35
+ },
36
+ "files": [
37
+ "bin",
38
+ "templates",
39
+ "README.md",
40
+ "LICENSE",
41
+ "SECURITY.md",
42
+ "CONTRIBUTING.md"
43
+ ],
44
+ "keywords": [
45
+ "guardex",
46
+ "multi-agent",
47
+ "git-hooks",
48
+ "branch-guard",
49
+ "agent-safety",
50
+ "codex"
51
+ ],
52
+ "author": "recodeecom",
53
+ "repository": {
54
+ "type": "git",
55
+ "url": "git+https://github.com/recodeecom/multiagent-safety.git"
56
+ },
57
+ "bugs": {
58
+ "url": "https://github.com/recodeecom/multiagent-safety/issues"
59
+ },
60
+ "homepage": "https://github.com/recodeecom/multiagent-safety#readme",
61
+ "funding": "https://github.com/sponsors/recodeecom",
62
+ "publishConfig": {
63
+ "access": "public"
64
+ },
65
+ "devDependencies": {
66
+ "fast-check": "^3.23.2"
67
+ }
68
+ }
@@ -0,0 +1,60 @@
1
+ <!-- multiagent-safety:START -->
2
+ ## Multi-Agent Execution Contract (multiagent-safety)
3
+
4
+ 0. Session plan comment + read gate (required)
5
+
6
+ - Before editing, each agent must post a short session comment/handoff note that includes:
7
+ - plan/change name (or checkpoint id),
8
+ - owned files/scope,
9
+ - intended action.
10
+ - Before deleting/replacing code, each agent must read the latest session comments/handoffs first and confirm the target code is in their owned scope.
11
+ - If ownership is unclear or overlaps, stop that edit, post a blocker comment, and let the leader/integrator reassign scope.
12
+ - For git isolation, each agent must start on a dedicated branch via `scripts/agent-branch-start.sh "<task-or-plan>" "<agent-name>"`.
13
+ - Agent completion must use `scripts/agent-branch-finish.sh` (direct merge to base when allowed; auto PR fallback for protected bases, then cleanup after merge).
14
+
15
+ 1. Explicit ownership before edits
16
+
17
+ - Assign each agent clear file/module ownership.
18
+ - Do not edit files outside your assigned scope unless the leader reassigns ownership.
19
+
20
+ 2. Preserve parallel safety
21
+
22
+ - Assume other agents are editing nearby code concurrently.
23
+ - Never revert unrelated changes authored by others.
24
+ - If another change conflicts with your approach, adapt and report the conflict in handoff.
25
+
26
+ 3. Verify before completion
27
+
28
+ - Run required local checks for the area you changed.
29
+ - Do not mark work complete without command output evidence.
30
+
31
+ 4. Required handoff format (every agent)
32
+
33
+ - Files changed
34
+ - Behavior touched
35
+ - Verification commands + results
36
+ - Risks / follow-ups
37
+
38
+ ## OpenSpec Plan Workspace (recommended)
39
+
40
+ When work needs a durable planning phase, scaffold a plan workspace before implementation:
41
+
42
+ ```bash
43
+ bash scripts/openspec/init-plan-workspace.sh "<plan-slug>"
44
+ ```
45
+
46
+ Expected shape:
47
+
48
+ ```text
49
+ openspec/plan/<plan-slug>/
50
+ summary.md
51
+ checkpoints.md
52
+ planner/plan.md
53
+ planner/tasks.md
54
+ architect/tasks.md
55
+ critic/tasks.md
56
+ executor/tasks.md
57
+ writer/tasks.md
58
+ verifier/tasks.md
59
+ ```
60
+ <!-- multiagent-safety:END -->
@@ -0,0 +1,18 @@
1
+ # /guardex
2
+
3
+ Run a GuardeX check-and-repair workflow for the current repository.
4
+
5
+ ## Steps
6
+
7
+ 1. Run `gx status`.
8
+ 2. If status is degraded, run `gx doctor`.
9
+ 3. If still degraded, run `gx scan` and summarize each finding with a fix.
10
+ 4. Report final verdict as one of:
11
+ - `Repo is guarded`
12
+ - `Repo is not guarded` (include blockers)
13
+
14
+ ## Style
15
+
16
+ - Keep output short and operational.
17
+ - Include exact commands you executed.
18
+ - Prefer concrete next actions over generic advice.
@@ -0,0 +1,36 @@
1
+ ---
2
+ name: guardex
3
+ description: "Use when you need to check, repair, or bootstrap multi-agent safety guardrails in this repository."
4
+ ---
5
+
6
+ # GuardeX (Codex skill)
7
+
8
+ Use this skill whenever branch safety, lock ownership, or guardrail setup may be broken.
9
+
10
+ ## Fast path
11
+
12
+ 1. Run `gx status`.
13
+ 2. If repo safety is degraded, run `gx doctor`.
14
+ 3. If issues remain, run `gx scan` and address the findings.
15
+
16
+ ## Setup path
17
+
18
+ If guardrails are missing entirely, run:
19
+
20
+ ```sh
21
+ gx setup
22
+ ```
23
+
24
+ Then verify:
25
+
26
+ ```sh
27
+ gx status
28
+ gx scan
29
+ ```
30
+
31
+ ## Operator notes
32
+
33
+ - Prefer `gx doctor` for one-step repair + verification.
34
+ - Keep agent work isolated (`agent/*` branches + lock claims).
35
+ - For one-command Codex sandbox startup, use `bash scripts/codex-agent.sh "<task>" "<agent-name>"`.
36
+ - Do not bypass protected branch safeguards unless explicitly required.
@@ -0,0 +1,178 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ branch="$(git rev-parse --abbrev-ref HEAD 2>/dev/null || true)"
5
+ if [[ -z "$branch" || "$branch" == "HEAD" ]]; then
6
+ branch="$(git symbolic-ref --quiet --short HEAD 2>/dev/null || true)"
7
+ fi
8
+ if [[ -z "$branch" ]]; then
9
+ exit 0
10
+ fi
11
+
12
+ if [[ "${ALLOW_COMMIT_ON_PROTECTED_BRANCH:-0}" == "1" ]]; then
13
+ exit 0
14
+ fi
15
+
16
+ is_unborn_branch=0
17
+ if ! git rev-parse --verify HEAD >/dev/null 2>&1; then
18
+ is_unborn_branch=1
19
+ fi
20
+
21
+ is_codex_session=0
22
+ if [[ -n "${CODEX_THREAD_ID:-}" || -n "${OMX_SESSION_ID:-}" || "${CODEX_CI:-0}" == "1" ]]; then
23
+ is_codex_session=1
24
+ fi
25
+
26
+ protected_branches_raw="${MUSAFETY_PROTECTED_BRANCHES:-$(git config --get multiagent.protectedBranches || true)}"
27
+ if [[ -z "$protected_branches_raw" ]]; then
28
+ protected_branches_raw="dev main master"
29
+ fi
30
+ protected_branches_raw="${protected_branches_raw//,/ }"
31
+
32
+ is_protected_branch=0
33
+ for protected_branch in $protected_branches_raw; do
34
+ if [[ "$branch" == "$protected_branch" ]]; then
35
+ is_protected_branch=1
36
+ break
37
+ fi
38
+ done
39
+
40
+ codex_require_agent_branch_raw="${MUSAFETY_CODEX_REQUIRE_AGENT_BRANCH:-$(git config --get multiagent.codexRequireAgentBranch || true)}"
41
+ if [[ -z "$codex_require_agent_branch_raw" ]]; then
42
+ codex_require_agent_branch_raw="true"
43
+ fi
44
+ codex_require_agent_branch="$(printf '%s' "$codex_require_agent_branch_raw" | tr '[:upper:]' '[:lower:]')"
45
+
46
+ should_require_codex_agent_branch=0
47
+ case "$codex_require_agent_branch" in
48
+ 1|true|yes|on) should_require_codex_agent_branch=1 ;;
49
+ 0|false|no|off) should_require_codex_agent_branch=0 ;;
50
+ *) should_require_codex_agent_branch=1 ;;
51
+ esac
52
+
53
+ if [[ "$should_require_codex_agent_branch" == "1" && "${MUSAFETY_ALLOW_CODEX_ON_NON_AGENT:-0}" != "1" ]]; then
54
+ if [[ "$is_codex_session" == "1" && "$branch" != agent/* ]]; then
55
+ if [[ "$is_protected_branch" == "1" ]]; then
56
+ cat >&2 <<'MSG'
57
+ [guardex-preedit-guard] Codex edit/commit detected on a protected branch.
58
+ GuardeX requires Codex work to run from an isolated agent/* branch.
59
+ Start the sub-branch/worktree with:
60
+ bash scripts/codex-agent.sh "<task-or-plan>" "<agent-name>"
61
+ Or manually:
62
+ bash scripts/agent-branch-start.sh "<task-or-plan>" "<agent-name>"
63
+ Then commit from the created agent/* branch.
64
+
65
+ Temporary bypass (not recommended):
66
+ MUSAFETY_ALLOW_CODEX_ON_NON_AGENT=1 git commit ...
67
+ MSG
68
+ exit 1
69
+ fi
70
+
71
+ cat >&2 <<'MSG'
72
+ [codex-branch-guard] Codex agent commit blocked on non-agent branch.
73
+ Use isolated branch/worktree first:
74
+ bash scripts/agent-branch-start.sh "<task-or-plan>" "<agent-name>"
75
+ Then commit from the created agent/* branch.
76
+
77
+ Temporary bypass (not recommended):
78
+ MUSAFETY_ALLOW_CODEX_ON_NON_AGENT=1 git commit ...
79
+ Disable this rule for a repo (not recommended):
80
+ git config multiagent.codexRequireAgentBranch false
81
+ MSG
82
+ exit 1
83
+ fi
84
+ fi
85
+
86
+ if [[ "$is_protected_branch" == "1" ]]; then
87
+ if [[ "$is_unborn_branch" == "1" && "$is_codex_session" != "1" ]]; then
88
+ exit 0
89
+ fi
90
+
91
+ git_dir="$(git rev-parse --git-dir)"
92
+ if [[ -f "$git_dir/MERGE_HEAD" ]]; then
93
+ exit 0
94
+ fi
95
+
96
+ cat >&2 <<'MSG'
97
+ [agent-branch-guard] Direct commits on protected branches are blocked.
98
+ Use an agent branch first:
99
+ bash scripts/agent-branch-start.sh "<task-or-plan>" "<agent-name>"
100
+ After finishing work:
101
+ bash scripts/agent-branch-finish.sh
102
+
103
+ Temporary bypass (not recommended):
104
+ ALLOW_COMMIT_ON_PROTECTED_BRANCH=1 git commit ...
105
+ MSG
106
+ exit 1
107
+ fi
108
+
109
+ if [[ "$branch" == agent/* ]]; then
110
+ if ! python3 scripts/agent-file-locks.py validate --branch "$branch" --staged; then
111
+ cat >&2 <<'MSG'
112
+ [agent-branch-guard] Agent branch commits require file ownership locks.
113
+ Claim files first:
114
+ python3 scripts/agent-file-locks.py claim --branch "$(git rev-parse --abbrev-ref HEAD)" <file...>
115
+ MSG
116
+ exit 1
117
+ fi
118
+
119
+ require_sync_before_commit_raw="$(git config --get multiagent.sync.requireBeforeCommit || true)"
120
+ if [[ -z "$require_sync_before_commit_raw" ]]; then
121
+ require_sync_before_commit_raw="false"
122
+ fi
123
+ require_sync_before_commit="$(printf '%s' "$require_sync_before_commit_raw" | tr '[:upper:]' '[:lower:]')"
124
+
125
+ should_require_sync=0
126
+ case "$require_sync_before_commit" in
127
+ 1|true|yes|on) should_require_sync=1 ;;
128
+ 0|false|no|off) should_require_sync=0 ;;
129
+ *) should_require_sync=0 ;;
130
+ esac
131
+
132
+ if [[ "$should_require_sync" == "1" ]]; then
133
+ base_branch="$(git config --get multiagent.baseBranch || true)"
134
+ if [[ -z "$base_branch" ]]; then
135
+ base_branch="dev"
136
+ fi
137
+
138
+ max_behind_raw="$(git config --get multiagent.sync.maxBehindCommits || true)"
139
+ if [[ -z "$max_behind_raw" ]]; then
140
+ max_behind_raw="0"
141
+ fi
142
+ if [[ ! "$max_behind_raw" =~ ^[0-9]+$ ]]; then
143
+ echo "[agent-sync-guard] Invalid multiagent.sync.maxBehindCommits value: ${max_behind_raw}" >&2
144
+ echo "[agent-sync-guard] Expected non-negative integer. Example: git config multiagent.sync.maxBehindCommits 0" >&2
145
+ exit 1
146
+ fi
147
+
148
+ if ! git fetch origin "$base_branch" --quiet >/dev/null 2>&1; then
149
+ echo "[agent-sync-guard] Unable to fetch origin/${base_branch} while commit sync gate is enabled." >&2
150
+ echo "[agent-sync-guard] Disable gate temporarily with: git config multiagent.sync.requireBeforeCommit false" >&2
151
+ exit 1
152
+ fi
153
+
154
+ if ! git show-ref --verify --quiet "refs/remotes/origin/${base_branch}"; then
155
+ echo "[agent-sync-guard] Remote base branch not found: origin/${base_branch}" >&2
156
+ exit 1
157
+ fi
158
+
159
+ behind_count="$(git rev-list --left-right --count "${branch}...origin/${base_branch}" 2>/dev/null | awk '{print $2}')"
160
+ behind_count="${behind_count:-0}"
161
+ max_behind="${max_behind_raw}"
162
+
163
+ if [[ "$behind_count" -gt "$max_behind" ]]; then
164
+ cat >&2 <<MSG
165
+ [agent-sync-guard] Commit blocked: '${branch}' is behind origin/${base_branch} by ${behind_count} commit(s) (max allowed: ${max_behind}).
166
+ Run:
167
+ gx sync --base ${base_branch}
168
+ Or relax threshold:
169
+ git config multiagent.sync.maxBehindCommits <n>
170
+ MSG
171
+ exit 1
172
+ fi
173
+ fi
174
+ fi
175
+
176
+ if command -v pre-commit >/dev/null 2>&1 && [[ -f .pre-commit-config.yaml ]]; then
177
+ pre-commit run --hook-stage pre-commit
178
+ fi
@@ -0,0 +1,57 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ if [[ "${ALLOW_PUSH_ON_PROTECTED_BRANCH:-0}" == "1" || "${ALLOW_COMMIT_ON_PROTECTED_BRANCH:-0}" == "1" ]]; then
5
+ exit 0
6
+ fi
7
+
8
+ is_vscode_git_context=0
9
+ if [[ -n "${VSCODE_GIT_IPC_HANDLE:-}" || -n "${VSCODE_GIT_ASKPASS_NODE:-}" || -n "${VSCODE_IPC_HOOK_CLI:-}" ]]; then
10
+ is_vscode_git_context=1
11
+ fi
12
+
13
+ if [[ "$is_vscode_git_context" == "1" ]]; then
14
+ exit 0
15
+ fi
16
+
17
+ protected_branches_raw="${MUSAFETY_PROTECTED_BRANCHES:-$(git config --get multiagent.protectedBranches || true)}"
18
+ if [[ -z "$protected_branches_raw" ]]; then
19
+ protected_branches_raw="dev main master"
20
+ fi
21
+ protected_branches_raw="${protected_branches_raw//,/ }"
22
+
23
+ is_protected_branch() {
24
+ local branch="$1"
25
+ for protected_branch in $protected_branches_raw; do
26
+ if [[ "$branch" == "$protected_branch" ]]; then
27
+ return 0
28
+ fi
29
+ done
30
+ return 1
31
+ }
32
+
33
+ blocked_refs=()
34
+ while IFS=' ' read -r local_ref local_sha remote_ref remote_sha; do
35
+ if [[ -z "${remote_ref:-}" || "$remote_ref" != refs/heads/* ]]; then
36
+ continue
37
+ fi
38
+
39
+ remote_branch="${remote_ref#refs/heads/}"
40
+ if is_protected_branch "$remote_branch"; then
41
+ blocked_refs+=("$remote_branch")
42
+ fi
43
+ done
44
+
45
+ if [[ "${#blocked_refs[@]}" -gt 0 ]]; then
46
+ {
47
+ echo "[agent-branch-guard] Push to protected branch blocked outside VS Code Git context."
48
+ echo "[agent-branch-guard] Protected target(s): ${blocked_refs[*]}"
49
+ echo "[agent-branch-guard] Use VS Code Source Control for protected-branch push, or push from an agent branch and merge via PR."
50
+ echo
51
+ echo "Temporary bypass (not recommended):"
52
+ echo " ALLOW_PUSH_ON_PROTECTED_BRANCH=1 git push ..."
53
+ } >&2
54
+ exit 1
55
+ fi
56
+
57
+ exit 0