Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
351b057
Add startup state cleanup
AtomEons May 29, 2026
4fda170
Add temporal memory expanded overlay
AtomEons May 29, 2026
98930d7
Wire startup cleanup and temporal memory expansion
AtomEons May 29, 2026
4f1b712
Add temporal memory expansion styles
AtomEons May 29, 2026
c087285
Import temporal overlay styles
AtomEons May 29, 2026
b344dab
Add product surface overlay router
AtomEons May 29, 2026
e10ff1a
Add reusable product surface shell
AtomEons May 29, 2026
2ee6407
Add settings product drawer
AtomEons May 29, 2026
1143ab0
Add notifications product drawer
AtomEons May 29, 2026
e4ef423
Add artifact inspector product drawer
AtomEons May 29, 2026
300dd80
Add real product modal stack
AtomEons May 29, 2026
492a731
Route dedicated product surfaces before fallback workbench
AtomEons May 29, 2026
f68e442
Add basic product surface styles
AtomEons May 29, 2026
975ff72
Import product surface styles
AtomEons May 29, 2026
27cdad2
Fix temporal memory overlay TypeScript namespace issue
AtomEons May 29, 2026
62f775c
Make root npm scripts cross-platform
AtomEons May 29, 2026
3810cbd
Add AE See-Suite MCP tool pack
AtomEons May 29, 2026
8574d7a
Add standalone AE See-Suite MCP server
AtomEons May 29, 2026
47276c6
Add real product surface command actions
AtomEons May 29, 2026
c12a49a
Make temporal ribbon open expanded memory surface
AtomEons May 29, 2026
b5e4c2c
Include temporal memory in frontend anchor proof scripts
AtomEons May 29, 2026
502faf1
Wire top rail controls to product surfaces
AtomEons May 29, 2026
73416e3
Wire left rail to real product surfaces
AtomEons May 29, 2026
2b73e48
Include temporal memory anchor in frontend proof CI
AtomEons May 29, 2026
deb5eb3
Keep StateWorkbenchOverlay as fallback only
AtomEons May 29, 2026
bda46b6
Render product surfaces separately from fallback workbench
AtomEons May 29, 2026
ff7279c
Document AE See-Suite MCP setup
AtomEons May 29, 2026
b4219d4
Add AE See-Suite MCP syntax workflow
AtomEons May 29, 2026
391b8f1
Make calm boot causality-free in store baseline
AtomEons May 30, 2026
58400a9
Capture frontend build logs for green debugging
AtomEons May 30, 2026
1562f91
Capture Project Green frontend build logs
AtomEons May 30, 2026
2deca1a
Fix left rail action type mismatch
AtomEons May 30, 2026
d662e15
Make AELID remote adapter gracefully fall back when OrangeBOX is absent
AtomEons May 30, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions .github/workflows/ae-see-suite-mcp.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
name: AE See-Suite MCP

on:
pull_request:
paths:
- "scripts/ae-see-suite-mcp-*.mjs"
- ".github/workflows/ae-see-suite-mcp.yml"
push:
branches: [main]
paths:
- "scripts/ae-see-suite-mcp-*.mjs"
- ".github/workflows/ae-see-suite-mcp.yml"

jobs:
ae-see-suite-mcp-check:
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: 22

- name: Syntax check AE See-Suite MCP tools
run: node --check ./scripts/ae-see-suite-mcp-tools.mjs

- name: Syntax check AE See-Suite MCP server
run: node --check ./scripts/ae-see-suite-mcp-server.mjs
13 changes: 10 additions & 3 deletions .github/workflows/frontend-proof.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,18 +28,25 @@ jobs:
run: npm install

- name: Build frontend
run: npm run build -w @ae-see-suite/web
shell: bash
run: |
mkdir -p frontend/proof/logs
set +e
npm run build -w @ae-see-suite/web 2>&1 | tee frontend/proof/logs/build-web.log
status=${PIPESTATUS[0]}
set -e
exit "$status"

- name: Install Playwright Chromium
run: npx playwright install chromium --with-deps

- name: Capture anchor visual states
working-directory: frontend
run: npm run proof:visual -- --states=01,06,26,37,61 --label=ci-anchors
run: npm run proof:visual -- --states=01,06,22,26,37,61 --label=ci-anchors

- name: Produce non-strict pixel receipt
working-directory: frontend
run: npm run proof:pixel -- --states=01,06,26,37,61
run: npm run proof:pixel -- --states=01,06,22,26,37,61

