Skip to content

release: spec-kit b3ac9b0 to production - #41

Merged
jm-rivera merged 21 commits into
mainfrom
release/2026-10-31
Oct 31, 2026
Merged

jm-rivera merged 21 commits into
mainfrom
release/2026-10-31

Conversation

@jm-rivera

@jm-rivera jm-rivera commented Oct 31, 2026 •

Copy link
Copy Markdown
Contributor

Releases spec-kit at b3ac9b0 to production, cut on release/2026-10-31: five pull requests.

ai on dev pins 2dd2400, the head of #37's branch, and apis pins afdae02, the head of #39's branch. This branch reaches both through their merge commits. Merge this first, with a merge commit, so both pins are on main before the apis and ai releases build.

Testing: CI passed on each pull request into dev.

…' codes (#30)

* feat(contract): add derived refs, an output digest and analysis rules

DatasetRef format 2 names derived members: an ops_ spec with its recipe
hashes, the ocv_ version, an output digest (out_), the root versions
with their renderings, the execution identity and resolved periods.
Format 1 refs validate unchanged.

New rule vector sets pin the output digest (JCS over roles, period,
value and unit, leaving out stat_var and provenance), output comparison
(== against same_data), operation outputs (share_of in percent, join in
long format, compare as data minus other, growth as a fraction), rolling
composition (rolling_populations_differ) and share publication (slot
URLs survive a live replace; a snapshot cannot be replaced).

The registry gains the datasets.analysis and presentation.shares
endpoints and the codes allowance_exhausted, rolling_populations_differ,
several_members, share_not_replaceable, write_token_required and
write_token_invalid. operations.json states each verb's output shape
and pairs sum and compare by role.

* feat(registry): register the analysis engine's refusal codes

The datasets.analysis endpoint gains a row for each of the 34 refusal
codes the analysis engine raises, including compare_no_key_matched and
sum_of_no_key_matched for paired calls, each 422 with the fix_request
action.

operations.json lists unmatched_key under sum's and compare's left-out
reasons and describes their paired form: `on` pairs data's members with
other's by role, and compare returns data minus other.

* feat(registry): map the Datasets codes the analysis route serves

datasets.analysis also answers 27 existing Datasets codes, for roots it
cannot read or build (snapshot_not_found, artifact_expired,
recipe_not_found, rendering_not_recorded and others) and for platform
faults. Each maps at the status it has on the Datasets endpoints.

* feat(registry): map timeout on analysis and the platform codes on shares

datasets.analysis answers timeout at 504 when a run passes its
deadline. presentation.shares maps not_found, request_invalid,
frame_unavailable, edit_conflict, service_unavailable, internal_error
and timeout at the statuses the presentation write endpoint uses.

* feat(registry): map the share routes' refusals and add the SDKs' left-out warning

presentation.shares maps binding_invalid, schema_invalid,
constraint_violation and resource_exhausted at 400 and release_mismatch
at 503, the statuses the components routes use, and a new
payload_too_large at 413 for a share body over the routes' limit.
pin_not_permitted is retired: the pin route admits any caller under its
allowance. The client contract gains the payload_too_large action row
and the series_left_out warning, which a client issues when a derived
frame left series out for missing data.

* feat(registry): map the card allowance on presentation writes

allowance_exhausted answers 429 on presentation.write, where creating
or revising a card spends the caller's daily card allowance.

* fix(contract): name each value's variable in the output digest

The output digest (out2) holds each row's stat_var, so frames that pin
the same numbers to different variables differ; every derived identity
in refs/ and output-comparison.json is computed by the dfo-apis runner,
and the validator checks that equal identities agree across fixtures.
allowance_exhausted is never retried and a Retry-After above 60 s
raises at once. write_token_invalid takes a new action, stop. The
series-left-out rule fires on a derived manifest's left_out, growth's
left-out reasons are stated with vectors, a derived member's parts are
empty, a growth window starts before it ends, and a scenario fetches
dataset refs only. share lists unmatched_key among its left-out
reasons.

* fix(contract): name a computed variable by what was computed

The output digest names a variable that compare, sum_of, share_of or
quotient_of writes by its verb and its inputs' variables, so equal
computations over equal variables share a digest across recipes,
engine releases and rebuilds that move no number, and swapped sides
differ. Output-digest vectors carry a variables map; three new vectors
pin the naming.

