diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..86557be --- /dev/null +++ b/.env.example @@ -0,0 +1,2 @@ +## Copy this file to .env and fill in your key. Do not commit .env. +ANTHROPIC_API_KEY=your-anthropic-api-key-here diff --git a/.gitignore b/.gitignore index effa2fc..d8b5240 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ node_modules/ .DS_Store Thumbs.db *.log +.env diff --git a/QUICKSTART.md b/QUICKSTART.md new file mode 100644 index 0000000..9daf2a3 --- /dev/null +++ b/QUICKSTART.md @@ -0,0 +1,112 @@ +# Quick Start: SDE Meeting Toolkit + +## Open a tool + +1. Go to the `tools` folder. +2. Double-click `field-problem-workshop.html` or `scope-lock-meeting-suite.html`. +3. The file opens in your default browser. + +No install step is needed for this method. + +## Field Problem Workshop + +The tool has three panels: Problem Map, Breadcrumbs, Actions. + +### Problem Map panel + +1. Type a problem into the entry box and click **Add**. +2. Click **Add cluster** to create a new group. +3. Drag a problem into a cluster, or use the cluster picker on the item. +4. Use dot voting to mark priority problems. +5. Unsorted problems stay under **Unclustered** at the top. + +### Breadcrumbs panel + +1. Click **Add a blank breadcrumb** to start a new one. +2. Fill in **Baseline**, **Method**, **Metric**, and, once you have a baseline, **Target**. +3. Click **Scan for incomplete items** to find breadcrumbs missing a field. +4. Click **Save** on a breadcrumb to lock in your edits. + +### Actions panel + +1. Click **Add** to create an action item. +2. Assign an owner and a due date. +3. Click **Save** to store the action. + +### Save your session + +The tool does not save to disk on its own. + +1. Click **Save JSON** before you close the tab. +2. Store the file somewhere you can find it. +3. Next time, click **Load JSON** and pick that file to pick up where you left off. +4. Click **Export summary** to produce the meeting write-up (markdown). +5. Click **Reset** only when you want to return to the July 21 baseline (43 problems, 7 clusters, 6 breadcrumbs, 5 actions). Reset erases current data, so export first. + +## Scope Lock Meeting Suite + +The tool has four panels: Scope Boundary Board, MVP Priority Ranker, Decision Registry, Micron Pilot Readiness. + +### Scope Boundary Board + +1. Click **Add item** to enter a new scope item. +2. Move it into one of four columns: **In MVP**, **Later Phase**, **Out**, **Parking Lot**. +3. Items start in **Unsorted** until you sort them. + +### MVP Priority Ranker + +1. Use **Move line up** / **Move line down** to reorder items by priority. + +### Decision Registry + +1. Click **Log decision** to record a decision made in the meeting. + +### Micron Pilot Readiness + +1. Review the readiness checklist shown on this panel. + +### Save your session + +1. This tool autosaves to the browser's local storage on the computer you use. It does not need a manual save step. +2. Local storage does not follow you to another computer or browser. +3. Click **Export meeting summary** to create the durable record to share or file. +4. **Reset all** returns the tool to its starting state. Export first if you want to keep current data. + +## Run it from a local server instead + +Use this if you want the tools served over HTTP, or if you want the AI draft button to work outside of Claude. + +1. Open a terminal in the `sde-meeting-toolkit` folder. +2. Run `npm run serve`. +3. Open `http://localhost:5173` in a browser. +4. Click a tool link on that page, or go directly to a file under `tools`. + +## Use the AI draft button + +The Field Problem Workshop has an AI draft feature on the Breadcrumbs panel. It calls Claude to draft breadcrumb fields for you. Use one of these two methods. + +### Method A: Local server (needs an API key) + +1. Copy `.env.example` to a new file named `.env`, in the `sde-meeting-toolkit` folder. +2. Open `.env` and set `ANTHROPIC_API_KEY` to your key. +3. Run `npm run serve`. +4. Open the tool at `http://localhost:5173/tools/field-problem-workshop.html`. +5. Click the AI draft button. + +If the button reports a missing key, check that `.env` exists, holds the correct key, and that you restarted the server after editing it. + +### Method B: Claude artifact (no key needed) + +1. Upload `field-problem-workshop.html` to a Claude chat, or add it to a Claude project. +2. Ask Claude to render it as an artifact. +3. Use the AI draft button from inside that artifact. + +If you open the file directly, with no server running, the AI draft button fails. This is expected. Use Method A or Method B instead. + +## Install the breadcrumb skill + +1. In Claude, open `skills/construction-breadcrumbs.skill`. +2. Use **Save skill** to install it. +3. Start a new chat to use it. + +Next: open a tool and click **Add** to create your first item. diff --git a/README.md b/README.md index b5273cb..3a32bff 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ This folder holds two workshop tools for Project SDE. Each tool is one HTML file ## Requirements -Install Node.js version 18 or later to run the local server. Node.js includes `npx`. +Install Node.js version 18 or later to run the local server. You do not need Node.js to open a tool file directly in a browser. @@ -28,8 +28,11 @@ Follow these steps to set up the project on your computer. ``` git status ``` +4. To use the AI draft button through the local server, copy `.env.example` to `.env`. +5. Open `.env` and set `ANTHROPIC_API_KEY` to your key. +6. Do not commit `.env`. Git already ignores it. -The setup step ends here. The project has no other dependencies to install. +Skip steps 4 through 6 if you plan to run the AI draft button only from inside a Claude artifact (see Method 3 below). The project has no other dependencies to install. ## Run a tool @@ -45,7 +48,7 @@ This method works offline. This method does not run the AI draft button in the F ### Method 2: Run a local server -Use this method to test the tools the way a browser would load them from a web server. +Use this method to test the tools the way a browser would load them from a web server. This method also makes the AI draft button work, if you completed steps 4 through 6 in Setup. 1. Open a terminal. 2. Go to the `sde-meeting-toolkit` folder. @@ -53,20 +56,32 @@ Use this method to test the tools the way a browser would load them from a web s ``` npm run serve ``` -4. Open a browser. -5. Go to this address: `http://localhost:5173` -6. Click a tool file under the `tools` folder. -7. Press `Ctrl+C` in the terminal to stop the server. +4. Check the terminal output. It reports whether it found an API key. +5. Open a browser. +6. Go to this address: `http://localhost:5173` +7. Click a tool link, or go directly to a file under the `tools` folder. +8. Press `Ctrl+C` in the terminal to stop the server. ### Method 3: Use the tool as a Claude artifact -Use this method to run the AI draft button in the Field Problem Workshop. +Use this method to run the AI draft button without setting up a local API key. 1. Open a chat in Claude. 2. Upload the tool file, or add it to a Claude project. 3. Ask Claude to render the file as an artifact. -The AI draft button needs a network connection and the Claude environment. Outside of Claude, the button fails without an error. +This method needs a network connection. It does not need the local server or a `.env` file. + +## AI draft button + +The Field Problem Workshop calls Claude to draft breadcrumb fields. It reaches Claude through one of two paths, never directly from the browser to the Anthropic API. + +- **Local server path**: The browser calls `/api/claude` on your own machine. `server.js` reads `ANTHROPIC_API_KEY` from `.env` and forwards the request. Your key stays on your machine and is never sent to the browser. +- **Claude artifact path**: The Claude environment handles the request. No key setup is needed on your side. + +If you run a tool by double-clicking the file, with no server, the AI draft button fails. This is expected: a plain file has no server to call. + +If you run `npm run serve` without a `.env` file, or with `ANTHROPIC_API_KEY` unset, the button reports that the key is missing. Add the key to `.env` and restart the server to fix it. ## Save and load your work diff --git a/package.json b/package.json index 23c235c..7a3637b 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "private": true, "description": "Local environment for the Project SDE meeting and workshop tools", "scripts": { - "serve": "npx --yes serve . -l 5173", + "serve": "node server.js", "start": "npm run serve" } } diff --git a/server.js b/server.js new file mode 100644 index 0000000..6a16e69 --- /dev/null +++ b/server.js @@ -0,0 +1,128 @@ +/* + * Local server for the SDE meeting toolkit. + * Serves the static tool files. + * Proxies AI draft requests to the Anthropic API, so the API key + * stays on the server and never appears in the browser. + */ +const http = require('http'); +const fs = require('fs'); +const path = require('path'); + +const ROOT = __dirname; +const PORT = process.env.PORT || 5173; +const ANTHROPIC_VERSION = '2023-06-01'; + +const MIME = { + '.html': 'text/html; charset=utf-8', + '.js': 'text/javascript; charset=utf-8', + '.css': 'text/css; charset=utf-8', + '.json': 'application/json; charset=utf-8', + '.svg': 'image/svg+xml', + '.png': 'image/png', + '.skill': 'application/zip' +}; + +function loadEnvFile() { + const envPath = path.join(ROOT, '.env'); + let content; + try { + content = fs.readFileSync(envPath, 'utf8'); + } catch (err) { + return; // no .env file; that is allowed, the AI draft route will report it + } + content.split('\n').forEach((line) => { + const trimmed = line.trim(); + if (!trimmed || trimmed.startsWith('#')) return; + const idx = trimmed.indexOf('='); + if (idx === -1) return; + const key = trimmed.slice(0, idx).trim(); + const value = trimmed.slice(idx + 1).trim().replace(/^["']|["']$/g, ''); + if (key && !(key in process.env)) process.env[key] = value; + }); +} +loadEnvFile(); + +function sendJson(res, status, obj) { + const body = JSON.stringify(obj); + res.writeHead(status, { 'Content-Type': 'application/json; charset=utf-8' }); + res.end(body); +} + +function proxyToClaude(req, res) { + if (!process.env.ANTHROPIC_API_KEY) { + sendJson(res, 500, { + error: 'ANTHROPIC_API_KEY is not set. Add it to the .env file in this folder, then restart the server.' + }); + return; + } + let body = ''; + req.on('data', (chunk) => { body += chunk; }); + req.on('end', async () => { + try { + const upstream = await fetch('https://api.anthropic.com/v1/messages', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'x-api-key': process.env.ANTHROPIC_API_KEY, + 'anthropic-version': ANTHROPIC_VERSION + }, + body + }); + const text = await upstream.text(); + res.writeHead(upstream.status, { 'Content-Type': 'application/json; charset=utf-8' }); + res.end(text); + } catch (err) { + sendJson(res, 502, { error: 'Could not reach the Anthropic API: ' + err.message }); + } + }); +} + +function serveStatic(req, res) { + const urlPath = decodeURIComponent(req.url.split('?')[0]); + if (urlPath === '/') { + const index = `
+