Weave
Weave maintains a private, provenance-backed social graph of people, relationships, preferences, and shared experiences — queryable for meeting prep, gift ideas, hosting, introductions, city connections, and serendipity discovery. Every stored fact carries source type, reference, timestamp, and confidence score; the graph never silently merges two person records and never writes back to external systems without explicit per-sync approval. All queries use Cypher — no SQL. The database initializes automatically on first use.
When to use
- Store or update information about a person, relationship, or preference
- Look up who someone is, how they relate to others, or what they like
- Prepare for a meeting, dinner, or introduction
- Find who you know in a given city
- Generate gift ideas grounded in known preferences
- Discover serendipity connections between people
- Sync contacts from Google Contacts or Clay
When not to use
- Web research without a social graph need — use Sift
- OSINT investigations on people — use Scout
- CRM or sales pipeline automation
- Personality profiling without evidence
Responsibility boundary
Weave owns the private social graph: people, relationships, preferences, and shared experiences.
Weave does not own: general world knowledge (Elephas/Chronicle), OSINT research (Scout), web research (Sift), task management (Triage).
Weave is a standalone database. It does not write to Chronicle and has no runtime dependency on Chronicle. If a person in Weave also exists in Chronicle, Chronicle may store a weave:person_id reference on its Entity node. That is Chronicle's concern, not Weave's.
Storage layout
~/openclaw/db/ocas-weave/
weave.lbug — LadybugDB database (auto-created on first use)
config.json — connector and sync configuration
staging/ — temporary import/export files
~/openclaw/journals/ocas-weave/
YYYY-MM-DD/
{run_id}.json — one journal per run
Default config.json:
{
"skill_id": "ocas-weave",
"skill_version": "2.3.0",
"config_version": "1",
"created_at": "",
"updated_at": "",
"writeback": {
"google_contacts": false,
"clay": false
},
"last_sync": {
"google_contacts": null,
"clay": null
},
"retention": {
"days": 0
}
}
Database rules
LadybugDB is an embedded single-file database. One READ_WRITE process at a time. If another process holds the lock, operations fail immediately with a lock error — do not retry silently, surface the error.
Multiple READ_ONLY connections are safe simultaneously. COPY FROM is for bulk import (>100 rows). MERGE is for sporadic single-record upserts. Never loop MERGE over bulk data.
Auto-initialization
Every command that opens the database runs _ensure_init() first. No manual init command is needed on first use.
Read references/init_pattern.md for the _open_db implementation pattern. Full DDL is in references/schemas.md.
Commands
weave.upsert.person -- Add or update a person. Auto-inits DB on first call. MERGE on id. Read back after write; report failure if no row returned — never claim success unconfirmed.
weave.upsert.relationship -- Add or update a Knows edge. Confirm both Person nodes exist first. Halt and report which is missing.
weave.upsert.preference -- Store a provenance-backed preference. Each preference is a distinct CREATE (not merged). Link to Person via HasPreference edge.
weave.import.csv -- Bulk import contacts via COPY FROM. Read references/import_export.md. Pre-process CSV to staging dir first. Check CALL show_warnings() RETURN * after. Report: N imported, N skipped (with reasons), N failed.
weave.query -- Query the graph. Read references/query_patterns.md. Modes: lookup, connection, serendipity, city, summarize, gift. Return only stored facts with provenance. Never speculate.
weave.attach -- Query an external skill database read-only. Read references/cross_db.md.
weave.export -- Export data to staging dir via COPY TO. Read references/import_export.md.
weave.sync.google-contacts -- Bidirectional sync with Google Contacts. Read references/connectors.md. Inbound before outbound. Outbound requires writeback.google_contacts: true AND explicit per-sync approval.
weave.sync.clay -- Bidirectional sync with Clay. Read references/connectors.md. Clay is enrichment source — Weave provenance wins conflicts. Outbound requires writeback.clay: true AND explicit approval.
weave.project.vcard -- Generate vCard 4.0 draft. Read references/vcard_projection.md. Omit fields with confidence below 0.7. Label DRAFT. Requires explicit approval before writeback.
weave.writeback.contacts -- Push records to Google Contacts or Clay. Disabled by default. Requires config enablement AND per-action user approval.
weave.init -- Diagnostic and repair command. Checks schema, creates missing tables, verifies indexes. Use when troubleshooting, not as a prerequisite — the database initializes automatically on first use.
weave.status -- Report graph health and config state.
CALL show_tables() RETURN *;
MATCH (p:Person) RETURN count(p) AS people;
MATCH ()-[r:Knows]->() RETURN count(r) AS relationships;
MATCH (pref:Preference) RETURN count(pref) AS preferences;
CALL show_warnings() RETURN *;
weave.journal -- Write journal for the current run. Read references/journal.md. Called at end of every run. Journals are immutable after write.
weave.update -- Pull latest skill package from GitHub source. Preserves journals and data.
Run completion
After every Weave command that reads or writes data:
- Persist any new or updated records to the database
- Log material decisions to
decisions.jsonl
- Write journal via
weave.journal — Observation Journal for queries/upserts/imports, Action Journal for syncs/writebacks
Provenance
Every written fact requires: source_type (direct / inferred / imported / user-stated), source_ref, record_time (ISO 8601), confidence (0.0–1.0). Use event_time when the real-world occurrence has a distinct time. Never write facts without provenance.
Constraints
- Never use SQL.
- Never report a write as successful before read-back confirms it.
- Never parse or modify
.lbug, .wal, .shadow, or .tmp files directly.
- Never write to Chronicle or any other skill's database.
- Never silently collapse two Person records into one.
- Use ontology standard relationship types in
Knows.rel_type.
- Store useful, durable, socially actionable facts only.
- No outbound sync without explicit per-sync user approval.
- Surface lock errors immediately.
- Write a journal at the end of every run. Runs missing journals are invalid.
OKRs
Universal OKRs from spec-ocas-journal.md apply. Weave-specific:
skill_okrs:
- name: person_record_completeness
metric: fraction of Person nodes with name + (email or phone) + record_time
direction: maximize
target: 0.80
evaluation_window: 30_runs
- name: sync_success_rate
metric: fraction of sync runs with zero failed records
direction: maximize
target: 0.90
evaluation_window: 30_runs
- name: import_skip_rate
metric: fraction of imported rows skipped due to missing required fields
direction: minimize
target: 0.05
evaluation_window: 30_runs
- name: query_provenance_coverage
metric: fraction of returned facts carrying source_ref and record_time
direction: maximize
target: 1.0
evaluation_window: 30_runs
Optional skill cooperation
- Elephas — read Chronicle read-only for entity enrichment (optional, degrades gracefully if absent)
- Scout — receive OSINT findings about people as upsert candidates
- Dispatch — provide social graph context for communication drafting
Journal outputs
- Observation Journal — query runs, upsert runs, import runs
- Action Journal — sync runs, writeback runs
Initialization
On first invocation of any Weave command, _open_db() handles auto-initialization:
- Create
~/openclaw/db/ocas-weave/ and subdirectories (staging/)
- Write default
config.json with ConfigBase fields if absent
- Create
~/openclaw/journals/ocas-weave/
- Open database (auto-creates
weave.lbug and runs DDL if tables absent)
- Register cron job
weave:update if not already present (check openclaw cron list first)
- Log initialization as a DecisionRecord
Background tasks
| Job name | Mechanism | Schedule | Command |
|---|
weave:update | cron | 0 0 * * * (midnight daily) | weave.update |
openclaw cron add --name weave:update --schedule "0 0 * * *" --command "weave.update" --sessionTarget isolated --lightContext true --timezone America/Los_Angeles
Self-update
weave.update pulls the latest package from the source: URL in this file's frontmatter. Runs silently — no output unless the version changed or an error occurred.
- Read
source: from frontmatter → extract {owner}/{repo} from URL
- Read local version from
skill.json
- Fetch remote version:
gh api "repos/{owner}/{repo}/contents/skill.json" --jq '.content' | base64 -d | python3 -c "import sys,json;print(json.load(sys.stdin)['version'])"
- If remote version equals local version → stop silently
- Download and install:
TMPDIR=$(mktemp -d)
gh api "repos/{owner}/{repo}/tarball/main" > "$TMPDIR/archive.tar.gz"
mkdir "$TMPDIR/extracted"
tar xzf "$TMPDIR/archive.tar.gz" -C "$TMPDIR/extracted" --strip-components=1
cp -R "$TMPDIR/extracted/"* ./
rm -rf "$TMPDIR"
- On failure → retry once. If second attempt fails, report the error and stop.
- Output exactly:
I updated Weave from version {old} to {new}
Visibility
public
Support file map
| File | When to read |
|---|
references/schemas.md | Before any DDL, upsert, or import; before weave.init |
references/init_pattern.md | When implementing _open_db or troubleshooting initialization |
references/query_patterns.md | Before any weave.query call |
references/import_export.md | Before any COPY FROM or COPY TO operation |
references/cross_db.md | Before any weave.attach call or Chronicle enrichment query |
references/connectors.md | Before any sync with Google Contacts or Clay |
references/vcard_projection.md | Before weave.project.vcard |
references/journal.md | Before weave.journal; at end of every run |