7.3 KiB
Roadmap: One Unified Tool with a Backing Database
This is a plan, not code yet. It sets direction for merging the Field Problem Workshop and the Scope Lock Meeting Suite into one tool, backed by a database. Decisions already made: a separate, lightweight database for this toolkit (not shared with the Work Package Suite), and a single-facilitator-at-a-time model (no real-time multi-user sync).
Why integrate at all
Today the two tools do not connect. Each holds its own state in the browser, and a person carries results from one into the other by hand. The one piece of real evidence that they are meant to connect: four of the seven baseline clusters in the Field Problem Workshop already carry a candidate-solution tag, for example "Tracking MVP (pilot)" on the Progress Visibility cluster, and "AWP Process RFP" on two others. That tag is exactly the kind of item the Scope Lock Meeting Suite sorts into In MVP, Later Phase, Out, or Parking Lot. A database turns that tag from a note into a real link.
A database also gives you two things the current JSON-file model cannot: a history of every session ever run, not just the one currently loaded, and the ability to query and report across sessions instead of opening files one at a time.
Target shape
One backend, one database, two frontends that call it instead of holding state locally. A "pilot" or "project" record ties a Workshop session to its paired Scope Lock session, so the link that exists today only as a text tag becomes a real relationship.
Data model
SQLite is enough for this scale (a handful of sessions a month, one facilitator at a time). No separate database server to run or patch.
projects
id, name, created_at
-- e.g. "Micron EUV"
workshop_sessions
id, project_id -> projects.id, name, created_at, facilitator_user
clusters
id, workshop_session_id -> workshop_sessions.id, name, description, candidate_solution
-- candidate_solution is today's free-text tag ("Tracking MVP (pilot)")
problems
id, cluster_id -> clusters.id, text, votes
breadcrumbs
id, cluster_id -> clusters.id, type, driver, cap, metric, method, baseline, ai_drafted (bool)
actions
id, workshop_session_id -> workshop_sessions.id, text, owner, due_date, done
scope_sessions
id, project_id -> projects.id, name, created_at, facilitator_user
scope_items
id, scope_session_id -> scope_sessions.id, name, column
-- column is one of: unsorted, in_mvp, later_phase, out, parking_lot
source_cluster_id -> clusters.id, nullable
-- set when an item was promoted from a Workshop cluster's candidate_solution tag,
-- instead of typed fresh into the Scope Lock board
priority_rank
scope_item_id -> scope_items.id, rank
decisions
id, scope_session_id -> scope_sessions.id, text, decided_at, decided_by
readiness_checks
id, scope_session_id -> scope_sessions.id, item, status, notes
source_cluster_id is the whole point of unifying these tools. Today, someone reads "Tracking MVP (pilot)" off the Workshop screen and retypes it into the Scope Lock board. With this link, the Scope Lock session can offer a "Promote from Workshop" action that lists every cluster carrying a candidate-solution tag from the paired Workshop session, and creates a scope_item with source_cluster_id set. From then on, the scope item and the breadcrumb evidence that justified it are one clickable hop apart, not two separate exports.
API surface
A REST endpoint per resource above: list, get, create, update, delete. A few extras beyond plain CRUD:
POST /api/scope-items/promote— body:{cluster_id}. Creates a scope item pre-filled from that cluster's name and candidate-solution tag.GET /api/projects/:id/summary— pulls both sessions' data together for a single export, replacing the two separate "Export summary" buttons with one that shows the full picture: problems, breadcrumbs, and the scope decisions made from them.- The existing
/api/claudeproxy carries over unchanged. It has nothing to do with persistence.
Reuse the login already built (APP_USERS) to identify facilitator_user and decided_by. No new auth work needed.
Frontend approach
Both tools are single HTML files that hold state in a JS object and re-render on every change. The lowest-risk migration keeps that shape and swaps what backs it:
- On page load, fetch the current session's data from the API instead of reading
DEFAULT_STATEorlocalStorage. - Replace the existing
save()function's body. Today it writes to memory orlocalStorage. It should instead call the matching API endpoint (PATCH /api/breadcrumbs/:id, and so on) and update local state from the response. - Keep Save JSON / Load JSON / Export summary as import-export conveniences around the database, not as the primary way data survives. They are useful for taking a copy of a session offline, or seeding a new session from an old export.
This avoids a full rewrite of the rendering code, which is most of both files. It touches the data-access edges, not the UI.
Migration path for existing data
- Write a one-time import script that reads an exported Workshop JSON file (the July 21 baseline, for example) and inserts it as a
workshop_sessionwith its clusters, problems, breadcrumbs, and actions. - Do the same for any Scope Lock exports.
- From then on, new sessions are created through the app, not by hand-editing JSON.
Phased rollout
- Schema and API, no UI change. Stand up SQLite, the tables above, and the CRUD endpoints. Test with curl or a REST client. Nothing user-facing changes yet.
- Migrate the Field Problem Workshop's data access to the API, per the frontend approach above. Verify Save JSON / Load JSON / Export summary still work, now reading from and writing to the database.
- Migrate the Scope Lock Meeting Suite the same way.
- Build the actual link: the
source_cluster_idfield, the "Promote from Workshop" action, and the combined project summary export. This is the step that turns two tools into one. - Add a project/session list view: a simple page listing every project and its paired sessions, since the database now holds more than the one session someone currently has open. This is the first piece of value a database gives you that a JSON file never could.
- Later, if it comes up: multi-user real-time editing (websockets), re-enabling the per-user token quota now scoped to real sessions instead of just a daily counter, or a tighter identity integration than the shared-credential login.
Open decisions for you
- Naming: is "project" the right top-level container, or should it be "pilot," matching the language already in the Scope Lock export ("Pilot: Micron")? Pick the word the team already uses out loud.
- Multiple concurrent projects: the schema above supports more than one project at a time (Micron plus whatever comes after it). Confirm that is wanted, versus a model that assumes only one active pilot at a time.
- Where the SQLite file lives in Docker: the same volume-mount pattern already used for
data/token-usage.jsonindocker-compose.ymlworks for a database file. No new infrastructure decision needed there. - Who builds this: this is a multi-week effort, not an afternoon change, given two 800-plus line HTML files need their data-access layer reworked. Decide whether that is you, a broader team effort, or something to scope out to whoever ends up owning the Work Package Suite integration work too.