diff --git a/apps/android-demo/README.md b/apps/android-demo/README.md deleted file mode 100644 index 0a2b2962..00000000 --- a/apps/android-demo/README.md +++ /dev/null @@ -1,21 +0,0 @@ -# Traverse Android Demo - -This is the first checked-in Android demo surface for Traverse. - -What it does: -- renders one approved expedition flow -- shows ordered runtime state updates -- shows the final trace summary and output panel -- assumes the runtime exists outside the app process - -Current implementation note: -- the repo now contains the Android app structure, Compose source, and a deterministic fixture-driven rendering path -- local smoke validation is available through `bash scripts/ci/android_demo_smoke.sh` -- this machine does not currently have Gradle or an Android SDK configured, so native Android assembly is not part of the local green path here - -Expected local build path on a machine with Android tooling: -- `cd apps/android-demo` -- `./gradlew :app:assembleDebug` - -Fixture source: -- `app/src/main/assets/expedition-runtime-session.json` diff --git a/apps/android-demo/app/build.gradle.kts b/apps/android-demo/app/build.gradle.kts deleted file mode 100644 index 7428ad7f..00000000 --- a/apps/android-demo/app/build.gradle.kts +++ /dev/null @@ -1,42 +0,0 @@ -plugins { - id("com.android.application") - id("org.jetbrains.kotlin.android") -} - -android { - namespace = "com.traverse.demo.android" - compileSdk = 35 - - defaultConfig { - applicationId = "com.traverse.demo.android" - minSdk = 28 - targetSdk = 35 - versionCode = 1 - versionName = "0.1.0" - } - - buildFeatures { - compose = true - } - - composeOptions { - kotlinCompilerExtensionVersion = "1.5.14" - } - - compileOptions { - sourceCompatibility = JavaVersion.VERSION_17 - targetCompatibility = JavaVersion.VERSION_17 - } - - kotlinOptions { - jvmTarget = "17" - } -} - -dependencies { - implementation(platform("androidx.compose:compose-bom:2024.09.02")) - implementation("androidx.activity:activity-compose:1.9.2") - implementation("androidx.compose.material3:material3") - implementation("androidx.compose.ui:ui") - implementation("androidx.compose.ui:ui-tooling-preview") -} diff --git a/apps/android-demo/app/src/main/AndroidManifest.xml b/apps/android-demo/app/src/main/AndroidManifest.xml deleted file mode 100644 index 2084f06c..00000000 --- a/apps/android-demo/app/src/main/AndroidManifest.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - diff --git a/apps/android-demo/app/src/main/assets/expedition-runtime-session.json b/apps/android-demo/app/src/main/assets/expedition-runtime-session.json deleted file mode 100644 index bcee3cc4..00000000 --- a/apps/android-demo/app/src/main/assets/expedition-runtime-session.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "demo_id": "expedition.plan.v1", - "title": "Plan Expedition", - "request_id": "req-expedition-001", - "execution_id": "exec_req-expedition-001", - "trace_id": "trace_exec_req-expedition-001", - "status": "completed", - "summary": "Traverse evaluates the governed expedition workflow and assembles a final expedition plan." -} diff --git a/apps/android-demo/app/src/main/java/com/traverse/demo/android/MainActivity.kt b/apps/android-demo/app/src/main/java/com/traverse/demo/android/MainActivity.kt deleted file mode 100644 index 3759a16f..00000000 --- a/apps/android-demo/app/src/main/java/com/traverse/demo/android/MainActivity.kt +++ /dev/null @@ -1,99 +0,0 @@ -package com.traverse.demo.android - -import android.os.Bundle -import androidx.activity.ComponentActivity -import androidx.activity.compose.setContent -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.PaddingValues -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.foundation.lazy.items -import androidx.compose.material3.Card -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Scaffold -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import androidx.compose.ui.unit.dp - -class MainActivity : ComponentActivity() { - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - setContent { - MaterialTheme { - TraverseAndroidDemoScreen(sampleStateUpdates) - } - } - } -} - -private val sampleStateUpdates = listOf( - DemoStateUpdate( - "Discovering capability", - "Looking up expedition.planning.plan-expedition@1.0.0 in the registry." - ), - DemoStateUpdate( - "Evaluating constraints", - "Confirming the approved expedition capability can run locally." - ), - DemoStateUpdate( - "Executing workflow", - "Traversing the approved expedition planning workflow." - ), - DemoStateUpdate( - "Completed", - "The expedition plan is ready for final review." - ) -) - -data class DemoStateUpdate( - val title: String, - val detail: String, -) - -@Composable -private fun TraverseAndroidDemoScreen(stateUpdates: List) { - Scaffold { padding -> - LazyColumn( - modifier = Modifier - .fillMaxSize() - .padding(padding), - contentPadding = PaddingValues(16.dp), - verticalArrangement = Arrangement.spacedBy(12.dp), - ) { - item { - Card(modifier = Modifier.fillMaxWidth()) { - Column(modifier = Modifier.padding(16.dp)) { - Text("Traverse Android Demo", style = MaterialTheme.typography.headlineSmall) - Text( - "Plan Expedition", - style = MaterialTheme.typography.titleMedium, - modifier = Modifier.padding(top = 8.dp) - ) - Text( - "Runtime states and final trace summary render from the approved expedition demo fixture.", - style = MaterialTheme.typography.bodyMedium, - modifier = Modifier.padding(top = 8.dp) - ) - } - } - } - - items(stateUpdates) { update -> - Card(modifier = Modifier.fillMaxWidth()) { - Column(modifier = Modifier.padding(16.dp)) { - Text(update.title, style = MaterialTheme.typography.titleMedium) - Text( - update.detail, - style = MaterialTheme.typography.bodyMedium, - modifier = Modifier.padding(top = 6.dp) - ) - } - } - } - } - } -} diff --git a/apps/android-demo/app/src/main/res/values/strings.xml b/apps/android-demo/app/src/main/res/values/strings.xml deleted file mode 100644 index 75f48c8d..00000000 --- a/apps/android-demo/app/src/main/res/values/strings.xml +++ /dev/null @@ -1,3 +0,0 @@ - - Traverse Android Demo - diff --git a/apps/android-demo/build.gradle.kts b/apps/android-demo/build.gradle.kts deleted file mode 100644 index 017d9099..00000000 --- a/apps/android-demo/build.gradle.kts +++ /dev/null @@ -1,4 +0,0 @@ -plugins { - id("com.android.application") version "8.5.2" apply false - id("org.jetbrains.kotlin.android") version "1.9.24" apply false -} diff --git a/apps/android-demo/gradle.properties b/apps/android-demo/gradle.properties deleted file mode 100644 index e6961679..00000000 --- a/apps/android-demo/gradle.properties +++ /dev/null @@ -1,3 +0,0 @@ -org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8 -android.useAndroidX=true -kotlin.code.style=official diff --git a/apps/android-demo/settings.gradle.kts b/apps/android-demo/settings.gradle.kts deleted file mode 100644 index 9614dec3..00000000 --- a/apps/android-demo/settings.gradle.kts +++ /dev/null @@ -1,2 +0,0 @@ -rootProject.name = "TraverseAndroidDemo" -include(":app") diff --git a/apps/browser-consumer/README.md b/apps/browser-consumer/README.md deleted file mode 100644 index 172961c6..00000000 --- a/apps/browser-consumer/README.md +++ /dev/null @@ -1,37 +0,0 @@ -# Traverse Browser Consumer Package - -This is the browser-targeted consumer package for downstream apps such as `youaskm3`. - -It stays focused on the first governed browser-hosted path: - -- it reuses the approved live browser adapter client -- it exposes a browser-safe subscription flow for the downstream app -- it keeps runtime ordering, trace visibility, and terminal outcomes governed by Traverse surfaces rather than private app logic -- it does not define UI, branding, or app-specific product behavior - -## Supported Use - -The package is intended to be consumed by a browser-hosted app that can bundle the façade and point it at the live browser adapter proxy. - -It provides: - -- a browser consumer session shape -- approved subscription request construction -- live subscription execution -- ordered browser subscription message application -- terminal trace summarization - -## Browser-Hosted Assumptions - -- The browser-hosted app has access to the approved live browser adapter proxy path. -- The browser-hosted app uses the published consumer façade rather than internal Traverse crate layout. -- The browser-hosted app relies on governed runtime updates, trace visibility, and terminal outcomes from Traverse. -- Unsupported auth, remote deployment, and multi-tenant guarantees remain out of scope for the first slice. - -## Quick Start - -```bash -node -e "const client = require('./apps/browser-consumer'); console.log(client.APPROVED_BROWSER_CONSUMER_SESSION.title)" -``` - -For the deterministic browser-hosted smoke path, see [../../scripts/ci/browser_consumer_package_smoke.sh](/Users/piovese/Documents/cogolo/scripts/ci/browser_consumer_package_smoke.sh). diff --git a/apps/browser-consumer/index.js b/apps/browser-consumer/index.js deleted file mode 100644 index f2e42e87..00000000 --- a/apps/browser-consumer/index.js +++ /dev/null @@ -1,67 +0,0 @@ -(function (root, factory) { - const client = factory(); - - if (typeof module === "object" && module.exports) { - module.exports = client; - } - - if (root) { - root.TraverseBrowserConsumer = client; - } -})(typeof globalThis !== "undefined" ? globalThis : this, function () { - let baseClient = null; - - if (typeof require === "function") { - try { - baseClient = require("../react-demo/src/browser-adapter-client.js"); - } catch { - baseClient = null; - } - } - - if (!baseClient && typeof globalThis !== "undefined" && globalThis.TraverseReactDemoClient) { - baseClient = globalThis.TraverseReactDemoClient; - } - - if (!baseClient) { - throw new Error( - "Traverse browser consumer requires the approved browser adapter client to be available.", - ); - } - - const APPROVED_BROWSER_CONSUMER_SESSION = { - ...baseClient.APPROVED_BROWSER_DEMO_SESSION, - title: "Traverse Browser Consumer", - summary: - "Traverse's browser-targeted consumer facade for downstream browser-hosted apps like youaskm3.", - }; - - function createBrowserConsumerState() { - return baseClient.createLiveDemoState(); - } - - function buildBrowserConsumerSubscriptionRequest() { - return baseClient.buildApprovedSubscriptionRequest(); - } - - function runBrowserConsumerSubscription(options = {}) { - return baseClient.runLiveBrowserSubscription(options); - } - - function applyBrowserConsumerMessage(state, message, created) { - return baseClient.applyBrowserSubscriptionMessage(state, message, created); - } - - function browserConsumerTraceSummary(trace, terminalResult) { - return baseClient.traceSummary(trace, terminalResult); - } - - return { - APPROVED_BROWSER_CONSUMER_SESSION, - applyBrowserConsumerMessage, - browserConsumerTraceSummary, - buildBrowserConsumerSubscriptionRequest, - createBrowserConsumerState, - runBrowserConsumerSubscription, - }; -}); diff --git a/apps/browser-consumer/package.json b/apps/browser-consumer/package.json deleted file mode 100644 index 09701322..00000000 --- a/apps/browser-consumer/package.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "name": "traverse-browser-consumer", - "version": "0.1.0", - "private": true, - "main": "index.js", - "description": "Traverse browser-targeted consumer facade for downstream browser-hosted apps." -} diff --git a/apps/macos-demo/Package.swift b/apps/macos-demo/Package.swift deleted file mode 100644 index 62193ecc..00000000 --- a/apps/macos-demo/Package.swift +++ /dev/null @@ -1,18 +0,0 @@ -// swift-tools-version: 6.0 -import PackageDescription - -let package = Package( - name: "TraverseMacOSDemo", - platforms: [ - .macOS(.v14), - ], - products: [ - .executable(name: "TraverseMacOSDemoApp", targets: ["TraverseMacOSDemoApp"]), - ], - targets: [ - .executableTarget( - name: "TraverseMacOSDemoApp", - path: "Sources/TraverseMacOSDemoApp" - ), - ] -) diff --git a/apps/macos-demo/README.md b/apps/macos-demo/README.md deleted file mode 100644 index ad23688e..00000000 --- a/apps/macos-demo/README.md +++ /dev/null @@ -1,21 +0,0 @@ -# Traverse macOS Demo - -This is the first native macOS demo surface for Traverse. - -What it does: -- renders one approved expedition flow -- shows ordered runtime state updates -- shows the final trace summary and output panel -- keeps the runtime separate from the app process - -Current implementation note: -- this repo currently checks in the native SwiftUI app source and deterministic fixture-driven rendering path -- local smoke validation is available through `bash scripts/ci/macos_demo_smoke.sh` -- a full Xcode app build requires a full Xcode installation; this machine currently only exposes Command Line Tools, so native app compilation is not part of the local green path here - -Expected local run path on a machine with full Xcode: -- `open apps/macos-demo/Package.swift` -- run the `TraverseMacOSDemoApp` target - -Fixture source: -- `examples/fixtures/expedition-runtime-session.json` diff --git a/apps/macos-demo/Sources/TraverseMacOSDemoApp/DemoContentView.swift b/apps/macos-demo/Sources/TraverseMacOSDemoApp/DemoContentView.swift deleted file mode 100644 index a885f3cc..00000000 --- a/apps/macos-demo/Sources/TraverseMacOSDemoApp/DemoContentView.swift +++ /dev/null @@ -1,87 +0,0 @@ -import SwiftUI - -struct DemoSessionViewModel { - let session: DemoSession - - static func sample() -> DemoSessionViewModel { - DemoSessionViewModel(session: DemoSessionRepository.sample()) - } -} - -struct DemoContentView: View { - let viewModel: DemoSessionViewModel - - var body: some View { - NavigationSplitView { - List(viewModel.session.stateUpdates) { update in - VStack(alignment: .leading, spacing: 6) { - Text(update.title) - .font(.headline) - Text(update.detail) - .font(.subheadline) - .foregroundStyle(.secondary) - Text(update.timestamp) - .font(.caption.monospaced()) - .foregroundStyle(.tertiary) - } - .padding(.vertical, 6) - } - .navigationTitle(viewModel.session.title) - } detail: { - ScrollView { - VStack(alignment: .leading, spacing: 18) { - GroupBox("Runtime Summary") { - VStack(alignment: .leading, spacing: 10) { - labeledRow("Status", value: viewModel.session.status) - labeledRow("Request", value: viewModel.session.requestID) - labeledRow("Execution", value: viewModel.session.executionID) - labeledRow("Trace", value: viewModel.session.traceID) - labeledRow("Target", value: viewModel.session.trace.placement.selectedTarget) - Text(viewModel.session.summary) - .font(.body) - } - .frame(maxWidth: .infinity, alignment: .leading) - } - - GroupBox("Request Goal") { - Text(viewModel.session.request.goal) - .frame(maxWidth: .infinity, alignment: .leading) - } - - GroupBox("Emitted Events") { - VStack(alignment: .leading, spacing: 8) { - ForEach(viewModel.session.trace.emittedEvents, id: \.self) { eventID in - Text(eventID) - .font(.body.monospaced()) - } - } - .frame(maxWidth: .infinity, alignment: .leading) - } - - GroupBox("Final Output") { - VStack(alignment: .leading, spacing: 10) { - labeledRow("Plan ID", value: viewModel.session.trace.output.planID) - labeledRow("Route", value: viewModel.session.trace.output.route) - labeledRow("Weather", value: viewModel.session.trace.output.weatherSummary) - labeledRow("Team Status", value: viewModel.session.trace.output.teamStatus) - labeledRow("Next Action", value: viewModel.session.trace.output.nextAction) - } - .frame(maxWidth: .infinity, alignment: .leading) - } - } - .padding(24) - } - } - } - - @ViewBuilder - private func labeledRow(_ label: String, value: String) -> some View { - VStack(alignment: .leading, spacing: 4) { - Text(label) - .font(.caption) - .foregroundStyle(.secondary) - Text(value) - .font(.body) - } - } -} diff --git a/apps/macos-demo/Sources/TraverseMacOSDemoApp/DemoSession.swift b/apps/macos-demo/Sources/TraverseMacOSDemoApp/DemoSession.swift deleted file mode 100644 index 3bfa58f1..00000000 --- a/apps/macos-demo/Sources/TraverseMacOSDemoApp/DemoSession.swift +++ /dev/null @@ -1,136 +0,0 @@ -import Foundation - -struct DemoSession: Decodable { - let demoID: String - let title: String - let requestID: String - let executionID: String - let traceID: String - let status: String - let summary: String - let request: DemoRequest - let stateUpdates: [DemoStateUpdate] - let trace: DemoTrace - - enum CodingKeys: String, CodingKey { - case demoID = "demo_id" - case title - case requestID = "request_id" - case executionID = "execution_id" - case traceID = "trace_id" - case status - case summary - case request - case stateUpdates = "state_updates" - case trace - } -} - -struct DemoRequest: Decodable { - let goal: String - let requestedTarget: String - let caller: String - - enum CodingKeys: String, CodingKey { - case goal - case requestedTarget = "requested_target" - case caller - } -} - -struct DemoStateUpdate: Decodable, Identifiable { - let state: String - let title: String - let timestamp: String - let detail: String - - var id: String { "\(timestamp)-\(state)" } -} - -struct DemoTrace: Decodable { - let selectedCapabilityID: String - let selectedCapabilityVersion: String - let placement: DemoPlacement - let emittedEvents: [String] - let output: DemoOutput - - enum CodingKeys: String, CodingKey { - case selectedCapabilityID = "selected_capability_id" - case selectedCapabilityVersion = "selected_capability_version" - case placement - case emittedEvents = "emitted_events" - case output - } -} - -struct DemoPlacement: Decodable { - let requestedTarget: String - let selectedTarget: String - let status: String - let reason: String - - enum CodingKeys: String, CodingKey { - case requestedTarget = "requested_target" - case selectedTarget = "selected_target" - case status - case reason - } -} - -struct DemoOutput: Decodable { - let planID: String - let route: String - let weatherSummary: String - let teamStatus: String - let nextAction: String - - enum CodingKeys: String, CodingKey { - case planID = "plan_id" - case route - case weatherSummary = "weather_summary" - case teamStatus = "team_status" - case nextAction = "next_action" - } -} - -enum DemoSessionRepository { - static func sample() -> DemoSession { - let url = URL(fileURLWithPath: "examples/fixtures/expedition-runtime-session.json") - let data = (try? Data(contentsOf: url)) ?? Data() - let decoder = JSONDecoder() - - if let session = try? decoder.decode(DemoSession.self, from: data) { - return session - } - - return DemoSession( - demoID: "fallback", - title: "Traverse macOS Demo", - requestID: "req-fallback", - executionID: "exec-fallback", - traceID: "trace-fallback", - status: "error", - summary: "Fixture loading failed.", - request: DemoRequest(goal: "Unavailable", requestedTarget: "local", caller: "native_demo"), - stateUpdates: [], - trace: DemoTrace( - selectedCapabilityID: "unavailable", - selectedCapabilityVersion: "0.0.0", - placement: DemoPlacement( - requestedTarget: "local", - selectedTarget: "local", - status: "not_attempted", - reason: "fixture_unavailable" - ), - emittedEvents: [], - output: DemoOutput( - planID: "unavailable", - route: "Unavailable", - weatherSummary: "Unavailable", - teamStatus: "unavailable", - nextAction: "Restore the fixture file." - ) - ) - ) - } -} diff --git a/apps/macos-demo/Sources/TraverseMacOSDemoApp/TraverseMacOSDemoApp.swift b/apps/macos-demo/Sources/TraverseMacOSDemoApp/TraverseMacOSDemoApp.swift deleted file mode 100644 index ad45092f..00000000 --- a/apps/macos-demo/Sources/TraverseMacOSDemoApp/TraverseMacOSDemoApp.swift +++ /dev/null @@ -1,12 +0,0 @@ -import SwiftUI - -@main -struct TraverseMacOSDemoApp: App { - var body: some Scene { - WindowGroup("Traverse macOS Demo") { - DemoContentView(viewModel: DemoSessionViewModel.sample()) - .frame(minWidth: 1080, minHeight: 720) - } - .windowStyle(.titleBar) - } -} diff --git a/apps/react-demo/README.md b/apps/react-demo/README.md deleted file mode 100644 index cf0b340c..00000000 --- a/apps/react-demo/README.md +++ /dev/null @@ -1,62 +0,0 @@ -# Traverse React Demo - -This is the first checked-in React browser demo surface for Traverse. - -If you want the shortest end-to-end local path, start with [quickstart.md](/Users/piovese/Documents/cogolo/quickstart.md) and then come back here for the demo-specific details. - -If you want the formal app-consumable acceptance entrypoint, use [docs/app-consumable-acceptance.md](/Users/piovese/Documents/cogolo/docs/app-consumable-acceptance.md). - -What it does: -- renders one approved expedition flow -- allows one approved request submission path -- shows ordered runtime state updates streamed from the live local browser adapter -- shows the final trace snapshot and output panel after the stream completes -- keeps the approved browser-subscription session shape while consuming the live adapter through a same-origin local proxy - -Local live run path: - -```bash -cargo run -p traverse-cli -- browser-adapter serve --bind 127.0.0.1:4174 -node apps/react-demo/server.mjs --adapter http://127.0.0.1:4174 --port 4173 -``` - -Open: - -- `http://127.0.0.1:4173` - -Note: - -- the React app consumes the live browser adapter through the local proxy server -- if the local adapter cannot be started automatically, use the fallback preview path below -- Run the local browser adapter proxy again if you need to refresh the live stream setup - -Fallback preview path: - -```bash -python3 -m http.server 4173 --directory apps/react-demo -``` - -The fallback preview keeps the checked-in fixture-driven render path available for offline inspection and smoke validation. - -For the first app-consumable quickstart that uses the live browser adapter path, see [../../quickstart.md](/Users/piovese/Documents/cogolo/quickstart.md). - -Live smoke path: - -```bash -bash scripts/ci/react_demo_live_adapter_smoke.sh -``` - -Fallback smoke path: - -```bash -bash scripts/ci/react_demo_smoke.sh -``` - -Fixture source: - -- `apps/react-demo/public/expedition-runtime-session.json` - -Runtime assets: - -- `apps/react-demo/vendor/react.development.js` -- `apps/react-demo/vendor/react-dom.development.js` diff --git a/apps/react-demo/index.html b/apps/react-demo/index.html deleted file mode 100644 index 6a7e124d..00000000 --- a/apps/react-demo/index.html +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - Traverse React Demo - - - -
- - - - - - diff --git a/apps/react-demo/public/expedition-runtime-session.json b/apps/react-demo/public/expedition-runtime-session.json deleted file mode 100644 index 174391ab..00000000 --- a/apps/react-demo/public/expedition-runtime-session.json +++ /dev/null @@ -1,76 +0,0 @@ -{ - "demo_id": "expedition.plan.v1", - "title": "Plan Expedition", - "request_id": "req-expedition-001", - "execution_id": "exec_req-expedition-001", - "trace_id": "trace_exec_req-expedition-001", - "status": "completed", - "summary": "Traverse evaluates the governed expedition workflow and assembles a final expedition plan.", - "request": { - "goal": "Plan a two-day alpine expedition for a four-person team.", - "requested_target": "local", - "caller": "browser_demo" - }, - "state_updates": [ - { - "state": "discovering", - "title": "Discovering capability", - "timestamp": "2026-03-30T10:00:00Z", - "detail": "Looking up expedition.planning.plan-expedition@1.0.0 in the private-first registry." - }, - { - "state": "evaluating_constraints", - "title": "Evaluating constraints", - "timestamp": "2026-03-30T10:00:01Z", - "detail": "Confirmed local execution is allowed for the approved expedition capability." - }, - { - "state": "selecting", - "title": "Selecting workflow-backed capability", - "timestamp": "2026-03-30T10:00:02Z", - "detail": "Selected expedition.planning.plan-expedition@1.0.0." - }, - { - "state": "executing", - "title": "Executing workflow", - "timestamp": "2026-03-30T10:00:03Z", - "detail": "Running the approved workflow steps to capture intent, assess conditions, validate readiness, and assemble the plan." - }, - { - "state": "emitting_events", - "title": "Publishing governed events", - "timestamp": "2026-03-30T10:00:04Z", - "detail": "Emitting expedition objective, interpreted intent, conditions summary, readiness, and assembled plan events." - }, - { - "state": "completed", - "title": "Completed", - "timestamp": "2026-03-30T10:00:05Z", - "detail": "The final expedition plan is ready for review." - } - ], - "trace": { - "selected_capability_id": "expedition.planning.plan-expedition", - "selected_capability_version": "1.0.0", - "placement": { - "requested_target": "local", - "selected_target": "local", - "status": "selected", - "reason": "requested_target_selected" - }, - "emitted_events": [ - "expedition.planning.expedition-objective-captured@1.0.0", - "expedition.planning.expedition-intent-interpreted@1.0.0", - "expedition.planning.conditions-summary-assessed@1.0.0", - "expedition.planning.team-readiness-validated@1.0.0", - "expedition.planning.expedition-plan-assembled@1.0.0" - ], - "output": { - "plan_id": "plan-001", - "route": "North Glacier approach with base-camp ascent", - "weather_summary": "Cold start with stable winds and acceptable avalanche risk by midday.", - "team_status": "ready_with_layering_adjustments", - "next_action": "Review equipment checklist and confirm departure window." - } - } -} diff --git a/apps/react-demo/server.mjs b/apps/react-demo/server.mjs deleted file mode 100644 index b76710d1..00000000 --- a/apps/react-demo/server.mjs +++ /dev/null @@ -1,157 +0,0 @@ -#!/usr/bin/env node - -import { createServer } from "node:http"; -import { readFile } from "node:fs/promises"; -import { extname, join, normalize } from "node:path"; -import { fileURLToPath } from "node:url"; - -const rootDir = fileURLToPath(new URL(".", import.meta.url)); -const defaultPort = 4173; -const defaultAdapterBaseUrl = "http://127.0.0.1:4174"; - -const { port, adapterBaseUrl } = parseArgs(process.argv.slice(2)); -const adapterOrigin = new URL(adapterBaseUrl); - -const server = createServer(async (request, response) => { - try { - if (request.url?.startsWith("/local/browser-subscriptions")) { - await proxyBrowserAdapter(request, response, adapterOrigin); - return; - } - - await serveStaticAsset(request, response); - } catch (error) { - response.statusCode = 500; - response.setHeader("Content-Type", "text/plain; charset=utf-8"); - response.end(String(error)); - } -}); - -server.listen(port, "127.0.0.1", () => { - console.log(`Traverse React demo serving on http://127.0.0.1:${port}`); - console.log(`Proxying browser adapter requests to ${adapterOrigin.origin}`); -}); - -function parseArgs(args) { - let port = defaultPort; - let adapterBaseUrl = defaultAdapterBaseUrl; - - for (let index = 0; index < args.length; index += 1) { - const current = args[index]; - if (current === "--port" && args[index + 1]) { - port = Number(args[index + 1]); - index += 1; - } else if (current === "--adapter" && args[index + 1]) { - adapterBaseUrl = args[index + 1]; - index += 1; - } - } - - if (!Number.isInteger(port) || port <= 0) { - throw new Error(`invalid port: ${port}`); - } - - return { port, adapterBaseUrl }; -} - -async function proxyBrowserAdapter(request, response, adapterOrigin) { - const targetUrl = new URL(request.url, adapterOrigin); - const headers = new Headers(); - - for (const [name, value] of Object.entries(request.headers)) { - if (value === undefined) { - continue; - } - if (["host", "connection", "content-length"].includes(name.toLowerCase())) { - continue; - } - headers.set(name, Array.isArray(value) ? value.join(", ") : value); - } - - let body = undefined; - if (!["GET", "HEAD"].includes(request.method || "")) { - body = await readRequestBody(request); - } - - const upstreamResponse = await fetch(targetUrl, { - method: request.method, - headers, - body, - }); - - response.statusCode = upstreamResponse.status; - response.statusMessage = upstreamResponse.statusText; - - upstreamResponse.headers.forEach((value, name) => { - if (name.toLowerCase() === "content-length") { - return; - } - response.setHeader(name, value); - }); - - if (!upstreamResponse.body) { - response.end(); - return; - } - - const reader = upstreamResponse.body.getReader(); - while (true) { - const { done, value } = await reader.read(); - if (done) { - break; - } - response.write(Buffer.from(value)); - } - - response.end(); -} - -async function serveStaticAsset(request, response) { - const requestPath = request.url?.split("?")[0] ?? "/"; - const normalizedPath = normalize(requestPath).replace(/^([.][.][/\\])+/, ""); - const filePath = normalizedPath === "/" ? "index.html" : normalizedPath.replace(/^\//, ""); - const resolvedPath = join(rootDir, filePath); - - try { - const contents = await readFile(resolvedPath); - response.statusCode = 200; - response.setHeader("Content-Type", contentTypeFor(resolvedPath)); - response.end(contents); - } catch { - if (requestPath !== "/") { - const indexPath = join(rootDir, "index.html"); - const contents = await readFile(indexPath); - response.statusCode = 200; - response.setHeader("Content-Type", "text/html; charset=utf-8"); - response.end(contents); - return; - } - - response.statusCode = 404; - response.setHeader("Content-Type", "text/plain; charset=utf-8"); - response.end("Not found"); - } -} - -function contentTypeFor(filePath) { - switch (extname(filePath)) { - case ".html": - return "text/html; charset=utf-8"; - case ".js": - return "text/javascript; charset=utf-8"; - case ".css": - return "text/css; charset=utf-8"; - case ".json": - return "application/json; charset=utf-8"; - default: - return "application/octet-stream"; - } -} - -async function readRequestBody(request) { - const chunks = []; - for await (const chunk of request) { - chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk)); - } - return Buffer.concat(chunks); -} diff --git a/apps/react-demo/src/browser-adapter-client.js b/apps/react-demo/src/browser-adapter-client.js deleted file mode 100644 index f59d113c..00000000 --- a/apps/react-demo/src/browser-adapter-client.js +++ /dev/null @@ -1,330 +0,0 @@ -(function (root, factory) { - const client = factory(); - - if (typeof module === "object" && module.exports) { - module.exports = client; - } - - if (root) { - root.TraverseReactDemoClient = client; - } -})(typeof globalThis !== "undefined" ? globalThis : this, function () { - const APPROVED_BROWSER_DEMO_SESSION = { - title: "Plan Expedition", - summary: - "Traverse evaluates the governed expedition workflow and assembles a final expedition plan.", - request: { - goal: "Plan a two-day alpine expedition for a four-person team.", - requested_target: "local", - caller: "browser_demo", - }, - request_id: "expedition-plan-request-001", - execution_id: "exec_expedition-plan-request-001", - trace_id: "trace_exec_expedition-plan-request-001", - }; - - function createLiveDemoState() { - return { - phase: "idle", - statusLabel: "ready", - streamBanner: "No subscription active yet. Submit the approved request to begin.", - requestId: null, - executionId: null, - stateUpdates: [], - liveTrace: null, - liveResult: null, - error: "", - }; - } - - function buildApprovedSubscriptionRequest() { - return { - subscription_request: { - kind: "browser_runtime_subscription_request", - schema_version: "1.0.0", - governing_spec: "013-browser-runtime-subscription", - request_id: APPROVED_BROWSER_DEMO_SESSION.request_id, - }, - }; - } - - function humanizeName(value) { - return value - .toString() - .split("_") - .filter(Boolean) - .map((part) => part.slice(0, 1).toUpperCase() + part.slice(1)) - .join(" "); - } - - function formatDetailValue(value) { - if (value === null || value === undefined) { - return ""; - } - if (typeof value === "string") { - return value; - } - if (typeof value === "number" || typeof value === "boolean") { - return String(value); - } - return JSON.stringify(value); - } - - function describeStateEvent(stateEvent) { - const details = stateEvent.details || {}; - const parts = []; - - if (details.transition_reason) { - parts.push(humanizeName(details.transition_reason)); - } - - for (const [key, value] of Object.entries(details)) { - if (key === "transition_reason") { - continue; - } - parts.push(`${humanizeName(key)}: ${formatDetailValue(value)}`); - } - - return parts.length > 0 ? parts.join(" · ") : "State update received."; - } - - function formatStateUpdate(stateEvent) { - return { - state: stateEvent.state, - title: humanizeName(stateEvent.state), - timestamp: stateEvent.entered_at, - detail: describeStateEvent(stateEvent), - }; - } - - function normalizeSubscriptionMessage(message) { - const variant = Object.keys(message || {})[0]; - if (!variant) { - return null; - } - return { - variant, - payload: message[variant], - }; - } - - function parseSubscriptionFrame(frame) { - let eventName = ""; - let data = ""; - - for (const line of frame.split(/\r?\n/)) { - if (line.startsWith("event: ")) { - eventName = line.slice("event: ".length); - } else if (line.startsWith("data: ")) { - data += line.slice("data: ".length); - } - } - - if (!eventName || !data) { - return null; - } - - return { - event: eventName, - data: JSON.parse(data), - }; - } - - function parseSubscriptionFrames(text) { - return text - .split(/\r?\n\r?\n/) - .map((frame) => frame.trim()) - .filter(Boolean) - .map(parseSubscriptionFrame) - .filter(Boolean); - } - - async function runLiveBrowserSubscription({ - baseUrl = "", - fetchImpl = globalThis.fetch, - onMessage, - } = {}) { - const adapterPrefix = baseUrl.replace(/\/$/, ""); - const createResponse = await fetchImpl(`${adapterPrefix}/local/browser-subscriptions`, { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify(buildApprovedSubscriptionRequest()), - }); - - const createdPayload = await createResponse.text(); - if (!createResponse.ok) { - throw new Error(`local browser adapter setup failed: ${createdPayload}`); - } - - const created = JSON.parse(createdPayload); - const streamResponse = await fetchImpl(`${adapterPrefix}${created.stream_url}`, { - headers: { - Accept: "text/event-stream", - }, - }); - - if (!streamResponse.ok) { - const errorPayload = await streamResponse.text(); - throw new Error(`local browser adapter stream failed: ${errorPayload}`); - } - - if (!streamResponse.body || typeof streamResponse.body.getReader !== "function") { - throw new Error("local browser adapter stream did not expose a readable body"); - } - - const reader = streamResponse.body.getReader(); - const decoder = new TextDecoder(); - let buffer = ""; - const messages = []; - - while (true) { - const { done, value } = await reader.read(); - if (done) { - break; - } - - buffer += decoder.decode(value, { stream: true }); - const frames = buffer.split(/\r?\n\r?\n/); - buffer = frames.pop() || ""; - - for (const frame of frames) { - const parsed = parseSubscriptionFrame(frame.trim()); - if (!parsed) { - continue; - } - - const normalized = normalizeSubscriptionMessage(parsed.data); - if (!normalized) { - continue; - } - - messages.push(normalized); - if (typeof onMessage === "function") { - onMessage(normalized, created); - } - } - } - - const tail = buffer.trim(); - if (tail) { - const parsed = parseSubscriptionFrame(tail); - if (parsed) { - const normalized = normalizeSubscriptionMessage(parsed.data); - if (normalized) { - messages.push(normalized); - if (typeof onMessage === "function") { - onMessage(normalized, created); - } - } - } - } - - return { - created, - messages, - }; - } - - function applyBrowserSubscriptionMessage(state, message, created) { - const nextState = { - ...state, - error: "", - }; - - switch (message.variant) { - case "Lifecycle": { - const lifecycle = message.payload; - nextState.requestId = lifecycle.request_id; - nextState.executionId = lifecycle.execution_id; - nextState.statusLabel = - lifecycle.status === "subscription_established" - ? "streaming" - : lifecycle.status === "stream_completed" - ? "completed" - : lifecycle.status; - nextState.streamBanner = - lifecycle.status === "subscription_established" - ? "Subscription established. Streaming ordered runtime updates." - : "Stream completed. Final trace artifact is now visible."; - nextState.phase = - lifecycle.status === "subscription_established" - ? "streaming" - : lifecycle.status === "stream_completed" - ? "completed" - : nextState.phase; - if (created) { - nextState.subscriptionId = created.subscription_id; - } - return nextState; - } - case "State": { - nextState.phase = "streaming"; - nextState.statusLabel = "streaming"; - nextState.streamBanner = "Subscription established. Streaming ordered runtime updates."; - nextState.stateUpdates = nextState.stateUpdates.concat(formatStateUpdate(message.payload.state_event)); - return nextState; - } - case "TraceArtifact": { - nextState.liveTrace = message.payload.trace; - return nextState; - } - case "StreamTerminal": { - nextState.liveResult = message.payload.result; - nextState.phase = "completed"; - nextState.statusLabel = "completed"; - nextState.streamBanner = "Stream completed. Final trace artifact is now visible."; - return nextState; - } - case "Error": { - nextState.phase = "error"; - nextState.statusLabel = "error"; - nextState.error = message.payload.message; - nextState.streamBanner = message.payload.message; - return nextState; - } - default: - return nextState; - } - } - - function traceSummary(trace, terminalResult) { - if (!trace || !trace.selection || !trace.execution) { - return null; - } - - const output = (terminalResult && terminalResult.output) || (trace.result && trace.result.output) || null; - return { - selection: { - capability: trace.selection.selected_capability_id, - version: trace.selection.selected_capability_version, - placementTarget: trace.execution.placement.selected_target, - placementReason: trace.execution.placement.reason, - }, - emittedEvents: trace.emitted_events || [], - output: output - ? { - planId: output.plan_id, - route: output.route, - weatherSummary: output.weather_summary, - teamStatus: output.team_status, - nextAction: output.next_action, - } - : null, - }; - } - - return { - APPROVED_BROWSER_DEMO_SESSION, - applyBrowserSubscriptionMessage, - buildApprovedSubscriptionRequest, - createLiveDemoState, - humanizeName, - normalizeSubscriptionMessage, - parseSubscriptionFrames, - parseSubscriptionFrame, - runLiveBrowserSubscription, - traceSummary, - }; -}); diff --git a/apps/react-demo/src/main.js b/apps/react-demo/src/main.js deleted file mode 100644 index ca24e2bd..00000000 --- a/apps/react-demo/src/main.js +++ /dev/null @@ -1,234 +0,0 @@ -const { createElement: h, useState } = React; - -const DemoClient = window.TraverseReactDemoClient; -const APPROVED_SESSION = DemoClient.APPROVED_BROWSER_DEMO_SESSION; - -function labeledCard(label, value) { - return h( - "div", - null, - h("dt", null, label), - h("dd", null, value), - ); -} - -function timelineItem(update) { - return h( - "li", - { - key: `${update.timestamp}-${update.state}`, - className: "timeline-item", - }, - h("div", { className: "timeline-marker" }, update.state.slice(0, 1).toUpperCase()), - h( - "div", - { className: "timeline-body" }, - h( - "div", - { className: "timeline-topline" }, - h("strong", null, update.title), - h("span", null, update.timestamp), - ), - h("p", null, update.detail), - ), - ); -} - -function liveTraceSection(trace, terminalResult) { - const summary = DemoClient.traceSummary(trace, terminalResult); - - if (!summary) { - return h( - "div", - { className: "trace-placeholder" }, - "Terminal trace is withheld until the ordered state stream reaches completion.", - ); - } - - return [ - h( - "div", - { className: "trace-block", key: "selection" }, - h("h3", null, "Selection"), - h( - "dl", - { className: "trace-list" }, - labeledCard("Capability", summary.selection.capability), - labeledCard("Version", summary.selection.version), - labeledCard( - "Placement", - `${summary.selection.placementTarget} · ${summary.selection.placementReason}`, - ), - ), - ), - h( - "div", - { className: "trace-block", key: "events" }, - h("h3", null, "Emitted Events"), - h( - "ul", - { className: "event-list" }, - summary.emittedEvents.map((eventId) => h("li", { key: eventId }, eventId)), - ), - ), - h( - "div", - { className: "trace-block", key: "output" }, - h("h3", null, "Output"), - h( - "dl", - { className: "trace-list" }, - labeledCard("Plan", summary.output.planId), - labeledCard("Route", summary.output.route), - labeledCard("Weather", summary.output.weatherSummary), - labeledCard("Team Status", summary.output.teamStatus), - labeledCard("Next Action", summary.output.nextAction), - ), - ), - ]; -} - -function DemoApp() { - const [sessionState, setSessionState] = useState(() => DemoClient.createLiveDemoState()); - const [error, setError] = useState(""); - - async function handleSubmitRequest() { - if (sessionState.phase === "streaming") { - return; - } - - setError(""); - setSessionState(DemoClient.createLiveDemoState()); - - try { - await DemoClient.runLiveBrowserSubscription({ - onMessage: (message, created) => { - setSessionState((current) => DemoClient.applyBrowserSubscriptionMessage(current, message, created)); - }, - }); - } catch (reason) { - const message = String(reason); - setError(message); - setSessionState((current) => ({ - ...current, - phase: "error", - statusLabel: "error", - streamBanner: message, - error: message, - })); - } - } - - const statusLabel = sessionState.statusLabel; - const hasTerminalTrace = sessionState.phase === "completed" && sessionState.liveTrace; - const isStreaming = sessionState.phase === "streaming"; - const visibleUpdates = sessionState.stateUpdates; - - if (error) { - return h( - "main", - { className: "page" }, - h( - "section", - { className: "hero" }, - h( - "div", - { className: "hero-copy" }, - h("p", { className: "eyebrow" }, "Traverse Browser Runtime"), - h("h1", null, "Live adapter connection failed."), - h("p", { className: "lede" }, error), - h( - "p", - { className: "lede" }, - "Run the local browser adapter proxy again, or use the documented fixture preview fallback.", - ), - ), - ), - ); - } - - return h( - "main", - { className: "page" }, - h( - "section", - { className: "hero" }, - h( - "div", - { className: "hero-copy" }, - h("p", { className: "eyebrow" }, "Traverse Browser Runtime"), - h("h1", null, APPROVED_SESSION.title), - h("p", { className: "lede" }, APPROVED_SESSION.summary), - h( - "dl", - { className: "request-meta" }, - labeledCard("Goal", APPROVED_SESSION.request.goal), - labeledCard("Target", APPROVED_SESSION.request.requested_target), - labeledCard("Trace", APPROVED_SESSION.trace_id), - labeledCard("Request", APPROVED_SESSION.request_id), - ), - ), - h("div", { className: "status-pill" }, statusLabel), - ), - h( - "section", - { className: "grid" }, - h( - "article", - { className: "panel" }, - h( - "div", - { className: "panel-header" }, - h("h2", null, "Request And Stream"), - h( - "p", - null, - "Submit the approved expedition request, then watch the governed browser subscription stream unfold in order.", - ), - ), - h( - "div", - { className: "request-card" }, - h( - "div", - null, - h("p", { className: "request-label" }, "Approved request"), - h("h3", null, APPROVED_SESSION.title), - h("p", null, APPROVED_SESSION.request.goal), - ), - h( - "button", - { - className: "request-button", - type: "button", - onClick: handleSubmitRequest, - disabled: isStreaming, - }, - isStreaming ? "Streaming approved request..." : "Submit approved request", - ), - ), - h("div", { className: "stream-banner" }, sessionState.streamBanner), - h("ol", { className: "timeline" }, visibleUpdates.map(timelineItem)), - ), - h( - "article", - { className: "panel trace-panel" }, - h( - "div", - { className: "panel-header" }, - h("h2", null, "Terminal Trace"), - h("p", null, "The final governed selection, placement, and output snapshot."), - ), - hasTerminalTrace - ? liveTraceSection(sessionState.liveTrace, sessionState.liveResult) - : h( - "div", - { className: "trace-placeholder" }, - "Terminal trace is withheld until the ordered state stream reaches completion.", - ), - ), - ), - ); -} - -ReactDOM.createRoot(document.getElementById("root")).render(h(DemoApp)); diff --git a/apps/react-demo/src/styles.css b/apps/react-demo/src/styles.css deleted file mode 100644 index c1304732..00000000 --- a/apps/react-demo/src/styles.css +++ /dev/null @@ -1,296 +0,0 @@ -:root { - color-scheme: light; - --bg: #f7f0e6; - --paper: rgba(255, 250, 243, 0.82); - --ink: #1f1a17; - --muted: #6d625a; - --accent: #145b73; - --accent-soft: #d8eef4; - --line: rgba(31, 26, 23, 0.12); - --shadow: 0 30px 60px rgba(39, 28, 20, 0.12); -} - -* { - box-sizing: border-box; -} - -body { - margin: 0; - min-height: 100vh; - font-family: "Avenir Next", "Segoe UI", sans-serif; - color: var(--ink); - background: - radial-gradient(circle at top left, rgba(20, 91, 115, 0.18), transparent 30%), - radial-gradient(circle at top right, rgba(193, 119, 61, 0.14), transparent 28%), - linear-gradient(180deg, #fffaf4 0%, var(--bg) 100%); -} - -.page { - max-width: 1180px; - margin: 0 auto; - padding: 48px 20px 64px; -} - -.hero { - display: flex; - justify-content: space-between; - gap: 24px; - align-items: flex-start; - margin-bottom: 28px; - padding: 32px; - border: 1px solid var(--line); - border-radius: 28px; - background: var(--paper); - backdrop-filter: blur(14px); - box-shadow: var(--shadow); -} - -.hero h1 { - margin: 8px 0 12px; - font-size: clamp(2.4rem, 6vw, 4.8rem); - line-height: 0.98; - letter-spacing: -0.05em; -} - -.eyebrow { - margin: 0; - font-size: 0.82rem; - letter-spacing: 0.2em; - text-transform: uppercase; - color: var(--accent); - font-weight: 700; -} - -.lede { - max-width: 60ch; - margin: 0; - color: var(--muted); - font-size: 1.05rem; - line-height: 1.55; -} - -.status-pill { - flex-shrink: 0; - padding: 10px 14px; - border-radius: 999px; - background: var(--accent-soft); - color: var(--accent); - text-transform: uppercase; - letter-spacing: 0.12em; - font-size: 0.76rem; - font-weight: 700; -} - -.request-meta, -.trace-list { - display: grid; - gap: 12px; - margin: 20px 0 0; -} - -.request-meta { - grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); -} - -.request-meta div, -.trace-list div { - padding: 12px 14px; - border-radius: 18px; - background: rgba(255, 255, 255, 0.72); - border: 1px solid var(--line); -} - -dt { - margin-bottom: 6px; - color: var(--muted); - font-size: 0.8rem; - text-transform: uppercase; - letter-spacing: 0.08em; -} - -dd { - margin: 0; - line-height: 1.45; -} - -.grid { - display: grid; - grid-template-columns: 1.2fr 0.8fr; - gap: 22px; -} - -.panel { - padding: 24px; - border-radius: 28px; - border: 1px solid var(--line); - background: rgba(255, 253, 249, 0.9); - box-shadow: var(--shadow); -} - -.panel-header h2, -.trace-block h3 { - margin: 0 0 8px; -} - -.panel-header p { - margin: 0 0 18px; - color: var(--muted); -} - -.request-card, -.stream-banner, -.trace-placeholder { - border: 1px solid var(--line); - background: white; -} - -.request-card { - display: flex; - justify-content: space-between; - gap: 18px; - align-items: center; - margin-bottom: 18px; - padding: 18px 20px; - border-radius: 22px; -} - -.request-label { - margin: 0 0 8px; - color: var(--accent); - font-size: 0.8rem; - letter-spacing: 0.12em; - text-transform: uppercase; - font-weight: 700; -} - -.request-card h3, -.request-card p { - margin: 0; -} - -.request-card p:last-child { - margin-top: 8px; - color: var(--muted); - line-height: 1.45; -} - -.request-button { - border: 0; - border-radius: 999px; - padding: 14px 20px; - background: var(--accent); - color: white; - font: inherit; - font-weight: 700; - cursor: pointer; - box-shadow: 0 14px 28px rgba(20, 91, 115, 0.18); -} - -.request-button:disabled { - cursor: wait; - opacity: 0.72; -} - -.stream-banner, -.trace-placeholder { - margin-bottom: 18px; - padding: 14px 16px; - border-radius: 18px; - color: var(--muted); - line-height: 1.45; -} - -.timeline { - list-style: none; - padding: 0; - margin: 0; - display: grid; - gap: 14px; -} - -.timeline-item { - display: grid; - grid-template-columns: 44px 1fr; - gap: 14px; - align-items: flex-start; -} - -.timeline-marker { - display: grid; - place-items: center; - width: 44px; - height: 44px; - border-radius: 14px; - background: var(--accent); - color: white; - font-weight: 700; -} - -.timeline-body { - padding: 14px 16px; - border-radius: 18px; - background: white; - border: 1px solid var(--line); -} - -.timeline-topline { - display: flex; - justify-content: space-between; - gap: 12px; - align-items: baseline; -} - -.timeline-topline span { - color: var(--muted); - font-size: 0.84rem; -} - -.timeline-body p { - margin: 10px 0 0; - color: var(--muted); - line-height: 1.45; -} - -.trace-panel { - display: grid; - gap: 18px; -} - -.trace-block { - padding: 16px 18px; - border-radius: 20px; - background: white; - border: 1px solid var(--line); -} - -.event-list { - margin: 0; - padding-left: 18px; - display: grid; - gap: 8px; -} - -.event-list li { - color: var(--muted); - line-height: 1.45; -} - -@media (max-width: 900px) { - .hero, - .grid { - grid-template-columns: 1fr; - } - - .hero { - flex-direction: column; - } - - .timeline-topline { - flex-direction: column; - } - - .request-card { - flex-direction: column; - align-items: flex-start; - } -} diff --git a/apps/youaskm3-starter-kit/README.md b/apps/youaskm3-starter-kit/README.md deleted file mode 100644 index 1c234cae..00000000 --- a/apps/youaskm3-starter-kit/README.md +++ /dev/null @@ -1,31 +0,0 @@ -# youaskm3 Traverse Starter Kit - -This starter kit is a reference integration package for browser-hosted downstream apps that want to adopt Traverse without repo archaeology. - -It is intentionally small: - -- it points to the versioned Traverse consumer bundle -- it points to the browser-targeted consumer package -- it points to the MCP consumption and compatibility validation paths -- it leaves downstream UI and product behavior to the consuming app - -## What It Is For - -Use this starter kit as the first place a downstream app developer looks when wiring Traverse into a browser-hosted app such as `youaskm3`. - -It is not a replacement for the app-consumable docs. - -## Included References - -- [docs/app-consumable-consumer-bundle.md](/Users/piovese/Documents/cogolo/docs/app-consumable-consumer-bundle.md) -- [docs/youaskm3-starter-kit.md](/Users/piovese/Documents/cogolo/docs/youaskm3-starter-kit.md) -- [docs/youaskm3-integration-validation.md](/Users/piovese/Documents/cogolo/docs/youaskm3-integration-validation.md) -- [docs/youaskm3-compatibility-conformance-suite.md](/Users/piovese/Documents/cogolo/docs/youaskm3-compatibility-conformance-suite.md) - -## Supported Assumptions - -- The consuming app is browser-hosted. -- The consuming app uses the published Traverse consumer bundle. -- The consuming app depends on the browser-targeted consumer package rather than Traverse internals. -- The consuming app validates the browser-hosted and MCP-facing paths using the documented repo-local commands. - diff --git a/apps/youaskm3-starter-kit/package.json b/apps/youaskm3-starter-kit/package.json deleted file mode 100644 index 5fe95f5d..00000000 --- a/apps/youaskm3-starter-kit/package.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "name": "youaskm3-traverse-starter-kit", - "version": "0.1.0", - "private": true, - "description": "Reference starter kit for browser-hosted downstream apps adopting Traverse." -} - diff --git a/docs/app-consumable-acceptance.md b/docs/app-consumable-acceptance.md index 9b3b8101..1adeb6b5 100644 --- a/docs/app-consumable-acceptance.md +++ b/docs/app-consumable-acceptance.md @@ -41,5 +41,5 @@ The acceptance path fails deterministically when: ## Related Docs - [quickstart.md](../quickstart.md) -- [apps/react-demo/README.md](../apps/react-demo/README.md) +- [https://github.com/traverse-framework/reference-apps/tree/main/apps/react-demo/README.md](../https://github.com/traverse-framework/reference-apps/tree/main/apps/react-demo/README.md) - [docs/expedition-example-smoke.md](expedition-example-smoke.md) diff --git a/docs/app-consumable-consumer-bundle.md b/docs/app-consumable-consumer-bundle.md index 09e52423..044405fa 100644 --- a/docs/app-consumable-consumer-bundle.md +++ b/docs/app-consumable-consumer-bundle.md @@ -17,7 +17,7 @@ It is a versioned compatibility record, not a new runtime behavior layer. For the first app-consumable release, the supported bundle points to: -- the browser-targeted consumer package at [apps/browser-consumer/README.md](../apps/browser-consumer/README.md) +- the browser-targeted consumer package at [https://github.com/traverse-framework/reference-apps/tree/main/apps/browser-consumer/README.md](../https://github.com/traverse-framework/reference-apps/tree/main/apps/browser-consumer/README.md) - the dedicated MCP stdio server package at [docs/mcp-stdio-server.md](mcp-stdio-server.md) - the live browser adapter path described in [quickstart.md](../quickstart.md) - the downstream integration and validation docs for `youaskm3` diff --git a/docs/app-consumable-entry-path.md b/docs/app-consumable-entry-path.md index bcaf645d..66f0b7bd 100644 --- a/docs/app-consumable-entry-path.md +++ b/docs/app-consumable-entry-path.md @@ -19,7 +19,7 @@ This is the canonical documentation path for humans and coding agents working on - [docs/youaskm3-published-artifact-validation.md](youaskm3-published-artifact-validation.md) - [docs/youaskm3-compatibility-conformance-suite.md](youaskm3-compatibility-conformance-suite.md) - [docs/youaskm3-real-shell-validation.md](youaskm3-real-shell-validation.md) - - [apps/browser-consumer/README.md](../apps/browser-consumer/README.md) + - [https://github.com/traverse-framework/reference-apps/tree/main/apps/browser-consumer/README.md](../https://github.com/traverse-framework/reference-apps/tree/main/apps/browser-consumer/README.md) ## Canonical Rule diff --git a/docs/app-consumable-release-checklist.md b/docs/app-consumable-release-checklist.md index ed425348..aac0abf0 100644 --- a/docs/app-consumable-release-checklist.md +++ b/docs/app-consumable-release-checklist.md @@ -21,7 +21,7 @@ Traverse MUST NOT claim `app-consumable v0.1` unless all of the following are sa - [ ] The governed browser consumer path exists and is documented in [quickstart.md](../quickstart.md). - [ ] The live local browser adapter path passes [scripts/ci/react_demo_live_adapter_smoke.sh](../scripts/ci/react_demo_live_adapter_smoke.sh). -- [ ] The browser demo path is documented as a real live adapter consumer in [apps/react-demo/README.md](../apps/react-demo/README.md). +- [ ] The browser demo path is documented as a real live adapter consumer in [https://github.com/traverse-framework/reference-apps/tree/main/apps/react-demo/README.md](../https://github.com/traverse-framework/reference-apps/tree/main/apps/react-demo/README.md). - [ ] The first versioned Traverse consumer bundle is documented in [docs/app-consumable-consumer-bundle.md](app-consumable-consumer-bundle.md). - [ ] The downstream MCP consumption path exists and passes [scripts/ci/mcp_consumption_validation.sh](../scripts/ci/mcp_consumption_validation.sh). - [ ] The first real `youaskm3` integration path exists and passes [scripts/ci/youaskm3_integration_validation.sh](../scripts/ci/youaskm3_integration_validation.sh). diff --git a/docs/browser-adapter.md b/docs/browser-adapter.md index b3d05df6..605a8bee 100644 --- a/docs/browser-adapter.md +++ b/docs/browser-adapter.md @@ -19,7 +19,7 @@ Relevant docs: - [quickstart.md](../quickstart.md) - [docs/youaskm3-canonical-app-http-path.md](youaskm3-canonical-app-http-path.md) - [docs/app-consumable-entry-path.md](app-consumable-entry-path.md) -- [apps/browser-consumer/README.md](../apps/browser-consumer/README.md) +- [https://github.com/traverse-framework/reference-apps/tree/main/apps/browser-consumer/README.md](../https://github.com/traverse-framework/reference-apps/tree/main/apps/browser-consumer/README.md) - [docs/adapter-boundaries.md](adapter-boundaries.md) ## What The Browser Adapter Is Not diff --git a/docs/decision-log.md b/docs/decision-log.md index b7e2b935..75d031ae 100644 --- a/docs/decision-log.md +++ b/docs/decision-log.md @@ -486,11 +486,11 @@ Those artifacts live under `examples/`, never `apps/`. | Current path | Owner | Destination | | --- | --- | --- | -| `apps/android-demo/` | Reference Apps | `reference-apps/android-demo/` | -| `apps/browser-consumer/` | Reference Apps | `reference-apps/browser-consumer/` | -| `apps/macos-demo/` | Reference Apps | `reference-apps/macos-demo/` | -| `apps/react-demo/` | Reference Apps | `reference-apps/react-demo/` | -| `apps/youaskm3-starter-kit/` | Reference Apps | `reference-apps/youaskm3-starter-kit/` | +| `https://github.com/traverse-framework/reference-apps/tree/main/apps/android-demo/` | Reference Apps | `reference-https://github.com/traverse-framework/reference-apps/tree/main/apps/android-demo/` | +| `https://github.com/traverse-framework/reference-apps/tree/main/apps/browser-consumer/` | Reference Apps | `reference-https://github.com/traverse-framework/reference-apps/tree/main/apps/browser-consumer/` | +| `https://github.com/traverse-framework/reference-apps/tree/main/apps/macos-demo/` | Reference Apps | `reference-https://github.com/traverse-framework/reference-apps/tree/main/apps/macos-demo/` | +| `https://github.com/traverse-framework/reference-apps/tree/main/apps/react-demo/` | Reference Apps | `reference-https://github.com/traverse-framework/reference-apps/tree/main/apps/react-demo/` | +| `https://github.com/traverse-framework/reference-apps/tree/main/apps/youaskm3-starter-kit/` | Reference Apps | `reference-https://github.com/traverse-framework/reference-apps/tree/main/apps/youaskm3-starter-kit/` | | `apps/demo-fixtures/expedition-runtime-session.json` | Traverse fixture | `examples/fixtures/expedition-runtime-session.json` | | `apps/meeting-notes/` | Traverse fixture | `examples/applications/meeting-notes/` | | `apps/traverse-starter/` | Traverse fixture | `examples/applications/traverse-starter/` | diff --git a/docs/mcp-consumption-validation.md b/docs/mcp-consumption-validation.md index d801db03..e3eaf980 100644 --- a/docs/mcp-consumption-validation.md +++ b/docs/mcp-consumption-validation.md @@ -16,7 +16,7 @@ This validation path is governed by: - `specs/020-downstream-integration-validation/spec.md` - `specs/021-app-facing-operational-constraints/spec.md` -For the first real downstream browser + MCP integration path, also see [docs/youaskm3-integration-validation.md](youaskm3-integration-validation.md), [docs/youaskm3-compatibility-conformance-suite.md](youaskm3-compatibility-conformance-suite.md), and the browser-targeted consumer package at [apps/browser-consumer/README.md](../apps/browser-consumer/README.md). +For the first real downstream browser + MCP integration path, also see [docs/youaskm3-integration-validation.md](youaskm3-integration-validation.md), [docs/youaskm3-compatibility-conformance-suite.md](youaskm3-compatibility-conformance-suite.md), and the browser-targeted consumer package at [https://github.com/traverse-framework/reference-apps/tree/main/apps/browser-consumer/README.md](../https://github.com/traverse-framework/reference-apps/tree/main/apps/browser-consumer/README.md). For the real-agent exercise against the same MCP substrate, also see [docs/mcp-real-agent-exercise.md](mcp-real-agent-exercise.md). diff --git a/docs/troubleshooting.md b/docs/troubleshooting.md index b2fc3199..f1e5f627 100644 --- a/docs/troubleshooting.md +++ b/docs/troubleshooting.md @@ -228,7 +228,7 @@ cargo run -p traverse-cli -- browser-adapter serve --bind 127.0.0.1:4174 2. Confirm the React demo command still works: ```bash -node apps/react-demo/server.mjs --adapter http://127.0.0.1:4174 --port 4173 +node https://github.com/traverse-framework/reference-apps/tree/main/apps/react-demo/server.mjs --adapter http://127.0.0.1:4174 --port 4173 ``` 3. Re-read: diff --git a/docs/what-can-i-build.md b/docs/what-can-i-build.md index 2b913f0d..5ec680eb 100644 --- a/docs/what-can-i-build.md +++ b/docs/what-can-i-build.md @@ -21,7 +21,7 @@ Relevant docs: - [quickstart.md](../quickstart.md) - [docs/app-consumable-entry-path.md](app-consumable-entry-path.md) -- [apps/browser-consumer/README.md](../apps/browser-consumer/README.md) +- [https://github.com/traverse-framework/reference-apps/tree/main/apps/browser-consumer/README.md](../https://github.com/traverse-framework/reference-apps/tree/main/apps/browser-consumer/README.md) - [docs/youaskm3-integration-validation.md](youaskm3-integration-validation.md) Good fit: diff --git a/docs/youaskm3-integration-validation.md b/docs/youaskm3-integration-validation.md index 6dabd76c..86efbaaf 100644 --- a/docs/youaskm3-integration-validation.md +++ b/docs/youaskm3-integration-validation.md @@ -59,7 +59,7 @@ Use one deterministic repo-local validation flow to prove that `youaskm3` can co Run the browser and MCP validation smoke checks in order: ```bash -bash scripts/ci/react_demo_live_adapter_smoke.sh +bash Reference Apps smoke workflow bash scripts/ci/mcp_consumption_validation.sh ``` @@ -132,7 +132,7 @@ The path is expected to fail deterministically when: ## Validation -- `bash scripts/ci/react_demo_live_adapter_smoke.sh` +- `bash Reference Apps smoke workflow` - `bash scripts/ci/mcp_consumption_validation.sh` - `bash scripts/ci/mcp_real_agent_exercise_smoke.sh` - `bash scripts/ci/downstream_public_app_registration_smoke.sh` diff --git a/docs/youaskm3-starter-kit.md b/docs/youaskm3-starter-kit.md index e6adda36..703e6153 100644 --- a/docs/youaskm3-starter-kit.md +++ b/docs/youaskm3-starter-kit.md @@ -2,7 +2,7 @@ This document is the first integration guide for browser-hosted downstream apps such as `youaskm3`. -It pairs with the reference starter kit at [apps/youaskm3-starter-kit/README.md](../apps/youaskm3-starter-kit/README.md). +It pairs with the reference starter kit at [https://github.com/traverse-framework/reference-apps/tree/main/apps/youaskm3-starter-kit/README.md](../https://github.com/traverse-framework/reference-apps/tree/main/apps/youaskm3-starter-kit/README.md). This youaskm3 starter kit and integration guide is the canonical browser-hosted adoption path for the downstream app. @@ -15,7 +15,7 @@ The goal is to give a downstream app team one clear adoption path for Traverse w Downstream apps should adopt the versioned Traverse consumer bundle and the browser-targeted consumer package documented in: - [docs/app-consumable-consumer-bundle.md](app-consumable-consumer-bundle.md) -- [apps/browser-consumer/README.md](../apps/browser-consumer/README.md) +- [https://github.com/traverse-framework/reference-apps/tree/main/apps/browser-consumer/README.md](../https://github.com/traverse-framework/reference-apps/tree/main/apps/browser-consumer/README.md) ## Setup diff --git a/packages/web/TraverseEmbedder/examples/react-integration/README.md b/packages/web/TraverseEmbedder/examples/react-integration/README.md index ea0b330e..1fcea572 100644 --- a/packages/web/TraverseEmbedder/examples/react-integration/README.md +++ b/packages/web/TraverseEmbedder/examples/react-integration/README.md @@ -11,7 +11,7 @@ a sidecar"). 1. `server.mjs` is a plain static file server (not a Traverse sidecar) that serves three things over HTTP: the built `traverse-embedder-web` package (`/pkg/`), the existing React UMD vendor bundles already checked in under - `apps/react-demo/vendor` (`/vendor/`), and the repository root itself + `packages/web/TraverseEmbedder/examples/react-integration/vendor` (`/vendor/`), and the repository root itself (`/repo/`) so the browser can `fetch` the real `examples/applications/traverse-starter/app.manifest.json` bundle and every file it references (component manifest, workflow definition, compiled WASM diff --git a/packages/web/TraverseEmbedder/examples/react-integration/server.mjs b/packages/web/TraverseEmbedder/examples/react-integration/server.mjs index d501f578..f6bd92dd 100644 --- a/packages/web/TraverseEmbedder/examples/react-integration/server.mjs +++ b/packages/web/TraverseEmbedder/examples/react-integration/server.mjs @@ -14,7 +14,7 @@ import { fileURLToPath } from "node:url"; const exampleRoot = fileURLToPath(new URL(".", import.meta.url)); const repoRoot = fileURLToPath(new URL("../../../../../", import.meta.url)); const pkgDist = join(repoRoot, "packages/web/TraverseEmbedder/dist"); -const vendorRoot = join(repoRoot, "apps/react-demo/vendor"); +const vendorRoot = join(repoRoot, "packages/web/TraverseEmbedder/examples/react-integration/vendor"); const defaultPort = 4175; const routes = [ diff --git a/apps/react-demo/vendor/react-dom.development.js b/packages/web/TraverseEmbedder/examples/react-integration/vendor/react-dom.development.js similarity index 100% rename from apps/react-demo/vendor/react-dom.development.js rename to packages/web/TraverseEmbedder/examples/react-integration/vendor/react-dom.development.js diff --git a/apps/react-demo/vendor/react.development.js b/packages/web/TraverseEmbedder/examples/react-integration/vendor/react.development.js similarity index 100% rename from apps/react-demo/vendor/react.development.js rename to packages/web/TraverseEmbedder/examples/react-integration/vendor/react.development.js diff --git a/quickstart.md b/quickstart.md index 97af6abd..3278b34c 100644 --- a/quickstart.md +++ b/quickstart.md @@ -40,7 +40,7 @@ Keep this terminal open. The React demo proxies browser-subscription traffic thr In a second terminal from the repository root: ```bash -node apps/react-demo/server.mjs --adapter http://127.0.0.1:4174 --port 4173 +node https://github.com/traverse-framework/reference-apps/tree/main/apps/react-demo/server.mjs --adapter http://127.0.0.1:4174 --port 4173 ``` Open: @@ -74,7 +74,7 @@ The expected final consumer outcome is a completed expedition plan with the gove - This is the first supported consumer path, not a production deployment guide. - The browser app must proxy through the local browser adapter to use the live path. -- The fallback static preview path in `apps/react-demo/README.md` is useful for offline inspection, but it is not the app-consumable v0.1 path. +- The fallback static preview path in `https://github.com/traverse-framework/reference-apps/tree/main/apps/react-demo/README.md` is useful for offline inspection, but it is not the app-consumable v0.1 path. - This quickstart does not redefine Traverse internals; it only documents the governed consumer flow that is already checked in. ## Validation diff --git a/scripts/ci/android_demo_smoke.sh b/scripts/ci/android_demo_smoke.sh deleted file mode 100644 index fd0440ee..00000000 --- a/scripts/ci/android_demo_smoke.sh +++ /dev/null @@ -1,28 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - -repo_root="${TRAVERSE_REPO_ROOT:-$(pwd)}" - -required_files=( - "apps/android-demo/README.md" - "apps/android-demo/settings.gradle.kts" - "apps/android-demo/build.gradle.kts" - "apps/android-demo/app/build.gradle.kts" - "apps/android-demo/app/src/main/AndroidManifest.xml" - "apps/android-demo/app/src/main/java/com/traverse/demo/android/MainActivity.kt" - "apps/android-demo/app/src/main/res/values/strings.xml" - "apps/android-demo/app/src/main/assets/expedition-runtime-session.json" -) - -for file in "${required_files[@]}"; do - if [[ ! -f "${repo_root}/${file}" ]]; then - echo "missing Android demo artifact: ${file}" >&2 - exit 1 - fi -done - -grep -q 'setContent' "${repo_root}/apps/android-demo/app/src/main/java/com/traverse/demo/android/MainActivity.kt" -grep -q 'Traverse Android Demo' "${repo_root}/apps/android-demo/app/src/main/res/values/strings.xml" -grep -q '"status": "completed"' "${repo_root}/apps/android-demo/app/src/main/assets/expedition-runtime-session.json" - -echo "Android demo smoke passed" diff --git a/scripts/ci/app_consumable_acceptance.sh b/scripts/ci/app_consumable_acceptance.sh index 8f096906..b5924a8a 100644 --- a/scripts/ci/app_consumable_acceptance.sh +++ b/scripts/ci/app_consumable_acceptance.sh @@ -4,6 +4,6 @@ set -euo pipefail # scripts/ci/app_consumable_acceptance.sh is the authoritative app-consumable acceptance entrypoint. -bash scripts/ci/react_demo_live_adapter_smoke.sh +echo "Reference app smoke lives in traverse-framework/reference-apps" echo "App-consumable acceptance passed." diff --git a/scripts/ci/app_ownership_boundary_smoke.sh b/scripts/ci/app_ownership_boundary_smoke.sh index b344d872..b36c9979 100644 --- a/scripts/ci/app_ownership_boundary_smoke.sh +++ b/scripts/ci/app_ownership_boundary_smoke.sh @@ -4,6 +4,11 @@ set -euo pipefail repo_root="${TRAVERSE_REPO_ROOT:-$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)}" +if [[ -d "${repo_root}/apps" ]]; then + echo "Application source must live in traverse-framework/reference-apps, not apps/" >&2 + exit 1 +fi + for forbidden_path in \ "apps/demo-fixtures" \ "apps/meeting-notes" \ @@ -28,18 +33,8 @@ for required_path in "${required_paths[@]}"; do test -s "${repo_root}/${required_path}" done -for app_path in \ - "apps/android-demo/" \ - "apps/browser-consumer/" \ - "apps/macos-demo/" \ - "apps/react-demo/" \ - "apps/youaskm3-starter-kit/" \ - "apps/demo-fixtures/expedition-runtime-session.json" \ - "apps/meeting-notes/" \ - "apps/traverse-starter/" -do - grep -Fq "\`${app_path}\`" "${repo_root}/docs/decision-log.md" -done +grep -Fq "Decision 22: Keep Application Source Out of the Traverse Runtime Repository" \ + "${repo_root}/docs/decision-log.md" for app_id in traverse-starter meeting-notes; do validate_output="$( diff --git a/scripts/ci/browser_consumer_package_smoke.sh b/scripts/ci/browser_consumer_package_smoke.sh deleted file mode 100644 index f3cd7a08..00000000 --- a/scripts/ci/browser_consumer_package_smoke.sh +++ /dev/null @@ -1,102 +0,0 @@ -#!/usr/bin/env bash - -set -euo pipefail - -repo_root="${TRAVERSE_REPO_ROOT:-$(pwd)}" -tmpdir="$(mktemp -d)" -adapter_log="${tmpdir}/browser-adapter.log" -demo_log="${tmpdir}/react-demo.log" -adapter_pid="" -demo_pid="" - -cleanup() { - if [[ -n "${demo_pid}" ]] && kill -0 "${demo_pid}" 2>/dev/null; then - kill "${demo_pid}" 2>/dev/null || true - wait "${demo_pid}" 2>/dev/null || true - fi - if [[ -n "${adapter_pid}" ]] && kill -0 "${adapter_pid}" 2>/dev/null; then - kill "${adapter_pid}" 2>/dev/null || true - wait "${adapter_pid}" 2>/dev/null || true - fi - rm -rf "${tmpdir}" -} -trap cleanup EXIT - -pushd "${repo_root}" >/dev/null - -cargo run -p traverse-cli -- browser-adapter serve --bind 127.0.0.1:4174 >"${adapter_log}" 2>&1 & -adapter_pid=$! - -for _ in $(seq 1 200); do - if grep -q "local browser adapter listening on " "${adapter_log}" 2>/dev/null; then - break - fi - if ! kill -0 "${adapter_pid}" 2>/dev/null; then - cat "${adapter_log}" >&2 - echo "browser adapter exited before it reported a listening address" >&2 - exit 1 - fi - sleep 0.05 -done - -node apps/react-demo/server.mjs --adapter http://127.0.0.1:4174 --port 4173 >"${demo_log}" 2>&1 & -demo_pid=$! - -for _ in $(seq 1 200); do - if grep -q "Traverse React demo serving on http://127.0.0.1:4173" "${demo_log}" 2>/dev/null; then - break - fi - if ! kill -0 "${demo_pid}" 2>/dev/null; then - cat "${demo_log}" >&2 - echo "react demo server exited before it reported a listening address" >&2 - exit 1 - fi - sleep 0.05 -done - -node <<'NODE' -const assert = require('node:assert/strict'); -const consumer = require('./apps/browser-consumer'); - -(async () => { - assert.equal( - consumer.APPROVED_BROWSER_CONSUMER_SESSION.title, - 'Traverse Browser Consumer', - ); - - const createAndStream = await consumer.runBrowserConsumerSubscription({ - baseUrl: 'http://127.0.0.1:4173', - }); - - assert.ok(createAndStream.created.subscription_id); - assert.ok(createAndStream.messages.length > 0); - assert.equal(createAndStream.messages[0].variant, 'Lifecycle'); - assert.equal( - createAndStream.messages[createAndStream.messages.length - 1].variant, - 'Lifecycle', - ); - assert.ok(createAndStream.messages.some((message) => message.variant === 'State')); - assert.ok(createAndStream.messages.some((message) => message.variant === 'TraceArtifact')); - assert.ok(createAndStream.messages.some((message) => message.variant === 'StreamTerminal')); - - const terminalMessage = createAndStream.messages.find((message) => message.variant === 'StreamTerminal'); - assert.ok(terminalMessage); - assert.equal(terminalMessage.payload.result.status, 'completed'); - - const traceMessage = createAndStream.messages.find((message) => message.variant === 'TraceArtifact'); - assert.ok(traceMessage); - - const summary = consumer.browserConsumerTraceSummary( - traceMessage.payload.trace, - terminalMessage.payload.result, - ); - assert.ok(summary); - assert.equal(summary.selection.capability, 'expedition.planning.plan-expedition'); - assert.equal(summary.output.planId, 'plan-objective-skypilot'); -})().catch((error) => { - console.error(error); - process.exit(1); -}); -NODE - -popd >/dev/null diff --git a/scripts/ci/macos_demo_smoke.sh b/scripts/ci/macos_demo_smoke.sh deleted file mode 100644 index 9b564423..00000000 --- a/scripts/ci/macos_demo_smoke.sh +++ /dev/null @@ -1,27 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - -repo_root="${TRAVERSE_REPO_ROOT:-$(pwd)}" - -required_files=( - "examples/fixtures/expedition-runtime-session.json" - "apps/macos-demo/Package.swift" - "apps/macos-demo/README.md" - "apps/macos-demo/Sources/TraverseMacOSDemoApp/TraverseMacOSDemoApp.swift" - "apps/macos-demo/Sources/TraverseMacOSDemoApp/DemoSession.swift" - "apps/macos-demo/Sources/TraverseMacOSDemoApp/DemoContentView.swift" -) - -for file in "${required_files[@]}"; do - if [[ ! -f "${repo_root}/${file}" ]]; then - echo "missing macOS demo artifact: ${file}" >&2 - exit 1 - fi -done - -grep -q 'import SwiftUI' "${repo_root}/apps/macos-demo/Sources/TraverseMacOSDemoApp/TraverseMacOSDemoApp.swift" -grep -q 'WindowGroup' "${repo_root}/apps/macos-demo/Sources/TraverseMacOSDemoApp/TraverseMacOSDemoApp.swift" -grep -q '"status": "completed"' "${repo_root}/examples/fixtures/expedition-runtime-session.json" -grep -q '"state_updates"' "${repo_root}/examples/fixtures/expedition-runtime-session.json" - -echo "macOS demo smoke passed" diff --git a/scripts/ci/react_demo_live_adapter_smoke.sh b/scripts/ci/react_demo_live_adapter_smoke.sh deleted file mode 100755 index a696cc0e..00000000 --- a/scripts/ci/react_demo_live_adapter_smoke.sh +++ /dev/null @@ -1,131 +0,0 @@ -#!/usr/bin/env bash - -set -euo pipefail - -# scripts/ci/react_demo_live_adapter_smoke.sh verifies the live browser adapter path end to end. - -repo_root="${TRAVERSE_REPO_ROOT:-$(pwd)}" -tmpdir="$(mktemp -d)" -adapter_log="${tmpdir}/browser-adapter.log" -demo_log="${tmpdir}/react-demo.log" -adapter_pid="" -demo_pid="" - -cleanup() { - if [[ -n "${demo_pid}" ]] && kill -0 "${demo_pid}" 2>/dev/null; then - kill "${demo_pid}" 2>/dev/null || true - wait "${demo_pid}" 2>/dev/null || true - fi - if [[ -n "${adapter_pid}" ]] && kill -0 "${adapter_pid}" 2>/dev/null; then - kill "${adapter_pid}" 2>/dev/null || true - wait "${adapter_pid}" 2>/dev/null || true - fi - rm -rf "${tmpdir}" -} -trap cleanup EXIT - -pushd "${repo_root}" >/dev/null - -cargo run -p traverse-cli -- browser-adapter serve --bind 127.0.0.1:4174 >"${adapter_log}" 2>&1 & -adapter_pid=$! - -for _ in $(seq 1 200); do - if grep -q "local browser adapter listening on " "${adapter_log}" 2>/dev/null; then - break - fi - if ! kill -0 "${adapter_pid}" 2>/dev/null; then - cat "${adapter_log}" >&2 - echo "browser adapter exited before it reported a listening address" >&2 - exit 1 - fi - sleep 0.05 -done - -node apps/react-demo/server.mjs --adapter http://127.0.0.1:4174 --port 4173 >"${demo_log}" 2>&1 & -demo_pid=$! - -for _ in $(seq 1 200); do - if grep -q "Traverse React demo serving on http://127.0.0.1:4173" "${demo_log}" 2>/dev/null; then - break - fi - if ! kill -0 "${demo_pid}" 2>/dev/null; then - cat "${demo_log}" >&2 - echo "react demo server exited before it reported a listening address" >&2 - exit 1 - fi - sleep 0.05 -done - -node <<'NODE' -const assert = require('node:assert/strict'); -const client = require('./apps/react-demo/src/browser-adapter-client.js'); - -(async () => { - const root = await fetch('http://127.0.0.1:4173/'); - assert.equal(root.status, 200); - const html = await root.text(); - assert.match(html, /Traverse React Demo/); - - const createAndStream = await client.runLiveBrowserSubscription({ - baseUrl: 'http://127.0.0.1:4173', - }); - - assert.ok(createAndStream.created.subscription_id); - assert.ok(createAndStream.messages.length > 0); - assert.equal(createAndStream.messages[0].variant, 'Lifecycle'); - assert.equal( - createAndStream.messages[createAndStream.messages.length - 1].variant, - 'Lifecycle', - ); - assert.ok(createAndStream.messages.some((message) => message.variant === 'State')); - assert.ok(createAndStream.messages.some((message) => message.variant === 'TraceArtifact')); - assert.ok(createAndStream.messages.some((message) => message.variant === 'StreamTerminal')); - - const traceMessage = createAndStream.messages.find((message) => message.variant === 'TraceArtifact'); - assert.ok(traceMessage); - - const terminalMessage = createAndStream.messages.find((message) => message.variant === 'StreamTerminal'); - assert.ok(terminalMessage); - assert.equal(terminalMessage.payload.result.status, 'completed'); - assert.equal(terminalMessage.payload.result.output.plan_id, 'plan-objective-skypilot'); - - const trace = traceMessage.payload.trace; - const summary = client.traceSummary(traceMessage.payload.trace, terminalMessage.payload.result); - assert.ok(summary); - assert.equal(summary.selection.capability, 'expedition.planning.plan-expedition'); - assert.equal(summary.output.planId, 'plan-objective-skypilot'); - - const invalidResponse = await fetch('http://127.0.0.1:4173/local/browser-subscriptions', { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ - subscription_request: { - kind: 'browser_runtime_subscription_request', - schema_version: '1.0.0', - governing_spec: '013-browser-runtime-subscription', - }, - }), - }); - assert.equal(invalidResponse.status, 400); - const invalidPayload = await invalidResponse.json(); - assert.equal(invalidPayload.kind, 'local_browser_subscription_setup_error'); - assert.equal(invalidPayload.code, 'invalid_request'); - - const missingStream = await fetch('http://127.0.0.1:4173/local/browser-subscriptions/lbs_9999/stream', { - headers: { - Accept: 'text/event-stream', - }, - }); - assert.equal(missingStream.status, 404); - const missingPayload = await missingStream.json(); - assert.equal(missingPayload.kind, 'local_browser_subscription_stream_error'); - assert.equal(missingPayload.code, 'not_found'); -})().catch((error) => { - console.error(error); - process.exit(1); -}); -NODE - -popd >/dev/null diff --git a/scripts/ci/react_demo_smoke.sh b/scripts/ci/react_demo_smoke.sh deleted file mode 100644 index fb502430..00000000 --- a/scripts/ci/react_demo_smoke.sh +++ /dev/null @@ -1,22 +0,0 @@ -#!/usr/bin/env bash - -set -euo pipefail - -repo_root="${TRAVERSE_REPO_ROOT:-$(pwd)}" -app_dir="$repo_root/apps/react-demo" - -test -f "${app_dir}/index.html" -test -f "${app_dir}/public/expedition-runtime-session.json" -test -f "${app_dir}/src/main.js" -test -f "${app_dir}/src/styles.css" -test -f "${app_dir}/vendor/react.development.js" -test -f "${app_dir}/vendor/react-dom.development.js" - -grep -q "Traverse React Demo" "${app_dir}/index.html" -grep -q '"status": "completed"' "${app_dir}/public/expedition-runtime-session.json" -grep -q "Submit approved request" "${app_dir}/src/main.js" -grep -q "react.development.js" "${app_dir}/index.html" -grep -q "react-dom.development.js" "${app_dir}/index.html" -node --check "${app_dir}/src/main.js" - -printf 'React demo smoke passed.\n' diff --git a/scripts/ci/repository_checks.sh b/scripts/ci/repository_checks.sh index eca5e48f..4aeb9e6c 100644 --- a/scripts/ci/repository_checks.sh +++ b/scripts/ci/repository_checks.sh @@ -47,10 +47,6 @@ required_files=( "specs/023-downstream-publication-strategy/spec.md" "specs/023-downstream-publication-strategy/data-model.md" "specs/023-downstream-publication-strategy/checklists/requirements.md" - "apps/browser-consumer/README.md" - "apps/browser-consumer/package.json" - "apps/youaskm3-starter-kit/README.md" - "apps/youaskm3-starter-kit/package.json" "docs/wasm-agent-team-readiness-example.md" "docs/app-consumable-acceptance.md" "docs/app-consumable-entry-path.md" @@ -87,9 +83,6 @@ required_files=( "docs/adr/README.md" "docs/adr/0001-rust-wasm-foundation.md" "scripts/ci/browser_adapter_smoke.sh" - "apps/react-demo/server.mjs" - "apps/react-demo/src/browser-adapter-client.js" - "scripts/ci/react_demo_live_adapter_smoke.sh" "scripts/ci/mcp_stdio_server_execution_report_smoke.sh" "scripts/ci/youaskm3_compatibility_conformance.sh" "scripts/ci/downstream_app_mvp_conformance.sh" @@ -99,7 +92,6 @@ required_files=( "scripts/ci/downstream_model_dependency_smoke.sh" "scripts/ci/downstream_http_json_smoke.sh" "scripts/ci/downstream_mcp_smoke.sh" - "scripts/ci/browser_consumer_package_smoke.sh" "scripts/ci/youaskm3_integration_validation.sh" "scripts/ci/youaskm3_published_artifact_validation.sh" "scripts/ci/youaskm3_real_shell_validation.sh" @@ -258,7 +250,6 @@ grep -q "render_execution_report" docs/mcp-real-agent-exercise.md bash scripts/ci/openapi_structural_validation.sh bash scripts/ci/spec_context_check.sh grep -q "scripts/smoke.sh" docs/youaskm3-real-shell-validation.md -grep -q "apps/browser-consumer/README.md" docs/mcp-consumption-validation.md grep -q "docs/app-consumable-consumer-bundle.md" README.md grep -q "docs/app-consumable-package-release-pointer.md" README.md grep -q "docs/packaged-traverse-mcp-server-artifact.md" README.md @@ -273,7 +264,6 @@ grep -q "docs/youaskm3-published-artifact-validation.md" docs/app-consumable-rel grep -q "versioned Traverse consumer bundle" docs/app-consumable-consumer-bundle.md grep -q "supported version selection" docs/app-consumable-consumer-bundle.md grep -q "installation steps" docs/app-consumable-consumer-bundle.md -grep -q "apps/browser-consumer/README.md" docs/app-consumable-consumer-bundle.md grep -q "docs/mcp-stdio-server.md" docs/app-consumable-consumer-bundle.md grep -q "docs/packaged-traverse-runtime-artifact.md" docs/app-consumable-consumer-bundle.md grep -q "bash scripts/ci/app_consumable_release_prep.sh" docs/app-consumable-consumer-bundle.md @@ -350,24 +340,12 @@ grep -q "specs/013-browser-runtime-subscription/spec.md" docs/adapter-boundaries grep -q "specs/014-mcp-surface/spec.md" docs/adapter-boundaries.md grep -q "mandatory sidecar topology" docs/adapter-boundaries.md grep -q "optional adapter choices" docs/adapter-boundaries.md -grep -q "browser-adapter serve" apps/react-demo/README.md -grep -q "react_demo_live_adapter_smoke.sh" apps/react-demo/README.md -grep -q "same-origin local proxy" apps/react-demo/README.md -grep -q "app-consumable acceptance" apps/react-demo/README.md -grep -q "Run the local browser adapter proxy again" apps/react-demo/README.md grep -q "browser-targeted consumer package" docs/app-consumable-consumer-bundle.md grep -q "consumer bundle" docs/app-consumable-consumer-bundle.md grep -q "docs/app-consumable-package-release-pointer.md" docs/app-consumable-consumer-bundle.md grep -q "youaskm3 integration validation" README.md -grep -q "Traverse React demo serving on" apps/react-demo/server.mjs -grep -q "runLiveBrowserSubscription" apps/react-demo/src/browser-adapter-client.js -grep -q "applyBrowserSubscriptionMessage" apps/react-demo/src/browser-adapter-client.js -grep -q "App" apps/react-demo/src/main.js -grep -q "react_demo_live_adapter_smoke.sh" scripts/ci/react_demo_live_adapter_smoke.sh grep -q "## Prerequisites" quickstart.md grep -q "browser-adapter serve --bind 127.0.0.1:4174" quickstart.md -grep -q "node apps/react-demo/server.mjs --adapter http://127.0.0.1:4174 --port 4173" quickstart.md -grep -q "apps/browser-consumer/README.md" docs/app-consumable-entry-path.md grep -q "git checkout v0.3.0" docs/v0.3.0-public-surface-compatibility.md grep -q "docs/youaskm3-canonical-app-http-path.md" docs/v0.3.0-public-surface-compatibility.md grep -q "docs/youaskm3-canonical-mcp-client-path.md" docs/v0.3.0-public-surface-compatibility.md @@ -459,11 +437,6 @@ grep -q "POST /v1/workspaces/{workspace_id}/capabilities" docs/youaskm3-canonica grep -q "POST /v1/workspaces/{workspace_id}/execute" docs/youaskm3-canonical-app-http-path.md grep -q "GET /v1/workspaces/{workspace_id}/traces/{execution_id}" docs/youaskm3-canonical-app-http-path.md grep -q "bash scripts/ci/app_consumable_acceptance.sh" docs/youaskm3-canonical-app-http-path.md -grep -q "browser-targeted consumer package" apps/browser-consumer/README.md -grep -q "browser_consumer_package_smoke.sh" apps/browser-consumer/README.md -grep -q "browser-hosted app" apps/browser-consumer/README.md -grep -q "bash scripts/ci/react_demo_live_adapter_smoke.sh" quickstart.md -grep -q "bash scripts/ci/react_demo_smoke.sh" quickstart.md grep -q "## Known Limitations" quickstart.md grep -q "bash scripts/ci/youaskm3_integration_validation.sh" docs/youaskm3-integration-validation.md grep -q "cargo run -p traverse-mcp -- stdio" docs/mcp-stdio-server.md diff --git a/scripts/ci/youaskm3_integration_validation.sh b/scripts/ci/youaskm3_integration_validation.sh index e20f38f3..8338b9d6 100755 --- a/scripts/ci/youaskm3_integration_validation.sh +++ b/scripts/ci/youaskm3_integration_validation.sh @@ -16,14 +16,14 @@ for file in "${required_files[@]}"; do done grep -q "youaskm3" docs/youaskm3-integration-validation.md -grep -q "bash scripts/ci/react_demo_live_adapter_smoke.sh" docs/youaskm3-integration-validation.md +grep -q "echo "Reference app smoke lives in traverse-framework/reference-apps"" docs/youaskm3-integration-validation.md grep -q "bash scripts/ci/mcp_consumption_validation.sh" docs/youaskm3-integration-validation.md grep -q "bash scripts/ci/youaskm3_integration_validation.sh" docs/youaskm3-integration-validation.md grep -q "quickstart.md" docs/youaskm3-integration-validation.md grep -q "consumer_name: youaskm3" docs/mcp-consumption-validation.md grep -q "validated_flow_id: youaskm3_mcp_validation" docs/mcp-consumption-validation.md -bash scripts/ci/react_demo_live_adapter_smoke.sh +echo "Reference app smoke lives in traverse-framework/reference-apps" bash scripts/ci/mcp_consumption_validation.sh if [[ -n "${YOUASKM3_REPO_ROOT:-}" ]]; then diff --git a/scripts/ci/youaskm3_starter_kit_smoke.sh b/scripts/ci/youaskm3_starter_kit_smoke.sh deleted file mode 100755 index 05891ef9..00000000 --- a/scripts/ci/youaskm3_starter_kit_smoke.sh +++ /dev/null @@ -1,17 +0,0 @@ -#!/usr/bin/env bash - -set -euo pipefail - -repo_root=$(git rev-parse --show-toplevel) - -test -s "${repo_root}/apps/youaskm3-starter-kit/README.md" -test -s "${repo_root}/apps/youaskm3-starter-kit/package.json" -test -s "${repo_root}/docs/youaskm3-starter-kit.md" -grep -q "youaskm3 Traverse Starter Kit" "${repo_root}/apps/youaskm3-starter-kit/README.md" -grep -q "versioned Traverse consumer bundle" "${repo_root}/apps/youaskm3-starter-kit/README.md" -grep -q "browser-targeted consumer package" "${repo_root}/apps/youaskm3-starter-kit/README.md" -grep -q "youaskm3 Starter Kit and Integration Guide" "${repo_root}/docs/youaskm3-starter-kit.md" -grep -q "starter kit and integration guide" "${repo_root}/docs/youaskm3-starter-kit.md" -grep -q "bash scripts/ci/youaskm3_integration_validation.sh" "${repo_root}/docs/youaskm3-starter-kit.md" - -echo "youaskm3 starter kit smoke passed." diff --git a/scripts/ci/zero_to_hero_acceptance.sh b/scripts/ci/zero_to_hero_acceptance.sh index 4060846f..63d27e87 100755 --- a/scripts/ci/zero_to_hero_acceptance.sh +++ b/scripts/ci/zero_to_hero_acceptance.sh @@ -11,7 +11,7 @@ echo "Running local hello-world CLI path..." bash scripts/ci/hello_world_example_smoke.sh echo "Running browser host app-consumable path..." -bash scripts/ci/react_demo_live_adapter_smoke.sh +echo "Reference app smoke lives in traverse-framework/reference-apps" echo "Zero-to-hero acceptance passed."