greprag 5.68.0 → 5.69.2
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/capture-manifest.d.ts +5 -2
- package/dist/capture-manifest.js +9 -5
- package/dist/capture-manifest.js.map +1 -1
- package/dist/commands/codex-coordinate.d.ts +46 -0
- package/dist/commands/codex-coordinate.js +257 -0
- package/dist/commands/codex-coordinate.js.map +1 -0
- package/dist/commands/collision-check.d.ts +1 -1
- package/dist/commands/collision-check.js +10 -3
- package/dist/commands/collision-check.js.map +1 -1
- package/dist/commands/coordinate-gate.d.ts +5 -4
- package/dist/commands/coordinate-gate.js +43 -8
- package/dist/commands/coordinate-gate.js.map +1 -1
- package/dist/commands/inbox-primer-reminder.js +3 -3
- package/dist/commands/inbox-primer-reminder.js.map +1 -1
- package/dist/commands/init.js +21 -3
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/mechanic-spawn.js +1 -1
- package/dist/commands/mechanic-spawn.js.map +1 -1
- package/dist/commands/status.d.ts +1 -0
- package/dist/commands/status.js +3 -1
- package/dist/commands/status.js.map +1 -1
- package/dist/hook.js +77 -77
- package/dist/hook.js.map +1 -1
- package/dist/index.js +17 -7
- package/dist/index.js.map +1 -1
- package/dist/inline-atom-episode.d.ts +72 -0
- package/dist/inline-atom-episode.js +380 -0
- package/dist/inline-atom-episode.js.map +1 -0
- package/dist/inline-atom-hook.d.ts +19 -0
- package/dist/inline-atom-hook.js +89 -0
- package/dist/inline-atom-hook.js.map +1 -0
- package/dist/inline-atom.d.ts +13 -13
- package/dist/inline-atom.js +15 -62
- package/dist/inline-atom.js.map +1 -1
- package/dist/opencode-plugin.bundle.js +44 -9
- package/package.json +1 -1
- package/skill/commander/SKILL.md +2 -2
- package/skill/greprag/SKILL.md +2 -2
- package/skill/templates/codex-chip-spawn.md +1 -1
package/dist/hook.js
CHANGED
|
@@ -106,11 +106,13 @@ const archive_1 = require("./commands/archive");
|
|
|
106
106
|
// repo (cloud watcher registry) and inject a coordinate-now directive. All real
|
|
107
107
|
// logic lives in ./commands/collision-check. docs/schematic-triggers.md
|
|
108
108
|
const collision_check_1 = require("./commands/collision-check");
|
|
109
|
-
// Coordinate-GATE (PreToolUse) — on
|
|
110
|
-
//
|
|
111
|
-
//
|
|
112
|
-
//
|
|
109
|
+
// Coordinate-GATE (PreToolUse) — on risky shared-state actions, Claude/OpenCode
|
|
110
|
+
// consult the watcher registry; Codex additionally requires committed,
|
|
111
|
+
// artifact-bound native/cross-harness conferral evidence. ask is unsupported by
|
|
112
|
+
// Codex, so its adapter uses deny + agent-correctable evidence. adr:
|
|
113
|
+
// adr/codex-coordinate-gate.md
|
|
113
114
|
const coordinate_gate_1 = require("./commands/coordinate-gate");
|
|
115
|
+
const codex_coordinate_1 = require("./commands/codex-coordinate");
|
|
114
116
|
// (The asyncRewake idle-wake poll was REVERTED 2026-06-23 — falsified: a detached
|
|
115
117
|
// process's exit-2 has no harness event to attach to in true deep idle, so it never
|
|
116
118
|
// woke an idle session. Only a live Monitor task delivers to idle. adr: adr/monitor-
|
|
@@ -123,11 +125,11 @@ const inbox_drain_1 = require("./commands/inbox-drain");
|
|
|
123
125
|
const procedure_1 = require("./procedure");
|
|
124
126
|
const ship_through_gate_1 = require("./commands/ship-through-gate");
|
|
125
127
|
// Procedure System LEARN leg (docs/procedure-system.md §V1 LEARN-leg build
|
|
126
|
-
// spec): the
|
|
128
|
+
// spec): the episode watch — opened at UserPromptSubmit (procedureCheck), observed
|
|
127
129
|
// per turn by the Stop hook (observeProcedureTurn), closed by negative
|
|
128
130
|
// continuity, distilled server-side, transitions applied to the local store.
|
|
129
131
|
const procedure_watch_1 = require("./procedure-watch");
|
|
130
|
-
const
|
|
132
|
+
const inline_atom_hook_1 = require("./inline-atom-hook");
|
|
131
133
|
const skill_landing_1 = require("./skill-landing");
|
|
132
134
|
const skill_mirror_client_1 = require("./skill-mirror-client");
|
|
133
135
|
const equipped_loadouts_cache_1 = require("./equipped-loadouts-cache");
|
|
@@ -950,42 +952,6 @@ async function observeProcedureTurn(cfg, anchor, turn, cwd, redaction) {
|
|
|
950
952
|
}
|
|
951
953
|
(0, procedure_watch_1.writeProcedureWatch)(anchor.projectId, next);
|
|
952
954
|
}
|
|
953
|
-
async function observeInlineAtoms(cfg, anchor, turn, sessionId, userPrompt, agentResponse) {
|
|
954
|
-
const atoms = (0, inline_atom_1.mergeInlineAtoms)(userPrompt, agentResponse);
|
|
955
|
-
if (atoms.length === 0)
|
|
956
|
-
return;
|
|
957
|
-
// Provider policy:
|
|
958
|
-
// - auto/greprag: portable command-hook path, costed to GrepRAG Flash-Lite.
|
|
959
|
-
// - harness: reserved for Claude Code's native Haiku prompt-hook bridge. Until
|
|
960
|
-
// that bridge can write the same local state file, fall back to GrepRAG.
|
|
961
|
-
// - off: disable the detector.
|
|
962
|
-
const provider = (process.env.GREPRAG_INLINE_ATOM_JUDGE || 'auto').toLowerCase();
|
|
963
|
-
if (provider === 'off')
|
|
964
|
-
return;
|
|
965
|
-
let verdicts = [];
|
|
966
|
-
try {
|
|
967
|
-
const res = await fetch(`${cfg.apiUrl}/v1/inline-atom/${anchor.projectId}/judge`, {
|
|
968
|
-
method: 'POST',
|
|
969
|
-
headers: { 'Authorization': `Bearer ${cfg.apiKey}`, 'Content-Type': 'application/json' },
|
|
970
|
-
body: JSON.stringify({
|
|
971
|
-
projectName: anchor.projectName,
|
|
972
|
-
user: userPrompt,
|
|
973
|
-
assistant: agentResponse,
|
|
974
|
-
atoms,
|
|
975
|
-
provider: provider === 'harness' ? 'greprag-fallback' : 'greprag',
|
|
976
|
-
}),
|
|
977
|
-
});
|
|
978
|
-
if (res.ok) {
|
|
979
|
-
const data = await res.json();
|
|
980
|
-
verdicts = Array.isArray(data.verdicts) ? data.verdicts : [];
|
|
981
|
-
}
|
|
982
|
-
}
|
|
983
|
-
catch { /* detector is best-effort */ }
|
|
984
|
-
(0, inline_atom_1.promoteInlineAtomResolutions)(anchor.projectId, (0, session_id_1.truncateSessionId)(sessionId) || null, verdicts);
|
|
985
|
-
if (verdicts.some(v => v.label === 'friction')) {
|
|
986
|
-
(0, inline_atom_1.writeInlineAtomFriction)(anchor.projectId, (0, session_id_1.truncateSessionId)(sessionId) || null, verdicts);
|
|
987
|
-
}
|
|
988
|
-
}
|
|
989
955
|
/** SessionStart fetch: the live enrichment-health verdict (fix c2eb8777).
|
|
990
956
|
* Null = healthy OR unreachable — the outage announce only fires on a
|
|
991
957
|
* POSITIVE probe failure, so an API blip never cries wolf. The worker
|
|
@@ -1249,7 +1215,7 @@ async function store(input, source = 'claude-code') {
|
|
|
1249
1215
|
}
|
|
1250
1216
|
catch { /* best-effort — a docptr outage never fails the Stop hook */ }
|
|
1251
1217
|
}
|
|
1252
|
-
// Procedure System
|
|
1218
|
+
// Procedure System episode observer (docs/procedure-system.md V1 LEARN leg):
|
|
1253
1219
|
// gated on "a watch file exists" — zero cost when no watch is open. One
|
|
1254
1220
|
// synchronous flash-lite continuity call per observed turn; close/watchdog
|
|
1255
1221
|
// logic is pure in procedure-watch.ts. Best-effort, never throws.
|
|
@@ -1259,12 +1225,11 @@ async function store(input, source = 'claude-code') {
|
|
|
1259
1225
|
}
|
|
1260
1226
|
catch { /* fail-open — a procedure outage never fails the Stop hook */ }
|
|
1261
1227
|
}
|
|
1262
|
-
// Inline-Atom
|
|
1263
|
-
//
|
|
1264
|
-
//
|
|
1265
|
-
// directive. Best-effort, never blocks capture.
|
|
1228
|
+
// Inline-Atom Episode Capture (docs/capture-system.md): new backtick
|
|
1229
|
+
// candidates, active episodes, and replay receipts share one Flash-Lite
|
|
1230
|
+
// observation call. Closed episodes alone reach the Flash distiller.
|
|
1266
1231
|
try {
|
|
1267
|
-
await observeInlineAtoms(cfg, anchor,
|
|
1232
|
+
await (0, inline_atom_hook_1.observeInlineAtoms)(cfg, anchor, input.session_id, userPrompt, agentResponse, toolCalls);
|
|
1268
1233
|
}
|
|
1269
1234
|
catch { /* fail-open — an inline-atom miss never fails the Stop hook */ }
|
|
1270
1235
|
// Skill mirror (docs/load-system.md Tier 3): a skill-load turn shadows that
|
|
@@ -1929,7 +1894,7 @@ async function notify(input, source = 'claude-code', chipContext) {
|
|
|
1929
1894
|
excludeMessageIds: liveMessageId ? [liveMessageId] : [],
|
|
1930
1895
|
});
|
|
1931
1896
|
const reminders = await injectReminders(input, cfg, short, 'codex');
|
|
1932
|
-
const inlineAtoms = buildPendingInlineAtomContext(input, short);
|
|
1897
|
+
const inlineAtoms = (0, inline_atom_hook_1.buildPendingInlineAtomContext)(input, short);
|
|
1933
1898
|
const parts = [duplicateDelegation, chipContext, context, reminders, inlineAtoms].filter((p) => !!p);
|
|
1934
1899
|
if (parts.length)
|
|
1935
1900
|
writeAdditionalContext('UserPromptSubmit', parts.join('\n\n'));
|
|
@@ -1941,24 +1906,11 @@ async function notify(input, source = 'claude-code', chipContext) {
|
|
|
1941
1906
|
// subcommand reaching the operator's settings. Fires whatever's deficient (stacking),
|
|
1942
1907
|
// and auto-silences each module the instant its deficiency resolves.
|
|
1943
1908
|
const reminders = await injectReminders(input, cfg, short);
|
|
1944
|
-
const inlineAtoms = buildPendingInlineAtomContext(input, short);
|
|
1909
|
+
const inlineAtoms = (0, inline_atom_hook_1.buildPendingInlineAtomContext)(input, short);
|
|
1945
1910
|
const parts = [reminders, inlineAtoms].filter((p) => !!p);
|
|
1946
1911
|
if (parts.length)
|
|
1947
1912
|
writeAdditionalContext('UserPromptSubmit', parts.join('\n\n'));
|
|
1948
1913
|
}
|
|
1949
|
-
function buildPendingInlineAtomContext(input, short) {
|
|
1950
|
-
try {
|
|
1951
|
-
const anchor = (0, project_anchor_1.readAnchor)(input.cwd || process.cwd());
|
|
1952
|
-
if (!anchor.projectId)
|
|
1953
|
-
return null;
|
|
1954
|
-
const records = (0, inline_atom_1.readAndClearInlineAtomFriction)(anchor.projectId, short);
|
|
1955
|
-
const prompt = typeof input.prompt === 'string' ? input.prompt : '';
|
|
1956
|
-
return (0, inline_atom_1.buildInlineAtomContext)({ projectId: anchor.projectId, prompt, records });
|
|
1957
|
-
}
|
|
1958
|
-
catch {
|
|
1959
|
-
return null;
|
|
1960
|
-
}
|
|
1961
|
-
}
|
|
1962
1914
|
/** Has the operator hit the Mechanic kill switch (`mechanic off` → the D8 panic
|
|
1963
1915
|
* switch file the guard dispatcher also checks first)? When set, the active-
|
|
1964
1916
|
* Mechanic pair (SessionStart announce + per-turn friction reminder) stays quiet,
|
|
@@ -2356,17 +2308,16 @@ function stateUpdate(input) {
|
|
|
2356
2308
|
}
|
|
2357
2309
|
catch { /* state update is best-effort — never block the turn */ }
|
|
2358
2310
|
}
|
|
2359
|
-
/** PreToolUse coordinate-GATE
|
|
2360
|
-
*
|
|
2361
|
-
*
|
|
2362
|
-
*
|
|
2363
|
-
* live peers and tells the agent to message them first. Fires the network read
|
|
2311
|
+
/** PreToolUse coordinate-GATE. On a risky shared-state action (git merge / push /
|
|
2312
|
+
* deploy), does a FRESH inbox-watchers read. Claude/OpenCode inject the roster;
|
|
2313
|
+
* Codex denies until committed, artifact-bound conferral evidence exists.
|
|
2314
|
+
* Both paths name live peers and tell the agent to message them first. Fires the network read
|
|
2364
2315
|
* ONLY for risky commands — a non-risky Bash call is classified locally and
|
|
2365
2316
|
* exits silent, no network. NO dedup: a fresh read every fire (a stale roster at
|
|
2366
2317
|
* merge is the exact failure this prevents). Reads only the watcher registry (no
|
|
2367
|
-
* inbox content) — no eavesdrop surface.
|
|
2368
|
-
* action
|
|
2369
|
-
async function coordinateGate(input) {
|
|
2318
|
+
* inbox content) — no eavesdrop surface. Watcher misses fail quiet; Codex still
|
|
2319
|
+
* requires its local artifact/action attestation. docs/collision-schematic.md */
|
|
2320
|
+
async function coordinateGate(input, codex = false) {
|
|
2370
2321
|
const cwd = input.cwd || process.cwd();
|
|
2371
2322
|
const cfg = getConfig(cwd);
|
|
2372
2323
|
if (!cfg.enabled || !cfg.apiKey)
|
|
@@ -2388,6 +2339,28 @@ async function coordinateGate(input) {
|
|
|
2388
2339
|
}
|
|
2389
2340
|
if (!anchor.projectId)
|
|
2390
2341
|
return; // unanchored → nothing to match
|
|
2342
|
+
// First Codex denial is local. Only an already-attested retry pays for the
|
|
2343
|
+
// fresh watcher read, so API latency cannot bypass commit-first enforcement.
|
|
2344
|
+
if (codex) {
|
|
2345
|
+
const local = (0, codex_coordinate_1.evaluateCodexCoordinationGate)({
|
|
2346
|
+
projectId: anchor.projectId,
|
|
2347
|
+
sessionId: short,
|
|
2348
|
+
cwd,
|
|
2349
|
+
trigger,
|
|
2350
|
+
command: typeof toolInput.command === 'string' ? toolInput.command : '',
|
|
2351
|
+
watcherPeers: [],
|
|
2352
|
+
});
|
|
2353
|
+
if (!local.ready) {
|
|
2354
|
+
process.stdout.write(JSON.stringify({
|
|
2355
|
+
hookSpecificOutput: {
|
|
2356
|
+
hookEventName: input.hook_event_name || 'PreToolUse',
|
|
2357
|
+
permissionDecision: 'deny',
|
|
2358
|
+
permissionDecisionReason: local.reason,
|
|
2359
|
+
},
|
|
2360
|
+
}) + '\n');
|
|
2361
|
+
return;
|
|
2362
|
+
}
|
|
2363
|
+
}
|
|
2391
2364
|
// I/O stays in the hook: fresh peer read off the hot path → env.collisionPeers.
|
|
2392
2365
|
const peers = await (0, coordinate_gate_1.resolveCollisionPeers)({
|
|
2393
2366
|
short,
|
|
@@ -2397,6 +2370,26 @@ async function coordinateGate(input) {
|
|
|
2397
2370
|
apiKey: cfg.apiKey,
|
|
2398
2371
|
alias: (0, session_id_1.readIdentityAlias)(),
|
|
2399
2372
|
});
|
|
2373
|
+
if (codex) {
|
|
2374
|
+
const current = (0, codex_coordinate_1.evaluateCodexCoordinationGate)({
|
|
2375
|
+
projectId: anchor.projectId,
|
|
2376
|
+
sessionId: short,
|
|
2377
|
+
cwd,
|
|
2378
|
+
trigger,
|
|
2379
|
+
command: typeof toolInput.command === 'string' ? toolInput.command : '',
|
|
2380
|
+
watcherPeers: peers.map(peer => peer.short),
|
|
2381
|
+
});
|
|
2382
|
+
if (!current.ready) {
|
|
2383
|
+
process.stdout.write(JSON.stringify({
|
|
2384
|
+
hookSpecificOutput: {
|
|
2385
|
+
hookEventName: input.hook_event_name || 'PreToolUse',
|
|
2386
|
+
permissionDecision: 'deny',
|
|
2387
|
+
permissionDecisionReason: current.reason,
|
|
2388
|
+
},
|
|
2389
|
+
}) + '\n');
|
|
2390
|
+
return;
|
|
2391
|
+
}
|
|
2392
|
+
}
|
|
2400
2393
|
// ship-through: review is a run prerequisite, not a human permission prompt.
|
|
2401
2394
|
// It applies to routine merge/deploy only; standalone push keeps its own gate.
|
|
2402
2395
|
try {
|
|
@@ -2434,9 +2427,10 @@ async function coordinateGate(input) {
|
|
|
2434
2427
|
const fired = (0, reminder_registry_1.collectReminders)(env, (0, reminder_registry_1.commandModules)());
|
|
2435
2428
|
if (!fired.length)
|
|
2436
2429
|
return;
|
|
2437
|
-
//
|
|
2430
|
+
// Non-Codex effect: inject as additionalContext — advisory heads-up, NO permission pause.
|
|
2438
2431
|
// `ask` was too intrusive (prompted on every git op while peers were live); inject
|
|
2439
|
-
// keeps the agent aware without a manual-allow.
|
|
2432
|
+
// keeps the agent aware without a manual-allow. Codex uses the evidence gate above.
|
|
2433
|
+
// adr: adr/codex-coordinate-gate.md
|
|
2440
2434
|
process.stdout.write(JSON.stringify({
|
|
2441
2435
|
hookSpecificOutput: {
|
|
2442
2436
|
hookEventName: input.hook_event_name || 'PreToolUse',
|
|
@@ -2466,7 +2460,7 @@ async function main() {
|
|
|
2466
2460
|
const subcommand = process.argv[2];
|
|
2467
2461
|
const validSubs = new Set([
|
|
2468
2462
|
'store', 'recap', 'recompact', 'notify', 'mail', 'friction-reminder', 'session-id', 'pre-spawn-check', 'armcheck',
|
|
2469
|
-
'collision-check', 'drain', 'coordinate-gate', 'procedure-check',
|
|
2463
|
+
'collision-check', 'drain', 'coordinate-gate', 'codex-coordinate-gate', 'procedure-check',
|
|
2470
2464
|
'guard', 'guard-refresh', 'guard-flush',
|
|
2471
2465
|
'context-probe', 'context-check', 'crush-wrap',
|
|
2472
2466
|
'pre-compact', 'archive-pointer',
|
|
@@ -2475,7 +2469,7 @@ async function main() {
|
|
|
2475
2469
|
'codex-chip-hook',
|
|
2476
2470
|
]);
|
|
2477
2471
|
if (!validSubs.has(subcommand)) {
|
|
2478
|
-
process.stderr.write(`Usage: greprag-hook <store|recap|recompact|notify|mail|friction-reminder|procedure-check|session-id|pre-spawn-check|armcheck|collision-check|drain|coordinate-gate|guard|guard-refresh|guard-flush|context-probe|context-check|crush-wrap|pre-compact|archive-pointer|codex-store|codex-notify|codex-inbox|codex-recap|codex-permission-context|codex-subagent-start|codex-chip-hook>\n`);
|
|
2472
|
+
process.stderr.write(`Usage: greprag-hook <store|recap|recompact|notify|mail|friction-reminder|procedure-check|session-id|pre-spawn-check|armcheck|collision-check|drain|coordinate-gate|codex-coordinate-gate|guard|guard-refresh|guard-flush|context-probe|context-check|crush-wrap|pre-compact|archive-pointer|codex-store|codex-notify|codex-inbox|codex-recap|codex-permission-context|codex-subagent-start|codex-chip-hook>\n`);
|
|
2479
2473
|
process.exit(1);
|
|
2480
2474
|
}
|
|
2481
2475
|
let input = {};
|
|
@@ -2578,11 +2572,17 @@ async function main() {
|
|
|
2578
2572
|
await drain(input);
|
|
2579
2573
|
}
|
|
2580
2574
|
else if (subcommand === 'coordinate-gate') {
|
|
2581
|
-
// PreToolUse[Bash] —
|
|
2582
|
-
//
|
|
2575
|
+
// Claude/OpenCode PreToolUse[Bash] — fresh watcher read + context injection
|
|
2576
|
+
// when a risky shared-state action has a live same-repo peer.
|
|
2583
2577
|
// docs/collision-schematic.md
|
|
2584
2578
|
await coordinateGate(input);
|
|
2585
2579
|
}
|
|
2580
|
+
else if (subcommand === 'codex-coordinate-gate') {
|
|
2581
|
+
// Codex PreToolUse[Bash] — deny risky shared-state actions until the
|
|
2582
|
+
// committed artifact has fresh native + cross-harness conferral evidence.
|
|
2583
|
+
// adr: adr/codex-coordinate-gate.md
|
|
2584
|
+
await coordinateGate(input, true);
|
|
2585
|
+
}
|
|
2586
2586
|
else if (subcommand === 'context-probe') {
|
|
2587
2587
|
// Stop probe — transcript-tail context-size measurement, local state only.
|
|
2588
2588
|
(0, context_governor_1.runContextProbe)(input);
|