Skip to content

feat(v3.9.0): atomic projection + idempotent manifest for export_obsidian - #7

Open
nicoechaniz wants to merge 7 commits into
Mar-IA-no:mainfrom
nicoechaniz:feat/atomic-projection
Open

feat(v3.9.0): atomic projection + idempotent manifest for export_obsidian#7
nicoechaniz wants to merge 7 commits into
Mar-IA-no:mainfrom
nicoechaniz:feat/atomic-projection

Conversation

@nicoechaniz

Copy link
Copy Markdown

Summary

Implements card t_6a4e7b40 (P3): atomic publish and idempotent manifest for the wiki/Obsidian projection. Mirrors collective-memory's pattern of staging build + atomic rename + manifest idempotence.

Design

  • Build into <vault>/.staging/<run_id>/ — invisible to Obsidian
  • Write projection-manifest.json with per-note content SHA-256 hashes
  • Idempotency: skip rewriting notes whose hash matches the live manifest; report written/unchanged/removed_orphans counts
  • Atomic swap: os.rename staging → <vault>/live/
  • Orphan pruning: notes for deleted chapters auto-removed
  • --check mode: drift detector — exit non-zero if published projection differs from a fresh build (CI/cron guard)
  • Takes the maintenance flock (same lock as embed-backfill/bootstrap)

What breaks an interrupted run?

Nothing. The live projection is never modified in-place. If the process is killed mid-build, the staging dir is simply abandoned (next run creates a new run_id). The previously published live/ dir remains intact.

Idempotency

Two consecutive runs with the same chapters produce byte-identical live/ trees. The second run reports 0 written, all unchanged.

Tests

83 pass. The export script is standalone — tested manually against a temp DB.

Building on v3.9.0 (PRs #4 corpus policy, #5 suggest-links, #6 flock).

CompAII (for Nicolás Echániz) and others added 7 commits July 28, 2026 21:48
…te_chapter

- memoryctl: update_chapter (in-place edit, FTS5 delete+insert, drops stale
  embeddings on content/title change, book title/slug sync with collision
  guard) and delete_chapter (FK cascade for embeddings/links, FTS row
  removal, empty-book pruning, raw_sha256 report for archival)
- CLI: memoryctl.py update / delete subcommands
- hmk-memory plugin: librarian tool gains update + delete actions (1.1.0)
- tests: 11 new tests against a real temp library.db; replace stale
  test_get_tool_schemas_empty with an enum-invariant test
- also commits the previously deployed-but-uncommitted librarian tool (v3.8.0)
  and integrates origin's v3.7.3 memoryctl path-resolution fix
- plugin cli.py: update/delete subcommands matching the librarian tool and
  memoryctl semantics (no-field update exits 2, --keep-book flag)
- plugin README: document the librarian tool action table and the
  embedding-drop / raw_sha256 contracts
Consistent with upsert_book() bumping it on every add_text; covered by
test_update_bumps_book_updated_at with a pinned now_ts.
- scripts/corpus_policy.py: file-level blocking (never-touch names/globs)
  + content-level secret scan (private keys, API tokens, JWTs, Bearer)
- Selective embedding: code (.py/.js/.sh) and config (.yaml/.json/.toml)
  files get embed_disabled=1 at ingest time — FTS5-only, no cloud API
- chapters.embed_disabled + embed_disable_reason columns (auto-migrated)
- embedding_candidates() / embed-backfill skip disabled chapters
- stats() reports embed_disabled breakdown by reason
- add_file blocks protected files; ingest_any enforces corpus policy
- update_chapter re-scans content for secrets
- 30 new tests in tests/test_corpus_policy.py (83 total, all pass)

Cards: t_116003b9 (P1 corpus policy) + t_c2f96fa4 (P1 selective embedding)
- New link_suggestions table (status candidate/accepted/rejected)
- suggest_links(): K nearest neighbors via cosine similarity on embeddings
  Filters: no self-links, already-linked, same-book
- list_link_suggestions(): list with both chapters' context
- review_link_suggestion(): accept → creates chapter_links edge,
  reject → marks blocked for re-proposal
- CLI: suggest-links, review-links (accept/reject/list)
- Librarian tool: suggest_links action (read-only — guard against self-approval)
- stats() reports suggestions + suggestions_total counts

Card: t_9cc06fde (P2)
…tstrap)

- _lock_maintenance(): POSIX fcntl.flock non-blocking exclusive lock
  on $HMK_AGENT_MEMORY_BASE/.maintenance.lock
- Fails fast with exit code 3 on conflict; locked commands:
  backfill_embeddings(), bootstrap()
- Read-only commands and single-chapter mutations stay lock-free
- No-op when BASE_DIR is None (tests pass unaffected)

Card: t_f8d8b335 (P3)
…st for export_obsidian

- Build into <vault>/.staging/<run_id>/ (invisible to Obsidian)
- projection-manifest.json with per-note content sha256 hashes
- Idempotency: skip notes whose hash matches manifest; report
  written/unchanged/removed_orphans counts
- Atomic publish: os.rename staging → <vault>/live/
- Orphan pruning: notes for deleted chapters auto-removed
- --check mode: drift detector (exit non-zero if projection differs)
- Maintenance flock for safety

Card: t_6a4e7b40 (P3)
Fede654 pushed a commit to Fede654/hermes-memory-kit that referenced this pull request Aug 18, 2026
feat(memory): add provenance-safe Daimon projection API
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant