This tutorial prepares the palmerpenguins repository for project memory: who authors facts, which project they belong to, and how a later session finds them. Later coding-memory tutorials build on it.
Complete Tutorial 00, Tutorial 01, and Tutorial 02 first.
The word appears in three places. They are related but not the same thing:
demo folder.Workspace is a node in the store that groups projects, one level above a project in the scope chain of §3.[workspace.<name>] entry in ~/.loom/stores.toml that tells this computer which store holds coding memory for one workspace. §4 adds one only if you choose to.loom_demo the session defaultloom_demo and make it the default for this session only. Confirm the effective session default, and do not edit ~/.loom/stores.toml.loom_demo store and changes only this session's default.loom_demo is now the default for this session. Persistent configuration was not changed.Continue in the palmerpenguins repository you opened in Tutorial 00. If it is not the current harness workspace, return to Tutorial 00 and complete its first step.
The repository says which work a memory belongs to; the store says where it is kept. Verify both before creating facts so later sessions read from the same place.
loom_demo. It reports what the store says now rather than assuming earlier counts.palmerpenguins/, bundled CSV files are under palmerpenguins/data/, and tests are under tests/. loom_demo is the session's practice store; its description confirms the coding domain and that the store is reachable.If loom_demo is missing, sign in again with durmem login (for a private server, durmem login --base https://durmem.ai) and stop here if it is still missing. Do not use an unrelated store just because its name looks close.
loom_demo for tutorial changes.loom_demo branch without changing a remote branch.loom_demo branch is ready. Git will record source changes; the loom_demo store will hold durable agent memory about the work.durmem attributes every fact to a real author, so a shared store stays trustworthy when several developers use it. The author identity comes from git, not from a name you type.
GitUser exists in loom_demo so my facts can be attributed to it. Create it if it is missing.git config user.email, then saves GitUser("<that email>") in loom_demo. If the node already exists, the save returns the same fact rather than a duplicate, so rerunning this step is safe.git config user.email returned dev1@gmail.com. GitUser("dev1@gmail.com") exists in loom_demo. This is masked sample output; in your run, the node and every author edge use the email git actually returned.An edge can point only to a node that already exists, which is why the identity node comes before any fact that names its author.
Saving a fact that already exists returns the existing fact and leaves its original author unchanged. If a tutorial fact was saved earlier under another author, the agent should say so rather than claim it was re-attributed.
If git config user.email is empty, belongs to a CI system, or is otherwise not the identity you intend, fix it before saving anything. A wrong email creates a second author that never matches your real history.
Tutorial 01 recalled memory by naming a project, and that is all a first recall needs. Coding work benefits from more structure: a fact about one repository should also see the rules that apply to its whole project or organization. durmem does this with a scope chain of four nodes, each PartOf the next:
Repo("palmerpenguins")
PartOf → Project("palmerpenguins")
PartOf → Workspace("palmerpenguins")
PartOf → Organization("loom-tutorials")A fact is filed at one node with an InScope() edge. A read at a node also includes facts filed at its ancestors, so a repository-level read sees project-, workspace-, and organization-wide facts. Reads follow PartOf upward only: reading at Organization("loom-tutorials") does not return facts filed under the project below it. File each fact at the narrowest node that fits, and read from the node where you are working.
loom_demo, make sure Repo("palmerpenguins") exists and is PartOf Project("palmerpenguins"), which continues through Workspace("palmerpenguins") to Organization("loom-tutorials"). Verify the complete chain.PartOf link. It adds a missing link to an existing node directly, because saving the node again would not add the link. Finally it reads the chain back.Repo("palmerpenguins") → Project("palmerpenguins") → Workspace("palmerpenguins") → Organization("loom-tutorials") (created on a first run; unchanged on a rerun).Then tell future sessions where they are. Without this, a new agent may infer the repository name but miss the project, workspace, and organization, and its automatic reads would return only repository context:
loom-scope: project=palmerpenguins workspace=palmerpenguins org=loom-tutorials to this repository's existing root agent guidance. If none of AGENTS.md, CLAUDE.md, or CODEX.md exists at the root, create AGENTS.md containing only that line.loom-scope line.loom_demoSo far each tutorial session has started with a prompt that makes loom_demo the session default. A workspace mapping makes that choice persistent for this one workspace. It is an explicit opt-in that edits your private ~/.loom/stores.toml. It is optional for ordinary coding, but the hook exercise in Tutorial 06 requires it, so do it before that tutorial; otherwise keep the per-session prompt.
~/.loom/stores.toml, add or update only [workspace.palmerpenguins] with loom-coding = "loom_demo". Do not change the top-level default or any other mapping, and do not show me the file's contents.palmerpenguins workspace now goes to loom_demo in future sessions. The top-level default and other mappings are unchanged.To undo it, ask the agent to remove only that [workspace.palmerpenguins] entry.
Before saving project facts, ask for a bounded view of the whole store. It shows both the data you expected and anything you did not know was there, without letting one large type flood the answer.
loom_demo, display up to 5 current items for every populated type in this store.Decision (2):
- small reviewed tutorial changes before live deploys
- use the existing notification service for invitation emails
Directive (2):
- ask before pushing origin main
- keep access bundles local
GitUser (1):
- dev1@gmail.com
Goal (1):
- ship a private beta by September 30 [critical]
Organization (1):
- loom-tutorials
Project (3):
- durmem practice notebook
- loom_demo
- palmerpenguins
Repo (1):
- palmerpenguins
Roadmap (2):
- finish invitation emails before the beta [done]
- publish runnable onboarding demo for new agents [in_flight]
Workspace (1):
- palmerpenguinsRead this as "the store includes at least these", not as an exact report. The Directives, the onboarding Roadmap item, and the reviewed-changes Decision are sample facts the store started with, under Project("loom_demo"). The Goal, the invitation-email items, and durmem practice notebook come from Tutorial 01. The identity and scope nodes come from §2 and §3. Counts grow as you work through later tutorials, and a rerun shows facts from earlier passes.
This view shows only populated types. Tutorial 04 shows the full list of declared types, including ones with no facts yet. To see only one project's facts, ask for that project explicitly.
Workspace node, and an optional stores.toml mapping.git config user.email, never from a typed-in name.Repo -> Project -> Workspace -> Organization chain lets a read include facts from wider scopes. File each fact at the narrowest node that fits.