Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion .obsidian/community-plugins.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
[
"obsidian-style-settings"
"obsidian-style-settings",
"automatic-table-of-contents",
"dataview",
"folder-notes",
"frontmatter-modified-date"
]
10 changes: 10 additions & 0 deletions .obsidian/hotkeys.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"app:reload": [
{
"modifiers": [
"Mod"
],
"key": "R"
}
]
}
53 changes: 53 additions & 0 deletions docs/ARCHIVE/CHANGELOG/CHANGELOG-2026-05-20-828bf0c.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
---
class: archive
category:
- changelog
log-scope: general
modified: 2026-05-20
UUID: 4ad76a84-5a4d-47c9-9cbe-46abf5b65a30
commit-sha: "828bf0c"
files-modified: 3
files-created: 3
files-archived: 0
tags:
- archivist-cli
---

# Centralized DB Development Prep — 2026-05-20

## Overview

| Field | Value |
|-------|-------|
| Date | 2026-05-20 |
| Commit SHA | 828bf0c065ec461f2efa8052ddbd2a5237ee600d |
| Files Added | 3 |
| Files Modified | 3 |
| Files Archived | 0 |

## Changes

### Files Modified
- `.obsidian/community-plugins.json`: [description]
- `docs/ROADMAP/CENTRALIZED_DB/CENTRALIZED_DATABASE_SPEC.md`: revised spec to include foundation for multi-vault orchestration feature
- `docs/ROADMAP/GIT_INTEGRATION/GIT_INTEGRATION_SPEC.md`: removed unnecessary content

### New Files Created
- `.obsidian/hotkeys.json`: [description]
- `docs/ROADMAP/MANIFEST_AUGMENT_SPEC.md`: new spec for feature revision
- `docs/ROADMAP/MULTI_VAULT_ORCHESTRATION/MULTI_VAULT_ORCHESTRATION_SPEC.md`: new spec for planned feature

### Files Removed / Archived
- No files archived


<!-- archivist:auto-end -->
## Notes

docs: updated plans in prep for Centralized DB development

---

