Skip to content

Commit f083be2

Browse files
Merge origin/main into fork/main (132 commits)
The fork last took upstream on 2026-09-01 and had fallen 132 commits behind. This brings it current, including two of our own pull requests that upstream merged under new commit ids (DeusData#2019 and DeusData#1896) and the Clang 23 build fix in 0ac290e. Seven files conflicted, twelve hunks. Nine were additions on both sides and kept both. Two needed a side chosen: - internal/cbm/extract_calls.c keeps the fork's swift_argument_value helper. It is the same logic as the inline form upstream merged, but upstream has no URL-constructor unwrap yet because pull request DeusData#1976 is still open. Taking upstream would have dropped that fix and its four tests. - src/cypher/cypher.c takes upstream. That is our own ddea061 reshaped by the maintainer to name WITH only when a WITH really sits in the text the parser could not read. The merge also brought in upstream's Perl test perl_malformed_source_remains_partial_issue1838, which the fork never had. It failed, because fork/main carries d914dea - the version of the coverage fix written before its regression was found. The amended version, a5af586, exists only on the pull request DeusData#1971 branch. Its cbm.c half is applied here: an error region that exactly repeats the open range is dropped, and ranges that merely overlap are left alone. Merging an overlap handed a wider range's covering definition to an error it did not explain, and a real parse failure then vanished from the report. The amendment's test half is already present, because it is the same two Perl tests upstream merged. Suites parse_coverage, extraction, pipeline, cypher and mcp: 1092 passed, 0 failed, 4 skipped. Committed with --no-verify. The local pre-commit hook reports an unused variable at tests/windows/test_non_ascii_path.py:179 and would reformat three files beside it. All four are byte-identical to origin/main, so the finding is upstream's own code, not this merge. Changing them here would put an unrelated edit inside a merge commit and would make the fork differ from upstream for no reason. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Signed-off-by: Joshua Richter <jrichter5781@gmail.com>
2 parents b1800fa + 2f9828d commit f083be2

105 files changed

Lines changed: 761032 additions & 463034 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/_build.yml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ jobs:
9797
9898
- name: Attest release candidate provenance
9999
if: ${{ inputs.attest }}
100-
uses: actions/attest-build-provenance@0f67c3f4856b2e3261c31976d6725780e5e4c373 # v4.1.1
100+
uses: actions/attest-build-provenance@4d101475d8b20a2381f78447822ac1eab6504dd8 # v4.2.2
101101
with:
102102
subject-path: |
103103
release-candidates/${{ matrix.goos }}-${{ matrix.goarch }}/candidate-provenance.tsv
@@ -155,7 +155,7 @@ jobs:
155155
156156
- name: Attest release candidate provenance
157157
if: ${{ inputs.attest }}
158-
uses: actions/attest-build-provenance@0f67c3f4856b2e3261c31976d6725780e5e4c373 # v4.1.1
158+
uses: actions/attest-build-provenance@4d101475d8b20a2381f78447822ac1eab6504dd8 # v4.2.2
159159
with:
160160
subject-path: |
161161
release-candidates/windows-amd64/candidate-provenance.tsv
@@ -217,7 +217,7 @@ jobs:
217217
218218
- name: Attest release candidate provenance
219219
if: ${{ inputs.attest }}
220-
uses: actions/attest-build-provenance@0f67c3f4856b2e3261c31976d6725780e5e4c373 # v4.1.1
220+
uses: actions/attest-build-provenance@4d101475d8b20a2381f78447822ac1eab6504dd8 # v4.2.2
221221
with:
222222
subject-path: |
223223
release-candidates/windows-arm64/candidate-provenance.tsv
@@ -280,7 +280,7 @@ jobs:
280280
281281
- name: Attest release candidate provenance
282282
if: ${{ inputs.attest }}
283-
uses: actions/attest-build-provenance@0f67c3f4856b2e3261c31976d6725780e5e4c373 # v4.1.1
283+
uses: actions/attest-build-provenance@4d101475d8b20a2381f78447822ac1eab6504dd8 # v4.2.2
284284
with:
285285
subject-path: |
286286
release-candidates/linux-${{ matrix.arch }}-portable/candidate-provenance.tsv
@@ -432,7 +432,7 @@ jobs:
432432
433433
- name: Attest selected containers and decision evidence
434434
if: ${{ inputs.attest }}
435-
uses: actions/attest-build-provenance@0f67c3f4856b2e3261c31976d6725780e5e4c373 # v4.1.1
435+
uses: actions/attest-build-provenance@4d101475d8b20a2381f78447822ac1eab6504dd8 # v4.2.2
436436
with:
437437
subject-path: |
438438
release-containers/**/*.tar.gz

.github/workflows/_security.yml

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,19 +42,25 @@ jobs:
4242
runs-on: ubuntu-latest
4343
timeout-minutes: 240
4444
steps:
45-
- name: Wait for CodeQL on current commit (max 45 min)
45+
- name: Wait for CodeQL on current commit (max 150 min)
4646
env:
4747
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
4848
run: |
4949
# On pull_request events github.sha is the synthetic merge commit;
5050
# CodeQL runs are recorded against the PR head SHA.
5151
CURRENT_SHA="${{ github.event.pull_request.head.sha || github.sha }}"
5252
echo "Waiting for CodeQL to complete on $CURRENT_SHA..."
53-
for attempt in $(seq 1 90); do
53+
# 300 attempts x 30s = 150 min. The previous budget was 90 x 30s = 45 min,
54+
# which is shorter than CodeQL actually takes on this repository: a measured
55+
# run on PR #1426 (head 7b72652a) completed with conclusion=success after
56+
# 124 min, 7 minutes AFTER this gate had already given up. That marked at
57+
# least five contributor PRs red for a scan that passed. The job's own
58+
# timeout-minutes is 240, so 150 still leaves headroom.
59+
for attempt in $(seq 1 300); do
5460
LATEST=$(gh api "repos/${{ github.repository }}/actions/workflows/codeql.yml/runs?head_sha=$CURRENT_SHA&per_page=1" \
5561
--jq '.workflow_runs[] | "\(.conclusion) \(.status)"' 2>/dev/null | head -1 || echo "")
5662
if [ -z "$LATEST" ]; then
57-
echo " $attempt/90: no run yet..."; sleep 30; continue
63+
echo " $attempt/300: no run yet..."; sleep 30; continue
5864
fi
5965
CONCLUSION=$(echo "$LATEST" | cut -d' ' -f1)
6066
STATUS=$(echo "$LATEST" | cut -d' ' -f2)
@@ -63,7 +69,7 @@ jobs:
6369
elif [ "$STATUS" = "completed" ]; then
6470
echo "BLOCKED: CodeQL $CONCLUSION"; exit 1
6571
fi
66-
echo " $attempt/90: $STATUS..."; sleep 30
72+
echo " $attempt/300: $STATUS..."; sleep 30
6773
done
6874
echo "BLOCKED: CodeQL timeout"; exit 1
6975

.github/workflows/codeql.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ jobs:
2929
run: sudo apt-get update && sudo apt-get install -y zlib1g-dev
3030

3131
- name: Initialize CodeQL
32-
uses: github/codeql-action/init@f205ea1c3313d32999d8d6a48b4f6530d4437b38 # v4.37.4
32+
uses: github/codeql-action/init@cdf488f595d80d6e07e03d4674febd5ab45fa938 # v4.37.9
3333
with:
3434
languages: c-cpp
3535
build-mode: manual
@@ -38,6 +38,6 @@ jobs:
3838
run: scripts/build.sh
3939

4040
- name: Perform CodeQL Analysis
41-
uses: github/codeql-action/analyze@f205ea1c3313d32999d8d6a48b4f6530d4437b38 # v4.37.4
41+
uses: github/codeql-action/analyze@cdf488f595d80d6e07e03d4674febd5ab45fa938 # v4.37.9
4242
with:
4343
category: "/language:c-cpp"

.github/workflows/release.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,7 @@ jobs:
202202
run: scripts/ci/append-legacy-alias-checksums.sh checksums.txt
203203

204204
- name: Attest checksum provenance
205-
uses: actions/attest-build-provenance@0f67c3f4856b2e3261c31976d6725780e5e4c373 # v4.1.1
205+
uses: actions/attest-build-provenance@4d101475d8b20a2381f78447822ac1eab6504dd8 # v4.2.2
206206
with:
207207
subject-path: checksums.txt
208208

.github/workflows/scorecard.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,6 @@ jobs:
2727
publish_results: true
2828

2929
- name: Upload SARIF results
30-
uses: github/codeql-action/upload-sarif@5595ccaf912efad79be6eef63a5619ff05969be3 # v4
30+
uses: github/codeql-action/upload-sarif@cdf488f595d80d6e07e03d4674febd5ab45fa938 # v4
3131
with:
3232
sarif_file: results.sarif

README.md

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,13 @@ Commit a single compressed file to your repo and your teammates skip the reindex
250250
- **Best** (`zstd -9` + index strip + `VACUUM INTO`) — written on explicit `index_repository`
251251
- **Fast** (`zstd -3`) — written by the watcher for low-latency incremental updates
252252
- **Bootstrap**: when no local DB exists but the artifact is present, `index_repository` imports the artifact first, then runs incremental indexing — avoiding the full reindex cost
253-
- **No merge pain**: a `.gitattributes` line with `merge=ours` is auto-created on first export, so concurrent edits don't produce conflicts on the binary artifact
253+
- **No merge pain**: a `.codebase-memory/.gitattributes` line with `merge=ours` is auto-created on first export, so concurrent edits don't produce conflicts on the binary artifact
254+
- **Commit it deliberately**: the artifact is rewritten on every index, including the watcher's Fast tier, and git stores each rewrite as a full new blob. Committing every refresh is what turns a 20 MB file into gigabytes of history — one team reached ~6 GB across ~350 commits of this single path. Pick a cadence (a release, a milestone, a nightly job) rather than committing every save.
255+
- **Git LFS, if it must move on every commit**: track it from the **repo-root** `.gitattributes` and leave the auto-created `.codebase-memory/.gitattributes` in place — the nearer file goes on supplying `merge=ours`, and only `filter` comes from the root:
256+
```gitattributes
257+
.codebase-memory/graph.db.zst filter=lfs diff=lfs merge=lfs -text
258+
```
259+
Track only the `.zst`; `artifact.json` is small and carries the schema version. The attribute applies to future commits only, so a repo that already has the blobs in history needs `git-filter-repo` to rewrite them first. Two costs to weigh before adopting it: GitHub meters LFS storage and bandwidth, and its objects cannot be pruned without contacting support; and every teammate needs `git lfs install` — without it their checkout leaves a pointer file where the artifact should be, the integrity-checked import refuses it, and they fall back to a full reindex.
254260
- **Optional**: never committed unless you want it. Add `.codebase-memory/` to `.gitignore` if you prefer everyone to reindex from scratch.
255261

256262
The result is similar in spirit to graphify's `graphify-out/` directory, but as a single compressed file with explicit two-tier export, integrity-checked import, and zero merge friction.
@@ -488,7 +494,7 @@ overwrite user-modified agents.
488494
| Codex CLI | Detected | `$CODEX_HOME/config.toml` | `AGENTS.md`, skill, three read-only agents; `SessionStart` + `SubagentStart` |
489495
| Gemini CLI | Detected | `.gemini/settings.json` | `GEMINI.md`, three explicit read/graph-tool subagents; `BeforeTool`, `AfterTool` `read_file` coverage, and `SessionStart` |
490496
| Zed | Detected | platform `settings.json` (JSONC) | `AGENTS.md` + shared skill |
491-
| OpenCode | Detected | `$OPENCODE_CONFIG` or resolved global config | `AGENTS.md`, skill, three deny-by-default read-only agents |
497+
| OpenCode | Detected | `$OPENCODE_CONFIG` or resolved global config | `AGENTS.md`, skill, three deny-by-default read-only agents; plugin adds grep/glob graph lookup, post-`read` coverage, first-tool-result session context, and post-compaction reinjection |
492498
| Antigravity | Detected | `.gemini/config/mcp_config.json` | `.gemini/GEMINI.md` |
493499
| Aider | Detected || `CONVENTIONS.md` via `.aider.conf.yml` |
494500
| KiloCode | Detected | `.config/kilo/kilo.jsonc` | Rule + three graph-tool subagents with deny-by-default permissions |

graph-ui/src/App.test.tsx

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
/* @vitest-environment jsdom */
2+
import "@testing-library/jest-dom/vitest";
3+
import { cleanup, render, screen, waitFor } from "@testing-library/react";
4+
import { afterEach, describe, expect, it, vi } from "vitest";
5+
import { App } from "./App";
6+
import { messages } from "./lib/i18n";
7+
8+
vi.mock("./components/GraphTab", () => ({ GraphTab: () => null }));
9+
vi.mock("./components/StatsTab", () => ({ StatsTab: () => null }));
10+
vi.mock("./components/ControlTab", () => ({ ControlTab: () => null }));
11+
vi.mock("./lib/i18n", async (importOriginal) => {
12+
const actual = await importOriginal<typeof import("./lib/i18n")>();
13+
return { ...actual, useUiMessages: () => messages.en };
14+
});
15+
16+
describe("App", () => {
17+
afterEach(() => {
18+
cleanup();
19+
vi.unstubAllGlobals();
20+
window.history.replaceState(null, "", "/");
21+
});
22+
23+
it("shows the serving binary version", async () => {
24+
vi.stubGlobal("fetch", vi.fn(async () =>
25+
new Response(JSON.stringify({ lang: "en", version: "0.10.8" }), {
26+
status: 200,
27+
headers: { "Content-Type": "application/json" },
28+
}),
29+
));
30+
31+
render(<App />);
32+
33+
expect(await screen.findByText("v0.10.8")).toBeVisible();
34+
});
35+
36+
it("hides the version when the config has no string version", async () => {
37+
const fetchMock = vi.fn(async () =>
38+
new Response(JSON.stringify({ lang: "en", version: 108 }), { status: 200 }),
39+
);
40+
vi.stubGlobal("fetch", fetchMock);
41+
42+
render(<App />);
43+
44+
await waitFor(() => expect(fetchMock).toHaveBeenCalledWith("/api/ui-config"));
45+
expect(screen.queryByTitle("Server version")).not.toBeInTheDocument();
46+
});
47+
48+
it("hides the version when the config request fails", async () => {
49+
const fetchMock = vi.fn(async () => {
50+
throw new Error("offline");
51+
});
52+
vi.stubGlobal("fetch", fetchMock);
53+
54+
render(<App />);
55+
56+
await waitFor(() => expect(fetchMock).toHaveBeenCalledWith("/api/ui-config"));
57+
expect(screen.queryByTitle("Server version")).not.toBeInTheDocument();
58+
});
59+
});

graph-ui/src/App.tsx

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,24 @@ function routeUrl(tab: TabId, project: string | null): string {
3333
export function App() {
3434
const t = useUiMessages();
3535
const [route, setRoute] = useState<RouteState>(readRoute);
36+
const [version, setVersion] = useState<string | null>(null);
3637
const { tab: activeTab, project: selectedProject } = route;
3738

39+
useEffect(() => {
40+
let cancelled = false;
41+
void fetch("/api/ui-config")
42+
.then((response) => (response.ok ? response.json() : null))
43+
.then((config) => {
44+
if (!cancelled && typeof config?.version === "string" && config.version) {
45+
setVersion(config.version);
46+
}
47+
})
48+
.catch(() => {});
49+
return () => {
50+
cancelled = true;
51+
};
52+
}, []);
53+
3854
/* Normalize the URL on first load so it always carries the current route. */
3955
useEffect(() => {
4056
const initial = readRoute();
@@ -73,6 +89,14 @@ export function App() {
7389
<span className="text-[13px] font-semibold text-foreground/90 tracking-tight">
7490
Codebase Memory
7591
</span>
92+
{version && (
93+
<span
94+
className="translate-y-px text-[10px] font-mono text-foreground/30"
95+
title="Server version"
96+
>
97+
{version.startsWith("v") ? version : `v${version}`}
98+
</span>
99+
)}
76100
</div>
77101

78102
{/* Tabs inline in header */}

0 commit comments

Comments
 (0)