Repository navigation
Upstream sync 13M-1: merge DeusData 5689ea54c with CLI ports of #2198, #1561, #1430 - #33
Conversation
In-process, type-aware call resolution for single Ruby files, mirroring the perl_lsp.c / php_lsp.c shape and dispatched from cbm_extract_file: - PASS 1 collects classes and modules with lexical nesting, superclasses, and include / prepend / extend mixins, plus method tables with instance and singleton methods classified from the AST. Singleton methods key on "<class_qn>.self", which cannot collide with a constant path. - PASS 1.5 infers instance-variable types from `@x = Const.new`; conflicting assignments latch to no type rather than guessing. - PASS 2 resolves constructors (`Const.new` targets the class node, the way Python's lsp_constructor does), implicit and explicit self dispatch, singleton methods, superclass chains, mixin lookup in Ruby's method-resolution order, super, and ivar / local / chained receivers. The stdlib seed covers Ruby core plus a curated Rails surface, including ActiveRecord query typing: `User.find(1)` is a User, and relation chains keep the model type. Dynamic dispatch (send, method_missing, define_method) and unresolved receivers emit no edge, and only project-defined targets are emitted. Cross-file resolution is a separate tier and is not part of this change; the 18 rows here drive the resolver through cbm_extract_file exactly as the extraction pipeline calls it. PROVENANCE: this resolver was authored clean-room from the tree-sitter-ruby grammar and Ruby language semantics. No Ruby language server source was consulted. scripts/check-lsp-originality.sh gains Shopify's ruby-lsp (MIT) as the Ruby reference so the boundary is auditable alongside the generated data it guards; `check-lsp-originality.sh --lang ruby` reports CLEAN — no verbatim string or comment overlap and no structural clones. Refs DeusData#1701 Assisted-by: OpenCode:anthropic/claude-opus-5 Signed-off-by: Ben Fairless <ben@oaf.org.au>
Signed-off-by: tmonestudio <tmonestudio@users.noreply.github.com>
Signed-off-by: lorenzozanee <wyz0707@proton.me>
Agents that use `git worktree add` to run parallel branches end up with one
indexed project per worktree. Each is a near-duplicate of the main checkout,
so the cache fills with redundant graphs and project pickers get noisy.
Add an opt-in `ignore_worktrees` config key. When enabled, a linked worktree
is left alone:
- auto-index on connect skips it (logged as autoindex.skip)
- the daemon's background auto-index skips it
- explicit index_repository refuses with an actionable message naming both
ways forward (index_worktree=true, or turn the key off)
- the hook-augment "not indexed" guidance stops telling the agent to run
index_repository in a directory where it would only be refused
Detection is git plumbing, no subprocess: <path>/.git must be a regular file
holding a "gitdir:" pointer AND that gitdir must contain a `commondir` file.
The commondir check is what separates a linked worktree from a submodule,
whose .git is also a gitlink file but whose gitdir has no commondir. The main
checkout of a repo that has worktrees is never affected.
Defaults to false, so behaviour is unchanged unless the key is set.
Signed-off-by: Nohj <vitalnohj@gmail.com>
pr-smoke (macos-14) was cancelled mid-run (operation was canceled) at an unrelated UI-server check, with all 30+ other legs green; ci-ok failed only as a consequence. Empty commit to get a fresh run. Signed-off-by: Amir Fathi <amirfathi.me@gmail.com>
Agents that use `git worktree add` to run parallel branches end up with one
indexed project per worktree. Each is a near-duplicate of the main checkout,
so the cache fills with redundant graphs and project pickers get noisy.
Add an opt-in `ignore_worktrees` config key. When enabled, a linked worktree
is left alone:
- auto-index on connect skips it (logged as autoindex.skip)
- the daemon's background auto-index skips it
- explicit index_repository refuses with an actionable message naming both
ways forward (index_worktree=true, or turn the key off)
- the hook-augment "not indexed" guidance stops telling the agent to run
index_repository in a directory where it would only be refused
Detection is git plumbing, no subprocess: <path>/.git must be a regular file
holding a "gitdir:" pointer AND that gitdir must contain a `commondir` file.
The commondir check is what separates a linked worktree from a submodule,
whose .git is also a gitlink file but whose gitdir has no commondir. The main
checkout of a repo that has worktrees is never affected.
Defaults to false, so behaviour is unchanged unless the key is set.
Signed-off-by: Nohj <vitalnohj@gmail.com>
Upstream's Unicode path fix dropped stat() from this file because it follows symlinks and rejects non-ASCII paths on Windows. Keep ignore_worktrees detection on cbm_path_info_utf8 so the rebase does not restore that probe. Signed-off-by: Nohj <vitalnohj@gmail.com>
A session queued while capacity was full could still be indexed after the setting was turned on. Retry admission now applies the same linked-worktree gate as the initial path. Signed-off-by: Nohj <vitalnohj@gmail.com>
The production hook builds its server with cbm_mcp_server_new(NULL), so ignore_worktrees stayed off and an unindexed linked worktree still told the agent to run index_repository. Attach the runtime store for that check, then drop it before return. Signed-off-by: Nohj <vitalnohj@gmail.com>
ignore_worktrees only inspected <path>/.git, so a session or index path inside a linked worktree still passed the gate. Walk ancestors until a git anchor, and stop at a main checkout or a submodule. Signed-off-by: Nohj <vitalnohj@gmail.com>
ignore_worktrees checked the setting only after project resolution, so a linked worktree nested in an indexed checkout was reported as that parent project. Drop an ancestor match and keep an index whose root is the worktree itself. Signed-off-by: Nohj <vitalnohj@gmail.com>
The parent-graph drop treated any linked worktree root as a match, so an unindexed worktree nested inside an indexed one still inherited that parent. Compare the gitdir of each path's own anchor and keep the project only when both paths are that same linked worktree. Signed-off-by: Nohj <vitalnohj@gmail.com>
A 64-level walk missed a deep session path, and a relative gitdir joined onto a symlink spelling no longer matched the real project root. Walk to the filesystem root and compare canonical gitdirs. Drop the unused project resolver that failed the macOS -Werror build. Signed-off-by: Nohj <vitalnohj@gmail.com>
A symlink into a linked worktree has no .git on its lexical path, so the hook told the agent to run index_repository. That call canonicalizes first and then refuses. Resolve the cwd before project lookup and the ignore_worktrees checks. Signed-off-by: Nohj <vitalnohj@gmail.com>
The ignore_linked initializer exceeded the formatter's assignment break. Lint treats that as an error, so the line now matches .clang-format. Signed-off-by: Nohj <vitalnohj@gmail.com>
The memory-core ratchet rejects another raw free() in the hook. Keep the parent name until the existing free(project) and skip it when the match is a different worktree. Signed-off-by: Nohj <vitalnohj@gmail.com>
The structural extractor names a class by appending the declaration's raw name text to the enclosing class QN, so `class Admin::User` yields `<module_qn>.Admin::User` while `module Admin; class User` yields `<module_qn>.Admin.User`. The resolver normalised both to the dotted form, and because the pipeline joins resolved rows to defs by exact caller QN, every row from or to a compact-declared class was silently dropped — the most common Rails style. All three passes now enter a class through one shared frame helper that computes the extractor-shaped QN from the raw name and keeps the dotted path only for constant lookup. The class table dedupes on QN. Nesting is now one raw frame per declaration joined by '.', and the constant probe strips one frame at a time: inside `class A::B` only `A.B.x` and `x` are tried, never `A.x`, matching Ruby's lexical scoping (`class A::B` does not open A). Tests pin exact QN equality on both ends of the row for compact, nested-compact, and the outer-scope-not-opened case. Assisted by OpenCode using anthropic/claude-fable-5-1. Signed-off-by: Ben Fairless <ben@oaf.org.au>
…ignment A `def` body inherited the enclosing scope, so a typed local from the surrounding body (or a preceding sibling method) typed a same-named parameter or local inside it. Parameters and block parameters were never bound, so they could not shadow an outer local either. And an assignment whose right-hand side had no proven type was ignored, so `a = Foo.new; a = x; a.bar` still resolved to Foo#bar. Ruby scoping is now modeled explicitly: `def`, `class` and `module` bodies start from a fresh, unparented scope; blocks and lambdas get a chained child scope; method, block and lambda parameters (including destructured groups and block-local names) bind to UNKNOWN; and any write the resolver cannot type — plain reassignment, multiple assignment, `||=` on an already-typed name, other compound operators, or an assignment inside a block — rebinds the nearest existing binding to UNKNOWN. `a ||= Foo.new` on a fresh name still types as Foo. Assisted by OpenCode using anthropic/claude-fable-5-1. Signed-off-by: Ben Fairless <ben@oaf.org.au>
PASS 1.5 only recorded `@x = Const.new` and ignored every other write, so `@x = compute` (or a parameter, a compound operator, a multiple assignment, or an unresolved constant's .new) left the ivar typed by whichever constructor it saw elsewhere. Any such write now latches the conflict, exactly as two different constructors already did; `nil` is neutral. `@x ||= Const.new` — the memoised-constructor idiom — counts as a constructor assignment. Assisted by OpenCode using anthropic/claude-fable-5-1. Signed-off-by: Ben Fairless <ben@oaf.org.au>
instance_eval/instance_exec, class_eval/class_exec, module_eval/ module_exec, define_method and Class.new/Module.new run their block with a different `self`, but bare and `self.` calls inside them were dispatched on the enclosing class. The eval call itself was already typed unknown; the walk into its block was not. The block of such a call is now walked with self_unknown set: bare calls, `self.` calls and `super` emit nothing there, `self` has no type, and PASS 1.5 does not attribute ivar writes inside it to the enclosing class. Receiver and argument expressions of the same call still resolve, and the suppression ends with the block. The *_exec forms join the dynamic-dispatch list. The existing negative test passed only because Meta had no `hidden`; it now has one, and the calls are written with `()` because tree-sitter-ruby parses a lone identifier as a variable reference, which the extractor never emits as a call. Assisted by OpenCode using anthropic/claude-fable-5-1. Signed-off-by: Ben Fairless <ben@oaf.org.au>
The lookup walks skipped a mixin whose module did not resolve and carried on to the class's own methods and superclass chain, and a bare call whose class ancestry did not resolve fell through to a same-named top-level def. An unseen ancestor may define or shadow the method, so none of those answers is trustworthy. Every lookup now carries a `blocked` flag set the moment the walk meets an unresolved prepend, include, extend or superclass reference, in Ruby's lookup order: an unresolved prepend blocks even an own-method hit; an unresolved include (or superclass) stops the walk before the superclass chain; an unresolved extend blocks the singleton walk. When blocked, nothing is emitted — no Object typing fallback, no top-level fallthrough, no `super` edge. Hits found before the unseen ancestor are still returned (an own method ahead of an unresolved include; a resolved include listed after an unresolved one). Assisted by OpenCode using anthropic/claude-fable-5-1. Signed-off-by: Ben Fairless <ben@oaf.org.au>
PASS 1 recursed through blocks and registered any `def` it met on the enclosing class or module, so ActiveSupport's `class_methods do … end` and `included do … end` bodies became instance methods of the concern and were then found through `include Concern` — edges to defs the structural extractor does not even emit. `include X` written inside such a block was likewise recorded on the concern instead of the includer. PASS 1 now tracks the block depth since the nearest class/module body and, inside a block, registers no methods and collects no mixins. In PASS 2 a class-body block def is skipped outright (no def exists for it to join), and a top-level block def (an RSpec group) is walked with self unknown: typed-receiver calls in its body may still resolve, bare and self. calls emit nothing, and other top-level code cannot reach it. Assisted by OpenCode using anthropic/claude-fable-5-1. Signed-off-by: Ben Fairless <ben@oaf.org.au>
The nested-modules row matched caller and callee by substring, which would have let a wrongly-spelled class path pass; it now pins the full extractor QNs on both ends with strcmp, as the compact-class rows already do. Refresh the file headers to describe the scope gates, fail-closed ancestry and self-rebinding rules the resolver now follows. Assisted by OpenCode using anthropic/claude-fable-5-1. Signed-off-by: Ben Fairless <ben@oaf.org.au>
…-6ddc feat(config): ignore_worktrees rework for DeusData#1430
Signed-off-by: Nohj <vitalnohj@gmail.com>
Signed-off-by: Nohj <vitalnohj@gmail.com>
Signed-off-by: Nohj <vitalnohj@gmail.com>
Signed-off-by: Nohj <vitalnohj@gmail.com>
…iority perf(index): run supervised index workers at below-normal CPU priority
…e-drops-held-lock fix(daemon): stop the lifetime-lock probe from dropping a held lock
…ons/actions/setup-python-7.1.0 build(deps): bump actions/setup-python from 7.0.0 to 7.1.0
…e-guard fix(install): reject unsupported Android portable installs
Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
index_coverage_meta is one of the tables the graph digest pins column by column, so the new indexed_checkout_sha column made the digest reject every live store with a schema error: the live-schema compatibility test failed, and test-impact, which digests the graph it builds for HEAD, fell back to running every test for every change. Record the checkout in a table of its own instead: index_checkout (project primary key referencing projects ON DELETE CASCADE, indexed_checkout_sha NOT NULL). A checkout is source identity, which the graph digest deliberately does not bind, and the store already keeps other per-project data (doc_link_*, observed_*) outside the digested tables. index_coverage_meta keeps exactly the shape the digest expects, so the digest needs no change and no version bump, and a new table needs no migration of existing databases. The row is written and cleared in the same coverage transaction, so a failed replace keeps the previous identity, and it is removed with its project. The store API is unchanged: cbm_coverage_meta_t carries indexed_checkout_sha as before. Read-only opens of databases without the table report no identity, as before. store_graph_digest_indexed_checkout_identity_is_not_bound writes a store through the real coverage API with and without a checkout SHA and asserts that it still digests and that the SHA leaves the digest unchanged. Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
Second maintainer refresh of DeusData#1561 (truthful index_status freshness), onto main 9c19b5d, after the fix-up that keeps the indexed checkout in its own index_checkout table (a0d0521). The first refresh is b44a22c. Five files conflicted; each is resolved as main plus the branch change: - src/pipeline/pipeline.c and src/pipeline/pipeline_incremental.c (two sites): main added .unresolved_calls_complete to the coverage-meta initializers where the branch added .indexed_checkout_sha. Both fields are kept, main first. - src/store/store.h cbm_coverage_meta_t: main added unresolved_calls_complete where the branch added indexed_checkout_sha. Both fields are kept, main first. - src/store/store.c init_schema: main added the unresolved_calls_complete column where the branch closed index_coverage_meta and created index_checkout. index_coverage_meta keeps main DDL exactly, and the index_checkout table follows it. - src/store/store.c coverage replace: main moved the coverage-meta write out of cbm_store_coverage_replace_ex into coverage_write_metadata, whose caller owns the transaction and rolls it back on failure. The branch wrote or cleared the index_checkout row right after that write, so its two calls move into the helper: the upsert path returns index_checkout_write(s, project, meta->indexed_checkout_sha), the delete path returns index_checkout_write(s, project, NULL). index_checkout_write stays where the branch defined it, ahead of the new helpers. - tests/test_store_nodes.c: main added store_coverage_shadow_excludes_unresolved_calls and its helper where the branch added store_coverage_meta_indexed_checkout_sha_roundtrip_and_rollback. Both tests are kept and registered, main first. src/pipeline/pipeline_internal.h merged without a conflict: main raised CBM_SEMANTIC_INDEX_VERSION to 13 for Next.js App Router routes, in a separate hunk from the branch's cbm_pipeline_indexed_checkout_sha declaration. No semantic conflicts: - The branch bumps no version. index_checkout is created by init_schema with IF NOT EXISTS and read only when present, so main's semantic index version 13 applies unchanged. - The branch changes no existing function signature, and main changes none that the branch calls. - Every main caller of cbm_store_coverage_meta_get added since the merge base, including the new Next.js upgrade test in test_pipeline.c, releases the result with cbm_store_coverage_meta_clear exactly once, which frees the checkout string. That test passes a shallow copy of the result to cbm_store_coverage_replace_ex and never frees the copy on its own. No test call site needed adapting. Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
feat(config): add ignore_worktrees to skip linked git worktrees
…file feat(lsp): add the Ruby per-file resolver
…uctor-calls-init fix(python): resolve ClassName() calls to __init__
…ons/actions/upload-artifact-7.0.2 build(deps): bump actions/upload-artifact from 7.0.1 to 7.0.2
…e-isolation fix(test): isolate benchmark harness daemon runtimes
…ul-index-freshness feat(mcp): report truthful index freshness from checkout evidence
…o fork Ancestry-preserving merge of upstream DeusData/codebase-memory-mcp through first-parent merge 5689ea5 ("Merge pull request DeusData#1561 ... truthful index freshness"). Fork base cf63fe6; previous merge base a5b248f; 104 upstream-only commits across 11 first-parent merges: DeusData#2747 Next.js app-router routes, DeusData#2838 index worker priority, DeusData#2207 lifetime lock probe, DeusData#2879 setup-python bump, DeusData#2245 Termux installer guard, DeusData#1430 ignore_worktrees, DeusData#1711 Ruby LSP per-file, DeusData#2424 Python constructor calls __init__, DeusData#2781 upload-artifact bump, DeusData#2198 benchmark runtime isolation, DeusData#1561 truthful index freshness. Conflict resolution (CLI-first): - src/mcp/mcp.c, src/mcp/mcp_internal.h, tests/test_mcp.c: kept deleted. MCP-side behaviour of DeusData#1430 (index_worktree override on explicit index) and DeusData#1561 (verbose index_status freshness block) is ported to the CLI in follow-up commits on this branch. - .github/workflows/pr.yml, test-impact-artifact.yml: kept deleted (Jenkins owns automatic CI). _build.yml keeps the fork's `platforms != 'linux'` guards and takes upload-artifact v7.0.2. release.yml keeps the fork side (no MCP registry checksum artifact). - Makefile.cbm: fork ALL_TEST_SRCS plus upstream TEST_RUBY_LSP_SRCS. - scripts/test.sh: keeps the fork's Jenkins prepare phase and adds upstream's Android/Termux installer guard step. - README.md, docs/CONFIGURATION.md, scripts/benchmark-*.sh: fork side kept; CLI-adapted docs and benchmark isolation follow separately. - src/daemon/application.c: ignore_worktrees gate reads the daemon's own config (application_ignore_worktrees_enabled) instead of an MCP session server; includes git/git_context.h. - src/cli/hook_augment.c / tests/test_cli.c: fork's CLI resolution path kept; worktree-ignored guidance text now names `codebase-memory-cli index`. Full ignore_worktrees hook resolution is ported in a follow-up. Checks: strict GitHub Actions policy passes; scripts/build-dev.sh and build/c/test-runner compile with -Werror; every fork-side hunk from a5b248f..cf63fe6 still applies in reverse to the result for files both sides touched (only the intentionally extended ALL_TEST_SRCS line differs); no fork-defined function was dropped.
…usData#1696) Finish the merge of the benchmark harness isolation work onto the CLI-first fork. The auto-merged upstream hunks left both scripts as a mix of fork and upstream invocations (undefined INDEX_RC, an unused INDEX_ERR, MCP `cli index_repository` calls). benchmark-index.sh: run `codebase-memory-cli index REPO --mode full --json` with stderr captured to INDEX_ERR and the exit status kept in INDEX_RC, so a refused index fails the run, prints "--- index stderr ---" and the cause. Dropped the now-unneeded hand-built JSON path (argv carries the path). benchmark-search-graph.sh: index through `index REPO --mode full --json` instead of the MCP `cli index_repository` request; stop unwrapping the MCP content envelope; fix usage comment (arg is a repo path). docs/EVALUATION_PLAN.md: example invocations name codebase-memory-cli. Contract test adaptations (assertions on isolation, stderr surfacing, exit status, handoff and stop behaviour unchanged): - Probe fixture detects `index` (argv 1) instead of `cli index_repository`. - The fixture logs the repo path (argv 2) rather than a JSON body; the quoted/backslash-path check now asserts the path reaches the index command as one intact argument, since the fork's CLI has no JSON request. - "MCP session" comment wording changed to "graph session".
Port upstream DeusData PR DeusData#1561 from the removed MCP server into the operations layer. `status --verbose` now emits a `freshness` object next to the unchanged `git` object: - indexed_generation, indexed_checkout_sha (recorded in coverage meta at the staged-generation boundary), checkout_sha (live HEAD) - status_available plus bounded tracked_changes / untracked_source samples (cap 16, truncated flag) from cbm_git_worktree_status - verdict current/stale/unknown, dominant reason, reasons[] (max 8), recommended_action The verdict is fail-closed: a missing recorded identity is unknown, a SHA mismatch or tracked changes are stale, and untracked sources, an unavailable git status or an unresolvable HEAD prevent "current". It is report-only and never triggers indexing; the default (non-verbose) status output is unchanged. The status tool schema description and docs/MEASURING_SAVINGS.md describe the new block. Integration tests (real git repos, real project DB in a private cache dir) cover current, mismatch, tracked, untracked-only, mixed, non-git, missing identity, sample-cap truncation and the verbose-only gate.
…d explicit index refusal hook_augment: when ignore_worktrees is on in an existing _config.db (never created by the hook), canonicalize cwd and resolve the project through ha_resolve_project_ignoring_worktrees, dropping a parent graph that does not belong to the cwd's own linked worktree and switching to the 'not indexed on purpose' guidance. Key off (default) takes the previous path and the test gate counter does not move. index operation: an explicit index of a linked git worktree is refused when ignore_worktrees is on, with an error naming --index-worktree (per-call index_worktree arg, added to the tool schema) and 'config set ignore_worktrees false'. No silent skip. docs/CONFIGURATION.md: settings row, config example, CLI wording for the ignore_worktrees section, --index-worktree mention. tests: refusal/override/off/main-checkout integration test with a real git worktree, --index-worktree arg parsing test, and hook assertions updated for the CLI guidance text (codebase-memory-cli index).
cbm_git_context_resolve returns 0 on success, but execute_status treated its result as a boolean, so status --verbose only entered the git branch when resolution failed (and then is_git was unset). The git object was therefore never emitted. Compare against 0 like the other callers (http_server.c, pipeline.c). Found while porting upstream DeusData#1561.
index_policy_mcp_rejects_forged_override_and_preserves_serving_index called th_mktempdir twice and kept both returned pointers, but th_mktempdir returns a shared static buffer. After the second call `repo` and `cache` were the same string (the cache directory), so the first index_repository request targeted the cache root and was refused by the workspace guard: /tmp/cbm_index_policy_mcp_cache_LjrHdR: path is a volume root or holds the codebase-memory cache; it cannot be indexed. That guard is intentional (fork commit 19f5bdf, "fix workspace cache root authorization"), which landed on main after the last green full Jenkins run (DeusData#88 at 214b87b). The failure therefore pre-exists on main cf63fe6 and surfaced in release-tooling build DeusData#89; it is not caused by the upstream 13M-1 merge. Copy each path into its own buffer so the fixture's repository and cache are separate sibling directories. Product behaviour is unchanged. Root cause found by a Codex gpt-6-luna agent; verified by rerunning the index_policy and index_supervisor suites.
|
Caution Review failedThe pull request is closed.
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. |
ngallodev
left a comment
There was a problem hiding this comment.
Reviewed PR #33 at c3c5271. The index_policy failure is caused by the test retaining two pointers to th_mktempdir's shared static buffer; the second call replaced the repo path with the cache path, which the workspace guard correctly refuses. Copying each path into its own buffer fixes the fixture while preserving the intentional cache-root denial. Local validation passed: dev build, test-runner build, memory-core lint (3211 raw allocator sites across 102 files, none grew), index_policy 12/12, and index_supervisor 11/11. Jenkins DeusData#90 is reported successful on this exact head. Native Windows validation remains unrun. No blocking findings.
ngallodev
left a comment
There was a problem hiding this comment.
Review passed after an independent review of exact head c3c5271ab8f454287452f0df5eca9e38ffd250cf.
- Verified
5689ea54cis an ancestor, the sync is 0 commits behindcf63fe667, and the checkpoint merge records both parents. - Checked the full 59-file diff, including the DeusData#2198, DeusData#1561 and DeusData#1430 CLI ports, their call sites, publication and rollback paths, and the MCP/automatic-trigger exclusions. No blocking correctness finding.
- Local:
scripts/test.sh --suites git_context,incrementalpassed 192 tests.tests/test_benchmark_runtime_isolation_contract.sh,tests/test_install_android_guard.sh, andgit diff --checkpassed. The review used an unchanged local checkout; the working tree was clean at the files being reviewed.
Limits: native Windows was not exercised in this review. The added worktree and symlink fixtures are skipped on Windows, so Linux coverage does not establish Windows parity. The prior Jenkins DeusData#90 and draft-state checks are separate evidence.
…ification Adds per-batch receipts (13m1.md, 13m2.md, 13n.md) and updates ledger.json, PLAN.md and CONTINUE.md for the 2026-11-08 upstream closeout against DeusData 612eee2. Jenkins release-tooling full gate, exact heads: - 13M-1 c3c5271: DeusData#90 SUCCESS; merged to main via PR #33 (929adfe). DeusData#89 on 3cbefe2 failed only on the index_policy fixture fixed there. - 13M-2 0f1927f: DeusData#93 SUCCESS. DeusData#91 on 1c5f82a failed two upstream Hermes hook cycle tests, fixed in 0f1927f. - 13N 98eab3c: DeusData#94 SUCCESS. DeusData#92 on cf24b6a was aborted because that head lacked the 13M-2 test fix. Native Windows was not run for any batch, so the reserved-`nul` change (DeusData#2903) is unverified on Windows. This commit only touches docs; the code Jenkins qualified is 98eab3c.
First of three stacked upstream-sync PRs (13M-1 → 13M-2 → 13N) that bring the fork up to DeusData/codebase-memory-mcp
612eee251. This one merges the first upstream checkpoint with real ancestry and ports the shared features that apply to the CLI.The plan labels batches by upstream range: 13M-1 (this PR) and 13M-2 cover upstream up to
e0c7a1da6, and 13N covers the rest up to612eee251.Ancestry
main)cf63fe667579482c7e3b73238b73d4ad2d01db975689ea54ceac23d7e5bf59d54b9c718b59ae9ee0(first-parent ancestor of upstreammain; 104 commits, 11 first-parent PR merges)3a4fdb9b975106489b764556823d9528681301c2(--no-ff, parentscf63fe667+5689ea54c)c3c5271ab8f454287452f0df5eca9e38ffd250cfgit merge-base --is-ancestor 5689ea54c c3c5271abholds. Relative tomain, this branch is 108 ahead and 0 behind.Commits on top of the merge
42a2e2dd7: port of upstream fix(test): isolate benchmark harness daemon runtimes DeusData/codebase-memory-mcp#2198 (benchmark runtime isolation, from Audit smoke, soak, profiling, and benchmark harnesses for account daemon runtime isolation DeusData/codebase-memory-mcp#1696). The bench scripts andtests/test_benchmark_runtime_isolation_contract.shnow use CLI argv in place of MCP calls.0aad606d0: port of feat(mcp): report truthful index freshness from checkout evidence DeusData/codebase-memory-mcp#1561.status --verbosenow reports an index freshness verdict and worktree status.0dccc267b: port of feat(config): add ignore_worktrees to skip linked git worktrees DeusData/codebase-memory-mcp#1430,ignore_worktrees:indexrefuses a linked worktree unless--index-worktreeis passed, and the refusal names that flag andconfig set ignore_worktrees false.docs/CONFIGURATION.mddocuments the setting.3cbefe210: fixesstatus --verbose, which never emitted itsgitobject.cbm_git_context_resolvereturns 0 on success and the old check had that backwards. The bug predates this merge.c3c5271ab: fixes theindex_policytest fixture. It usedth_mktempdir's static buffer for both the repo and cache roots, so the cache-root guard added in19f5bdfa8refused to index. The test has failed onmainsince19f5bdfa8. The fixture now copies each root into its own buffer.Excluded (MCP-only)
Changes to
src/mcp/*,tests/test_mcp.c, the MCP frontend recovery insrc/daemon/frontend.c(DeusData#1784; the file is deleted in the fork), and MCP registry/packaging steps inrelease.ymlwere not taken. The PR adds no automatic GitHub Actions triggers. The automatic-trigger workflowspr.ymlandtest-impact-artifact.ymlare left out, andscripts/ci/check-github-actions-policy.pypasses.Verification
scripts/build-dev.shwith-Werror,scripts/lint-memory-core.py(ratchet holds), Actions policy check, targeted suites 18/18, andindex_policy12/12.c3c5271ab: release-tooling build Installation using asdf DeusData/codebase-memory-mcp#90 SUCCESS. Build Virus detected in ui version DeusData/codebase-memory-mcp#89, run on the earlier head3cbefe210, failed only on theindex_policyfixture fixed above.Migrations
None. No schema or index-format change. A new config key,
ignore_worktrees, defaults tofalse.Review
docs/upstream-sync/land with 13N.mainneeds explicit human approval.