Commit Graph

50 Commits

Author SHA1 Message Date
matt wilkie 935afe2466 fix(examples): tidy both example modules and build them in CI (#5229)
* fix(examples): tidy both example modules and build them in CI

Both Go modules under examples/ fail a plain `go build` on current main:

    go: updates to go.mod needed; to update it:
            go mod tidy

They are separate modules that reach the parent through
`replace github.com/steveyegge/beads => ../..`, so their go.mod and go.sum
record the parent's entire dependency graph. Every root dependency change
therefore invalidates them — and nothing in CI ever compiled them, so the drift
accumulated silently. examples/ is the first code a new user copies, which makes
this a bad first five minutes rather than a cosmetic wart.

Two parts:

1. `go mod tidy` in examples/bd-example-extension-go and examples/library-usage.
   The extension example carries most of the churn (~1.6k lines of go.sum),
   which is inherent to recording the parent graph through the replace directive
   and is why an earlier fix (#4942, the Go 1.26.5 bump) deliberately left it
   out. Both modules now build clean with the project's canonical
   `-tags gms_pure_go`.

2. scripts/build-examples.sh plus a `build-examples` job in the PR workflow, so
   the same drift cannot recur unnoticed. The script discovers example modules
   from `git ls-files 'examples/*/go.mod'` (no hardcoded list), sources
   .buildflags for the canonical CGO/tag settings, builds into a scratch
   directory so it leaves no untracked binaries, reports every failing module
   rather than stopping at the first, and prints the exact `go mod tidy`
   command to run.

The job is deliberately NOT added to ci-gate's required list. Because of the
replace directive it would fail on any root go.mod change not mirrored into the
examples, so making it blocking imposes a "tidy the examples too" step on every
dependency bump. That is a maintainer call about contributor friction; the job
is visible on the checks list either way, and pr.yml records how to promote it.

Verified locally: both modules build with -tags gms_pure_go; the script exits 1
and names the module when an example go.mod is reverted to its pre-tidy state;
scripts/check-build-tags.sh stays clean (the script sources .buildflags).

Agent-Signature: claude-opus-5-high on behalf of matt wilkie

* fix(examples): address dual-vendor review — vet not build, advisory job, portability

Reviewed by a claude reviewer and scripts/codex-agent reviewer (gpt-5.6-sol).
Four fixes, two of them correctness.

1. `go build -o <dir>/ ./...` was a FALSE GREEN: with -o naming a directory, Go
   compiles only the MAIN packages and silently skips every library package.
   Reproduced in an isolated module with a good main package plus a library
   package containing a type error — `go build -o dir/ ./...` exits 0 while
   `go build ./...` and `go vet ./...` both exit 1. The mirror-image bug: a
   library-only example module fails `go build` with "no main packages to
   build", a false red. Switched to `go vet ./...`, which type-checks every
   package INCLUDING test files (examples/library-usage/main_test.go exercises
   a lot of live API, and `go mod tidy` counts its imports, so a build that
   never compiles it left part of the recorded graph unverified), writes no
   artifacts, and still fails on the stale-go.mod condition this exists for.
   That also deletes the mktemp/trap/scratch-dir machinery entirely.

2. "Not in ci-gate" is NOT "non-blocking", which the previous comment claimed.
   Verified in source: pr-preflight.sh gates on every FAILURE in the raw
   statusCheckRollup and calls block(), and pr-babysit requires all rollup
   entries SUCCESS/NEUTRAL/SKIPPED before merging. Both ignore ci-gate
   membership. So the previous state was the one posture that stalls the merge
   patrol repo-wide after any un-mirrored dependency bump while advertising
   itself as optional. The job is now continue-on-error: true — genuinely
   advisory — and the comment records how to promote it to a real gate. Whether
   it SHOULD be a gate remains the maintainers' call.

3. Portability and robustness in the script, all reproduced by the reviewers:
   - `mapfile` does not exist in bash 3.2 (stock macOS) and `xargs -r` is
     GNU-only, so the advertised local check could not run on macOS. Replaced
     with a NUL-delimited read loop, which also fixes module paths containing
     whitespace (`git ls-files | xargs -n1 dirname` turned "examples/has
     space/go.mod" into two bogus entries).
   - `source ./.buildflags` was unguarded under `set -uo pipefail`; a failure
     continued with GOFLAGS unset and would type-check the ICU path while
     check-build-tags.sh still passed, since that only greps for the literal
     string. Now a hard exit.
   - Finding zero modules exited 0. A job that checks nothing must not report
     success; it is now an error.

Verified: both modules vet clean; reverting an example go.mod to its pre-tidy
state still exits 1 with the exact `go mod tidy` command; a broken library
package now fails where it previously passed; check-build-tags.sh clean
(97 files); shellcheck clean.

Agent-Signature: claude-opus-5-high on behalf of matt wilkie

* fix(examples): drop GNU-only sort -z from the module discovery pipeline

BSD sort has no -z, so on stock macOS — the exact platform the Bash-3.2
compatibility block targets — the sort stage emptied the pipeline and the
script exited claiming 'found no example modules'. git ls-files output is
already sorted, so the stage bought nothing. Found by cross-vendor review
(codex gpt-5.6-sol) of this branch.

Agent-Signature: claude-fable-5-high on behalf of maphew

* fix(ci,examples): disable setup-go cache in build-examples; re-tidy examples after merge

TestGoCacheOwnershipTopology requires every setup-go step in pr.yml to set
cache: false (caching is owned by explicit restore/save steps); the new
build-examples job predates that policy landing on main. Also re-run
go mod tidy in both example modules so their recorded dependency graphs
match the merged main — exactly the drift this PR's CI job exists to catch.

Agent-Signature: claude-fable-5-high on behalf of maphew

* ci(examples): bound build-examples with timeout-minutes: 10

continue-on-error keeps a red result advisory, but a hung job at the
6-hour default timeout holds the check pending, stalling merge-lane
consumers the advisory posture was meant to protect. Matches
pr-preflight-platforms' bound.

Agent-Signature: claude-fable-5-high on behalf of maphew

* ci(examples): make the advisory posture real - step-level continue-on-error

Job-level continue-on-error still reports the check run as FAILURE in the
PR rollup (only the workflow-run conclusion flips), and pr-preflight /
pr-babysit gate on per-check-run conclusions - so the job as written was
de facto blocking while advertising itself advisory. Follow the cygwin-leg
precedent: continue-on-error on the build step, outcome-guarded ::warning
annotation on failure. Also restore the repo-wide Go module cache (the
examples' graph is the parent's via the replace directive) so the job
stops cold-downloading the full dependency graph on every PR.

Agent-Signature: claude-fable-5-high on behalf of maphew

* test: register build-examples' module-cache restore in the cache topology registry

TestGoCacheOwnershipTopology keeps an explicit inventory of every cache
step per job; the advisory-lane fix added a restore step to build-examples
without registering it, so the whole scripts package went red on this
head. Register the job (inventory, managed map, ordering, setup-go id)
and drop the step's unused 'restore-cache' id — the registry compares
ids, and nothing references it.

Agent-Signature: claude-fable-5-high on behalf of maphew
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019CwiLhLbAGZdJtKYT76CPp

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-08-12 21:16:27 -07:00
ecuthiell 0498b22a75 fix(scripts): scrub Windows env keys case-insensitively (#5534) (#5609)
Signed-off-by: Ewen Cuthiell <ewencuthiell@gmail.com>

Agent-Signature: codex-gpt-5-unknown-reasoning on behalf of Ewen Cuthiell

Co-authored-by: Steve Yegge <steve.yegge@gmail.com>
2026-08-10 23:45:33 -07:00
ecuthiell 59abaff140 fix(make): quote install paths containing spaces (#5600)
* Fix Make install paths containing spaces (#5526)

Quote expanded build and install operands, and prove native Windows install-force preserves an exact spaced destination.

Agent-Signature: codex-gpt-5-unknown-reasoning on behalf of Ewen Cuthiell

* Keep proven rm-first install shape on native Windows (atomic rename fails the spaced-USERPROFILE proof there)

---------

Co-authored-by: Steve Yegge <steve.yegge@gmail.com>
2026-08-10 23:03:42 -07:00
ecuthiell 9628c0189f ci: simplify js/wasm boundary proof (saa-cgh.63) (#5612)
Use Go's supported wasm executor wrapper directly in the required CI lane. Preserve non-vacuous exact-test outcome checks and aggregate-gate propagation without runner host-attestation ceremony.

Fixes #5491

Agent-Signature: codex-gpt-5-unknown-reasoning on behalf of Ewen Cuthiell
2026-08-10 21:02:35 -07:00
ecuthiell 6748ef650c build: make repository text EOL deterministic (#5319)
* build: make repository text EOL deterministic

Apply one repository-wide LF policy to detected text so Windows checkout settings cannot turn ordinary Go source or future text formats into CRLF. Preserve concise rationale for LF-sensitive hook templates, embedded Markdown, migration hashes, and generated-doc comparisons; keep the tracked JPEG explicitly binary and remove redundant path selectors.

Exercise a real isolated Git checkout with core.autocrlf=true through a narrow test package. Bind the existing required Ubuntu, macOS, and Windows matrix to exact expected GOOS values, fail closed on missing or wrong host identity and skipped or zero EOL coverage, and preserve the original doc-freshness command as a separate step.

Resolve and positively identify one canonical Git executable, reuse it under a curated environment with repo-local hooks, and protect the workflow topology with regression tests. Bind the required aggregate to startup-clean absolute Linux Bash and uname identities, require the exact POSIX checkout workspace, and re-enter privileged profile-free Bash with exec so ambient functions or startup state cannot turn a gate failure into success.

Exercise the aggregate shell boundary in subprocess regressions with hostile exported source and exit functions, poisoned startup options, paired clean and failing fixtures, wrong-host falsification, and invalid-workspace cases.

Agent-Signature: codex-gpt-5-unknown-reasoning on behalf of Ewen Cuthiell

* build: split CI-gate hardening from EOL policy

Remove the profile-free CI-gate host-binding chain and its structural and subprocess tests from PR #5319 so the final diff matches the accepted repository EOL motivation. Preserve the required three-host EOL policy lane and its CI Gate propagation. The merge-gate hardening will be reconstructed from current main under its own threat model and review vehicle.

Agent-Signature: codex-gpt-5-unknown-reasoning on behalf of Ewen Cuthiell
2026-08-10 20:48:09 -07:00
ecuthiell 766e6c17f2 fix: reject incompatible timeout in generated hooks (#5522)
Select timeout or gtimeout only after a successful GNU coreutils identity probe, validate BEADS_HOOK_TIMEOUT as positive whole seconds, and preserve the Perl and warned direct fallbacks under inherited shell options.

Keep GNU and Perl deadlines soft and backend-scoped, preserve natural status 137, regenerate every tracked hook artifact, and exercise the real process boundary through the required three-host preflight.

Fixes #5503

Agent-Signature: codex-gpt-5-unknown-reasoning on behalf of Ewen Cuthiell
2026-08-10 20:47:53 -07:00
ecuthiell 07d679ea51 fix: export the native prebuilt test binary path (#5512)
Derive the complete test-runner output with go env GOEXE before both
building and exporting it. Add a fast process regression for launchability
and caller precedence, maintained by the existing three-host preflight lane.

Fixes #5502

Agent-Signature: codex-gpt-5-unknown-reasoning on behalf of Ewen Cuthiell
2026-08-10 05:31:23 -07:00
Julian Knutsen cff62bd631 Make the pre-commit lint gate trustworthy, and stop one main-side lint word from reddening every PR (#5538)
* fix(githooks): build golangci-lint with the repo's Go, not golangci-lint's

The pre-commit hook ran `go run golangci-lint@v2.10.1`. For a pkg@version
build the go command honours the TARGET module's toolchain directive, so
GOTOOLCHAIN=auto downgraded to go1.25.12 — and golangci-lint built by
go1.25 refuses this repo's `go 1.26.5` at config load:

    go: github.com/golangci/golangci-lint/v2@v2.10.1 requires go >= 1.25.0; switching to go1.25.12
    Error: can't load config: the Go language version (go1.25) used to build golangci-lint is lower than the targeted Go version (1.26.5)

Every Go commit failed there, so the hook taught six-plus contributors to
reach for --no-verify — the one habit a lint gate must never train.

CI never hit it because actions/setup-go installs the go.mod version and
exports GOTOOLCHAIN=local, so its `go install ...@v2.10.1` compiles the
linter with go1.26.5. Pinning GOTOOLCHAIN to the go directive reproduces
that resolution on any host, including one whose base toolchain is older
than the repo's target (where a bare GOTOOLCHAIN=local would pin the
linter to that older toolchain instead).

Verified on a real staged Go change: red before with the message above,
`0 issues.` after, and still exit 1 on a planted errcheck violation.

Bead: ga-2ltro.13

* ci: lint PRs for what they introduce, sweep the whole tree on main

Both PR lint gates linted the whole tree: the `lint` job left
only-new-issues at its false default, and pr-lint-wrapper ran
`make ci-pr-lint` over ./... . So a single lint word landing on main —
twice this wave, once a prose misspell — turned EVERY open PR red for a
change it did not make, and each author had to either fix someone else's
line or wait.

The tradeoff, recorded beside the job: a pre-existing issue in untouched
code no longer blocks a PR, and because "new" is measured off the diff, a
violation carried in by a MOVE or a rename does. What it buys is that a
main-side word now reds main's own run, where it belongs. main.yml
already runs both jobs unscoped on every push, so whole-tree coverage —
including the GOOS=windows cross-lint — is unchanged; only its blast
radius moves.

The wrapper takes its scope from BD_LINT_NEW_FROM_MERGE_BASE, set only
by pr.yml, so `make ci-pr-lint` run by hand still sweeps the tree. That
makes the local wrapper STRICTER than the PR gate rather than equal to
it, which is what LINTING.md and CI_CLEANUP_PLAN.md said before and no
longer would: both now state the two-lane contract and say the local
run's extra strictness is deliberate. Their freshness markers move with
the workflow and wrapper files they are pinned to.

Bead: ga-uwix0.2

---------

Co-authored-by: Julian Knutsen <ci@beads.test>
2026-08-10 04:55:55 -07:00
ecuthiell c469a4bc64 fix(hooks): make js/wasm execution explicitly unsupported (#5478)
* fix(hooks): make js/wasm execution explicitly unsupported (saa-cgh.14)

Provide the runHook implementation required by the shared hook runner on js/wasm. Keep process execution out of the WebAssembly target and return a precise unsupported-platform error when the platform-specific boundary is reached.

Agent-Signature: codex-gpt-5-unknown-reasoning on behalf of Ewen Cuthiell

* ci: enforce js/wasm hook boundary (saa-cgh.14)

Exercise the exact unsupported-execution contract under Go js/wasm and pinned Node in an existing required leaf job. Guard the host identity, exact test selection, and required-gate reachability against false-green drift.

Agent-Signature: codex-gpt-5-unknown-reasoning on behalf of Ewen Cuthiell

* ci: bind js/wasm proof authority (saa-cgh.14)

Launch the required boundary proof through startup-clean privileged Bash, bind its Go, GOROOT, and Node identities, and curate inherited runtime controls. Parse the exact test result with Bash builtins so ambient helpers cannot counterfeit execution counts.

Agent-Signature: codex-gpt-5-unknown-reasoning on behalf of Ewen Cuthiell

* ci: follow up js/wasm review (saa-cgh.14)

Keep go.mod as the sole Go-version authority for the required wasm lane, centralize pinned setup action identities, and document the singleton test selector's maintenance contract.

Agent-Signature: codex-gpt-5-unknown-reasoning on behalf of Ewen Cuthiell
2026-08-09 11:49:54 -07:00
ecuthiell bad15e7959 ci: give storage jobs explicit timeout budgets (saa-cgh.60) (#5488)
The race-enabled UOW package now runs close enough to Go's implicit 10-minute deadline that ordinary CI variance can fail unrelated changes. Give the storage tier 15 minutes, preserve the doctor/fix tier's existing 10-minute behavior explicitly, and bound their shared job at 30 minutes. Mirror the policy in PR and main workflows and pin the nested budgets plus required-gate wiring in a structural test.

Agent-Signature: codex-gpt-5-unknown-reasoning on behalf of Ewen Cuthiell
2026-08-09 09:13:09 -07:00
dependabot[bot] b7aedd4efc chore(deps): bump the actions group with 5 updates
Bumps the actions group with 5 updates:

| Package | From | To |
| --- | --- | --- |
| [actions/checkout](https://github.com/actions/checkout) | `7.0.0` | `7.0.1` |
| [DeterminateSystems/determinate-nix-action](https://github.com/determinatesystems/determinate-nix-action) | `3.21.8` | `3.21.9` |
| [actions/cache/restore](https://github.com/actions/cache) | `5.1.0` | `6.1.0` |
| [actions/cache/save](https://github.com/actions/cache) | `5.1.0` | `6.1.0` |
| [actions/attest](https://github.com/actions/attest) | `4.2.0` | `4.2.2` |


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/v7...3d3c42e5aac5ba805825da76410c181273ba90b1)

Updates `DeterminateSystems/determinate-nix-action` from 3.21.8 to 3.21.9
- [Release notes](https://github.com/determinatesystems/determinate-nix-action/releases)
- [Commits](https://github.com/determinatesystems/determinate-nix-action/compare/d96678350ffd6a456235832eb11e1c491589b7bb...61cbfe2efc2d4e7a8a6d56967c3c1058e846c858)

Updates `actions/cache/restore` from 5.1.0 to 6.1.0
- [Release notes](https://github.com/actions/cache/releases)
- [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md)
- [Commits](https://github.com/actions/cache/compare/caa296126883cff596d87d8935842f9db880ef25...55cc8345863c7cc4c66a329aec7e433d2d1c52a9)

Updates `actions/cache/save` from 5.1.0 to 6.1.0
- [Release notes](https://github.com/actions/cache/releases)
- [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md)
- [Commits](https://github.com/actions/cache/compare/caa296126883cff596d87d8935842f9db880ef25...55cc8345863c7cc4c66a329aec7e433d2d1c52a9)

Updates `actions/attest` from 4.2.0 to 4.2.2
- [Release notes](https://github.com/actions/attest/releases)
- [Changelog](https://github.com/actions/attest/blob/main/RELEASE.md)
- [Commits](https://github.com/actions/attest/compare/f7c74d28b9d84cb8768d0b8ca14a4bac6ef463e6...1e69f48acb82d1966a394da916b4c1698aa569d6)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: 7.0.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: DeterminateSystems/determinate-nix-action
  dependency-version: 3.21.9
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: actions/cache/restore
  dependency-version: 6.1.0
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: actions
- dependency-name: actions/cache/save
  dependency-version: 6.1.0
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: actions
- dependency-name: actions/attest
  dependency-version: 4.2.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-08-07 20:49:50 +00:00
Steve Yegge 041f1d64d4 ci(pr): bring test-windows-liveness setup-go under cache ownership (hotfix for #4808 x bd-712nf collision) (#5404)
PR #4808 was reviewed and CI-verified before the TestGoCacheOwnershipTopology
invariant (bd-712nf, #5278) landed on main, so its new test-windows-liveness
job carried an unmanaged setup-go pin (unreleased SHA, implicit cache). Merging
it turned PR Core red on main and on every PR snapshot. Pin the released
v7.0.0 SHA and set cache: false, matching every other managed job.
2026-08-07 11:14:58 -07:00
Marco Del Pin 9200e3d5d1 fix(windows): report Dolt run-state correctly in bd config drift (#4808)
* fix(windows): report Dolt server run-state correctly

isServerProbablyRunning() checked the server PID with proc.Signal(syscall.Signal(0)),
the Unix null-signal probe. Windows has no signals (os.Process.Signal rejects
everything but Kill), so the probe always errored and every live PID looked dead --
bd doctor / drift always reported the shared Dolt server as not running on Windows.

An existence-only replacement is wrong too: on Windows a terminated process's kernel
object stays openable while any handle to it lingers (an un-Wait()ed parent, AV/EDR,
a debugger, Task Manager), so it reports a dead server as alive for a window after exit.

Split the probe into a build-tagged processAlive(pid), matching internal/doltserver
and internal/linear: Unix keeps Signal(0); Windows uses
OpenProcess(SYNCHRONIZE|PROCESS_QUERY_LIMITED_INFORMATION) + WaitForSingleObject(h,0) +
CloseHandle -- a terminated process's handle is signaled (WAIT_OBJECT_0), a running one
times out (WAIT_TIMEOUT). Unix behavior is unchanged.

Adds a Windows regression test that reproduces the lingering-handle false positive
deterministically (fails on the naive OpenProcess-success probe, passes on this fix).

Agent-Signature: claude-code-opus-4.8-high on behalf of Marco Del Pin

* fix(windows): address #4808 review: WAIT_OBJECT_0 precondition, Windows PR-time test lane, naming

- Require WAIT_OBJECT_0 from WaitForSingleObject in the lingering-handle
  test precondition (the pinned x/sys returns nil error on WAIT_TIMEOUT;
  only WAIT_FAILED errors), matching the pattern of the newer Windows
  tests in internal/doltserver and internal/linear.
- Add a targeted windows-latest PR-time job (test-windows-liveness)
  running the ^TestIsServerProbablyRunning tests, wired into the CI gate:
  the //go:build windows regression test is compiled out on the Ubuntu
  jobs, and main.yml's Windows job is push-to-main build/smoke only, so
  without this lane the regression guard never executes at PR time.
- Rename h/s to processHandle/waitResult in processAlive.

Scope note (review should-fix 1): this PR fixes the bd config drift
probe only, processAlive's single production caller. bd doctor's server
run-state goes through doltserver.IsRunning, fixed separately upstream
by 594c464cc.

* fix(windows): rename processAlive to pidAlive to avoid merge-ref collision with #5004 test helper

Upstream bb9bb7487 (#5004, merged 2026-07-24) added a test-only
processAlive helper in cmd/bd/proxied_local_helpers_test.go
(//go:build cgo && unix). On the PR merge ref both declarations
coexist in package main and the cgo unix lanes fail to compile
(processAlive redeclared - Build (Embedded Dolt) + PR Core).
Renaming the production helper introduced by this PR is the
minimal fix; the #5004 test helper is untouched.

* fix(windows): check CloseHandle in pidAlive to satisfy errcheck

The PR gate went red after the maintainer merge of current main wired the
windows lint lane into ci-gate:

  cmd/bd/config_drift_windows.go:26:27: Error return value of
  windows.CloseHandle is not checked (errcheck)

failing both Build Artifacts and PR Lint (wrapper timing) on run 30422840210.

Adopt the pattern every other windows file in the tree already uses for a
deferred handle close - doltserver_windows.go:110, synclock_windows.go:14,
procid_windows.go:35/47, process_executable_windows.go:21:

  defer func() { _ = windows.CloseHandle(processHandle) }()

This file was the only defer windows.CloseHandle(...) without the wrapper.

Verified with the linter itself rather than by inspection: errcheck v1.20.0,
GOOS=windows, -tags gms_pure_go.
  fixed tree     -> 0 hits on config_drift_windows.go:26
  line reverted  -> 1 hit  on config_drift_windows.go:26
so the check demonstrably goes red on the old line and green on the new one.
Also GOOS=windows go vet ./cmd/bd clean, gofmt clean.

The three remaining bare CloseHandle calls in config_drift_windows_test.go are
deliberately untouched: .golangci.yml sets tests: false, which is why CI named
only line 26.

---------

Co-authored-by: Test <test@test.com>
Co-authored-by: matt wilkie <maphew@gmail.com>
Co-authored-by: Marco Del Pin <marco@omniaevo.it>
2026-08-07 10:34:32 -07:00
Julian Knutsen 8a2748c4dd ci: reuse built bd in macOS tests (bd-vygvv) (#5311)
Reuse the current-checkout binary that each macOS job already builds instead of letting subprocess helpers relink it serially. The workflow contract test pins provenance, ordering, matrix scope, and unchanged race-enabled test commands.

Expected hosted saving: 61.66-105.74 seconds without removing coverage or raising timeouts.

Agent-Signature: codex-unknown-model-unknown-reasoning on behalf of CI Bot

Co-authored-by: CI Bot <ci@beads.test>
2026-08-02 21:46:29 -07:00
Julian Knutsen ba55d4ca78 ci: give Go caches explicit ownership (bd-712nf) (#5278) 2026-08-02 07:10:35 -07:00
Julian Knutsen b73c987302 ci: decouple artifacts from duplicate checks (bd-4b1dt) (#5264)
Build and upload reusable artifacts immediately while the existing policy and lint wrapper jobs retain independent required ownership. This releases artifact-dependent tests 4.6-6.2 minutes earlier in recent PR runs without dropping any check.

Agent-Signature: codex-unknown-model-unknown-reasoning on behalf of CI Bot

Co-authored-by: CI Bot <ci@beads.test>
2026-08-01 22:49:45 -07:00
matt wilkie c860100b84 ci(pr): add macOS test job so PR CI catches macOS-only regressions (#5240)
main.yml's Test (macos-latest) leg only runs on push to main
(if: github.event_name == 'push' && github.ref == 'refs/heads/main'),
so no PR ever exercises it. On 2026-08-01 main went red on that leg
from three separately-merged PRs in one day, all $TMPDIR=/var/folders
symlink/path-depth consequences unique to macOS; none of the three
could have seen the failure pre-merge, and the local bisect lane can't
diagnose it either (Linux host, macOS-only failure).

Add a standalone test-macos job to pr.yml that mirrors the exact steps
the macos-latest leg of main.yml's Test job runs (checkout, setup-go,
install Dolt, verify on PATH, configure git/dolt identity, `go build`,
then `go test -tags gms_pure_go -v -race -short -skip '^TestEmbedded'
./...`). It is self-contained with no build-artifacts dependency,
matching what the macOS leg in main.yml actually does (it never
downloads the Linux artifact bundle). It is deliberately not
continue-on-error - a red macOS test is a real regression - and
deliberately not yet added to ci-gate's needs/CI_GATE_REQUIRED,
following the same file's pattern of running new jobs unrequired
before promoting them once proven stable.

Agent-Signature: claude-fable-5-high on behalf of maphew
2026-08-01 15:11:01 -07:00
Julian Knutsen 06b34deba0 ci: retry Dolt image pulls (bd-m0o1z) (#5228) 2026-08-01 08:18:41 -07:00
Steve Yegge 132fec3f44 test(doctor/fix): un-dark the DB-backed cgo suite + fix doctor's fresh-clone create path (bd-nxt5e, bd-kjfsq) (#5174)
The whole fix-package DB-backed suite was silently skipping, locally and in
CI: newFixTestStore predates the dolt.New create-guard and never passed
CreateIfMissing, so every test using it hit the skip path (bd-nxt5e).

Re-enabling it surfaced what the darkness was hiding:
- newIdentityTestStore built database names from full subtest names, blowing
  past Dolt's name length limit — 4/5 TestVerifyFixTargetIdentity subtests
  were failing. Names are now hashed like newFixTestStore's.
- The same missing CreateIfMissing bug in maintenance_cgo_test.go,
  migrate_import_test.go, and metadata_dolt_test.go setups.
- A real product bug (bd-kjfsq): DatabaseVersionWithBdVersion's fresh-clone
  branch — whose explicit purpose is creating the store — calls
  dolt.NewFromConfig without CreateIfMissing, so doctor --fix has failed
  with 'database not found' on exactly the fresh clones it exists for since
  the create-guard landed. Caught by
  TestDatabaseVersionWithBdVersion_ImportsJSONL the moment its skip fell.

Guard against regression: requireFixDoltContainer centralizes the
no-container skip and honors BEADS_FIX_REQUIRE_DOLT=1 (mirroring the
protocol package's BEADS_PROTOCOL_REQUIRE_DOLT), set in the test-domain-uow
CI job — which already pulls the Dolt image — so a missing container is a
hard failure there, never a silent skip. Once the container is up, dolt.New
failures are t.Fatal, not t.Skip.

Full package suite vs the real container: 92 passed, 0 failed; remaining
skips are bd-binary E2E tests and removed-feature stubs.


Claude-Session: https://claude.ai/code/session_01L5Z2ovQDzoMFDxyRe87vD5

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-30 18:04:53 -07:00
Robin Carswell 728b8dfe8f ci(pr): soft-fail the Cygwin Make-shell setup on installer-download flakes (#5035)
The windows-make-shell cygwin leg installs its toolchain via
cygwin/cygwin-install-action, which downloads setup-x86_64.exe from cygwin.com.
That download times out often enough to red the *required* CI gate for a reason
unrelated to the change under test (the leg also skips on non-Windows changes).

Make an installer-download failure a non-blocking warning instead:
- continue-on-error: true on the Cygwin setup step, so its failure no longer
  fails the job;
- gate the Cygwin smoke step on steps.cygwin.outcome == 'success' (outcome, not
  conclusion — outcome reflects the real result before continue-on-error), so it
  skips cleanly on a failed install rather than erroring on a missing bash;
- emit a ::warning:: annotation when the leg is skipped so the flake stays
  visible.

A genuine Cygwin Make regression (install succeeds, smoke fails) still fails the
job exactly as before — only the flaky third-party installer download is
downgraded to a warning.

Fixes #5034

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: matt wilkie <maphew@gmail.com>
2026-07-26 19:52:52 -07:00
matt wilkie 46417b5837 ci(lint): cross-lint Windows-tagged Go, fix fmt-check exit status, pin golangci-lint (core of #5075) (#5083)
Closes #4991; extracted from PR #5075 per its review (split-merge). The
full PR bundled this fix with substantial CI toolchain-identity/host-binding
machinery; this commit keeps only the reviewed core:

- scripts/ci/pr-lint.sh: after the native golangci-lint pass, add a second
  pass with GOOS=windows GOARCH=amd64 CGO_ENABLED=0 GOWORK=off (skipped if
  the native target already matches), so files guarded by
  //go:build windows && !cgo get linted.
- Makefile fmt-check: stop swallowing gofmt's own exit status - a gofmt
  failure (not just "found unformatted files") now fails the check.
- Pin golangci-lint-action from version: latest to v2.10.1 in
  .github/workflows/pr.yml and .github/workflows/main.yml, and harden the
  lint invocations with --config=.golangci.yml,
  --modules-download-mode=readonly, and GOWORK=off.

.github/workflows/ci-measurements.yml already pinned golangci-lint to
v2.10.1 via `go install ...@v2.10.1`, so no change was needed there.


Agent-Signature: claude-fable-5-medium on behalf of maphew

Co-authored-by: Ewen Cuthiell <ewencuthiell@gmail.com>
2026-07-26 12:41:18 -07:00
ecuthiell bbda695454 fix(scripts): remove Python from doc freshness checks (#4978) (#4979)
Use strict pure-Bash proleptic-Gregorian validation and day numbering so the full 0001-01-01 through 9999-12-31 domain is independent of platform date parsing. Keep native date only as the default TODAY provider, with distinct provider-versus-override diagnostics.

Mark the real-process suite integration-only, harden Git Bash discovery and its child environment, and require native Linux, macOS, and Windows boundaries in PR CI.

Agent-Signature: codex-tui-gpt-5.6-sol-ultra on behalf of Ewen Cuthiell

Co-authored-by: matt wilkie <maphew@gmail.com>
2026-07-25 22:53:47 -07:00
dependabot[bot] 9cf254488e build(deps): bump the actions group across 1 directory with 3 updates (#5059)
Bumps the actions group with 3 updates in the / directory: [actions/checkout](https://github.com/actions/checkout), [actions/setup-go](https://github.com/actions/setup-go) and [actions/setup-python](https://github.com/actions/setup-python).


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/v7...3d3c42e5aac5ba805825da76410c181273ba90b1)

Updates `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)

Updates `actions/setup-python` from 6.3.0 to 7.0.0
- [Release notes](https://github.com/actions/setup-python/releases)
- [Commits](https://github.com/actions/setup-python/compare/ece7cb06caefa5fff74198d8649806c4678c61a1...5fda3b95a4ea91299a34e894583c3862153e4b97)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: 7.0.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: actions/setup-go
  dependency-version: 7.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: actions
- dependency-name: actions/setup-python
  dependency-version: 7.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-25 19:05:02 -07:00
ecuthiell cd25e0919d fix(worktree): add explicit merge containment (#4929)
* fix(worktree): add explicit merge containment (#4919)

Allow worktree removal to verify HEAD containment against a caller-selected ref while failing closed when no upstream can be resolved.

Agent-Signature: codex-tui-gpt-5.6-sol-ultra on behalf of Ewen Cuthiell

* fix(worktree): preserve Windows path identity (#4919)

Git for Windows canonicalizes an 8.3 ancestor before recording worktree paths. Match two missing paths only when their exact unresolved suffixes peel to stat-proven identical ancestors, while keeping existing-versus-missing identities distinct.

Force ordinal matching for the destructive Git selector so a final-boundary target disappearance or core.ignorecase change cannot redirect removal to a case-variant sibling. Add real-process coverage for the short-path lookup, ordinary case-insensitive repositories, the selector race, and a restoration hook that is proven to execute.

Agent-Signature: codex-tui-gpt-5.6-sol-ultra on behalf of Ewen Cuthiell

---------

Co-authored-by: matt wilkie <maphew@gmail.com>
2026-07-25 17:05:48 -07:00
ecuthiell 8137ed4092 test(preflight): inject fake gh in Bash (#4967) (#4968)
Execute the production script as a real Bash process whose controlled BASH_ENV defines the fake gh function. Curate shell, Git, GitHub, and path state; poison inherited startup/configuration in the fixture; and require the process boundary on Linux, macOS, and Windows.

Agent-Signature: codex-tui-gpt-5.6-sol-ultra on behalf of Ewen Cuthiell
2026-07-25 16:14:33 -07:00
dependabot[bot] 4fd05a5748 build(deps): bump actions/checkout from 7.0.0 to 7.0.1 (#5016)
Bumps [actions/checkout](https://github.com/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)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-25 08:52:22 -07:00
ecuthiell 2e20a183f2 fix(make): distinguish native Windows shell bootstrap (#4948) (#4949)
Bootstrap Git Bash only for native GNU Make host identities. Neutralize startup overrides, validate the required Git tools, preserve MSYS2 and Cygwin POSIX semantics, and feed real native, MSYS2, and Cygwin smoke lanes into the required PR aggregate.

Agent-Signature: codex-tui-gpt-5.6-sol-ultra on behalf of Ewen Cuthiell
2026-07-24 10:52:46 -07:00
dependabot[bot] ca44d76f93 build(deps): bump actions/setup-node from 6.4.0 to 7.0.0 (#4872)
Bumps [actions/setup-node](https://github.com/actions/setup-node) from 6.4.0 to 7.0.0.
- [Release notes](https://github.com/actions/setup-node/releases)
- [Commits](https://github.com/actions/setup-node/compare/48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e...820762786026740c76f36085b0efc47a31fe5020)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-23 14:08:05 -07:00
coffeegoddd☕️✨ e79ea8e65d /{.github,docs,engdocs,go,internal,scripts}: bump dolt 2026-07-15 13:14:34 -07:00
Steve Yegge b92b369962 ci(protocol): gate the whole cmd/bd/protocol package, not a -run subset (wy-h8fm9)
The contract-corpus job was the only CI job that installs Dolt and sets
BEADS_PROTOCOL_REQUIRE_DOLT=1, but its -run filter matched only the golden
corpus + determinism tests. The TestProtocol_/TestJSONContract_ behavioral
conformance suite therefore ran in NO job: every other job reaches
./cmd/bd/protocol via a broad ./... without a Dolt store, so requireDoltStore
skips the whole suite. Five of those tests sat red on main for ~3 months
(since cfcc95799) with every CI run green.

Drop the -run filter so the required gate runs the package. Package scope is
the point: any -run regex re-creates the same hole for the next test added.
Add an explicit -timeout — the package runs past `go test`'s 10m default, and
a timeout panic is not a verdict.

Verified by mutation: with the empty-comment-text rejection removed from
cmd/bd/comments.go, the old -run subset still reports ok, while the package
scope fails TestProtocol_CommentRejectsEmptyText. Full package is green on
main (~9 min at GOMAXPROCS=4).
2026-07-13 10:43:24 -07:00
Chris Sells 52aea3f7e3 docs: go all-in on Mintlify — delete the Docusaurus site and its machinery
Per the decision record: no parallel run and no cutover PR. Removes
website/ (including the four versioned doc snapshots — current-only
versioning; snapshots remain in git history), deploy-docs.yml,
generate-llms-full.sh (Mintlify serves llms.txt natively), the ci-website
package gate (Makefile target, scripts/ci/website.sh, the package-website
jobs and their aggregate-gate entries in pr.yml/main.yml/release.yml, the
ci-measurements suite, detect-package-gates wiring), and the release-time
docs snapshot flow (snapshot-release-docs.sh, check-docs-version.sh, their
call sites in update-versions.sh/check-versions.sh, RELEASING.md section
rewritten for the Mintlify reality).

Drift machinery now covers exactly the Mintlify artifacts:
check-cli-docs-drift.sh pathspecs/fingerprint, docs-autofix-push.sh
allowlist, and check-doc-flags.sh scans drop the website/llms paths. The
beads-docs skill's generated-content and verification sections updated to
the bd-generic + docsmint pipeline.

NOTE for merge time: if branch protection requires the 'Package Gate
(website)' check by name (rather than the aggregate gate), drop it from
the required checks or PRs will wait forever.

Gates: docsync PASS, generate-cli-docs.sh --check PASS, freshness PASS.
2026-07-12 10:37:17 -07:00
Chris Sells 3198395a32 docs(ci): add Mintlify preview, docsync guard, and broken-links workflow
- mint.sh + make docs-dev: local preview of the docs/ Mintlify site
  (Node 22 handling modeled on the Gas City wrapper).
- test/docsync: Go guard keeping docs/ and docs.json in exact
  correspondence — every nav entry has a file, every page is in the nav
  (tiny stub allowlist for paths released bd binaries print), published
  pages use root-relative extensionless links that resolve, and engdocs/
  plus curated root markdown keep exact GitHub-style paths. Wired into
  make check-docs.
- .github/workflows/docs-mintlify.yml: docsync + baseline-aware
  mint broken-links check on PRs touching docs/**.
- Retire scripts/sync-website-docs.sh and its mirror-drift gate: the six
  mirrored files now live once in the Mintlify site; the committed
  Docusaurus mirrors stay frozen so the parallel-run site keeps building.
- Repoint inbound links to moved docs across README, guides, examples,
  npm-package, plugin resources, and Go comments; add docs/SYNC_CONCEPTS.md
  pointer stub (bd's agent templates print that path). Runtime strings in
  cmd/bd (prime.go, store_factory_nocgo.go, init_git_hooks.go) still print
  old paths — covered by stubs, flagged in the PR.
2026-07-12 10:37:07 -07:00
Chris Sells 0e017821f4 docs: move internal/maintainer docs from docs/ to engdocs/
Relocate contributor- and maintainer-facing material out of docs/ so the
directory can become the user-facing Mintlify site. Moves preserve subpaths
(adr/, design/, staged-for-removal/ intact). messaging.md, UI_PHILOSOPHY.md,
and AGENT_SIGNING.md move per their DOC_INVENTORY dispositions (design doc,
design philosophy, maintainer convention).

Inbound links updated repo-wide: root guides, CONTRIBUTING, AGENTS,
workflows, lint config, scripts (check-doc-freshness now resolves the
inventory at engdocs/DOC_INVENTORY.md), Go comments, and the synced website
metadata page (regenerated via sync-website-docs.sh + generate-llms-full.sh).

The emitted help text in cmd/bd/init_safety_help.go still references
docs/adr/0002-init-safety-invariants.md; changing it would change bd's
runtime output, which is out of scope for this branch (flagged in the PR).
2026-07-12 10:37:07 -07:00
Test User 1fc38ba778 feat: choose your own storage backend (Postgres / MySQL / SQLite) — rebased on main
Rebase of PR #4601 (feat/choose-your-own-backend) onto current origin/main,
squashed to a single commit because the original 73-commit history built and then
removed the uowStore derisk spike incrementally, which does not replay cleanly
over the 125 commits main has since advanced (notably #4679, the ready-work
counts fix, which merged to main and is now inherited rather than re-applied).
The full pre-rebase history remains on the original branch tip for reference.

Contents (multi-backend feature + the six review follow-ups):
- bd init --backend=postgres|mysql|sqlite provisioning behind the Dolt-parity
  seam; the three SQL backends share *sqlkit.Store over pluggable dialects and
  carry a generated typed-unsupported shell for the non-core surface.
- Passwords in init DSNs are redacted before persisting to metadata.json (driver
  parser + re-parse verification), with a negative-test matrix proving no secret
  survives (pgdialect + mysql).
- The uowStore derisk spike and its report artifacts are removed; the shell
  generator now lives in internal/storage/unsupportedgen (neutral name).
- Compile-time guard `var _ storage.DoltStorage = (*Store)(nil)` on each backend
  plus a regen-idempotence test keep the generated skip lists honest.
- sqlkit exposes CountReadyWork so every SQL backend satisfies
  storage.ReadyWorkCounter and inherits the shared page-pushed ready-counts path.
- Commercial/product names scrubbed from the feature's own code for vendor
  neutrality.

Rebase reconciliations: adopted main's metadata-load hardening in the store
factories alongside the backend dispatch; combined the config interface
(GetMetadata + ReconcileVersion) and the conformance registrations (ReadyCounts +
Claim/lease); took main's versions of the shared-infra concurrency (uow
doltserver_tx) and delete-cascade (domain/issue_delete) evolutions; implemented
the interface's new UnclaimIssue on sqlkit (delegating to issueops) and added it
to the skip lists.

Verified: go build (cgo + CGO_ENABLED=0) and go vet clean; unit tests
(sqlbuild/issueops/pgdialect/mysql/unsupportedgen) and the SQLite conformance
suite green (RunAll, incl. ReadyCounts equivalence and Claim/lease on the real
sqlkit backend).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-10 17:44:37 +00:00
dependabot[bot] 0dfb00aaa9 build(deps): bump golangci/golangci-lint-action from 9.2.1 to 9.3.0 (#4664)
Bumps [golangci/golangci-lint-action](https://github.com/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)

---
updated-dependencies:
- dependency-name: golangci/golangci-lint-action
  dependency-version: 9.3.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-08 10:47:20 -07:00
dependabot[bot] 3adfbeff2a build(deps): bump actions/setup-python from 6.2.0 to 6.3.0 (#4496)
Bumps [actions/setup-python](https://github.com/actions/setup-python) from 6.2.0 to 6.3.0.
- [Release notes](https://github.com/actions/setup-python/releases)
- [Commits](https://github.com/actions/setup-python/compare/a309ff8b426b58ec0e2a45f0f869d46889d02405...ece7cb06caefa5fff74198d8649806c4678c61a1)

---
updated-dependencies:
- dependency-name: actions/setup-python
  dependency-version: 6.3.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-08 08:30:59 -07:00
dependabot[bot] 17dc590963 build(deps): bump actions/setup-go from 6.4.0 to 6.5.0 (#4495)
Bumps [actions/setup-go](https://github.com/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)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-08 08:30:55 -07:00
matt wilkie 4cef43d2fb docs(website): refresh committed mirrors and add CI drift gate (#4661)
* docs(website): refresh committed sync-website-docs mirrors

Regenerate the Docusaurus mirrors of docs/METADATA.md and
docs/COMMUNITY_TOOLS.md with scripts/sync-website-docs.sh: the metadata
mirror was missing the "portable hints" paragraph and the gh-3541
resolution wording (#4358), and community-tools.md was missing five
entries (bd-board, Bead Me Up Scotty, beads.nvim, BeadSpec, LoopTroop)
present in the source doc. sync-website-docs.sh also regenerates the
versioned_docs/version-1.1.0 copies, so both metadata.md drift sites are
fixed by running the script; no manual versioned_docs edit was needed.

Agent-Signature: claude-sonnet-5-high on behalf of matt wilkie

* ci: add website-docs drift gate to pr.yml

Add scripts/check-website-docs-drift.sh, mirroring the seam
scripts/check-cli-docs-drift.sh uses in the check-doc-flags job: run the
generator (scripts/sync-website-docs.sh) and fail if it produces any diff
against the committed website/docs and website/versioned_docs mirrors.
Unlike the CLI reference docs, the website-docs mirror is a pure text
transform of files already committed in this repo, so no bd binary build
and no merge-base attribution are needed; the check backs up the tree,
regenerates, diffs, and restores the tree either way so it is
side-effect-free.

Wire it into the check-doc-flags job in .github/workflows/pr.yml as a new
"Validate website doc mirrors" step alongside "Validate docs against CLI".

Not extended: the docs-autofix.yml / docs-autofix-push.sh auto-push loop
that closes the loop for CLI docs drift. That pipeline is a nontrivial
addition (patch artifact, path allowlist, workflow_run consumer) built
specifically around generate-cli-docs.sh's build-dependent regeneration;
extending it for the website mirrors is left as a follow-up rather than
bolted on here.

Agent-Signature: claude-sonnet-5-high on behalf of matt wilkie

* docs: regenerate llms-full.txt for refreshed website mirrors

The mirror refresh changed website/docs content (metadata.md portable-hints
paragraph, community-tools.md new tools), and llms-full.txt is generated
from those pages. CI's check-doc-flags caught the stale committed copy;
this applies the cli-docs-freshness-patch artifact from run 28923961592's
PR job verbatim.

Agent-Signature: claude-fable-5-high on behalf of matt wilkie
2026-07-08 08:23:47 -07:00
matt wilkie 1ecabad275 ci(docs): auto-apply CLI docs regeneration to PR branches (#4653)
* ci(docs): auto-apply CLI docs regeneration to PR branches

The check-doc-flags gate already computes the exact regeneration patch
with CI's canonical build and uploads it as an artifact; contributors
still had to notice, download, and apply it by hand - a recurring
friction point (most recently the 2026-07-07 agent.profile drift).

Close the loop with a workflow_run job: on a failed PR run that left
the cli-docs-freshness-patch artifact, push the regen commit to
same-repo PR branches, or leave an idempotent comment with the apply
recipe on fork PRs (always - no token we hold can push to a fork).

Security: the privileged side checks out base main only and treats the
patch as untrusted data. An anchored allowlist (single path segment,
no traversal, symlink modes refused) pins which files may change, and
git apply --index supplies the underlying escape guards, so a hostile
patch can at most rewrite generated docs on its own PR branch. A
circuit breaker refuses to stack autofix commits if regeneration ever
stops converging.

Default-token pushes do not retrigger PR checks; an optional
DOCS_AUTOFIX_TOKEN secret upgrades same-repo PRs to fully hands-off.

Agent-Signature: claude-fable-5-high on behalf of matt wilkie
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* ci(docs): split API token from push token in docs-autofix

Review finding (maphew, 2026-07-07): with a contents-only
DOCS_AUTOFIX_TOKEN configured, all gh api calls used the PAT, so the
push would succeed and the comment endpoints would 403 (they need
pull-requests write). gh api now always uses the workflow token, which
carries this job's pull-requests:write; the optional PAT flows only
into the git extraheader for the push, so contents:write remains the
complete requirement documented for it.

Agent-Signature: claude-fable-5-high on behalf of matt wilkie
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-07 22:16:37 -07:00
matt wilkie ed0c86a158 fix(lint): align golangci-lint pins at v2.10.1 and triage new gosec findings (mybd-kpd7) (#4594)
CI installed golangci-lint v2.9.0 via `go install` in main.yml and pr.yml,
while .pre-commit-config.yaml pinned v2.10.1. Under v2.10.1, gosec's taint
analysis (G702/G704/G705) and secret-pattern check (G117) surface 8 new
findings that v2.9.0 does not report, so contributors running pre-commit
hit lint failures CI never shows and can't reproduce locally against CI's
pinned version.

Bump the CI `go install ... @v2.9.0` pins to v2.10.1 in main.yml, pr.yml,
and ci-measurements.yml so CI and pre-commit run the same version.

Triage the 8 new findings against v2.10.1:
- internal/github/client.go G704 (SSRF via taint on c.HTTPClient.Do):
  same category as the existing G704 exclusion for gitlab/jira/linear API
  clients with user-configured URLs; add it to that path list.
- internal/linear/oauth.go G704 (SSRF via taint on m.client.Do): same
  category, OAuth token endpoint is user-configured; add to the G704 path
  list alongside linear/client.go.
- internal/linear/oauth.go G117 x2 (ClientSecret, AccessToken exported
  fields matching secret patterns): same category as the existing G117
  exclusion for jira/client.go and linear/types.go; add oauth.go.
- internal/linear/client.go G705 (XSS via taint on fmt.Fprintf to
  os.Stderr): CLI stderr output, no browser context - same category as
  the existing G705 exclusion for cmd/bd/compact.go; add linear/client.go.
- scripts/repro-dolt-prod-timeouts/main.go G704 (SSRF via taint on
  net.DialTimeout to 127.0.0.1) and G702 x2 (command injection via taint
  on exec.CommandContext with cfg.BDPath): throwaway local repro tool
  probing a locally started dolt server with fixed subcommand args and an
  operator-supplied binary path; resolved with inline `#nosec` comments
  matching the existing style in this repo (e.g. init_stealth.go, dolt
  store.go) rather than a repo-wide .golangci.yml exclusion.

Verified: golangci-lint v2.10.1 (installed to a private GOBIN outside the
repo tree) reports 0 issues with --build-tags=gms_pure_go ./..., `go build
-tags gms_pure_go ./...` passes, and `go test -tags gms_pure_go
./internal/github/... ./internal/linear/...` passes.


Claude-Session: https://claude.ai/code/session_01FWVnjn3Bq4PSG1akpFpKnY
Agent-Signature: claude-sonnet-5-medium on behalf of matt wilkie

Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-07 13:33:07 -07:00
coffeegoddd☕️✨ aff3b22bc3 /{.github,docs,go,internal,scripts}: bump dolt min version and driver 2026-07-06 16:04:11 -07:00
Julian Knutsen 1914af5852 test(protocol): golden-JSON contract corpus + diff guard (Beads↔Gas City contract, Phase 2) (#4490)
* test(protocol): add canonicalized golden-JSON contract corpus + diff guard (contract Phase 2)

Producer half of the Beads<->Gas City cross-version contract-test system.
Generates a deterministic, canonicalized golden-JSON corpus of bd's --json
wire surface (create/show/list/ready/dep/count/version + the
{error,schema_version} envelope, in both flat and BD_JSON_ENVELOPE=1
variants) and fails on any unreviewed diff. Gas City vendors this corpus
to detect cross-version drift without a live bd.

- corpus.go: deterministic command plan, canonicalizer (timestamps -> <TS>,
  object arrays stable-sorted, sorted keys), provenance manifest.
- corpus_test.go: TestCorpusGolden (byte-compare vs committed corpus;
  -corpus.update regenerates; Dolt-boot is an infra skip, a diff is a hard
  fail). Pins IDs with --force for determinism; captures stdout only.
- canonicalize_test.go: canonicalizer unit tests + TestCorpusDoubleRunByteIdentical.
- make corpus-regen; cmd/bd/protocol/CATALOG.md.

Pre-commit hook bypassed: it fails in golangci-lint (built with Go 1.25,
repo targets 1.26.2) unrelated to this change; gofmt, go vet, and the full
corpus test suite were run manually and pass.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* ci: gate the contract corpus in beads CI (contract-corpus job)

Adds a Docker-enabled contract-corpus job to the PR gate that regenerates
the canonicalized golden corpus from this branch's bd and byte-compares it
to the committed testdata/corpus/, plus the determinism double-run. An
unreviewed bd --json wire change is now a hard CI failure on the producer
side, mirroring the gascity consumer gate. Wired into ci-gate/CI_GATE_REQUIRED.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(protocol): drop build-provenance from the corpus so it is reproducible across build envs

The contract-corpus CI gate caught a real reproducibility bug: bd version
--json embeds a 'commit' field from Go's VCS stamping that varies by build
environment (a local worktree build omits it; a CI clean-clone build embeds
the SHA), so the committed golden corpus failed the diff in CI. Canonicalization
now drops the 'commit' key entirely (value AND presence vary), and the manifest
no longer records bd_commit. bd_version plus the per-blob checksums remain the
reproducible provenance.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* ci: publish the contract corpus as a release artifact (contract Phase 3)

Ships cmd/bd/protocol/testdata/corpus as beads_<version>_contract_corpus.tar.gz
with each release and appends its checksum to the release checksums.txt, so Gas
City can anchor its vendored-corpus drift-check to a signed beads release rather
than a self-recomputed manifest. Runs in the goreleaser job before the macOS
job's serial checksums.txt append (goreleaser-macos needs goreleaser), so the
corpus entry is preserved.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* test(protocol): extend the contract corpus to the full command surface

Adds update, close, reopen, delete, dep remove, and two more create beads to
the corpus plan, taking it to 17 commands x {flat, envelope}. New shapes pinned:
the update/close/reopen issue arrays (incl. close_reason + closed_at), the
dual-key dep edge {issue_id, depends_on_id, type, status} for add AND remove,
the delete confirmation {deleted, dependencies_removed, references_updated}, and
metadata coercion (--set-metadata phase=2 -> integer 2) plus label round-trip.
Mutations run after the show/dep_list reads so those long-standing blobs stay
byte-identical; list/ready/count now reflect post-mutation state. Golden +
double-run determinism verified.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(protocol): make the corpus version-agnostic (placeholder version/branch/build)

The contract-corpus gate failed when beads main bumped to 1.1.0-rc.1: the corpus
version.json pinned the literal bd version, which changes every release (CI builds
the PR merged with current main). The corpus pins wire SHAPES, not release
identity, so canonicalization now replaces version/branch/build values with
placeholders and the manifest drops bd_version/bd_commit entirely. schema_version
(the coordination canary) + per-blob checksums remain. gc's real version
parsing/gating is covered by the cross-version matrix + bd_version_pin_test.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(protocol): satisfy build-tag policy + misspell lint for contract corpus

Pre-review CI repair for the golden-JSON contract corpus PR (#4490):

- Makefile: add -tags "$(BUILD_TAGS)" to the corpus-regen target so it
  passes scripts/check-build-tags.sh (ICU build-tag policy, see
  docs/ICU-POLICY.md), matching every other go test/build target.
- corpus.go: fix "re-marshalled" -> "re-marshaled" (misspell, US locale).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(protocol): harden the contract corpus per maintainer review

Maintainer review fixups for the golden-JSON contract corpus (PR #4490),
folded into one maintainer commit across review iterations.

- CanonicalizeJSON now rejects trailing stdout after the first JSON value.
  A command that printed valid JSON followed by a warning line (or a second
  JSON value) would otherwise be silently truncated to the leading value and
  pass the corpus gate, while a real consumer decoding the whole stream would
  choke. Add regression tests for trailing text, multiple values, and the
  still-allowed trailing-whitespace case.
- TestCorpusGolden now asserts the committed corpus file set is exactly the
  generated blobs plus manifest.json, and `make corpus-regen` recreates each
  mode directory before writing. A capture removed or renamed in CorpusPlan can
  no longer leave a stale blob committed and shipped in the release archive.
- The required contract-corpus CI job sets BEADS_PROTOCOL_REQUIRE_DOLT=1 and
  the corpus tests hard-fail (not skip) when the Dolt store is unavailable, so
  the gate cannot report success without exercising the golden and double-run
  checks.
- Document the intentionally global (bare-key) scope of provenance
  canonicalization and the required future action if a non-version command adds
  a commit/version/branch/build field.
- Make the release corpus-checksum append idempotent so a re-run of the
  goreleaser job does not leave a duplicate row in checksums.txt.
- generateCorpus now pins each capture's subprocess exit status instead of
  discarding cmd.Run(): every capture must exit 0 except the dedicated error
  capture, which must exit non-zero with bd's not-found code. Otherwise the
  corpus could pass while a "successful" command exited non-zero, or while the
  error capture stopped failing, leaving the exit-codes-and-errors half of the
  error blob's contract (CATALOG.md) unpinned. Add a checkCaptureExit helper
  and TestCheckCaptureExit, and run the test in the required CI job.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: CI Bot <ci@beads.test>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-04 18:54:28 -07:00
coffeegoddd☕️✨ d7d7a34607 : refactor to use RunE, emit usage metrics, skip metrics in CI
(cherry picked from commit 9596c7233d)
2026-06-22 20:44:43 +00:00
dependabot[bot] 823b0ed343 build(deps): bump actions/checkout from 6.0.2 to 7.0.0 (#4456)
Bumps [actions/checkout](https://github.com/actions/checkout) from 6.0.2 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/de0fac2e4500dabe0009e67214ff5f5447ce83dd...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>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-22 13:17:29 -07:00
dependabot[bot] c57bcc879c build(deps): bump golangci/golangci-lint-action from 9.2.0 to 9.2.1 (#4111)
Bumps [golangci/golangci-lint-action](https://github.com/golangci/golangci-lint-action) from 9.2.0 to 9.2.1.
- [Release notes](https://github.com/golangci/golangci-lint-action/releases)
- [Commits](https://github.com/golangci/golangci-lint-action/compare/1e7e51e771db61008b38414a730f564565cf7c20...82606bf257cbaff209d206a39f5134f0cfbfd2ee)

---
updated-dependencies:
- dependency-name: golangci/golangci-lint-action
  dependency-version: 9.2.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-22 10:34:19 -07:00
matt wilkie 1de37278ad ci(docs): blame-scoped CLI docs freshness gate + fix patch artifact (#4301)
The doc freshness gate regenerated all generated doc artifacts and failed
the PR on any diff, even drift the contributor did not cause: staleness
inherited from the base branch, or local regeneration environments that
do not match CI's canonical build. Contributors ended up futzing with
regeneration loops for docs unrelated to their change (#4300, #4301).

New scripts/check-cli-docs-drift.sh keeps the strict regenerate-and-diff
probe as the fast path, but on failure in a PR it attributes the drift
before failing anyone: it regenerates the artifacts at HEAD and at the
merge-base in scratch worktrees, each with the canonical pinned build
(CGO_ENABLED=0 -tags gms_pure_go). If the PR neither changed the
regenerated CLI surface nor touched generated files, the drift is
inherited: warn and pass. Contributors only own docs for code they
actually touched.

When the drift IS attributable, CI now writes the exact regenerated fix
as a patch and uploads it as the cli-docs-freshness-patch artifact, so
the fix never depends on the contributor's local environment: download,
git apply, push.

Strict behavior is preserved wherever there is no PR base ref: pushes to
main, releases, and plain local runs. The pr-policy wrapper picks up the
same logic through check-doc-flags.sh.

Refs #4301, #4203. Complements #4312 (docgen binary pinning).

Agent-Signature: claude-unknown-model-high on behalf of matt wilkie
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-14 23:40:17 -07:00
Steve Yegge 262b0afd5e ci: actually run internal/tracker tests in the docker-backed test job (bd-578h9.1)
CI compiled ./internal/tracker tests but never ran them: the only job
with the dolt-sql-server image pulled ran domain/... and uow/... alone,
and everywhere else the tracker tests self-skip when the image is
absent. That hid six born-failing engine tests for ten weeks. Add the
package to the docker-backed job on both pr.yml and main.yml.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-11 10:26:36 -04:00
Steve Yegge 5bdc8bc6e7 ci(migrations): enforce migration hygiene: dup versions, nondeterministic SQL, frozen shipped files (bd-6dnrw.15)
scripts/check-migration-hygiene.sh consolidates the inline duplicate-version
CI check and adds two guards derived from the Apr-Jun audit:

- Lint UUID()/NOW()/RAND() in migration SQL (the PR 4039 / #4259 root-cause
  class), with a justification-required allowlist grandfathering shipped
  files. Stale or unjustified allowlist entries fail CI.
- Freeze migration files that exist on the base branch (the PR 3991/3918/3942
  in-place-edit class): modification, deletion, or rename fails; fix forward
  with a new version. Complements the PR 4270 content hashes, which assume
  applied migration content never changes.

CODEOWNERS now routes migrations/ and the hygiene script to maintainers
(enforcement still needs the code-owner branch-protection toggle, tracked
under bd-6dnrw.23). Duplicate-version coverage now includes migrations/ignored/.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-10 23:57:41 -04:00
Dustin Brown 9a1c88b63a /{.github,docs,go,internal,scripts}: bump driver/dolt version to 2.1.4 (#4326)
* /{.github,docs,go,internal,scripts}: bump driver/dolt version to 2.1.4

* /default.nix: update hash
2026-06-08 11:31:14 -07:00
Julian Knutsen 9e8d411f71 Add PR CI wrapper command surface (#4211)
* ci: add PR wrapper command surface

* ci: collect wrapper timing in PR checks

* docs: record initial CI wrapper measurements

* ci: add manual measurement workflow

* ci: allow branch measurement dispatch

* ci: keep measuring independent commands after failures

* docs: record branch-dispatched CI measurement

* ci: keep measuring package suites after failures

* docs: record CI measurement batch

* fix: repair CI-measured test failures

* test: make local Go gates hermetic

* ci: add sharded integration measurement lane

* test: fix internal beads integration TestMain

* docs: record fixed integration shard measurement

* ci: add hybrid integration sharding measurement

* ci: speed up cmd/bd test shard discovery

* ci: add 16-way integration sharding measurement

* ci: measure prebuilt cmd bd sharding

* docs: record prebuilt sharding measurement

* docs: design CI build artifact stage

* docs: record repeat prebuilt integration measurement

* ci: add build artifact stage

* ci: reuse build artifact in linux test lane

* ci: promote main linux integration shards

* ci: gate legacy platform tests to main

* ci: satisfy workflow shell lint

* ci: ignore archived migrations in duplicate check

* ci: add package gate wrappers

* test: clean up testing short boundaries

* ci: allow unreleased version docs lag

* ci: gate releases on package checks

* ci: split workflow by tier

* ci: add aggregate PR gates
2026-05-29 18:52:53 -07:00