Skip to content

v0.9.30-chronode.2: adversarial-review fixes (graphify path scoping, data-dir split-brain, index-ready flag) + release - #11

Merged
ChronodeAi merged 15 commits into
mainfrom
hotfix/adversarial-fixes
Aug 24, 2026
Merged

v0.9.30-chronode.2: adversarial-review fixes (graphify path scoping, data-dir split-brain, index-ready flag) + release#11
ChronodeAi merged 15 commits into
mainfrom
hotfix/adversarial-fixes

Conversation

@ChronodeAi

Copy link
Copy Markdown
Owner

Fixes all verified findings from the three post-ship adversarial reviews of the v0.9.29 sync wave:

Security — graphify import explicit paths constrained to /graph.json with non-echoing rejections (per-project capability token no longer an arbitrary-file-read primitive); credential redaction on unnormalizable-remote stderr warnings; capability-secret provisioning hardening (dir 0700, symlink refusal, partial-file removal on chmod failure).

Correctness/perf — --data-dir folds into env BEFORE .env hydration (split-brain config); standalone MCP persist path delegates to the data-dir-aware resolver after hydrating; successful boot reconciliation sets memoryIndexReady (remember stops falling back to full KV scans); rejected consolidation dispatch releases its cooldown marker; mesh peer upserts gain shared-channel Origin; project override YAMLs resolve via data-dir with legacy fallback.

Release: 0.9.30-chronode.2 (version trio, CHANGELOG section, bundles regenerated).

Test plan

  • vitest 1927 passed / 0 failures; tsc byte-identical to baseline
  • Full canonical R-13 run passed (176 tracked files, no waivers)
  • evidence/skills/bundle gates green

…project cwd

An explicit path on mem::graph::import-graphify could point anywhere the
daemon can read. Explicit paths must now resolve inside the requested cwd
and keep the graph.json basename; violations return a generic error that
does not echo the attempted path. Stat failures for explicit paths keep
the same no-echo discipline while the default computed path retains its
specific pointer.
…t remote to stderr

The identity-fallback warning wrote the raw `git remote get-url` output,
leaking embedded passwords for remotes URL parsing rejected. New
redactRemoteForLog helper keeps everything from the last @ onward and
masks the credential segment; credential-free remotes pass through
unchanged.
mkdirSync now requests 0700 for the credential directory. A symlink at
the credential path is refused via lstat instead of being followed to a
foreign target. A chmod failure on a pre-existing populated credential
logs one stderr line and continues (the file predates this run), while a
chmod failure on the freshly written credential removes the partial file
and fails loud instead of leaving an unsecured secret on disk.
…dration

The CLI hydrated <data-dir>/.env before folding the --data-dir flag into
AGENTMEMORY_DATA_DIR, so a flagged run read its .env from the default
~/.agentmemory instead of the requested location. The fold (and the
legacy-store warning that consumes the resolved dir) now runs before
hydrateProcessEnvFromFile(); --version keeps its pre-side-effect exit.
…ir-aware config resolver

The shim kept its own copy of the persist-path resolution pinned to
~/.agentmemory, ignoring AGENTMEMORY_DATA_DIR and duplicating
config.ts. It now calls hydrateProcessEnvFromFile() at boot and
delegates getStandalonePersistPath to the shared export, preserving the
STANDALONE_PERSIST_PATH override precedence while honoring a relocated
data dir.
…iation

reconcileCanonicalSearchIndex walks the full KV.memories corpus, so a
successful run leaves the keyword index covering the memory corpus just
like performRebuildIndex does — but the ready flag stayed false, forcing
mem::remember onto the full-scan fallback until an explicit rebuild ran.
Set the same flag on the reconcile success path; a failed walk leaves it
untouched.
…h is rejected

The cooldown marker was written before the Void fan-out, so a rejected
mem::consolidate-pipeline / mem::auto-crystallize dispatch pinned the
debounce for the whole window with no pipeline behind it. Rejection and
sync-throw handlers now best-effort delete the marker (plain KV write,
no pipeline lock) without touching the fire-and-forget latency profile,
letting the next eligible stop retry.
mem::mesh-receive and the mesh pull path wrote peer memories straight
into KV.memories, so records arriving without provenance bypassed the
write-time Origin rule every local capture surface follows. Incoming
memories now go through the types.js importOrigin factory: a
peer-provided origin is preserved, anything else is marked with the
shared channel at receive time.
…cts dir

getUserProjectConfigPath was pinned to ~/.agentmemory/projects and
ignored a relocated data dir. It now resolves <data-dir>/projects/<hash>.yaml
first and falls back to the legacy ~/.agentmemory copy when the data-dir
file is absent, so existing overrides keep working; nothing writes this
file today, so no write path changes.
Fixed bullets for graphify import path scoping, remote credential
redaction, capability secret hardening, --data-dir hydration order,
standalone persist-path delegation, consolidation cooldown release on
rejected dispatch, mesh peer-origin stamping, reconciliation readiness,
and data-dir-aware user overrides; Changed notes that .env is parsed
once per process. Strict-session heuristic graph extraction stays
documented solely in the 0.9.30-chronode.1 notes.
npm run build after the project-config, cli.ts, and mcp/standalone.ts
changes: redactRemoteForLog rides in the shared auth/project chunks and
the standalone shim now hydrates .env before resolving its persist path
through the shared config resolver. Shared-chunk hashes rotate
accordingly.
Adds graph-import-scope, project-config-redaction,
capability-secret-hardening, search-reconcile-ready, and mesh-origin
suites (171 -> 176 files) with recomputed manifest and content hashes
per scripts/r13/run.mjs.
…s train

Measured surface counts are unchanged (137 REST routes, 60 MCP tools,
13 hooks, 19 connectors); only the source-identity hashes rotate with
the branch head.
@ChronodeAi
ChronodeAi merged commit aceb69b into main Aug 24, 2026
4 checks passed
@ChronodeAi
ChronodeAi deleted the hotfix/adversarial-fixes branch August 24, 2026 22:54
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