106 Commits

Author SHA1 Message Date
dependabot[bot] 906c4c5610 ci(deps): bump github/codeql-action/upload-sarif
Bumps the actions-minor-patch group with 1 update: [github/codeql-action/upload-sarif](https://github.com/github/codeql-action).


Updates `github/codeql-action/upload-sarif` from 4.37.7 to 4.37.8
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/codeql-action/compare/ff2f1c621b7f889edc0d3c761ac2e6a3f8cdb0dd...db488ddef3bf6cb639b32c2e9a7c0a7ea8271d28)

---
updated-dependencies:
- dependency-name: github/codeql-action/upload-sarif
  dependency-version: 4.37.8
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions-minor-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-08-24 05:15:10 +00:00
Tien Dung Dao 49b7e5ecd0 fix(analysis,mcp): convert repo-relative paths with no prefix, and hand CODEOWNERS the repo-relative spelling
Fourth review round on #646.

1. GraphKey returned early on an empty repo prefix, before filepath.FromSlash.

A standalone index carries no prefix but its keys still use native
separators, so a '/'-spelled forge or git path missed them on Windows and
get_pr_impact / suggest_reviewers(number=...) silently lost changed symbols
and reviewer signals. Only GraphKeyedPath returns unchanged now;
RepoRelativePath always converts, then takes the prefix when one applies.

2. CODEOWNERS received a graph key in ids mode.

relForRepo only strips an absolute repo root, so repo-a/pkg/auth/login.go
reached MatchFile with the prefix still on and a root-anchored rule such as
/pkg/auth/ matched nothing. matched_files reported the same spelling back to
the caller. Both now go through the new analysis.RepoRelPath, GraphKey's
inverse: it strips the prefix only for a GraphKeyedPath, because that is the
one domain that carries it by construction.

3. Tests.

- Empty-prefix multi-segment cases for GraphKey and JoinFileNodes. The
  previous a.go fixture has no separator, so it cannot fail either way.
- The ids CODEOWNERS fixture is now root-anchored (/pkg/auth/). The
  unanchored rule also matched the graph-keyed spelling and masked the bug.
- TestJoinHunksToSymbolsPrefixedDeleteAndRename covers the two hunk-less
  change kinds against a prefix-shadowed graph: the delete's Path and the
  rename's PreviousPath must resolve the nested old-side key and never the
  same-named shadow. Their existing tests use an empty prefix and so did not
  bind this contract.
- The Windows selector gains PrefixedDeleteAndRename.

Each fix is sabotage-verified separately: forcing the ids branch back to a
raw graph key leaves only the CODEOWNERS-less reviewers, passing the graph
key to MatchFile drops the codeowner signal entirely, and declaring the
vanished path GraphKeyedPath makes the delete/rename test miss both old-side
symbols.

Four fixtures needed the same correction as TestChangedSymbolsForFiles did
earlier: prToolsTestServer, conflictsTestServer and conflictsBudgetServer
hard-coded '/'-spelled graph keys while supplying the same strings as forge
paths, which describes an index a Windows daemon never writes. They now store
native and supply the forge spelling, which is the shape under test.

Windows: internal/mcp 27 -> 24 against main, failing test names diffed,
newly-broken set empty. internal/analysis passes clean. internal/review keeps
its four pre-existing failures. Lint: 6 staticcheck findings, pre-existing.
2026-08-24 00:24:12 +07:00
Tien Dung Dao a1a5b87fb2 fix(review): carry the ids path domain and normalize file risk before stripping
Third review round on #646.

1. suggest_reviewers(ids=...) double-prefixed graph-keyed paths.

resolveReviewerChangeset's three sources do not share a vocabulary: ids
returns graph node FilePaths, base (git) and number (forge) return
repo-relative paths. Forcing analysis.RepoRelativePath on all three
looked up repo-a/pkg/auth/login.go as repo-a/repo-a/pkg/auth/login.go, so
the ownership and co-change signals disappeared while CODEOWNERS - which
matches the repo-relative spelling - still answered and the tool looked
healthy.

The resolver now returns the domain with the files and the two lookups
use it. That also gives GraphKeyedPath its first production caller.

My round-two audit missed this: I read the call site's comment, which
says the paths are repo-relative, without walking all three producers
feeding it. The comment was true for two of them.

2. File risk stripped the prefix after filepath.Clean.

fromGraphKey called cleanPath first, and cleanPath ends in filepath.Clean,
so on Windows repo-a/repo-a\widget.go became repo-a\repo-a\widget.go and
the '/'-joined prefix no longer matched. Changed-symbol impact stayed on a
graph-prefixed row while findings and ChangedFiles produced a second
repo-relative row for the same file. Both domains now normalize through
graphpath.Norm before the strip and leave in the documented repo-relative
'/' spelling.

This also fixes three pre-existing Windows failures in internal/review:
TestRankFileRiskUsesImpact, TestRankFileRiskNormalizesRepoPrefix and
TestRankFileRiskExemptsTestFilesFromCoverageDebt. The package goes from
seven failures to four; the remaining four are untouched by this change.

3. Windows coverage.

The selector gains GraphKey, JoinFileNodes, ChangedSymbolsForFiles, both
prefix-shadow end-to-end tests, the new ids test and RankFileRisk, and
./internal/review joins the package list.

Tests. The new prefixed-graph ids test asserts all three reviewer signals
survive; the existing ids tests use an unprefixed graph where both domains
coincide, which is why they could not see the regression. Both
prefix-shadow end-to-end tests now require exactly one FileRisk row equal
to the changed file - the previous NotEqual(shadow) assertion passed even
when both erroneous rows were present.

