Skip to content

Releases: Tranquility2/quizzing

v0.7.1 — the docs catch up with the cap

Choose a tag to compare

@Tranquility2 Tranquility2 released this 01 Aug 09:37

A documentation-correctness release. v0.7.0 made the question cap negotiable — default 20,
or the number the user asked for — and updated the requirements that say so. It did not
update the prose that restates the old rule as an absolute, so the docs asserted both
versions at once. Two of the corrected files ship inside the installed plugin, and plugin
components are cached at install time, so this needs a version bump to reach anyone.
No behaviour change.

Fixed

  • The docs now agree with the shipped cap. Eleven places across README.md,
    docs/design.md and SKILL.md's frontmatter still promised "no more than 20 questions"
    or a "hard maximum of 20 user-visible questions". The frontmatter matters most: it is the
    agent's matching surface, and it advertised capped (<=20) for a form that will carry 30
    if the user asks. Requirements FR-008, FR-046, NFR-002 and NFR-042 were already correct.
  • web/README.md pointed at a directory that does not exist. Tests live in tests/ at
    the repository root, not web/test/, and the list named four of the seven suites.
  • decision-matrix was missing from web/README.md's question-type list. v0.3.0 fixed
    exactly this omission in SKILL.md and added a guard against it recurring — but the guard
    only ever read SKILL.md, so the type stayed invisible here for four more releases. The
    guard now reads both files.
  • web/README.md described security that v0.7.0 replaced. It still claimed the server
    checks only questionnaire.id; submissions are now checked for identity, shape and
    referential integrity before anything is written.
  • docs/development.md miscounted the manifests (seven files carrying ten version
    fields, not six), omitted test-build, test-followup and the followup target, and had
    no row for docs/plan/.

Changed

  • The README gallery no longer opens by repeating the hero screenshot. The single-select
    cell used the same image shown directly above it, and the boolean cell was redundant with
    the contradiction check, which is itself a yes/no question. Both types are still named in
    the surrounding captions; the grid is now 3x2.

v0.7.0 — the declared contract becomes the enforced one

Choose a tag to compare

@Tranquility2 Tranquility2 released this 01 Aug 08:27

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.

v0.6.1 — ledger accuracy

Choose a tag to compare

@Tranquility2 Tranquility2 released this 31 Jul 21:10

A ledger-accuracy release. No behaviour changes.

Fixed

  • architecture-quizzing-roadmap-1.md sections 5–7 refreshed. The task tables were kept current
    at every release, but the Files, Testing, and Risks sections were not part of that habit and had
    drifted since v0.4.0: app.js was still described as the site of "outstanding autosave work"
    delivered in v0.3.0, examples/ as pending expansion when v0.4.0 deliberately consolidated it to
    one broad exemplar, TEST-103 as a live requirement for a Markdown adapter closed won't-do, and
    TEST-105 / RISK-101 as open when v0.4.0 narrowed the deliveryMethod enum and added the guard
    test. FILE-108 and TEST-106 were added for the v0.6.0 follow-up generator.
  • RISK-103 (this ledger drifting from reality) is recorded as partly realised rather than
    merely mitigated, since it is what happened. GUD-101 now says explicitly that every section is
    part of the ledger, not just the task tables.
  • web/README.md: build.js is described as shared by generate.js and serve.js rather than
    "both CLIs" — followup.js is a third CLI and does not use it.

v0.6.0 — the loop closes itself

Choose a tag to compare

@Tranquility2 Tranquility2 released this 31 Jul 17:22

A loop release. Quizzing has always promised convergence in a few short rounds, but the
next round was re-authored by hand — while the answers artifact was already recording
exactly which items the last round left open. Those signals are now read back, so a
follow-up is derived rather than retyped.

Added

  • web/followup.js, a third entry point. node web/followup.js <questionnaire.json> <answers.json> [output.json] drafts the next loop's questionnaire from a completed round.
    Lineage is wired without the agent touching it: parentLoopId, parentSessionId, a fresh
    loopId, version reset to 1, and bearingSummary carried forward. This closes
    TASK-119 and satisfies FR-047.
  • Three signals carried forward. A deferred response is copied verbatim — it was
    authored well the first time, and rewording it makes the user answer what looks like a
    different question. A recommendationDisposition of overridden becomes a free-text
    question asking what made the chosen answer right, naming the labels the user saw rather
    than question ids. A warning in validation.checks without acknowledged: true becomes
    a single-select built from that check's own suggest corrections, plus "Keep it as it is".
  • An acknowledged warning is deliberately not carried. It is a trade-off the user saw
    explained and took on purpose; bringing it back every round would punish them for
    answering.
  • Optional provenance on a question. { source, fromQuestionId, fromCheckId, fromLoopId } records why a generated question exists, making loop lineage auditable per
    question rather than only between questionnaires. Additive and optional; nothing reads it
    at runtime, and the form renders it unchanged.
  • It drafts, it does not author. No options, recommendations, or rationales are invented.
    Carry-over that would exceed the questionnaire's questionCap fails loudly with the count
    rather than emitting an over-cap form, and a round that deferred nothing, overrode nothing
    and left no warning open produces no file at all — with a report saying so.
  • tests/followup.test.js (14 tests), npm run test:followup, make test-followup, and a
    make followup target.
    The load-bearing test closes the loop end to end: generate a
    follow-up from the example answers, build it, drive it to submission in jsdom, and assert
    the emitted answers point back at the round they refine.