- name: Summarize proof
working-directory: frontend
Expand Down
22 changes: 21 additions & 1 deletion .github/workflows/project-green.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ jobs:
syntax-and-build:
runs-on: ubuntu-latest
timeout-minutes: 25
env:
DATABASE_URL: postgresql://ae:ae@localhost:5432/ae_see_suite
steps:
- name: Checkout
uses: actions/checkout@v4
Expand All @@ -30,8 +32,26 @@ jobs:
- name: Build API workspace
run: npm run build -w @ae-see-suite/api

- name: Test API workspace
run: npm run test -w @ae-see-suite/api

- name: Build frontend workspace
run: npm run build -w @ae-see-suite/web
shell: bash
run: |
mkdir -p frontend/proof/logs
set +e
npm run build -w @ae-see-suite/web 2>&1 | tee frontend/proof/logs/project-green-build-web.log
status=${PIPESTATUS[0]}
set -e
exit "$status"

- name: AtomSmasher runtime syntax
run: node --check ./scripts/v4/atomsmasher-runtime.mjs && node --check ./scripts/v4/atomsmasher-api-routes.mjs

- name: Upload green logs
uses: actions/upload-artifact@v4
if: always()
with:
name: project-green-logs
path: frontend/proof/logs/
if-no-files-found: warn
87 changes: 87 additions & 0 deletions docs/ae-see-suite/MCP_SETUP.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
# AE See-Suite MCP Setup

This repo now includes a dedicated AE See-Suite MCP lane for build/proof control of the living dashboard.

## Server

```bash
node ./scripts/ae-see-suite-mcp-server.mjs
```

The server registers a focused AE See-Suite tool pack. It does not replace the broader OrangeBOX MCP server; it gives Claude Code/Codex a smaller surface specifically for the living dashboard work.

## Tools

- `ae_see_suite_help`
- `ae_see_suite_build_frontend`
- `ae_see_suite_proof_anchors`
- `ae_see_suite_proof_72`
- `ae_see_suite_state_open_command`

## Product law encoded in MCP

- One AppShell.
- Many semantic states.
- Do not build 72 pages.
- Do not use mockup images as UI.
- Use the 72-state atlas as proof/QA, not production logic.

## Anchor state proof target

The canonical anchor states are:

- `01` Calm Overview
- `06` Alert / Critical Latency
- `22` Temporal Memory Expanded
- `26` Command Palette
- `37` Agent Queue
- `61` Living Canvas

Run anchor proof through MCP with:

```txt
ae_see_suite_proof_anchors
```

Equivalent shell path:

```bash
npm run build:web
npm run frontend:proof:visual -- --states=01,06,22,26,37,61 --label=anchor-pass
npm run frontend:proof:pixel -- --states=01,06,22,26,37,61
```

Run the full atlas proof with:

```txt
ae_see_suite_proof_72
```

Equivalent shell path:

```bash
npm run build:web
npm run frontend:proof:visual:72
```

## Example Claude Desktop / MCP config shape

Use the local repo path that exists on the machine running the MCP client.

```json
{
"mcpServers": {
"ae-see-suite": {
"command": "node",
"args": ["C:/AtomEons/orangebox-delta/scripts/ae-see-suite-mcp-server.mjs"],
"env": {
"ORANGEBOX_URL": "http://127.0.0.1:8787"
}
}
}
}
```

## Operating note

