Document product boundary and release authority #46
|
|
@ -4,6 +4,7 @@ A working mobile-first bowel diary with an optional **photo-first AI assist**:
|
||||||
|
|
||||||
- [Product roadmap and live Gitea epic map](ROADMAP.md)
|
- [Product roadmap and live Gitea epic map](ROADMAP.md)
|
||||||
- [Product and safety boundary](PRODUCT.md)
|
- [Product and safety boundary](PRODUCT.md)
|
||||||
|
- [Product boundary and release authority decision](docs/PRODUCT-DECISIONS.md)
|
||||||
- [Self-hosted stool-vision decision](research/SELF-HOSTED-STOOL-VISION.md)
|
- [Self-hosted stool-vision decision](research/SELF-HOSTED-STOOL-VISION.md)
|
||||||
|
|
||||||
## Build a gated review release
|
## Build a gated review release
|
||||||
|
|
|
||||||
51
docs/PRODUCT-DECISIONS.md
Normal file
51
docs/PRODUCT-DECISIONS.md
Normal file
|
|
@ -0,0 +1,51 @@
|
||||||
|
# Product Boundary and Release Authority Decision
|
||||||
|
|
||||||
|
- **Status:** Accepted
|
||||||
|
- **Date:** 2026-08-20
|
||||||
|
- **Scope:** Photo-assisted bowel logging and release governance
|
||||||
|
|
||||||
|
## Context
|
||||||
|
|
||||||
|
Timmy can make a conservative visual suggestion from a user-selected image, but the available general-purpose model is not clinically validated. The product must preserve manual logging, deterministic red-flag escalation, and user control regardless of model availability or output.
|
||||||
|
|
||||||
|
## Decision
|
||||||
|
|
||||||
|
### Observable AI fields
|
||||||
|
|
||||||
|
AI may suggest only:
|
||||||
|
|
||||||
|
- visible Bristol form (Types 1–7);
|
||||||
|
- broad color;
|
||||||
|
- image quality.
|
||||||
|
|
||||||
|
Every suggestion is provisional, may abstain, and requires user review or correction before it can enter the journal. Symptoms remain user-entered, and journal saving is separate from training contribution consent.
|
||||||
|
|
||||||
|
### Prohibited inferences
|
||||||
|
|
||||||
|
AI must not infer or claim disease, bleeding, pain, urgency, fever, vomiting, treatment, causation, or whether a food is safe. It must not replace professional care, suppress deterministic red-flag escalation, or present a suggestion as a diagnosis.
|
||||||
|
|
||||||
|
### Release authority
|
||||||
|
|
||||||
|
Hermes/Timmy is the release authority for routine engineering, test, build, deployment, and release-candidate preparation. Automated evidence must remain reproducible and must not overstate model accuracy or safety.
|
||||||
|
|
||||||
|
### Human gates
|
||||||
|
|
||||||
|
Human gates are limited to:
|
||||||
|
|
||||||
|
1. clinical and privacy review when language or policy crosses those boundaries;
|
||||||
|
2. beta consent before participation;
|
||||||
|
3. RC approval before shipping a release candidate.
|
||||||
|
|
||||||
|
Routine provisioning, deployment, label sweeps, and release-candidate assembly are not human-operated gates.
|
||||||
|
|
||||||
|
## Consequences
|
||||||
|
|
||||||
|
- Model output is assistive and fail-closed, never authoritative.
|
||||||
|
- A generic open-weight VLM can support bootstrap experiments but cannot become the production Bristol classifier without the documented calibration and evaluation evidence.
|
||||||
|
- Release evidence and demonstrations must use fictional or synthetic data and state the non-diagnostic boundary honestly.
|
||||||
|
|
||||||
|
## Evidence and governing references
|
||||||
|
|
||||||
|
- [Product brief and safety boundary](../PRODUCT.md)
|
||||||
|
- [AI execution evidence](../AI-EVIDENCE.md)
|
||||||
|
- [Sovereign vision decision and measured limitations](../research/SELF-HOSTED-STOOL-VISION.md)
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "node --test tests/domain.test.js tests/analysis.test.js tests/vision-service.test.js tests/vision-config.test.js tests/training-ingest.test.js tests/ci-workflow.test.js tests/release-demo.test.js",
|
"test": "node --test tests/domain.test.js tests/analysis.test.js tests/vision-service.test.js tests/vision-config.test.js tests/training-ingest.test.js tests/ci-workflow.test.js tests/product-decisions.test.js tests/release-demo.test.js",
|
||||||
"test:ui": "node tests/ui.acceptance.mjs",
|
"test:ui": "node tests/ui.acceptance.mjs",
|
||||||
"test:photo": "node tests/photo-first.acceptance.mjs",
|
"test:photo": "node tests/photo-first.acceptance.mjs",
|
||||||
"check:syntax": "node --check app.js && node --check server.mjs && node --check service-worker.js && node --check src/analysis.js && node --check src/domain.js && node --check src/vision-config.js && node --check src/vision-service.js && node --check scripts/record_release_demo.mjs && bash -n scripts/run_selfhost_smolvlm.sh && python3 -m py_compile scripts/ingest_training_photo.py scripts/build_release.py",
|
"check:syntax": "node --check app.js && node --check server.mjs && node --check service-worker.js && node --check src/analysis.js && node --check src/domain.js && node --check src/vision-config.js && node --check src/vision-service.js && node --check scripts/record_release_demo.mjs && bash -n scripts/run_selfhost_smolvlm.sh && python3 -m py_compile scripts/ingest_training_photo.py scripts/build_release.py",
|
||||||
|
|
|
||||||
|
|
@ -97,10 +97,11 @@ await caption('The photo stays unsaved until explicit consent', 1300);
|
||||||
await page.locator('#ai-consent').check();
|
await page.locator('#ai-consent').check();
|
||||||
await tap('#analyze-photo', 500);
|
await tap('#analyze-photo', 500);
|
||||||
await page.getByText(/83% confidence/i).waitFor();
|
await page.getByText(/83% confidence/i).waitFor();
|
||||||
await caption('Timmy suggests only visible form and broad color', 1500);
|
await caption('AI may suggest visible form, broad color, and image quality — never symptoms or diagnosis', 1900);
|
||||||
await tap('#use-suggestion', 600);
|
await tap('#use-suggestion', 600);
|
||||||
await caption('Nothing persists until the user reviews or corrects it', 1500);
|
await caption('Nothing persists until the user reviews or corrects it', 1500);
|
||||||
await page.locator('[data-type="4"]').scrollIntoViewIfNeeded();
|
await page.locator('[data-type="4"]').scrollIntoViewIfNeeded();
|
||||||
|
await caption('Release gates: clinical/privacy review, beta consent, and RC approval', 1800);
|
||||||
await sleep(700);
|
await sleep(700);
|
||||||
await page.evaluate(() => {
|
await page.evaluate(() => {
|
||||||
document.querySelector('#demo-caption')?.remove();
|
document.querySelector('#demo-caption')?.remove();
|
||||||
|
|
|
||||||
17
tests/product-decisions.test.js
Normal file
17
tests/product-decisions.test.js
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
import test from 'node:test';
|
||||||
|
import assert from 'node:assert/strict';
|
||||||
|
import { readFile } from 'node:fs/promises';
|
||||||
|
|
||||||
|
const decisionPath = new URL('../docs/PRODUCT-DECISIONS.md', import.meta.url);
|
||||||
|
|
||||||
|
test('product decision record fixes the AI boundary and release authority', async () => {
|
||||||
|
const decision = await readFile(decisionPath, 'utf8');
|
||||||
|
|
||||||
|
assert.match(decision, /Observable AI fields[\s\S]*Bristol form[\s\S]*broad color[\s\S]*image quality/i);
|
||||||
|
assert.match(decision, /Prohibited inferences[\s\S]*disease[\s\S]*bleeding[\s\S]*pain[\s\S]*urgency[\s\S]*fever[\s\S]*vomiting[\s\S]*food/i);
|
||||||
|
assert.match(decision, /Hermes\/Timmy[\s\S]*release authority/i);
|
||||||
|
assert.match(decision, /Human gates[\s\S]*clinical and privacy review[\s\S]*beta consent[\s\S]*RC approval/i);
|
||||||
|
assert.match(decision, /\.\.\/PRODUCT\.md/);
|
||||||
|
assert.match(decision, /\.\.\/AI-EVIDENCE\.md/);
|
||||||
|
assert.match(decision, /\.\.\/research\/SELF-HOSTED-STOOL-VISION\.md/);
|
||||||
|
});
|
||||||
|
|
@ -9,5 +9,7 @@ test('release demo visibly explains the CI-protected browser path without overst
|
||||||
|
|
||||||
assert.match(demo, /Automated checks replay this synthetic path before review/);
|
assert.match(demo, /Automated checks replay this synthetic path before review/);
|
||||||
assert.match(demo, /tests\/fixtures\/synthetic-type4\.jpg/);
|
assert.match(demo, /tests\/fixtures\/synthetic-type4\.jpg/);
|
||||||
|
assert.match(demo, /AI may suggest visible form, broad color, and image quality — never symptoms or diagnosis/);
|
||||||
|
assert.match(demo, /Release gates: clinical\/privacy review, beta consent, and RC approval/);
|
||||||
assert.match(demo, /Visual assistance — never a diagnosis\./);
|
assert.match(demo, /Visual assistance — never a diagnosis\./);
|
||||||
});
|
});
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user