Each fix is sabotage-verified separately: restoring the ids branch to
RepoRelativePath leaves only the CODEOWNERS reviewer, and restoring
cleanPath-before-strip produces exactly the two rows described above.

Also audited, and clean: every other JoinFileNodes / GraphKey caller.
changedSymbolsForFiles is fed only by forge PR file lists through
resolvePRFiles and prImpactForNumber, so its repo-relative domain is
correct. The only two remaining repoPrefix strips both normalize first and
both have an established domain.
2026-08-23 20:54:52 +07:00
Tien Dung Dao f447a10dc1 fix(review): join the changeset to native-separator graph paths
reviewRulepackMatches builds the changed-file key correctly and then
looks it up with filepath.Clean, which rewrites the one separator a graph
path keeps as '/': the repo prefix. Probed on windows/amd64:

    changed map key            "repo-a/pkg\widget.go"
    target.GraphPath           "repo-a/pkg\widget.go"   <- identical
    filepath.Clean(GraphPath)  "repo-a\pkg\widget.go"   <- prefix slash lost
    hit                        false

So `review` narrowed the rulepack to an empty target set and reported
zero findings on code its own detector bundle flags — the same false
clean the join was written to fix, reintroduced by the Clean.

Compare in graphpath.Norm form on both sides instead. Norm is the
canonical comparison spelling for a path that is "<prefix>/" plus a
native remainder, and it is filepath.ToSlash, so this is the identity on
POSIX.

Second half, same contract: reviewRepoRelPath feeds the `.gortex.yaml`
rule globs, rankFileRisk's row keys and the forge comment API, all of
which speak '/'. It returned `pkg\widget.go` on Windows, which matches no
glob and anchors no comment. Normalize there too.

Whole package on windows before/after: 27 -> 24 failures, exactly the
three rulepack tests flip, nothing else changes state. Each half is
separately load-bearing: reverting the join fails all three, reverting
the output normalization fails the two that assert m.File.

graphpath.Norm is deliberately a no-op on POSIX — a backslash is an
ordinary filename byte there — so no test can bind this on the
linux/macos matrix. The three names join the existing windows
native-separator step, whose package list already carries internal/mcp.
2026-08-21 15:42:55 +07:00
Tien Dung Dao d3a2d3b8f0 test: stop three assertions assuming POSIX separators on native paths
TestFeedbackDir, TestParseDiffGitPaths and TestParseDiffLinesNewSide all
compare against a '/'-spelled path while the value under test is a native
filesystem path. On POSIX the two coincide, so the linux/macos matrix has
never seen it; on windows/amd64 all three fail:

    "\home\user\.cache\gortex\5887dcec1741_latest"
      does not contain ".cache/gortex"
    parseDiffGitPaths("diff --git a/pkg/foo.go b/pkg/foo.go")
      = "pkg\foo.go", want "pkg/foo.go"
    diffmap_test.go:63: expected new-side lines for pkg/foo.go

The production values are correct in each case and are left alone:

  - FeedbackDir is filepath.Join(cacheDir, key) and feeds os.Open, so it
    must carry native separators.
  - cleanDiffPath is filepath.Clean, and JoinFileNodes looks a diff path
    up as repoPrefix + "/" + path. Indexed paths are repoPrefix + '/' +
    the rest in native separators (see internal/graphpath), so the
    cleaned native form is exactly what the join needs. Making diff paths
    slash-canonical would break that lookup on Windows.

So the fix is on the assertion side: build the expectation with
filepath.Join / filepath.Clean instead of a literal. On POSIX both are
identity for these inputs, so the assertions keep exactly the strength
they had on the matrix that already runs them.

Fold the three into the existing native-separator windows step rather
than adding one: internal/analysis, internal/mcp, internal/resolver and
internal/graph/store_sqlite are already in that step's package list, and
internal/persistence is already compiled by the sidecar step above it.
2026-08-21 07:17:48 +07:00
Andrew Kumanyaev b8b13ca70d Merge pull request #641 from tiendungdev/fix/plan-lock-fixture-close-store 2026-08-21 00:17:59 +02:00
Andrey Kumanyaev ee1b77a142 release: stop running go mod tidy at release time, assert tidiness in CI
goreleaser ran `go mod tidy` as a before-hook inside the release container.
It took v0.63.8 down: the hook spent 4m49s walking the module graph and then
failed when proxy.golang.org returned HTTP/2 INTERNAL_ERROR on six unrelated
fetches. `go mod tidy` resolves the test dependencies of dependencies too, so
it touches far more of the network than a build needs, on the one path where
a flake costs a release.

The hook was also unsound in a quieter way. It MUTATES go.mod/go.sum, so a
drifted module set would have been silently rewritten inside the container
and the published binaries built against something no CI job had ever
compiled. A release-time rewrite is not a check.

Drop it — the config already skips tests here on the reasoning that the tag
is on a green commit, and the same argument applies.

Nothing verified module tidiness before this: no workflow, no Makefile
target. So the `lint` job gains a `go mod tidy` + `git diff --exit-code`
step, which fails the PR that introduces drift instead of papering over it
at tag time. main is already tidy, so the gate is green on landing.

Verified with the real toolchain, not by reading it:

  * `goreleaser build --snapshot` with a deliberately failing before-hook
    aborts at "running before hooks" in 0s, so hooks do execute in that mode;
    with `hooks: []` the stage never appears and the run goes straight from
    snapshotting to building. No default hook takes its place.
  * `goreleaser check` validates the config.
  * The CI gate passes on main unchanged, and fails with exit 1 (naming
    go.mod) against a commit carrying a deliberately untidy require line.
