greprag 5.54.0 → 5.56.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/dist/commands/loadout-reminder.d.ts +37 -0
- package/dist/commands/loadout-reminder.js +78 -0
- package/dist/commands/loadout-reminder.js.map +1 -0
- package/dist/commands/loadout.d.ts +15 -0
- package/dist/commands/loadout.js +288 -0
- package/dist/commands/loadout.js.map +1 -0
- package/dist/commands/opencode-interrupt.d.ts +1 -0
- package/dist/commands/opencode-interrupt.js +2 -0
- package/dist/commands/opencode-interrupt.js.map +1 -1
- package/dist/commands/procedure-reminder.d.ts +8 -0
- package/dist/commands/procedure-reminder.js +27 -0
- package/dist/commands/procedure-reminder.js.map +1 -0
- package/dist/commands/procedure.js +311 -12
- package/dist/commands/procedure.js.map +1 -1
- package/dist/commands/reminder-registry.js +4 -0
- package/dist/commands/reminder-registry.js.map +1 -1
- package/dist/commands/reminder-types.d.ts +21 -0
- package/dist/commands/ship-through-gate.d.ts +16 -0
- package/dist/commands/ship-through-gate.js +43 -0
- package/dist/commands/ship-through-gate.js.map +1 -0
- package/dist/equipped-loadouts-cache.d.ts +20 -0
- package/dist/equipped-loadouts-cache.js +79 -0
- package/dist/equipped-loadouts-cache.js.map +1 -0
- package/dist/hook.js +79 -1
- package/dist/hook.js.map +1 -1
- package/dist/index.js +16 -0
- package/dist/index.js.map +1 -1
- package/dist/opencode-plugin.bundle.js +231 -52
- package/dist/opencode-plugin.js +9 -0
- package/dist/opencode-plugin.js.map +1 -1
- package/dist/procedure-run.d.ts +51 -0
- package/dist/procedure-run.js +186 -0
- package/dist/procedure-run.js.map +1 -0
- package/dist/procedure.d.ts +71 -1
- package/dist/procedure.js +168 -6
- package/dist/procedure.js.map +1 -1
- package/package.json +1 -1
|
@@ -24,9 +24,9 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
24
24
|
|
|
25
25
|
// src/opencode-plugin.ts
|
|
26
26
|
var crypto2 = __toESM(require("crypto"));
|
|
27
|
-
var
|
|
27
|
+
var fs3 = __toESM(require("fs"));
|
|
28
28
|
var os = __toESM(require("os"));
|
|
29
|
-
var
|
|
29
|
+
var path3 = __toESM(require("path"));
|
|
30
30
|
|
|
31
31
|
// src/opencode-plugin-helpers.ts
|
|
32
32
|
var crypto = __toESM(require("crypto"));
|
|
@@ -2160,6 +2160,64 @@ var skillMirrorAnnounceModule = {
|
|
|
2160
2160
|
reminder: () => null
|
|
2161
2161
|
};
|
|
2162
2162
|
|
|
2163
|
+
// src/commands/procedure-reminder.ts
|
|
2164
|
+
function buildProcedureAnnounce(lines) {
|
|
2165
|
+
const active = (lines ?? []).map((s) => s.trim()).filter(Boolean);
|
|
2166
|
+
if (!active.length)
|
|
2167
|
+
return null;
|
|
2168
|
+
return [
|
|
2169
|
+
"[greprag procedures \u2014 active project procedures:]",
|
|
2170
|
+
...active.map((line) => `\u2022 ${line}`)
|
|
2171
|
+
].join("\n");
|
|
2172
|
+
}
|
|
2173
|
+
var procedureAnnounceModule = {
|
|
2174
|
+
id: "procedure-announce",
|
|
2175
|
+
// ship-through references peer coordination taught by the inbox primer.
|
|
2176
|
+
dependsOn: ["inbox-primer"],
|
|
2177
|
+
detect: (_env) => ({ tier: "silent" }),
|
|
2178
|
+
announce: (env) => buildProcedureAnnounce(env.procedureAnnounces),
|
|
2179
|
+
reminder: () => null
|
|
2180
|
+
};
|
|
2181
|
+
|
|
2182
|
+
// src/commands/loadout-reminder.ts
|
|
2183
|
+
function matchLoadouts(promptText, equipped) {
|
|
2184
|
+
const prompt = (promptText || "").toLowerCase();
|
|
2185
|
+
if (!prompt.trim() || !equipped || equipped.length === 0)
|
|
2186
|
+
return [];
|
|
2187
|
+
return equipped.filter((l) => (l.keywords || []).some((kw) => {
|
|
2188
|
+
const k = kw.trim().toLowerCase();
|
|
2189
|
+
return k.length >= 3 && prompt.includes(k);
|
|
2190
|
+
}));
|
|
2191
|
+
}
|
|
2192
|
+
function buildLoadoutAnnounce(equipped) {
|
|
2193
|
+
const decls = (equipped || []).filter((l) => l.announceLine);
|
|
2194
|
+
if (decls.length === 0)
|
|
2195
|
+
return null;
|
|
2196
|
+
return [
|
|
2197
|
+
"[greprag loadouts \u2014 equipped skill bundles (served on demand via `greprag load`):]",
|
|
2198
|
+
...decls.map((l) => ` ${l.announceLine}`)
|
|
2199
|
+
].join("\n");
|
|
2200
|
+
}
|
|
2201
|
+
function buildLoadoutReminder(matched) {
|
|
2202
|
+
if (matched.length === 0)
|
|
2203
|
+
return null;
|
|
2204
|
+
return matched.map((l) => `\u{1F392} your equipped loadout "${l.name}" covers this \u2192 \`greprag load ${l.advisor}\` (it routes to the right expert)`).join("\n");
|
|
2205
|
+
}
|
|
2206
|
+
function loadoutDetect(env) {
|
|
2207
|
+
const matched = matchLoadouts(env.promptText, env.equippedLoadouts);
|
|
2208
|
+
if (matched.length === 0)
|
|
2209
|
+
return { tier: "silent" };
|
|
2210
|
+
return { tier: "nudge", detail: { matched } };
|
|
2211
|
+
}
|
|
2212
|
+
var loadoutRegistrarModule = {
|
|
2213
|
+
id: "loadout-registrar",
|
|
2214
|
+
// The announce says "greprag load" — depends on the load primer teaching it.
|
|
2215
|
+
dependsOn: ["load-primer"],
|
|
2216
|
+
detect: loadoutDetect,
|
|
2217
|
+
announce: (env) => buildLoadoutAnnounce(env.equippedLoadouts),
|
|
2218
|
+
reminder: (d) => buildLoadoutReminder(d.detail?.matched || [])
|
|
2219
|
+
};
|
|
2220
|
+
|
|
2163
2221
|
// src/commands/reminder-registry.ts
|
|
2164
2222
|
var REGISTRY = [
|
|
2165
2223
|
inboxPrimerModule,
|
|
@@ -2174,6 +2232,10 @@ var REGISTRY = [
|
|
|
2174
2232
|
// announce-only skill-gain landings (docs/skill-learning-loop.md)
|
|
2175
2233
|
skillMirrorAnnounceModule,
|
|
2176
2234
|
// one-line Tier-3 pointer: your skills travel via greprag load (docs/load-system.md)
|
|
2235
|
+
procedureAnnounceModule,
|
|
2236
|
+
// active project procedures, rendered generically from operator-owned installs
|
|
2237
|
+
loadoutRegistrarModule,
|
|
2238
|
+
// equipped loadouts: one advisor announce each + per-turn keyword Match (docs/loadout.md)
|
|
2177
2239
|
setupWarningModule,
|
|
2178
2240
|
versionUpgradeModule,
|
|
2179
2241
|
// Deficiency-gated announce — silent unless a newer release exists
|
|
@@ -2253,6 +2315,7 @@ var OPENCODE_MODULE_IDS = /* @__PURE__ */ new Set([
|
|
|
2253
2315
|
"setup-warning",
|
|
2254
2316
|
"version-upgrade",
|
|
2255
2317
|
"memory-primer",
|
|
2318
|
+
"procedure-announce",
|
|
2256
2319
|
"collision"
|
|
2257
2320
|
]);
|
|
2258
2321
|
var opencodeRegistry = REGISTRY.filter(
|
|
@@ -2268,7 +2331,8 @@ function buildOpenCodeEnv(params) {
|
|
|
2268
2331
|
projectName: params.projectName,
|
|
2269
2332
|
setupWarning: params.setupWarning ?? null,
|
|
2270
2333
|
corpusApiDocs: params.corpusApiDocs ?? [],
|
|
2271
|
-
updateAvailable: params.updateAvailable ?? null
|
|
2334
|
+
updateAvailable: params.updateAvailable ?? null,
|
|
2335
|
+
procedureAnnounces: params.procedureAnnounces ?? []
|
|
2272
2336
|
};
|
|
2273
2337
|
}
|
|
2274
2338
|
var OPENCODE_CHIP_BOOTLOADER_POINTER = '[greprag chips \u2014 agent coordination is built in (messaging plumbing in the inbox primer).]\n\u2022 Delegating a component of a plan to an isolated sub-session (a "chip") for focused, efficient work? \u2192 run `greprag load chip-bootloader` for the copyable bootloader template (Block 1 setup + Block 2 report-back).';
|
|
@@ -2279,15 +2343,123 @@ function getOpenCodeReminders(env) {
|
|
|
2279
2343
|
return collectReminders(env, opencodeRegistry);
|
|
2280
2344
|
}
|
|
2281
2345
|
|
|
2346
|
+
// src/procedure.ts
|
|
2347
|
+
var path2 = __toESM(require("path"));
|
|
2348
|
+
var fs2 = __toESM(require("fs"));
|
|
2349
|
+
var PROCEDURE_STORE_VERSION = "2";
|
|
2350
|
+
function stateDir() {
|
|
2351
|
+
const home = process.env.HOME || process.env.USERPROFILE || "";
|
|
2352
|
+
return path2.join(home, ".greprag", "state");
|
|
2353
|
+
}
|
|
2354
|
+
function procedureStorePath(projectId) {
|
|
2355
|
+
return path2.join(stateDir(), `procedures-${projectId}.json`);
|
|
2356
|
+
}
|
|
2357
|
+
function readProcedureStore(projectId) {
|
|
2358
|
+
try {
|
|
2359
|
+
const raw = fs2.readFileSync(procedureStorePath(projectId), "utf-8");
|
|
2360
|
+
const parsed = JSON.parse(raw);
|
|
2361
|
+
if (parsed && Array.isArray(parsed.procedures)) {
|
|
2362
|
+
return {
|
|
2363
|
+
version: parsed.version || "1",
|
|
2364
|
+
procedures: parsed.procedures,
|
|
2365
|
+
installs: Array.isArray(parsed.installs) ? parsed.installs : []
|
|
2366
|
+
};
|
|
2367
|
+
}
|
|
2368
|
+
} catch {
|
|
2369
|
+
}
|
|
2370
|
+
return { version: PROCEDURE_STORE_VERSION, procedures: [], installs: [] };
|
|
2371
|
+
}
|
|
2372
|
+
function procedureId(proc) {
|
|
2373
|
+
return proc.verb;
|
|
2374
|
+
}
|
|
2375
|
+
function explicitInstall(store, id) {
|
|
2376
|
+
return (store.installs ?? []).find((i) => i.procedureId === id) ?? null;
|
|
2377
|
+
}
|
|
2378
|
+
function effectiveInstall(store, proc) {
|
|
2379
|
+
const id = procedureId(proc);
|
|
2380
|
+
const found = explicitInstall(store, id);
|
|
2381
|
+
if (found)
|
|
2382
|
+
return found;
|
|
2383
|
+
const legacyStored = store.procedures.some((p) => procedureId(p) === id);
|
|
2384
|
+
return {
|
|
2385
|
+
procedureId: id,
|
|
2386
|
+
definitionVersion: proc.definitionVersion ?? 1,
|
|
2387
|
+
state: legacyStored ? "active" : "disabled",
|
|
2388
|
+
autonomy: legacyStored ? "advise" : proc.defaultInstall?.autonomy ?? "advise",
|
|
2389
|
+
authority: legacyStored ? "fresh" : proc.defaultInstall?.authority ?? "fresh",
|
|
2390
|
+
settings: defaultProcedureSettings(proc),
|
|
2391
|
+
updatedAt: proc.updatedAt ?? ""
|
|
2392
|
+
};
|
|
2393
|
+
}
|
|
2394
|
+
function defaultProcedureSettings(proc) {
|
|
2395
|
+
return Object.fromEntries(Object.entries(proc.settingsSchema ?? {}).map(([key, spec]) => [key, spec.default]));
|
|
2396
|
+
}
|
|
2397
|
+
var SHIP_THROUGH_PROCEDURE = {
|
|
2398
|
+
verb: "ship-through",
|
|
2399
|
+
triggers: [],
|
|
2400
|
+
steps: [
|
|
2401
|
+
"Start the run with `greprag procedure begin ship-through`, then reach a coherent diff.",
|
|
2402
|
+
"Confer with reachable same-project GrepRAG peers; if none are reachable, use an independent local reviewer/subagent.",
|
|
2403
|
+
"Incorporate valid findings, run proportional checks, then attest current-artifact review with `greprag procedure attest ship-through review --via peer|local --ref <reviewer>`.",
|
|
2404
|
+
"Commit/merge only the task-scoped files.",
|
|
2405
|
+
"Invoke only the affected target's registered deploy procedure(s).",
|
|
2406
|
+
"Verify production health and the changed behavior."
|
|
2407
|
+
].join(" "),
|
|
2408
|
+
caveats: "Routine code changes only. Stop for failed checks, missing migrations/secrets, money, destructive live data, undeclared external systems, or scope expansion. Peer review informs correctness but never grants authority.",
|
|
2409
|
+
endpoint: "the affected production target is healthy and verified at the reviewed current commit",
|
|
2410
|
+
status: "seeded",
|
|
2411
|
+
definitionVersion: 1,
|
|
2412
|
+
settingsSchema: {
|
|
2413
|
+
review_strategy: {
|
|
2414
|
+
type: "string",
|
|
2415
|
+
default: "peer-or-local",
|
|
2416
|
+
enum: ["peer-or-local", "peer-required", "local"],
|
|
2417
|
+
riskBearing: true,
|
|
2418
|
+
description: "Independent review source before commit/deploy."
|
|
2419
|
+
}
|
|
2420
|
+
},
|
|
2421
|
+
defaultInstall: { autonomy: "execute", authority: "standing" },
|
|
2422
|
+
announce: {
|
|
2423
|
+
summary: "`ship-through` ACTIVE \u2014 change/build tasks end peer-reviewed and verified in production, not \u201Cready to deploy.\u201D Start: `greprag procedure begin ship-through`; contract: `greprag procedure show ship-through`.",
|
|
2424
|
+
reannounceOnCompact: true
|
|
2425
|
+
},
|
|
2426
|
+
risk: {
|
|
2427
|
+
maximumAutonomy: "execute",
|
|
2428
|
+
standingAuthorityAllowed: true,
|
|
2429
|
+
authorityScope: ["task-scoped commit/merge", "registered deploy procedures", "production verification"]
|
|
2430
|
+
}
|
|
2431
|
+
};
|
|
2432
|
+
var BUILTIN_PROCEDURES = [SHIP_THROUGH_PROCEDURE];
|
|
2433
|
+
function listProcedureDefinitions(store) {
|
|
2434
|
+
const out = [...store.procedures];
|
|
2435
|
+
const seen = new Set(out.map(procedureId));
|
|
2436
|
+
for (const proc of BUILTIN_PROCEDURES) {
|
|
2437
|
+
if (!seen.has(procedureId(proc)))
|
|
2438
|
+
out.push(proc);
|
|
2439
|
+
}
|
|
2440
|
+
return out;
|
|
2441
|
+
}
|
|
2442
|
+
function activeProcedureAnnounces(store) {
|
|
2443
|
+
const lines = [];
|
|
2444
|
+
for (const proc of listProcedureDefinitions(store)) {
|
|
2445
|
+
if (!proc.announce)
|
|
2446
|
+
continue;
|
|
2447
|
+
if (effectiveInstall(store, proc).state !== "active")
|
|
2448
|
+
continue;
|
|
2449
|
+
lines.push(proc.announce.summary);
|
|
2450
|
+
}
|
|
2451
|
+
return lines;
|
|
2452
|
+
}
|
|
2453
|
+
|
|
2282
2454
|
// src/opencode-plugin.ts
|
|
2283
|
-
var DEBUG_LOG_PATH =
|
|
2455
|
+
var DEBUG_LOG_PATH = path3.join(os.homedir(), ".greprag", "opencode-plugin-debug.log");
|
|
2284
2456
|
var _debugLogReady = false;
|
|
2285
2457
|
function dlogInit() {
|
|
2286
2458
|
if (_debugLogReady)
|
|
2287
2459
|
return;
|
|
2288
2460
|
_debugLogReady = true;
|
|
2289
2461
|
try {
|
|
2290
|
-
|
|
2462
|
+
fs3.writeFileSync(DEBUG_LOG_PATH, "");
|
|
2291
2463
|
} catch {
|
|
2292
2464
|
}
|
|
2293
2465
|
}
|
|
@@ -2296,7 +2468,7 @@ function dlog(msg) {
|
|
|
2296
2468
|
const line = `[${(/* @__PURE__ */ new Date()).toISOString()}] [greprag-memory] ${msg}
|
|
2297
2469
|
`;
|
|
2298
2470
|
try {
|
|
2299
|
-
|
|
2471
|
+
fs3.appendFileSync(DEBUG_LOG_PATH, line);
|
|
2300
2472
|
} catch {
|
|
2301
2473
|
}
|
|
2302
2474
|
}
|
|
@@ -2304,9 +2476,9 @@ dlog(`module top reached: pid=${process.pid} argv0=${process.argv[0]} distPath=$
|
|
|
2304
2476
|
var API_URL = "https://api.greprag.com";
|
|
2305
2477
|
function loadEnvFile(filePath) {
|
|
2306
2478
|
try {
|
|
2307
|
-
if (!
|
|
2479
|
+
if (!fs3.existsSync(filePath))
|
|
2308
2480
|
return;
|
|
2309
|
-
const raw =
|
|
2481
|
+
const raw = fs3.readFileSync(filePath, "utf-8");
|
|
2310
2482
|
for (const line of raw.split(/\r?\n/)) {
|
|
2311
2483
|
const trimmed = line.trim();
|
|
2312
2484
|
if (!trimmed || trimmed.startsWith("#"))
|
|
@@ -2326,12 +2498,12 @@ function loadEnvFile(filePath) {
|
|
|
2326
2498
|
}
|
|
2327
2499
|
}
|
|
2328
2500
|
function loadGrepragEnv() {
|
|
2329
|
-
loadEnvFile(
|
|
2501
|
+
loadEnvFile(path3.join(HOME, ".greprag", ".env"));
|
|
2330
2502
|
try {
|
|
2331
|
-
const p =
|
|
2332
|
-
if (!
|
|
2503
|
+
const p = path3.join(HOME, ".claude", "settings.json");
|
|
2504
|
+
if (!fs3.existsSync(p))
|
|
2333
2505
|
return;
|
|
2334
|
-
const data = JSON.parse(
|
|
2506
|
+
const data = JSON.parse(fs3.readFileSync(p, "utf-8"));
|
|
2335
2507
|
if (data && data.env && typeof data.env === "object") {
|
|
2336
2508
|
for (const [key, val] of Object.entries(data.env)) {
|
|
2337
2509
|
if (!process.env[key] && typeof val === "string") {
|
|
@@ -2344,11 +2516,11 @@ function loadGrepragEnv() {
|
|
|
2344
2516
|
}
|
|
2345
2517
|
loadGrepragEnv();
|
|
2346
2518
|
dlog(`env loaded: MEMORY_HOOK_ENABLED=${process.env.MEMORY_HOOK_ENABLED || "<unset>"} GREPRAG_API_KEY=${process.env.GREPRAG_API_KEY ? "set" : "<unset>"} GREPRAG_OPENCODE_CAPTURE=${process.env.GREPRAG_OPENCODE_CAPTURE || "<unset>"}`);
|
|
2347
|
-
var WATCHER_LOCK =
|
|
2519
|
+
var WATCHER_LOCK = path3.join(HOME || os.homedir(), ".greprag", "opencode-watch.lock");
|
|
2348
2520
|
var WATCHER_STALE_MS = 3e4;
|
|
2349
2521
|
function findGrepragBinary() {
|
|
2350
2522
|
const override = process.env.GREPRAG_BIN;
|
|
2351
|
-
if (override &&
|
|
2523
|
+
if (override && fs3.existsSync(override))
|
|
2352
2524
|
return override;
|
|
2353
2525
|
const binaryName = process.platform === "win32" ? "greprag.cmd" : "greprag";
|
|
2354
2526
|
try {
|
|
@@ -2357,14 +2529,14 @@ function findGrepragBinary() {
|
|
|
2357
2529
|
const candidate = line.trim();
|
|
2358
2530
|
if (!candidate)
|
|
2359
2531
|
continue;
|
|
2360
|
-
if (!
|
|
2532
|
+
if (!fs3.existsSync(candidate))
|
|
2361
2533
|
continue;
|
|
2362
2534
|
if (process.platform === "win32") {
|
|
2363
|
-
const ext =
|
|
2535
|
+
const ext = path3.extname(candidate).toLowerCase();
|
|
2364
2536
|
if (ext === ".cmd" || ext === ".exe" || ext === ".bat")
|
|
2365
2537
|
return candidate;
|
|
2366
2538
|
const cmdSibling = candidate + ".cmd";
|
|
2367
|
-
if (
|
|
2539
|
+
if (fs3.existsSync(cmdSibling))
|
|
2368
2540
|
return cmdSibling;
|
|
2369
2541
|
continue;
|
|
2370
2542
|
}
|
|
@@ -2373,19 +2545,19 @@ function findGrepragBinary() {
|
|
|
2373
2545
|
} catch {
|
|
2374
2546
|
}
|
|
2375
2547
|
const candidates = process.platform === "win32" ? [
|
|
2376
|
-
|
|
2377
|
-
|
|
2378
|
-
|
|
2379
|
-
|
|
2548
|
+
path3.join(HOME, "AppData", "Roaming", "npm", "greprag.cmd"),
|
|
2549
|
+
path3.join(HOME, "AppData", "Roaming", "npm", "greprag"),
|
|
2550
|
+
path3.join(HOME, "AppData", "Local", "Yarn", "bin", "greprag.cmd"),
|
|
2551
|
+
path3.join(HOME, "AppData", "Local", "pnpm", "bin", "greprag.cmd")
|
|
2380
2552
|
] : [
|
|
2381
2553
|
"/usr/local/bin/greprag",
|
|
2382
2554
|
"/opt/homebrew/bin/greprag",
|
|
2383
|
-
|
|
2384
|
-
|
|
2555
|
+
path3.join(HOME || "", ".local", "bin", "greprag"),
|
|
2556
|
+
path3.join(HOME || "", ".yarn", "bin", "greprag")
|
|
2385
2557
|
];
|
|
2386
2558
|
for (const c of candidates) {
|
|
2387
2559
|
try {
|
|
2388
|
-
if (c &&
|
|
2560
|
+
if (c && fs3.existsSync(c))
|
|
2389
2561
|
return c;
|
|
2390
2562
|
} catch {
|
|
2391
2563
|
}
|
|
@@ -2394,18 +2566,18 @@ function findGrepragBinary() {
|
|
|
2394
2566
|
}
|
|
2395
2567
|
function tryClaimWatcherLock() {
|
|
2396
2568
|
try {
|
|
2397
|
-
const fd =
|
|
2569
|
+
const fd = fs3.openSync(WATCHER_LOCK, "wx");
|
|
2398
2570
|
return { ok: true, fd };
|
|
2399
2571
|
} catch (err) {
|
|
2400
2572
|
if (err.code !== "EEXIST") {
|
|
2401
2573
|
return { ok: false, reason: "lock-create-failed" };
|
|
2402
2574
|
}
|
|
2403
2575
|
try {
|
|
2404
|
-
const stat =
|
|
2576
|
+
const stat = fs3.statSync(WATCHER_LOCK);
|
|
2405
2577
|
const ageMs = Date.now() - stat.mtimeMs;
|
|
2406
2578
|
let pidAlive = false;
|
|
2407
2579
|
try {
|
|
2408
|
-
const pid = parseInt(
|
|
2580
|
+
const pid = parseInt(fs3.readFileSync(WATCHER_LOCK, "utf-8").trim(), 10);
|
|
2409
2581
|
pidAlive = pid > 0 && isPidAlive(pid);
|
|
2410
2582
|
} catch {
|
|
2411
2583
|
}
|
|
@@ -2413,10 +2585,10 @@ function tryClaimWatcherLock() {
|
|
|
2413
2585
|
return { ok: false, reason: "busy" };
|
|
2414
2586
|
}
|
|
2415
2587
|
try {
|
|
2416
|
-
|
|
2588
|
+
fs3.unlinkSync(WATCHER_LOCK);
|
|
2417
2589
|
} catch {
|
|
2418
2590
|
}
|
|
2419
|
-
const fd =
|
|
2591
|
+
const fd = fs3.openSync(WATCHER_LOCK, "wx");
|
|
2420
2592
|
return { ok: true, fd };
|
|
2421
2593
|
} catch (err2) {
|
|
2422
2594
|
return { ok: false, reason: "lock-stale-replace-failed" };
|
|
@@ -2457,11 +2629,11 @@ function startCaptureWatcher() {
|
|
|
2457
2629
|
return;
|
|
2458
2630
|
}
|
|
2459
2631
|
try {
|
|
2460
|
-
|
|
2461
|
-
|
|
2632
|
+
fs3.writeSync(claim.fd, String(process.pid));
|
|
2633
|
+
fs3.closeSync(claim.fd);
|
|
2462
2634
|
} catch {
|
|
2463
2635
|
try {
|
|
2464
|
-
|
|
2636
|
+
fs3.unlinkSync(WATCHER_LOCK);
|
|
2465
2637
|
} catch {
|
|
2466
2638
|
}
|
|
2467
2639
|
return;
|
|
@@ -2477,11 +2649,11 @@ function startCaptureWatcher() {
|
|
|
2477
2649
|
const claim2 = tryClaimWatcherLock();
|
|
2478
2650
|
if (claim2.ok) {
|
|
2479
2651
|
try {
|
|
2480
|
-
|
|
2481
|
-
|
|
2652
|
+
fs3.writeSync(claim2.fd, String(process.pid));
|
|
2653
|
+
fs3.closeSync(claim2.fd);
|
|
2482
2654
|
} catch {
|
|
2483
2655
|
try {
|
|
2484
|
-
|
|
2656
|
+
fs3.unlinkSync(WATCHER_LOCK);
|
|
2485
2657
|
} catch {
|
|
2486
2658
|
}
|
|
2487
2659
|
return false;
|
|
@@ -2524,7 +2696,7 @@ function startCaptureWatcher() {
|
|
|
2524
2696
|
childStartTime = Date.now();
|
|
2525
2697
|
dlog(`startCaptureWatcher: spawned 'greprag opencode watch' pid=${child.pid ?? "<none>"}`);
|
|
2526
2698
|
try {
|
|
2527
|
-
|
|
2699
|
+
fs3.writeFileSync(WATCHER_LOCK, String(child.pid));
|
|
2528
2700
|
} catch {
|
|
2529
2701
|
}
|
|
2530
2702
|
child.stderr?.on("data", (chunk) => {
|
|
@@ -2536,9 +2708,9 @@ function startCaptureWatcher() {
|
|
|
2536
2708
|
child.on("exit", (code, signal) => {
|
|
2537
2709
|
dlog(`startCaptureWatcher: child pid=${child.pid ?? "<none>"} exited code=${code} signal=${signal || "none"}`);
|
|
2538
2710
|
try {
|
|
2539
|
-
const current =
|
|
2711
|
+
const current = fs3.readFileSync(WATCHER_LOCK, "utf-8").trim();
|
|
2540
2712
|
if (current === String(child.pid))
|
|
2541
|
-
|
|
2713
|
+
fs3.unlinkSync(WATCHER_LOCK);
|
|
2542
2714
|
} catch {
|
|
2543
2715
|
}
|
|
2544
2716
|
currentChild = null;
|
|
@@ -2567,7 +2739,7 @@ function startCaptureWatcher() {
|
|
|
2567
2739
|
`
|
|
2568
2740
|
);
|
|
2569
2741
|
try {
|
|
2570
|
-
|
|
2742
|
+
fs3.unlinkSync(WATCHER_LOCK);
|
|
2571
2743
|
} catch {
|
|
2572
2744
|
}
|
|
2573
2745
|
return;
|
|
@@ -2599,7 +2771,7 @@ function startCaptureWatcher() {
|
|
|
2599
2771
|
}, 2e3).unref();
|
|
2600
2772
|
}
|
|
2601
2773
|
try {
|
|
2602
|
-
|
|
2774
|
+
fs3.unlinkSync(WATCHER_LOCK);
|
|
2603
2775
|
} catch {
|
|
2604
2776
|
}
|
|
2605
2777
|
};
|
|
@@ -2674,11 +2846,11 @@ function startSessionRelay(sessionId, serverUrl) {
|
|
|
2674
2846
|
return;
|
|
2675
2847
|
}
|
|
2676
2848
|
try {
|
|
2677
|
-
|
|
2678
|
-
|
|
2849
|
+
fs3.writeSync(claim.fd, String(process.pid));
|
|
2850
|
+
fs3.closeSync(claim.fd);
|
|
2679
2851
|
} catch {
|
|
2680
2852
|
try {
|
|
2681
|
-
|
|
2853
|
+
fs3.unlinkSync(lockPath);
|
|
2682
2854
|
} catch {
|
|
2683
2855
|
}
|
|
2684
2856
|
return;
|
|
@@ -2693,11 +2865,11 @@ function startSessionRelay(sessionId, serverUrl) {
|
|
|
2693
2865
|
const claim2 = tryClaimRelayLock(lockPath);
|
|
2694
2866
|
if (claim2.ok) {
|
|
2695
2867
|
try {
|
|
2696
|
-
|
|
2697
|
-
|
|
2868
|
+
fs3.writeSync(claim2.fd, String(process.pid));
|
|
2869
|
+
fs3.closeSync(claim2.fd);
|
|
2698
2870
|
} catch {
|
|
2699
2871
|
try {
|
|
2700
|
-
|
|
2872
|
+
fs3.unlinkSync(lockPath);
|
|
2701
2873
|
} catch {
|
|
2702
2874
|
}
|
|
2703
2875
|
return false;
|
|
@@ -2733,7 +2905,7 @@ function startSessionRelay(sessionId, serverUrl) {
|
|
|
2733
2905
|
childStartTime = Date.now();
|
|
2734
2906
|
dlog(`startSessionRelay: spawned 'greprag opencode relay' pid=${child.pid ?? "<none>"}`);
|
|
2735
2907
|
try {
|
|
2736
|
-
|
|
2908
|
+
fs3.writeFileSync(lockPath, String(child.pid));
|
|
2737
2909
|
} catch {
|
|
2738
2910
|
}
|
|
2739
2911
|
child.stderr?.on("data", (chunk) => {
|
|
@@ -2744,9 +2916,9 @@ function startSessionRelay(sessionId, serverUrl) {
|
|
|
2744
2916
|
});
|
|
2745
2917
|
child.on("exit", (code, signal) => {
|
|
2746
2918
|
try {
|
|
2747
|
-
const current =
|
|
2919
|
+
const current = fs3.readFileSync(lockPath, "utf-8").trim();
|
|
2748
2920
|
if (current === String(child.pid))
|
|
2749
|
-
|
|
2921
|
+
fs3.unlinkSync(lockPath);
|
|
2750
2922
|
} catch {
|
|
2751
2923
|
}
|
|
2752
2924
|
currentChild = null;
|
|
@@ -2773,7 +2945,7 @@ function startSessionRelay(sessionId, serverUrl) {
|
|
|
2773
2945
|
`
|
|
2774
2946
|
);
|
|
2775
2947
|
try {
|
|
2776
|
-
|
|
2948
|
+
fs3.unlinkSync(lockPath);
|
|
2777
2949
|
} catch {
|
|
2778
2950
|
}
|
|
2779
2951
|
return;
|
|
@@ -2805,7 +2977,7 @@ function startSessionRelay(sessionId, serverUrl) {
|
|
|
2805
2977
|
}, 2e3).unref();
|
|
2806
2978
|
}
|
|
2807
2979
|
try {
|
|
2808
|
-
|
|
2980
|
+
fs3.unlinkSync(lockPath);
|
|
2809
2981
|
} catch {
|
|
2810
2982
|
}
|
|
2811
2983
|
};
|
|
@@ -2932,7 +3104,14 @@ ALWAYS pass \`--from-session ${sid82}\` when you run \`greprag send\`, so recipi
|
|
|
2932
3104
|
const env = buildOpenCodeEnv({
|
|
2933
3105
|
short: sid8,
|
|
2934
3106
|
turnCount,
|
|
2935
|
-
projectName: anchor.projectName
|
|
3107
|
+
projectName: anchor.projectName,
|
|
3108
|
+
procedureAnnounces: (() => {
|
|
3109
|
+
try {
|
|
3110
|
+
return activeProcedureAnnounces(readProcedureStore(anchor.projectId));
|
|
3111
|
+
} catch {
|
|
3112
|
+
return [];
|
|
3113
|
+
}
|
|
3114
|
+
})()
|
|
2936
3115
|
});
|
|
2937
3116
|
if (!announcedBySession.has(sid8)) {
|
|
2938
3117
|
announcedBySession.add(sid8);
|
package/dist/opencode-plugin.js
CHANGED
|
@@ -98,6 +98,7 @@ const opencode_plugin_helpers_1 = require("./opencode-plugin-helpers");
|
|
|
98
98
|
const proc_1 = require("./proc");
|
|
99
99
|
const opencode_plugin_crush_1 = require("./opencode-plugin-crush");
|
|
100
100
|
const opencode_interrupt_1 = require("./commands/opencode-interrupt");
|
|
101
|
+
const procedure_1 = require("./procedure");
|
|
101
102
|
// ============================================================================
|
|
102
103
|
// File-based debug log. opencode's plugin loader (Bun) does NOT route plugin
|
|
103
104
|
// stderr into the opencode log file at ~/.local/share/opencode/log/*.log —
|
|
@@ -906,6 +907,14 @@ const GrepRAGMemoryPlugin = async (ctx) => {
|
|
|
906
907
|
short: sid8,
|
|
907
908
|
turnCount,
|
|
908
909
|
projectName: anchor.projectName,
|
|
910
|
+
procedureAnnounces: (() => {
|
|
911
|
+
try {
|
|
912
|
+
return (0, procedure_1.activeProcedureAnnounces)((0, procedure_1.readProcedureStore)(anchor.projectId));
|
|
913
|
+
}
|
|
914
|
+
catch {
|
|
915
|
+
return [];
|
|
916
|
+
}
|
|
917
|
+
})(),
|
|
909
918
|
});
|
|
910
919
|
// Announces: inject on first fire per session (static primers)
|
|
911
920
|
if (!announcedBySession.has(sid8)) {
|