Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
SUPERDOCS_API_KEY=your-key-here
SUPERDOCS_BASE_URL=https://api.superdocs.app
SUPERDOCS_MODE=fake
RUN_SUPERDOCS_LIVE_TESTS=0
25 changes: 25 additions & 0 deletions use-cases/yemulambika/tax-technical-memorandum-builder/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
node_modules/
dist/
coverage/
local-output/
.e2e-runtime/
playwright-report/
test-results/
downloads/
browser-profile/
*.tsbuildinfo
*.trace
*.zip
*.webm
*.mp4
.env
.env.*
!.env.example

# Generated only by Playwright/live verification; review-workflow.png is curated.
docs/evidence/offline-duplicate-analysis-proposals.png
docs/evidence/ui-live/
docs/evidence/ui-live-superdocs-validation.json
docs/evidence/client-export-render.png
docs/evidence/file-export-render.png
docs/evidence/manual-live/
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
node_modules/
dist/
coverage/
local-output/
.e2e-runtime/
playwright-report/
test-results/
fixtures/
docs/evidence/*.png
100 changes: 100 additions & 0 deletions use-cases/yemulambika/tax-technical-memorandum-builder/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
# Tax Technical Memorandum Builder

This build gives accounting and in-house tax reviewers an evidence-first way to turn four synthetic source documents into a reviewable tax memorandum. In the demonstrated workflow it verifies three quotation candidates, traces five supported monetary values, refuses one fabricated quotation and one unmatched number, and keeps two same-heading proposals independently actionable through approval and HTML export.

![Tax Technical Memorandum Builder review workflow](docs/evidence/review-workflow.png)

Built by Ambika Yemul for the SuperDocs task.

## What it builds and who it serves

The React interface walks a tax manager through facts, the question presented, supplied authorities, analysis, conclusion, and confidence. It is designed for reviewers who need citations and source-number traceability before they accept AI-proposed edits. The included Deccan Byteworks scenario and every document in `fixtures/` are fictional; this project is not tax advice and is not production-ready.

The workflow produces two HTML views from the same reviewed session state:

- **Client-ready HTML** contains the supported memorandum without internal warnings.
- **File-ready HTML** retains the same approved content and adds the authorities table, numeric traceability register, unsupported-authority warning, and reviewer decision log.

DOCX and PDF export are not claimed.

## Safeguards and human review

- Exact quotation verification normalizes whitespace but requires the quoted text to exist in its attached authority and retains its citation and locator.
- The authorities table distinguishes verified sources from an intentionally unattached/fabricated authority. Missing or unattached authority blocks finalization.
- Monetary values remain strings. Deterministic calculations and source-row IDs provide numeric traceability without binary floating-point arithmetic.
- A narrative-wide scan refuses unmatched monetary figures. The intentional negative control must be corrected before approval or export becomes available.
- Proposal identity uses the upstream change ID. A deterministic local fingerprint is used only when upstream identity is absent; heading text is never identity.
- Duplicate `Analysis` headings render as separate cards with independent decisions and reviewer notes.
- Every mandatory proposal requires an explicit decision and note. Approved material remains; rejected material is excluded from both outputs.
- An application fingerprint suppresses an identical second decision submission before it can replay the upstream approval request.
- Polling stops at `awaiting_approval`, `completed`, or `failed`.

## Architecture and SuperDocs operations

The browser calls only same-origin `/api/superdocs/*` routes. A Node BFF owns the real client, reads `SUPERDOCS_API_KEY` only from its process environment or the project-local ignored `.env`, and adds the Bearer header server-side. No `VITE_*` secret is accepted. Real mode fails visibly when configuration or an upstream request fails; it does not fall back to the offline adapter.

The build uses four logical SuperDocs operation groups:

1. **Upload** — `POST /v1/documents/upload-base64` once for each of the four inputs.
2. **Chat** — `POST /v1/chat/async`, followed by bounded `GET /v1/jobs/{job_id}` polling.
3. **Approve** — `POST /v1/chat/{session_id}/approve` with separate approved/rejected change decisions and notes.
4. **Export** — `POST /v1/documents/export` for client-ready and file-ready HTML.

See [the contract record](docs/superdocs-contract.md) and [live runbook](docs/SUPERDOCS_RUNBOOK.md).

## Run the quota-free offline demo

Prerequisites: Node.js 20+, npm, and Playwright Chromium.

```bash
npm ci
npx playwright install chromium
npm test
npm run typecheck
npm run lint
npm run format:check
npm run build
npm run test:ui
```

Start the offline BFF and frontend in separate terminals:

```bash
npm run bff:offline
```

```bash
npm run dev -- --host 127.0.0.1 --port 4175
```

Open `http://127.0.0.1:4175`, create the case, and select the four files in `fixtures/`. Filename validation accepts any browser `FileList` order and uploads them internally in the displayed canonical order.

## Optional live mode

Set these variables only in the BFF/server environment; never expose the key to Vite or browser code:

```text
SUPERDOCS_API_KEY=your-key-here
SUPERDOCS_BASE_URL=https://api.superdocs.app
SUPERDOCS_MODE=real
```

Then start `npm run bff` and the same frontend command shown above. The quota-bearing live harnesses are separately opt-in with `RUN_SUPERDOCS_LIVE_TESTS=1`; do not run `npm run test:live` or `npm run test:ui:live` without explicit authorization.

## Verified results

The real visible workflow succeeded with four uploaded documents and reached `awaiting_approval`. It displayed three quotation checks and monetary traceability, approved one proposal, rejected one proposal, reached zero mandatory pending decisions, submitted the reviewed content once, and downloaded client-ready and file-ready HTML. Both files rendered in Chromium; approved content and citations remained, while rejected and fabricated material was absent.

The observed live exports contained an orphan duplicate `Analysis` heading after rejection. The renderer was then corrected so a rejected proposal's complete block, including its heading, is removed. Regression tests prove the approved `Analysis` section remains and no empty heading survives. No corrected second live API run was made.

The public package intentionally includes only a sanitized verification summary and one offline screenshot. It excludes credentials, browser profiles, recordings, traces, raw Playwright output, temporary downloads, and the historical live export files.

## Limitations

- The public evidence proves the corrected renderer offline; it does not claim a second corrected live export.
- Only HTML exports were downloaded and inspected. DOCX and PDF are not claimed.
- The demonstration is a single fictional scenario and is not legal, tax, or accounting advice.
- State is in memory and single-process. Authentication, persistence, multi-tenant isolation, deployment hardening, rate-limit coordination, and production observability are out of scope.
- See [the full limitations record](docs/limitations.md).

There is no public deployment or video included; the reviewed workflow screenshot above is the public visual demonstration.
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# SuperDocs live runbook

1. Set `SUPERDOCS_BASE_URL=https://api.superdocs.app`, `SUPERDOCS_MODE=real`, and `SUPERDOCS_API_KEY` in the BFF process. Never use a `VITE_*` name. Add `RUN_SUPERDOCS_LIVE_TESTS=1` only for an explicitly authorized live test.
2. Run offline checks first: `npm test`, `npm run lint`, `npm run format:check`, `npm run build`, and `npm run test:ui`.
3. Run `npm run test:live`. It must stop on any non-2xx response, malformed proposal, failed/cancelled job, timeout, invalid quotation, unmatched number, or undecided mandatory proposal. Never substitute the fake adapter.
4. Inspect each downloaded HTML file structurally and by rendering it. This build does not claim DOCX or PDF export.
5. Live harness output belongs under ignored `local-output/`. Before sharing evidence, create a sanitized summary containing only endpoint templates, status codes, truncated IDs, durations, decisions, counts, filenames, and SHA-256 hashes. Never include credentials, authorization headers, source text, traces, recordings, or browser profiles.

The approval action approves proposed memorandum content only. It does not make a tax decision.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
{
"schema_version": 1,
"scope": "sanitized public verification summary",
"offline_verification": {
"unit_test_files_passed": 2,
"unit_tests_passed": 18,
"playwright_tests_passed": 4,
"playwright_retries": 0,
"typescript": "passed",
"eslint": "passed",
"prettier": "passed",
"production_build": "passed",
"dependency_vulnerabilities": 0
},
"observed_manual_live_workflow": {
"uploaded_document_count": 4,
"terminal_job_status": "awaiting_approval",
"quotation_checks": 3,
"verified_quotations": 2,
"rejected_fabricated_quotations": 1,
"traced_monetary_values": 5,
"unmatched_negative_controls_before_correction": 1,
"unmatched_negative_controls_after_correction": 0,
"approved_proposals": 1,
"rejected_proposals": 1,
"mandatory_pending_after_review": 0,
"reviewed_content_submission": "succeeded",
"exports": [
{
"filename": "synthetic-tax-memo-client.html",
"format": "html",
"bytes": 2378,
"sha256": "2c18c7d1b9654ce0cf5dede7b9880d24c82ba8477075a051736026681ab511fe",
"rendered_in_chromium": true
},
{
"filename": "synthetic-tax-memo-file.html",
"format": "html",
"bytes": 3034,
"sha256": "f0373c703b9e728c03b679c6d9984f20f8f308647636f0be50f023236eb3058f",
"rendered_in_chromium": true
}
],
"rejected_material_absent": true,
"approved_material_and_citations_present": true,
"historical_orphan_heading_observed": true
},
"post_live_renderer_correction": {
"verified_offline": true,
"approved_heading_and_content_retained": true,
"rejected_heading_and_content_absent": true,
"orphan_heading_absent": true,
"corrected_second_live_run_performed": false
},
"public_screenshot": {
"path": "review-workflow.png",
"bytes": 164005,
"width": 1280,
"height": 2930,
"sha256": "1284f553f741897c3110fe27dab30f88e856c5d59fc2a003854b89753e2c63c6",
"scope": "offline duplicate-heading review workflow"
},
"additional_live_requests_during_pr_preparation": 0,
"contains_credentials": false,
"contains_personal_email": false,
"contains_source_document_text": false
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Limitations

- Only HTML was requested, downloaded, hashed, and rendered. DOCX and PDF are not claimed.
- SuperDocs approval replay returned HTTP 400 during an earlier harness observation. Duplicate submission safety is therefore application-side fingerprint suppression, not a claim that the hosted approval endpoint is replay-idempotent.
- The supervised visible live workflow completed, but its exports contained an orphan duplicate `Analysis` heading after the rejected proposal was removed. The corrected renderer is regression-tested offline only; no second live API run was made.
- The completed manual browser session did not preserve trustworthy per-request timing, so the manual job duration is unavailable and is not reconstructed.
- Public evidence is deliberately minimal and sanitized: one offline screenshot plus a verification summary. Recordings, browser profiles, traces, raw results, and historical exports are excluded.
- The case, authorities, people, and monetary values are wholly fictional. This build is not tax advice and is not production-ready.
- The BFF stores state in memory. Authentication, durable storage, multi-tenant isolation, deployment hardening, rate-limit coordination, and production observability are out of scope.
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# SuperDocs contract record — 2026-08-13

Source: official `superdocsapp/docs` OpenAPI and examples. Authentication is `Authorization: Bearer <SUPERDOCS_API_KEY>`. This build requires the server-side base URL to be exactly `https://api.superdocs.app`.

The build uses `upload_document_base64`, `chat_async` in `ask_every_time` mode, `get_job`, per-change HITL approval, and `export_document`. Polling is bounded and terminates on `awaiting_approval`, `completed`, or `failed`. Proposed changes may be an array or a JSON-encoded string and are schema-checked after the optional second parse.

Live observation on 2026-08-15: replaying an identical approval after the first successful submission returned HTTP 400. The application therefore fingerprints a reviewed decision payload and suppresses an identical repeat instead of replaying it upstream. This is application-level idempotency; the hosted approval endpoint is not claimed to be replay-idempotent.

Current OpenAPI location: while status is `awaiting_approval`, proposals are
`metadata.pending_changes`; completed compact responses may expose
`result.document_changes.pending_changes` or `chunk_diffs`. Each `PendingChange` uses
`change_id`, `old_html`, and `new_html`. Any other shape fails visibly. Export bytes are not
considered valid merely because the HTTP request succeeded; live verification must inspect
non-empty content/type and expected sections.

This submission exports and claims HTML only. The client-ready and file-ready variants are generated from the same reviewed state before each HTML export request.
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
import { expect, test } from "@playwright/test";
import type { Proposal } from "../src/domain";
import { renderReviewedExports } from "../src/export-renderer";

const reviewedState = {
draftHtml:
"<h1>Tax Technical Memorandum</h1><h2>Facts</h2><p>Synthetic facts.</p><h2>Question presented</h2><p>Synthetic question.</p><h2>Authorities</h2><p>Synthetic Tax Code § 10(1)</p><p>Synthetic Tax Regulations 24(2)</p><h2>Analysis</h2><p>INR 1200000.00 is traced.</p><h2>Conclusion</h2><p>Supported conclusion.</p><h2>Confidence level</h2><p>Moderate</p>",
proposals: [
{
id: "approved-analysis",
section: "Analysis",
before: "",
after:
"<h2>Approved Analysis</h2><p>Approved proposal content remains.</p>",
decision: "APPROVED",
reviewerNote: "Retain",
},
{
id: "rejected-analysis",
section: "Analysis",
before: "",
after:
"<h2>Rejected Analysis</h2><p>Rejected proposal content is removed.</p>",
decision: "REJECTED",
reviewerNote: "Exclude",
},
{
id: "orphan-heading",
section: "Analysis",
before: "",
after: "<h2>Analysis</h2>",
decision: "APPROVED",
reviewerNote: "Heading-only fragment",
},
] satisfies Proposal[],
authorities: [
{ title: "Synthetic Basis Rule", citation: "Synthetic Tax Code § 10(1)" },
{
title: "Synthetic Disposal Rule",
citation: "Synthetic Tax Regulations 24(2)",
},
],
rows: [{ amount: "1200000.00", source_row_id: "CALC-001" }],
rejectedAuthorityTitle: "Fabricated Quotation Negative Control",
};
const rendered = renderReviewedExports(reviewedState);

for (const kind of ["client", "file"] as const) {
test(`${kind} corrected offline HTML derives from reviewed state and renders`, async ({
page,
}) => {
const consoleErrors: string[] = [];
page.on("console", (message) => {
if (message.type() === "error") consoleErrors.push(message.text());
});
await page.setContent(rendered[kind]);
await expect(
page.getByRole("heading", { name: "Approved Analysis", exact: true }),
).toBeVisible();
await expect(page.locator("body")).toContainText(
"Approved proposal content remains.",
);
await expect(page.locator("body")).not.toContainText("Rejected Analysis");
await expect(page.locator("body")).not.toContainText(
"Rejected proposal content is removed.",
);
const orphanHeadings = await page
.locator("h2")
.evaluateAll(
(headings) =>
headings.filter(
(heading) =>
heading.nextElementSibling?.tagName.toLowerCase() === "h2",
).length,
);
expect(orphanHeadings).toBe(0);
const overflow = await page.evaluate(() => ({
horizontal:
document.documentElement.scrollWidth >
document.documentElement.clientWidth,
clipped: [...document.querySelectorAll("*")].some((element) => {
const style = getComputedStyle(element);
return (
element.scrollWidth > element.clientWidth &&
style.overflowX === "hidden"
);
}),
}));
expect(overflow).toEqual({ horizontal: false, clipped: false });
if (kind === "client") {
await expect(page.locator("body")).not.toContainText(
"Unsupported-authority warnings",
);
await expect(page.locator("body")).not.toContainText(
"Reviewer decision log",
);
} else {
for (const heading of [
"Authorities table",
"Numeric traceability register",
"Unsupported-authority warnings",
"Reviewer decision log",
])
await expect(
page.getByRole("heading", { name: heading, exact: true }),
).toBeVisible();
}
expect(rendered.file.startsWith(rendered.client)).toBe(true);
expect(consoleErrors).toEqual([]);
await page.screenshot({
path: `docs/evidence/manual-live/corrected-offline-${kind}-render.png`,
fullPage: true,
});
});
}
Loading