2026-08-20 21:56:42 +02:00
Tien Dung Dao 79777259ac test(store_sqlite): close the plan-lock fixture store so TempDir cleanup works on Windows
newPlanLockFixture opens an on-disk Store and never closes it. Windows
refuses to unlink an open file, so plan_lock.sqlite survives the test and
the enclosing t.TempDir() cleanup fails.

Measured on windows/amd64, go1.26.6, whole package before the change:

    --- FAIL: TestSweepPlanLocks
    --- FAIL: TestAdjacencyPlanLocksDuringBulkLoad
    --- FAIL: TestSweepPlanLockReceiverRebindBatch
    --- FAIL: TestPreparedStatementPlansNeverScanBigTables
    --- FAIL: TestSweepWarnPlanLocks
        testing.go:1464: TempDir RemoveAll cleanup: unlinkat
        ...\plan_lock.sqlite: The process cannot access the file because
        it is being used by another process.

Five failures, one cause, zero failing assertions — the fixture is the
only holder. After the change the package is ok, 147s, no failures.

Register the close with t.Cleanup after t.TempDir() so LIFO ordering
closes the database before the directory is removed. This is already the
convention at 160 of the 165 Open() sites in the package's tests.

Guard it on the windows runner. Every assertion in these tests is
platform-neutral: on linux/macos an unlinked-but-open file is removed
normally, so the whole set passes with or without the Close and the
matrix cannot protect the fixture from losing it again. Same reasoning,
and the same shape, as the sidecar-handle step added in #415.
2026-08-21 02:45:54 +07:00
Andrey Kumanyaev 9449485dcf release: fix the homebrew cask so it loads at all
The generated cask used `pre_install` / `post_install`. Those are formula
DSL methods; a cask has no such stanzas, so brew rejected the file at load
time with

  Error: Cask 'gortex' definition is invalid: undefined method 'pre_install'

Every brew command that touches the cask parses it, so `brew install` and
`brew upgrade` both failed for every macOS user on both arches, starting
with v0.63.7. Closes #639.

Two further defects made a straight rename insufficient:

  * The cask DSL's `system_command` is `SystemCommand.run!`, which raises on
    a non-zero exit. `gortex daemon status` exits 1 exactly when no daemon
    is reachable, so `next unless status.success?` could never run — brew
    would have aborted the install outright on any machine without a live
    daemon. The probe now passes `must_succeed: false`.

  * `preflight` was the wrong hook for stopping the daemon. On upgrade brew
    unlinks the old cask's binary (`start_upgrade` -> `uninstall_artifacts`)
    before installing the new cask's artifacts, so by the time a preflight
    block runs there is no gortex on disk to ask. The stop half could never
    fire on the path it was written for.

`postflight` handles both halves instead: after the new binary is linked,
probe for a daemon and, only if one answers, `daemon restart` — which stops
the old process (blocking until it exits, releasing the store lock) before
starting the new one, so a store migration still runs alone. A fresh install
and CI have no daemon answering and skip it.

The cask body moves out of the release.yml heredoc into
.github/homebrew/gortex.rb.tmpl, rendered by scripts/render-cask.sh. That
makes it reviewable as Ruby, removes the shell-expansion hazards of an
unquoted heredoc, and — the point — lets a real brew load it before
publication. The renderer also refuses a malformed sha256, a version with a
leading "v", or a placeholder that survived substitution. Rendered output is
byte-identical to the published cask apart from the hook block.

Nothing could have caught this: the file was valid Ruby, valid YAML, and the
tap has no CI, so the first machine to evaluate the cask was a user's.
scripts/validate-cask.sh renders the template with dummy values and loads it
through a real brew. It runs on every PR that touches the cask
(.github/workflows/homebrew-cask.yml) and again in build-darwin as the last
gate before the release job pushes to the tap. Both are macOS-only —
Homebrew on Linux cannot load casks. Verified by reintroducing `pre_install`
in the template: the validator fails with the exact error users reported.
2026-08-20 21:16:46 +02:00
Andrew Kumanyaev d9c08610cf Merge pull request #632 from zzet/fix/verify-signatures-repo-context
fix(release): give the signature gate an explicit repo to query
2026-08-20 09:16:49 +02:00
Andrew Kumanyaev 870552893d Merge pull request #612 from madeinoz67/feat/cask-daemon-restart-hooks 2026-08-20 08:08:26 +02:00
Andrey Kumanyaev aed0c1dda7 fix(release): give the signature gate an explicit repo to query
verify-signatures skips actions/checkout on purpose — it verifies
published bytes, not the source tree — so the job has no git remote for
gh to infer the repository from. `gh release download` aborted with
"failed to run git: fatal: not a git repository" before downloading
anything, and the gate failed the v0.63.6 release despite that release
being sound.

Pass --repo "$GITHUB_REPOSITORY" so the lookup does not depend on a
checkout.

The gate was originally rehearsed against a stubbed gh, which could not
surface a repository-resolution failure. It is now exercised end to end
against the published v0.63.6 release with the real gh and cosign: all
12 signatures verify, and re-appending a line to the signed
checksums.txt makes the gate name checksums.txt.sig and exit 1.
2026-08-20 08:04:40 +02:00
Andrey Kumanyaev 6191952cdb ci(release): verify every published signature against its artifact
checksums.txt is assembled across three jobs — goreleaser, then darwin,
then windows — and signed along the way. Nothing checked that the
signature a release ships still matches the bytes it ships, so a step
that rewrote a file after signing it went unnoticed for 28 releases.

