forked from jason/echo
Phase 3: per-member namespacing — schema 5 (the core group conversion)
One shared vault, per-member namespaces for all churn-prone state:
- _agent/members/<member>/{preferences,current-context,heartbeat,inbox}.md
+ _agent/sessions/<member>/ session logs; shared group-profile.md
(with auto-rostered ## Members) and inbox/captures/group.md.
- Self-onboarding: load detects a bootstrapped vault lacking THIS
member's namespace and seeds it (bootstrap.member_bootstrap()).
- load = 8 reads (marker, group profile, my prefs/context/heartbeat,
shared daily, my inbox, group inbox); heartbeat fallback lists my
sessions dir; scope show/set is per member.
- Member-tagged shared writes: daily Agent Log lines and entity-update
dated blocks are '- YYYY-MM-DD [member]: …'; capture --inbox targets
my inbox; triage lists both inboxes and writes attributed audit lines.
- routing.json: member-anchors / inbox-group / member-segmented session
routes; single-user anchor paths retired (schema 5). vault_lint runs
aging-inbox + scope-drift per member. migrate.py 4->5 for alpha vaults.
- Scaffold: member-* seeds ({{MEMBER}}-stamped), group-profile/group-inbox
seeds, marker schema 5. Docs (SKILL, vault-layout, routing-map,
bootstrap) synced; manifest -> 2.0.0-alpha.3; rebuilt plugin (81 files).
Verified: all suites green (25/25 unit, scaffold, routing-sync 36 routes,
4 mock e2e, run_eval unchanged) + 19-check two-member smoke: bootstrap ->
self-onboard -> interleaved tagged daily log -> cross-member update
attribution -> independent scopes -> mine/group triage -> lint clean.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -29,7 +29,7 @@ For a vault large enough that even the concurrent pass approaches the tool timeo
|
||||
# Read any file by vault path
|
||||
curl -s \
|
||||
-H "Authorization: Bearer $CHORUS_KEY" \
|
||||
"$CHORUS_BASE/vault/_agent/context/current-context.md"
|
||||
"$CHORUS_BASE/vault/_agent/members/<member>/current-context.md"
|
||||
```
|
||||
|
||||
Returns raw file content (text/markdown). On 404, the file does not exist.
|
||||
@@ -38,7 +38,7 @@ Returns raw file content (text/markdown). On 404, the file does not exist.
|
||||
# Read a specific heading's content only
|
||||
curl -s \
|
||||
-H "Authorization: Bearer $CHORUS_KEY" \
|
||||
"$CHORUS_BASE/vault/_agent/memory/semantic/operator-preferences.md/heading/Operator"
|
||||
"$CHORUS_BASE/vault/_agent/members/<member>/preferences.md/heading/Operator"
|
||||
```
|
||||
|
||||
Nested headings: separate levels with `::` (URL-encode spaces as `%20`):
|
||||
@@ -74,7 +74,7 @@ curl -s -X POST \
|
||||
-H "Authorization: Bearer $CHORUS_KEY" \
|
||||
-H "Content-Type: text/markdown" \
|
||||
--data-binary @/tmp/obs_entry.md \
|
||||
"$CHORUS_BASE/vault/inbox/captures/inbox.md"
|
||||
"$CHORUS_BASE/vault/_agent/members/<member>/inbox.md"
|
||||
```
|
||||
|
||||
---
|
||||
@@ -116,7 +116,7 @@ curl -s -X PUT \
|
||||
|
||||
### 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.
|
||||
**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: Preferences::Fact / Pattern`. Percent-encode non-ASCII characters (e.g. `H%C3%A9llo`); spaces are fine.
|
||||
|
||||
```bash
|
||||
cat > /tmp/obs_patch.md << 'OBSEOF'
|
||||
@@ -127,10 +127,10 @@ curl -s -X PATCH \
|
||||
-H "Authorization: Bearer $CHORUS_KEY" \
|
||||
-H "Operation: append" \
|
||||
-H "Target-Type: heading" \
|
||||
-H "Target: Operator Preferences::Fact / Pattern" \
|
||||
-H "Target: Preferences::Fact / Pattern" \
|
||||
-H "Content-Type: text/markdown" \
|
||||
--data-binary @/tmp/obs_patch.md \
|
||||
"$CHORUS_BASE/vault/_agent/memory/semantic/operator-preferences.md"
|
||||
"$CHORUS_BASE/vault/_agent/members/<member>/preferences.md"
|
||||
```
|
||||
|
||||
### Discover heading / block / frontmatter targets
|
||||
@@ -141,7 +141,7 @@ When unsure of the exact heading path, GET the note with the document-map Accept
|
||||
curl -s \
|
||||
-H "Authorization: Bearer $CHORUS_KEY" \
|
||||
-H "Accept: application/vnd.olrapi.document-map+json" \
|
||||
"$CHORUS_BASE/vault/_agent/memory/semantic/operator-preferences.md"
|
||||
"$CHORUS_BASE/vault/_agent/members/<member>/preferences.md"
|
||||
```
|
||||
|
||||
Returns `{ "headings": [...], "blocks": [...], "frontmatterFields": [...] }`. Copy the heading string verbatim into `Target`.
|
||||
@@ -211,7 +211,7 @@ Only on explicit operator request. Deletion is destructive.
|
||||
- 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.
|
||||
- Heading text in the `Target:` header: the **full heading path** joined by `::` (e.g. `Preferences::Fact / Pattern`), no `#`; spaces are fine; percent-encode non-ASCII.
|
||||
|
||||
---
|
||||
|
||||
@@ -219,14 +219,14 @@ Only on explicit operator request. Deletion is destructive.
|
||||
|
||||
| Situation | Vault path | Method |
|
||||
|-----------|-----------|--------|
|
||||
| Quick capture / unsorted | `inbox/captures/inbox.md` (date-prefixed line) | POST |
|
||||
| Quick capture / unsorted | `_agent/members/<member>/inbox.md` (date-prefixed line) | POST |
|
||||
| Raw imported material | `inbox/imports/` | PUT |
|
||||
| Operator preference / durable fact | `_agent/memory/semantic/operator-preferences.md` | PATCH |
|
||||
| Operator preference / durable fact | `_agent/members/<member>/preferences.md` | PATCH |
|
||||
| Other durable facts, patterns | `_agent/memory/semantic/<slug>.md` | PUT |
|
||||
| Event record (what happened) | `_agent/memory/episodic/<slug>.md` | PUT |
|
||||
| Short-lived, time-boxed state | `_agent/memory/working/<slug>.md` | PUT |
|
||||
| Task-scoped context / focus | `_agent/context/current-context.md` | PATCH / PUT |
|
||||
| Working-session log | `_agent/sessions/YYYY-MM-DD-HHMM-<slug>.md` | PUT |
|
||||
| Task-scoped context / focus | `_agent/members/<member>/current-context.md` | PATCH / PUT |
|
||||
| Working-session log | `_agent/sessions/<member>/YYYY-MM-DD-HHMM-<slug>.md` | PUT |
|
||||
| Long-running project state | `projects/<lifecycle>/<slug>.md` (lifecycle: `incubating` → `active` → `on-hold`/`archived`; folder and `status:` MUST agree) | PUT + PATCH |
|
||||
| Ongoing area of responsibility (standing domain, no end state) | `areas/<domain>/<slug>.md` (`<domain>`: `business`/`personal`/`learning`/`systems`) | PUT |
|
||||
| Non-obvious decision (ADR) | `decisions/by-date/YYYY-MM-DD-<slug>.md` (mirror only into an existing project note's `## Key Decisions`; otherwise skip) | PUT |
|
||||
@@ -238,7 +238,7 @@ Only on explicit operator request. Deletion is destructive.
|
||||
| Daily activity / Agent Log | `journal/daily/YYYY-MM-DD.md` | POST / PATCH |
|
||||
| Journal rollup | `journal/{weekly/YYYY-Www,monthly/YYYY-MM,quarterly/YYYY-Qn,annual/YYYY}.md` (weekly = opt-in on first session of a new ISO week; monthly = offered with Vault Health; quarterly/annual = manual) | PUT |
|
||||
| Vault-health audit (agent self-maintenance) | `_agent/health/YYYY-MM-vault-health.md` (monthly; NOT a journal entry) | PUT |
|
||||
| Session-end orientation pointer | `_agent/heartbeat/last-session.md` (one line, overwritten each session end) | PUT |
|
||||
| Session-end orientation pointer | `_agent/members/<member>/heartbeat.md` (one line, overwritten each session end) | PUT |
|
||||
| Bootstrap marker (plugin-owned) | `_agent/chorus-vault.md` (`schema_version`, bootstrap date) — the "is this vault set up?" probe | GET / PUT |
|
||||
|
||||
**Slug rules:** kebab-case, ASCII, ~40 chars max. Every file carries canonical frontmatter (see `vault-layout.md`).
|
||||
|
||||
@@ -43,7 +43,7 @@ curl -s -o /dev/null -w "%{http_code}" -H "$AUTH" "$BASE/vault/_agent/chorus-vau
|
||||
|
||||
Idempotent and additive. **Never overwrite an existing file** — GET-probe each path and skip any that already returns `200`. The marker is written **last**, so the vault is only flagged "set up" after every piece is in place.
|
||||
|
||||
Throughout, `{{DATE}}` means today's date (`YYYY-MM-DD`), resolved from the conversation's `currentDate`. Substitute it before PUTting any scaffold file or anchor seed.
|
||||
Throughout, `{{DATE}}` means today's date (`YYYY-MM-DD`), resolved from the conversation's `currentDate`, and `{{MEMBER}}` means this machine's configured member id. Substitute both before PUTting any scaffold file or anchor seed.
|
||||
|
||||
### 1. Folder tree
|
||||
|
||||
@@ -57,10 +57,13 @@ areas/business areas/personal areas/learning areas/systems
|
||||
resources/concepts resources/references resources/people resources/companies resources/meetings
|
||||
decisions/by-date
|
||||
_agent/context _agent/memory/working _agent/memory/episodic _agent/memory/semantic
|
||||
_agent/sessions _agent/health _agent/templates _agent/heartbeat
|
||||
_agent/sessions _agent/health _agent/templates _agent/members
|
||||
_agent/skills/active _agent/skills/archived
|
||||
```
|
||||
|
||||
Plus, per member (created by `bootstrap.py` for the configured member, and by `chorus.py load`'s
|
||||
self-onboarding for any later member): `_agent/sessions/<member>` (→ README).
|
||||
|
||||
> `decisions/by-project/` is intentionally **not** created — it is retired. A project-relevant decision is mirrored as a `[[wikilink]]` under that project's `## Key Decisions` heading instead.
|
||||
>
|
||||
> `reviews/` is **not** created — it is retired. Journal rollups (weekly/monthly/quarterly/annual) live under `journal/`; the monthly vault-health audit lives under `_agent/health/`.
|
||||
@@ -101,15 +104,28 @@ curl -s -X PUT -H "$AUTH" -H "Content-Type: text/markdown" \
|
||||
|
||||
### 3. Anchor seeds (only if absent — no fabricated facts)
|
||||
|
||||
Substitute `{{DATE}}` → today, then PUT each:
|
||||
Substitute `{{DATE}}` → today and `{{MEMBER}}` → the configured member, then PUT each.
|
||||
|
||||
**Shared group anchors** (once per vault):
|
||||
|
||||
| Scaffold file | Vault path |
|
||||
|---|---|
|
||||
| `scaffold/anchors/operator-preferences.seed.md` | `_agent/memory/semantic/operator-preferences.md` |
|
||||
| `scaffold/anchors/current-context.seed.md` | `_agent/context/current-context.md` |
|
||||
| `scaffold/anchors/inbox.seed.md` | `inbox/captures/inbox.md` |
|
||||
| `scaffold/anchors/group-profile.seed.md` | `_agent/memory/semantic/group-profile.md` |
|
||||
| `scaffold/anchors/group-inbox.seed.md` | `inbox/captures/group.md` |
|
||||
|
||||
The operator-preferences seed is deliberately empty — **do not invent preferences.** Real facts accrue through use.
|
||||
**Member anchors** (once per member — `bootstrap.py member_bootstrap()`, also invoked by
|
||||
`chorus.py load`'s self-onboarding; a roster line `- <member> (joined YYYY-MM-DD)` is appended
|
||||
idempotently under the group profile's `## Members`):
|
||||
|
||||
| Scaffold file | Vault path |
|
||||
|---|---|
|
||||
| `scaffold/anchors/member-preferences.seed.md` | `_agent/members/<member>/preferences.md` |
|
||||
| `scaffold/anchors/member-context.seed.md` | `_agent/members/<member>/current-context.md` |
|
||||
| `scaffold/anchors/member-inbox.seed.md` | `_agent/members/<member>/inbox.md` |
|
||||
|
||||
`_agent/members/<member>/heartbeat.md` is deliberately NOT seeded — it appears at the first
|
||||
session end. The preferences seed is deliberately empty — **do not invent preferences.** Real
|
||||
facts accrue through use.
|
||||
|
||||
### 4. Vault README (human signpost)
|
||||
|
||||
|
||||
@@ -39,7 +39,7 @@ Assume clients may operate without filesystem access, through the Obsidian Local
|
||||
|
||||
The vault is a **shared** substrate — Claude Code, CoWork, and other REST API clients may operate on it concurrently. The REST API offers no transactions, so writers coordinate cooperatively:
|
||||
|
||||
- Single-line, overwrite-style files (`_agent/heartbeat/last-session.md`, `current-context.md::Scope`) and append targets (`inbox.md`, `## Agent Log`) assume **one writer at a time**. Two sessions writing at once can clobber or duplicate.
|
||||
- Single-line, overwrite-style files (`_agent/members/<member>/heartbeat.md`, `current-context.md::Scope`) and append targets (`inbox.md`, `## Agent Log`) assume **one writer at a time**. Two sessions writing at once can clobber or duplicate.
|
||||
- Before a burst of writes in a session that may overlap another, take the advisory lock (`chorus.py lock <id>` → `_agent/locks/vault.lock`) and release it at session end. The lock is read-back-confirmed and cooperative with a TTL (stale locks are reclaimable); it is a courtesy, not a hard mutex.
|
||||
- Idempotent append (read-before-POST, whole-line match, via `chorus.py append`) is the second line of defense against duplicate lines from retries or overlapping sessions.
|
||||
- Status-check every write. A write that returns `>= 400` did **not** land — surface it rather than assuming success.
|
||||
|
||||
@@ -17,8 +17,8 @@ Views of the same truth: `scripts/routing.json` is the **machine-readable canoni
|
||||
|
||||
| Path | Trigger | What lands | Distinct because | Method |
|
||||
|------|---------|------------|------------------|--------|
|
||||
| `inbox/captures/inbox.md` | "Save this, sort later" — destination genuinely unknown at capture time | One date-prefixed line | The only path whose contract is *deferred routing*; everything else here has a known home | POST |
|
||||
| `inbox/imports/<slug>.md` | Raw external material dropped in wholesale (export, paste, dump) | The raw artifact, unedited | Holds un-triaged *bulk*, vs `captures` which holds single lines | PUT |
|
||||
| `inbox/captures/group.md` | Unowned "someone should look at this" capture for the whole group | One date-prefixed **member-tagged** line (`- YYYY-MM-DD [member]: …`) | Shared deferred routing — whoever triages first routes it. Personal captures go to your own `_agent/members/<member>/inbox.md` | POST |
|
||||
| `inbox/imports/<slug>.md` | Raw external material dropped in wholesale (export, paste, dump) | The raw artifact, unedited | Holds un-triaged *bulk*, vs captures which hold single lines | PUT |
|
||||
| `inbox/processing-log/YYYY-MM-DD.md` | An inbox item is routed to its real home | One line: `<original> → <destination path>` | Audit trail of moves — never holds memory itself, only the record of routing | POST |
|
||||
|
||||
Captures and imports are temporary by contract. Triage drains them into the homes below and logs the move; the original is left until the operator okays deletion.
|
||||
@@ -79,14 +79,16 @@ Lifecycle folders; `status:` frontmatter MUST equal the folder name (the linter
|
||||
| Path | Trigger | What lands | Distinct because | Method |
|
||||
|------|---------|------------|------------------|--------|
|
||||
| `_agent/chorus-vault.md` | Bootstrap / schema migration only | Marker: `schema_version`, bootstrap date | Plugin-owned probe; never hand-edited | GET / PUT |
|
||||
| `_agent/context/current-context.md` | Active scope changes; task focus shifts | `## Scope`, `## Scope History`, priorities | Single *live* scope pointer, vs episodic which is a *past* record | PATCH / PUT |
|
||||
| `_agent/memory/semantic/operator-preferences.md` | A preference/pattern about the operator | Append under `## Observations`; promote to `## Fact / Pattern` when stable | The one curated profile; distinct from ad-hoc semantic notes | PATCH |
|
||||
| `_agent/memory/semantic/<slug>.md` | A durable fact/pattern that isn't an operator-preference | Semantic note | Timeless fact, vs episodic (time-stamped event) and working (transient) | PUT |
|
||||
| `_agent/members/<member>/current-context.md` | THIS member's active scope changes; task focus shifts | `## Scope`, `## Scope History`, priorities | Per-member live scope pointer — members work on different things concurrently | PATCH / PUT |
|
||||
| `_agent/members/<member>/preferences.md` | A preference/pattern about THIS member | Append under `## Observations`; promote to `## Fact / Pattern` when stable | The member's curated profile; only their own sessions edit it (group-visible by design) | PATCH |
|
||||
| `_agent/members/<member>/heartbeat.md` | End of every session, after the session log is written | One line: `<session-log-path> @ <ISO-timestamp>` | Per-member O(1) orientation pointer read first at load; overwritten, never grows | PUT |
|
||||
| `_agent/members/<member>/inbox.md` | THIS member's "save this, sort later" capture | One date-prefixed line | Personal deferred routing — no cross-member append contention | POST |
|
||||
| `_agent/context/<slug>.md` | Shared task bundles / reading lists for the group | Context bundle | Task-scoped shared context; the live scope itself is per member (`members/`) | PATCH / PUT |
|
||||
| `_agent/memory/semantic/<slug>.md` | A durable group fact/pattern (incl. `group-profile.md`) | Semantic note | Timeless fact, vs episodic (time-stamped event) and working (transient) | PUT |
|
||||
| `_agent/memory/episodic/<slug>.md` | A record of *what happened, when* | Episodic note | Anchored to an event in time; not a standing fact | PUT |
|
||||
| `_agent/memory/working/<slug>.md` | Short-lived state needed only for the current effort | Working note | Explicitly transient/time-boxed; safe to go stale | PUT |
|
||||
| `_agent/sessions/YYYY-MM-DD-HHMM-<slug>.md` | A substantive session ends (decisions/artifacts/commitments) | Session log (see template) | Per-session record; the unit loading Step 4 scans | PUT |
|
||||
| `_agent/health/YYYY-MM-vault-health.md` | First substantive session of a month (Vault Health pass) | Health-audit findings | Agent self-maintenance about vault integrity — NOT the operator's work narrative, so not in `journal/` | PUT |
|
||||
| `_agent/heartbeat/last-session.md` | End of every session, after the session log is written | One line: `<session-log-path> @ <ISO-timestamp>` | O(1) orientation pointer read first at load (Step 4); overwritten, never grows | PUT |
|
||||
| `_agent/sessions/<member>/YYYY-MM-DD-HHMM-<slug>.md` | A substantive session ends (decisions/artifacts/commitments) | Session log (see template) | Per-session record, namespaced by member; the unit loading's heartbeat fallback scans | PUT |
|
||||
| `_agent/health/YYYY-MM-vault-health.md` | First substantive session of a month (Vault Health pass) | Health-audit findings | Agent self-maintenance about vault integrity — NOT a work narrative, so not in `journal/` | PUT |
|
||||
| `_agent/templates/` | Bootstrap only (seeded from plugin masters) | Canonical note templates | Holds templates, not memory; never a runtime routing target | PUT (seed) |
|
||||
| `_agent/skills/active/<slug>.md` | The operator authors/installs a skill and wants it catalogued | Skill capability entry | Catalogs a *capability*, vs `projects/` which tracks the *build effort* | PUT |
|
||||
| `_agent/skills/archived/<slug>.md` | A catalogued skill is retired | Skill entry (moved from `active/`) | Terminal state of the skill catalog | PUT |
|
||||
@@ -112,6 +114,11 @@ Listed so they are recognised as dead and never recreated. Any one of these appe
|
||||
|
||||
| Path | Status | Where it went instead |
|
||||
|------|--------|-----------------------|
|
||||
| `inbox/captures/inbox.md` (single shared inbox) | Retired in schema 5 | Personal captures → `_agent/members/<member>/inbox.md`; unowned items → `inbox/captures/group.md` |
|
||||
| `_agent/memory/semantic/operator-preferences.md` | Retired in schema 5 | Per-member `_agent/members/<member>/preferences.md` |
|
||||
| `_agent/context/current-context.md` (single shared scope) | Retired in schema 5 | Per-member `_agent/members/<member>/current-context.md` |
|
||||
| `_agent/heartbeat/` (single shared pointer) | Retired in schema 5 | Per-member `_agent/members/<member>/heartbeat.md` |
|
||||
| `_agent/sessions/YYYY-MM-DD-HHMM-<slug>.md` (flat, unattributed) | Retired in schema 5 | Member-namespaced `_agent/sessions/<member>/YYYY-MM-DD-HHMM-<slug>.md` |
|
||||
| `reviews/` (weekly/monthly/quarterly/annual) | Retired in schema 2 | Journal rollups → `journal/{weekly,monthly,quarterly,annual}/`; vault-health → `_agent/health/` |
|
||||
| `decisions/by-project/` | Retired in schema 1 | ADR mirrored as a `[[wikilink]]` under the project's `## Key Decisions` |
|
||||
| `archive/` (top-level) | Never existed | Project archival → `projects/archived/`; skill archival → `_agent/skills/archived/` |
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Session Log Template
|
||||
|
||||
Session logs go in: `_agent/sessions/YYYY-MM-DD-HHMM-<slug>.md`
|
||||
Session logs go in: `_agent/sessions/<member>/YYYY-MM-DD-HHMM-<slug>.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 exist in the vault; do not edit their names, but every new write must use the full form.
|
||||
|
||||
|
||||
@@ -8,7 +8,8 @@
|
||||
/vault/
|
||||
├── README.md ← thin human signpost (NOT read for routing)
|
||||
├── inbox/
|
||||
│ ├── captures/ ← quick captures (inbox.md), date-prefixed lines
|
||||
│ ├── captures/ ← group.md — unowned group-wide captures (member-tagged lines);
|
||||
│ │ personal captures live in _agent/members/<member>/inbox.md
|
||||
│ ├── imports/ ← raw imported material
|
||||
│ └── processing-log/
|
||||
├── journal/ ← one append-only time-series stream; rollups are coarser journal entries, NOT a separate reviews/ tree
|
||||
@@ -37,23 +38,28 @@
|
||||
│ (reviews/ is retired — journal rollups live under journal/; vault-health audits under _agent/health/)
|
||||
└── _agent/
|
||||
├── chorus-vault.md ← bootstrap marker: schema_version + bootstrap date (plugin-owned; the "is this vault set up?" probe)
|
||||
├── context/ ← current-context.md and task bundles
|
||||
├── members/ ← PER-MEMBER namespaces (schema 5) — each member's churn-prone state
|
||||
│ └── <member>/
|
||||
│ ├── preferences.md ← this member's profile/preferences (group-visible)
|
||||
│ ├── current-context.md ← this member's active scope + Scope History
|
||||
│ ├── heartbeat.md ← this member's last-session pointer (written at session end)
|
||||
│ └── inbox.md ← this member's quick captures
|
||||
├── context/ ← shared task bundles / reading lists (scope itself is per member)
|
||||
├── memory/
|
||||
│ ├── working/ ← transient, time-boxed
|
||||
│ ├── episodic/ ← what happened, when
|
||||
│ └── semantic/ ← durable facts/patterns (operator-preferences.md)
|
||||
├── sessions/ ← YYYY-MM-DD-HHMM-<slug>.md
|
||||
│ └── semantic/ ← durable group facts/patterns (group-profile.md)
|
||||
├── sessions/ ← <member>/YYYY-MM-DD-HHMM-<slug>.md (member-namespaced session logs)
|
||||
├── health/ ← YYYY-MM-vault-health.md (monthly self-maintenance audit; NOT a journal entry)
|
||||
├── templates/ ← canonical note templates
|
||||
├── skills/ ← active / archived
|
||||
├── heartbeat/ ← single-line pointers (e.g. last-session.md → most-recent session log path)
|
||||
├── index/ ← entities.json — machine-maintained slug→{path,kind,title,aliases} registry
|
||||
└── locks/ ← vault.lock — cooperative advisory multi-writer lock
|
||||
```
|
||||
|
||||
**Entity index:** `_agent/index/entities.json` is a machine-maintained registry mapping each entity slug to its `{path, kind, title, aliases, last_seen}`. It makes routing/resolve an O(1), alias-aware lookup and supplies the name→path map for cross-linking and recall. `resolve` matches slug/title/alias exactly; when nothing matches exactly it falls back to **fuzzy candidates** — entities sharing a distinctive token with the mention — so a shortened name ("chorus memory" → the project `chorus`) surfaces the existing note instead of spawning a duplicate. Aliases are auto-derived from titles, learned from mentions on update, and re-folded from note frontmatter on `sweep`. It is rebuilt automatically by `chorus.py capture` and by `sweep.py`; do not hand-edit. The only JSON file in the vault.
|
||||
|
||||
**Heartbeat:** `_agent/heartbeat/last-session.md` is a one-line pointer (`<session-log-path> @ <ISO-timestamp>`) the **session-logging procedure writes (PUT, overwrite) at session end** and the **loading procedure reads first (Step 4)** as an O(1) shortcut to the latest session log. It is a hint, not a source of truth — fall back to the `sessions/` directory listing if it's missing or stale. Because it's PUT-overwritten, it never grows or duplicates.
|
||||
**Heartbeat:** `_agent/members/<member>/heartbeat.md` is a one-line pointer (`<session-log-path> @ <ISO-timestamp>`) the **session-logging procedure writes (PUT, overwrite) at session end** and the **loading procedure reads first (Step 4)** as an O(1) shortcut to the latest session log. It is a hint, not a source of truth — fall back to the `sessions/` directory listing if it's missing or stale. Because it's PUT-overwritten, it never grows or duplicates.
|
||||
|
||||
**Slug rules:** kebab-case, ASCII only, truncate to ~40 chars.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user