@polygraph/codex-plugin 0.4.40 → 0.4.41
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/.codex-plugin/plugin.json +1 -1
- package/README.md +1 -0
- package/agents/session-debrief.toml +24 -0
- package/bin/polygraph-codex-plugin.mjs +163 -60
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -46,6 +46,7 @@ It detects your AI agent — Claude Code, Codex, OpenCode, and more — and inst
|
|
|
46
46
|
|
|
47
47
|
- **polygraph-init-subagent** — Discovers candidate repositories and initializes a Polygraph session
|
|
48
48
|
- **polygraph-delegate-subagent** — Delegates work to a child agent in another repository, polls for completion
|
|
49
|
+
- **session-debrief** — Analyzes the raw logs of past Polygraph sessions and returns a structured, rank-ordered debrief for the current task
|
|
49
50
|
|
|
50
51
|
## Development
|
|
51
52
|
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
name = "session-debrief"
|
|
2
|
+
description = "Analyze the raw logs of one or more past Polygraph sessions and return a structured, rank-ordered debrief for the current task. Launch as a background agent with a ranked list of relevant Polygraph session IDs/lines and a one-paragraph statement of the current task; it invokes the session-debrief skill, pulls parent and child transcripts via the polygraph CLI, and returns one consolidated debrief. Read-only with respect to the inspected sessions."
|
|
3
|
+
developer_instructions = '''
|
|
4
|
+
# Session Debrief Subagent
|
|
5
|
+
|
|
6
|
+
You produce debriefs of PAST Polygraph sessions so a parent agent working on a NEW task can decide what context is relevant. You run in the background and speed matters — the parent keeps working while it waits and folds your debrief in whenever it lands.
|
|
7
|
+
|
|
8
|
+
You are READ-ONLY with respect to the inspected sessions: never resume them, never spawn agents into them, never push branches, create PRs, or update their descriptions.
|
|
9
|
+
|
|
10
|
+
## Input Parameters (from Main Agent)
|
|
11
|
+
|
|
12
|
+
The main agent provides these in the prompt:
|
|
13
|
+
|
|
14
|
+
| Parameter | Description |
|
|
15
|
+
| ------------- | ------------------------------------------------------------------------------------------------ |
|
|
16
|
+
| `sessions` | A ranked list of relevant Polygraph sessions (IDs/lines, most relevant first, with optional titles/URLs) |
|
|
17
|
+
| `currentTask` | A one-paragraph statement of the task the parent is currently working on |
|
|
18
|
+
|
|
19
|
+
## What to do
|
|
20
|
+
|
|
21
|
+
Invoke the `session-debrief` skill and follow its procedure and output template exactly. Pass through the ranked session list and the current-task statement you received. The skill is the single source of truth for how to pull transcripts via the polygraph CLI, how to fan out across multiple sessions, and how to format each debrief section — do not reinvent or duplicate that procedure here.
|
|
22
|
+
|
|
23
|
+
Return the consolidated, rank-ordered debrief as your final message.
|
|
24
|
+
'''
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
// source/codex/lib/installer.mjs
|
|
4
|
+
import { spawnSync } from "node:child_process";
|
|
4
5
|
import {
|
|
5
6
|
cpSync,
|
|
6
7
|
existsSync,
|
|
@@ -35,10 +36,19 @@ function resolveUserHome(env = process.env) {
|
|
|
35
36
|
const userHome = env.HOME?.trim() || homedir();
|
|
36
37
|
return resolve(expandHome(userHome, env));
|
|
37
38
|
}
|
|
38
|
-
function
|
|
39
|
+
function getMarketplaceRoot(userHome) {
|
|
40
|
+
return join(userHome, ".polygraph", "codex-marketplace");
|
|
41
|
+
}
|
|
42
|
+
function getMarketplacePath(marketplaceRoot) {
|
|
43
|
+
return join(marketplaceRoot, ".agents", "plugins", "marketplace.json");
|
|
44
|
+
}
|
|
45
|
+
function getPluginInstallPath(marketplaceRoot) {
|
|
46
|
+
return join(marketplaceRoot, "plugins", PLUGIN_NAME);
|
|
47
|
+
}
|
|
48
|
+
function getLegacyMarketplacePath(userHome) {
|
|
39
49
|
return join(userHome, ".agents", "plugins", "marketplace.json");
|
|
40
50
|
}
|
|
41
|
-
function
|
|
51
|
+
function getLegacyPluginInstallPath(userHome) {
|
|
42
52
|
return join(userHome, ".agents", "plugins", PLUGIN_NAME);
|
|
43
53
|
}
|
|
44
54
|
function loadPackageMetadata(packageRoot) {
|
|
@@ -74,7 +84,9 @@ function loadPackageMetadata(packageRoot) {
|
|
|
74
84
|
function installPlugin({
|
|
75
85
|
packageRoot,
|
|
76
86
|
env = process.env,
|
|
77
|
-
force = false
|
|
87
|
+
force = false,
|
|
88
|
+
// Injectable so tests do not have to shell out to a real codex binary.
|
|
89
|
+
register = registerMarketplace
|
|
78
90
|
} = {}) {
|
|
79
91
|
if (!packageRoot) {
|
|
80
92
|
throw new Error("packageRoot is required");
|
|
@@ -83,8 +95,9 @@ function installPlugin({
|
|
|
83
95
|
const codexHome = resolveCodexHome(env);
|
|
84
96
|
const userHome = resolveUserHome(env);
|
|
85
97
|
const agentsPath = getAgentsPath(codexHome);
|
|
86
|
-
const
|
|
87
|
-
const
|
|
98
|
+
const marketplaceRoot = getMarketplaceRoot(userHome);
|
|
99
|
+
const marketplacePath = getMarketplacePath(marketplaceRoot);
|
|
100
|
+
const pluginPath = getPluginInstallPath(marketplaceRoot);
|
|
88
101
|
const installAlreadyPresent = existsSync(pluginPath);
|
|
89
102
|
let previousVersion = null;
|
|
90
103
|
if (installAlreadyPresent) {
|
|
@@ -117,15 +130,20 @@ function installPlugin({
|
|
|
117
130
|
copied = true;
|
|
118
131
|
}
|
|
119
132
|
const agentsChanged = installCodexAgents({ packageRoot, agentsPath });
|
|
120
|
-
const marketplaceChanged =
|
|
133
|
+
const marketplaceChanged = writeMarketplaceManifest({
|
|
121
134
|
marketplacePath,
|
|
122
|
-
|
|
123
|
-
|
|
135
|
+
marketplaceRoot,
|
|
136
|
+
pluginPath
|
|
124
137
|
});
|
|
138
|
+
const legacyCleanup = cleanLegacyMarketplaceEntry({ userHome });
|
|
139
|
+
const registration = register({ marketplaceRoot, env });
|
|
125
140
|
return {
|
|
126
141
|
ok: true,
|
|
127
142
|
action: "install",
|
|
128
143
|
plugin: PLUGIN_ID,
|
|
144
|
+
marketplaceName: MARKETPLACE_NAME,
|
|
145
|
+
marketplaceRoot,
|
|
146
|
+
marketplaceRegistered: registration.registered,
|
|
129
147
|
version,
|
|
130
148
|
codexHome,
|
|
131
149
|
agentsPath,
|
|
@@ -136,9 +154,68 @@ function installPlugin({
|
|
|
136
154
|
pluginUpdated: installAlreadyPresent && versionMismatch && !force,
|
|
137
155
|
previousVersion,
|
|
138
156
|
agentsChanged,
|
|
139
|
-
marketplaceChanged
|
|
157
|
+
marketplaceChanged,
|
|
158
|
+
legacyEntryRemoved: legacyCleanup.entryRemoved,
|
|
159
|
+
legacyMarketplaceRemoved: legacyCleanup.fileRemoved,
|
|
160
|
+
...registration.error ? { marketplaceRegistrationError: registration.error } : {}
|
|
140
161
|
};
|
|
141
162
|
}
|
|
163
|
+
function registerMarketplace({ marketplaceRoot, env = process.env }) {
|
|
164
|
+
const result = spawnSync(
|
|
165
|
+
"codex",
|
|
166
|
+
["plugin", "marketplace", "add", marketplaceRoot, "--json"],
|
|
167
|
+
{ encoding: "utf8", env }
|
|
168
|
+
);
|
|
169
|
+
if (result.error) {
|
|
170
|
+
return {
|
|
171
|
+
registered: false,
|
|
172
|
+
error: `Could not run \`codex\`: ${result.error.message}. Run \`codex plugin marketplace add ${marketplaceRoot}\` once codex is available.`
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
if (result.status !== 0) {
|
|
176
|
+
return {
|
|
177
|
+
registered: false,
|
|
178
|
+
error: `\`codex plugin marketplace add\` failed: ${(result.stderr || "").trim()}`
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
return { registered: true };
|
|
182
|
+
}
|
|
183
|
+
function cleanLegacyMarketplaceEntry({ userHome }) {
|
|
184
|
+
const legacyPath = getLegacyMarketplacePath(userHome);
|
|
185
|
+
const unchanged = { entryRemoved: false, fileRemoved: false };
|
|
186
|
+
if (!existsSync(legacyPath)) {
|
|
187
|
+
return unchanged;
|
|
188
|
+
}
|
|
189
|
+
let marketplace;
|
|
190
|
+
try {
|
|
191
|
+
marketplace = readJsonFile(legacyPath);
|
|
192
|
+
} catch {
|
|
193
|
+
return unchanged;
|
|
194
|
+
}
|
|
195
|
+
if (!isPlainObject(marketplace) || !Array.isArray(marketplace.plugins)) {
|
|
196
|
+
return unchanged;
|
|
197
|
+
}
|
|
198
|
+
const remaining = marketplace.plugins.filter(
|
|
199
|
+
(plugin) => plugin?.name !== PLUGIN_NAME
|
|
200
|
+
);
|
|
201
|
+
if (remaining.length === marketplace.plugins.length) {
|
|
202
|
+
return unchanged;
|
|
203
|
+
}
|
|
204
|
+
if (remaining.length === 0 && marketplace.name === MARKETPLACE_NAME) {
|
|
205
|
+
rmSync(legacyPath, { force: true });
|
|
206
|
+
rmSync(getLegacyPluginInstallPath(userHome), {
|
|
207
|
+
recursive: true,
|
|
208
|
+
force: true
|
|
209
|
+
});
|
|
210
|
+
return { entryRemoved: true, fileRemoved: true };
|
|
211
|
+
}
|
|
212
|
+
writeJsonFile(legacyPath, { ...marketplace, plugins: remaining });
|
|
213
|
+
rmSync(getLegacyPluginInstallPath(userHome), {
|
|
214
|
+
recursive: true,
|
|
215
|
+
force: true
|
|
216
|
+
});
|
|
217
|
+
return { entryRemoved: true, fileRemoved: false };
|
|
218
|
+
}
|
|
142
219
|
function checkInstall({ packageRoot, env = process.env } = {}) {
|
|
143
220
|
let version = null;
|
|
144
221
|
if (packageRoot) {
|
|
@@ -147,29 +224,46 @@ function checkInstall({ packageRoot, env = process.env } = {}) {
|
|
|
147
224
|
const codexHome = resolveCodexHome(env);
|
|
148
225
|
const userHome = resolveUserHome(env);
|
|
149
226
|
const agentsPath = getAgentsPath(codexHome);
|
|
150
|
-
const
|
|
151
|
-
const
|
|
227
|
+
const marketplaceRoot = getMarketplaceRoot(userHome);
|
|
228
|
+
const marketplacePath = getMarketplacePath(marketplaceRoot);
|
|
229
|
+
const pluginPath = getPluginInstallPath(marketplaceRoot);
|
|
152
230
|
const pluginInstalled = isValidInstalledPluginDir(pluginPath);
|
|
153
231
|
const agentsInstalled = packageRoot ? areCodexAgentsInstalled({ packageRoot, agentsPath }) : hasDefaultCodexAgents(agentsPath);
|
|
154
232
|
const marketplaceConfigured = isPluginConfiguredInMarketplace({
|
|
155
233
|
marketplacePath,
|
|
156
|
-
|
|
234
|
+
marketplaceRoot,
|
|
157
235
|
pluginPath
|
|
158
236
|
});
|
|
159
|
-
const
|
|
237
|
+
const legacyMarketplacePresent = hasLegacyPluginEntry({ userHome });
|
|
238
|
+
const ok = pluginInstalled && agentsInstalled && marketplaceConfigured && !legacyMarketplacePresent;
|
|
160
239
|
return {
|
|
161
240
|
ok,
|
|
162
241
|
action: "check",
|
|
163
242
|
plugin: PLUGIN_ID,
|
|
243
|
+
marketplaceName: MARKETPLACE_NAME,
|
|
244
|
+
marketplaceRoot,
|
|
164
245
|
codexHome,
|
|
165
246
|
agentsPath,
|
|
166
247
|
pluginPath,
|
|
167
248
|
marketplacePath,
|
|
168
249
|
pluginInstalled,
|
|
169
250
|
agentsInstalled,
|
|
170
|
-
marketplaceConfigured
|
|
251
|
+
marketplaceConfigured,
|
|
252
|
+
legacyMarketplacePresent
|
|
171
253
|
};
|
|
172
254
|
}
|
|
255
|
+
function hasLegacyPluginEntry({ userHome }) {
|
|
256
|
+
const legacyPath = getLegacyMarketplacePath(userHome);
|
|
257
|
+
if (!existsSync(legacyPath)) {
|
|
258
|
+
return false;
|
|
259
|
+
}
|
|
260
|
+
try {
|
|
261
|
+
const marketplace = readJsonFile(legacyPath);
|
|
262
|
+
return Array.isArray(marketplace?.plugins) && marketplace.plugins.some((plugin) => plugin?.name === PLUGIN_NAME);
|
|
263
|
+
} catch {
|
|
264
|
+
return false;
|
|
265
|
+
}
|
|
266
|
+
}
|
|
173
267
|
function getPackagePayloadPaths(packageRoot, packageJson) {
|
|
174
268
|
const relativePaths = new Set(packageJson.files ?? []);
|
|
175
269
|
relativePaths.add("package.json");
|
|
@@ -234,44 +328,30 @@ function hasDefaultCodexAgents(agentsPath) {
|
|
|
234
328
|
(agentFile) => existsSync(join(agentsPath, agentFile))
|
|
235
329
|
);
|
|
236
330
|
}
|
|
237
|
-
function
|
|
331
|
+
function writeMarketplaceManifest({
|
|
238
332
|
marketplacePath,
|
|
239
|
-
|
|
240
|
-
|
|
333
|
+
marketplaceRoot,
|
|
334
|
+
pluginPath
|
|
241
335
|
}) {
|
|
242
|
-
const marketplace = readJsonFile(marketplacePath, {});
|
|
243
|
-
if (marketplace.plugins !== void 0 && !Array.isArray(marketplace.plugins)) {
|
|
244
|
-
throw new Error(`Expected plugins array in ${marketplacePath}`);
|
|
245
|
-
}
|
|
246
|
-
const marketplacePluginPath = toMarketplaceSourcePath(userHome, pluginPath);
|
|
247
|
-
const nextPluginEntry = {
|
|
248
|
-
name: PLUGIN_NAME,
|
|
249
|
-
source: {
|
|
250
|
-
source: "local",
|
|
251
|
-
path: marketplacePluginPath
|
|
252
|
-
},
|
|
253
|
-
policy: {
|
|
254
|
-
installation: "AVAILABLE",
|
|
255
|
-
authentication: "ON_INSTALL"
|
|
256
|
-
},
|
|
257
|
-
category: "Productivity"
|
|
258
|
-
};
|
|
259
|
-
const plugins = marketplace.plugins ?? [];
|
|
260
|
-
const existingIndex = plugins.findIndex(
|
|
261
|
-
(plugin) => plugin?.name === PLUGIN_NAME
|
|
262
|
-
);
|
|
263
|
-
const nextPlugins = existingIndex === -1 ? [...plugins, nextPluginEntry] : plugins.map(
|
|
264
|
-
(plugin, index) => index === existingIndex ? nextPluginEntry : plugin
|
|
265
|
-
);
|
|
266
336
|
const nextMarketplace = {
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
337
|
+
name: MARKETPLACE_NAME,
|
|
338
|
+
interface: { displayName: MARKETPLACE_DISPLAY_NAME },
|
|
339
|
+
plugins: [
|
|
340
|
+
{
|
|
341
|
+
name: PLUGIN_NAME,
|
|
342
|
+
source: {
|
|
343
|
+
source: "local",
|
|
344
|
+
path: toMarketplaceSourcePath(marketplaceRoot, pluginPath)
|
|
345
|
+
},
|
|
346
|
+
policy: {
|
|
347
|
+
installation: "AVAILABLE",
|
|
348
|
+
authentication: "ON_INSTALL"
|
|
349
|
+
},
|
|
350
|
+
category: "Productivity"
|
|
351
|
+
}
|
|
352
|
+
]
|
|
274
353
|
};
|
|
354
|
+
const marketplace = readJsonFile(marketplacePath, null);
|
|
275
355
|
const changed = JSON.stringify(nextMarketplace) !== JSON.stringify(marketplace);
|
|
276
356
|
if (changed) {
|
|
277
357
|
writeJsonFile(marketplacePath, nextMarketplace);
|
|
@@ -280,13 +360,21 @@ function enablePluginInMarketplace({
|
|
|
280
360
|
}
|
|
281
361
|
function isPluginConfiguredInMarketplace({
|
|
282
362
|
marketplacePath,
|
|
283
|
-
|
|
363
|
+
marketplaceRoot,
|
|
284
364
|
pluginPath
|
|
285
365
|
}) {
|
|
286
366
|
if (!existsSync(marketplacePath)) {
|
|
287
367
|
return false;
|
|
288
368
|
}
|
|
289
|
-
|
|
369
|
+
let marketplace;
|
|
370
|
+
try {
|
|
371
|
+
marketplace = readJsonFile(marketplacePath);
|
|
372
|
+
} catch {
|
|
373
|
+
return false;
|
|
374
|
+
}
|
|
375
|
+
if (marketplace?.name !== MARKETPLACE_NAME) {
|
|
376
|
+
return false;
|
|
377
|
+
}
|
|
290
378
|
if (!Array.isArray(marketplace.plugins)) {
|
|
291
379
|
return false;
|
|
292
380
|
}
|
|
@@ -296,7 +384,7 @@ function isPluginConfiguredInMarketplace({
|
|
|
296
384
|
if (!isPlainObject(pluginEntry?.source) || pluginEntry.source.source !== "local") {
|
|
297
385
|
return false;
|
|
298
386
|
}
|
|
299
|
-
const configuredPath = resolve(
|
|
387
|
+
const configuredPath = resolve(marketplaceRoot, pluginEntry.source.path);
|
|
300
388
|
return configuredPath === resolve(pluginPath);
|
|
301
389
|
}
|
|
302
390
|
function readJsonFile(path, fallbackValue) {
|
|
@@ -341,11 +429,11 @@ function expandHome(inputPath, env) {
|
|
|
341
429
|
}
|
|
342
430
|
return inputPath;
|
|
343
431
|
}
|
|
344
|
-
function toMarketplaceSourcePath(
|
|
345
|
-
const relativePath = relative(
|
|
432
|
+
function toMarketplaceSourcePath(marketplaceRoot, targetPath) {
|
|
433
|
+
const relativePath = relative(marketplaceRoot, targetPath);
|
|
346
434
|
if (relativePath === "" || relativePath === "." || relativePath.startsWith(`..${sep}`) || relativePath === "..") {
|
|
347
435
|
throw new Error(
|
|
348
|
-
`Expected plugin install path ${targetPath} to be inside ${
|
|
436
|
+
`Expected plugin install path ${targetPath} to be inside ${marketplaceRoot} so it can be referenced from the marketplace manifest`
|
|
349
437
|
);
|
|
350
438
|
}
|
|
351
439
|
return `./${relativePath.split(sep).join("/")}`;
|
|
@@ -360,8 +448,10 @@ var usage = `Usage:
|
|
|
360
448
|
npx @polygraph/codex-plugin install [--force] [--json]
|
|
361
449
|
npx @polygraph/codex-plugin check [--json]
|
|
362
450
|
|
|
363
|
-
The install command materializes the plugin payload
|
|
364
|
-
|
|
451
|
+
The install command materializes the plugin payload into the marketplace Polygraph
|
|
452
|
+
owns (~/.polygraph/codex-marketplace) and registers that marketplace with codex.
|
|
453
|
+
It does not write to the shared ~/.agents/plugins/marketplace.json. After running
|
|
454
|
+
install, run:
|
|
365
455
|
|
|
366
456
|
codex plugin add polygraph@polygraph-plugins
|
|
367
457
|
|
|
@@ -408,17 +498,30 @@ ${usage}`);
|
|
|
408
498
|
} else {
|
|
409
499
|
const pluginState = result.pluginInstalled ? "plugin files present" : "plugin files not present";
|
|
410
500
|
const agentsState = result.agentsInstalled ? "agents installed" : "agents not installed";
|
|
411
|
-
const marketplaceState = result.marketplaceConfigured ?
|
|
501
|
+
const marketplaceState = result.marketplaceConfigured ? `plugin published from the ${result.marketplaceName} marketplace` : `plugin not published from the ${result.marketplaceName} marketplace`;
|
|
502
|
+
const legacyState = result.legacyMarketplacePresent ? "; a stale entry remains in ~/.agents/plugins/marketplace.json (re-run install to clear it)" : "";
|
|
412
503
|
console.error(
|
|
413
|
-
`Polygraph Codex plugin check failed: ${pluginState}; ${agentsState}; ${marketplaceState}.`
|
|
504
|
+
`Polygraph Codex plugin check failed: ${pluginState}; ${agentsState}; ${marketplaceState}${legacyState}.`
|
|
414
505
|
);
|
|
415
506
|
}
|
|
416
507
|
} else {
|
|
417
508
|
console.log(`Materialized Polygraph Codex plugin ${result.version}.`);
|
|
418
509
|
console.log(`Plugin path: ${result.pluginPath}`);
|
|
419
510
|
console.log(`Agents: ${result.agentsPath}`);
|
|
420
|
-
console.log(`Marketplace: ${result.
|
|
421
|
-
|
|
511
|
+
console.log(`Marketplace: ${result.marketplaceName} (${result.marketplaceRoot})`);
|
|
512
|
+
if (result.legacyEntryRemoved) {
|
|
513
|
+
console.log(
|
|
514
|
+
result.legacyMarketplaceRemoved ? "Removed the obsolete ~/.agents/plugins/marketplace.json written by an earlier version." : "Removed the obsolete polygraph entry from ~/.agents/plugins/marketplace.json; your other plugins were left untouched."
|
|
515
|
+
);
|
|
516
|
+
}
|
|
517
|
+
if (result.marketplaceRegistered) {
|
|
518
|
+
console.log(`Next step: codex plugin add ${result.plugin}`);
|
|
519
|
+
} else {
|
|
520
|
+
console.warn(`Warning: ${result.marketplaceRegistrationError}`);
|
|
521
|
+
console.warn(
|
|
522
|
+
`Then run: codex plugin add ${result.plugin}`
|
|
523
|
+
);
|
|
524
|
+
}
|
|
422
525
|
}
|
|
423
526
|
if (command === "check" && !result.ok) {
|
|
424
527
|
process.exitCode = 1;
|
package/package.json
CHANGED