chore: promote runtime surface deriv@1.0.1 - #8
Conversation
Built by scripts/build-promotion-bundle.mjs from the allowlist in deriv-com/deriv-api-plugin-specs at bac78f7. Copy-by-inclusion: no file is removed. - Adds the deriv-smartcharts and deriv-lightweight-charts skills, closing the superset gap against the hosted get_skill catalogue. - Replaces deriv-trade-lifecycle's frontmatter description with a double-quoted scalar. The unquoted form currently on master is not parseable YAML, so a spec-compliant skill loader rejects the file. - Carries the housed skills' corrected MCP server name and the listing copy authored here in #7, adopted upstream so a refresh no longer reverts it. - Bumps the plugin version to 1.0.1. 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 |
ako-deriv
left a comment
There was a problem hiding this comment.
Checked out the branch and verified the main claims locally:
skills/deriv-trade-lifecycle/SKILL.mdfrontmatter fails to parse with js-yaml onmaster(YAMLException) and parses on this branch. All 8SKILL.mdfrontmatters and all 7agents/openai.yamlfiles parse here.node .github/workflows/verify-surface.mjspasses locally (120 paths, all gates clean).- Every relative link in the new and changed skill files resolves, including the new cross-links from the README,
chart-selection.md, andderiv-trading-app/SKILL.md. - All four manifests read
1.0.1; the newopenai.yamlfiles reference thederivserver key declared in.mcp.json.
Nothing blocking. A few notes, most of them inline:
- PR description: the bullet "Carries the corrected MCP server name … prose named a
deriv-apiserver" does not apply to this repository. There is noderiv-apiserver reference onmaster(only the repository URL and therules/deriv-api-conventions.mdcfilename), so that bullet is a no-op here. Worth trimming so it does not end up in generated release notes. - The
verify-surface.mjsregex change tightens the gate (see inline). Not mentioned in the description. - The two new
openai.yamldisplay names use title case, while #7 moved listing copy to sentence case (see inline). - Pre-existing and not introduced here:
skills/deriv-llms/is the only skill without anagents/openai.yaml.
| /PLAN\.md/, | ||
| /(^|[\s"'(/])specs\//m, | ||
| /(?<!~\/)\.claude\//, | ||
| /\.claude\/(?!skills\/)|(?<!~\/)\.claude\/skills\//, |
There was a problem hiding this comment.
This is a behavioural change, not just a refactor. Before, any .claude/ path was allowed as long as it was preceded by ~/. Now only ~/.claude/skills/ is allowed and every other .claude/... path is rejected, including ~/.claude/<anything-else>.
README line 66 (~/.claude/skills/) still passes, so nothing breaks today, but since this PR is titled as a promotion chore it would be good to call the tightening out in the description (or split it) so the intent is recorded.
There was a problem hiding this comment.
Confirmed, and recorded in the PR description rather than left implicit.
The gate went from "any .claude/… path passes if preceded by ~/" to "only ~/.claude/skills/ passes; every other .claude/… is rejected, including ~/.claude/<anything-else>". You are right that nothing breaks today — README.md line 66 is ~/.claude/skills/ and still passes.
Worth knowing where it came from: this file is not authored in the public repo. It lives in deriv-com/deriv-api-plugin-specs under promotion/public-repo-scaffold/.github/workflows/, and the narrowing landed there as part of tightening the promotion content gates — the wider ~/.claude/… allowance let through paths the gate was meant to catch. The public copy has simply been behind since then; this promotion is what brings it level. So it is a genuine behavioural change, but not one introduced here.
I have added a section to the description naming the change and its effect, so the intent is on the record rather than discovered later.
| @@ -0,0 +1,11 @@ | |||
| interface: | |||
| display_name: "Lightweight Charts Price Chart" | |||
There was a problem hiding this comment.
Casing: #7 moved the listing copy to sentence case (Trading authentication, Trading market data, Trading lifecycle, …). Suggest keeping the product name capitalised but lowering the generic part:
| display_name: "Lightweight Charts Price Chart" | |
| display_name: "Lightweight Charts price chart" |
There was a problem hiding this comment.
Agreed on the inconsistency, and confirmed: the five skills #7 authored are sentence case (Trading authentication, Trading lifecycle, …) while both chart skills are Title Case, because they were never in #7 — there was no downstream copy to adopt when the listing copy was backported.
The fix cannot land in this PR, though. agents/openai.yaml for both chart skills is authored in deriv-com/deriv-api-mcp under src/deriv_api_mcp/guides/skills/<name>/agents/, and the plugin bundle is generated from that checkout by scripts/refresh-offline-skills.mjs in the specs repo. Editing the values here — or in the specs repo — would be reverted by the next refresh, which is the same trap that made #7's copy need backporting in the first place.
So it needs the three-repo chain: correct the two display_name values at the MCP source, refresh the bundle in the specs repo, then promote. Happy to run that before this merges if you would rather ship consistent casing, or take it as the follow-up promotion — your call, since it is cosmetic and this PR carries a parse failure fix that is live on the marketplace today.
Same reasoning applies to your note about the uneven dependencies: descriptions — those are authored at the MCP source too.
| @@ -0,0 +1,11 @@ | |||
| interface: | |||
| display_name: "SmartCharts Price Chart" | |||
There was a problem hiding this comment.
Same casing note as the Lightweight Charts entry, to match the sentence-case display names from #7:
| display_name: "SmartCharts Price Chart" | |
| display_name: "SmartCharts price chart" |
There was a problem hiding this comment.
Same answer as on the Lightweight Charts thread, and the same suggested wording — SmartCharts price chart.
Both chart skills' agents/openai.yaml are authored in deriv-com/deriv-api-mcp, so fixing the casing here or in the specs repo is reverted by the next refresh-offline-skills.mjs run. It needs the MCP source first, then the refresh, then a promotion.
Tracked with your other two follow-ups at deriv-com/deriv-api-plugin-specs#176.
| - type: "mcp" | ||
| value: "deriv" | ||
| description: "Live Deriv API guides, schemas, examples, and payload validation" | ||
| description: "Live Deriv trading schemas, examples, and payload validation" |
There was a problem hiding this comment.
Nit: three skills (market-data, trade-lifecycle, trade-types) get a tailored MCP dependency description in this PR, but deriv-auth and deriv-trading-app keep the generic "Live Deriv API guides, schemas, examples, and payload validation". Not wrong, just uneven; fine to leave for a follow-up.
There was a problem hiding this comment.
Confirmed, and it is worth more than "uneven" — there are two records currently disagreeing about it.
PR #7 here rewrote the dependencies: description: for deriv-market-data, deriv-trade-lifecycle and deriv-trade-types downstream. When that listing copy was adopted upstream into deriv-com/deriv-api-mcp, those three strings were deliberately left out of scope and recorded as a deferral, because the adoption was scoped to the frontmatter description and the three interface: fields. So deriv-auth and deriv-trading-app keep the generic wording not by oversight but because nothing has yet decided which side wins.
Agreed it should not block this PR. Tracked at deriv-com/deriv-api-plugin-specs#176, with a note that whichever wording is chosen should settle both this and the open upstream deferral in one pass, rather than leaving the two records contradicting each other.
There was a problem hiding this comment.
Correcting my previous reply on this thread — I claimed the upstream and downstream records currently disagree about these strings. They do not. I have just compared all five, and deriv-com/deriv-api-mcp and this repository are byte-identical on every one:
| Skill | Both repos |
|---|---|
deriv-auth |
Live Deriv authentication guides and endpoint schemas |
deriv-market-data |
Live Deriv market-data schemas, examples, and validation |
deriv-trade-lifecycle |
Live Deriv trading schemas, examples, and payload validation |
deriv-trade-types |
Live Deriv contract schemas, examples, and payload validation |
deriv-trading-app |
Live Deriv API guides, schemas, examples, and payload validation |
So there is no divergence to settle and no open contradiction — the adoption and refresh already synchronised them. What is left is only what you actually described: a style inconsistency, and a narrower one than I implied. Four of the five are specific; only deriv-trading-app is generic. Both chart skills are specific too (Live Deriv tick-history, subscription, and trading-times schemas the chart feed must follow), so it is one skill out of seven.
And arguably the right one: deriv-trading-app is the router that composes the others, so a description spanning the whole API surface fits it in a way it would not fit deriv-auth.
That lowers this to a judgement call about a single string rather than a reconciliation, which is worth knowing before anyone picks it up. deriv-com/deriv-api-plugin-specs#176 has been left open for it; I will correct its framing there too.
There was a problem hiding this comment.
Retracting my previous correction on this thread — it was wrong, and the original note was right.
I measured the two repositories after this PR merged (14:59:35) and found them identical, and concluded there had never been a divergence. The identity was the consequence of this merge, not evidence against the divergence.
What actually happened, from this PR's own diff:
- description: "Live Deriv API guides, schemas, examples, and payload validation"
+ description: "Live Deriv market-data schemas, examples, and validation"
- description: "Live Deriv API guides, schemas, examples, and payload validation"
+ description: "Live Deriv trading schemas, examples, and payload validation"
- description: "Live Deriv API guides, schemas, examples, and payload validation"
+ description: "Live Deriv contract schemas, examples, and payload validation"
#7 rewrote those three strings from specific to generic as part of its UX pass. The upstream adoption deliberately did not take them, and recorded that as a deferral. This promotion therefore carried the upstream wording downstream and reverted #7's three strings — without a decision being taken, and without appearing in the PR description.
That is exactly the failure mode the backport work existed to prevent: promotion is copy-by-inclusion, so any downstream-only edit is reverted at the next promotion. It was avoided for the listing copy and the publisher capitalisation, and it was not avoided here, because these three were the one part deliberately left out of the adoption.
So the substance of your original comment stands and is now more than cosmetic: the unevenness you saw is real, and the dependencies: block is presently upstream's wording, not #7's. deriv-trading-app was already generic upstream and is unaffected.
What needs deciding is the same question as before, now with the revert as the status quo: keep upstream's specific wording (the current state, no action), or restore #7's generic wording — in which case it must be adopted upstream in deriv-com/deriv-api-mcp, not re-applied here, or the next promotion reverts it again.
Tracked at deriv-com/deriv-api-plugin-specs#176, whose framing I am correcting now too. Apologies for the noise on this thread — I should have checked the merge state before asserting the comparison.
| Never name a host-namespaced tool; use the bare tool name only. | ||
|
|
||
| Snapshot: these pages were fetched from developers.deriv.com on 2026-09-10. They are a point-in-time snapshot, not a live source — while the hosted Deriv API MCP tools work, they are authoritative. | ||
| Snapshot: these pages were fetched from developers.deriv.com on 2026-09-14. They are a point-in-time snapshot, not a live source — while the hosted Deriv API MCP tools work, they are authoritative. |
There was a problem hiding this comment.
The snapshot date moves from 2026-09-10 to 2026-09-14, but no file under skills/deriv-llms/references/ changes in this PR. If the refetch was byte-identical that is fine, but the date is then the only evidence of a refresh. Consider either leaving the date at the last content change or noting in the description that the refetch produced no diff.
There was a problem hiding this comment.
Checked this rather than assuming, and you are exactly right: the only change under skills/deriv-llms/ in this PR is 1+ 1- on SKILL.md, the date line itself. Not one file under references/ changes.
The refetch did run, against developers.deriv.com, and returned byte-identical pages — so the date is accurate as written. It records when the snapshot was last verified against the live source, not when its content last changed. That is the useful reading, since a stale-but-unchanged snapshot and a never-rechecked one are different things.
But your point stands that the date alone is then the only evidence, and nothing said so. I have added a note to the PR description stating that the refetch produced no content diff and that the date is a verification timestamp, so the absent diff reads as expected rather than as an oversight.
|
|
||
| ## `chartData`: active symbols plus trading times | ||
|
|
||
| The chart's market selector and its "is this market open" logic read a `chartData` object the host supplies. At the installed version the chart makes no market requests of its own, so there is nothing to switch off: the `feedCall` prop was observed inert, and `shouldFetchTradingTimes` — despite its name — gates whether the chart *processes* the trading times you pass, and that processing is what resolves its internal trading-times promise. Setting it to `false` was observed to let the first `initialize()` finish while leaving that promise unresolved, so the hang starts on the second `initialize()` — any remount, and `StrictMode` in development — because the statically held store keeps its initialised flag and hands back the never-resolved promise, leaving the chart on "Retrieving Trading Times..." with no error; leave it at its default. No trading-times map is built either, so `isMarketOpened` was observed returning `undefined` and `getDelayedMinutes` throwing on the missing entry. Confirm both props against the installed version. Assemble both halves from the application's existing discovery layer: |
There was a problem hiding this comment.
The content of both chart skills reads consistently with the rest of the plugin (hosted MCP first, bare tool names, one shared socket, chart never in the purchase path). One thing to be aware of: this reference is very specific about observed runtime behaviour of @deriv-com/smartcharts-champion (shouldFetchTradingTimes semantics, the StrictMode double-mount hang, half-open trading-times windows, the two pip_size meanings). It is correctly hedged as "observed" and "at the installed version", but these statements will rot as the package evolves. Suggest someone owns re-verifying them whenever the package version is bumped, or a short "last verified against version X" line is added so readers know how fresh the observations are.
There was a problem hiding this comment.
Agreed, and this is the most durable of your notes — the others are cosmetic, this one decays on its own.
The hedging is deliberate ("observed", "at the installed version"), but you are right that hedging without a version number does not help a reader decide whether to trust it. shouldFetchTradingTimes gating processing rather than fetching, the StrictMode double-mount hang, the half-open trading-times windows and the two meanings of pip_size are all exactly the kind of claim that silently stops being true.
A "last verified against @deriv-com/smartcharts-champion vX.Y.Z" line is the cheaper of the two options you offer, and it makes the staleness visible rather than requiring someone to own a recurring check.
Like the others, the file is authored in deriv-com/deriv-api-mcp, so it takes the same MCP → refresh → promote chain. Tracked at deriv-com/deriv-api-plugin-specs#176.
Promotes the runtime surface from
deriv-com/deriv-api-plugin-specsatbac78f7, built byscripts/build-promotion-bundle.mjsfromscripts/promotion-allowlist.json. Copy-by-inclusion — no file is removed. Content gates ran clean over 116 allowlisted paths plus 4 scaffold files, with 0 internal-reference matches.What changes
Fixes a defect on the published plugin.
skills/deriv-trade-lifecycle/SKILL.mdcurrently carries its description as an unquoted plain scalar openingImplement the New Deriv API Options flow: price, …. A": "inside a plain scalar is a mapping indicator, so that frontmatter block does not parse — PyYAML raisesScannerError, js-yaml rejects it, and a spec-compliant skill loader rejects the file whole. It is now a double-quoted single-line scalar that parses back to the same string. Every one of the eight bundled skills' frontmatter parses after this change; one does not before it.Adds the two chart skills.
deriv-smartchartsandderiv-lightweight-chartsship here for the first time. The hostedget_skillcatalogue already advertises both, so an agent could see a skill the installed plugin had no directory for — visible whenever the hosted MCP is unreachable and the bundle is the fallback.Carries the corrected MCP server name. Housed prose named a
deriv-apiserver that nothing registers; the declared server key isderiv.Preserves this repository's listing copy. The marketplace copy and publisher capitalisation authored here in #7 were adopted upstream, so promotion no longer reverts them.
plugin.jsondiffers from master in one line only: the version.Version
1.0.0→1.0.1.Verification
npm testgreen upstream, including a new gate asserting every bundledSKILL.mdfrontmatter parses as YAML withnameanddescriptionvalidate-plugin.mjspasses and still rejects a capitalised plugin identifierverify-surface.ymlre-checks the allowlist and re-runs the content gates independently on this PR🤖 Generated with Claude Code
Two changes worth calling out explicitly
verify-surface.mjstightens the.claude/gate — a behavioural change, not a refactor. Previously any.claude/path passed so long as it was preceded by~/. Now only~/.claude/skills/is permitted, and every other.claude/…path is rejected, including~/.claude/<anything-else>. Nothing in the tree breaks today —README.mdline 66 (~/.claude/skills/) still passes — but the narrower rule is deliberate and is recorded here rather than left to be discovered in a promotion chore.deriv-llms's snapshot date moves with no content change. The date advances from 2026-09-10 to 2026-09-14 while no file underskills/deriv-llms/references/changes, because the refetch fromdevelopers.deriv.comreturned byte-identical pages. The date records when the snapshot was last verified against the live source, not when it last changed, so it is accurate as written — but the absence of any accompanying content diff is expected here, not an oversight.