chore: promote the runtime surface at 1.0.4 - #10
Conversation
Copy-by-inclusion promotion of the runtime surface, built by
`build-promotion-bundle.mjs` from the allowlist in the private working
repo: 116 allowlisted paths plus this repo's own four `.github/` files,
assembled into an empty tree. A path not on the allowlist does not exist
to the build. Content gates are fail-closed and all report 0 matches
(internal hostnames/repo names, secrets, tooling artefacts, local-runtime
remnants, internal references), and the private-only absence backstop
finds nothing.
Version moves 1.0.2 -> 1.0.4, in lockstep across all four manifests.
The checker travels with the surface, deliberately
--------------------------------------------------
`verify-surface.mjs` is normally kept out of a promotion, so a promotion
run cannot replace the verifier checking it. That holds for the automated
receiver. It cannot hold here, because the new checker does not merely
*accept* the url-pinned catalogues, it *requires* them:
FAIL: codex listing: marketplace source must be the url pin at the lockstep version tag
FAIL: claude listing: marketplace source must be the url pin at the lockstep version tag
Landing the checker first would therefore fail its own PR and leave
master red until the surface followed. Landing the surface first would
fail against today's checker, which demands `{source: "local", path:
"./"}`. Measured both ways; only the atomic change is green. It is
reviewable precisely because the checker diff is in this PR.
What the checker now requires of the Claude and Codex entries is the url
pin at `v<that manifest's own version>`, so a catalogue pinned to a tag
other than the version it ships is still rejected rather than any url pin
being waved through; extra keys on a pinned source are rejected by name.
Cursor's entry is untouched and still the string `"./"` -- its published
marketplace schema has no url-pin form.
Also in this surface
--------------------
- `.mcp.json` records the expected initialize `serverInfo.name`. No host
enforces it; it is checked against a captured initialize before a
release is promoted. SECURITY.md is reworded to say exactly that,
including that a different build reporting the same name still matches.
- The `deriv-llms` proposal examples gate the buy on a non-null stored
proposal and state that an expired proposal id must be replaced by a
fresh one put through the same user-confirmation step, never reused and
never treated as pre-confirmed.
No file is deleted: this repo carries no path the staged tree lacks.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Dependency Review✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.OpenSSF Scorecard
Scanned Manifest Files |
sparsh-deriv
left a comment
There was a problem hiding this comment.
The 1.0.4 tree is the intended public surface. The committed runtime files plus the four workflow files are 120 paths and nothing else. node .github/workflows/verify-surface.mjs on this HEAD printed OK — 120 path(s). All four manifests are 1.0.4. Cursor stays "./". Claude and Codex use the HTTPS url pin.
Do not merge until someone who can create the annotated tag v1.0.4 and the GitHub Release is in the same session. This repository has no tags and no Releases. After merge, both catalogues tell Claude and Codex to fetch v1.0.4, and that install fails until the tag exists. Leave the pin on the version tag.
skills/deriv-llms/references/workflows.md step 3 still sends { buy } on the proposal response. The two files in this PR wait for confirmation. An agent that follows the workflow page will skip the gate. If 1.0.4 is supposed to carry the confirmation rule in every llms reference, that page needs the same sentence. If you want this PR to stay a straight 1.0.4 promotion, leave the mismatch for the next surface.
| "source": { | ||
| "source": "url", | ||
| "url": "https://github.com/deriv-com/deriv-api-plugin.git", | ||
| "ref": "v1.0.4" |
There was a problem hiding this comment.
This pin is v1.0.4. The repository has no tags and no GitHub Releases, so git ls-remote --tags resolves nothing. Claude's documented install (/plugin marketplace add then install) reads this catalogue from the default branch and then clones that ref. After merge, master advertises a ref nobody can fetch until an annotated v1.0.4 and its Release exist. Codex's catalogue uses the same pin. Merge only when someone who can create both is in the session. Leave this on the version tag. A master pin would undo the install contract.
| "path": "./" | ||
| "source": "url", | ||
| "url": "https://github.com/deriv-com/deriv-api-plugin.git", | ||
| "ref": "v1.0.4" |
There was a problem hiding this comment.
Same tag hold as the Claude catalogue. Codex marketplace add then install will try to clone v1.0.4. That ref does not exist yet. The pin is correct; the merge and the annotated tag have to happen together.
| }); | ||
| ``` | ||
|
|
||
| A proposal id expires. If the stored proposal is stale, request a fresh proposal and put the new id through the same user-confirmation gate before buying from it; never reuse an expired id, and never treat a refresh as pre-confirmed. |
There was a problem hiding this comment.
The null check and this stale-id sentence match the confirmation heading above. workflows.md step 3 still says to send { buy } on the proposal response, so an agent that follows that page never reaches this gate. If 1.0.4 is supposed to carry the confirmation rule in every llms reference, that page needs the same sentence. If you want this PR to stay a straight 1.0.4 promotion, leave the mismatch for the next surface.
sparsh-deriv
left a comment
There was a problem hiding this comment.
The 1.0.4 tree is the intended public surface and the checker is green on this HEAD. Approving.
Create the annotated tag v1.0.4 and the GitHub Release in the same session as the merge. Claude and Codex install from that ref, and it does not exist yet.
Copy-by-inclusion promotion of the runtime surface from the private working repo, raised after human approval of the reviewed manifest (publication gate 2). Built by
build-promotion-bundle.mjsfrom the allowlist into an empty tree — a path not on the allowlist does not exist to the build.Version 1.0.2 → 1.0.4, lockstep across all four manifests.
Manifest
120 paths = 116 allowlisted + 4 scaffold. All fail-closed content gates clean, and the private-only absence backstop finds nothing.
plugin.json.mcp.jsonREADME.mdLICENSESECURITY.mdPRIVACY.mdCONTRIBUTING.md.cursor-plugin/×2,.claude-plugin/×2,.codex-plugin/plugin.json,.agents/plugins/marketplace.jsonrules/deriv-api-conventions.mdclogo.png,logo-dark.pngderiv-authderiv-lightweight-chartsderiv-llmsderiv-market-dataderiv-smartchartsderiv-trade-lifecyclederiv-trade-typesderiv-trading-app.github/workflows/×4No deletions — this repo carries no path the staged tree lacks.
Why the checker is in this PR
verify-surface.mjsis normally withheld from a promotion so a promotion cannot replace the verifier checking it. That holds for the automated receiver; it cannot hold here, because the new checker does not merely accept the url-pinned catalogues — it requires them.I measured all three orderings:
FAIL: codex listing: … must be the url pin at the lockstep version tag+ the same for claude — red on its own PR, and master stays red until the surface followsFAIL: codex listing: marketplace source must be local path ./against today's checkerOK — 120 path(s), surface + presence + MCP URL pin + content + internal-reference + Codex gates cleanOnly the atomic change is green. It is reviewable precisely because the checker diff is in this PR — 51 lines, and the substance is one rule.
The checker now requires the Claude and Codex entries to be the url pin at
v<that manifest's own version>, so a catalogue pinned to a tag other than the version it ships is still rejected rather than any url pin being waved through; extra keys on a pinned source are rejected by name. Cursor's entry is untouched and still the string"./"— its published marketplace schema has no url-pin form.Also in this surface
.mcp.jsonrecords the expected initializeserverInfo.name(deriv-api). No host enforces that field, and all three still connect; it is checked against a captured initialize before a release is promoted.SECURITY.mdis reworded to say exactly that, including that a different build reporting the same name still matches.deriv-llmsproposal examples gate the buy on a non-null stored proposal, and state that an expired proposal id must be replaced by a fresh one put through the same user-confirmation step — never reused, never treated as pre-confirmed.After merge
The catalogues advertise
ref: v1.0.4, which does not exist yet —git ls-remote --tagson this repo resolves nothing. An annotated tagv1.0.4on the merge commit plus its GitHub Release must follow in the same session, or master advertises a ref no consumer can resolve. That step needs credentials I do not hold.🤖 Generated with Claude Code