The MCP tools call the existing OrangeBOX receipted executor for builds/proofs. The OrangeBOX service must be running at `ORANGEBOX_URL` for build/proof tools to execute. The state URL helper does not require execution; it returns direct browser URLs and acceptance checks.
4 changes: 2 additions & 2 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@
"dev": "vite --host 127.0.0.1",
"build": "tsc --noEmit && vite build",
"preview": "vite preview --host 127.0.0.1",
"proof:visual": "node ./scripts/visual-proof.mjs --states=01,06,26,37,61 --label=anchors",
"proof:visual": "node ./scripts/visual-proof.mjs --states=01,06,22,26,37,61 --label=anchors",
"proof:visual:72": "node ./scripts/visual-proof.mjs --states=all --label=72-state",
"proof:pixel": "node ./scripts/pixel-compare.mjs --states=01,06,26,37,61",
"proof:pixel": "node ./scripts/pixel-compare.mjs --states=01,06,22,26,37,61",
"proof:summary": "node ./scripts/proof-summary.mjs"
},
"dependencies": {
Expand Down
2 changes: 2 additions & 0 deletions frontend/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import "./styles/motion.css";
import "./styles/command-palette.css";
import "./styles/drawers.css";
import "./styles/canvas.css";
import "./styles/temporal.css";
import "./styles/product-surfaces.css";
import "./styles/animations.css";
import "./styles/responsive.css";
import "./styles/visual-atlas.css";
Expand Down
33 changes: 33 additions & 0 deletions frontend/src/components/overlays/ProductSurfaceOverlay.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { AnimatePresence } from "motion/react";
import { useAppStore } from "../../store/useAppStore";
import { SettingsDrawer } from "../surfaces/SettingsDrawer";
import { NotificationsDrawer } from "../surfaces/NotificationsDrawer";
import { ArtifactInspectorDrawer } from "../surfaces/ArtifactInspectorDrawer";
import { ProductModalStack } from "../surfaces/ProductModalStack";

const productDrawers = new Set(["settings", "notifications", "artifact-inspector"]);
const productModals = new Set(["add-widget", "context-picker", "model-selector", "export", "approval", "shortcuts", "compare", "stop-confirm"]);

export function isProductSurfaceDrawer(drawer?: string) {
return Boolean(drawer && productDrawers.has(drawer));
}

export function isProductSurfaceModal(modal?: string) {
return Boolean(modal && productModals.has(modal));
}

export function ProductSurfaceOverlay() {
const activeDrawer = useAppStore((s) => s.activeDrawer);
const activeModal = useAppStore((s) => s.activeModal);

return (
<>
<AnimatePresence>
{activeDrawer === "settings" ? <SettingsDrawer /> : null}
{activeDrawer === "notifications" ? <NotificationsDrawer /> : null}
{activeDrawer === "artifact-inspector" ? <ArtifactInspectorDrawer /> : null}
</AnimatePresence>
<AnimatePresence>{isProductSurfaceModal(activeModal) ? <ProductModalStack modalId={activeModal} /> : null}</AnimatePresence>
</>
);
}
28 changes: 5 additions & 23 deletions frontend/src/components/overlays/StateWorkbenchOverlay.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,34 +2,16 @@ import { AnimatePresence, motion } from "motion/react";
import { X } from "lucide-react";
import { getMockupStateSpec } from "../../engine/mockupStateBank";
import { useAppStore } from "../../store/useAppStore";
import { isProductSurfaceDrawer, isProductSurfaceModal } from "./ProductSurfaceOverlay";

const drawerTitles: Record<string, string> = {
settings: "Settings",
notifications: "Notifications",
"artifact-inspector": "Artifact Inspector",
performance: "Performance Overlay",
};

const modalTitles: Record<string, string> = {
"add-widget": "Add Widget",
"context-picker": "Context Picker",
"model-selector": "Model Selector",
export: "Export Workspace",
approval: "Deployment Approval",
shortcuts: "Keyboard Shortcuts",
compare: "Artifact Branch Compare",
"stop-confirm": "Stop Active Run?",
};
const modalTitles: Record<string, string> = {};

function linesForSurface(label: string) {
if (label.includes("Settings")) return ["Motion intensity", "Memory scope", "Backend: mock / remote", "Visual priority tuning"];
if (label.includes("Notifications")) return ["Critical latency", "Tool result returned", "Artifact created", "Agent task completed"];
if (label.includes("Artifact")) return ["Deployment Report", "Primary branch", "Related panels: pipeline, model, causality", "Export ready"];
if (label.includes("Context")) return ["System Health", "Project Nexus", "Causal Insights", "Temporal Memory"];
if (label.includes("Model")) return ["GPT-5.5 frontier", "Deep mode", "Latency budget: medium", "Tool policy: approved"];
if (label.includes("Approval")) return ["Canary 5%", "Risk: medium", "Rollback gate: ready", "Human approval required"];
if (label.includes("Shortcuts")) return ["Cmd/Ctrl+K command palette", "Cmd/Ctrl+L composer focus", "Cmd/Ctrl+Enter run", "Escape closes overlays"];
if (label.includes("Compare")) return ["Branch A: concise", "Branch B: evidence-rich", "Branch C: deployment-safe", "Recommended: Branch B"];
if (label.includes("Performance")) return ["FPS", "Memory", "Render cost", "Stream health"];
return ["Workspace snapshot", "Timeline range", "Artifacts and memory", "Ready"];
}

Expand All @@ -41,8 +23,8 @@ export function StateWorkbenchOverlay() {
const setModalOpen = useAppStore((s) => s.setModalOpen);

const mockup = getMockupStateSpec(activeMockupStateId);
const drawerTitle = activeDrawer ? drawerTitles[activeDrawer] : undefined;
const modalTitle = activeModal ? modalTitles[activeModal] : undefined;
const drawerTitle = activeDrawer && !isProductSurfaceDrawer(activeDrawer) ? drawerTitles[activeDrawer] : undefined;
const modalTitle = activeModal && !isProductSurfaceModal(activeModal) ? modalTitles[activeModal] : undefined;

return (
<>
Expand Down
72 changes: 72 additions & 0 deletions frontend/src/components/overlays/TemporalMemoryExpandedOverlay.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import { AnimatePresence, motion } from "motion/react";
import { Clock, FastForward, Play, RotateCcw, Search, X } from "lucide-react";
import { useAppStore } from "../../store/useAppStore";

export function TemporalMemoryExpandedOverlay() {
const memoryPanel = useAppStore((s) => s.panels.find((panel) => panel.id === "memory-ribbon"));
const timeline = useAppStore((s) => s.timeline);
const focusPanel = useAppStore((s) => s.focusPanel);
const setContextPanels = useAppStore((s) => s.setContextPanels);
const setComposerValue = useAppStore((s) => s.setComposerValue);
const expandPanel = useAppStore((s) => s.expandPanel);
const activeMockupStateId = useAppStore((s) => s.activeMockupStateId);

const open = Boolean(memoryPanel?.expanded);
const events = timeline.slice(-12).reverse();

return (
<AnimatePresence>
{open ? (
<motion.section
className={`temporal-expanded glass neon-edge ${activeMockupStateId === "22" ? "temporal-expanded--state-22" : ""}`}
initial={{ opacity: 0, y: 24, scale: 0.96, filter: "blur(10px)" }}
animate={{ opacity: 1, y: 0, scale: 1, filter: "blur(0px)" }}
exit={{ opacity: 0, y: 24, scale: 0.96, filter: "blur(10px)" }}
transition={{ type: "spring", stiffness: 260, damping: 30 }}
aria-label="Expanded temporal memory"
>
<header className="temporal-expanded__header">
<div>
<strong><Clock size={17} /> Temporal Memory</strong>
<span>Timeline scrub, snapshots, rewind, and event replay</span>
</div>
<button type="button" aria-label="Close temporal memory" onClick={() => expandPanel("memory-ribbon", false)}>
<X size={18} />
</button>
</header>

<div className="temporal-expanded__search">
<Search size={15} />
<span>Search memory, timeline, decisions, artifacts...</span>
</div>

<div className="temporal-expanded__scrub">
<button type="button"><RotateCcw size={14} /> Rewind</button>
<button type="button"><Play size={14} /> Replay</button>
<button type="button"><FastForward size={14} /> Forward</button>
</div>

<div className="temporal-expanded__track" aria-label="Memory events">
{events.map((event) => (
<button
key={event.id}
type="button"
className={`temporal-expanded__event temporal-expanded__event--${event.severity}`}
onClick={() => {
setContextPanels(event.relatedPanelIds);
focusPanel(event.relatedPanelIds[0]);
setComposerValue(`/timeline explain "${event.title}"`);
}}
>
<i>{event.timeLabel}</i>
<strong>{event.title}</strong>
{event.description ? <span>{event.description}</span> : null}
<em>{event.relatedPanelIds.slice(0, 3).join(" / ") || "global"}</em>
</button>
))}
</div>
</motion.section>
) : null}
</AnimatePresence>
);
}
15 changes: 13 additions & 2 deletions frontend/src/components/overlays/TemporalMemoryRibbon.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,21 @@ import { useAppStore } from "../../store/useAppStore";

export function TemporalMemoryRibbon() {
const timeline = useAppStore((s) => s.timeline);
const setDrawerOpen = useAppStore((s) => s.setDrawerOpen);
const expandPanel = useAppStore((s) => s.expandPanel);
const setMode = useAppStore((s) => s.setMode);
const setContextPanels = useAppStore((s) => s.setContextPanels);
const events = timeline.slice(-7);

return (
<button type="button" className="temporal-memory-ribbon glass" onClick={() => setDrawerOpen("memory")}>
<button
type="button"
className="temporal-memory-ribbon glass"
onClick={() => {
expandPanel("memory-ribbon", true);
setMode("reviewing");
setContextPanels(["memory-ribbon", "activity-feed", "causality"]);
}}
>
<span className="temporal-memory-ribbon__label"><Clock size={15} /> Temporal Memory</span>
<span className="temporal-memory-ribbon__track">
{events.map((event) => (
Expand Down
Loading