*This changelog was automatically generated by Archivist CLI.*
*See [Archivist CLI](https://github.com/lvnacy-notes/archivist-cli) for more information.*

1 change: 1 addition & 0 deletions docs/ROADMAP/CENTRALIZED_DB/CENTRALIZED_DATABASE_SPEC.md
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ CREATE TABLE modules (
git_remote TEXT, -- remote URL; used for cross-module sync
library_tag TEXT, -- library modules only
created_at TEXT NOT NULL,
last_synced_at TEXT, -- ISO datetime; updated by pre-commit hook on each registry upsert
decimated_at TEXT -- NULL = active; ISO date = tombstoned
);

Expand Down
8 changes: 1 addition & 7 deletions docs/ROADMAP/GIT_INTEGRATION/GIT_INTEGRATION_SPEC.md
Original file line number Diff line number Diff line change
Expand Up @@ -234,10 +234,6 @@ The following centralized DB behaviors must be in place before git integration i
- `archivist add` scaffolded (git passthrough not yet active) — §1.5.3
- `archivist deinit` scaffolded (git passthrough not yet active) — §1.5.4

**Potential gap — hook installation into cloned/added modules:**

`archivist add` (step 7 of the flow in §3.2) installs git hooks into the target module. The centralized DB spec notes hook installation as part of `archivist add` but does not detail what "install hooks" means in the context of a freshly cloned repo versus an existing repo. The hooks module (`archivist hooks install` / `archivist hooks sync`) should be verified to handle both cases cleanly before git integration begins.

**Gap — `git_remote` population and remote selection:**

The centralized DB implementation checklist specifies that `git_remote` is collected via `git remote get-url origin` during `archivist init` (§1.5.5). This is a footgun. Not every user names their remote "origin"; git imposes no such convention, and users who manage multiple remotes per repo — e.g. named by platform — will have no "origin" to get.
Expand All @@ -262,6 +258,4 @@ SQLite files are binary. Git tracks them but cannot diff or merge them meaningfu

The shape of the first-run initialization flow — specifically, when and how the user configures the registry remote — is a dependency for this feature and must be resolved in the prerequisite checklist before implementation begins.

**Superproject detection in `deinit`:** Step 3 of the deinit flow removes `module_bays` rows scoped to the current superproject's vault module. Detecting the superproject reliably requires `git rev-parse --show-superproject-working-tree`. This is already used in the centralized DB spec (§1.5.5); confirm it behaves correctly when called from the superproject working directory rather than from within the submodule.

**Archivist Manifest**: `archivist manifest` should run `git add` under the hood when passed a path. This should be workshopped further.
**Superproject detection in `deinit`:** Step 3 of the deinit flow removes `module_bays` rows scoped to the current superproject's vault module. Detecting the superproject reliably requires `git rev-parse --show-superproject-working-tree`. This is already used in the centralized DB spec (§1.5.5); confirm it behaves correctly when called from the superproject working directory rather than from within the submodule.
74 changes: 74 additions & 0 deletions docs/ROADMAP/MANIFEST_AUGMENT_SPEC.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
---
class: spec
category:
- feature
- git
affiliations:
- git-integration
created: 2026-05-19
modified: 2026-05-19
version: 0.1
related:
- "[[GIT_INTEGRATION]]"
tags:
---

Patches `archivist manifest` to resolve its input from the staging index, matching the behavioral contract of `archivist changelog`. Adds a `path` argument that triggers auto-staging when nothing is staged under the given directory.

---

## Command Signature (Revised)

```
archivist manifest [path] [--dry-run]
```

`path` is optional. If omitted, manifest runs over everything currently staged — same as `archivist changelog` with no `--path`. If provided, it scopes to that directory.

---

## Execution Paths

```
path provided, files already staged under it
→ proceed; generate manifest over staged files

path provided, nothing staged under it
→ git add <path>
→ proceed; generate manifest over newly staged files

path provided, nothing staged under it, --dry-run set
→ print what would be staged
→ print what manifest would contain
→ write nothing, stage nothing

no path, files staged
→ proceed over full index

no path, nothing staged
→ exit with error
```

---

## The `git add` Step

- Runs `git add <path>` — recursive, respects `.gitignore` naturally
- Stages only what's under the given path; nothing outside it is touched
- On failure (git error, path doesn't exist, nothing to add): propagate the error and abort — do not proceed to manifest generation with an empty or partial index
- After staging, calls `ensure_staged_under(path, git_root)` as usual to confirm something actually landed in the index before continuing

---

## `--dry-run` Contract

`--dry-run` must gate both the staging step and the write step. A dry run that stages files is not a dry run. Print what `git add` would touch, print the manifest that would be generated, write nothing, stage nothing.

---

## What Doesn't Change

- Manifest generation logic — untouched
- `ensure_staged_under` — still the gate before generation
- Output format — untouched
- DB interaction — untouched
Original file line number Diff line number Diff line change
@@ -0,0 +1,211 @@
---
class: spec
category:
- feature
- infrastructure
affiliations:
- centralized-db
- git-integration
created: 2026-05-19
modified: 2026-05-19
version: 0.2
related:
- "[[MULTI_VAULT_ORCHESTRATION]]"
- "[[CENTRALIZED_DB]]"
- "[[GIT_INTEGRATION]]"
tags:
---

**Depends on:** Centralized Database feature (must ship first)

---

## 1. Overview

Two pain points, one feature. If you update a guidance doc in one module and it's relevant across the Apparatus, you should be able to sync it without dropping into six repos. If you've standardized a new frontmatter property and want it everywhere, you should be able to run that once.

That's the whole thing. File distribution and frontmatter consistency across registered modules. Nothing more.

---

## 2. Commands

| Command | Does |
|---|---|
| `archivist muster` | Status report across registered modules |
| `archivist distribute` | Copy a file to multiple modules |
| `archivist broadcast` | Run a frontmatter subcommand across multiple modules |

---

## 3. Scope Selectors

Every multi-module operation requires an explicit scope. No implicit scope exists. A command without a scope selector exits immediately with an error.

```
--apparatus <name> All active (non-decimated) modules in this apparatus
--vault <name> All active modules under this vault, including the vault itself
--type <type> Filter by module type; combinable with --apparatus or --vault
--module <name|uuid> One or more specific modules; repeatable; mutually exclusive
with --apparatus and --vault
```

`--type` is a filter, not a scope. `--apparatus` or `--vault` establishes scope; `--type` narrows it. `--module` is its own scope for when you already know exactly what you're targeting.

`--vault` includes the vault module itself. A vault is a module. If you need to exclude it, `--type library,story,publication` handles it.

Operations run in series, in alphabetical order by module name. No parallelism.

---

## 4. `archivist muster`

```
archivist muster [--apparatus <name>] [--vault <name>] [--type <type>] [--include-decimated]
```

Prints a status table across all matching modules. Read-only; no `--dry-run` needed or accepted.

### 4.1 Output

```
cosmic-horror (library) ~/writing/cosmic-horror ✓ last seal: 2026-05-12 synced: 2026-05-14
victorian-mayhem (library) ~/writing/victorian-mayhem ✓ last seal: 2026-05-19 synced: 2026-05-19
panopticon (library) ~/writing/panopticon ✗ PATH NOT FOUND synced: 2026-03-01
fiction-vault (vault) ~/writing/fiction-vault ✓ last seal: — synced: 2026-05-18
```

**Path validity** is checked by `path.exists()` at muster time. No guessing.

**Last seal** is pulled from the `changelogs` table in the apparatus DB. Falls back to `—` if no changelogs are recorded.

**Synced** is `modules.last_synced_at` — when the pre-commit hook last confirmed this module's path. Requires the schema addition in §7.

Decimated modules are excluded by default. `--include-decimated` to show them.

---

## 5. `archivist distribute`

```
archivist distribute <source> [--dest <relative-path>]
--apparatus|--vault|--module [--type <type>]
[--overwrite] [--dry-run]
```

Copies `<source>` into every module in scope. `--dest` is the relative path within each module where the file lands. If `--dest` is omitted, the file lands at the same relative path as `<source>`. If `<source>` is an absolute path or outside the current repo, `--dest` is required.

### 5.1 Flow (per module)

```
1. Validate module path exists → skip with warning if not
2. Resolve destination: <module-path> / <dest>
3. If destination exists and --overwrite not set → skip with warning
4. If --dry-run → print what would happen, write nothing
5. Write file
6. Report result
```

### 5.2 Output

```
→ cosmic-horror: writing .archivist/AGENTS.md
✓ cosmic-horror: done
→ victorian-mayhem: writing .archivist/AGENTS.md
✓ victorian-mayhem: done
→ panopticon: PATH NOT FOUND — skipping
⚠ fiction-vault: .archivist/AGENTS.md already exists — pass --overwrite to replace it
```

Summary at the end: N written, M skipped, K failed. Failures skip and continue; the run does not abort.

No silent overwrites. If the file exists, you get a warning and a flag to pass. The flag is your explicit consent.

Distribute writes the file. It does not stage it. Staging is the user's job.

---

## 6. `archivist broadcast`

```
archivist broadcast frontmatter <subcommand> [subcommand-args]
--apparatus|--vault|--module [--type <type>]
[--dry-run]
```

Runs a `frontmatter` subcommand in each module's working directory, in series. Scoped strictly to frontmatter commands — this is not a general execution engine.

```
archivist broadcast frontmatter add reviewed false --apparatus writing --type library
archivist broadcast frontmatter remove draft --vault fiction-vault --dry-run
```

### 6.1 Argument Parsing

`frontmatter` is a required literal — broadcast does not accept other command families. Everything after `frontmatter` is the subcommand and its arguments. Scope selectors and `--dry-run` belong to broadcast; everything else passes through to the inner command.

`--dry-run` on broadcast propagates as `--dry-run` to the inner command. You should not have to pass it twice.

### 6.2 Flow (per module)

```
1. Validate module path exists → skip with warning if not
2. chdir into module root
3. Invoke the frontmatter subcommand's run() with the parsed inner args
4. Capture result
5. chdir back
6. Continue to next module
```

### 6.3 Output

```
[cosmic-horror]
✓ Added reviewed: false to 47 files.

[victorian-mayhem]
✓ Added reviewed: false to 31 files.

[panopticon]
✗ PATH NOT FOUND — skipping

[fiction-vault]
— 0 files matched
```

Summary at the end: N succeeded, M skipped, K failed. Failures don't abort the run.

### 6.4 Implementation Note: `git_root` Resolution

Frontmatter subcommands call `get_repo_root()` inside `run()`. If broadcast has already `chdir`'d into the module, this resolves correctly. Confirm no frontmatter subcommand resolves git root at import time before implementing broadcast.

---

## 7. Failure Semantics

**Path not found:** skip with warning; continue. Never abort the whole run for a stale path.

**Module command failure:** capture stderr, report with the per-module block, continue. Surfaced in the end summary.

**Registry not accessible:** hard abort. No registry, no scope, no module list.

**Partial run:** no rollback. What ran, ran. Every operation is safe to re-run.

---

## 8. Required CDB Schema Addition

Add to `modules` in `registry.db` before the CDB implementation checklist is finalized:

```sql
last_synced_at TEXT -- ISO datetime; set by pre-commit hook on each registry upsert
```

The pre-commit hook already upserts the `modules` row on every commit. Adding `last_synced_at = datetime.now()` to that upsert is one line. Without it, `muster` cannot show how fresh the registered path data is.

---

## 9. Deferred: Git Integration Phase

- Automatic staging after `distribute`
- `archivist muster --fetch` — remote tracking state per module