Commit Graph
1107 Commits
Author SHA1 Message Date
Martin Vogel 92a27deab0 Merge pull request #883 from jstar0/fix/cypher-path-semantics
fix(cypher): enforce variable-length path semantics
2026-08-26 18:54:58 +02:00
King Star 7583376fd0 test(cypher): make bounded trails deterministic
Signed-off-by: King Star <mcxin.y@gmail.com>
2026-08-22 03:50:42 +08:00
Alexander Musichen 104c9a7262 Merge branch 'main' into fix/pi-extension-tool-schemas 2026-08-21 04:26:56 +02:00
Alex Musichen 2ae84e7f73 test(pi): pin result wrap, error throw, and abort in generated adapter
Maintainer asked for in-tree coverage of {content, details} wrapping and
how tool errors are surfaced, plus a cheap abort-signal line. String-shape
only; no live Pi process.

Signed-off-by: Alex Musichen <alex.musichen@gmail.com>
2026-08-21 04:11:51 +02:00
Martin Vogel 65c7cf10f3 Merge pull request #1775 from DeusData/distill/install-plan-fixture-cleanup
test(cli): clean up before failing the install-plan receipt fixture
2026-08-21 02:58:52 +02:00
Martin Vogel 35ddda9f51 Merge pull request #1774 from DeusData/distill/nomic-blob-generator
fix(build): stop blob regeneration from reverting the ELF stack hardening
2026-08-21 02:15:24 +02:00
Martin Vogel 7b6363d0b6 Merge pull request #1772 from DeusData/fix/startup-coordination-lingering-lock
fix(cli): wait out a held startup transition instead of failing at 10s
2026-08-21 01:44:12 +02:00
Martin Vogel 8ec7e5c322 Merge pull request #1771 from DeusData/fix/java-enum-methods
test(java): pin enum constants surviving alongside enum methods
2026-08-21 00:58:57 +02:00
Martin VogelandAnand Aiyer f3b356afed test(cli): clean up before failing the install-plan receipt fixture
cli_install_plan_receipt_no_mutation_issue388 asserted inline, so any failure
returned before free(json) and test_rmdir_r(tmpdir). A red run therefore leaked
the receipt and left a stray /tmp/cli-plan-* directory behind -- the failure
report was accompanied by exactly the noise that makes the next debugging
session harder.

Record what went wrong, release everything, then fail. The message now names
the specific missing marker rather than reporting that some marker was absent,
which is the difference between reading a failure and bisecting one.

The env-isolation half of the original PR is not carried over: main's
tf_setup_cache_sentinel already unsets CODEX_HOME along with every other client
home override, so a per-test save/unset/restore would be redundant now.

Distilled from #1149 by Anand Aiyer, which predates that sentinel and could not
land as written once its companion PR closed unmerged.

Co-authored-by: Anand Aiyer <anand@aiyer.com>
Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
2026-08-20 21:36:57 +02:00
Martin VogelandAnand Aiyer 18edfa0023 fix(build): stop blob regeneration from reverting the ELF stack hardening
vendored/nomic/code_vectors_blob.S is a GENERATED file that was hand-edited.
1f674c80 added the ELF .note.GNU-stack section to it after finding that every
Linux binary we had ever shipped requested an executable stack: an object
carrying no such note tells GNU ld nothing about its stack requirement, and ld
then assumes the worst for the entire link. That fix went into the artifact
only. scripts/extract_nomic_vectors.py still emitted the Mach-O branch alone,
so the next regeneration would have overwritten the tracked .S, dropped both
the ELF and COFF branches, and put GNU_STACK RWE back into every release --
silently, because nothing compared the generator against its own output.

write_blob_s() now emits the tracked wrapper verbatim, and the new contract
test fails if the two ever drift again. The template is compared rather than
executed so the test does not need the torch/transformers import the extraction
script pulls in. The write is pinned to UTF-8 because the WHY comment carries
an em dash and the default encoding is locale-dependent.

check-binary-composition.sh already fails a release whose binary has an
executable stack; this closes the same hole at edit time, where the diff is
still small enough to read.

Reported and originally fixed by Anand Aiyer in #1151, which also carried the
COFF branch. That PR sat unreviewed for a month while the .S half was
rediscovered and landed independently without credit.

Co-authored-by: Anand Aiyer <anand@aiyer.com>
Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
2026-08-20 21:20:44 +02:00
Martin Vogel e830293ef1 Merge pull request #1065 from tmonestudio/codex/fix-json-edge-properties
fix(pipeline): escape dynamic edge properties as JSON
2026-08-20 19:11:33 +02:00
Martin Vogelandsahil-mangla 1acd87912f test(java): pin enum constants surviving alongside enum methods
Java enum methods already resolve on main: find_class_member_body
descends into enum_body_declarations (Java-gated) while find_class_body
keeps returning enum_body, which is what extract_enum_members needs to
reach the constants — they are siblings of enum_body_declarations, not
children.

That distinction was unguarded. java_enum_dedup_preserves_calls_issue1234
asserted the methods and the absence of duplicate Function defs, but
never asserted the constants, so collapsing the two lookups would have
passed the suite while silently dropping every enum constant from the
graph.

PR #984 proposed exactly that collapse — redirecting the shared
find_class_body — which is what surfaced the gap. Verified binding:
pointing extract_enum_members at find_class_member_body reddens the new
Variable assertions and nothing else.

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
Co-authored-by: sahil-mangla <manglasahil2017@gmail.com>
2026-08-20 18:42:26 +02:00
Martin Vogelandbethzyy 1af49dfe58 fix(watcher): stop nested non-git dirs and monorepo siblings retriggering
Three related defects in how the watcher decides what counts as a change.

1. `git rev-parse --git-dir` walks UP the tree, so an ordinary folder that
   merely sits under an unrelated repository answered yes. The watcher then
   inherited that ancestor's dirty state -- permanently non-empty and about
   entirely different files -- and reindexed on every poll forever. A
   directory is now git-managed only if it carries its own .git (directory
   or gitlink file) or the ancestor actually tracks something inside it, so
   a real monorepo sub-package still qualifies while a scratch or ignored
   folder does not.

2. `git status` reports the whole repository regardless of -C, so every
   package in a monorepo reindexed whenever any sibling was edited. The
   status call is now scoped with a `-- .` pathspec.

3. Porcelain paths are REPOSITORY-relative but were stat'ed against
   root_path. For a project watched at the repository root the two coincide
   and the bug is invisible; for a subdirectory project every stat missed,
   silently degrading the dirty signature to text-only and losing the
   size/mtime component that makes an edit to an already-dirty file
   detectable. Paths now resolve through `rev-parse --show-cdup`.
   --show-cdup rather than --show-toplevel because MSYS/Cygwin git returns a
   translated absolute path from the latter that will not join onto the
   native path we hold; a relative hop composes on every platform.

Distilled from #1001 by bethzyy, whose diagnosis identified all three.
Main independently fixed that PR's two headline problems (the unbounded
non-git file count, and per-poll churn via a dirty-state signature) while
it waited, and the watcher was rewritten onto a supervised argv-spawn
harness in between, so this is a reimplementation against the new code
rather than a rebase of theirs.

Both new tests are verified binding: reverting the classification guard
reddens the nested-directory test, and removing the pathspec reddens the
monorepo one, each without disturbing the other.

Addresses the remaining parts of #713, #841 and #937.

Co-authored-by: bethzyy <bethzyy@users.noreply.github.com>
Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
2026-08-20 16:43:38 +02:00
King Star 12b7886648 test(cypher): avoid duplicate upstream regression
Signed-off-by: King Star <mcxin.y@gmail.com>
2026-08-20 22:42:09 +08:00
King Star cd22487ca6 fix(cypher): surface bounded trail traversal truncation
Signed-off-by: King Star <mcxin.y@gmail.com>
2026-08-20 22:38:57 +08:00
King Star 0d97729c39 fix(cypher): scope trail traversal to path expansion
Signed-off-by: King Star <mcxin.y@gmail.com>
2026-08-20 22:38:57 +08:00
King Star 0c5ffa50f9 fix(store): cap recursive BFS path rows
Signed-off-by: King Star <mcxin.y@gmail.com>
2026-08-20 22:38:57 +08:00
King Star 8546070dc2 fix(cypher): enforce variable-length path semantics
Signed-off-by: King Star <mcxin.y@gmail.com>
2026-08-20 22:38:57 +08:00
Martin Vogel 5e9c63304e Merge pull request #1763 from DeusData/feat/swift-protocol-methods
fix(swift): index protocol method requirements as Method nodes
2026-08-20 15:19:53 +02:00
Martin Vogelandxbsjason 5cabeb4b10 fix(swift): index protocol method requirements as Method nodes
A Swift protocol requirement — a bodyless `func generate() -> String`
inside a protocol — was absent from the graph entirely. Swift codebases
are heavily protocol-driven, so the requirement is very often the
declaration a reader is looking for, and "who declares generate()" had no
answer.

Three edits deliver it: protocol_body joins the class-body types so a
protocol's members are walked at all; protocol_function_declaration joins
swift_func_types, because extract_class_methods gates on that set and
would otherwise walk the requirement and discard it; and both name
resolvers accept the node, which has the same simple_identifier shape as
function_declaration.

Distilled from #613 by xbsjason. That PR also carried an enum/struct half
whose two assertions fail on CI: tree-sitter-swift has no
struct_declaration or enum_declaration node type (it models both as
class_declaration), so the corresponding swift_class_types entries are
inert and a bare enum is still labeled Class. That is a real pre-existing
modelling gap, left untouched here and now documented at the dead entries
rather than silently deleted.

Also dropped from the original: a find_first_descendant_by_kind rescue in
extract_class_methods. Removing it changes no test outcome once the
function-type entry is present, so it was carrying nothing.

Advances #43.

Co-authored-by: xbsjason <xbsjason@gmail.com>
Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
2026-08-20 13:39:49 +02:00
Martin Vogelandalexisperinger-ux 43ecc0988c feat(dbt): extract dbt model lineage from Jinja-templated SQL
A dbt model is an ordinary .sql file whose dependencies are written
{{ ref('other_model') }} or {{ source('group','table') }}, never as
literal table names. The SQL grammar cannot read those -- FROM {{ ref(
'x') }} is a parse error to it -- so the dependency structure of an
entire dbt project was invisible to the graph.

extract_dbt.c runs as a sub-extractor inside the normal indexing
pipeline. Per qualifying file it emits one Model definition (named by
the file stem, dbt's own model identity) plus one usage per ref()/
source() call; pass_usages resolves those into model -> relation
lineage edges like any other reference.

Model is a relation label alongside Table and View, which is what makes
the rest work without new plumbing: registry seeding, the central
relation veto, the incremental surface hash, search ranking and the
architecture queries all pick it up from cbm_label_is_relation. Sharing
one label class also means a model's source('raw','customers') resolves
onto a Table declared in a plain DDL migration in the same repository,
so dbt lineage and SQL lineage form one graph rather than two, while
the veto keeps model names out of every non-lineage consumer.

The pass is self-gating: SQL files only, and only those carrying a real
ref()/source() call. The dbt builtins are themselves the evidence, which
is cheaper than a dbt_project.yml lookup and more precise -- templated
SQL that is not dbt (an Airflow {{ ds }} parameter) produces no Model
node and no usages even inside a dbt repository.

{% macro %} definitions are deliberately excluded: the vendored
tree-sitter-jinja2 grammar has no node types for {% %} statements, so
they can only be recovered by a hand-written scanner that cannot see
comments or find {% endmacro %} for a correct span. Filed as follow-up
rather than approximated.

Tests cover the lineage, the last-string-argument semantics of both
builtins, the gate (against a plain-SQL control extraction), plain DDL
staying untouched, and an end-to-end pipeline case asserting model ->
model across files, model -> Table onto plain DDL, and cross-language
isolation. Disabling the pass reddens three of them; removing Model from
the relation set breaks lineage outright.

Implements the lineage half of #575.

Co-authored-by: alexisperinger-ux <alexis.peringer@iss-stoxx.com>
Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
2026-08-20 10:23:48 +02:00
Alexander Musichen 495a79dc25 Merge branch 'main' into fix/pi-extension-tool-schemas 2026-08-20 04:14:09 +02:00
Martin Vogelandalexisperinger-ux 7ba84e3754 feat(sql): first-class Table/View nodes with FROM/JOIN lineage
CREATE TABLE / CREATE VIEW / CREATE MATERIALIZED VIEW now produce Table
and View nodes (previously generic Variable), CREATE PROCEDURE produces
a Function, and schema-qualified DDL names (schema.table) are named by
the table identifier instead of the schema. A view's FROM/JOIN relations
are emitted as usages and resolve into view -> table USAGE lineage
edges.

Relations join the cross-file name registry so lineage can resolve, with
two structural safeguards:

- Registry membership is defined once by cbm_label_is_registry_symbol
  (helpers.c); the full, parallel and incremental seed sites all call
  it, ending the KEEP-IN-SYNC copies the old label lists required.
- The default cbm_registry_resolve vetoes relation-labeled results:
  common table names (users, orders, config) collide with code
  identifiers in every language, and no CALLS/USAGE/READS/WRITES/THROWS/
  handler/decorator consumer may bind them. The SQL lineage path opts in
  through the new cbm_registry_resolve_lineage.

Table/View also join the registry-only per-file LSP surface labels so a
table rename invalidates dependent SQL files on incremental (no stale
lineage edges), rank with the type tier in BM25 search, and appear in
the architecture boundary/package/cluster queries via the pinned
CBM_SQL_RELATION_LABELS fragment.

Tests: extraction trio (labels, lineage usages, schema-qualified names),
grammar golden + probe updates, relation-label contract pin, and two
pipeline tests: cross-language isolation (binding: fails without the
veto) and incremental table-rename stale-lineage.

Closes #574.

Co-authored-by: alexisperinger-ux <alexis.peringer@iss-stoxx.com>
Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
2026-08-20 00:12:28 +02:00
Martin Vogel 98c1f8c3e1 test: gate-chain contract pins the explicit-result conditions
The contract required the bare '!cancelled() && !failure()' idiom on
build/smoke/soak — the exact form the v0.10.7 incident proved fail-open
(failure() does not cover a CANCELLED needed job). It now requires each
gate's explicit accepted results, the sanctioned skip_tests clause on
build, and the preflight version guard wired before lint.

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
2026-08-18 22:30:28 +02:00
Alexander Musichen 0b22dfff7b Merge branch 'main' into fix/pi-extension-tool-schemas 2026-08-18 20:52:22 +02:00
Martin Vogel afebf0092b Merge pull request #1326 from Enferlain/fix/1287-persisted-coverage-summary
fix(index): preserve persisted coverage summaries
2026-08-18 18:57:53 +02:00
Martin Vogel 39bd040505 Merge pull request #1699 from DeusData/fix/lf-endings-distill
fix(build): LF contract for extensionless git hooks + a line-ending guard
2026-08-18 16:36:50 +02:00
Martin Vogel 00beec9397 Merge pull request #1608 from ertankucukoglu/fix/search-code-cancellation
fix(mcp): bound and cancel Windows code search
2026-08-18 16:36:40 +02:00
Alexander Musichen 1f1832ab37 Merge branch 'main' into fix/pi-extension-tool-schemas 2026-08-18 13:37:23 +02:00
Martin Vogel fe4396f906 Merge branch 'main' into fix/1287-persisted-coverage-summary 2026-08-18 11:21:46 +02:00
Martin Vogelandxumian520 32633bab9a fix(build): LF contract for extensionless git hooks + a line-ending guard
The *.sh eol=lf rule landed via #1314, but the git hooks
(scripts/git-hooks/commit-msg, scripts/hooks/pre-commit) are extensionless
and were still at the mercy of core.autocrlf. Add their explicit entries,
plus the contract test from #1272 wired as scripts/test.sh Step 0t: every
shell entrypoint (*.sh + both hook directories) must carry an eol=lf
attribute, with a matched-zero-files guard so a broken glob can never pass
vacuously.

Distilled from #1272: the diagnosis (CRLF checkouts breaking shebangs under
WSL/MSYS), the hook-file coverage, and the guard design are @xumian520's;
verified RED without the *.sh rule (105 uncovered entrypoints) and green
with it (107 files).

Co-Authored-By: xumian520 <126989134+xumian520@users.noreply.github.com>
Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
2026-08-18 11:21:36 +02:00
Martin Vogel 58ef9f19ac fix(cypher): expansion materializes every matched row — the cap falsified aggregates
Second mechanism of #1196, exposed by the reporter's v0.10.6 retest: every
relationship-expansion site capped its output buffer at bind_cap*10, so edges
past the cap were silently dropped BEFORE WHERE and aggregation ever ran.
count() then reported the scanned prefix as if it were a fact — 9,360 of
13,691 DEFINES field-measured at --max-rows 1000 — and a LABEL on the source
did not protect you (the label workaround only ever fixed source
enumeration, which #1323 already made exact). max_rows is an output-row
limit per the public header; projection already enforces it.

All five capped sites now share one growable append (geometric growth,
size_t sizing): the per-hop expansion, its fixed/variable-length helpers and
process_edges, the bound-terminal driver, and the cross-join outer buffer.
Only allocation failure stops materialisation; match_count stays truthful
either way, so the #627 OPTIONAL contracts hold (a saturated buffer can no
longer exist, and the fallback rows share the same append). The #601
deadline still bounds pathological time, and hop caps keep bounding depth —
this removes only the silent row-dropping.

Regression test: 2 labeled sources x 30 edges with max_rows=2 — the old cap
returned count=20; ground truth 60 now holds, and the list form returns
exactly max_rows rows. Proven RED before and RED again on revert; cypher
181/181 and mcp suites green, including every OPTIONAL/#627 semantics test.

Fixes #1196 (together with #1323, which fixed the unlabeled source scan).

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
2026-08-18 11:19:32 +02:00
Martin Vogel 07cac7d6b3 Merge pull request #1371 from Joseph-MingEn/fix/py-aliased-from-import-calls
fix(python): resolve aliased from-import CALLS to real def
2026-08-18 11:19:19 +02:00
Martin Vogel 847da2fff2 fix: restore test closer lost in the merge resolution
The conflict's shared tail (#endif + closing brace) was emitted once for
two adjacent Windows tests; re-add the closer so both tests compile.

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
2026-08-18 11:18:43 +02:00
Martin Vogel e24ce80bdc Merge origin/main into fix/search-code-cancellation
Trivial insertion-point collision in tests/test_mcp.c: both this branch and
main (#1704's UTF-8 pin) add a Windows search_code test at the same spot.
Both tests kept.
2026-08-18 11:08:17 +02:00
Martin Vogel 9de6831d2c Merge pull request #1695 from astandrik/codex/fix-1691-test-runtime-isolation
fix(test): isolate harness daemon runtimes
2026-08-18 11:00:03 +02:00
Martin Vogel 4dd099679d fix(windows): pin the search_code PowerShell pipe to UTF-8
PowerShell 5.1 encodes stdout for a native-process pipe in the console
OEM codepage, so raw search content containing characters the inherited
CP cannot carry (Cyrillic under CP437/850, ...) reached
collect_grep_matches as '?' — and whether it degraded depended entirely
on which console the server happened to inherit. That surfaced as the
intermittent test_mcp raw-Русский mojibake on the windows CI leg and
means real Windows users in a default console get '?' for all
non-ASCII search_code raw content.

Every generated command now pins [Console]::OutputEncoding to UTF-8, so
the pipe is codepage-independent by construction. The read side needs
no pin: Select-String decodes BOM-less UTF-8 via .NET StreamReader
defaults. A Windows-side builder test asserts all five command variants
carry the prelude.

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
2026-08-18 09:31:59 +02:00
Martin Vogel 773bb037dc fix(test): the stdin gate's #1359 guards survive a registry with no zero-argument tool
#1181 gave list_projects pagination parameters, retiring the last
empty-properties schema — and the two #1359 regression tests leaned on
list_projects as their live zero-argument example, so main went red the
moment the merge train composed (the PR was green on its July base, which
predated these tests).

The gate's schema→decision core is split behind a CBM_CLI_ENABLE_TEST_API
seam, so the zero-argument branch stays pinned directly (empty properties,
absent properties, populated properties) regardless of what the registry
ships; list_projects now asserts its NEW truth (piped args accepted, TTY
still refused); and the schema↔gate parity sweep keeps running over every
tool without the impossible >=1 zero-argument floor. Production behavior
is unchanged — this is the tests catching up with an intended schema
change, plus a seam so they never again depend on a shipped example.

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
2026-08-18 07:15:09 +02:00
Alexander Musichen 4656a5f3e1 Merge branch 'main' into fix/pi-extension-tool-schemas 2026-08-18 04:20:37 +02:00
Alex Musichen 109299f262 fix(pi): match ToolDefinition.execute arity on 0.84.2
Pi 0.84.2 calls execute(toolCallId, params, signal, onUpdate, ctx).
The generated (args, ctx) shape bound the call id as the MCP arguments.

Forward params and signal, pin the @earendil-works/pi-coding-agent
contract in the generated header, and lock the 5-arg form in tests.

Signed-off-by: Alex Musichen <alex.musichen@gmail.com>
2026-08-18 04:11:49 +02:00
Martin Vogel 9a547b3399 Merge pull request #1253 from anfedoro/agent/fix-search-code-utf8
fix: preserve UTF-8 in search_code source
2026-08-18 00:14:32 +02:00
Martin Vogel 78d1b2f0a6 Merge pull request #1203 from ibaldr89/fix/extensionless-shebang-language
fix(discover): detect extensionless scripts by shebang
2026-08-18 00:14:17 +02:00
Martin Vogel b61949355b Merge branch 'main' into fix/1287-persisted-coverage-summary 2026-08-18 00:12:02 +02:00
Martin Vogel 3dab881b66 Merge pull request #1181 from tmonestudio/codex/fix-list-projects-coverage-scope
fix(mcp): restore scalable project discovery
2026-08-18 00:08:28 +02:00
Martin Vogel ce1f273efe Merge pull request #1467 from PR9000/fix/freebsd-platform-support
fix(daemon): add native FreeBSD process-image identity and /home log-path alias
2026-08-18 00:08:05 +02:00
Martin Vogel 415a64a2f9 Merge pull request #1263 from astandrik/fix/index-mode-capability-rebuild
fix: rebuild index when mode adds capabilities
2026-08-18 00:07:51 +02:00
Martin Vogel 89f0cd43c0 Merge pull request #1647 from rudi193-cmd/fix/725-cross-language-suffix-match
fix(registry): drop suffix_match CALLS across language boundaries
2026-08-18 00:05:33 +02:00
Martin Vogel 22d93dd12b Merge pull request #1323 from Enferlain/fix/1196-unlabeled-candidate-limit
fix(cypher): scan all unlabeled query candidates
2026-08-18 00:05:18 +02:00
Martin Vogel 2397d58da6 Merge pull request #1325 from Enferlain/fix/1284-list-valued-fields
fix(search): preserve compound requested fields
2026-08-18 00:04:55 +02:00
Martin Vogel de4ec9b5e9 Merge pull request #1319 from JJordan0C/fix/search-graph-semantic-only-results
fix(mcp): isolate semantic-only JSON search
2026-08-18 00:04:36 +02:00