Skip to content
Closed
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
2 changes: 1 addition & 1 deletion .github/workflows/playwright.yml
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ jobs:
run: cd backend && npm ci --include=dev

- name: Install frontend dependencies
run: cd frontend && npm install --legacy-peer-deps
run: cd frontend && OPENUI_TELEMETRY_DISABLED=1 npm install --legacy-peer-deps

- name: Install Playwright browsers
run: npx playwright install chromium --with-deps
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ jobs:
frontend/package-lock.json
# Frontend typecheck follows shared imports into backend TypeScript.
- run: cd backend && npm ci --include=dev
- run: cd frontend && npm install --legacy-peer-deps
- run: cd frontend && OPENUI_TELEMETRY_DISABLED=1 npm install --legacy-peer-deps
- run: cd frontend && npm run typecheck
- name: Run frontend tests (coverage on the nightly schedule only)
run: |
Expand All @@ -139,7 +139,7 @@ jobs:
else
npx jest --watchAll=false --forceExit
fi
- run: cd frontend && node --test scripts/generate-seo-pages.test.mjs scripts/nginx-routing.test.mjs
- run: cd frontend && node --test scripts/generate-seo-pages.test.mjs scripts/nginx-routing.test.mjs scripts/ui-card-catalogue.test.mjs

tool-tests:
name: CLI, MCP and hosted runtime tests
Expand Down
8 changes: 8 additions & 0 deletions commonly-mcp/__tests__/tools.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
* (via the same _fetchImpl seam in client.js) and assert the wire shape.
*/

import { readFileSync } from 'node:fs';
import { jest } from '@jest/globals';
import { buildTools } from '../src/tools.js';
import { HttpError } from '../src/client.js';
Expand Down Expand Up @@ -690,3 +691,10 @@ describe('per-event inbox checkpoint', () => {
expect(fetchSpy).toHaveBeenCalledTimes(1);
});
});

test('post schema publishes the current catalogue tuple without a private manifest lookup', () => {
const revision = JSON.parse(readFileSync(new URL('../../backend/config/uiCardCatalogueRevision.json', import.meta.url), 'utf8'));
const description = byName.commonly_post_message.inputSchema.properties.payload.description;
for (const value of Object.values(revision)) expect(description).toContain(String(value));
expect(description).not.toContain('published catalogue revision manifest');
});
31 changes: 31 additions & 0 deletions docs/audits/task-498/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# TASK-498 renderer proof

Artboard: TASK-495, expanded to text in PR #2675 comment 6395684963.

The screenshots render the actual V2UICard and OpenUI 1.0.1 runtime against local fixtures. No production API, agent or grant was used. The preview is `frontend/design-system/preview/ui-card.html` compiled by Vite in production mode and served by its preview server. Browser API routes supplied the board task and the trace receipt. Both widths have seven cards, including malformed, expired and unsupported revision states.

- 1440: no horizontal overflow, ordinary primary link 32px tall.
- 390: no horizontal overflow, footer link 44px tall and full width; the three-column table becomes records.
- No page errors or OpenUI inspector auto-mount at either width.
- Static real-package render passes on the lockfile's React 18.3.1.

`catalogue-1440.png` and `catalogue-390.png` capture the actual component specimens. Ego's seat wrapper denied access, so these were measured with an isolated headless Chrome profile using Playwright, without any signed-in browser session.

The renderer accepts only the exact commonly.ui revision-1 ID/revision/hash tuple; missing or unsupported tuples retain the content with an unsupported-version note. Its hostname allowlist is exact: commonly.me, docs.commonly.me, github.com, HTTPS only, without credentials or custom ports. Other links are visible but unavailable. Legacy gig cards retain their narrower GitHub-only rule. Card source is never HTML and receives no tool provider.

TaskStatus reads the current pod's board. RunTrace reads the pod-scoped TASK-499 endpoint from the server-stamped run ID; it uses only name, outcome and duration. Endpoint routing/provenance is supplied by #2686. No raw arguments or results enter the preview.

The canonical grammar is owned by TASK-497 in `backend/config/uiCardCatalogue.json`. Run `node frontend/scripts/sync-ui-card-catalogue.mjs` to update the frontend copy; the byte-for-byte tests preserve positional prop order and the revision manifest.

## Repeat the production check

From the repository root with root and frontend dependencies installed:

```sh
OPENUI_TELEMETRY_DISABLED=1 npm ci --prefix frontend --legacy-peer-deps
node scripts/check-ui-card-production.mjs
```

The check compiles the real component specimen with the production Vite configuration, checks emitted JavaScript for the devtools CDN/mount code, opens the production assets in isolated Playwright Chromium, records outgoing requests and measures both widths. Set `CHROME_EXECUTABLE` to use an existing Chrome binary. It does not call a live API. `production-proof.json` records zero jsDelivr/PostHog requests and page errors. This is local production-build evidence, not a deployed walk.

Source parsing rejects dormant capabilities and bounds reference expansion before materialization (4,096 AST nodes across statements), plus a separate parsed-tree bound. Tests cover an exponential repeated-reference graph and its valid small control. The renderer has no A2UI interoperability claim.
Binary file added docs/audits/task-498/catalogue-1440.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/audits/task-498/catalogue-390.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
21 changes: 21 additions & 0 deletions docs/audits/task-498/production-proof.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"mode": "production",
"api": "controlled fixtures; no deployed walk",
"measurements": [
{
"width": 1440,
"overflow": false,
"buttonHeight": 32,
"devtools": 0
},
{
"width": 390,
"overflow": false,
"buttonHeight": 44,
"devtools": 0
}
],
"jsdelivrRequests": 0,
"posthogRequests": 0,
"pageErrors": []
}
1 change: 1 addition & 0 deletions frontend/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ WORKDIR /app

COPY package*.json ./

ENV OPENUI_TELEMETRY_DISABLED=1
RUN npm install

COPY . .
Expand Down
1 change: 1 addition & 0 deletions frontend/design-system/preview/ui-card.html
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<!doctype html><html><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1"><style>body{margin:0}</style></head><body><div id="root"></div><script type="module" src="/design-system/preview/ui-card.tsx"></script></body></html>
20 changes: 20 additions & 0 deletions frontend/design-system/preview/ui-card.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import revision from '../../src/v2/cards/uiCardCatalogueRevision.json';
import React from 'react';
import { createRoot } from 'react-dom/client';
import { MemoryRouter } from 'react-router-dom';
import { SocketProvider } from '../../src/context/SocketContext';
import { AuthContext } from '../../src/context/AuthContext';
import V2UICard from '../../src/v2/cards/V2UICard';
import '../../src/v2/v2.css';
import '@fontsource/ibm-plex-sans/400.css';
import '@fontsource/ibm-plex-sans/600.css';
import '@fontsource/ibm-plex-mono/500.css';
const sources = [
'root = Card("Release assessment", [Text("The change preserves identity and existing grants."), Steps([Step("Read the patch", "done"), Step("Check the release", "active", "CI is running"), Step("Publish", "pending")]), DiffSummary([File("frontend/src/v2/cards/V2UICard.tsx", 84, 12), File("backend/config/uiCardCatalogue.json", 30, 2)]), Link("Open pull request", "https://github.com/Team-Commonly/commonly/pull/2675", "primary")], "4 minutes ago", "The catalogue uses the same Signal tokens as the shell.")',
'root = Card("Project state", [TaskStatus("TASK-498", "Agent note: ready for review"), KeyValue([Pair("Repository", "Team-Commonly/commonly"), Pair("Tests", 71)]), Badge("Review pending", "pending"), List(["The component API is fixed", "The trace persists"], true)])',
'root = Card("Verification", [Table([Col("Surface"), Col("Width", "number"), Col("Result")], [["Pod chat", 1440, "Ready"], ["Pod chat", 390, "Ready"]]), RunTrace(3)])',
'root = Card("Links", [Text(["Source: ", Link("GitHub", "https://github.com/Team-Commonly/commonly", "text")]), Link("Unapproved host", "https://github.com.evil.test/", "button"), Badge("Done", "done")])',
'root = Text(@Run("unsafe"))',
];
const auth = { token:null, currentUser:null, user:null, loading:false, error:null, isAuthenticated:false } as any;
createRoot(document.getElementById('root')!).render(<AuthContext.Provider value={auth}><SocketProvider><MemoryRouter><div className="v2-root" style={{height:'auto',minHeight:'100vh',padding:16,boxSizing:'border-box'}}><main style={{maxWidth:560,margin:'0 auto',display:'grid',gap:24}}>{sources.map((source, i) => <V2UICard key={i} authorLabel="Polish" time="now" message={{id:String(i),pod_id:'111111111111111111111111',user_id:'u1',message_type:'card',created_at:new Date().toISOString(),content:'Plain text fallback remains readable.',payload:{...revision,kind:'ui',v:1,lang:'openui@1',source,runId:'012345678901234567890123'}}} />)}<V2UICard authorLabel="Polish" time="31d" message={{id:'old',pod_id:'111111111111111111111111',user_id:'u1',message_type:'card',created_at:new Date(Date.now()-31*86400000).toISOString(),content:'Expired card content.',payload:{...revision,kind:'ui',v:1,lang:'openui@1',source:'root = Text("Old")',runId:'012345678901234567890123'}}} /><V2UICard authorLabel="Polish" message={{id:"unsupported",pod_id:"111111111111111111111111",user_id:"u1",message_type:"card",created_at:new Date().toISOString(),content:"Unsupported revision keeps this text.",payload:{...revision,catalogRev:2,kind:"ui",v:1,lang:"openui@1",source:'root = Text("Do not guess")'}}} /></main></div></MemoryRouter></SocketProvider></AuthContext.Provider>);
Loading
Loading