Skip to content

v0.7.0 — the declared contract becomes the enforced one

Choose a tag to compare

@Tranquility2 Tranquility2 released this 01 Aug 08:27
· 3 commits to main since this release

A contract-integrity release. An audit of all five plans and seven releases found the same
defect three times: the JSON schema declared a constraint that no shipped code enforced.
skills/quizzing/web/ is deliberately dependency-free, so nothing on the shipped path ever
runs the schema — make validate is a dev-only target. The schema had been quietly acting
as documentation while reading as a guarantee. No new features; three false promises made
true and one requirement corrected to describe the product that actually shipped.

Changed

  • questionCap is negotiable and enforced. The schema pinned maximum: 20 while
    build.js enforced whatever cap it was handed, so a questionnaire declaring
    questionCap: 30 built and served normally and failed make validate. The fixed maximum
    is gone: the declared cap is the maximum, the default is still 20, and SKILL.md now
    carries the rule that a different cap is legitimate only when the user asked for one. No
    code can tell a user-requested cap from an agent-inflated one, so build.js reports a
    non-default cap on every run rather than applying it silently.
  • FR-052 reworded to the model that shipped. It required "custom-answer requirements
    when Other is chosen", but Quizzing has no "Other" option — free text is a separate
    customInput channel. The implementable rule replaces it and is now enforced.
  • NFR-026 (non-browser fallback) formally withdrawn. v0.4.0 deleted the implementation
    and left the requirement asserted, alongside SKILL.md text saying the opposite.

Fixed

  • "No external network calls" is now true. diagram.content was documented as a data URI
    and typed as a bare string, and app.js assigned it straight to <img src>, so a remote
    URL passed validation and was fetched under a banner reading "self-contained: no external
    network calls". The schema now constrains image content to a base64 data URI, and app.js
    re-checks it independently, since nothing on the build path runs the schema.
  • The CSS route to the network is closed. The SVG sanitiser checked href, xlink:href,
    and src only, so <style>@import url(https://…)</style> and style="fill:url(https://…)"
    both survived, as did filter, mask, clip-path, and the marker attributes. <style> is
    now dropped whole like <script>, and any attribute containing a url() that is not a
    same-document url(#id) is dropped.
  • Submitted answers are actually validated. serve.js accepted a submission after
    checking that it was an object, that responses was an array, and that the questionnaire
    id matched. New lib.validateSubmission adds the referential half: unknown question ids,
    unknown option ids, duplicate answers, and mismatched version or loop id are rejected with
    400 before anything is written, and every issue is reported at once. followup.js runs the
    same check on its inputs, where a mismatch would have carried phantom questions into the
    next round. This is hand-rolled rather than schema validation, deliberately and explicitly.
  • FR-049 and FR-051 implemented. docs/design.md stated that FR-048–FR-052 "are
    checked as each question is answered"; three of the five were not implemented. A
    rangeValue of 999 against a 1–5 scale and a ranking of ["a","a"] both validated clean.
  • The SKILL.md dangling pointer. Two passages told the agent to "skip to No Node.js?
    Fall back to conversational delivery
    " — a section deleted in v0.4.0 — four lines from text
    saying there is no non-browser adapter and none should be improvised.
  • Stale plan claims corrected. "ES5-compatible" (CON-302, CON-401) has never been true
    of a directory using const, let, and arrows throughout; FILE-305/TASK-310 named a
    web/style.css that does not exist (it is app.css); TASK-330 shipped in v0.5.0 unticked;
    and REQ-205/FILE-208/TEST-206/RISK-204 still promised the three extra exemplars that
    v0.4.0 replaced with one broad example, having been left behind when only the task row was
    reworded.

Added

  • A two-way contract-coverage guard (tests/docs.test.js). The existing guards ran one
    way — catching runtime code that reads a field the schema forbids — and so could never have
    caught any of the above. The new table asserts the reverse: every constraint the project
    declares names the code that enforces it.
  • tests/build.test.js — the question-cap contract, pinned from both the runtime and the
    schema side.