Add a gate that runs after every job which can touch a release asset,
re-downloads the release, and verifies each published .sig against the
published artifact with the same cosign command consumers are told to
use. It also asserts that every primary artifact is both signed and
listed in checksums.txt, the two verification paths consumers rely on.

Rekor lookups are a network call against a shared service, so a
verification failure is retried twice before the release is failed; a
genuine mismatch fails deterministically and still stops the release.
2026-08-19 23:35:56 +02:00
Andrey Kumanyaev cc86fda3ec fix(release): re-sign checksums.txt after appending the windows entry
The release job signs checksums.txt once it has folded in the darwin
tarballs. release-windows then downloads that signed file, appends the
windows zip's sha256, and re-uploads it with --clobber — but never
re-signs. The published checksums.txt.sig therefore covers the file as
it was before the windows line existed, and verification fails on a
release whose artifacts are all authentic.

Every release from v0.35.3 to v0.63.5 shipped this way. Stripping the
trailing windows line from a published checksums.txt makes its
published signature verify, which pins the cause exactly.

Per-artifact signatures were always correct, and install.sh verifies
the asset's own .sig/.pem rather than the checksums file, so installs
were unaffected — but the conventional "verify checksums.txt, then
check everything against it" supply-chain gate fails closed.

Make the last writer of checksums.txt also its signer: append, sort,
re-sign, and clobber the file plus its .sig and .pem together. Keyless
signing here produces the same certificate identity as the release job
(same workflow ref, same tag), so the documented verification command
is unchanged.

Also stop the append from failing open. `gh release download ... ||
: > checksums.txt` turned a transient download failure into an empty
file, which the subsequent --clobber would publish as a windows-only
checksums.txt, breaking sha256 verification for every other platform.
needs:release guarantees the file exists, so treat a failed download
as fatal.
2026-08-19 23:35:37 +02:00
Stephen Eaton 908a57675d ci(release): stop and restart the daemon around cask upgrades
The generated cask gains guarded pre_install/post_install hooks: pre stops
a running daemon (only when one answers; recorded via a tmp marker) so the
binary swap and any store migration happen without a stale daemon holding
the old image and the store lock; post restarts onto the new binary only
when one was running. Fresh installs and CI never launch a daemon.

Fixes the brew-upgrade leg of #609 alongside PR #611's detection layers.
2026-08-19 10:28:02 +10:00
Andrey Kumanyaev a51b9194e3 ci: raise the race-suite timeout to thirty minutes
The store_sqlite package under race and coverage sits just under the old
twenty-minute wall on Linux runners, and the localization projection tests
this branch adds push it past. Thirty minutes matches how long the suite
actually needs; the per-test alarms still catch a genuine hang early.
2026-08-17 22:00:17 +02:00
dependabot[bot] 9dd5c0c78b ci(deps): bump github/codeql-action/upload-sarif
Bumps the actions-minor-patch group with 1 update: [github/codeql-action/upload-sarif](https://github.com/github/codeql-action).


Updates `github/codeql-action/upload-sarif` from 4.37.6 to 4.37.7
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/codeql-action/compare/5595ccaf912efad79be6eef63a5619ff05969be3...ff2f1c621b7f889edc0d3c761ac2e6a3f8cdb0dd)

---
updated-dependencies:
- dependency-name: github/codeql-action/upload-sarif
  dependency-version: 4.37.7
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions-minor-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-08-17 05:11:47 +00:00
Andrey Kumanyaev 9cc360c53f ci: cover the Copilot CLI adapter in the init smoke test
Adds the ~/.copilot sentinel and the copilot-cli expectation, and notes
that the list is hand-maintained so the next adapter is covered only
when both places are updated.
2026-08-15 12:54:43 +02:00
Andrey Kumanyaev 1d4c9d981a Normalize the remaining store-path prefix filters and guard them on Windows
Indexed paths are repoPrefix + '/' + the rest in the indexing machine's
native separators, so a stored path on Windows reads `repo/dir\file.cs`.
Slash-only prefix logic applied to that shape sees the whole repo as one
directory: every `analyze path_prefix`, guard rule, doc filter and trigram
scope silently matches nothing below the repo root.

Three such filters were normalized when graphpath landed; the audit that
found them named "the remaining members" but only covered the reference
implementations in graph.go. Thirty-five were left raw. This finishes the
sweep through a single graphpath.HasPrefix helper, which also absorbs the
`prefix != ""` guard every call site repeated.

The helper deliberately keeps raw string-prefix semantics rather than
becoming segment-aware: `internal/mcp` matched `internal/mcpx` before and
still does. Making it segment-aware would quietly change what every
path_prefix argument returns, which is a different change from this one.

Left alone on purpose:
  - `external::` / `external-call::` node sentinels, which are not paths
  - comparisons against `repoPrefix + "/"`, where the separator after the
    repo prefix is '/' by the storage invariant

Both of the earlier Windows fixes shipped with tests that cannot fail on
the runners that execute them: on POSIX a backslash is an ordinary filename
byte, so filepath.Clean and ToSlash leave the fixtures untouched and the
assertions pass with or without the production code. The build-windows job
already exists for exactly this class of platform-divergent semantics, so
the separator tests now run there — the only place they can go red.

Also simplifies the import-adjacency canonicality guard: `cleaned != path`
was redundant ahead of the normalized comparison, since equal normalized
forms already imply the two spellings differ only in separators.
2026-08-11 19:22:04 +02:00
dependabot[bot] fcd23ffade ci(deps): bump github/codeql-action/upload-sarif
Bumps the actions-minor-patch group with 1 update: [github/codeql-action/upload-sarif](https://github.com/github/codeql-action).


Updates `github/codeql-action/upload-sarif` from 4.37.4 to 4.37.6
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/codeql-action/compare/f205ea1c3313d32999d8d6a48b4f6530d4437b38...5595ccaf912efad79be6eef63a5619ff05969be3)

