jorgex-stack 1.9.47 → 1.9.49
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/dist/cli.js +6 -21
- package/package.json +1 -1
- package/stack/agents/implementer.md +1 -1
- package/stack/agents/tester.md +1 -1
- package/stack/agents/translator.md +1 -1
- package/stack/config/defaults.json +35 -0
- package/stack/scripts/repair-worktree-config.cjs +2 -2
- package/stack/scripts/block-destructive-git.cjs +0 -110
package/dist/cli.js
CHANGED
|
@@ -1401,11 +1401,6 @@ ${gitReadCommands.map((command) => `- \`${command}\``).join("\n")}
|
|
|
1401
1401
|
import path10 from "path";
|
|
1402
1402
|
import fs7 from "fs";
|
|
1403
1403
|
import { isDeepStrictEqual as isDeepStrictEqual2 } from "util";
|
|
1404
|
-
|
|
1405
|
-
// src/lib/git-guard.ts
|
|
1406
|
-
var GIT_GUARD_SCRIPT = "block-destructive-git.cjs";
|
|
1407
|
-
|
|
1408
|
-
// src/adapters/claude-code.ts
|
|
1409
1404
|
function yamlString2(value) {
|
|
1410
1405
|
return JSON.stringify(value);
|
|
1411
1406
|
}
|
|
@@ -1551,16 +1546,6 @@ ${agent.body}`;
|
|
|
1551
1546
|
const tools = toolsFor(agent);
|
|
1552
1547
|
if (tools !== null) lines.push(`tools: ${tools}`);
|
|
1553
1548
|
lines.push(`model: ${resolveAgentModel(models, agent.name, agent.tier).model}`);
|
|
1554
|
-
if (agent.bash === "full") {
|
|
1555
|
-
lines.push(
|
|
1556
|
-
"hooks:",
|
|
1557
|
-
" PreToolUse:",
|
|
1558
|
-
' - matcher: "Bash|PowerShell"',
|
|
1559
|
-
" hooks:",
|
|
1560
|
-
" - type: command",
|
|
1561
|
-
` command: "node \\"{{SCRIPTS_DIR}}/${GIT_GUARD_SCRIPT}\\""`
|
|
1562
|
-
);
|
|
1563
|
-
}
|
|
1564
1549
|
return [
|
|
1565
1550
|
{
|
|
1566
1551
|
file: `${agent.name}.md`,
|
|
@@ -6146,16 +6131,16 @@ import { createHash as createHash2 } from "crypto";
|
|
|
6146
6131
|
var pi_runtime_pin_default = {
|
|
6147
6132
|
package: {
|
|
6148
6133
|
name: "jorgex-pi",
|
|
6149
|
-
version: "0.8.
|
|
6150
|
-
source: "npm:jorgex-pi@0.8.
|
|
6134
|
+
version: "0.8.24",
|
|
6135
|
+
source: "npm:jorgex-pi@0.8.24"
|
|
6151
6136
|
},
|
|
6152
6137
|
provenance: {
|
|
6153
|
-
commit: "
|
|
6138
|
+
commit: "652d7e445e6f184c4543593c115026aa2f71e761"
|
|
6154
6139
|
},
|
|
6155
6140
|
tarball: {
|
|
6156
|
-
bytes:
|
|
6157
|
-
sha256: "
|
|
6158
|
-
sha512: "
|
|
6141
|
+
bytes: 89140631,
|
|
6142
|
+
sha256: "6f67e546c86f21f9b5ff139f429551e696be4a8389ce4a6262e137dcce923a5f",
|
|
6143
|
+
sha512: "1ce4bfc316f1635c5e498af7134ae16f430a4f6a3d2c99c7aa6fc31b76ce18684759c6480f506b5de45aa5b5b682e03f68d10fc77c83ae1679006dab679d9aa4"
|
|
6159
6144
|
}
|
|
6160
6145
|
};
|
|
6161
6146
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "jorgex-stack",
|
|
3
|
-
"version": "1.9.
|
|
3
|
+
"version": "1.9.49",
|
|
4
4
|
"description": "Harness multi-agente portable: instala la config JorgeX (agentes, skills, hooks, Engram, MCPs) en Claude Code, Codex CLI, OpenCode y Pi",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -13,7 +13,7 @@ You implement real changes. You don't stop at analysis, you don't answer with ju
|
|
|
13
13
|
|
|
14
14
|
**Mandatory first action**: load the `agent-delegation` skill.
|
|
15
15
|
|
|
16
|
-
**
|
|
16
|
+
**Ask before destructive git** (`reset`, `clean`, `checkout --`, `restore`, `push --force`) — it can discard work or rewrite history. Prefer commit forward; if you need to discard or reset repo state, ask the main agent/orchestrator first and only proceed with explicit approval.
|
|
17
17
|
|
|
18
18
|
**Conditional skill**:
|
|
19
19
|
|
package/stack/agents/tester.md
CHANGED
|
@@ -13,7 +13,7 @@ Your job is to produce the strongest testing evidence for the risk—not to maxi
|
|
|
13
13
|
|
|
14
14
|
**Mandatory first action**: load the `tdd` and `agent-delegation` skills.
|
|
15
15
|
|
|
16
|
-
**
|
|
16
|
+
**Ask before destructive git** (`reset`, `clean`, `checkout --`, `restore`, `push --force`) — it can discard work or rewrite history. Prefer commit forward; if you need to discard or reset repo state, ask the main agent/orchestrator first and only proceed with explicit approval.
|
|
17
17
|
|
|
18
18
|
## Before acting
|
|
19
19
|
|
|
@@ -13,7 +13,7 @@ You handle translations, multi-language text and integration with the project's
|
|
|
13
13
|
|
|
14
14
|
**Mandatory first action**: load the `agent-delegation` skill.
|
|
15
15
|
|
|
16
|
-
**
|
|
16
|
+
**Ask before destructive git** (`reset`, `clean`, `checkout --`, `restore`, `push --force`) — it can discard work or rewrite history. Prefer commit forward; if you need to discard or reset repo state, ask the main agent/orchestrator first and only proceed with explicit approval.
|
|
17
17
|
|
|
18
18
|
**Final output, last of all**: your final report (ending with the Result contract) must be the very last thing you emit. If you need to save anything to memory, do it BEFORE that output — never after.
|
|
19
19
|
|
|
@@ -162,6 +162,41 @@
|
|
|
162
162
|
"git.exe *push*": "ask",
|
|
163
163
|
"*/git.exe *push*": "ask",
|
|
164
164
|
"*\\git.exe *push*": "ask",
|
|
165
|
+
"git *checkout*--*": "ask",
|
|
166
|
+
"*/git *checkout*--*": "ask",
|
|
167
|
+
"git.exe *checkout*--*": "ask",
|
|
168
|
+
"*/git.exe *checkout*--*": "ask",
|
|
169
|
+
"*\\git.exe *checkout*--*": "ask",
|
|
170
|
+
"git *checkout* -f*": "ask",
|
|
171
|
+
"*/git *checkout* -f*": "ask",
|
|
172
|
+
"git.exe *checkout* -f*": "ask",
|
|
173
|
+
"*/git.exe *checkout* -f*": "ask",
|
|
174
|
+
"*\\git.exe *checkout* -f*": "ask",
|
|
175
|
+
"git *restore*": "ask",
|
|
176
|
+
"*/git *restore*": "ask",
|
|
177
|
+
"git.exe *restore*": "ask",
|
|
178
|
+
"*/git.exe *restore*": "ask",
|
|
179
|
+
"*\\git.exe *restore*": "ask",
|
|
180
|
+
"git *switch*--discard-changes*": "ask",
|
|
181
|
+
"*/git *switch*--discard-changes*": "ask",
|
|
182
|
+
"git.exe *switch*--discard-changes*": "ask",
|
|
183
|
+
"*/git.exe *switch*--discard-changes*": "ask",
|
|
184
|
+
"*\\git.exe *switch*--discard-changes*": "ask",
|
|
185
|
+
"git *rebase*": "ask",
|
|
186
|
+
"*/git *rebase*": "ask",
|
|
187
|
+
"git.exe *rebase*": "ask",
|
|
188
|
+
"*/git.exe *rebase*": "ask",
|
|
189
|
+
"*\\git.exe *rebase*": "ask",
|
|
190
|
+
"* git *checkout*--*": "ask",
|
|
191
|
+
"* git.exe *checkout*--*": "ask",
|
|
192
|
+
"* git *checkout* -f*": "ask",
|
|
193
|
+
"* git.exe *checkout* -f*": "ask",
|
|
194
|
+
"* git *restore*": "ask",
|
|
195
|
+
"* git.exe *restore*": "ask",
|
|
196
|
+
"* git *switch*--discard-changes*": "ask",
|
|
197
|
+
"* git.exe *switch*--discard-changes*": "ask",
|
|
198
|
+
"* git *rebase*": "ask",
|
|
199
|
+
"* git.exe *rebase*": "ask",
|
|
165
200
|
"git -c *": "ask",
|
|
166
201
|
"*/git -c *": "ask",
|
|
167
202
|
"git.exe -c *": "ask",
|
|
@@ -17,8 +17,8 @@
|
|
|
17
17
|
//
|
|
18
18
|
// Cross-agent (Claude Code / Codex / OpenCode) y cross-platform: node puro, sin deps.
|
|
19
19
|
// Idempotente, INDEPENDIENTE del cwd de escritura (opera con --file sobre rutas absolutas),
|
|
20
|
-
// fail-open y exit 0 SIEMPRE (un guardian nunca debe bloquear una tool)
|
|
21
|
-
//
|
|
20
|
+
// fail-open y exit 0 SIEMPRE (un guardian nunca debe bloquear una tool): un
|
|
21
|
+
// fail-open deja rastro en stderr para ser diagnosticable.
|
|
22
22
|
|
|
23
23
|
const { execFileSync } = require("node:child_process");
|
|
24
24
|
const fs = require("node:fs");
|
|
@@ -1,110 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
// PreToolUse guard (Claude Code): blocks destructive git commands in the
|
|
3
|
-
// subagents that declare it, leaving the main agent unrestricted. Claude Code
|
|
4
|
-
// has no per-subagent command denylist, so this is the documented mechanism
|
|
5
|
-
// (sub-agents docs -> "Conditional rules with hooks"). Reads the PreToolUse
|
|
6
|
-
// payload from stdin and exits 2 to block if any segment of the command would
|
|
7
|
-
// discard work or rewrite history. Best-effort guardrail, not an adversarial
|
|
8
|
-
// sandbox. Fail-open: any read/parse problem allows the command (exit 0) so the
|
|
9
|
-
// guard can never wedge legitimate work — but it logs why, so a silent no-op is
|
|
10
|
-
// diagnosable.
|
|
11
|
-
|
|
12
|
-
// git global options that sit BETWEEN `git` and the subcommand. Without skipping
|
|
13
|
-
// them, `git -C /repo reset --hard` would slip past a naive `git reset` match.
|
|
14
|
-
const GLOBAL_OPT_WITH_ARG = new Set([
|
|
15
|
-
"-C", "-c", "--git-dir", "--work-tree", "--namespace", "--exec-path", "--super-prefix", "--config-env",
|
|
16
|
-
]);
|
|
17
|
-
|
|
18
|
-
const isForceFlag = (token) =>
|
|
19
|
-
token === "--force" || token === "--force-with-lease" || /^-[a-z]*f[a-z]*$/i.test(token);
|
|
20
|
-
|
|
21
|
-
/** True if a single command segment is a destructive git invocation. */
|
|
22
|
-
function isDestructiveSegment(segment) {
|
|
23
|
-
const tokens = segment.trim().split(/\s+/).filter(Boolean);
|
|
24
|
-
const gitIdx = tokens.indexOf("git");
|
|
25
|
-
if (gitIdx === -1) return false;
|
|
26
|
-
|
|
27
|
-
// Skip leading git global options to reach the real subcommand.
|
|
28
|
-
let i = gitIdx + 1;
|
|
29
|
-
while (i < tokens.length) {
|
|
30
|
-
const token = tokens[i];
|
|
31
|
-
if (token === "--") break;
|
|
32
|
-
if (/^(--git-dir|--work-tree|--namespace|--exec-path|--super-prefix|--config-env)=/.test(token)) { i++; continue; }
|
|
33
|
-
if (GLOBAL_OPT_WITH_ARG.has(token)) { i += 2; continue; } // option + its value
|
|
34
|
-
if (token.startsWith("-")) { i++; continue; } // any other global flag
|
|
35
|
-
break;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
const sub = tokens[i];
|
|
39
|
-
const rest = tokens.slice(i + 1);
|
|
40
|
-
if (!sub) return false;
|
|
41
|
-
|
|
42
|
-
// Always destructive: discard worktree/index, delete untracked files.
|
|
43
|
-
if (sub === "reset" || sub === "clean" || sub === "restore") return true;
|
|
44
|
-
// git switch --discard-changes drops local modifications.
|
|
45
|
-
if (sub === "switch") return rest.includes("--discard-changes");
|
|
46
|
-
// git checkout: a branch switch is safe; the discard forms carry "--", a
|
|
47
|
-
// force flag, or a "." pathspec (git checkout . / git checkout HEAD -- .).
|
|
48
|
-
if (sub === "checkout") {
|
|
49
|
-
return rest.includes("--") || rest.includes(".") || rest.some(isForceFlag);
|
|
50
|
-
}
|
|
51
|
-
// git push --force / --force-with-lease / -f (incl. bundled like -fq) or a
|
|
52
|
-
// leading "+" refspec all force-overwrite remote history.
|
|
53
|
-
if (sub === "push") {
|
|
54
|
-
return rest.some((t) => isForceFlag(t) || /^\+/.test(t));
|
|
55
|
-
}
|
|
56
|
-
return false;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
function isDestructive(command) {
|
|
60
|
-
// Evaluate each command segment independently so a destructive op anywhere in
|
|
61
|
-
// a compound command is caught (cd x && git reset), without a quoted token in
|
|
62
|
-
// one command (git commit -m "git reset") leaking into another's match.
|
|
63
|
-
return command
|
|
64
|
-
.split(/&&|\|\||[;|\n]/)
|
|
65
|
-
.some((segment) => isDestructiveSegment(segment));
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
function extractCommand(payload) {
|
|
69
|
-
const toolInput = payload && payload.tool_input;
|
|
70
|
-
const raw = toolInput && (toolInput.command != null ? toolInput.command : toolInput.script);
|
|
71
|
-
// Codex-style hooks pass argv as an array; normalize like post-pr-review.cjs.
|
|
72
|
-
if (Array.isArray(raw)) return raw.join(" ");
|
|
73
|
-
return typeof raw === "string" ? raw : "";
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
function allow(reason) {
|
|
77
|
-
if (reason) process.stderr.write(`block-destructive-git: ${reason} (fail-open, allowing)\n`);
|
|
78
|
-
process.exit(0);
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
let input = "";
|
|
82
|
-
process.stdin.on("data", (chunk) => {
|
|
83
|
-
input += chunk;
|
|
84
|
-
});
|
|
85
|
-
process.stdin.on("error", () => allow("stdin error"));
|
|
86
|
-
process.stdin.on("end", () => {
|
|
87
|
-
let command = "";
|
|
88
|
-
try {
|
|
89
|
-
command = extractCommand(JSON.parse(input || "{}"));
|
|
90
|
-
} catch {
|
|
91
|
-
allow("unreadable payload");
|
|
92
|
-
return;
|
|
93
|
-
}
|
|
94
|
-
if (command.trim() === "") process.exit(0);
|
|
95
|
-
|
|
96
|
-
if (isDestructive(command)) {
|
|
97
|
-
process.stderr.write(
|
|
98
|
-
"Blocked: destructive git is not allowed in this subagent " +
|
|
99
|
-
"(reset / clean / checkout discard / restore / switch --discard-changes / push --force). " +
|
|
100
|
-
"Don't discard or rewrite repo state — commit forward, or stop and ask the user.\n",
|
|
101
|
-
);
|
|
102
|
-
process.exit(2);
|
|
103
|
-
}
|
|
104
|
-
process.exit(0);
|
|
105
|
-
});
|
|
106
|
-
|
|
107
|
-
// Safety nets so the guard can never hang the tool call: resume the stream (some
|
|
108
|
-
// shells need it to emit EOF) and bail out fail-open if stdin never ends.
|
|
109
|
-
process.stdin.resume();
|
|
110
|
-
setTimeout(() => allow("stdin timeout"), 2000).unref();
|