codex-plugin-doctor 1.77.0 → 1.78.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/README.md +5 -2
- package/dist/core/init-ci.d.ts +1 -0
- package/dist/core/init-ci.js +16 -2
- package/dist/run-cli.js +20 -10
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -186,6 +186,9 @@ server with `--server <name> --runtime`, without retrieving any prompt.
|
|
|
186
186
|
`doctor prompts-file` inspects a saved list offline, and `doctor prompts-diff`
|
|
187
187
|
labels a removed prompt, a removed argument, or a newly required argument as
|
|
188
188
|
breaking. Like the tool diff, reports omit names unless `--show-names` is given.
|
|
189
|
+
The GitHub Action runs the same capture and comparison through `prompts-*`
|
|
190
|
+
inputs and comments on pull requests, and
|
|
191
|
+
`init-ci --tools-diff-server <name> --prompts-baseline <path>` writes that workflow.
|
|
189
192
|
See [MCP Prompt Catalog and Diff](docs/guides/mcp-prompts.md).
|
|
190
193
|
|
|
191
194
|
### Remote MCP Readiness
|
|
@@ -606,9 +609,9 @@ jobs:
|
|
|
606
609
|
runs-on: ubuntu-latest
|
|
607
610
|
steps:
|
|
608
611
|
- uses: actions/checkout@v5
|
|
609
|
-
- uses: Esquetta/CodexPluginDoctor@v1.
|
|
612
|
+
- uses: Esquetta/CodexPluginDoctor@v1.78.0
|
|
610
613
|
with:
|
|
611
|
-
version: "1.
|
|
614
|
+
version: "1.78.0"
|
|
612
615
|
path: .
|
|
613
616
|
runtime: "true"
|
|
614
617
|
policy: codex-publish
|
package/dist/core/init-ci.d.ts
CHANGED
|
@@ -6,6 +6,7 @@ export interface ToolsDiffWorkflowOptions {
|
|
|
6
6
|
server: string;
|
|
7
7
|
baseline: string;
|
|
8
8
|
sandbox: "docker" | null;
|
|
9
|
+
promptsBaseline: string | null;
|
|
9
10
|
}
|
|
10
11
|
export declare function initToolsDiffWorkflow(targetPath: string, options: ToolsDiffWorkflowOptions): Promise<InitCiResult>;
|
|
11
12
|
export declare function initCiWorkflow(targetPath: string): Promise<InitCiResult>;
|
package/dist/core/init-ci.js
CHANGED
|
@@ -66,6 +66,11 @@ function buildToolsDiffWorkflow(options) {
|
|
|
66
66
|
...(options.sandbox === "docker" ? [" tools-capture-sandbox: docker"] : []),
|
|
67
67
|
" # Catalog findings do not fail this job; the compare job re-checks the saved list.",
|
|
68
68
|
" tools-capture-defer-findings: \"true\"",
|
|
69
|
+
...(options.promptsBaseline === null ? [] : [
|
|
70
|
+
` prompts-capture-server: ${yamlString(options.server)}`,
|
|
71
|
+
...(options.sandbox === "docker" ? [" prompts-capture-sandbox: docker"] : []),
|
|
72
|
+
" prompts-capture-defer-findings: \"true\""
|
|
73
|
+
]),
|
|
69
74
|
" artifact-name: mcp-tools-capture",
|
|
70
75
|
"",
|
|
71
76
|
" compare:",
|
|
@@ -91,6 +96,12 @@ function buildToolsDiffWorkflow(options) {
|
|
|
91
96
|
" tools-diff-after: ${{ runner.temp }}/mcp-tools-capture/mcp-tools-current.json",
|
|
92
97
|
" tools-diff-fail-on: breaking",
|
|
93
98
|
" tools-diff-comment: \"true\"",
|
|
99
|
+
...(options.promptsBaseline === null ? [] : [
|
|
100
|
+
` prompts-diff-before: ${yamlString(options.promptsBaseline)}`,
|
|
101
|
+
" prompts-diff-after: ${{ runner.temp }}/mcp-tools-capture/mcp-prompts-current.json",
|
|
102
|
+
" prompts-diff-fail-on: breaking",
|
|
103
|
+
" prompts-diff-comment: \"true\""
|
|
104
|
+
]),
|
|
94
105
|
" output-dir: ${{ runner.temp }}/codex-plugin-doctor-reports",
|
|
95
106
|
" artifact-name: mcp-tools-diff",
|
|
96
107
|
""
|
|
@@ -101,8 +112,11 @@ export async function initToolsDiffWorkflow(targetPath, options) {
|
|
|
101
112
|
const workflowPath = path.join(rootPath, ".github", "workflows", "codex-plugin-doctor-tools.yml");
|
|
102
113
|
await mkdir(path.dirname(workflowPath), { recursive: true });
|
|
103
114
|
await writeFile(workflowPath, buildToolsDiffWorkflow(options), "utf8");
|
|
104
|
-
// doctor tools --save-response writes into an existing directory, so the
|
|
105
|
-
|
|
115
|
+
// doctor tools --save-response writes into an existing directory, so the baselines can be captured next.
|
|
116
|
+
for (const baseline of [options.baseline, options.promptsBaseline]) {
|
|
117
|
+
if (baseline !== null)
|
|
118
|
+
await mkdir(path.dirname(path.resolve(rootPath, baseline)), { recursive: true });
|
|
119
|
+
}
|
|
106
120
|
return { rootPath, workflowPath };
|
|
107
121
|
}
|
|
108
122
|
export async function initCiWorkflow(targetPath) {
|
package/dist/run-cli.js
CHANGED
|
@@ -129,11 +129,11 @@ const PROMPT_CATALOG_COMMAND = { name: "prompts", noun: "Prompt", method: "promp
|
|
|
129
129
|
const discoveryUsage = "Usage: codex-plugin-doctor doctor discover <url> --allow-network [--allow-local-network] [--json] [--bearer-token-env <NAME>]";
|
|
130
130
|
const bearerTokenHelp = "--bearer-token-env reads a bearer token from the named environment variable and sends it only over HTTPS or to an approved loopback target; the token is never printed or saved.";
|
|
131
131
|
const ENVIRONMENT_VARIABLE_NAME = /^[A-Za-z_][A-Za-z0-9_]*$/u;
|
|
132
|
-
/** Reads init-ci --tools-diff-server, --baseline, and --sandbox; options is null when none is given. */
|
|
132
|
+
/** Reads init-ci --tools-diff-server, --baseline, --prompts-baseline, and --sandbox; options is null when none is given. */
|
|
133
133
|
function parseToolsDiffWorkflowOptions(flags) {
|
|
134
134
|
const values = new Map();
|
|
135
135
|
for (let index = 0; index < flags.length; index += 1) {
|
|
136
|
-
if (!["--tools-diff-server", "--baseline", "--sandbox"].includes(flags[index]))
|
|
136
|
+
if (!["--tools-diff-server", "--baseline", "--prompts-baseline", "--sandbox"].includes(flags[index]))
|
|
137
137
|
continue;
|
|
138
138
|
const value = flags[index + 1];
|
|
139
139
|
const present = value !== undefined && !value.startsWith("--");
|
|
@@ -144,7 +144,7 @@ function parseToolsDiffWorkflowOptions(flags) {
|
|
|
144
144
|
if (values.size === 0)
|
|
145
145
|
return { options: null };
|
|
146
146
|
if (!values.has("--tools-diff-server"))
|
|
147
|
-
return { error: "--baseline and --sandbox require --tools-diff-server." };
|
|
147
|
+
return { error: "--baseline, --prompts-baseline, and --sandbox require --tools-diff-server." };
|
|
148
148
|
// Control characters would break the generated workflow lines, GitHub evaluates "${{" in any
|
|
149
149
|
// workflow value, and the Action rejects values that start with "-".
|
|
150
150
|
const usable = (value) => value !== undefined && value.trim() !== "" && !value.startsWith("-") && !value.includes("${{")
|
|
@@ -152,16 +152,23 @@ function parseToolsDiffWorkflowOptions(flags) {
|
|
|
152
152
|
const server = values.get("--tools-diff-server");
|
|
153
153
|
if (!usable(server))
|
|
154
154
|
return { error: "--tools-diff-server requires a server name." };
|
|
155
|
-
// The workflow runs on Linux from the repository root, so
|
|
155
|
+
// The workflow runs on Linux from the repository root, so baselines are relative POSIX paths.
|
|
156
|
+
const relative = (value) => usable(value) && !path.posix.isAbsolute(value)
|
|
157
|
+
&& !/^[A-Za-z]:/u.test(value) && !path.posix.normalize(value).split("/").includes("..");
|
|
156
158
|
const baseline = (values.has("--baseline") ? values.get("--baseline") : "mcp/tools-baseline.json")?.replaceAll("\\", "/");
|
|
157
|
-
if (!
|
|
158
|
-
|| path.posix.normalize(baseline).split("/").includes("..")) {
|
|
159
|
+
if (!relative(baseline))
|
|
159
160
|
return { error: "--baseline requires a relative path inside the repository." };
|
|
161
|
+
const promptsBaseline = values.has("--prompts-baseline") ? values.get("--prompts-baseline")?.replaceAll("\\", "/") : null;
|
|
162
|
+
if (promptsBaseline !== null && !relative(promptsBaseline)) {
|
|
163
|
+
return { error: "--prompts-baseline requires a relative path inside the repository." };
|
|
164
|
+
}
|
|
165
|
+
if (promptsBaseline !== null && path.posix.normalize(promptsBaseline) === path.posix.normalize(baseline)) {
|
|
166
|
+
return { error: "--prompts-baseline must differ from --baseline." };
|
|
160
167
|
}
|
|
161
168
|
const sandbox = values.get("--sandbox");
|
|
162
169
|
if (values.has("--sandbox") && sandbox !== "docker")
|
|
163
170
|
return { error: "--sandbox must be docker." };
|
|
164
|
-
return { options: { server, baseline, sandbox: sandbox === "docker" ? "docker" : null } };
|
|
171
|
+
return { options: { server, baseline, sandbox: sandbox === "docker" ? "docker" : null, promptsBaseline } };
|
|
165
172
|
}
|
|
166
173
|
const MAX_FORWARDED_ENVIRONMENT_VARIABLES = 32;
|
|
167
174
|
const forwardedEnvironmentHelp = "--env forwards the named host environment variable into the Docker sandbox by name; Doctor never prints its value, writes it to a report, or passes it as a command argument. Native servers already inherit Doctor's environment.";
|
|
@@ -509,7 +516,7 @@ function parseRemoteNetworkFlags(flags, runtime) {
|
|
|
509
516
|
return { allowNetwork, allowLocalNetwork, allowSessionLifecycle, requireRemoteReliability };
|
|
510
517
|
}
|
|
511
518
|
function printUsage(io) {
|
|
512
|
-
io.writeStderr("Usage: codex-plugin-doctor check <path|--installed> [filter] [--policy codex-publish|mcp-strict|security] [--compat] [--json|--markdown|--badge-json|--badge-markdown] [--output <path>] [--history <path>] [--runtime [--allow-network [--allow-local-network]]] [--sandbox docker] [--require-runtime-approval --runtime-approval-digest <digest>] [--verbose-runtime] [--explain] [--no-animations] [--ascii] [--changed-since <ref>] [--fail-on <rule-id>]\n codex-plugin-doctor audit --installed [filter] [--policy codex-publish|mcp-strict|security] [--security] [--compat] [--json] [--output <path>] [--cache] [--changed]\n codex-plugin-doctor audit deps <path> [--policy codex-publish|mcp-strict|security] [--recommend] [--json|--sarif] [--output <path>]\n codex-plugin-doctor mcp <path> [--runtime [--allow-network [--allow-local-network]]] [--json] [--output <path>]\n codex-plugin-doctor security <path> [--policy security] [--json|--scorecard]\n codex-plugin-doctor compat <path> [--all|--client <client>] [--json] [--scorecard] [--output <path>] [--install-preview|--apply --backup]\n codex-plugin-doctor suppress add <path> [--fingerprint <sha256> --reason <text> --expires-at YYYY-MM-DD] [--config <path>] [--json]\n codex-plugin-doctor suppress list <path> [--config <path>] [--json]\n codex-plugin-doctor suppress remove <path> [--fingerprint <sha256>|--index <n>] [--config <path>] [--json]\n codex-plugin-doctor fix <path> (--dry-run|--interactive --backup|--apply --backup)\n codex-plugin-doctor history <history.jsonl> [--json] [--fail-on-regression]\n codex-plugin-doctor watch <path> [--runtime] [--json] [--output <path>] [--debounce-ms <ms>] [--max-iterations <n>] [--fail-fast] [--accumulate-json <path>]\n codex-plugin-doctor doctor [npm <package>|contract|corpus [--manifest <corpus.json>] [--json] [--output <path>]|corpus metrics --manifest <corpus.json> [--json|--markdown] [--output <path>] [--min-precision <0..1>] [--min-recall <0..1>] [--max-false-positive-rate <0..1>]|runtime-plan <path> [--sandbox docker] [--json|--markdown] [--output <path>]|runtime-policy <path> [--sandbox docker] [--json] [--output <path>]|review-bundle <path> --output <dir> --sign-key-env NAME [--json] [--allow-dirty] [--allow-untagged]|review-bundle verify <bundle-dir> --target <path> --sign-key-env NAME [--json] [--output <path>] [--failures-only]|review-bundle diff --before <dir> --after <dir> [--json]|attest <path> [--sign-key-env NAME]|attest verify <attestation.json> --target <path> --sign-key-env NAME|release-evidence <path> --sign-key-env NAME [--runtime [--allow-network [--allow-local-network]]] [--sandbox docker] [--allow-dirty] [--allow-untagged] [--require-runtime-approval --runtime-approval-digest <digest>]|release-evidence verify <evidence.json> --target <path> --sign-key-env NAME|release-evidence asset <path> --tag <tag> --output <evidence.json> --sign-key-env NAME [--runtime [--allow-network [--allow-local-network]]] [--sandbox docker] [--allow-dirty] [--allow-untagged] [--require-runtime-approval --runtime-approval-digest <digest>] [--upload]|mcp <path> [--runtime [--allow-network [--allow-local-network]]]|inspector <path>|diff --before <path> --after <path>|recommend <path>|trust <path>|perf <path> [--max-total-ms <ms>] [--max-stage-ms stage=ms]|export --bundle <path>|snapshot|clients|--json|--update-check]\n codex-plugin-doctor init [path] [--template skill-only|mcp-stdio|mcp-http|full-runtime]\n codex-plugin-doctor init-ci [path] [--tools-diff-server <name> [--baseline <path>] [--sandbox docker]]\n codex-plugin-doctor init-git-hooks [path] [--force] [--json]\n codex-plugin-doctor init-git-hooks [path] --remove [--json]\n codex-plugin-doctor completion bash|zsh|fish\n codex-plugin-doctor config validate <path> [--json]\n codex-plugin-doctor release check <path> [--json] [--runtime [--allow-network [--allow-local-network]]] [--sandbox docker]\n codex-plugin-doctor self-test\n codex-plugin-doctor list --installed\n codex-plugin-doctor explain <finding-id>\n codex-plugin-doctor --version\n\nFirst run:\n codex-plugin-doctor doctor\n codex-plugin-doctor self-test\n codex-plugin-doctor init my-plugin\n codex-plugin-doctor check . --runtime --explain");
|
|
519
|
+
io.writeStderr("Usage: codex-plugin-doctor check <path|--installed> [filter] [--policy codex-publish|mcp-strict|security] [--compat] [--json|--markdown|--badge-json|--badge-markdown] [--output <path>] [--history <path>] [--runtime [--allow-network [--allow-local-network]]] [--sandbox docker] [--require-runtime-approval --runtime-approval-digest <digest>] [--verbose-runtime] [--explain] [--no-animations] [--ascii] [--changed-since <ref>] [--fail-on <rule-id>]\n codex-plugin-doctor audit --installed [filter] [--policy codex-publish|mcp-strict|security] [--security] [--compat] [--json] [--output <path>] [--cache] [--changed]\n codex-plugin-doctor audit deps <path> [--policy codex-publish|mcp-strict|security] [--recommend] [--json|--sarif] [--output <path>]\n codex-plugin-doctor mcp <path> [--runtime [--allow-network [--allow-local-network]]] [--json] [--output <path>]\n codex-plugin-doctor security <path> [--policy security] [--json|--scorecard]\n codex-plugin-doctor compat <path> [--all|--client <client>] [--json] [--scorecard] [--output <path>] [--install-preview|--apply --backup]\n codex-plugin-doctor suppress add <path> [--fingerprint <sha256> --reason <text> --expires-at YYYY-MM-DD] [--config <path>] [--json]\n codex-plugin-doctor suppress list <path> [--config <path>] [--json]\n codex-plugin-doctor suppress remove <path> [--fingerprint <sha256>|--index <n>] [--config <path>] [--json]\n codex-plugin-doctor fix <path> (--dry-run|--interactive --backup|--apply --backup)\n codex-plugin-doctor history <history.jsonl> [--json] [--fail-on-regression]\n codex-plugin-doctor watch <path> [--runtime] [--json] [--output <path>] [--debounce-ms <ms>] [--max-iterations <n>] [--fail-fast] [--accumulate-json <path>]\n codex-plugin-doctor doctor [npm <package>|contract|corpus [--manifest <corpus.json>] [--json] [--output <path>]|corpus metrics --manifest <corpus.json> [--json|--markdown] [--output <path>] [--min-precision <0..1>] [--min-recall <0..1>] [--max-false-positive-rate <0..1>]|runtime-plan <path> [--sandbox docker] [--json|--markdown] [--output <path>]|runtime-policy <path> [--sandbox docker] [--json] [--output <path>]|review-bundle <path> --output <dir> --sign-key-env NAME [--json] [--allow-dirty] [--allow-untagged]|review-bundle verify <bundle-dir> --target <path> --sign-key-env NAME [--json] [--output <path>] [--failures-only]|review-bundle diff --before <dir> --after <dir> [--json]|attest <path> [--sign-key-env NAME]|attest verify <attestation.json> --target <path> --sign-key-env NAME|release-evidence <path> --sign-key-env NAME [--runtime [--allow-network [--allow-local-network]]] [--sandbox docker] [--allow-dirty] [--allow-untagged] [--require-runtime-approval --runtime-approval-digest <digest>]|release-evidence verify <evidence.json> --target <path> --sign-key-env NAME|release-evidence asset <path> --tag <tag> --output <evidence.json> --sign-key-env NAME [--runtime [--allow-network [--allow-local-network]]] [--sandbox docker] [--allow-dirty] [--allow-untagged] [--require-runtime-approval --runtime-approval-digest <digest>] [--upload]|mcp <path> [--runtime [--allow-network [--allow-local-network]]]|inspector <path>|diff --before <path> --after <path>|recommend <path>|trust <path>|perf <path> [--max-total-ms <ms>] [--max-stage-ms stage=ms]|export --bundle <path>|snapshot|clients|--json|--update-check]\n codex-plugin-doctor init [path] [--template skill-only|mcp-stdio|mcp-http|full-runtime]\n codex-plugin-doctor init-ci [path] [--tools-diff-server <name> [--baseline <path>] [--prompts-baseline <path>] [--sandbox docker]]\n codex-plugin-doctor init-git-hooks [path] [--force] [--json]\n codex-plugin-doctor init-git-hooks [path] --remove [--json]\n codex-plugin-doctor completion bash|zsh|fish\n codex-plugin-doctor config validate <path> [--json]\n codex-plugin-doctor release check <path> [--json] [--runtime [--allow-network [--allow-local-network]]] [--sandbox docker]\n codex-plugin-doctor self-test\n codex-plugin-doctor list --installed\n codex-plugin-doctor explain <finding-id>\n codex-plugin-doctor --version\n\nFirst run:\n codex-plugin-doctor doctor\n codex-plugin-doctor self-test\n codex-plugin-doctor init my-plugin\n codex-plugin-doctor check . --runtime --explain");
|
|
513
520
|
io.writeStderr(discoveryUsage);
|
|
514
521
|
io.writeStderr(toolsUsage);
|
|
515
522
|
io.writeStderr(promptsUsage);
|
|
@@ -2882,13 +2889,16 @@ export async function runCli(args, io = defaultIo, options = {}) {
|
|
|
2882
2889
|
return 2;
|
|
2883
2890
|
}
|
|
2884
2891
|
if (toolsDiff.options !== null) {
|
|
2885
|
-
const { server, baseline, sandbox } = toolsDiff.options;
|
|
2892
|
+
const { server, baseline, sandbox, promptsBaseline } = toolsDiff.options;
|
|
2886
2893
|
const toolsResult = await initToolsDiffWorkflow(targetPath, toolsDiff.options);
|
|
2887
2894
|
io.writeStdout([
|
|
2888
2895
|
"Initialized Codex Plugin Doctor tool diff workflow",
|
|
2889
2896
|
`Root: ${toolsResult.rootPath}`,
|
|
2890
2897
|
`Workflow: ${toolsResult.workflowPath}`,
|
|
2891
|
-
`Capture and commit a baseline at ${baseline}, for example with: codex-plugin-doctor doctor tools ${JSON.stringify(targetPath)} --server ${JSON.stringify(server)} --runtime${sandbox === "docker" ? " --sandbox docker" : ""} --save-response ${JSON.stringify(path.join(targetPath, baseline))}
|
|
2898
|
+
`Capture and commit a baseline at ${baseline}, for example with: codex-plugin-doctor doctor tools ${JSON.stringify(targetPath)} --server ${JSON.stringify(server)} --runtime${sandbox === "docker" ? " --sandbox docker" : ""} --save-response ${JSON.stringify(path.join(targetPath, baseline))}`,
|
|
2899
|
+
...(promptsBaseline === null ? [] : [
|
|
2900
|
+
`Capture and commit a prompt baseline at ${promptsBaseline}, for example with: codex-plugin-doctor doctor prompts ${JSON.stringify(targetPath)} --server ${JSON.stringify(server)} --runtime${sandbox === "docker" ? " --sandbox docker" : ""} --save-response ${JSON.stringify(path.join(targetPath, promptsBaseline))}`
|
|
2901
|
+
])
|
|
2892
2902
|
].join("\n"));
|
|
2893
2903
|
return 0;
|
|
2894
2904
|
}
|
package/package.json
CHANGED