greprag 5.74.14 → 5.74.16
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/codex-fast-hook.js
CHANGED
|
@@ -95,10 +95,6 @@ async function main() {
|
|
|
95
95
|
return;
|
|
96
96
|
}
|
|
97
97
|
let result = chipResult;
|
|
98
|
-
if (subcommand === 'codex-pretooluse' && !result?.hookSpecificOutput.permissionDecision) {
|
|
99
|
-
const { evaluateCodexDeliveryCoordination } = await Promise.resolve().then(() => __importStar(require('./codex-delivery-coordination')));
|
|
100
|
-
result = mergeOutputs(result, evaluateCodexDeliveryCoordination(input));
|
|
101
|
-
}
|
|
102
98
|
if (!result?.hookSpecificOutput.permissionDecision && input.tool_name === 'Bash') {
|
|
103
99
|
const { runSearchGuard } = await Promise.resolve().then(() => __importStar(require('./commands/search-guard')));
|
|
104
100
|
result = mergeOutputs(result, runSearchGuard(input));
|
|
@@ -27,10 +27,10 @@
|
|
|
27
27
|
* dedups to stay quiet), the merge gate must reflect live truth each time.
|
|
28
28
|
*
|
|
29
29
|
* EFFECT is the adapter's choice, not the eval's: Claude/OpenCode inject the
|
|
30
|
-
* fresh roster as context. Codex
|
|
31
|
-
*
|
|
32
|
-
* ingress-source wrapper would inject
|
|
33
|
-
* the message.
|
|
30
|
+
* fresh roster as context. Codex keeps delivery coordination in the native
|
|
31
|
+
* agent/tool layer through the Delivery announce, because shell hooks cannot
|
|
32
|
+
* observe native task coordination. An ingress-source wrapper would inject
|
|
33
|
+
* instead. The eval below only produces the message.
|
|
34
34
|
*
|
|
35
35
|
* Shared-file Write was CONSIDERED (chip spec) but deferred: classifying a
|
|
36
36
|
* write as "shared" is ambiguous, and a fresh network read on every Write/Edit
|
|
@@ -12,7 +12,7 @@ exports.buildDeliveryAnnounce = buildDeliveryAnnounce;
|
|
|
12
12
|
// adr: adr/delivery-announce-pilot.md
|
|
13
13
|
function coordinationLine(platform) {
|
|
14
14
|
if (platform === 'codex') {
|
|
15
|
-
return 'Codex: at the merge/deploy gate, call codex_app.list_threads unfiltered, filter to peers in the same repo, then use codex_app.send_message_to_thread once for ready or overlapping work. Delivery owner: rename this task `DEPLOY: <existing title>`; transfer the prefix on handoff.';
|
|
15
|
+
return 'Codex: at the merge/deploy gate, call codex_app.list_threads unfiltered, filter to peers in the same repo, then use codex_app.send_message_to_thread once for ready or overlapping work. Delivery owner: rename this task `DEPLOY: <existing title>`; transfer the prefix on handoff; remove the prefix when delivery is done.';
|
|
16
16
|
}
|
|
17
17
|
if (platform === 'claude-code') {
|
|
18
18
|
return 'Claude Code: at the merge/deploy gate, discover peers in the same repo and send one concise delivery notice to peers with ready or overlapping work.';
|
|
@@ -2401,7 +2401,7 @@ var loadoutRegistrarModule = {
|
|
|
2401
2401
|
// src/commands/delivery-reminder.ts
|
|
2402
2402
|
function coordinationLine(platform) {
|
|
2403
2403
|
if (platform === "codex") {
|
|
2404
|
-
return "Codex: at the merge/deploy gate, call codex_app.list_threads unfiltered, filter to peers in the same repo, then use codex_app.send_message_to_thread once for ready or overlapping work. Delivery owner: rename this task `DEPLOY: <existing title>`; transfer the prefix on handoff.";
|
|
2404
|
+
return "Codex: at the merge/deploy gate, call codex_app.list_threads unfiltered, filter to peers in the same repo, then use codex_app.send_message_to_thread once for ready or overlapping work. Delivery owner: rename this task `DEPLOY: <existing title>`; transfer the prefix on handoff; remove the prefix when delivery is done.";
|
|
2405
2405
|
}
|
|
2406
2406
|
if (platform === "claude-code") {
|
|
2407
2407
|
return "Claude Code: at the merge/deploy gate, discover peers in the same repo and send one concise delivery notice to peers with ready or overlapping work.";
|
package/package.json
CHANGED
|
@@ -1,215 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/** Codex delivery coordination - interrupt the first delivery action once,
|
|
3
|
-
* then keep the rest of that delivery run non-blocking.
|
|
4
|
-
*
|
|
5
|
-
* The hook cannot call native Codex task tools. It names the exact agent-owned
|
|
6
|
-
* discovery and messaging actions, persists the open delivery window before
|
|
7
|
-
* denying, and never waits for peer replies or attestation.
|
|
8
|
-
*
|
|
9
|
-
* adr: adr/codex-coordinate-gate.md */
|
|
10
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
11
|
-
if (k2 === undefined) k2 = k;
|
|
12
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
13
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
14
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
15
|
-
}
|
|
16
|
-
Object.defineProperty(o, k2, desc);
|
|
17
|
-
}) : (function(o, m, k, k2) {
|
|
18
|
-
if (k2 === undefined) k2 = k;
|
|
19
|
-
o[k2] = m[k];
|
|
20
|
-
}));
|
|
21
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
22
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
23
|
-
}) : function(o, v) {
|
|
24
|
-
o["default"] = v;
|
|
25
|
-
});
|
|
26
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
27
|
-
var ownKeys = function(o) {
|
|
28
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
29
|
-
var ar = [];
|
|
30
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
31
|
-
return ar;
|
|
32
|
-
};
|
|
33
|
-
return ownKeys(o);
|
|
34
|
-
};
|
|
35
|
-
return function (mod) {
|
|
36
|
-
if (mod && mod.__esModule) return mod;
|
|
37
|
-
var result = {};
|
|
38
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
39
|
-
__setModuleDefault(result, mod);
|
|
40
|
-
return result;
|
|
41
|
-
};
|
|
42
|
-
})();
|
|
43
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
44
|
-
exports.DELIVERY_COORDINATION_WINDOW_MS = void 0;
|
|
45
|
-
exports.codexDeliveryTrigger = codexDeliveryTrigger;
|
|
46
|
-
exports.codexDeliveryCoordinationText = codexDeliveryCoordinationText;
|
|
47
|
-
exports.evaluateCodexDeliveryCoordination = evaluateCodexDeliveryCoordination;
|
|
48
|
-
const crypto = __importStar(require("crypto"));
|
|
49
|
-
const fs = __importStar(require("fs"));
|
|
50
|
-
const path = __importStar(require("path"));
|
|
51
|
-
const child_process_1 = require("child_process");
|
|
52
|
-
const coordinate_gate_1 = require("./commands/coordinate-gate");
|
|
53
|
-
exports.DELIVERY_COORDINATION_WINDOW_MS = 30 * 60 * 1000;
|
|
54
|
-
function homeDir() {
|
|
55
|
-
return process.env.USERPROFILE || process.env.HOME || '';
|
|
56
|
-
}
|
|
57
|
-
function normalize(value) {
|
|
58
|
-
return path.resolve(value).replace(/\\/g, '/').toLowerCase();
|
|
59
|
-
}
|
|
60
|
-
function gitRoot(cwd) {
|
|
61
|
-
try {
|
|
62
|
-
const root = (0, child_process_1.execFileSync)('git', ['rev-parse', '--show-toplevel'], {
|
|
63
|
-
cwd,
|
|
64
|
-
encoding: 'utf8',
|
|
65
|
-
stdio: ['ignore', 'pipe', 'ignore'],
|
|
66
|
-
windowsHide: true,
|
|
67
|
-
}).trim();
|
|
68
|
-
return root ? normalize(root) : null;
|
|
69
|
-
}
|
|
70
|
-
catch {
|
|
71
|
-
return null;
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
function statePath(input, repoRoot) {
|
|
75
|
-
const home = homeDir();
|
|
76
|
-
const session = (input.session_id || '').trim();
|
|
77
|
-
if (!home || !session)
|
|
78
|
-
return null;
|
|
79
|
-
const key = crypto.createHash('sha256')
|
|
80
|
-
.update(`${session}\0${repoRoot}`)
|
|
81
|
-
.digest('hex')
|
|
82
|
-
.slice(0, 24);
|
|
83
|
-
return path.join(home, '.greprag', 'state', `codex-delivery-${key}.json`);
|
|
84
|
-
}
|
|
85
|
-
function readWindow(file) {
|
|
86
|
-
try {
|
|
87
|
-
return JSON.parse(fs.readFileSync(file, 'utf8'));
|
|
88
|
-
}
|
|
89
|
-
catch {
|
|
90
|
-
return null;
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
function writeWindow(file, window) {
|
|
94
|
-
try {
|
|
95
|
-
fs.mkdirSync(path.dirname(file), { recursive: true });
|
|
96
|
-
fs.writeFileSync(file, JSON.stringify(window, null, 2) + '\n');
|
|
97
|
-
return true;
|
|
98
|
-
}
|
|
99
|
-
catch {
|
|
100
|
-
return false;
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
function isShellCapableTool(input) {
|
|
104
|
-
const name = (input.tool_name || '').toLowerCase();
|
|
105
|
-
return /(?:^|[.:/_-])(bash|shell|exec|exec_command)$/.test(name);
|
|
106
|
-
}
|
|
107
|
-
function decodeQuoted(value) {
|
|
108
|
-
if (value.startsWith('"')) {
|
|
109
|
-
try {
|
|
110
|
-
return JSON.parse(value);
|
|
111
|
-
}
|
|
112
|
-
catch {
|
|
113
|
-
return null;
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
if (value.startsWith("'")) {
|
|
117
|
-
return value.slice(1, -1).replace(/\\'/g, "'").replace(/\\\\/g, '\\');
|
|
118
|
-
}
|
|
119
|
-
return null;
|
|
120
|
-
}
|
|
121
|
-
function embeddedCommands(code) {
|
|
122
|
-
const commands = [];
|
|
123
|
-
const re = /(?:command|cmd)\s*:\s*("(?:\\.|[^"])*"|'(?:\\.|[^'])*')/g;
|
|
124
|
-
for (const match of code.matchAll(re)) {
|
|
125
|
-
const decoded = decodeQuoted(match[1]);
|
|
126
|
-
if (decoded)
|
|
127
|
-
commands.push(decoded);
|
|
128
|
-
}
|
|
129
|
-
return commands;
|
|
130
|
-
}
|
|
131
|
-
function commandCandidates(input) {
|
|
132
|
-
if (!isShellCapableTool(input))
|
|
133
|
-
return [];
|
|
134
|
-
const toolInput = input.tool_input;
|
|
135
|
-
if (typeof toolInput === 'string')
|
|
136
|
-
return embeddedCommands(toolInput);
|
|
137
|
-
if (!toolInput || typeof toolInput !== 'object')
|
|
138
|
-
return [];
|
|
139
|
-
const candidates = [];
|
|
140
|
-
const fields = toolInput;
|
|
141
|
-
for (const key of ['command', 'cmd', 'script']) {
|
|
142
|
-
const value = fields[key];
|
|
143
|
-
if (typeof value === 'string')
|
|
144
|
-
candidates.push(value);
|
|
145
|
-
}
|
|
146
|
-
for (const key of ['code', 'input']) {
|
|
147
|
-
const value = fields[key];
|
|
148
|
-
if (typeof value === 'string')
|
|
149
|
-
candidates.push(...embeddedCommands(value));
|
|
150
|
-
}
|
|
151
|
-
return candidates;
|
|
152
|
-
}
|
|
153
|
-
function codexDeliveryTrigger(input) {
|
|
154
|
-
for (const command of commandCandidates(input)) {
|
|
155
|
-
const trigger = (0, coordinate_gate_1.classifyRiskyCommand)(command);
|
|
156
|
-
if (trigger)
|
|
157
|
-
return trigger;
|
|
158
|
-
}
|
|
159
|
-
return null;
|
|
160
|
-
}
|
|
161
|
-
function codexDeliveryCoordinationText(trigger) {
|
|
162
|
-
return `[DELIVERY NOW]
|
|
163
|
-
|
|
164
|
-
Before ${trigger.label}, call codex_app.list_threads unfiltered and keep only peers in the same repo. Use codex_app.send_message_to_thread once for peers with ready or overlapping work; include your branch/commit and ask only for ready commits or concrete blockers.
|
|
165
|
-
|
|
166
|
-
Delivery owner: rename this task \`DEPLOY: <existing title>\`; transfer the prefix on handoff.
|
|
167
|
-
|
|
168
|
-
Include ready handoffs and clear known blockers, then retry immediately. Do not call wait_threads, wait for replies, or send follow-ups. Missing replies and unfinished peer work do not block delivery.`;
|
|
169
|
-
}
|
|
170
|
-
/** First delivery action opens a 30-minute session/repo window and interrupts
|
|
171
|
-
* once. Later merge/push/deploy/release actions refresh the same window and
|
|
172
|
-
* proceed without another coordination round. */
|
|
173
|
-
function evaluateCodexDeliveryCoordination(input, now = Date.now()) {
|
|
174
|
-
if (input.hook_event_name !== 'PreToolUse')
|
|
175
|
-
return null;
|
|
176
|
-
const trigger = codexDeliveryTrigger(input);
|
|
177
|
-
if (!trigger)
|
|
178
|
-
return null;
|
|
179
|
-
const cwd = input.cwd || process.cwd();
|
|
180
|
-
const repoRoot = gitRoot(cwd);
|
|
181
|
-
if (!repoRoot)
|
|
182
|
-
return null;
|
|
183
|
-
const file = statePath(input, repoRoot);
|
|
184
|
-
if (!file)
|
|
185
|
-
return null;
|
|
186
|
-
const previous = readWindow(file);
|
|
187
|
-
const previousLastAction = previous ? Date.parse(previous.lastActionAt) : NaN;
|
|
188
|
-
if (previous
|
|
189
|
-
&& previous.repoRoot === repoRoot
|
|
190
|
-
&& Number.isFinite(previousLastAction)
|
|
191
|
-
&& now - previousLastAction < exports.DELIVERY_COORDINATION_WINDOW_MS) {
|
|
192
|
-
writeWindow(file, {
|
|
193
|
-
...previous,
|
|
194
|
-
lastActionAt: new Date(now).toISOString(),
|
|
195
|
-
});
|
|
196
|
-
return null;
|
|
197
|
-
}
|
|
198
|
-
const openedAt = new Date(now).toISOString();
|
|
199
|
-
if (!writeWindow(file, {
|
|
200
|
-
sessionId: input.session_id || '',
|
|
201
|
-
repoRoot,
|
|
202
|
-
openedAt,
|
|
203
|
-
lastActionAt: openedAt,
|
|
204
|
-
})) {
|
|
205
|
-
return null;
|
|
206
|
-
}
|
|
207
|
-
return {
|
|
208
|
-
hookSpecificOutput: {
|
|
209
|
-
hookEventName: 'PreToolUse',
|
|
210
|
-
additionalContext: codexDeliveryCoordinationText(trigger),
|
|
211
|
-
permissionDecision: 'deny',
|
|
212
|
-
permissionDecisionReason: `Run one same-repo coordination pass, then retry ${trigger.label} immediately; peer replies are not required.`,
|
|
213
|
-
},
|
|
214
|
-
};
|
|
215
|
-
}
|