---
updated-dependencies:
- dependency-name: github/codeql-action/upload-sarif
  dependency-version: 4.37.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions-minor-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-08-10 05:14:55 +00:00
Andrey Kumanyaev 38cbf85df0 Verify the user-state sandbox on the platform it exists for
A HOME-only override is a no-op only on Windows, so the helper that
fixes it and the resolver it protects are unverifiable on the linux and
macos matrix. Run both packages on the Windows job.

This is also the first time ./internal/platform runs there at all,
despite the package already shipping a Windows-only test file.
2026-08-08 17:31:19 +02:00
Andrey Kumanyaev b7336a9ad9 Verify symlink confinement on Windows in CI
The guard's behaviour is more platform-dependent than most of this
codebase, and Windows was the platform not exercising it. Go maps a
symlink reparse point to ModeSymlink, which the guard keys on, but a
directory junction maps to ModeIrregular instead — the walk still refuses
to descend one, because Go treats both as name surrogates and withholds
ModeDir, so that difference is safe rather than a hole. Path case is the
other divergence: evalSymlinks normalises it on Windows, which is what
lets the containment test compare a resolved target against a resolved
root without a case-folding step of its own.

None of that was covered by an executing test. The Windows job deliberately
skips the full suite, so this adds only the guard's own package — pure Go,
no cgo, a fraction of a second — alongside the agent and sidecar tests
already there for the same reason.

Symlink creation on Windows needs SeCreateSymbolicLinkPrivilege, so the
tests skip rather than fail when the host will not grant it; on every other
platform a failure to create one stays a hard error.
2026-08-05 01:36:20 +02:00
dependabot[bot] a679da2dba ci(deps): bump github/codeql-action/upload-sarif
Bumps the actions-minor-patch group with 1 update: [github/codeql-action/upload-sarif](https://github.com/github/codeql-action).


Updates `github/codeql-action/upload-sarif` from 4.37.3 to 4.37.4
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/codeql-action/compare/e4fba868fa4b1b91e1fdab776edc8cfbe6e9fb81...f205ea1c3313d32999d8d6a48b4f6530d4437b38)

---
updated-dependencies:
- dependency-name: github/codeql-action/upload-sarif
  dependency-version: 4.37.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions-minor-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-08-03 05:11:34 +00:00
Tien Dung Dao 5ca38c4d00 test(persistence): cover CloseSidecar and run it on the Windows job
Review catch: nothing in CI exercised any of this. On linux/macos the modified
tests pass whether or not the handle is released, because POSIX unlinks an open
file; the Windows job only built and ran internal/agents. So the fix was
unverified exactly where it matters.

TestCloseSidecar_ReleasesTheHandleAndStaysHarmless covers the four cases:

  - closing a path that was never opened creates neither the database nor its
    parent directory (the reason this is not OpenSidecar(path).Close())
  - open -> CloseSidecar -> reopen returns a different, usable store — usable
    meaning it serves a query, not merely that it is non-nil
  - closing repeatedly is harmless
  - the containing directory can then be removed

The reopen case is what gives the test teeth everywhere: with CloseSidecar
stubbed to return nil the cache still holds the old store, so the reopen hands
back the same pointer and the assertion fails on any platform. The RemoveAll
case is the one that only bites on Windows, and it now runs there.

Wired into build-windows next to the existing agents step, with the asymmetry
spelled out in the comment so the reason the test lives there is not lost.

Also hardened CloseSidecar per the non-blocking note: the entry is dropped
under the same lock that found it, so a concurrent OpenSidecar misses the cache
and opens a fresh handle rather than receiving one that is about to close.
Close still runs outside the lock, since it takes sidecarMu itself to clear any
other keys pointing at the same store.

