feat: Obsidian integration via cli scripts
This commit is contained in:
@@ -13,10 +13,14 @@ Behavior rules:
|
|||||||
- Treat `core/` as the reusable project-independent operating model.
|
- Treat `core/` as the reusable project-independent operating model.
|
||||||
- Treat `profiles/fidelity/profile.md` as the active Fidelity project profile.
|
- Treat `profiles/fidelity/profile.md` as the active Fidelity project profile.
|
||||||
- Treat `vault/` as the canonical clean knowledge base for humans and AI.
|
- Treat `vault/` as the canonical clean knowledge base for humans and AI.
|
||||||
|
- Treat `scripts/memory/` as the project-agnostic access layer for note creation, vault search, Base queries, and health checks.
|
||||||
|
- Treat `scripts/obsidian/` as the current Obsidian adapter. Do not couple durable memory rules to Obsidian-specific behavior.
|
||||||
- Treat `ai/inbox/` and generated connector files as raw evidence only, not promoted memory.
|
- Treat `ai/inbox/` and generated connector files as raw evidence only, not promoted memory.
|
||||||
- Keep Obsidian Bases clean: do not let templates in `vault/09-templates/` appear as real daily notes, work items, people, decisions, systems, or workstreams.
|
- Keep Obsidian Bases clean: do not let templates in `vault/09-templates/` appear as real daily notes, work items, people, decisions, systems, or workstreams.
|
||||||
- Role mapping notes such as `vault/04-people/manager.md` are `type: role-map`; actual people profiles are `type: person`.
|
- Role mapping notes such as `vault/04-people/manager.md` are `type: role-map`; actual people profiles are `type: person`.
|
||||||
- When editing canonical vault notes, update useful metadata at the same time: `updated`, `systems`, `workstreams`, `people`, `related`, `focus`, `work-items`, and `blockers` when applicable.
|
- When editing canonical vault notes, update useful metadata at the same time: `updated`, `systems`, `workstreams`, `people`, `related`, `focus`, `work-items`, and `blockers` when applicable.
|
||||||
|
- When creating a new typed note, prefer `bash scripts/memory/memory.sh create <type> <slug> [title]`, then inspect and refine the generated Markdown.
|
||||||
|
- When checking vault quality, use `bash scripts/memory/memory.sh health` and direct file inspection.
|
||||||
- Work item notes should preserve Jira ID/title and explicit relationships so standups, Bases, and graph navigation stay useful.
|
- Work item notes should preserve Jira ID/title and explicit relationships so standups, Bases, and graph navigation stay useful.
|
||||||
- Daily notes should include `focus`, `work-items`, and `blockers` when those values are clear.
|
- Daily notes should include `focus`, `work-items`, and `blockers` when those values are clear.
|
||||||
- Before answering a prompt that depends on current state, verify the latest relevant files instead of relying only on conversation history.
|
- Before answering a prompt that depends on current state, verify the latest relevant files instead of relying only on conversation history.
|
||||||
@@ -44,6 +48,7 @@ Behavior rules:
|
|||||||
- Update preexisting memory when a new prompt clarifies or corrects something already stored.
|
- Update preexisting memory when a new prompt clarifies or corrects something already stored.
|
||||||
- Do not wait for a dedicated sync command if the correct memory update is already obvious.
|
- Do not wait for a dedicated sync command if the correct memory update is already obvious.
|
||||||
- Do not leave behavior-only corrections only in daily logs. If a correction should affect future output, update the tool or instruction that produces that output.
|
- Do not leave behavior-only corrections only in daily logs. If a correction should affect future output, update the tool or instruction that produces that output.
|
||||||
|
- If the memory interface or Obsidian adapter fails, continue with direct Markdown operations when safe and do not promote the failure as project memory.
|
||||||
- Do not over-promote uncertain information. Keep uncertain items in the daily log.
|
- Do not over-promote uncertain information. Keep uncertain items in the daily log.
|
||||||
- When drafting communication, preserve technical meaning and improve clarity in natural US English.
|
- When drafting communication, preserve technical meaning and improve clarity in natural US English.
|
||||||
- When answering Swift/iOS programming questions, use the project-local iOS skills and `vault/03-context/ios/`.
|
- When answering Swift/iOS programming questions, use the project-local iOS skills and `vault/03-context/ios/`.
|
||||||
|
|||||||
@@ -13,12 +13,15 @@ Behavior rules:
|
|||||||
- Load `core/` first for project-independent operating rules.
|
- Load `core/` first for project-independent operating rules.
|
||||||
- Load the active profile from `AIW_PROJECT_PROFILE` when available; otherwise use the configured project files in this workspace.
|
- Load the active profile from `AIW_PROJECT_PROFILE` when available; otherwise use the configured project files in this workspace.
|
||||||
- Treat `vault/` as the canonical clean knowledge base.
|
- Treat `vault/` as the canonical clean knowledge base.
|
||||||
|
- Treat `scripts/memory/` as the stable memory access layer.
|
||||||
|
- Treat tool-specific integrations such as Obsidian as replaceable adapters.
|
||||||
- Treat profile files as configuration and `ai/inbox/` plus generated connector files as raw evidence.
|
- Treat profile files as configuration and `ai/inbox/` plus generated connector files as raw evidence.
|
||||||
- Keep Obsidian Bases clean by excluding templates and typing role maps separately from people.
|
- Keep Obsidian Bases clean by excluding templates and typing role maps separately from people.
|
||||||
- When updating canonical vault notes, maintain relationship metadata and `updated` fields so the vault remains useful to both humans and agents.
|
- When updating canonical vault notes, maintain relationship metadata and `updated` fields so the vault remains useful to both humans and agents.
|
||||||
- Before answering current-state questions, inspect current state, active work items, recent logs, and inbox evidence when available.
|
- Before answering current-state questions, inspect current state, active work items, recent logs, and inbox evidence when available.
|
||||||
- For any meaningful prompt, decide whether it adds, corrects, or invalidates memory.
|
- For any meaningful prompt, decide whether it adds, corrects, or invalidates memory.
|
||||||
- Update the smallest correct canonical file when memory should change.
|
- Update the smallest correct canonical file when memory should change.
|
||||||
|
- Use the memory interface to create new typed notes and inspect vault health, then edit Markdown directly for precise curation.
|
||||||
- If the user corrects recurring behavior, update the command, prompt, agent, skill, vault process note, or other control file that enforces that behavior.
|
- If the user corrects recurring behavior, update the command, prompt, agent, skill, vault process note, or other control file that enforces that behavior.
|
||||||
- Keep imported evidence separate from promoted memory.
|
- Keep imported evidence separate from promoted memory.
|
||||||
- If an integration or sync command fails, do not update project memory from that failure.
|
- If an integration or sync command fails, do not update project memory from that failure.
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ Use these files as the baseline context:
|
|||||||
@README.md
|
@README.md
|
||||||
@core/README.md
|
@core/README.md
|
||||||
@core/memory/operational-memory.md
|
@core/memory/operational-memory.md
|
||||||
|
@core/integrations/memory-vault-model.md
|
||||||
@core/integrations/communication-model.md
|
@core/integrations/communication-model.md
|
||||||
@profiles/fidelity/profile.md
|
@profiles/fidelity/profile.md
|
||||||
@vault/00-start/start-here.md
|
@vault/00-start/start-here.md
|
||||||
|
|||||||
@@ -7,6 +7,8 @@ Slash commands available in this workspace.
|
|||||||
## Generic Commands
|
## Generic Commands
|
||||||
|
|
||||||
- [Workspace Context](workspace-context.md)
|
- [Workspace Context](workspace-context.md)
|
||||||
|
- [Memory Health](memory-health.md)
|
||||||
|
- [Memory Create](memory-create.md)
|
||||||
- [Communication Sync](communication-sync.md)
|
- [Communication Sync](communication-sync.md)
|
||||||
- [Archive Import](archive-import.md)
|
- [Archive Import](archive-import.md)
|
||||||
- [AI Prompt](ai-prompt.md)
|
- [AI Prompt](ai-prompt.md)
|
||||||
|
|||||||
43
.opencode/commands/memory-create.md
Normal file
43
.opencode/commands/memory-create.md
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
---
|
||||||
|
description: Create a canonical memory note using the project-agnostic memory interface
|
||||||
|
---
|
||||||
|
|
||||||
|
Create a new canonical memory note from a known type.
|
||||||
|
|
||||||
|
Supported types:
|
||||||
|
|
||||||
|
- `daily`
|
||||||
|
- `work-item`
|
||||||
|
- `person`
|
||||||
|
- `decision`
|
||||||
|
- `system`
|
||||||
|
- `workstream`
|
||||||
|
- `meeting-note`
|
||||||
|
|
||||||
|
User request:
|
||||||
|
|
||||||
|
$ARGUMENTS
|
||||||
|
|
||||||
|
Read:
|
||||||
|
|
||||||
|
@core/integrations/memory-vault-model.md
|
||||||
|
@vault/00-start/workspace-architecture.md
|
||||||
|
@vault/09-templates/work-item.md
|
||||||
|
@vault/09-templates/person.md
|
||||||
|
@vault/09-templates/decision.md
|
||||||
|
@vault/09-templates/system.md
|
||||||
|
@vault/09-templates/workstream.md
|
||||||
|
|
||||||
|
Instructions:
|
||||||
|
|
||||||
|
- Parse the requested type, slug, and title from `$ARGUMENTS`.
|
||||||
|
- Use `bash scripts/memory/memory.sh create <type> <slug> [title]` when type and slug are clear.
|
||||||
|
- If type or slug is not clear, do not guess. Explain the expected format.
|
||||||
|
- After creation, inspect the generated file and update metadata/content if the user provided enough context.
|
||||||
|
- Keep the note in the canonical folder selected by the memory interface.
|
||||||
|
|
||||||
|
Return:
|
||||||
|
|
||||||
|
1. Created file
|
||||||
|
2. Any metadata/content refined
|
||||||
|
3. Any missing details the user may want to add
|
||||||
27
.opencode/commands/memory-health.md
Normal file
27
.opencode/commands/memory-health.md
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
---
|
||||||
|
description: Check canonical memory health and Obsidian adapter status
|
||||||
|
---
|
||||||
|
|
||||||
|
Run a lightweight health check for the canonical memory vault.
|
||||||
|
|
||||||
|
Read:
|
||||||
|
|
||||||
|
@core/integrations/memory-vault-model.md
|
||||||
|
@core/integrations/obsidian-model.md
|
||||||
|
@vault/00-start/workspace-architecture.md
|
||||||
|
|
||||||
|
Run:
|
||||||
|
|
||||||
|
!`bash scripts/memory/memory.sh health`
|
||||||
|
|
||||||
|
Structured views:
|
||||||
|
|
||||||
|
!`for base in work-items people decisions daily systems workstreams; do echo "\n## $base"; bash scripts/memory/memory.sh base-query "$base" paths 2>/dev/null || bash scripts/memory/memory.sh base-query "$base" 2>/dev/null || true; done`
|
||||||
|
|
||||||
|
Respond with:
|
||||||
|
|
||||||
|
1. Health status
|
||||||
|
2. Any issues that should be fixed now
|
||||||
|
3. Any optional Obsidian-only improvements
|
||||||
|
|
||||||
|
Do not modify project memory unless the user explicitly asks for cleanup.
|
||||||
@@ -8,6 +8,7 @@ Read core:
|
|||||||
|
|
||||||
@core/README.md
|
@core/README.md
|
||||||
@core/memory/operational-memory.md
|
@core/memory/operational-memory.md
|
||||||
|
@core/integrations/memory-vault-model.md
|
||||||
@core/integrations/communication-model.md
|
@core/integrations/communication-model.md
|
||||||
@core/profiles/create-project-profile.md
|
@core/profiles/create-project-profile.md
|
||||||
|
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ The detailed operating rules live in:
|
|||||||
- `vault/03-context/process/ai-to-ai-prompting.md`
|
- `vault/03-context/process/ai-to-ai-prompting.md`
|
||||||
- `vault/03-context/process/workspace-model.md`
|
- `vault/03-context/process/workspace-model.md`
|
||||||
- `vault/03-context/process/memory-promotion-rules.md`
|
- `vault/03-context/process/memory-promotion-rules.md`
|
||||||
|
- `core/integrations/memory-vault-model.md`
|
||||||
- `vault/04-people/manager.md`
|
- `vault/04-people/manager.md`
|
||||||
- `vault/04-people/index.md`
|
- `vault/04-people/index.md`
|
||||||
- `vault/02-work-items/index.md`
|
- `vault/02-work-items/index.md`
|
||||||
@@ -37,6 +38,8 @@ These are also loaded through `opencode.json`.
|
|||||||
|
|
||||||
- Assume the workspace may contain stale context until checked.
|
- Assume the workspace may contain stale context until checked.
|
||||||
- Treat `vault/` as the canonical clean memory for humans and AI. Treat `ai/inbox/` as raw evidence only.
|
- Treat `vault/` as the canonical clean memory for humans and AI. Treat `ai/inbox/` as raw evidence only.
|
||||||
|
- Treat `scripts/memory/` as the project-agnostic interface for creating notes, searching memory, querying Bases, and running vault health checks.
|
||||||
|
- Treat `scripts/obsidian/` as the current Obsidian adapter, not as the core memory abstraction.
|
||||||
- Keep Obsidian Bases clean: templates in `vault/09-templates/` must not be treated as real notes, and role mapping files such as `vault/04-people/manager.md` must not be typed as people.
|
- Keep Obsidian Bases clean: templates in `vault/09-templates/` must not be treated as real notes, and role mapping files such as `vault/04-people/manager.md` must not be typed as people.
|
||||||
- Maintain useful vault properties when editing canonical notes, especially work-item relationships (`systems`, `workstreams`, `people`, `related`) and daily note fields (`focus`, `work-items`, `blockers`).
|
- Maintain useful vault properties when editing canonical notes, especially work-item relationships (`systems`, `workstreams`, `people`, `related`) and daily note fields (`focus`, `work-items`, `blockers`).
|
||||||
- Before answering questions that depend on current work state, inspect `vault/01-current/current-work.md` and the latest relevant daily note under `vault/06-daily/`.
|
- Before answering questions that depend on current work state, inspect `vault/01-current/current-work.md` and the latest relevant daily note under `vault/06-daily/`.
|
||||||
@@ -58,6 +61,8 @@ These are also loaded through `opencode.json`.
|
|||||||
- If a new prompt corrects prior understanding, update the canonical file directly instead of keeping both versions alive.
|
- If a new prompt corrects prior understanding, update the canonical file directly instead of keeping both versions alive.
|
||||||
- Do not ask what should be saved when the correct destination is already clear.
|
- Do not ask what should be saved when the correct destination is already clear.
|
||||||
- If the user provides durable new facts, update the appropriate context files instead of leaving the new information only in chat history.
|
- If the user provides durable new facts, update the appropriate context files instead of leaving the new information only in chat history.
|
||||||
|
- When creating a new canonical note from a known type, prefer `scripts/memory/memory.sh create <type> <slug> [title]` so type-to-folder routing stays centralized.
|
||||||
|
- If the Obsidian CLI adapter fails, fall back to direct Markdown operations and treat the failure as tooling status, not project context.
|
||||||
- If a previous context file is now stale or inaccurate, update that file directly.
|
- If a previous context file is now stale or inaccurate, update that file directly.
|
||||||
- Prefer correcting canonical context over appending contradictory notes.
|
- Prefer correcting canonical context over appending contradictory notes.
|
||||||
- Keep changes concise and auditable.
|
- Keep changes concise and auditable.
|
||||||
|
|||||||
21
README.md
21
README.md
@@ -119,7 +119,12 @@ Repeatable working guides for:
|
|||||||
|
|
||||||
### /scripts
|
### /scripts
|
||||||
|
|
||||||
Helpers for future automation around context generation and communication drafting.
|
Helpers for automation around memory access, context generation, communication drafting, and imports.
|
||||||
|
|
||||||
|
- `scripts/memory/` -> project-agnostic interface for canonical memory
|
||||||
|
- `scripts/obsidian/` -> current Obsidian adapter and URI helpers
|
||||||
|
- `scripts/mattermost/` -> live communication connector
|
||||||
|
- `scripts/slack/` -> historical archive importer
|
||||||
|
|
||||||
### /vault/.obsidian
|
### /vault/.obsidian
|
||||||
|
|
||||||
@@ -129,6 +134,8 @@ Open `vault/` as the Obsidian vault. Do not open the repository root as the vaul
|
|||||||
|
|
||||||
Portable vault configuration can be versioned, while local layout and plugin runtime files are ignored.
|
Portable vault configuration can be versioned, while local layout and plugin runtime files are ignored.
|
||||||
|
|
||||||
|
Obsidian is the current visual interface over canonical memory. The reusable memory access layer is `scripts/memory/`, so the workspace can later swap Obsidian for another Markdown knowledge tool without changing the memory model.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Daily Usage
|
## Daily Usage
|
||||||
@@ -218,6 +225,8 @@ This keeps AI output tied to the latest workspace state instead of relying on ch
|
|||||||
## Generic Commands
|
## Generic Commands
|
||||||
|
|
||||||
- `/workspace-context` -> load core plus active profile
|
- `/workspace-context` -> load core plus active profile
|
||||||
|
- `/memory-health` -> check canonical memory and adapter health
|
||||||
|
- `/memory-create` -> create a typed canonical note through the memory interface
|
||||||
- `/communication-sync` -> sync live communication evidence and promote high-confidence memory
|
- `/communication-sync` -> sync live communication evidence and promote high-confidence memory
|
||||||
- `/archive-import` -> import historical archive evidence
|
- `/archive-import` -> import historical archive evidence
|
||||||
- `/ai-prompt` -> generate a self-contained prompt for another AI
|
- `/ai-prompt` -> generate a self-contained prompt for another AI
|
||||||
@@ -293,8 +302,16 @@ Runtime/evidence stays outside the vault:
|
|||||||
|
|
||||||
Ignored Obsidian runtime files include workspace layout, plugin cache, snippets, and local plugin installs.
|
Ignored Obsidian runtime files include workspace layout, plugin cache, snippets, and local plugin installs.
|
||||||
|
|
||||||
Obsidian URI helpers live under `scripts/obsidian/`:
|
Project-agnostic memory helpers live under `scripts/memory/`:
|
||||||
|
|
||||||
|
- `scripts/memory/memory.sh create <type> <slug> [title]`
|
||||||
|
- `scripts/memory/memory.sh search <query> [folder]`
|
||||||
|
- `scripts/memory/memory.sh base-query <base-name> [format]`
|
||||||
|
- `scripts/memory/memory.sh health`
|
||||||
|
|
||||||
|
Obsidian adapter helpers live under `scripts/obsidian/`:
|
||||||
|
|
||||||
|
- `scripts/obsidian/cli.sh <obsidian-cli-command>`
|
||||||
- `scripts/obsidian/open.sh <vault-relative-path>`
|
- `scripts/obsidian/open.sh <vault-relative-path>`
|
||||||
- `scripts/obsidian/daily.sh`
|
- `scripts/obsidian/daily.sh`
|
||||||
- `scripts/obsidian/search.sh <query>`
|
- `scripts/obsidian/search.sh <query>`
|
||||||
|
|||||||
@@ -64,3 +64,5 @@ See `core/integrations/communication-model.md` for the reusable connector contra
|
|||||||
Optional navigation layers such as Obsidian should read the same Markdown files instead of copying memory into a second store.
|
Optional navigation layers such as Obsidian should read the same Markdown files instead of copying memory into a second store.
|
||||||
|
|
||||||
See `core/integrations/obsidian-model.md` for the recommended vault model.
|
See `core/integrations/obsidian-model.md` for the recommended vault model.
|
||||||
|
|
||||||
|
The project-agnostic memory interface lives in `scripts/memory/` and is documented in `core/integrations/memory-vault-model.md`. Agents should use that interface for note creation, vault search, Base queries, and health checks, while still editing Markdown directly for precise curation.
|
||||||
|
|||||||
92
core/integrations/memory-vault-model.md
Normal file
92
core/integrations/memory-vault-model.md
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
# Memory Vault Integration Model
|
||||||
|
|
||||||
|
## Purpose
|
||||||
|
|
||||||
|
Define a project-agnostic interface for reading, creating, searching, and validating the canonical Markdown memory.
|
||||||
|
|
||||||
|
Obsidian is the current human-facing implementation, but the workspace should not depend on Obsidian-specific behavior for core memory maintenance.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Layers
|
||||||
|
|
||||||
|
### Canonical Memory
|
||||||
|
|
||||||
|
The source of truth is plain Markdown under `vault/`.
|
||||||
|
|
||||||
|
Agents should edit canonical notes directly when precision matters because direct edits produce auditable diffs.
|
||||||
|
|
||||||
|
### Memory Interface
|
||||||
|
|
||||||
|
Use `scripts/memory/memory.sh` for vault-level operations:
|
||||||
|
|
||||||
|
- `root` prints the configured memory root
|
||||||
|
- `read <path>` reads a vault-relative note
|
||||||
|
- `search <query> [folder]` searches memory
|
||||||
|
- `create <type> <slug> [title]` creates a note in the canonical folder from the matching template
|
||||||
|
- `base-query <base-name> [format]` queries a structured view when supported
|
||||||
|
- `health` checks required files and optional navigation health
|
||||||
|
|
||||||
|
### Tool Adapter
|
||||||
|
|
||||||
|
The current adapter is Obsidian CLI through `scripts/obsidian/cli.sh`.
|
||||||
|
|
||||||
|
If Obsidian CLI is unavailable or fails, `scripts/memory/memory.sh` falls back to direct Markdown operations unless `AIW_MEMORY_BACKEND=obsidian` is explicitly set.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
- `AIW_MEMORY_VAULT_DIR`: canonical memory directory. Defaults to `<workspace-root>/vault`.
|
||||||
|
- `AIW_MEMORY_BACKEND`: `auto`, `files`, or `obsidian`. Defaults to `auto`.
|
||||||
|
- `AIW_OBSIDIAN_VAULT_DIR`: Obsidian-specific vault override, still supported by the adapter.
|
||||||
|
- `AIW_OBSIDIAN_VAULT_NAME`: Obsidian URI vault name override for URI wrappers.
|
||||||
|
|
||||||
|
Backend meanings:
|
||||||
|
|
||||||
|
- `auto`: use Obsidian CLI when useful and available; otherwise use direct Markdown.
|
||||||
|
- `files`: force direct Markdown behavior.
|
||||||
|
- `obsidian`: require Obsidian CLI for supported operations and fail if unavailable.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Note Type Routing
|
||||||
|
|
||||||
|
The memory interface owns type-to-folder routing:
|
||||||
|
|
||||||
|
- `daily` -> `vault/06-daily/`
|
||||||
|
- `work-item` -> `vault/02-work-items/`
|
||||||
|
- `person` -> `vault/04-people/`
|
||||||
|
- `decision` -> `vault/05-decisions/`
|
||||||
|
- `system` -> `vault/03-context/systems/`
|
||||||
|
- `workstream` -> `vault/03-context/workstreams/`
|
||||||
|
- `meeting-note` -> `vault/06-daily/`
|
||||||
|
|
||||||
|
Templates live in `vault/09-templates/`.
|
||||||
|
|
||||||
|
This gives agents an automatic destination for new notes without coupling the rule to Obsidian.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Agent Rules
|
||||||
|
|
||||||
|
- Use the memory interface when creating new canonical notes from a known type.
|
||||||
|
- Use the memory interface for broad search, Base queries, and vault health checks.
|
||||||
|
- Edit Markdown directly for precise memory curation, corrections, and content updates.
|
||||||
|
- Do not treat Obsidian CLI failure as project context.
|
||||||
|
- Do not require Obsidian to be running for core workspace operation.
|
||||||
|
- Keep raw evidence outside `vault/`; promote only curated memory.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Useful Obsidian CLI Operations
|
||||||
|
|
||||||
|
When available, Obsidian CLI improves human-facing memory workflows:
|
||||||
|
|
||||||
|
- `search:context` gives Obsidian-aware search context.
|
||||||
|
- `create path=... template=...` creates notes from templates.
|
||||||
|
- `base:query` reads Bases as structured views.
|
||||||
|
- `properties` and `property:*` inspect or update metadata.
|
||||||
|
- `unresolved`, `orphans`, `links`, `backlinks`, and `tags` support vault health checks.
|
||||||
|
|
||||||
|
These are optional enhancements. The canonical memory remains Markdown.
|
||||||
@@ -126,11 +126,23 @@ Do not use Bases for raw inboxes, generated evidence, scripts, or runtime logs.
|
|||||||
|
|
||||||
## CLI Wrappers
|
## CLI Wrappers
|
||||||
|
|
||||||
Use `scripts/obsidian/` for non-interactive Obsidian URI helpers:
|
Use `scripts/memory/` as the project-agnostic memory interface.
|
||||||
|
|
||||||
|
Use `scripts/obsidian/` only as the current Obsidian adapter:
|
||||||
|
|
||||||
|
- `cli.sh` runs the official Obsidian CLI from the configured vault directory.
|
||||||
- `uri.sh` generates encoded Obsidian URIs.
|
- `uri.sh` generates encoded Obsidian URIs.
|
||||||
- `open.sh <vault-relative-path>` opens a note.
|
- `open.sh <vault-relative-path>` opens a note through Obsidian URI.
|
||||||
- `daily.sh` opens the configured daily note.
|
- `daily.sh` opens the configured daily note through Obsidian URI.
|
||||||
- `search.sh <query>` opens Obsidian search.
|
- `search.sh <query>` opens Obsidian search through Obsidian URI.
|
||||||
|
|
||||||
The wrappers default to `vault/` and can be overridden with `AIW_OBSIDIAN_VAULT_DIR` and `AIW_OBSIDIAN_VAULT_NAME`.
|
The memory interface can use Obsidian CLI when available and fall back to direct Markdown operations when it is not.
|
||||||
|
|
||||||
|
The agent should depend on `scripts/memory/memory.sh` for portable operations:
|
||||||
|
|
||||||
|
- `create <type> <slug> [title]`
|
||||||
|
- `search <query> [folder]`
|
||||||
|
- `base-query <base-name> [format]`
|
||||||
|
- `health`
|
||||||
|
|
||||||
|
This keeps Obsidian replaceable while still making the current vault easier to use.
|
||||||
|
|||||||
@@ -58,6 +58,8 @@ Use generic variables first:
|
|||||||
|
|
||||||
```text
|
```text
|
||||||
AIW_PROJECT_PROFILE=<project>
|
AIW_PROJECT_PROFILE=<project>
|
||||||
|
AIW_MEMORY_VAULT_DIR=<optional custom vault path>
|
||||||
|
AIW_MEMORY_BACKEND=auto
|
||||||
AIW_CHANNEL_PREFIX=<project-or-team-prefix>
|
AIW_CHANNEL_PREFIX=<project-or-team-prefix>
|
||||||
AIW_MATTERMOST_SYNC_CMD=<optional custom command>
|
AIW_MATTERMOST_SYNC_CMD=<optional custom command>
|
||||||
AIW_SLACK_EXPORT_PATH=<optional archive path>
|
AIW_SLACK_EXPORT_PATH=<optional archive path>
|
||||||
@@ -72,6 +74,8 @@ Connector secrets belong in ignored `.env` files, not in profile files.
|
|||||||
Start with generic commands:
|
Start with generic commands:
|
||||||
|
|
||||||
- `/workspace-context`
|
- `/workspace-context`
|
||||||
|
- `/memory-health`
|
||||||
|
- `/memory-create`
|
||||||
- `/communication-sync`
|
- `/communication-sync`
|
||||||
- `/archive-import`
|
- `/archive-import`
|
||||||
- `/standup`
|
- `/standup`
|
||||||
@@ -92,6 +96,7 @@ Before using the workspace for real work:
|
|||||||
- run a communication sync with test channels or a dry sample
|
- run a communication sync with test channels or a dry sample
|
||||||
- generate one standup from sample context
|
- generate one standup from sample context
|
||||||
- verify that imported evidence and promoted memory stay separate
|
- verify that imported evidence and promoted memory stay separate
|
||||||
|
- run `bash scripts/memory/memory.sh health`
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -99,6 +104,8 @@ Before using the workspace for real work:
|
|||||||
|
|
||||||
Open `vault/` as the Obsidian vault.
|
Open `vault/` as the Obsidian vault.
|
||||||
|
|
||||||
|
Use `scripts/memory/` as the project-agnostic memory interface. Obsidian is the default visual and CLI-backed adapter, but profile logic should not depend on Obsidian.
|
||||||
|
|
||||||
Recommended rules:
|
Recommended rules:
|
||||||
|
|
||||||
- keep `vault/` as the clean canonical human/AI memory
|
- keep `vault/` as the clean canonical human/AI memory
|
||||||
|
|||||||
@@ -43,6 +43,7 @@
|
|||||||
"./README.md",
|
"./README.md",
|
||||||
"./core/README.md",
|
"./core/README.md",
|
||||||
"./core/memory/operational-memory.md",
|
"./core/memory/operational-memory.md",
|
||||||
|
"./core/integrations/memory-vault-model.md",
|
||||||
"./core/integrations/communication-model.md",
|
"./core/integrations/communication-model.md",
|
||||||
"./core/integrations/obsidian-model.md",
|
"./core/integrations/obsidian-model.md",
|
||||||
"./core/profiles/create-project-profile.md",
|
"./core/profiles/create-project-profile.md",
|
||||||
|
|||||||
@@ -70,6 +70,8 @@ Core Fidelity context remains in:
|
|||||||
|
|
||||||
Raw communication evidence remains outside the vault under `ai/inbox/` and generated connector folders.
|
Raw communication evidence remains outside the vault under `ai/inbox/` and generated connector folders.
|
||||||
|
|
||||||
|
Memory access should go through the project-agnostic `scripts/memory/` interface for note creation, search, Base queries, and health checks. Obsidian is the current visual and CLI adapter, not a Fidelity-specific dependency.
|
||||||
|
|
||||||
Important domain themes:
|
Important domain themes:
|
||||||
|
|
||||||
- Fid4 consumer validation
|
- Fid4 consumer validation
|
||||||
@@ -87,6 +89,8 @@ Important domain themes:
|
|||||||
Generic commands:
|
Generic commands:
|
||||||
|
|
||||||
- `/workspace-context`
|
- `/workspace-context`
|
||||||
|
- `/memory-health`
|
||||||
|
- `/memory-create`
|
||||||
- `/communication-sync`
|
- `/communication-sync`
|
||||||
- `/archive-import`
|
- `/archive-import`
|
||||||
- `/ai-prompt`
|
- `/ai-prompt`
|
||||||
|
|||||||
@@ -3,11 +3,26 @@
|
|||||||
This directory contains helpers that automate:
|
This directory contains helpers that automate:
|
||||||
|
|
||||||
- context aggregation
|
- context aggregation
|
||||||
|
- canonical memory access
|
||||||
- standup generation
|
- standup generation
|
||||||
- manager update drafting
|
- manager update drafting
|
||||||
- Mattermost-ready message formatting
|
- Mattermost-ready message formatting
|
||||||
- historical Slack import
|
- historical Slack import
|
||||||
|
|
||||||
|
The project-agnostic memory interface lives in:
|
||||||
|
|
||||||
|
- `scripts/memory/`
|
||||||
|
|
||||||
|
Recommended commands:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
bash scripts/memory/memory.sh health
|
||||||
|
bash scripts/memory/memory.sh search "PDIAP-15765"
|
||||||
|
bash scripts/memory/memory.sh create work-item pdiap-15999 "Example title"
|
||||||
|
```
|
||||||
|
|
||||||
|
This interface defaults to Markdown files under `vault/`, uses Obsidian CLI when useful and available, and falls back to direct file operations.
|
||||||
|
|
||||||
The default workspace Mattermost extractor now lives in:
|
The default workspace Mattermost extractor now lives in:
|
||||||
|
|
||||||
- `scripts/mattermost/`
|
- `scripts/mattermost/`
|
||||||
|
|||||||
42
scripts/memory/README.md
Normal file
42
scripts/memory/README.md
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
# Memory Scripts
|
||||||
|
|
||||||
|
This directory exposes a project-agnostic interface for the canonical memory vault.
|
||||||
|
|
||||||
|
The current implementation uses Markdown files under `vault/` and can optionally delegate to the Obsidian CLI when it is available. The agent should depend on this memory interface, not on Obsidian-specific behavior, so the backing tool can be replaced later.
|
||||||
|
|
||||||
|
## Backend Model
|
||||||
|
|
||||||
|
- `AIW_MEMORY_VAULT_DIR` points to the canonical Markdown memory directory.
|
||||||
|
- `AIW_MEMORY_BACKEND` defaults to `auto`.
|
||||||
|
- `auto` uses Obsidian CLI when it is useful and available, then falls back to direct Markdown operations.
|
||||||
|
- `files` forces direct Markdown operations.
|
||||||
|
- `obsidian` requires the Obsidian CLI for supported operations.
|
||||||
|
|
||||||
|
## Commands
|
||||||
|
|
||||||
|
```bash
|
||||||
|
bash scripts/memory/memory.sh root
|
||||||
|
bash scripts/memory/memory.sh read 01-current/current-work.md
|
||||||
|
bash scripts/memory/memory.sh search "PDIAP-15765"
|
||||||
|
bash scripts/memory/memory.sh create work-item pdiap-15999 "Example title"
|
||||||
|
bash scripts/memory/memory.sh base-query work-items
|
||||||
|
bash scripts/memory/memory.sh health
|
||||||
|
```
|
||||||
|
|
||||||
|
## Note Creation
|
||||||
|
|
||||||
|
`create` maps note types to canonical folders and templates:
|
||||||
|
|
||||||
|
- `daily` -> `06-daily/`
|
||||||
|
- `work-item` -> `02-work-items/`
|
||||||
|
- `person` -> `04-people/`
|
||||||
|
- `decision` -> `05-decisions/`
|
||||||
|
- `system` -> `03-context/systems/`
|
||||||
|
- `workstream` -> `03-context/workstreams/`
|
||||||
|
- `meeting-note` -> `06-daily/`
|
||||||
|
|
||||||
|
The template is resolved from `09-templates/<type>.md`. When Obsidian CLI is available, the script uses `obsidian create path=... template=...`. Otherwise it creates the file directly from the template and resolves the basic `{{title}}`, `{{date}}`, and `{{time}}` variables.
|
||||||
|
|
||||||
|
## Agent Rule
|
||||||
|
|
||||||
|
Use these scripts for vault-level operations such as creating notes, querying Bases, validating navigation health, and searching memory. For precise content edits, agents should still edit Markdown files directly so diffs remain auditable.
|
||||||
335
scripts/memory/memory.sh
Executable file
335
scripts/memory/memory.sh
Executable file
@@ -0,0 +1,335 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
WORKSPACE_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
||||||
|
VAULT_DIR="${AIW_MEMORY_VAULT_DIR:-${AIW_OBSIDIAN_VAULT_DIR:-$WORKSPACE_ROOT/vault}}"
|
||||||
|
BACKEND="${AIW_MEMORY_BACKEND:-auto}"
|
||||||
|
OBSIDIAN_CLI="$WORKSPACE_ROOT/scripts/obsidian/cli.sh"
|
||||||
|
|
||||||
|
usage() {
|
||||||
|
cat >&2 <<'EOF'
|
||||||
|
usage: memory.sh <command> [args]
|
||||||
|
|
||||||
|
commands:
|
||||||
|
root
|
||||||
|
read <vault-relative-path>
|
||||||
|
search <query> [folder]
|
||||||
|
create <type> <slug> [title]
|
||||||
|
base-query <base-name> [format]
|
||||||
|
health
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
die() {
|
||||||
|
echo "$*" >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
ensure_vault() {
|
||||||
|
[[ -d "$VAULT_DIR" ]] || die "vault directory not found: $VAULT_DIR"
|
||||||
|
}
|
||||||
|
|
||||||
|
has_obsidian() {
|
||||||
|
[[ "$BACKEND" != "files" ]] && command -v obsidian >/dev/null 2>&1 && [[ -x "$OBSIDIAN_CLI" ]]
|
||||||
|
}
|
||||||
|
|
||||||
|
require_obsidian_if_forced() {
|
||||||
|
if [[ "$BACKEND" == "obsidian" ]] && ! has_obsidian; then
|
||||||
|
die "AIW_MEMORY_BACKEND=obsidian but Obsidian CLI is unavailable"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
safe_path() {
|
||||||
|
local rel="$1"
|
||||||
|
[[ "$rel" != /* ]] || die "path must be vault-relative: $rel"
|
||||||
|
[[ "$rel" != *".."* ]] || die "path must not contain '..': $rel"
|
||||||
|
printf '%s/%s\n' "$VAULT_DIR" "$rel"
|
||||||
|
}
|
||||||
|
|
||||||
|
template_name_for_type() {
|
||||||
|
case "$1" in
|
||||||
|
daily) echo "daily" ;;
|
||||||
|
work-item) echo "work-item" ;;
|
||||||
|
person) echo "person" ;;
|
||||||
|
decision) echo "decision" ;;
|
||||||
|
system) echo "system" ;;
|
||||||
|
workstream) echo "workstream" ;;
|
||||||
|
meeting-note) echo "meeting-note" ;;
|
||||||
|
*) die "unsupported note type: $1" ;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
folder_for_type() {
|
||||||
|
case "$1" in
|
||||||
|
daily) echo "06-daily" ;;
|
||||||
|
work-item) echo "02-work-items" ;;
|
||||||
|
person) echo "04-people" ;;
|
||||||
|
decision) echo "05-decisions" ;;
|
||||||
|
system) echo "03-context/systems" ;;
|
||||||
|
workstream) echo "03-context/workstreams" ;;
|
||||||
|
meeting-note) echo "06-daily" ;;
|
||||||
|
*) die "unsupported note type: $1" ;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
note_path_for_type() {
|
||||||
|
local type="$1"
|
||||||
|
local slug="$2"
|
||||||
|
local folder
|
||||||
|
folder="$(folder_for_type "$type")"
|
||||||
|
case "$slug" in
|
||||||
|
*.md) echo "$folder/$slug" ;;
|
||||||
|
*) echo "$folder/$slug.md" ;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
render_template() {
|
||||||
|
local template="$1"
|
||||||
|
local title="$2"
|
||||||
|
local slug="$3"
|
||||||
|
python3 - "$template" "$title" "$slug" <<'PY'
|
||||||
|
import datetime
|
||||||
|
import pathlib
|
||||||
|
import re
|
||||||
|
import sys
|
||||||
|
|
||||||
|
template = pathlib.Path(sys.argv[1])
|
||||||
|
title = sys.argv[2]
|
||||||
|
slug = sys.argv[3]
|
||||||
|
now = datetime.datetime.now()
|
||||||
|
ticket = slug.removesuffix(".md").upper()
|
||||||
|
ticket = re.sub(r"^([A-Z]+)-?(\d+)$", r"\1-\2", ticket)
|
||||||
|
content = template.read_text()
|
||||||
|
content = content.replace("{{title}}", title)
|
||||||
|
content = content.replace("{{slug}}", slug.removesuffix(".md"))
|
||||||
|
content = content.replace("{{ticket}}", ticket)
|
||||||
|
content = content.replace("{{date}}", now.strftime("%Y-%m-%d"))
|
||||||
|
content = content.replace("{{date:YYYY-MM-DD}}", now.strftime("%Y-%m-%d"))
|
||||||
|
content = content.replace("{{time}}", now.strftime("%H:%M"))
|
||||||
|
print(content, end="")
|
||||||
|
PY
|
||||||
|
}
|
||||||
|
|
||||||
|
postprocess_note() {
|
||||||
|
local rel="$1"
|
||||||
|
local title="$2"
|
||||||
|
local slug="$3"
|
||||||
|
local target
|
||||||
|
target="$(safe_path "$rel")"
|
||||||
|
[[ -f "$target" ]] || return 0
|
||||||
|
python3 - "$target" "$title" "$slug" <<'PY'
|
||||||
|
import datetime
|
||||||
|
import pathlib
|
||||||
|
import re
|
||||||
|
import sys
|
||||||
|
|
||||||
|
path = pathlib.Path(sys.argv[1])
|
||||||
|
title = sys.argv[2]
|
||||||
|
slug = sys.argv[3].removesuffix(".md")
|
||||||
|
ticket = re.sub(r"^([A-Z]+)-?(\d+)$", r"\1-\2", slug.upper())
|
||||||
|
today = datetime.datetime.now().strftime("%Y-%m-%d")
|
||||||
|
now = datetime.datetime.now().strftime("%H:%M")
|
||||||
|
|
||||||
|
content = path.read_text()
|
||||||
|
content = content.replace("{{title}}", title)
|
||||||
|
content = content.replace("{{slug}}", slug)
|
||||||
|
content = content.replace("{{ticket}}", ticket)
|
||||||
|
content = content.replace("{{date}}", today)
|
||||||
|
content = content.replace("{{date:YYYY-MM-DD}}", today)
|
||||||
|
content = content.replace("{{time}}", now)
|
||||||
|
|
||||||
|
lines = content.splitlines()
|
||||||
|
if lines[:1] == ["---"]:
|
||||||
|
try:
|
||||||
|
end = lines.index("---", 1)
|
||||||
|
except ValueError:
|
||||||
|
end = -1
|
||||||
|
if end > 0:
|
||||||
|
frontmatter = lines[1:end]
|
||||||
|
body = lines[end + 1 :]
|
||||||
|
for i, line in enumerate(frontmatter):
|
||||||
|
if line.startswith("title:"):
|
||||||
|
frontmatter[i] = f"title: {title}"
|
||||||
|
elif line.startswith("ticket:"):
|
||||||
|
frontmatter[i] = f"ticket: {ticket}"
|
||||||
|
elif line.startswith("date:"):
|
||||||
|
frontmatter[i] = f"date: {today}"
|
||||||
|
elif line.startswith("updated:"):
|
||||||
|
frontmatter[i] = f"updated: {today}"
|
||||||
|
lines = ["---", *frontmatter, "---", *body]
|
||||||
|
content = "\n".join(lines) + "\n"
|
||||||
|
|
||||||
|
path.write_text(content)
|
||||||
|
PY
|
||||||
|
}
|
||||||
|
|
||||||
|
create_direct() {
|
||||||
|
local type="$1"
|
||||||
|
local slug="$2"
|
||||||
|
local title="${3:-$slug}"
|
||||||
|
local rel target template_name template
|
||||||
|
rel="$(note_path_for_type "$type" "$slug")"
|
||||||
|
target="$(safe_path "$rel")"
|
||||||
|
template_name="$(template_name_for_type "$type")"
|
||||||
|
template="$VAULT_DIR/09-templates/$template_name.md"
|
||||||
|
|
||||||
|
[[ -e "$target" ]] && die "note already exists: $rel"
|
||||||
|
[[ -f "$template" ]] || die "template not found: 09-templates/$template_name.md"
|
||||||
|
mkdir -p "$(dirname "$target")"
|
||||||
|
render_template "$template" "$title" "$slug" > "$target"
|
||||||
|
postprocess_note "$rel" "$title" "$slug"
|
||||||
|
echo "$rel"
|
||||||
|
}
|
||||||
|
|
||||||
|
create_note() {
|
||||||
|
local type="$1"
|
||||||
|
local slug="$2"
|
||||||
|
local title="${3:-$slug}"
|
||||||
|
local rel template_name
|
||||||
|
rel="$(note_path_for_type "$type" "$slug")"
|
||||||
|
template_name="$(template_name_for_type "$type")"
|
||||||
|
|
||||||
|
require_obsidian_if_forced
|
||||||
|
if has_obsidian; then
|
||||||
|
if "$OBSIDIAN_CLI" create "path=$rel" "template=$template_name" >/dev/null 2>&1; then
|
||||||
|
postprocess_note "$rel" "$title" "$slug"
|
||||||
|
echo "$rel"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
[[ "$BACKEND" == "obsidian" ]] && die "obsidian create failed for $rel"
|
||||||
|
fi
|
||||||
|
|
||||||
|
create_direct "$type" "$slug" "$title"
|
||||||
|
}
|
||||||
|
|
||||||
|
search_memory() {
|
||||||
|
local query="$1"
|
||||||
|
local folder="${2:-}"
|
||||||
|
|
||||||
|
require_obsidian_if_forced
|
||||||
|
if has_obsidian; then
|
||||||
|
if [[ -n "$folder" ]]; then
|
||||||
|
if "$OBSIDIAN_CLI" search:context "query=$query" "path=$folder" "limit=50"; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
if "$OBSIDIAN_CLI" search:context "query=$query" "limit=50"; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
[[ "$BACKEND" == "obsidian" ]] && die "obsidian search failed"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -n "$folder" ]]; then
|
||||||
|
rg -n -- "$query" "$VAULT_DIR/$folder"
|
||||||
|
else
|
||||||
|
rg -n -- "$query" "$VAULT_DIR"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
base_query() {
|
||||||
|
local base="$1"
|
||||||
|
local format="${2:-md}"
|
||||||
|
local base_path="08-bases/${base%.base}.base"
|
||||||
|
local type_name="${base%.base}"
|
||||||
|
|
||||||
|
require_obsidian_if_forced
|
||||||
|
if has_obsidian; then
|
||||||
|
if "$OBSIDIAN_CLI" base:query "path=$base_path" "format=$format"; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
[[ "$BACKEND" == "obsidian" ]] && die "obsidian base query failed for $base_path"
|
||||||
|
fi
|
||||||
|
|
||||||
|
case "$type_name" in
|
||||||
|
work-items) rg -l '^type: work-item$' "$VAULT_DIR/02-work-items" ;;
|
||||||
|
people) rg -l '^type: person$' "$VAULT_DIR/04-people" ;;
|
||||||
|
decisions) rg -l '^type: decision$' "$VAULT_DIR/05-decisions" ;;
|
||||||
|
daily) rg -l '^type: daily$' "$VAULT_DIR/06-daily" ;;
|
||||||
|
systems) rg -l '^type: system$' "$VAULT_DIR/03-context/systems" ;;
|
||||||
|
workstreams) rg -l '^type: workstream$' "$VAULT_DIR/03-context/workstreams" ;;
|
||||||
|
*) die "unsupported base fallback: $base" ;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
health_check() {
|
||||||
|
local failed=0
|
||||||
|
local required=(
|
||||||
|
"00-start/start-here.md"
|
||||||
|
"01-current/current-work.md"
|
||||||
|
"01-current/work-items.md"
|
||||||
|
"02-work-items/index.md"
|
||||||
|
"03-context/project.md"
|
||||||
|
"04-people/index.md"
|
||||||
|
"07-maps/index.md"
|
||||||
|
"08-bases/work-items.base"
|
||||||
|
"09-templates/work-item.md"
|
||||||
|
)
|
||||||
|
|
||||||
|
ensure_vault
|
||||||
|
|
||||||
|
for rel in "${required[@]}"; do
|
||||||
|
if [[ ! -e "$VAULT_DIR/$rel" ]]; then
|
||||||
|
echo "missing: $rel"
|
||||||
|
failed=1
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
if [[ -d "$WORKSPACE_ROOT/.obsidian" ]]; then
|
||||||
|
echo "unexpected root Obsidian config: .obsidian"
|
||||||
|
failed=1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if has_obsidian; then
|
||||||
|
"$OBSIDIAN_CLI" unresolved total 2>/dev/null | sed 's/^/unresolved-links: /' || true
|
||||||
|
"$OBSIDIAN_CLI" orphans total 2>/dev/null | sed 's/^/orphans: /' || true
|
||||||
|
"$OBSIDIAN_CLI" tags total 2>/dev/null | sed 's/^/tags: /' || true
|
||||||
|
else
|
||||||
|
echo "obsidian-cli: unavailable; file checks only"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "$failed" -eq 0 ]]; then
|
||||||
|
echo "memory health ok"
|
||||||
|
fi
|
||||||
|
exit "$failed"
|
||||||
|
}
|
||||||
|
|
||||||
|
main() {
|
||||||
|
ensure_vault
|
||||||
|
local command="${1:-}"
|
||||||
|
[[ -n "$command" ]] || { usage; exit 1; }
|
||||||
|
shift || true
|
||||||
|
|
||||||
|
case "$command" in
|
||||||
|
root)
|
||||||
|
echo "$VAULT_DIR"
|
||||||
|
;;
|
||||||
|
read)
|
||||||
|
[[ $# -eq 1 ]] || die "usage: memory.sh read <vault-relative-path>"
|
||||||
|
cat "$(safe_path "$1")"
|
||||||
|
;;
|
||||||
|
search)
|
||||||
|
[[ $# -ge 1 ]] || die "usage: memory.sh search <query> [folder]"
|
||||||
|
search_memory "$1" "${2:-}"
|
||||||
|
;;
|
||||||
|
create)
|
||||||
|
[[ $# -ge 2 ]] || die "usage: memory.sh create <type> <slug> [title]"
|
||||||
|
create_note "$1" "$2" "${3:-$2}"
|
||||||
|
;;
|
||||||
|
base-query)
|
||||||
|
[[ $# -ge 1 ]] || die "usage: memory.sh base-query <base-name> [format]"
|
||||||
|
base_query "$1" "${2:-md}"
|
||||||
|
;;
|
||||||
|
health)
|
||||||
|
health_check
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
usage
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
main "$@"
|
||||||
20
scripts/obsidian/cli.sh
Executable file
20
scripts/obsidian/cli.sh
Executable file
@@ -0,0 +1,20 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
WORKSPACE_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
||||||
|
VAULT_DIR="${AIW_MEMORY_VAULT_DIR:-${AIW_OBSIDIAN_VAULT_DIR:-$WORKSPACE_ROOT/vault}}"
|
||||||
|
|
||||||
|
if ! command -v obsidian >/dev/null 2>&1; then
|
||||||
|
echo "obsidian CLI is not installed or not in PATH" >&2
|
||||||
|
exit 127
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ ! -d "$VAULT_DIR" ]]; then
|
||||||
|
echo "vault directory not found: $VAULT_DIR" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
cd "$VAULT_DIR"
|
||||||
|
exec obsidian "$@"
|
||||||
@@ -4,7 +4,7 @@ set -euo pipefail
|
|||||||
|
|
||||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
WORKSPACE_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
WORKSPACE_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
||||||
VAULT_DIR="${AIW_OBSIDIAN_VAULT_DIR:-$WORKSPACE_ROOT/vault}"
|
VAULT_DIR="${AIW_OBSIDIAN_VAULT_DIR:-${AIW_MEMORY_VAULT_DIR:-$WORKSPACE_ROOT/vault}}"
|
||||||
VAULT_NAME="${AIW_OBSIDIAN_VAULT_NAME:-$(basename "$VAULT_DIR")}"
|
VAULT_NAME="${AIW_OBSIDIAN_VAULT_NAME:-$(basename "$VAULT_DIR")}"
|
||||||
|
|
||||||
URI="$("$SCRIPT_DIR/uri.sh" daily "vault=$VAULT_NAME")"
|
URI="$("$SCRIPT_DIR/uri.sh" daily "vault=$VAULT_NAME")"
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ set -euo pipefail
|
|||||||
|
|
||||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
WORKSPACE_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
WORKSPACE_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
||||||
VAULT_DIR="${AIW_OBSIDIAN_VAULT_DIR:-$WORKSPACE_ROOT/vault}"
|
VAULT_DIR="${AIW_OBSIDIAN_VAULT_DIR:-${AIW_MEMORY_VAULT_DIR:-$WORKSPACE_ROOT/vault}}"
|
||||||
VAULT_NAME="${AIW_OBSIDIAN_VAULT_NAME:-$(basename "$VAULT_DIR")}"
|
VAULT_NAME="${AIW_OBSIDIAN_VAULT_NAME:-$(basename "$VAULT_DIR")}"
|
||||||
|
|
||||||
if [[ $# -lt 1 ]]; then
|
if [[ $# -lt 1 ]]; then
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ set -euo pipefail
|
|||||||
|
|
||||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
WORKSPACE_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
WORKSPACE_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
||||||
VAULT_DIR="${AIW_OBSIDIAN_VAULT_DIR:-$WORKSPACE_ROOT/vault}"
|
VAULT_DIR="${AIW_OBSIDIAN_VAULT_DIR:-${AIW_MEMORY_VAULT_DIR:-$WORKSPACE_ROOT/vault}}"
|
||||||
VAULT_NAME="${AIW_OBSIDIAN_VAULT_NAME:-$(basename "$VAULT_DIR")}"
|
VAULT_NAME="${AIW_OBSIDIAN_VAULT_NAME:-$(basename "$VAULT_DIR")}"
|
||||||
|
|
||||||
if [[ $# -lt 1 ]]; then
|
if [[ $# -lt 1 ]]; then
|
||||||
|
|||||||
2
vault/.obsidian/graph.json
vendored
2
vault/.obsidian/graph.json
vendored
@@ -60,6 +60,6 @@
|
|||||||
"repelStrength": 10,
|
"repelStrength": 10,
|
||||||
"linkStrength": 1,
|
"linkStrength": 1,
|
||||||
"linkDistance": 250,
|
"linkDistance": 250,
|
||||||
"scale": 1.0087453683557874,
|
"scale": 1.3297103454416062,
|
||||||
"close": true
|
"close": true
|
||||||
}
|
}
|
||||||
@@ -24,6 +24,7 @@ Common terms used in this workspace.
|
|||||||
- `inbox`: raw or lightly processed communication evidence under `ai/inbox/`.
|
- `inbox`: raw or lightly processed communication evidence under `ai/inbox/`.
|
||||||
- `promotion`: moving high-confidence evidence into canonical memory.
|
- `promotion`: moving high-confidence evidence into canonical memory.
|
||||||
- `tooling behavior`: reusable behavior encoded in commands, prompts, skills, agents, or knowledge rules.
|
- `tooling behavior`: reusable behavior encoded in commands, prompts, skills, agents, or knowledge rules.
|
||||||
|
- `memory interface`: project-agnostic scripts under `scripts/memory/` that create, search, query, and validate canonical memory without coupling the workspace to Obsidian.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,8 @@ tags:
|
|||||||
|
|
||||||
Use Obsidian to navigate and review workspace memory. Do not use it as a separate memory database.
|
Use Obsidian to navigate and review workspace memory. Do not use it as a separate memory database.
|
||||||
|
|
||||||
|
Obsidian is the current interface over canonical Markdown memory. The workspace-level abstraction is `scripts/memory/`, so agents should use Obsidian-specific commands only through that adapter when possible.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Recommended Start
|
## Recommended Start
|
||||||
@@ -126,3 +128,26 @@ For normal onboarding, keep them hidden and navigate through the named maps.
|
|||||||
- Templates may contain the final note `type` so newly created notes are useful immediately, but Bases must exclude the template folder so template files do not appear as data rows.
|
- Templates may contain the final note `type` so newly created notes are useful immediately, but Bases must exclude the template folder so template files do not appear as data rows.
|
||||||
- Role mapping files such as `04-people/manager.md` should use `type: role-map`, not `type: person`.
|
- Role mapping files such as `04-people/manager.md` should use `type: role-map`, not `type: person`.
|
||||||
- Bookmarks should keep `00-start/start-here.md`, `00-start/onboarding.md`, current work, work items, people, and high-value Bases easy to open.
|
- Bookmarks should keep `00-start/start-here.md`, `00-start/onboarding.md`, current work, work items, people, and high-value Bases easy to open.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## CLI And Templates
|
||||||
|
|
||||||
|
The official Obsidian CLI can create notes from templates, query Bases, inspect properties, and search the vault.
|
||||||
|
|
||||||
|
In this workspace, prefer the platform-agnostic memory wrapper:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
bash scripts/memory/memory.sh create work-item pdiap-15999 "Example title"
|
||||||
|
bash scripts/memory/memory.sh search "PDIAP-15765"
|
||||||
|
bash scripts/memory/memory.sh base-query work-items
|
||||||
|
bash scripts/memory/memory.sh health
|
||||||
|
```
|
||||||
|
|
||||||
|
The wrapper owns note type routing, so a `work-item` goes to `02-work-items/`, a `person` goes to `04-people/`, a `decision` goes to `05-decisions/`, and so on.
|
||||||
|
|
||||||
|
Use Obsidian CLI directly only when debugging Obsidian-specific behavior:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
bash scripts/obsidian/cli.sh help
|
||||||
|
```
|
||||||
|
|||||||
@@ -75,6 +75,8 @@ If you are new to this project, read:
|
|||||||
- [Communication Rules](../03-context/process/communication-rules.md)
|
- [Communication Rules](../03-context/process/communication-rules.md)
|
||||||
- [Context Maintenance](../03-context/process/context-maintenance.md)
|
- [Context Maintenance](../03-context/process/context-maintenance.md)
|
||||||
- [Workspace Architecture](workspace-architecture.md)
|
- [Workspace Architecture](workspace-architecture.md)
|
||||||
|
- Memory interface: `scripts/memory/`
|
||||||
|
- Obsidian adapter: `scripts/obsidian/`
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -50,6 +50,19 @@ Runtime and generated files can be used as evidence, but durable project facts s
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## Memory Access Layer
|
||||||
|
|
||||||
|
Use `scripts/memory/` as the platform-agnostic interface to canonical memory.
|
||||||
|
|
||||||
|
Obsidian is the current visual and CLI-backed adapter, but the source of truth remains Markdown under `vault/`.
|
||||||
|
|
||||||
|
- Agents use `scripts/memory/memory.sh create` when a new typed note is needed.
|
||||||
|
- Agents use `scripts/memory/memory.sh search` or direct Markdown reads for context lookup.
|
||||||
|
- Agents use `scripts/memory/memory.sh base-query` and `health` for structured review.
|
||||||
|
- Precise memory edits should still be made directly to Markdown so changes stay auditable.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Memory Rule
|
## Memory Rule
|
||||||
|
|
||||||
Promoted memory lives in `vault/`.
|
Promoted memory lives in `vault/`.
|
||||||
|
|||||||
@@ -48,6 +48,8 @@ When the user corrects a recurring behavior, the workspace should update the fil
|
|||||||
- `core/` for reusable project-independent behavior
|
- `core/` for reusable project-independent behavior
|
||||||
- `profiles/<project>/` for project-specific assumptions
|
- `profiles/<project>/` for project-specific assumptions
|
||||||
- `vault/.obsidian/` only for portable vault configuration, not project memory
|
- `vault/.obsidian/` only for portable vault configuration, not project memory
|
||||||
|
- `scripts/memory/` for project-agnostic memory access, creation, search, Base queries, and health checks
|
||||||
|
- `scripts/obsidian/` for the current Obsidian adapter, not for core memory semantics
|
||||||
- `.opencode/commands/` for slash commands
|
- `.opencode/commands/` for slash commands
|
||||||
- `prompts/` for reusable drafting templates
|
- `prompts/` for reusable drafting templates
|
||||||
- `.opencode/agents/` and `AGENTS.md` for default agent behavior
|
- `.opencode/agents/` and `AGENTS.md` for default agent behavior
|
||||||
|
|||||||
@@ -24,6 +24,8 @@ Commands, prompts, skills, workflows, and automation surfaces that make the work
|
|||||||
|
|
||||||
- Commands index: `.opencode/commands/index.md`
|
- Commands index: `.opencode/commands/index.md`
|
||||||
- Workspace context: `.opencode/commands/workspace-context.md`
|
- Workspace context: `.opencode/commands/workspace-context.md`
|
||||||
|
- Memory health: `.opencode/commands/memory-health.md`
|
||||||
|
- Memory create: `.opencode/commands/memory-create.md`
|
||||||
- Communication sync: `.opencode/commands/communication-sync.md`
|
- Communication sync: `.opencode/commands/communication-sync.md`
|
||||||
- Archive import: `.opencode/commands/archive-import.md`
|
- Archive import: `.opencode/commands/archive-import.md`
|
||||||
- AI prompt: `.opencode/commands/ai-prompt.md`
|
- AI prompt: `.opencode/commands/ai-prompt.md`
|
||||||
@@ -51,3 +53,11 @@ Commands, prompts, skills, workflows, and automation surfaces that make the work
|
|||||||
- Story draft prompt: `prompts/story-draft.md`
|
- Story draft prompt: `prompts/story-draft.md`
|
||||||
- OpenCode entry workflow: `workflows/opencode-entry.md`
|
- OpenCode entry workflow: `workflows/opencode-entry.md`
|
||||||
- Daily context sync: `workflows/daily-context-sync.md`
|
- Daily context sync: `workflows/daily-context-sync.md`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Memory Interface
|
||||||
|
|
||||||
|
- Project-agnostic memory scripts: `scripts/memory/`
|
||||||
|
- Current Obsidian adapter: `scripts/obsidian/`
|
||||||
|
- Canonical vault: `vault/`
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ type: decision
|
|||||||
project: fidelity
|
project: fidelity
|
||||||
status: proposed
|
status: proposed
|
||||||
date:
|
date:
|
||||||
title:
|
title: "{{title}}"
|
||||||
systems: []
|
systems: []
|
||||||
workstreams: []
|
workstreams: []
|
||||||
people: []
|
people: []
|
||||||
@@ -11,10 +11,10 @@ related: []
|
|||||||
tags:
|
tags:
|
||||||
- decision
|
- decision
|
||||||
- fidelity
|
- fidelity
|
||||||
updated:
|
updated: "{{date:YYYY-MM-DD}}"
|
||||||
---
|
---
|
||||||
|
|
||||||
# Decision Title
|
# {{title}}
|
||||||
|
|
||||||
## Decision
|
## Decision
|
||||||
|
|
||||||
@@ -37,4 +37,3 @@ updated:
|
|||||||
## Follow-up
|
## Follow-up
|
||||||
|
|
||||||
-
|
-
|
||||||
|
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
---
|
---
|
||||||
type: meeting-note
|
type: meeting-note
|
||||||
project: fidelity
|
project: fidelity
|
||||||
date:
|
date: "{{date:YYYY-MM-DD}}"
|
||||||
people: []
|
people: []
|
||||||
work-items: []
|
work-items: []
|
||||||
systems: []
|
systems: []
|
||||||
tags:
|
tags:
|
||||||
- meeting
|
- meeting
|
||||||
- fidelity
|
- fidelity
|
||||||
updated:
|
updated: "{{date:YYYY-MM-DD}}"
|
||||||
---
|
---
|
||||||
|
|
||||||
# Meeting Note
|
# {{title}}
|
||||||
|
|
||||||
## Context
|
## Context
|
||||||
|
|
||||||
@@ -34,4 +34,3 @@ updated:
|
|||||||
## Memory Updates
|
## Memory Updates
|
||||||
|
|
||||||
-
|
-
|
||||||
|
|
||||||
|
|||||||
@@ -9,10 +9,10 @@ related: []
|
|||||||
tags:
|
tags:
|
||||||
- person
|
- person
|
||||||
- fidelity
|
- fidelity
|
||||||
updated:
|
updated: "{{date:YYYY-MM-DD}}"
|
||||||
---
|
---
|
||||||
|
|
||||||
# Name
|
# {{title}}
|
||||||
|
|
||||||
## Role
|
## Role
|
||||||
|
|
||||||
@@ -35,4 +35,3 @@ updated:
|
|||||||
## Related Context
|
## Related Context
|
||||||
|
|
||||||
-
|
-
|
||||||
|
|
||||||
|
|||||||
@@ -9,10 +9,10 @@ related: []
|
|||||||
tags:
|
tags:
|
||||||
- system
|
- system
|
||||||
- fidelity
|
- fidelity
|
||||||
updated:
|
updated: "{{date:YYYY-MM-DD}}"
|
||||||
---
|
---
|
||||||
|
|
||||||
# System Name
|
# {{title}}
|
||||||
|
|
||||||
## Role
|
## Role
|
||||||
|
|
||||||
@@ -35,4 +35,3 @@ updated:
|
|||||||
## Related Context
|
## Related Context
|
||||||
|
|
||||||
-
|
-
|
||||||
|
|
||||||
|
|||||||
@@ -2,8 +2,8 @@
|
|||||||
type: work-item
|
type: work-item
|
||||||
project: fidelity
|
project: fidelity
|
||||||
status: active
|
status: active
|
||||||
ticket:
|
ticket: "{{ticket}}"
|
||||||
title:
|
title: "{{title}}"
|
||||||
systems: []
|
systems: []
|
||||||
workstreams: []
|
workstreams: []
|
||||||
people: []
|
people: []
|
||||||
@@ -11,10 +11,10 @@ related: []
|
|||||||
tags:
|
tags:
|
||||||
- work-item
|
- work-item
|
||||||
- fidelity
|
- fidelity
|
||||||
updated:
|
updated: "{{date:YYYY-MM-DD}}"
|
||||||
---
|
---
|
||||||
|
|
||||||
# Ticket - Title
|
# {{ticket}} - {{title}}
|
||||||
|
|
||||||
## Status
|
## Status
|
||||||
|
|
||||||
@@ -43,4 +43,3 @@ updated:
|
|||||||
## Next Step
|
## Next Step
|
||||||
|
|
||||||
-
|
-
|
||||||
|
|
||||||
|
|||||||
@@ -9,10 +9,10 @@ related: []
|
|||||||
tags:
|
tags:
|
||||||
- workstream
|
- workstream
|
||||||
- fidelity
|
- fidelity
|
||||||
updated:
|
updated: "{{date:YYYY-MM-DD}}"
|
||||||
---
|
---
|
||||||
|
|
||||||
# Workstream Name
|
# {{title}}
|
||||||
|
|
||||||
## Goal
|
## Goal
|
||||||
|
|
||||||
@@ -35,4 +35,3 @@ updated:
|
|||||||
## Related Work
|
## Related Work
|
||||||
|
|
||||||
-
|
-
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user