greprag 5.78.1 → 5.78.6
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/README.md +7 -9
- package/dist/codex-chip-hooks.js +2 -2
- package/dist/commands/codex-chip/prompt.js +1 -1
- package/dist/commands/codex-doctor.js +1 -1
- package/dist/commands/codex-startup.js +1 -1
- package/dist/commands/codex.js +1 -1
- package/dist/commands/collision-check.js +3 -3
- package/dist/commands/delivery-reminder.js +6 -5
- package/dist/commands/fix.js +1 -1
- package/dist/commands/init.js +30 -108
- package/dist/commands/mechanic-spawn.js +7 -7
- package/dist/commands/mechanic.js +1 -1
- package/dist/commands/opencode-chip-mission.js +1 -1
- package/dist/commands/os-primer-reminder.js +1 -1
- package/dist/commands/reminder-registry.js +0 -2
- package/dist/delivery-config.js +2 -2
- package/dist/hook.js +3 -70
- package/dist/index.js +11 -13
- package/dist/opencode-plugin.bundle.js +8 -151
- package/dist/procedure.js +1 -1
- package/package.json +2 -2
- package/skill/greprag/SKILL.md +14 -7
- package/skill/greprag/docs/codex-chip.md +2 -2
- package/skill/greprag/docs/setup.md +6 -6
- package/skill/mechanic/SKILL.md +6 -6
- package/skill/templates/chip-spawn.md +1 -1
- package/skill/templates/codex-chip-spawn.md +4 -4
- package/dist/commands/collision-reminder.js +0 -39
- package/dist/commands/coordinate-gate.js +0 -232
|
@@ -1,232 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/** Coordinate-GATE — the high-value half of the cross-session coordination reflex.
|
|
3
|
-
* Fires at the moment of a risky SHARED-STATE action (git merge / push / deploy)
|
|
4
|
-
* and, if another live session is working in THIS repo, compels the agent to
|
|
5
|
-
* coordinate with that peer BEFORE the irreversible action runs. Automates the
|
|
6
|
-
* manual "notice the peer, message them, then merge" handshake.
|
|
7
|
-
*
|
|
8
|
-
* SEAM (forward-compat — agreed with ec71d875/36ef8cb8): the EVAL+message
|
|
9
|
-
* (runCoordinateGate) is decoupled from the trigger SOURCE. The PreToolUse
|
|
10
|
-
* adapter (triggerFromPreToolUse) is the only piece that knows the tool-call
|
|
11
|
-
* shape; it produces a source-agnostic CoordinateTrigger. The eval does a FRESH
|
|
12
|
-
* watcher read and builds the directive without ever seeing the source. The
|
|
13
|
-
* ddb7dcc8 ingress-trigger bridge will add a SECOND source (message-ingress /
|
|
14
|
-
* stress-threshold / registry-change) that produces its own CoordinateTrigger
|
|
15
|
-
* and calls this same eval — purely additive, no refactor of the gate.
|
|
16
|
-
*
|
|
17
|
-
* WHY NOT A guard.ts MATCHSET RULE: the matchset dispatcher is local-only/pure
|
|
18
|
-
* (no network on the hot path — the D5 "ad-blocker" model) and injects STATIC
|
|
19
|
-
* rule text. This gate needs a FRESH `inbox watchers` network read at fire time
|
|
20
|
-
* (a stale roster at merge is the exact failure it prevents), which a static
|
|
21
|
-
* matchset cannot express. So it is a hand-wired PreToolUse hook like
|
|
22
|
-
* collision-check — the documented fallback in the chip spec. The bridge's
|
|
23
|
-
* shared eval will likewise need this off-hot-path read, so this module is its
|
|
24
|
-
* home too. docs/collision-schematic.md, docs/harness-control-point-matrix.md
|
|
25
|
-
*
|
|
26
|
-
* NO DEDUP: every fire does a fresh read. Unlike the SessionStart roster (which
|
|
27
|
-
* dedups to stay quiet), the merge gate must reflect live truth each time.
|
|
28
|
-
*
|
|
29
|
-
* EFFECT is the adapter's choice, not the eval's: Claude/OpenCode inject the
|
|
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
|
-
*
|
|
35
|
-
* Shared-file Write was CONSIDERED (chip spec) but deferred: classifying a
|
|
36
|
-
* write as "shared" is ambiguous, and a fresh network read on every Write/Edit
|
|
37
|
-
* is too costly/noisy for the value — merge/push/deploy is where irreversible
|
|
38
|
-
* shared-state mutation actually happens. The eval is ready for a future Write
|
|
39
|
-
* adapter; only a new triggerFrom* + a `Write|Edit` matcher would be needed. */
|
|
40
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
41
|
-
exports.hasGitSubcommand = hasGitSubcommand;
|
|
42
|
-
exports.classifyRiskyCommand = classifyRiskyCommand;
|
|
43
|
-
exports.triggerFromPreToolUse = triggerFromPreToolUse;
|
|
44
|
-
exports.buildCoordinateDirective = buildCoordinateDirective;
|
|
45
|
-
exports.resolveCollisionPeers = resolveCollisionPeers;
|
|
46
|
-
exports.runCoordinateGate = runCoordinateGate;
|
|
47
|
-
const collision_check_1 = require("./collision-check");
|
|
48
|
-
/** Risky shared-state command signatures. Each segment of a (possibly chained)
|
|
49
|
-
* Bash command is tested against these. SPECIFIC to the Bash/PreToolUse source. */
|
|
50
|
-
const RISKY_PATTERNS = [
|
|
51
|
-
{ kind: 'merge', label: 'gh pr merge', re: /^gh\s+pr\s+merge\b/ },
|
|
52
|
-
{ kind: 'deploy', label: 'wrangler deploy', re: /^(?:npx\s+)?wrangler\s+deploy\b/ },
|
|
53
|
-
{ kind: 'deploy', label: 'npm run deploy', re: /^npm\s+run\s+deploy\b/ },
|
|
54
|
-
{ kind: 'deploy', label: 'npm publish', re: /^npm\s+publish\b/ },
|
|
55
|
-
{ kind: 'deploy', label: 'gh release create', re: /^gh\s+release\s+create\b/ },
|
|
56
|
-
];
|
|
57
|
-
/** Split a shell command on executable separators so `cd x && git push` is
|
|
58
|
-
* caught, while regex/search patterns like `"before; git push; after"` stay a
|
|
59
|
-
* single argument. */
|
|
60
|
-
function commandSegments(command) {
|
|
61
|
-
const segments = [];
|
|
62
|
-
let current = '';
|
|
63
|
-
let quote = null;
|
|
64
|
-
let escaped = false;
|
|
65
|
-
const flush = () => {
|
|
66
|
-
const trimmed = current.trim();
|
|
67
|
-
if (trimmed)
|
|
68
|
-
segments.push(trimmed);
|
|
69
|
-
current = '';
|
|
70
|
-
};
|
|
71
|
-
for (let i = 0; i < command.length; i++) {
|
|
72
|
-
const ch = command[i];
|
|
73
|
-
const next = command[i + 1];
|
|
74
|
-
if (escaped) {
|
|
75
|
-
current += ch;
|
|
76
|
-
escaped = false;
|
|
77
|
-
continue;
|
|
78
|
-
}
|
|
79
|
-
if (ch === '\\' && quote !== "'") {
|
|
80
|
-
current += ch;
|
|
81
|
-
escaped = true;
|
|
82
|
-
continue;
|
|
83
|
-
}
|
|
84
|
-
if (quote) {
|
|
85
|
-
current += ch;
|
|
86
|
-
if (ch === quote)
|
|
87
|
-
quote = null;
|
|
88
|
-
continue;
|
|
89
|
-
}
|
|
90
|
-
if (ch === '"' || ch === "'") {
|
|
91
|
-
quote = ch;
|
|
92
|
-
current += ch;
|
|
93
|
-
continue;
|
|
94
|
-
}
|
|
95
|
-
if (ch === '\n' || ch === ';' || ch === '|') {
|
|
96
|
-
flush();
|
|
97
|
-
if ((ch === '|' && next === '|'))
|
|
98
|
-
i++;
|
|
99
|
-
continue;
|
|
100
|
-
}
|
|
101
|
-
if (ch === '&' && next === '&') {
|
|
102
|
-
flush();
|
|
103
|
-
i++;
|
|
104
|
-
continue;
|
|
105
|
-
}
|
|
106
|
-
current += ch;
|
|
107
|
-
}
|
|
108
|
-
flush();
|
|
109
|
-
return segments;
|
|
110
|
-
}
|
|
111
|
-
/** Parse enough shell words to locate a git subcommand after global options.
|
|
112
|
-
* Codex worktrees routinely use `git -C <main> merge ...`; matching only
|
|
113
|
-
* `^git merge` left the most common Codex landing shape outside the gate. */
|
|
114
|
-
function shellWords(segment) {
|
|
115
|
-
const matches = segment.match(/"(?:\\.|[^"])*"|'[^']*'|[^\s]+/g) || [];
|
|
116
|
-
return matches.map(word => {
|
|
117
|
-
if ((word.startsWith('"') && word.endsWith('"'))
|
|
118
|
-
|| (word.startsWith("'") && word.endsWith("'"))) {
|
|
119
|
-
return word.slice(1, -1);
|
|
120
|
-
}
|
|
121
|
-
return word;
|
|
122
|
-
});
|
|
123
|
-
}
|
|
124
|
-
function classifyGit(tokens) {
|
|
125
|
-
if (tokens[0] !== 'git')
|
|
126
|
-
return null;
|
|
127
|
-
let i = 1;
|
|
128
|
-
const optionsWithValue = new Set([
|
|
129
|
-
'-C', '-c', '--exec-path', '--git-dir', '--work-tree', '--namespace', '--super-prefix', '--config-env',
|
|
130
|
-
]);
|
|
131
|
-
while (i < tokens.length && tokens[i].startsWith('-')) {
|
|
132
|
-
const option = tokens[i++];
|
|
133
|
-
if (optionsWithValue.has(option) && i < tokens.length)
|
|
134
|
-
i++;
|
|
135
|
-
}
|
|
136
|
-
const subcommand = tokens[i];
|
|
137
|
-
if (subcommand === 'merge')
|
|
138
|
-
return { kind: 'merge', label: 'git merge' };
|
|
139
|
-
if (subcommand === 'rebase')
|
|
140
|
-
return { kind: 'merge', label: 'git rebase' };
|
|
141
|
-
if (subcommand === 'push')
|
|
142
|
-
return { kind: 'push', label: 'git push' };
|
|
143
|
-
return null;
|
|
144
|
-
}
|
|
145
|
-
/** True when any executable command segment invokes the requested Git
|
|
146
|
-
* subcommand, including `git -C <worktree> <subcommand>`. Exported so lifecycle
|
|
147
|
-
* hooks can key off agent-generated Git actions instead of user prompt words. */
|
|
148
|
-
function hasGitSubcommand(command, expected) {
|
|
149
|
-
if (!command || !expected)
|
|
150
|
-
return false;
|
|
151
|
-
for (const seg of commandSegments(command)) {
|
|
152
|
-
const tokens = shellWords(seg);
|
|
153
|
-
if (tokens[0] !== 'git')
|
|
154
|
-
continue;
|
|
155
|
-
let i = 1;
|
|
156
|
-
const optionsWithValue = new Set([
|
|
157
|
-
'-C', '-c', '--exec-path', '--git-dir', '--work-tree', '--namespace', '--super-prefix', '--config-env',
|
|
158
|
-
]);
|
|
159
|
-
while (i < tokens.length && tokens[i].startsWith('-')) {
|
|
160
|
-
const option = tokens[i++];
|
|
161
|
-
if (optionsWithValue.has(option) && i < tokens.length)
|
|
162
|
-
i++;
|
|
163
|
-
}
|
|
164
|
-
if (tokens[i] === expected)
|
|
165
|
-
return true;
|
|
166
|
-
}
|
|
167
|
-
return false;
|
|
168
|
-
}
|
|
169
|
-
/** Classify a Bash command into a risky-action trigger, or null. PURE. Matches
|
|
170
|
-
* the FIRST risky segment (a chained command fires on whichever risky verb
|
|
171
|
-
* appears first). */
|
|
172
|
-
function classifyRiskyCommand(command) {
|
|
173
|
-
if (!command)
|
|
174
|
-
return null;
|
|
175
|
-
for (const seg of commandSegments(command)) {
|
|
176
|
-
const git = classifyGit(shellWords(seg));
|
|
177
|
-
if (git)
|
|
178
|
-
return git;
|
|
179
|
-
for (const p of RISKY_PATTERNS) {
|
|
180
|
-
if (p.re.test(seg))
|
|
181
|
-
return { kind: p.kind, label: p.label };
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
return null;
|
|
185
|
-
}
|
|
186
|
-
/** PreToolUse adapter: extract a CoordinateTrigger from a tool call, or null.
|
|
187
|
-
* SPECIFIC to the PreToolUse event shape — the only source-aware piece. Only
|
|
188
|
-
* Bash calls carry a risky command; everything else returns null (cheap: the
|
|
189
|
-
* hook never reaches the network for a non-risky call). */
|
|
190
|
-
function triggerFromPreToolUse(toolName, toolInput) {
|
|
191
|
-
if (toolName !== 'Bash')
|
|
192
|
-
return null;
|
|
193
|
-
const command = typeof toolInput.command === 'string' ? toolInput.command : '';
|
|
194
|
-
return classifyRiskyCommand(command);
|
|
195
|
-
}
|
|
196
|
-
/** The LOUD coordinate directive — names the action + the live same-repo peers
|
|
197
|
-
* and tells the agent to message them BEFORE proceeding. PURE, source-agnostic
|
|
198
|
-
* (takes a CoordinateTrigger, not a PreToolUse event). */
|
|
199
|
-
function buildCoordinateDirective(trigger, peers, myShort, alias) {
|
|
200
|
-
const handle = alias || '<handle>';
|
|
201
|
-
const plural = peers.length === 1 ? '' : 's';
|
|
202
|
-
const list = peers.map(p => p.short).join(', ');
|
|
203
|
-
return (`COORDINATE before ${trigger.label}: ${peers.length} peer${plural} live in this repo (${list}). `
|
|
204
|
-
+ `Ping before proceeding. Codex peers: use codex_app.list_threads and codex_app.send_message_to_thread. `
|
|
205
|
-
+ `GrepRAG watcher/cross-harness peers: greprag send "heads up, about to ${trigger.label}" `
|
|
206
|
-
+ `--to ${handle}@greprag.com/<8hex> --from-session ${myShort}`);
|
|
207
|
-
}
|
|
208
|
-
/** FRESH watcher read → the same-repo peers live right now (the I/O half, kept out
|
|
209
|
-
* of the pure module). NO dedup, NO local state: a fresh read every call. Empty on
|
|
210
|
-
* any failure / no peer (fail-open). The collision Match-on-command module
|
|
211
|
-
* (collision-reminder.ts) calls this in the hook, then detects purely on the result. */
|
|
212
|
-
async function resolveCollisionPeers(opts) {
|
|
213
|
-
try {
|
|
214
|
-
const watchers = await (0, collision_check_1.fetchTenantWatchers)(opts.apiUrl, opts.apiKey);
|
|
215
|
-
if (watchers.length === 0)
|
|
216
|
-
return [];
|
|
217
|
-
return (0, collision_check_1.detectCollisions)(opts.short, opts.projectId, opts.projectName, watchers);
|
|
218
|
-
}
|
|
219
|
-
catch {
|
|
220
|
-
return [];
|
|
221
|
-
}
|
|
222
|
-
}
|
|
223
|
-
/** Source-agnostic eval+message. Given a trigger from ANY source, resolve live
|
|
224
|
-
* same-repo peers and return the LOUD directive — or null if none. Retained for
|
|
225
|
-
* the existing PreToolUse path + tests; the registry now reaches the same result
|
|
226
|
-
* via resolveCollisionPeers + the collision module. */
|
|
227
|
-
async function runCoordinateGate(trigger, opts) {
|
|
228
|
-
const peers = await resolveCollisionPeers(opts);
|
|
229
|
-
if (peers.length === 0)
|
|
230
|
-
return null;
|
|
231
|
-
return buildCoordinateDirective(trigger, peers, opts.short, opts.alias);
|
|
232
|
-
}
|