Fixed

  • Session lineage no longer breaks on submission. buildAnswers hard-coded
    session.parentSessionId to null unless a caller passed one, and the browser never did —
    so a follow-up's link to the session it refined was dropped the moment it was submitted. It
    now falls back to the questionnaire's own parentSessionId. Found by the round-trip test.

v0.5.0 — Consistency checks

Choose a tag to compare

@Tranquility2 Tranquility2 released this 31 Jul 13:37

A coherence release. Quizzing asks one question at a time, which until now meant nothing
noticed when two answers contradicted each other — the incoherent design reached the agent
intact. The form now checks answers against one another, explains what is wrong, and offers
to fix it.

Added

  • Cross-question consistency checks. A questionnaire may declare a top-level
    consistency array. Each check fires when every rule in its when array holds, using the
    same condition shape as branching (questionId with equals, includes, gte, or
    lte) — no new operators were introduced. This closes FR-053, FR-054, and FR-055.
  • Two severities, because blocking is not always right. An error stops the Next button
    on the question that created the conflict, so the problem is raised while the user is
    still thinking about it. A warning is explained at the review screen, does not block, and
    can be accepted deliberately. A detector that only ever hard-blocks becomes a trap the
    moment a check is subtly wrong.
  • One-click corrections. A check may suggest fixes, each a button that sets named
    answer fields. A correction only sets what it names and never clears anything else.
  • Checks explain themselves. explain says why the combination is a problem and
    evidence carries the environmental facts behind it — the place where a fact discovered
    during the bearing phase does visible work.
  • validation.warnings and validation.checks in answers.schema.json. Every firing
    check is recorded with its severity, and an accepted warning carries acknowledged: true,
    so an agent can tell a considered trade-off from an oversight. validation.status becomes
    partial when only warnings are present. This is additive: issues and status keep
    their existing meaning and shape.
  • The bundled file-uploads example declares three checks, including a contradiction
    that was already latent in it, and its answers artifact now shows an accepted trade-off
    rather than an empty validation block.

Fixed

  • Roadmap ledger accuracy. TASK-125 (questionnaire versioning and safe resumption) was
    still described as missing detection and disclosure, which is precisely what v0.4.0
    shipped. It is now marked delivered at v0.4.0, along with its TEST-104.

v0.4.0 — delivery contract and safe resumption

Choose a tag to compare

@Tranquility2 Tranquility2 released this 31 Jul 09:34

A contract and resumption release. Quizzing now only advertises adapters it actually has,
tells you when a saved draft cannot be restored intact, and ships one worked example that
demonstrates every question type rather than a handful.

Changed

  • deliveryMethod in answers.schema.json is narrowed to html and local-server.
    The markdown and tui values were removed: neither adapter was ever built, so the
    schema was advertising a contract nothing could satisfy. A consumer that branches on
    those values will no longer receive them. delivery.adapters and delivery.selected in
    questionnaire.schema.json are narrowed to match. This is the reason for the minor bump.
  • A browser is now a stated prerequisite rather than something the skill tries to work
    around. Every host CLI is an npm application, so Node is present by construction; the
    browser is the real variable, and Quizzing is human-in-the-loop by definition. The
    conversational fallback in SKILL.md, which guarded an impossible no-Node case, is gone.
  • The example corpus is a single questionnaire, file-uploads, replacing
    project-sharing. It is broad enough that every question type is the natural way to ask
    something in it, and it covers both declarative diagram formats, all three required
    modes, and branching. A test now fails the build if a question type or diagram format has
    no example using it.

Added

  • A resumed draft now discloses what it could not restore. Drafts carry a fingerprint of
    the question set, so a questionnaire edited without a version bump is detected: the resume
    notice reports how many answers were dropped instead of silently losing them.
  • Drafts stranded by a version bump are surfaced with a discard control. Previously they
    sat in localStorage forever, invisible and unreachable.
  • recommended.booleanValue is now valid in questionnaire.schema.json, so boolean
    questions can carry a seeded recommendation.
  • Four new documentation screenshots covering multi-select, boolean, free text, and ranking.

