diff --git a/.source-references/goldbrain-memory.plugin b/.source-references/goldbrain-memory.plugin index 5d11de5..ef2b28e 100644 Binary files a/.source-references/goldbrain-memory.plugin and b/.source-references/goldbrain-memory.plugin differ diff --git a/GOLDBRAIN ISSUE TRACKER.txt b/GOLDBRAIN ISSUE TRACKER.txt new file mode 100644 index 0000000..fea398a --- /dev/null +++ b/GOLDBRAIN ISSUE TRACKER.txt @@ -0,0 +1,19 @@ +Just a small bug report on Goldbrain, not critical but could surface elsewhere: Bug: PATCH Target header fails when heading contains an em dash (—) +Endpoint: PATCH /vault/projects/active/earthdnd-personal.md +Reproduction: +The file contains a top-level heading: + +# EarthDnD — Personal Project + +A subheading target using the full :: path fails: + +Target: EarthDnD — Personal Project::AI Platform Roles + +Error returned: + +{ "message": "The patch you provided could not be applied to the target content.\ninvalid-target", "errorCode": 40080 } + +What works: PATCH succeeds on headings with no special characters (e.g., Target: AI Platform Roles on a file where that H2 exists at the top level, or Target: EarthDnD::AI Platform Roles if the H1 used a regular hyphen). +Workaround currently in use: GET the full file → edit content in memory → PUT the entire file back. This is reliable but overwrites atomically rather than patching in place, which creates a race condition risk on frequently-written files. +Suspected cause: The em dash (—, U+2014) in the heading path is either not being URL/header decoded correctly before the heading lookup, or the heading-matching regex doesn't treat it as a valid character. Parentheses in heading names have caused the same error in testing, suggesting the parser may be applying regex-special-character rules to the target string without escaping. +Request: Support em dash and parentheses in Target heading paths, or document a percent-encoding workaround (e.g., EarthDnD%20%E2%80%94%20Personal%20Project::AI%20Platform%20Roles) if that's the intended escape mechanism. \ No newline at end of file diff --git a/goldbrain-memory.plugin b/goldbrain-memory.plugin new file mode 100644 index 0000000..ef2b28e Binary files /dev/null and b/goldbrain-memory.plugin differ diff --git a/goldbrain-memory.src/.claude-plugin/plugin.json b/goldbrain-memory.src/.claude-plugin/plugin.json new file mode 100644 index 0000000..8d50077 --- /dev/null +++ b/goldbrain-memory.src/.claude-plugin/plugin.json @@ -0,0 +1,15 @@ +{ + "name": "goldbrain-memory", + "version": "0.2.0", + "description": "Persistent memory via the goldbrain Obsidian vault over the Local REST API. Reads and writes notes across Claude/CoWork sessions using direct REST calls — no MCP server required. Defers to the vault's own control docs for structure. v0.2 adopts the ECHO procedural model: parallel context loading, search-before-write, append idempotency, project lifecycle (incubating/active/on-hold/archived), scope switching, monthly vault health, a resilient daily Agent Log, and em-dash/parenthesis-safe PATCH targeting. Bryan Gilliom's memory vault.", + "author": { + "name": "Jason" + }, + "keywords": [ + "memory", + "obsidian", + "notes", + "persistence", + "goldbrain" + ] +} diff --git a/goldbrain-memory.src/README.md b/goldbrain-memory.src/README.md new file mode 100644 index 0000000..79dfc3b --- /dev/null +++ b/goldbrain-memory.src/README.md @@ -0,0 +1,72 @@ +# goldbrain-memory + +Persistent memory for Claude via the **goldbrain** Obsidian vault, using the [Obsidian Local REST API](https://github.com/coddingtonbear/obsidian-local-rest-api). + +Reads and writes notes across Claude/CoWork sessions using direct REST calls — no MCP server required. Built for **Bryan Gilliom** (CEO, Message Point Media) as the primary operator; Jason is the vault architect. + +## What it does + +- Loads operator preferences, current context, and relevant project notes at the start of substantive conversations (parallel cold-start reads) +- Writes facts, preferences, and decisions Bryan asks Claude to remember — searching first so it updates rather than duplicates +- Manages project lifecycle (`incubating → active → on-hold/archived`) with folder/`status:` agreement +- Tracks scope switches, triages the inbox, and runs a monthly vault-health pass +- Logs working sessions so future conversations can pick up where they left off +- Defers to the vault's own `BOOTSTRAP.md`/`CLAUDE.md`/`STRUCTURE.md` for structure and the operating contract + +## What's new in 0.2 + +Adopts the procedural model from Jason's ECHO plugin (v0.5) while keeping goldbrain's in-vault control docs as the source of truth: + +- Parallel context loading, **search-before-write**, and **append idempotency** (no more duplicate log lines) +- Project lifecycle folders and the folder/`status:` agreement rule +- **Scope switching** with a rolling Scope History, **inbox triage**, and a monthly **vault-health** check +- A **resilient daily Agent Log** routine that auto-creates the note/heading and avoids duplicate headings +- `operator-preferences.md` split into promoted **Fact / Pattern** rules vs. timestamped **Observations** +- **Em-dash / parenthesis bug fix:** heading PATCH targets now percent-encode special characters (em dash → `%E2%80%94`), with a GET→edit→PUT fallback and an ASCII-heading prevention rule + +## Configuration + +The plugin is hardcoded for: + +- **Server:** `https://goldbrainapi.mpm.to` (reverse proxy → Obsidian Local REST API on `192.168.86.15:27124`) +- **API Key:** stored in the skill (personal plugin, not for distribution) + +The endpoint presents a **valid TLS certificate**, so `-k` is not required. The bearer key lives only in the plugin — never inside the vault (per the vault's own safety rules). + +## Vault layout (root-addressed) + +``` +/vault/ +├── CLAUDE.md STRUCTURE.md BOOTSTRAP.md spinup.md index.md README.md +├── inbox/ (captures, imports, processing-log) +├── journal/ (daily, weekly, monthly, templates) +├── projects/ (active, incubating, on-hold, archived) +├── areas/ (business, personal, learning, systems) +├── resources/ (concepts, references, people, meetings, source-material) +├── decisions/ (by-date, by-project) +├── reviews/ (weekly, monthly, quarterly, annual) +├── archive/ (notes, projects, imports) +└── _agent/ + ├── context/ ← task-scoped context bundles + ├── memory/ ← working / episodic / semantic + ├── sessions/ ← YYYY-MM-DD-HHMM-.md + ├── templates/ ← canonical note templates + ├── outputs/ ← briefs / drafts / summaries / synthesis + ├── skills/ ← active / archived + └── heartbeat/ +``` + +## First run + +The vault ships its own `BOOTSTRAP.md`. On first use the skill reads `/vault/BOOTSTRAP.md`; if present it follows that preflight, and if absent (a fresh empty vault) it offers to bootstrap. + +## Skills + +| Skill | Triggers | +|-------|----------| +| `goldbrain-memory` | "remember that", "save to memory", "what do you know about me", "load my profile", "check my notes", "log this decision", "add to my inbox" — and proactively at the start of substantive conversations | + +## Requirements + +- Obsidian running on the backend with the [Local REST API plugin](https://github.com/coddingtonbear/obsidian-local-rest-api) enabled (binding host `0.0.0.0`) +- HTTPS access to `https://goldbrainapi.mpm.to` from the Claude/CoWork session environment diff --git a/goldbrain-memory.src/skills/goldbrain-memory/SKILL.md b/goldbrain-memory.src/skills/goldbrain-memory/SKILL.md new file mode 100644 index 0000000..9936b92 --- /dev/null +++ b/goldbrain-memory.src/skills/goldbrain-memory/SKILL.md @@ -0,0 +1,424 @@ +--- +name: goldbrain-memory +description: Use the goldbrain Obsidian vault as Bryan's persistent memory across Claude/CoWork sessions. Use whenever the operator asks to remember, save, note, log, or capture anything durable — facts, preferences, decisions, schedule changes, commitments — or asks what Claude knows about them, what was discussed or decided before, to check their notes, load their memory/profile/context, add to their inbox, or to track a new project. Trigger even without memory phrasing when the request implies recalling or persisting state across sessions ("pick up where we left off", "anything on X before my meeting?"). Also use proactively at the start of substantive work sessions to load context and at the end to log outcomes. Do NOT use for Jason's ECHO vault, Obsidian/REST-API development questions, "memory" meaning RAM, timed reminders, email or local-file lookups, or generic second-brain advice. +--- + +# Goldbrain Memory + +Use the **goldbrain** Obsidian vault as persistent memory. Read context accumulated across sessions; write things the operator asks to be remembered. + +The primary operator is **Bryan Gilliom** (CEO, Message Point Media). Unless stated otherwise, "the operator" means Bryan. Jason is the vault's architect, not the day-to-day user. Write memory in third person ("Bryan prefers X", not "I prefer X") so the vault stays readable by humans and other agents. + +## API Configuration + +All calls use these constants — hardcoded for this personal plugin: + +``` +OBSIDIAN_BASE = https://goldbrainapi.mpm.to +OBSIDIAN_KEY = fb72065a05fabb28ae87c45880cc3b7aba4fd3f58e70297934145cef974e8ed8 +``` + +The endpoint has a **valid TLS certificate**, so `-k` is not needed (add it only if the cert ever changes to self-signed). Always pass the `Authorization: Bearer` header. Paths address the vault **at its root** (e.g. `/vault/_agent/...`). + +**The goldbrain vault carries its own control docs.** Unlike Jason's ECHO vault, goldbrain keeps `CLAUDE.md` / `BOOTSTRAP.md` / `STRUCTURE.md` / `index.md` at the vault root, and those remain the canonical source of truth for the operating contract and structure. This plugin holds the day-to-day *procedure* (loading order, search-first, triage, scope switching, PATCH/append rules) and **defers** to the in-vault docs for the durable contract: + +- Operating contract, principles, and safety rules: the vault's `CLAUDE.md` +- Bootstrapping an empty vault and repair: `references/bootstrap.md` (which defers to the vault's `BOOTSTRAP.md`) +- Vault layout and frontmatter conventions: `references/vault-layout.md` (mirrors the vault's `STRUCTURE.md`) +- Full API reference with every endpoint pattern and the memory routing map: `references/api-reference.md` + +## Operating Contract & Safety + +The vault is the **system of record** for long-term memory, not a scratchpad. Default to **additive updates, explicit status changes, and traceable summaries**. Keep agent-managed content (`agent_written: true` + `source_notes`) separable from human-authored content. Non-negotiable safety rules: + +- Do not fabricate facts, relationships, or prior decisions. +- Do not mass-restructure the vault unless explicitly asked. +- Do not delete notes unless deletion is explicitly requested and clearly safe. +- Never store secrets or API keys inside a vault note. + +Full contract lives in the vault's `CLAUDE.md`. + +## When to Load Memory + +Load at the start of any substantive conversation — anything beyond a single quick factual question. The signal: the operator is starting work, planning, asking for help with something that has state, or referencing prior discussions. + +### Loading procedure + +The cold-start reads are independent — **issue them in parallel** (one batch of 4–5 GETs), not sequentially. Parallel loading is ~3× faster wall-clock for the same call count. + +| # | GET | Notes | +|---|-----|-------| +| 1 | `/vault/BOOTSTRAP.md` | The in-vault preflight/repair manifest. 404 → vault not set up; follow `references/bootstrap.md`. 200 → proceed (skim its checklist only if a structural path 404s later). | +| 2 | `/vault/_agent/memory/semantic/operator-preferences.md` | Bryan's profile | +| 3 | `/vault/_agent/context/current-context.md` | Active scope + Scope History | +| 4 | `/vault/_agent/sessions/` (listing) | Pick the ~5 most recent by reverse lex sort (filenames `YYYY-MM-DD-HHMM-.md`, so lex == chrono); only read the ones whose slugs look relevant | +| 5 | `/vault/journal/daily/YYYY-MM-DD.md` | Today's note; 404 is fine — it's created on first agent activity | + +Do not read every session log — older sessions are reachable via `POST /search/simple/?query=...` when needed. + +**If a specific project is in play**, follow up with a **search across all lifecycle subfolders** (`active/`, `incubating/`, `on-hold/`, `archived/`) — searching one folder at a time misses notes filed elsewhere. Search by **both the slug AND any human title** the operator used in this conversation: + +```bash +# slug +curl -s -X POST -H "Authorization: Bearer fb72065a05fabb28ae87c45880cc3b7aba4fd3f58e70297934145cef974e8ed8" \ + "https://goldbrainapi.mpm.to/search/simple/?query=" + +# human title (avoids missing notes filed under a different name) +curl -s -X POST -H "Authorization: Bearer fb72065a05fabb28ae87c45880cc3b7aba4fd3f58e70297934145cef974e8ed8" \ + "https://goldbrainapi.mpm.to/search/simple/?query=" +``` + +Then read whichever match lives at `projects//.md`. + +Do NOT narrate this loading. Reading memory is expected behavior. + +## Inbox Triage + +`inbox/captures/inbox.md` is the catch-all for "save this somewhere — figure out where later." Without triage it grows forever and durable facts get stranded there. + +At the start of a substantive session, GET `inbox/captures/inbox.md`. If it contains lines older than ~7 days that haven't been routed elsewhere, surface them once: + +> "Three captures from last week are still in the inbox — want to route them now or leave them?" + +When routing accepted items, send each to its proper home: + +- Preference / pattern → PATCH-append under `operator-preferences.md::Observations` +- Project idea → PUT `projects/incubating/.md` +- Durable fact → PUT `_agent/memory/semantic/.md` +- Person fact → PUT/PATCH `resources/people/.md` + +Then record the move in `inbox/processing-log/YYYY-MM-DD.md` (one line per item: `- `). Don't delete the original capture unless Bryan explicitly asks — the processing log is the audit trail. + +## Project Lifecycle + +Projects move through four folders under `projects/`. The folder name and the `status:` frontmatter field MUST agree — they are two views of the same state. + +| Folder | `status:` | Meaning | +|--------|-----------|---------| +| `projects/incubating/` | `incubating` | Idea captured; not actively worked. Promote when work starts. | +| `projects/active/` | `active` | Current work. The default state for anything in motion. | +| `projects/on-hold/` | `on-hold` | Paused but still tracked. Resumable. | +| `projects/archived/` | `archived` | Done, abandoned, or rolled into something else. Not deleted. | + +**Promotion / transition rule:** move the file to the new folder AND update `status:` in the same change. A file in `projects/active/` with `status: on-hold` is broken state — fix it when you see it. + +**Searching:** `POST /search/simple/?query=` covers all four subfolders in one call. Always search before creating a new note (see the pre-write rule below). + +## When to Write Memory + +Write when the operator: + +- States a fact, preference, or commitment worth keeping ("I prefer X", "we use uv not pip", "standup is Tuesday at 10") +- Makes a non-obvious decision worth recording +- Says "remember that", "save this", "log this", "add to memory", "note that" +- Finishes a meaningful working session future sessions should pick up + +Write in third person about Bryan. Every note carries the canonical frontmatter (see below). Agent-generated notes set `agent_written: true`. + +### Before you write — search first (MANDATORY for new notes) + +**Before creating any new note at `projects//.md`, `_agent/memory/semantic/.md`, `resources/people/.md`, or any other slug-addressed location, search the whole vault for that slug.** Listing a single folder (e.g. `projects/active/`) is NOT sufficient — a note with the same slug may exist in `projects/on-hold/`, `projects/incubating/`, `projects/archived/`, or under a different folder entirely. + +```bash +curl -s -X POST \ + -H "Authorization: Bearer fb72065a05fabb28ae87c45880cc3b7aba4fd3f58e70297934145cef974e8ed8" \ + "https://goldbrainapi.mpm.to/search/simple/?query=" +``` + +If a match is found: +- In a non-active project subfolder (`on-hold/`, `incubating/`, `archived/`): **promote/merge** — PUT the merged content to `projects/active/.md` with `status: active`, then DELETE the old location. Preserve the earliest `created:` date. +- In the same folder you intended to write: **update in place** (PATCH or merged PUT). Never silently overwrite — fold the existing content in first. +- Elsewhere (e.g. a stale duplicate under `resources/`): tell Bryan and ask which should be canonical before writing. + +**Search both the slug AND any human title** the operator used (e.g. slug `goldbrain-memory` and title `goldbrain plugin`). Slug-only searches miss notes filed under a different naming scheme. Two cheap `POST /search/simple/?query=...` calls beat one expensive cleanup pass later. + +Only after the search comes back empty (or you've decided to merge) is it safe to create a new note. This rule prevents the most common duplication bug: a note exists in `on-hold/` but the agent only checked `active/` and created a parallel record. + +### Before you append — read first (idempotency) + +POST appends to the end of a file. It is **not idempotent** — running the same write twice (network retry, replay, re-trigger) produces duplicate lines that grow files silently. Before any POST that adds an entry to: + +- `inbox/captures/inbox.md` +- a daily note's `## Agent Log` section +- a `## Fact / Pattern` / `## Observations` / `## Log` heading + +…GET the target file (or the heading, via `/heading/...`) and substring-search for the exact line you're about to write. If present, skip the POST. The extra GET is cheap and pays for itself within a few sessions. + +This rule does **not** apply to PUT (which is fully replacing the file) or PATCH `replace` (which is overwriting a section by design). + +### Append to a file (default — additive entries) + +Write content to a temp file first to handle multi-line markdown cleanly, then POST: + +```bash +cat > /tmp/obs_entry.md << 'OBSEOF' +- 2026-06-07: +OBSEOF + +curl -s -X POST \ + -H "Authorization: Bearer fb72065a05fabb28ae87c45880cc3b7aba4fd3f58e70297934145cef974e8ed8" \ + -H "Content-Type: text/markdown" \ + --data-binary @/tmp/obs_entry.md \ + "https://goldbrainapi.mpm.to/vault/inbox/captures/inbox.md" +``` + +POST appends to the end of a file (creating it if absent). Use it for inbox captures and log sections. + +### Patch a specific heading (targeted update) + +**Heading targets use the FULL heading path, `::`-delimited from the top-level heading** — a bare subheading name fails with `400 invalid-target` (errorCode 40080) and the write is lost. For example, `## Fact / Pattern` under the `# Operator Preferences` H1 is targeted as `Operator Preferences::Fact / Pattern`. + +**Default: GET the document map first** (every first PATCH to a file in a session — cache the result mentally for subsequent PATCHes to the same file). This eliminates the most common failure mode of PATCH: + +```bash +curl -s -H "Authorization: Bearer fb72065a05fabb28ae87c45880cc3b7aba4fd3f58e70297934145cef974e8ed8" \ + -H "Accept: application/vnd.olrapi.document-map+json" \ + "https://goldbrainapi.mpm.to/vault/_agent/memory/semantic/operator-preferences.md" +``` + +Returns `{ "headings": [...], "blocks": [...], "frontmatterFields": [...] }`. Copy the heading string verbatim into `Target`. Only skip the doc-map GET if you wrote the file yourself in this session (you already know its structure). + +Then PATCH: + +```bash +cat > /tmp/obs_patch.md << 'OBSEOF' +Bryan prefers status updates that lead with the decision. +OBSEOF + +curl -s -X PATCH \ + -H "Authorization: Bearer fb72065a05fabb28ae87c45880cc3b7aba4fd3f58e70297934145cef974e8ed8" \ + -H "Operation: append" \ + -H "Target-Type: heading" \ + -H "Target: Operator Preferences::Fact / Pattern" \ + -H "Content-Type: text/markdown" \ + --data-binary @/tmp/obs_patch.md \ + "https://goldbrainapi.mpm.to/vault/_agent/memory/semantic/operator-preferences.md" +``` + +Use `Operation: replace` to overwrite a section entirely (e.g. a project's `Project Name::Current status`). + +#### Special characters in heading targets — em dashes, parentheses (KNOWN BUG) + +The `Target` header is matched against the heading text only after the server URL-decodes it, and some characters break that match. A heading like `# EarthDnD — Personal Project` targeted literally returns `invalid-target` (40080), because raw non-ASCII bytes (the em dash `—`, U+2014) ride unreliably in an HTTP header and the matcher applies regex-special rules to characters like parentheses and brackets without escaping them. Three rules, in priority order: + +1. **Prevent it — keep new headings ASCII (the durable fix).** When you create or rewrite a heading you may later PATCH, use a plain hyphen surrounded by spaces (` - `), never an em dash (`—`) or en dash (`–`), and avoid parentheses/brackets in heading text. Write `# EarthDnD - Personal Project`, not `# EarthDnD — Personal Project`. ASCII headings are always PATCH-safe. **Do not auto-format hyphens into em dashes in headings** — this is the root cause of the bug. (Em dashes in body prose are fine; the rule is about heading text that becomes a PATCH `Target`.) + +2. **Target an existing special-char heading by percent-encoding the offending run.** Em dash `—` (U+2014) → `%E2%80%94`; en dash `–` (U+2013) → `%E2%80%93`; spaces may stay literal or be `%20`. Reproduction case from the bug report, fixed: + + ```bash + # heading in file: # EarthDnD — Personal Project + curl -s -X PATCH \ + -H "Authorization: Bearer fb72065a05fabb28ae87c45880cc3b7aba4fd3f58e70297934145cef974e8ed8" \ + -H "Operation: append" \ + -H "Target-Type: heading" \ + -H "Target: EarthDnD %E2%80%94 Personal Project::AI Platform Roles" \ + -H "Content-Type: text/markdown" \ + --data-binary @/tmp/obs_patch.md \ + "https://goldbrainapi.mpm.to/vault/projects/active/earthdnd-personal.md" + ``` + +3. **Fallback when encoding still fails (e.g. parentheses in the heading).** GET the whole file, edit the section in memory, and PUT the file back. This overwrites atomically rather than patching in place, so it carries a small race-condition risk on frequently-written files — use it sparingly and, where you control the heading, fix it to ASCII (rule 1) so the next write can PATCH cleanly. + +See `references/api-reference.md` for the full encoding table. + +### Bump `updated:` after meaningful changes + +When a PATCH or PUT changes meaningful content (status update, decision recorded, current-status replacement, scope switch), also PATCH the frontmatter `updated:` field to today's date. This keeps stale-detection queries honest. + +```bash +curl -s -X PATCH \ + -H "Authorization: Bearer fb72065a05fabb28ae87c45880cc3b7aba4fd3f58e70297934145cef974e8ed8" \ + -H "Operation: replace" -H "Target-Type: frontmatter" -H "Target: updated" \ + -H "Content-Type: application/json" --data '"2026-06-07"' \ + "https://goldbrainapi.mpm.to/vault/projects/active/.md" +``` + +Skip the bump for **routine log appends** — adding an Agent Log line, an inbox capture, or a timestamped Observations bullet doesn't constitute a meaningful content change. Bump on substance, not on heartbeat. + +### Create or overwrite a file (PUT) + +```bash +cat > /tmp/obs_file.md << 'OBSEOF' +--- +type: project +status: active +created: 2026-06-07 +updated: 2026-06-07 +tags: [] +agent_written: true +source_notes: [] +--- + +# Project Name + +## Current status +... + +## Related +- [[journal/daily/2026-06-07]] +OBSEOF + +curl -s -X PUT \ + -H "Authorization: Bearer fb72065a05fabb28ae87c45880cc3b7aba4fd3f58e70297934145cef974e8ed8" \ + -H "Content-Type: text/markdown" \ + --data-binary @/tmp/obs_file.md \ + "https://goldbrainapi.mpm.to/vault/projects/active/my-project.md" +``` + +The API creates intermediate directories automatically. + +### Search the vault + +```bash +curl -s -X POST \ + -H "Authorization: Bearer fb72065a05fabb28ae87c45880cc3b7aba4fd3f58e70297934145cef974e8ed8" \ + "https://goldbrainapi.mpm.to/search/simple/?query=your+search+terms" +``` + +## Scope Switching (`current-context.md`) + +`_agent/context/current-context.md` tracks a single active scope. The operator routinely shifts scope within a day (a project → MPM ops → something else). + +When scope changes: + +1. PATCH `prepend` a dated bullet to `## Scope History` capturing the **prior** scope (one line: `- 2026-06-07: `). If `## Scope History` doesn't exist yet, POST the heading first, same pattern as the daily-note Agent Log. +2. PATCH `replace` `## Scope` with the new scope. +3. PATCH the frontmatter `updated:` field. + +This keeps a rolling trail of recent scopes in one file instead of spawning separate stash notes. Trim Scope History to the last ~10 entries when it grows past that. + +## Vault Health (monthly) + +On the first substantive session of a calendar month, run a quick health pass and write findings to `reviews/monthly/YYYY-MM-vault-health.md`. Don't auto-fix without asking. + +Checks: + +1. **Stale active projects** — for each note in `projects/active/`, check `updated:` >30 days. Likely belongs in `on-hold/`. +2. **Unprocessed inbox** — GET `inbox/captures/inbox.md`. List items older than 14 days that never moved through the triage protocol. +3. **Duplicate slugs across lifecycle folders** — any slug appearing in more than one of `active/`, `incubating/`, `on-hold/`, `archived/` is broken state. +4. **Broken-heading risk** — sample 2–3 frequently-PATCHed files; confirm `## Agent Log`, `## Scope`, `## Fact / Pattern`, `## Observations` headings still exist, and that no heading has acquired an em dash or parentheses that would break PATCH targeting. + +The pass is cheap (a few searches + a directory listing) and pays for itself by catching drift before it requires a reorg. + +## Daily Note — Agent Log + +After substantive activity, write a one-line entry to today's daily note's `## Agent Log` heading. The daily-note **template** (`journal/templates/daily-note-template.md`) defines this heading, but ad-hoc daily notes created without the template don't have it — so PATCH can fail with `invalid-target` if the note exists but lacks the heading. + +**Procedure (resilient):** + +1. Try to GET `journal/daily/YYYY-MM-DD.md`. +2. If 404 — PUT a fresh daily note from the template, then PATCH. +3. If 200 but `## Agent Log` is missing — POST `\n\n## Agent Log\n` to the file to add the heading, then PATCH. **Detect the heading by grepping the raw markdown for an anchored `^## Agent Log` line — do NOT grep the document-map JSON, whose headings are full `::`-delimited paths (e.g. `"2026-06-07::Agent Log"`); a bare `"Agent Log"` match fails there and a duplicate heading gets appended.** +4. PATCH-append the entry under the target `::Agent Log` (the H1 of a daily note is the date, so that's the full target path). + +```bash +DATE=$(date +%Y-%m-%d) +DAILY="https://goldbrainapi.mpm.to/vault/journal/daily/${DATE}.md" +AUTH="Authorization: Bearer fb72065a05fabb28ae87c45880cc3b7aba4fd3f58e70297934145cef974e8ed8" + +# 1+2: ensure the daily note exists (PUT from template if missing) +HTTP=$(curl -s -o /dev/null -w "%{http_code}" -H "$AUTH" "$DAILY") +if [ "$HTTP" = "404" ]; then + curl -s -H "$AUTH" "https://goldbrainapi.mpm.to/vault/journal/templates/daily-note-template.md" \ + | sed "s/{{date:YYYY-MM-DD}}/${DATE}/g" \ + | curl -s -X PUT -H "$AUTH" -H "Content-Type: text/markdown" --data-binary @- "$DAILY" +fi + +# 3: ensure the `## Agent Log` heading exists. +# Grep the RAW markdown for an anchored heading line. Do NOT grep the document-map +# JSON: its headings are full "::"-delimited paths (e.g. "2026-06-07::Agent Log"), so a +# bare '"Agent Log"' match never matches and a DUPLICATE heading gets appended each time. +if ! curl -s -H "$AUTH" "$DAILY" | grep -q '^## Agent Log'; then + printf '\n\n## Agent Log\n' | curl -s -X POST -H "$AUTH" -H "Content-Type: text/markdown" --data-binary @- "$DAILY" +fi + +# 4: PATCH-append the entry +cat > /tmp/agent_log.md << OBSEOF +- ${DATE}: +OBSEOF + +curl -s -X PATCH -H "$AUTH" \ + -H "Operation: append" \ + -H "Target-Type: heading" \ + -H "Target: ${DATE}::Agent Log" \ + -H "Content-Type: text/markdown" \ + --data-binary @/tmp/agent_log.md \ + "$DAILY" +``` + +## Where to Write + +| Situation | File / path | Method | +|-----------|-------------|--------| +| Unsure where it goes / quick capture | `inbox/captures/inbox.md` (date-prefixed line) | POST | +| Operator preference or durable fact | `_agent/memory/semantic/operator-preferences.md` (append under the right heading) | PATCH | +| Other durable facts / patterns | `_agent/memory/semantic/.md` | PUT | +| What happened (event record) | `_agent/memory/episodic/.md` | PUT | +| Short-lived working state | `_agent/memory/working/.md` | PUT | +| Task-scoped context / focus | `_agent/context/current-context.md` | PATCH / PUT | +| Working session ended with substance | `_agent/sessions/YYYY-MM-DD-HHMM-.md` | PUT | +| Long-running project state | `projects//.md` (see Project Lifecycle) | PUT + PATCH | +| Non-obvious decision (ADR) | `decisions/by-date/YYYY-MM-DD-.md` (see mirror note below) | PUT | +| Person context | `resources/people/.md` | PUT / PATCH | +| Concept / reference note | `resources/concepts/` or `resources/references/` | PUT | +| Daily activity / Agent Log | `journal/daily/YYYY-MM-DD.md` — see **Daily Note — Agent Log** above | PATCH (with auto-create) | + +**Decision mirrors:** mirror a project-relevant ADR as a `[[wikilink]]` under that project's `## Decisions` heading (PATCH), and optionally into `decisions/by-project/` per the vault's `STRUCTURE.md`. The by-date ADR is always the canonical record. + +Never delete files unless Bryan explicitly asks. Memory is append-friendly; deletion is destructive. + +## Session Logging + +At the end of substantive conversations (ones that produced decisions, artifacts, or commitments), create a session log. Ask once if unsure: "Want me to log a session note for this?" + +**Filename format is canonical: `_agent/sessions/YYYY-MM-DD-HHMM-.md`.** Always include the four-digit local-time HHMM component — it makes filenames lexically sort in true chronological order, which is what Step 3 of loading relies on. Older session logs without the HHMM part may exist; leave them alone, but every new one must use the full form. + +See `references/session-log-template.md` for the body format. + +```bash +cat > /tmp/obs_session.md << 'OBSEOF' + +OBSEOF + +curl -s -X PUT \ + -H "Authorization: Bearer fb72065a05fabb28ae87c45880cc3b7aba4fd3f58e70297934145cef974e8ed8" \ + -H "Content-Type: text/markdown" \ + --data-binary @/tmp/obs_session.md \ + "https://goldbrainapi.mpm.to/vault/_agent/sessions/2026-06-07-1430-my-session.md" +``` + +Then add a one-line entry to today's daily note via the **Daily Note — Agent Log** procedure above. + +## Vault Unreachable + +If the API returns a connection error, timeout, or `502`, tell Bryan once that the memory vault is unreachable (a `502` usually means Obsidian/the REST plugin is not running on the backend), then proceed without memory. Do not retry repeatedly. + +## Style Rules + +- Write in third person about Bryan: "Bryan prefers X", not "I prefer X". +- Do not attribute Jason's design preferences to Bryan — capture Bryan's preferences only from observed interactions. Jason's preferences belong in the ECHO vault, Bryan's belong here. +- **Anchor relative dates on the conversation's `currentDate`** before writing. "Today" → `currentDate`. "Thursday" / "next week" → resolve to an absolute `YYYY-MM-DD`. Never guess from training-data knowledge of the current year. +- **Keep heading text ASCII** so it stays PATCH-targetable — plain hyphens, no em dashes or parentheses in headings (see the special-characters note under PATCH). +- Every memory file has canonical YAML frontmatter — see `references/vault-layout.md`. +- Set `agent_written: true` on agent-generated notes and list `source_notes` (plain relative paths, not links). +- **`created:` is the earliest known date the entity was tracked anywhere in the vault, not "today".** When merging notes (e.g. promoting `on-hold/` → `active/`), preserve the earliest `created:` and only bump `updated:`. +- **`source_notes` lists the note(s) that *triggered* or *supplied content for* this one** — e.g. the session log that produced a project update, or the daily note where a captured fact originated. It is a *backward* link to inputs. Forward links (this note → other notes it references) belong in the `## Related` section in the note body, never in frontmatter. +- **Never put `[[wikilinks]]` in frontmatter** — YAML parses them as nested lists and the links break in Obsidian's reading view. Put all cross-references in a `## Related` section in the note **body** as a bulleted list of `[[links]]`. +- Use Obsidian wiki links (`[[note name]]`) freely in the note **body** for cross-references. +- Keep entries short and focused. Fewer, sharper entries beat many noisy ones. +- About to write something large or sensitive? Show Bryan the content first and confirm. + +## operator-preferences.md — Rules vs Observations + +`_agent/memory/semantic/operator-preferences.md` separates two kinds of content: + +- `## Fact / Pattern` — **promoted, deduped rules.** No date prefix. These are timeless: "Bryan prefers concise communication." Append here only when a rule is stable. +- `## Observations` — **timestamped raw observations.** Date-prefixed: `- 2026-06-07: Bryan chose X over Y because Z.` This is where new evidence goes by default. + +During monthly Vault Health or when an observation stabilizes, promote it from `## Observations` into `## Fact / Pattern` (drop the date) and remove the duplicate from Observations. Trim Observations to the last ~30 entries when it grows past that — the rest live in session logs. + +## What This Skill Does Not Do + +- Does not replace reasoning. The vault is reference material — apply judgment. +- Does not auto-summarize the whole vault. Read targeted files, not everything. +- Does not store passwords or secrets, and never writes the API key into a vault note. If asked to "remember my password is X", decline and suggest a password manager. diff --git a/goldbrain-memory.src/skills/goldbrain-memory/references/api-reference.md b/goldbrain-memory.src/skills/goldbrain-memory/references/api-reference.md new file mode 100644 index 0000000..50d482e --- /dev/null +++ b/goldbrain-memory.src/skills/goldbrain-memory/references/api-reference.md @@ -0,0 +1,221 @@ +# Goldbrain — Obsidian Local REST API Reference + +Server: `https://goldbrainapi.mpm.to` (reverse proxy → Obsidian Local REST API on `192.168.86.15:27124`) +Auth header: `Authorization: Bearer fb72065a05fabb28ae87c45880cc3b7aba4fd3f58e70297934145cef974e8ed8` +The endpoint has a **valid TLS certificate** — `-k` is not required. Paths address the vault at its **root**. + +--- + +## Reading Files + +```bash +# Read any file by vault path +curl -s \ + -H "Authorization: Bearer fb72065a05fabb28ae87c45880cc3b7aba4fd3f58e70297934145cef974e8ed8" \ + "https://goldbrainapi.mpm.to/vault/_agent/context/current-context.md" +``` + +Returns raw file content (text/markdown). On 404, the file does not exist. + +```bash +# Read a specific heading's content only +curl -s \ + -H "Authorization: Bearer fb72065a05fabb28ae87c45880cc3b7aba4fd3f58e70297934145cef974e8ed8" \ + "https://goldbrainapi.mpm.to/vault/_agent/memory/semantic/operator-preferences.md/heading/Operator" +``` + +Nested headings: separate levels with `::` (URL-encode spaces as `%20`): +``` +/vault/path/to/note.md/heading/Work%3A%3AMeetings +``` + +--- + +## Listing Directories + +```bash +# List contents of a directory (trailing slash required) +curl -s \ + -H "Authorization: Bearer fb72065a05fabb28ae87c45880cc3b7aba4fd3f58e70297934145cef974e8ed8" \ + "https://goldbrainapi.mpm.to/vault/_agent/sessions/" +``` + +Returns JSON: `{ "files": [...], "folders": [...] }`. + +--- + +## Appending Content (POST) + +`POST` appends to the **end** of an existing file. Creates the file if it doesn't exist. + +```bash +cat > /tmp/obs_entry.md << 'OBSEOF' +- 2026-06-02: your entry here +OBSEOF + +curl -s -X POST \ + -H "Authorization: Bearer fb72065a05fabb28ae87c45880cc3b7aba4fd3f58e70297934145cef974e8ed8" \ + -H "Content-Type: text/markdown" \ + --data-binary @/tmp/obs_entry.md \ + "https://goldbrainapi.mpm.to/vault/inbox/captures/inbox.md" +``` + +--- + +## Creating or Overwriting Files (PUT) + +`PUT` creates a new file or fully overwrites an existing one. Intermediate directories are created automatically. + +```bash +cat > /tmp/obs_file.md << 'OBSEOF' +--- +type: session-log +status: complete +created: 2026-06-02 +updated: 2026-06-02 +tags: [agent, session] +agent_written: true +source_notes: [] +--- + +# content here + +## Related +- [[projects/active/some-project]] +OBSEOF + +curl -s -X PUT \ + -H "Authorization: Bearer fb72065a05fabb28ae87c45880cc3b7aba4fd3f58e70297934145cef974e8ed8" \ + -H "Content-Type: text/markdown" \ + --data-binary @/tmp/obs_file.md \ + "https://goldbrainapi.mpm.to/vault/_agent/sessions/2026-06-02-1430-my-session.md" +``` + +--- + +## Patching a Specific Section (PATCH) + +`PATCH` edits inside a file without rewriting it. Target and operation are set via headers. + +### Append under a heading + +**Heading targets must be the FULL heading path, `::`-delimited from the top-level heading.** A bare subheading name returns `400 invalid-target` (errorCode 40080). Example: `## Fact / Pattern` nested under `# Operator Preferences` → `Target: Operator Preferences::Fact / Pattern`. Percent-encode non-ASCII characters (e.g. `H%C3%A9llo`); spaces are fine. + +> **Special characters in heading targets (em dashes, parentheses) — known failure.** The server matches the `Target` header against heading text only after URL-decoding it, and the matcher applies regex-special handling to characters like `(` `)` `[` `]`. A heading such as `# EarthDnD — Personal Project` targeted literally fails with `invalid-target` (40080), because the raw em dash (`—`, U+2014) rides unreliably in an HTTP header. Handle it in this priority order: +> +> 1. **Prevent — keep new headings ASCII.** When you author a heading you might later PATCH, use a plain hyphen with spaces (` - `), never an em dash/en dash, and avoid parentheses/brackets. `# EarthDnD - Personal Project` is always PATCH-safe. This is the durable fix. +> 2. **Percent-encode the offending run** when targeting an existing special-char heading: em dash `—` → `%E2%80%94`, en dash `–` → `%E2%80%93`. Example fixing the bug-report case: `Target: EarthDnD %E2%80%94 Personal Project::AI Platform Roles`. +> 3. **Fallback (GET → edit → PUT)** when even encoding fails (e.g. parentheses): read the whole file, edit the section in memory, PUT it back. Atomic, not in-place — small race-condition risk on hot files, so prefer fixing the heading to ASCII. + +| Character | Glyph | Percent-encoding | +|-----------|-------|------------------| +| Em dash | `—` (U+2014) | `%E2%80%94` | +| En dash | `–` (U+2013) | `%E2%80%93` | +| Space | ` ` | `%20` (literal space also works) | +| `::` (nesting, in URL path only) | `::` | `%3A%3A` | +| é (example accented char) | `é` | `%C3%A9` | + +```bash +cat > /tmp/obs_patch.md << 'OBSEOF' +Bryan prefers concise status updates — lead with the decision. +OBSEOF + +curl -s -X PATCH \ + -H "Authorization: Bearer fb72065a05fabb28ae87c45880cc3b7aba4fd3f58e70297934145cef974e8ed8" \ + -H "Operation: append" \ + -H "Target-Type: heading" \ + -H "Target: Operator Preferences::Fact / Pattern" \ + -H "Content-Type: text/markdown" \ + --data-binary @/tmp/obs_patch.md \ + "https://goldbrainapi.mpm.to/vault/_agent/memory/semantic/operator-preferences.md" +``` + +### Discover heading / block / frontmatter targets + +When unsure of the exact heading path, GET the note with the document-map Accept header: + +```bash +curl -s \ + -H "Authorization: Bearer fb72065a05fabb28ae87c45880cc3b7aba4fd3f58e70297934145cef974e8ed8" \ + -H "Accept: application/vnd.olrapi.document-map+json" \ + "https://goldbrainapi.mpm.to/vault/_agent/memory/semantic/operator-preferences.md" +``` + +Returns `{ "headings": [...], "blocks": [...], "frontmatterFields": [...] }`. Copy the heading string verbatim into `Target`. + +### Replace a heading's content entirely + +Same call with `Operation: replace` — e.g. to refresh a project's `Project Name::Current status`. + +### Prepend under a heading + +Same call with `Operation: prepend`. + +### Patch a frontmatter field + +```bash +curl -s -X PATCH \ + -H "Authorization: Bearer fb72065a05fabb28ae87c45880cc3b7aba4fd3f58e70297934145cef974e8ed8" \ + -H "Operation: replace" \ + -H "Target-Type: frontmatter" \ + -H "Target: updated" \ + -H "Content-Type: application/json" \ + --data '"2026-06-02"' \ + "https://goldbrainapi.mpm.to/vault/projects/active/vault-foundation.md" +``` + +--- + +## Searching + +```bash +curl -s -X POST \ + -H "Authorization: Bearer fb72065a05fabb28ae87c45880cc3b7aba4fd3f58e70297934145cef974e8ed8" \ + "https://goldbrainapi.mpm.to/search/simple/?query=weekly+review" +``` + +Returns an array of `{ filename, score, matches: [{ context, match }] }`. + +--- + +## Deleting Files + +```bash +curl -s -X DELETE \ + -H "Authorization: Bearer fb72065a05fabb28ae87c45880cc3b7aba4fd3f58e70297934145cef974e8ed8" \ + "https://goldbrainapi.mpm.to/vault/archive/notes/old-note.md" +``` + +Only on explicit operator request. Deletion is destructive. + +--- + +## URL-Encoding Notes + +- Path separators (`/`) in the vault path are **literal** — do not encode them. +- Spaces in filenames or heading targets in a URL: use `%20`. +- Nested heading levels in a URL path: use `%3A%3A` for `::`. +- Heading text in the `Target:` header: the **full heading path** joined by `::` (e.g. `Operator Preferences::Fact / Pattern`), no `#`; spaces are fine; **percent-encode non-ASCII and regex-special characters** — em dash `—` → `%E2%80%94`, en dash `–` → `%E2%80%93` (see the special-characters note under *Patching* above). Best practice: keep heading text ASCII so targets never need encoding. + +--- + +## Memory Routing Map + +| Situation | Vault path | Method | +|-----------|-----------|--------| +| Quick capture / unsorted | `inbox/captures/inbox.md` (date-prefixed line) | POST | +| Raw imported material | `inbox/imports/` | PUT | +| Operator preference / durable fact | `_agent/memory/semantic/operator-preferences.md` | PATCH | +| Other durable facts, patterns | `_agent/memory/semantic/.md` | PUT | +| Event record (what happened) | `_agent/memory/episodic/.md` | PUT | +| Short-lived, time-boxed state | `_agent/memory/working/.md` | PUT | +| Task-scoped context / focus | `_agent/context/current-context.md` | PATCH / PUT | +| Working-session log | `_agent/sessions/YYYY-MM-DD-HHMM-.md` | PUT | +| Long-running project state | `projects//.md` (lifecycle: `incubating` → `active` → `on-hold`/`archived`; folder and `status:` MUST agree) | PUT + PATCH | +| Non-obvious decision (ADR) | `decisions/by-date/YYYY-MM-DD-.md` (mirror `by-project/`) | PUT | +| Person context | `resources/people/.md` | PUT / PATCH | +| Concept / reference note | `resources/concepts/` or `resources/references/` | PUT | +| Daily activity / Agent Log | `journal/daily/YYYY-MM-DD.md` | POST / PATCH | +| Periodic review | `reviews/{weekly,monthly,quarterly,annual}/` | PUT | + +**Slug rules:** kebab-case, ASCII, ~40 chars max. Every file carries canonical frontmatter (see `vault-layout.md`). diff --git a/goldbrain-memory.src/skills/goldbrain-memory/references/bootstrap.md b/goldbrain-memory.src/skills/goldbrain-memory/references/bootstrap.md new file mode 100644 index 0000000..8442873 --- /dev/null +++ b/goldbrain-memory.src/skills/goldbrain-memory/references/bootstrap.md @@ -0,0 +1,39 @@ +# Bootstrap Procedure + +The goldbrain vault ships its **own** `BOOTSTRAP.md` at the vault root — that file is the canonical preflight/repair manifest. This plugin defers to it rather than duplicating the logic. + +> **Structure vs. procedure.** This file (and the vault's `BOOTSTRAP.md`/`STRUCTURE.md`) own *structure* — what folders and seed files must exist. Day-to-day *procedure* — parallel loading, search-before-write, append idempotency, project lifecycle transitions, scope switching, vault health, and the em-dash-safe PATCH rules — lives in `SKILL.md`. When repairing, ensure the four project-lifecycle folders exist: `projects/{incubating,active,on-hold,archived}/`. + +## Normal case — vault already bootstrapped + +At session start, read the in-vault manifest: + +```bash +curl -s \ + -H "Authorization: Bearer fb72065a05fabb28ae87c45880cc3b7aba4fd3f58e70297934145cef974e8ed8" \ + "https://goldbrainapi.mpm.to/vault/BOOTSTRAP.md" +``` + +If it returns content (200), the vault is set up. Skim its preflight checklist, then read `CLAUDE.md` for the operating contract and proceed with the loading procedure in `SKILL.md`. The in-vault `BOOTSTRAP.md` describes how to repair any missing folders/files; follow it if something is absent. **Never overwrite an existing file** during repair — generate only what is missing. + +## Fresh-vault case — BOOTSTRAP.md returns 404 + +This means the REST API is pointed at an empty vault. Confirm with the operator once: + +> "The goldbrain vault looks empty — there's no `BOOTSTRAP.md`. The standard scaffold (control docs, folder tree, templates, seed notes) needs to be loaded before I can use it as memory. Want me to create the core seed files now?" + +If yes, create the minimum viable seed with `PUT` (the API creates intermediate directories automatically), then let the vault's own structure grow from there: + +1. `CLAUDE.md` — operating contract and session protocol +2. `BOOTSTRAP.md` — preflight/repair manifest +3. `STRUCTURE.md` — layout, taxonomy, frontmatter standard +4. `index.md` — navigation hub +5. `_agent/memory/semantic/operator-preferences.md` — operator profile (empty, no fabricated facts) +6. `_agent/context/current-context.md` — empty context bundle +7. `inbox/captures/inbox.md` — capture file + +Prefer copying the full prepared scaffold into the Obsidian vault folder over reconstructing it by hand — it is the source of truth for goldbrain's structure. + +## After bootstrap + +Tell the operator briefly what was created, append a line to the daily note's **Agent Log**, and write a session log in `_agent/sessions/`. Do not over-explain — they can browse the vault. diff --git a/goldbrain-memory.src/skills/goldbrain-memory/references/session-log-template.md b/goldbrain-memory.src/skills/goldbrain-memory/references/session-log-template.md new file mode 100644 index 0000000..0d4793e --- /dev/null +++ b/goldbrain-memory.src/skills/goldbrain-memory/references/session-log-template.md @@ -0,0 +1,110 @@ +# Session Log Template + +Session logs go in: `_agent/sessions/YYYY-MM-DD-HHMM-.md` + +**Filename format is canonical and not optional.** The four-digit local-time HHMM component is what makes session filenames lex-sort in true chronological order — the loading procedure depends on it. Before PUT-ing a new session log, validate the filename matches `^\d{4}-\d{2}-\d{2}-\d{4}-[a-z0-9-]+\.md$`. Legacy session logs without HHMM may exist; do not rename them, but every new write must use the full form. + +The slug describes what the session was about in 2–5 words, kebab-case. +Examples: `2026-06-07-1430-goldbrain-plugin-build.md`, `2026-05-14-0900-q1-review-prep.md`. + +Keep logs focused. Capture the goal, what was read/done, decisions, outputs, open threads, and the next step. This matches the vault's `_agent/templates/session-log-template.md`. + +--- + +## Template + +```markdown +--- +type: session-log +status: complete +created: 2026-06-07T14:30 +updated: 2026-06-07T14:30 +tags: [agent, session] +agent_written: true +source_notes: [] +session_date: 2026-06-07 +client: claude-code +--- + +# Session Log + +## Goal +One line — what this session set out to do. + +## Notes Read +- [[note]] — why it was relevant +(omit if none) + +## Actions Taken +Brief narrative or bullets of what was done. + +## Decisions Made +- Decision — why +(omit section if none) + +## Outputs Created +- `path/or/filename` — what it is +(omit section if none) + +## Open Threads +- [ ] unresolved question or next step +(omit section if none) + +## Suggested Next Step +One sentence: what to do first next time on this topic. + +## Related +- [[wikilinks go here, in the body — never in frontmatter]] +``` + +--- + +## Example + +```markdown +--- +type: session-log +status: complete +created: 2026-06-07T14:30 +updated: 2026-06-07T14:30 +tags: [agent, session, plugin] +agent_written: true +source_notes: ["resources/references/obsidian-local-rest-api.md"] +session_date: 2026-06-07 +client: claude-code +--- + +# Session Log + +## Goal +Build and package the goldbrain-memory CoWork plugin against the live vault. + +## Notes Read +- [[BOOTSTRAP]], [[STRUCTURE]], [[_agent/memory/semantic/operator-preferences]] + +## Actions Taken +Verified the REST API end-to-end, confirmed the scaffold copied into the live vault, +created missing empty folders, and built the plugin (SKILL + 4 reference files). + +## Decisions Made +- Vault addressed at root (no `Projects/agents/` prefix) — goldbrain is a dedicated vault. +- Key hardcoded in the plugin (not in the vault) — personal plugin, per the reference pattern. + +## Outputs Created +- `goldbrain-memory.plugin` — installable CoWork plugin + +## Open Threads +- [ ] Validate Claude Code direct filesystem access to the vault host. + +## Suggested Next Step +Install the plugin and run a live load/write through it to confirm the skill triggers. + +## Related +- [[projects/active/vault-foundation]] +- [[resources/references/obsidian-local-rest-api]] +``` + +After writing the log, append a one-line entry to the daily note's **Agent Log** section. + +> **Reminder:** wiki links go in the body (e.g. this `## Related` section), never in YAML +> frontmatter. `source_notes` in frontmatter holds plain relative path strings, not `[[links]]`. diff --git a/goldbrain-memory.src/skills/goldbrain-memory/references/vault-layout.md b/goldbrain-memory.src/skills/goldbrain-memory/references/vault-layout.md new file mode 100644 index 0000000..cbde5a7 --- /dev/null +++ b/goldbrain-memory.src/skills/goldbrain-memory/references/vault-layout.md @@ -0,0 +1,155 @@ +# Vault Layout & Frontmatter Conventions + +Mirrors the canonical conventions defined in the vault's own `STRUCTURE.md` and `BOOTSTRAP.md`. If those change, they are the source of truth. + +## Folder Map (root-addressed) + +``` +/vault/ +├── CLAUDE.md ← operating contract + session protocol +├── STRUCTURE.md ← layout, taxonomy, frontmatter standard +├── BOOTSTRAP.md ← preflight/repair manifest (read first) +├── spinup.md index.md README.md +├── inbox/ +│ ├── captures/ ← quick captures (inbox.md), date-prefixed lines +│ ├── imports/ ← raw imported material +│ └── processing-log/ +├── journal/ +│ ├── daily/ ← YYYY-MM-DD.md (has an "Agent Log" section) +│ ├── weekly/ monthly/ +│ └── templates/ +├── projects/ ← lifecycle: incubating → active → on-hold/archived +│ ├── active/ ← current work (status: active) +│ ├── incubating/ ← idea captured, not yet started (status: incubating) +│ ├── on-hold/ ← paused but kept (status: on-hold) +│ ├── archived/ ← done / abandoned (status: archived) +│ └── project-template.md +├── areas/ ← business / personal / learning / systems +├── resources/ +│ ├── concepts/ references/ meetings/ source-material/ +│ └── people/ ← .md +├── decisions/ +│ ├── by-date/ ← YYYY-MM-DD-.md (ADR-style) +│ ├── by-project/ ← mirror by project +│ └── decision-template.md +├── reviews/ ← weekly / monthly / quarterly / annual +├── archive/ ← notes / projects / imports +└── _agent/ + ├── context/ ← current-context.md and task bundles + ├── memory/ + │ ├── working/ ← transient, time-boxed + │ ├── episodic/ ← what happened, when + │ └── semantic/ ← durable facts/patterns (operator-preferences.md) + ├── sessions/ ← YYYY-MM-DD-HHMM-.md + ├── templates/ ← canonical note templates + ├── outputs/ ← briefs / drafts / summaries / synthesis + ├── skills/ ← active / archived + └── heartbeat/ +``` + +**Slug rules:** kebab-case, ASCII only, truncate to ~40 chars. + +--- + +## Canonical Frontmatter + +Every note starts with this block. Fill what applies; leave the rest empty rather than guessing. + +```yaml +--- +type: # see Note Types below +status: # active | draft | done | archived | complete +created: # YYYY-MM-DD (or YYYY-MM-DDTHH:mm for sessions) +updated: # YYYY-MM-DD +tags: [] +agent_written: false +source_notes: [] # plain relative paths as strings — NEVER [[wikilinks]] +--- +``` + +`agent_written: true` + a populated `source_notes` is the key signal separating +agent-managed content from human-authored content. When appending with POST, do +not rewrite frontmatter — the append goes after existing content. To change +`updated:` or `status:`, use PATCH with `Target-Type: frontmatter`. + +> **No `[[wikilinks]]` in frontmatter.** YAML parses `[[...]]` as nested lists, so wiki +> links there break and never render as clickable links in reading view. Put all +> cross-references in a **`## Related`** section in the note **body** (bulleted `[[links]]`). +> Frontmatter holds scalar/string metadata only; `source_notes` values are plain relative +> paths, not links. + +## Note Types + +`daily-note`, `weekly-note`, `monthly-note`, `project`, `project-update`, `area`, +`concept`, `reference`, `person`, `meeting`, `decision`, `review`, `session-log`, +`working-memory`, `episodic-memory`, `semantic-memory`, `context-bundle`, `skill`, +`draft`, `inbox-item`. + +--- + +## File-Specific Conventions + +### operator-preferences.md (`_agent/memory/semantic/`) + +The profile analog. Canonical headings: + +- `## Operator` — who Bryan is (one paragraph) +- `## Fact / Pattern` — **promoted, deduped rules.** No date prefix. Timeless. +- `## Observations` — **timestamped raw observations.** Date-prefixed lines (`- 2026-06-07: ...`). Default landing zone for new evidence. +- `## Evidence` — citations/links supporting the rules +- `## Recommendation or Implication` — how the rules should shape behavior +- `## Review Notes` — confidence / last review date + +Append observed facts under `## Observations` by default. Promote to `## Fact / Pattern` (dropping the date) once a pattern stabilizes. "The operator" is Bryan; do not attribute Jason's design preferences to Bryan without evidence — Jason's preferences live in the ECHO vault. + +### projects/active/\.md + +```markdown +--- +type: project +status: active +created: 2026-06-07 +updated: 2026-06-07 +tags: [] +agent_written: false +source_notes: [] +--- + +# Project Name + +## Current status +One paragraph, kept fresh via PATCH replace. + +## Decisions +- [[YYYY-MM-DD-decision-slug]] — one-line summary + +## Open threads +- [ ] unresolved thing + +## Log +- 2026-06-07: observation or update + +## Related +- [[areas/business/business-ops]] +``` + +**Lifecycle / status agreement:** a project's folder under `projects/` (`active`, `incubating`, `on-hold`, `archived`) and its `status:` frontmatter MUST match — moving the file and updating `status:` are the same operation. A note in `projects/active/` with `status: on-hold` is broken state; fix it when you see it. Keep heading text ASCII (plain hyphens, no em dashes/parentheses) so headings stay PATCH-targetable. + +### sessions/YYYY-MM-DD-HHMM-\.md + +See `session-log-template.md`. goldbrain uses an **HHMM time component** in the filename — this is **canonical, not optional**. The four-digit local-time component makes filenames lex-sort in true chronological order, which the loading procedure relies on. Older session logs without HHMM may exist; leave them alone, but every new one must use the full `YYYY-MM-DD-HHMM-.md` form. + +### decisions/by-date/YYYY-MM-DD-\.md + +ADR-style: Context → Decision → Consequences. Mirror a project-relevant ADR as a `[[wikilink]]` under that project's `## Decisions` heading, and optionally into `by-project/` per the vault's `STRUCTURE.md`. The by-date ADR is always the canonical record. + +### people/\.md + +`type: person`. Use lowercase kebab-case for the slug (e.g. `bryan-gilliom.md`). + +--- + +## Cross-References + +Use Obsidian wiki links freely: `[[note-name]]` or `[[folder/note]]`. The REST API +doesn't resolve them, but Obsidian does when the operator browses the vault.