{
  "packet": "si-delivery-evidence/1",
  "kind": "synthetic-sample",
  "visibility": "public",
  "outcome": "ship-one-feature-with-running-preview",
  "title": "Worked example: a small feature on a synthetic project",
  "notice": "This shared shopping list and its customer request are made up. Synthetic Industry built this small app only to demonstrate an evidence packet. It is not a customer delivery, not proof of past customer work and not a production project.",
  "generated": "2026-10-09",
  "request": {
    "text": "Add a button that clears the items I've already bought, and show how many items are still left to buy.",
    "received": "2026-10-09 (synthetic request, not a real customer)"
  },
  "acceptance_criteria": [
    {
      "id": "AC1",
      "text": "A 'Clear bought items' button removes every checked item and leaves unchecked ones."
    },
    {
      "id": "AC2",
      "text": "A counter reads 'N left to buy' (singular 'item'/plural 'items' handled) and updates when items are added, checked or cleared."
    },
    {
      "id": "AC3",
      "text": "With an empty list the counter reads '0 left to buy' and the button is disabled."
    },
    {
      "id": "AC4",
      "text": "The button and counter are usable with a keyboard and announced by a screen reader (counter in an aria-live region, button reachable and labelled)."
    }
  ],
  "implementation": {
    "summary": "Added the clear button and the live counter to the Shared shopping list app. The pure list module now has clearBought, remaining, remainingLabel and canClear; the page calls them after add, check and clear. The public preview runs from one file, with five demo items (two already bought).",
    "changes": [
      {
        "ref": "https://syntheticindustry.ai/examples/shopping-list-evidence/files/evidence/change.patch",
        "description": "The actual before-to-after patch (HTML, pure logic and tests)"
      },
      {
        "ref": "https://syntheticindustry.ai/examples/shopping-list-evidence/files/evidence/tests-before.txt",
        "description": "Test-first record: the 11 new AC1 to AC3 tests, run before any implementation, failed because the functions did not exist yet (5 existing tests passed). A historical record, not a current result."
      },
      {
        "ref": "https://syntheticindustry.ai/examples/shopping-list-evidence/files/after/list.js",
        "description": "The finished pure logic module"
      },
      {
        "ref": "https://syntheticindustry.ai/examples/shopping-list-evidence/files/after/list.test.js",
        "description": "The 16 automated tests, including the 11 added before the feature was written"
      },
      {
        "ref": "https://syntheticindustry.ai/examples/shopping-list-evidence/files/README.md",
        "description": "How to reproduce the example, with the commands that were run"
      }
    ]
  },
  "tests": [
    {
      "criterion": "AC1",
      "result": "pass",
      "summary": "After implementation, all 16 Node tests passed. AC1 tests show that clearing removes every bought item, keeps the other items in order with their ids intact, handles all-bought and none-bought lists and does not change the list it was given.",
      "command": "cd opportunities/catalogue/samples/lane-demo/after && node --test",
      "output_ref": "https://syntheticindustry.ai/examples/shopping-list-evidence/files/evidence/tests-after.txt"
    },
    {
      "criterion": "AC2",
      "result": "pass",
      "summary": "AC2 tests passed: remaining counts only unbought items; the label is singular for one item, plural for two or more, and changes after add, toggle and clear. Zero reads '0 left to buy'.",
      "command": "cd opportunities/catalogue/samples/lane-demo/after && node --test",
      "output_ref": "https://syntheticindustry.ai/examples/shopping-list-evidence/files/evidence/tests-after.txt"
    },
    {
      "criterion": "AC3",
      "result": "pass",
      "summary": "AC3 tests passed: the empty list has nothing left to buy, its label is '0 left to buy', and canClear is false. Clearing the final bought items leaves that state.",
      "command": "cd opportunities/catalogue/samples/lane-demo/after && node --test",
      "output_ref": "https://syntheticindustry.ai/examples/shopping-list-evidence/files/evidence/tests-after.txt"
    },
    {
      "result": "pass",
      "summary": "In a real Chromium browser, check-browser.js drove the preview and all 21 checks passed. It clicked the actual clear button, added and ticked items, reached the empty state and verified the text and disabled state. Keyboard Tab, Space and Enter worked; the button has an accessible name and the counter has aria-live='polite'.",
      "command": "PLAYWRIGHT_MODULE=/path/to/node_modules/playwright node check-browser.js",
      "output_ref": "https://syntheticindustry.ai/examples/shopping-list-evidence/files/evidence/browser-check.txt"
    },
    {
      "criterion": "AC4",
      "result": "not_run",
      "summary": "A real screen reader (VoiceOver, NVDA or TalkBack) has not been used. The browser checks above cover the keyboard behaviour, live-region attribute and accessible button name; they do not prove an announcement was heard. No screen-reader test has been run."
    }
  ],
  "preview": {
    "status": "provided",
    "access": "public-sample",
    "source": "https://syntheticindustry.ai/examples/shopping-list-evidence/files/evidence/shopping-list-preview.html"
  },
  "screenshots": {
    "status": "provided",
    "items": [
      {
        "ref": "https://syntheticindustry.ai/examples/shopping-list-evidence/files/evidence/before-desktop.png",
        "caption": "Before, desktop (1280x800): the starting list has add and tick controls, but no counter or clear button.",
        "alt": "The Shared shopping list before the change, with five items, Oat milk and Free-range eggs checked, and no counter or clear button."
      },
      {
        "ref": "https://syntheticindustry.ai/examples/shopping-list-evidence/files/evidence/after-desktop.png",
        "caption": "After, desktop (1280x800): the finished preview shows '3 items left to buy' and the 'Clear bought items' button.",
        "alt": "The finished Shared shopping list on desktop: five items, two checked, counter 3 items left to buy, and a Clear bought items button.",
        "criterion": "AC2"
      },
      {
        "ref": "https://syntheticindustry.ai/examples/shopping-list-evidence/files/evidence/after-mobile.png",
        "caption": "After, mobile (390x844, 2x): the same preview, with the counter and button fitting below the list.",
        "alt": "The finished Shared shopping list at mobile width, with the counter and labelled Clear bought items button beneath the five items.",
        "criterion": "AC2"
      }
    ]
  },
  "video": {
    "status": "provided",
    "ref": "https://syntheticindustry.ai/examples/shopping-list-evidence/files/evidence/walkthrough.webm",
    "caption": "A real 8.28-second capture: add Butter, check Sourdough loaf, then clear the bought items. No audio."
  },
  "review": {
    "status": "provided",
    "by": "Independent verifier (a fresh reviewer, not the builder; Node and static inspection only, no browser, no screen reader)",
    "verdict": "pass",
    "findings": [
      {
        "severity": "Medium",
        "text": "Very long unbroken item text is not wrapped, so it can overflow narrow screens. The same CSS is in the starting app.",
        "resolution": "Left as found: it is outside the agreed request. It is listed under known limits and would be offered as a separate small job."
      },
      {
        "severity": "Low",
        "text": "The test that the clear function does not change its input only checks the list length.",
        "resolution": "Left as found in this sample; the behaviour itself was confirmed by the reviewer."
      },
      {
        "severity": "Low",
        "text": "An item name made only of zero-width spaces is accepted.",
        "resolution": "Left as found: not part of the request."
      },
      {
        "severity": "Low",
        "text": "The review request called the recording 8.24 seconds; the file is 8.28 seconds.",
        "resolution": "Fixed in the review request and the packet caption."
      },
      {
        "severity": "Low",
        "text": "The README and packet said the preview builder only inlines the app; it also adds a noindex tag and the company footer.",
        "resolution": "Fixed: wording corrected."
      }
    ],
    "ref": "https://syntheticindustry.ai/examples/shopping-list-evidence/files/evidence/independent-review.md"
  },
  "limitations": [
    "This is a synthetic app and request, not a customer project or a customer delivery. It shows one small feature, not a track record of delivery.",
    "No production environment, real users, persistence, account sharing, build system or deployment was tested. Items live in memory and reset on reload; 'Shared' is the app's made-up name, not a multi-user feature.",
    "The preview is a single local/static file. It is supplied here for the public-page builder to copy; no public URL has been deployed or checked by this example's author.",
    "The video has no narration or audio. Screenshots show the initial seeded list, not every acceptance state.",
    "AC4 keyboard behaviour, the live-region attribute and accessible button name were checked in Chromium. No real screen reader announcement was heard, and no other browser or touch device was tested.",
    "The test output replaces only the absolute checkout path with <repo>. Node timings vary on rerun; the red record is from before implementation.",
    "The list does not wrap very long unbroken item text on narrow screens. Unrelated to the requested feature, so it was left as found rather than quietly widened in scope.",
    "The independent review used Node and static inspection only. It did not open a browser, play the video, view the screenshots or use a screen reader, and it did not test other browsers, touch devices or older Node versions. There is no customer sign-off or real pull request."
  ],
  "feedback": [],
  "acceptance": {
    "status": "pending",
    "reason": "A made-up example: nobody accepts it. In a real delivery this is where you accept the change or ask for changes."
  },
  "public_projection": {
    "date": "2026-10-10",
    "notice": "Public copy of the synthetic packet; artifact references changed to public SI URLs. Original run commands and independent review paths are historical provenance, not claims of a rerun or client delivery."
  }
}