* fix: name minted variables by a fixed-size digest and admit grouped roots

A minted variable is named mv_ plus the first 32 hex of SHA-256 over the
RFC 8785 JSON of {verb, slot: sorted input names}, 35 characters at any
depth. rules/README.md states the form, three output-digest vectors are
regenerated, and rules.schema.json requires the mv_ form in vectors.

A derived ref's root takes its own root_rendering, which admits the
groupby (by, op sum, levels) DFO read a summed root with. The artifact
rendering selector still refuses groupby. Three ref vectors cover a
grouped root, a groupby with another op, and groupby on an artifact.
The client contract validator compares a root's groupby with the one
its scenario posted, and leaves it to the schema when none was posted.

* fix: pin nested minted names and record grouped-root ids from a real run

Output-digest vectors carry name_documents, the document each mv_ name
hashes, and a new quotient-of-a-sum-of vector names a minted variable
whose input is another minted variable. The validator checks that each
name hashes from its document and that every nested mv_ name has one.

The grouped-root ref vectors record by sorted, as DFO writes it, with
ids from a dfo-apis run_analysis. rendering and root_rendering share one
selector definition, and root_rendering adds only groupby. The
validator's derived-identity check includes each root's rendering.
dfo-apis' PUT /api/presentation/shares/{id}/import, which the website's
share migration job calls once per share, refuses with share_id_taken
(409) when the id holds another share or the same share under another
write-token digest, and share_import_not_permitted (403) when the caller
lacks the import principal. Both sit on presentation.shares, with
actions.json rows fix_request and request_scope.
Adds the datasets.exports and datasets.export_link endpoints for the dfo-apis export routes, with provenance_unavailable and licence_not_redistributable. Adds the mcp_refusal channel and mcp.tools endpoint for refusals an MCP tool result carries, with tool_not_found, frame_ref_incomplete, frame_not_held, frame_expired and rolling_reanchor_unavailable.
A prepare that names only a spec_id resolves its newest version and can rebuild it, so datasets.exports carries the 21 codes datasets.definition answers for a rebuild, at the same statuses.
…sets.exports

entities_unbound and resolution_ambiguous are catalogue entries no rebuild raises.
Definitions of frame_not_held, frame_expired, rolling_reanchor_unavailable and provenance_unavailable now state the conditions dfo-ai and dfo-apis serve them for, and provenance_unavailable takes the fix_request action.

The mcp.tools endpoint and the mcp_refusal channel require each other in the schema. Eight codes only an MCP tool result carries join the registry, and rate_limited and transient_unavailable share their spelling with the proxy table, so the proxy check refuses only codes that reach a problem document or a no_data reason.

datasets.export_link registers identity_quarantined, as datasets.files does.
…face

mcp.tools now holds every code data-mcp, analysis-mcp, presentation-mcp and the combined server write, so a mapping states where a code appears. presentation-mcp also forwards platform codes it does not write itself.

A proxy code may share a spelling only with a code whose every mapping is mcp_refusal, and rate_limited and transient_unavailable are worded to hold on both surfaces. provenance_unavailable takes the stop action, since a recipe root that cannot be cited survives a rebuild. Definitions name no store mechanics, and the README states every field of the mcp_refusal envelope.
…-mcp-codes

feat(registry): register the export and MCP refusal codes
…and cap a refused failed poll's Retry-After

The README said a fetch warns series_left_out only for the rolling anchor's
left-out series. The rule, its vectors and test_rules warn for any manifest's
left_out and for left_out_complete false.

LongBuild.polled decided whether to repost after an operation_failed refused
poll with retryable(), so a Retry-After over the 60-second cap reposted at
once. tries_again now decides for every refused poll.

The CHANGELOG counts 148 active refusal codes in actions.json.
…t-doc-and-poll-cap

fix(client-contract): state the series_left_out rule the vectors pin and cap a refused failed poll's Retry-After
@jm-rivera jm-rivera changed the title release: spec-kit 9814852 to production release: spec-kit d8d16ac to production Oct 31, 2026
…ation-read-endpoints

feat(registry): map every Presentation route and state where a frame refusal lands
@jm-rivera jm-rivera changed the title release: spec-kit d8d16ac to production release: spec-kit b3ac9b0 to production Oct 31, 2026
@jm-rivera
jm-rivera merged commit 2ab2f26 into main Oct 31, 2026
38 checks passed
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