Files
dinos f2f010a350 feat(memory): observation linking (#307)
* refactor(gateway): create module for launching async/bg agents

* refactor(memory): refactor worker launch around source context & output deltas

* refactor(gateway): generalize async/bg module

* refactor(memory): revamp worker launching

* feat(memory): add observation linking

* test(memory): remove redundant test branches

* fix(memory): make 'supersedes' relation directional

* fix(memory): don't create empty project observation dirs

* fix(memory): schedule direct observations for linking

* fix(cli): wait for observation linker before shutdown

* fix(memory): block arbitrary writes to /memories

* fix(linker): remove `linked_by` attribute from frontmatter

* refactor(linker): rename base relationship to `comlpements`

* fix(cli): bump worker wait to 2m

* feat(tools): catch malformed tool calls & retry

* feat(status): add linking result to statusbar

* fix(linker): don't launch linker when observations are disabled

* fix(memory): use posix paths

* fix(watcher): call abort hook on error status

* fix(watcher): delete thread on failed run creation

* fix(watcher): preserve url

* fix(observation): record session_id, drop unused fields

* fix(memory): reject unsupported worker source types

* refactor(backends): shared memory backend builder

* fix(scheduler): resolve linker inputs outside lock

* fix(memory): dont launch workers / record observations without thread_id

* feat(memory): include related observations in tool results

* fix(memory): skip malformed observation frontmatter

* revert(tools): drop tool error handling changes from this PR

* fix(memory): serialize observation link writes

* fix(memory): queue observations written by aborted workers

* fix(memory): track observation linker launch handoff

* fix(memory): resolve cross-project related observations

* fix(status): avoid recounting reason-only link updates

* fix(memory): avoid rereading file for content

* fix(linker): use neutral prose for bidirectional reasons

* test(memory): coverage for aborted/failed launches

* test(memory): cleanup & helpers

* feat(linker): add observations index hint
2026-06-26 22:20:52 +01:00

44 lines
1.3 KiB
Python

"""Project identity helpers for file-backed memory."""
from __future__ import annotations
import hashlib
import subprocess
from pathlib import Path
from .. import paths as _paths
def _short_hash(text: str, *, n: int = 16) -> str:
return hashlib.sha256(text.encode("utf-8")).hexdigest()[:n]
def _run_git(args: list[str], cwd: Path) -> str | None:
try:
result = subprocess.run(
["git", *args],
cwd=str(cwd),
check=False,
capture_output=True,
text=True,
timeout=2,
)
except (OSError, subprocess.SubprocessError):
return None
if result.returncode != 0:
return None
value = result.stdout.strip()
return value or None
def resolve_project_id(workspace: str | Path | None = None) -> str:
"""Return the stable id used for this workspace's project memory."""
root = Path(workspace or _paths.WORKSPACE_ROOT).expanduser().resolve()
git_root = _run_git(["rev-parse", "--show-toplevel"], root)
if git_root:
git_root_path = Path(git_root).expanduser().resolve()
remote = _run_git(["remote", "get-url", "origin"], git_root_path)
source = f"git-remote:{remote}" if remote else f"git-root:{git_root_path}"
return f"P-{_short_hash(source)}"
return f"P-{_short_hash(f'path:{root}')}"