Skip to content

fix: emit JSON-Schema bounds in generated references; drop a stale ttl note - #19

Merged
dg-coreylweathers merged 3 commits into
mainfrom
fix/schema-constraints-and-stale-ttl-note
Sep 20, 2026
Merged

dg-coreylweathers merged 3 commits into
mainfrom
fix/schema-constraints-and-stale-ttl-note

Conversation

@dg-coreylweathers

Copy link
Copy Markdown
Contributor

Two fixes, one of them a prerequisite for a docs change already in review.

1. The generator silently discarded every JSON-Schema bound

scripts/generate-skills.ts emitted type, required, default and description, and nothing else. minimum and maximum appeared zero times in the script, so every numeric bound in the specs was dropped on the floor.

This is not theoretical. deepgram-docs#1219 raises the /v1/auth/grant ttl_seconds schema maximum from 3600 to the real 28800 (the live API rejects 28801 with TTL is too long, max is 28800 seconds). Because the generator ignored maximum, regenerating after that lands would have been a no-op and the correct ceiling would never have reached references/auth.md. That PR worked around it by also writing the ceiling into the schema description. The workaround should not be necessary, so this fixes the cause.

Duplication rule. Bounds render in the same parenthesis as the default, and are suppressed when the description already states the same numbers in prose. Two reasons:

  • A separate group read as a stumble: (default: `1`) (range: `0.7` to `1.5`). One parenthesis gives (default: `1`, range: `0.7` to `1.5`). A schema with only a default still renders exactly (default: `x`), so the thousands of bullets carrying no bound are untouched.
  • Several params already document their own range. eot_threshold says "Valid range: 0.5 - 1.0. Defaults to 0.7." Appending a bound there would stutter. The suppression is per-number, so a schema stating a bound the prose omits still renders it.

The rule is visibly working in both directions: SpeakV2Speed states "Accepted values run 0.5 to 1.5" in prose and is correctly suppressed, while SpeakV1Speed states no range and correctly renders one.

What changed in the output:

- `ttl_seconds` number (range: `1` to `3600`) — Time to live in seconds for the token. Defaults to 30 seconds.
- `speed` number (default: `1`, range: `0.7` to `1.5`) — Speaking rate multiplier ...   (x2, both /v1/speak transports)
- `turn_index` integer **(required)** (minimum: `0`) — The index of the current turn

Once deepgram-docs#1219 lands and the hourly mirror syncs, a regen turns that first line into range: 1 to 28800 on its own.

Keywords handled: minimum, maximum, exclusiveMinimum, exclusiveMaximum, minLength, maxLength, minItems, maxItems, multipleOf. Of these, only minimum/maximum currently occur in these specs.

Nothing from #17 regressed. The Flux STT knobs still render their full prose descriptions with defaults and no redundant bound. JSON Pointer resolution, the messageName fix, the self-hosted path routing and the prune pass are all untouched. Regeneration is idempotent across two consecutive runs, and produces 8 reference files, 0 pruned.

Pre-existing gap, reported not fixed: temperature, volume, sequence_id and several other bounded properties render nowhere in references/agent.md. Confirmed they are absent on main too, so this is a nested-schema expansion-depth gap that predates this change, not a regression. Worth its own look.

2. A stale claim in skills/browser-agent/SKILL.md

"Common mistakes" item 2 said "Some snippets in the browser-agent documentation still show ttl". deepgram-docs#1218 merged and corrected those snippets, so that clause was false.

Surgical fix. The mistake itself stays, because it is still easy to make and still silently wrong. Re-verified live today:

body response
{"ttl": 300} 200, expires_in: 30
{"ttl_seconds": 300} 200, expires_in: 300
{"totally_bogus_field": 999} 200, expires_in: 30
{} 200, expires_in: 30

The advice to read expires_in rather than trust the field name you sent also stays, and now gives the actual reason: /v1/auth/grant ignores any field it does not recognize and still answers 200. It is generic unknown-field tolerance, not anything ttl-specific.

Gates

  • validate-skills.ts: exit 0, 14 skills, 14 valid
  • npx skills add ./ --list: Found 14 skills
  • Regeneration idempotent across two runs
  • tsc --noEmit --strict: 4 errors, identical on main (no @types/node), so no new error
  • No verification dates added to any skill. The four em dashes in the diff are all in generated reference files, which use param — description as their established format

Changelog entry added under ## [Unreleased] with a compare link. metadata.version deliberately untouched, since deepgram-skills-v1.6.0 is already tagged and released.

…w ttl

deepgram-docs #1218 corrected those snippets. The field-name mistake, the
observed expires_in values, and the advice to read expires_in rather than
trust the field name all stand; the reason given for that advice is now the
behavior that causes it, which is that /v1/auth/grant ignores any field it
does not recognize and still answers HTTP 200.
The generator emitted type, required, default and description, and discarded
every numeric bound in the specs. A schema maximum therefore never reached a
reference file, so correcting one upstream was a no-op downstream.

Bounds now render in the same parenthesis as the default, and are suppressed
when the description already states the same numbers in prose, so params that
document their own range do not stutter.
Adds ttl_seconds range 1 to 3600 on /v1/auth/grant and speed range 0.7 to 1.5
on both /v1/speak transports. Records the change under Unreleased.
@dg-coreylweathers
dg-coreylweathers merged commit c56c10b into main Sep 20, 2026
3 checks passed
@dg-coreylweathers
dg-coreylweathers deleted the fix/schema-constraints-and-stale-ttl-note branch September 20, 2026 14:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant