diff --git a/CHANGELOG.md b/CHANGELOG.md
index af343f8..4845352 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,10 @@
All notable changes to this project are logged here, newest first. This file starts from the point the toolkit was handed off and set up in this repo.
+## 2026-09-04 (2)
+
+- Added: the two tools now work together. Each tool's header has a link to the other tool. On the Field Problem Workshop, a cluster tagged with a candidate solution (for example "Tracking MVP (pilot)") gets a "Send to Scope Lock" button. Clicking it adds that cluster as a real, unsorted item on the Scope Lock Meeting Suite's Scope Boundary Board. Both tools already share the same browser origin, so this uses a small shared `localStorage` queue; no backend or database was needed. The item lands on Scope Lock's board the next time that tool is opened or refreshed, and re-sending the same cluster will not create a duplicate. Verified with a jsdom test that simulates both tools sharing one browser's storage.
+
## 2026-09-04
- Fixed: Portainer stack deploy failed with `env file /data/compose/44/.env not found`. Cause: `docker-compose.yml` used `env_file: - .env`, which requires a real file on disk; Portainer's UI-entered environment variables satisfy `${VAR}` substitution in the compose file but do not create that file. Changed `docker-compose.yml` to reference each setting as `${VAR:-default}` under `environment:` instead, which works both for a real local `.env` (auto-loaded by Compose for substitution) and for values entered directly in Portainer. Corrected the wrong explanation of this in `PORTAINER_DEPLOY.md`.
diff --git a/README.md b/README.md
index d5998b3..168a189 100644
--- a/README.md
+++ b/README.md
@@ -99,6 +99,18 @@ The two tools store data in different ways.
1. Click Export in the tool to create a durable record.
2. Save the exported file to your computer or to a shared drive.
+## How the tools work together
+
+Each tool's header has a link to the other tool.
+
+The Field Problem Workshop can send a cluster to the Scope Lock Meeting Suite.
+
+1. Tag a cluster with a candidate solution, for example "Tracking MVP (pilot)".
+2. Click "Send to Scope Lock" on that cluster.
+3. Open the Scope Lock Meeting Suite. The cluster appears as a new, unsorted item on the Scope Boundary Board.
+
+The send action stores the item in the browser's local storage. Both tools must run from the same server address for this to work. Sending the same cluster twice does not create a duplicate item.
+
## Reset a tool
Each tool has a Reset control.
diff --git a/tools/field-problem-workshop.html b/tools/field-problem-workshop.html
index 1e89cc4..4319b4f 100644
--- a/tools/field-problem-workshop.html
+++ b/tools/field-problem-workshop.html
@@ -24,7 +24,7 @@
header .brand span{color:#c6c6c6; font-weight:400;}
header .spacer{flex:1;}
.persist-note{font-size:12px; color:#c6c6c6;}
- .hdr-btn{background:transparent; color:#fff; border:1px solid #6f6f6f; padding:7px 13px; font-size:13.5px;}
+ .hdr-btn{background:transparent; color:#fff; border:1px solid #6f6f6f; padding:7px 13px; font-size:13.5px; text-decoration:none; display:inline-block;}
.hdr-btn:hover{background:#353535;}
.hdr-btn.primary{background:var(--interactive); border-color:var(--interactive);}
.hdr-btn.primary:hover{background:var(--interactive-hover);}
@@ -181,6 +181,7 @@
Project SDE| Field Problem Workshop v5
State lives in this session. Save JSON before closing.
+ Scope Lock Meeting Suite →
@@ -388,6 +389,26 @@ function clusterById(id){ return S.clusters.find(c=>c.id===id); }
function membersOf(cid){ return S.problems.filter(p=>p.cluster===cid); }
function activeMembers(cid){ return S.problems.filter(p=>p.cluster===cid && p.type==='Problem'); }
+/* ================= HANDOFF TO SCOPE LOCK ================= */
+// Shared localStorage queue that the Scope Lock Meeting Suite reads on load.
+// Both tools are served from the same origin, so this works with no backend.
+const SCOPE_HANDOFF_KEY = 'sde_scope_handoff_v1';
+function sendToScopeLock(c){
+ let queue = [];
+ try{
+ const raw = localStorage.getItem(SCOPE_HANDOFF_KEY);
+ if(raw) queue = JSON.parse(raw);
+ if(!Array.isArray(queue)) queue = [];
+ }catch(e){ queue = []; }
+ queue.push({
+ id: 'ws_' + c.id,
+ t: c.ws,
+ note: c.root || c.name || '',
+ sentAt: Date.now()
+ });
+ try{ localStorage.setItem(SCOPE_HANDOFF_KEY, JSON.stringify(queue)); }catch(e){}
+}
+
document.querySelectorAll('nav button').forEach(b=>{
b.addEventListener('click', ()=>{
document.querySelectorAll('nav button').forEach(x=>x.classList.remove('active'));
@@ -474,6 +495,7 @@ function renderMap(){
${mem.length} issue${mem.length===1?'':'s'}${c.ws?' · '+esc(c.ws):''}
${c.promoted?'✓ In Breadcrumbs':``}
+ ${c.ws ? (c.sentToScope ? '✓ Sent to Scope Lock' : ``) : ''}