jettypod 4.4.118 → 4.4.121
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env +4 -3
- package/Cargo.lock +6450 -0
- package/Cargo.toml +35 -0
- package/README.md +5 -1
- package/TAURI-MIGRATION-PLAN.md +840 -0
- package/apps/dashboard/app/connect-claude/page.tsx +5 -6
- package/apps/dashboard/app/decision/[id]/page.tsx +63 -58
- package/apps/dashboard/app/demo/gates/page.tsx +43 -45
- package/apps/dashboard/app/design-system/page.tsx +868 -0
- package/apps/dashboard/app/globals.css +80 -4
- package/apps/dashboard/app/install-claude/page.tsx +4 -6
- package/apps/dashboard/app/login/page.tsx +72 -54
- package/apps/dashboard/app/page.tsx +101 -48
- package/apps/dashboard/app/settings/page.tsx +61 -13
- package/apps/dashboard/app/signup/page.tsx +242 -0
- package/apps/dashboard/app/subscribe/page.tsx +0 -2
- package/apps/dashboard/app/tests/page.tsx +37 -4
- package/apps/dashboard/app/welcome/page.tsx +13 -16
- package/apps/dashboard/app/work/[id]/page.tsx +117 -118
- package/apps/dashboard/app/work/[id]/proof/page.tsx +1489 -0
- package/apps/dashboard/components/AppShell.tsx +92 -85
- package/apps/dashboard/components/CardMenu.tsx +45 -12
- package/apps/dashboard/components/ClaudePanel.tsx +771 -850
- package/apps/dashboard/components/ClaudePanelInput.tsx +43 -15
- package/apps/dashboard/components/ConnectClaudeScreen.tsx +17 -34
- package/apps/dashboard/components/CopyableId.tsx +3 -4
- package/apps/dashboard/components/DetailReviewActions.tsx +100 -0
- package/apps/dashboard/components/DragContext.tsx +134 -63
- package/apps/dashboard/components/DraggableCard.tsx +3 -5
- package/apps/dashboard/components/DropZone.tsx +6 -7
- package/apps/dashboard/components/EditableDetailDescription.tsx +7 -13
- package/apps/dashboard/components/EditableDetailTitle.tsx +6 -13
- package/apps/dashboard/components/EditableTitle.tsx +26 -7
- package/apps/dashboard/components/ElapsedTimer.tsx +66 -0
- package/apps/dashboard/components/EpicGroup.tsx +359 -0
- package/apps/dashboard/components/GateCard.tsx +79 -17
- package/apps/dashboard/components/GateChoiceCard.tsx +15 -18
- package/apps/dashboard/components/InstallClaudeScreen.tsx +15 -32
- package/apps/dashboard/components/JettyLoader.tsx +37 -0
- package/apps/dashboard/components/KanbanBoard.tsx +368 -958
- package/apps/dashboard/components/KanbanCard.tsx +740 -0
- package/apps/dashboard/components/LazyCard.tsx +62 -0
- package/apps/dashboard/components/LazyMarkdown.tsx +11 -0
- package/apps/dashboard/components/MainNav.tsx +38 -73
- package/apps/dashboard/components/MessageBlock.tsx +468 -0
- package/apps/dashboard/components/ModeStartCard.tsx +15 -16
- package/apps/dashboard/components/OnboardingWelcome.tsx +213 -0
- package/apps/dashboard/components/PlaceholderCard.tsx +3 -4
- package/apps/dashboard/components/ProjectSwitcher.tsx +30 -30
- package/apps/dashboard/components/PrototypeTimeline.tsx +72 -51
- package/apps/dashboard/components/RealTimeKanbanWrapper.tsx +406 -388
- package/apps/dashboard/components/RealTimeTestsWrapper.tsx +373 -235
- package/apps/dashboard/components/ReviewFooter.tsx +139 -0
- package/apps/dashboard/components/SessionList.tsx +19 -19
- package/apps/dashboard/components/SubscribeContent.tsx +91 -47
- package/apps/dashboard/components/TestTree.tsx +16 -16
- package/apps/dashboard/components/TipCard.tsx +16 -17
- package/apps/dashboard/components/Toast.tsx +5 -6
- package/apps/dashboard/components/TypeIcon.tsx +55 -0
- package/apps/dashboard/components/ViewModeToolbar.tsx +104 -0
- package/apps/dashboard/components/WaveCompletionAnimation.tsx +52 -65
- package/apps/dashboard/components/WelcomeScreen.tsx +19 -35
- package/apps/dashboard/components/WorkItemHeader.tsx +4 -5
- package/apps/dashboard/components/WorkItemTree.tsx +11 -32
- package/apps/dashboard/components/settings/AccountSection.tsx +55 -35
- package/apps/dashboard/components/settings/AiContextSection.tsx +89 -0
- package/apps/dashboard/components/settings/ContextDocumentsSection.tsx +317 -0
- package/apps/dashboard/components/settings/EnvVarsSection.tsx +74 -152
- package/apps/dashboard/components/settings/GeneralSection.tsx +162 -56
- package/apps/dashboard/components/settings/ProjectStackSection.tsx +948 -0
- package/apps/dashboard/components/settings/SettingsLayout.tsx +4 -5
- package/apps/dashboard/components/ui/Button.tsx +104 -0
- package/apps/dashboard/components/ui/Input.tsx +78 -0
- package/apps/dashboard/components.json +1 -1
- package/apps/dashboard/contexts/ClaudeSessionContext.tsx +711 -418
- package/apps/dashboard/contexts/ConnectionStatusContext.tsx +25 -5
- package/apps/dashboard/contexts/UsageContext.tsx +87 -32
- package/apps/dashboard/dev.sh +35 -0
- package/apps/dashboard/eslint.config.mjs +9 -9
- package/apps/dashboard/hooks/useKanbanAnimation.ts +29 -0
- package/apps/dashboard/hooks/useKanbanUndo.ts +83 -0
- package/apps/dashboard/hooks/useWebSocket.ts +138 -83
- package/apps/dashboard/index.html +73 -0
- package/apps/dashboard/lib/constants.ts +43 -0
- package/apps/dashboard/lib/data-bridge.ts +722 -0
- package/apps/dashboard/lib/db.ts +69 -1265
- package/apps/dashboard/lib/environment-config.ts +173 -0
- package/apps/dashboard/lib/environment-verification.ts +119 -0
- package/apps/dashboard/lib/kanban-utils.ts +270 -0
- package/apps/dashboard/lib/proof-run.ts +495 -0
- package/apps/dashboard/lib/proof-scenario-runner.ts +346 -0
- package/apps/dashboard/lib/run-migrations.js +27 -2
- package/apps/dashboard/lib/service-recovery.ts +326 -0
- package/apps/dashboard/lib/session-state-machine.ts +1 -0
- package/apps/dashboard/lib/session-state-utils.ts +0 -164
- package/apps/dashboard/lib/session-stream-manager.ts +308 -134
- package/apps/dashboard/lib/shadows.ts +7 -0
- package/apps/dashboard/lib/stream-manager-registry.ts +46 -6
- package/apps/dashboard/lib/tauri-bridge.ts +102 -0
- package/apps/dashboard/lib/tauri.ts +106 -0
- package/apps/dashboard/lib/utils.ts +6 -0
- package/apps/dashboard/next-env.d.ts +1 -1
- package/apps/dashboard/package.json +21 -32
- package/apps/dashboard/public/bug-icon.png +0 -0
- package/apps/dashboard/public/buoy-icon.png +0 -0
- package/apps/dashboard/public/fonts/Satoshi-Variable.woff2 +0 -0
- package/apps/dashboard/public/fonts/Satoshi-VariableItalic.woff2 +0 -0
- package/apps/dashboard/public/in-flight-seagull.png +0 -0
- package/apps/dashboard/public/jetty-icon-loading-alt.svg +11 -0
- package/apps/dashboard/public/jetty-icon-loading.svg +11 -0
- package/apps/dashboard/public/jettypod_logo.png +0 -0
- package/apps/dashboard/public/pier-icon.png +0 -0
- package/apps/dashboard/public/star-icon.png +0 -0
- package/apps/dashboard/public/wrench-icon.png +0 -0
- package/apps/dashboard/scripts/tauri-build.js +228 -0
- package/apps/dashboard/scripts/upload-tauri-to-r2.js +125 -0
- package/apps/dashboard/scripts/ws-server.js +191 -0
- package/apps/dashboard/src/main.tsx +12 -0
- package/apps/dashboard/src/router.tsx +107 -0
- package/apps/dashboard/src/vite-env.d.ts +1 -0
- package/apps/dashboard/tsconfig.json +7 -12
- package/apps/dashboard/tsconfig.tsbuildinfo +1 -1
- package/apps/dashboard/vite.config.ts +33 -0
- package/apps/update-server/src/index.ts +228 -80
- package/claude-hooks/global-guardrails.js +14 -13
- package/crates/jettypod-cli/Cargo.toml +19 -0
- package/crates/jettypod-cli/src/commands.rs +1249 -0
- package/crates/jettypod-cli/src/main.rs +595 -0
- package/crates/jettypod-core/Cargo.toml +26 -0
- package/crates/jettypod-core/build.rs +98 -0
- package/crates/jettypod-core/migrations/V1__baseline.sql +197 -0
- package/crates/jettypod-core/migrations/V2__work_items_indexes.sql +6 -0
- package/crates/jettypod-core/migrations/V3__qa_steps.sql +2 -0
- package/crates/jettypod-core/src/auth.rs +294 -0
- package/crates/jettypod-core/src/config.rs +397 -0
- package/crates/jettypod-core/src/db/mod.rs +507 -0
- package/crates/jettypod-core/src/db/recovery.rs +114 -0
- package/crates/jettypod-core/src/db/startup.rs +101 -0
- package/crates/jettypod-core/src/db/validate.rs +149 -0
- package/crates/jettypod-core/src/error.rs +76 -0
- package/crates/jettypod-core/src/git.rs +458 -0
- package/crates/jettypod-core/src/lib.rs +20 -0
- package/crates/jettypod-core/src/sessions.rs +625 -0
- package/crates/jettypod-core/src/skills.rs +556 -0
- package/crates/jettypod-core/src/work.rs +1086 -0
- package/crates/jettypod-core/src/worktree.rs +628 -0
- package/crates/jettypod-core/src/ws.rs +767 -0
- package/cucumber-test.cjs +6 -0
- package/cucumber.js +9 -3
- package/docs/COMMAND_REFERENCE.md +34 -0
- package/hooks/post-checkout +32 -75
- package/hooks/post-merge +111 -10
- package/jest.setup.js +1 -0
- package/jettypod.js +145 -116
- package/lib/bdd-preflight.js +96 -0
- package/lib/chore-taxonomy.js +33 -10
- package/lib/database.js +36 -16
- package/lib/db-watcher.js +1 -1
- package/lib/git-hooks/pre-commit +1 -1
- package/lib/jettypod-backup.js +27 -4
- package/lib/merge-lock.js +111 -253
- package/lib/migrations/027-plan-at-creation-column.js +3 -1
- package/lib/migrations/029-remove-autoincrement.js +307 -0
- package/lib/migrations/029-rename-corrupted-to-cleaned.js +149 -0
- package/lib/migrations/030-rejection-round-columns.js +54 -0
- package/lib/migrations/031-session-isolation-index.js +17 -0
- package/lib/migrations/index.js +47 -4
- package/lib/schema.js +10 -5
- package/lib/seed-onboarding.js +1 -1
- package/lib/update-command/index.js +9 -175
- package/lib/work-commands/index.js +144 -19
- package/lib/work-tracking/index.js +148 -27
- package/lib/worktree-diagnostics.js +16 -16
- package/lib/worktree-facade.js +1 -1
- package/lib/worktree-manager.js +8 -8
- package/lib/worktree-reconciler.js +5 -5
- package/package.json +9 -2
- package/scripts/ndjson-to-cucumber-json.js +152 -0
- package/scripts/postinstall.js +25 -0
- package/skills-templates/bug-mode/SKILL.md +79 -20
- package/skills-templates/bug-planning/SKILL.md +25 -29
- package/skills-templates/chore-mode/SKILL.md +171 -69
- package/skills-templates/chore-mode/verification.js +51 -10
- package/skills-templates/chore-planning/SKILL.md +47 -18
- package/skills-templates/design-system-selection/SKILL.md +273 -0
- package/skills-templates/epic-planning/SKILL.md +82 -48
- package/skills-templates/external-transition/SKILL.md +47 -47
- package/skills-templates/feature-planning/SKILL.md +173 -74
- package/skills-templates/production-mode/SKILL.md +69 -49
- package/skills-templates/request-routing/SKILL.md +4 -4
- package/skills-templates/simple-improvement/SKILL.md +74 -29
- package/skills-templates/speed-mode/SKILL.md +217 -141
- package/skills-templates/stable-mode/SKILL.md +148 -89
- package/apps/dashboard/README.md +0 -36
- package/apps/dashboard/app/api/claude/[workItemId]/message/route.ts +0 -386
- package/apps/dashboard/app/api/claude/[workItemId]/pin/route.ts +0 -24
- package/apps/dashboard/app/api/claude/[workItemId]/route.ts +0 -167
- package/apps/dashboard/app/api/claude/sessions/[sessionId]/content/route.ts +0 -52
- package/apps/dashboard/app/api/claude/sessions/[sessionId]/message/route.ts +0 -378
- package/apps/dashboard/app/api/claude/sessions/[sessionId]/pin/route.ts +0 -24
- package/apps/dashboard/app/api/claude/sessions/cleanup/route.ts +0 -34
- package/apps/dashboard/app/api/claude/sessions/route.ts +0 -184
- package/apps/dashboard/app/api/decisions/[id]/route.ts +0 -25
- package/apps/dashboard/app/api/internal/set-project/route.ts +0 -17
- package/apps/dashboard/app/api/kanban/route.ts +0 -15
- package/apps/dashboard/app/api/settings/env-vars/route.ts +0 -125
- package/apps/dashboard/app/api/settings/general/route.ts +0 -21
- package/apps/dashboard/app/api/tests/route.ts +0 -9
- package/apps/dashboard/app/api/tests/run/route.ts +0 -82
- package/apps/dashboard/app/api/tests/run/stream/route.ts +0 -71
- package/apps/dashboard/app/api/tests/undefined/route.ts +0 -9
- package/apps/dashboard/app/api/usage/route.ts +0 -17
- package/apps/dashboard/app/api/work/[id]/description/route.ts +0 -21
- package/apps/dashboard/app/api/work/[id]/epic/route.ts +0 -21
- package/apps/dashboard/app/api/work/[id]/order/route.ts +0 -21
- package/apps/dashboard/app/api/work/[id]/status/route.ts +0 -21
- package/apps/dashboard/app/api/work/[id]/title/route.ts +0 -21
- package/apps/dashboard/app/layout.tsx +0 -43
- package/apps/dashboard/components/UpgradeBanner.tsx +0 -29
- package/apps/dashboard/electron/ipc-handlers.js +0 -1028
- package/apps/dashboard/electron/main.js +0 -2124
- package/apps/dashboard/electron/preload.js +0 -123
- package/apps/dashboard/electron/session-manager.js +0 -141
- package/apps/dashboard/electron-builder.config.js +0 -357
- package/apps/dashboard/hooks/useClaudeSessions.ts +0 -299
- package/apps/dashboard/lib/claude-process-manager.ts +0 -492
- package/apps/dashboard/lib/db-bridge.ts +0 -282
- package/apps/dashboard/lib/prototypes.ts +0 -202
- package/apps/dashboard/lib/test-results-db.ts +0 -307
- package/apps/dashboard/lib/tests.ts +0 -282
- package/apps/dashboard/next.config.js +0 -50
- package/apps/dashboard/postcss.config.mjs +0 -7
- package/apps/dashboard/public/file.svg +0 -1
- package/apps/dashboard/public/globe.svg +0 -1
- package/apps/dashboard/public/next.svg +0 -1
- package/apps/dashboard/public/vercel.svg +0 -1
- package/apps/dashboard/public/window.svg +0 -1
- package/apps/dashboard/scripts/download-node.js +0 -104
- package/apps/dashboard/scripts/upload-to-r2.js +0 -89
- package/docs/bdd-guidance.md +0 -390
|
@@ -1,18 +1,17 @@
|
|
|
1
|
-
'use client';
|
|
2
|
-
|
|
3
1
|
import { ConnectClaudeScreen } from '@/components/ConnectClaudeScreen';
|
|
2
|
+
import { isTauri, claudeCode } from '@/lib/tauri-bridge';
|
|
4
3
|
|
|
5
4
|
export default function ConnectClaudePage() {
|
|
6
5
|
const handleConnect = async () => {
|
|
7
|
-
if (!
|
|
6
|
+
if (!isTauri()) {
|
|
8
7
|
return { success: false, error: 'Only available in the desktop app.' };
|
|
9
8
|
}
|
|
10
|
-
return await
|
|
9
|
+
return await claudeCode.login();
|
|
11
10
|
};
|
|
12
11
|
|
|
13
12
|
const handleCheckAuth = async () => {
|
|
14
|
-
if (!
|
|
15
|
-
return await
|
|
13
|
+
if (!isTauri()) return false;
|
|
14
|
+
return await claudeCode.isAuthenticated();
|
|
16
15
|
};
|
|
17
16
|
|
|
18
17
|
return (
|
|
@@ -1,41 +1,65 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import Link from '
|
|
3
|
-
import {
|
|
1
|
+
import { useState, useEffect } from 'react';
|
|
2
|
+
import { useParams, Link } from 'react-router-dom';
|
|
3
|
+
import { dataBridge } from '@/lib/data-bridge';
|
|
4
|
+
import type { DecisionData } from '@/lib/data-bridge';
|
|
4
5
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
export default function DecisionPage() {
|
|
7
|
+
const { id } = useParams<{ id: string }>();
|
|
8
|
+
const [decision, setDecision] = useState<DecisionData | null>(null);
|
|
9
|
+
const [loading, setLoading] = useState(true);
|
|
10
|
+
const [notFound, setNotFound] = useState(false);
|
|
8
11
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
+
useEffect(() => {
|
|
13
|
+
async function loadData() {
|
|
14
|
+
const decisionId = parseInt(id || '', 10);
|
|
15
|
+
if (isNaN(decisionId)) {
|
|
16
|
+
setNotFound(true);
|
|
17
|
+
setLoading(false);
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
12
20
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
21
|
+
try {
|
|
22
|
+
const data = await dataBridge.getDecision(decisionId);
|
|
23
|
+
if (!data) {
|
|
24
|
+
setNotFound(true);
|
|
25
|
+
} else {
|
|
26
|
+
setDecision(data);
|
|
27
|
+
}
|
|
28
|
+
} catch {
|
|
29
|
+
setNotFound(true);
|
|
30
|
+
} finally {
|
|
31
|
+
setLoading(false);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
loadData();
|
|
35
|
+
}, [id]);
|
|
16
36
|
|
|
17
|
-
|
|
37
|
+
if (loading) return null;
|
|
18
38
|
|
|
19
|
-
if (!decision) {
|
|
20
|
-
|
|
39
|
+
if (notFound || !decision) {
|
|
40
|
+
return (
|
|
41
|
+
<div className="flex-1 flex items-center justify-center">
|
|
42
|
+
<div className="text-center">
|
|
43
|
+
<h1 className="text-2xl font-bold text-zinc-900 dark:text-zinc-100 mb-2">Not Found</h1>
|
|
44
|
+
<p className="text-zinc-500 mb-4">Decision not found.</p>
|
|
45
|
+
<Link to="/" viewTransition className="text-[#5a7d7f] hover:underline">← Back to Dashboard</Link>
|
|
46
|
+
</div>
|
|
47
|
+
</div>
|
|
48
|
+
);
|
|
21
49
|
}
|
|
22
50
|
|
|
23
51
|
return (
|
|
24
|
-
<div className="
|
|
25
|
-
{/* Header */}
|
|
52
|
+
<div className="flex-1 overflow-y-auto bg-zinc-50 dark:bg-zinc-950">
|
|
26
53
|
<header className="border-b border-zinc-200 dark:border-zinc-800 bg-white dark:bg-zinc-900">
|
|
27
|
-
<div className="max-w-4xl mx-auto px-
|
|
28
|
-
<Link
|
|
29
|
-
← Back to Dashboard
|
|
30
|
-
</Link>
|
|
54
|
+
<div className="max-w-4xl mx-auto px-6 py-6">
|
|
55
|
+
<Link to="/" viewTransition className="text-[#5a7d7f] dark:text-[#a3bfc0] hover:underline text-base">← Back to Dashboard</Link>
|
|
31
56
|
</div>
|
|
32
57
|
</header>
|
|
33
58
|
|
|
34
59
|
<main className="max-w-4xl mx-auto px-4 py-6">
|
|
35
|
-
{/* Breadcrumb to parent work item */}
|
|
36
60
|
{decision.work_item_id && (
|
|
37
|
-
<div className="mb-
|
|
38
|
-
<Link
|
|
61
|
+
<div className="mb-6 text-base text-zinc-500">
|
|
62
|
+
<Link to={`/work/${decision.work_item_id}`} viewTransition className="hover:underline">
|
|
39
63
|
#{decision.work_item_id} {decision.work_item_title}
|
|
40
64
|
</Link>
|
|
41
65
|
<span className="mx-2">→</span>
|
|
@@ -43,65 +67,46 @@ export default async function DecisionPage({ params }: PageProps) {
|
|
|
43
67
|
</div>
|
|
44
68
|
)}
|
|
45
69
|
|
|
46
|
-
{/* Main card */}
|
|
47
70
|
<div className="bg-white dark:bg-zinc-900 rounded-lg border border-zinc-200 dark:border-zinc-800 overflow-hidden">
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
<div className="flex items-start justify-between gap-4">
|
|
71
|
+
<div className="px-8 py-6 border-b border-zinc-200 dark:border-zinc-800">
|
|
72
|
+
<div className="flex items-start justify-between gap-6">
|
|
51
73
|
<div>
|
|
52
|
-
<div className="flex items-center gap-
|
|
74
|
+
<div className="flex items-center gap-3 text-base text-zinc-500 mb-1.5">
|
|
53
75
|
<span>📋 Decision</span>
|
|
54
76
|
<span>•</span>
|
|
55
77
|
<span className="font-mono">#{decision.id}</span>
|
|
56
78
|
</div>
|
|
57
|
-
<h1 className="text-2xl font-bold text-zinc-900 dark:text-zinc-100">
|
|
58
|
-
{decision.aspect}
|
|
59
|
-
</h1>
|
|
79
|
+
<h1 className="text-2xl font-bold text-zinc-900 dark:text-zinc-100">{decision.aspect}</h1>
|
|
60
80
|
</div>
|
|
61
81
|
</div>
|
|
62
82
|
</div>
|
|
63
83
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
<
|
|
67
|
-
Decision
|
|
68
|
-
</h2>
|
|
69
|
-
<p className="text-zinc-700 dark:text-zinc-300 whitespace-pre-wrap text-lg">
|
|
70
|
-
{decision.decision}
|
|
71
|
-
</p>
|
|
84
|
+
<div className="px-8 py-6 border-b border-zinc-200 dark:border-zinc-800">
|
|
85
|
+
<h2 className="text-base font-semibold text-zinc-500 uppercase tracking-wide mb-3">Decision</h2>
|
|
86
|
+
<p className="text-zinc-700 dark:text-zinc-300 whitespace-pre-wrap text-lg">{decision.decision}</p>
|
|
72
87
|
</div>
|
|
73
88
|
|
|
74
|
-
{/* Rationale */}
|
|
75
89
|
{decision.rationale && (
|
|
76
|
-
<div className="px-
|
|
77
|
-
<h2 className="text-
|
|
78
|
-
|
|
79
|
-
</h2>
|
|
80
|
-
<p className="text-zinc-700 dark:text-zinc-300 whitespace-pre-wrap">
|
|
81
|
-
{decision.rationale}
|
|
82
|
-
</p>
|
|
90
|
+
<div className="px-8 py-6 border-b border-zinc-200 dark:border-zinc-800">
|
|
91
|
+
<h2 className="text-base font-semibold text-zinc-500 uppercase tracking-wide mb-3">Rationale</h2>
|
|
92
|
+
<p className="text-zinc-700 dark:text-zinc-300 whitespace-pre-wrap">{decision.rationale}</p>
|
|
83
93
|
</div>
|
|
84
94
|
)}
|
|
85
95
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
<
|
|
89
|
-
Details
|
|
90
|
-
</h2>
|
|
91
|
-
<dl className="grid grid-cols-2 gap-4 text-sm">
|
|
96
|
+
<div className="px-8 py-6">
|
|
97
|
+
<h2 className="text-base font-semibold text-zinc-500 uppercase tracking-wide mb-4">Details</h2>
|
|
98
|
+
<dl className="grid grid-cols-2 gap-6 text-base">
|
|
92
99
|
<div>
|
|
93
100
|
<dt className="text-zinc-500">Related Work Item</dt>
|
|
94
101
|
<dd className="text-zinc-900 dark:text-zinc-100">
|
|
95
|
-
<Link
|
|
102
|
+
<Link to={`/work/${decision.work_item_id}`} viewTransition className="hover:underline text-[#5a7d7f] dark:text-[#a3bfc0]">
|
|
96
103
|
#{decision.work_item_id} {decision.work_item_title}
|
|
97
104
|
</Link>
|
|
98
105
|
</dd>
|
|
99
106
|
</div>
|
|
100
107
|
<div>
|
|
101
108
|
<dt className="text-zinc-500">Created</dt>
|
|
102
|
-
<dd className="text-zinc-900 dark:text-zinc-100">
|
|
103
|
-
{new Date(decision.created_at).toLocaleDateString()}
|
|
104
|
-
</dd>
|
|
109
|
+
<dd className="text-zinc-900 dark:text-zinc-100">{new Date(decision.created_at).toLocaleDateString()}</dd>
|
|
105
110
|
</div>
|
|
106
111
|
</dl>
|
|
107
112
|
</div>
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
'use client';
|
|
2
|
-
|
|
3
1
|
import { useState, useEffect, useCallback } from 'react';
|
|
4
2
|
import { GateCard } from '@/components/GateCard';
|
|
5
3
|
import { GateChoiceCard } from '@/components/GateChoiceCard';
|
|
@@ -124,18 +122,18 @@ export default function GateDemoPage() {
|
|
|
124
122
|
const [activeTab, setActiveTab] = useState<DemoTab>('workflow');
|
|
125
123
|
|
|
126
124
|
return (
|
|
127
|
-
<div className="
|
|
125
|
+
<div className="flex-1 overflow-y-auto bg-zinc-100 dark:bg-zinc-900 p-10">
|
|
128
126
|
<div className="max-w-5xl mx-auto">
|
|
129
127
|
{/* Header */}
|
|
130
|
-
<div className="mb-
|
|
131
|
-
<h1 className="text-2xl font-bold text-zinc-900 dark:text-zinc-100 mb-1">Gate Protocol Demo</h1>
|
|
132
|
-
<p className="text-zinc-500 dark:text-zinc-400 text-
|
|
128
|
+
<div className="mb-8">
|
|
129
|
+
<h1 className="text-2xl font-bold text-zinc-900 dark:text-zinc-100 mb-1.5">Gate Protocol Demo</h1>
|
|
130
|
+
<p className="text-zinc-500 dark:text-zinc-400 text-base">
|
|
133
131
|
Prototype narrated UI components for workflow status and user input.
|
|
134
132
|
</p>
|
|
135
133
|
</div>
|
|
136
134
|
|
|
137
135
|
{/* Tab nav */}
|
|
138
|
-
<div className="flex gap-1 mb-
|
|
136
|
+
<div className="flex gap-1.5 mb-8 bg-white dark:bg-zinc-800 rounded-xl border border-zinc-200 dark:border-zinc-700 p-1.5 w-fit"
|
|
139
137
|
style={{ boxShadow: '0 1px 2px rgba(0,0,0,0.03)' }}
|
|
140
138
|
>
|
|
141
139
|
{([
|
|
@@ -146,7 +144,7 @@ export default function GateDemoPage() {
|
|
|
146
144
|
<button
|
|
147
145
|
key={id}
|
|
148
146
|
onClick={() => setActiveTab(id)}
|
|
149
|
-
className={`px-
|
|
147
|
+
className={`px-5 py-2 text-base font-medium rounded-lg transition-colors ${
|
|
150
148
|
activeTab === id
|
|
151
149
|
? 'bg-zinc-900 dark:bg-zinc-100 text-white dark:text-zinc-900'
|
|
152
150
|
: 'text-zinc-500 dark:text-zinc-400 hover:text-zinc-700 dark:hover:text-zinc-200'
|
|
@@ -250,11 +248,11 @@ function WorkflowDemo() {
|
|
|
250
248
|
return (
|
|
251
249
|
<>
|
|
252
250
|
{/* Controls */}
|
|
253
|
-
<div className="flex items-center gap-
|
|
251
|
+
<div className="flex items-center gap-4 mb-8">
|
|
254
252
|
<button
|
|
255
253
|
onClick={play}
|
|
256
254
|
disabled={isPlaying}
|
|
257
|
-
className="px-
|
|
255
|
+
className="px-5 py-3 bg-zinc-900 dark:bg-zinc-100 hover:bg-zinc-800 dark:hover:bg-zinc-200 disabled:opacity-50 text-white dark:text-zinc-900 text-base font-medium rounded-xl transition-[color,background-color,opacity] duration-200"
|
|
258
256
|
style={{ boxShadow: '0 1px 2px rgba(0,0,0,0.1), 0 2px 4px rgba(0,0,0,0.06)' }}
|
|
259
257
|
>
|
|
260
258
|
{isDone ? 'Replay' : isPaused ? 'Waiting for input...' : isPlaying ? 'Playing...' : 'Play Workflow'}
|
|
@@ -262,20 +260,20 @@ function WorkflowDemo() {
|
|
|
262
260
|
{(isPlaying || isDone) && (
|
|
263
261
|
<button
|
|
264
262
|
onClick={reset}
|
|
265
|
-
className="px-
|
|
263
|
+
className="px-5 py-3 bg-white dark:bg-zinc-800 border border-zinc-200 dark:border-zinc-700 hover:bg-zinc-50 dark:hover:bg-zinc-700 text-zinc-700 dark:text-zinc-300 text-base font-medium rounded-xl transition-colors"
|
|
266
264
|
>
|
|
267
265
|
Reset
|
|
268
266
|
</button>
|
|
269
267
|
)}
|
|
270
268
|
<div className="flex-1" />
|
|
271
|
-
<div className="flex bg-white dark:bg-zinc-800 rounded-xl border border-zinc-200 dark:border-zinc-700 p-1 overflow-hidden"
|
|
269
|
+
<div className="flex bg-white dark:bg-zinc-800 rounded-xl border border-zinc-200 dark:border-zinc-700 p-1.5 overflow-hidden"
|
|
272
270
|
style={{ boxShadow: '0 1px 2px rgba(0,0,0,0.03)' }}
|
|
273
271
|
>
|
|
274
272
|
{(['narrated', 'direct', 'split'] as ViewMode[]).map(mode => (
|
|
275
273
|
<button
|
|
276
274
|
key={mode}
|
|
277
275
|
onClick={() => setViewMode(mode)}
|
|
278
|
-
className={`px-
|
|
276
|
+
className={`px-4 py-2 text-base font-medium rounded-lg transition-colors ${
|
|
279
277
|
viewMode === mode
|
|
280
278
|
? 'bg-zinc-900 dark:bg-zinc-100 text-white dark:text-zinc-900'
|
|
281
279
|
: 'text-zinc-500 dark:text-zinc-400 hover:text-zinc-700 dark:hover:text-zinc-200'
|
|
@@ -290,13 +288,13 @@ function WorkflowDemo() {
|
|
|
290
288
|
{/* Progress */}
|
|
291
289
|
{(isPlaying || isDone) && (
|
|
292
290
|
<div className="mb-6">
|
|
293
|
-
<div className="flex items-center justify-between text-
|
|
291
|
+
<div className="flex items-center justify-between text-base text-zinc-500 dark:text-zinc-400 mb-2">
|
|
294
292
|
<span>{gateCount} of {WORKFLOW_GATES.length} gates</span>
|
|
295
293
|
<span>{visibleCount} of {totalSteps} events</span>
|
|
296
294
|
</div>
|
|
297
295
|
<div className="h-1 bg-zinc-200 dark:bg-zinc-700 rounded-full overflow-hidden">
|
|
298
296
|
<div
|
|
299
|
-
className="h-full bg-zinc-900 dark:bg-zinc-100 rounded-full transition-
|
|
297
|
+
className="h-full bg-zinc-900 dark:bg-zinc-100 rounded-full transition-[width] duration-500"
|
|
300
298
|
style={{ width: `${(visibleCount / totalSteps) * 100}%` }}
|
|
301
299
|
/>
|
|
302
300
|
</div>
|
|
@@ -305,7 +303,7 @@ function WorkflowDemo() {
|
|
|
305
303
|
|
|
306
304
|
{/* Content */}
|
|
307
305
|
{viewMode === 'split' ? (
|
|
308
|
-
<div className="grid grid-cols-2 gap-
|
|
306
|
+
<div className="grid grid-cols-2 gap-6">
|
|
309
307
|
<Panel title="Summary View" subtitle="What the user sees" highlight>
|
|
310
308
|
<NarratedView gates={visibleGates} isPlaying={isPlaying} answeredQuestions={answeredQuestions} onAnswerQuestion={handleAnswerQuestion} />
|
|
311
309
|
</Panel>
|
|
@@ -324,26 +322,26 @@ function WorkflowDemo() {
|
|
|
324
322
|
)}
|
|
325
323
|
|
|
326
324
|
{!isPlaying && !isPaused && !isDone && (
|
|
327
|
-
<div className="mt-6 bg-white dark:bg-zinc-800 rounded-xl border border-zinc-200 dark:border-zinc-700 p-
|
|
325
|
+
<div className="mt-6 bg-white dark:bg-zinc-800 rounded-xl border border-zinc-200 dark:border-zinc-700 p-6"
|
|
328
326
|
style={{ boxShadow: '0 1px 2px rgba(0,0,0,0.03)' }}
|
|
329
327
|
>
|
|
330
|
-
<h3 className="text-
|
|
331
|
-
<div className="grid grid-cols-4 gap-
|
|
328
|
+
<h3 className="text-base font-semibold text-zinc-700 dark:text-zinc-300 mb-4">How it works</h3>
|
|
329
|
+
<div className="grid grid-cols-4 gap-6 text-base text-zinc-500 dark:text-zinc-400">
|
|
332
330
|
<div>
|
|
333
331
|
<span className="font-medium text-zinc-700 dark:text-zinc-300">1. User sends request</span>
|
|
334
|
-
<p className="mt-1">"Add form validation to the signup page"</p>
|
|
332
|
+
<p className="mt-1.5">"Add form validation to the signup page"</p>
|
|
335
333
|
</div>
|
|
336
334
|
<div>
|
|
337
335
|
<span className="font-medium text-zinc-700 dark:text-zinc-300">2. Question gates pause</span>
|
|
338
|
-
<p className="mt-1">When Claude needs input, an interactive choice card appears</p>
|
|
336
|
+
<p className="mt-1.5">When Claude needs input, an interactive choice card appears</p>
|
|
339
337
|
</div>
|
|
340
338
|
<div>
|
|
341
339
|
<span className="font-medium text-zinc-700 dark:text-zinc-300">3. Claude works (hidden)</span>
|
|
342
|
-
<p className="mt-1">Reads files, makes edits, runs commands — behind the scenes</p>
|
|
340
|
+
<p className="mt-1.5">Reads files, makes edits, runs commands — behind the scenes</p>
|
|
343
341
|
</div>
|
|
344
342
|
<div>
|
|
345
343
|
<span className="font-medium text-zinc-700 dark:text-zinc-300">4. Gates signal progress</span>
|
|
346
|
-
<p className="mt-1">Clean status cards appear at key workflow milestones</p>
|
|
344
|
+
<p className="mt-1.5">Clean status cards appear at key workflow milestones</p>
|
|
347
345
|
</div>
|
|
348
346
|
</div>
|
|
349
347
|
</div>
|
|
@@ -376,10 +374,10 @@ function CardsShowcase() {
|
|
|
376
374
|
|
|
377
375
|
return (
|
|
378
376
|
<div>
|
|
379
|
-
<p className="text-
|
|
377
|
+
<p className="text-base text-zinc-500 dark:text-zinc-400 mb-4">
|
|
380
378
|
All gate card types shown with sample data, including the interactive question gate. Each card matches the kanban card design system.
|
|
381
379
|
</p>
|
|
382
|
-
<div className="grid grid-cols-2 gap-
|
|
380
|
+
<div className="grid grid-cols-2 gap-4">
|
|
383
381
|
{allGateTypes.map((gate, i) => (
|
|
384
382
|
<GateCard
|
|
385
383
|
key={i}
|
|
@@ -411,8 +409,8 @@ function ChoicesShowcase() {
|
|
|
411
409
|
<div className="space-y-8">
|
|
412
410
|
{/* Approach selection */}
|
|
413
411
|
<div>
|
|
414
|
-
<h3 className="text-
|
|
415
|
-
<p className="text-
|
|
412
|
+
<h3 className="text-base font-semibold text-zinc-700 dark:text-zinc-300 mb-1">UX Approach Selection</h3>
|
|
413
|
+
<p className="text-base text-zinc-500 dark:text-zinc-400 mb-3">
|
|
416
414
|
Shown during feature-planning when Claude proposes multiple approaches.
|
|
417
415
|
</p>
|
|
418
416
|
<div className="max-w-lg">
|
|
@@ -427,8 +425,8 @@ function ChoicesShowcase() {
|
|
|
427
425
|
|
|
428
426
|
{/* Confirmation */}
|
|
429
427
|
<div>
|
|
430
|
-
<h3 className="text-
|
|
431
|
-
<p className="text-
|
|
428
|
+
<h3 className="text-base font-semibold text-zinc-700 dark:text-zinc-300 mb-1">Plan Confirmation</h3>
|
|
429
|
+
<p className="text-base text-zinc-500 dark:text-zinc-400 mb-3">
|
|
432
430
|
Shown when Claude needs a go/no-go decision before starting implementation.
|
|
433
431
|
</p>
|
|
434
432
|
<div className="max-w-lg">
|
|
@@ -443,8 +441,8 @@ function ChoicesShowcase() {
|
|
|
443
441
|
|
|
444
442
|
{/* Disabled state (after selection) */}
|
|
445
443
|
<div>
|
|
446
|
-
<h3 className="text-
|
|
447
|
-
<p className="text-
|
|
444
|
+
<h3 className="text-base font-semibold text-zinc-700 dark:text-zinc-300 mb-1">After Selection (Locked)</h3>
|
|
445
|
+
<p className="text-base text-zinc-500 dark:text-zinc-400 mb-3">
|
|
448
446
|
How the card looks after the user has made their choice and the workflow continues.
|
|
449
447
|
</p>
|
|
450
448
|
<div className="max-w-lg">
|
|
@@ -476,21 +474,21 @@ function Panel({ title, subtitle, highlight, children }: {
|
|
|
476
474
|
<div
|
|
477
475
|
className={`bg-white dark:bg-zinc-800 rounded-xl border overflow-hidden ${
|
|
478
476
|
highlight
|
|
479
|
-
? 'border-
|
|
477
|
+
? 'border-[#819D9F]/30 dark:border-[#819D9F]/30'
|
|
480
478
|
: 'border-zinc-200 dark:border-zinc-700'
|
|
481
479
|
}`}
|
|
482
480
|
style={{ boxShadow: PANEL_SHADOW }}
|
|
483
481
|
>
|
|
484
482
|
<div className={`px-4 py-3 border-b ${
|
|
485
483
|
highlight
|
|
486
|
-
? 'border-
|
|
484
|
+
? 'border-[#819D9F]/20 dark:border-[#819D9F]/20 bg-[#e8f0f0]/50 dark:bg-[#819D9F]/10'
|
|
487
485
|
: 'border-zinc-100 dark:border-zinc-700'
|
|
488
486
|
}`}>
|
|
489
|
-
<h2 className={`text-
|
|
490
|
-
highlight ? 'text-
|
|
487
|
+
<h2 className={`text-base font-semibold ${
|
|
488
|
+
highlight ? 'text-zinc-900 dark:text-[#a3bfc0]' : 'text-zinc-700 dark:text-zinc-300'
|
|
491
489
|
}`}>{title}</h2>
|
|
492
|
-
<p className={`text-
|
|
493
|
-
highlight ? 'text-
|
|
490
|
+
<p className={`text-base ${
|
|
491
|
+
highlight ? 'text-[#819D9F] dark:text-[#a3bfc0]' : 'text-zinc-400 dark:text-zinc-500'
|
|
494
492
|
}`}>{subtitle}</p>
|
|
495
493
|
</div>
|
|
496
494
|
<div className="p-4 min-h-[400px] max-h-[600px] overflow-y-auto">
|
|
@@ -503,13 +501,13 @@ function Panel({ title, subtitle, highlight, children }: {
|
|
|
503
501
|
function UserBubble({ text }: { text: string }) {
|
|
504
502
|
return (
|
|
505
503
|
<div
|
|
506
|
-
className="bg-
|
|
504
|
+
className="bg-[#e8f0f0] dark:bg-[#819D9F]/20 border border-[#819D9F]/30 dark:border-[#819D9F]/30 rounded-xl p-3 ml-8"
|
|
507
505
|
style={{ boxShadow: '0 1px 2px rgba(0,0,0,0.03)' }}
|
|
508
506
|
>
|
|
509
507
|
<div className="flex items-center gap-2 mb-1">
|
|
510
|
-
<span className="text-
|
|
508
|
+
<span className="text-base font-medium text-[#5a7d7f] dark:text-[#a3bfc0]">You</span>
|
|
511
509
|
</div>
|
|
512
|
-
<p className="text-
|
|
510
|
+
<p className="text-base text-zinc-900 dark:text-zinc-100">{text}</p>
|
|
513
511
|
</div>
|
|
514
512
|
);
|
|
515
513
|
}
|
|
@@ -522,7 +520,7 @@ function NarratedView({ gates, isPlaying, answeredQuestions, onAnswerQuestion }:
|
|
|
522
520
|
}) {
|
|
523
521
|
if (gates.length === 0 && !isPlaying) {
|
|
524
522
|
return (
|
|
525
|
-
<div className="flex items-center justify-center h-full text-zinc-400 dark:text-zinc-500 text-
|
|
523
|
+
<div className="flex items-center justify-center h-full text-zinc-400 dark:text-zinc-500 text-base">
|
|
526
524
|
Press "Play Workflow" to start
|
|
527
525
|
</div>
|
|
528
526
|
);
|
|
@@ -558,7 +556,7 @@ function DirectView({ messages, gates, isPlaying, answeredQuestions, onAnswerQue
|
|
|
558
556
|
}) {
|
|
559
557
|
if (messages.length === 0 && !isPlaying) {
|
|
560
558
|
return (
|
|
561
|
-
<div className="flex items-center justify-center h-full text-zinc-400 dark:text-zinc-500 text-
|
|
559
|
+
<div className="flex items-center justify-center h-full text-zinc-400 dark:text-zinc-500 text-base">
|
|
562
560
|
Press "Play Workflow" to start
|
|
563
561
|
</div>
|
|
564
562
|
);
|
|
@@ -603,7 +601,7 @@ function DirectView({ messages, gates, isPlaying, answeredQuestions, onAnswerQue
|
|
|
603
601
|
if (msg.type === 'assistant') {
|
|
604
602
|
return (
|
|
605
603
|
<div key={i} className="bg-zinc-50 dark:bg-zinc-800/50 rounded-xl p-3" style={{ boxShadow: '0 1px 2px rgba(0,0,0,0.02)' }}>
|
|
606
|
-
<p className="text-
|
|
604
|
+
<p className="text-base text-zinc-700 dark:text-zinc-300">{msg.content}</p>
|
|
607
605
|
</div>
|
|
608
606
|
);
|
|
609
607
|
}
|
|
@@ -645,8 +643,8 @@ function DirectView({ messages, gates, isPlaying, answeredQuestions, onAnswerQue
|
|
|
645
643
|
|
|
646
644
|
function WorkingIndicator() {
|
|
647
645
|
return (
|
|
648
|
-
<div className="flex items-center gap-2 text-
|
|
649
|
-
<span className="w-1.5 h-1.5 bg-
|
|
646
|
+
<div className="flex items-center gap-2 text-base text-zinc-400 dark:text-zinc-500 py-2 pl-1">
|
|
647
|
+
<span className="w-1.5 h-1.5 bg-[#819D9F] rounded-full animate-pulse" />
|
|
650
648
|
Working...
|
|
651
649
|
</div>
|
|
652
650
|
);
|