Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,23 @@ All notable changes to `codex-plugin-doctor` are documented here.

This changelog groups the shipped work into product-level release blocks instead of repeating every low-level git diff in isolation.

## [1.60.0] - 2026-08-25

### Added

- added existing-ZIP Submission Archive Preflight reports through the CLI, JSON and Markdown output contracts, and opt-in GitHub Action archive inputs and reports
- added bounded no-extraction ZIP validation for the submission archive layout and supported skill metadata

### Changed

- archive blockers remain advisory by default and `--require-ready` enables strict readiness gating; MCP, app, and screenshot exclusions remain warnings for manual review
- kept directory submission preflight behavior unchanged

### Security

- validate stored and deflate ZIP entries with full safety passes for CRC, size, ZIP64, descriptors, paths, entry types, overlaps, and resource budgets
- keep archive preflight offline and non-executing: it performs no extraction, process execution, or network access and redacts paths and content from reports

## [1.59.0] - 2026-08-17

### Added
Expand Down
10 changes: 8 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -143,10 +143,16 @@ codex-plugin-doctor doctor submission <path>
codex-plugin-doctor doctor submission <path> --json
codex-plugin-doctor doctor submission <path> --markdown
codex-plugin-doctor doctor submission <path> --require-ready
codex-plugin-doctor doctor submission archive <zip>
codex-plugin-doctor doctor submission archive <zip> --json --output submission-archive.json
codex-plugin-doctor doctor submission archive <zip> --markdown --output submission-archive.md
codex-plugin-doctor doctor submission archive <zip> --require-ready
```

The preflight is offline and non-executing: it does not submit a package, make network requests, start MCP servers, verify domains, or handle OAuth credentials. Its automatic `status` is `pass` or `fail`; a passing automatic result remains `manual_review_required` until portal-only review is complete. It never claims directory acceptance. See [Public Directory Submission Preflight](./docs/architecture/public-directory-submission-preflight.md).

The archive variant accepts an existing skills-only ZIP and does not extract archive entries to disk, execute package code, or repair the archive. It reports malformed ZIP structures and deterministic package blockers; unsupported portal rules remain manual or `coverage: unavailable` rather than an automatic pass.

Output formats:

- human text output
Expand Down Expand Up @@ -493,9 +499,9 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: Esquetta/CodexPluginDoctor@v1.59.0
- uses: Esquetta/CodexPluginDoctor@v1.60.0
with:
version: "1.59.0"
version: "1.60.0"
path: .
runtime: "true"
policy: codex-publish
Expand Down
55 changes: 52 additions & 3 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ inputs:
description: Generate offline public directory submission preflight JSON and Markdown reports.
required: false
default: "false"
submission-archive:
description: Optional existing ZIP path for offline skills-only archive submission preflight reports.
required: false
default: ""
require-submission-ready:
description: Fail unless the offline submission preflight is automatically ready; this does not replace manual review.
required: false
Expand Down Expand Up @@ -183,6 +187,12 @@ outputs:
submission-summary-path:
description: Path to the offline submission preflight Markdown report when submission is enabled.
value: ${{ steps.run-doctor.outputs.submission-summary-path }}
submission-archive-json-path:
description: Path to the offline archive submission preflight JSON report when submission-archive is configured.
value: ${{ steps.run-doctor.outputs.submission-archive-json-path }}
submission-archive-summary-path:
description: Path to the offline archive submission preflight Markdown report when submission-archive is configured.
value: ${{ steps.run-doctor.outputs.submission-archive-summary-path }}
review-bundle-path:
description: Path to the generated review bundle directory when review-bundle is enabled.
value: ${{ steps.run-doctor.outputs.review-bundle-path }}
Expand All @@ -208,6 +218,7 @@ runs:
REGISTRY_METADATA_INPUT: ${{ inputs['registry-metadata'] }}
REQUIRE_REGISTRY_READINESS_INPUT: ${{ inputs['require-registry-readiness'] }}
SUBMISSION_INPUT: ${{ inputs.submission }}
SUBMISSION_ARCHIVE_INPUT: ${{ inputs['submission-archive'] }}
REQUIRE_SUBMISSION_READY_INPUT: ${{ inputs['require-submission-ready'] }}
CORPUS_METRICS_MANIFEST_INPUT: ${{ inputs['corpus-metrics-manifest'] }}
CORPUS_METRICS_BASELINE_INPUT: ${{ inputs['corpus-metrics-baseline'] }}
Expand All @@ -227,14 +238,20 @@ runs:
registry_report_path="$report_dir/mcp-registry-readiness.json"
submission_json_path="$report_dir/codex-plugin-doctor-submission.json"
submission_summary_path="$report_dir/codex-plugin-doctor-submission.md"
submission_archive_json_path="$report_dir/codex-plugin-doctor-submission-archive.json"
submission_archive_summary_path="$report_dir/codex-plugin-doctor-submission-archive.md"
review_bundle_path="$report_dir/${{ inputs['review-bundle-dir'] }}"
review_bundle_verification_path="$report_dir/review-bundle-verification.json"
status_file="${RUNNER_TEMP:-.}/codex-plugin-doctor-status"
submission_state_file="${RUNNER_TEMP:-.}/codex-plugin-doctor-submission-ran"
submission_archive_state_file="${RUNNER_TEMP:-.}/codex-plugin-doctor-submission-archive-ran"
status=0
submission_ran=false
submission_archive_ran=false
submission_json_output=""
submission_summary_output=""
submission_archive_json_output=""
submission_archive_summary_output=""
doctor_version="$(codex-plugin-doctor --version)"

mkdir -p "$report_dir"
Expand Down Expand Up @@ -370,8 +387,11 @@ runs:
run_doctor "MCP Registry readiness" "${registry_args[@]}"
fi

if [[ "$REQUIRE_SUBMISSION_READY_INPUT" == "true" && "$SUBMISSION_INPUT" != "true" ]]; then
echo "require-submission-ready requires submission." >&2
if [[ "$SUBMISSION_INPUT" == "true" && -n "$SUBMISSION_ARCHIVE_INPUT" ]]; then
echo "submission and submission-archive cannot be selected together." >&2
record_status 2
elif [[ "$REQUIRE_SUBMISSION_READY_INPUT" == "true" && "$SUBMISSION_INPUT" != "true" && -z "$SUBMISSION_ARCHIVE_INPUT" ]]; then
echo "require-submission-ready requires exactly one submission mode." >&2
record_status 2
elif [[ "$SUBMISSION_INPUT" == "true" && "${{ inputs.installed }}" == "true" ]]; then
echo "Submission preflight requires a single package path, not installed-cache mode." >&2
Expand All @@ -386,6 +406,16 @@ runs:
run_doctor "submission summary" doctor submission "${{ inputs.path }}" --markdown --output "$submission_summary_path"
submission_json_output="$submission_json_path"
submission_summary_output="$submission_summary_path"
elif [[ -n "$SUBMISSION_ARCHIVE_INPUT" ]]; then
submission_archive_ran=true
submission_archive_args=(doctor submission archive "$SUBMISSION_ARCHIVE_INPUT" --json --output "$submission_archive_json_path")
if [[ "$REQUIRE_SUBMISSION_READY_INPUT" == "true" ]]; then
submission_archive_args+=(--require-ready)
fi
run_doctor "submission archive preflight" "${submission_archive_args[@]}"
run_doctor "submission archive summary" doctor submission archive "$SUBMISSION_ARCHIVE_INPUT" --markdown --output "$submission_archive_summary_path"
submission_archive_json_output="$submission_archive_json_path"
submission_archive_summary_output="$submission_archive_summary_path"
fi

if [[ "${{ inputs['review-bundle'] }}" == "true" ]]; then
Expand Down Expand Up @@ -436,6 +466,7 @@ runs:
export CODEX_PLUGIN_DOCTOR_ACTION_CONTRACT="${{ inputs.contract }}"
export CODEX_PLUGIN_DOCTOR_ACTION_REGISTRY="$([[ -n "$REGISTRY_METADATA_INPUT" ]] && echo true || echo false)"
export CODEX_PLUGIN_DOCTOR_ACTION_SUBMISSION="$submission_ran"
export CODEX_PLUGIN_DOCTOR_ACTION_SUBMISSION_ARCHIVE="$submission_archive_ran"
export CODEX_PLUGIN_DOCTOR_ACTION_REVIEW_BUNDLE="${{ inputs['review-bundle'] }}"
export CODEX_PLUGIN_DOCTOR_ACTION_REVIEW_BUNDLE_VERIFY="${{ inputs['review-bundle-verify'] }}"
export CODEX_PLUGIN_DOCTOR_ACTION_SUMMARY_PATH="$summary_path"
Expand All @@ -448,6 +479,8 @@ runs:
export CODEX_PLUGIN_DOCTOR_ACTION_REGISTRY_PATH="$registry_report_path"
export CODEX_PLUGIN_DOCTOR_ACTION_SUBMISSION_JSON_PATH="$submission_json_output"
export CODEX_PLUGIN_DOCTOR_ACTION_SUBMISSION_SUMMARY_PATH="$submission_summary_output"
export CODEX_PLUGIN_DOCTOR_ACTION_SUBMISSION_ARCHIVE_JSON_PATH="$submission_archive_json_output"
export CODEX_PLUGIN_DOCTOR_ACTION_SUBMISSION_ARCHIVE_SUMMARY_PATH="$submission_archive_summary_output"
export CODEX_PLUGIN_DOCTOR_ACTION_REVIEW_BUNDLE_PATH="$review_bundle_path"
export CODEX_PLUGIN_DOCTOR_ACTION_REVIEW_BUNDLE_VERIFICATION_PATH="$review_bundle_verification_path"
node <<'NODE'
Expand Down Expand Up @@ -487,6 +520,8 @@ runs:
registryReport: report("registryReport", "CODEX_PLUGIN_DOCTOR_ACTION_REGISTRY", "CODEX_PLUGIN_DOCTOR_ACTION_REGISTRY_PATH"),
submissionJson: report("submissionJson", "CODEX_PLUGIN_DOCTOR_ACTION_SUBMISSION", "CODEX_PLUGIN_DOCTOR_ACTION_SUBMISSION_JSON_PATH"),
submissionSummary: report("submissionSummary", "CODEX_PLUGIN_DOCTOR_ACTION_SUBMISSION", "CODEX_PLUGIN_DOCTOR_ACTION_SUBMISSION_SUMMARY_PATH"),
submissionArchiveJson: report("submissionArchiveJson", "CODEX_PLUGIN_DOCTOR_ACTION_SUBMISSION_ARCHIVE", "CODEX_PLUGIN_DOCTOR_ACTION_SUBMISSION_ARCHIVE_JSON_PATH"),
submissionArchiveSummary: report("submissionArchiveSummary", "CODEX_PLUGIN_DOCTOR_ACTION_SUBMISSION_ARCHIVE", "CODEX_PLUGIN_DOCTOR_ACTION_SUBMISSION_ARCHIVE_SUMMARY_PATH"),
reviewBundle: report("reviewBundle", "CODEX_PLUGIN_DOCTOR_ACTION_REVIEW_BUNDLE", "CODEX_PLUGIN_DOCTOR_ACTION_REVIEW_BUNDLE_PATH"),
reviewBundleVerification: report("reviewBundleVerification", "CODEX_PLUGIN_DOCTOR_ACTION_REVIEW_BUNDLE_VERIFY", "CODEX_PLUGIN_DOCTOR_ACTION_REVIEW_BUNDLE_VERIFICATION_PATH")
}
Expand All @@ -501,6 +536,7 @@ runs:

printf "%s" "$status" > "$status_file"
printf "%s" "$submission_ran" > "$submission_state_file"
printf "%s" "$submission_archive_ran" > "$submission_archive_state_file"

{
echo "status=$status"
Expand All @@ -516,6 +552,8 @@ runs:
echo "registry-report-path=$registry_report_path"
echo "submission-json-path=$submission_json_output"
echo "submission-summary-path=$submission_summary_output"
echo "submission-archive-json-path=$submission_archive_json_output"
echo "submission-archive-summary-path=$submission_archive_summary_output"
echo "review-bundle-path=$review_bundle_path"
echo "review-bundle-verification-path=$review_bundle_verification_path"
} >> "$GITHUB_OUTPUT"
Expand All @@ -529,10 +567,13 @@ runs:
report_dir="${{ inputs['output-dir'] }}"
summary_path="$report_dir/codex-plugin-doctor-summary.md"
submission_summary_path="$report_dir/codex-plugin-doctor-submission.md"
submission_archive_summary_path="$report_dir/codex-plugin-doctor-submission-archive.md"
status_file="${RUNNER_TEMP:-.}/codex-plugin-doctor-status"
submission_state_file="${RUNNER_TEMP:-.}/codex-plugin-doctor-submission-ran"
submission_archive_state_file="${RUNNER_TEMP:-.}/codex-plugin-doctor-submission-archive-ran"
status="unknown"
submission_ran=false
submission_archive_ran=false

if [[ -f "$status_file" ]]; then
status="$(cat "$status_file")"
Expand All @@ -542,6 +583,10 @@ runs:
submission_ran="$(cat "$submission_state_file")"
fi

if [[ -f "$submission_archive_state_file" ]]; then
submission_archive_ran="$(cat "$submission_archive_state_file")"
fi

if [[ -n "${GITHUB_STEP_SUMMARY:-}" && -f "$summary_path" ]]; then
cat "$summary_path" >> "$GITHUB_STEP_SUMMARY"
fi
Expand All @@ -550,7 +595,11 @@ runs:
cat "$submission_summary_path" >> "$GITHUB_STEP_SUMMARY"
fi

if [[ -n "${GITHUB_STEP_SUMMARY:-}" && ! -f "$summary_path" && ( "$submission_ran" != "true" || ! -f "$submission_summary_path" ) ]]; then
if [[ -n "${GITHUB_STEP_SUMMARY:-}" && "$submission_archive_ran" == "true" && -f "$submission_archive_summary_path" ]]; then
cat "$submission_archive_summary_path" >> "$GITHUB_STEP_SUMMARY"
fi

if [[ -n "${GITHUB_STEP_SUMMARY:-}" && ! -f "$summary_path" && ( "$submission_ran" != "true" || ! -f "$submission_summary_path" ) && ( "$submission_archive_ran" != "true" || ! -f "$submission_archive_summary_path" ) ]]; then
{
echo "## Codex Plugin Doctor"
echo ""
Expand Down
1 change: 1 addition & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ This directory contains public documentation for users, contributors, and securi
- [MCP Registry Readiness](architecture/mcp-registry-readiness.md)
- [MCP Registry Publication Preflight](architecture/mcp-registry-publication-preflight.md)
- [Public Directory Submission Preflight](architecture/public-directory-submission-preflight.md)
- [Public Directory Archive Preflight](architecture/public-directory-archive-preflight.md)
- [Real-World Corpus Quality Metrics](architecture/real-world-corpus-quality-metrics.md)
- [Corpus Metrics Regression Diff](architecture/corpus-metrics-regression-diff.md)

Expand Down
Loading