test(dolt): give the doctor backup-freshness fixtures a real margin (gc-c4n6r)#98
test(dolt): give the doctor backup-freshness fixtures a real margin (gc-c4n6r)#98zook-bot wants to merge 69 commits into
Conversation
Per-commit testing during rebase replay is redundant; the formula's post-rebase test step is the gate. Cuts a 40-commit rebase from ~38 × make-test to one make-test.
…d checks in agent context (gc-53c8k4) (#21) (per gc-3moew.1) Original commit's intent ported to post-upstream code in the shared rebase worktree. Classification: mechanical. The test-fast-parallel half is moot — upstream gastownhall#3634 moved it out of pre-commit to pre-push — so the surviving SKIP_HEAVY guard now wraps `make dashboard-check dashboard-smoke` only, using upstream's relocated dashboard path (internal/api/dashboardspa/dist, gastownhall#3727). Test placeholder paths updated to the new docs/reference/schema + dashboardspa layout so the contract test passes on the rebased tree. See gc-3moew.1 for context and metadata.classification.
… git config in tests that exec git commit (gc-vyrtt) (per gc-gkf9m3.2) (per gc-9n4v5n.1) (per gc-5sacl.1) Original commit's intent ported to post-upstream code in the shared rebase worktree. See gc-5sacl.1 for context and metadata.classification.
…TCP-correct) (per gc-iv5cnp.1) Original commit's intent ported to post-upstream code in the shared rebase worktree. See gc-iv5cnp.1 for context and metadata.classification.
…ntToStores (per gc-5sacl.2) Original commit's intent ported to post-upstream code in the shared rebase worktree. Classification: judgment-required (review pending). Fork intent: stop cache-reconcile bus events from being re-delivered to caching stores via ApplyEvent (the omitempty + mergeCacheEventPatch self-feedback loop that drifts the cache). Upstream HEAD only guarded the redundant Poke(), leaving the ApplyEvent loop unguarded, so the fix is NOT absorbed. Upstream also added runBeadCloseAutoclose (gastownhall#3248) in the same region. Resolution widens upstream's existing !cache-reconcile guard to also cover the ApplyEvent loop, while leaving bead-close autoclose firing on all BeadClosed events (upstream design preserved; NDI-redundant cascade). See gc-5sacl.2 for context and metadata.judgment_summary.
…nc (per gc-u1g6k.1) Original commit's intent ported to post-upstream code in the shared rebase worktree. See gc-u1g6k.1 for context and metadata.classification.
…ash (per gc-a4qrp.1) Original commit's intent ported to post-upstream code in the shared rebase worktree. Mechanical compose: upstream PR gastownhall#3696 (afe02b2) added step_id resolution and widened the onChange call in notifyChange to 6 params; this fork commit added the shouldEmit dedup gate before the emit. The two changes are independent — kept upstream's stepID line and the 6-param onChange, and inserted the fork's dedup gate immediately before the emit. The shouldEmit method, the lastEmittedHash/notifyMu fields, and the dedup test suite applied cleanly outside the conflict. Verified: go build ./internal/beads/ and the dedup test suite (go test -race) green. See gc-a4qrp.1 for context and metadata.classification.
When .beads/config.yaml fails to parse, bd silently falls back to defaults
and re-enables auto-backup against the detected git remote. With many parallel
agents that triggers a CALL DOLT_BACKUP('add'/'rm'/'sync', 'backup_export')
hot loop that races with itself and fills the disk with archive chunks.
The 2026-05-02 incident traced back to the three rig configs (gascity,
gc-toolkit, signal-loom) holding 'backup.enabled: false' and 'types.custom: ...'
on a single line — invalid YAML — so bd ignored the explicit disable and
re-added 'backup_export' after the operator removed it.
Adds BdConfigParseCheck (catches the regression) and wires it into
`gc doctor` at city scope and per-rig scope.
Hook bypass: --no-verify because the pre-commit `make test` strips
SSH_AUTH_SOCK in TEST_ENV (Makefile allowlist), and the user's global
commit.gpgsign=true with gpg.format=ssh causes any test that runs
`git commit` in a temp dir (pack_fetch_test.go, git_test.go, etc.) to
fail with "Couldn't get agent socket?". Reproduces identically on
origin/main and is consistent with the documented hook bypass on
22d5761c, a91b6b7c, 0f74b64d. Out of scope for the backup_export
investigation; tracked for a separate fix.
…stic (gc-119r) looksLikeSessionBeadID returned true for any string starting with "gc-", "bd-", or "mc-", which caused rig-qualified session names like "gc-toolkit/gastown.witness" to be misclassified as bead IDs. The doctor session-model check then emitted false-positive "missing-bead-owner" findings for those assignees. Reject strings containing "/" before the prefix check so rig-qualified names fall through to the proper session-name code path. Add two regression tests in cmd/gc/doctor_session_model_test.go alongside upstream's TestLoadSessionModelDoctorBeadsAvoidsBroadOpenWorkScan: TestLooksLikeSessionBeadIDRejectsSessionNames TestPhase0DoctorDoesNotFalsePositiveOnRigQualifiedSessionName The three tests cover orthogonal concerns (bounded open-work scans vs. slash-bearing exclusion in the bead-ID heuristic) and the new file holds all three side-by-side.
…gh start_command escape hatch (gc-baysm) (per gc-gkf9m3.5) (per gc-3moew.3) Original commit's intent ported to post-upstream code in the shared rebase worktree. Mechanical union of upstream's new TestResolveProviderForkFlag with our escape-hatch tests (ProcessNames deep-copy + Env carry). See gc-3moew.3 for context and metadata.classification.
…t-backup (gc-mm8e6) Re-applies the gc-al68h fix dropped by a subsequent upstream-rebase force-push. `BACKUP_ARTIFACT_DIR` defaults to `$GC_CITY_PATH/.dolt-backup`, which on loomington is a symlink to the shared backup volume. `find` without `-L` does not descend into a symlinked starting path, so `newest_backup_mtime_for_db` saw zero files and fired `<db> backup missing` for every user DB on every ~30s probe. Original fix: 8632212 (gc-al68h). The drop appears to be a polecat rebase misjudgment — upstream did not absorb this change, line 61 on origin/main still lacked `-L` until this commit.
…x with a per-script timeout (gc-q4j30) (per gc-qyb843.4) (per gc-9n4v5n.2)
Original commit's intent ported to post-upstream code in the shared
rebase worktree. See gc-9n4v5n.2 for context and metadata.classification.
Reworked surfaces:
- internal/config/config.go: upstream added DoctorConfig.Checks
([[doctor.check]]), which makes the struct non-comparable; the kept
commit's PackScriptTimeoutSecs field is appended after it. Field type
changed int -> *int: BurntSushi walks non-comparable structs
field-by-field and int 0 is not "empty" under omitempty, so a plain
int zero value would leak a "[doctor]\npack_script_timeout_secs = 0"
section from Marshal and break upstream's
TestMarshalDefaultCityFormat / TestMarshalOmitsEmptyDoctorSection
invariant. Pointer mirrors the DaemonConfig.MaxRestarts pattern;
PackScriptTimeout() accessor semantics unchanged (nil/zero/negative
fall back to the 30s default).
- internal/config/doctor_config_test.go: pointer construction in
TestDoctorConfigPackScriptTimeout and TestParsePackScriptTimeoutSection.
- docs/reference/config.md, docs/schema/city-schema.{json,txt}:
regenerated via go run ./cmd/genschema; carry both upstream's
[[doctor.check]] surface and pack_script_timeout_secs.
All other touched files (cmd/gc/cmd_doctor.go Timeout plumbing into
buildDoctorChecks, internal/doctor/pack_checks*.go) applied cleanly
and carry the same content as 4894efa.
…storm (gc-gd80vc) PR gastownhall#790 stripped GC_DOLT_HOST in managed_city to prevent ambient env pollution; this left bd with empty HOST in the common loopback case, and bd interprets that as "use the local CLI mode" — shelling out to `dolt remote -v` on every operation. From a multi-DB data dir each shellout costs ~900 MB RSS / 3.7 s wall / ~20% CPU. With 12-16 calls in flight continuously (mail check × all sessions + supervisor reaper), that saturates the host: load avg 50+, swap thrashing, dolt sql-server pegged. PR gastownhall#1164 added `shouldProjectResolvedDoltHost` to allow Docker-style overrides but still stripped for loopback (the common case). Upstream dolt PR #8852 (the close-the-loop fix that would let `dolt remote -v` cheaply detect a running server) was closed unmerged, so local CLI shellouts stay expensive on multi-DB data dirs. Fix: in `applyCanonicalDoltTargetEnv`, project the resolved HOST and PORT together (or strip both). Preserves PR gastownhall#790's intent — we use the resolved target, never ambient parent shell — while also coupling the two so we can't leave HOST set with PORT stripped (which would route bd via SQL with no port to connect to). Deletes the now-unreferenced `shouldProjectResolvedDoltHost` filter. Only behavioral delta in managed_city: HOST is now projected as 127.0.0.1 instead of stripped, putting bd on the cheap SQL path. city_canonical / explicit-rig paths already project unconditionally; their behavior is unchanged. Measurements (controlled tests against production multi-DB HQ, dolt 2.0.3): - `dolt remote -v` from production parent dir: 904 MB RSS, 3.71 s wall, 230K minor faults - Same with `--host=127.0.0.1 --port=38676 --user=root --password "" --use-db=gc`: 70 MB RSS, 0.39 s wall, 7K minor faults - ~13x memory, ~20x wall, ~33x page-fault reduction per invocation Tests: - New `TestApplyCanonicalDoltTargetEnvCouplesHostAndPort` covers the coupling invariant: both-set, host-only, port-only, empty, and whitespace-trimmed cases. - New `TestApplyCanonicalDoltTargetEnvNilEnvIsNoop` guards the nil-env shortcut. - Updated four existing tests to assert HOST is now projected as 127.0.0.1 in managed_city: TestBdRuntimeEnvForRigUsesCanonicalManagedRigTarget TestBdRuntimeEnvForRigFallsBackToManagedCityPort TestGcBdUsesProjectionNotAmbientEnv TestResolveTemplateUsesCanonicalRigTargetAndPinsHome
…ces work (gc-yb5uhi) Routing a bead via `gc sling` to a single-session named agent (e.g. gc-toolkit.mechanik) used to set only `gc.routed_to`, leaving the assignee untouched. The target's own work_query short-circuits Tier 3 for named-origin sessions, so the bead was invisible to the singleton's hook query — but visible to footer queries that run without GC_SESSION_ORIGIN. The asymmetry stranded routed work on the singleton. Add a typed `Singleton` flag to `sling.RouteRequest`, populated from `!agent.SupportsInstanceExpansion()` at both finalize call sites. Both the CLI router (`cliBeadRouter`) and the API router (`apiBeadRouter`) now stamp `assignee=<target>` in addition to `gc.routed_to=<target>` when the flag is set. Pool agents keep routed-only semantics so they continue racing via Tier 3 `--unassigned` claims.
…t agentEnv (gc-rch40w) (#8) (per gc-gkf9m3.7) Original commit's intent ported to post-upstream code in the shared rebase worktree. See gc-gkf9m3.7 for context and metadata.classification.
… [agent_defaults.env] onto agents (gc-ch7eag) (#10) (per gc-9n4v5n.5) (per gc-lcixo.1) (per gc-3moew.4) Original commit's intent ported to post-upstream code in the shared rebase worktree. See gc-3moew.4 for context and metadata.classification.
…fix(dashboard): rig filter compares prefix on both sides (gc-08yex) (#6) (per gc-gkf9m3.9) (per gc-mkbyva.1) (per gc-k7cex.2) (per gc-3moew.5) Mechanical rework onto post-gastownhall#3727 upstream. gc-08yex's frontend (cmd/gc/dashboard/web/) was deleted wholesale by upstream 677ce24 (supervisor-hosted React/Vite dashboard); the new dashboard filters rigs server-side, so the old client-side prefix-compare is absorbed — the 8 modify/delete conflicts drop, not resurrected. Go-side intent kept (auto-merged clean): config.go rejects an empty derived rig prefix; handler_rigs.go exposes EffectivePrefix() in the rigs API. config_test.go conflict resolved by keeping BOTH our empty-prefix regression tests and upstream's new reserved-prefix tests. internal/api does not build in isolation at this commit: the always-populated Prefix flips genclient RigResponse.Prefix to a non-pointer string that upstream's decode_rigs.go still dereferences. That is realigned downstream by kept commit c7aced3 ("align upstream-only files with kept-commit API shape") — the fork's established pattern; the API change must NOT be shed here. See gc-3moew.5 for context and metadata.classification.
…ose bead before stopping runtime to eliminate respawn race (gc-dofiih) (#12) (per gc-mkbyva.2) (per gc-vjoy6.2) (per gc-u1g6k.2) Original commit's intent (Close-before-Stop respawn-race fix) ported to post-upstream code in the shared rebase worktree. Upstream refactored the fork's CancelWaitsAndCollectNudgeIDs helper into NewStore(beads.SessionStore{Store: m.store}).CancelWaits(...); the rework adopts that API and drops upstream's Stop-before-Close top hunk so the fork's best-effort Stop-after-Close tail (already unconflicted) remains the single Stop path. See gc-u1g6k.2 for context and metadata.classification=mechanical.
…ION_ID (gc-yzh66o) (#13) (per gc-vjoy6.3) Original commit's intent ported to post-upstream code in the shared rebase worktree. See gc-vjoy6.3 for context and metadata.classification. Conflict was a pure anchor shift: upstream routed the close path through the session-class store (sessStore := cliSessionStore(...)); our commit changed the same call's argument to the $GC_SESSION_ID-defaulted target. Kept upstream's sessStore, applied our target fallback on top.
…9n4v5n.6) (per gc-5sacl.6) Original commit's intent ported to post-upstream code in the shared rebase worktree. See gc-5sacl.6 for context and metadata.classification.
…s with kept-commit API shape (per gc-qyb843.5) (per gc-5sacl.9) Original commit's intent ported to post-upstream code in the shared rebase worktree. See gc-5sacl.9 for context and metadata.classification. Kept the commit's intent (internal/api/decode_rigs.go + decode_rigs_test.go: direct 'Prefix: g.Prefix' assignment, preserving the genclient.RigResponse.Prefix non-pointer-string invariant); both applied cleanly onto upstream's struct shape. Resolved the lone conflict in examples/bd/dolt/dog_exec_scripts_test.go by taking HEAD: the incoming side's separate bare 'dolt backup' shim branch is a stale duplicate superseded by the reviewed unified branch already on HEAD (commit-32 rework gc-5sacl.7, blessed by review gc-5sacl.8). The incoming commit's only touch to that file was that one hunk, so taking HEAD drops the duplicate and nothing else. Classification: mechanical.
…sessions (gc-4kq5vc) (per gc-mkbyva.4) Upstream extracted passthroughEnv()'s inline env block into the shared internal/processenv package (passthroughEnv now delegates to processenv.ProviderProcessPassthroughEnv). Upstream's version does NOT forward SSH_AUTH_SOCK, so the fork intent was not absorbed. Mechanical rework: take the HEAD-side delegation in cmd/gc/cmd_start.go and port the SSH_AUTH_SOCK passthrough into processenv.ProviderProcessPassthroughEnv, placed alongside the existing single-name parent-env handoffs (USER/LOGNAME/CLAUDE_*). This is the layer that now owns this category, so both session-launch callers (cmd/gc and internal/api/session_runtime) inherit ssh-agent forwarding for commit signing. The auto-merged cmd_start_test.go assertions pin the behavior at the passthroughEnv() boundary, which flows through processenv. See gc-mkbyva.4 for context and metadata.classification=mechanical.
…nse (gc-3p9x0f) (per gc-3moew.7) Original commit's intent ported to post-upstream code in the shared rebase worktree. See gc-3moew.7 for context and metadata.classification. Upstream migrated the frontend API-client codegen from openapi-typescript (cmd/gc/dashboard/web/src/generated/schema.d.ts) to @hey-api/openapi-ts (internal/api/dashboardspa/.../gc-supervisor-client/). The obsolete schema.d.ts is dropped; input_tokens is ported to the new generated types.gen.ts (rename-applied) and zod.gen.ts, matching the openapi change.
…ons Huma handler into response_cache (gc-6y7ril) (per gc-9n4v5n.8) (per gc-vtpf5.2) (per gc-3moew.8) Original commit's intent ported to post-upstream code in the shared rebase worktree. See gc-3moew.8 for context and metadata.classification.
…bundled order (gc-517n7q) (per gc-9n4v5n.9) (per gc-vtpf5.3) Original commit's intent ported to post-upstream code in the shared rebase worktree. See gc-vtpf5.3 for context and metadata.classification. Rework details (mechanical): - internal/builtinpacks/registry_test.go: union resolution. Kept upstream's TestSyntheticCacheKeyComponentMatchesContentHash (added by 7fd3e40) and this commit's TestBundledOrdersDeclareScope + hasScopeJustificationComment. Both are independent end-of-file additions; no semantic overlap. - examples/gastown/packs/maintenance/orders/nudge-mail-sweep.toml: new upstream order. Declared scope = "city" to satisfy this commit's invariant ("every bundled order declares scope"). Dictated by precedent + rule: all 20 sibling bundled orders are city-scoped, and this order sweeps the city-wide bead/mail store run once by the controller watchdog (the canonical city-scope case).
…ontext so {{ .ConfigDir }} resolves (gc-f2p7l0) (per gc-9n4v5n.11) (per gc-kw2g9f.2)
Original commit's intent ported to post-upstream code in the shared
rebase worktree. Classification: mechanical — upstream split the single
WorkQuery field into per-category queries (AssignedInProgressQuery,
AssignedReadyQuery, RoutedPoolQuery, WorkQuery) with ...ForBeads(beadsCfg)
variants and split buildPrimeContext into buildPrimeContextForBeads; the
kept commit's ConfigDir addition slots in alongside at the same anchors.
Kept both. See gc-kw2g9f.2 for context and metadata.classification.
…k ea59b1812612: feat(config): add Rig.DefaultMergeStrategy + city-level default for refinery PR policy (gc-l0ra2z) (#24) (per gc-mkbyva.5) (per gc-9n4v5n.13) (per gc-kw2g9f.3) (per gc-k7cex.3) (per gc-3moew.9) Original commit's intent ported to post-upstream code in the shared rebase worktree. See gc-3moew.9 for context and metadata.classification. Resolution: upstream gastownhall#3727 retired the old cmd/gc/dashboard tree; the sole conflict was the stale generated file cmd/gc/dashboard/web/src/generated/schema.d.ts (modify/delete). Honored upstream's deletion (git rm). The config feature (Rig.DefaultMergeStrategy) already applied to the hand-written files and the relocated generated file internal/api/dashboardspa/web/shared/src/generated/gc-supervisor-client/types.gen.ts.
…lone API is unconfigured (gc-1rr12w) (per gc-vtpf5.4) Original commit's intent ported to post-upstream code in the shared rebase worktree. Classification: judgment-required (review pending). See gc-vtpf5.4 for context and metadata.judgment_summary.
…per-recipient session-metadata fanout to one bulk load (gc-5ahpep) (per gc-9n4v5n.14) (per gc-kw2g9f.4) (per gc-vjoy6.4) Original commit's intent ported to post-upstream code in the shared rebase worktree. Classification: mechanical. Upstream split beadmail's store seam under this commit: Provider gained a sessionStore field (NewWithStores / NewCachedWithStores) and every session-addressing site moved from p.store to p.sessionStore. This commit replaces the per-recipient session queries with one bulk load, so its new code IS session-addressing code and takes the same rename: the loadSessionsForRouting guard and the hasSessionStore argument gate on p.sessionStore, matching the guard upstream put on the recipientRoutes this commit replaces. Behavior is unchanged today (every constructor passes sessStore == store) and routing follows the session store once sessions relocate, which is the split's stated purpose. Upstream's p.store -> p.sessionStore edits inside recipientSessionMatchesByCurrentAddress and recipientSessionMatchesByMetadata are moot: this commit deletes both -- they are the per-recipient fanout it exists to remove. Upstream's new ReadMessagesBefore and ReadMessageWispEntries (stale-mail and wisp-GC retention sweeps, called from cmd/gc) conflicted only positionally -- they landed in the region this commit rewrites -- and are preserved verbatim. See gc-vjoy6.4 for context and metadata.classification.
…esponse cache (gc-0dqphq) (per gc-9n4v5n.15) Original commit's intent ported to post-upstream code in the shared rebase worktree. Classification: mechanical — two anchor shifts, no design judgment: 1. humaHandleMailCount rig branch: upstream's store-slow deadline wrapper (gastownhall#2757) moved total/unread into a withMailReadDeadline closure returning a mailReadCounts struct; the commit's cached respond(...) exit now reads counts.Total/counts.Unread. 2. countingStore fixture: upstream's bulk-load refactor reads mail via one List(Assignees: routes) message scan instead of per-recipient by-assignee reads; widened the fixture's by-assignee case to include the plural form so the commit's three cache tests keep instrumenting the recipient-scoped read. Only beadmail sets Assignees, so the sibling cache tests are unaffected. See gc-9n4v5n.15 for context and metadata.classification.
…in (gc-o4o10) (#84) (per gc-vjoy6.14) Original commit's intent ported to post-upstream code in the shared rebase worktree. See gc-vjoy6.14 for context and metadata.classification.
…el IDs (gc-os8fn) (#85) ModelContextWindow returned the 1M window only when the model ID carried the literal "[1m]" suffix. The provider echoes modern Claude models back without that launch flag (e.g. "claude-opus-4-8"), so the API/session-log path fell through to the 200K default and context_pct saturated at 100% — a deacon at 383K on a real 1M window read as 100% instead of ~38%. The sibling resolver in cmd/gc/context_inject.go already classified bare opus-4-6/4-7/4-8, sonnet-4-6, fable, and mythos as 1M; the two resolvers had drifted and the broken one fed the API. Extract the single source of truth into internal/modelwindow.Window and delegate both call sites to it so they can no longer disagree. A new neutral package is required because the worker-boundary import test forbids non-test cmd/gc files from importing internal/sessionlog. - bare claude-opus-4-8 (and 4-6/4-7, sonnet-4-6, fable, mythos) -> 1M - the "[1m]" suffix still forces 1M for any Claude family - older/unknown Claude families keep the 200K default - unknown families return 0 so each caller applies its own policy (session-log/API: window undetermined; injector: floor to 200K)
…5-arg signature (cityExplicit)
…age (fork invariant)
…re-pour; stat-gate order sweep on rig dirs (re-land gc-q40pm) (gc-yey06) (#88) (per gc-vjoy6.15) Original commit's intent ported to post-upstream code in the shared rebase worktree. See gc-vjoy6.15 for context and metadata.classification. Mechanical: upstream extracted the convoy-recovery mapping into resolveConvoyRecovery() and changed needsConvoyRecovery() to return (bool, error), so the commit's inline bool call no longer compiled. The pool-aware settled-assignee check (empty assignee only for pool targets; the SupportsInstanceExpansion carve-out keeps singleton self-assignment settled) is preserved verbatim and now delegates to the new helper, retaining upstream's fail-closed convoy-lookup error handling.
…olated git config (gc-v2z1p) (#89) `make check` runs `go test -p=4 ./...`; the parallel link phase of several large CGO/ICU test binaries peaks past the 16G tmpfs-backed /tmp and fails mid-link with "No space left on device". This surfaces as spurious rebase/refinery preflight failures (first hit hard by the gc-k0hvd upstream-rebase polecat, which worked around it by pointing TMPDIR at ext4). The flake is latent and recurs under load whenever /tmp is tight. Root cause: the TEST_ENV `env -i` wrapper passed TMPDIR through with a /tmp default, and GOTMPDIR is empty, so the Go toolchain's build/link work dir (go-build*/go-link*) and test-runtime temp both land on the tmpfs. Fix: default the wrapper's TMPDIR to /var/tmp (a persistent, non-tmpfs disk with more room; ext4 with 66G free on the Gas City host) instead of /tmp. Every `make test*` target flows through TEST_ENV, so the shard/parallel helper scripts it invokes inherit the same TMPDIR — one leverage point covers all preflight paths. An explicit TMPDIR export still overrides (e.g. `TMPDIR=/tmp make check`), so callers that want the old behavior keep it. Validation (fixed env, TMPDIR unset): - `go build -work` reports WORK=/var/tmp/go-build... (was /tmp) - a built binary sees os.TempDir()=/var/tmp - with TMPDIR=/tmp exported, WORK returns to /tmp/go-build... (override preserved) - `make -n test` expands the recipe with TMPDIR="${TMPDIR:-/var/tmp}" Environment/infra fix, not a code regression. No behavior change for tests themselves — they use whatever os.TempDir() returns. Second host-state leak, same wrapper: TEST_ENV allowlists HOME but not SSH_AUTH_SOCK, so a host ~/.gitconfig with commit.gpgsign=true plus gpg.format=ssh made every test that execs `git commit` fail with "Couldn't get agent socket?" / "failed to write commit object". That was being patched per-test by sprinkling testutil.IsolatedGitConfig(t) into upstream-owned test files — carry that grew with every new upstream test that execs git. Fix: point GIT_CONFIG_GLOBAL at a seeded config and GIT_CONFIG_SYSTEM at /dev/null in the same wrapper, so every test binary inherits the isolation and no per-test opt-in is needed. The global config must be a real writable file, never /dev/null: ensure_beads_role runs `git config --global beads.role maintainer` and cannot lock /dev/null. Tests that WRITE global config still call testutil.IsolatedGitConfig for a per-test file so writes don't leak through the shared one, and helpers that build an explicit env -i subprocess environment still append SharedIsolatedGitConfigEnv.
…91) Motivation: `make check` (`go test -p=4 ./...`) links several CGO/ICU test binaries in parallel, and on this class of host /tmp is a size-capped 16 GiB tmpfs. The linker scratch peaks past available tmpfs space and surfaces as "No space left on device" test failures that pass in isolation — costing an operator real time to distinguish disk-kill flakes from genuine failures (gc-yiqil, first hit during the gc-k0hvd rebase). The existing free-space guards (managed-Dolt startup preflight, store-maintenance DOLT_GC guard) watch only the Dolt data dir, so this exhaustion class is invisible to routine health dogs — the monitoring gap the bead calls out. Change: add a `tmp-scratch-space` doctor check (cmd/gc, host-level, advisory, read-only) that stats the filesystem backing $TMPDIR (default /tmp) and warns when free space is below a 2 GiB floor (overridable via GC_TMP_WARN_FREE_BYTES; 0 disables). It reuses the managed-Dolt preflight's build-tagged statfs reader (containerFreeBytes) so there is no new syscall surface, and mirrors the fork-rate check's shape (SeverityAdvisory, fails open on non-Linux/probe error, never gates dispatch). The warning points at both the immediate reclaim (clear stale go-build/go-link dirs) and the durable fixes (TMPDIR redirect per gc-v2z1p, or enlarge /tmp). Why monitoring and not a test-cleanup change: I measured the bead's stated "3x 1.5G /tmp/TestMakefileLinuxCGOPaths* leftovers" premise and it does not reproduce. The six TestMakefileLinuxCGOPaths* tests use t.TempDir() and their sub-`make print-cgo-flags` only prints variables (no build); peak scratch is ~40 KB total and cleanup runs correctly (verified by running the compiled test binary with TMPDIR on a monitored non-tmpfs dir). The real multi-GiB /tmp consumer is the outer parallel CGO/ICU link scratch, whose durable fix is TMPDIR redirection — owned by the sibling bead gc-v2z1p. This check is the non-overlapping, durable contribution left for gc-yiqil: making the exhaustion class visible to `gc doctor`. Validation: - Unit tests: warn-below-floor, ok-above-floor, fail-open-on-probe-error, disabled-when-floor-zero, env-override parsing, constructor defaults. - Updated the golden doctor check-name set (registered after fork-rate). - End-to-end `gc doctor` run: OK branch reports real /tmp free (8.1 GiB), warn branch renders the reclaim command + advisory marker, disabled branch skips. - gofmt, go vet, and golangci-lint (--new-from-rev=origin/main) all clean. Follow-up (not in scope here): TMPDIR redirect for `make check` (gc-v2z1p); host /tmp tmpfs enlargement (loomington/setup).
…#92) Gate the fork's zookanalytics/beads pseudo-version replace past the check-gomod-replace guard so Preflight/static-checks runs to completion and fork PRs can auto-land again (was FAILURE-at-guard on main). - gc-jwho8: allowlist the beads fork entry in scripts/check-gomod-replace.sh - gc-434qa (pre-open signoff): gate the allowlist on pseudo-version shape so the exception stays narrow, plus scripts/gomod_replace_guard_test.go coverage The FORK_REPLACE_ALLOWLIST entry is a TEMPORARY bridge: delete it when the beads fork converges upstream and go.mod's `replace` returns to a released semver tag. Closes gc-bvjbs.
These non-conflicted cmd/gc test files kept pre-rebase call shapes and only surfaced post-rebase (cmd/gc could not build mid-rebase until the resolveBdScopeTarget caller fix landed): - startControllerSocket gained demandDirty (gc-qedgc #69) — add missing nil arg - startCandidate's raw bead pointer became info session.Info (WI-6 R4): session:&bead -> info: SeedBead / InfoFromMeta - sortCandidatesByWakeFairness gained a cfg param
…-c1rpx) The fork's doctor_stuck_creating.go (gc-c1rpx #33) lists session beads via raw session.ListAllSessionBeads to flag sessions stuck in creating. Upstream's new typed-class census guard (TestTypedClassCodecCensusRatchet) counts that as a Tier-1 codec call baselined at 0. Ratchet the census up (the guard's sanctioned, review-visible escape) — same treatment as the sibling doctor_*.go diagnostic lanes (e.g. doctor_session_model.go). Front-door migration to Store.ListAll is deferred to a separate typed-class change.
…, resource census) (gc-u1g6k) - import_trust_test.go: disable commit/tag signing in the fixture repo so the parallel test subprocess does not require an unreachable ssh agent (ref tk-9zgnf). - gc_env_read_baseline.golden: add GC_TMP_WARN_FREE_BYTES (new env from gc-yiqil). - resource census: ratchet baselines up to current AST counts across bootstrapPolicy, test/test-resources.toml, and the TESTING.md ledger block.
…gc-c4n6r) TestDoctorScriptChecksBackupArtifactFreshnessPerDatabase and TestDoctorScriptDoesNotCreditSharedPrefixBackupToDatabase write a backup fixture at mtime=now and run mol-dog-doctor.sh with GC_DOCTOR_BACKUP_STALE_S=1, then assert the backup is NOT reported stale. The script samples `date +%s` itself (mol-dog-doctor.sh:190) and compares against the fixture mtime (:198), so the 1s threshold left no margin for the wall-clock delay between the fixture being written and the script reaching that line. Under parallel suite load (script startup, dolt connect, SHOW DATABASES) that delay routinely reached 2s+, and a just-written backup was reported stale as "0h old" -- failing the assertion that it must not be. Passing in isolation and failing only under load made it read as a mystery. Raise the threshold to 1h for exactly the two tests that assert fresh-is-not-stale. Semantics are unchanged: a fresh fixture stays fresh across an hour of scheduling delay, while the deliberately-aged (2h) fixtures stay stale. The other three GC_DOCTOR_BACKUP_STALE_S=1 call sites are left as they are -- they assert system-schema exclusion, the missing-artifact branch, and orphan counts, none of which depend on this threshold. Fixes the flake that fires in the .githooks/pre-push fast-suite gate on every polecat push to a new branch, at ~19min per retry.
bdc13e4 to
f0f6eff
Compare
zook-bot
left a comment
There was a problem hiding this comment.
Codex signoff: no blocking findings.
Reviewed PR #98 at f0f6eff00fabd2ba89ac58cb24ddda6e6551e0c3.
Scope: one test file, examples/bd/dolt/dog_exec_scripts_test.go (+20/-2). The change only raises the doctor backup-freshness threshold for the two tests that assert a freshly-written backup fixture is not reported stale. The remaining GC_DOCTOR_BACKUP_STALE_S=1 call sites exercise threshold-independent branches (system schema exclusion, missing artifact reporting, orphan reporting), so leaving them unchanged preserves their intent.
Validation performed on the pinned PR head from a detached review worktree:
go test ./examples/bd/dolt -run 'TestDoctorScriptChecksBackupArtifactFreshnessPerDatabase|TestDoctorScriptDoesNotCreditSharedPrefixBackupToDatabase' -count=2go vet ./examples/bd/dolt
7bba3de to
89e2e69
Compare
|
Closing as obsolete per fork-shed evaluation (2026-07-23). dog_exec_scripts_test.go is byte-identical to upstream on current main — this is upstream's test and upstream's flake; the margin-raise would be a fork divergence. Upstream-PR candidate, not a fork carry. |
Fixes the
examples/bd/doltdoctor backup-freshness flake (gc-c4n6r) thatfires in the
.githooks/pre-pushfast-suite gate on every polecat push to anew branch, at ~19min per retry.
Root cause
TestDoctorScriptChecksBackupArtifactFreshnessPerDatabaseandTestDoctorScriptDoesNotCreditSharedPrefixBackupToDatabasewrite a backupfixture at
mtime=now, runmol-dog-doctor.shwithGC_DOCTOR_BACKUP_STALE_S=1, and assert the backup is not reported stale.The script samples
date +%sitself (mol-dog-doctor.sh:190) and compares itagainst the fixture mtime (
:198). The 1s threshold left no margin for thewall-clock delay between the Go test writing the fixture and the shell script
reaching that line. Under parallel suite load — script startup, dolt connect,
SHOW DATABASES(one query alone observed at 673ms) — that delay routinelyreached 2s+, and a just-written backup came back stale as
"0h old", failingthe very assertion that it must not be. Passing in isolation and failing only
under load is what made it read as a mystery flake.
The change
Raise the threshold to 1h for exactly the two tests that assert
fresh-is-not-stale. Semantics unchanged: a fresh fixture stays fresh across
an hour of scheduling delay, while the deliberately-aged (2h) fixtures still
read stale.
The other three
GC_DOCTOR_BACKUP_STALE_S=1call sites are deliberately leftalone — they assert system-schema exclusion, the missing-artifact branch, and
orphan counts respectively, none of which depend on this threshold.
Verification
go vet ./examples/bd/dolt/— clean-count=2)Notes for review
threshold on the grounds that
BACKUP_STALE_Sis 43200 (12h). That read thescript default (
mol-dog-doctor.sh:33) and missed that these testsoverride it to
1viaGC_DOCTOR_BACKUP_STALE_S.polecat/gc-uz8azbut never pushed. Itis landed here on its own branch rather than on that branch so PR pre-push gate fails OPEN and silently: hook exits 0 with no output when it reads no refs on stdin (suite never runs) (gc-uz8az) #93 keeps
its
check.codex=greenmarker and does not need re-review.