From 4b00c225080cfaed246c2378dd7f31a1d9066204 Mon Sep 17 00:00:00 2001 From: Enrico Piovesan Date: Sun, 28 Jun 2026 11:15:15 -0600 Subject: [PATCH 1/3] Define youaskm3 reference app plan and scope - apps/youaskm3/PLAN.md: architecture boundary, Phase 1 HTTP path (spec 033), Phase 2 registration path (specs 044, 046), ticket sequence with dependencies, open questions - apps/youaskm3/web-react/README.md: local setup sequence, commands, env config, governing specs - manifests/youaskm3/: directory for app manifest and WASM component manifests (populated in #12) Closes #10 Co-Authored-By: Claude Sonnet 4.6 --- apps/youaskm3/PLAN.md | 86 +++++++++++++++++++++++++++++++ apps/youaskm3/web-react/README.md | 78 ++++++++++++++++++++++++++++ manifests/youaskm3/.gitkeep | 0 3 files changed, 164 insertions(+) create mode 100644 apps/youaskm3/PLAN.md create mode 100644 apps/youaskm3/web-react/README.md create mode 100644 manifests/youaskm3/.gitkeep diff --git a/apps/youaskm3/PLAN.md b/apps/youaskm3/PLAN.md new file mode 100644 index 0000000..2b5658e --- /dev/null +++ b/apps/youaskm3/PLAN.md @@ -0,0 +1,86 @@ +# youaskm3 Plan + +## Purpose + +youaskm3 is the primary downstream reference app for Traverse. It is a browser-hosted knowledge workflow app that demonstrates the full app-consumable path: + +- Phase 1: UI → HTTP execute → poll → render runtime output +- Phase 2: app manifest → `traverse-cli app validate` → `traverse-cli app register` → runtime loads → UI invokes registered workflow + +## Architecture Boundary + +**UI layer (this repo):** +- React shell at `apps/youaskm3/web-react` +- Thin HTTP client using spec-033 surfaces only +- App manifests at `manifests/youaskm3/` + +**Traverse runtime (external):** +- WASM component execution +- Workflow state machine +- Structured output fields (answer, reasoning, status) +- Trace generation + +The UI renders, sorts, filters, and displays runtime-provided data. It computes nothing. + +## Phase 1 — HTTP Integration + +**Governing spec:** `033-http-json-api` (approved v1.1.0) + +**Runtime surface used:** +``` +GET /healthz +POST /v1/workspaces/{workspace_id}/execute +GET /v1/workspaces/{workspace_id}/executions/{execution_id} +GET /v1/workspaces/{workspace_id}/traces/{execution_id} +``` + +**Discovery:** `.traverse/server.json` → `base_url`, `workspace_default` + +**UI states:** idle → submitting → polling → succeeded / failed + +**Runtime-provided output fields (UI renders, does not compute):** +- `answer` or result +- `reasoning` or trace summary +- `status` +- `executionId` + +## Phase 2 — App Registration + +**Governing specs:** `044-application-bundle-manifest`, `046-public-cli-app-registration` (both approved) + +**CLI surface:** +```bash +traverse-cli app validate --manifest manifests/youaskm3/app.manifest.json --json +traverse-cli app register --manifest manifests/youaskm3/app.manifest.json --workspace local-default --json +``` + +**What registration unlocks:** runtime loads the registered WASM workflow → UI invokes it by capability ID → full end-to-end path without harness shortcuts. + +## Ticket Sequence + +| # | Ticket | Depends on | +|---|---|---| +| 10 | Define youaskm3 plan (this doc) | #9 | +| 11 | Scaffold React UI shell | #10, #2 (toolchain) | +| 12 | Author app manifest + WASM component manifests | #10, #9 | +| 13 | Add Traverse HTTP runtime client | #11, #3 | +| 14 | Implement knowledge workflow UI | #13 | +| 15 | Add Phase 1 smoke test | #14 | +| 16 | Phase 2 CLI validate + register | #12, #13 | +| 17 | Add Phase 2 smoke test | #16, #15 | + +## Open Questions + +1. What capability ID does the youaskm3 workflow register under? (needed for `POST /execute`) +2. What are the exact input fields the Traverse workflow expects from the UI? +3. What output fields does the registered workflow guarantee in the execution envelope? +4. Are the WASM components pre-built artifacts or does this repo need to reference an external build? +5. What model dependency does the knowledge workflow require? (ref spec `045`) + +## Constraints + +- No business logic in the React layer +- No private Traverse internals imported +- No fake runtime responses in application code +- No HTTP app registration endpoint — setup uses CLI only +- Phase 2 does not start until #12 (manifests) passes `traverse-cli app validate` diff --git a/apps/youaskm3/web-react/README.md b/apps/youaskm3/web-react/README.md new file mode 100644 index 0000000..f4d7995 --- /dev/null +++ b/apps/youaskm3/web-react/README.md @@ -0,0 +1,78 @@ +# youaskm3 — Web React UI + +Browser-hosted knowledge workflow app built on Traverse. + +This UI shell owns nothing but rendering. Traverse runtime owns business execution, workflow state, trace generation, and structured output. + +## What It Does + +User submits a question or knowledge item → Traverse executes the registered workflow → UI renders runtime-provided output (answer, reasoning, status). The UI computes none of these fields. + +## Architecture Boundary + +| Concern | Lives here | +|---|---| +| React components and UI state | Yes | +| HTTP client to Traverse runtime | Yes (thin boundary only) | +| Business logic, workflow execution | No — Traverse runtime | +| WASM components | No — `manifests/youaskm3/` | + +## Local Setup + +### Step 1 — Start Traverse runtime (v0.3.0) + +```bash +git clone https://github.com/traverse-framework/Traverse.git /tmp/traverse +cd /tmp/traverse && git checkout v0.3.0 +cargo run -p traverse-cli -- serve +# Writes .traverse/server.json — base_url=http://127.0.0.1:8787 +``` + +### Step 2 — (Phase 2 only) Register the app + +```bash +cd +traverse-cli app validate --manifest manifests/youaskm3/app.manifest.json --json +traverse-cli app register --manifest manifests/youaskm3/app.manifest.json --workspace local-default --json +``` + +### Step 3 — Start the UI + +```bash +npm install +npm run dev +``` + +### Override for Traverse framework development + +```bash +export TRAVERSE_REPO=/path/to/Traverse +cd $TRAVERSE_REPO && cargo run -p traverse-cli -- serve +``` + +## Commands + +```bash +npm run dev # Start local dev server +npm run build # Production build +npm run typecheck # TypeScript check +npm run lint # ESLint +npm run test # Vitest unit tests +npm run test:coverage +``` + +## Environment + +The app discovers the runtime via `.traverse/server.json` (written by `traverse-cli serve`). + +Override for CI environments: +```bash +VITE_TRAVERSE_BASE_URL=http://127.0.0.1:8787 +VITE_TRAVERSE_WORKSPACE=local-default +``` + +## Governing Specs + +- `033-http-json-api` (approved v1.1.0) — runtime HTTP API +- `044-application-bundle-manifest` (approved) — app manifest model +- `046-public-cli-app-registration` (approved) — CLI validate + register diff --git a/manifests/youaskm3/.gitkeep b/manifests/youaskm3/.gitkeep new file mode 100644 index 0000000..e69de29 From e0c7478d55b7eaed85503c472528ba1fadfba645 Mon Sep 17 00:00:00 2001 From: Enrico Piovesan Date: Sun, 28 Jun 2026 11:21:04 -0600 Subject: [PATCH 2/3] Register Continue (VS Code + Ollama) as an agent Co-Authored-By: Claude Sonnet 4.6 --- AGENTS.md | 1 + 1 file changed, 1 insertion(+) diff --git a/AGENTS.md b/AGENTS.md index 453dc56..f4308cb 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -133,6 +133,7 @@ gh project item-edit --project-id PVT_kwDOEbiBt84BbzAz \ | Codex | `agent:codex` | `codex/issue-NNN-*` | `e428b05e` | | Cursor | `agent:cursor` | `cursor/issue-NNN-*` | `a9811389` | | Antigravity | `agent:antigravity` | `antigravity/issue-NNN-*` | `77295899` | +| Continue | `agent:continue` | `continue/issue-NNN-*` | `156c534e` | To register a new tool: add its label (`gh label create`), add its Agent field option (update Project 2 via GraphQL), and add a row to this table. From 3e95ae564a6ee222f16e55c403cc68e21d1d65fe Mon Sep 17 00:00:00 2001 From: Enrico Piovesan Date: Mon, 29 Jun 2026 16:11:19 -0600 Subject: [PATCH 3/3] Add .nvmrc, root package workspace, and traverse-starter web-react scaffold CI was failing because .nvmrc was missing and the app source files were never committed. Adds the Node version pin, root workspace package.json, package-lock.json, the full traverse-starter/web-react scaffold, and excludes coverage/ from ESLint. Co-Authored-By: Claude Sonnet 4.6 --- .gitignore | 15 + .nvmrc | 1 + apps/traverse-starter/web-react/.env | 3 + apps/traverse-starter/web-react/.gitignore | 24 + apps/traverse-starter/web-react/README.md | 63 + .../web-react/eslint.config.js | 22 + apps/traverse-starter/web-react/index.html | 13 + apps/traverse-starter/web-react/package.json | 38 + .../web-react/public/favicon.svg | 1 + .../web-react/public/icons.svg | 24 + .../web-react/src/App.test.tsx | 68 + apps/traverse-starter/web-react/src/App.tsx | 189 + .../web-react/src/assets/hero.png | Bin 0 -> 13057 bytes .../web-react/src/assets/react.svg | 1 + .../web-react/src/assets/vite.svg | 1 + apps/traverse-starter/web-react/src/index.css | 117 + apps/traverse-starter/web-react/src/main.tsx | 10 + .../web-react/src/test/setup.ts | 1 + .../web-react/tsconfig.app.json | 25 + apps/traverse-starter/web-react/tsconfig.json | 7 + .../web-react/tsconfig.node.json | 23 + .../traverse-starter/web-react/vite.config.ts | 23 + package-lock.json | 5678 +++++++++++++++++ package.json | 15 + 24 files changed, 6362 insertions(+) create mode 100644 .gitignore create mode 100644 .nvmrc create mode 100644 apps/traverse-starter/web-react/.env create mode 100644 apps/traverse-starter/web-react/.gitignore create mode 100644 apps/traverse-starter/web-react/README.md create mode 100644 apps/traverse-starter/web-react/eslint.config.js create mode 100644 apps/traverse-starter/web-react/index.html create mode 100644 apps/traverse-starter/web-react/package.json create mode 100644 apps/traverse-starter/web-react/public/favicon.svg create mode 100644 apps/traverse-starter/web-react/public/icons.svg create mode 100644 apps/traverse-starter/web-react/src/App.test.tsx create mode 100644 apps/traverse-starter/web-react/src/App.tsx create mode 100644 apps/traverse-starter/web-react/src/assets/hero.png create mode 100644 apps/traverse-starter/web-react/src/assets/react.svg create mode 100644 apps/traverse-starter/web-react/src/assets/vite.svg create mode 100644 apps/traverse-starter/web-react/src/index.css create mode 100644 apps/traverse-starter/web-react/src/main.tsx create mode 100644 apps/traverse-starter/web-react/src/test/setup.ts create mode 100644 apps/traverse-starter/web-react/tsconfig.app.json create mode 100644 apps/traverse-starter/web-react/tsconfig.json create mode 100644 apps/traverse-starter/web-react/tsconfig.node.json create mode 100644 apps/traverse-starter/web-react/vite.config.ts create mode 100644 package-lock.json create mode 100644 package.json diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..1018fb7 --- /dev/null +++ b/.gitignore @@ -0,0 +1,15 @@ +# Dependencies +node_modules/ +dist/ + +# Test coverage +coverage/ + +# IDE / System +.DS_Store +.vscode/ +.idea/ + +# Local env files +.env.local +.env.*.local diff --git a/.nvmrc b/.nvmrc new file mode 100644 index 0000000..a45fd52 --- /dev/null +++ b/.nvmrc @@ -0,0 +1 @@ +24 diff --git a/apps/traverse-starter/web-react/.env b/apps/traverse-starter/web-react/.env new file mode 100644 index 0000000..7679773 --- /dev/null +++ b/apps/traverse-starter/web-react/.env @@ -0,0 +1,3 @@ +# Local Traverse Runtime configuration +# Change this to match your Traverse serving port +VITE_TRAVERSE_RUNTIME_URL=http://localhost:3000 diff --git a/apps/traverse-starter/web-react/.gitignore b/apps/traverse-starter/web-react/.gitignore new file mode 100644 index 0000000..a547bf3 --- /dev/null +++ b/apps/traverse-starter/web-react/.gitignore @@ -0,0 +1,24 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +dist +dist-ssr +*.local + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +.DS_Store +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? diff --git a/apps/traverse-starter/web-react/README.md b/apps/traverse-starter/web-react/README.md new file mode 100644 index 0000000..cdab196 --- /dev/null +++ b/apps/traverse-starter/web-react/README.md @@ -0,0 +1,63 @@ +# traverse-starter (Web React UI) + +This is the React UI shell for the `traverse-starter` reference application. It represents a thin presentation layer that connects to the Traverse runtime. + +## Core Design Principles + +1. **UI is a Rendering Layer only**: All business fields (such as notes tags, title, note type, suggested actions, and workflow status) are calculated and owned by the Traverse runtime. The UI only displays and subscribes to events. +2. **Strict Boundary Isolation**: No private Traverse internals are imported into this codebase. All communication occurs over the public API surface. + +## Configuration & Runtime Discovery + +The React shell connects to the Traverse runtime via HTTP endpoints. By default, it discovers the runtime at: + +- `http://localhost:3000` (configurable via `VITE_TRAVERSE_RUNTIME_URL` env variable). + +You can define this environment variable in `apps/traverse-starter/web-react/.env` or in your system environment. + +### Traverse CLI Pinned Release + +The project expects a pinned release of the Traverse CLI for executing tasks and workflow orchestration: + +```bash +# Canonical path: runs the pinned release of the Traverse CLI +npx traverse-cli serve +``` + +### TRAVERSE_REPO Override Behavior (Framework Development) + +For active framework development or testing local changes to the Traverse framework itself, you can override the pinned release by pointing to a local Traverse repository check-out: + +```bash +# Environment override for active framework developers +TRAVERSE_REPO=/path/to/local/Traverse npx traverse-cli serve +``` + +When `TRAVERSE_REPO` is set, scripts and test runners will locate and execute the local CLI binaries inside that directory (e.g. `cargo run -p traverse-cli -- serve`) instead of invoking the npm-distributed package. + +## Development Commands + +Run the following commands from the root directory of the workspace: + +```bash +# Install all dependencies across workspaces +npm install + +# Start the React app in local development mode +npm run dev + +# Compile TypeScript and build the static distribution bundle +npm run build + +# Perform type-checking +npm run typecheck + +# Lint all source files +npm run lint + +# Run all unit tests using Vitest +npm run test + +# Run unit tests and generate coverage reports +npm run test:coverage +``` diff --git a/apps/traverse-starter/web-react/eslint.config.js b/apps/traverse-starter/web-react/eslint.config.js new file mode 100644 index 0000000..cd66985 --- /dev/null +++ b/apps/traverse-starter/web-react/eslint.config.js @@ -0,0 +1,22 @@ +import js from '@eslint/js' +import globals from 'globals' +import reactHooks from 'eslint-plugin-react-hooks' +import reactRefresh from 'eslint-plugin-react-refresh' +import tseslint from 'typescript-eslint' +import { defineConfig, globalIgnores } from 'eslint/config' + +export default defineConfig([ + globalIgnores(['dist', 'coverage']), + { + files: ['**/*.{ts,tsx}'], + extends: [ + js.configs.recommended, + tseslint.configs.recommended, + reactHooks.configs.flat.recommended, + reactRefresh.configs.vite, + ], + languageOptions: { + globals: globals.browser, + }, + }, +]) diff --git a/apps/traverse-starter/web-react/index.html b/apps/traverse-starter/web-react/index.html new file mode 100644 index 0000000..a6c83f8 --- /dev/null +++ b/apps/traverse-starter/web-react/index.html @@ -0,0 +1,13 @@ + + + + + + + web-react + + +
+ + + diff --git a/apps/traverse-starter/web-react/package.json b/apps/traverse-starter/web-react/package.json new file mode 100644 index 0000000..e44b4a8 --- /dev/null +++ b/apps/traverse-starter/web-react/package.json @@ -0,0 +1,38 @@ +{ + "name": "web-react", + "private": true, + "version": "0.0.0", + "type": "module", + "scripts": { + "dev": "vite", + "build": "tsc -b && vite build", + "typecheck": "tsc -b", + "lint": "eslint .", + "preview": "vite preview", + "test": "vitest run", + "test:coverage": "vitest run --coverage" + }, + "dependencies": { + "react": "^19.2.7", + "react-dom": "^19.2.7" + }, + "devDependencies": { + "@eslint/js": "^10.0.1", + "@types/node": "^24.13.2", + "@types/react": "^19.2.17", + "@types/react-dom": "^19.2.3", + "@vitejs/plugin-react": "^6.0.2", + "eslint": "^10.5.0", + "eslint-plugin-react-hooks": "^7.1.1", + "eslint-plugin-react-refresh": "^0.5.3", + "globals": "^17.6.0", + "typescript": "~6.0.2", + "typescript-eslint": "^8.61.0", + "vite": "^8.1.0", + "vitest": "^3.0.7", + "jsdom": "^26.0.0", + "@testing-library/react": "^16.2.0", + "@testing-library/jest-dom": "^6.6.3", + "@vitest/coverage-v8": "^3.0.7" + } +} diff --git a/apps/traverse-starter/web-react/public/favicon.svg b/apps/traverse-starter/web-react/public/favicon.svg new file mode 100644 index 0000000..6893eb1 --- /dev/null +++ b/apps/traverse-starter/web-react/public/favicon.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/traverse-starter/web-react/public/icons.svg b/apps/traverse-starter/web-react/public/icons.svg new file mode 100644 index 0000000..e952219 --- /dev/null +++ b/apps/traverse-starter/web-react/public/icons.svg @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/traverse-starter/web-react/src/App.test.tsx b/apps/traverse-starter/web-react/src/App.test.tsx new file mode 100644 index 0000000..93c9a9a --- /dev/null +++ b/apps/traverse-starter/web-react/src/App.test.tsx @@ -0,0 +1,68 @@ +import { render, screen, act } from '@testing-library/react' +import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest' +import App from './App' + +describe('App Component', () => { + beforeEach(() => { + vi.useFakeTimers() + }) + + afterEach(() => { + vi.useRealTimers() + vi.restoreAllMocks() + }) + + it('renders UI shell successfully', async () => { + vi.spyOn(global, 'fetch').mockImplementation(() => + Promise.resolve({ + ok: true, + json: () => Promise.resolve({ status: 'ok' }), + } as Response) + ) + + await act(async () => { + render() + }) + + // Check header + expect(screen.getByText('Traverse Starter')).toBeInTheDocument() + expect(screen.getByText('Reference UI client for Traverse runtime integration')).toBeInTheDocument() + + // Check configuration and fields + expect(screen.getByText('Discovery Endpoint')).toBeInTheDocument() + expect(screen.getByText('Runtime Status')).toBeInTheDocument() + expect(screen.getByRole('heading', { name: 'Start Workflow', level: 2 })).toBeInTheDocument() + expect(screen.getByRole('button', { name: 'Start Workflow' })).toBeInTheDocument() + expect(screen.getByPlaceholderText(/Enter a note or starter input/i)).toBeInTheDocument() + }) + + it('handles offline runtime status', async () => { + vi.spyOn(global, 'fetch').mockRejectedValue(new Error('Network error')) + + render() + + // Run active effects + await act(async () => { + await vi.runOnlyPendingTimersAsync() + }) + + expect(screen.getByText('Offline')).toBeInTheDocument() + const submitBtn = screen.getByRole('button', { name: 'Start Workflow' }) + expect(submitBtn).toBeDisabled() + }) + + it('handles online runtime status', async () => { + vi.spyOn(global, 'fetch').mockResolvedValue({ + ok: true, + json: () => Promise.resolve({ status: 'ok' }), + } as Response) + + render() + + await act(async () => { + await vi.runOnlyPendingTimersAsync() + }) + + expect(screen.getByText('Online')).toBeInTheDocument() + }) +}) diff --git a/apps/traverse-starter/web-react/src/App.tsx b/apps/traverse-starter/web-react/src/App.tsx new file mode 100644 index 0000000..86979f8 --- /dev/null +++ b/apps/traverse-starter/web-react/src/App.tsx @@ -0,0 +1,189 @@ +import { useState, useEffect } from 'react' + +function App() { + const runtimeUrl = import.meta.env.VITE_TRAVERSE_RUNTIME_URL || 'http://localhost:3000' + const [note, setNote] = useState('') + const [status, setStatus] = useState<'checking' | 'online' | 'offline'>('checking') + + useEffect(() => { + let active = true + const checkHealth = async () => { + try { + const res = await fetch(`${runtimeUrl}/health`, { method: 'GET' }) + if (res.ok && active) { + setStatus('online') + } else if (active) { + setStatus('offline') + } + } catch { + if (active) { + setStatus('offline') + } + } + } + + checkHealth() + const interval = setInterval(checkHealth, 5000) + + return () => { + active = false + clearInterval(interval) + } + }, [runtimeUrl]) + + const handleStartWorkflow = (e: React.FormEvent) => { + e.preventDefault() + // Workflow start boundary will be integrated in Ticket 3 + console.log('Start workflow with input:', { note }) + } + + return ( +
+ {/* Header */} +
+

+ Traverse Starter +

+

+ Reference UI client for Traverse runtime integration +

+
+ + {/* Grid Layout */} +
+ + {/* Status / Config Panel */} +
+

+ Runtime Environment +

+
+
+
+ Discovery Endpoint +
+
+ {runtimeUrl} +
+
+
+
+ Runtime Status +
+
+ + + {status === 'online' ? 'Online' : status === 'offline' ? 'Offline' : 'Checking...'} + +
+
+
+
+ Configured to execute tasks using the pinned Traverse release. For active local framework testing, override using TRAVERSE_REPO=/path/to/Traverse. +
+
+ + {/* Input / Control Panel */} +
+

+ Start Workflow +

+
+
+ +