fix(import): delete GitHub skill blobs when import fails - #3612
Conversation
importGitHubSkillForUser stored Convex blobs before validating slug/owner/semver, and publish failures left those ids unreferenced. Signed-off-by: Sebastien Tardif <SebTardif@ncf.ca>
|
🦞👀 Pull request received. I will update this pull request when review starts. ClawSweeper review completeClawSweeper finished reviewing this revision. The review result is being finalized. |
|
@SebTardif is attempting to deploy a commit to the OpenClaw Foundation Team on Vercel. A member of the Team first needs to authorize it. |
|
Codex review: needs maintainer review before merge. Reviewed September 16, 2026, 1:31 AM ET / 05:31 UTC (Revision 3). ClawSweeper reviewWhat this changesGitHub skill imports validate metadata before uploading files and delete failed uploads only until publication takes ownership of them. Merge readiness✅ Ready for maintainer review No blocking findings. The earlier committed-file deletion defect is resolved, and the updated local Convex evidence covers cleanup and preservation after persistence. Main still lacks cleanup for GitHub imports, so this PR remains necessary. Priority: P2 Review scores
Verification
How this fits togetherClawHub imports selected files from a publisher’s GitHub repository into Convex storage, then creates a skill version. Cleanup must remove rejected uploads while preserving files referenced by pending or published versions. flowchart TD
A[Selected GitHub files] --> B[Validate metadata and publisher]
B --> C[Store import files]
C --> D[Publish skill version]
D --> E{Version committed?}
E -->|No, import failed| F[Delete request uploads]
E -->|Yes| G[Version owns files]
G --> H[Followups or pending compensation]
Before mergeNone. Agent review detailsSecurityNone. Review metrics
Root-cause clusterRelationship: Members:
Proposal only: this assessment does not dispatch repair, suppress jobs, mutate sibling items, close, or merge anything. Technical reviewBest possible solution: Keep import cleanup local to newly uploaded files and use the shared commit signal as the definitive handoff to version ownership. Do we have a high-confidence way to reproduce the issue? Yes. Main visibly stores files before metadata validation and leaves earlier uploads behind after later failures; the supplied local Convex results corroborate that path, although this review did not execute it. Is this the best way to solve the issue? Yes. Reusing the shared persistence callback is the narrowest fix: deleting on every publication error corrupts committed versions, while moving cleanup into the shared helper would lose the importer’s request-specific ownership boundary. AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning medium; reviewed against e5f60853e9dd. LabelsLabel changes:
Label justifications:
EvidenceWhat I checked:
Likely related people:
Rating scale
Overall follows the weaker of proof and patch quality. Workflow
HistoryReview history (2 earlier review cycles) |
Multipart POST /api/v1/skills stored each uploaded file, then parsed the payload. An invalid body, a later oversized file, or a 400 after parse (license reject, owner resolution) left Convex blobs unreferenced. Match parseMultipartSkillScan: reject oversized parts before store, delete stored ids if store or parse fails, and delete them when the handler returns 400 after a successful parse. Replayed onto upstream/main d3bde70. Signed-off-by: Sebastien Tardif <sebtardif@ncf.ca>
GitHub skill imports now validate required metadata and resolve ownership before storing files, then delete partial or rejected uploads only while the request owns them. The shared publishing helper transfers ownership immediately when a pending or published version commits, preserving imported files through later scheduler or compensation failures. This completes Sebastien Tardif's existing cleanup patch.
Fixes #3672. Uses the shared persistence signal landed in #3549.
Native local Convex proof: invalid-version imports went from two orphan blobs to no stores; partial-store and rejected-insert failures now retain zero blobs. The previous PR deleted both committed files after a scheduler error (download 404); the repaired version retained them (download 200, 989 and 43 bytes). Pending success, successful compensation, failed compensation and normal publication also passed. The proof uses synthetic GitHub API/archive responses with real Convex identity, storage and publication; no production data was used.
Validation: 54 importer/shared-publishing tests passed after merging current main; static, full types/build and explicit schema/CLI/Convex typechecks passed; structured repair review returned no findings. Full coverage passed with 6,976 tests using four workers; the initial parallel run timed out in an existing large-archive test. No test or timeout was weakened.
Refreshed on main after #3549 merged. The final diff contains only the importer, its tests and its ownership invariant. The refresh preserves the exact previously validated file tree.