galaxyproject / galaxyproject/loom
Orbit: stash project context in the Galaxy history so another instance can resume the analysis
- Dominant language
- TypeScript
- Stars
- 14
- Forks
- 12
- Avg merge
- 6d 5h
- Merged PRs (30d)
- 17
Description
## Why
The notebook.md / activity.jsonl in the local project directory is today the only durable record of *why* a Galaxy workflow was invoked — the plan, the decisions, the routing rationale. If the user moves to a different machine, deletes the project dir, or just opens Orbit fresh, they see the Galaxy histories with their datasets but no narrative connecting them. Reconstructing the analysis means rereading workflow XML and guessing intent.
Galaxy histories are the most stable, server-side artifact in the Loom workflow. They survive local disk wipes and follow the user's account. Storing the project context **inside the history** lets a second Orbit instance pick up where the first left off, given only Galaxy credentials.
## Proposal
When Orbit submits a workflow invocation (or modifies a notebook with active invocations), upload a small **\`.loom-context\`** dataset into the same Galaxy history. Two flavors:
- \`.loom-context.md\` — a copy of \`notebook.md\` head + tail, for human reading inside Galaxy.
- \`.loom-context.json\` — structured payload for machine consumption: project id, plan list, invocation map, last-modified timestamp, schema version.
A second Orbit, on the same Galaxy account, scans recent histories at startup; any history with a \`.loom-context.json\` dataset offers a **\"Resume {project label}\"** affordance in the welcome screen. Clicking creates a local project dir with the recovered notebook + activity stub and a pinned reference to the Galaxy history.
## When to write
Trigger options, ranked by safety:
- **A. Per-invocation**: on \`galaxy_invocation_record\`, write/update the context dataset in the same history. Highest fidelity, also highest churn (a 5-step plan = 5 uploads).
- **B. Per-plan-approval + per-status-change**: write on plan approval and on every \`galaxy_invocation_check_all\` rollup transition. Lower frequency, captures the milestones.
- **C. Periodic (15-min idle timer)**: stash a snapshot if notebook.md changed since the last stash. Lowest churn, eventual consistency.
Recommend **B** for v1. **A** is too noisy; **C** loses recent edits if the local machine dies.
## Project identity
We need a stable \"project id\" so multiple histories (one per plan, perhaps) can be grouped, and so a Resume operation can find them all.
Generate a UUID at notebook init, persist as a YAML front-matter block at the top of \`notebook.md\`:
\`\`\`markdown
---
loom_project_id: 8e9c2a4b-6d1f-4a72-9c0e-3b5f7e8d9a01
loom_project_label: NY rats SARS-CoV-2 variant calling
created_at: 2026-04-30T12:00:00Z
---
\`\`\`
Embed the same \`loom_project_id\` in every \`.loom-context.json\` dataset and in dataset tags so Galaxy's history list / dataset search can find them.
## Discovery flow (second Orbit)
1. User opens Orbit on a fresh machine, connects to Galaxy.
2. Orbit lists histories modified in the last N days.
3. For each, look for datasets named \`.loom-context.json\` (or a tag like \`loom:project:\`).
4. Group by \`loom_project_id\` → present as \"Resume\" candidates in the welcome modal: project label, last touched, # of invocations.
5. User picks one → Orbit downloads \`.loom-context.md\` + \`.loom-context.json\`, creates a local cwd, hydrates \`notebook.md\` + \`activity.jsonl\` stub, sets \`loom_project_id\` in the front-matter.
6. From here Orbit operates normally — galaxy_invocation_check_all sees the history's existing invocations and resumes polling.
## Schema sketch (\`.loom-context.json\` v1)
\`\`\`json
{
\"loom_context_schema\": 1,
\"project_id\": \"8e9c2a4b-...\",
\"project_label\": \"NY rats SARS-CoV-2 variant calling\",
\"created_at\": \"2026-04-30T12:00:00Z\",
\"last_updated_at\": \"2026-04-30T18:42:00Z\",
\"galaxy_history_id\": \"f2db41e1fa331b3e\",
\"plans\": [
{
\"label\": \"chrM Variant Calling\",
\"status_tag\": \"hybrid\",
\"invocation_ids\": [\"inv-abc123\", \"inv-def456\"]
}
],
\"notebook_excerpt\": \"...head + tail of notebook.md, capped at 8 KB...\",
\"orbit_version\": \"0.1.0\"
}
\`\`\`
## Privacy + security
- Galaxy histories are private by default but the user may share them. The context dataset will follow whatever permissions the history has.
- Strip any path-shaped strings that look like \`/home//...\` before upload — they leak local username + project layout.
- Strip any text that matches API-key-shaped patterns (defense in depth — they shouldn't be in the notebook anyway).
- Document explicitly in the Preferences UI that enabling this feature uploads notebook excerpts to Galaxy.
## Out of scope for v1
- **Two-way sync** (editing the context dataset in Galaxy and pulling it back). The local notebook is authoritative; the Galaxy stash is a one-way snapshot.
- **Conflict resolution** between two concurrent Orbit sessions on the same project — declare last-write-wins; surface the timestamp.
- **Encrypting the context dataset** — Galaxy permissions are the trust boundary.
## Files
- \`extensions/loom/notebook-writer.ts\` — front-matter \`loom_project_id\` insertion + reader.
- \`extensions/loom/galaxy-context-stash.ts\` (new) — build payload, upload via Galaxy MCP, find existing context datasets.
- \`extensions/loom/tools.ts\` — wire to plan-approval and check_all status-change hooks.
- \`app/src/renderer/welcome.ts\` (or app.ts) — \"Resume from Galaxy history\" affordance in the welcome modal.
## Verification
End-to-end smoke:
1. Run a plan that invokes a Galaxy workflow. Confirm \`.loom-context.json\` and \`.loom-context.md\` appear in the same history.
2. Open Orbit on a different cwd, click \"Resume...\" in welcome → pick the project → verify notebook.md is recreated with project_id front-matter and the prior invocation YAML blocks.
3. Kick off a follow-up plan from the resumed state; verify the existing history is reused.
## Related
- #67 (live invocation progress) — same theme: leverage the Galaxy server as a continuity surface.
- #21 (session bootstrap resume/new/review) — the welcome-modal piece dovetails with this.
Contributor guide
No contributing guide indexed for this repository
Assessment
This issue has not been assessed yet.