Verified by sabotage: stubbing CloseSidecar to a no-op turns the reopen case
red. golangci-lint v2.11.4 clean, -race clean; internal/persistence reports one
failure, TestFeedbackDir, which fails identically on a clean origin/main (a
path-separator case, same class as #411, untouched here).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-31 17:36:05 +07:00
dependabot[bot] 2007f7a922 ci(deps): bump the actions-minor-patch group with 3 updates
Bumps the actions-minor-patch group with 3 updates: [actions/checkout](https://github.com/actions/checkout), [ossf/scorecard-action](https://github.com/ossf/scorecard-action) and [github/codeql-action/upload-sarif](https://github.com/github/codeql-action).


Updates `actions/checkout` from 7.0.0 to 7.0.1
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0...3d3c42e5aac5ba805825da76410c181273ba90b1)

Updates `ossf/scorecard-action` from 2.4.3 to 2.4.4
- [Release notes](https://github.com/ossf/scorecard-action/releases)
- [Changelog](https://github.com/ossf/scorecard-action/blob/main/RELEASE.md)
- [Commits](https://github.com/ossf/scorecard-action/compare/4eaacf0543bb3f2c246792bd56e8cdeffafb205a...2d1146689b8cda280b9bc96326124645441f03bc)

Updates `github/codeql-action/upload-sarif` from 4.37.1 to 4.37.3
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/codeql-action/compare/7188fc363630916deb702c7fdcf4e481b751f97a...e4fba868fa4b1b91e1fdab776edc8cfbe6e9fb81)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: 7.0.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions-minor-patch
- dependency-name: ossf/scorecard-action
  dependency-version: 2.4.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions-minor-patch
- dependency-name: github/codeql-action/upload-sarif
  dependency-version: 4.37.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions-minor-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-07-27 05:09:56 +00:00
Andrey Kumanyaev db7584f659 ci: catch a linux static-link regression on the PR, not at tag time
The release-time build hook fails a tag that produced a dynamically linked
binary, which is late. Build with the release link flags on every change and
run the same assertion, then execute the result on debian:11 (glibc 2.31,
the userland that reported the GLIBCXX failure) and alpine (no glibc at all)
so a missing netgo/osusergo tag surfaces here rather than for a user.

Also run the languages tests under static_link — that code path is compiled
out of every other job, so its tests would otherwise never execute anywhere.
2026-07-26 17:23:21 +02:00
Andrey Kumanyaev 1f7bf6ea48 release: link linux binaries statically so they run on any distro
The linux release was dynamically linked despite the README promising a
single static binary with no dependency chain. goreleaser-cross:v1.26 is
Ubuntu 24.04 / GCC 13.3, so the artifacts carried that host's floor —
GLIBCXX_3.4.32 and GLIBC_2.34 — and refused to start anywhere older:

  gortex: /lib/x86_64-linux-gnu/libstdc++.so.6:
          version `GLIBCXX_3.4.32' not found (required by gortex)

Debian 12 caps at GLIBCXX_3.4.30 and Ubuntu 22.04 at 3.4.29, so in practice
the binary only ran on Ubuntu 24.04+/Debian 13+. libstdc++ is in the link at
all because some tree-sitter grammars ship C++ external scanners. Windows
already linked -static; only linux was left dynamic.

Link -static with netgo, osusergo and static_link, which between them remove
every dlopen the binary would otherwise perform at runtime.

verify-static-elf.sh asserts no DT_NEEDED, no PT_INTERP and no symbol-version
requirements. It runs as a goreleaser build post-hook rather than a workflow
step because `goreleaser release` builds and publishes in the same run — a
check after it would only ever be a post-mortem on an already-published
artifact. The release job re-asserts it on the packaged tarballs and then
proves it by execution on debian:11 and alpine.
2026-07-26 17:23:21 +02:00
Andrew Kumanyaev 82cc97c74e Merge pull request #307 from zzet/dependabot/github_actions/actions/setup-go-7.0.0
ci(deps): bump actions/setup-go from 6.5.0 to 7.0.0
2026-07-20 07:55:57 +02:00
dependabot[bot] 32f38ef621 ci(deps): bump actions/setup-go from 6.5.0 to 7.0.0
Bumps [actions/setup-go](https://github.com/actions/setup-go) from 6.5.0 to 7.0.0.
- [Release notes](https://github.com/actions/setup-go/releases)
- [Commits](https://github.com/actions/setup-go/compare/924ae3a1cded613372ab5595356fb5720e22ba16...b7ad1dad31e06c5925ef5d2fc7ad053ef454303e)

---
updated-dependencies:
- dependency-name: actions/setup-go
  dependency-version: 7.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-07-20 05:11:08 +00:00
dependabot[bot] d229972bf9 ci(deps): bump the actions-minor-patch group with 2 updates
Bumps the actions-minor-patch group with 2 updates: [softprops/action-gh-release](https://github.com/softprops/action-gh-release) and [github/codeql-action/upload-sarif](https://github.com/github/codeql-action).


Updates `softprops/action-gh-release` from 3.0.1 to 3.0.2
- [Release notes](https://github.com/softprops/action-gh-release/releases)
- [Changelog](https://github.com/softprops/action-gh-release/blob/master/CHANGELOG.md)
- [Commits](https://github.com/softprops/action-gh-release/compare/718ea10b132b3b2eba29c1007bb80653f286566b...3d0d9888cb7fd7b750713d6e236d1fcb99157228)

Updates `github/codeql-action/upload-sarif` from 4.37.0 to 4.37.1
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/codeql-action/compare/99df26d4f13ea111d4ec1a7dddef6063f76b97e9...7188fc363630916deb702c7fdcf4e481b751f97a)

---
updated-dependencies:
- dependency-name: softprops/action-gh-release
  dependency-version: 3.0.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions-minor-patch
- dependency-name: github/codeql-action/upload-sarif
  dependency-version: 4.37.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions-minor-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-07-20 05:11:01 +00:00
Tien Dung Dao 31d2bdefd2 test(ci): run agent integrations on Windows 2026-07-19 19:59:08 +07:00
dependabot[bot] 198bde8198 ci(deps): bump the actions-minor-patch group with 2 updates
Bumps the actions-minor-patch group with 2 updates: [github/codeql-action/upload-sarif](https://github.com/github/codeql-action) and [golang/govulncheck-action](https://github.com/golang/govulncheck-action).


Updates `github/codeql-action/upload-sarif` from 4.36.3 to 4.37.0
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/codeql-action/compare/54f647b7e1bb85c95cddabcd46b0c578ec92bc1a...99df26d4f13ea111d4ec1a7dddef6063f76b97e9)

Updates `golang/govulncheck-action` from 1.0.4 to 1.1.0
- [Release notes](https://github.com/golang/govulncheck-action/releases)
- [Commits](https://github.com/golang/govulncheck-action/compare/b625fbe08f3bccbe446d94fbf87fcc875a4f50ee...032d45514ae346b1db93c04b0c90b841c370344f)

---
updated-dependencies:
- dependency-name: github/codeql-action/upload-sarif
  dependency-version: 4.37.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: actions-minor-patch
- dependency-name: golang/govulncheck-action
  dependency-version: 1.1.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: actions-minor-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-07-13 05:10:37 +00:00
dependabot[bot] 6c5c5a3894 ci(deps): bump the actions-minor-patch group with 2 updates
Bumps the actions-minor-patch group with 2 updates: [golangci/golangci-lint-action](https://github.com/golangci/golangci-lint-action) and [github/codeql-action/upload-sarif](https://github.com/github/codeql-action).


Updates `golangci/golangci-lint-action` from 9.2.1 to 9.3.0
- [Release notes](https://github.com/golangci/golangci-lint-action/releases)
- [Commits](https://github.com/golangci/golangci-lint-action/compare/82606bf257cbaff209d206a39f5134f0cfbfd2ee...ba0d7d2ec06a0ea1cb5fa41b2e4a3ab91d21278a)

Updates `github/codeql-action/upload-sarif` from 4.36.2 to 4.36.3
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/codeql-action/compare/8aad20d150bbac5944a9f9d289da16a4b0d87c1e...54f647b7e1bb85c95cddabcd46b0c578ec92bc1a)

---
updated-dependencies:
- dependency-name: golangci/golangci-lint-action
  dependency-version: 9.3.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: actions-minor-patch
- dependency-name: github/codeql-action/upload-sarif
  dependency-version: 4.36.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions-minor-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-07-06 05:10:12 +00:00
Andrey Kumanyaev 72e49f1e89 fix(ci): pass an explicit go test timeout to the test and benchmark jobs
Both steps relied on go test's silent 10-minute default, which internal/mcp
was starting to exceed on ubuntu-latest, failing CI runs with no actionable
error beyond a goroutine dump.
2026-07-04 22:23:15 +02:00
Andrey Kumanyaev f375944141 build(gomlx): provide libtokenizers for the XLA build's rust tokenizer
The embeddings_gomlx XLA build failed to link on a clean Linux runner with
'cannot find -ltokenizers': hugot's XLA session uses the rust tokenizer, which
is statically linked as libtokenizers.a — a native dependency the earlier
change did not account for (it happened to be present on the dev machine). The
pure-Go default and gortex's own ONNX path do not need it.

Install the matching daulet/tokenizers v1.27.0 archive in the CI gomlx step
(mirroring the onnxruntime install), teach 'make build-gomlx' to fetch it
cross-platform, and document the requirement so a user building the XLA backend
knows to provide libtokenizers.a.
2026-07-04 00:09:09 +02:00
Andrey Kumanyaev eda033d1cd build(gomlx): compile the real XLA session with the embeddings_gomlx XLA tag pair
The gomlx build entry points passed only -tags embeddings_gomlx, but hugot gates
its real XLA session behind its own XLA build tag — so every gomlx build linked
the disabled stub, the GoMLX provider always errored at runtime, and the local
chain silently fell through to the pure-Go backend. The GoMLX backend was dead
code in every shipped binary.

Move the Makefile target and the docs build command to -tags "embeddings_gomlx
XLA" so the XLA session is actually compiled (verified to build with no system
XLA libraries — PJRT is a runtime download). CI now compiles both the tag pair
and embeddings_gomlx alone (a regression guard for scripts that still pass it by
itself). The docs are honest that XLA runtime viability is platform-dependent
and experimental, with the pure-Go backend as the reliable default.
2026-07-03 23:17:40 +02:00
dependabot[bot] 07f1f78b76 ci(deps): bump actions/checkout from 6.0.3 to 7.0.0
Bumps [actions/checkout](https://github.com/actions/checkout) from 6.0.3 to 7.0.0.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/df4cb1c069e1874edd31b4311f1884172cec0e10...9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: 7.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-06-29 05:38:25 +00:00
dependabot[bot] 323b5c0ca8 ci(deps): bump the actions-minor-patch group with 2 updates
Bumps the actions-minor-patch group with 2 updates: [actions/setup-go](https://github.com/actions/setup-go) and [softprops/action-gh-release](https://github.com/softprops/action-gh-release).


Updates `actions/setup-go` from 6.4.0 to 6.5.0
- [Release notes](https://github.com/actions/setup-go/releases)
- [Commits](https://github.com/actions/setup-go/compare/4a3601121dd01d1626a1e23e37211e3254c1c06c...924ae3a1cded613372ab5595356fb5720e22ba16)

Updates `softprops/action-gh-release` from 3.0.0 to 3.0.1
- [Release notes](https://github.com/softprops/action-gh-release/releases)
- [Changelog](https://github.com/softprops/action-gh-release/blob/master/CHANGELOG.md)
- [Commits](https://github.com/softprops/action-gh-release/compare/b4309332981a82ec1c5618f44dd2e27cc8bfbfda...718ea10b132b3b2eba29c1007bb80653f286566b)

---
updated-dependencies:
- dependency-name: actions/setup-go
  dependency-version: 6.5.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: actions-minor-patch
- dependency-name: softprops/action-gh-release
  dependency-version: 3.0.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions-minor-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-06-29 05:10:06 +00:00
Andrey Kumanyaev d6880f4915 fix(release): build macOS binaries on a native runner so they load on macOS 15+
The 0.52.2 cask aborted at load on macOS Sequoia/Tahoe with
"__DATA_CONST segment missing SG_READ_ONLY flag" (#176). darwin was
cross-compiled inside goreleaser-cross, whose osxcross ld64 omits the
SG_READ_ONLY flag on the __DATA_CONST segment that the macOS 15+ dyld now
enforces. Apple's ld sets it, so locally built binaries always worked and
the bug only surfaced in the released artifact.

Build darwin on a native macos-15 runner instead:
- new build-darwin job links arm64 natively + amd64 via `clang -arch
  x86_64`, codesigns with rcodesign, smoke-tests the segment flag, and
  runs `gortex version` on the enforcing dyld before handing off archives.
- the release job now builds linux only, merges the darwin tarballs,
  notarizes, appends them to checksums.txt, signs, and uploads.

goreleaser's prebuilt builder is Pro-only, so the homebrew cask (which
references all four os/arch tarballs) is assembled and pushed to the tap
from the release job once every platform's hash exists, instead of by
goreleaser. Completions are still generated at brew-install time.

scripts/verify-macho-readonly.sh is the guard: it fails the release if a
darwin binary ships without SG_READ_ONLY, so this can never regress.
2026-06-27 10:25:19 +02:00
mune 5a896957d4 feat(agents): add Oh My Pi adapter
Register Oh My Pi as a new agent adapter writing config to `.omp/mcp.json`.
Includes detection in the init wizard, smoke test coverage, docs update,
and GCX default-format recognition for the `omp-coding-agent` client ID.
2026-06-20 17:29:07 +02:00
Andrey Kumanyaev 9233619627 fix ci timeout 2026-06-11 01:03:08 +02:00
Andrey Kumanyaev 697641525e cmd: gortex prs bundle + GitHub Action template 2026-06-11 00:27:32 +02:00
Andrew Kumanyaev c82f2b445b Merge pull request #62 from zzet/dependabot/github_actions/codecov/codecov-action-7.0.0
ci(deps): bump codecov/codecov-action from 6.0.1 to 7.0.0
2026-06-08 22:43:51 +02:00
dependabot[bot] 5a9188979b ci(deps): bump codecov/codecov-action from 6.0.1 to 7.0.0
Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from 6.0.1 to 7.0.0.
- [Release notes](https://github.com/codecov/codecov-action/releases)
- [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/codecov/codecov-action/compare/e79a6962e0d4c0c17b229090214935d2e33f8354...fb8b3582c8e4def4969c97caa2f19720cb33a72f)

---
updated-dependencies:
- dependency-name: codecov/codecov-action
  dependency-version: 7.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-06-08 05:09:56 +00:00
dependabot[bot] 718a1d1777 ci(deps): bump the actions-minor-patch group with 2 updates
Bumps the actions-minor-patch group with 2 updates: [actions/checkout](https://github.com/actions/checkout) and [github/codeql-action](https://github.com/github/codeql-action).


Updates `actions/checkout` from 6.0.2 to 6.0.3
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/de0fac2e4500dabe0009e67214ff5f5447ce83dd...df4cb1c069e1874edd31b4311f1884172cec0e10)

Updates `github/codeql-action` from 4.36.0 to 4.36.2
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/codeql-action/compare/7211b7c8077ea37d8641b6271f6a365a22a5fbfa...8aad20d150bbac5944a9f9d289da16a4b0d87c1e)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: 6.0.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions-minor-patch
- dependency-name: github/codeql-action
  dependency-version: 4.36.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions-minor-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-06-08 05:09:52 +00:00
Andrey Kumanyaev 42fbeee639 fix(ci): make skill-drift gate CGO-free and drop the vacuous claude-plugin check
claude-plugin/ is not tracked in this repo (the bundle is published to a
separate repo on release), so a local 'make claude-plugin-check' git-diff
is a no-op — and 'make' builds with -tags llama, which would break a
stock CI runner. Drop that step; the all-platform render golden test and
the structural --check (both pure-Go, no llama) are the real PR fence.
2026-06-06 12:27:00 +02:00
Andrey Kumanyaev 260b1aa061 feat(agents): all-platform skill-render drift fence
Extend drift detection from the Claude bundle to every agent adapter.
A new render engine applies each adapter in an isolated sandbox (with
ForceDetect so it renders regardless of which tools are installed) and
serialises its generated MCP config, instructions, hooks, and routing
blocks into a normalized, machine-independent manifest.

  - go test ./cmd/gortex -run TestAgentsRenderGolden byte-compares all
    16 adapters against committed goldens (regenerate with
    -update-agent-render); a stale or missing golden fails the test.
  - gortex agents render --check is a structural CI gate (every adapter
    still emits a gortex registration); --target dumps the manifests.
  - A skill-drift GitHub Actions workflow runs both on every PR and
    lifts the Claude-bundle fence (make claude-plugin-check) out of its
    release-only trigger.

ForceDetect is a new ApplyOpts field honoured by all adapters; it is
never set during a normal gortex init.
2026-06-06 12:09:51 +02:00
Andrew Kumanyaev 9909379fdb Merge pull request #44 from zzet/feat/retrieval-ranking-quality
Retrieval & ranking quality: smarter context, provenance-aware centrality, richer search
2026-06-03 22:30:05 +02:00
Andrey Kumanyaev fd1c8d1da2 ci: resolve Go toolchain from go.mod across workflows
Replace the floating go-version 1.26 pins in the ci, release, and security workflows with go-version-file: go.mod, so every job builds and scans with the exact patched toolchain go.mod declares (1.26.4) instead of whatever patch the setup-go manifest happens to serve.

Makes go.mod the single source of truth and keeps govulncheck from flagging stdlib advisories already fixed in a patch the floating manifest lagged behind. Matches the go-version-file pattern already used in bench-arm, init-smoke, and publish-claude-plugin.
2026-06-03 21:51:36 +02:00
Andrew Kumanyaev fc29b60836 Merge pull request #34 from zzet/dependabot/github_actions/actions-minor-patch-cadd9cfeda
ci(deps): bump the actions-minor-patch group with 3 updates
2026-06-02 20:38:20 +02:00