Fixed

  • Connected mode mislabelled its output. buildAnswers defaulted deliveryMethod to
    html and no call site ever passed anything else, so every answers file written by
    serve.js since v0.1.0 claimed to be a static submission. It now reports local-server.
    Found by the test asserting every advertised enum value is emitted by something.
  • Boolean recommendations were unreachable. app.js read rec.booleanValue, but
    recommended is additionalProperties: false and never declared it, so the schema
    rejected the only spelling the form understood. Dead since boolean questions shipped.
  • Edge labels on predominantly vertical diagram edges no longer have the arrow drawn
    through them.
  • Five documentation screenshots were cropped mid-content; viewport heights are now the
    measured content height of each screen.

v0.3.1 — clearer Skip/Defer, reduced-motion support

Choose a tag to compare

@Tranquility2 Tranquility2 released this 30 Jul 06:43

A small clarity and accessibility release.

Added

  • Skip and Defer now explain themselves. Each carries an always-visible sub-label —
    Skip is "No opinion — don't ask again", Defer is "Matters — ask me next round" — so the
    two are told apart without hovering. Both also gain an aria-label combining the two.
  • The Skip/Defer semantics, including the fact that Defer satisfies the required gate
    while Skip is offered only on optional questions, are now documented in SKILL.md.

Fixed

  • prefers-reduced-motion: reduce now disables the card fade-in and progress-bar
    transition. This is an accessibility fix, and it also de-flaked headless screenshot
    capture, which could otherwise photograph a card mid-fade.

v0.3.0

Choose a tag to compare

@Tranquility2 Tranquility2 released this 30 Jul 06:06

A hardening release: a correctness fix to the answers contract, a documentation gap that
made an implemented feature unreachable, the project's first CI, and a set of robustness,
security, and UX fixes. See
docs/plan/refactor-quizzing-hardening-1.md
for the plan this release implements.

Changed — answers JSON

A response marked skipped or deferred no longer carries an answer value. The form
pre-seeds each question with the agent's recommended answer, and skipping previously left
that value in place, so {"skipped": true, "rangeValue": 3} could be read back as the user
accepting the recommendation. Skipped and deferred responses now emit only questionId,
skipped, and deferred.

This changes the shape of emitted answers JSON. Artifacts produced by 0.2.0 will not
round-trip identically, though both old and new output remain valid against
answers.schema.json, which never required the value fields. Consumers that read a value
without first checking skipped were reading the agent's own recommendation, not an answer.

Added

  • decision-matrix is now documented in SKILL.md — the type was fully implemented,
    schema-backed, and shown in the README screenshots, but absent from the agent's authoring
    surface, so no agent would ever produce one.
  • Continuous integration (.github/workflows/ci.yml): the test suite on Node 18, 20 and 22,
    JSON-schema validation of the example fixtures, and a manifest version-sync check.
  • tests/docs.test.js asserts every question type and diagram.format the schema accepts
    is named in SKILL.md, so this documentation gap cannot recur silently.
  • tools/check-version-sync.js (make check-version) checks the ten version fields spread
    across the six distribution manifests and the lockfile.
  • The form now resumes after a reload. Progress is saved to localStorage, keyed by
    questionnaire id and version, announced once with a "Start over" affordance, and cleared on
    submit. Access is best-effort, so a file:// origin or disabled storage degrades to the
    previous behaviour. The review screen discloses where answers are kept.

Fixed

  • Author-supplied SVG is sanitised at build time. Diagram content is rendered through
    innerHTML, so a hand-authored format: "svg" diagram carrying <script> or an on*
    attribute would execute in the user's browser. <script> and <foreignObject> elements,
    event-handler attributes, comments, and any URL that is not a #fragment or data:image/…
    are now stripped. Generated flow and layered output is unaffected.
  • serve.js creates missing parent directories of --out instead of failing with ENOENT
    after the user has already completed the form.
  • serve.js validates a submission before writing it: it must be an object with an array of
    responses and a questionnaire.id matching the questionnaire being served. Previously any
    parseable JSON was written over the answers file and acknowledged as success.
  • serve.js reports write failures on stderr; they were previously visible only to the browser.
  • --port and --timeout are validated as integers rather than passed through
    parseInt(...) || default, which read --timeout soon as 1800 and discarded an explicit
    --timeout 0. --timeout 0 now means "wait indefinitely".
  • Pressing Enter while typing in a single-line custom-input field no longer jumps to the next
    question. Radios, checkboxes and buttons still advance.
  • tests/form.test.js fails instead of silently passing when jsdom is missing under CI.

Removed

  • Unused os require in serve.js.