Skip to content

test(dolt): give the doctor backup-freshness fixtures a real margin (gc-c4n6r)#98

Closed
zook-bot wants to merge 69 commits into
mainfrom
fix/gc-c4n6r-backup-freshness-margin
Closed

test(dolt): give the doctor backup-freshness fixtures a real margin (gc-c4n6r)#98
zook-bot wants to merge 69 commits into
mainfrom
fix/gc-c4n6r-backup-freshness-margin

Conversation

@zook-bot

Copy link
Copy Markdown

Fixes the examples/bd/dolt doctor backup-freshness flake (gc-c4n6r) that
fires in the .githooks/pre-push fast-suite gate on every polecat push to a
new branch
, at ~19min per retry.

Root cause

TestDoctorScriptChecksBackupArtifactFreshnessPerDatabase and
TestDoctorScriptDoesNotCreditSharedPrefixBackupToDatabase write a backup
fixture at mtime=now, run mol-dog-doctor.sh with
GC_DOCTOR_BACKUP_STALE_S=1, and assert the backup is not reported stale.

The script samples date +%s itself (mol-dog-doctor.sh:190) and compares it
against the fixture mtime (:198). The 1s threshold left no margin for the
wall-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 routinely
reached 2s+, and a just-written backup came back stale as "0h old", failing
the 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=1 call sites are deliberately left
alone — 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
  • Both affected tests: 4/4 green (-count=2)
  • Previously verified 3/3 green under concurrent load by the gascity witness

Notes for review

zook-bot added 30 commits July 16, 2026 21:54
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.
zook-bot added 12 commits July 21, 2026 07:00
…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)
…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.
@zook-bot
zook-bot force-pushed the fix/gc-c4n6r-backup-freshness-margin branch from bdc13e4 to f0f6eff Compare July 21, 2026 07:11

@zook-bot zook-bot left a comment

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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=2
  • go vet ./examples/bd/dolt

@zook-bot
zook-bot force-pushed the main branch 12 times, most recently from 7bba3de to 89e2e69 Compare July 22, 2026 23:13
@zook-bot

Copy link
Copy Markdown
Author

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.

@zook-bot zook-bot closed this Jul 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant